diff --git a/frontend/src/components/sort-menu.js b/frontend/src/components/sort-menu.js index 570ce6e84d..5892c4648d 100644 --- a/frontend/src/components/sort-menu.js +++ b/frontend/src/components/sort-menu.js @@ -17,12 +17,12 @@ class SortMenu extends React.Component { constructor(props) { super(props); this.sortOptions = this.props.sortOptions || [ - { value: 'name-asc', text: gettext('By name ascending') }, - { value: 'name-desc', text: gettext('By name descending') }, - { value: 'size-asc', text: gettext('By size ascending') }, - { value: 'size-desc', text: gettext('By size descending') }, - { value: 'time-asc', text: gettext('By time ascending') }, - { value: 'time-desc', text: gettext('By time descending') } + { value: 'name-asc', text: gettext('Ascending by name') }, + { value: 'name-desc', text: gettext('Descending by name') }, + { value: 'size-asc', text: gettext('Ascending by size') }, + { value: 'size-desc', text: gettext('Descending by size') }, + { value: 'time-asc', text: gettext('Ascending by time') }, + { value: 'time-desc', text: gettext('Descending by time') } ]; this.state = { isDropdownMenuOpen: false diff --git a/frontend/src/pages/org-admin/departments/department.js b/frontend/src/pages/org-admin/departments/department.js index 3433fefc16..356a8600c6 100644 --- a/frontend/src/pages/org-admin/departments/department.js +++ b/frontend/src/pages/org-admin/departments/department.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { Dropdown, DropdownToggle } from 'reactstrap'; import Loading from '../../../components/loading'; import EmptyTip from '../../../components/empty-tip'; +import SortMenu from '../../../components/sort-menu'; import { gettext } from '../../../utils/constants'; import MemberItem from './member-item'; import RepoItem from './repo-item'; @@ -31,6 +32,13 @@ class Department extends React.Component { repos: [], dropdownOpen: false, }; + + this.sortOptions = [ + { value: 'name-asc', text: gettext('Ascending by name') }, + { value: 'name-desc', text: gettext('Descending by name') }, + { value: 'role-asc', text: gettext('Ascending by role') }, + { value: 'role-desc', text: gettext('Descending by role') } + ]; } componentDidMount() { @@ -67,19 +75,8 @@ class Department extends React.Component { return currentDepartment; }; - sortByName = (e) => { - e.preventDefault(); - const sortBy = 'name'; - let { sortOrder } = this.props; - sortOrder = sortOrder === 'asc' ? 'desc' : 'asc'; - this.props.sortItems(sortBy, sortOrder); - }; - - sortByRole = (e) => { - e.preventDefault(); - const sortBy = 'role'; - let { sortOrder } = this.props; - sortOrder = sortOrder === 'asc' ? 'desc' : 'asc'; + onSelectSortOption = (item) => { + const [sortBy, sortOrder] = item.value.split('-'); this.props.sortItems(sortBy, sortOrder); }; @@ -106,9 +103,7 @@ class Department extends React.Component { render() { const { activeNav, repos } = this.state; const { membersList, isMembersListLoading, sortBy, sortOrder } = this.props; - const sortByName = sortBy === 'name'; - const sortByRole = sortBy === 'role'; - const sortIcon = ; + const showSortIcon = activeNav == 'members'; const currentDepartment = this.getCurrentDepartment(); return ( @@ -150,6 +145,14 @@ class Department extends React.Component { this.changeActiveNav('repos')}>{gettext('Libraries')} + {showSortIcon && + + } {activeNav === 'members' && @@ -161,8 +164,8 @@ class Department extends React.Component { - {gettext('Name')}{' '}{sortByName && sortIcon} - {gettext('Role')}{' '}{sortByRole && sortIcon} + {gettext('Name')} + {gettext('Role')} {gettext('Contact email')} {/* Operations */} diff --git a/frontend/src/pages/org-admin/departments/departments.js b/frontend/src/pages/org-admin/departments/departments.js index 6f2e58bd7a..54011b3bc3 100644 --- a/frontend/src/pages/org-admin/departments/departments.js +++ b/frontend/src/pages/org-admin/departments/departments.js @@ -35,8 +35,8 @@ class Departments extends React.Component { membersList: [], isTopDepartmentLoading: false, isMembersListLoading: false, - sortBy: 'name', // 'name' or 'role' - sortOrder: 'asc', // 'asc' or 'desc', + sortBy: '', // 'name' or 'role' + sortOrder: '', // 'asc' or 'desc', }; } diff --git a/frontend/src/pages/org-admin/libraries/org-all-repos.js b/frontend/src/pages/org-admin/libraries/org-all-repos.js index d3bba4a36b..ee3f507ca2 100644 --- a/frontend/src/pages/org-admin/libraries/org-all-repos.js +++ b/frontend/src/pages/org-admin/libraries/org-all-repos.js @@ -52,8 +52,7 @@ class Content extends Component { }; render() { - // offer 'sort' only for 'all repos' - const { loading, errorMsg, items, pageInfo, curPerPage, sortBy } = this.props; + const { loading, errorMsg, items, pageInfo, curPerPage } = this.props; if (loading) { return ; } else if (errorMsg) { @@ -62,8 +61,6 @@ class Content extends Component { const emptyTip = ( ); - const initialSortIcon = ; - const sortIcon = ; const table = ( @@ -71,15 +68,7 @@ class Content extends Component { - + @@ -128,8 +117,6 @@ Content.propTypes = { resetPerPage: PropTypes.func, pageInfo: PropTypes.object, curPerPage: PropTypes.number, - sortItems: PropTypes.func, - sortBy: PropTypes.string, transferRepoItem: PropTypes.func.isRequired, }; @@ -389,14 +376,16 @@ class OrgAllRepos extends Component {
- +
{ + const [sortBy,] = item.value.split('-'); + this.props.sortItems(sortBy); + }; + render() { - const { currentItem } = this.props; + const { currentItem, sortBy, sortOrder = 'desc' } = this.props; + const showSortIcon = currentItem == 'all'; return (
    @@ -30,6 +44,14 @@ class Nav extends React.Component { ); })}
+ {showSortIcon && + + }
); } diff --git a/frontend/src/pages/org-admin/org-users-list.js b/frontend/src/pages/org-admin/org-users-list.js index 3d04752049..9100cda7ee 100644 --- a/frontend/src/pages/org-admin/org-users-list.js +++ b/frontend/src/pages/org-admin/org-users-list.js @@ -9,10 +9,7 @@ const propTypes = { changeStatus: PropTypes.func.isRequired, orgUsers: PropTypes.array.isRequired, page: PropTypes.number.isRequired, - pageNext: PropTypes.bool.isRequired, - sortByQuotaUsage: PropTypes.func.isRequired, - sortOrder: PropTypes.string.isRequired, - sortBy: PropTypes.string.isRequired, + pageNext: PropTypes.bool.isRequired }; class OrgUsersList extends React.Component { @@ -49,21 +46,8 @@ class OrgUsersList extends React.Component { this.props.initOrgUsersData(page); }; - sortByQuotaUsage = (e) => { - e.preventDefault(); - this.props.sortByQuotaUsage(); - }; - render() { - const { sortBy, sortOrder } = this.props; - let sortIcon; - if (sortBy == '') { - // initial sort icon - sortIcon = ; - } else { - sortIcon = ; - } - let { orgUsers, page, pageNext } = this.props; + const { orgUsers, page, pageNext } = this.props; return (
{/* icon*/} {gettext('Name')} - {sortBy != undefined ? - - {gettext('Files')} {sortBy == 'file_count' ? sortIcon : initialSortIcon}{' / '} - {gettext('Size')} {sortBy == 'size' ? sortIcon : initialSortIcon} - : - gettext('Files') / gettext('Size') - } - {gettext('Files')} / {gettext('Size')} ID {gettext('Owner')} {/* Operations*/}
@@ -71,9 +55,7 @@ class OrgUsersList extends React.Component { - + diff --git a/frontend/src/pages/org-admin/org-users-nav.js b/frontend/src/pages/org-admin/org-users-nav.js index cef35c9ee6..b46c770fc6 100644 --- a/frontend/src/pages/org-admin/org-users-nav.js +++ b/frontend/src/pages/org-admin/org-users-nav.js @@ -2,9 +2,12 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Link } from '@gatsbyjs/reach-router'; import { siteRoot, gettext } from '../../utils/constants'; +import SortMenu from '../../components/sort-menu'; const propTypes = { - currentItem: PropTypes.string.isRequired + currentItem: PropTypes.string.isRequired, + sortBy: PropTypes.string, + sortItems: PropTypes.func }; class Nav extends React.Component { @@ -15,10 +18,21 @@ class Nav extends React.Component { { name: 'all', urlPart: 'useradmin', text: gettext('All') }, { name: 'admins', urlPart: 'useradmin/admins', text: gettext('Admin') } ]; + + this.sortOptions = [ + { value: 'quota_usage-asc', text: gettext('Ascending by space used') }, + { value: 'quota_usage-desc', text: gettext('Descending by space used') } + ]; } + onSelectSortOption = (item) => { + const [sortBy, sortOrder] = item.value.split('-'); + this.props.sortItems(sortBy, sortOrder); + }; + render() { - const { currentItem } = this.props; + const { currentItem, sortBy, sortOrder } = this.props; + const showSortIcon = currentItem == 'all'; return (
    @@ -30,6 +44,14 @@ class Nav extends React.Component { ); })}
+ {showSortIcon && + + }
); } diff --git a/frontend/src/pages/org-admin/org-users-users.js b/frontend/src/pages/org-admin/org-users-users.js index e18dfe9c51..88e37490e2 100644 --- a/frontend/src/pages/org-admin/org-users-users.js +++ b/frontend/src/pages/org-admin/org-users-users.js @@ -102,10 +102,10 @@ class OrgUsers extends Component { }); } - sortByQuotaUsage = () => { + sortByQuotaUsage = (sortBy, sortOrder) => { this.setState({ - sortBy: 'quota_usage', - sortOrder: this.state.sortOrder == 'asc' ? 'desc' : 'asc', + sortBy: sortBy, + sortOrder: sortOrder, page: 1 }, () => { let url = new URL(location.href); @@ -309,7 +309,12 @@ class OrgUsers extends Component {
-
diff --git a/frontend/src/pages/sys-admin/departments/department.js b/frontend/src/pages/sys-admin/departments/department.js index b727bf5742..dd10e6c5e4 100644 --- a/frontend/src/pages/sys-admin/departments/department.js +++ b/frontend/src/pages/sys-admin/departments/department.js @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Dropdown, DropdownToggle } from 'reactstrap'; import { gettext } from '../../../utils/constants'; +import SortMenu from '../../../components/sort-menu'; import Paginator from '../../../components/paginator'; import Loading from '../../../components/loading'; import EmptyTip from '../../../components/empty-tip'; @@ -41,6 +42,13 @@ class Department extends React.Component { showDeleteRepoDialog: false, dropdownOpen: false, }; + + this.sortOptions = [ + { value: 'name-asc', text: gettext('Ascending by name') }, + { value: 'name-desc', text: gettext('Descending by name') }, + { value: 'role-asc', text: gettext('Ascending by role') }, + { value: 'role-desc', text: gettext('Descending by role') } + ]; } componentDidMount() { @@ -95,19 +103,8 @@ class Department extends React.Component { return currentDepartment; }; - sortByName = (e) => { - e.preventDefault(); - const sortBy = 'name'; - let { sortOrder } = this.props; - sortOrder = sortOrder === 'asc' ? 'desc' : 'asc'; - this.props.sortItems(sortBy, sortOrder); - }; - - sortByRole = (e) => { - e.preventDefault(); - const sortBy = 'role'; - let { sortOrder } = this.props; - sortOrder = sortOrder === 'asc' ? 'desc' : 'asc'; + onSelectSortOption = (item) => { + const [sortBy, sortOrder] = item.value.split('-'); this.props.sortItems(sortBy, sortOrder); }; @@ -129,9 +126,7 @@ class Department extends React.Component { render() { const { activeNav, repos } = this.state; const { membersList, isMembersListLoading, sortBy, sortOrder } = this.props; - const sortByName = sortBy === 'name'; - const sortByRole = sortBy === 'role'; - const sortIcon = ; + const showSortIcon = activeNav == 'members'; const currentDepartment = this.getCurrentDepartment(); return ( @@ -173,6 +168,15 @@ class Department extends React.Component { this.changeActiveNav('repos')}>{gettext('Libraries')} + + {showSortIcon && + + } {activeNav === 'members' && ( @@ -187,8 +191,8 @@ class Department extends React.Component {
- - + + diff --git a/frontend/src/pages/sys-admin/departments/departments.js b/frontend/src/pages/sys-admin/departments/departments.js index 89c1e1a0c9..187b576d35 100644 --- a/frontend/src/pages/sys-admin/departments/departments.js +++ b/frontend/src/pages/sys-admin/departments/departments.js @@ -35,8 +35,8 @@ class Departments extends React.Component { membersList: [], isTopDepartmentLoading: false, isMembersListLoading: false, - sortBy: 'name', // 'name' or 'role' - sortOrder: 'asc', // 'asc' or 'desc', + sortBy: '', // 'name' or 'role' + sortOrder: '', // 'asc' or 'desc', currentPageInfo: null, currentPage: 1, perPage: 100 diff --git a/frontend/src/pages/sys-admin/links/links-nav.js b/frontend/src/pages/sys-admin/links/links-nav.js index 50d99e9134..ca8a33303e 100644 --- a/frontend/src/pages/sys-admin/links/links-nav.js +++ b/frontend/src/pages/sys-admin/links/links-nav.js @@ -2,9 +2,13 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Link } from '@gatsbyjs/reach-router'; import { siteRoot, gettext } from '../../../utils/constants'; +import SortMenu from '../../../components/sort-menu'; const propTypes = { - currentItem: PropTypes.string.isRequired + currentItem: PropTypes.string.isRequired, + sortBy: PropTypes.string, + sortOrder: PropTypes.string, + sortItems: PropTypes.func }; class Nav extends React.Component { @@ -15,10 +19,23 @@ class Nav extends React.Component { { name: 'shareLinks', urlPart: 'share-links', text: gettext('Share Links') }, { name: 'uploadLinks', urlPart: 'upload-links', text: gettext('Upload Links') }, ]; + + this.sortOptions = [ + { value: 'ctime-asc', text: gettext('Ascending by creation time') }, + { value: 'ctime-desc', text: gettext('Descending by creation time') }, + { value: 'view_cnt-asc', text: gettext('Ascending by visit count') }, + { value: 'view_cnt-desc', text: gettext('Descending by visit count') } + ]; } + onSelectSortOption = (item) => { + const [sortBy, sortOrder] = item.value.split('-'); + this.props.sortItems(sortBy, sortOrder); + }; + render() { - const { currentItem } = this.props; + const { currentItem, sortBy, sortOrder } = this.props; + const showSortIcon = currentItem == 'shareLinks'; return (
    @@ -30,6 +47,14 @@ class Nav extends React.Component { ); })}
+ {showSortIcon && + + }
); } diff --git a/frontend/src/pages/sys-admin/links/share-links.js b/frontend/src/pages/sys-admin/links/share-links.js index 12cd00bb60..99f26337e1 100644 --- a/frontend/src/pages/sys-admin/links/share-links.js +++ b/frontend/src/pages/sys-admin/links/share-links.js @@ -31,21 +31,10 @@ class Content extends Component { this.props.getShareLinksByPage(this.props.currentPage + 1); }; - sortByTime = (e) => { - e.preventDefault(); - this.props.sortItems('ctime'); - }; - - sortByCount = (e) => { - e.preventDefault(); - this.props.sortItems('view_cnt'); - }; - render() { const { loading, errorMsg, items, - perPage, currentPage, hasNextPage, - sortBy, sortOrder + perPage, currentPage, hasNextPage } = this.props; if (loading) { return ; @@ -57,8 +46,6 @@ class Content extends Component { ); - const initialSortIcon = ; - const sortIcon = ; const table = (
{gettext('Name')} {gettext('Status')} - {gettext('Space Used')} {sortIcon} / {gettext('Quota')} - {gettext('Space Used')} / {gettext('Quota')} {gettext('Created At')} / {gettext('Last Login')} {/* Operations*/}
{gettext('Name')}{' '}{sortByName && sortIcon}{gettext('Role')}{' '}{sortByRole && sortIcon}{gettext('Name')}{gettext('Role')} {gettext('Contact email')} {/* Operations */}
@@ -67,12 +54,8 @@ class Content extends Component { - - + + @@ -115,9 +98,6 @@ Content.propTypes = { pageInfo: PropTypes.object, hasNextPage: PropTypes.bool, getShareLinksByPage: PropTypes.func.isRequired, - sortItems: PropTypes.func.isRequired, - sortBy: PropTypes.string.isRequired, - sortOrder: PropTypes.string.isRequired, deleteShareLink: PropTypes.func.isRequired, }; @@ -242,11 +222,11 @@ class ShareLinks extends Component { }); }; - sortItems = (sortBy) => { + sortItems = (sortBy, sortOrder) => { this.setState({ currentPage: 1, sortBy: sortBy, - sortOrder: this.state.sortOrder == 'asc' ? 'desc' : 'asc' + sortOrder: sortOrder }, () => { let url = new URL(location.href); let searchParams = new URLSearchParams(url.search); @@ -285,7 +265,12 @@ class ShareLinks extends Component {
- +
diff --git a/frontend/src/pages/sys-admin/repos/all-repos.js b/frontend/src/pages/sys-admin/repos/all-repos.js index 386fe6089c..d59e8ed111 100644 --- a/frontend/src/pages/sys-admin/repos/all-repos.js +++ b/frontend/src/pages/sys-admin/repos/all-repos.js @@ -155,14 +155,16 @@ class AllRepos extends Component {
- +
- +
{ + const [sortBy,] = item.value.split('-'); + this.props.sortItems(sortBy); + }; + render() { - const { currentItem } = this.props; + const { currentItem, sortBy, sortOrder = 'desc' } = this.props; + const showSortIcon = currentItem == 'all' || currentItem == 'wikis'; return (
    @@ -32,6 +45,14 @@ class Nav extends React.Component { ); })}
+ {showSortIcon && + + }
); } diff --git a/frontend/src/pages/sys-admin/repos/repos.js b/frontend/src/pages/sys-admin/repos/repos.js index d48ab880cd..40a0141d42 100644 --- a/frontend/src/pages/sys-admin/repos/repos.js +++ b/frontend/src/pages/sys-admin/repos/repos.js @@ -43,19 +43,8 @@ class Content extends Component { this.props.getListByPage(this.props.pageInfo.current_page + 1); }; - sortByFileCount = (e) => { - e.preventDefault(); - this.props.sortItems('file_count'); - }; - - sortBySize = (e) => { - e.preventDefault(); - this.props.sortItems('size'); - }; - render() { - // offer 'sort' only for 'all repos' - const { loading, errorMsg, items, pageInfo, curPerPage, sortBy } = this.props; + const { loading, errorMsg, items, pageInfo, curPerPage } = this.props; if (loading) { return ; } else if (errorMsg) { @@ -65,8 +54,6 @@ class Content extends Component { ); - const initialSortIcon = ; - const sortIcon = ; const table = (
{gettext('Name')} {gettext('Token')} {gettext('Owner')} - {gettext('Created At')} {sortBy == 'ctime' ? sortIcon : initialSortIcon} - - {gettext('Visit count')} {sortBy == 'view_cnt' ? sortIcon : initialSortIcon} - {gettext('Created At')}{gettext('Visit count')} {gettext('Expiration')} {/* Operations*/}
@@ -74,20 +61,10 @@ class Content extends Component { - - - - - - + + + + @@ -134,8 +111,6 @@ Content.propTypes = { resetPerPage: PropTypes.func, pageInfo: PropTypes.object, curPerPage: PropTypes.number, - sortItems: PropTypes.func, - sortBy: PropTypes.string, onTransferRepo: PropTypes.func.isRequired, }; diff --git a/frontend/src/pages/sys-admin/users/users-content.js b/frontend/src/pages/sys-admin/users/users-content.js index 669b77325d..af4bacfed7 100644 --- a/frontend/src/pages/sys-admin/users/users-content.js +++ b/frontend/src/pages/sys-admin/users/users-content.js @@ -57,8 +57,7 @@ class Content extends Component { render() { const { isAdmin, loading, errorMsg, items, isAllUsersSelected, - curPerPage, hasNextPage, currentPage, - sortBy, sortOrder + curPerPage, hasNextPage, currentPage } = this.props; if (loading) { @@ -68,20 +67,7 @@ class Content extends Component { } else { let columns = []; - let sortIcon; - if (sortBy == '') { - // initial sort icon - sortIcon = ; - } else { - sortIcon = ; - } - const spaceText = gettext('Space Used'); - const spaceEl = - sortBy != undefined ? // only offer 'sort' for 'DB' & 'LDAPImported' users - {spaceText} {sortIcon} : - spaceText; - const colSpaceText = {spaceEl}{` / ${gettext('Quota')}`}; - + const colSpaceText = `${gettext('Space Used')} / ${gettext('Quota')}`; const colNameText = `${gettext('Name')} / ${gettext('Contact Email')}`; const colCreatedText = `${gettext('Created At')} / ${gettext('Last Login')} / ${gettext('Last Access')}`; if (isPro) { diff --git a/frontend/src/pages/sys-admin/users/users-nav.js b/frontend/src/pages/sys-admin/users/users-nav.js index 130925a5b6..d827f2d991 100644 --- a/frontend/src/pages/sys-admin/users/users-nav.js +++ b/frontend/src/pages/sys-admin/users/users-nav.js @@ -2,9 +2,13 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Link } from '@gatsbyjs/reach-router'; import { siteRoot, gettext, haveLDAP, isDefaultAdmin } from '../../../utils/constants'; +import SortMenu from '../../../components/sort-menu'; const propTypes = { - currentItem: PropTypes.string.isRequired + currentItem: PropTypes.string.isRequired, + sortBy: PropTypes.string, + sortOrder: PropTypes.string, + sortItems: PropTypes.func }; class Nav extends React.Component { @@ -25,10 +29,21 @@ class Nav extends React.Component { { name: 'admin', urlPart: 'users/admins', text: gettext('Admin') } ); } + + this.sortOptions = [ + { value: 'quota_usage-asc', text: gettext('Ascending by space used') }, + { value: 'quota_usage-desc', text: gettext('Descending by space used') } + ]; } + onSelectSortOption = (item) => { + const [sortBy, sortOrder] = item.value.split('-'); + this.props.sortItems(sortBy, sortOrder); + }; + render() { - const { currentItem } = this.props; + const { currentItem, sortBy, sortOrder } = this.props; + const showSortIcon = currentItem == 'database' || currentItem == 'ldap-imported'; return (
    @@ -40,6 +55,14 @@ class Nav extends React.Component { ); })}
+ {showSortIcon && + + }
); } diff --git a/frontend/src/pages/sys-admin/users/users.js b/frontend/src/pages/sys-admin/users/users.js index 2d74ecd774..91e7a722aa 100644 --- a/frontend/src/pages/sys-admin/users/users.js +++ b/frontend/src/pages/sys-admin/users/users.js @@ -227,10 +227,10 @@ class Users extends Component { }); }; - sortByQuotaUsage = () => { + sortByQuotaUsage = (sortBy, sortOrder) => { this.setState({ - sortBy: 'quota_usage', - sortOrder: this.state.sortOrder == 'asc' ? 'desc' : 'asc', + sortBy: sortBy, + sortOrder: sortOrder, currentPage: 1 }, () => { const { currentPage, perPage, sortBy, sortOrder } = this.state; @@ -504,7 +504,12 @@ class Users extends Component {
- +
{curTab == 'database' &&
{/* icon*/} {gettext('Name')} - {sortBy != undefined ? - - {gettext('Files')} {sortBy == 'file_count' ? sortIcon : initialSortIcon}{' / '} - {gettext('Size')} {sortBy == 'size' ? sortIcon : initialSortIcon} - : - <>{gettext('Files')}{' / '}{gettext('Size')} - } - ID{gettext('Owner')}{/* Operations*/}{gettext('Files')} / {gettext('Size')}ID{gettext('Owner')}{/* Operations*/}