diff options
author | Iván Ávalos <avalos@disroot.org> | 2021-12-12 19:51:20 -0600 |
---|---|---|
committer | Iván Ávalos <avalos@disroot.org> | 2021-12-12 19:51:20 -0600 |
commit | d7edd918d1435384e2b51d8f3ce8fb61aa7e7e01 (patch) | |
tree | 6d611bd3f4bb978958a6e641b8c7506e1750acae /modern/src | |
parent | 5e3bbc09e614df29091f1836ce095af2825ca1a7 (diff) | |
download | etbsa-traccar-web-d7edd918d1435384e2b51d8f3ce8fb61aa7e7e01.tar.gz etbsa-traccar-web-d7edd918d1435384e2b51d8f3ce8fb61aa7e7e01.tar.bz2 etbsa-traccar-web-d7edd918d1435384e2b51d8f3ce8fb61aa7e7e01.zip |
Added commands support (untested) and removed all languages except ES and EN
Diffstat (limited to 'modern/src')
-rw-r--r-- | modern/src/App.js | 2 | ||||
-rw-r--r-- | modern/src/CommandsPage.js | 119 | ||||
-rw-r--r-- | modern/src/LocalizationProvider.js | 104 | ||||
-rw-r--r-- | modern/src/map/PositionsMap.js | 1 | ||||
-rw-r--r-- | modern/src/map/StatusView.js | 26 |
5 files changed, 142 insertions, 110 deletions
diff --git a/modern/src/App.js b/modern/src/App.js index a53ffc6..b6d0084 100644 --- a/modern/src/App.js +++ b/modern/src/App.js @@ -26,6 +26,7 @@ import DriversPage from './settings/DriversPage'; import DriverPage from './settings/DriverPage'; import CalendarsPage from './settings/CalendarsPage'; import CalendarPage from './settings/CalendarPage'; +import CommandsPage from './CommandsPage'; import ComputedAttributesPage from './settings/ComputedAttributesPage'; import ComputedAttributePage from './settings/ComputedAttributePage'; import MaintenancesPage from './settings/MaintenancesPage'; @@ -63,6 +64,7 @@ const App = () => { <Route exact path="/position/:id?" component={PositionPage} /> <Route exact path="/user/:id?" component={UserPage} /> <Route exact path="/device/:id?" component={DevicePage} /> + <Route exact path="/device/:id?/commands" component={CommandsPage} /> <Route exact path="/geofence/:id?" component={GeofencePage} /> <Route exact path="/geofences" component={GeofencesPage} /> <Route exact path="/settings/notifications" component={NotificationsPage} /> diff --git a/modern/src/CommandsPage.js b/modern/src/CommandsPage.js new file mode 100644 index 0000000..e36c365 --- /dev/null +++ b/modern/src/CommandsPage.js @@ -0,0 +1,119 @@ +import React, { useState } from 'react'; +import { useHistory, useParams } from 'react-router-dom'; +import { + makeStyles, Typography, Container, Card, CardContent, RadioGroup, Radio, FormControl, FormControlLabel, Button +} from '@material-ui/core'; + +import MainToolbar from './MainToolbar'; +import { useEffectAsync } from './reactHelper'; +import { useTranslation } from './LocalizationProvider'; + +const useStyles = makeStyles((theme) => ({ + root: { + marginTop: theme.spacing(2), + marginBottom: theme.spacing(2), + }, + buttons: { + display: 'flex', + justifyContent: 'space-evenly', + '& > *': { + flexBasis: '33%', + }, + }, +})); + +const CommandsPage = () => { + const classes = useStyles(); + const { id } = useParams(); + const t = useTranslation(); + const history = useHistory(); + + const [device, setDevice] = useState(); + const [commands, setCommands] = useState([]); + const [selectedCommand, setSelectedCommand] = useState(); + + useEffectAsync(async () => { + if (id) { + let device = undefined; + + const response = await fetch(`/api/devices?id=${id}`, { + headers: { + Accept: 'application/json' + }, + }); + if (response.ok) { + const items = await response.json(); + device = items[0]; + setDevice(items[0]); + } else { + setDevice({}); + } + + if (device) { + const response = await fetch(`/api/commands/send?deviceId=${device.id}`, { + headers: { + Accept: 'application/json' + }, + }); + if (response.ok) { + const items = await response.json(); + setCommands(items); + } else { + setCommands([]); + } + } + } + }, [id]); + + const handleSend = async () => { + console.log ('Selected: ' + selectedCommand); + const response = await fetch(`/api/commands/send`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + id: selectedCommand.id, + deviceId: device.id, + }), + }); + + if (response.ok) { + history.goBack(); + } + }; + + return ( + <> + <MainToolbar /> + <Container maxWidth="sm" className={classes.root}> + <Card> + {device && ( + <> + <CardContent> + <Typography gutterBottom variant="h5">{t('commandSend')}</Typography> + {commands && ( + <FormControl fullWidth aria-label="command"> + <RadioGroup onChange={(event) => setSelectedCommand(event.target.value) }> + {commands.map (command => ( + <FormControlLabel value={command.id.toString()} control={<Radio />} label={command.description} /> + ))} + </RadioGroup> + <div className={classes.buttons}> + <Button type="button" color="primary" variant="outlined" onClick={() => history.goBack()}> + {t('sharedCancel')} + </Button> + <Button type="button" color="primary" variant="contained" onClick={handleSend}> + {t('commandSend')} + </Button> + </div> + </FormControl> + )} + </CardContent> + </> + )} + </Card> + </Container> + </> + ); +} + +export default CommandsPage; diff --git a/modern/src/LocalizationProvider.js b/modern/src/LocalizationProvider.js index 1069075..6d8605b 100644 --- a/modern/src/LocalizationProvider.js +++ b/modern/src/LocalizationProvider.js @@ -1,116 +1,12 @@ import React, { createContext, useContext } from 'react'; import usePersistedState from './common/usePersistedState'; -import af from '../../web/l10n/af.json'; -import ar from '../../web/l10n/ar.json'; -import az from '../../web/l10n/az.json'; -import bg from '../../web/l10n/bg.json'; -import bn from '../../web/l10n/bn.json'; -import cs from '../../web/l10n/cs.json'; -import da from '../../web/l10n/da.json'; -import de from '../../web/l10n/de.json'; -import el from '../../web/l10n/el.json'; import en from '../../web/l10n/en.json'; import es from '../../web/l10n/es.json'; -import fa from '../../web/l10n/fa.json'; -import fi from '../../web/l10n/fi.json'; -import fr from '../../web/l10n/fr.json'; -import he from '../../web/l10n/he.json'; -import hi from '../../web/l10n/hi.json'; -import hr from '../../web/l10n/hr.json'; -import hu from '../../web/l10n/hu.json'; -import id from '../../web/l10n/id.json'; -import it from '../../web/l10n/it.json'; -import ja from '../../web/l10n/ja.json'; -import ka from '../../web/l10n/ka.json'; -import kk from '../../web/l10n/kk.json'; -import km from '../../web/l10n/km.json'; -import ko from '../../web/l10n/ko.json'; -import lo from '../../web/l10n/lo.json'; -import lt from '../../web/l10n/lt.json'; -import lv from '../../web/l10n/lv.json'; -import ml from '../../web/l10n/ml.json'; -import mn from '../../web/l10n/mn.json'; -import ms from '../../web/l10n/ms.json'; -import nb from '../../web/l10n/nb.json'; -import ne from '../../web/l10n/ne.json'; -import nl from '../../web/l10n/nl.json'; -import nn from '../../web/l10n/nn.json'; -import pl from '../../web/l10n/pl.json'; -import pt from '../../web/l10n/pt.json'; -import ptBR from '../../web/l10n/pt_BR.json'; -import ro from '../../web/l10n/ro.json'; -import ru from '../../web/l10n/ru.json'; -import si from '../../web/l10n/si.json'; -import sk from '../../web/l10n/sk.json'; -import sl from '../../web/l10n/sl.json'; -import sq from '../../web/l10n/sq.json'; -import sr from '../../web/l10n/sr.json'; -import sv from '../../web/l10n/sv.json'; -import ta from '../../web/l10n/ta.json'; -import th from '../../web/l10n/th.json'; -import tr from '../../web/l10n/tr.json'; -import uk from '../../web/l10n/uk.json'; -import uz from '../../web/l10n/uz.json'; -import vi from '../../web/l10n/vi.json'; -import zh from '../../web/l10n/zh.json'; -import zhTW from '../../web/l10n/zh_TW.json'; const languages = { - af: { data: af, name: 'Afrikaans' }, - ar: { data: ar, name: 'العربية' }, - az: { data: az, name: 'Azərbaycanca' }, - bg: { data: bg, name: 'Български' }, - bn: { data: bn, name: 'বাংলা' }, - cs: { data: cs, name: 'Čeština' }, - de: { data: de, name: 'Deutsch' }, - da: { data: da, name: 'Dansk' }, - el: { data: el, name: 'Ελληνικά' }, en: { data: en, name: 'English' }, es: { data: es, name: 'Español' }, - fa: { data: fa, name: 'فارسی' }, - fi: { data: fi, name: 'Suomi' }, - fr: { data: fr, name: 'Français' }, - he: { data: he, name: 'עברית' }, - hi: { data: hi, name: 'हिन्दी' }, - hr: { data: hr, name: 'Hrvatski' }, - hu: { data: hu, name: 'Magyar' }, - id: { data: id, name: 'Bahasa Indonesia' }, - it: { data: it, name: 'Italiano' }, - ja: { data: ja, name: '日本語' }, - ka: { data: ka, name: 'ქართული' }, - kk: { data: kk, name: 'Қазақша' }, - ko: { data: ko, name: '한국어' }, - km: { data: km, name: 'ភាសាខ្មែរ' }, - lo: { data: lo, name: 'ລາວ' }, - lt: { data: lt, name: 'Lietuvių' }, - lv: { data: lv, name: 'Latviešu' }, - ml: { data: ml, name: 'മലയാളം' }, - mn: { data: mn, name: 'Монгол хэл' }, - ms: { data: ms, name: 'بهاس ملايو' }, - nb: { data: nb, name: 'Norsk bokmål' }, - ne: { data: ne, name: 'नेपाली' }, - nl: { data: nl, name: 'Nederlands' }, - nn: { data: nn, name: 'Norsk nynorsk' }, - pl: { data: pl, name: 'Polski' }, - pt: { data: pt, name: 'Português' }, - ptBR: { data: ptBR, name: 'Português (Brasil)' }, - ro: { data: ro, name: 'Română' }, - ru: { data: ru, name: 'Русский' }, - si: { data: si, name: 'සිංහල' }, - sk: { data: sk, name: 'Slovenčina' }, - sl: { data: sl, name: 'Slovenščina' }, - sq: { data: sq, name: 'Shqipëria' }, - sr: { data: sr, name: 'Srpski' }, - sv: { data: sv, name: 'Svenska' }, - ta: { data: ta, name: 'தமிழ்' }, - th: { data: th, name: 'ไทย' }, - tr: { data: tr, name: 'Türkçe' }, - uk: { data: uk, name: 'Українська' }, - uz: { data: uz, name: 'Oʻzbekcha' }, - vi: { data: vi, name: 'Tiếng Việt' }, - zh: { data: zh, name: '中文' }, - zhTW: { data: zhTW, name: '中文 (Taiwan)' }, }; const getDefaultLanguage = () => { diff --git a/modern/src/map/PositionsMap.js b/modern/src/map/PositionsMap.js index 1e7571b..f9a2a23 100644 --- a/modern/src/map/PositionsMap.js +++ b/modern/src/map/PositionsMap.js @@ -61,6 +61,7 @@ const PositionsMap = ({ positions }) => { onShowDetails={(positionId) => history.push(`/position/${positionId}`)} onShowHistory={() => history.push('/replay')} onEditClick={(deviceId) => history.push(`/device/${deviceId}`)} + onCommandsClick={(deviceId) => history.push(`/device/${deviceId}/commands`) } /> </ThemeProvider> </Provider>, diff --git a/modern/src/map/StatusView.js b/modern/src/map/StatusView.js index aaf2882..6b6836c 100644 --- a/modern/src/map/StatusView.js +++ b/modern/src/map/StatusView.js @@ -4,12 +4,12 @@ import { } from '@material-ui/core'; import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; -import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; import ListItemText from '@material-ui/core/ListItemText'; import { useSelector } from 'react-redux'; import ReplayIcon from '@material-ui/icons/Replay'; import EditIcon from '@material-ui/icons/Edit'; +import SendIcon from '@material-ui/icons/Send'; import DeleteIcon from '@material-ui/icons/Delete'; import LinkIcon from '@material-ui/icons/Link'; @@ -29,10 +29,14 @@ const useStyles = makeStyles((theme) => ({ listItemContainer: { maxWidth: '300px', }, + listItemRoot: { + paddingTop: '0px', + paddingBottom: '0px', + } })); const StatusView = ({ - deviceId, onShowDetails, onShowHistory, onEditClick, + deviceId, onShowDetails, onShowHistory, onEditClick, onCommandsClick, }) => { const classes = useStyles(); const t = useTranslation(); @@ -54,6 +58,11 @@ const StatusView = ({ onEditClick(deviceId); }; + const handleCommandsClick = (e) => { + e.preventDefault(); + onCommandsClick(deviceId); + } + const handleRemove = () => { setRemoveDialogShown(true); }; @@ -73,18 +82,18 @@ const StatusView = ({ <Grid container direction="column"> <Grid item> <List> - <ListItem classes={{ container: classes.listItemContainer}}> + <ListItem classes={{ container: classes.listItemContainer, root: classes.listItemRoot }} > <ListItemText primary={t('positionDatetime')} secondary={formatDate(position.serverTime)} /> </ListItem> - <ListItem classes={{ container: classes.listItemContainer }}> + <ListItem classes={{ container: classes.listItemContainer, root: classes.listItemRoot }}> <ListItemText primary={t('positionSpeed')} secondary={formatSpeed(position.speed, speedUnit, t)} /> </ListItem> {position.attributes.hours && ( - <ListItem classes={{ container: classes.listItemContainer }}> + <ListItem classes={{ container: classes.listItemContainer, root: classes.listItemRoot }}> <ListItemText primary={t('positionHours')} secondary={formatHours(position.attributes.hours, t)} /> </ListItem>)} {position.address && ( - <ListItem classes={{ container: classes.listItemContainer }}> + <ListItem classes={{ container: classes.listItemContainer, root: classes.listItemRoot }}> <ListItemText primary={t('positionAddress')} secondary={position.address} /> </ListItem>)} </List> @@ -104,6 +113,11 @@ const StatusView = ({ </IconButton> </Grid> <Grid item> + <IconButton onClick={handleCommandsClick}> + <SendIcon /> + </IconButton> + </Grid> + <Grid item> <IconButton onClick={handleEditClick}> <EditIcon /> </IconButton> |