1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-05 17:02:47 +00:00

[system admin / users] redesigned the 'user filter' toolbar for the 'Database' tab (#7667)

This commit is contained in:
llj
2025-03-27 14:15:45 +08:00
committed by GitHub
parent 18c72b9391
commit 0666b7a303
5 changed files with 103 additions and 160 deletions

View File

@@ -74,7 +74,7 @@ class Selector extends Component {
{customSelectorToggle ? customSelectorToggle : ( {customSelectorToggle ? customSelectorToggle : (
<span className="cur-option"> <span className="cur-option">
{currentSelectedOption.text} {currentSelectedOption.text}
{isDropdownToggleShown && <i className="sf3-font sf3-font-down ml-2 toggle-icon"></i>} {isDropdownToggleShown && <i className="sf3-font sf3-font-down ml-1 toggle-icon"></i>}
</span> </span>
)} )}
</div> </div>

View File

@@ -15,7 +15,6 @@ import OpMenu from '../../../components/dialog/op-menu';
import SysAdminUserSetQuotaDialog from '../../../components/dialog/sysadmin-dialog/set-quota'; import SysAdminUserSetQuotaDialog from '../../../components/dialog/sysadmin-dialog/set-quota';
import CommonOperationConfirmationDialog from '../../../components/dialog/common-operation-confirmation-dialog'; import CommonOperationConfirmationDialog from '../../../components/dialog/common-operation-confirmation-dialog';
import UserLink from '../user-link'; import UserLink from '../user-link';
import UsersFilterBar from './users-filter-bar';
const { availableRoles, availableAdminRoles, institutions } = window.sysadmin.pageOptions; const { availableRoles, availableAdminRoles, institutions } = window.sysadmin.pageOptions;
dayjs.extend(relativeTime); dayjs.extend(relativeTime);
@@ -42,11 +41,11 @@ class Content extends Component {
}; };
getPreviousPage = () => { getPreviousPage = () => {
this.props.getListByPage(this.props.currentPage - 1, this.props.is_active, this.props.role); this.props.getListByPage(this.props.currentPage - 1);
}; };
getNextPage = () => { getNextPage = () => {
this.props.getListByPage(this.props.currentPage + 1, this.props.is_active, this.props.role); this.props.getListByPage(this.props.currentPage + 1);
}; };
sortByQuotaUsage = (e) => { sortByQuotaUsage = (e) => {
@@ -164,14 +163,6 @@ class Content extends Component {
return ( return (
<div> <div>
{this.props.currentItem === 'database' &&
<UsersFilterBar
isActive={this.props.is_active}
role={this.props.role}
onStatusChange={this.props.onStatusChange}
onRoleChange={this.props.onRoleChange}
/>
}
{items.length ? table : <EmptyTip text={gettext('No users')} />} {items.length ? table : <EmptyTip text={gettext('No users')} />}
</div> </div>
); );
@@ -201,12 +192,7 @@ Content.propTypes = {
onUserSelected: PropTypes.func, onUserSelected: PropTypes.func,
curPerPage: PropTypes.number, curPerPage: PropTypes.number,
hasNextPage: PropTypes.bool, hasNextPage: PropTypes.bool,
sortOrder: PropTypes.string, sortOrder: PropTypes.string
is_active: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
role: PropTypes.string,
currentItem: PropTypes.string,
onStatusChange: PropTypes.func,
onRoleChange: PropTypes.func
}; };
class Item extends Component { class Item extends Component {

View File

@@ -1,29 +1,4 @@
.users-filter-bar .users-filter-bar-dropdown-toggle { .users-filter-bar .filter-item,
height: 30px; .users-filter-bar .cur-option {
line-height: 30px;
padding-left: 8px;
font-size: 14px; font-size: 14px;
border-radius: 5px;
}
.users-filter-bar .users-filter-bar-dropdown-toggle .sf3-font-down {
color: #999;
margin-left: auto;
display: inline-flex;
justify-content: center;
align-items: center;
font-size: 12px;
width: 24px;
height: 24px;
}
.users-filter-bar .users-filter-bar-dropdown-toggle:hover {
background-color: #f5f5f5;
cursor: pointer;
}
.users-filter-bar .dropdown-menu .dropdown-item {
padding: 0.25rem 0.5rem;
display: flex;
justify-content: space-between;
} }

View File

@@ -1,117 +1,83 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Dropdown, DropdownToggle, DropdownItem, DropdownMenu } from 'reactstrap';
import { gettext } from '../../../utils/constants'; import { gettext } from '../../../utils/constants';
import Selector from '../../../components/single-selector';
import './users-filter-bar.css'; import './users-filter-bar.css';
const { availableRoles } = window.sysadmin.pageOptions; const { availableRoles } = window.sysadmin.pageOptions;
class UsersFilterBar extends Component { class UsersFilterBar extends Component {
constructor(props) {
super(props);
this.state = {
isStatusOpen: false,
isRoleOpen: false,
};
}
translateStatus = (status) => {
switch (status) {
case '0':
return gettext('Inactive');
case '1':
return gettext('Active');
default:
return gettext('All');
}
};
translateRole = (role) => { translateRole = (role) => {
switch (role) { switch (role) {
case '':
return gettext('All');
case 'default': case 'default':
return gettext('Default'); return gettext('Default');
case 'guest': case 'guest':
return gettext('Guest'); return gettext('Guest');
default: default:
return gettext('All'); return role;
} }
}; };
toggleStatusDropdown = () => { selectStatusOption = (option) => {
this.setState({ isStatusOpen: !this.state.isStatusOpen }); this.props.onStatusChange(option.value);
}; };
toggleRoleDropdown = () => { selectRoleOption = (option) => {
this.setState({ isRoleOpen: !this.state.isRoleOpen }); this.props.onRoleChange(option.value);
};
renderCheck = () => {
return <span className="sf2-icon-tick text-gray font-weight-bold"></span>;
}; };
render() { render() {
const { onStatusChange, onRoleChange } = this.props; const { isActive, role } = this.props;
this.statusOptions = [
{ value: '', text: gettext('All') },
{ value: '1', text: gettext('Active') },
{ value: '0', text: gettext('Inactive') }
].map(item => {
item.isSelected = isActive == item.value;
return item;
});
const currentSelectedStatusOption = this.statusOptions.filter(item => item.isSelected)[0];
this.roleOptions = [''].concat(availableRoles).map(item => {
return {
value: item,
text: this.translateRole(item),
isSelected: item == role
};
});
const currentSelectedRoleOption = this.roleOptions.filter(item => item.isSelected)[0] || { // `|| {...}`: to be compatible with old data(roles not in the present `availableRoles`
value: role,
text: this.translateRole(role),
isSelected: true
};
return ( return (
<div className="users-filter-bar mt-4 mb-2 d-flex"> <div className="users-filter-bar mt-4 mb-2 d-flex align-items-center">
<Dropdown isOpen={this.state.isStatusOpen} toggle={this.toggleStatusDropdown}> <span className="filter-item mr-2">{`${gettext('Status')}:`}</span>
<DropdownToggle <Selector
tag="div" isDropdownToggleShown={true}
data-toggle="dropdown" currentSelectedOption={currentSelectedStatusOption}
aria-expanded={this.state.isStatusOpen} options={this.statusOptions}
className="users-filter-bar-dropdown-toggle" selectOption={this.selectStatusOption}
> />
<span>{gettext('Status')}{': '}{this.translateStatus(this.props.isActive)}</span>
<span className='sf3-font-down sf3-font'></span> <span className="filter-item mr-2 ml-4">{`${gettext('Role')}:`}</span>
</DropdownToggle> <Selector
<DropdownMenu> isDropdownToggleShown={true}
<DropdownItem key={0} onClick={() => { onStatusChange(''); }}> currentSelectedOption={currentSelectedRoleOption}
<span>{gettext('All')}</span>{this.props.isActive === '' && this.renderCheck()} options={this.roleOptions}
</DropdownItem> selectOption={this.selectRoleOption}
<DropdownItem key={1} onClick={() => { onStatusChange('1'); }}> />
<span>{gettext('Active')}</span>{this.props.isActive === '1' && this.renderCheck()}
</DropdownItem>
<DropdownItem key={2} onClick={() => { onStatusChange('0'); }}>
<span>{gettext('Inactive')}</span>{this.props.isActive === '0' && this.renderCheck()}
</DropdownItem>
</DropdownMenu>
</Dropdown>
<Dropdown isOpen={this.state.isRoleOpen} toggle={this.toggleRoleDropdown} className="ml-4">
<DropdownToggle
tag="div"
data-toggle="dropdown"
aria-expanded={this.state.isRoleOpen}
className="users-filter-bar-dropdown-toggle"
>
<span>{gettext('Role')}{': '}{this.translateRole(this.props.role)}</span>
<span className='sf3-font-down sf3-font'></span>
</DropdownToggle>
<DropdownMenu>
<DropdownItem key={0} onClick={() => { onRoleChange(''); }}>
<span>{gettext('All')}</span>
{this.props.role === '' && this.renderCheck()}
</DropdownItem>
{availableRoles.map((item, index) => {
return (
<DropdownItem key={index} onClick={() => { onRoleChange(item); }}>
<span>{this.translateRole(item)}</span>
{this.props.role === item && this.renderCheck()}
</DropdownItem>
);
})}
</DropdownMenu>
</Dropdown>
</div> </div>
); );
} }
} }
UsersFilterBar.propTypes = { UsersFilterBar.propTypes = {
loading: PropTypes.bool,
curPerPage: PropTypes.number,
sortBy: PropTypes.string,
currentPage: PropTypes.number,
sortOrder: PropTypes.string,
onStatusChange: PropTypes.func, onStatusChange: PropTypes.func,
onRoleChange: PropTypes.func, onRoleChange: PropTypes.func,
role: PropTypes.string, role: PropTypes.string,

View File

@@ -16,6 +16,7 @@ import SysAdminAdminUser from '../../../models/sysadmin-admin-user';
import MainPanelTopbar from '../main-panel-topbar'; import MainPanelTopbar from '../main-panel-topbar';
import Search from '../search'; import Search from '../search';
import UsersNav from './users-nav'; import UsersNav from './users-nav';
import UsersFilterBar from './users-filter-bar';
import Content from './users-content'; import Content from './users-content';
const { availableRoles } = window.sysadmin.pageOptions; const { availableRoles } = window.sysadmin.pageOptions;
@@ -44,8 +45,8 @@ class Users extends Component {
isBatchSetQuotaDialogOpen: false, isBatchSetQuotaDialogOpen: false,
isBatchDeleteUserDialogOpen: false, isBatchDeleteUserDialogOpen: false,
isBatchAddAdminDialogOpen: false, isBatchAddAdminDialogOpen: false,
is_active: null, is_active: '',
role: null, role: ''
}; };
} }
@@ -59,15 +60,17 @@ class Users extends Component {
sortBy = '', sortBy = '',
sortOrder = 'asc', sortOrder = 'asc',
is_active, is_active,
role, role
} = this.state; } = this.state;
this.setState({ this.setState({
perPage: parseInt(urlParams.get('per_page') || perPage), perPage: parseInt(urlParams.get('per_page') || perPage),
currentPage: parseInt(urlParams.get('page') || currentPage), currentPage: parseInt(urlParams.get('page') || currentPage),
sortBy: urlParams.get('order_by') || sortBy, sortBy: urlParams.get('order_by') || sortBy,
sortOrder: urlParams.get('direction') || sortOrder, sortOrder: urlParams.get('direction') || sortOrder,
is_active: urlParams.get('is_active') || is_active,
role: urlParams.get('role') || role
}, () => { }, () => {
this.getUsersListByPage(this.state.currentPage, is_active, role); this.getUsersListByPage(this.state.currentPage);
}); });
} }
} }
@@ -164,8 +167,8 @@ class Users extends Component {
}); });
}; };
getUsersListByPage = (page, is_active, role) => { getUsersListByPage = (page) => {
const { perPage, sortBy, sortOrder } = this.state; const { perPage, sortBy, sortOrder, is_active, role } = this.state;
const { isLDAPImported } = this.props; const { isLDAPImported } = this.props;
systemAdminAPI.sysAdminListUsers(page, perPage, isLDAPImported, sortBy, sortOrder, is_active, role).then(res => { systemAdminAPI.sysAdminListUsers(page, perPage, isLDAPImported, sortBy, sortOrder, is_active, role).then(res => {
let users = res.data.data.map(user => {return new SysAdminUser(user);}); let users = res.data.data.map(user => {return new SysAdminUser(user);});
@@ -183,11 +186,12 @@ class Users extends Component {
}); });
}; };
updateURL = (page, perPage) => { updateURLSearchParams = (obj) => {
let url = new URL(location.href); let url = new URL(location.href);
let searchParams = new URLSearchParams(url.search); let searchParams = new URLSearchParams(url.search);
searchParams.set('page', page); for (const key in obj) {
searchParams.set('per_page', perPage); searchParams.set(key, obj[key]);
}
url.search = searchParams.toString(); url.search = searchParams.toString();
navigate(url.toString()); navigate(url.toString());
}; };
@@ -198,21 +202,28 @@ class Users extends Component {
is_active: is_active, is_active: is_active,
currentPage: 1 currentPage: 1
}, () => { }, () => {
const { currentPage, perPage, is_active, role } = this.state; const { currentPage, perPage } = this.state;
this.updateURL(currentPage, perPage); this.updateURLSearchParams({
this.getUsersListByPage(currentPage, is_active, role); 'page': currentPage,
'per_page': perPage,
'is_active': is_active
});
this.getUsersListByPage(currentPage);
}); });
}; };
// role: 'default', 'guest', ''
onRoleChange = (role) => { onRoleChange = (role) => {
this.setState({ this.setState({
role: role, role: role,
currentPage: 1 currentPage: 1
}, () => { }, () => {
const { currentPage, perPage, is_active, role } = this.state; const { currentPage, perPage } = this.state;
this.updateURL(currentPage, perPage); this.updateURLSearchParams({
this.getUsersListByPage(currentPage, is_active, role); 'page': currentPage,
'per_page': perPage,
'role': role
});
this.getUsersListByPage(currentPage);
}); });
}; };
@@ -222,15 +233,14 @@ class Users extends Component {
sortOrder: this.state.sortOrder == 'asc' ? 'desc' : 'asc', sortOrder: this.state.sortOrder == 'asc' ? 'desc' : 'asc',
currentPage: 1 currentPage: 1
}, () => { }, () => {
let url = new URL(location.href); const { currentPage, perPage, sortBy, sortOrder } = this.state;
let searchParams = new URLSearchParams(url.search); this.updateURLSearchParams({
const { currentPage, sortBy, sortOrder, is_active, role } = this.state; 'page': currentPage,
searchParams.set('page', currentPage); 'per_page': perPage,
searchParams.set('order_by', sortBy); 'order_by': sortBy,
searchParams.set('direction', sortOrder); 'direction': sortOrder
url.search = searchParams.toString(); });
navigate(url.toString()); this.getUsersListByPage(currentPage);
this.getUsersListByPage(currentPage, is_active, role);
}); });
}; };
@@ -346,7 +356,7 @@ class Users extends Component {
this.setState({ this.setState({
perPage: perPage perPage: perPage
}, () => { }, () => {
this.getUsersListByPage(1, this.state.is_active, this.state.role); this.getUsersListByPage(1);
}); });
}; };
@@ -471,6 +481,8 @@ class Users extends Component {
render() { render() {
const { isAdmin, isLDAPImported } = this.props; const { isAdmin, isLDAPImported } = this.props;
const { const {
is_active,
role,
hasUserSelected, hasUserSelected,
isImportUserDialogOpen, isImportUserDialogOpen,
isAddUserDialogOpen, isAddUserDialogOpen,
@@ -478,6 +490,7 @@ class Users extends Component {
isBatchSetQuotaDialogOpen, isBatchSetQuotaDialogOpen,
isBatchAddAdminDialogOpen isBatchAddAdminDialogOpen
} = this.state; } = this.state;
const curTab = this.getCurrentNavItem();
return ( return (
<Fragment> <Fragment>
<MainPanelTopbar search={this.getSearch()} {...this.props}> <MainPanelTopbar search={this.getSearch()} {...this.props}>
@@ -491,8 +504,16 @@ class Users extends Component {
</MainPanelTopbar> </MainPanelTopbar>
<div className="main-panel-center flex-row"> <div className="main-panel-center flex-row">
<div className="cur-view-container"> <div className="cur-view-container">
<UsersNav currentItem={this.getCurrentNavItem()} /> <UsersNav currentItem={curTab} />
<div className="cur-view-content"> <div className="cur-view-content">
{curTab == 'database' &&
<UsersFilterBar
isActive={is_active}
role={role}
onStatusChange={this.onStatusChange}
onRoleChange={this.onRoleChange}
/>
}
<Content <Content
isAdmin={isAdmin} isAdmin={isAdmin}
isLDAPImported={isLDAPImported} isLDAPImported={isLDAPImported}
@@ -505,8 +526,6 @@ class Users extends Component {
currentPage={this.state.currentPage} currentPage={this.state.currentPage}
hasNextPage={this.state.hasNextPage} hasNextPage={this.state.hasNextPage}
curPerPage={this.state.perPage} curPerPage={this.state.perPage}
is_active={this.state.is_active}
role={this.state.role}
resetPerPage={this.resetPerPage} resetPerPage={this.resetPerPage}
getListByPage={this.getUsersListByPage} getListByPage={this.getUsersListByPage}
updateUser={this.updateUser} updateUser={this.updateUser}
@@ -516,9 +535,6 @@ class Users extends Component {
onUserSelected={this.onUserSelected} onUserSelected={this.onUserSelected}
isAllUsersSelected={this.isAllUsersSelected} isAllUsersSelected={this.isAllUsersSelected}
toggleSelectAllUsers={this.toggleSelectAllUsers} toggleSelectAllUsers={this.toggleSelectAllUsers}
onRoleChange={this.onRoleChange}
onStatusChange={this.onStatusChange}
currentItem={this.getCurrentNavItem()}
/> />
</div> </div>
</div> </div>