Browse Source

fix(iot-hub): suppress global error toast and add Back button on provisioning error

- Add ignoreErrors: true to all entity creation API calls so errors
  are only shown in the dialog, not as global toast notifications
- Add Back button on provisioning error to navigate back to the last
  form step, allowing users to fix parameters (e.g. device name)
- Make form steps editable so stepper allows backward navigation
- Reset progress step state when going back so it re-runs with
  updated form values
pull/15347/head
Andrii Shvaika 4 months ago
parent
commit
e1e9a0cf03
  1. 3
      ui-ngx/src/app/modules/home/pages/iot-hub/device-install-dialog/device-install-dialog.component.html
  2. 33
      ui-ngx/src/app/modules/home/pages/iot-hub/device-install-dialog/device-install-dialog.component.ts

3
ui-ngx/src/app/modules/home/pages/iot-hub/device-install-dialog/device-install-dialog.component.html

@ -67,7 +67,7 @@
</ng-template>
@for (ws of wizardSteps; track ws.label; let i = $index; let last = $last) {
<mat-step [editable]="false"
<mat-step [editable]="ws.type === 'form'"
[completed]="ws.completed"
[stepControl]="ws.type === 'form' ? ws.formGroup : null">
<ng-template matStepLabel>{{ ws.label }}</ng-template>
@ -216,6 +216,7 @@
@case ('progress') {
@if (step.progressError) {
<button mat-button (click)="cancel()">{{ 'action.cancel' | translate }}</button>
<button mat-button (click)="goBackToForm()">{{ 'action.back' | translate }}</button>
<button mat-flat-button color="primary" (click)="retryEntitySteps(step)">
{{ 'action.retry' | translate }}
</button>

33
ui-ngx/src/app/modules/home/pages/iot-hub/device-install-dialog/device-install-dialog.component.ts

@ -191,6 +191,27 @@ export class TbDeviceInstallDialogComponent implements OnInit {
this.runEntitySteps(step);
}
goBackToForm(): void {
// Find the last form step before the current progress step
const currentIdx = this.stepper.selectedIndex;
for (let i = currentIdx - 1; i >= 0; i--) {
if (this.wizardSteps[i].type === 'form') {
// Reset the progress step so it re-runs when we come back
const progressStep = this.wizardSteps[currentIdx];
progressStep.entitySteps = null;
progressStep.progressError = null;
progressStep.progressDone = false;
progressStep.completed = false;
// Allow navigation back by making intermediate steps editable
for (let j = i; j < currentIdx; j++) {
this.wizardSteps[j].completed = false;
}
this.stepper.selectedIndex = i;
return;
}
}
}
getPatternErrorMessage(field: FormFieldDefinition): string {
return field.validators?.[0]?.message || 'Invalid format';
}
@ -411,16 +432,16 @@ export class TbDeviceInstallDialogComponent implements OnInit {
if (existing) {
return existing;
}
const result = await firstValueFrom(this.deviceProfileService.saveDeviceProfile(template));
const result = await firstValueFrom(this.deviceProfileService.saveDeviceProfile(template, {ignoreErrors: true}));
return { id: result.id.id, name: result.name };
}
case InstallStepType.DEVICE: {
const result = await firstValueFrom(this.deviceService.saveDevice(template));
const creds = await firstValueFrom(this.deviceService.getDeviceCredentials(result.id.id));
const result = await firstValueFrom(this.deviceService.saveDevice(template, {ignoreErrors: true}));
const creds = await firstValueFrom(this.deviceService.getDeviceCredentials(result.id.id, false, {ignoreErrors: true}));
return { id: result.id.id, name: result.name, token: creds.credentialsId };
}
case InstallStepType.DASHBOARD: {
const result = await firstValueFrom(this.dashboardService.saveDashboard(template));
const result = await firstValueFrom(this.dashboardService.saveDashboard(template, {ignoreErrors: true}));
return { id: result.id.id, name: result.title };
}
case InstallStepType.RULE_CHAIN: {
@ -430,10 +451,10 @@ export class TbDeviceInstallDialogComponent implements OnInit {
if (existing) {
return existing;
}
const saved = await firstValueFrom(this.ruleChainService.saveRuleChain(ruleChain));
const saved = await firstValueFrom(this.ruleChainService.saveRuleChain(ruleChain, {ignoreErrors: true}));
if (metadata) {
metadata.ruleChainId = saved.id;
await firstValueFrom(this.ruleChainService.saveRuleChainMetadata(metadata));
await firstValueFrom(this.ruleChainService.saveRuleChainMetadata(metadata, {ignoreErrors: true}));
}
return { id: saved.id.id, name: saved.name };
}

Loading…
Cancel
Save