Commit 52d07fe080c99765b8844d87c292df013f1052ba
Merge branch 'feature/ota-tag' of github.com:YevhenBondarenko/thingsboard into feature/ota-tag
Showing
7 changed files
with
52 additions
and
23 deletions
@@ -62,6 +62,7 @@ public class OtaPackageInfo extends SearchTextBasedWithAdditionalInfo<OtaPackage | @@ -62,6 +62,7 @@ public class OtaPackageInfo extends SearchTextBasedWithAdditionalInfo<OtaPackage | ||
62 | this.type = otaPackageInfo.getType(); | 62 | this.type = otaPackageInfo.getType(); |
63 | this.title = otaPackageInfo.getTitle(); | 63 | this.title = otaPackageInfo.getTitle(); |
64 | this.version = otaPackageInfo.getVersion(); | 64 | this.version = otaPackageInfo.getVersion(); |
65 | + this.tag = otaPackageInfo.getTag(); | ||
65 | this.url = otaPackageInfo.getUrl(); | 66 | this.url = otaPackageInfo.getUrl(); |
66 | this.hasData = otaPackageInfo.isHasData(); | 67 | this.hasData = otaPackageInfo.isHasData(); |
67 | this.fileName = otaPackageInfo.getFileName(); | 68 | this.fileName = otaPackageInfo.getFileName(); |
@@ -145,6 +145,7 @@ public class OtaPackageInfoEntity extends BaseSqlEntity<OtaPackageInfo> implemen | @@ -145,6 +145,7 @@ public class OtaPackageInfoEntity extends BaseSqlEntity<OtaPackageInfo> implemen | ||
145 | this.type = type; | 145 | this.type = type; |
146 | this.title = title; | 146 | this.title = title; |
147 | this.version = version; | 147 | this.version = version; |
148 | + this.tag = tag; | ||
148 | this.url = url; | 149 | this.url = url; |
149 | this.fileName = fileName; | 150 | this.fileName = fileName; |
150 | this.contentType = contentType; | 151 | this.contentType = contentType; |
@@ -59,9 +59,10 @@ export class OtaUpdateTableConfigResolve implements Resolve<EntityTableConfig<Ot | @@ -59,9 +59,10 @@ export class OtaUpdateTableConfigResolve implements Resolve<EntityTableConfig<Ot | ||
59 | 59 | ||
60 | this.config.columns.push( | 60 | this.config.columns.push( |
61 | new DateEntityTableColumn<OtaPackageInfo>('createdTime', 'common.created-time', this.datePipe, '150px'), | 61 | new DateEntityTableColumn<OtaPackageInfo>('createdTime', 'common.created-time', this.datePipe, '150px'), |
62 | - new EntityTableColumn<OtaPackageInfo>('title', 'ota-update.title', '20%'), | ||
63 | - new EntityTableColumn<OtaPackageInfo>('version', 'ota-update.version', '20%'), | ||
64 | - new EntityTableColumn<OtaPackageInfo>('type', 'ota-update.package-type', '20%', entity => { | 62 | + new EntityTableColumn<OtaPackageInfo>('title', 'ota-update.title', '15%'), |
63 | + new EntityTableColumn<OtaPackageInfo>('version', 'ota-update.version', '15%'), | ||
64 | + new EntityTableColumn<OtaPackageInfo>('tag', 'ota-update.version-tag', '15%'), | ||
65 | + new EntityTableColumn<OtaPackageInfo>('type', 'ota-update.package-type', '15%', entity => { | ||
65 | return this.translate.instant(OtaUpdateTypeTranslationMap.get(entity.type)); | 66 | return this.translate.instant(OtaUpdateTypeTranslationMap.get(entity.type)); |
66 | }), | 67 | }), |
67 | new EntityTableColumn<OtaPackageInfo>('url', 'ota-update.direct-url', '20%', entity => { | 68 | new EntityTableColumn<OtaPackageInfo>('url', 'ota-update.direct-url', '20%', entity => { |
@@ -74,6 +74,11 @@ | @@ -74,6 +74,11 @@ | ||
74 | </mat-error> | 74 | </mat-error> |
75 | </mat-form-field> | 75 | </mat-form-field> |
76 | </div> | 76 | </div> |
77 | + <mat-form-field class="mat-block" fxFlex style="margin-bottom: 8px"> | ||
78 | + <mat-label translate>ota-update.version-tag</mat-label> | ||
79 | + <input matInput formControlName="tag" type="text" [readonly]="!isAdd"> | ||
80 | + <mat-hint *ngIf="isAdd" translate>ota-update.version-tag-hint</mat-hint> | ||
81 | + </mat-form-field> | ||
77 | <tb-device-profile-autocomplete | 82 | <tb-device-profile-autocomplete |
78 | formControlName="deviceProfileId" | 83 | formControlName="deviceProfileId" |
79 | required | 84 | required |
@@ -94,8 +99,8 @@ | @@ -94,8 +99,8 @@ | ||
94 | <section *ngIf="isAdd"> | 99 | <section *ngIf="isAdd"> |
95 | <div class="mat-caption" style="margin: -8px 0 8px;" translate>ota-update.warning-after-save-no-edit</div> | 100 | <div class="mat-caption" style="margin: -8px 0 8px;" translate>ota-update.warning-after-save-no-edit</div> |
96 | <mat-radio-group formControlName="isURL" fxLayoutGap="16px"> | 101 | <mat-radio-group formControlName="isURL" fxLayoutGap="16px"> |
97 | - <mat-radio-button [value]="false">Upload binary file</mat-radio-button> | ||
98 | - <mat-radio-button [value]="true">Use external URL</mat-radio-button> | 102 | + <mat-radio-button [value]="false">{{ "ota-update.upload-binary-file" | translate }}</mat-radio-button> |
103 | + <mat-radio-button [value]="true">{{ "ota-update.use-external-url" | translate }}</mat-radio-button> | ||
99 | </mat-radio-group> | 104 | </mat-radio-group> |
100 | </section> | 105 | </section> |
101 | <section *ngIf="!entityForm.get('isURL').value"> | 106 | <section *ngIf="!entityForm.get('isURL').value"> |
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | /// | 15 | /// |
16 | 16 | ||
17 | import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; | 17 | import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; |
18 | -import { Subject } from 'rxjs'; | 18 | +import { combineLatest, Subject } from 'rxjs'; |
19 | import { Store } from '@ngrx/store'; | 19 | import { Store } from '@ngrx/store'; |
20 | import { AppState } from '@core/core.state'; | 20 | import { AppState } from '@core/core.state'; |
21 | import { TranslateService } from '@ngx-translate/core'; | 21 | import { TranslateService } from '@ngx-translate/core'; |
@@ -30,7 +30,7 @@ import { | @@ -30,7 +30,7 @@ import { | ||
30 | OtaUpdateTypeTranslationMap | 30 | OtaUpdateTypeTranslationMap |
31 | } from '@shared/models/ota-package.models'; | 31 | } from '@shared/models/ota-package.models'; |
32 | import { ActionNotificationShow } from '@core/notification/notification.actions'; | 32 | import { ActionNotificationShow } from '@core/notification/notification.actions'; |
33 | -import { filter, takeUntil } from 'rxjs/operators'; | 33 | +import { filter, startWith, takeUntil } from 'rxjs/operators'; |
34 | import { isNotEmptyStr } from '@core/utils'; | 34 | import { isNotEmptyStr } from '@core/utils'; |
35 | 35 | ||
36 | @Component({ | 36 | @Component({ |
@@ -56,22 +56,36 @@ export class OtaUpdateComponent extends EntityComponent<OtaPackage> implements O | @@ -56,22 +56,36 @@ export class OtaUpdateComponent extends EntityComponent<OtaPackage> implements O | ||
56 | 56 | ||
57 | ngOnInit() { | 57 | ngOnInit() { |
58 | super.ngOnInit(); | 58 | super.ngOnInit(); |
59 | - this.entityForm.get('isURL').valueChanges.pipe( | ||
60 | - filter(() => this.isAdd), | ||
61 | - takeUntil(this.destroy$) | ||
62 | - ).subscribe((isURL) => { | ||
63 | - if (isURL === false) { | ||
64 | - this.entityForm.get('url').clearValidators(); | ||
65 | - this.entityForm.get('file').setValidators(Validators.required); | ||
66 | - this.entityForm.get('url').updateValueAndValidity({emitEvent: false}); | ||
67 | - this.entityForm.get('file').updateValueAndValidity({emitEvent: false}); | ||
68 | - } else { | ||
69 | - this.entityForm.get('file').clearValidators(); | ||
70 | - this.entityForm.get('url').setValidators([Validators.required, Validators.pattern('(.|\\s)*\\S(.|\\s)*')]); | ||
71 | - this.entityForm.get('file').updateValueAndValidity({emitEvent: false}); | ||
72 | - this.entityForm.get('url').updateValueAndValidity({emitEvent: false}); | ||
73 | - } | ||
74 | - }); | 59 | + if (this.isAdd) { |
60 | + this.entityForm.get('isURL').valueChanges.pipe( | ||
61 | + takeUntil(this.destroy$) | ||
62 | + ).subscribe((isURL) => { | ||
63 | + if (isURL === false) { | ||
64 | + this.entityForm.get('url').clearValidators(); | ||
65 | + this.entityForm.get('file').setValidators(Validators.required); | ||
66 | + this.entityForm.get('url').updateValueAndValidity({emitEvent: false}); | ||
67 | + this.entityForm.get('file').updateValueAndValidity({emitEvent: false}); | ||
68 | + } else { | ||
69 | + this.entityForm.get('file').clearValidators(); | ||
70 | + this.entityForm.get('url').setValidators([Validators.required, Validators.pattern('(.|\\s)*\\S(.|\\s)*')]); | ||
71 | + this.entityForm.get('file').updateValueAndValidity({emitEvent: false}); | ||
72 | + this.entityForm.get('url').updateValueAndValidity({emitEvent: false}); | ||
73 | + } | ||
74 | + }); | ||
75 | + combineLatest([ | ||
76 | + this.entityForm.get('title').valueChanges.pipe(startWith(''), takeUntil(this.destroy$)), | ||
77 | + this.entityForm.get('version').valueChanges.pipe(startWith(''), takeUntil(this.destroy$)) | ||
78 | + ]).pipe( | ||
79 | + filter(() => this.entityForm.get('tag').pristine), | ||
80 | + takeUntil(this.destroy$) | ||
81 | + ).subscribe(([title, version]) => { | ||
82 | + let tag = `${title} ${version}`.trim(); | ||
83 | + if (tag === '') { | ||
84 | + tag = ''; | ||
85 | + } | ||
86 | + this.entityForm.get('tag').patchValue(tag); | ||
87 | + }); | ||
88 | + } | ||
75 | } | 89 | } |
76 | 90 | ||
77 | ngOnDestroy() { | 91 | ngOnDestroy() { |
@@ -92,6 +106,7 @@ export class OtaUpdateComponent extends EntityComponent<OtaPackage> implements O | @@ -92,6 +106,7 @@ export class OtaUpdateComponent extends EntityComponent<OtaPackage> implements O | ||
92 | const form = this.fb.group({ | 106 | const form = this.fb.group({ |
93 | title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]], | 107 | title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]], |
94 | version: [entity ? entity.version : '', [Validators.required, Validators.maxLength(255)]], | 108 | version: [entity ? entity.version : '', [Validators.required, Validators.maxLength(255)]], |
109 | + tag: [entity ? entity.tag : '', [Validators.maxLength(255)]], | ||
95 | type: [entity?.type ? entity.type : OtaUpdateType.FIRMWARE, Validators.required], | 110 | type: [entity?.type ? entity.type : OtaUpdateType.FIRMWARE, Validators.required], |
96 | deviceProfileId: [entity ? entity.deviceProfileId : null, Validators.required], | 111 | deviceProfileId: [entity ? entity.deviceProfileId : null, Validators.required], |
97 | checksumAlgorithm: [entity && entity.checksumAlgorithm ? entity.checksumAlgorithm : ChecksumAlgorithm.SHA256], | 112 | checksumAlgorithm: [entity && entity.checksumAlgorithm ? entity.checksumAlgorithm : ChecksumAlgorithm.SHA256], |
@@ -119,6 +134,7 @@ export class OtaUpdateComponent extends EntityComponent<OtaPackage> implements O | @@ -119,6 +134,7 @@ export class OtaUpdateComponent extends EntityComponent<OtaPackage> implements O | ||
119 | this.entityForm.patchValue({ | 134 | this.entityForm.patchValue({ |
120 | title: entity.title, | 135 | title: entity.title, |
121 | version: entity.version, | 136 | version: entity.version, |
137 | + tag: entity.tag, | ||
122 | type: entity.type, | 138 | type: entity.type, |
123 | deviceProfileId: entity.deviceProfileId, | 139 | deviceProfileId: entity.deviceProfileId, |
124 | checksumAlgorithm: entity.checksumAlgorithm, | 140 | checksumAlgorithm: entity.checksumAlgorithm, |
@@ -91,6 +91,7 @@ export interface OtaPackageInfo extends BaseData<OtaPackageId> { | @@ -91,6 +91,7 @@ export interface OtaPackageInfo extends BaseData<OtaPackageId> { | ||
91 | deviceProfileId?: DeviceProfileId; | 91 | deviceProfileId?: DeviceProfileId; |
92 | title?: string; | 92 | title?: string; |
93 | version?: string; | 93 | version?: string; |
94 | + tag?: string; | ||
94 | hasData?: boolean; | 95 | hasData?: boolean; |
95 | url?: string; | 96 | url?: string; |
96 | fileName: string; | 97 | fileName: string; |
@@ -2342,8 +2342,12 @@ | @@ -2342,8 +2342,12 @@ | ||
2342 | "firmware": "Firmware", | 2342 | "firmware": "Firmware", |
2343 | "software": "Software" | 2343 | "software": "Software" |
2344 | }, | 2344 | }, |
2345 | + "upload-binary-file": "Upload binary file", | ||
2346 | + "use-external-url": "Use external URL", | ||
2345 | "version": "Version", | 2347 | "version": "Version", |
2346 | "version-required": "Version is required.", | 2348 | "version-required": "Version is required.", |
2349 | + "version-tag": "Version Tag", | ||
2350 | + "version-tag-hint": "Custom tag should match the package version reported by your device.", | ||
2347 | "warning-after-save-no-edit": "Once the package is uploaded, you will not be able to modify title, version, device profile and package type." | 2351 | "warning-after-save-no-edit": "Once the package is uploaded, you will not be able to modify title, version, device profile and package type." |
2348 | }, | 2352 | }, |
2349 | "position": { | 2353 | "position": { |