1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-10 03:11:07 +00:00

refactor dir column view (#6743)

This commit is contained in:
Michael An
2024-09-10 11:46:50 +08:00
committed by GitHub
parent 9d917d8599
commit 9e78a7aa93
20 changed files with 128 additions and 193 deletions

View File

@@ -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>
);
}

View File

@@ -0,0 +1,3 @@
export const LIST_MODE = 'list';
export const GRID_MODE = 'grid';
export const METADATA_MODE = 'metadata';

View File

@@ -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}

View File

@@ -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>
);

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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}

View File

@@ -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>

View File

@@ -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