diff --git a/frontend/src/components/dirent-detail/detail-list-view.js b/frontend/src/components/dirent-detail/detail-list-view.js index 701f7ddc6c..2353ddd658 100644 --- a/frontend/src/components/dirent-detail/detail-list-view.js +++ b/frontend/src/components/dirent-detail/detail-list-view.js @@ -6,6 +6,7 @@ import { Utils } from '../../utils/utils'; import EditFileTagDialog from '../dialog/edit-filetag-dialog'; import ModalPortal from '../modal-portal'; import RelatedFileDialogs from '../dialog/related-file-dialogs'; +import { seafileAPI } from '../../utils/seafile-api'; const propTypes = { repoInfo: PropTypes.object.isRequired, @@ -27,6 +28,7 @@ class DetailListView extends React.Component { this.state = { isEditFileTagShow: false, showRelatedFileDialog: false, + repo: {}, }; } @@ -69,6 +71,28 @@ class DetailListView extends React.Component { showRelatedFileDialog: false, }); } + + getRepoInfo = (repoID) => { + seafileAPI.listRepos({type: 'mine'}).then((res) => { + let repoList = res.data.repos; + for (let i = 0, length = repoList.length; i < length; i++) { + if (repoList[i].repo_id === repoID) { + this.setState({ repo: repoList[i] }); + break; + } + } + }); + } + + componentDidMount() { + this.getRepoInfo(this.props.repoID); + } + + componentWillReceiveProps(nextProps) { + if (nextProps.repoID !== this.props.repoID) { + this.getRepoInfo(nextProps.repoID); + } + } render() { let { direntType, direntDetail, fileTagList, relatedFiles } = this.props; @@ -86,6 +110,20 @@ class DetailListView extends React.Component { ); + } else if (direntType === 'repo') { + const repoInfo = this.props.repoInfo; + return ( + + + + + + + + + +
{gettext('File Count')}{repoInfo.file_count}
{gettext('Size')}{repoInfo.size}
{gettext('Last Update')}{moment(this.state.repo.last_modified).format('YYYY-MM-DD')}
+ ); } else { return ( diff --git a/frontend/src/components/dirent-detail/dirent-details.js b/frontend/src/components/dirent-detail/dirent-details.js index 5340ed3473..696601fcca 100644 --- a/frontend/src/components/dirent-detail/dirent-details.js +++ b/frontend/src/components/dirent-detail/dirent-details.js @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Utils } from '../../utils/utils'; import { seafileAPI } from '../../utils/seafile-api'; +import Dirent from '../../models/dirent'; import DetailListView from './detail-list-view'; import RepoInfo from '../../models/repo-info'; import FileTag from '../../models/file-tag'; @@ -25,9 +26,16 @@ class DirentDetail extends React.Component { repoInfo: null, fileTagList: [], relatedFiles: [], + currentFolderDirent: null, }; } + componentWillMount() { + if (!this.props.dirent.name) { + this.getCurrentFolderDirent(); + } + } + componentDidMount() { let { dirent, path, repoID } = this.props; let direntPath = Utils.joinPath(path, dirent.name); @@ -46,7 +54,7 @@ class DirentDetail extends React.Component { updateDetailView = (dirent, direntPath) => { let repoID = this.props.repoID; - if (dirent.type === 'file') { + if (dirent && dirent.type === 'file') { seafileAPI.getFileInfo(repoID, direntPath).then(res => { this.setState({ direntType: 'file', @@ -76,16 +84,44 @@ class DirentDetail extends React.Component { }); } }); - } else { + } else if (this.props.path !== '/') { + const dirPath = dirent.name ? direntPath : this.props.path; + seafileAPI.getDirInfo(repoID, dirPath).then(res => { + this.setState({ + direntType: 'dir', + direntDetail: res.data + }); + }); + } else if (this.props.path === '/' && dirent.name) { seafileAPI.getDirInfo(repoID, direntPath).then(res => { this.setState({ direntType: 'dir', direntDetail: res.data }); }); + } else if (this.props.path === '/' && !dirent.name) { + this.setState({ + direntType: 'repo', + direntDetail: {}, + }); } } + getCurrentFolderDirent = () => { + const path = this.props.path; + const parentPath = path.slice(0, path.lastIndexOf('/')); + seafileAPI.listDir(this.props.repoID, parentPath).then(res => { + try { + res.data.dirent_list.forEach((dirent) => { + if ((dirent.parent_dir + dirent.name) === path) throw dirent; + }); + } catch (dirent) { + let dirent = new Dirent(dirent); + this.setState({ currentFolderDirent: dirent }); + } + }); + } + onFileTagChanged = (dirent, direntPath) => { this.updateDetailView(dirent, direntPath); this.props.onFileTagChanged(dirent, direntPath); @@ -98,9 +134,26 @@ class DirentDetail extends React.Component { } render() { - let { dirent } = this.props; - let smallIconUrl = Utils.getDirentIcon(dirent); - let bigIconUrl = Utils.getDirentIcon(dirent, true); + let { dirent, path, currentRepoInfo } = this.props; + let smallIconUrl, bigIconUrl, direntName; + let folderDirent = this.state.currentFolderDirent; + + if (dirent.name) { + // selected something + smallIconUrl = Utils.getDirentIcon(dirent); + bigIconUrl = Utils.getDirentIcon(dirent, true); + direntName = dirent.name; + } else if (!dirent.name && path === '/') { + // seleted nothing and parent is repo + smallIconUrl = Utils.getLibIconUrl(currentRepoInfo); + bigIconUrl = Utils.getLibIconUrl(currentRepoInfo, true); + direntName = currentRepoInfo.repo_name; + } else if (!dirent.name && path !== '/') { + // select nothing and parent is folder + smallIconUrl = folderDirent && Utils.getDirentIcon(folderDirent); + bigIconUrl = folderDirent && Utils.getDirentIcon(folderDirent, true); + direntName = folderDirent && folderDirent.name; + } return (
@@ -108,7 +161,7 @@ class DirentDetail extends React.Component {
{' '} - {dirent.name} + {direntName}
@@ -121,7 +174,7 @@ class DirentDetail extends React.Component { repoInfo={this.state.repoInfo} path={this.props.path} repoID={this.props.repoID} - dirent={this.props.dirent} + dirent={this.props.dirent || folderDirent} direntType={this.state.direntType} direntDetail={this.state.direntDetail} fileTagList={this.state.fileTagList} diff --git a/frontend/src/components/toolbar/view-mode-toolbar.js b/frontend/src/components/toolbar/view-mode-toolbar.js index f664519207..a83d84b38e 100644 --- a/frontend/src/components/toolbar/view-mode-toolbar.js +++ b/frontend/src/components/toolbar/view-mode-toolbar.js @@ -21,11 +21,16 @@ class ViewModeToolbar extends React.Component { render() { let baseClass = 'btn btn-secondary btn-icon sf-view-mode-btn '; return ( -
- - {/* */} - -
+ +
+ + {/* */} + +
+
+ +
+
); } } diff --git a/frontend/src/css/dirent-detail.css b/frontend/src/css/dirent-detail.css index 59655c6fd6..61d836f2b6 100644 --- a/frontend/src/css/dirent-detail.css +++ b/frontend/src/css/dirent-detail.css @@ -13,6 +13,7 @@ line-height: 2.5rem; background-color: #f9f9f9; border-bottom: 1px solid #e8e8e8; + height: 40px; } .detail-header .detail-control { diff --git a/frontend/src/css/layout.css b/frontend/src/css/layout.css index b6a4e06eee..3c0677b15b 100644 --- a/frontend/src/css/layout.css +++ b/frontend/src/css/layout.css @@ -52,6 +52,7 @@ flex-shrink: 0; background: #f4f4f7; border-bottom: 1px solid #e8e8e8; + z-index: 100; } @media (max-width: 767px) { @@ -140,8 +141,30 @@ } .cur-view-detail { - flex: 0 0 20rem; - display: flex; + display: block; + position: absolute; + right: 0; + background-color: #fff; + width: 300px; + height: calc(100% - 50px); + box-shadow: -1px 0 3px 0 #ccc; + top: 49px; + animation: move .5s ease-in-out 1; +} + +@keyframes move { + from { + right: -500px; + opacity: 0.5; + } + to { + right: 0px; + opacity: 1; + } +} + +.cur-view-detail .detail-container { + height: 100%; } /* for reach/router */ diff --git a/frontend/src/css/toolbar.css b/frontend/src/css/toolbar.css index 3e125d9f25..21af69c1a9 100644 --- a/frontend/src/css/toolbar.css +++ b/frontend/src/css/toolbar.css @@ -61,6 +61,11 @@ border-radius: 0 !important; } +.dirent-detail-btn .sf-view-mode-btn { + font-size: 15px; + border-radius: 3px !important; +} + .sf-view-mode-btn.current-mode { background-color: #ccc !important; color: #fff !important; diff --git a/frontend/src/pages/lib-content-view/lib-content-container.js b/frontend/src/pages/lib-content-view/lib-content-container.js index b7dbf94587..30c31eba75 100644 --- a/frontend/src/pages/lib-content-view/lib-content-container.js +++ b/frontend/src/pages/lib-content-view/lib-content-container.js @@ -83,7 +83,7 @@ class LibContentContainer extends React.Component { constructor(props) { super(props); this.state = { - currentDirent: null, + currentDirent: {}, appMenuType: 'item_op_menu', }; @@ -286,6 +286,7 @@ class LibContentContainer extends React.Component { repoID={repoID} path={this.props.path} dirent={this.state.currentDirent} + currentRepoInfo={this.props.currentRepoInfo} onItemDetailsClose={this.onItemDetailsClose} onFileTagChanged={this.props.onFileTagChanged} /> diff --git a/frontend/src/pages/lib-content-view/lib-content-view.js b/frontend/src/pages/lib-content-view/lib-content-view.js index a5aa45f7d8..359c3f0e25 100644 --- a/frontend/src/pages/lib-content-view/lib-content-view.js +++ b/frontend/src/pages/lib-content-view/lib-content-view.js @@ -83,6 +83,10 @@ class LibContentView extends React.Component { }); } + toggleDirentDetail = () => { + this.setState({ isDirentDetailShow: !this.state.isDirentDetailShow }); + } + closeDirentDetail = () => { this.setState({ isDirentDetailShow: false }); } @@ -538,6 +542,10 @@ class LibContentView extends React.Component { if (mode === this.state.currentMode) { return; } + if (mode === 'detail') { + this.toggleDirentDetail(); + return; + } cookie.save('seafile-view-mode', mode); let path = this.state.path; if (this.state.currentMode === 'column' && this.state.isViewFile) {