diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a226e60f62..ad38c938d8 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -5286,7 +5286,7 @@ }, "git-up": { "version": "1.2.1", - "resolved": "http://registry.npmjs.org/git-up/-/git-up-1.2.1.tgz", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-1.2.1.tgz", "integrity": "sha1-JkSAoAax2EJhrB/gmjpRacV+oZ0=", "requires": { "is-ssh": "^1.0.0", @@ -5295,7 +5295,7 @@ }, "git-url-parse": { "version": "5.0.1", - "resolved": "http://registry.npmjs.org/git-url-parse/-/git-url-parse-5.0.1.tgz", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-5.0.1.tgz", "integrity": "sha1-/j15xnRq4FBIz6UIyB553du6OEM=", "requires": { "git-up": "^1.0.0" @@ -7858,7 +7858,7 @@ }, "node-status-codes": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=" }, "noop6": { @@ -8165,7 +8165,7 @@ }, "package.json": { "version": "2.0.1", - "resolved": "http://registry.npmjs.org/package.json/-/package.json-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/package.json/-/package.json-2.0.1.tgz", "integrity": "sha1-+IYFnSpJ7QduZIg2ldc7K0bSHW0=", "requires": { "git-package-json": "^1.4.0", @@ -8175,7 +8175,7 @@ "dependencies": { "got": { "version": "5.7.1", - "resolved": "http://registry.npmjs.org/got/-/got-5.7.1.tgz", + "resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz", "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", "requires": { "create-error-class": "^3.0.1", @@ -8197,7 +8197,7 @@ }, "package-json": { "version": "2.4.0", - "resolved": "http://registry.npmjs.org/package-json/-/package-json-2.4.0.tgz", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-2.4.0.tgz", "integrity": "sha1-DRW9Z9HLvduyyiIv8u24a8sxqLs=", "requires": { "got": "^5.0.0", diff --git a/frontend/src/components/shared-repo-list-view/shared-repo-list-item.js b/frontend/src/components/shared-repo-list-view/shared-repo-list-item.js index 869828fe6e..133ee036fe 100644 --- a/frontend/src/components/shared-repo-list-view/shared-repo-list-item.js +++ b/frontend/src/components/shared-repo-list-view/shared-repo-list-item.js @@ -7,6 +7,7 @@ import { Utils } from '../../utils/utils'; import { gettext, siteRoot, isPro, username, folderPermEnabled, isSystemStaff } from '../../utils/constants'; import ModalPotal from '../../components/modal-portal'; import ShareDialog from '../../components/dialog/share-dialog'; +import Rename from '../rename'; const propTypes = { currentGroup: PropTypes.object, @@ -14,8 +15,10 @@ const propTypes = { repo: PropTypes.object.isRequired, isItemFreezed: PropTypes.bool.isRequired, onFreezedItem: PropTypes.func.isRequired, + onUnfreezedItem: PropTypes.func.isRequired, onItemUnshare: PropTypes.func.isRequired, onItmeDetails: PropTypes.func, + onItemRename: PropTypes.func, }; class SharedRepoListItem extends React.Component { @@ -27,6 +30,7 @@ class SharedRepoListItem extends React.Component { isOperationShow: false, isItemMenuShow: false, isShowSharedDialog: false, + isRenaming: false, }; this.isDeparementOnwerGroupMember = false; } @@ -59,23 +63,30 @@ class SharedRepoListItem extends React.Component { } clickOperationMenuToggle = (e) => { - e.preventDefault(); - this.toggleOperationMenu(); + this.toggleOperationMenu(e); } - toggleOperationMenu = () => { - if (this.props.isItemFreezed) { - this.setState({ - highlight: false, - isOperationShow: false, - isItemMenuShow: !this.state.isItemMenuShow - }); - } else { - this.setState({ - isItemMenuShow: !this.state.isItemMenuShow - }); + toggleOperationMenu = (e) => { + let dataset = e.target ? e.target.dataset : null; + if (dataset && dataset.toggle && dataset.toggle === 'Rename') { + this.setState({isItemMenuShow: !this.state.isItemMenuShow}); + return; } - this.props.onFreezedItem(); + + this.setState( + {isItemMenuShow: !this.state.isItemMenuShow}, + () => { + if (this.state.isItemMenuShow) { + this.props.onFreezedItem(); + } else { + this.props.onUnfreezedItem(); + this.setState({ + highlight: false, + isOperationShow: false, + }); + } + } + ); } getRepoComputeParams = () => { @@ -92,7 +103,7 @@ class SharedRepoListItem extends React.Component { let operation = e.target.dataset.toggle; switch(operation) { case 'Rename': - this.onItemRename(); + this.onItemRenameToggle(); break; case 'Folder Permission': this.onItemPermisionChanged(); @@ -111,8 +122,22 @@ class SharedRepoListItem extends React.Component { } } - onItemRename = () => { - // todo + onItemRenameToggle = () => { + this.props.onFreezedItem(); + this.setState({ + isRenaming: !this.state.isRenaming, + isOperationShow: !this.state.isOperationShow + }); + } + + onRenameConfirm = (name) => { + this.props.onItemRename(this.props.repo, name); + this.onRenameCancel(); + } + + onRenameCancel = () => { + this.props.onUnfreezedItem(); + this.setState({isRenaming: !this.state.isRenaming}); } onItemPermisionChanged = () => { @@ -308,7 +333,12 @@ class SharedRepoListItem extends React.Component { {iconTitle} - {repo.repo_name} + + {this.state.isRenaming ? + : + {repo.repo_name} + } + {this.state.isOperationShow && this.generatorPCMenu()} {repo.size} {moment(repo.last_modified).fromNow()} @@ -343,7 +373,11 @@ class SharedRepoListItem extends React.Component { {iconTitle}/ - {repo.repo_name}
+ {this.state.isRenaming ? + : + {repo.repo_name} + } +
{repo.owner_name} {repo.size} {moment(repo.last_modified).fromNow()} diff --git a/frontend/src/components/shared-repo-list-view/shared-repo-list-view.js b/frontend/src/components/shared-repo-list-view/shared-repo-list-view.js index c7dc95da50..6f7af802a1 100644 --- a/frontend/src/components/shared-repo-list-view/shared-repo-list-view.js +++ b/frontend/src/components/shared-repo-list-view/shared-repo-list-view.js @@ -1,7 +1,9 @@ import React, {Fragment} from 'react'; import PropTypes from 'prop-types'; import { gettext } from '../../utils/constants'; +import { Utils } from '../../utils/utils'; import SharedRepoListItem from './shared-repo-list-item'; +import toaster from '../toast'; const propTypes = { libraryType: PropTypes.string, @@ -14,6 +16,7 @@ const propTypes = { onItemUnshare: PropTypes.func.isRequired, onItemDelete: PropTypes.func.isRequired, onItemDetails: PropTypes.func, + onItemRename: PropTypes.func, }; class SharedRepoListView extends React.Component { @@ -48,9 +51,24 @@ class SharedRepoListView extends React.Component { } onFreezedItem = () => { - this.setState({ - isItemFreezed: !this.state.isItemFreezed, + this.setState({isItemFreezed: true}); + } + + onUnfreezedItem = () => { + this.setState({isItemFreezed: false}); + } + + onItemRename = (repo, newName) => { + let isDuplicated = this.props.repoList.some(item => { + return item.name === newName; }); + if (isDuplicated) { + let errMessage = gettext('The name "{name}" is already taken. Please choose a different name.'); + errMessage = errMessage.replace('{name}', Utils.HTMLescape(newName)); + toaster.danger(errMessage); + return false; + } + this.props.onItemRename(repo, newName); } renderRepoListView = () => { @@ -65,9 +83,11 @@ class SharedRepoListView extends React.Component { currentGroup={this.props.currentGroup} isItemFreezed={this.state.isItemFreezed} onFreezedItem={this.onFreezedItem} + onUnfreezedItem={this.onUnfreezedItem} onItemUnshare={this.props.onItemUnshare} onItemDelete={this.props.onItemDelete} onItemDetails={this.props.onItemDetails} + onItemRename={this.props.onItemRename} /> ); })} diff --git a/frontend/src/pages/groups/group-view.js b/frontend/src/pages/groups/group-view.js index 8438943797..61f0a6787b 100644 --- a/frontend/src/pages/groups/group-view.js +++ b/frontend/src/pages/groups/group-view.js @@ -239,6 +239,20 @@ class GroupView extends React.Component { }); } + onItemRename = (repo, newName) => { + seafileAPI.renameGroupOwnedLibrary(this.props.groupID, repo.repo_id, newName).then(res => { + let repoList = this.state.repoList.map(item => { + if (item.repo_id === repo.repo_id) { + item.repo_name = newName; + } + return item; + }); + this.setState({repoList: repoList}); + }).catch(() => { + // todo + }); + } + onTabNavClick = (tabName) => { this.props.onTabNavClick(tabName); } @@ -436,6 +450,7 @@ class GroupView extends React.Component { onItemUnshare={this.onItemUnshare} onItemDelete={this.onItemDelete} onItemDetails={this.onItemDetails} + onItemRename={this.onItemRename} /> } diff --git a/frontend/src/pages/groups/groups-view.js b/frontend/src/pages/groups/groups-view.js index c43928771c..70fcc2f330 100644 --- a/frontend/src/pages/groups/groups-view.js +++ b/frontend/src/pages/groups/groups-view.js @@ -57,6 +57,21 @@ class RepoListViewPanel extends React.Component { // todo; }); } + + onItemRename = (repo, newName) => { + let group = this.props.group; + seafileAPI.renameGroupOwnedLibrary(group.id, repo.repo_id, newName).then(res => { + let repoList = this.state.repoList.map(item => { + if (item.repo_id === repo.repo_id) { + item.repo_name = newName; + } + return item; + }); + this.setState({repoList: repoList}); + }).catch(() => { + // todo + }); + } render() { let group = this.props.group; @@ -76,6 +91,7 @@ class RepoListViewPanel extends React.Component { onItemUnshare={this.onItemUnshare} onItemDelete={this.onItemDelete} onItemDetails={this.props.onItemDetails} + onItemRename={this.onItemRename} /> }