diff options
-rw-r--r-- | modern/src/common/attributes/useCommonUserAttributes.js | 4 | ||||
-rw-r--r-- | modern/src/common/attributes/useServerAttributes.js | 8 | ||||
-rw-r--r-- | modern/src/common/components/BottomMenu.js | 2 | ||||
-rw-r--r-- | modern/src/common/util/permissions.js | 22 | ||||
-rw-r--r-- | modern/src/login/LoginLayout.js | 38 | ||||
-rw-r--r-- | modern/src/login/LoginPage.js | 25 | ||||
-rw-r--r-- | modern/src/map/core/useMapStyles.js | 2 | ||||
-rw-r--r-- | modern/src/map/overlay/useMapOverlays.js | 2 | ||||
-rw-r--r-- | modern/src/settings/ServerPage.js | 4 | ||||
-rw-r--r-- | modern/src/settings/components/SettingsMenu.js | 2 | ||||
-rw-r--r-- | web/l10n/en.json | 1 |
11 files changed, 55 insertions, 55 deletions
diff --git a/modern/src/common/attributes/useCommonUserAttributes.js b/modern/src/common/attributes/useCommonUserAttributes.js index 1409c5ac..ddd5d970 100644 --- a/modern/src/common/attributes/useCommonUserAttributes.js +++ b/modern/src/common/attributes/useCommonUserAttributes.js @@ -69,8 +69,4 @@ export default (t) => useMemo(() => ({ name: t('attributeWebMaxZoom'), type: 'number', }, - /* 'ui.hidePositionAttributes': { - name: t('attributeUiHidePositionAttributes'), - type: 'string', - }, */ }), [t]); diff --git a/modern/src/common/attributes/useServerAttributes.js b/modern/src/common/attributes/useServerAttributes.js new file mode 100644 index 00000000..ba49e44d --- /dev/null +++ b/modern/src/common/attributes/useServerAttributes.js @@ -0,0 +1,8 @@ +import { useMemo } from 'react'; + +export default (t) => useMemo(() => ({ + 'ui.disableLoginLanguage': { + name: t('attributeUiDisableLoginLanguage'), + type: 'boolean', + }, +}), [t]); diff --git a/modern/src/common/components/BottomMenu.js b/modern/src/common/components/BottomMenu.js index 282ae69e..37bdcf10 100644 --- a/modern/src/common/components/BottomMenu.js +++ b/modern/src/common/components/BottomMenu.js @@ -22,7 +22,7 @@ const BottomMenu = () => { const t = useTranslation(); const readonly = useReadonly(); - const userId = useSelector((state) => state.session.user?.id); + const userId = useSelector((state) => state.session.user.id); const socket = useSelector((state) => state.session.socket); const [anchorEl, setAnchorEl] = useState(null); diff --git a/modern/src/common/util/permissions.js b/modern/src/common/util/permissions.js index 34aeb89d..c866c41e 100644 --- a/modern/src/common/util/permissions.js +++ b/modern/src/common/util/permissions.js @@ -1,28 +1,28 @@ import { useSelector } from 'react-redux'; export const useAdministrator = () => useSelector((state) => { - const admin = state.session.user?.administrator; + const admin = state.session.user.administrator; return admin; }); export const useManager = () => useSelector((state) => { - const admin = state.session.user?.administrator; - const manager = (state.session.user?.userLimit || 0) > 0; + const admin = state.session.user.administrator; + const manager = (state.session.user.userLimit || 0) > 0; return admin || manager; }); export const useReadonly = () => useSelector((state) => { - const admin = state.session.user?.administrator; - const serverReadonly = state.session.server?.readonly; - const userReadonly = state.session.user?.readonly; + const admin = state.session.user.administrator; + const serverReadonly = state.session.server.readonly; + const userReadonly = state.session.user.readonly; return !admin && (serverReadonly || userReadonly); }); export const useDeviceReadonly = () => useSelector((state) => { - const admin = state.session.user?.administrator; - const serverReadonly = state.session.server?.readonly; - const userReadonly = state.session.user?.readonly; - const serverDeviceReadonly = state.session.server?.deviceReadonly; - const userDeviceReadonly = state.session.user?.deviceReadonly; + const admin = state.session.user.administrator; + const serverReadonly = state.session.server.readonly; + const userReadonly = state.session.user.readonly; + const serverDeviceReadonly = state.session.server.deviceReadonly; + const userDeviceReadonly = state.session.user.deviceReadonly; return !admin && (serverReadonly || userReadonly || serverDeviceReadonly || userDeviceReadonly); }); diff --git a/modern/src/login/LoginLayout.js b/modern/src/login/LoginLayout.js index dff187c4..83a87500 100644 --- a/modern/src/login/LoginLayout.js +++ b/modern/src/login/LoginLayout.js @@ -40,12 +40,6 @@ const useStyles = makeStyles((theme) => ({ padding: theme.spacing(5), width: '100%', }, - attribution: { - position: 'fixed', - bottom: theme.spacing(1), - right: theme.spacing(1.5), - fontSize: 'x-small', - }, })); const LoginLayout = ({ children }) => { @@ -53,26 +47,20 @@ const LoginLayout = ({ children }) => { const theme = useTheme(); return ( - <> - <main className={classes.root}> - <div className={classes.sidebar}> - {!useMediaQuery(theme.breakpoints.down('lg')) && ( - <svg height="64" width="240"> - <use xlinkHref={`${logoSvg}#img`} /> - </svg> - )} - </div> - <Paper className={classes.paper}> - <form className={classes.form}> - {children} - </form> - </Paper> - </main> - <div className={classes.attribution}> - Powered by - <a href="https://www.traccar.org/">Traccar GPS Tracking System</a> + <main className={classes.root}> + <div className={classes.sidebar}> + {!useMediaQuery(theme.breakpoints.down('lg')) && ( + <svg height="64" width="240"> + <use xlinkHref={`${logoSvg}#img`} /> + </svg> + )} </div> - </> + <Paper className={classes.paper}> + <form className={classes.form}> + {children} + </form> + </Paper> + </main> ); }; diff --git a/modern/src/login/LoginPage.js b/modern/src/login/LoginPage.js index 88a25d9d..c108f739 100644 --- a/modern/src/login/LoginPage.js +++ b/modern/src/login/LoginPage.js @@ -40,7 +40,8 @@ const useStyles = makeStyles((theme) => ({ }, resetPassword: { cursor: 'pointer', - textAlign: 'right', + textAlign: 'center', + marginTop: theme.spacing(2), }, })); @@ -59,11 +60,12 @@ const LoginPage = () => { const [email, setEmail] = usePersistedState('loginEmail', ''); const [password, setPassword] = useState(''); - const registrationEnabled = useSelector((state) => state.session.server?.registration); - const emailEnabled = useSelector((state) => state.session.server?.emailEnabled); + const registrationEnabled = useSelector((state) => state.session.server.registration); + const languageEnabled = useSelector((state) => !state.session.server.attributes['ui.disableLoginLanguage']); + const emailEnabled = useSelector((state) => state.session.server.emailEnabled); const [announcementShown, setAnnouncementShown] = useState(false); - const announcement = useSelector((state) => state.session.server?.announcement); + const announcement = useSelector((state) => state.session.server.announcement); const handleSubmit = async (event) => { event.preventDefault(); @@ -158,18 +160,21 @@ const LoginPage = () => { > {t('loginRegister')} </Button> - <FormControl fullWidth> - <InputLabel>{t('loginLanguage')}</InputLabel> - <Select label={t('loginLanguage')} value={language} onChange={(e) => setLanguage(e.target.value)}> - {languageList.map((it) => <MenuItem key={it.code} value={it.code}>{it.name}</MenuItem>)} - </Select> - </FormControl> + {languageEnabled && ( + <FormControl fullWidth> + <InputLabel>{t('loginLanguage')}</InputLabel> + <Select label={t('loginLanguage')} value={language} onChange={(e) => setLanguage(e.target.value)}> + {languageList.map((it) => <MenuItem key={it.code} value={it.code}>{it.name}</MenuItem>)} + </Select> + </FormControl> + )} </div> {emailEnabled && ( <Link onClick={() => navigate('/reset-password')} className={classes.resetPassword} underline="none" + variant="caption" > {t('loginReset')} </Link> diff --git a/modern/src/map/core/useMapStyles.js b/modern/src/map/core/useMapStyles.js index 72f18ebc..78b3cdee 100644 --- a/modern/src/map/core/useMapStyles.js +++ b/modern/src/map/core/useMapStyles.js @@ -29,7 +29,7 @@ export default () => { const tomTomKey = useAttributePreference('tomTomKey'); const hereKey = useAttributePreference('hereKey'); const mapboxAccessToken = useAttributePreference('mapboxAccessToken'); - const customMapUrl = useSelector((state) => state.session.server?.mapUrl); + const customMapUrl = useSelector((state) => state.session.server.mapUrl); return [ { diff --git a/modern/src/map/overlay/useMapOverlays.js b/modern/src/map/overlay/useMapOverlays.js index e6311202..664054b8 100644 --- a/modern/src/map/overlay/useMapOverlays.js +++ b/modern/src/map/overlay/useMapOverlays.js @@ -18,7 +18,7 @@ export default () => { const openWeatherKey = useAttributePreference('openWeatherKey'); const tomTomKey = useAttributePreference('tomTomKey'); const hereKey = useAttributePreference('hereKey'); - const customMapOverlay = useSelector((state) => state.session.server?.overlayUrl); + const customMapOverlay = useSelector((state) => state.session.server.overlayUrl); return [ { diff --git a/modern/src/settings/ServerPage.js b/modern/src/settings/ServerPage.js index 26ef5bbf..90b854db 100644 --- a/modern/src/settings/ServerPage.js +++ b/modern/src/settings/ServerPage.js @@ -29,6 +29,7 @@ import SettingsMenu from './components/SettingsMenu'; import useCommonDeviceAttributes from '../common/attributes/useCommonDeviceAttributes'; import useCommonUserAttributes from '../common/attributes/useCommonUserAttributes'; import { useCatch } from '../reactHelper'; +import useServerAttributes from '../common/attributes/useServerAttributes'; const useStyles = makeStyles((theme) => ({ container: { @@ -59,6 +60,7 @@ const ServerPage = () => { const commonUserAttributes = useCommonUserAttributes(t); const commonDeviceAttributes = useCommonDeviceAttributes(t); + const serverAttributes = useServerAttributes(t); const original = useSelector((state) => state.session.server); const [item, setItem] = useState({ ...original }); @@ -238,7 +240,7 @@ const ServerPage = () => { <EditAttributesView attributes={item.attributes} setAttributes={(attributes) => setItem({ ...item, attributes })} - definitions={{ ...commonUserAttributes, ...commonDeviceAttributes }} + definitions={{ ...commonUserAttributes, ...commonDeviceAttributes, ...serverAttributes }} /> </AccordionDetails> </Accordion> diff --git a/modern/src/settings/components/SettingsMenu.js b/modern/src/settings/components/SettingsMenu.js index a37d5d1a..181cd74c 100644 --- a/modern/src/settings/components/SettingsMenu.js +++ b/modern/src/settings/components/SettingsMenu.js @@ -34,7 +34,7 @@ const SettingsMenu = () => { const readonly = useReadonly(); const admin = useAdministrator(); const manager = useManager(); - const userId = useSelector((state) => state.session.user?.id); + const userId = useSelector((state) => state.session.user.id); const features = useFeatures(); diff --git a/web/l10n/en.json b/web/l10n/en.json index fc5a13a1..f0c51f96 100644 --- a/web/l10n/en.json +++ b/web/l10n/en.json @@ -121,6 +121,7 @@ "attributeUiDisableCalendars": "UI: Disable Calendars", "attributeUiDisableMaintenance": "UI: Disable Maintenance", "attributeUiHidePositionAttributes": "UI: Hide Position Attributes", + "attributeUiDisableLoginLanguage": "UI: Disable Login Language", "attributeNotificationTokens": "Notification Tokens", "errorTitle": "Error", "errorGeneral": "Invalid parameters or constraints violation", |