diff --git a/frontend/src/app.js b/frontend/src/app.js index 7439201870..8d081738ab 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -113,6 +113,19 @@ class App extends Component { } } + onGroupChanged = (groupID) => { + setTimeout(function(){ + let url = new URL(window.location.origin); + if (groupID) { + url = url + 'group/' + groupID + '/'; + } + else { + url = url + 'groups/'; + } + window.location = url.toString(); + }, 1); + } + tabItemClick = (tabName, groupID) => { let pathPrefix = []; if (groupID || this.dirViewPanels.indexOf(tabName) > -1) { @@ -200,7 +213,13 @@ class App extends Component { - + diff --git a/frontend/src/components/dialog/dismiss-group-dialog.js b/frontend/src/components/dialog/dismiss-group-dialog.js new file mode 100644 index 0000000000..981eebd193 --- /dev/null +++ b/frontend/src/components/dialog/dismiss-group-dialog.js @@ -0,0 +1,46 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { gettext } from '../../utils/constants'; +import { seafileAPI } from '../../utils/seafile-api'; +import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from 'reactstrap'; + +class DismissGroupDialog extends React.Component { + + constructor(props) { + super(props); + } + + dismissGroup = () => { + let that = this; + seafileAPI.deleteGroup(this.props.groupID).then((res)=> { + that.props.onGroupChanged(); + }); + } + + render() { + return( + + {gettext('Dismiss Group')} + + {gettext('Really want to dismiss this group?')} + + + {gettext('Cancel')} + {gettext('Dismiss')} + + + ); + } +} + +const DismissGroupDialogPropTypes = { + showDismissGroupDialog: PropTypes.bool.isRequired, + toggleDismissGroupDialog: PropTypes.func.isRequired, + loadGroup: PropTypes.func.isRequired, + groupID: PropTypes.string.isRequired, + onGroupChanged: PropTypes.func.isRequired, +}; + +DismissGroupDialog.propTypes = DismissGroupDialogPropTypes; + +export default DismissGroupDialog; \ No newline at end of file diff --git a/frontend/src/components/dialog/rename-group-dialog.js b/frontend/src/components/dialog/rename-group-dialog.js new file mode 100644 index 0000000000..e0956f848f --- /dev/null +++ b/frontend/src/components/dialog/rename-group-dialog.js @@ -0,0 +1,72 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { gettext } from '../../utils/constants'; +import { seafileAPI } from '../../utils/seafile-api'; +import { Modal, ModalHeader, ModalBody, ModalFooter, Input, Button } from 'reactstrap'; + +class RenameGroupDialog extends React.Component { + + constructor(props) { + super(props); + this.state = { + newGroupName: '', + }; + } + + handleGroupNameChange = (event) => { + let name = event.target.value; + this.setState({ + newGroupName: name + }); + } + + renameGroup = () => { + let name = this.state.newGroupName.trim(); + if (name) { + let that = this; + seafileAPI.renameGroup(this.props.groupID, name).then((res)=> { + that.props.loadGroup(this.props.groupID); + that.props.onGroupChanged(res.data.id); + }); + } + this.setState({ + newGroupName: '', + }); + this.props.toggleRenameGroupDialog(); + } + + handleKeyDown = (event) => { + if (event.keyCode === 13) { + this.renameGroup(); + } + } + + render() { + return( + + {gettext('Rename Group')} + + {gettext('Rename group to')} + + + + {gettext('Cancel')} + {gettext('Submit')} + + + ); + } +} + +const RenameGroupDialogPropTypes = { + showRenameGroupDialog: PropTypes.bool.isRequired, + toggleRenameGroupDialog: PropTypes.func.isRequired, + loadGroup: PropTypes.func.isRequired, + groupID: PropTypes.string.isRequired, + onGroupChanged: PropTypes.func.isRequired, +}; + +RenameGroupDialog.propTypes = RenameGroupDialogPropTypes; + +export default RenameGroupDialog; \ No newline at end of file diff --git a/frontend/src/pages/groups/group-view.js b/frontend/src/pages/groups/group-view.js index c71a63ead8..f5ca0d6f33 100644 --- a/frontend/src/pages/groups/group-view.js +++ b/frontend/src/pages/groups/group-view.js @@ -1,4 +1,5 @@ import React,{ Fragment } from 'react'; +import { Popover } from 'reactstrap'; import PropTypes from 'prop-types'; import { gettext, siteRoot, username, loginUrl } from '../../utils/constants'; import { Link } from '@reach/router'; @@ -10,11 +11,15 @@ import Repo from '../../models/repo'; import CommonToolbar from '../../components/toolbar/common-toolbar'; import CreateRepoDialog from '../../components/dialog/create-repo-dialog'; import CreateDepartmentRepoDialog from '../../components/dialog/create-department-repo-dialog'; +import DismissGroupDialog from '../../components/dialog/dismiss-group-dialog'; +import RenameGroupDialog from '../../components/dialog/rename-group-dialog'; import SharedRepoListView from '../../components/shared-repo-list-view/shared-repo-list-view'; const propTypes = { onShowSidePanel: PropTypes.func.isRequired, onSearchedClick: PropTypes.func.isRequired, + onGroupChanged: PropTypes.func.isRequired, + groupID: PropTypes.string, }; const DEPARETMENT_GROUP_ONWER_NAME = 'system admin'; @@ -33,7 +38,10 @@ class GroupView extends React.Component { libraryType: 'group', isCreateRepoDialogShow: false, isDepartmentGroup: false, - } + showGroupDropdown: false, + showRenameGroupDialog: false, + showDismissGroupDialog: false, + }; } componentDidMount() { @@ -216,6 +224,24 @@ class GroupView extends React.Component { onTabNavClick = (tabName) => { this.props.onTabNavClick(tabName); } + + toggleGroupDropdown = () => { + this.setState({ + showGroupDropdown: !this.state.showGroupDropdown + }); + } + + toggleDismissGroupDialog = () => { + this.setState({ + showDismissGroupDialog: !this.state.showDismissGroupDialog + }); + } + + toggleRenameGroupDialog = () => { + this.setState({ + showRenameGroupDialog: !this.state.showRenameGroupDialog + }); + } render() { let { errMessage, emptyTip, currentGroup } = this.state; @@ -248,9 +274,28 @@ class GroupView extends React.Component { )} - {isShowSettingIcon && ( - - )} + { isShowSettingIcon && + + + + + {gettext("Settings")} + + + + + {gettext("Rename")} + + + {gettext("Dismiss")} + + + + + } @@ -288,6 +333,24 @@ class GroupView extends React.Component { onCreateRepo={this.onCreateRepo} /> } + { this.state.showRenameGroupDialog && + + } + { this.state.showDismissGroupDialog && + + } ); } diff --git a/media/css/seahub_react.css b/media/css/seahub_react.css index 307a67ec4c..3d0d8079cd 100644 --- a/media/css/seahub_react.css +++ b/media/css/seahub_react.css @@ -700,8 +700,7 @@ a.op-icon:focus { } .sf-popover-hd { padding:5px 0 3px; - border-bottom:1px solid #dfdfe1; - margin:0 10px; + margin: 10px; } .sf-popover-title { text-align:center; @@ -710,11 +709,28 @@ a.op-icon:focus { font-size:16px; color:#b9b9b9; margin:4px 0 0; + float:right; } .sf-popover-con { padding:0 10px; overflow:auto; } +.sf-popover-list { + border-top: 1px solid #e3e3e5; + list-style: none; +} +a.sf-popover-item { + display:block; + color:#444; + font-weight:normal; + line-height:31px; + text-decoration:none; + padding:0 10px; + margin:5px -10px; +} +a.sf-popover-item:hover { + background-color: #f8f8f8; +} /* for go-back */ .go-back {