mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-01 23:20:51 +00:00
refactor dir column view (#6743)
This commit is contained in:
@@ -1,12 +1,9 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Link } from '@gatsbyjs/reach-router';
|
||||
import { UncontrolledTooltip } from 'reactstrap';
|
||||
import { siteRoot, gettext } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { InternalLinkOperation } from '../operations';
|
||||
import DirOperationToolBar from '../../components/toolbar/dir-operation-toolbar';
|
||||
import ViewFileToolbar from '../../components/toolbar/view-file-toolbar';
|
||||
import { PRIVATE_FILE_TYPE } from '../../constants';
|
||||
import MetadataViewId2Name from '../../metadata/metadata-view-id-2-name';
|
||||
|
||||
@@ -151,42 +148,24 @@ class DirPath extends React.Component {
|
||||
return (
|
||||
<Fragment key={index}>
|
||||
<span className="path-split">/</span>
|
||||
{this.props.isViewFile ?
|
||||
<ViewFileToolbar
|
||||
path={this.props.currentPath}
|
||||
repoID={this.props.repoID}
|
||||
userPerm={this.props.userPerm}
|
||||
repoEncrypted={this.props.repoEncrypted}
|
||||
enableDirPrivateShare={this.props.enableDirPrivateShare}
|
||||
isGroupOwnedRepo={this.props.isGroupOwnedRepo}
|
||||
filePermission={this.props.filePermission}
|
||||
fileTags={this.props.fileTags}
|
||||
onFileTagChanged={this.props.onFileTagChanged}
|
||||
showShareBtn={this.props.showShareBtn}
|
||||
repoTags={this.props.repoTags}
|
||||
>
|
||||
<span className="path-file-name">{item}</span>
|
||||
</ViewFileToolbar>
|
||||
:
|
||||
<DirOperationToolBar
|
||||
path={this.props.currentPath}
|
||||
repoID={this.props.repoID}
|
||||
repoName={this.props.repoName}
|
||||
repoEncrypted={this.props.repoEncrypted}
|
||||
direntList={this.props.direntList}
|
||||
showShareBtn={this.props.showShareBtn}
|
||||
enableDirPrivateShare={this.props.enableDirPrivateShare}
|
||||
userPerm={this.props.userPerm}
|
||||
isGroupOwnedRepo={this.props.isGroupOwnedRepo}
|
||||
onAddFile={this.props.onAddFile}
|
||||
onAddFolder={this.props.onAddFolder}
|
||||
onUploadFile={this.props.onUploadFile}
|
||||
onUploadFolder={this.props.onUploadFolder}
|
||||
loadDirentList={this.props.loadDirentList}
|
||||
>
|
||||
<span className="path-file-name">{item}</span>
|
||||
</DirOperationToolBar>
|
||||
}
|
||||
<DirOperationToolBar
|
||||
path={this.props.currentPath}
|
||||
repoID={this.props.repoID}
|
||||
repoName={this.props.repoName}
|
||||
repoEncrypted={this.props.repoEncrypted}
|
||||
direntList={this.props.direntList}
|
||||
showShareBtn={this.props.showShareBtn}
|
||||
enableDirPrivateShare={this.props.enableDirPrivateShare}
|
||||
userPerm={this.props.userPerm}
|
||||
isGroupOwnedRepo={this.props.isGroupOwnedRepo}
|
||||
onAddFile={this.props.onAddFile}
|
||||
onAddFolder={this.props.onAddFolder}
|
||||
onUploadFile={this.props.onUploadFile}
|
||||
onUploadFolder={this.props.onUploadFolder}
|
||||
loadDirentList={this.props.loadDirentList}
|
||||
>
|
||||
<span className="path-file-name">{item}</span>
|
||||
</DirOperationToolBar>
|
||||
</Fragment>
|
||||
);
|
||||
} else {
|
||||
@@ -219,16 +198,8 @@ class DirPath extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
let { currentPath, repoName, fileTags } = this.props;
|
||||
let { currentPath, repoName } = this.props;
|
||||
let pathElem = this.turnPathToLink(currentPath);
|
||||
|
||||
let tagTitle = '';
|
||||
if (fileTags.length > 0) {
|
||||
fileTags.forEach(item => {
|
||||
tagTitle += item.name + ' ';
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="path-container dir-view-path">
|
||||
<span className="cur-view-path-btn mr-1" onClick={this.props.toggleTreePanel}>
|
||||
@@ -276,19 +247,6 @@ class DirPath extends React.Component {
|
||||
<span className="path-item" data-path="/" onClick={this.onPathClick} role="button">{repoName}</span>
|
||||
}
|
||||
{pathElem}
|
||||
{this.props.isViewFile && !this.isViewMetadata() && (
|
||||
<InternalLinkOperation repoID={this.props.repoID} path={this.props.currentPath}/>
|
||||
)}
|
||||
{(this.props.isViewFile && fileTags.length !== 0) &&
|
||||
<span id='column-mode-file-tags' className="tag-list tag-list-stacked align-middle ml-1 d-flex align-items-center">
|
||||
{fileTags.map((fileTag, index) => {
|
||||
return (<span className="file-tag" key={fileTag.id} style={{ zIndex: index, backgroundColor: fileTag.color }}></span>);
|
||||
})}
|
||||
<UncontrolledTooltip target="column-mode-file-tags" placement="bottom">
|
||||
{tagTitle}
|
||||
</UncontrolledTooltip>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
3
frontend/src/components/dir-view-mode/constants.js
Normal file
3
frontend/src/components/dir-view-mode/constants.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export const LIST_MODE = 'list';
|
||||
export const GRID_MODE = 'grid';
|
||||
export const METADATA_MODE = 'metadata';
|
@@ -344,7 +344,13 @@ class DirColumnNav extends React.Component {
|
||||
<Loading />
|
||||
) : (
|
||||
<>
|
||||
<TreeSection title={gettext('Files')} moreKey={{ name: 'files' }} moreOperations={this.state.operationList} moreOperationClick={this.onMoreOperationClick} isDisplayFiles={this.state.isDisplayFiles}>
|
||||
<TreeSection
|
||||
title={gettext('Files')}
|
||||
moreKey={{ name: 'files' }}
|
||||
moreOperations={this.state.operationList}
|
||||
moreOperationClick={this.onMoreOperationClick}
|
||||
isDisplayFiles={this.state.isDisplayFiles}
|
||||
>
|
||||
<TreeView
|
||||
userPerm={userPerm}
|
||||
isNodeMenuShow={this.isNodeMenuShow}
|
||||
|
@@ -1,12 +1,15 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import DirColumnNav from './dir-column-nav';
|
||||
import DirColumnFile from './dir-column-file';
|
||||
import MarkdownViewerDialog from './markdown-viewer-dialog';
|
||||
import DirListView from './dir-list-view';
|
||||
import DirGridView from './dir-grid-view';
|
||||
import { SIDE_PANEL_FOLDED_WIDTH } from '../../constants';
|
||||
import ResizeBar from '../resize-bar';
|
||||
import { DRAG_HANDLER_HEIGHT, MAX_SIDE_PANEL_RATE, MIN_SIDE_PANEL_RATE } from '../resize-bar/constants';
|
||||
import { SeafileMetadata } from '../../metadata';
|
||||
import { mediaUrl } from '../../utils/constants';
|
||||
import { GRID_MODE, LIST_MODE, METADATA_MODE } from './constants';
|
||||
|
||||
const propTypes = {
|
||||
isSidePanelFolded: PropTypes.bool,
|
||||
@@ -34,8 +37,6 @@ const propTypes = {
|
||||
// file
|
||||
isViewFile: PropTypes.bool.isRequired,
|
||||
isFileLoading: PropTypes.bool.isRequired,
|
||||
isFileLoadedErr: PropTypes.bool.isRequired,
|
||||
hash: PropTypes.string,
|
||||
filePermission: PropTypes.string,
|
||||
content: PropTypes.string,
|
||||
viewId: PropTypes.string,
|
||||
@@ -139,13 +140,14 @@ class DirColumnView extends React.Component {
|
||||
render() {
|
||||
const { currentMode, isTreePanelShown } = this.props;
|
||||
const { navRate, inResizing } = this.state;
|
||||
const onResizeMove = inResizing ? this.onResizeMouseMove : null;
|
||||
const select = inResizing ? 'none' : '';
|
||||
const mainFlex = '1 0 ' + (1 - navRate) * 100 + '%';
|
||||
const dirContentMainStyle = {
|
||||
userSelect: inResizing ? 'none' : '',
|
||||
flex: '1 0 ' + (1 - navRate) * 100 + '%',
|
||||
};
|
||||
return (
|
||||
<div
|
||||
className="dir-column-view"
|
||||
onMouseMove={onResizeMove}
|
||||
onMouseMove={inResizing ? this.onResizeMouseMove : null}
|
||||
onMouseUp={this.onResizeMouseUp}
|
||||
ref={this.viewModeContainer}
|
||||
>
|
||||
@@ -186,28 +188,19 @@ class DirColumnView extends React.Component {
|
||||
</>
|
||||
)}
|
||||
<div
|
||||
className="dir-content-main" style={{ userSelect: select, flex: mainFlex }}
|
||||
className="dir-content-main" style={dirContentMainStyle}
|
||||
onScroll={this.props.isViewFile ? () => {} : this.props.onItemsScroll}
|
||||
ref={this.dirContentMain}
|
||||
>
|
||||
{this.props.isViewFile ? (
|
||||
<DirColumnFile
|
||||
path={this.props.path}
|
||||
{currentMode === METADATA_MODE &&
|
||||
<SeafileMetadata
|
||||
mediaUrl={mediaUrl}
|
||||
repoID={this.props.repoID}
|
||||
hash={this.props.hash}
|
||||
isFileLoading={this.props.isFileLoading}
|
||||
isFileLoadedErr={this.props.isFileLoadedErr}
|
||||
filePermission={this.props.filePermission}
|
||||
content={this.props.content}
|
||||
viewId={this.props.viewId}
|
||||
currentDirent={this.props.currentDirent}
|
||||
currentRepoInfo={this.props.currentRepoInfo}
|
||||
lastModified={this.props.lastModified}
|
||||
latestContributor={this.props.latestContributor}
|
||||
onLinkClick={this.props.onLinkClick}
|
||||
onCloseMarkdownViewDialog={this.props.onCloseMarkdownViewDialog}
|
||||
repoInfo={this.props.currentRepoInfo}
|
||||
viewID={this.props.viewId}
|
||||
/>
|
||||
) : (currentMode == 'list' ?
|
||||
}
|
||||
{currentMode === LIST_MODE &&
|
||||
<DirListView
|
||||
path={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
@@ -246,7 +239,9 @@ class DirColumnView extends React.Component {
|
||||
showDirentDetail={this.props.showDirentDetail}
|
||||
getMenuContainerSize={this.getMenuContainerSize}
|
||||
eventBus={this.props.eventBus}
|
||||
/> :
|
||||
/>
|
||||
}
|
||||
{currentMode === GRID_MODE &&
|
||||
<DirGridView
|
||||
path={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
@@ -283,7 +278,20 @@ class DirColumnView extends React.Component {
|
||||
getMenuContainerSize={this.getMenuContainerSize}
|
||||
eventBus={this.props.eventBus}
|
||||
/>
|
||||
)}
|
||||
}
|
||||
{this.props.isViewFile &&
|
||||
<MarkdownViewerDialog
|
||||
path={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
isFileLoading={this.props.isFileLoading}
|
||||
content={this.props.content}
|
||||
currentDirent={this.props.currentDirent}
|
||||
lastModified={this.props.lastModified}
|
||||
latestContributor={this.props.latestContributor}
|
||||
onLinkClick={this.props.onLinkClick}
|
||||
onCloseMarkdownViewDialog={this.props.onCloseMarkdownViewDialog}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@@ -1,5 +1,10 @@
|
||||
.seafile-markdown-viewer-modal {
|
||||
max-width: 950px;
|
||||
height: calc(100% - 56px);
|
||||
}
|
||||
|
||||
.seafile-markdown-viewer-modal .seafile-markdown-viewer-modal-content {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.seafile-markdown-viewer-modal-header {
|
@@ -1,65 +1,37 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Modal, ModalBody } from 'reactstrap';
|
||||
import { SeafileMetadata } from '../../metadata';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { gettext, siteRoot, mediaUrl } from '../../utils/constants';
|
||||
import { siteRoot, mediaUrl } from '../../utils/constants';
|
||||
import SeafileMarkdownViewer from '../seafile-markdown-viewer';
|
||||
|
||||
import './dir-column-file.css';
|
||||
import './markdown-viewer-dialog.css';
|
||||
|
||||
const propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
repoID: PropTypes.string.isRequired,
|
||||
hash: PropTypes.string,
|
||||
isFileLoading: PropTypes.bool.isRequired,
|
||||
isFileLoadedErr: PropTypes.bool.isRequired,
|
||||
filePermission: PropTypes.string,
|
||||
content: PropTypes.string,
|
||||
viewId: PropTypes.string,
|
||||
lastModified: PropTypes.string,
|
||||
latestContributor: PropTypes.string,
|
||||
onLinkClick: PropTypes.func.isRequired,
|
||||
currentRepoInfo: PropTypes.object,
|
||||
currentDirent: PropTypes.object,
|
||||
onCloseMarkdownViewDialog: PropTypes.func
|
||||
};
|
||||
|
||||
class DirColumnFile extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.hash) {
|
||||
let hash = this.props.hash;
|
||||
setTimeout(function () {
|
||||
window.location.hash = hash;
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
class MarkdownViewerDialog extends React.Component {
|
||||
|
||||
onOpenFile = (e) => {
|
||||
e.preventDefault();
|
||||
let { path, repoID, currentDirent } = this.props;
|
||||
let { name } = currentDirent || {};
|
||||
let newUrl = siteRoot + 'lib/' + repoID + '/file' + Utils.encodePath(path) + '/' + name;
|
||||
let newUrl = siteRoot + 'lib/' + repoID + '/file' + Utils.encodePath(path) + (path.endsWith('/') ? '' : '/') + name;
|
||||
window.open(newUrl, '_blank');
|
||||
};
|
||||
|
||||
render() {
|
||||
const { currentDirent } = this.props;
|
||||
const { name } = currentDirent || {};
|
||||
|
||||
if (this.props.isFileLoadedErr) {
|
||||
return (
|
||||
<div className="message err-tip">{gettext('File does not exist.')}</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (this.props.content === '__sf-metadata') {
|
||||
const { repoID, currentRepoInfo, viewId } = this.props;
|
||||
|
||||
return (<SeafileMetadata mediaUrl={mediaUrl} repoID={repoID} repoInfo={currentRepoInfo} viewID={viewId} />);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={true}
|
||||
@@ -70,12 +42,10 @@ class DirColumnFile extends React.Component {
|
||||
>
|
||||
<div className='seafile-markdown-viewer-modal-header'>
|
||||
<div className='seafile-markdown-viewer-modal-header-left-name'>
|
||||
<span ><img src={`${mediaUrl}img/file/256/md.png`} width='24' alt='' /></span>
|
||||
<span><img src={`${mediaUrl}img/file/256/md.png`} width='24' alt='' /></span>
|
||||
<span>{name}</span>
|
||||
</div>
|
||||
<div className='seafile-markdown-viewer-modal-header-right-tool'>
|
||||
{/* Hidden for now, operations may be added later */}
|
||||
{/* <span className='sf3-font sf3-font-more'></span> */}
|
||||
<span className='sf3-font sf3-font-open' onClick={this.onOpenFile}></span>
|
||||
<span className='sf3-font sf3-font-x-01' onClick={this.props.onCloseMarkdownViewDialog}></span>
|
||||
</div>
|
||||
@@ -98,6 +68,6 @@ class DirColumnFile extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
DirColumnFile.propTypes = propTypes;
|
||||
MarkdownViewerDialog.propTypes = propTypes;
|
||||
|
||||
export default DirColumnFile;
|
||||
export default MarkdownViewerDialog;
|
@@ -19,6 +19,7 @@ import toaster from '../toast';
|
||||
import RepoAPITokenDialog from '../dialog/repo-api-token-dialog';
|
||||
import RepoShareAdminDialog from '../dialog/repo-share-admin-dialog';
|
||||
import RepoMonitoredIcon from '../../components/repo-monitored-icon';
|
||||
import { GRID_MODE, LIST_MODE } from '../dir-view-mode/constants';
|
||||
|
||||
const propTypes = {
|
||||
currentViewMode: PropTypes.string,
|
||||
@@ -141,7 +142,7 @@ class SharedRepoListItem extends React.Component {
|
||||
getRepoComputeParams = () => {
|
||||
const { repo, currentViewMode } = this.props;
|
||||
|
||||
const useBigLibaryIcon = currentViewMode == 'grid';
|
||||
const useBigLibaryIcon = currentViewMode == GRID_MODE;
|
||||
const iconUrl = Utils.getLibIconUrl(repo, useBigLibaryIcon);
|
||||
let iconTitle = Utils.getLibIconTitle(repo);
|
||||
let libPath = `${siteRoot}library/${repo.repo_id}/${Utils.encodePath(repo.repo_name)}/`;
|
||||
@@ -619,7 +620,7 @@ class SharedRepoListItem extends React.Component {
|
||||
const { isStarred } = this.state;
|
||||
let { iconUrl, iconTitle, libPath } = this.getRepoComputeParams();
|
||||
const { repo, currentViewMode } = this.props;
|
||||
return currentViewMode == 'list' ? (
|
||||
return currentViewMode == LIST_MODE ? (
|
||||
<tr
|
||||
className={this.state.highlight ? 'tr-highlight' : ''}
|
||||
onMouseEnter={this.onMouseEnter}
|
||||
|
@@ -6,6 +6,7 @@ import SharedRepoListItem from './shared-repo-list-item';
|
||||
import toaster from '../toast';
|
||||
import LibsMobileThead from '../libs-mobile-thead';
|
||||
import Loading from '../loading';
|
||||
import { LIST_MODE } from '../dir-view-mode/constants';
|
||||
|
||||
const propTypes = {
|
||||
currentViewMode: PropTypes.string,
|
||||
@@ -86,7 +87,7 @@ class SharedRepoListView extends React.Component {
|
||||
};
|
||||
|
||||
renderRepoListView = () => {
|
||||
const { currentViewMode = 'list' } = this.props;
|
||||
const { currentViewMode = LIST_MODE } = this.props;
|
||||
return (
|
||||
<Fragment>
|
||||
{this.props.repoList.map(repo => {
|
||||
@@ -112,10 +113,10 @@ class SharedRepoListView extends React.Component {
|
||||
};
|
||||
|
||||
renderPCUI = () => {
|
||||
const { theadHidden = false, currentViewMode = 'list' } = this.props;
|
||||
const { theadHidden = false, currentViewMode = LIST_MODE } = this.props;
|
||||
const { sortByName, sortByTime, sortBySize, sortIcon } = this.getSortMetaData();
|
||||
|
||||
return currentViewMode == 'list' ? (
|
||||
return currentViewMode == LIST_MODE ? (
|
||||
<table className={theadHidden ? 'table-thead-hidden' : ''}>
|
||||
<thead>
|
||||
<tr>
|
||||
|
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap';
|
||||
import { gettext } from '../utils/constants';
|
||||
import { GRID_MODE, LIST_MODE } from './dir-view-mode/constants';
|
||||
|
||||
import '../css/view-modes.css';
|
||||
|
||||
@@ -29,9 +30,9 @@ class ViewModes extends React.Component {
|
||||
|
||||
onKeyDown = (event) => {
|
||||
if (event.shiftKey && event.keyCode === 49) {
|
||||
this.props.switchViewMode('list');
|
||||
this.props.switchViewMode(LIST_MODE);
|
||||
} else if (event.shiftKey && event.keyCode === 50) {
|
||||
this.props.switchViewMode('grid');
|
||||
this.props.switchViewMode(GRID_MODE);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -45,8 +46,8 @@ class ViewModes extends React.Component {
|
||||
const { isDropdownMenuOpen } = this.state;
|
||||
const { currentViewMode } = this.props;
|
||||
const options = [
|
||||
{ 'icon': 'list-view', 'text': gettext('List view'), 'value': 'list', 'shortcut': 'Shift 1' },
|
||||
{ 'icon': 'grid-view', 'text': gettext('Grid view'), 'value': 'grid', 'shortcut': 'Shift 2' }
|
||||
{ 'icon': 'list-view', 'text': gettext('List view'), 'value': LIST_MODE, 'shortcut': 'Shift 1' },
|
||||
{ 'icon': 'grid-view', 'text': gettext('Grid view'), 'value': GRID_MODE, 'shortcut': 'Shift 2' }
|
||||
];
|
||||
return (
|
||||
<Dropdown
|
||||
|
@@ -8,6 +8,7 @@ import SharedRepoListView from '../../components/shared-repo-list-view/shared-re
|
||||
import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar';
|
||||
import CreateRepoDialog from '../../components/dialog/create-repo-dialog';
|
||||
import Repo from '../../models/repo';
|
||||
import { LIST_MODE } from '../../components/dir-view-mode/constants';
|
||||
|
||||
const propTypes = {
|
||||
inAllLibs: PropTypes.bool,
|
||||
@@ -107,14 +108,14 @@ class GroupItem extends React.Component {
|
||||
|
||||
|
||||
render() {
|
||||
const { inAllLibs = false, group, currentViewMode = 'list' } = this.props;
|
||||
const { inAllLibs = false, group, currentViewMode = LIST_MODE } = this.props;
|
||||
const { parent_group_id, admins } = group;
|
||||
const emptyTip = <p className={`libraries-empty-tip-in-${currentViewMode}-mode`}>{gettext('No libraries')}</p>;
|
||||
|
||||
const isDeptAdmin = parent_group_id != 0 && admins.indexOf(username) > -1;
|
||||
return (
|
||||
<div className="pb-3">
|
||||
<div className={`d-flex justify-content-between mt-3 py-1 ${currentViewMode == 'list' ? 'sf-border-bottom' : ''}`}>
|
||||
<div className={`d-flex justify-content-between mt-3 py-1 ${currentViewMode == LIST_MODE ? 'sf-border-bottom' : ''}`}>
|
||||
<h4 className="sf-heading m-0 d-flex align-items-center">
|
||||
<span className={`${group.parent_group_id == 0 ? 'sf3-font-group' : 'sf3-font-department'} sf3-font nav-icon`} aria-hidden="true"></span>
|
||||
<a href={`${siteRoot}group/${group.id}/`} title={group.name} className="ellipsis">{group.name}</a>
|
||||
|
@@ -34,8 +34,6 @@ const propTypes = {
|
||||
onMainNavBarClick: PropTypes.func.isRequired,
|
||||
// file
|
||||
isViewFile: PropTypes.bool.isRequired,
|
||||
isFileLoadedErr: PropTypes.bool.isRequired,
|
||||
hash: PropTypes.string,
|
||||
fileTags: PropTypes.array.isRequired,
|
||||
isFileLoading: PropTypes.bool.isRequired,
|
||||
filePermission: PropTypes.string,
|
||||
@@ -305,8 +303,6 @@ class LibContentContainer extends React.Component {
|
||||
onDeleteNode={this.props.onDeleteNode}
|
||||
isViewFile={this.props.isViewFile}
|
||||
isFileLoading={this.props.isFileLoading}
|
||||
isFileLoadedErr={this.props.isFileLoadedErr}
|
||||
hash={this.props.hash}
|
||||
filePermission={this.props.filePermission}
|
||||
content={this.props.content}
|
||||
viewId={this.props.viewId}
|
||||
|
@@ -25,6 +25,7 @@ import DeleteFolderDialog from '../../components/dialog/delete-folder-dialog';
|
||||
import { EVENT_BUS_TYPE } from '../../components/common/event-bus-type';
|
||||
import { PRIVATE_FILE_TYPE } from '../../constants';
|
||||
import { MetadataProvider, CollaboratorsProvider } from '../../metadata/hooks';
|
||||
import { LIST_MODE, METADATA_MODE } from '../../components/dir-view-mode/constants';
|
||||
|
||||
const propTypes = {
|
||||
eventBus: PropTypes.object,
|
||||
@@ -45,12 +46,11 @@ class LibContentView extends React.Component {
|
||||
isTreePanelShown = storedTreePanelState == 'true';
|
||||
}
|
||||
this.state = {
|
||||
currentMode: cookie.load('seafile_view_mode') || 'list',
|
||||
currentMode: cookie.load('seafile_view_mode') || LIST_MODE,
|
||||
isTreePanelShown: isTreePanelShown, // display the 'dirent tree' side panel
|
||||
path: '',
|
||||
pathExist: true,
|
||||
isViewFile: false,
|
||||
hash: '',
|
||||
currentRepoInfo: null,
|
||||
repoName: '',
|
||||
repoEncrypted: false,
|
||||
@@ -66,7 +66,6 @@ class LibContentView extends React.Component {
|
||||
treeData: treeHelper.buildTree(),
|
||||
currentNode: null,
|
||||
isFileLoading: true,
|
||||
isFileLoadedErr: false,
|
||||
filePermission: '',
|
||||
content: '',
|
||||
lastModified: '',
|
||||
@@ -129,13 +128,6 @@ class LibContentView extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
const hash = window.location.hash;
|
||||
if (hash.slice(0, 1) === '#') {
|
||||
this.setState({ hash: hash });
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.calculatePara(this.props);
|
||||
}
|
||||
@@ -362,14 +354,12 @@ class LibContentView extends React.Component {
|
||||
latestContributor: last_modifier_name,
|
||||
lastModified: moment.unix(mtime).fromNow(),
|
||||
isFileLoading: false,
|
||||
isFileLoadedErr: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
}).catch(() => {
|
||||
this.setState({
|
||||
isFileLoading: false,
|
||||
isFileLoadedErr: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -500,7 +490,6 @@ class LibContentView extends React.Component {
|
||||
latestContributor: last_modifier_name,
|
||||
lastModified: moment.unix(mtime).fromNow(),
|
||||
isFileLoading: false,
|
||||
isFileLoadedErr: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -511,7 +500,6 @@ class LibContentView extends React.Component {
|
||||
}
|
||||
this.setState({
|
||||
isFileLoading: false,
|
||||
isFileLoadedErr: true,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -526,28 +514,20 @@ class LibContentView extends React.Component {
|
||||
showFileMetadata = (filePath, viewId) => {
|
||||
const repoID = this.props.repoID;
|
||||
const repoInfo = this.state.currentRepoInfo;
|
||||
|
||||
this.setState({
|
||||
currentMode: METADATA_MODE,
|
||||
path: filePath,
|
||||
isViewFile: true,
|
||||
isFileLoading: false,
|
||||
isFileLoadedErr: false,
|
||||
content: '__sf-metadata',
|
||||
viewId: viewId,
|
||||
isDirentDetailShow: false
|
||||
});
|
||||
|
||||
const url = `${siteRoot}library/${repoID}/${encodeURIComponent(repoInfo.repo_name)}/?view=${encodeURIComponent(viewId)}`;
|
||||
window.history.pushState({ url: url, path: '' }, '', url);
|
||||
};
|
||||
|
||||
hideFileMetadata = () => {
|
||||
this.setState({
|
||||
currentMode: LIST_MODE,
|
||||
path: '',
|
||||
isViewFile: false,
|
||||
isFileLoading: false,
|
||||
isFileLoadedErr: false,
|
||||
content: '',
|
||||
viewId: '',
|
||||
isDirentDetailShow: false
|
||||
}, () => {
|
||||
@@ -2019,6 +1999,11 @@ class LibContentView extends React.Component {
|
||||
isDirentSelected: false,
|
||||
isAllDirentSelected: false,
|
||||
});
|
||||
if (this.state.currentMode === METADATA_MODE) {
|
||||
this.setState({
|
||||
currentMode: cookie.load('seafile_view_mode') || LIST_MODE,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
recalculateSelectedDirents = (unSelectNames, newDirentList) => {
|
||||
@@ -2241,10 +2226,8 @@ class LibContentView extends React.Component {
|
||||
onTabNavClick={this.props.onTabNavClick}
|
||||
onMainNavBarClick={this.onMainNavBarClick}
|
||||
isViewFile={this.state.isViewFile}
|
||||
hash={this.state.hash}
|
||||
fileTags={this.state.fileTags}
|
||||
isFileLoading={this.state.isFileLoading}
|
||||
isFileLoadedErr={this.state.isFileLoadedErr}
|
||||
filePermission={this.state.filePermission}
|
||||
content={this.state.content}
|
||||
viewId={this.state.viewId}
|
||||
|
@@ -17,6 +17,7 @@ import MylibRepoListView from '../../pages/my-libs/mylib-repo-list-view';
|
||||
import SharedLibs from '../../pages/shared-libs/shared-libs';
|
||||
import SharedWithAll from '../../pages/shared-with-all';
|
||||
import GroupItem from '../../pages/groups/group-item';
|
||||
import { LIST_MODE } from '../../components/dir-view-mode/constants';
|
||||
|
||||
import '../../css/files.css';
|
||||
|
||||
@@ -41,7 +42,7 @@ class Libraries extends Component {
|
||||
sharedRepoList: [],
|
||||
publicRepoList: [],
|
||||
isCreateRepoDialogOpen: false,
|
||||
currentViewMode: localStorage.getItem('sf_repo_list_view_mode') || 'list',
|
||||
currentViewMode: localStorage.getItem('sf_repo_list_view_mode') || LIST_MODE,
|
||||
sortBy: localStorage.getItem('sf_repos_sort_by') || 'name', // 'name' or 'time'
|
||||
sortOrder: localStorage.getItem('sf_repos_sort_order') || 'asc', // 'asc' or 'desc'
|
||||
};
|
||||
@@ -249,7 +250,7 @@ class Libraries extends Component {
|
||||
<Loading /> :
|
||||
<div className="cur-view-content" id="files-content-container">
|
||||
|
||||
{(Utils.isDesktop() && currentViewMode == 'list') && (
|
||||
{(Utils.isDesktop() && currentViewMode == LIST_MODE) && (
|
||||
<table aria-hidden={true} className="my-3">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -267,7 +268,7 @@ class Libraries extends Component {
|
||||
|
||||
{canAddRepo && (
|
||||
<div className="pb-3">
|
||||
<div className={`d-flex justify-content-between mt-3 py-1 ${currentViewMode == 'list' ? 'sf-border-bottom' : ''}`}>
|
||||
<div className={`d-flex justify-content-between mt-3 py-1 ${currentViewMode == LIST_MODE ? 'sf-border-bottom' : ''}`}>
|
||||
<h4 className="sf-heading m-0 d-flex align-items-center">
|
||||
<span className="sf3-font-mine sf3-font nav-icon" aria-hidden="true"></span>
|
||||
{gettext('My Libraries')}
|
||||
|
@@ -22,6 +22,7 @@ import RepoAPITokenDialog from '../../components/dialog/repo-api-token-dialog';
|
||||
import RepoShareAdminDialog from '../../components/dialog/repo-share-admin-dialog';
|
||||
import LibOldFilesAutoDelDialog from '../../components/dialog/lib-old-files-auto-del-dialog';
|
||||
import RepoMonitoredIcon from '../../components/repo-monitored-icon';
|
||||
import { GRID_MODE, LIST_MODE } from '../../components/dir-view-mode/constants';
|
||||
|
||||
const propTypes = {
|
||||
currentViewMode: PropTypes.string,
|
||||
@@ -304,12 +305,12 @@ class MylibRepoListItem extends React.Component {
|
||||
|
||||
renderPCUI = () => {
|
||||
const { isStarred } = this.state;
|
||||
const { repo, currentViewMode = 'list' } = this.props;
|
||||
let useBigLibaryIcon = currentViewMode == 'grid';
|
||||
const { repo, currentViewMode = LIST_MODE } = this.props;
|
||||
let useBigLibaryIcon = currentViewMode == GRID_MODE;
|
||||
let iconUrl = Utils.getLibIconUrl(repo, useBigLibaryIcon);
|
||||
let iconTitle = Utils.getLibIconTitle(repo);
|
||||
let repoURL = `${siteRoot}library/${repo.repo_id}/${Utils.encodePath(repo.repo_name)}/`;
|
||||
return currentViewMode == 'list' ? (
|
||||
return currentViewMode == LIST_MODE ? (
|
||||
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave} onFocus={this.onFocus}>
|
||||
<td className="text-center">
|
||||
<i
|
||||
|
@@ -4,6 +4,7 @@ import MediaQuery from 'react-responsive';
|
||||
import { gettext, storages } from '../../utils/constants';
|
||||
import MylibRepoListItem from './mylib-repo-list-item';
|
||||
import LibsMobileThead from '../../components/libs-mobile-thead';
|
||||
import { LIST_MODE } from '../../components/dir-view-mode/constants';
|
||||
|
||||
const propTypes = {
|
||||
sortBy: PropTypes.string.isRequired,
|
||||
@@ -80,11 +81,11 @@ class MylibRepoListView extends React.Component {
|
||||
};
|
||||
|
||||
renderPCUI = () => {
|
||||
const { inAllLibs, currentViewMode = 'list' } = this.props;
|
||||
const { inAllLibs, currentViewMode = LIST_MODE } = this.props;
|
||||
const showStorageBackend = !inAllLibs && storages.length > 0;
|
||||
const sortIcon = this.props.sortOrder === 'asc' ? <span className="sf3-font sf3-font-down rotate-180 d-inline-block"></span> : <span className="sf3-font sf3-font-down"></span>;
|
||||
|
||||
return currentViewMode == 'list' ? (
|
||||
return currentViewMode == LIST_MODE ? (
|
||||
<table className={inAllLibs ? 'table-thead-hidden' : ''}>
|
||||
<thead>
|
||||
<tr>
|
||||
|
@@ -16,6 +16,7 @@ import ModalPotal from '../../components/modal-portal';
|
||||
import ShareDialog from '../../components/dialog/share-dialog';
|
||||
import SortOptionsDialog from '../../components/dialog/sort-options';
|
||||
import RepoMonitoredIcon from '../../components/repo-monitored-icon';
|
||||
import { GRID_MODE, LIST_MODE } from '../../components/dir-view-mode/constants';
|
||||
|
||||
class Content extends Component {
|
||||
|
||||
@@ -105,7 +106,7 @@ class Content extends Component {
|
||||
})}
|
||||
</>
|
||||
);
|
||||
const content = currentViewMode == 'list' ? (
|
||||
const content = currentViewMode == LIST_MODE ? (
|
||||
<table className={(isDesktop && !theadHidden) ? '' : 'table-thead-hidden'}>
|
||||
{isDesktop ? desktopThead : <LibsMobileThead inAllLibs={inAllLibs} />}
|
||||
<tbody>
|
||||
@@ -270,8 +271,8 @@ class Item extends Component {
|
||||
}
|
||||
|
||||
const { isStarred } = this.state;
|
||||
const { data, currentViewMode = 'list' } = this.props;
|
||||
const useBigLibaryIcon = currentViewMode == 'grid';
|
||||
const { data, currentViewMode = LIST_MODE } = this.props;
|
||||
const useBigLibaryIcon = currentViewMode == GRID_MODE;
|
||||
data.icon_url = Utils.getLibIconUrl(data, useBigLibaryIcon);
|
||||
data.icon_title = Utils.getLibIconTitle(data);
|
||||
|
||||
@@ -286,7 +287,7 @@ class Item extends Component {
|
||||
if (this.props.isDesktop) {
|
||||
return (
|
||||
<Fragment>
|
||||
{currentViewMode == 'list' ? (
|
||||
{currentViewMode == LIST_MODE ? (
|
||||
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut} onFocus={this.handleMouseOver}>
|
||||
<td className="text-center">
|
||||
<i
|
||||
@@ -525,7 +526,7 @@ class SharedLibraries extends Component {
|
||||
};
|
||||
|
||||
renderContent = () => {
|
||||
const { inAllLibs = false, currentViewMode = 'list', repoList } = this.props; // inAllLibs: in 'All Libs'('Files') page
|
||||
const { inAllLibs = false, currentViewMode = LIST_MODE, repoList } = this.props; // inAllLibs: in 'All Libs'('Files') page
|
||||
const { items } = this.state;
|
||||
return (
|
||||
<Content
|
||||
@@ -552,12 +553,12 @@ class SharedLibraries extends Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { inAllLibs = false, currentViewMode = 'list' } = this.props; // inAllLibs: in 'All Libs'('Files') page
|
||||
const { inAllLibs = false, currentViewMode = LIST_MODE } = this.props; // inAllLibs: in 'All Libs'('Files') page
|
||||
return (
|
||||
<Fragment>
|
||||
{inAllLibs ? (
|
||||
<>
|
||||
<div className={`d-flex justify-content-between mt-3 py-1 ${currentViewMode == 'list' ? 'sf-border-bottom' : ''}`}>
|
||||
<div className={`d-flex justify-content-between mt-3 py-1 ${currentViewMode == LIST_MODE ? 'sf-border-bottom' : ''}`}>
|
||||
<h4 className="sf-heading m-0">
|
||||
<span className="sf3-font-share-with-me sf3-font nav-icon" aria-hidden="true"></span>
|
||||
{gettext('Shared with me')}
|
||||
|
@@ -14,6 +14,7 @@ import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-tool
|
||||
import ModalPortal from '../../components/modal-portal';
|
||||
import CreateRepoDialog from '../../components/dialog/create-repo-dialog';
|
||||
import ShareRepoDialog from '../../components/dialog/share-repo-dialog';
|
||||
import { LIST_MODE } from '../../components/dir-view-mode/constants';
|
||||
|
||||
const propTypes = {
|
||||
currentViewMode: PropTypes.string,
|
||||
@@ -120,7 +121,7 @@ class PublicSharedView extends React.Component {
|
||||
};
|
||||
|
||||
renderContent = () => {
|
||||
const { inAllLibs = false, currentViewMode = 'list' } = this.props; // inAllLibs: in 'All Libs'('Files') page
|
||||
const { inAllLibs = false, currentViewMode = LIST_MODE } = this.props; // inAllLibs: in 'All Libs'('Files') page
|
||||
const { errMessage } = this.state;
|
||||
const emptyTip = inAllLibs ?
|
||||
<p className={`libraries-empty-tip-in-${currentViewMode}-mode`}>{gettext('No public libraries')}</p> : (
|
||||
@@ -202,12 +203,12 @@ class PublicSharedView extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { inAllLibs = false, currentViewMode = 'list' } = this.props; // inAllLibs: in 'All Libs'('Files') page
|
||||
const { inAllLibs = false, currentViewMode = LIST_MODE } = this.props; // inAllLibs: in 'All Libs'('Files') page
|
||||
|
||||
if (inAllLibs) {
|
||||
return (
|
||||
<>
|
||||
<div className={`d-flex justify-content-between mt-3 py-1 ${currentViewMode == 'list' ? 'sf-border-bottom' : ''}`}>
|
||||
<div className={`d-flex justify-content-between mt-3 py-1 ${currentViewMode == LIST_MODE ? 'sf-border-bottom' : ''}`}>
|
||||
<h4 className="sf-heading m-0">
|
||||
<span className="sf3-font-share-with-all sf3-font nav-icon" aria-hidden="true"></span>
|
||||
{gettext('Shared with all')}
|
||||
|
@@ -28,7 +28,6 @@ class Wiki extends Component {
|
||||
path: '',
|
||||
pathExist: true,
|
||||
closeSideBar: false,
|
||||
isViewFile: true,
|
||||
isDataLoading: false,
|
||||
editorContent: {},
|
||||
permission: '',
|
||||
@@ -144,7 +143,6 @@ class Wiki extends Component {
|
||||
permission,
|
||||
seadoc_access_token,
|
||||
assets_url,
|
||||
isViewFile: true,
|
||||
path: filePath,
|
||||
});
|
||||
const docUuid = assets_url.slice(assets_url.lastIndexOf('/') + 1);
|
||||
@@ -249,7 +247,6 @@ class Wiki extends Component {
|
||||
config={this.state.config}
|
||||
currentPageId={this.state.currentPageId}
|
||||
pathExist={this.state.pathExist}
|
||||
isViewFile={this.state.isViewFile}
|
||||
isDataLoading={this.state.isDataLoading}
|
||||
editorContent={this.state.editorContent}
|
||||
permission={this.state.permission}
|
||||
|
@@ -12,7 +12,6 @@ import RightHeader from './wiki-right-header';
|
||||
const propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
pathExist: PropTypes.bool.isRequired,
|
||||
isViewFile: PropTypes.bool.isRequired,
|
||||
isDataLoading: PropTypes.bool.isRequired,
|
||||
editorContent: PropTypes.object,
|
||||
permission: PropTypes.string,
|
||||
@@ -57,9 +56,9 @@ class MainPanel extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { permission, pathExist, isDataLoading, isViewFile, config, onUpdatePage, isUpdateBySide } = this.props;
|
||||
const { permission, pathExist, isDataLoading, config, onUpdatePage, isUpdateBySide } = this.props;
|
||||
const { currentPageConfig = {} } = this.state;
|
||||
const isViewingFile = pathExist && !isDataLoading && isViewFile;
|
||||
const isViewingFile = pathExist && !isDataLoading;
|
||||
const isReadOnly = !(permission === 'rw');
|
||||
|
||||
return (
|
||||
|
@@ -18,6 +18,7 @@ import SaveSharedDirDialog from './components/dialog/save-shared-dir-dialog';
|
||||
import CopyMoveDirentProgressDialog from './components/dialog/copy-move-dirent-progress-dialog';
|
||||
import RepoInfoBar from './components/repo-info-bar';
|
||||
import RepoTag from './models/repo-tag';
|
||||
import { GRID_MODE, LIST_MODE } from './components/dir-view-mode/constants';
|
||||
|
||||
import './css/shared-dir-view.css';
|
||||
import './css/grid-view.css';
|
||||
@@ -454,14 +455,14 @@ class SharedDirView extends React.Component {
|
||||
<div className="view-mode btn-group">
|
||||
<a
|
||||
href={`?p=${encodeURIComponent(relativePath)}&mode=list`}
|
||||
className={`${modeBaseClass} sf2-icon-list-view ${mode == 'list' ? 'current-mode' : ''}`}
|
||||
className={`${modeBaseClass} sf2-icon-list-view ${mode == LIST_MODE ? 'current-mode' : ''}`}
|
||||
title={gettext('List')}
|
||||
aria-label={gettext('List')}
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
href={`?p=${encodeURIComponent(relativePath)}&mode=grid`}
|
||||
className={`${modeBaseClass} sf2-icon-grid-view ${mode == 'grid' ? 'current-mode' : ''}`}
|
||||
className={`${modeBaseClass} sf2-icon-grid-view ${mode == GRID_MODE ? 'current-mode' : ''}`}
|
||||
title={gettext('Grid')}
|
||||
aria-label={gettext('Grid')}
|
||||
>
|
||||
@@ -653,7 +654,7 @@ class Content extends React.Component {
|
||||
}
|
||||
|
||||
const sortIcon = <span className={`sf3-font ${sortOrder == 'asc' ? 'sf3-font-down rotate-180 d-inline-block' : 'sf3-font-down'}`}></span>;
|
||||
return mode == 'list' ? (
|
||||
return mode == LIST_MODE ? (
|
||||
<table className="table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
|
Reference in New Issue
Block a user