aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-11-01 17:15:18 -0700
committerAnton Tananaev <anton@traccar.org>2022-11-01 17:15:18 -0700
commit4d5d9b320ce2578af26d4193b739c4b381f9d034 (patch)
tree1475599f7db42c6bba28053221e521b5dcb230ac
parentfff8187e659ecffe5fffaf8dfdecd85ac634bcd5 (diff)
downloadtrackermap-web-4d5d9b320ce2578af26d4193b739c4b381f9d034.tar.gz
trackermap-web-4d5d9b320ce2578af26d4193b739c4b381f9d034.tar.bz2
trackermap-web-4d5d9b320ce2578af26d4193b739c4b381f9d034.zip
Fix readonly preferences
-rw-r--r--modern/src/settings/PreferencesPage.js391
1 files changed, 199 insertions, 192 deletions
diff --git a/modern/src/settings/PreferencesPage.js b/modern/src/settings/PreferencesPage.js
index 6aad1153..a7115bf8 100644
--- a/modern/src/settings/PreferencesPage.js
+++ b/modern/src/settings/PreferencesPage.js
@@ -19,6 +19,7 @@ import useMapStyles from '../map/core/useMapStyles';
import useMapOverlays from '../map/overlay/useMapOverlays';
import { useCatch } from '../reactHelper';
import { sessionActions } from '../store';
+import { useRestriction } from '../common/util/permissions';
const deviceFields = [
{ id: 'name', name: 'sharedName' },
@@ -60,6 +61,8 @@ const PreferencesPage = () => {
const navigate = useNavigate();
const t = useTranslation();
+ const readonly = useRestriction('readonly');
+
const user = useSelector((state) => state.session.user);
const [attributes, setAttributes] = useState(user.attributes);
@@ -147,203 +150,207 @@ const PreferencesPage = () => {
</FormControl>
</AccordionDetails>
</Accordion>
- <Accordion>
- <AccordionSummary expandIcon={<ExpandMoreIcon />}>
- <Typography variant="subtitle1">
- {t('mapTitle')}
- </Typography>
- </AccordionSummary>
- <AccordionDetails className={classes.details}>
- <FormControl>
- <InputLabel>{t('mapActive')}</InputLabel>
- <Select
- label={t('mapActive')}
- value={attributes.activeMapStyles?.split(',') || ['locationIqStreets', 'osm', 'carto']}
- onChange={(e, child) => {
- const clicked = mapStyles.find((s) => s.id === child.props.value);
- if (clicked.available) {
- setAttributes({ ...attributes, activeMapStyles: e.target.value.join(',') });
- } else if (clicked.id !== 'custom') {
- const query = new URLSearchParams({ attribute: clicked.attribute });
- navigate(`/settings/user/${user.id}?${query.toString()}`);
- }
- }}
- multiple
- >
- {mapStyles.map((style) => (
- <MenuItem key={style.id} value={style.id}>
- <Typography component="span" color={style.available ? 'textPrimary' : 'error'}>{style.title}</Typography>
- </MenuItem>
- ))}
- </Select>
- </FormControl>
- <FormControl>
- <InputLabel>{t('mapOverlay')}</InputLabel>
- <Select
- label={t('mapOverlay')}
- value={attributes.selectedMapOverlay || ''}
- onChange={(e) => {
- const clicked = mapOverlays.find((o) => o.id === e.target.value);
- if (!clicked || clicked.available) {
- setAttributes({ ...attributes, selectedMapOverlay: e.target.value });
- } else if (clicked.id !== 'custom') {
- const query = new URLSearchParams({ attribute: clicked.attribute });
- navigate(`/settings/user/${user.id}?${query.toString()}`);
- }
- }}
- >
- <MenuItem value="">{'\u00a0'}</MenuItem>
- {mapOverlays.map((overlay) => (
- <MenuItem key={overlay.id} value={overlay.id}>
- <Typography component="span" color={overlay.available ? 'textPrimary' : 'error'}>{overlay.title}</Typography>
- </MenuItem>
- ))}
- </Select>
- </FormControl>
- <Autocomplete
- multiple
- freeSolo
- options={Object.keys(positionAttributes)}
- getOptionLabel={(option) => (positionAttributes.hasOwnProperty(option) ? positionAttributes[option].name : option)}
- value={attributes.positionItems?.split(',') || ['speed', 'address', 'totalDistance', 'course']}
- onChange={(_, option) => {
- setAttributes({ ...attributes, positionItems: option.join(',') });
- }}
- filterOptions={(options, params) => {
- const filtered = filter(options, params);
- if (params.inputValue && !filtered.includes(params.inputValue)) {
- filtered.push(params.inputValue);
- }
- return filtered;
- }}
- renderInput={(params) => (
- <TextField
- {...params}
- label={t('attributePopupInfo')}
+ {!readonly && (
+ <>
+ <Accordion>
+ <AccordionSummary expandIcon={<ExpandMoreIcon />}>
+ <Typography variant="subtitle1">
+ {t('mapTitle')}
+ </Typography>
+ </AccordionSummary>
+ <AccordionDetails className={classes.details}>
+ <FormControl>
+ <InputLabel>{t('mapActive')}</InputLabel>
+ <Select
+ label={t('mapActive')}
+ value={attributes.activeMapStyles?.split(',') || ['locationIqStreets', 'osm', 'carto']}
+ onChange={(e, child) => {
+ const clicked = mapStyles.find((s) => s.id === child.props.value);
+ if (clicked.available) {
+ setAttributes({ ...attributes, activeMapStyles: e.target.value.join(',') });
+ } else if (clicked.id !== 'custom') {
+ const query = new URLSearchParams({ attribute: clicked.attribute });
+ navigate(`/settings/user/${user.id}?${query.toString()}`);
+ }
+ }}
+ multiple
+ >
+ {mapStyles.map((style) => (
+ <MenuItem key={style.id} value={style.id}>
+ <Typography component="span" color={style.available ? 'textPrimary' : 'error'}>{style.title}</Typography>
+ </MenuItem>
+ ))}
+ </Select>
+ </FormControl>
+ <FormControl>
+ <InputLabel>{t('mapOverlay')}</InputLabel>
+ <Select
+ label={t('mapOverlay')}
+ value={attributes.selectedMapOverlay || ''}
+ onChange={(e) => {
+ const clicked = mapOverlays.find((o) => o.id === e.target.value);
+ if (!clicked || clicked.available) {
+ setAttributes({ ...attributes, selectedMapOverlay: e.target.value });
+ } else if (clicked.id !== 'custom') {
+ const query = new URLSearchParams({ attribute: clicked.attribute });
+ navigate(`/settings/user/${user.id}?${query.toString()}`);
+ }
+ }}
+ >
+ <MenuItem value="">{'\u00a0'}</MenuItem>
+ {mapOverlays.map((overlay) => (
+ <MenuItem key={overlay.id} value={overlay.id}>
+ <Typography component="span" color={overlay.available ? 'textPrimary' : 'error'}>{overlay.title}</Typography>
+ </MenuItem>
+ ))}
+ </Select>
+ </FormControl>
+ <Autocomplete
+ multiple
+ freeSolo
+ options={Object.keys(positionAttributes)}
+ getOptionLabel={(option) => (positionAttributes.hasOwnProperty(option) ? positionAttributes[option].name : option)}
+ value={attributes.positionItems?.split(',') || ['speed', 'address', 'totalDistance', 'course']}
+ onChange={(_, option) => {
+ setAttributes({ ...attributes, positionItems: option.join(',') });
+ }}
+ filterOptions={(options, params) => {
+ const filtered = filter(options, params);
+ if (params.inputValue && !filtered.includes(params.inputValue)) {
+ filtered.push(params.inputValue);
+ }
+ return filtered;
+ }}
+ renderInput={(params) => (
+ <TextField
+ {...params}
+ label={t('attributePopupInfo')}
+ />
+ )}
/>
- )}
- />
- <FormControl>
- <InputLabel>{t('mapLiveRoutes')}</InputLabel>
- <Select
- label={t('mapLiveRoutes')}
- value={attributes.mapLiveRoutes || 'none'}
- onChange={(e) => setAttributes({ ...attributes, mapLiveRoutes: e.target.value })}
- >
- <MenuItem value="none">{t('sharedDisabled')}</MenuItem>
- <MenuItem value="selected">{t('deviceSelected')}</MenuItem>
- <MenuItem value="all">{t('notificationAlways')}</MenuItem>
- </Select>
- </FormControl>
- <FormGroup>
- <FormControlLabel
- control={(
- <Checkbox
- checked={attributes.hasOwnProperty('mapGeofences') ? attributes.mapGeofences : true}
- onChange={(e) => setAttributes({ ...attributes, mapGeofences: e.target.checked })}
+ <FormControl>
+ <InputLabel>{t('mapLiveRoutes')}</InputLabel>
+ <Select
+ label={t('mapLiveRoutes')}
+ value={attributes.mapLiveRoutes || 'none'}
+ onChange={(e) => setAttributes({ ...attributes, mapLiveRoutes: e.target.value })}
+ >
+ <MenuItem value="none">{t('sharedDisabled')}</MenuItem>
+ <MenuItem value="selected">{t('deviceSelected')}</MenuItem>
+ <MenuItem value="all">{t('notificationAlways')}</MenuItem>
+ </Select>
+ </FormControl>
+ <FormGroup>
+ <FormControlLabel
+ control={(
+ <Checkbox
+ checked={attributes.hasOwnProperty('mapGeofences') ? attributes.mapGeofences : true}
+ onChange={(e) => setAttributes({ ...attributes, mapGeofences: e.target.checked })}
+ />
+ )}
+ label={t('attributeShowGeofences')}
/>
- )}
- label={t('attributeShowGeofences')}
- />
- <FormControlLabel
- control={(
- <Checkbox
- checked={attributes.hasOwnProperty('mapFollow') ? attributes.mapFollow : false}
- onChange={(e) => setAttributes({ ...attributes, mapFollow: e.target.checked })}
+ <FormControlLabel
+ control={(
+ <Checkbox
+ checked={attributes.hasOwnProperty('mapFollow') ? attributes.mapFollow : false}
+ onChange={(e) => setAttributes({ ...attributes, mapFollow: e.target.checked })}
+ />
+ )}
+ label={t('deviceFollow')}
/>
- )}
- label={t('deviceFollow')}
- />
- <FormControlLabel
- control={(
- <Checkbox
- checked={attributes.hasOwnProperty('mapCluster') ? attributes.mapCluster : true}
- onChange={(e) => setAttributes({ ...attributes, mapCluster: e.target.checked })}
+ <FormControlLabel
+ control={(
+ <Checkbox
+ checked={attributes.hasOwnProperty('mapCluster') ? attributes.mapCluster : true}
+ onChange={(e) => setAttributes({ ...attributes, mapCluster: e.target.checked })}
+ />
+ )}
+ label={t('mapClustering')}
/>
- )}
- label={t('mapClustering')}
- />
- <FormControlLabel
- control={(
- <Checkbox
- checked={attributes.hasOwnProperty('mapOnSelect') ? attributes.mapOnSelect : true}
- onChange={(e) => setAttributes({ ...attributes, mapOnSelect: e.target.checked })}
+ <FormControlLabel
+ control={(
+ <Checkbox
+ checked={attributes.hasOwnProperty('mapOnSelect') ? attributes.mapOnSelect : true}
+ onChange={(e) => setAttributes({ ...attributes, mapOnSelect: e.target.checked })}
+ />
+ )}
+ label={t('mapOnSelect')}
/>
- )}
- label={t('mapOnSelect')}
- />
- </FormGroup>
- </AccordionDetails>
- </Accordion>
- <Accordion>
- <AccordionSummary expandIcon={<ExpandMoreIcon />}>
- <Typography variant="subtitle1">
- {t('deviceTitle')}
- </Typography>
- </AccordionSummary>
- <AccordionDetails className={classes.details}>
- <SelectField
- emptyValue={null}
- value={attributes.devicePrimary || 'name'}
- onChange={(e) => setAttributes({ ...attributes, devicePrimary: e.target.value })}
- data={deviceFields}
- titleGetter={(it) => t(it.name)}
- label={t('devicePrimaryInfo')}
- />
- <SelectField
- emptyValue=""
- value={attributes.deviceSecondary || ''}
- onChange={(e) => setAttributes({ ...attributes, deviceSecondary: e.target.value })}
- data={deviceFields}
- titleGetter={(it) => t(it.name)}
- label={t('deviceSecondaryInfo')}
- />
- </AccordionDetails>
- </Accordion>
- <Accordion>
- <AccordionSummary expandIcon={<ExpandMoreIcon />}>
- <Typography variant="subtitle1">
- {t('sharedSound')}
- </Typography>
- </AccordionSummary>
- <AccordionDetails className={classes.details}>
- <SelectField
- multiple
- value={attributes.soundEvents?.split(',') || []}
- onChange={(e) => setAttributes({ ...attributes, soundEvents: e.target.value.join(',') })}
- endpoint="/api/notifications/types"
- keyGetter={(it) => it.type}
- titleGetter={(it) => t(prefixString('event', it.type))}
- label={t('eventsSoundEvents')}
- />
- <SelectField
- multiple
- value={attributes.soundAlarms?.split(',') || ['sos']}
- onChange={(e) => setAttributes({ ...attributes, soundAlarms: e.target.value.join(',') })}
- data={alarms}
- keyGetter={(it) => it.key}
- label={t('eventsSoundAlarms')}
- />
- </AccordionDetails>
- </Accordion>
- <div className={classes.buttons}>
- <Button
- type="button"
- color="primary"
- variant="outlined"
- onClick={() => navigate(-1)}
- >
- {t('sharedCancel')}
- </Button>
- <Button
- type="button"
- color="primary"
- variant="contained"
- onClick={handleSave}
- >
- {t('sharedSave')}
- </Button>
- </div>
+ </FormGroup>
+ </AccordionDetails>
+ </Accordion>
+ <Accordion>
+ <AccordionSummary expandIcon={<ExpandMoreIcon />}>
+ <Typography variant="subtitle1">
+ {t('deviceTitle')}
+ </Typography>
+ </AccordionSummary>
+ <AccordionDetails className={classes.details}>
+ <SelectField
+ emptyValue={null}
+ value={attributes.devicePrimary || 'name'}
+ onChange={(e) => setAttributes({ ...attributes, devicePrimary: e.target.value })}
+ data={deviceFields}
+ titleGetter={(it) => t(it.name)}
+ label={t('devicePrimaryInfo')}
+ />
+ <SelectField
+ emptyValue=""
+ value={attributes.deviceSecondary || ''}
+ onChange={(e) => setAttributes({ ...attributes, deviceSecondary: e.target.value })}
+ data={deviceFields}
+ titleGetter={(it) => t(it.name)}
+ label={t('deviceSecondaryInfo')}
+ />
+ </AccordionDetails>
+ </Accordion>
+ <Accordion>
+ <AccordionSummary expandIcon={<ExpandMoreIcon />}>
+ <Typography variant="subtitle1">
+ {t('sharedSound')}
+ </Typography>
+ </AccordionSummary>
+ <AccordionDetails className={classes.details}>
+ <SelectField
+ multiple
+ value={attributes.soundEvents?.split(',') || []}
+ onChange={(e) => setAttributes({ ...attributes, soundEvents: e.target.value.join(',') })}
+ endpoint="/api/notifications/types"
+ keyGetter={(it) => it.type}
+ titleGetter={(it) => t(prefixString('event', it.type))}
+ label={t('eventsSoundEvents')}
+ />
+ <SelectField
+ multiple
+ value={attributes.soundAlarms?.split(',') || ['sos']}
+ onChange={(e) => setAttributes({ ...attributes, soundAlarms: e.target.value.join(',') })}
+ data={alarms}
+ keyGetter={(it) => it.key}
+ label={t('eventsSoundAlarms')}
+ />
+ </AccordionDetails>
+ </Accordion>
+ <div className={classes.buttons}>
+ <Button
+ type="button"
+ color="primary"
+ variant="outlined"
+ onClick={() => navigate(-1)}
+ >
+ {t('sharedCancel')}
+ </Button>
+ <Button
+ type="button"
+ color="primary"
+ variant="contained"
+ onClick={handleSave}
+ >
+ {t('sharedSave')}
+ </Button>
+ </div>
+ </>
+ )}
</Container>
</PageLayout>
);