1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-01 23:20:51 +00:00

Detail panel (#3232)

* update dirent detail btn

* update icon

* add animation

* update
This commit is contained in:
Michael An
2019-04-10 16:04:26 +08:00
committed by Daniel Pan
parent 49199d7990
commit d1f509e8fd
8 changed files with 149 additions and 15 deletions

View File

@@ -6,6 +6,7 @@ import { Utils } from '../../utils/utils';
import EditFileTagDialog from '../dialog/edit-filetag-dialog'; import EditFileTagDialog from '../dialog/edit-filetag-dialog';
import ModalPortal from '../modal-portal'; import ModalPortal from '../modal-portal';
import RelatedFileDialogs from '../dialog/related-file-dialogs'; import RelatedFileDialogs from '../dialog/related-file-dialogs';
import { seafileAPI } from '../../utils/seafile-api';
const propTypes = { const propTypes = {
repoInfo: PropTypes.object.isRequired, repoInfo: PropTypes.object.isRequired,
@@ -27,6 +28,7 @@ class DetailListView extends React.Component {
this.state = { this.state = {
isEditFileTagShow: false, isEditFileTagShow: false,
showRelatedFileDialog: false, showRelatedFileDialog: false,
repo: {},
}; };
} }
@@ -69,6 +71,28 @@ class DetailListView extends React.Component {
showRelatedFileDialog: false, 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() { render() {
let { direntType, direntDetail, fileTagList, relatedFiles } = this.props; let { direntType, direntDetail, fileTagList, relatedFiles } = this.props;
@@ -86,6 +110,20 @@ class DetailListView extends React.Component {
</tbody> </tbody>
</table> </table>
); );
} else if (direntType === 'repo') {
const repoInfo = this.props.repoInfo;
return (
<table className="table-thead-hidden">
<thead>
<tr><th width="35%"></th><th width="65%"></th></tr>
</thead>
<tbody>
<tr><th>{gettext('File Count')}</th><td>{repoInfo.file_count}</td></tr>
<tr><th>{gettext('Size')}</th><td>{repoInfo.size}</td></tr>
<tr><th>{gettext('Last Update')}</th><td>{moment(this.state.repo.last_modified).format('YYYY-MM-DD')}</td></tr>
</tbody>
</table>
);
} else { } else {
return ( return (
<Fragment> <Fragment>

View File

@@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import Dirent from '../../models/dirent';
import DetailListView from './detail-list-view'; import DetailListView from './detail-list-view';
import RepoInfo from '../../models/repo-info'; import RepoInfo from '../../models/repo-info';
import FileTag from '../../models/file-tag'; import FileTag from '../../models/file-tag';
@@ -25,9 +26,16 @@ class DirentDetail extends React.Component {
repoInfo: null, repoInfo: null,
fileTagList: [], fileTagList: [],
relatedFiles: [], relatedFiles: [],
currentFolderDirent: null,
}; };
} }
componentWillMount() {
if (!this.props.dirent.name) {
this.getCurrentFolderDirent();
}
}
componentDidMount() { componentDidMount() {
let { dirent, path, repoID } = this.props; let { dirent, path, repoID } = this.props;
let direntPath = Utils.joinPath(path, dirent.name); let direntPath = Utils.joinPath(path, dirent.name);
@@ -46,7 +54,7 @@ class DirentDetail extends React.Component {
updateDetailView = (dirent, direntPath) => { updateDetailView = (dirent, direntPath) => {
let repoID = this.props.repoID; let repoID = this.props.repoID;
if (dirent.type === 'file') { if (dirent && dirent.type === 'file') {
seafileAPI.getFileInfo(repoID, direntPath).then(res => { seafileAPI.getFileInfo(repoID, direntPath).then(res => {
this.setState({ this.setState({
direntType: 'file', 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 => { seafileAPI.getDirInfo(repoID, direntPath).then(res => {
this.setState({ this.setState({
direntType: 'dir', direntType: 'dir',
direntDetail: res.data 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) => { onFileTagChanged = (dirent, direntPath) => {
this.updateDetailView(dirent, direntPath); this.updateDetailView(dirent, direntPath);
this.props.onFileTagChanged(dirent, direntPath); this.props.onFileTagChanged(dirent, direntPath);
@@ -98,9 +134,26 @@ class DirentDetail extends React.Component {
} }
render() { render() {
let { dirent } = this.props; let { dirent, path, currentRepoInfo } = this.props;
let smallIconUrl = Utils.getDirentIcon(dirent); let smallIconUrl, bigIconUrl, direntName;
let bigIconUrl = Utils.getDirentIcon(dirent, true); 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 ( return (
<div className="detail-container"> <div className="detail-container">
@@ -108,7 +161,7 @@ class DirentDetail extends React.Component {
<div className="detail-control sf2-icon-x1" onClick={this.props.onItemDetailsClose}></div> <div className="detail-control sf2-icon-x1" onClick={this.props.onItemDetailsClose}></div>
<div className="detail-title dirent-title"> <div className="detail-title dirent-title">
<img src={smallIconUrl} width="24" height="24" alt="" />{' '} <img src={smallIconUrl} width="24" height="24" alt="" />{' '}
<span className="name ellipsis" title={dirent.name}>{dirent.name}</span> <span className="name ellipsis" title={direntName}>{direntName}</span>
</div> </div>
</div> </div>
<div className="detail-body dirent-info"> <div className="detail-body dirent-info">
@@ -121,7 +174,7 @@ class DirentDetail extends React.Component {
repoInfo={this.state.repoInfo} repoInfo={this.state.repoInfo}
path={this.props.path} path={this.props.path}
repoID={this.props.repoID} repoID={this.props.repoID}
dirent={this.props.dirent} dirent={this.props.dirent || folderDirent}
direntType={this.state.direntType} direntType={this.state.direntType}
direntDetail={this.state.direntDetail} direntDetail={this.state.direntDetail}
fileTagList={this.state.fileTagList} fileTagList={this.state.fileTagList}

View File

@@ -21,11 +21,16 @@ class ViewModeToolbar extends React.Component {
render() { render() {
let baseClass = 'btn btn-secondary btn-icon sf-view-mode-btn '; let baseClass = 'btn btn-secondary btn-icon sf-view-mode-btn ';
return ( return (
<div className="view-mode btn-group"> <React.Fragment>
<button className={`${baseClass} sf2-icon-list-view ${this.props.currentMode === 'list' ? 'current-mode' : ''}`} id='list' title={gettext('List')} onClick={this.switchViewMode}></button> <div className="view-mode btn-group">
{/* <button className={`${baseClass} sf2-icon-grid-view ${this.props.currentMode === 'grid' ? 'current-mode' : ''}`} id='grid' title={gettext('Grid')} onClick={this.switchViewMode}></button> */} <button className={`${baseClass} sf2-icon-list-view ${this.props.currentMode === 'list' ? 'current-mode' : ''}`} id='list' title={gettext('List')} onClick={this.switchViewMode}></button>
<button className={`${baseClass} sf2-icon-two-columns ${this.props.currentMode === 'column' ? 'current-mode' : ''}`} id='column' title={gettext('Column')} onClick={this.switchViewMode}></button> {/* <button className={`${baseClass} sf2-icon-grid-view ${this.props.currentMode === 'grid' ? 'current-mode' : ''}`} id='grid' title={gettext('Grid')} onClick={this.switchViewMode}></button> */}
</div> <button className={`${baseClass} sf2-icon-two-columns ${this.props.currentMode === 'column' ? 'current-mode' : ''}`} id='column' title={gettext('Column')} onClick={this.switchViewMode}></button>
</div>
<div className="dirent-detail-btn btn-group">
<button className={`${baseClass} ml-1 fas fa-info`} id='detail' title={gettext('Detail')} onClick={this.switchViewMode}></button>
</div>
</React.Fragment>
); );
} }
} }

View File

@@ -13,6 +13,7 @@
line-height: 2.5rem; line-height: 2.5rem;
background-color: #f9f9f9; background-color: #f9f9f9;
border-bottom: 1px solid #e8e8e8; border-bottom: 1px solid #e8e8e8;
height: 40px;
} }
.detail-header .detail-control { .detail-header .detail-control {

View File

@@ -52,6 +52,7 @@
flex-shrink: 0; flex-shrink: 0;
background: #f4f4f7; background: #f4f4f7;
border-bottom: 1px solid #e8e8e8; border-bottom: 1px solid #e8e8e8;
z-index: 100;
} }
@media (max-width: 767px) { @media (max-width: 767px) {
@@ -140,8 +141,30 @@
} }
.cur-view-detail { .cur-view-detail {
flex: 0 0 20rem; display: block;
display: flex; 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 */ /* for reach/router */

View File

@@ -61,6 +61,11 @@
border-radius: 0 !important; border-radius: 0 !important;
} }
.dirent-detail-btn .sf-view-mode-btn {
font-size: 15px;
border-radius: 3px !important;
}
.sf-view-mode-btn.current-mode { .sf-view-mode-btn.current-mode {
background-color: #ccc !important; background-color: #ccc !important;
color: #fff !important; color: #fff !important;

View File

@@ -83,7 +83,7 @@ class LibContentContainer extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
currentDirent: null, currentDirent: {},
appMenuType: 'item_op_menu', appMenuType: 'item_op_menu',
}; };
@@ -286,6 +286,7 @@ class LibContentContainer extends React.Component {
repoID={repoID} repoID={repoID}
path={this.props.path} path={this.props.path}
dirent={this.state.currentDirent} dirent={this.state.currentDirent}
currentRepoInfo={this.props.currentRepoInfo}
onItemDetailsClose={this.onItemDetailsClose} onItemDetailsClose={this.onItemDetailsClose}
onFileTagChanged={this.props.onFileTagChanged} onFileTagChanged={this.props.onFileTagChanged}
/> />

View File

@@ -83,6 +83,10 @@ class LibContentView extends React.Component {
}); });
} }
toggleDirentDetail = () => {
this.setState({ isDirentDetailShow: !this.state.isDirentDetailShow });
}
closeDirentDetail = () => { closeDirentDetail = () => {
this.setState({ isDirentDetailShow: false }); this.setState({ isDirentDetailShow: false });
} }
@@ -538,6 +542,10 @@ class LibContentView extends React.Component {
if (mode === this.state.currentMode) { if (mode === this.state.currentMode) {
return; return;
} }
if (mode === 'detail') {
this.toggleDirentDetail();
return;
}
cookie.save('seafile-view-mode', mode); cookie.save('seafile-view-mode', mode);
let path = this.state.path; let path = this.state.path;
if (this.state.currentMode === 'column' && this.state.isViewFile) { if (this.state.currentMode === 'column' && this.state.isViewFile) {