Commit fa3bbb2851a443d088ceb86e08f1daa41111e54a
1 parent
b978f0f7
UI: And confirm dialog after change ota package in device profile
Showing
9 changed files
with
62 additions
and
18 deletions
... | ... | @@ -14,16 +14,21 @@ |
14 | 14 | /// limitations under the License. |
15 | 15 | /// |
16 | 16 | |
17 | -import {Injectable} from '@angular/core'; | |
18 | -import {HttpClient} from '@angular/common/http'; | |
19 | -import {PageLink} from '@shared/models/page/page-link'; | |
20 | -import {defaultHttpOptionsFromConfig, RequestConfig} from './http-utils'; | |
21 | -import {Observable} from 'rxjs'; | |
22 | -import {PageData} from '@shared/models/page/page-data'; | |
23 | -import {DeviceProfile, DeviceProfileInfo, DeviceTransportType} from '@shared/models/device.models'; | |
24 | -import {isDefinedAndNotNull, isEmptyStr} from '@core/utils'; | |
25 | -import {ObjectLwM2M, ServerSecurityConfig} from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models'; | |
26 | -import {SortOrder} from '@shared/models/page/sort-order'; | |
17 | +import { Injectable } from '@angular/core'; | |
18 | +import { HttpClient } from '@angular/common/http'; | |
19 | +import { PageLink } from '@shared/models/page/page-link'; | |
20 | +import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils'; | |
21 | +import { forkJoin, Observable, of, throwError } from 'rxjs'; | |
22 | +import { PageData } from '@shared/models/page/page-data'; | |
23 | +import { DeviceProfile, DeviceProfileInfo, DeviceTransportType } from '@shared/models/device.models'; | |
24 | +import { isDefinedAndNotNull, isEmptyStr } from '@core/utils'; | |
25 | +import { ObjectLwM2M, ServerSecurityConfig } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models'; | |
26 | +import { SortOrder } from '@shared/models/page/sort-order'; | |
27 | +import { OtaPackageService } from '@core/http/ota-package.service'; | |
28 | +import { OtaUpdateType } from '@shared/models/ota-package.models'; | |
29 | +import { mergeMap } from 'rxjs/operators'; | |
30 | +import { DialogService } from '@core/services/dialog.service'; | |
31 | +import { TranslateService } from '@ngx-translate/core'; | |
27 | 32 | |
28 | 33 | @Injectable({ |
29 | 34 | providedIn: 'root' |
... | ... | @@ -31,7 +36,10 @@ import {SortOrder} from '@shared/models/page/sort-order'; |
31 | 36 | export class DeviceProfileService { |
32 | 37 | |
33 | 38 | constructor( |
34 | - private http: HttpClient | |
39 | + private http: HttpClient, | |
40 | + private otaPackageService: OtaPackageService, | |
41 | + private dialogService: DialogService, | |
42 | + private translate: TranslateService | |
35 | 43 | ) { |
36 | 44 | } |
37 | 45 | |
... | ... | @@ -70,6 +78,34 @@ export class DeviceProfileService { |
70 | 78 | ); |
71 | 79 | } |
72 | 80 | |
81 | + public saveDeviceProfileAndConfirmOtaChange(originDeviceProfile: DeviceProfile, deviceProfile: DeviceProfile, | |
82 | + config?: RequestConfig): Observable<DeviceProfile> { | |
83 | + const tasks: Observable<number>[] = []; | |
84 | + if (originDeviceProfile?.id?.id && originDeviceProfile.firmwareId?.id !== deviceProfile.firmwareId?.id) { | |
85 | + tasks.push(this.otaPackageService.countUpdateDeviceAfterChangePackage(OtaUpdateType.FIRMWARE, deviceProfile.id.id)); | |
86 | + } else { | |
87 | + tasks.push(of(0)); | |
88 | + } | |
89 | + if (originDeviceProfile?.id?.id && originDeviceProfile.softwareId?.id !== deviceProfile.softwareId?.id) { | |
90 | + tasks.push(this.otaPackageService.countUpdateDeviceAfterChangePackage(OtaUpdateType.SOFTWARE, deviceProfile.id.id)); | |
91 | + } else { | |
92 | + tasks.push(of(0)); | |
93 | + } | |
94 | + return forkJoin(tasks).pipe( | |
95 | + mergeMap(([deviceFirmwareUpdate, deviceSoftwareUpdate]) => { | |
96 | + let text = ''; | |
97 | + if (deviceFirmwareUpdate > 0) { | |
98 | + text += this.translate.instant('ota-update.change-firmware', {count: deviceFirmwareUpdate}); | |
99 | + } | |
100 | + if (deviceSoftwareUpdate > 0) { | |
101 | + text += text.length ? '<br/>' : ''; | |
102 | + text += this.translate.instant('ota-update.change-software', {count: deviceSoftwareUpdate}); | |
103 | + } | |
104 | + return text !== '' ? this.dialogService.confirm('', text) : of(true); | |
105 | + }), | |
106 | + mergeMap((update) => update ? this.saveDeviceProfile(deviceProfile, config) : throwError('Canceled saving device profiles'))); | |
107 | + } | |
108 | + | |
73 | 109 | public saveDeviceProfile(deviceProfile: DeviceProfile, config?: RequestConfig): Observable<DeviceProfile> { |
74 | 110 | return this.http.post<DeviceProfile>('/api/deviceProfile', deviceProfile, defaultHttpOptionsFromConfig(config)); |
75 | 111 | } | ... | ... |
... | ... | @@ -120,4 +120,8 @@ export class OtaPackageService { |
120 | 120 | return this.http.delete(`/api/otaPackage/${otaPackageId}`, defaultHttpOptionsFromConfig(config)); |
121 | 121 | } |
122 | 122 | |
123 | + public countUpdateDeviceAfterChangePackage(type: OtaUpdateType, deviceProfileId: string, config?: RequestConfig): Observable<number> { | |
124 | + return this.http.get<number>(`/api/devices/count/${type}?deviceProfileId=${deviceProfileId}`, defaultHttpOptionsFromConfig(config)); | |
125 | + } | |
126 | + | |
123 | 127 | } | ... | ... |
... | ... | @@ -280,7 +280,7 @@ export class EntityDetailsPanelComponent extends PageComponent implements AfterV |
280 | 280 | editingEntity.additionalInfo = |
281 | 281 | mergeDeep((this.editingEntity as any).additionalInfo, this.entityComponent.entityFormValue()?.additionalInfo); |
282 | 282 | } |
283 | - this.entitiesTableConfig.saveEntity(editingEntity).subscribe( | |
283 | + this.entitiesTableConfig.saveEntity(editingEntity, this.editingEntity).subscribe( | |
284 | 284 | (entity) => { |
285 | 285 | this.entity = entity; |
286 | 286 | this.entityComponent.entity = entity; | ... | ... |
... | ... | @@ -66,5 +66,5 @@ |
66 | 66 | <mat-error *ngIf="selectDeviceProfileFormGroup.get('deviceProfile').hasError('required')"> |
67 | 67 | {{ 'device-profile.device-profile-required' | translate }} |
68 | 68 | </mat-error> |
69 | - <mat-hint *ngIf="!!hint">{{ hint | translate }}</mat-hint> | |
69 | + <mat-hint *ngIf="hint && !disabled">{{ hint | translate }}</mat-hint> | |
70 | 70 | </mat-form-field> | ... | ... |
... | ... | @@ -90,7 +90,7 @@ export class DeviceProfileDialogComponent extends |
90 | 90 | this.submitted = true; |
91 | 91 | if (this.deviceProfileComponent.entityForm.valid) { |
92 | 92 | this.deviceProfile = {...this.deviceProfile, ...this.deviceProfileComponent.entityFormValue()}; |
93 | - this.deviceProfileService.saveDeviceProfile(this.deviceProfile).subscribe( | |
93 | + this.deviceProfileService.saveDeviceProfileAndConfirmOtaChange(this.deviceProfile, this.deviceProfile).subscribe( | |
94 | 94 | (deviceProfile) => { |
95 | 95 | this.dialogRef.close(deviceProfile); |
96 | 96 | } | ... | ... |
... | ... | @@ -37,7 +37,7 @@ export type EntityStringFunction<T extends BaseData<HasId>> = (entity: T) => str |
37 | 37 | export type EntityVoidFunction<T extends BaseData<HasId>> = (entity: T) => void; |
38 | 38 | export type EntityIdsVoidFunction<T extends BaseData<HasId>> = (ids: HasUUID[]) => void; |
39 | 39 | export type EntityCountStringFunction = (count: number) => string; |
40 | -export type EntityTwoWayOperation<T extends BaseData<HasId>> = (entity: T) => Observable<T>; | |
40 | +export type EntityTwoWayOperation<T extends BaseData<HasId>> = (entity: T, originalEntity?: T) => Observable<T>; | |
41 | 41 | export type EntityByIdOperation<T extends BaseData<HasId>> = (id: HasUUID) => Observable<T>; |
42 | 42 | export type EntityIdOneWayOperation = (id: HasUUID) => Observable<any>; |
43 | 43 | export type EntityActionFunction<T extends BaseData<HasId>> = (action: EntityAction<T>) => boolean; |
... | ... | @@ -173,7 +173,7 @@ export class EntityTableConfig<T extends BaseData<HasId>, P extends PageLink = P |
173 | 173 | deleteEntitiesTitle: EntityCountStringFunction = () => ''; |
174 | 174 | deleteEntitiesContent: EntityCountStringFunction = () => ''; |
175 | 175 | loadEntity: EntityByIdOperation<T | L> = () => of(); |
176 | - saveEntity: EntityTwoWayOperation<T> = (entity) => of(entity); | |
176 | + saveEntity: EntityTwoWayOperation<T> = (entity, originalEntity) => of(entity); | |
177 | 177 | deleteEntity: EntityIdOneWayOperation = () => of(); |
178 | 178 | entitiesFetchFunction: EntitiesFetchFunction<L, P> = () => of(emptyPageData<L>()); |
179 | 179 | onEntityAction: EntityActionFunction<T> = () => false; | ... | ... |
... | ... | @@ -104,7 +104,8 @@ export class DeviceProfilesTableConfigResolver implements Resolve<EntityTableCon |
104 | 104 | |
105 | 105 | this.config.entitiesFetchFunction = pageLink => this.deviceProfileService.getDeviceProfiles(pageLink); |
106 | 106 | this.config.loadEntity = id => this.deviceProfileService.getDeviceProfile(id.id); |
107 | - this.config.saveEntity = deviceProfile => this.deviceProfileService.saveDeviceProfile(deviceProfile); | |
107 | + this.config.saveEntity = (deviceProfile, originDeviceProfile) => | |
108 | + this.deviceProfileService.saveDeviceProfileAndConfirmOtaChange(originDeviceProfile, deviceProfile); | |
108 | 109 | this.config.deleteEntity = id => this.deviceProfileService.deleteDeviceProfile(id.id); |
109 | 110 | this.config.onEntityAction = action => this.onDeviceProfileAction(action); |
110 | 111 | this.config.deleteEnabled = (deviceProfile) => deviceProfile && !deviceProfile.default; | ... | ... |
... | ... | @@ -69,6 +69,7 @@ |
69 | 69 | <tb-device-profile-autocomplete |
70 | 70 | formControlName="deviceProfileId" |
71 | 71 | required |
72 | + [ngStyle]="{'padding-bottom': isAdd ? '16px': 0}" | |
72 | 73 | [hint]="'ota-update.chose-compatible-device-profile'" |
73 | 74 | [editProfileEnabled]="false" |
74 | 75 | [addNewProfile]="false" | ... | ... |
... | ... | @@ -2155,7 +2155,9 @@ |
2155 | 2155 | "checksum": "Checksum", |
2156 | 2156 | "checksum-algorithm": "Checksum algorithm", |
2157 | 2157 | "checksum-copied-message": "Package checksum has been copied to clipboard", |
2158 | - "chose-compatible-device-profile": "Choose compatible device profile", | |
2158 | + "change-firmware": "You have changed the firmware. This may cause update of the { count, plural, 1 {1 device} other {# devices} }.", | |
2159 | + "change-software": "You have changed the software. This may cause update of the { count, plural, 1 {1 device} other {# devices} }.", | |
2160 | + "chose-compatible-device-profile": "Choose compatible device profile. The uploaded package will be available only for devices with the chosen profile.", | |
2159 | 2161 | "chose-firmware-distributed-device": "Choose firmware that will be distributed to the devices", |
2160 | 2162 | "chose-software-distributed-device": "Choose software that will be distributed to the devices", |
2161 | 2163 | "content-type": "Content type", | ... | ... |