diff options
Diffstat (limited to 'modern/src/settings')
-rw-r--r-- | modern/src/settings/PreferencesPage.js | 48 | ||||
-rw-r--r-- | modern/src/settings/UserPage.js | 27 |
2 files changed, 47 insertions, 28 deletions
diff --git a/modern/src/settings/PreferencesPage.js b/modern/src/settings/PreferencesPage.js index 11cf860c..3b0c7e9c 100644 --- a/modern/src/settings/PreferencesPage.js +++ b/modern/src/settings/PreferencesPage.js @@ -1,11 +1,13 @@ -import React from 'react'; +import React, { useState } from 'react'; import { useSelector } from 'react-redux'; import { useNavigate } from 'react-router-dom'; import { - Accordion, AccordionSummary, AccordionDetails, Typography, Container, FormControl, InputLabel, Select, MenuItem, Checkbox, FormControlLabel, FormGroup, + Accordion, AccordionSummary, AccordionDetails, Typography, Container, FormControl, InputLabel, Select, MenuItem, Checkbox, FormControlLabel, FormGroup, InputAdornment, IconButton, OutlinedInput, } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import CachedIcon from '@mui/icons-material/Cached'; +import ContentCopyIcon from '@mui/icons-material/ContentCopy'; import { useLocalization, useTranslation, useTranslationKeys } from '../common/components/LocalizationProvider'; import usePersistedState from '../common/util/usePersistedState'; import PageLayout from '../common/components/PageLayout'; @@ -15,6 +17,7 @@ import { prefixString, unprefixString } from '../common/util/stringUtils'; import SelectField from '../common/components/SelectField'; import useMapStyles from '../map/core/useMapStyles'; import useMapOverlays from '../map/overlay/useMapOverlays'; +import { useCatch } from '../reactHelper'; const useStyles = makeStyles((theme) => ({ container: { @@ -26,6 +29,10 @@ const useStyles = makeStyles((theme) => ({ gap: theme.spacing(2), paddingBottom: theme.spacing(3), }, + tokenActions: { + display: 'flex', + flexDirection: 'column', + }, })); const PreferencesPage = () => { @@ -38,6 +45,8 @@ const PreferencesPage = () => { const { languages, language, setLanguage } = useLocalization(); const languageList = Object.entries(languages).map((values) => ({ code: values[0], name: values[1].name })); + const [token, setToken] = useState(); + const mapStyles = useMapStyles(); const [activeMapStyles, setActiveMapStyles] = usePersistedState('activeMapStyles', ['locationIqStreets', 'osm', 'carto']); @@ -53,6 +62,18 @@ const PreferencesPage = () => { const [mapCluster, setMapCluster] = usePersistedState('mapCluster', true); const [mapOnSelect, setMapOnSelect] = usePersistedState('mapOnSelect', false); + const generateToken = useCatch(async () => { + const response = await fetch('/api/session/token', { + method: 'POST', + body: new URLSearchParams(), + }); + if (response.ok) { + setToken(await response.text()); + } else { + throw Error(await response.text()); + } + }); + const alarms = useTranslationKeys((it) => it.startsWith('alarm')).map((it) => ({ key: unprefixString('alarm', it), name: t(it), @@ -81,6 +102,29 @@ const PreferencesPage = () => { {languageList.map((it) => <MenuItem key={it.code} value={it.code}>{it.name}</MenuItem>)} </Select> </FormControl> + <FormControl> + <InputLabel>{t('userToken')}</InputLabel> + <OutlinedInput + multiline + rows={6} + readOnly + type="text" + label={t('userToken')} + value={token || ''} + endAdornment={( + <InputAdornment position="end"> + <div className={classes.tokenActions}> + <IconButton size="small" onClick={generateToken} disabled={!!token}> + <CachedIcon fontSize="small" /> + </IconButton> + <IconButton size="small" onClick={() => navigator.clipboard.writeText(token)} disabled={!token}> + <ContentCopyIcon fontSize="small" /> + </IconButton> + </div> + </InputAdornment> + )} + /> + </FormControl> </AccordionDetails> </Accordion> <Accordion> diff --git a/modern/src/settings/UserPage.js b/modern/src/settings/UserPage.js index 85f4ae34..4dc6be95 100644 --- a/modern/src/settings/UserPage.js +++ b/modern/src/settings/UserPage.js @@ -11,16 +11,12 @@ import { 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'; @@ -263,28 +259,7 @@ const UserPage = () => { </Typography> </AccordionSummary> <AccordionDetails className={classes.details}> - <FormControl> - <InputLabel>{t('userToken')}</InputLabel> - <OutlinedInput - type="text" - label={t('userToken')} - value={item.token || ''} - onChange={(e) => setItem({ ...item, token: e.target.value })} - endAdornment={( - <InputAdornment position="end"> - <IconButton - size="small" - onClick={() => { - const token = [...Array(30)].map(() => Math.random().toString(36)[2]).join(''); - setItem({ ...item, token }); - }} - > - <CachedIcon fontSize="small" /> - </IconButton> - </InputAdornment> - )} - /> - </FormControl> + token <TextField label={t('userExpirationTime')} type="date" |