diff options
author | Anton Tananaev <anton@traccar.org> | 2024-04-06 09:22:10 -0700 |
---|---|---|
committer | Anton Tananaev <anton@traccar.org> | 2024-04-06 09:22:10 -0700 |
commit | f418231b6b2f5e030a0d2dcc390c314602b1f740 (patch) | |
tree | 10326adf3792bc2697e06bb5f2b8ef2a8f7e55fe /src/settings/UsersPage.jsx | |
parent | b392a4af78e01c8e0f50aad5468e9583675b24be (diff) | |
download | trackermap-web-f418231b6b2f5e030a0d2dcc390c314602b1f740.tar.gz trackermap-web-f418231b6b2f5e030a0d2dcc390c314602b1f740.tar.bz2 trackermap-web-f418231b6b2f5e030a0d2dcc390c314602b1f740.zip |
Move modern to the top
Diffstat (limited to 'src/settings/UsersPage.jsx')
-rw-r--r-- | src/settings/UsersPage.jsx | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/settings/UsersPage.jsx b/src/settings/UsersPage.jsx new file mode 100644 index 00000000..2941965b --- /dev/null +++ b/src/settings/UsersPage.jsx @@ -0,0 +1,130 @@ +import React, { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { + Table, TableRow, TableCell, TableHead, TableBody, Switch, TableFooter, FormControlLabel, +} from '@mui/material'; +import LoginIcon from '@mui/icons-material/Login'; +import LinkIcon from '@mui/icons-material/Link'; +import { useCatch, useEffectAsync } from '../reactHelper'; +import { formatBoolean, formatTime } from '../common/util/formatter'; +import { useTranslation } from '../common/components/LocalizationProvider'; +import PageLayout from '../common/components/PageLayout'; +import SettingsMenu from './components/SettingsMenu'; +import CollectionFab from './components/CollectionFab'; +import CollectionActions from './components/CollectionActions'; +import TableShimmer from '../common/components/TableShimmer'; +import { useManager } from '../common/util/permissions'; +import SearchHeader, { filterByKeyword } from './components/SearchHeader'; +import { usePreference } from '../common/util/preferences'; +import useSettingsStyles from './common/useSettingsStyles'; + +const UsersPage = () => { + const classes = useSettingsStyles(); + const navigate = useNavigate(); + const t = useTranslation(); + + const manager = useManager(); + + const hours12 = usePreference('twelveHourFormat'); + + const [timestamp, setTimestamp] = useState(Date.now()); + const [items, setItems] = useState([]); + const [searchKeyword, setSearchKeyword] = useState(''); + const [loading, setLoading] = useState(false); + const [temporary, setTemporary] = useState(false); + + const handleLogin = useCatch(async (userId) => { + const response = await fetch(`/api/session/${userId}`); + if (response.ok) { + window.location.replace('/'); + } else { + throw Error(await response.text()); + } + }); + + const actionLogin = { + key: 'login', + title: t('loginLogin'), + icon: <LoginIcon fontSize="small" />, + handler: handleLogin, + }; + + const actionConnections = { + key: 'connections', + title: t('sharedConnections'), + icon: <LinkIcon fontSize="small" />, + handler: (userId) => navigate(`/settings/user/${userId}/connections`), + }; + + useEffectAsync(async () => { + setLoading(true); + try { + const response = await fetch('/api/users'); + if (response.ok) { + setItems(await response.json()); + } else { + throw Error(await response.text()); + } + } finally { + setLoading(false); + } + }, [timestamp]); + + return ( + <PageLayout menu={<SettingsMenu />} breadcrumbs={['settingsTitle', 'settingsUsers']}> + <SearchHeader keyword={searchKeyword} setKeyword={setSearchKeyword} /> + <Table className={classes.table}> + <TableHead> + <TableRow> + <TableCell>{t('sharedName')}</TableCell> + <TableCell>{t('userEmail')}</TableCell> + <TableCell>{t('userAdmin')}</TableCell> + <TableCell>{t('sharedDisabled')}</TableCell> + <TableCell>{t('userExpirationTime')}</TableCell> + <TableCell className={classes.columnAction} /> + </TableRow> + </TableHead> + <TableBody> + {!loading ? items.filter((u) => temporary || !u.temporary).filter(filterByKeyword(searchKeyword)).map((item) => ( + <TableRow key={item.id}> + <TableCell>{item.name}</TableCell> + <TableCell>{item.email}</TableCell> + <TableCell>{formatBoolean(item.administrator, t)}</TableCell> + <TableCell>{formatBoolean(item.disabled, t)}</TableCell> + <TableCell>{formatTime(item.expirationTime, 'date', hours12)}</TableCell> + <TableCell className={classes.columnAction} padding="none"> + <CollectionActions + itemId={item.id} + editPath="/settings/user" + endpoint="users" + setTimestamp={setTimestamp} + customActions={manager ? [actionLogin, actionConnections] : [actionConnections]} + /> + </TableCell> + </TableRow> + )) : (<TableShimmer columns={6} endAction />)} + </TableBody> + <TableFooter> + <TableRow> + <TableCell colSpan={6} align="right"> + <FormControlLabel + control={( + <Switch + value={temporary} + onChange={(e) => setTemporary(e.target.checked)} + size="small" + /> + )} + label={t('userTemporary')} + labelPlacement="start" + /> + </TableCell> + </TableRow> + </TableFooter> + </Table> + <CollectionFab editPath="/settings/user" /> + </PageLayout> + ); +}; + +export default UsersPage; |