import React, { useState } from 'react'; import TextField from '@mui/material/TextField'; import { Accordion, AccordionSummary, AccordionDetails, Typography, Button, FormControl, Container, Checkbox, FormControlLabel, InputLabel, Select, MenuItem, FormGroup, } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { useNavigate } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; import { DropzoneArea } from 'react-mui-dropzone'; import { sessionActions } from '../store'; import EditAttributesAccordion from './components/EditAttributesAccordion'; import { useTranslation } from '../common/components/LocalizationProvider'; import SelectField from '../common/components/SelectField'; import PageLayout from '../common/components/PageLayout'; 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'; import useMapStyles from '../map/core/useMapStyles'; import { map } from '../map/core/MapView'; const useStyles = makeStyles((theme) => ({ container: { marginTop: theme.spacing(2), }, buttons: { marginTop: theme.spacing(2), marginBottom: theme.spacing(2), display: 'flex', justifyContent: 'space-evenly', '& > *': { flexBasis: '33%', }, }, details: { display: 'flex', flexDirection: 'column', gap: theme.spacing(2), paddingBottom: theme.spacing(3), }, })); const ServerPage = () => { const classes = useStyles(); const navigate = useNavigate(); const dispatch = useDispatch(); const t = useTranslation(); const mapStyles = useMapStyles(); const commonUserAttributes = useCommonUserAttributes(t); const commonDeviceAttributes = useCommonDeviceAttributes(t); const serverAttributes = useServerAttributes(t); const original = useSelector((state) => state.session.server); const [item, setItem] = useState({ ...original }); const handleFiles = useCatch(async (files) => { if (files.length > 0) { const file = files[0]; const response = await fetch(`/api/server/file/${file.path}`, { method: 'POST', body: file, }); if (!response.ok) { throw Error(await response.text()); } } }); const handleSave = useCatch(async () => { const response = await fetch('/api/server', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(item), }); if (response.ok) { dispatch(sessionActions.updateServer(await response.json())); navigate(-1); } else { throw Error(await response.text()); } }); return ( } breadcrumbs={['settingsTitle', 'settingsServer']}> {item && ( <> }> {t('sharedPreferences')} setItem({ ...item, mapUrl: event.target.value })} label={t('mapCustomLabel')} /> setItem({ ...item, overlayUrl: event.target.value })} label={t('mapOverlayCustom')} /> {t('mapDefault')} setItem({ ...item, map: e.target.value })} > {mapStyles.filter((style) => style.available).map((style) => ( {style.title} ))} {t('settingsCoordinateFormat')} setItem({ ...item, coordinateFormat: event.target.value })} > {t('sharedDecimalDegrees')} {t('sharedDegreesDecimalMinutes')} {t('sharedDegreesMinutesSeconds')} {t('settingsSpeedUnit')} setItem({ ...item, attributes: { ...item.attributes, speedUnit: e.target.value } })} > {t('sharedKn')} {t('sharedKmh')} {t('sharedMph')} {t('settingsDistanceUnit')} setItem({ ...item, attributes: { ...item.attributes, distanceUnit: e.target.value } })} > {t('sharedKm')} {t('sharedMi')} {t('sharedNmi')} {t('settingsAltitudeUnit')} setItem({ ...item, attributes: { ...item.attributes, altitudeUnit: e.target.value } })} > {t('sharedMeters')} {t('sharedFeet')} {t('settingsVolumeUnit')} setItem({ ...item, attributes: { ...item.attributes, volumeUnit: e.target.value } })} > {t('sharedLiter')} {t('sharedUsGallon')} {t('sharedImpGallon')} setItem({ ...item, attributes: { ...item.attributes, timezone: e.target.value } })} endpoint="/api/server/timezones" keyGetter={(it) => it} titleGetter={(it) => it} label={t('sharedTimezone')} /> setItem({ ...item, poiLayer: event.target.value })} label={t('mapPoiLayer')} /> setItem({ ...item, announcement: event.target.value })} label={t('serverAnnouncement')} /> setItem({ ...item, twelveHourFormat: event.target.checked })} />} label={t('settingsTwelveHourFormat')} /> setItem({ ...item, forceSettings: event.target.checked })} />} label={t('serverForceSettings')} /> }> {t('sharedLocation')} setItem({ ...item, latitude: Number(event.target.value) })} label={t('positionLatitude')} /> setItem({ ...item, longitude: Number(event.target.value) })} label={t('positionLongitude')} /> setItem({ ...item, zoom: Number(event.target.value) })} label={t('serverZoom')} /> { const { lng, lat } = map.getCenter(); setItem({ ...item, latitude: Number(lat.toFixed(6)), longitude: Number(lng.toFixed(6)), zoom: Number(map.getZoom().toFixed(1)), }); }} > {t('mapCurrentLocation')} }> {t('sharedPermissions')} setItem({ ...item, registration: event.target.checked })} />} label={t('serverRegistration')} /> setItem({ ...item, readonly: event.target.checked })} />} label={t('serverReadonly')} /> setItem({ ...item, deviceReadonly: event.target.checked })} />} label={t('userDeviceReadonly')} /> setItem({ ...item, limitCommands: event.target.checked })} />} label={t('userLimitCommands')} /> setItem({ ...item, disableReports: event.target.checked })} />} label={t('userDisableReports')} /> setItem({ ...item, fixedEmail: e.target.checked })} />} label={t('userFixedEmail')} /> }> {t('sharedFile')} setItem({ ...item, attributes })} definitions={{ ...commonUserAttributes, ...commonDeviceAttributes, ...serverAttributes }} /> > )} navigate(-1)}> {t('sharedCancel')} {t('sharedSave')} ); }; export default ServerPage;