From d3c7705bedebd65c94f9eea691aaf2fe03b0cafe Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 19 Aug 2023 13:58:45 -0700 Subject: Move to Vite --- modern/src/settings/UserPage.jsx | 402 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 402 insertions(+) create mode 100644 modern/src/settings/UserPage.jsx (limited to 'modern/src/settings/UserPage.jsx') diff --git a/modern/src/settings/UserPage.jsx b/modern/src/settings/UserPage.jsx new file mode 100644 index 00000000..21859ea7 --- /dev/null +++ b/modern/src/settings/UserPage.jsx @@ -0,0 +1,402 @@ +import React, { useEffect, useState } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { + Accordion, + AccordionSummary, + AccordionDetails, + Typography, + FormControl, + InputLabel, + Select, + MenuItem, + FormControlLabel, + Checkbox, + FormGroup, + TextField, + Button, +} from '@mui/material'; +import makeStyles from '@mui/styles/makeStyles'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import DeleteForeverIcon from '@mui/icons-material/DeleteForever'; +import { useDispatch, useSelector } from 'react-redux'; +import moment from 'moment'; +import EditItemView from './components/EditItemView'; +import EditAttributesAccordion from './components/EditAttributesAccordion'; +import { useTranslation } from '../common/components/LocalizationProvider'; +import useUserAttributes from '../common/attributes/useUserAttributes'; +import { sessionActions } from '../store'; +import SelectField from '../common/components/SelectField'; +import SettingsMenu from './components/SettingsMenu'; +import useCommonUserAttributes from '../common/attributes/useCommonUserAttributes'; +import { useAdministrator, useRestriction, useManager } from '../common/util/permissions'; +import useQuery from '../common/util/useQuery'; +import { useCatch } from '../reactHelper'; +import useMapStyles from '../map/core/useMapStyles'; +import { map } from '../map/core/MapView'; + +const useStyles = makeStyles((theme) => ({ + details: { + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(2), + paddingBottom: theme.spacing(3), + }, +})); + +const UserPage = () => { + const classes = useStyles(); + const navigate = useNavigate(); + const dispatch = useDispatch(); + const t = useTranslation(); + + const admin = useAdministrator(); + const manager = useManager(); + const fixedEmail = useRestriction('fixedEmail'); + + const currentUser = useSelector((state) => state.session.user); + const registrationEnabled = useSelector((state) => state.session.server.registration); + const openIdForced = useSelector((state) => state.session.server.openIdForce); + + const mapStyles = useMapStyles(); + const commonUserAttributes = useCommonUserAttributes(t); + const userAttributes = useUserAttributes(t); + + const { id } = useParams(); + const [item, setItem] = useState(id === currentUser.id.toString() ? currentUser : null); + + const [deleteEmail, setDeleteEmail] = useState(); + const [deleteFailed, setDeleteFailed] = useState(false); + + const handleDelete = useCatch(async () => { + if (deleteEmail === currentUser.email) { + setDeleteFailed(false); + const response = await fetch(`/api/users/${currentUser.id}`, { method: 'DELETE' }); + if (response.ok) { + navigate('/login'); + dispatch(sessionActions.updateUser(null)); + } else { + throw Error(await response.text()); + } + } else { + setDeleteFailed(true); + } + }); + + const query = useQuery(); + const [queryHandled, setQueryHandled] = useState(false); + const attribute = query.get('attribute'); + + useEffect(() => { + if (!queryHandled && item && attribute) { + if (!item.attributes.hasOwnProperty('attribute')) { + const updatedAttributes = { ...item.attributes }; + updatedAttributes[attribute] = ''; + setItem({ ...item, attributes: updatedAttributes }); + } + setQueryHandled(true); + } + }, [item, queryHandled, setQueryHandled, attribute]); + + const onItemSaved = (result) => { + if (result.id === currentUser.id) { + dispatch(sessionActions.updateUser(result)); + } + }; + + const validate = () => item && item.name && item.email && (item.id || item.password); + + return ( + } + breadcrumbs={['settingsTitle', 'settingsUser']} + > + {item && ( + <> + + }> + + {t('sharedRequired')} + + + + setItem({ ...item, name: event.target.value })} + label={t('sharedName')} + /> + setItem({ ...item, email: event.target.value })} + label={t('userEmail')} + disabled={fixedEmail} + /> + {!openIdForced && ( + setItem({ ...item, password: event.target.value })} + label={t('userPassword')} + /> + )} + + + + }> + + {t('sharedPreferences')} + + + + setItem({ ...item, phone: event.target.value })} + label={t('sharedPhone')} + /> + + {t('mapDefault')} + + + + {t('settingsCoordinateFormat')} + + + + {t('settingsSpeedUnit')} + + + + {t('settingsDistanceUnit')} + + + + {t('settingsAltitudeUnit')} + + + + {t('settingsVolumeUnit')} + + + setItem({ ...item, attributes: { ...item.attributes, timezone: e.target.value } })} + endpoint="/api/server/timezones" + keyGetter={(it) => it} + titleGetter={(it) => it} + label={t('sharedTimezone')} + /> + setItem({ ...item, poiLayer: event.target.value })} + label={t('mapPoiLayer')} + /> + + setItem({ ...item, twelveHourFormat: event.target.checked })} />} + label={t('settingsTwelveHourFormat')} + /> + + + + + }> + + {t('sharedLocation')} + + + + setItem({ ...item, latitude: Number(event.target.value) })} + label={t('positionLatitude')} + /> + setItem({ ...item, longitude: Number(event.target.value) })} + label={t('positionLongitude')} + /> + setItem({ ...item, zoom: Number(event.target.value) })} + label={t('serverZoom')} + /> + + + + + }> + + {t('sharedPermissions')} + + + + setItem({ ...item, expirationTime: moment(e.target.value, moment.HTML5_FMT.DATE).locale('en').format() })} + disabled={!manager} + /> + setItem({ ...item, deviceLimit: Number(e.target.value) })} + label={t('userDeviceLimit')} + disabled={!admin} + /> + setItem({ ...item, userLimit: Number(e.target.value) })} + label={t('userUserLimit')} + disabled={!admin} + /> + + setItem({ ...item, disabled: e.target.checked })} />} + label={t('sharedDisabled')} + disabled={!manager} + /> + setItem({ ...item, administrator: e.target.checked })} />} + label={t('userAdmin')} + disabled={!admin} + /> + setItem({ ...item, readonly: e.target.checked })} />} + label={t('serverReadonly')} + disabled={!manager} + /> + setItem({ ...item, deviceReadonly: e.target.checked })} />} + label={t('userDeviceReadonly')} + disabled={!manager} + /> + setItem({ ...item, limitCommands: e.target.checked })} />} + label={t('userLimitCommands')} + disabled={!manager} + /> + setItem({ ...item, disableReports: e.target.checked })} />} + label={t('userDisableReports')} + disabled={!manager} + /> + setItem({ ...item, fixedEmail: e.target.checked })} />} + label={t('userFixedEmail')} + disabled={!manager} + /> + + + + setItem({ ...item, attributes })} + definitions={{ ...commonUserAttributes, ...userAttributes }} + focusAttribute={attribute} + /> + {registrationEnabled && item.id === currentUser.id && !manager && ( + + }> + + {t('userDeleteAccount')} + + + + setDeleteEmail(event.target.value)} + label={t('userEmail')} + error={deleteFailed} + /> + + + + )} + + )} + + ); +}; + +export default UserPage; -- cgit v1.2.3