grant ready-only Information, Battery , PV, Log and Report to Partner role in Sodistore Home and Report to Customer role

This commit is contained in:
Yinyin Liu 2026-02-26 14:52:29 +01:00
parent d464c9cd71
commit 075624717d
3 changed files with 293 additions and 172 deletions

View File

@ -175,6 +175,9 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
return true;
};
const canEdit = currentUser.userType === UserType.admin;
const isPartner = currentUser.userType === UserType.partner;
return (
<>
{openModalDeleteInstallation && (
@ -276,6 +279,7 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
onChange={handleChange}
variant="outlined"
fullWidth
inputProps={{ readOnly: !canEdit }}
/>
</div>
<div>
@ -288,8 +292,9 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
onChange={handleChange}
variant="outlined"
fullWidth
required
error={formValues.region === ''}
required={canEdit}
error={canEdit && formValues.region === ''}
inputProps={{ readOnly: !canEdit }}
/>
</div>
<div>
@ -305,8 +310,9 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
onChange={handleChange}
variant="outlined"
fullWidth
required
error={formValues.location === ''}
required={canEdit}
error={canEdit && formValues.location === ''}
inputProps={{ readOnly: !canEdit }}
/>
</div>
<div>
@ -319,23 +325,26 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
onChange={handleChange}
variant="outlined"
fullWidth
required
error={formValues.country === ''}
required={canEdit}
error={canEdit && formValues.country === ''}
inputProps={{ readOnly: !canEdit }}
/>
</div>
<div>
<TextField
label={
<FormattedMessage id="vpnip" defaultMessage="VPN IP" />
}
name="vpnIp"
value={formValues.vpnIp}
onChange={handleChange}
variant="outlined"
fullWidth
/>
</div>
{canEdit && (
<div>
<TextField
label={
<FormattedMessage id="vpnip" defaultMessage="VPN IP" />
}
name="vpnIp"
value={formValues.vpnIp}
onChange={handleChange}
variant="outlined"
fullWidth
/>
</div>
)}
<div>
<FormControl
@ -362,6 +371,7 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
name="device"
value={formValues.device}
onChange={handleChange}
inputProps={{ readOnly: !canEdit }}
>
{DeviceTypes.map((device) => (
<MenuItem key={device.id} value={device.id}>
@ -372,106 +382,116 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
</FormControl>
</div>
<div>
<TextField
label={
<FormattedMessage
id="installationSerialNumber"
defaultMessage="Installation Serial Number"
/>
}
name="serialNumber"
value={formValues.serialNumber}
onChange={handleChange}
variant="outlined"
fullWidth
/>
</div>
<div>
<TextField
label={
<FormattedMessage
id="inverterSN"
defaultMessage="Inverter Serial Number"
/>
}
name="inverterSN"
value={formValues.inverterSN}
onChange={handleChange}
variant="outlined"
fullWidth
/>
</div>
<div>
<TextField
label={
<FormattedMessage
id="dataloggerSN"
defaultMessage="Datalogger Serial Number"
/>
}
name="dataloggerSN"
value={formValues.dataloggerSN}
onChange={handleChange}
variant="outlined"
fullWidth
/>
</div>
<div>
<TextField
label={
<FormattedMessage
id="batteryClusterNumber"
defaultMessage="Battery Cluster Number"
/>
}
name="batteryClusterNumber"
value={formValues.batteryClusterNumber}
onChange={handleChange}
variant="outlined"
fullWidth
/>
</div>
<div>
<TextField
label={
<FormattedMessage
id="batteryNumber"
defaultMessage="Battery Number"
/>
}
name="batteryNumber"
type="text"
value={batteryNumber === 0 ? '' : batteryNumber}
onChange={handleBatteryNumberChange}
variant="outlined"
fullWidth
placeholder="Enter number of batteries"
/>
</div>
{batteryNumber > 0 &&
batterySerialNumbers.map((serialNumber, index) => (
<div key={index}>
{(canEdit || isPartner) && (
<>
<div>
<TextField
label={`Battery Pack ${index + 1}`}
name={`batterySN${index + 1}`}
value={serialNumber}
onChange={(e) =>
handleBatterySerialNumberChange(index, e.target.value)
label={
<FormattedMessage
id="installationSerialNumber"
defaultMessage="Installation Serial Number"
/>
}
onKeyDown={(e) => handleBatterySnKeyDown(e, index)}
inputRef={(el) => (batterySnRefs.current[index] = el)}
name="serialNumber"
value={formValues.serialNumber}
onChange={handleChange}
variant="outlined"
fullWidth
placeholder="Scan or enter serial number"
inputProps={{ readOnly: !canEdit }}
/>
</div>
))}
<div>
<TextField
label={
<FormattedMessage
id="inverterSN"
defaultMessage="Inverter Serial Number"
/>
}
name="inverterSN"
value={formValues.inverterSN}
onChange={handleChange}
variant="outlined"
fullWidth
inputProps={{ readOnly: !canEdit }}
/>
</div>
<div>
<TextField
label={
<FormattedMessage
id="dataloggerSN"
defaultMessage="Datalogger Serial Number"
/>
}
name="dataloggerSN"
value={formValues.dataloggerSN}
onChange={handleChange}
variant="outlined"
fullWidth
inputProps={{ readOnly: !canEdit }}
/>
</div>
<div>
<TextField
label={
<FormattedMessage
id="batteryClusterNumber"
defaultMessage="Battery Cluster Number"
/>
}
name="batteryClusterNumber"
value={formValues.batteryClusterNumber}
onChange={handleChange}
variant="outlined"
fullWidth
inputProps={{ readOnly: !canEdit }}
/>
</div>
<div>
<TextField
label={
<FormattedMessage
id="batteryNumber"
defaultMessage="Battery Number"
/>
}
name="batteryNumber"
type="text"
value={batteryNumber === 0 ? '' : batteryNumber}
onChange={handleBatteryNumberChange}
variant="outlined"
fullWidth
placeholder={canEdit ? 'Enter number of batteries' : ''}
inputProps={{ readOnly: !canEdit }}
/>
</div>
{batteryNumber > 0 &&
batterySerialNumbers.map((serialNumber, index) => (
<div key={index}>
<TextField
label={`Battery Pack ${index + 1}`}
name={`batterySN${index + 1}`}
value={serialNumber}
onChange={(e) =>
handleBatterySerialNumberChange(index, e.target.value)
}
onKeyDown={(e) => handleBatterySnKeyDown(e, index)}
inputRef={(el) => (batterySnRefs.current[index] = el)}
variant="outlined"
fullWidth
placeholder={canEdit ? 'Scan or enter serial number' : ''}
inputProps={{ readOnly: !canEdit }}
/>
</div>
))}
</>
)}
<div>
<TextField
@ -486,10 +506,11 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
onChange={handleChange}
variant="outlined"
fullWidth
inputProps={{ readOnly: !canEdit }}
/>
</div>
{currentUser.userType == UserType.admin && (
{canEdit && (
<>
<div>
<TextField
@ -533,21 +554,23 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
marginTop: 10
}}
>
<Button
variant="contained"
onClick={handleSubmit}
sx={{
marginLeft: '10px'
}}
disabled={!areRequiredFieldsFilled()}
>
<FormattedMessage
id="applyChanges"
defaultMessage="Apply Changes"
/>
</Button>
{canEdit && (
<Button
variant="contained"
onClick={handleSubmit}
sx={{
marginLeft: '10px'
}}
disabled={!areRequiredFieldsFilled()}
>
<FormattedMessage
id="applyChanges"
defaultMessage="Apply Changes"
/>
</Button>
)}
{currentUser.userType == UserType.admin && (
{canEdit && (
<Button
variant="contained"
onClick={handleDelete}

View File

@ -474,16 +474,18 @@ function SodioHomeInstallation(props: singleInstallationProps) {
}
/>
<Route
path={routes.log}
element={
<Log
errorLoadingS3Data={errorLoadingS3Data}
id={props.current_installation.id}
status={props.current_installation.status}
></Log>
}
/>
{currentUser.userType !== UserType.client && (
<Route
path={routes.log}
element={
<Log
errorLoadingS3Data={errorLoadingS3Data}
id={props.current_installation.id}
status={props.current_installation.status}
></Log>
}
/>
)}
<Route
path={routes.live}
@ -497,18 +499,20 @@ function SodioHomeInstallation(props: singleInstallationProps) {
}
/>
<Route
path={routes.batteryview + '/*'}
element={
<BatteryViewSodioHome
values={values}
s3Credentials={s3Credentials}
installationId={props.current_installation.id}
installation={props.current_installation}
connected={connected}
></BatteryViewSodioHome>
}
></Route>
{currentUser.userType !== UserType.client && (
<Route
path={routes.batteryview + '/*'}
element={
<BatteryViewSodioHome
values={values}
s3Credentials={s3Credentials}
installationId={props.current_installation.id}
installation={props.current_installation}
connected={connected}
></BatteryViewSodioHome>
}
/>
)}
{currentUser.userType == UserType.admin && (
<Route
@ -559,16 +563,14 @@ function SodioHomeInstallation(props: singleInstallationProps) {
}
/>
{currentUser.userType == UserType.admin && (
<Route
path={routes.report}
element={
<WeeklyReport
installationId={props.current_installation.id}
/>
}
/>
)}
<Route
path={routes.report}
element={
<WeeklyReport
installationId={props.current_installation.id}
/>
}
/>
<Route
path={'*'}

View File

@ -118,7 +118,6 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) {
value: 'log',
label: <FormattedMessage id="log" defaultMessage="Log" />
},
{
value: 'manage',
label: (
@ -128,14 +127,12 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) {
/>
)
},
{
value: 'information',
label: (
<FormattedMessage id="information" defaultMessage="Information" />
)
},
{
value: 'configuration',
label: (
@ -164,6 +161,45 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) {
)
}
]
: currentUser.userType == UserType.partner
? [
{
value: 'live',
label: <FormattedMessage id="live" defaultMessage="Live" />
},
{
value: 'overview',
label: <FormattedMessage id="overview" defaultMessage="Overview" />
},
{
value: 'batteryview',
label: (
<FormattedMessage
id="batteryview"
defaultMessage="Battery View"
/>
)
},
{
value: 'log',
label: <FormattedMessage id="log" defaultMessage="Log" />
},
{
value: 'information',
label: (
<FormattedMessage id="information" defaultMessage="Information" />
)
},
{
value: 'report',
label: (
<FormattedMessage
id="report"
defaultMessage="Report"
/>
)
}
]
: [
{
value: 'live',
@ -178,14 +214,24 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) {
label: (
<FormattedMessage id="information" defaultMessage="Information" />
)
},
{
value: 'report',
label: (
<FormattedMessage
id="report"
defaultMessage="Report"
/>
)
}
];
const tabs =
const inInstallationView =
currentTab != 'list' &&
currentTab != 'tree' &&
!location.pathname.includes('folder') &&
currentUser.userType == UserType.admin
!location.pathname.includes('folder');
const tabs = inInstallationView && currentUser.userType == UserType.admin
? [
{
value: 'list',
@ -216,7 +262,6 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) {
value: 'log',
label: <FormattedMessage id="log" defaultMessage="Log" />
},
{
value: 'manage',
label: (
@ -226,7 +271,6 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) {
/>
)
},
{
value: 'information',
label: (
@ -261,10 +305,7 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) {
)
}
]
: currentTab != 'list' &&
currentTab != 'tree' &&
!location.pathname.includes('folder') &&
currentUser.userType == UserType.client
: inInstallationView && currentUser.userType == UserType.partner
? [
{
value: 'list',
@ -282,12 +323,67 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) {
value: 'overview',
label: <FormattedMessage id="overview" defaultMessage="Overview" />
},
{
value: 'batteryview',
label: (
<FormattedMessage
id="batteryview"
defaultMessage="Battery View"
/>
)
},
{
value: 'log',
label: <FormattedMessage id="log" defaultMessage="Log" />
},
{
value: 'information',
label: (
<FormattedMessage id="information" defaultMessage="Information" />
)
},
{
value: 'report',
label: (
<FormattedMessage
id="report"
defaultMessage="Report"
/>
)
}
]
: inInstallationView && currentUser.userType == UserType.client
? [
{
value: 'list',
icon: <ListIcon id="mode-toggle-button-list-icon" />
},
{
value: 'tree',
icon: <AccountTreeIcon id="mode-toggle-button-tree-icon" />
},
{
value: 'live',
label: <FormattedMessage id="live" defaultMessage="Live" />
},
{
value: 'overview',
label: <FormattedMessage id="overview" defaultMessage="Overview" />
},
{
value: 'information',
label: (
<FormattedMessage id="information" defaultMessage="Information" />
)
},
{
value: 'report',
label: (
<FormattedMessage
id="report"
defaultMessage="Report"
/>
)
}
]
: [