diff --git a/frontend/src/components/dialog/transfer-dialog.js b/frontend/src/components/dialog/transfer-dialog.js index 4fb656d305..24f1af273e 100644 --- a/frontend/src/components/dialog/transfer-dialog.js +++ b/frontend/src/components/dialog/transfer-dialog.js @@ -1,14 +1,11 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; -import toaster from '../toast'; import { gettext } from '../../utils/constants'; -import { seafileAPI } from '../../utils/seafile-api.js'; import UserSelect from '../user-select'; const propTypes = { itemName: PropTypes.string.isRequired, - repoID: PropTypes.string.isRequired, toggleDialog: PropTypes.func.isRequired, submit: PropTypes.func.isRequired, }; @@ -30,17 +27,8 @@ class TransferDialog extends React.Component { } submit = () => { - let repoID = this.props.repoID; - let user = this.state.selectedOption.email; - seafileAPI.transferRepo(repoID, user).then(res => { - let message = gettext('Successfully transferred the library.'); - toaster.success(message); - this.props.submit(repoID); - }).catch(res => { - let message = gettext('Failed. Please check the network.'); - this.props.toggleDialog(); - toaster.danger(message); - }); + let user = this.state.selectedOption; + this.props.submit(user); } render() { diff --git a/frontend/src/components/draft-list-view/draft-list-item.js b/frontend/src/components/draft-list-view/draft-list-item.js index d928319d94..64326d792c 100644 --- a/frontend/src/components/draft-list-view/draft-list-item.js +++ b/frontend/src/components/draft-list-view/draft-list-item.js @@ -81,7 +81,6 @@ class DraftListItem extends React.Component { let fileName = Utils.getFileName(filePath); let draftUrl = siteRoot + 'drafts/' + draft.id + '/'; let libraryUrl = siteRoot + 'library/' + repoID + '/' + encodeURIComponent(draft.repo_name) + '/' ; - let reviewUrl = siteRoot + 'drafts/review/' + draft.review_id + '/'; let localTime = moment.utc(draft.updated_at).toDate(); localTime = moment(localTime).fromNow(); diff --git a/frontend/src/models/org-admin-repo.js b/frontend/src/models/org-admin-repo.js new file mode 100644 index 0000000000..31d49b59c8 --- /dev/null +++ b/frontend/src/models/org-admin-repo.js @@ -0,0 +1,15 @@ +import { Utils } from '../utils/utils'; + +class OrgAdminRepo { + constructor(object) { + this.repoID = object.repo_id; + this.repoName = object.repo_name; + this.ownerName = object.owner_name; + this.ownerEmail = object.owner_email; + this.encrypted = object.encrypted; + this.isDepartmentRepo = object.is_department_repo; + this.groupID = object.group_id; + } +} + +export default OrgAdminRepo; diff --git a/frontend/src/pages/drafts/draft-content.js b/frontend/src/pages/drafts/draft-content.js index ec651b2b6f..39a99c3b37 100644 --- a/frontend/src/pages/drafts/draft-content.js +++ b/frontend/src/pages/drafts/draft-content.js @@ -1,5 +1,5 @@ import React, { Fragment } from 'react'; -import { siteRoot, gettext } from '../../utils/constants'; +import { gettext } from '../../utils/constants'; import editUtilties from '../../utils/editor-utilties'; import { Utils } from '../../utils/utils'; import PropTypes from 'prop-types'; diff --git a/frontend/src/pages/my-libs/mylib-repo-list-item.js b/frontend/src/pages/my-libs/mylib-repo-list-item.js index b56f756259..9021e48b93 100644 --- a/frontend/src/pages/my-libs/mylib-repo-list-item.js +++ b/frontend/src/pages/my-libs/mylib-repo-list-item.js @@ -8,6 +8,7 @@ import { seafileAPI } from '../../utils/seafile-api'; import { gettext, siteRoot, storages } from '../../utils/constants'; import ModalPortal from '../../components/modal-portal'; import ShareDialog from '../../components/dialog/share-dialog'; +import toaster from '../../components/toast'; import DeleteRepoDialog from '../../components/dialog/delete-repo-dialog'; import TransferDialog from '../../components/dialog/transfer-dialog'; import LibHistorySettingDialog from '../../components/dialog/lib-history-setting-dialog'; @@ -175,9 +176,18 @@ class MylibRepoListItem extends React.Component { this.setState({isRenaming: !this.state.isRenaming}); } - onTransferRepo = (repoID) => { + onTransferRepo = (user) => { + let repoID = this.props.repo.repo_id; + seafileAPI.transferRepo(repoID, user.email).then(res => { + this.props.onTransferRepo(repoID); + let message = gettext('Successfully transferred the library.'); + toaster.success(message); + }).catch(res => { + let message = gettext('Failed. Please check the network.'); + toaster.danger(message); + }); + this.onTransferToggle(); - this.props.onTransferRepo(repoID); } onDeleteRepo = (repo) => { @@ -316,7 +326,6 @@ class MylibRepoListItem extends React.Component { {this.state.isTransferDialogShow && ( - - + + diff --git a/frontend/src/pages/org-admin/org-admin-list.js b/frontend/src/pages/org-admin/org-admin-list.js index 25d6fff818..495d7eeead 100644 --- a/frontend/src/pages/org-admin/org-admin-list.js +++ b/frontend/src/pages/org-admin/org-admin-list.js @@ -83,18 +83,18 @@ class OrgAdminList extends React.Component { let orgAdminUsers = this.state.orgAdminUsers; return ( -
- - - - - - - - - - - +
+
{gettext('Name')}{gettext('Status')}{gettext('Space Used')}{gettext('Create At / Last Login')}{gettext('Operations')}
+ + + + + + + + + + {orgAdminUsers.map(item => { return ( )})} - -
{gettext('Name')}{gettext('Status')}{gettext('Space Used')}{gettext('Create At / Last Login')}{gettext('Operations')}
- {this.props.isShowAddOrgAdminDialog && ( - - - - )} + + + {this.props.isShowAddOrgAdminDialog && ( + + + + )}
); } diff --git a/frontend/src/pages/org-admin/org-groups.js b/frontend/src/pages/org-admin/org-groups.js index cabb6e8ded..91f498ede8 100644 --- a/frontend/src/pages/org-admin/org-groups.js +++ b/frontend/src/pages/org-admin/org-groups.js @@ -1,5 +1,4 @@ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; import OrgGroupInfo from '../../models/org-group'; @@ -14,10 +13,10 @@ class OrgGroups extends Component { super(props); this.state = { page: 1, - pageNext: 2, + pageNext: false, orgGroups: [], isItemFreezed: false - } + }; } componentDidMount() { @@ -68,7 +67,7 @@ class OrgGroups extends Component { let msg = gettext('Successfully deleted {name}'); msg = msg.replace('{name}', group.groupName); Toast.success(msg); - }) + }); } render() { @@ -76,8 +75,8 @@ class OrgGroups extends Component { return (
-
-

{gettext('All Groups')}

+
+

{gettext('All Groups')}

@@ -104,8 +103,9 @@ class OrgGroups extends Component {
- {this.state.page != 1 && this.onChangePageNum(e, -1)}>{gettext("Previous")}} - {this.state.pageNext && this.onChangePageNum(e, 1)}>{gettext("Next")}} + {this.state.page != 1 && this.onChangePageNum(e, -1)}>{gettext('Previous')}} + {(this.state.page != 1 && this.state.pageNext) && | } + {this.state.pageNext && this.onChangePageNum(e, 1)}>{gettext('Next')}}
@@ -172,9 +172,9 @@ class GroupItem extends React.Component { renderGroupHref = (group) => { let groupInfoHref; if (group.creatorName == 'system admin') { - groupInfoHref = siteRoot + 'org/admin/#address-book/groups/' + group.id + '/' + groupInfoHref = siteRoot + 'org/admin/#address-book/groups/' + group.id + '/'; } else { - groupInfoHref = siteRoot + 'org/groupadmin/' + group.id + '/' + groupInfoHref = siteRoot + 'org/groupadmin/' + group.id + '/'; } return groupInfoHref; @@ -185,13 +185,13 @@ class GroupItem extends React.Component { if (group.creatorName == 'system admin') { return ( -- - ) + ); } else { return( {group.creatorName} - ) + ); } } @@ -206,21 +206,21 @@ class GroupItem extends React.Component { {this.renderGroupCreator(group)} {group.ctime} - {isOperationMenuShow && - - - - {gettext('Delete')} - - - } + {isOperationMenuShow && + + + + {gettext('Delete')} + + + } ); diff --git a/frontend/src/pages/org-admin/org-libraries.js b/frontend/src/pages/org-admin/org-libraries.js new file mode 100644 index 0000000000..b1da5411d9 --- /dev/null +++ b/frontend/src/pages/org-admin/org-libraries.js @@ -0,0 +1,276 @@ +import React, { Fragment, Component } from 'react'; +import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; + +import OrgAdminRepo from '../../models/org-admin-repo'; +import toaster from '../../components/toast'; +import TransferDialog from '../../components/dialog/transfer-dialog'; +import ModalPortal from '../../components/modal-portal'; +import { seafileAPI } from '../../utils/seafile-api'; +import { mediaUrl, siteRoot, gettext, orgID } from '../../utils/constants'; + +class OrgLibraries extends Component { + + constructor(props) { + super(props); + this.state = { + page: 1, + pageNext: false, + orgRepos: [], + isItemFreezed: false + }; + } + + componentDidMount() { + let page = this.state.page; + this.initData(page); + } + + initData = (page) => { + seafileAPI.listOrgRepos(orgID, page).then(res => { + let orgRepos = res.data.repo_list.map(item => { + return new OrgAdminRepo(item); + }); + + this.setState({ + orgRepos: orgRepos, + pageNext: res.data.page_next, + page: res.data.page, + }); + }); + } + + + onChangePageNum = (e, num) => { + e.preventDefault(); + let page = this.state.page; + + if (num == 1) { + page = page + 1; + } else { + page = page - 1; + } + this.initData(page); + } + + onFreezedItem = () => { + this.setState({isItemFreezed: true}); + } + + onUnfreezedItem = () => { + this.setState({isItemFreezed: false}); + } + + deleteRepoItem = (repo) => { + seafileAPI.deleteOrgRepo(orgID, repo.repoID).then(res => { + this.setState({ + orgRepos: this.state.orgRepos.filter(item => item.repoID != repo.repoID) + }); + let msg = gettext('Successfully deleted {name}'); + msg = msg.replace('{name}', repo.repoName); + toaster.success(msg); + }); + } + + transferRepoItem = (repoID, user) => { + this.setState({ + orgRepos: this.state.orgRepos.map(item =>{ + if (item.repoID == repoID) { + item.ownerEmail = user.email; + item.ownerName = user.value; + } + return item; + }) + }); + } + + render() { + let repos = this.state.orgRepos; + return ( +
+
+
+

{gettext('All Libraries')}

+
+
+ + + + + + + + + + + + {repos.map(item => { + return ( + + )})} + +
{gettext('Name')}{gettext('ID')}{gettext('Owner')}{gettext('Operations')}
+
+ {this.state.page != 1 && this.onChangePageNum(e, -1)}>{gettext('Previous')}} + {(this.state.page != 1 && this.state.pageNext) && | } + {this.state.pageNext && this.onChangePageNum(e, 1)}>{gettext('Next')}} +
+
+
+
+ ); + } +} + +class RepoItem extends React.Component { + + constructor(props) { + super(props); + this.state = { + highlight: false, + showMenu: false, + isItemMenuShow: false, + isTransferDialogShow: false + }; + } + + onMouseEnter = () => { + if (!this.props.isItemFreezed) { + this.setState({ + showMenu: true, + highlight: true, + }); + } + } + + onMouseLeave = () => { + if (!this.props.isItemFreezed) { + this.setState({ + showMenu: false, + highlight: false + }); + } + } + + onDropdownToggleClick = (e) => { + e.preventDefault(); + this.toggleOperationMenu(e); + } + + toggleOperationMenu = (e) => { + e.stopPropagation(); + this.setState( + {isItemMenuShow: !this.state.isItemMenuShow }, () => { + if (this.state.isItemMenuShow) { + this.props.onFreezedItem(); + } else { + this.setState({ + highlight: false, + showMenu: false, + }); + this.props.onUnfreezedItem(); + } + } + ); + } + + toggleDelete = () => { + this.props.deleteRepoItem(this.props.repo); + } + + toggleTransfer = () => { + this.props.transferRepoItem(this.props.repo); + } + + renderLibIcon = (repo) => { + let href; + let iconTitle; + if (repo.encrypted) { + href = mediaUrl + 'img/lib/48/lib-encrypted.png'; + iconTitle = gettext('Encrypted library'); + } else { + href = mediaUrl + 'img/lib/48/lib.png'; + iconTitle = gettext('Read-Write library'); + } + return {iconTitle}; + } + + renderRepoOwnerHref = (repo) => { + let href; + if (repo.isDepartmentRepo) { + href = siteRoot + 'org/admin/#address-book/groups/' + repo.groupID + '/'; + } else { + href = siteRoot + 'org/useradmin/info/' + repo.ownerEmail + '/'; + } + return href; + } + + toggleTransfer = () => { + this.setState({isTransferDialogShow: !this.state.isTransferDialogShow}); + } + + onTransferRepo = (user) => { + let repo = this.props.repo; + seafileAPI.transferOrgRepo(orgID, repo.repoID, user.email).then(res => { + this.props.transferRepoItem(repo.repoID, user); + let msg = gettext('Successfully transferred the library.'); + toaster.success(msg); + }).catch(res => { + let msg = gettext('Failed. Please check the network.'); + toaster.danger(msg); + }); + this.toggleTransfer(); + } + + render() { + let { repo } = this.props; + + let isOperationMenuShow = this.state.showMenu && !repo.isDepartmentRepo; + return ( + + + {this.renderLibIcon(repo)} + {repo.repoName} + {repo.repoID} + {repo.ownerName} + + {isOperationMenuShow && + + + + {gettext('Delete')} + {gettext('Transfer')} + + + } + + + {this.state.isTransferDialogShow && ( + + + + )} + + ); + } +} + +export default OrgLibraries; diff --git a/frontend/src/pages/org-admin/org-users-list.js b/frontend/src/pages/org-admin/org-users-list.js index 342216417b..d57d7425f0 100644 --- a/frontend/src/pages/org-admin/org-users-list.js +++ b/frontend/src/pages/org-admin/org-users-list.js @@ -25,7 +25,7 @@ class OrgUsersList extends React.Component { orgUsers: [], isItemFreezed: false, page: 1, - pageNext: 2, + pageNext: false, }; } @@ -127,7 +127,8 @@ class OrgUsersList extends React.Component {
- {this.state.page !=1 && this.onChangePageNum(e, -1)}>{gettext('Previous')}{' | '}} + {this.state.page !=1 && this.onChangePageNum(e, -1)}>{gettext('Previous')}} + {(this.state.page != 1 && this.state.pageNext) && | } {this.state.pageNext && this.onChangePageNum(e, 1)}>{gettext('Next')}}
{this.props.isShowAddOrgUserDialog && ( diff --git a/frontend/src/pages/org-admin/org-users.js b/frontend/src/pages/org-admin/org-users.js index c0e77ed497..1227beb2b8 100644 --- a/frontend/src/pages/org-admin/org-users.js +++ b/frontend/src/pages/org-admin/org-users.js @@ -1,7 +1,5 @@ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import { Link } from '@reach/router'; - import { siteRoot, gettext } from '../../utils/constants'; class OrgUsers extends Component { @@ -21,10 +19,10 @@ class OrgUsers extends Component {
  • this.tabItemClick('users')}> - {gettext('All')} + {gettext('All')}
  • this.tabItemClick('admins')}> - {gettext('Admin')} + {gettext('Admin')}
diff --git a/frontend/src/pages/org-admin/side-panel.js b/frontend/src/pages/org-admin/side-panel.js index 41a9a9f12e..26fa121476 100644 --- a/frontend/src/pages/org-admin/side-panel.js +++ b/frontend/src/pages/org-admin/side-panel.js @@ -33,25 +33,25 @@ class SidePanel extends React.Component {

{gettext('Admin')}