Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
179c2fe0fc
|
@ -119,6 +119,10 @@ function App() {
|
||||||
path={routes.forgotPassword}
|
path={routes.forgotPassword}
|
||||||
element={<ForgotPassword />}
|
element={<ForgotPassword />}
|
||||||
></Route>
|
></Route>
|
||||||
|
<Route
|
||||||
|
path={'*'}
|
||||||
|
element={<Navigate to={routes.login}></Navigate>}
|
||||||
|
></Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
|
@ -147,6 +151,10 @@ function App() {
|
||||||
path={''}
|
path={''}
|
||||||
element={<Navigate to={routes.installations}></Navigate>}
|
element={<Navigate to={routes.installations}></Navigate>}
|
||||||
></Route>
|
></Route>
|
||||||
|
<Route
|
||||||
|
path={'login'}
|
||||||
|
element={<Navigate to={routes.installations}></Navigate>}
|
||||||
|
></Route>
|
||||||
<Route
|
<Route
|
||||||
path="/"
|
path="/"
|
||||||
element={
|
element={
|
||||||
|
@ -168,7 +176,10 @@ function App() {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route path={routes.users + '*'} element={<Users />} />
|
<Route path={routes.users + '*'} element={<Users />} />
|
||||||
|
<Route
|
||||||
|
path={'*'}
|
||||||
|
element={<Navigate to={routes.installations}></Navigate>}
|
||||||
|
></Route>
|
||||||
<Route path="ResetPassword" element={<ResetPassword />}></Route>
|
<Route path="ResetPassword" element={<ResetPassword />}></Route>
|
||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
|
|
|
@ -91,7 +91,7 @@ function Login() {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div style={{ userSelect: 'none' }}>
|
||||||
<Container maxWidth="xl" sx={{ pt: 2 }} className="login">
|
<Container maxWidth="xl" sx={{ pt: 2 }} className="login">
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid item xs={3} container justifyContent="flex-start" mb={2}>
|
<Grid item xs={3} container justifyContent="flex-start" mb={2}>
|
||||||
|
@ -263,7 +263,7 @@ function Login() {
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,10 @@ function InstallationTabs() {
|
||||||
value: 'live',
|
value: 'live',
|
||||||
label: <FormattedMessage id="live" defaultMessage="Live" />
|
label: <FormattedMessage id="live" defaultMessage="Live" />
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: 'overview',
|
||||||
|
label: <FormattedMessage id="overview" defaultMessage="Overview" />
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: 'batteryview',
|
value: 'batteryview',
|
||||||
label: (
|
label: (
|
||||||
|
@ -148,12 +151,7 @@ function InstallationTabs() {
|
||||||
value: 'overview',
|
value: 'overview',
|
||||||
label: <FormattedMessage id="overview" defaultMessage="Overview" />
|
label: <FormattedMessage id="overview" defaultMessage="Overview" />
|
||||||
},
|
},
|
||||||
{
|
|
||||||
value: 'batteryview',
|
|
||||||
label: (
|
|
||||||
<FormattedMessage id="batteryview" defaultMessage="Battery View" />
|
|
||||||
)
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
value: 'log',
|
value: 'log',
|
||||||
label: <FormattedMessage id="log" defaultMessage="Log" />
|
label: <FormattedMessage id="log" defaultMessage="Log" />
|
||||||
|
|
|
@ -29,10 +29,17 @@ interface LogProps {
|
||||||
|
|
||||||
function Log(props: LogProps) {
|
function Log(props: LogProps) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const searchParams = new URLSearchParams(location.search);
|
||||||
|
const openModal = searchParams.get('open');
|
||||||
|
|
||||||
const [warnings, setWarnings] = useState<ErrorMessage[]>([]);
|
const [warnings, setWarnings] = useState<ErrorMessage[]>([]);
|
||||||
const [errors, setErrors] = useState<ErrorMessage[]>([]);
|
const [errors, setErrors] = useState<ErrorMessage[]>([]);
|
||||||
const [errorButtonPressed, setErrorButtonPressed] = useState(false);
|
const [errorButtonPressed, setErrorButtonPressed] = useState(
|
||||||
const [warningButtonPressed, setWarningButtonPressed] = useState(false);
|
openModal === 'error' ? true : false
|
||||||
|
);
|
||||||
|
const [warningButtonPressed, setWarningButtonPressed] = useState(
|
||||||
|
openModal === 'warning' ? true : false
|
||||||
|
);
|
||||||
const [updateCount, setUpdateCount] = useState(0);
|
const [updateCount, setUpdateCount] = useState(0);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const tokencontext = useContext(TokenContext);
|
const tokencontext = useContext(TokenContext);
|
||||||
|
|
|
@ -260,7 +260,7 @@ export const getChartOptions = (
|
||||||
: chartInfo.max <= 0
|
: chartInfo.max <= 0
|
||||||
? Math.ceil(chartInfo.min / findPower(chartInfo.min).value) *
|
? Math.ceil(chartInfo.min / findPower(chartInfo.min).value) *
|
||||||
findPower(chartInfo.min).value
|
findPower(chartInfo.min).value
|
||||||
: Math.abs(chartInfo.min) < 1
|
: Math.abs(chartInfo.min) < 1 || Math.abs(chartInfo.max) < 1
|
||||||
? -Math.max(
|
? -Math.max(
|
||||||
Math.abs(
|
Math.abs(
|
||||||
Math.ceil(chartInfo.min / findPower(chartInfo.min).value) *
|
Math.ceil(chartInfo.min / findPower(chartInfo.min).value) *
|
||||||
|
@ -278,7 +278,7 @@ export const getChartOptions = (
|
||||||
).toFixed(2)
|
).toFixed(2)
|
||||||
: chartInfo.max <= 0
|
: chartInfo.max <= 0
|
||||||
? 0
|
? 0
|
||||||
: Math.abs(chartInfo.min) < 1
|
: Math.abs(chartInfo.min) < 1 || Math.abs(chartInfo.max) < 1
|
||||||
? +Math.max(
|
? +Math.max(
|
||||||
Math.abs(
|
Math.abs(
|
||||||
Math.ceil(chartInfo.min / findPower(chartInfo.min).value) *
|
Math.ceil(chartInfo.min / findPower(chartInfo.min).value) *
|
||||||
|
@ -306,6 +306,17 @@ export const getChartOptions = (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
annotations: {
|
||||||
|
yaxis: [
|
||||||
|
{
|
||||||
|
y: 0,
|
||||||
|
strokeDashArray: 0,
|
||||||
|
borderColor: '#d3d3d3',
|
||||||
|
borderWidth: 1,
|
||||||
|
yAxisIndex: 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
y: {
|
y: {
|
||||||
formatter: function (val) {
|
formatter: function (val) {
|
||||||
|
|
|
@ -687,7 +687,7 @@ function Overview(props: OverviewProps) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Net Energy',
|
name: 'Net Energy',
|
||||||
color: '#666666',
|
color: '#ff3333',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: weeklybalance
|
data: weeklybalance
|
||||||
}
|
}
|
||||||
|
@ -917,7 +917,7 @@ function Overview(props: OverviewProps) {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{weeklyData && (
|
{weeklyData && currentUser.hasWriteAccess && (
|
||||||
<ReactApexChart
|
<ReactApexChart
|
||||||
options={{
|
options={{
|
||||||
...getChartOptions(
|
...getChartOptions(
|
||||||
|
@ -930,7 +930,7 @@ function Overview(props: OverviewProps) {
|
||||||
series={[
|
series={[
|
||||||
{
|
{
|
||||||
...weeklyDataArray.chartData.dcChargingPower,
|
...weeklyDataArray.chartData.dcChargingPower,
|
||||||
color: '#69d2e7'
|
color: '#008FFB'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...weeklyDataArray.chartData.heatingPower,
|
...weeklyDataArray.chartData.heatingPower,
|
||||||
|
@ -938,7 +938,7 @@ function Overview(props: OverviewProps) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...weeklyDataArray.chartData.dcDischargingPower,
|
...weeklyDataArray.chartData.dcDischargingPower,
|
||||||
color: '#008FFB'
|
color: '#69d2e7'
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
type="bar"
|
type="bar"
|
||||||
|
@ -946,7 +946,33 @@ function Overview(props: OverviewProps) {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{monthlyData && (
|
{weeklyData && !currentUser.hasWriteAccess && (
|
||||||
|
<ReactApexChart
|
||||||
|
options={{
|
||||||
|
...getChartOptions(
|
||||||
|
weeklyDataArray.chartOverview.dcPowerWithoutHeating,
|
||||||
|
'weekly',
|
||||||
|
weeklyDateList,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
series={[
|
||||||
|
{
|
||||||
|
...weeklyDataArray.chartData.dcChargingPower,
|
||||||
|
color: '#008FFB'
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
...weeklyDataArray.chartData.dcDischargingPower,
|
||||||
|
color: '#69d2e7'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
type="bar"
|
||||||
|
height={400}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{monthlyData && currentUser.hasWriteAccess && (
|
||||||
<ReactApexChart
|
<ReactApexChart
|
||||||
options={{
|
options={{
|
||||||
...getChartOptions(
|
...getChartOptions(
|
||||||
|
@ -959,7 +985,7 @@ function Overview(props: OverviewProps) {
|
||||||
series={[
|
series={[
|
||||||
{
|
{
|
||||||
...monthlyDataArray.chartData.dcChargingPower,
|
...monthlyDataArray.chartData.dcChargingPower,
|
||||||
color: '#69d2e7'
|
color: '#008FFB'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...weeklyDataArray.chartData.heatingPower,
|
...weeklyDataArray.chartData.heatingPower,
|
||||||
|
@ -967,7 +993,34 @@ function Overview(props: OverviewProps) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...monthlyDataArray.chartData.dcDischargingPower,
|
...monthlyDataArray.chartData.dcDischargingPower,
|
||||||
|
color: '#69d2e7'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
type="bar"
|
||||||
|
height={400}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{monthlyData && !currentUser.hasWriteAccess && (
|
||||||
|
<ReactApexChart
|
||||||
|
options={{
|
||||||
|
...getChartOptions(
|
||||||
|
monthlyDataArray.chartOverview
|
||||||
|
.dcPowerWithoutHeating,
|
||||||
|
'monthly',
|
||||||
|
monthlyDateList,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
series={[
|
||||||
|
{
|
||||||
|
...monthlyDataArray.chartData.dcChargingPower,
|
||||||
color: '#008FFB'
|
color: '#008FFB'
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
...monthlyDataArray.chartData.dcDischargingPower,
|
||||||
|
color: '#69d2e7'
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
type="bar"
|
type="bar"
|
||||||
|
@ -1106,7 +1159,6 @@ function Overview(props: OverviewProps) {
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{currentUser.hasWriteAccess && (
|
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
direction="row"
|
direction="row"
|
||||||
|
@ -1256,8 +1308,7 @@ function Overview(props: OverviewProps) {
|
||||||
<ReactApexChart
|
<ReactApexChart
|
||||||
options={{
|
options={{
|
||||||
...getChartOptions(
|
...getChartOptions(
|
||||||
dailyDataArray[chartState].chartOverview
|
dailyDataArray[chartState].chartOverview.gridPower,
|
||||||
.gridPower,
|
|
||||||
'daily',
|
'daily',
|
||||||
[],
|
[],
|
||||||
true
|
true
|
||||||
|
@ -1331,7 +1382,6 @@ function Overview(props: OverviewProps) {
|
||||||
</Card>
|
</Card>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Container, Grid, Switch } from '@mui/material';
|
import { Container, Grid, Switch, Typography } from '@mui/material';
|
||||||
import TopologyColumn from './topologyColumn';
|
import TopologyColumn from './topologyColumn';
|
||||||
import {
|
import {
|
||||||
getAmount,
|
getAmount,
|
||||||
|
@ -41,6 +41,10 @@ function Topology(props: TopologyProps) {
|
||||||
justifyContent: 'right'
|
justifyContent: 'right'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<div>
|
||||||
|
<Typography sx={{ marginTop: '5px', marginRight: '20px' }}>
|
||||||
|
Display Values
|
||||||
|
</Typography>
|
||||||
<Switch
|
<Switch
|
||||||
edge="start"
|
edge="start"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
|
@ -48,9 +52,22 @@ function Topology(props: TopologyProps) {
|
||||||
sx={{
|
sx={{
|
||||||
'& .MuiSwitch-thumb': {
|
'& .MuiSwitch-thumb': {
|
||||||
backgroundColor: 'orange'
|
backgroundColor: 'orange'
|
||||||
}
|
},
|
||||||
|
marginLeft: '20px'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/*<Switch*/}
|
||||||
|
{/* edge="start"*/}
|
||||||
|
{/* color="secondary"*/}
|
||||||
|
{/* onChange={handleSwitch()}*/}
|
||||||
|
{/* sx={{*/}
|
||||||
|
{/* '& .MuiSwitch-thumb': {*/}
|
||||||
|
{/* backgroundColor: 'orange'*/}
|
||||||
|
{/* }*/}
|
||||||
|
{/* }}*/}
|
||||||
|
{/*/>*/}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid
|
<Grid
|
||||||
|
|
|
@ -29,7 +29,7 @@ const isInt = (value: number) => {
|
||||||
return value % 1 === 0;
|
return value % 1 === 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
function formatPower(value) {
|
function formatPower(value, unit) {
|
||||||
if (isNaN(value)) {
|
if (isNaN(value)) {
|
||||||
return 'Invalid';
|
return 'Invalid';
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,12 @@ function formatPower(value) {
|
||||||
magnitude++;
|
magnitude++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const roundedValue = value.toFixed(1);
|
const roundedValue = Math.round(value);
|
||||||
|
|
||||||
|
//Filter all values less than 100 Watts
|
||||||
|
if (magnitude === 0 && value < 100 && unit === 'W') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return negative === false
|
return negative === false
|
||||||
? `${roundedValue} ${prefixes[magnitude]}`
|
? `${roundedValue} ${prefixes[magnitude]}`
|
||||||
|
@ -243,8 +248,12 @@ function TopologyBox(props: TopologyBoxProps) {
|
||||||
{props.data.values.map((boxData, index) => {
|
{props.data.values.map((boxData, index) => {
|
||||||
return (
|
return (
|
||||||
<Typography key={index}>
|
<Typography key={index}>
|
||||||
{formatPower(boxData.value)}
|
{formatPower(boxData.value, boxData.unit) === 0
|
||||||
{boxData.unit}
|
? null
|
||||||
|
: formatPower(boxData.value, boxData.unit)}
|
||||||
|
{formatPower(boxData.value, boxData.unit) === 0
|
||||||
|
? null
|
||||||
|
: boxData.unit}
|
||||||
</Typography>
|
</Typography>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -45,7 +45,12 @@ function formatPower(value) {
|
||||||
magnitude++;
|
magnitude++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const roundedValue = value.toFixed(1);
|
const roundedValue = Math.round(value);
|
||||||
|
|
||||||
|
//Filter all values less than 100 Watts
|
||||||
|
if (magnitude === 0 && value < 100) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return negative === false
|
return negative === false
|
||||||
? `${roundedValue} ${prefixes[magnitude]}`
|
? `${roundedValue} ${prefixes[magnitude]}`
|
||||||
|
@ -113,8 +118,12 @@ function TopologyFlow(props: TopologyFlowProps) {
|
||||||
zIndex: 1
|
zIndex: 1
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{formatPower(props.data.values[0].value)}
|
{formatPower(props.data.values[0].value) === 0
|
||||||
{props.data.values[0].unit}
|
? null
|
||||||
|
: formatPower(props.data.values[0].value)}
|
||||||
|
{formatPower(props.data.values[0].value) === 0
|
||||||
|
? null
|
||||||
|
: props.data.values[0].unit}
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
Grid,
|
Grid,
|
||||||
IconButton,
|
IconButton,
|
||||||
Modal,
|
Modal,
|
||||||
|
Switch,
|
||||||
Tab,
|
Tab,
|
||||||
Tabs,
|
Tabs,
|
||||||
TextField,
|
TextField,
|
||||||
|
@ -22,6 +23,7 @@ import { InnovEnergyUser } from 'src/interfaces/UserTypes';
|
||||||
import { TokenContext } from 'src/contexts/tokenContext';
|
import { TokenContext } from 'src/contexts/tokenContext';
|
||||||
import { TabsContainerWrapper } from 'src/layouts/TabsContainerWrapper';
|
import { TabsContainerWrapper } from 'src/layouts/TabsContainerWrapper';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||||
|
|
||||||
interface singleUserProps {
|
interface singleUserProps {
|
||||||
current_user: InnovEnergyUser;
|
current_user: InnovEnergyUser;
|
||||||
|
@ -80,6 +82,14 @@ function User(props: singleUserProps) {
|
||||||
[name]: value
|
[name]: value
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleAdminChange = (event) => {
|
||||||
|
setFormValues({
|
||||||
|
...formValues,
|
||||||
|
['hasWriteAccess']: event.target.checked
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmit = async (e) => {
|
const handleSubmit = async (e) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setError(false);
|
setError(false);
|
||||||
|
@ -94,8 +104,13 @@ function User(props: singleUserProps) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
setUpdated(true);
|
props.fetchDataAgain();
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
setUpdated(true);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setUpdated(false);
|
||||||
|
}, 3000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -278,6 +293,34 @@ function User(props: singleUserProps) {
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<FormControlLabel
|
||||||
|
labelPlacement="start"
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
checked={
|
||||||
|
formValues.hasWriteAccess ? true : false
|
||||||
|
}
|
||||||
|
color="primary"
|
||||||
|
name="hasWriteAccess"
|
||||||
|
onChange={handleAdminChange}
|
||||||
|
sx={{
|
||||||
|
marginLeft: '8px',
|
||||||
|
marginTop: '2px'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={
|
||||||
|
<Typography sx={{ marginTop: '4px' }}>
|
||||||
|
Admin
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
sx={{
|
||||||
|
marginLeft: '10px'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
|
|
@ -8,7 +8,7 @@ function Users() {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div style={{ userSelect: 'none' }}>
|
||||||
<AccessContextProvider>
|
<AccessContextProvider>
|
||||||
<Container maxWidth="xl" sx={{ marginTop: '20px' }}>
|
<Container maxWidth="xl" sx={{ marginTop: '20px' }}>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
|
@ -19,7 +19,7 @@ function Users() {
|
||||||
</Container>
|
</Container>
|
||||||
<Footer />
|
<Footer />
|
||||||
</AccessContextProvider>
|
</AccessContextProvider>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,9 @@ import {
|
||||||
MenuItem,
|
MenuItem,
|
||||||
Modal,
|
Modal,
|
||||||
Select,
|
Select,
|
||||||
|
Switch,
|
||||||
TextField,
|
TextField,
|
||||||
|
Typography,
|
||||||
useTheme
|
useTheme
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
|
@ -17,10 +19,9 @@ import { Close as CloseIcon } from '@mui/icons-material';
|
||||||
import { InnovEnergyUser } from 'src/interfaces/UserTypes';
|
import { InnovEnergyUser } from 'src/interfaces/UserTypes';
|
||||||
import axiosConfig from 'src/Resources/axiosConfig';
|
import axiosConfig from 'src/Resources/axiosConfig';
|
||||||
import { TokenContext } from 'src/contexts/tokenContext';
|
import { TokenContext } from 'src/contexts/tokenContext';
|
||||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
|
||||||
import Checkbox from '@mui/material/Checkbox';
|
|
||||||
import { I_Folder, I_Installation } from 'src/interfaces/InstallationTypes';
|
import { I_Folder, I_Installation } from 'src/interfaces/InstallationTypes';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||||
|
|
||||||
interface userFormProps {
|
interface userFormProps {
|
||||||
cancel: () => void;
|
cancel: () => void;
|
||||||
|
@ -385,16 +386,22 @@ function userForm(props: userFormProps) {
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
|
labelPlacement="start"
|
||||||
control={
|
control={
|
||||||
<Checkbox
|
<Switch
|
||||||
|
color="primary"
|
||||||
onChange={handleAdminChange}
|
onChange={handleAdminChange}
|
||||||
sx={{
|
sx={{
|
||||||
marginLeft: '11px'
|
marginLeft: '8px',
|
||||||
|
marginTop: '2px'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label="Admin"
|
label={<Typography sx={{ marginTop: '6px' }}>Admin</Typography>}
|
||||||
sx={{ marginTop: 1 }}
|
sx={{
|
||||||
|
marginLeft: '10px',
|
||||||
|
marginTop: '9px'
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,12 @@
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Card,
|
|
||||||
Typography,
|
|
||||||
Container,
|
|
||||||
Divider,
|
|
||||||
Button,
|
Button,
|
||||||
FormControl,
|
Container,
|
||||||
OutlinedInput,
|
OutlinedInput,
|
||||||
InputAdornment,
|
styled,
|
||||||
styled
|
Typography
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { Helmet } from 'react-helmet-async';
|
import { Helmet } from 'react-helmet-async';
|
||||||
import SearchTwoToneIcon from '@mui/icons-material/SearchTwoTone';
|
|
||||||
|
|
||||||
const MainContent = styled(Box)(
|
const MainContent = styled(Box)(
|
||||||
({ theme }) => `
|
({ theme }) => `
|
||||||
|
@ -50,42 +45,14 @@ function Status404() {
|
||||||
<Typography variant="h2" sx={{ my: 2 }}>
|
<Typography variant="h2" sx={{ my: 2 }}>
|
||||||
The page you were looking for doesn't exist.
|
The page you were looking for doesn't exist.
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography
|
<Button
|
||||||
variant="h4"
|
href="/login"
|
||||||
color="text.secondary"
|
variant="outlined"
|
||||||
fontWeight="normal"
|
sx={{ backgroundColor: 'white' }}
|
||||||
sx={{ mb: 4 }}
|
|
||||||
>
|
>
|
||||||
It's on us, we moved the content to a different page. The search
|
|
||||||
below should help!
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<Container maxWidth="sm">
|
|
||||||
<Card sx={{ textAlign: 'center', mt: 3, p: 4 }}>
|
|
||||||
<FormControl variant="outlined" fullWidth>
|
|
||||||
<OutlinedInputWrapper
|
|
||||||
type="text"
|
|
||||||
placeholder="Search terms here..."
|
|
||||||
endAdornment={
|
|
||||||
<InputAdornment position="end">
|
|
||||||
<ButtonSearch variant="contained" size="small">
|
|
||||||
Search
|
|
||||||
</ButtonSearch>
|
|
||||||
</InputAdornment>
|
|
||||||
}
|
|
||||||
startAdornment={
|
|
||||||
<InputAdornment position="start">
|
|
||||||
<SearchTwoToneIcon />
|
|
||||||
</InputAdornment>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<Divider sx={{ my: 4 }}>OR</Divider>
|
|
||||||
<Button href="/overview" variant="outlined">
|
|
||||||
Go to homepage
|
Go to homepage
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Box>
|
||||||
</Container>
|
|
||||||
</Container>
|
</Container>
|
||||||
</MainContent>
|
</MainContent>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -11,6 +11,7 @@ export interface overviewInterface {
|
||||||
soc: chartInfoInterface;
|
soc: chartInfoInterface;
|
||||||
temperature: chartInfoInterface;
|
temperature: chartInfoInterface;
|
||||||
dcPower: chartInfoInterface;
|
dcPower: chartInfoInterface;
|
||||||
|
dcPowerWithoutHeating: chartInfoInterface;
|
||||||
gridPower: chartInfoInterface;
|
gridPower: chartInfoInterface;
|
||||||
pvProduction: chartInfoInterface;
|
pvProduction: chartInfoInterface;
|
||||||
dcBusVoltage: chartInfoInterface;
|
dcBusVoltage: chartInfoInterface;
|
||||||
|
@ -78,6 +79,7 @@ export const transformInputToDailyData = async (
|
||||||
soc: { magnitude: 0, unit: '', min: 0, max: 0 },
|
soc: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
temperature: { magnitude: 0, unit: '', min: 0, max: 0 },
|
temperature: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
dcPower: { magnitude: 0, unit: '', min: 0, max: 0 },
|
dcPower: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
|
dcPowerWithoutHeating: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
gridPower: { magnitude: 0, unit: '', min: 0, max: 0 },
|
gridPower: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
pvProduction: { magnitude: 0, unit: '', min: 0, max: 0 },
|
pvProduction: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
dcBusVoltage: { magnitude: 0, unit: '', min: 0, max: 0 },
|
dcBusVoltage: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
|
@ -108,7 +110,7 @@ export const transformInputToDailyData = async (
|
||||||
while (startUnixTime < endTimestamp) {
|
while (startUnixTime < endTimestamp) {
|
||||||
timestampPromises.push(fetchData(startUnixTime, s3Credentials));
|
timestampPromises.push(fetchData(startUnixTime, s3Credentials));
|
||||||
|
|
||||||
startUnixTime = UnixTime.fromTicks(startUnixTime.ticks + diff / 200);
|
startUnixTime = UnixTime.fromTicks(startUnixTime.ticks + diff / 100);
|
||||||
if (startUnixTime.ticks % 2 !== 0) {
|
if (startUnixTime.ticks % 2 !== 0) {
|
||||||
startUnixTime = UnixTime.fromTicks(startUnixTime.ticks + 1);
|
startUnixTime = UnixTime.fromTicks(startUnixTime.ticks + 1);
|
||||||
}
|
}
|
||||||
|
@ -280,7 +282,7 @@ export const transformInputToAggregatedData = async (
|
||||||
maxsoc: { name: 'max SOC', data: [] },
|
maxsoc: { name: 'max SOC', data: [] },
|
||||||
pvProduction: { name: 'Pv Energy', data: [] },
|
pvProduction: { name: 'Pv Energy', data: [] },
|
||||||
dcChargingPower: { name: 'Charging Battery Energy', data: [] },
|
dcChargingPower: { name: 'Charging Battery Energy', data: [] },
|
||||||
heatingPower: { name: 'Heating Power', data: [] },
|
heatingPower: { name: 'Heating Energy', data: [] },
|
||||||
dcDischargingPower: { name: 'Discharging Battery Energy', data: [] },
|
dcDischargingPower: { name: 'Discharging Battery Energy', data: [] },
|
||||||
gridImportPower: { name: 'Grid Import Energy', data: [] },
|
gridImportPower: { name: 'Grid Import Energy', data: [] },
|
||||||
gridExportPower: { name: 'Grid Export Energy', data: [] }
|
gridExportPower: { name: 'Grid Export Energy', data: [] }
|
||||||
|
@ -290,6 +292,7 @@ export const transformInputToAggregatedData = async (
|
||||||
soc: { magnitude: 0, unit: '', min: 0, max: 0 },
|
soc: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
temperature: { magnitude: 0, unit: '', min: 0, max: 0 },
|
temperature: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
dcPower: { magnitude: 0, unit: '', min: 0, max: 0 },
|
dcPower: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
|
dcPowerWithoutHeating: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
gridPower: { magnitude: 0, unit: '', min: 0, max: 0 },
|
gridPower: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
pvProduction: { magnitude: 0, unit: '', min: 0, max: 0 },
|
pvProduction: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
dcBusVoltage: { magnitude: 0, unit: '', min: 0, max: 0 },
|
dcBusVoltage: { magnitude: 0, unit: '', min: 0, max: 0 },
|
||||||
|
@ -329,6 +332,9 @@ export const transformInputToAggregatedData = async (
|
||||||
dateList.push(currentDay.format('DD-MM'));
|
dateList.push(currentDay.format('DD-MM'));
|
||||||
pathsToSearch.forEach((path) => {
|
pathsToSearch.forEach((path) => {
|
||||||
if (result[path]) {
|
if (result[path]) {
|
||||||
|
if (path === '/GridExportPower') {
|
||||||
|
result[path].value = -result[path].value;
|
||||||
|
}
|
||||||
if (result[path].value < overviewData[path].min) {
|
if (result[path].value < overviewData[path].min) {
|
||||||
overviewData[path].min = result[path].value;
|
overviewData[path].min = result[path].value;
|
||||||
}
|
}
|
||||||
|
@ -336,9 +342,9 @@ export const transformInputToAggregatedData = async (
|
||||||
if (result[path].value > overviewData[path].max) {
|
if (result[path].value > overviewData[path].max) {
|
||||||
overviewData[path].max = result[path].value;
|
overviewData[path].max = result[path].value;
|
||||||
}
|
}
|
||||||
if (path === '/GridExportPower' && result[path].value < 0.1) {
|
// if (path === '/GridExportPower' && Math.abs(result[path].value) < 0.1) {
|
||||||
result[path].value = 0.3;
|
// result[path].value = -0.3;
|
||||||
}
|
// }
|
||||||
data[path].push(result[path].value as number);
|
data[path].push(result[path].value as number);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -395,6 +401,16 @@ export const transformInputToAggregatedData = async (
|
||||||
path = '/HeatingPower';
|
path = '/HeatingPower';
|
||||||
chartAggregatedData.heatingPower.data = data[path];
|
chartAggregatedData.heatingPower.data = data[path];
|
||||||
|
|
||||||
|
chartOverview.dcPowerWithoutHeating = {
|
||||||
|
magnitude: Math.max(
|
||||||
|
overviewData['/ChargingBatteryPower'].magnitude,
|
||||||
|
overviewData['/DischargingBatteryPower'].magnitude
|
||||||
|
),
|
||||||
|
unit: '(kWh)',
|
||||||
|
min: overviewData['/DischargingBatteryPower'].min,
|
||||||
|
max: overviewData['/ChargingBatteryPower'].max
|
||||||
|
};
|
||||||
|
|
||||||
chartOverview.dcPower = {
|
chartOverview.dcPower = {
|
||||||
magnitude: Math.max(
|
magnitude: Math.max(
|
||||||
overviewData['/ChargingBatteryPower'].magnitude,
|
overviewData['/ChargingBatteryPower'].magnitude,
|
||||||
|
@ -420,12 +436,8 @@ export const transformInputToAggregatedData = async (
|
||||||
overviewData['/GridExportPower'].magnitude
|
overviewData['/GridExportPower'].magnitude
|
||||||
),
|
),
|
||||||
unit: '(kWh)',
|
unit: '(kWh)',
|
||||||
min:
|
min: overviewData['/GridExportPower'].min,
|
||||||
overviewData['/GridImportPower'].min +
|
max: overviewData['/GridImportPower'].max
|
||||||
overviewData['/GridExportPower'].min,
|
|
||||||
max:
|
|
||||||
overviewData['/GridImportPower'].max +
|
|
||||||
overviewData['/GridExportPower'].max
|
|
||||||
};
|
};
|
||||||
|
|
||||||
chartOverview.overview = {
|
chartOverview.overview = {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { styled } from '@mui/material/styles';
|
||||||
import ExpandMoreTwoToneIcon from '@mui/icons-material/ExpandMoreTwoTone';
|
import ExpandMoreTwoToneIcon from '@mui/icons-material/ExpandMoreTwoTone';
|
||||||
import { ThemeContext } from '../../../../theme/ThemeProvider';
|
import { ThemeContext } from '../../../../theme/ThemeProvider';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
import '../../../../App.css';
|
||||||
|
|
||||||
interface HeaderButtonsProps {
|
interface HeaderButtonsProps {
|
||||||
language: string;
|
language: string;
|
||||||
|
@ -106,7 +107,7 @@ function HeaderMenu(props: HeaderButtonsProps) {
|
||||||
const isMobile = window.innerWidth <= 1280;
|
const isMobile = window.innerWidth <= 1280;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div style={{ userSelect: 'none' }}>
|
||||||
<ListWrapper
|
<ListWrapper
|
||||||
sx={{
|
sx={{
|
||||||
color: isMobile ? 'white' : ''
|
color: isMobile ? 'white' : ''
|
||||||
|
@ -132,6 +133,9 @@ function HeaderMenu(props: HeaderButtonsProps) {
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
</ListWrapper>
|
</ListWrapper>
|
||||||
|
<div
|
||||||
|
style={{ userSelect: 'none', pointerEvents: 'none', cursor: 'default' }}
|
||||||
|
>
|
||||||
<Menu anchorEl={ref.current} onClose={handleClose} open={isOpen}>
|
<Menu anchorEl={ref.current} onClose={handleClose} open={isOpen}>
|
||||||
<MenuItem value="en" onClick={() => handleLanguageSelect('en')}>
|
<MenuItem value="en" onClick={() => handleLanguageSelect('en')}>
|
||||||
English
|
English
|
||||||
|
@ -143,7 +147,8 @@ function HeaderMenu(props: HeaderButtonsProps) {
|
||||||
French
|
French
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { TokenContext } from 'src/contexts/tokenContext';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import routes from 'src/Resources/routes.json';
|
import routes from 'src/Resources/routes.json';
|
||||||
import { WebSocketContext } from '../../../../contexts/WebSocketContextProvider';
|
import { WebSocketContext } from '../../../../contexts/WebSocketContextProvider';
|
||||||
|
import '../../../../App.css';
|
||||||
|
|
||||||
const UserBoxButton = styled(Button)(
|
const UserBoxButton = styled(Button)(
|
||||||
({ theme }) => `
|
({ theme }) => `
|
||||||
|
@ -86,8 +87,13 @@ function HeaderUserbox() {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div style={{ userSelect: 'none' }}>
|
||||||
<UserBoxButton color="secondary" ref={ref} onClick={handleOpen}>
|
<UserBoxButton
|
||||||
|
color="secondary"
|
||||||
|
ref={ref}
|
||||||
|
onClick={handleOpen}
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
>
|
||||||
<Hidden mdDown>
|
<Hidden mdDown>
|
||||||
<UserBoxText>
|
<UserBoxText>
|
||||||
<UserBoxLabel variant="body1">{currentUser?.name}</UserBoxLabel>
|
<UserBoxLabel variant="body1">{currentUser?.name}</UserBoxLabel>
|
||||||
|
@ -113,6 +119,7 @@ function HeaderUserbox() {
|
||||||
horizontal: 'right'
|
horizontal: 'right'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<div style={{ userSelect: 'none', cursor: 'none' }}>
|
||||||
<MenuUserBox sx={{ minWidth: 210 }} display="flex">
|
<MenuUserBox sx={{ minWidth: 210 }} display="flex">
|
||||||
<UserBoxText>
|
<UserBoxText>
|
||||||
<UserBoxLabel variant="body1">{currentUser?.name}</UserBoxLabel>
|
<UserBoxLabel variant="body1">{currentUser?.name}</UserBoxLabel>
|
||||||
|
@ -121,6 +128,7 @@ function HeaderUserbox() {
|
||||||
</UserBoxDescription>
|
</UserBoxDescription>
|
||||||
</UserBoxText>
|
</UserBoxText>
|
||||||
</MenuUserBox>
|
</MenuUserBox>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<Box sx={{ m: 1 }}>
|
<Box sx={{ m: 1 }}>
|
||||||
|
@ -130,7 +138,7 @@ function HeaderUserbox() {
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Popover>
|
</Popover>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,12 @@ const SidebarLayout = (props: SidebarLayoutProps) => {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<div style={{ userSelect: 'none' }}>
|
||||||
<Header
|
<Header
|
||||||
language={props.language}
|
language={props.language}
|
||||||
onSelectLanguage={props.onSelectLanguage}
|
onSelectLanguage={props.onSelectLanguage}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
|
|
Loading…
Reference in New Issue