all of the linting
parent
df44a9f49e
commit
0e6b7c7d3a
15
src/App.js
15
src/App.js
|
@ -4,9 +4,9 @@ import React, { useState } from 'react';
|
||||||
import Login from './components/views/login';
|
import Login from './components/views/login';
|
||||||
import UserAdmin from './components/views/useradmin';
|
import UserAdmin from './components/views/useradmin';
|
||||||
import GlobalSnack from './components/widgets/globalSnack';
|
import GlobalSnack from './components/widgets/globalSnack';
|
||||||
import DeviceStore from './context/devices';
|
import DevicesProvider from './context/devices';
|
||||||
import ToastStore from './context/toast';
|
import ToastProvider from './context/toast';
|
||||||
import { UserProvider } from './context/users';
|
import UserProvider from './context/users';
|
||||||
import * as authenticationController from './controllers/authentication';
|
import * as authenticationController from './controllers/authentication';
|
||||||
|
|
||||||
// Connection opened
|
// Connection opened
|
||||||
|
@ -34,16 +34,15 @@ function App() {
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
|
|
||||||
<UserProvider>
|
<UserProvider>
|
||||||
<DeviceStore>
|
<DevicesProvider>
|
||||||
<ToastStore>
|
<ToastProvider>
|
||||||
|
|
||||||
<GlobalSnack />
|
<GlobalSnack />
|
||||||
|
|
||||||
{session ? <UserAdmin /> : <Login />}
|
{session ? <UserAdmin /> : <Login />}
|
||||||
|
|
||||||
</ToastStore>
|
</ToastProvider>
|
||||||
</DeviceStore>
|
</DevicesProvider>
|
||||||
|
|
||||||
</UserProvider>
|
</UserProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import Grid from '@mui/material/Grid';
|
import Grid from '@mui/material/Grid';
|
||||||
import GoogleMapReact from 'google-map-react';
|
import GoogleMapReact from 'google-map-react';
|
||||||
import React from 'react';
|
|
||||||
import { Scrollbars } from 'react-custom-scrollbars';
|
import { Scrollbars } from 'react-custom-scrollbars';
|
||||||
|
|
||||||
import DrivesTable from './tabPane';
|
import DrivesTable from './tabPane';
|
||||||
|
|
||||||
function DeviceLastSeenMap() {
|
function DeviceLastSeenMap() {
|
||||||
return (
|
return (
|
||||||
<div style={{ height: '500px', width: 'calc(100%)' }}>
|
<div style={{ height: '500px', width: 'calc(100%)' }}>
|
||||||
|
|
||||||
<GoogleMapReact
|
<GoogleMapReact
|
||||||
height="100px"
|
height="100px"
|
||||||
bootstrapURLKeys={{ key: process.env.REACT_APP_GMAPS_API_KEY }}
|
bootstrapURLKeys={{ key: process.env.REACT_APP_GMAPS_API_KEY }}
|
||||||
|
@ -103,14 +104,16 @@ function DeviceLastSeenMap() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SignIn(props) {
|
function DeviceData(props) {
|
||||||
return (
|
const { device } = props;
|
||||||
<div style={{
|
|
||||||
height: '100%',
|
|
||||||
width: '100%',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: '100%',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Scrollbars autoHeightMin="100%" autoHeightMax="100%">
|
<Scrollbars autoHeightMin="100%" autoHeightMax="100%">
|
||||||
<Grid container style={{ padding: 30 }}>
|
<Grid container style={{ padding: 30 }}>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
|
@ -118,12 +121,18 @@ export default function SignIn(props) {
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<DrivesTable dongleId={props.device.dongle_id} />
|
<DrivesTable dongleId={device.dongle_id} />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Scrollbars>
|
</Scrollbars>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceData.propTypes = {
|
||||||
|
device: PropTypes.shape({
|
||||||
|
dongle_id: PropTypes.string.isRequired,
|
||||||
|
}).isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeviceData;
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import ButtonBase from '@mui/material/ButtonBase';
|
import ButtonBase from '@mui/material/ButtonBase';
|
||||||
import Chip from '@mui/material/Chip';
|
import Chip from '@mui/material/Chip';
|
||||||
import Divider from '@mui/material/Divider';
|
import Divider from '@mui/material/Divider';
|
||||||
import Grid from '@mui/material/Grid';
|
import Grid from '@mui/material/Grid';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import React, { useEffect } from 'react';
|
|
||||||
|
|
||||||
const stylezz = {
|
const stylezz = {
|
||||||
margin: '0px 2px 0px 0px',
|
margin: '0px 2px 0px 0px',
|
||||||
|
@ -22,10 +23,11 @@ function timeSince(date) {
|
||||||
return 'just now';
|
return 'just now';
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SignIn(props) {
|
function DeviceOverview(props) {
|
||||||
const [state, setState] = React.useState({ count: 0, last_seen: 0 });
|
|
||||||
const { device } = props;
|
const { device } = props;
|
||||||
|
|
||||||
|
const [state, setState] = React.useState({ count: 0, last_seen: 0 });
|
||||||
|
|
||||||
// Reloads component to update X time ago
|
// Reloads component to update X time ago
|
||||||
// TODO prevent X time ago from being refreshed when the device has been
|
// TODO prevent X time ago from being refreshed when the device has been
|
||||||
// updated to show offline.
|
// updated to show offline.
|
||||||
|
@ -72,7 +74,6 @@ export default function SignIn(props) {
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
{device.online
|
{device.online
|
||||||
? <Chip style={{ background: '#004d40', ...stylezz }} label="Online" size="small" variant="outlined" />
|
? <Chip style={{ background: '#004d40', ...stylezz }} label="Online" size="small" variant="outlined" />
|
||||||
: <Chip style={{ background: '#b71c1c', ...stylezz }} label={`Offline ${deviceLastSeen}`} size="small" variant="outlined" />}
|
: <Chip style={{ background: '#b71c1c', ...stylezz }} label={`Offline ${deviceLastSeen}`} size="small" variant="outlined" />}
|
||||||
|
@ -84,6 +85,15 @@ export default function SignIn(props) {
|
||||||
</ButtonBase>
|
</ButtonBase>
|
||||||
<Divider />
|
<Divider />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceOverview.propTypes = {
|
||||||
|
device: PropTypes.shape({
|
||||||
|
dongle_id: PropTypes.string.isRequired,
|
||||||
|
last_seen: PropTypes.string.isRequired,
|
||||||
|
online: PropTypes.bool.isRequired,
|
||||||
|
}).isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeviceOverview;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import DeleteIcon from '@mui/icons-material/Delete';
|
import React, { useContext, useEffect } from 'react';
|
||||||
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
|
import PropTypes from 'prop-types';
|
||||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
|
||||||
import { Skeleton } from '@mui/material';
|
import { Skeleton } from '@mui/material';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
|
@ -12,9 +11,12 @@ import TableContainer from '@mui/material/TableContainer';
|
||||||
import TableHead from '@mui/material/TableHead';
|
import TableHead from '@mui/material/TableHead';
|
||||||
import TableRow from '@mui/material/TableRow';
|
import TableRow from '@mui/material/TableRow';
|
||||||
import Tooltip from '@mui/material/Tooltip';
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
import React, { useContext, useEffect } from 'react';
|
import DeleteIcon from '@mui/icons-material/Delete';
|
||||||
import { context as DeviceContext } from '../../../context/devices';
|
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
|
||||||
import { context as SnackbarContext } from '../../../context/toast';
|
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
||||||
|
|
||||||
|
import { DevicesContext } from '../../../context/devices';
|
||||||
|
import { ToastContext } from '../../../context/toast';
|
||||||
import * as deviceController from '../../../controllers/devices';
|
import * as deviceController from '../../../controllers/devices';
|
||||||
import * as helpers from '../../../controllers/helpers';
|
import * as helpers from '../../../controllers/helpers';
|
||||||
|
|
||||||
|
@ -29,20 +31,26 @@ function loading() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function EnhancedTable(props) {
|
function BootLogsTable(props) {
|
||||||
const [state, dispatch] = useContext(DeviceContext);
|
const { dongleId } = props;
|
||||||
|
|
||||||
const [, notifDispatch] = useContext(SnackbarContext);
|
const [state, dispatch] = useContext(DevicesContext);
|
||||||
|
const [, notifDispatch] = useContext(ToastContext);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
deviceController.getBootlogs(props.dongleId).then((res) => {
|
deviceController.getBootlogs(dongleId).then((res) => {
|
||||||
|
// TODO: why set timeout 1?
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
dispatch({ type: 'update_dongle_bootlogs', dongle_id: props.dongleId, bootlogs: res.data });
|
dispatch({
|
||||||
|
type: 'update_dongle_bootlogs',
|
||||||
|
dongle_id: dongleId,
|
||||||
|
bootlogs: res.data,
|
||||||
|
});
|
||||||
}, 1);
|
}, 1);
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
notifDispatch({ type: 'NEW_TOAST', msg: 'Failed to load bootlogs' });
|
notifDispatch({ type: 'NEW_TOAST', msg: 'Failed to load bootlogs' });
|
||||||
});
|
});
|
||||||
}, [dispatch, notifDispatch, props.dongleId]);
|
}, [dispatch, notifDispatch, dongleId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: '100%' }}>
|
<Box sx={{ width: '100%' }}>
|
||||||
|
@ -65,14 +73,13 @@ export default function EnhancedTable(props) {
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{/* if you don't need to support IE11, you can replace the `stableSort` call with:
|
{/* if you don't need to support IE11, you can replace the `stableSort` call with:
|
||||||
rows.slice().sort(getComparator(order, orderBy)) */}
|
rows.slice().sort(getComparator(order, orderBy)) */}
|
||||||
{state.dongles[props.dongleId].boot ? state.dongles[props.dongleId].boot.map((row) => (
|
{state.dongles[dongleId].boot ? state.dongles[dongleId].boot.map((row) => (
|
||||||
<TableRow hover>
|
<TableRow hover>
|
||||||
<TableCell>{helpers.formatDate(row.date)}</TableCell>
|
<TableCell>{helpers.formatDate(row.date)}</TableCell>
|
||||||
<TableCell>{row.name}</TableCell>
|
<TableCell>{row.name}</TableCell>
|
||||||
<TableCell>{`${Math.round(row.size / 1024)} MiB`}</TableCell>
|
<TableCell>{`${Math.round(row.size / 1024)} MiB`}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Tooltip title="Open in new window">
|
<Tooltip title="Open in new window">
|
||||||
|
|
||||||
<IconButton size="small" onClick={() => window.open(row.permalink, '_blank')}>
|
<IconButton size="small" onClick={() => window.open(row.permalink, '_blank')}>
|
||||||
<OpenInNewIcon fontSize="inherit" />
|
<OpenInNewIcon fontSize="inherit" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
@ -100,3 +107,9 @@ export default function EnhancedTable(props) {
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BootLogsTable.propTypes = {
|
||||||
|
dongleId: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BootLogsTable;
|
||||||
|
|
|
@ -54,31 +54,26 @@ function RichContent(props) {
|
||||||
</AccordionDetails>
|
</AccordionDetails>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
export default function Console() {
|
function ConsoleTable() {
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: '100%' }}>
|
<Box sx={{ width: '100%' }}>
|
||||||
<Paper sx={{ width: '100%', mb: 2 }}>
|
<Paper sx={{ width: '100%', mb: 2 }}>
|
||||||
|
|
||||||
{/*
|
{/*
|
||||||
Object.keys(state).map(key => {
|
Object.keys(state).map(key => {
|
||||||
console.log(key, state[key])
|
console.log(key, state[key])
|
||||||
return (<RichContent content={state[key]} key1={key} />)
|
return (<RichContent content={state[key]} key1={key} />)
|
||||||
}
|
}
|
||||||
|
|
||||||
)
|
)
|
||||||
*/}
|
*/}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default ConsoleTable;
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
import React, { useContext, useEffect } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import DeleteIcon from '@mui/icons-material/Delete';
|
|
||||||
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
|
|
||||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
|
||||||
import { Skeleton } from '@mui/material';
|
import { Skeleton } from '@mui/material';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
|
@ -14,17 +11,17 @@ import TableContainer from '@mui/material/TableContainer';
|
||||||
import TableHead from '@mui/material/TableHead';
|
import TableHead from '@mui/material/TableHead';
|
||||||
import TableRow from '@mui/material/TableRow';
|
import TableRow from '@mui/material/TableRow';
|
||||||
import Tooltip from '@mui/material/Tooltip';
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
import React, { useContext, useEffect } from 'react';
|
import DeleteIcon from '@mui/icons-material/Delete';
|
||||||
import { context as DeviceContext } from '../../../context/devices';
|
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
|
||||||
|
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
||||||
|
|
||||||
|
import { ACTIONS, DevicesContext } from '../../../context/devices';
|
||||||
import * as deviceController from '../../../controllers/devices';
|
import * as deviceController from '../../../controllers/devices';
|
||||||
import * as helpers from '../../../controllers/helpers';
|
import * as helpers from '../../../controllers/helpers';
|
||||||
|
|
||||||
function buildContent(row) {
|
function buildContent(row) {
|
||||||
return (
|
return (
|
||||||
<TableRow
|
<TableRow hover>
|
||||||
hover
|
|
||||||
>
|
|
||||||
|
|
||||||
<TableCell>{helpers.formatDate(row.date)}</TableCell>
|
<TableCell>{helpers.formatDate(row.date)}</TableCell>
|
||||||
<TableCell>{row.name}</TableCell>
|
<TableCell>{row.name}</TableCell>
|
||||||
<TableCell>{`${Math.round(row.size / 1024)} MiB`}</TableCell>
|
<TableCell>{`${Math.round(row.size / 1024)} MiB`}</TableCell>
|
||||||
|
@ -47,7 +44,6 @@ function buildContent(row) {
|
||||||
<DeleteIcon fontSize="inherit" />
|
<DeleteIcon fontSize="inherit" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
|
@ -64,17 +60,23 @@ function loading() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function EnhancedTable(props) {
|
function CrashLogsTable(props) {
|
||||||
// eslint-disable-next-line no-unused-vars
|
const { dongleId } = props;
|
||||||
const [state, dispatch] = useContext(DeviceContext);
|
|
||||||
useEffect(() => {
|
|
||||||
deviceController.getCrashlogs(props.dongleId).then((res) => {
|
|
||||||
dispatch({ type: 'update_dongle_bootlogs', dongle_id: props.dongleId, bootlogs: res.data });
|
|
||||||
});
|
|
||||||
}, [dispatch, props.dongleId]);
|
|
||||||
|
|
||||||
console.log('drives', state.dongles[props.dongleId]);
|
// eslint-disable-next-line no-unused-vars
|
||||||
console.log('drives', typeof state.dongles[props.dongleId]);
|
const [state, dispatch] = useContext(DevicesContext);
|
||||||
|
useEffect(() => {
|
||||||
|
deviceController.getCrashlogs(dongleId).then((res) => {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.UPDATE_DONGLE_BOOTLOGS,
|
||||||
|
dongle_id: dongleId,
|
||||||
|
bootlogs: res.data,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, [dispatch, dongleId]);
|
||||||
|
|
||||||
|
console.log('drives', state.dongles[dongleId]);
|
||||||
|
console.log('drives', typeof state.dongles[dongleId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: '100%' }}>
|
<Box sx={{ width: '100%' }}>
|
||||||
|
@ -95,10 +97,11 @@ export default function EnhancedTable(props) {
|
||||||
</TableHead>
|
</TableHead>
|
||||||
|
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{state.dongles[props.dongleId].crash
|
{state.dongles[dongleId].crash
|
||||||
? state.dongles[props.dongleId].crash.length > 0 ? state.dongles[props.dongleId].crash.map(buildContent) : <p> No drives </p>
|
? (state.dongles[dongleId].crash.length > 0
|
||||||
|
? state.dongles[dongleId].crash.map(buildContent)
|
||||||
|
: <p> No drives </p>)
|
||||||
: [1, 1, 1, 1, 1].map(loading)}
|
: [1, 1, 1, 1, 1].map(loading)}
|
||||||
|
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
|
@ -107,3 +110,9 @@ export default function EnhancedTable(props) {
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CrashLogsTable.propTypes = {
|
||||||
|
dongleId: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CrashLogsTable;
|
||||||
|
|
|
@ -1,37 +1,43 @@
|
||||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
import React, { useContext } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import Grid from '@mui/material/Grid';
|
import Grid from '@mui/material/Grid';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
import Skeleton from '@mui/material/Skeleton';
|
import Skeleton from '@mui/material/Skeleton';
|
||||||
import Tooltip from '@mui/material/Tooltip';
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import React, { useContext } from 'react';
|
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
||||||
import { context as DeviceContext } from '../../../context/devices';
|
|
||||||
import { context as SnackbarContext } from '../../../context/toast';
|
import { DevicesContext } from '../../../context/devices';
|
||||||
|
import { ACTIONS as ToastActions, ToastContext } from '../../../context/toast';
|
||||||
import * as helpers from '../../../controllers/helpers';
|
import * as helpers from '../../../controllers/helpers';
|
||||||
|
|
||||||
export default function SignIn(props) {
|
function DeviceInfo(props) {
|
||||||
const [state] = useContext(DeviceContext);
|
const { dongleId } = props;
|
||||||
const [, notifDispatch] = useContext(SnackbarContext);
|
|
||||||
|
const [devicesState] = useContext(DevicesContext);
|
||||||
|
const [, toastDispatch] = useContext(ToastContext);
|
||||||
|
|
||||||
|
if (!devicesState.dongles[dongleId]) {
|
||||||
|
return (<p>no</p>);
|
||||||
|
}
|
||||||
|
|
||||||
function pubKeyClipboard(newClip) {
|
function pubKeyClipboard(newClip) {
|
||||||
navigator.clipboard.writeText(newClip).then(() => {
|
navigator.clipboard.writeText(newClip).then(() => {
|
||||||
notifDispatch({
|
toastDispatch({
|
||||||
type: 'NEW_TOAST',
|
type: ToastActions.NEW_TOAST,
|
||||||
open: true,
|
open: true,
|
||||||
msg: 'Successfully copied to clipboard!',
|
msg: 'Successfully copied to clipboard!',
|
||||||
});
|
});
|
||||||
}, () => {
|
}, () => {
|
||||||
notifDispatch({
|
toastDispatch({
|
||||||
type: 'NEW_TOAST',
|
type: ToastActions.NEW_TOAST,
|
||||||
open: true,
|
open: true,
|
||||||
msg: 'Failed to write to clipboard!',
|
msg: 'Failed to write to clipboard!',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state.dongles[props.dongleId]) { return (<p>no</p>); }
|
const dongle = devicesState.dongles[dongleId];
|
||||||
const dongle = state.dongles[props.dongleId];
|
|
||||||
|
|
||||||
if (!dongle) {
|
if (!dongle) {
|
||||||
return (
|
return (
|
||||||
<Grid container>
|
<Grid container>
|
||||||
|
@ -40,15 +46,13 @@ export default function SignIn(props) {
|
||||||
<Skeleton animation="wave" />
|
<Skeleton animation="wave" />
|
||||||
<Skeleton animation="wave" />
|
<Skeleton animation="wave" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="wrapper" style={{ marginTop: '10px' }}>
|
<div className="wrapper" style={{ marginTop: '10px' }}>
|
||||||
<Typography variant="body1">{state.dongles[props.dongleId].dongle_id}</Typography>
|
<Typography variant="body1">{devicesState.dongles[dongleId].dongle_id}</Typography>
|
||||||
|
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid item xs={3}>
|
<Grid item xs={3}>
|
||||||
|
@ -97,3 +101,9 @@ export default function SignIn(props) {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceInfo.propTypes = {
|
||||||
|
dongleId: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeviceInfo;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import DeleteIcon from '@mui/icons-material/Delete';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
|
import PropTypes from 'prop-types';
|
||||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
|
||||||
import { Skeleton } from '@mui/material';
|
import { Skeleton } from '@mui/material';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
|
@ -12,27 +11,32 @@ import TableContainer from '@mui/material/TableContainer';
|
||||||
import TableHead from '@mui/material/TableHead';
|
import TableHead from '@mui/material/TableHead';
|
||||||
import TableRow from '@mui/material/TableRow';
|
import TableRow from '@mui/material/TableRow';
|
||||||
import Tooltip from '@mui/material/Tooltip';
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
import React, { useContext, useEffect, useState } from 'react';
|
import DeleteIcon from '@mui/icons-material/Delete';
|
||||||
import { context as DeviceContext } from '../../../context/devices';
|
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
|
||||||
import { context as SnackbarContext } from '../../../context/toast';
|
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
||||||
|
|
||||||
|
import { DevicesContext } from '../../../context/devices';
|
||||||
|
import { ToastContext } from '../../../context/toast';
|
||||||
import * as deviceController from '../../../controllers/devices';
|
import * as deviceController from '../../../controllers/devices';
|
||||||
import * as helpers from '../../../controllers/helpers';
|
import * as helpers from '../../../controllers/helpers';
|
||||||
import ViewDrive from './view_drive';
|
import ViewDrive from './view_drive';
|
||||||
|
|
||||||
export default function EnhancedTable(props) {
|
function DrivesLogTable(props) {
|
||||||
const [deviceState, dispatch] = useContext(DeviceContext);
|
const { dongleId } = props;
|
||||||
const [, notifDispatch] = useContext(SnackbarContext);
|
|
||||||
|
const [devicesState, dispatch] = useContext(DevicesContext);
|
||||||
|
const [, notifDispatch] = useContext(ToastContext);
|
||||||
const [state, setState] = useState({ selectedSegment: null });
|
const [state, setState] = useState({ selectedSegment: null });
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
deviceController.getDrives(props.dongleId).then((res) => {
|
deviceController.getDrives(dongleId).then((res) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
dispatch({ type: 'update_dongle_drive', dongle_id: props.dongleId, drives: res.data });
|
dispatch({ type: 'update_dongle_drive', dongle_id: dongleId, drives: res.data });
|
||||||
}, 1);
|
}, 1);
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
notifDispatch({ type: 'NEW_TOAST', msg: 'Failed to load drives' });
|
notifDispatch({ type: 'NEW_TOAST', msg: 'Failed to load drives' });
|
||||||
});
|
});
|
||||||
}, [dispatch, notifDispatch, props.dongleId]);
|
}, [dispatch, notifDispatch, dongleId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: '100%' }}>
|
<Box sx={{ width: '100%' }}>
|
||||||
|
@ -61,57 +65,58 @@ export default function EnhancedTable(props) {
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{/* if you don't need to support IE11, you can replace the `stableSort` call with:
|
{/* if you don't need to support IE11, you can replace the `stableSort` call with:
|
||||||
rows.slice().sort(getComparator(order, orderBy)) */}
|
rows.slice().sort(getComparator(order, orderBy)) */}
|
||||||
{deviceState.dongles[props.dongleId].drives ? deviceState.dongles[props.dongleId].drives.map((row, index) => {
|
{devicesState.dongles[dongleId].drives
|
||||||
let metadata;
|
? devicesState.dongles[dongleId].drives.map((row, index) => {
|
||||||
|
let metadata;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
metadata = JSON.parse(row.metadata);
|
metadata = JSON.parse(row.metadata);
|
||||||
} catch (err) { metadata = {}; }
|
} catch (err) { metadata = {}; }
|
||||||
return (
|
return (
|
||||||
<TableRow
|
<TableRow
|
||||||
hover
|
hover
|
||||||
onClick={() => { state.selectedSegment === index ? setState({ ...state, selectedSegment: null }) : setState({ ...state, selectedSegment: index }); }}
|
onClick={() => (state.selectedSegment === index
|
||||||
>
|
? setState({ ...state, selectedSegment: null })
|
||||||
<TableCell
|
: setState({ ...state, selectedSegment: index }))}
|
||||||
scope="row"
|
|
||||||
>
|
>
|
||||||
{row.identifier}
|
<TableCell scope="row">
|
||||||
</TableCell>
|
{row.identifier}
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
<TableCell>{metadata.hasOwnProperty('CarParams1') ? metadata.CarParams.CarName : 'Glorious Skoda'}</TableCell>
|
<TableCell>{metadata.CarParams ? metadata.CarParams.CarName : 'Glorious Skoda'}</TableCell>
|
||||||
<TableCell>{metadata.hasOwnProperty('InitData1') ? metadata.InitData.Version : 'Lemon boy'}</TableCell>
|
<TableCell>{metadata.InitData ? metadata.InitData.Version : 'Lemon boy'}</TableCell>
|
||||||
<TableCell>{`${Math.round(row.filesize / 1024)} MiB`}</TableCell>
|
<TableCell>{`${Math.round(row.filesize / 1024)} MiB`}</TableCell>
|
||||||
<TableCell>{helpers.formatDuration(row.duration)}</TableCell>
|
<TableCell>{helpers.formatDuration(row.duration)}</TableCell>
|
||||||
<TableCell>{Math.round(row.distance_meters / 1000)}</TableCell>
|
<TableCell>{Math.round(row.distance_meters / 1000)}</TableCell>
|
||||||
<TableCell>{row.upload_complete.toString()}</TableCell>
|
<TableCell>{row.upload_complete.toString()}</TableCell>
|
||||||
<TableCell>{row.is_processed.toString()}</TableCell>
|
<TableCell>{row.is_processed.toString()}</TableCell>
|
||||||
<TableCell>{helpers.formatDate(row.drive_date)}</TableCell>
|
<TableCell>{helpers.formatDate(row.drive_date)}</TableCell>
|
||||||
|
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Tooltip title="Open in new window">
|
<Tooltip title="Open in new window">
|
||||||
<IconButton size="small">
|
<IconButton size="small">
|
||||||
<OpenInNewIcon fontSize="inherit" />
|
<OpenInNewIcon fontSize="inherit" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip title="Preserve">
|
<Tooltip title="Preserve">
|
||||||
<IconButton size="small">
|
<IconButton size="small">
|
||||||
<FavoriteBorderIcon fontSize="inherit" />
|
<FavoriteBorderIcon fontSize="inherit" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip title="Delete">
|
<Tooltip title="Delete">
|
||||||
<IconButton size="small">
|
<IconButton size="small">
|
||||||
<DeleteIcon fontSize="inherit" />
|
<DeleteIcon fontSize="inherit" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|
||||||
: [1, 1, 1, 1, 1].map((v) => (
|
: [1, 1, 1, 1, 1].map(() => (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell padding="checkbox">
|
<TableCell padding="checkbox">
|
||||||
<Skeleton animation="wave" />
|
<Skeleton animation="wave" />
|
||||||
|
@ -138,7 +143,15 @@ export default function EnhancedTable(props) {
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
{state.selectedSegment ? <ViewDrive dongleId={props.dongleId} drive={state.selectedSegment} /> : null }
|
{state.selectedSegment
|
||||||
|
? <ViewDrive dongleId={dongleId} drive={state.selectedSegment} />
|
||||||
|
: null }
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrivesLogTable.propTypes = {
|
||||||
|
dongleId: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DrivesLogTable;
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import Tab from '@mui/material/Tab';
|
import Tab from '@mui/material/Tab';
|
||||||
import Tabs from '@mui/material/Tabs';
|
import Tabs from '@mui/material/Tabs';
|
||||||
import React from 'react';
|
|
||||||
import BootLogsTable from './boot';
|
import BootLogsTable from './boot';
|
||||||
import Console from './console';
|
import ConsoleTable from './console';
|
||||||
import CrashLogsTable from './crash';
|
import CrashLogsTable from './crash';
|
||||||
import DeviceInfo from './device';
|
import DeviceInfo from './device';
|
||||||
import DrivesLogTable from './drives';
|
import DrivesLogTable from './drives';
|
||||||
|
|
||||||
function TabPanel(props) {
|
function TabPanel(props) {
|
||||||
const {
|
const {
|
||||||
children, value, index, ...other
|
children,
|
||||||
|
value,
|
||||||
|
index,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -19,7 +23,6 @@ function TabPanel(props) {
|
||||||
hidden={value !== index}
|
hidden={value !== index}
|
||||||
id={`simple-tabpanel-${index}`}
|
id={`simple-tabpanel-${index}`}
|
||||||
aria-labelledby={`simple-tab-${index}`}
|
aria-labelledby={`simple-tab-${index}`}
|
||||||
{...other}
|
|
||||||
>
|
>
|
||||||
{value === index && (
|
{value === index && (
|
||||||
<div style={{ padding: '5px' }}>
|
<div style={{ padding: '5px' }}>
|
||||||
|
@ -30,7 +33,15 @@ function TabPanel(props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SignIn(props) {
|
TabPanel.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
index: PropTypes.number.isRequired,
|
||||||
|
value: PropTypes.number.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
function TabPane(props) {
|
||||||
|
const { dongleId } = props;
|
||||||
|
|
||||||
const [value, setValue] = React.useState(0);
|
const [value, setValue] = React.useState(0);
|
||||||
|
|
||||||
const handleChange = (event, newValue) => {
|
const handleChange = (event, newValue) => {
|
||||||
|
@ -39,7 +50,6 @@ export default function SignIn(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="wrapper">
|
<div className="wrapper">
|
||||||
|
|
||||||
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
||||||
<Tabs
|
<Tabs
|
||||||
value={value}
|
value={value}
|
||||||
|
@ -56,24 +66,26 @@ export default function SignIn(props) {
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
<TabPanel value={value} index={0}>
|
<TabPanel value={value} index={0}>
|
||||||
<DeviceInfo dongleId={props.dongleId} />
|
<DeviceInfo dongleId={dongleId} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel value={value} index={1}>
|
<TabPanel value={value} index={1}>
|
||||||
<DrivesLogTable dongleId={props.dongleId} />
|
<DrivesLogTable dongleId={dongleId} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel value={value} index={2}>
|
<TabPanel value={value} index={2}>
|
||||||
<CrashLogsTable dongleId={props.dongleId} />
|
<CrashLogsTable dongleId={dongleId} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel value={value} index={3}>
|
<TabPanel value={value} index={3}>
|
||||||
<BootLogsTable dongleId={props.dongleId} />
|
<BootLogsTable dongleId={dongleId} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel value={value} index={4}>
|
<TabPanel value={value} index={4}>
|
||||||
<Console dongleId={props.dongleId} />
|
<ConsoleTable dongleId={dongleId} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TabPane.propTypes = {
|
||||||
|
dongleId: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TabPane;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import React, { useContext, useState } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
|
@ -9,38 +11,41 @@ import TableContainer from '@mui/material/TableContainer';
|
||||||
import TableHead from '@mui/material/TableHead';
|
import TableHead from '@mui/material/TableHead';
|
||||||
import TableRow from '@mui/material/TableRow';
|
import TableRow from '@mui/material/TableRow';
|
||||||
import Tooltip from '@mui/material/Tooltip';
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
import React, { useContext, useState } from 'react';
|
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import { context as DeviceContext } from '../../../context/devices';
|
|
||||||
|
import { DevicesContext } from '../../../context/devices';
|
||||||
import * as deviceController from '../../../controllers/devices';
|
import * as deviceController from '../../../controllers/devices';
|
||||||
|
|
||||||
export default function EnhancedTable(props) {
|
function ViewDrive(props) {
|
||||||
const [deviceState] = useContext(DeviceContext);
|
const {
|
||||||
|
dongleId,
|
||||||
|
drive: driveId,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const [deviceState] = useContext(DevicesContext);
|
||||||
|
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
loading: true, firstReqSent: false, segment: null, drive: null,
|
loading: true, firstReqSent: false, segment: null, driveId: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (state.drive === null) {
|
if (state.drive === null) {
|
||||||
setState({ ...state, drive: props.drive });
|
setState({ ...state, driveId });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.drive !== state.drive) {
|
if (driveId !== state.drive) {
|
||||||
setState({
|
setState({
|
||||||
...state, loading: true, firstReqSent: false, segment: null, drive: props.drive,
|
...state, loading: true, firstReqSent: false, segment: null, driveId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const dongle_id = props.dongleId;
|
const dongle = deviceState.dongles[dongleId];
|
||||||
const drive_id = props.drive;
|
|
||||||
const dongle = deviceState.dongles[dongle_id];
|
|
||||||
console.log('view drive', dongle);
|
console.log('view drive', dongle);
|
||||||
console.log('drives', dongle.drives);
|
console.log('drives', dongle.drives);
|
||||||
if (!dongle || !dongle.drives) return (<p>loading</p>);
|
if (!dongle || !dongle.drives) return (<p>loading</p>);
|
||||||
|
|
||||||
if (state.segment === null) {
|
if (state.segment === null) {
|
||||||
// TODO Make this not run multiple times
|
// TODO Make this not run multiple times
|
||||||
deviceController.getDriveSegments(dongle_id, dongle.drives[drive_id].identifier).then((res) => {
|
deviceController.getDriveSegments(dongleId, dongle.drives[driveId].identifier).then((res) => {
|
||||||
console.log('my res', res.data);
|
console.log('my res', res.data);
|
||||||
if (res.data === null) {
|
if (res.data === null) {
|
||||||
setState({
|
setState({
|
||||||
|
@ -56,7 +61,7 @@ export default function EnhancedTable(props) {
|
||||||
|
|
||||||
// test
|
// test
|
||||||
|
|
||||||
const drive = dongle.drives[drive_id];
|
const drive = dongle.drives[driveId];
|
||||||
|
|
||||||
let vehicle = '';
|
let vehicle = '';
|
||||||
let version = '';
|
let version = '';
|
||||||
|
@ -76,8 +81,12 @@ export default function EnhancedTable(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metadata.CarParams) {
|
if (metadata.CarParams) {
|
||||||
if (metadata.CarParams.CarName !== undefined) vehicle += `${metadata.CarParams.CarName.toUpperCase()} `;
|
if (metadata.CarParams.CarName !== undefined) {
|
||||||
if (metadata.CarParams.CarFingerprint !== undefined) vehicle += (metadata.CarParams.CarFingerprint.toUpperCase());
|
vehicle += `${metadata.CarParams.CarName.toUpperCase()} `;
|
||||||
|
}
|
||||||
|
if (metadata.CarParams.CarFingerprint !== undefined) {
|
||||||
|
vehicle += (metadata.CarParams.CarFingerprint.toUpperCase());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (exception) { console.log(exception); }
|
} catch (exception) { console.log(exception); }
|
||||||
|
|
||||||
|
@ -99,7 +108,6 @@ export default function EnhancedTable(props) {
|
||||||
url: `${driveUrl}/${segment}/${directoryTree.children[i].children[c].name}`,
|
url: `${driveUrl}/${segment}/${directoryTree.children[i].children[c].name}`,
|
||||||
name: directoryTree.children[i].children[c].name,
|
name: directoryTree.children[i].children[c].name,
|
||||||
fileSize: directoryTree.children[i].children[c].size,
|
fileSize: directoryTree.children[i].children[c].size,
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +120,6 @@ export default function EnhancedTable(props) {
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: '100%' }}>
|
<Box sx={{ width: '100%' }}>
|
||||||
<Paper sx={{ width: '100%', mb: 2, padding: '20px' }}>
|
<Paper sx={{ width: '100%', mb: 2, padding: '20px' }}>
|
||||||
|
|
||||||
<Typography variant="body1">
|
<Typography variant="body1">
|
||||||
<b>Vehicle:</b>
|
<b>Vehicle:</b>
|
||||||
{' '}
|
{' '}
|
||||||
|
@ -157,33 +164,41 @@ export default function EnhancedTable(props) {
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{
|
{
|
||||||
directorySegments ? Object.keys(directorySegments).map((key, index) => Object.keys(directorySegments[key]).map((key1, index1) => (
|
directorySegments
|
||||||
<TableRow hover>
|
? Object.keys(directorySegments)
|
||||||
<TableCell>{key}</TableCell>
|
.map((key) => Object.keys(directorySegments[key])
|
||||||
<TableCell>{directorySegments[key][key1].name}</TableCell>
|
.map((key1) => (
|
||||||
<TableCell>{`${Math.round(directorySegments[key][key1].fileSize / 1024)} MiB`}</TableCell>
|
<TableRow hover>
|
||||||
|
<TableCell>{key}</TableCell>
|
||||||
<TableCell>
|
<TableCell>{directorySegments[key][key1].name}</TableCell>
|
||||||
<Tooltip title="Open in new window">
|
<TableCell>{`${Math.round(directorySegments[key][key1].fileSize / 1024)} MiB`}</TableCell>
|
||||||
<IconButton size="small" onClick={() => window.open(directorySegments[key][key1].url, '_blank')}>
|
|
||||||
<OpenInNewIcon fontSize="inherit" />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
</TableCell>
|
|
||||||
|
|
||||||
</TableRow>
|
|
||||||
))) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
<Tooltip title="Open in new window">
|
||||||
|
<IconButton size="small" onClick={() => window.open(directorySegments[key][key1].url, '_blank')}>
|
||||||
|
<OpenInNewIcon fontSize="inherit" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)))
|
||||||
|
: null
|
||||||
|
}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
|
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ViewDrive.propTypes = {
|
||||||
|
dongleId: PropTypes.string.isRequired,
|
||||||
|
drive: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ViewDrive;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
var dongleIdHash = crypto.createHmac('sha256', config.applicationSalt).update(device.dongle_id).digest('hex');
|
var dongleIdHash = crypto.createHmac('sha256', config.applicationSalt).update(device.dongle_id).digest('hex');
|
||||||
|
|
|
@ -1,28 +1,10 @@
|
||||||
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
import React from 'react';
|
||||||
import React, { useContext, useState } from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { UserContext } from '../../context/users';
|
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
||||||
|
|
||||||
const theme = createTheme();
|
const theme = createTheme();
|
||||||
|
|
||||||
export default function SignIn() {
|
function Home() {
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [state, dispatch] = useContext(UserContext);
|
|
||||||
console.log('component', state);
|
|
||||||
const handleSubmit = (event) => {
|
|
||||||
dispatch({ type: 'toggle_button' });
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
const data = new FormData(event.currentTarget);
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log({
|
|
||||||
email: data.get('email'),
|
|
||||||
password: data.get('password'),
|
|
||||||
});
|
|
||||||
|
|
||||||
setLoading(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<p>hello</p>
|
<p>hello</p>
|
||||||
|
@ -32,3 +14,5 @@ export default function SignIn() {
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Home;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import React, { useContext, useState } from 'react';
|
||||||
import LoadingButton from '@mui/lab/LoadingButton';
|
import LoadingButton from '@mui/lab/LoadingButton';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import Container from '@mui/material/Container';
|
import Container from '@mui/material/Container';
|
||||||
|
@ -6,7 +7,7 @@ import Link from '@mui/material/Link';
|
||||||
import Paper from '@mui/material/Paper';
|
import Paper from '@mui/material/Paper';
|
||||||
import TextField from '@mui/material/TextField';
|
import TextField from '@mui/material/TextField';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import React, { useContext, useState } from 'react';
|
|
||||||
import { UserContext } from '../../context/users';
|
import { UserContext } from '../../context/users';
|
||||||
|
|
||||||
export default function SignIn() {
|
export default function SignIn() {
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
|
import React, { useContext } from 'react';
|
||||||
import Grid from '@mui/material/Grid';
|
import Grid from '@mui/material/Grid';
|
||||||
import Paper from '@mui/material/Paper';
|
import Paper from '@mui/material/Paper';
|
||||||
import { Scrollbars } from 'rc-scrollbars';
|
import { Scrollbars } from 'rc-scrollbars';
|
||||||
import React, { useContext } from 'react';
|
|
||||||
import { context as DeviceContext } from '../../context/devices';
|
import { DevicesContext } from '../../context/devices';
|
||||||
import DeviceData from '../device/deviceData';
|
import DeviceData from '../device/deviceData';
|
||||||
import DeviceOverview from '../device/overview';
|
import DeviceOverview from '../device/overview';
|
||||||
|
|
||||||
export default function SignIn() {
|
export default function SignIn() {
|
||||||
const [deviceState] = useContext(DeviceContext);
|
const [deviceState] = useContext(DevicesContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="wrapper">
|
<div className="wrapper">
|
||||||
|
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
spacing={0}
|
spacing={0}
|
||||||
|
@ -23,18 +23,17 @@ export default function SignIn() {
|
||||||
<Paper style={{ minHeight: '100%', maxHeight: '100%', margin: '0' }}>
|
<Paper style={{ minHeight: '100%', maxHeight: '100%', margin: '0' }}>
|
||||||
<Scrollbars autoHeight autoHeightMin="calc(100vh - 14px)" autoHeightMax="calc(100% - 14px)">
|
<Scrollbars autoHeight autoHeightMin="calc(100vh - 14px)" autoHeightMax="calc(100% - 14px)">
|
||||||
<div style={{ padding: '5px' }}>
|
<div style={{ padding: '5px' }}>
|
||||||
{deviceState ? Object.keys(deviceState.dongles).map((key) => <DeviceOverview device={deviceState.dongles[key]} />) : <p>no</p>}
|
{deviceState
|
||||||
|
? (Object.keys(deviceState.dongles)
|
||||||
|
.map((key) => <DeviceOverview device={deviceState.dongles[key]} />))
|
||||||
|
: <p>no</p>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</Scrollbars>
|
</Scrollbars>
|
||||||
|
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} md={8} lg={9} sm={6} xl={10}>
|
<Grid item xs={12} md={8} lg={9} sm={6} xl={10}>
|
||||||
{deviceState.dongles['53331425'] ? <DeviceData device={deviceState.dongles['53331425']} /> : <p>no</p>}
|
{deviceState.dongles['53331425'] ? <DeviceData device={deviceState.dongles['53331425']} /> : <p>no</p>}
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import Snackbar from '@mui/material/Snackbar';
|
|
||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { context as DeviceContext } from '../../context/toast';
|
import Snackbar from '@mui/material/Snackbar';
|
||||||
|
|
||||||
export default function Toast(props) {
|
import { ACTIONS, ToastContext } from '../../context/toast';
|
||||||
const [state, dispatch] = useContext(DeviceContext);
|
|
||||||
|
function Toast() {
|
||||||
|
const [state, dispatch] = useContext(ToastContext);
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
dispatch({ type: 'CLOSE_TOAST' });
|
dispatch({ type: ACTIONS.CLOSE_TOAST });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -19,3 +20,5 @@ export default function Toast(props) {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Toast;
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
const ACTIONS = {
|
||||||
|
ADD_DATA: 'add_data',
|
||||||
|
FETCH_ALL_DONGLES: 'fetch_all_dongles',
|
||||||
|
UPDATE_DONGLE_DRIVE: 'update_dongle_drive',
|
||||||
|
UPDATE_DONGLE_BOOTLOGS: 'update_dongle_bootlogs',
|
||||||
|
UPDATE_DONGLE_CRASHLOGS: 'update_dongle_crashlogs',
|
||||||
|
USER_AUTHENTICATION: 'user_authentication',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ACTIONS;
|
|
@ -1,125 +1,68 @@
|
||||||
import React, { createContext, useEffect, useReducer } from 'react';
|
import React, {
|
||||||
|
createContext,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useReducer,
|
||||||
|
} from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import * as deviceController from '../../controllers/devices';
|
import * as deviceController from '../../controllers/devices';
|
||||||
|
|
||||||
function process(state, action) {
|
import ACTIONS from './actions';
|
||||||
if (action.type !== 'ADD_DATA') { return state; }
|
import reducer from './reducer';
|
||||||
|
|
||||||
switch (action.data.command) {
|
|
||||||
case 'dongle_status':
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
dongles: {
|
|
||||||
...state.dongles,
|
|
||||||
[action.data.data.dongle_id]: {
|
|
||||||
...state.dongles[action.data.data.dongle_id],
|
|
||||||
online: action.data.data.online,
|
|
||||||
last_seen: action.data.data.time,
|
|
||||||
dongle_id: action.data.data.dongle_id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Reducer = (state, action) => {
|
|
||||||
console.log('input', state, action);
|
|
||||||
switch (action.type) {
|
|
||||||
case 'ADD_DATA':
|
|
||||||
return process(state, action);
|
|
||||||
case 'fetch_all_dongles':
|
|
||||||
console.log('fetch', action);
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
dongles: action.data,
|
|
||||||
};
|
|
||||||
|
|
||||||
case 'update_dongle_drive':
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
dongles: {
|
|
||||||
...state.dongles,
|
|
||||||
[action.dongle_id]: {
|
|
||||||
...state.dongles[action.dongle_id],
|
|
||||||
drives: action.drives,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
case 'update_dongle_bootlogs':
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
dongles: {
|
|
||||||
...state.dongles,
|
|
||||||
[action.dongle_id]: {
|
|
||||||
...state.dongles[action.dongle_id],
|
|
||||||
boot: action.bootlogs,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
case 'update_dongle_crashlogs':
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
dongles: {
|
|
||||||
...state.dongles,
|
|
||||||
[action.dongle_id]: {
|
|
||||||
...state.dongles[action.dongle_id],
|
|
||||||
crash: action.crashlogs,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
case 'user_authentication':
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
user: action.user,
|
|
||||||
};
|
|
||||||
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
dongles: {},
|
dongles: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
function Store({ children }) {
|
const DevicesContext = createContext(initialState);
|
||||||
console.log('STORE HAS BEEN RERENDERED');
|
|
||||||
const [state, dispatch] = useReducer(Reducer, initialState);
|
function DevicesProvider({ children }) {
|
||||||
|
const [state, dispatch] = useReducer(reducer, initialState);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const ws = new WebSocket('ws://localhost:81');
|
const ws = new WebSocket('ws://localhost:81');
|
||||||
|
|
||||||
ws.onmessage = ({ data }) => {
|
ws.onmessage = ({ data }) => {
|
||||||
data = JSON.parse(data);
|
const payload = JSON.parse(data);
|
||||||
console.log('Message');
|
console.log('devices onmessage', payload);
|
||||||
if (data.id) {
|
|
||||||
dispatch({ type: 'ADD_DATA', id: data.id, data });
|
if (!payload.id) {
|
||||||
|
dispatch({ type: ACTIONS.ADD_DATA, data: payload });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
deviceController.getAllDevices().then((devices) => {
|
deviceController.getAllDevices().then((devices) => {
|
||||||
console.log('store', devices);
|
console.log('devices store', devices);
|
||||||
|
|
||||||
dispatch({ type: 'fetch_all_dongles', data: devices });
|
dispatch({ type: ACTIONS.FETCH_ALL_DONGLES, data: devices });
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
// Clean up the websocket
|
||||||
try {
|
try {
|
||||||
ws.close();
|
ws.close();
|
||||||
} catch (e) { }
|
} catch (e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const contextValue = useMemo(() => ([state, dispatch]), [state, dispatch]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<context.Provider value={[state, dispatch]}>
|
<DevicesContext.Provider value={contextValue}>
|
||||||
{children}
|
{ children }
|
||||||
</context.Provider>
|
</DevicesContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const context = createContext(initialState);
|
DevicesProvider.propTypes = {
|
||||||
export default Store;
|
children: PropTypes.node.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DevicesProvider;
|
||||||
|
export {
|
||||||
|
ACTIONS,
|
||||||
|
DevicesContext,
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
import ACTIONS from './actions';
|
||||||
|
|
||||||
|
function process(state, action) {
|
||||||
|
if (action.type !== ACTIONS.ADD_DATA) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (action.data.command) {
|
||||||
|
case 'dongle_status':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dongles: {
|
||||||
|
...state.dongles,
|
||||||
|
[action.data.data.dongle_id]: {
|
||||||
|
...state.dongles[action.data.data.dongle_id],
|
||||||
|
online: action.data.data.online,
|
||||||
|
last_seen: action.data.data.time,
|
||||||
|
dongle_id: action.data.data.dongle_id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function reducer(state, action) {
|
||||||
|
console.log('input', state, action);
|
||||||
|
switch (action.type) {
|
||||||
|
case ACTIONS.ADD_DATA:
|
||||||
|
return process(state, action);
|
||||||
|
|
||||||
|
case ACTIONS.FETCH_ALL_DONGLES:
|
||||||
|
console.log('fetch', action);
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dongles: action.data,
|
||||||
|
};
|
||||||
|
|
||||||
|
case ACTIONS.UPDATE_DONGLE_DRIVE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dongles: {
|
||||||
|
...state.dongles,
|
||||||
|
[action.dongle_id]: {
|
||||||
|
...state.dongles[action.dongle_id],
|
||||||
|
drives: action.drives,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
case ACTIONS.UPDATE_DONGLE_BOOTLOGS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dongles: {
|
||||||
|
...state.dongles,
|
||||||
|
[action.dongle_id]: {
|
||||||
|
...state.dongles[action.dongle_id],
|
||||||
|
boot: action.bootlogs,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
case ACTIONS.UPDATE_DONGLE_CRASHLOGS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dongles: {
|
||||||
|
...state.dongles,
|
||||||
|
[action.dongle_id]: {
|
||||||
|
...state.dongles[action.dongle_id],
|
||||||
|
crash: action.crashlogs,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
case ACTIONS.USER_AUTHENTICATION:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
user: action.user,
|
||||||
|
};
|
||||||
|
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default reducer;
|
|
@ -0,0 +1,6 @@
|
||||||
|
const ACTIONS = {
|
||||||
|
NEW_TOAST: 'new_toast',
|
||||||
|
CLOSE_TOAST: 'close_toast',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ACTIONS;
|
|
@ -1,19 +1,34 @@
|
||||||
import React, { createContext, useReducer } from 'react';
|
import React, { createContext, useMemo, useReducer } from 'react';
|
||||||
import Reducer from './reducer';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import ACTIONS from './actions';
|
||||||
|
import reducer from './reducer';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
open: false,
|
open: false,
|
||||||
message: null,
|
message: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
function Store({ children }) {
|
const ToastContext = createContext(initialState);
|
||||||
const [state, dispatch] = useReducer(Reducer, initialState);
|
|
||||||
|
function ToastProvider({ children }) {
|
||||||
|
const [state, dispatch] = useReducer(reducer, initialState);
|
||||||
|
|
||||||
|
const contextValue = useMemo(() => ([state, dispatch]), [state, dispatch]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<context.Provider value={[state, dispatch]}>
|
<ToastContext.Provider value={contextValue}>
|
||||||
{children}
|
{children}
|
||||||
</context.Provider>
|
</ToastContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const context = createContext(initialState);
|
ToastProvider.propTypes = {
|
||||||
export default Store;
|
children: PropTypes.node.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ToastProvider;
|
||||||
|
export {
|
||||||
|
ACTIONS,
|
||||||
|
ToastContext,
|
||||||
|
};
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
const Reducer = (state, action) => {
|
import ACTIONS from './actions';
|
||||||
|
|
||||||
|
function reducer(state, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'NEW_TOAST':
|
case ACTIONS.NEW_TOAST:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
open: action.open,
|
open: action.open,
|
||||||
msg: action.message,
|
msg: action.message,
|
||||||
};
|
};
|
||||||
case 'CLOSE_TOAST':
|
case ACTIONS.CLOSE_TOAST:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
open: false,
|
open: false,
|
||||||
|
@ -15,6 +17,6 @@ const Reducer = (state, action) => {
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export default Reducer;
|
export default reducer;
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
const ACTIONS = {
|
||||||
|
SIGN_OUT: 'sign_out',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ACTIONS;
|
|
@ -1,17 +1,38 @@
|
||||||
import React from 'react';
|
import React, { createContext, useMemo, useReducer } from 'react';
|
||||||
import { reducer, initialState } from './reducer';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
export const UserContext = React.createContext({
|
import ACTIONS from './actions';
|
||||||
state: initialState,
|
import reducer from './reducer';
|
||||||
dispatch: () => null,
|
|
||||||
});
|
|
||||||
|
|
||||||
export function UserProvider({ children }) {
|
const initialState = {
|
||||||
const [state, dispatch] = React.useReducer(reducer, initialState);
|
signedIn: false,
|
||||||
|
user: {
|
||||||
|
id: null,
|
||||||
|
username: null,
|
||||||
|
JWT: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const UserContext = createContext(initialState);
|
||||||
|
|
||||||
|
function UserProvider({ children }) {
|
||||||
|
const [state, dispatch] = useReducer(reducer, initialState);
|
||||||
|
|
||||||
|
const contextValue = useMemo(() => ([state, dispatch]), [state, dispatch]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UserContext.Provider value={[state, dispatch]}>
|
<UserContext.Provider value={contextValue}>
|
||||||
{ children }
|
{ children }
|
||||||
</UserContext.Provider>
|
</UserContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UserProvider.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UserProvider;
|
||||||
|
export {
|
||||||
|
ACTIONS,
|
||||||
|
UserContext,
|
||||||
|
};
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
export const reducer = (state, action) => {
|
import ACTIONS from './actions';
|
||||||
switch (action.type) {
|
|
||||||
case 'sign_out':
|
|
||||||
|
|
||||||
|
function reducer(state, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case ACTIONS.SIGN_OUT:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
active: !state.active,
|
active: !state.active,
|
||||||
|
@ -10,13 +11,6 @@ export const reducer = (state, action) => {
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export const initialState = {
|
export default reducer;
|
||||||
signedIn: false,
|
|
||||||
user: {
|
|
||||||
id: null,
|
|
||||||
username: null,
|
|
||||||
JWT: null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
Loading…
Reference in New Issue