Compare commits

..

No commits in common. "cee72bebe636281853d425e0ce6c59f46395881c" and "453768c7090a0721cba2c0d8ae1a1fac82f9aae8" have entirely different histories.

22 changed files with 381 additions and 543 deletions

View File

@ -16,8 +16,7 @@ dotnet publish \
-r linux-x64 -r linux-x64
echo -e "\n============================ Deploy ============================\n" echo -e "\n============================ Deploy ============================\n"
ip_addresses=("10.2.3.115" "10.2.3.104" "10.2.4.33" "10.2.4.32" "10.2.4.36" "10.2.4.35" "10.2.4.154" "10.2.4.113" "10.2.4.29") ip_addresses=("10.2.3.115" "10.2.3.104" "10.2.4.33" "10.2.4.32" "10.2.4.36" "10.2.4.35" "10.2.4.154" "10.2.4.113" "10.2.4.29" "10.2.4.211")
for ip_address in "${ip_addresses[@]}"; do for ip_address in "${ip_addresses[@]}"; do
rsync -v \ rsync -v \

View File

@ -197,17 +197,16 @@ public static class Controller
(calibrationChargeForced == CalibrationChargeType.RepetitivelyEvery && repetitiveCalibrationRequired); (calibrationChargeForced == CalibrationChargeType.RepetitivelyEvery && repetitiveCalibrationRequired);
Console.WriteLine("Next Repetitive calibration charge date is "+statusRecord.Config.DayAndTimeForRepetitiveCalibration); Console.WriteLine("Next Repetitive calibration charge date is "+statusRecord.Config.DayAndTimeForRepetitiveCalibration);
Console.WriteLine("Next Additional calibration charge date is "+statusRecord.Config.DayAndTimeForAdditionalCalibration); Console.WriteLine("Next Additional calibration charge date is "+statusRecord.Config.DayAndTimeForAdditionalCalibration);
//Console.WriteLine("Time now is "+DateTime.Now);
if (statusRecord.Battery is not null) if (statusRecord.Battery is not null)
{ {
if (calibrationChargeForced == CalibrationChargeType.AdditionallyOnce && statusRecord.Battery.Eoc ) if (calibrationChargeForced == CalibrationChargeType.AdditionallyOnce && statusRecord.Battery.Eoc )
{ {
statusRecord.Config.ForceCalibrationChargeState = CalibrationChargeType.RepetitivelyEvery; statusRecord.Config.ForceCalibrationChargeState = CalibrationChargeType.RepetitivelyEvery;
//_hasAdditionalCalibrationChargeChecked = false; _hasAdditionalCalibrationChargeChecked = false;
} }
else if (calibrationChargeForced == CalibrationChargeType.RepetitivelyEvery && statusRecord.Battery.Eoc && _hasRepetitiveCalibrationChargeChecked) else if (calibrationChargeForced == CalibrationChargeType.RepetitivelyEvery && statusRecord.Battery.Eoc )
{ {
statusRecord.Config.DayAndTimeForRepetitiveCalibration = statusRecord.Config.DayAndTimeForRepetitiveCalibration.AddDays(7); statusRecord.Config.DayAndTimeForRepetitiveCalibration = statusRecord.Config.DayAndTimeForRepetitiveCalibration.AddDays(7);
_hasRepetitiveCalibrationChargeChecked = false; _hasRepetitiveCalibrationChargeChecked = false;
@ -218,41 +217,30 @@ public static class Controller
private static Boolean RepetitiveCalibrationDateHasBeenPassed(DateTime calibrationChargeDate) private static Boolean RepetitiveCalibrationDateHasBeenPassed(DateTime calibrationChargeDate)
{ {
// if (!_hasRepetitiveCalibrationChargeChecked) if (!_hasRepetitiveCalibrationChargeChecked)
// {
// if (DateTime.Now >= calibrationChargeDate )
// {
// _hasRepetitiveCalibrationChargeChecked = true;
// return true;
// }
// return false;
// }
// return true;
if (DateTime.Now >= calibrationChargeDate )
{ {
_hasRepetitiveCalibrationChargeChecked = true; if (DateTime.Now >= calibrationChargeDate )
return true; {
_hasRepetitiveCalibrationChargeChecked = true;
return true;
}
return false;
} }
return false; return true;
} }
private static Boolean AdditionalCalibrationDateHasBeenPassed(DateTime calibrationChargeDate) private static Boolean AdditionalCalibrationDateHasBeenPassed(DateTime calibrationChargeDate)
{ {
// if (!_hasAdditionalCalibrationChargeChecked) if (!_hasAdditionalCalibrationChargeChecked)
// { {
if (DateTime.Now >= calibrationChargeDate ) if (DateTime.Now >= calibrationChargeDate )
{ {
//_hasAdditionalCalibrationChargeChecked = true; _hasAdditionalCalibrationChargeChecked = true;
return true; return true;
} }
return false; return false;
// } }
// return true; return true;
} }

View File

@ -11,7 +11,6 @@ public static class MiddlewareAgent
{ {
public static UdpClient UdpListener = null!; public static UdpClient UdpListener = null!;
private static IPAddress? _controllerIpAddress; private static IPAddress? _controllerIpAddress;
private static EndPoint? _endPoint;
public static void InitializeCommunicationToMiddleware() public static void InitializeCommunicationToMiddleware()
{ {
@ -22,11 +21,11 @@ public static class MiddlewareAgent
} }
const Int32 udpPort = 9000; const Int32 udpPort = 9000;
_endPoint = new IPEndPoint(_controllerIpAddress, udpPort); var endPoint = new IPEndPoint(_controllerIpAddress, udpPort);
UdpListener = new UdpClient(); UdpListener = new UdpClient();
UdpListener.Client.Blocking = false; UdpListener.Client.Blocking = false;
UdpListener.Client.Bind(_endPoint); UdpListener.Client.Bind(endPoint);
} }
private static IPAddress FindVpnIp() private static IPAddress FindVpnIp()
@ -55,7 +54,6 @@ public static class MiddlewareAgent
{ {
if (UdpListener.Available > 0) if (UdpListener.Available > 0)
{ {
IPEndPoint? serverEndpoint = null; IPEndPoint? serverEndpoint = null;
var replyMessage = "ACK"; var replyMessage = "ACK";
@ -74,13 +72,6 @@ public static class MiddlewareAgent
return config; return config;
} }
if (!_endPoint.Equals((IPEndPoint)UdpListener.Client.LocalEndPoint))
{
Console.WriteLine("UDP address has changed, rebinding...");
InitializeCommunicationToMiddleware();
}
return null; return null;
} }

View File

@ -1,4 +1,4 @@
#undef Amax #define Amax
#undef GridLimit #undef GridLimit
using System.Reactive.Linq; using System.Reactive.Linq;

View File

@ -31,7 +31,6 @@ interface BatteryViewProps {
values: TopologyValues; values: TopologyValues;
s3Credentials: I_S3Credentials; s3Credentials: I_S3Credentials;
installationId: number; installationId: number;
productNum: number;
} }
function BatteryView(props: BatteryViewProps) { function BatteryView(props: BatteryViewProps) {
@ -158,7 +157,6 @@ function BatteryView(props: BatteryViewProps) {
s3Credentials={props.s3Credentials} s3Credentials={props.s3Credentials}
batteryData={findBatteryData(battery.BatteryId)} batteryData={findBatteryData(battery.BatteryId)}
installationId={props.installationId} installationId={props.installationId}
productNum={props.productNum}
></DetailedBatteryView> ></DetailedBatteryView>
} }
/> />
@ -274,83 +272,72 @@ function BatteryView(props: BatteryViewProps) {
battery.AverageTemperature.unit} battery.AverageTemperature.unit}
</TableCell> </TableCell>
{props.productNum === 0 && ( <TableCell
<> style={{
<TableCell width: '20%',
style={{ textAlign: 'center',
width: '20%', padding: '8px',
textAlign: 'center', fontWeight:
padding: '8px', battery.Warnings.value !== '' ? 'bold' : 'inherit',
fontWeight: backgroundColor:
battery.Warnings.value !== '' battery.Warnings.value === '' ? 'inherit' : '#ff9900',
? 'bold' color:
: 'inherit', battery.Warnings.value != '' ? 'black' : 'inherit'
backgroundColor: }}
battery.Warnings.value === '' >
? 'inherit' {battery.Warnings.value === '' ? (
: '#ff9900', 'None'
color: ) : battery.Warnings.value.toString().split('-').length >
battery.Warnings.value != '' ? 'black' : 'inherit' 1 ? (
}} <Link
style={{ color: 'black' }}
to={
currentLocation.pathname.substring(
0,
currentLocation.pathname.lastIndexOf('/') + 1
) +
routes.log +
'?open=warning'
}
> >
{battery.Warnings.value === '' ? ( Multiple Warnings
'None' </Link>
) : battery.Warnings.value.toString().split('-') ) : (
.length > 1 ? ( battery.Warnings.value
<Link )}
style={{ color: 'black' }} </TableCell>
to={ <TableCell
currentLocation.pathname.substring( sx={{
0, width: '20%',
currentLocation.pathname.lastIndexOf('/') + 1 textAlign: 'center',
) + fontWeight:
routes.log + battery.Alarms.value !== '' ? 'bold' : 'inherit',
'?open=warning' backgroundColor:
} battery.Alarms.value === '' ? 'inherit' : '#FF033E',
> color: battery.Alarms.value != '' ? 'black' : 'inherit'
Multiple Warnings }}
</Link> >
) : ( {battery.Alarms.value === '' ? (
battery.Warnings.value 'None'
)} ) : battery.Alarms.value.toString().split('-').length >
</TableCell> 1 ? (
<TableCell <Link
sx={{ style={{ color: 'black' }}
width: '20%', to={
textAlign: 'center', currentLocation.pathname.substring(
fontWeight: 0,
battery.Alarms.value !== '' ? 'bold' : 'inherit', currentLocation.pathname.lastIndexOf('/') + 1
backgroundColor: ) +
battery.Alarms.value === '' routes.log +
? 'inherit' '?open=error'
: '#FF033E', }
color:
battery.Alarms.value != '' ? 'black' : 'inherit'
}}
> >
{battery.Alarms.value === '' ? ( Multiple Alarms
'None' </Link>
) : battery.Alarms.value.toString().split('-') ) : (
.length > 1 ? ( battery.Alarms.value
<Link )}
style={{ color: 'black' }} </TableCell>
to={
currentLocation.pathname.substring(
0,
currentLocation.pathname.lastIndexOf('/') + 1
) +
routes.log +
'?open=error'
}
>
Multiple Alarms
</Link>
) : (
battery.Alarms.value
)}
</TableCell>
</>
)}
</TableRow> </TableRow>
))} ))}
</TableBody> </TableBody>

View File

@ -25,7 +25,6 @@ interface DetailedBatteryViewProps {
s3Credentials: I_S3Credentials; s3Credentials: I_S3Credentials;
batteryData: Battery; batteryData: Battery;
installationId: number; installationId: number;
productNum: number;
} }
function DetailedBatteryView(props: DetailedBatteryViewProps) { function DetailedBatteryView(props: DetailedBatteryViewProps) {
@ -274,24 +273,22 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
<ArrowBackIcon /> <ArrowBackIcon />
</IconButton> </IconButton>
{props.productNum === 0 && ( <Button
<Button variant="contained"
variant="contained" onClick={handleUpdateFirmware}
onClick={handleUpdateFirmware} sx={{
sx={{ marginTop: '20px',
marginTop: '20px', marginLeft: '20px',
marginLeft: '20px', backgroundColor: '#ffc04d',
backgroundColor: '#ffc04d', color: '#000000',
color: '#000000', '&:hover': { bgcolor: '#f7b34d' }
'&:hover': { bgcolor: '#f7b34d' } }}
}} >
> <FormattedMessage
<FormattedMessage id="update_firmware"
id="update_firmware" defaultMessage="Update Firmware"
defaultMessage="Update Firmware" />
/> </Button>
</Button>
)}
</Grid> </Grid>
</Grid> </Grid>
<Grid container> <Grid container>
@ -313,8 +310,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{ style={{
...batteryStringStyle, ...batteryStringStyle,
backgroundColor: backgroundColor:
props.batteryData.String1Active.value == 'True' || props.batteryData.String1Active.value == 'True'
props.batteryData.String4Active.value == 0
? '#32CD32' ? '#32CD32'
: '#FF033E' : '#FF033E'
}} }}
@ -323,8 +319,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{ style={{
...batteryStringStyle, ...batteryStringStyle,
backgroundColor: backgroundColor:
props.batteryData.String2Active.value == 'True' || props.batteryData.String2Active.value == 'True'
props.batteryData.String4Active.value == 0
? '#32CD32' ? '#32CD32'
: '#FF033E' : '#FF033E'
}} }}
@ -333,8 +328,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{ style={{
...batteryStringStyle, ...batteryStringStyle,
backgroundColor: backgroundColor:
props.batteryData.String3Active.value == 'True' || props.batteryData.String3Active.value == 'True'
props.batteryData.String4Active.value == 0
? '#32CD32' ? '#32CD32'
: '#FF033E' : '#FF033E'
}} }}
@ -343,8 +337,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{ style={{
...batteryStringStyle, ...batteryStringStyle,
backgroundColor: backgroundColor:
props.batteryData.String4Active.value == 'True' || props.batteryData.String4Active.value == 'True'
props.batteryData.String4Active.value == 0
? '#32CD32' ? '#32CD32'
: '#FF033E' : '#FF033E'
}} }}
@ -353,8 +346,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{ style={{
...batteryStringStyle, ...batteryStringStyle,
backgroundColor: backgroundColor:
props.batteryData.String5Active.value == 'True' || props.batteryData.String5Active.value == 'True'
props.batteryData.String4Active.value == 0
? '#32CD32' ? '#32CD32'
: '#FF033E' : '#FF033E'
}} }}
@ -522,7 +514,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
props.batteryData.Power.unit} props.batteryData.Power.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell <TableCell
component="th" component="th"
@ -618,200 +609,196 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
</Card> </Card>
</Grid> </Grid>
{/*----------------------------------------------------------------------------------------------------------------------------------*/} {/*----------------------------------------------------------------------------------------------------------------------------------*/}
{props.productNum === 0 && ( <Grid item md={3} xs={3}>
<> <Card
<Grid item md={3} xs={3}> sx={{
<Card overflow: 'visible',
sx={{ marginTop: '30px',
overflow: 'visible', marginLeft: '20px',
marginTop: '30px', display: 'flex',
marginLeft: '20px', flexDirection: 'column',
display: 'flex', alignItems: 'center',
flexDirection: 'column', border: '2px solid #ccc',
alignItems: 'center', borderRadius: '12px'
border: '2px solid #ccc', }}
borderRadius: '12px' >
}} <Typography
> variant="h6"
<Typography component="div"
variant="h6" sx={{
component="div" marginTop: '10px',
sx={{ borderBottom: '1px solid #ccc',
marginTop: '10px', fontWeight: 'bold'
borderBottom: '1px solid #ccc', }}
fontWeight: 'bold' >
}} Temperature
> </Typography>
Temperature
</Typography>
<TableContainer <TableContainer
component={Paper} component={Paper}
sx={{ marginTop: '20px', width: '100%' }} sx={{ marginTop: '20px', width: '100%' }}
> >
<Table size="medium" aria-label="a dense table"> <Table size="medium" aria-label="a dense table">
<TableBody> <TableBody>
<TableRow> <TableRow>
<TableCell <TableCell
component="th" component="th"
scope="row" scope="row"
align="left" align="left"
sx={{ fontWeight: 'bold' }} sx={{ fontWeight: 'bold' }}
> >
Heating Heating
</TableCell> </TableCell>
<TableCell <TableCell
align="right" align="right"
sx={{ sx={{
width: '6ch', width: '6ch',
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.HeatingTemperature.value + {props.batteryData.HeatingTemperature.value +
' ' + ' ' +
props.batteryData.HeatingTemperature.unit} props.batteryData.HeatingTemperature.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell <TableCell
component="th" component="th"
scope="row" scope="row"
align="left" align="left"
sx={{ fontWeight: 'bold' }} sx={{ fontWeight: 'bold' }}
> >
Board Temperature Board Temperature
</TableCell> </TableCell>
<TableCell <TableCell
align="right" align="right"
sx={{ sx={{
width: '6ch', width: '6ch',
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.BoardTemperature.value + {props.batteryData.BoardTemperature.value +
' ' + ' ' +
props.batteryData.BoardTemperature.unit} props.batteryData.BoardTemperature.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell <TableCell
component="th" component="th"
scope="row" scope="row"
align="left" align="left"
sx={{ fontWeight: 'bold' }} sx={{ fontWeight: 'bold' }}
> >
Center Cells Temperature Center Cells Temperature
</TableCell> </TableCell>
<TableCell <TableCell
align="right" align="right"
sx={{ sx={{
width: '6ch', width: '6ch',
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.AverageTemperature.value + {props.batteryData.AverageTemperature.value +
' ' + ' ' +
props.batteryData.AverageTemperature.unit} props.batteryData.AverageTemperature.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell <TableCell
component="th" component="th"
scope="row" scope="row"
align="left" align="left"
sx={{ fontWeight: 'bold' }} sx={{ fontWeight: 'bold' }}
> >
Left Cells Temperature Left Cells Temperature
</TableCell> </TableCell>
<TableCell <TableCell
align="right" align="right"
sx={{ sx={{
width: '6ch', width: '6ch',
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.LeftCellsTemperature.value + {props.batteryData.LeftCellsTemperature.value +
' ' + ' ' +
props.batteryData.LeftCellsTemperature.unit} props.batteryData.LeftCellsTemperature.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell <TableCell
component="th" component="th"
scope="row" scope="row"
align="left" align="left"
sx={{ fontWeight: 'bold' }} sx={{ fontWeight: 'bold' }}
> >
Right Cells Temperature Right Cells Temperature
</TableCell> </TableCell>
<TableCell <TableCell
align="right" align="right"
sx={{ sx={{
width: '6ch', width: '6ch',
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.RightCellsTemperature.value + {props.batteryData.RightCellsTemperature.value +
' ' + ' ' +
props.batteryData.RightCellsTemperature.unit} props.batteryData.RightCellsTemperature.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell <TableCell
component="th" component="th"
scope="row" scope="row"
align="left" align="left"
sx={{ fontWeight: 'bold' }} sx={{ fontWeight: 'bold' }}
> >
Average Temperature Average Temperature
</TableCell> </TableCell>
<TableCell <TableCell
align="right" align="right"
sx={{ sx={{
width: '6ch', width: '6ch',
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.AverageTemperature.value + {props.batteryData.AverageTemperature.value +
' ' + ' ' +
props.batteryData.AverageTemperature.unit} props.batteryData.AverageTemperature.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell <TableCell
component="th" component="th"
scope="row" scope="row"
align="left" align="left"
sx={{ fontWeight: 'bold' }} sx={{ fontWeight: 'bold' }}
> >
State State
</TableCell> </TableCell>
<TableCell <TableCell
align="right" align="right"
sx={{ sx={{
width: '6ch', width: '6ch',
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.StateTemperature.value + {props.batteryData.StateTemperature.value +
' ' + ' ' +
props.batteryData.StateTemperature.unit} props.batteryData.StateTemperature.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
</TableBody> </TableBody>
</Table> </Table>
</TableContainer> </TableContainer>
</Card> </Card>
</Grid> </Grid>
</>
)}
{/*----------------------------------------------------------------------------------------------------------------------------------*/} {/*----------------------------------------------------------------------------------------------------------------------------------*/}
<Grid item md={3} xs={3}> <Grid item md={3} xs={3}>
@ -820,7 +807,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
overflow: 'visible', overflow: 'visible',
marginTop: '30px', marginTop: '30px',
marginLeft: '20px', marginLeft: '20px',
marginBottom: '20px',
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
alignItems: 'center', alignItems: 'center',
@ -1006,7 +992,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
</Grid> </Grid>
{/*----------------------------------------------------------------------------------------------------------------------------------*/} {/*----------------------------------------------------------------------------------------------------------------------------------*/}
<Grid item md={3} xs={3}> <Grid item md={3} xs={3}>
<Card <Card
sx={{ sx={{
@ -1059,7 +1044,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
props.batteryData.Eoc.unit} props.batteryData.Eoc.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell <TableCell
component="th" component="th"
@ -1082,7 +1066,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
props.batteryData.SerialNumber.unit} props.batteryData.SerialNumber.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell <TableCell
component="th" component="th"
@ -1127,30 +1110,28 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
props.batteryData.TimeSinceTOC.unit} props.batteryData.TimeSinceTOC.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
{props.productNum === 0 && ( <TableRow>
<TableRow> <TableCell
<TableCell component="th"
component="th" scope="row"
scope="row" align="left"
align="left" sx={{ fontWeight: 'bold' }}
sx={{ fontWeight: 'bold' }} >
> Calibration Charge Requested
Calibration Charge Requested </TableCell>
</TableCell> <TableCell
<TableCell align="right"
align="right" sx={{
sx={{ width: '6ch',
width: '6ch', whiteSpace: 'nowrap',
whiteSpace: 'nowrap', paddingRight: '12px'
paddingRight: '12px' }}
}} >
> {props.batteryData.CalibrationChargeRequested.value +
{props.batteryData.CalibrationChargeRequested.value + ' ' +
' ' + props.batteryData.CalibrationChargeRequested.unit}
props.batteryData.CalibrationChargeRequested.unit} </TableCell>
</TableCell> </TableRow>
</TableRow>
)}
<TableRow> <TableRow>
<TableCell <TableCell
component="th" component="th"
@ -1200,7 +1181,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
</TableContainer> </TableContainer>
</Card> </Card>
</Grid> </Grid>
{/*----------------------------------------------------------------------------------------------------------------------------------*/} {/*----------------------------------------------------------------------------------------------------------------------------------*/}
{/*<Grid item md={1.5} xs={1.5}>*/} {/*<Grid item md={1.5} xs={1.5}>*/}

View File

@ -43,7 +43,7 @@ function Configuration(props: ConfigurationProps) {
const CalibrationChargeOptions = [ const CalibrationChargeOptions = [
'Repetitive Calibration', 'Repetitive Calibration',
'Additional Calibration', 'Additional Calibration',
'Force Permanent Calibration Now' 'Force Calibration Now'
]; ];
const CalibrationChargeOptionsController = [ const CalibrationChargeOptionsController = [
@ -93,11 +93,13 @@ function Configuration(props: ConfigurationProps) {
CalibrationChargeOptionsController.indexOf( CalibrationChargeOptionsController.indexOf(
props.values.calibrationChargeState[0].value.toString() props.values.calibrationChargeState[0].value.toString()
) == 0 ) == 0
? dayjs(props.values.repetitiveCalibrationChargeDate[0].value) ? dayjs
// .add(localOffset, 'minute') .utc(props.values.repetitiveCalibrationChargeDate[0].value)
.add(localOffset, 'minute')
.toDate() .toDate()
: dayjs(props.values.additionalCalibrationChargeDate[0].value) : dayjs
// .add(localOffset, 'minute') .utc(props.values.additionalCalibrationChargeDate[0].value)
.add(localOffset, 'minute')
.toDate() .toDate()
}); });
@ -122,19 +124,14 @@ function Configuration(props: ConfigurationProps) {
setErrorDateModalOpen(true); setErrorDateModalOpen(true);
return; return;
} else { } else {
// console.log('asked for', dayjs(formValues.calibrationChargeDate)); //console.log('asked for', dayjs(formValues.calibrationChargeDate));
const configurationToSend: ConfigurationValues = { const configurationToSend: ConfigurationValues = {
minimumSoC: formValues.minimumSoC, minimumSoC: formValues.minimumSoC,
gridSetPoint: formValues.gridSetPoint, gridSetPoint: formValues.gridSetPoint,
CalibrationChargeState: formValues.CalibrationChargeState, CalibrationChargeState: formValues.CalibrationChargeState,
calibrationChargeDate: dayjs calibrationChargeDate: dayjs(formValues.calibrationChargeDate).toDate()
.utc(formValues.calibrationChargeDate)
.add(localOffset, 'minute')
.toDate()
}; };
// console.log('will send ', dayjs(formValues.calibrationChargeDate));
setLoading(true); setLoading(true);
const res = await axiosConfig const res = await axiosConfig
.post( .post(
@ -160,11 +157,9 @@ function Configuration(props: ConfigurationProps) {
}; };
const handleConfirm = (newDate) => { const handleConfirm = (newDate) => {
//console.log('non adapted day is ', newDate);
//console.log('adapted day is ', dayjs.utc(newDate).toDate());
setFormValues({ setFormValues({
...formValues, ...formValues,
['calibrationChargeDate']: dayjs(newDate).toDate() ['calibrationChargeDate']: dayjs.utc(newDate).toDate()
}); });
}; };
@ -175,7 +170,6 @@ function Configuration(props: ConfigurationProps) {
if (difference < 0) { if (difference < 0) {
difference += 7; difference += 7;
} }
const adjustedDate = currentDate.add(difference, 'day'); const adjustedDate = currentDate.add(difference, 'day');
setFormValues({ setFormValues({
...formValues, ...formValues,
@ -191,11 +185,13 @@ function Configuration(props: ConfigurationProps) {
), ),
['calibrationChargeDate']: ['calibrationChargeDate']:
CalibrationChargeOptions.indexOf(event.target.value) == 0 CalibrationChargeOptions.indexOf(event.target.value) == 0
? dayjs(props.values.repetitiveCalibrationChargeDate[0].value) ? dayjs
// .add(localOffset, 'minute') .utc(props.values.repetitiveCalibrationChargeDate[0].value)
.add(localOffset, 'minute')
.toDate() .toDate()
: dayjs(props.values.additionalCalibrationChargeDate[0].value) : dayjs
// .add(localOffset, 'minute') .utc(props.values.additionalCalibrationChargeDate[0].value)
.add(localOffset, 'minute')
.toDate() .toDate()
}); });
}; };
@ -353,7 +349,7 @@ function Configuration(props: ConfigurationProps) {
format="DD/MM/YYYY HH:mm" format="DD/MM/YYYY HH:mm"
ampm={false} ampm={false}
label="Select Next Calibration Charge Date" label="Select Next Calibration Charge Date"
value={dayjs(formValues.calibrationChargeDate)} value={dayjs.utc(formValues.calibrationChargeDate)}
onChange={handleConfirm} onChange={handleConfirm}
sx={{ sx={{
marginTop: 2 marginTop: 2
@ -401,8 +397,8 @@ function Configuration(props: ConfigurationProps) {
<TimePicker <TimePicker
ampm={false} ampm={false}
label="Calibration Charge Hour" label="Calibration Charge Hour"
value={dayjs(formValues.calibrationChargeDate)} value={dayjs.utc(formValues.calibrationChargeDate)}
onChange={(newTime) => handleConfirm(dayjs(newTime))} onChange={handleConfirm}
/> />
</LocalizationProvider> </LocalizationProvider>
</div> </div>

View File

@ -307,7 +307,7 @@ function Information(props: InformationProps) {
label="S3 Bucket Name" label="S3 Bucket Name"
name="s3writesecretkey" name="s3writesecretkey"
value={ value={
formValues.s3BucketId + formValues.id +
'-3e5b3069-214a-43ee-8d85-57d72000c19d' '-3e5b3069-214a-43ee-8d85-57d72000c19d'
} }
variant="outlined" variant="outlined"

View File

@ -37,7 +37,7 @@ function InformationSalidomo(props: InformationSalidomoProps) {
const { currentUser } = context; const { currentUser } = context;
const theme = useTheme(); const theme = useTheme();
const [formValues, setFormValues] = useState(props.values); const [formValues, setFormValues] = useState(props.values);
const requiredFields = ['installationName', 'region', 'location', 'country']; const requiredFields = ['name', 'region', 'location', 'country'];
const [openModalDeleteInstallation, setOpenModalDeleteInstallation] = const [openModalDeleteInstallation, setOpenModalDeleteInstallation] =
useState(false); useState(false);
const navigate = useNavigate(); const navigate = useNavigate();
@ -194,7 +194,7 @@ function InformationSalidomo(props: InformationSalidomoProps) {
/> />
} }
name="installationName" name="installationName"
value={formValues.installationName} value={formValues.name}
onChange={handleChange} onChange={handleChange}
variant="outlined" variant="outlined"
fullWidth fullWidth
@ -280,8 +280,7 @@ function InformationSalidomo(props: InformationSalidomoProps) {
label="S3 Bucket Name" label="S3 Bucket Name"
name="s3writesecretkey" name="s3writesecretkey"
value={ value={
formValues.s3BucketId + formValues.id + '-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e'
'-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e'
} }
variant="outlined" variant="outlined"
fullWidth fullWidth

View File

@ -102,11 +102,11 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
<TableBody> <TableBody>
{props.installations.map((installation) => { {props.installations.map((installation) => {
const isInstallationSelected = const isInstallationSelected =
installation.s3BucketId === selectedInstallation; installation.id === selectedInstallation;
const status = getStatus(installation.id); const status = getStatus(installation.id);
const rowStyles = const rowStyles =
isRowHovered === installation.s3BucketId isRowHovered === installation.id
? { ? {
cursor: 'pointer', cursor: 'pointer',
backgroundColor: theme.colors.primary.lighter backgroundColor: theme.colors.primary.lighter
@ -116,15 +116,13 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
return ( return (
<TableRow <TableRow
hover hover
key={installation.s3BucketId} key={installation.id}
selected={isInstallationSelected} selected={isInstallationSelected}
style={rowStyles} style={rowStyles}
onClick={() => onClick={() =>
handleSelectOneInstallation(installation.s3BucketId) handleSelectOneInstallation(installation.id)
}
onMouseEnter={() =>
handleRowMouseEnter(installation.s3BucketId)
} }
onMouseEnter={() => handleRowMouseEnter(installation.id)}
onMouseLeave={() => handleRowMouseLeave()} onMouseLeave={() => handleRowMouseLeave()}
> >
<TableCell> <TableCell>

View File

@ -1,11 +1,5 @@
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
import { import { Card, CircularProgress, Grid, Typography } from '@mui/material';
Card,
CircularProgress,
Container,
Grid,
Typography
} from '@mui/material';
import { I_Installation } from 'src/interfaces/InstallationTypes'; import { I_Installation } from 'src/interfaces/InstallationTypes';
import { UserContext } from 'src/contexts/userContext'; import { UserContext } from 'src/contexts/userContext';
import AccessContextProvider from 'src/contexts/AccessContextProvider'; import AccessContextProvider from 'src/contexts/AccessContextProvider';
@ -45,14 +39,6 @@ function Installation(props: singleInstallationProps) {
const [currentTab, setCurrentTab] = useState<string>(undefined); const [currentTab, setCurrentTab] = useState<string>(undefined);
const [values, setValues] = useState<TopologyValues | null>(null); const [values, setValues] = useState<TopologyValues | null>(null);
const status = getStatus(props.current_installation.id); const status = getStatus(props.current_installation.id);
const [
failedToCommunicateWithInstallation,
setFailedToCommunicateWithInstallation
] = useState(0);
const [
openModalUnableToCommunicateWIthInstallation,
setOpenModalUnableToCommunicateWIthInstallation
] = useState(false);
if (props.current_installation == undefined) { if (props.current_installation == undefined) {
return null; return null;
@ -62,15 +48,14 @@ function Installation(props: singleInstallationProps) {
s3Region: props.current_installation.s3Region, s3Region: props.current_installation.s3Region,
s3Provider: props.current_installation.s3Provider, s3Provider: props.current_installation.s3Provider,
s3Key: props.current_installation.s3Key, s3Key: props.current_installation.s3Key,
s3Secret: props.current_installation.s3Secret, s3Secret: props.current_installation.s3Secret
s3BucketId: props.current_installation.s3BucketId
}; };
const s3Bucket = const s3Bucket =
props.current_installation.product === 0 props.current_installation.product === 0
? props.current_installation.s3BucketId.toString() + ? props.current_installation.id.toString() +
'-3e5b3069-214a-43ee-8d85-57d72000c19d' '-3e5b3069-214a-43ee-8d85-57d72000c19d'
: props.current_installation.s3BucketId.toString() + : props.current_installation.id.toString() +
'-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e'; '-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e';
const s3Credentials = { s3Bucket, ...S3data }; const s3Credentials = { s3Bucket, ...S3data };
@ -82,8 +67,6 @@ function Installation(props: singleInstallationProps) {
const res = await fetchData(now, s3Credentials); const res = await fetchData(now, s3Credentials);
if (res != FetchResult.notAvailable && res != FetchResult.tryLater) { if (res != FetchResult.notAvailable && res != FetchResult.tryLater) {
setFailedToCommunicateWithInstallation(0);
setOpenModalUnableToCommunicateWIthInstallation(false);
setValues( setValues(
extractValues({ extractValues({
time: now, time: now,
@ -91,13 +74,6 @@ function Installation(props: singleInstallationProps) {
}) })
); );
return true; return true;
} else {
setFailedToCommunicateWithInstallation((prevCount) => {
if (prevCount + 1 >= 3) {
setOpenModalUnableToCommunicateWIthInstallation(true);
}
return prevCount + 1;
});
} }
} catch (err) { } catch (err) {
return false; return false;
@ -123,12 +99,6 @@ function Installation(props: singleInstallationProps) {
setCurrentTab(path[path.length - 1]); setCurrentTab(path[path.length - 1]);
}, [location]); }, [location]);
useEffect(() => {
if (status === -1) {
setOpenModalUnableToCommunicateWIthInstallation(true);
}
}, [status]);
useEffect(() => { useEffect(() => {
if ( if (
currentTab == 'live' || currentTab == 'live' ||
@ -148,7 +118,7 @@ function Installation(props: singleInstallationProps) {
fetchDataOnlyOneTime(); fetchDataOnlyOneTime();
} }
// Cleanup function to cancel interval // Cleanup function to cancel interval and update isMounted when unmounted
return () => { return () => {
if ( if (
currentTab == 'live' || currentTab == 'live' ||
@ -160,10 +130,6 @@ function Installation(props: singleInstallationProps) {
} }
}, [currentTab, location]); }, [currentTab, location]);
const UnableToCommunicateModalHandleOk = () => {
setOpenModalUnableToCommunicateWIthInstallation(false);
};
return ( return (
<> <>
<Grid item xs={12} md={12}> <Grid item xs={12} md={12}>
@ -298,31 +264,6 @@ function Installation(props: singleInstallationProps) {
alignItems="stretch" alignItems="stretch"
spacing={0} spacing={0}
> >
{openModalUnableToCommunicateWIthInstallation && (
<Container
maxWidth="xl"
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '70vh'
}}
>
<CircularProgress size={60} style={{ color: '#ffc04d' }} />
<Typography
variant="body2"
style={{ color: 'black', fontWeight: 'bold' }}
mt={2}
>
Unable to communicate with the installation
</Typography>
<Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page
</Typography>
</Container>
)}
<Routes> <Routes>
<Route <Route
path={routes.information} path={routes.information}
@ -342,7 +283,6 @@ function Installation(props: singleInstallationProps) {
values={values} values={values}
s3Credentials={s3Credentials} s3Credentials={s3Credentials}
installationId={props.current_installation.id} installationId={props.current_installation.id}
productNum={props.current_installation.product}
></BatteryView> ></BatteryView>
} }
></Route> ></Route>

View File

@ -63,11 +63,11 @@ function InstallationSearch(props: installationSearchProps) {
{filteredData.map((installation) => { {filteredData.map((installation) => {
return ( return (
<Route <Route
key={installation.s3BucketId} key={installation.id}
path={routes.installation + installation.s3BucketId + '*'} path={routes.installation + installation.id + '*'}
element={ element={
<Installation <Installation
key={installation.s3BucketId} key={installation.id}
current_installation={installation} current_installation={installation}
type="installation" type="installation"
></Installation> ></Installation>

View File

@ -25,7 +25,6 @@ function installationForm(props: installationFormProps) {
const theme = useTheme(); const theme = useTheme();
const [open, setOpen] = useState(true); const [open, setOpen] = useState(true);
const [formValues, setFormValues] = useState<Partial<I_Installation>>({ const [formValues, setFormValues] = useState<Partial<I_Installation>>({
installationName: '',
name: '', name: '',
region: '', region: '',
location: '', location: '',
@ -33,14 +32,7 @@ function installationForm(props: installationFormProps) {
vpnIp: '', vpnIp: '',
orderNumbers: '' orderNumbers: ''
}); });
const requiredFields = [ const requiredFields = ['name', 'region', 'location', 'country', 'vpnIp'];
'installationName',
'name',
'region',
'location',
'country',
'vpnIp'
];
const tokencontext = useContext(TokenContext); const tokencontext = useContext(TokenContext);
const { removeToken } = tokencontext; const { removeToken } = tokencontext;
@ -113,21 +105,6 @@ function installationForm(props: installationFormProps) {
noValidate noValidate
autoComplete="off" autoComplete="off"
> >
<div>
<TextField
label={
<FormattedMessage
id="installationName"
defaultMessage="Installation Name"
/>
}
name="installationName"
value={formValues.installationName}
onChange={handleChange}
required
error={formValues.installationName === ''}
/>
</div>
<div> <div>
<TextField <TextField
label={ label={
@ -143,7 +120,6 @@ function installationForm(props: installationFormProps) {
error={formValues.name === ''} error={formValues.name === ''}
/> />
</div> </div>
<div> <div>
<TextField <TextField
label={<FormattedMessage id="region" defaultMessage="Region" />} label={<FormattedMessage id="region" defaultMessage="Region" />}

View File

@ -174,6 +174,7 @@ const batteryPaths = [
'/Battery/Devices/%id%/Dc/Voltage', '/Battery/Devices/%id%/Dc/Voltage',
'/Battery/Devices/%id%/Soc', '/Battery/Devices/%id%/Soc',
'/Battery/Devices/%id%/Temperatures/Cells/Average', '/Battery/Devices/%id%/Temperatures/Cells/Average',
//'/Log/SalimaxWarnings/Battery/%id%',
'/Battery/Devices/%id%/Warnings', '/Battery/Devices/%id%/Warnings',
'/Battery/Devices/%id%/Alarms', '/Battery/Devices/%id%/Alarms',
@ -318,8 +319,6 @@ export const extractValues = (
): TopologyValues | null => { ): TopologyValues | null => {
const extractedValues: TopologyValues = {} as TopologyValues; const extractedValues: TopologyValues = {} as TopologyValues;
// console.log('timeSeriesData=', timeSeriesData);
for (const topologyKey of Object.keys(topologyPaths)) { for (const topologyKey of Object.keys(topologyPaths)) {
//Each topologykey may have more than one paths (for example inverter) //Each topologykey may have more than one paths (for example inverter)
const paths = topologyPaths[topologyKey]; const paths = topologyPaths[topologyKey];

View File

@ -100,11 +100,11 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
<TableBody> <TableBody>
{props.installations.map((installation) => { {props.installations.map((installation) => {
const isInstallationSelected = const isInstallationSelected =
installation.s3BucketId === selectedInstallation; installation.id === selectedInstallation;
const status = getStatus(installation.id); const status = getStatus(installation.id);
const rowStyles = const rowStyles =
isRowHovered === installation.s3BucketId isRowHovered === installation.id
? { ? {
cursor: 'pointer', cursor: 'pointer',
backgroundColor: theme.colors.primary.lighter backgroundColor: theme.colors.primary.lighter
@ -114,15 +114,13 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
return ( return (
<TableRow <TableRow
hover hover
key={installation.s3BucketId} key={installation.id}
selected={isInstallationSelected} selected={isInstallationSelected}
style={rowStyles} style={rowStyles}
onClick={() => onClick={() =>
handleSelectOneInstallation(installation.s3BucketId) handleSelectOneInstallation(installation.id)
}
onMouseEnter={() =>
handleRowMouseEnter(installation.s3BucketId)
} }
onMouseEnter={() => handleRowMouseEnter(installation.id)}
onMouseLeave={() => handleRowMouseLeave()} onMouseLeave={() => handleRowMouseLeave()}
> >
<TableCell> <TableCell>
@ -134,7 +132,7 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
noWrap noWrap
sx={{ marginTop: '10px', fontSize: 'small' }} sx={{ marginTop: '10px', fontSize: 'small' }}
> >
{installation.installationName} {installation.name}
</Typography> </Typography>
</TableCell> </TableCell>

View File

@ -10,6 +10,7 @@ import {
} from 'src/content/dashboards/Log/graph.util'; } from 'src/content/dashboards/Log/graph.util';
import { WebSocketContext } from 'src/contexts/WebSocketContextProvider'; import { WebSocketContext } from 'src/contexts/WebSocketContextProvider';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import Overview from '../Overview/overview';
import { fetchData } from 'src/content/dashboards/Installations/fetchData'; import { fetchData } from 'src/content/dashboards/Installations/fetchData';
import { Navigate, Route, Routes, useLocation } from 'react-router-dom'; import { Navigate, Route, Routes, useLocation } from 'react-router-dom';
import routes from '../../../Resources/routes.json'; import routes from '../../../Resources/routes.json';
@ -40,12 +41,11 @@ function Installation(props: singleInstallationProps) {
s3Region: props.current_installation.s3Region, s3Region: props.current_installation.s3Region,
s3Provider: props.current_installation.s3Provider, s3Provider: props.current_installation.s3Provider,
s3Key: props.current_installation.s3Key, s3Key: props.current_installation.s3Key,
s3Secret: props.current_installation.s3Secret, s3Secret: props.current_installation.s3Secret
s3BucketId: props.current_installation.s3BucketId
}; };
const s3Bucket = const s3Bucket =
props.current_installation.s3BucketId.toString() + props.current_installation.id.toString() +
'-' + '-' +
'c0436b6a-d276-4cd8-9c44-1eae86cf5d0e'; 'c0436b6a-d276-4cd8-9c44-1eae86cf5d0e';
@ -182,10 +182,13 @@ function Installation(props: singleInstallationProps) {
values={values} values={values}
s3Credentials={s3Credentials} s3Credentials={s3Credentials}
installationId={props.current_installation.id} installationId={props.current_installation.id}
productNum={props.current_installation.product}
></BatteryView> ></BatteryView>
} }
></Route> ></Route>
<Route
path={routes.overview}
element={<Overview s3Credentials={s3Credentials}></Overview>}
/>
<Route <Route
path={'*'} path={'*'}

View File

@ -107,11 +107,11 @@ function InstallationSearch(props: installationSearchProps) {
{filteredData.map((installation) => { {filteredData.map((installation) => {
return ( return (
<Route <Route
key={installation.s3BucketId} key={installation.id}
path={routes.installation + installation.s3BucketId + '*'} path={routes.installation + installation.id + '*'}
element={ element={
<Installation <Installation
key={installation.s3BucketId} key={installation.id}
current_installation={installation} current_installation={installation}
type="installation" type="installation"
></Installation> ></Installation>

View File

@ -23,20 +23,14 @@ function SalidomonstallationForm(props: SalidomoInstallationFormProps) {
const theme = useTheme(); const theme = useTheme();
const [open, setOpen] = useState(true); const [open, setOpen] = useState(true);
const [formValues, setFormValues] = useState<Partial<I_Installation>>({ const [formValues, setFormValues] = useState<Partial<I_Installation>>({
installationName: '', name: '',
region: '', region: '',
location: '', location: '',
country: '', country: '',
vpnIp: '', vpnIp: '',
vrmLink: '' vrmLink: ''
}); });
const requiredFields = [ const requiredFields = ['name', 'location', 'country', 'vpnIp', 'vrmLink'];
'installationName',
'location',
'country',
'vpnIp',
'vrmLink'
];
const installationContext = useContext(InstallationsContext); const installationContext = useContext(InstallationsContext);
const { createInstallation, loading, setLoading, error, setError } = const { createInstallation, loading, setLoading, error, setError } =
installationContext; installationContext;
@ -114,11 +108,11 @@ function SalidomonstallationForm(props: SalidomoInstallationFormProps) {
defaultMessage="Installation Name" defaultMessage="Installation Name"
/> />
} }
name="installationName" name="name"
value={formValues.installationName} value={formValues.name}
onChange={handleChange} onChange={handleChange}
required required
error={formValues.installationName === ''} error={formValues.name === ''}
/> />
</div> </div>
<div> <div>

View File

@ -52,7 +52,7 @@ function CustomTreeItem(props: CustomTreeItemProps) {
routes.installations + routes.installations +
routes.tree + routes.tree +
routes.installation + routes.installation +
installation.s3BucketId + installation.id +
'/' + '/' +
routes.live, routes.live,
{ {

View File

@ -28,11 +28,7 @@ function InstallationTree() {
subnode != node && subnode != node &&
subnode.parentId == node.id && ( subnode.parentId == node.id && (
<TreeNode <TreeNode
key={ key={subnode.id.toString() + subnode.type}
subnode.type == 'Installation'
? subnode.s3BucketId.toString() + subnode.type
: subnode.id.toString() + subnode.type
}
node={subnode} node={subnode}
parent_id={node.id} parent_id={node.id}
/> />
@ -62,11 +58,7 @@ function InstallationTree() {
{foldersAndInstallations.map((node, index) => { {foldersAndInstallations.map((node, index) => {
return ( return (
<TreeNode <TreeNode
key={ key={node.id.toString() + node.type}
node.type == 'Installation'
? node.s3BucketId.toString() + node.type
: node.id.toString() + node.type
}
node={node} node={node}
parent_id={'0'} parent_id={'0'}
/> />
@ -80,11 +72,11 @@ function InstallationTree() {
if (installation.type == 'Installation') { if (installation.type == 'Installation') {
return ( return (
<Route <Route
key={installation.s3BucketId} key={installation.id}
path={routes.installation + installation.s3BucketId + '*'} path={routes.installation + installation.id + '*'}
element={ element={
<Installation <Installation
key={installation.s3BucketId} key={installation.id}
current_installation={installation} current_installation={installation}
type="installation" type="installation"
></Installation> ></Installation>

View File

@ -25,6 +25,5 @@ export interface I_Folder {
information: string; information: string;
parentId: number; parentId: number;
type: string; type: string;
s3BucketId: number;
children?: (I_Installation | I_Folder)[]; children?: (I_Installation | I_Folder)[];
} }

View File

@ -3,8 +3,7 @@ export interface I_S3Credentials {
s3Provider: string; s3Provider: string;
s3Key: string; s3Key: string;
s3Secret: string; s3Secret: string;
s3Bucket: string; s3Bucket?: string;
s3BucketId: number;
} }
export interface ErrorMessage { export interface ErrorMessage {