diff options
Diffstat (limited to 'modern/src')
-rw-r--r-- | modern/src/settings/PreferencesPage.js | 391 |
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> ); |