admin/accounts: delete multiple accounts

Massimo Melina committed Feb 4, 2023 at 17:28 UTC 270a0488ccb60095063b8780fef45e941438d8d5
1 file changed +30 -4
admin/src/AccountsPage.ts
+30 -4
@@ -1,15 +1,18 @@
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"
4 -import { useApiEx } from './api'
5 -import { Alert, Box, Card, CardContent, Grid, List, ListItem, ListItemText, Typography } from '@mui/material'
6 -import { Close, Group, MilitaryTech, Person, PersonAdd, Refresh } from '@mui/icons-material'
4 +import { apiCall, useApiEx } from './api'
5 +import { Alert, Box, Button, Card, CardContent, Grid, List, ListItem, ListItemText, Typography } from '@mui/material'
6 +import { Close, Delete, Group, MilitaryTech, Person, PersonAdd, Refresh } from '@mui/icons-material'
7 import { IconBtn, iconTooltip, newDialog, useBreakpoint } from './misc'
8 import { TreeItem, TreeView } from '@mui/lab'
9 import MenuButton from './MenuButton'
10 import AccountForm from './AccountForm'
11 import md from './md'
12 import _ from 'lodash'
13 +import { Flex } from '@hfs/frontend/src/components'
14 +import { alertDialog, confirmDialog } from './dialog'
15 +import { useSnapState } from './state'
16
17 export interface Account {
18 username: string
@@ -22,6 +25,7 @@ export interface Account {
25 }
26
27 export default function AccountsPage() {
28 + const { username } = useSnapState()
29 const { data, reload, element } = useApiEx('get_accounts')
30 const [sel, setSel] = useState<string[] | 'new-group' | 'new-user'>([])
31 const selectionMode = Array.isArray(sel)
@@ -41,7 +45,10 @@ export default function AccountsPage() {
45
46 const sideContent = !(sel.length > 0) || !list ? null // this clever test is true both when some accounts are selected and when we are in "new account" modes
47 : selectionMode && sel.length > 1 ? h(Fragment, {},
44 - h(Typography, {}, sel.length + " selected"),
48 + h(Flex, { alignItems: 'center' },
49 + h(Typography, {variant: 'h6'}, sel.length + " selected"),
50 + h(Button, { onClick: deleteAccounts, startIcon: h(Delete) }, "Remove"),
51 + ),
52 h(List, {},
53 sel.map(username =>
54 h(ListItem, { key: username },
@@ -135,6 +142,25 @@ export default function AccountsPage() {
142 isSideBreakpoint && sideContent && h(Grid, { item: true, md: 7 },
143 h(Card, {}, h(CardContent, {}, sideContent) )),
144 )
145 +
146 + async function deleteAccounts() {
147 + if (sel.length > _.pull(sel, username).length)
148 + await alertDialog("Won't delete current account", 'warning')
149 + if (!sel.length) return
150 + if (!await confirmDialog(`Delete ${sel.length} item(s)?`)) return
151 + try {
152 + const errors = []
153 + for (const username of sel)
154 + if (!await apiCall('del_account', { username }).then(() => 1, () => 0))
155 + errors.push(username)
156 + reload()
157 + if (errors.length)
158 + return alertDialog("Following elements couldn't be deleted: " + errors.join(', '), 'error')
159 + }
160 + catch(e) {
161 + await alertDialog(e as Error)
162 + }
163 + }
164 }
165
166 export function account2icon(ac: Account, props={}) {