diff --git a/frontend/src/components/dirent-detail/file-details.js b/frontend/src/components/dirent-detail/file-details.js new file mode 100644 index 0000000000..d135ec35ee --- /dev/null +++ b/frontend/src/components/dirent-detail/file-details.js @@ -0,0 +1,127 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import moment from 'moment'; +import { siteRoot, gettext } from '../../utils/constants'; +import { seafileAPI } from '../../utils/seafile-api'; +import { Utils } from '../../utils/utils'; +import toaster from '../toast'; +import FileTag from '../../models/file-tag'; + +import '../../css/dirent-detail.css'; + +const propTypes = { + repoID: PropTypes.string.isRequired, + repoName: PropTypes.string.isRequired, + dirent: PropTypes.object.isRequired, + path: PropTypes.string.isRequired, + togglePanel: PropTypes.func.isRequired +}; + +class FileDetails extends React.Component { + + constructor(props) { + super(props); + this.state = { + direntType: '', + direntDetail: '', + fileTagList: [] + }; + } + + componentDidMount() { + let { dirent, path, repoID } = this.props; + let direntPath = Utils.joinPath(path, dirent.name); + seafileAPI.getFileInfo(repoID, direntPath).then(res => { + this.setState({ + direntType: 'file', + direntDetail: res.data + }); + }).catch(error => { + let errMessage = Utils.getErrorMsg(error); + toaster.danger(errMessage); + }); + seafileAPI.listFileTags(repoID, direntPath).then(res => { + let fileTagList = []; + res.data.file_tags.forEach(item => { + let file_tag = new FileTag(item); + fileTagList.push(file_tag); + }); + this.setState({fileTagList: fileTagList}); + }).catch(error => { + let errMessage = Utils.getErrorMsg(error); + toaster.danger(errMessage); + }); + } + + renderHeader = (smallIconUrl, direntName) => { + return ( +
+
+
+ {' '} + {direntName} +
+
+ ); + } + + renderDetailBody = (bigIconUrl) => { + const { direntDetail, fileTagList } = this.state; + const { repoName, path } = this.props; + return ( +
+
+ {this.state.direntDetail && +
+ + + + + + + + + + + + + +
{gettext('Size')}{Utils.bytesToSize(direntDetail.size)}
{gettext('Location')}{repoName + path}
{gettext('Last Update')}{moment(direntDetail.last_modified).fromNow()}
{gettext('Tags')} +
    + {fileTagList.map((fileTag) => { + return ( +
  • + + {fileTag.name} +
  • + ); + })} +
+
+
+ } +
+ ); + } + + render() { + let { dirent, repoID, path } = this.props; + + const smallIconUrl = Utils.getFileIconUrl(dirent.name); + let bigIconUrl = Utils.getFileIconUrl(dirent.name, 192); + const isImg = Utils.imageCheck(dirent.name); + if (isImg) { + bigIconUrl = `${siteRoot}thumbnail/${repoID}/1024` + Utils.encodePath(`${path === '/' ? '' : path}/${dirent.name}`); + } + return ( +
+ {this.renderHeader(smallIconUrl, dirent.name)} + {this.renderDetailBody(bigIconUrl)} +
+ ); + } +} + +FileDetails.propTypes = propTypes; + +export default FileDetails; diff --git a/frontend/src/components/file-view/file-toolbar.js b/frontend/src/components/file-view/file-toolbar.js index 07ce459d13..7a12ab5dd0 100644 --- a/frontend/src/components/file-view/file-toolbar.js +++ b/frontend/src/components/file-view/file-toolbar.js @@ -1,6 +1,6 @@ import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; -import { ButtonGroup, Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; +import { ButtonGroup, ButtonDropdown, Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; import IconButton from '../icon-button'; import { gettext, siteRoot } from '../../utils/constants'; import { Utils } from '../../utils/utils'; @@ -14,11 +14,12 @@ const propTypes = { isSaving: PropTypes.bool, needSave: PropTypes.bool, toggleLockFile: PropTypes.func.isRequired, - toggleCommentPanel: PropTypes.func.isRequired + toggleCommentPanel: PropTypes.func.isRequired, + toggleDetailsPanel: PropTypes.func.isRequired }; const { - canLockUnlockFile, canGenerateShareLink, + canLockUnlockFile, repoID, repoName, repoEncrypted, parentDir, filePerm, filePath, fileName, canEditFile, err, @@ -32,7 +33,8 @@ class FileToolbar extends React.Component { super(props); this.state = { dropdownOpen: false, - isShareDialogOpen: false + moreDropdownOpen: false, + isShareDialogOpen: false, }; } @@ -40,14 +42,25 @@ class FileToolbar extends React.Component { this.setState({isShareDialogOpen: !this.state.isShareDialogOpen}); } + toggleMoreOpMenu = () => { + this.setState({ + moreDropdownOpen: !this.state.moreDropdownOpen + }); + } + toggle = () => { this.setState({ dropdownOpen: !this.state.dropdownOpen }); } + openFileViaClient = () => { + location.href = `seafile://openfile?repo_id=${encodeURIComponent(repoID)}&path=${encodeURIComponent(filePath)}`; + } + render() { const { isLocked, lockedByMe } = this.props; + const { moreDropdownOpen } = this.state; let showLockUnlockBtn = false; let lockUnlockText, lockUnlockIcon; if (canLockUnlockFile) { @@ -95,15 +108,7 @@ class FileToolbar extends React.Component { onClick={this.toggleShareDialog} /> )} - {filePerm == 'rw' && ( - - )} + {(canEditFile && !err) && ( this.props.isSaving ?