diff --git a/frontend/src/components/dir-view-mode/dir-column-nav.js b/frontend/src/components/dir-view-mode/dir-column-nav.js index a46b40766d..159d7a2207 100644 --- a/frontend/src/components/dir-view-mode/dir-column-nav.js +++ b/frontend/src/components/dir-view-mode/dir-column-nav.js @@ -12,6 +12,9 @@ import CreateFile from '../../components/dialog/create-file-dialog'; import ImageDialog from '../../components/dialog/image-dialog'; import { siteRoot, thumbnailSizeForOriginal } from '../../utils/constants'; import { Utils } from '../../utils/utils'; +import EditFileTagDialog from '../dialog/edit-filetag-dialog'; +import FileTag from '../../models/file-tag'; +import { seafileAPI } from '../../utils/seafile-api'; const propTypes = { currentPath: PropTypes.string.isRequired, @@ -31,6 +34,7 @@ const propTypes = { inResizing: PropTypes.bool.isRequired, currentRepoInfo: PropTypes.object.isRequired, selectedDirentList: PropTypes.array.isRequired, + onFileTagChanged: PropTypes.func, }; class DirColumnNav extends React.Component { @@ -49,12 +53,18 @@ class DirColumnNav extends React.Component { isCopyDialogShow: false, isMoveDialogShow: false, isMutipleOperation: false, + isEditFileTagShow: false, + fileTagList: [], + nodeDirent: '', }; this.isNodeMenuShow = true; } componentWillReceiveProps(nextProps) { this.setState({opNode: nextProps.currentNode}); + if (this.state.nodeDirent.object) { + this.getTagFileList(this.state.nodeDirent); + } } onNodeClick = (node) => { @@ -92,6 +102,9 @@ class DirColumnNav extends React.Component { case 'Copy': this.onCopyToggle(); break; + case 'Tags': + this.onEditFileTagToggle(node); + break; case 'Move': this.onMoveToggle(); break; @@ -101,6 +114,51 @@ class DirColumnNav extends React.Component { } } + onEditFileTagToggle = (node) => { + this.setState({ + isEditFileTagShow: !this.state.isEditFileTagShow, + nodeDirent: node, + }); + if (node.object) { + this.getTagFileList(node); + } + } + + onFileTagChanged = () => { + let currentPath; + + if (this.props.currentPath.charAt(this.props.currentPath.length - 1) === '/') { + currentPath = Utils.joinPath(this.props.currentPath, this.state.nodeDirent.object.name); + } else { + currentPath = this.props.currentPath; + } + + if (this.props.currentPath !== '/') { + if (currentPath === this.state.nodeDirent.path) { + this.props.onToolbarFileTagChanged(); + } + } + + if (this.props.currentPath !== this.state.nodeDirent.parentNode.path) { + this.getTagFileList(this.state.nodeDirent); + return; + } + + this.props.onFileTagChanged(this.state.nodeDirent.object, this.state.nodeDirent.path); + } + + getTagFileList = (node) => { + let {repoID} = this.props; + seafileAPI.listFileTags(repoID, node.path).then(res => { + let fileTagList = []; + res.data.file_tags.forEach(item => { + let file_tag = new FileTag(item); + fileTagList.push(file_tag); + }); + this.setState({fileTagList: fileTagList}); + }); + } + onAddFileToggle = (type) => { if (type === 'root') { let root = this.props.treeData.root; @@ -338,6 +396,15 @@ class DirColumnNav extends React.Component { /> )} + {this.state.isEditFileTagShow && + + } {this.state.isNodeImagePopupOpen && (
@@ -224,6 +227,7 @@ class DirColumnView extends React.Component { onItemsMove={this.props.onItemsMove} onItemsCopy={this.props.onItemsCopy} onItemsDelete={this.props.onItemsDelete} + onFileTagChanged={this.props.onFileTagChanged} /> )}
diff --git a/frontend/src/components/dir-view-mode/dir-list-view.js b/frontend/src/components/dir-view-mode/dir-list-view.js index 1ee02f0fd7..4a298a12b5 100644 --- a/frontend/src/components/dir-view-mode/dir-list-view.js +++ b/frontend/src/components/dir-view-mode/dir-list-view.js @@ -37,6 +37,7 @@ const propTypes = { onItemsMove: PropTypes.func.isRequired, onItemsCopy: PropTypes.func.isRequired, onItemsDelete: PropTypes.func.isRequired, + onFileTagChanged: PropTypes.func, }; class DirListView extends React.Component { @@ -94,6 +95,7 @@ class DirListView extends React.Component { onItemsDelete={this.props.onItemsDelete} onAddFile={this.props.onAddFile} onAddFolder={this.props.onAddFolder} + onFileTagChanged={this.props.onFileTagChanged} /> ); diff --git a/frontend/src/components/dirent-list-view/dirent-list-item.js b/frontend/src/components/dirent-list-view/dirent-list-item.js index d3b750556c..a0214674de 100644 --- a/frontend/src/components/dirent-list-view/dirent-list-item.js +++ b/frontend/src/components/dirent-list-view/dirent-list-item.js @@ -13,6 +13,7 @@ import MoveDirentDialog from '../dialog/move-dirent-dialog'; import CopyDirentDialog from '../dialog/copy-dirent-dialog'; import ShareDialog from '../dialog/share-dialog'; import ZipDownloadDialog from '../dialog/zip-download-dialog'; +import EditFileTagDialog from '../dialog/edit-filetag-dialog'; import '../../css/dirent-list-item.css'; @@ -60,6 +61,7 @@ class DirentListItem extends React.Component { isShowTagTooltip: false, isDragTipShow: false, isDropTipshow: false, + isEditFileTagShow: false, }; } @@ -190,6 +192,9 @@ class DirentListItem extends React.Component { case 'Copy': this.onItemCopyToggle(); break; + case 'Tags': + this.onEditFileTagToggle(); + break; case 'Permission': this.onPermissionItem(); break; @@ -216,6 +221,17 @@ class DirentListItem extends React.Component { } } + onEditFileTagToggle = () => { + this.setState({ + isEditFileTagShow: !this.state.isEditFileTagShow + }); + } + + onFileTagChanged = () => { + let direntPath = this.getDirentPath(this.props.dirent); + this.props.onFileTagChanged(this.props.dirent, direntPath); + } + onItemRenameToggle = () => { this.props.onItemRenameToggle(this.props.dirent); this.setState({ @@ -557,6 +573,15 @@ class DirentListItem extends React.Component { />
} + {this.state.isEditFileTagShow && + + } {this.state.isZipDialogOpen && { let { path, repoID, selectedDirentList } = this.props; if (selectedDirentList.length) { @@ -454,7 +456,7 @@ class DirentListView extends React.Component { contextmenuList = this.props.showShareBtn ? [SHARE, DOWNLOAD, DELETE, 'Divider'] : [DOWNLOAD, DELETE, 'Divider']; } - let { RENAME, MOVE, COPY, PERMISSION, OPEN_VIA_CLIENT, LOCK, UNLOCK, COMMENT, HISTORY, ACCESS_LOG } = TextTranslation; + let { RENAME, MOVE, COPY, PERMISSION, OPEN_VIA_CLIENT, LOCK, UNLOCK, COMMENT, HISTORY, ACCESS_LOG, TAGS } = TextTranslation; if (type === 'dir' && permission === 'rw') { if (can_set_folder_perm) { menuList = [...contextmenuList, RENAME, MOVE, COPY, 'Divider', PERMISSION, 'Divider', OPEN_VIA_CLIENT]; @@ -476,6 +478,7 @@ class DirentListView extends React.Component { menuList.push(MOVE); } menuList.push(COPY); + menuList.push(TAGS); if (isPro) { if (dirent.is_locked) { if (dirent.locked_by_me || (dirent.lock_owner === 'OnlineOffice' && permission === 'rw')) { @@ -573,6 +576,7 @@ class DirentListView extends React.Component { onItemContextMenu={this.onItemContextMenu} selectedDirentList={this.props.selectedDirentList} activeDirent={this.state.activeDirent} + onFileTagChanged={this.props.onFileTagChanged} /> ); })} diff --git a/frontend/src/components/tree-view/tree-node-view.js b/frontend/src/components/tree-view/tree-node-view.js index 3ec9e6cc67..045966336b 100644 --- a/frontend/src/components/tree-view/tree-node-view.js +++ b/frontend/src/components/tree-view/tree-node-view.js @@ -67,7 +67,8 @@ class TreeNodeView extends React.Component { this.props.onNodeClick(this.props.node); } - onLoadToggle = () => { + onLoadToggle = (e) => { + e.stopPropagation(); let { node } = this.props; if (node.isExpanded) { this.props.onNodeCollapse(node); diff --git a/frontend/src/components/tree-view/tree-node.js b/frontend/src/components/tree-view/tree-node.js index d8e5bc3957..da86841362 100644 --- a/frontend/src/components/tree-view/tree-node.js +++ b/frontend/src/components/tree-view/tree-node.js @@ -2,7 +2,7 @@ class TreeNode { constructor({ path, object, isLoaded, isPreload, isExpanded, parentNode }) { this.path = path || object.name, // The default setting is the object name, which is set to a relative path when the father is set. - this.object = object.clone(); + this.object = object; this.isLoaded = isLoaded || false; this.isPreload = isPreload || false; this.isExpanded = isExpanded || false; diff --git a/frontend/src/components/tree-view/tree-view.js b/frontend/src/components/tree-view/tree-view.js index 5ff8b26e95..d3eaf9f88c 100644 --- a/frontend/src/components/tree-view/tree-view.js +++ b/frontend/src/components/tree-view/tree-view.js @@ -168,7 +168,7 @@ class TreeView extends React.Component { getMenuList = (node) => { let menuList = []; - let { NEW_FOLDER, NEW_FILE, COPY, MOVE, RENAME, DELETE, OPEN_VIA_CLIENT} = TextTranslation; + let { NEW_FOLDER, NEW_FILE, COPY, MOVE, RENAME, DELETE, OPEN_VIA_CLIENT, TAGS} = TextTranslation; if (!node) { return [NEW_FOLDER, NEW_FILE]; @@ -177,7 +177,7 @@ class TreeView extends React.Component { if (node.object.type === 'dir') { menuList = [NEW_FOLDER, NEW_FILE, COPY, MOVE, RENAME, DELETE]; } else { - menuList = [RENAME, DELETE, COPY, MOVE, OPEN_VIA_CLIENT]; + menuList = [RENAME, DELETE, COPY, MOVE, TAGS, OPEN_VIA_CLIENT]; } return menuList; 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 883a0bf201..0e1ffc066c 100644 --- a/frontend/src/pages/lib-content-view/lib-content-container.js +++ b/frontend/src/pages/lib-content-view/lib-content-container.js @@ -187,6 +187,7 @@ class LibContentContainer extends React.Component { onItemsMove={this.props.onItemsMove} onItemsCopy={this.props.onItemsCopy} onItemsDelete={this.props.onItemsDelete} + onFileTagChanged={this.props.onFileTagChanged} /> )} {this.props.currentMode === 'grid' && ( @@ -250,6 +251,8 @@ class LibContentContainer extends React.Component { onItemsMove={this.props.onItemsMove} onItemsCopy={this.props.onItemsCopy} onItemsDelete={this.props.onItemsDelete} + onFileTagChanged={this.props.onFileTagChanged} + onToolbarFileTagChanged={this.props.onToolbarFileTagChanged} /> )} 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 fcaff31239..68bc24ddcc 100644 --- a/frontend/src/pages/lib-content-view/lib-content-view.js +++ b/frontend/src/pages/lib-content-view/lib-content-view.js @@ -1031,7 +1031,8 @@ class LibContentView extends React.Component { let results = {}; for (let i = 0; i < direntList.length; i++) { let object = direntList[i]; - let key = object.parent_dir; + let parentDir = object.parent_dir; + let key = parentDir === '/' ? '/' : parentDir.slice(0, parentDir.length - 1); if (!results[key]) { results[key] = []; } @@ -1444,6 +1445,7 @@ class LibContentView extends React.Component { closeDirentDetail={this.closeDirentDetail} showDirentDetail={this.showDirentDetail} onDeleteRepoTag={this.onDeleteRepoTag} + onToolbarFileTagChanged={this.onToolbarFileTagChanged} /> {this.state.pathExist && !this.state.isViewFile && (