diff --git a/frontend/src/components/cur-dir-path/dir-path.js b/frontend/src/components/cur-dir-path/dir-path.js index eaf5afb5e1..5b638d1256 100644 --- a/frontend/src/components/cur-dir-path/dir-path.js +++ b/frontend/src/components/cur-dir-path/dir-path.js @@ -33,7 +33,6 @@ const propTypes = { direntList: PropTypes.array.isRequired, repoTags: PropTypes.array.isRequired, filePermission: PropTypes.string, - onFileTagChanged: PropTypes.func.isRequired, onItemMove: PropTypes.func.isRequired, loadDirentList: PropTypes.func.isRequired, }; diff --git a/frontend/src/components/dialog/create-tag-dialog.js b/frontend/src/components/dialog/create-tag-dialog.js deleted file mode 100644 index 63c30fa445..0000000000 --- a/frontend/src/components/dialog/create-tag-dialog.js +++ /dev/null @@ -1,126 +0,0 @@ -import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { Button, ModalBody, ModalFooter, Input, Label } from 'reactstrap'; -import { gettext } from '../../utils/constants'; -import { TAG_COLORS } from '../../constants'; -import { seafileAPI } from '../../utils/seafile-api'; -import { Utils } from '../../utils/utils'; -import SeahubModalHeader from '@/components/common/seahub-modal-header'; - -const propTypes = { - repoID: PropTypes.string.isRequired, - onRepoTagCreated: PropTypes.func, - toggleCancel: PropTypes.func.isRequired, - onClose: PropTypes.func.isRequired -}; - -class CreateTagDialog extends React.Component { - constructor(props) { - super(props); - this.state = { - tagName: '', - tagColor: TAG_COLORS[0], - newTag: {}, - errorMsg: '', - }; - } - - inputNewName = (e) => { - this.setState({ - tagName: e.target.value, - }); - if (this.state.errorMsg) { - this.setState({ errorMsg: '' }); - } - }; - - selectTagcolor = (e) => { - this.setState({ - tagColor: e.target.value, - }); - }; - - createTag = () => { - let name = this.state.tagName; - let color = this.state.tagColor; - let repoID = this.props.repoID; - seafileAPI.createRepoTag(repoID, name, color).then((res) => { - let repoTagID = res.data.repo_tag.repo_tag_id; - if (this.props.onRepoTagCreated) this.props.onRepoTagCreated(repoTagID); - this.props.toggleCancel(); - }).catch((error) => { - let errMessage; - if (error.response.status === 500) { - errMessage = gettext('Internal Server Error'); - } else if (error.response.status === 400) { - errMessage = gettext('Tag "{name}" already exists.'); - errMessage = errMessage.replace('{name}', Utils.HTMLescape(name)); - } - this.setState({ errorMsg: errMessage }); - }); - }; - - handleKeyDown = (e) => { - if (e.key === 'Enter') { - this.createTag(); - } - }; - - render() { - let canSave = this.state.tagName.trim() ? true : false; - return ( - - - - {gettext('New Tag')} - - -
-
- - -
{this.state.errorMsg}
-
-
- -
- {TAG_COLORS.map((item, index) => { - return ( -
- -
- ); - }) - } -
-
-
-
- - - {canSave ? - : - - } - -
- ); - } -} - -CreateTagDialog.propTypes = propTypes; - -export default CreateTagDialog; diff --git a/frontend/src/components/dialog/edit-filetag-dialog.js b/frontend/src/components/dialog/edit-filetag-dialog.js deleted file mode 100644 index 3ea407143d..0000000000 --- a/frontend/src/components/dialog/edit-filetag-dialog.js +++ /dev/null @@ -1,220 +0,0 @@ -import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { Button, Modal, ModalBody, ModalFooter } from 'reactstrap'; -import { gettext } from '../../utils/constants'; -import { seafileAPI } from '../../utils/seafile-api'; -import { Utils } from '../../utils/utils'; -import CreateTagDialog from './create-tag-dialog'; -import toaster from '../toast'; -import SeahubModalHeader from '@/components/common/seahub-modal-header'; - -require('../../css/repo-tag.css'); - -const TagItemPropTypes = { - repoID: PropTypes.string.isRequired, - repoTag: PropTypes.object.isRequired, - filePath: PropTypes.string.isRequired, - fileTagList: PropTypes.array.isRequired, - onFileTagChanged: PropTypes.func.isRequired, -}; - -class TagItem extends React.Component { - - constructor(props) { - super(props); - this.state = { - isTagHighlighted: false - }; - } - - onMouseEnter = () => { - this.setState({ - isTagHighlighted: true - }); - }; - - onMouseLeave = () => { - this.setState({ - isTagHighlighted: false - }); - }; - - getRepoTagIdList = () => { - let repoTagIdList = []; - let fileTagList = this.props.fileTagList || []; - repoTagIdList = fileTagList.map((fileTag) => fileTag.repo_tag_id); - return repoTagIdList; - }; - - onEditFileTag = () => { - let { repoID, repoTag, filePath } = this.props; - let repoTagIdList = this.getRepoTagIdList(); - if (repoTagIdList.indexOf(repoTag.id) === -1) { - let id = repoTag.id; - seafileAPI.addFileTag(repoID, filePath, id).then(() => { - repoTagIdList = this.getRepoTagIdList(); - this.props.onFileTagChanged(); - }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - }); - } else { - let fileTag = null; - let fileTagList = this.props.fileTagList; - for (let i = 0; i < fileTagList.length; i++) { - if (fileTagList[i].repo_tag_id === repoTag.id) { - fileTag = fileTagList[i]; - break; - } - } - seafileAPI.deleteFileTag(repoID, fileTag.id).then(() => { - repoTagIdList = this.getRepoTagIdList(); - this.props.onFileTagChanged(); - }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - }); - } - }; - - render() { - const { isTagHighlighted } = this.state; - const { repoTag } = this.props; - const repoTagIdList = this.getRepoTagIdList(); - const isTagSelected = repoTagIdList.indexOf(repoTag.id) != -1; - return ( -
  • -
    - - {repoTag.name} -
    - {isTagSelected && } -
  • - ); - } - -} - -TagItem.propTypes = TagItemPropTypes; - -const TagListPropTypes = { - repoID: PropTypes.string.isRequired, - repoTags: PropTypes.array.isRequired, - filePath: PropTypes.string.isRequired, - fileTagList: PropTypes.array.isRequired, - onFileTagChanged: PropTypes.func.isRequired, - toggleCancel: PropTypes.func.isRequired, - createNewTag: PropTypes.func.isRequired, -}; - -class TagList extends React.Component { - - render() { - const { repoTags } = this.props; - return ( - - {gettext('Select Tags')} - - - - - {gettext('Create a new tag')} - - - - - - - ); - } -} - -TagList.propTypes = TagListPropTypes; - -const propTypes = { - repoID: PropTypes.string.isRequired, - repoTags: PropTypes.array.isRequired, - filePath: PropTypes.string.isRequired, - fileTagList: PropTypes.array.isRequired, - toggleCancel: PropTypes.func.isRequired, - onFileTagChanged: PropTypes.func.isRequired, -}; - -class EditFileTagDialog extends React.Component { - constructor(props) { - super(props); - this.state = { - isCreateRepoTagShow: false, - isListRepoTagShow: true, - }; - } - - createNewTag = () => { - this.setState({ - isCreateRepoTagShow: !this.state.isCreateRepoTagShow, - isListRepoTagShow: !this.state.isListRepoTagShow, - }); - }; - - onRepoTagCreated = (repoTagID) => { - let { repoID, filePath } = this.props; - seafileAPI.addFileTag(repoID, filePath, repoTagID).then(() => { - this.props.onFileTagChanged(); - }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - }); - }; - - render() { - return ( - - {this.state.isListRepoTagShow && - - } - {this.state.isCreateRepoTagShow && - - } - - ); - } -} - -EditFileTagDialog.propTypes = propTypes; - -export default EditFileTagDialog; diff --git a/frontend/src/components/dialog/tag-color.js b/frontend/src/components/dialog/tag-color.js deleted file mode 100644 index e4e0281fa2..0000000000 --- a/frontend/src/components/dialog/tag-color.js +++ /dev/null @@ -1,108 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Popover, PopoverBody } from 'reactstrap'; -import { seafileAPI } from '../../utils/seafile-api'; -import { Utils } from '../../utils/utils'; -import { TAG_COLORS } from '../../constants'; -import toaster from '../toast'; - -import '../../css/repo-tag.css'; - -const tagColorPropTypes = { - tag: PropTypes.object.isRequired, - repoID: PropTypes.string.isRequired -}; - -class TagColor extends React.Component { - - constructor(props) { - super(props); - this.state = { - tagColor: this.props.tag.color, - isPopoverOpen: false - }; - } - - UNSAFE_componentWillReceiveProps(nextProps) { - if (nextProps.tag.color !== this.props.tag.color) { - this.setState({ - tagColor: nextProps.tag.color, - }); - } - } - - togglePopover = () => { - this.setState({ - isPopoverOpen: !this.state.isPopoverOpen - }); - }; - - selectTagColor = (e) => { - const newColor = e.target.value; - const { repoID, tag } = this.props; - const { id, name } = tag; - seafileAPI.updateRepoTag(repoID, id, name, newColor).then(() => { - this.setState({ - tagColor: newColor, - isPopoverOpen: !this.state.isPopoverOpen - }); - }).catch((error) => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - }); - }; - - render() { - const { isPopoverOpen, tagColor } = this.state; - const { tag } = this.props; - const { id, color } = tag; - - let colorList = [...TAG_COLORS]; - // for color from previous color options - if (colorList.indexOf(color) == -1) { - colorList.unshift(color); - } - - return ( -
    - - - - - -
    - {colorList.map((item, index) => { - return ( -
    - -
    - ); - }) - } -
    -
    -
    -
    - ); - } -} - -TagColor.propTypes = tagColorPropTypes; - -export default TagColor; diff --git a/frontend/src/components/dialog/tag-name.js b/frontend/src/components/dialog/tag-name.js deleted file mode 100644 index a5925da2b7..0000000000 --- a/frontend/src/components/dialog/tag-name.js +++ /dev/null @@ -1,99 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { seafileAPI } from '../../utils/seafile-api'; -import { Utils } from '../../utils/utils'; -import toaster from '../toast'; - -import '../../css/repo-tag.css'; - -const tagNamePropTypes = { - tag: PropTypes.object.isRequired, - repoID: PropTypes.string.isRequired -}; - -class TagName extends React.Component { - - constructor(props) { - super(props); - this.state = { - tagName: this.props.tag.name, - isEditing: false - }; - this.input = React.createRef(); - } - - UNSAFE_componentWillReceiveProps(nextProps) { - if (nextProps.tag.name !== this.props.tag.name) { - this.setState({ - tagName: nextProps.tag.name, - }); - } - } - - toggleMode = () => { - this.setState({ - isEditing: !this.state.isEditing - }, () => { - if (this.state.isEditing) { - this.input.current.focus(); - } - }); - }; - - updateTagName = (e) => { - const newName = e.target.value; - const { repoID, tag } = this.props; - const { id, color } = tag; - seafileAPI.updateRepoTag(repoID, id, newName, color).then(() => { - this.setState({ - tagName: newName - }); - }).catch((error) => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - }); - }; - - onInputKeyDown = (e) => { - if (e.key == 'Enter') { - this.toggleMode(); - this.updateTagName(e); - } - else if (e.key == 'Escape') { - e.nativeEvent.stopImmediatePropagation(); - this.toggleMode(); - } - }; - - onInputBlur = (e) => { - this.toggleMode(); - this.updateTagName(e); - }; - - render() { - const { isEditing, tagName } = this.state; - return ( -
    - {isEditing ? - : - {tagName} - - } -
    - ); - } -} - -TagName.propTypes = tagNamePropTypes; - -export default TagName; diff --git a/frontend/src/components/dirent-grid-view/dirent-grid-view.js b/frontend/src/components/dirent-grid-view/dirent-grid-view.js index 20bfc860df..319dc8af88 100644 --- a/frontend/src/components/dirent-grid-view/dirent-grid-view.js +++ b/frontend/src/components/dirent-grid-view/dirent-grid-view.js @@ -15,7 +15,6 @@ 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 Rename from '../../components/dialog/rename-dirent'; import CreateFile from '../dialog/create-file-dialog'; import CreateFolder from '../dialog/create-folder-dialog'; @@ -53,7 +52,6 @@ const propTypes = { updateDirent: PropTypes.func.isRequired, onGridItemClick: PropTypes.func, repoTags: PropTypes.array.isRequired, - onFileTagChanged: PropTypes.func, onAddFolder: PropTypes.func.isRequired, showDirentDetail: PropTypes.func.isRequired, onItemRename: PropTypes.func.isRequired, @@ -80,7 +78,6 @@ class DirentGridView extends React.Component { isShareDialogShow: false, isMoveDialogShow: false, isCopyDialogShow: false, - isEditFileTagShow: false, isZipDialogOpen: false, isRenameDialogShow: false, isCreateFolderDialogShow: false, @@ -376,9 +373,6 @@ class DirentGridView extends React.Component { case 'Convert to sdoc': this.onItemConvert(currentObject, event, 'sdoc'); break; - case 'Tags': - this.onEditFileTagToggle(); - break; case 'Permission': this.onPermissionItem(); break; @@ -453,18 +447,6 @@ class DirentGridView extends React.Component { hideMenu(); }; - onEditFileTagToggle = () => { - this.setState({ - isEditFileTagShow: !this.state.isEditFileTagShow - }); - }; - - onFileTagChanged = () => { - let dirent = this.state.activeDirent ? this.state.activeDirent : ''; - let direntPath = Utils.joinPath(this.props.path, dirent.name); - this.props.onFileTagChanged(dirent, direntPath); - }; - getDirentPath = (dirent) => { let path = this.props.path; return path === '/' ? path + dirent.name : path + '/' + dirent.name; @@ -1004,16 +986,6 @@ class DirentGridView extends React.Component { onAddFolder={this.props.onAddFolder} /> } - {this.state.isEditFileTagShow && - - } {this.state.isShareDialogShow && {}; - } - - loadTags = () => { - seafileAPI.listRepoTags(this.props.repoID).then(res => { - let repotagList = []; - res.data.repo_tags.forEach(item => { - let repo_tag = new RepoTag(item); - repotagList.push(repo_tag); - }); - this.setState({ repotagList }); - }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - }); - }; - - updateTags = (newRepotagList) => { - this.setState({ - repotagList: [...this.state.repotagList, ...newRepotagList], - }); - }; - - onDeleteTag = (tag) => { - const { repoID } = this.props; - const { id: targetTagID } = tag; - seafileAPI.deleteRepoTag(repoID, targetTagID).then((res) => { - this.setState({ - repotagList: this.state.repotagList.filter(tag => tag.id != targetTagID) - }); - }).catch((error) => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - }); - }; - - createVirtualTag = (e) => { - e.preventDefault(); - let { repotagList } = this.state; - let virtual_repo_tag = { - name: '', - color: TAG_COLORS[Math.floor(Math.random() * TAG_COLORS.length)], // generate random tag color for virtual tag - id: `virtual-tag-${uuidv4()}`, - is_virtual: true, - }; - repotagList.push(virtual_repo_tag); - this.setState({ repotagList }); - }; - - deleteVirtualTag = (virtualTag) => { - let { repotagList } = this.state; - let index = repotagList.findIndex(item => item.id === virtualTag.id); - repotagList.splice(index, 1); - this.setState({ repotagList }); - }; - - updateVirtualTag = (virtualTag, data) => { - const repoID = this.props.repoID; - const { repotagList } = this.state; - const index = repotagList.findIndex(item => item.id === virtualTag.id); - if (index < 0) return null; - - // If virtual tag color is updated and virtual tag name is empty, it will be saved to local state, don't save it to the server - if (data.color) { - virtualTag.color = data.color; - repotagList[index] = virtualTag; - this.setState({ repotagList }); - return; - } - - // If virtual tag name is updated and name is not empty, virtual tag color use default, save it to the server - if (data.name && data.name.length > 0) { - let color = virtualTag.color; - let name = data.name; - seafileAPI.createRepoTag(repoID, name, color).then((res) => { - // After saving sag to the server, replace the virtual tag with newly created tag - repotagList[index] = new RepoTag(res.data.repo_tag); - this.setState({ repotagList }); - }).catch((error) => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - }); - } - }; - - render() { - return ( - -
      - {this.state.repotagList.map((repoTag, index) => { - if (repoTag.is_virtual) { - return ( - - ); - } else { - return ( - - ); - } - })} -
    -
    - {gettext('Create a new tag')} -
    - -
    - ); - } -} diff --git a/frontend/src/components/popover/tag-list-footer.js b/frontend/src/components/popover/tag-list-footer.js deleted file mode 100644 index ab0f584922..0000000000 --- a/frontend/src/components/popover/tag-list-footer.js +++ /dev/null @@ -1,137 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { Tooltip } from 'reactstrap'; -import { seafileAPI } from '../../utils/seafile-api'; -import { gettext } from '../../utils/constants'; -import { Utils } from '../../utils/utils'; -import RepoTag from '../../models/repo-tag'; -import toaster from '../toast'; - -export default class TagListFooter extends Component { - - static propTypes = { - repoID: PropTypes.string.isRequired, - toggle: PropTypes.func.isRequired, - repotagList: PropTypes.array.isRequired, - updateTags: PropTypes.func.isRequired, - }; - - constructor(props) { - super(props); - this.state = { - showTooltip: false, - }; - } - - toggleTooltip = () => { - this.setState({ showTooltip: !this.state.showTooltip }); - }; - - onClickImport = () => { - this.importOptionsInput.click(); - }; - - importTagsInputChange = () => { - if (!this.importOptionsInput.files || !this.importOptionsInput.files.length) { - toaster.warning(gettext('Please select a file')); - return; - } - const fileReader = new FileReader(); - fileReader.onload = this.onImportTags.bind(this); - fileReader.onerror = this.onImportTagsError.bind(this); - fileReader.readAsText(this.importOptionsInput.files[0]); - }; - - getValidTags = (tags) => { - let validTags = []; - let tagNameMap = {}; - this.props.repotagList.forEach(tag => tagNameMap[tag.name] = true); - for (let i = 0; i < tags.length; i++) { - if (!tags[i] || typeof tags[i] !== 'object' || !tags[i].name || !tags[i].color) { - continue; - } - if (!tagNameMap[tags[i].name]) { - validTags.push( - { - name: tags[i].name, - color: tags[i].color, - } - ); - tagNameMap[tags[i].name] = true; - } - } - return validTags; - }; - - onImportTags = (event) => { - let tags = []; - try { - tags = JSON.parse(event.target.result); // handle JSON file format is error - } catch (error) { - toaster.danger(gettext('The imported tags are invalid')); - return; - } - if (!Array.isArray(tags) || tags.length === 0) { - toaster.danger(gettext('The imported tags are invalid')); - return; - } - let validTags = this.getValidTags(tags); - if (validTags.length === 0) { - toaster.warning(gettext('The imported tag already exists')); - return; - } - seafileAPI.createRepoTags(this.props.repoID, validTags).then((res) => { - toaster.success(gettext('Tags imported')); - let repotagList = []; - res.data.repo_tags.forEach(item => { - let repo_tag = new RepoTag(item); - repotagList.push(repo_tag); - }); - this.props.updateTags(repotagList); - }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - }); - this.importOptionsInput.value = null; - }; - - onImportTagsError = () => { - toaster.success(gettext('Failed to import tags. Please reupload.')); - }; - - getDownloadUrl = () => { - const tags = this.props.repotagList.map(item => { - return { name: item.name, color: item.color }; - }); - return `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(tags))}`; - }; - - render() { - return ( -
    - - - {gettext('Use the import/export function to transfer tags quickly to another library. (The export is in JSON format.)')} - - this.importOptionsInput = ref} - accept='.json' - className="d-none" - onChange={this.importTagsInputChange} - /> - {gettext('Import tags')} - | - - {gettext('Export tags')} - -
    - ); - } -} diff --git a/frontend/src/components/popover/tag-list-item.js b/frontend/src/components/popover/tag-list-item.js deleted file mode 100644 index ec9ba5d2da..0000000000 --- a/frontend/src/components/popover/tag-list-item.js +++ /dev/null @@ -1,66 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { gettext } from '../../utils/constants'; -import TagColor from '../dialog/tag-color'; -import TagName from '../dialog/tag-name'; - -import '../../css/repo-tag.css'; -import './list-tag-popover.css'; - -const tagListItemPropTypes = { - item: PropTypes.object.isRequired, - repoID: PropTypes.string.isRequired, - onDeleteTag: PropTypes.func.isRequired -}; - -class TagListItem extends React.Component { - - constructor(props) { - super(props); - this.state = { - isTagHighlighted: false - }; - } - - onMouseOver = () => { - this.setState({ - isTagHighlighted: true - }); - }; - - onMouseOut = () => { - this.setState({ - isTagHighlighted: false - }); - }; - - deleteTag = () => { - this.props.onDeleteTag(this.props.item); - }; - - render() { - const { isTagHighlighted } = this.state; - const { item, repoID } = this.props; - return ( -
  • - - - -
  • - ); - } -} - -TagListItem.propTypes = tagListItemPropTypes; - -export default TagListItem; diff --git a/frontend/src/components/popover/virtual-tag-color.js b/frontend/src/components/popover/virtual-tag-color.js deleted file mode 100644 index b720ddd762..0000000000 --- a/frontend/src/components/popover/virtual-tag-color.js +++ /dev/null @@ -1,96 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Popover, PopoverBody } from 'reactstrap'; -import { TAG_COLORS } from '../../constants'; - -import '../../css/repo-tag.css'; - -export default class VirtualTagColor extends React.Component { - - static propTypes = { - updateVirtualTag: PropTypes.func.isRequired, - tag: PropTypes.object.isRequired, - repoID: PropTypes.string.isRequired - }; - - constructor(props) { - super(props); - this.state = { - tagColor: this.props.tag.color, - isPopoverOpen: false - }; - } - - UNSAFE_componentWillReceiveProps(nextProps) { - if (nextProps.tag.color !== this.props.tag.color) { - this.setState({ - tagColor: nextProps.tag.color, - }); - } - } - - togglePopover = () => { - this.setState({ - isPopoverOpen: !this.state.isPopoverOpen - }); - }; - - selectTagColor = (e) => { - const newColor = e.target.value; - this.props.updateVirtualTag(this.props.tag, { color: newColor }); - this.setState({ - tagColor: newColor, - isPopoverOpen: !this.state.isPopoverOpen, - }); - }; - - render() { - const { isPopoverOpen, tagColor } = this.state; - const { tag } = this.props; - const { id, color } = tag; - - let colorList = [...TAG_COLORS]; - // for color from previous color options - if (colorList.indexOf(color) == -1) { - colorList.unshift(color); - } - - return ( -
    - - - - - -
    - {colorList.map((item, index) => { - return ( -
    - -
    - ); - }) - } -
    -
    -
    -
    - ); - } -} diff --git a/frontend/src/components/popover/virtual-tag-list-item.js b/frontend/src/components/popover/virtual-tag-list-item.js deleted file mode 100644 index f5ae5d510e..0000000000 --- a/frontend/src/components/popover/virtual-tag-list-item.js +++ /dev/null @@ -1,59 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { gettext } from '../../utils/constants'; -import VirtualTagColor from './virtual-tag-color'; -import VirtualTagName from './virtual-tag-name'; - -import '../../css/repo-tag.css'; -import './list-tag-popover.css'; - -export default class VirtualTagListItem extends React.Component { - - static propTypes = { - item: PropTypes.object.isRequired, - repoID: PropTypes.string.isRequired, - deleteVirtualTag: PropTypes.func.isRequired, - updateVirtualTag: PropTypes.func.isRequired, - }; - - constructor(props) { - super(props); - this.state = { - isTagHighlighted: false - }; - } - - onMouseOver = () => { - this.setState({ isTagHighlighted: true }); - }; - - onMouseOut = () => { - this.setState({ isTagHighlighted: false }); - }; - - deleteVirtualTag = () => { - this.props.deleteVirtualTag(this.props.item); - }; - - render() { - const { isTagHighlighted } = this.state; - const { item, repoID } = this.props; - return ( -
  • - - - -
  • - ); - } -} diff --git a/frontend/src/components/popover/virtual-tag-name.js b/frontend/src/components/popover/virtual-tag-name.js deleted file mode 100644 index b50dbdf48e..0000000000 --- a/frontend/src/components/popover/virtual-tag-name.js +++ /dev/null @@ -1,90 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import '../../css/repo-tag.css'; - -export default class VirtualTagName extends React.Component { - - static propTypes = { - updateVirtualTag: PropTypes.func.isRequired, - tag: PropTypes.object.isRequired, - repoID: PropTypes.string.isRequired - }; - - constructor(props) { - super(props); - this.state = { - tagName: this.props.tag.name, - isEditing: true, - }; - this.input = React.createRef(); - } - - UNSAFE_componentWillReceiveProps(nextProps) { - if (nextProps.tag.name !== this.props.tag.name) { - this.setState({ - tagName: nextProps.tag.name, - }); - } - } - - componentDidMount() { - setTimeout(() => { - this.input.current.focus(); - }, 1); - } - - toggleMode = () => { - this.setState({ - isEditing: !this.state.isEditing - }); - }; - - updateTagName = (e) => { - const newName = e.target.value; - this.props.updateVirtualTag(this.props.tag, { name: newName }); - this.setState({ - tagName: newName - }); - }; - - onInputKeyDown = (e) => { - if (e.key == 'Enter') { - this.toggleMode(); - this.updateTagName(e); - } - else if (e.key == 'Escape') { - e.nativeEvent.stopImmediatePropagation(); - this.toggleMode(); - } - }; - - onInputBlur = (e) => { - this.toggleMode(); - this.updateTagName(e); - }; - - render() { - const { isEditing, tagName } = this.state; - return ( -
    - {isEditing ? - : - {tagName} - - } -
    - ); - } -} diff --git a/frontend/src/components/toolbar/selected-dirents-toolbar.js b/frontend/src/components/toolbar/selected-dirents-toolbar.js index 7a313e0896..b4b135c843 100644 --- a/frontend/src/components/toolbar/selected-dirents-toolbar.js +++ b/frontend/src/components/toolbar/selected-dirents-toolbar.js @@ -6,7 +6,6 @@ import { seafileAPI } from '../../utils/seafile-api'; import URLDecorator from '../../utils/url-decorator'; import MoveDirentDialog from '../dialog/move-dirent-dialog'; import CopyDirentDialog from '../dialog/copy-dirent-dialog'; -import EditFileTagDialog from '../dialog/edit-filetag-dialog'; import ZipDownloadDialog from '../dialog/zip-download-dialog'; import ShareDialog from '../dialog/share-dialog'; import Rename from '../dialog/rename-dirent'; @@ -23,7 +22,6 @@ const propTypes = { userPerm: PropTypes.string.isRequired, repoID: PropTypes.string.isRequired, repoEncrypted: PropTypes.bool.isRequired, - repoTags: PropTypes.array.isRequired, selectedDirentList: PropTypes.array.isRequired, onItemsMove: PropTypes.func.isRequired, onItemsCopy: PropTypes.func.isRequired, @@ -54,9 +52,7 @@ class SelectedDirentsToolbar extends React.Component { isMultipleOperation: true, showLibContentViewDialogs: false, showShareDialog: false, - showEditFileTagDialog: false, fileTagList: [], - multiFileTagList: [], isRenameDialogOpen: false, isPermissionDialogOpen: false }; @@ -174,9 +170,6 @@ class SelectedDirentsToolbar extends React.Component { case 'Permission': this.onPermissionItem(); break; - case 'Tags': - this.listFileTags(dirent); - break; case 'Lock': this.lockFile(dirent); break; @@ -297,46 +290,17 @@ class SelectedDirentsToolbar extends React.Component { this.setState({ showLibContentViewDialogs: false, showShareDialog: false, - showEditFileTagDialog: false, isRenameDialogOpen: false, isPermissionDialogOpen: false, }); }; - listFileTags = (dirent) => { - let filePath = this.getDirentPath(dirent); - seafileAPI.listFileTags(this.props.repoID, filePath).then(res => { - let fileTagList = res.data.file_tags; - for (let i = 0, length = fileTagList.length; i < length; i++) { - fileTagList[i].id = fileTagList[i].file_tag_id; - } - this.setState({ - fileTagList: fileTagList, - showLibContentViewDialogs: true, - showEditFileTagDialog: true, - }); - }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - }); - }; - - onMenuFileTagChanged = () => { - this.listFileTags(this.props.selectedDirentList[0]); - let length = this.props.selectedDirentList.length; - for (let i = 0; i < length; i++) { - const dirent = this.props.selectedDirentList[i]; - const direntPath = this.getDirentPath(dirent); - this.props.onFilesTagChanged(dirent, direntPath); - } - }; - getDirentPath = (dirent) => { if (dirent) return Utils.joinPath(this.props.path, dirent.name); }; render() { - const { repoID, repoTags, userPerm, selectedDirentList } = this.props; + const { repoID, userPerm, selectedDirentList } = this.props; const dirent = selectedDirentList[0]; const selectedLen = selectedDirentList.length; const direntPath = this.getDirentPath(dirent); @@ -480,18 +444,6 @@ class SelectedDirentsToolbar extends React.Component { />
    } - {this.state.showEditFileTagDialog && - - - - } {this.state.isFileAccessLogDialogOpen && { - this.setState({ isEditTagDialogShow: !this.state.isEditTagDialogShow }); - }; - onHistoryClick = () => { let historyUrl = siteRoot + 'repo/file_revisions/' + this.props.repoID + '/?p=' + Utils.encodePath(this.props.path); location.href = historyUrl; @@ -111,25 +105,6 @@ class ViewFileToolbar extends React.Component { }); } if (filePermission === 'rw') { - /* - let newSubOpList = []; - if (showShareBtn) { - newSubOpList.push({ - 'text': gettext('Share'), - 'onClick': this.onShareToggle - }); - } - newSubOpList.push( - {'text': gettext('Tags'), 'onClick': this.onEditFileTagToggle}, - {'text': gettext('History'), 'onClick': this.onHistoryClick} - ); - - opList.push({ - 'icon': 'more-vertical', - 'text': gettext('More'), - 'subOpList': newSubOpList - }); - */ if (showShareBtn) { opList.push({ 'icon': 'share', @@ -137,9 +112,7 @@ class ViewFileToolbar extends React.Component { 'onClick': this.onShareToggle }); } - opList.push( - { 'icon': 'tag', 'text': gettext('Tags'), 'onClick': this.onEditFileTagToggle }, { 'icon': 'history', 'text': gettext('History'), 'onClick': this.onHistoryClick } ); } @@ -220,18 +193,6 @@ class ViewFileToolbar extends React.Component { /> )} - {this.state.isEditTagDialogShow && ( - - - - )} ); } diff --git a/frontend/src/shared-dir-view.js b/frontend/src/shared-dir-view.js index 5d9c32f5c8..91ad646373 100644 --- a/frontend/src/shared-dir-view.js +++ b/frontend/src/shared-dir-view.js @@ -1,8 +1,7 @@ -import React, { Fragment } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import MD5 from 'MD5'; import { createRoot } from 'react-dom/client'; -import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem, UncontrolledTooltip } from 'reactstrap'; +import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; import Account from './components/common/account'; @@ -1113,14 +1112,6 @@ class Item extends React.Component { render() { const { item, isDesktop, mode } = this.props; const { isIconShown } = this.state; - - let toolTipID = ''; - let tagTitle = ''; - if (item.file_tags && item.file_tags.length > 0) { - toolTipID = MD5(item.file_name).slice(0, 7); - tagTitle = item.file_tags.map(item => item.tag_name).join(' '); - } - if (item.is_dir) { return isDesktop ? (