update sodistore home information tab based on weekly meeting's feedback
This commit is contained in:
parent
baaabbecd0
commit
0657a5fb82
|
|
@ -27,6 +27,13 @@ public class Installation : TreeNode
|
||||||
public String Location { get; set; } = "";
|
public String Location { get; set; } = "";
|
||||||
public String Region { get; set; } = "";
|
public String Region { get; set; } = "";
|
||||||
public String Country { get; set; } = "";
|
public String Country { get; set; } = "";
|
||||||
|
public String Street { get; set; } = "";
|
||||||
|
public String PostCode { get; set; } = "";
|
||||||
|
public String City { get; set; } = "";
|
||||||
|
public String Canton { get; set; } = "";
|
||||||
|
public String DistributionPartner { get; set; } = "";
|
||||||
|
public String InverterFirmwareVersion { get; set; } = "";
|
||||||
|
public String BatteryFirmwareVersion { get; set; } = "";
|
||||||
public String VpnIp { get; set; } = "";
|
public String VpnIp { get; set; } = "";
|
||||||
public String InstallationName { get; set; } = "";
|
public String InstallationName { get; set; } = "";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -364,12 +364,15 @@ public static class ReportAggregationService
|
||||||
var installationName = installation?.Name ?? $"Installation {installationId}";
|
var installationName = installation?.Name ?? $"Installation {installationId}";
|
||||||
var monthName = new DateTime(year, month, 1).ToString("MMMM yyyy");
|
var monthName = new DateTime(year, month, 1).ToString("MMMM yyyy");
|
||||||
|
|
||||||
|
var weatherCity = !string.IsNullOrWhiteSpace(installation?.City) ? installation.City : installation?.Location;
|
||||||
|
var weatherRegion = !string.IsNullOrWhiteSpace(installation?.Canton) ? installation.Canton : installation?.Region;
|
||||||
|
|
||||||
var aiInsight = await GenerateMonthlyAiInsightAsync(
|
var aiInsight = await GenerateMonthlyAiInsightAsync(
|
||||||
installationName, monthName, days.Count,
|
installationName, monthName, days.Count,
|
||||||
totalPv, totalConsump, totalGridIn, totalGridOut,
|
totalPv, totalConsump, totalGridIn, totalGridOut,
|
||||||
totalBattChg, totalBattDis, energySaved, savingsCHF,
|
totalBattChg, totalBattDis, energySaved, savingsCHF,
|
||||||
selfSufficiency, batteryEff, language,
|
selfSufficiency, batteryEff, language,
|
||||||
installation?.Location, installation?.Country, installation?.Region);
|
weatherCity, installation?.Country, weatherRegion);
|
||||||
|
|
||||||
var monthlySummary = new MonthlyReportSummary
|
var monthlySummary = new MonthlyReportSummary
|
||||||
{
|
{
|
||||||
|
|
@ -591,6 +594,8 @@ public static class ReportAggregationService
|
||||||
var installationName = installation?.Name
|
var installationName = installation?.Name
|
||||||
?? $"Installation {report.InstallationId}";
|
?? $"Installation {report.InstallationId}";
|
||||||
var monthName = new DateTime(report.Year, report.Month, 1).ToString("MMMM yyyy");
|
var monthName = new DateTime(report.Year, report.Month, 1).ToString("MMMM yyyy");
|
||||||
|
var weatherCity = !string.IsNullOrWhiteSpace(installation?.City) ? installation.City : installation?.Location;
|
||||||
|
var weatherRegion = !string.IsNullOrWhiteSpace(installation?.Canton) ? installation.Canton : installation?.Region;
|
||||||
return GetOrGenerateInsightAsync("monthly", report.Id, language,
|
return GetOrGenerateInsightAsync("monthly", report.Id, language,
|
||||||
() => GenerateMonthlyAiInsightAsync(
|
() => GenerateMonthlyAiInsightAsync(
|
||||||
installationName, monthName, report.WeekCount,
|
installationName, monthName, report.WeekCount,
|
||||||
|
|
@ -599,7 +604,7 @@ public static class ReportAggregationService
|
||||||
report.TotalBatteryCharged, report.TotalBatteryDischarged,
|
report.TotalBatteryCharged, report.TotalBatteryDischarged,
|
||||||
report.TotalEnergySaved, report.TotalSavingsCHF,
|
report.TotalEnergySaved, report.TotalSavingsCHF,
|
||||||
report.SelfSufficiencyPercent, report.BatteryEfficiencyPercent, language,
|
report.SelfSufficiencyPercent, report.BatteryEfficiencyPercent, language,
|
||||||
installation?.Location, installation?.Country, installation?.Region));
|
weatherCity, installation?.Country, weatherRegion));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Cached-or-generated AI insight for a stored YearlyReportSummary.</summary>
|
/// <summary>Cached-or-generated AI insight for a stored YearlyReportSummary.</summary>
|
||||||
|
|
|
||||||
|
|
@ -179,9 +179,9 @@ public static class WeeklyReportService
|
||||||
|
|
||||||
// 4. Get installation location for weather forecast
|
// 4. Get installation location for weather forecast
|
||||||
var installation = Db.GetInstallationById(installationId);
|
var installation = Db.GetInstallationById(installationId);
|
||||||
var location = installation?.Location;
|
var location = !string.IsNullOrWhiteSpace(installation?.City) ? installation.City : installation?.Location;
|
||||||
var country = installation?.Country;
|
var country = installation?.Country;
|
||||||
var region = installation?.Region;
|
var region = !string.IsNullOrWhiteSpace(installation?.Canton) ? installation.Canton : installation?.Region;
|
||||||
Console.WriteLine($"[WeeklyReportService] Installation {installationId}: Location='{location}', Region='{region}', Country='{country}', HourlyRecords={currentHourlyData.Count}");
|
Console.WriteLine($"[WeeklyReportService] Installation {installationId}: Location='{location}', Region='{region}', Country='{country}', HourlyRecords={currentHourlyData.Count}");
|
||||||
|
|
||||||
return await GenerateReportFromDataAsync(
|
return await GenerateReportFromDataAsync(
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [formValues, setFormValues] = useState(props.values);
|
const [formValues, setFormValues] = useState(props.values);
|
||||||
const requiredFields = ['name', 'region', 'location', 'country'];
|
const requiredFields = ['name'];
|
||||||
const [openModalDeleteInstallation, setOpenModalDeleteInstallation] =
|
const [openModalDeleteInstallation, setOpenModalDeleteInstallation] =
|
||||||
useState(false);
|
useState(false);
|
||||||
const [pendingPreset, setPendingPreset] = useState<string | null>(null);
|
const [pendingPreset, setPendingPreset] = useState<string | null>(null);
|
||||||
|
|
@ -95,7 +95,7 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
|
||||||
|
|
||||||
const DeviceTypes = [
|
const DeviceTypes = [
|
||||||
{ id: 3, name: 'Growatt' },
|
{ id: 3, name: 'Growatt' },
|
||||||
{ id: 4, name: 'Sinexcel' }
|
{ id: 4, name: 'inesco 12K - WR Hybrid' }
|
||||||
];
|
];
|
||||||
|
|
||||||
// Preset state — initializes from persisted installationModel, empty for legacy
|
// Preset state — initializes from persisted installationModel, empty for legacy
|
||||||
|
|
@ -533,27 +533,45 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
label={<FormattedMessage id="region" defaultMessage="Region" />}
|
label={<FormattedMessage id="street" defaultMessage="Street" />}
|
||||||
name="region"
|
name="street"
|
||||||
value={formValues.region}
|
value={formValues.street || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
fullWidth
|
fullWidth
|
||||||
required={canEdit}
|
|
||||||
error={canEdit && formValues.region === ''}
|
|
||||||
inputProps={{ readOnly: !canEdit }}
|
inputProps={{ readOnly: !canEdit }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
label={<FormattedMessage id="location" defaultMessage="Location" />}
|
label={<FormattedMessage id="postCode" defaultMessage="Postcode" />}
|
||||||
name="location"
|
name="postCode"
|
||||||
value={formValues.location}
|
value={formValues.postCode || ''}
|
||||||
|
onChange={handleChange}
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
inputProps={{ readOnly: !canEdit }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TextField
|
||||||
|
label={<FormattedMessage id="city" defaultMessage="City" />}
|
||||||
|
name="city"
|
||||||
|
value={formValues.city || ''}
|
||||||
|
onChange={handleChange}
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
inputProps={{ readOnly: !canEdit }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TextField
|
||||||
|
label={<FormattedMessage id="canton" defaultMessage="Canton" />}
|
||||||
|
name="canton"
|
||||||
|
value={formValues.canton || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
fullWidth
|
fullWidth
|
||||||
required={canEdit}
|
|
||||||
error={canEdit && formValues.location === ''}
|
|
||||||
inputProps={{ readOnly: !canEdit }}
|
inputProps={{ readOnly: !canEdit }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -561,12 +579,21 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
|
||||||
<TextField
|
<TextField
|
||||||
label={<FormattedMessage id="country" defaultMessage="Country" />}
|
label={<FormattedMessage id="country" defaultMessage="Country" />}
|
||||||
name="country"
|
name="country"
|
||||||
value={formValues.country}
|
value={formValues.country || ''}
|
||||||
|
onChange={handleChange}
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
inputProps={{ readOnly: !canEdit }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TextField
|
||||||
|
label={<FormattedMessage id="distributionPartner" defaultMessage="Distribution Partner" />}
|
||||||
|
name="distributionPartner"
|
||||||
|
value={formValues.distributionPartner || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
fullWidth
|
fullWidth
|
||||||
required={canEdit}
|
|
||||||
error={canEdit && formValues.country === ''}
|
|
||||||
inputProps={{ readOnly: !canEdit }}
|
inputProps={{ readOnly: !canEdit }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -696,6 +723,18 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
|
||||||
<FormattedMessage id="installationSetup" defaultMessage="Installation Setup" />
|
<FormattedMessage id="installationSetup" defaultMessage="Installation Setup" />
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<TextField
|
||||||
|
label={<FormattedMessage id="installationSerialNumber" defaultMessage="Installation Serial Number" />}
|
||||||
|
name="serialNumber"
|
||||||
|
value={formValues.serialNumber || ''}
|
||||||
|
onChange={handleChange}
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
inputProps={{ readOnly: !canEdit }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<FormControl sx={{ m: 1, width: '50ch' }}>
|
<FormControl sx={{ m: 1, width: '50ch' }}>
|
||||||
<InputLabel
|
<InputLabel
|
||||||
|
|
@ -725,9 +764,21 @@ function InformationSodistorehome(props: InformationSodistorehomeProps) {
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
label={<FormattedMessage id="installationSerialNumber" defaultMessage="Installation Serial Number" />}
|
label={<FormattedMessage id="inverterFirmwareVersion" defaultMessage="Inverter Firmware Version" />}
|
||||||
name="serialNumber"
|
name="inverterFirmwareVersion"
|
||||||
value={formValues.serialNumber}
|
value={formValues.inverterFirmwareVersion || ''}
|
||||||
|
onChange={handleChange}
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
inputProps={{ readOnly: !canEdit }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<TextField
|
||||||
|
label={<FormattedMessage id="batteryFirmwareVersion" defaultMessage="Battery Firmware Version" />}
|
||||||
|
name="batteryFirmwareVersion"
|
||||||
|
value={formValues.batteryFirmwareVersion || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
fullWidth
|
fullWidth
|
||||||
|
|
|
||||||
|
|
@ -288,7 +288,7 @@ function Log(props: LogProps) {
|
||||||
onChange={e => { setDemoAlarm(e.target.value); setDemoResult(null); }}
|
onChange={e => { setDemoAlarm(e.target.value); setDemoResult(null); }}
|
||||||
sx={{ minWidth: 260 }}
|
sx={{ minWidth: 260 }}
|
||||||
>
|
>
|
||||||
<ListSubheader>Sinexcel</ListSubheader>
|
<ListSubheader>inesco 12K - WR Hybrid</ListSubheader>
|
||||||
{DEMO_ALARMS.sinexcel.map(a => (
|
{DEMO_ALARMS.sinexcel.map(a => (
|
||||||
<MenuItem key={a} value={a}>{a}</MenuItem>
|
<MenuItem key={a} value={a}>{a}</MenuItem>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -96,14 +96,14 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<FormattedMessage id="name" defaultMessage="Name" />
|
<FormattedMessage id="name" defaultMessage="Name" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
|
||||||
<FormattedMessage id="location" defaultMessage="Location" />
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<FormattedMessage id="installationSN" defaultMessage="Installation SN" />
|
<FormattedMessage id="installationSN" defaultMessage="Installation SN" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<FormattedMessage id="region" defaultMessage="Region" />
|
<FormattedMessage id="DeviceType" defaultMessage="Device Type" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<FormattedMessage id="canton" defaultMessage="Canton" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<FormattedMessage id="country" defaultMessage="Country" />
|
<FormattedMessage id="country" defaultMessage="Country" />
|
||||||
|
|
@ -146,19 +146,6 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
|
||||||
</Typography>
|
</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell>
|
|
||||||
<Typography
|
|
||||||
variant="body2"
|
|
||||||
fontWeight="bold"
|
|
||||||
color="text.primary"
|
|
||||||
gutterBottom
|
|
||||||
noWrap
|
|
||||||
sx={{ marginTop: '10px', fontSize: 'small' }}
|
|
||||||
>
|
|
||||||
{installation.location}
|
|
||||||
</Typography>
|
|
||||||
</TableCell>
|
|
||||||
|
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
|
|
@ -181,7 +168,20 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
|
||||||
noWrap
|
noWrap
|
||||||
sx={{ marginTop: '10px', fontSize: 'small' }}
|
sx={{ marginTop: '10px', fontSize: 'small' }}
|
||||||
>
|
>
|
||||||
{installation.region}
|
{installation.device === 3 ? 'Growatt' : installation.device === 4 ? 'inesco 12K - WR Hybrid' : ''}
|
||||||
|
</Typography>
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
fontWeight="bold"
|
||||||
|
color="text.primary"
|
||||||
|
gutterBottom
|
||||||
|
noWrap
|
||||||
|
sx={{ marginTop: '10px', fontSize: 'small' }}
|
||||||
|
>
|
||||||
|
{installation.canton || ''}
|
||||||
</Typography>
|
</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,18 +30,15 @@ function SodistorehomeInstallationForm(props: SodistorehomeInstallationFormPros)
|
||||||
const [open, setOpen] = useState(true);
|
const [open, setOpen] = useState(true);
|
||||||
const [formValues, setFormValues] = useState<Partial<I_Installation>>({
|
const [formValues, setFormValues] = useState<Partial<I_Installation>>({
|
||||||
name: '',
|
name: '',
|
||||||
region: '',
|
|
||||||
location: '',
|
|
||||||
country: '',
|
|
||||||
vpnIp: '',
|
vpnIp: '',
|
||||||
installationModel: '',
|
installationModel: '',
|
||||||
externalEms: 'No',
|
externalEms: 'No',
|
||||||
});
|
});
|
||||||
const requiredFields = ['name', 'location', 'country', 'vpnIp', 'installationModel'];
|
const requiredFields = ['name', 'vpnIp', 'installationModel'];
|
||||||
|
|
||||||
const DeviceTypes = [
|
const DeviceTypes = [
|
||||||
{ id: 3, name: 'Growatt' },
|
{ id: 3, name: 'Growatt' },
|
||||||
{ id: 4, name: 'Sinexcel' }
|
{ id: 4, name: 'inesco 12K - WR Hybrid' }
|
||||||
];
|
];
|
||||||
const installationContext = useContext(InstallationsContext);
|
const installationContext = useContext(InstallationsContext);
|
||||||
const { createInstallation, loading, setLoading, error, setError } =
|
const { createInstallation, loading, setLoading, error, setError } =
|
||||||
|
|
@ -127,42 +124,6 @@ function SodistorehomeInstallationForm(props: SodistorehomeInstallationFormPros)
|
||||||
error={formValues.name === ''}
|
error={formValues.name === ''}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<TextField
|
|
||||||
label={<FormattedMessage id="region" defaultMessage="Region" />}
|
|
||||||
name="region"
|
|
||||||
value={formValues.region}
|
|
||||||
onChange={handleChange}
|
|
||||||
required
|
|
||||||
error={formValues.region === ''}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<TextField
|
|
||||||
label={
|
|
||||||
<FormattedMessage id="location" defaultMessage="Location" />
|
|
||||||
}
|
|
||||||
name="location"
|
|
||||||
value={formValues.location}
|
|
||||||
onChange={handleChange}
|
|
||||||
required
|
|
||||||
error={formValues.location === ''}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<TextField
|
|
||||||
label={
|
|
||||||
<FormattedMessage id="country" defaultMessage="Country" />
|
|
||||||
}
|
|
||||||
name="country"
|
|
||||||
value={formValues.country}
|
|
||||||
onChange={handleChange}
|
|
||||||
required
|
|
||||||
error={formValues.country === ''}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
label={<FormattedMessage id="VpnIp" defaultMessage="VpnIp" />}
|
label={<FormattedMessage id="VpnIp" defaultMessage="VpnIp" />}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ const deviceOptionsByProduct: Record<number, { value: number; label: string }[]>
|
||||||
],
|
],
|
||||||
2: [
|
2: [
|
||||||
{ value: 3, label: 'Growatt' },
|
{ value: 3, label: 'Growatt' },
|
||||||
{ value: 4, label: 'Sinexcel' }
|
{ value: 4, label: 'inesco 12K - WR Hybrid' }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,13 @@ export interface I_Installation extends I_S3Credentials {
|
||||||
location: string;
|
location: string;
|
||||||
region: string;
|
region: string;
|
||||||
country: string;
|
country: string;
|
||||||
|
street?: string;
|
||||||
|
postCode?: string;
|
||||||
|
city?: string;
|
||||||
|
canton?: string;
|
||||||
|
distributionPartner?: string;
|
||||||
|
inverterFirmwareVersion?: string;
|
||||||
|
batteryFirmwareVersion?: string;
|
||||||
installationName: string;
|
installationName: string;
|
||||||
vpnIp: string;
|
vpnIp: string;
|
||||||
orderNumbers: string[] | string;
|
orderNumbers: string[] | string;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,13 @@
|
||||||
"alarms": "Alarme",
|
"alarms": "Alarme",
|
||||||
"applyChanges": "Änderungen speichern",
|
"applyChanges": "Änderungen speichern",
|
||||||
"country": "Land",
|
"country": "Land",
|
||||||
|
"street": "Strasse",
|
||||||
|
"postCode": "PLZ",
|
||||||
|
"city": "Ort",
|
||||||
|
"canton": "Kanton",
|
||||||
|
"distributionPartner": "Vertriebspartner",
|
||||||
|
"inverterFirmwareVersion": "Wechselrichter-Firmware-Version",
|
||||||
|
"batteryFirmwareVersion": "Batterie-Firmware-Version",
|
||||||
"networkProvider": "Netzbetreiber",
|
"networkProvider": "Netzbetreiber",
|
||||||
"createNewFolder": "Neuer Ordner",
|
"createNewFolder": "Neuer Ordner",
|
||||||
"createNewUser": "Neuer Benutzer",
|
"createNewUser": "Neuer Benutzer",
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,13 @@
|
||||||
"allInstallations": "All installations",
|
"allInstallations": "All installations",
|
||||||
"applyChanges": "Apply changes",
|
"applyChanges": "Apply changes",
|
||||||
"country": "Country",
|
"country": "Country",
|
||||||
|
"street": "Street",
|
||||||
|
"postCode": "Postcode",
|
||||||
|
"city": "City",
|
||||||
|
"canton": "Canton",
|
||||||
|
"distributionPartner": "Distribution Partner",
|
||||||
|
"inverterFirmwareVersion": "Inverter Firmware Version",
|
||||||
|
"batteryFirmwareVersion": "Battery Firmware Version",
|
||||||
"networkProvider": "Network Provider",
|
"networkProvider": "Network Provider",
|
||||||
"customerName": "Customer name",
|
"customerName": "Customer name",
|
||||||
"english": "English",
|
"english": "English",
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,13 @@
|
||||||
"alarms": "Alarmes",
|
"alarms": "Alarmes",
|
||||||
"applyChanges": "Appliquer",
|
"applyChanges": "Appliquer",
|
||||||
"country": "Pays",
|
"country": "Pays",
|
||||||
|
"street": "Rue",
|
||||||
|
"postCode": "Code postal",
|
||||||
|
"city": "Ville",
|
||||||
|
"canton": "Canton",
|
||||||
|
"distributionPartner": "Partenaire de distribution",
|
||||||
|
"inverterFirmwareVersion": "Version firmware onduleur",
|
||||||
|
"batteryFirmwareVersion": "Version firmware batterie",
|
||||||
"networkProvider": "Gestionnaire de réseau",
|
"networkProvider": "Gestionnaire de réseau",
|
||||||
"createNewFolder": "Nouveau dossier",
|
"createNewFolder": "Nouveau dossier",
|
||||||
"createNewUser": "Nouvel utilisateur",
|
"createNewUser": "Nouvel utilisateur",
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,13 @@
|
||||||
"allInstallations": "Tutte le installazioni",
|
"allInstallations": "Tutte le installazioni",
|
||||||
"applyChanges": "Applica modifiche",
|
"applyChanges": "Applica modifiche",
|
||||||
"country": "Paese",
|
"country": "Paese",
|
||||||
|
"street": "Via",
|
||||||
|
"postCode": "CAP",
|
||||||
|
"city": "Città",
|
||||||
|
"canton": "Cantone",
|
||||||
|
"distributionPartner": "Partner di distribuzione",
|
||||||
|
"inverterFirmwareVersion": "Versione firmware inverter",
|
||||||
|
"batteryFirmwareVersion": "Versione firmware batteria",
|
||||||
"networkProvider": "Gestore di rete",
|
"networkProvider": "Gestore di rete",
|
||||||
"customerName": "Nome cliente",
|
"customerName": "Nome cliente",
|
||||||
"english": "Inglese",
|
"english": "Inglese",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue