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 ?