diff --git a/frontend/src/components/cur-dir-path/dir-tool.js b/frontend/src/components/cur-dir-path/dir-tool.js index 8144c17347..a909fd98a0 100644 --- a/frontend/src/components/cur-dir-path/dir-tool.js +++ b/frontend/src/components/cur-dir-path/dir-tool.js @@ -5,6 +5,7 @@ import PropTypes from 'prop-types'; import ListTagDialog from '../dialog/list-tag-dialog'; import CreateTagDialog from '../dialog/create-tag-dialog'; import UpdateTagDialog from '../dialog/update-tag-dialog'; +import ListTaggedFilesDialog from '../dialog/list-taggedfiles-dialog'; const propTypes = { repoID: PropTypes.string.isRequired, @@ -22,6 +23,7 @@ class DirTool extends React.Component { isListRepoTagShow: false, isUpdateRepoTagShow: false, isCreateRepoTagShow: false, + isListTaggedFileShow: false, }; } @@ -44,6 +46,14 @@ class DirTool extends React.Component { }); } + onListTaggedFileToggle = (currentTag) => { + this.setState({ + currentTag: currentTag, + isListRepoTagShow: !this.state.isListRepoTagShow, + isListTaggedFileShow: !this.state.isListTaggedFileShow, + }); + } + isMarkdownFile(filePath) { let name = Utils.getFileName(filePath); return name.indexOf('.md') > -1 ? true : false; @@ -70,6 +80,7 @@ class DirTool extends React.Component { onListTagCancel={this.onListRepoTagToggle} onCreateRepoTag={this.onCreateRepoTagToggle} onUpdateRepoTag={this.onUpdateRepoTagToggle} + onListFileCancel={this.onListTaggedFileToggle} /> } { @@ -87,6 +98,13 @@ class DirTool extends React.Component { toggleCancel={this.onUpdateRepoTagToggle} /> } + { + this.state.isListTaggedFileShow && + + } ); } else if (!isFile && permission) { diff --git a/frontend/src/components/dialog/list-tag-dialog.js b/frontend/src/components/dialog/list-tag-dialog.js index 3e2a73b924..d41ee170cd 100644 --- a/frontend/src/components/dialog/list-tag-dialog.js +++ b/frontend/src/components/dialog/list-tag-dialog.js @@ -9,19 +9,27 @@ import '../../css/repo-tag.css'; const tagListItemPropTypes = { item: PropTypes.object.isRequired, onTagUpdate: PropTypes.func.isRequired, + onListFileCancel: PropTypes.func.isRequired, }; class TagListItem extends React.Component { - + onTagUpdate = () => { this.props.onTagUpdate(this.props.item); } + onListFileCancel = () => { + this.props.onListFileCancel(this.props.item) + } + render() { let color = this.props.item.color; return(
  • - {this.props.item.name} + + {this.props.item.name} + {this.props.item.fileCount} +
  • ); @@ -35,6 +43,7 @@ const listTagPropTypes = { onListTagCancel: PropTypes.func.isRequired, onCreateRepoTag: PropTypes.func.isRequired, onUpdateRepoTag: PropTypes.func.isRequired, + onListFileCancel: PropTypes.func.isRequired, }; class ListTagDialog extends React.Component { @@ -79,7 +88,9 @@ class ListTagDialog extends React.Component { diff --git a/frontend/src/components/dialog/list-taggedfiles-dialog.js b/frontend/src/components/dialog/list-taggedfiles-dialog.js new file mode 100644 index 0000000000..27cb1aba09 --- /dev/null +++ b/frontend/src/components/dialog/list-taggedfiles-dialog.js @@ -0,0 +1,87 @@ +import React, { Fragment } from 'react'; +import PropTypes from 'prop-types'; +import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; +import { gettext, repoID } from '../../utils/constants'; +import { seafileAPI } from '../../utils/seafile-api'; +import moment from 'moment'; +import { Utils } from '../../utils/utils'; + +const propTypes = { + repoTagId: PropTypes.number.isRequired, + toggleCancel: PropTypes.func.isRequired, +}; + +class ListTaggedFilesDialog extends React.Component { + + constructor(props) { + super(props); + this.state = { + taggedFileList: [], + }; + } + + componentDidMount() { + this.getTaggedFiles(); + } + + getTaggedFiles = () => { + let repoTagId = this.props.repoTagId; + seafileAPI.listTaggedFiles(repoID, repoTagId).then(res => { + let taggedFileList = []; + res.data.tagged_files !== undefined && + res.data.tagged_files.forEach(file => { + let taggedFile = file; + taggedFileList.push(taggedFile) + }); + this.setState({ + taggedFileList: taggedFileList, + }) + }); + } + + toggle = () => { + this.props.toggleCancel(); + } + + render() { + let taggedFileList = this.state.taggedFileList; + return ( + + {gettext('Tagged Files')} + + { + + + + + + + + + + + {taggedFileList.map((taggedFile, index) => { + return ( + + + + + + + ); + })} + +
    {gettext('Name')}{gettext('Size')}{gettext('Last Update')}{gettext('Parent Path')}
    {taggedFile.filename}{Utils.bytesToSize(taggedFile.size)}{moment.unix(taggedFile.mtime).fromNow()}{taggedFile.parent_path}
    + } +
    + + + +
    + ); + } +} + +ListTaggedFilesDialog.propTypes = propTypes; + +export default ListTaggedFilesDialog; diff --git a/frontend/src/models/repo-tag.js b/frontend/src/models/repo-tag.js index 1571358d69..e9c8783ece 100644 --- a/frontend/src/models/repo-tag.js +++ b/frontend/src/models/repo-tag.js @@ -1,7 +1,7 @@ class RepoTag { constructor(object) { this.id = object.repo_tag_id; - this.repo_id = object.repo_id; + this.fileCount = object.files_count; this.name = object.tag_name; this.color = object.tag_color; } diff --git a/seahub/utils/file_tags.py b/seahub/utils/file_tags.py index b6ffa587f2..0b19003ac3 100644 --- a/seahub/utils/file_tags.py +++ b/seahub/utils/file_tags.py @@ -48,6 +48,7 @@ def get_tagged_files(repo, repo_tag_id): tagged_file["parent_path"] = parent_path tagged_file["filename"] = filename tagged_file["size"] = file_obj.size + tagged_file["mtime"] = file_obj.mtime tagged_file["last_modified"] = timestamp_to_isoformat_timestr(file_obj.mtime) tagged_file["modifier_email"] = file_obj.modifier tagged_file["modifier_contact_email"] = email2contact_email(file_obj.modifier)