Skip to content
Snippets Groups Projects
Commit 6febde0d authored by Léopold Chappuis's avatar Léopold Chappuis Committed by Léopold Chappuis
Browse files

admin-panel: require confirmation before deleting accounts

Admins must now confirm their intent before deleting accounts.

Change-Id: I3e75bedfc636db087c76ff648650e6b5d50b2164
parent 5eba0b04
No related branches found
No related tags found
No related merge requests found
...@@ -40,6 +40,7 @@ import { ChangeEvent, useMemo, useState } from 'react' ...@@ -40,6 +40,7 @@ import { ChangeEvent, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useDeleteAccounts, useGetAllAccounts } from '../../services/adminQueries' import { useDeleteAccounts, useGetAllAccounts } from '../../services/adminQueries'
import ValidationRequiredModal from './ValidationRequiredModal'
function descendingComparator<T>(a: T, b: T, orderBy: keyof T) { function descendingComparator<T>(a: T, b: T, orderBy: keyof T) {
if (b[orderBy] < a[orderBy]) { if (b[orderBy] < a[orderBy]) {
...@@ -200,6 +201,7 @@ export default function AccountsOverview() { ...@@ -200,6 +201,7 @@ export default function AccountsOverview() {
const [rowsPerPage, setRowsPerPage] = useState(rowPerPagesOptions[0]) const [rowsPerPage, setRowsPerPage] = useState(rowPerPagesOptions[0])
const getAllAccounts = useGetAllAccounts() const getAllAccounts = useGetAllAccounts()
const accountDeletionMutation = useDeleteAccounts() const accountDeletionMutation = useDeleteAccounts()
const [modalOpen, setModalOpen] = useState(false)
const rows = useMemo(() => { const rows = useMemo(() => {
if (getAllAccounts.data) { if (getAllAccounts.data) {
...@@ -240,6 +242,10 @@ export default function AccountsOverview() { ...@@ -240,6 +242,10 @@ export default function AccountsOverview() {
} }
const handleSubmitDeletion = () => { const handleSubmitDeletion = () => {
setModalOpen(true)
}
const handleSubmitDeletionValidation = () => {
const accountsToDelete: AccountOverview[] = [] const accountsToDelete: AccountOverview[] = []
for (const account of rows) { for (const account of rows) {
if (selected.includes(account.accountUri)) { if (selected.includes(account.accountUri)) {
...@@ -248,6 +254,7 @@ export default function AccountsOverview() { ...@@ -248,6 +254,7 @@ export default function AccountsOverview() {
} }
accountDeletionMutation.mutate(accountsToDelete) accountDeletionMutation.mutate(accountsToDelete)
setSelected([]) setSelected([])
setModalOpen(false)
} }
const handleChangePage = (event: unknown, newPage: number) => { const handleChangePage = (event: unknown, newPage: number) => {
...@@ -344,6 +351,16 @@ export default function AccountsOverview() { ...@@ -344,6 +351,16 @@ export default function AccountsOverview() {
/> />
</Paper> </Paper>
</Box> </Box>
{modalOpen && (
<ValidationRequiredModal
info={t('remove_account_info')}
title={t('validation_required')}
buttonText={t('remove_button')}
open={modalOpen}
onClose={() => setModalOpen(false)}
onValidation={handleSubmitDeletionValidation}
/>
)}
</Box> </Box>
) )
} }
/*
* Copyright (C) 2022-2025 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
import { Box, Button, Card, CardContent, CardHeader, Modal, useTheme } from '@mui/material'
import { useTranslation } from 'react-i18next'
interface ValidationRequiredModalProps {
open: boolean
onClose: () => void
onValidation: () => void
title: string
buttonText: string
info?: string
}
export default function ValidationRequiredModal({
open,
onClose,
onValidation,
title,
buttonText,
info,
}: ValidationRequiredModalProps) {
const theme = useTheme()
const { t } = useTranslation()
return (
<Modal
open={open}
onClose={() => {
onClose()
}}
sx={{
width: '100%',
height: '100%',
display: 'flex',
justifyContent: 'center',
alignContent: 'center',
alignItems: 'center',
}}
>
<Card
sx={{
width: '350px',
height: '350px',
backgroundColor: theme.SettingsNeedPassword.backgroundColor,
borderRadius: '6px',
border: 'none',
}}
>
<CardHeader title={title} />
<CardContent sx={{ height: '100%' }}>
<Box
sx={{
fontSize: '14px',
display: 'flex',
color: 'grey',
maxWidth: '100%',
whiteSpace: 'pre-wrap',
wordWrap: 'break-word',
overflowWrap: 'break-word',
overflow: 'hidden',
textOverflow: 'ellipsis',
margin: 'auto',
textAlign: 'start',
marginTop: '-14px',
}}
>
{info}
</Box>
<Box
sx={{
height: '45%',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
flexDirection: 'column',
}}
></Box>
<Box sx={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between' }}>
<Button variant="contained" onClick={onClose}>
{t('dialog_cancel')}
</Button>
<Button
variant="contained"
onClick={() => {
onValidation()
}}
>
{buttonText}
</Button>
</Box>
</CardContent>
</Card>
</Modal>
)
}
...@@ -238,6 +238,8 @@ ...@@ -238,6 +238,8 @@
"registration_success": "Account registered successfully. Logging in…", "registration_success": "Account registered successfully. Logging in…",
"resetting_display_name_success_alert": "Display name reset successfully.", "resetting_display_name_success_alert": "Display name reset successfully.",
"resetting_display_name_error_alert": "An error occurred while resetting the display name.", "resetting_display_name_error_alert": "An error occurred while resetting the display name.",
"remove_account_info": "You are about to delete the selected accounts.\n This action is irreversible.\n Are you sure you want to proceed?",
"remove_button": "Remove",
"remove_jams_server": "Remove", "remove_jams_server": "Remove",
"removing_jams_server_success": "JAMS server address removed successfully.", "removing_jams_server_success": "JAMS server address removed successfully.",
"removing_jams_server_error": "An error occurred while removing the JAMS server.", "removing_jams_server_error": "An error occurred while removing the JAMS server.",
...@@ -316,6 +318,7 @@ ...@@ -316,6 +318,7 @@
"username_rule_3": "The username may contain hyphens (-).", "username_rule_3": "The username may contain hyphens (-).",
"username_rule_4": "The username may contain underscores (_).", "username_rule_4": "The username may contain underscores (_).",
"username_rules_dialog_title": "Username rules", "username_rules_dialog_title": "Username rules",
"validation_required": "Validation required",
"version": "Version", "version": "Version",
"welcome_text": "Welcome to Jami", "welcome_text": "Welcome to Jami",
"welcome_to_text": "Welcome to ", "welcome_to_text": "Welcome to ",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment