aboutsummaryrefslogtreecommitdiff
path: root/modern
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-06-11 18:32:36 -0700
committerAnton Tananaev <anton@traccar.org>2022-06-11 18:32:36 -0700
commite7995f3b7a6b0828b81bebaf556ef7afb59bef61 (patch)
treebd9aebc2ed24253ca0bb2a604ac65ae96730a3d1 /modern
parent0aecbc3bf856b17f42e363eff2bac4fb0ce1f7ed (diff)
downloadtrackermap-web-e7995f3b7a6b0828b81bebaf556ef7afb59bef61.tar.gz
trackermap-web-e7995f3b7a6b0828b81bebaf556ef7afb59bef61.tar.bz2
trackermap-web-e7995f3b7a6b0828b81bebaf556ef7afb59bef61.zip
Automatically add map keys
Diffstat (limited to 'modern')
-rw-r--r--modern/src/common/attributes/useCommonUserAttributes.js12
-rw-r--r--modern/src/map/core/useMapStyles.js7
-rw-r--r--modern/src/settings/PreferencesPage.js32
-rw-r--r--modern/src/settings/UserPage.js26
-rw-r--r--modern/src/settings/components/EditAttributesView.js3
5 files changed, 60 insertions, 20 deletions
diff --git a/modern/src/common/attributes/useCommonUserAttributes.js b/modern/src/common/attributes/useCommonUserAttributes.js
index c17b5c5d..c1c7d981 100644
--- a/modern/src/common/attributes/useCommonUserAttributes.js
+++ b/modern/src/common/attributes/useCommonUserAttributes.js
@@ -1,6 +1,18 @@
import { useMemo } from 'react';
export default (t) => useMemo(() => ({
+ locationIqKey: {
+ name: t('mapLocationIqKey'),
+ type: 'string',
+ },
+ mapboxAccessToken: {
+ name: t('mapMapboxKey'),
+ type: 'string',
+ },
+ mapTilerKey: {
+ name: t('mapMapTilerKey'),
+ type: 'string',
+ },
notificationTokens: {
name: t('attributeNotificationTokens'),
type: 'string',
diff --git a/modern/src/map/core/useMapStyles.js b/modern/src/map/core/useMapStyles.js
index f635e15c..944cd3ea 100644
--- a/modern/src/map/core/useMapStyles.js
+++ b/modern/src/map/core/useMapStyles.js
@@ -78,12 +78,14 @@ export default () => {
title: t('mapLocationIqEarth'),
uri: styleLocationIq('earth', locationIqKey),
available: !!locationIqKey,
+ attribute: 'locationIqKey',
},
{
id: 'locationIqHybrid',
title: t('mapLocationIqHybrid'),
uri: styleLocationIq('hybrid', locationIqKey),
available: !!locationIqKey,
+ attribute: 'locationIqKey',
},
{
id: 'osm',
@@ -102,30 +104,35 @@ export default () => {
title: t('mapMapboxStreets'),
uri: styleMapbox('streets-v11'),
available: !!mapboxAccessToken,
+ attribute: 'mapboxAccessToken',
},
{
id: 'mapboxOutdoors',
title: t('mapMapboxOutdoors'),
uri: styleMapbox('outdoors-v11'),
available: !!mapboxAccessToken,
+ attribute: 'mapboxAccessToken',
},
{
id: 'mapboxSatellite',
title: t('mapMapboxSatellite'),
uri: styleMapbox('satellite-v9'),
available: !!mapboxAccessToken,
+ attribute: 'mapboxAccessToken',
},
{
id: 'mapTilerBasic',
title: t('mapMapTilerBasic'),
uri: styleMapTiler('basic', mapTilerKey),
available: !!mapTilerKey,
+ attribute: 'mapTilerKey',
},
{
id: 'mapTilerHybrid',
title: t('mapMapTilerHybrid'),
uri: styleMapTiler('hybrid', mapTilerKey),
available: !!mapTilerKey,
+ attribute: 'mapTilerKey',
},
{
id: 'custom',
diff --git a/modern/src/settings/PreferencesPage.js b/modern/src/settings/PreferencesPage.js
index c128e5e4..2a2674f7 100644
--- a/modern/src/settings/PreferencesPage.js
+++ b/modern/src/settings/PreferencesPage.js
@@ -1,17 +1,8 @@
import React 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,
} from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
@@ -38,8 +29,11 @@ const useStyles = makeStyles((theme) => ({
const PreferencesPage = () => {
const classes = useStyles();
+ const navigate = useNavigate();
const t = useTranslation();
+ const userId = useSelector((state) => state.session.user.id);
+
const { languages, language, setLanguage } = useLocalization();
const languageList = Object.entries(languages).map((values) => ({ code: values[0], name: values[1].name }));
@@ -96,11 +90,21 @@ const PreferencesPage = () => {
<Select
label={t('mapActive')}
value={activeMapStyles}
- onChange={(e) => setActiveMapStyles(e.target.value)}
+ onChange={(e, child) => {
+ const clicked = mapStyles.find((s) => s.id === child.props.value);
+ if (clicked.available) {
+ setActiveMapStyles(e.target.value);
+ } else if (clicked.id !== 'custom') {
+ const query = new URLSearchParams({ attribute: clicked.attribute });
+ navigate(`/settings/user/${userId}?${query.toString()}`);
+ }
+ }}
multiple
>
{mapStyles.map((style) => (
- <MenuItem key={style.id} value={style.id}>{style.title}</MenuItem>
+ <MenuItem key={style.id} value={style.id}>
+ <Typography component="span" color={style.available ? 'textPrimary' : 'error'}>{style.title}</Typography>
+ </MenuItem>
))}
</Select>
</FormControl>
diff --git a/modern/src/settings/UserPage.js b/modern/src/settings/UserPage.js
index d4046fbf..964291e8 100644
--- a/modern/src/settings/UserPage.js
+++ b/modern/src/settings/UserPage.js
@@ -1,6 +1,4 @@
-import React, { useState } from 'react';
-import TextField from '@mui/material/TextField';
-
+import React, { useEffect, useState } from 'react';
import {
Accordion,
AccordionSummary,
@@ -16,6 +14,7 @@ import {
IconButton,
OutlinedInput,
FormGroup,
+ TextField,
} from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
@@ -33,6 +32,7 @@ import SettingsMenu from './components/SettingsMenu';
import useCommonUserAttributes from '../common/attributes/useCommonUserAttributes';
import { useAdministrator, useManager } from '../common/util/permissions';
import { prefixString } from '../common/util/stringUtils';
+import useQuery from '../common/util/useQuery';
const useStyles = makeStyles((theme) => ({
details: {
@@ -58,6 +58,21 @@ const UserPage = () => {
const [item, setItem] = useState();
+ 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 === currentUserId) {
dispatch(sessionActions.updateUser(result));
@@ -79,7 +94,7 @@ const UserPage = () => {
>
{item && (
<>
- <Accordion defaultExpanded>
+ <Accordion defaultExpanded={!attribute}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography variant="subtitle1">
{t('sharedRequired')}
@@ -286,7 +301,7 @@ const UserPage = () => {
</FormGroup>
</AccordionDetails>
</Accordion>
- <Accordion>
+ <Accordion defaultExpanded={!!attribute}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography variant="subtitle1">
{t('sharedAttributes')}
@@ -297,6 +312,7 @@ const UserPage = () => {
attributes={item.attributes}
setAttributes={(attributes) => setItem({ ...item, attributes })}
definitions={{ ...commonUserAttributes, ...userAttributes }}
+ focusAttribute={attribute}
/>
</AccordionDetails>
</Accordion>
diff --git a/modern/src/settings/components/EditAttributesView.js b/modern/src/settings/components/EditAttributesView.js
index 6b7ab5ac..3329d7bc 100644
--- a/modern/src/settings/components/EditAttributesView.js
+++ b/modern/src/settings/components/EditAttributesView.js
@@ -27,7 +27,7 @@ const useStyles = makeStyles((theme) => ({
},
}));
-const EditAttributesView = ({ attributes, setAttributes, definitions }) => {
+const EditAttributesView = ({ attributes, setAttributes, definitions, focusAttribute }) => {
const classes = useStyles();
const t = useTranslation();
@@ -176,6 +176,7 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => {
type={type === 'number' ? 'number' : 'text'}
value={getDisplayValue(value, subtype)}
onChange={(e) => updateAttribute(key, e.target.value, type, subtype)}
+ autoFocus={focusAttribute === key}
endAdornment={(
<InputAdornment position="end">
<IconButton size="small" onClick={() => deleteAttribute(key)}>