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,
InputAdornment,
IconButton,
OutlinedInput,
} from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import DeleteForeverIcon from '@mui/icons-material/DeleteForever';
import CachedIcon from '@mui/icons-material/Cached';
import CloseIcon from '@mui/icons-material/Close';
import { useDispatch, useSelector } from 'react-redux';
import dayjs from 'dayjs';
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 totpEnable = useSelector((state) => state.session.server.attributes.totpEnable);
const totpForce = useSelector((state) => state.session.server.attributes.totpForce);
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 handleGenerateTotp = useCatch(async () => {
const response = await fetch('/api/users/totp', { method: 'POST' });
if (response.ok) {
setItem({ ...item, totpKey: await response.text() })
} else {
throw Error(await response.text());
}
});
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) && (admin || !totpForce || item.totpKey);
return (
}
breadcrumbs={['settingsTitle', 'settingsUser']}
>
{item && (
<>
}>
{t('sharedRequired')}
setItem({ ...item, name: e.target.value })}
label={t('sharedName')}
/>
setItem({ ...item, email: e.target.value })}
label={t('userEmail')}
disabled={fixedEmail}
/>
{!openIdForced && (
setItem({ ...item, password: e.target.value })}
label={t('userPassword')}
/>
)}
{totpEnable && (
{t('loginTotpKey')}
setItem({ ...item, totpKey: null })}>
)}
/>
)}
}>
{t('sharedPreferences')}
setItem({ ...item, phone: e.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: e.target.value })}
label={t('mapPoiLayer')}
/>
setItem({ ...item, twelveHourFormat: e.target.checked })} />}
label={t('settingsTwelveHourFormat')}
/>
}>
{t('sharedLocation')}
setItem({ ...item, latitude: Number(e.target.value) })}
label={t('positionLatitude')}
/>
setItem({ ...item, longitude: Number(e.target.value) })}
label={t('positionLongitude')}
/>
setItem({ ...item, zoom: Number(e.target.value) })}
label={t('serverZoom')}
/>
}>
{t('sharedPermissions')}
setItem({ ...item, expirationTime: dayjs(e.target.value, 'YYYY-MM-DD').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(e.target.value)}
label={t('userEmail')}
error={deleteFailed}
/>
}
>
{t('userDeleteAccount')}
)}
>
)}
);
};
export default UserPage;