@samitouri / QOSami-HFS / commits / c361da2f

admin/accounts: sorted list #747

Massimo Melina committed Sep 22, 2024 at 12:31 UTC c361da2fb954d6b7db70336f4715528bd7428fc2
2 files changed +13 -13
admin/src/AccountsPage.ts
+11 -11
@@ -1,6 +1,6 @@
1 // This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3 -import { createElement as h, useState, useEffect, Fragment } from "react"
3 +import { createElement as h, useState, useEffect, Fragment, useMemo } from "react"
4 import { apiCall, useApiEx } from './api'
5 import { Alert, Box, Card, CardContent, Grid, List, ListItem, ListItemText, Typography } from '@mui/material'
6 import { Close, Delete, DoNotDisturb, Group, MilitaryTech, Person, PersonAdd, Schedule } from '@mui/icons-material'
@@ -13,20 +13,20 @@ import _ from 'lodash'
13 import { alertDialog, confirmDialog, toast } from './dialog'
14 import { useSnapState } from './state'
15 import { importAccountsCsv } from './importAccountsCsv'
16 -import { AccountAdminSend } from '../../src/api.accounts'
16 +import apiAccounts from '../../src/api.accounts'
17
18 -export type Account = AccountAdminSend
18 +export type Account = ReturnType<typeof apiAccounts.get_accounts>['list'][0]
19
20 export default function AccountsPage() {
21 const { username } = useSnapState()
22 - const { data, reload, element } = useApiEx('get_accounts')
22 + const { data, reload, element } = useApiEx<typeof apiAccounts.get_accounts>('get_accounts')
23 const [sel, setSel] = useState<string[] | 'new-group' | 'new-user'>([])
24 const selectionMode = Array.isArray(sel)
25 useEffect(() => { // if accounts are reloaded, review the selection to remove elements that don't exist anymore
26 if (Array.isArray(data?.list) && selectionMode)
27 - setSel( sel.filter(u => data.list.find((e:any) => e?.username === u)) ) // remove elements that don't exist anymore
27 + setSel( sel.filter(u => data!.list.find((e:any) => e?.username === u)) ) // remove elements that don't exist anymore
28 }, [data]) //eslint-disable-line -- Don't fall for its suggestion to add `sel` here: we modify it and declaring it as a dependency would cause a logical loop
29 - const list: Account[] | undefined = data?.list
29 + const list = useMemo(() => data && _.sortBy(data.list, [x => !x.adminActualAccess, 'username']), [data])
30 const selectedAccount = selectionMode && _.find(list, { username: sel[0] })
31 const sideBreakpoint = 'md'
32 const isSideBreakpoint = useBreakpoint(sideBreakpoint)
@@ -109,7 +109,7 @@ export default function AccountsPage() {
109 setSel(ids)
110 }
111 },
112 - list?.map((ac: Account) =>
112 + list?.map(ac =>
113 h(TreeItem, {
114 key: ac.username,
115 nodeId: ac.username,
@@ -155,8 +155,8 @@ export default function AccountsPage() {
155 if (errors.length)
156 return alertDialog("Following elements couldn't be deleted: " + errors.join(', '), 'error')
157 }
158 -}
158
160 -export function account2icon(ac: Account, props={}) {
161 - return h(ac.hasPassword ? Person : Group, props)
162 -}
159 + function account2icon(ac: Account, props={}) {
160 + return h(ac.hasPassword ? Person : Group, props)
161 + }
162 +}
\ No newline at end of file
src/api.accounts.ts
+2 -2
@@ -6,7 +6,7 @@ import { Account, accountCanLoginAdmin, accountHasPassword, accountsConfig, addA
6 import _ from 'lodash'
7 import { HTTP_BAD_REQUEST, HTTP_CONFLICT, HTTP_NOT_FOUND } from './const'
8 import { getCurrentUsername, invalidateSessionBefore } from './auth'
9 -import { apiAssertTypes } from './misc'
9 +import { apiAssertTypes, onlyTruthy } from './misc'
10
11 export type AccountAdminSend = NonNullable<ReturnType<typeof prepareAccount>>
12 function prepareAccount(ac: Account | undefined) {
@@ -31,7 +31,7 @@ export default {
31 },
32
33 get_accounts() {
34 - return { list: Object.values(accountsConfig.get()).map(prepareAccount) }
34 + return { list: onlyTruthy(Object.values(accountsConfig.get()).map(prepareAccount)) }
35 },
36
37 get_admins() {