import React, { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import {
Accordion,
AccordionSummary,
AccordionDetails,
Typography,
FormControl,
InputLabel,
Select,
MenuItem,
FormControlLabel,
Checkbox,
InputAdornment,
IconButton,
OutlinedInput,
FormGroup,
TextField,
Button,
} from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import CachedIcon from '@mui/icons-material/Cached';
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 LinkField from '../common/components/LinkField';
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 { formatNotificationTitle } from '../common/util/formatter';
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 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}
/>
setItem({ ...item, password: event.target.value })}
label={t('userPassword')}
/>
}>
{t('sharedPreferences')}
setItem({ ...item, phone: event.target.value })}
label={t('sharedPhone')}
/>
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('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('sharedPermissions')}
{t('userToken')}
setItem({ ...item, token: e.target.value })}
endAdornment={(
{
const token = [...Array(30)].map(() => Math.random().toString(36)[2]).join('');
setItem({ ...item, token });
}}
>
)}
/>
setItem({ ...item, expirationTime: moment(e.target.value, moment.HTML5_FMT.DATE).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}
/>
{item.id === currentUser.id && !manager && (
}>
{t('userDeleteAccount')}
setDeleteEmail(event.target.value)}
label={t('userEmail')}
error={deleteFailed}
/>
}
>
{t('userDeleteAccount')}
)}
{item.id && manager && (
}>
{t('sharedConnections')}
formatNotificationTitle(t, it, true)}
label={t('sharedNotifications')}
/>
it.description}
label={t('sharedComputedAttributes')}
/>
it.description}
label={t('sharedSavedCommands')}
/>
)}
>
)}
);
};
export default UserPage;