From 7ef761393924b8e35ce6a22af7475653b08f3dd3 Mon Sep 17 00:00:00 2001 From: fe-dev Date: Thu, 5 May 2022 11:02:45 +0300 Subject: [PATCH] UI: Refactoring queue --- ui-ngx/src/app/core/http/entity.service.ts | 3 +- ui-ngx/src/app/modules/common/modules-map.ts | 4 +- .../home/components/home-components.module.ts | 6 +- .../add-device-profile-dialog.component.ts | 3 +- .../queue/tenant-profile-queue.component.html | 194 ------------------ .../tenant-profile-queues.component.html | 36 +++- .../tenant-profile-queues.component.scss | 8 +- .../queue/tenant-profile-queues.component.ts | 32 ++- .../tenant-profile-data.component.html | 17 +- .../profile/tenant-profile.component.html | 23 ++- .../profile/tenant-profile.component.ts | 2 +- .../queue/queue-form.component.html | 171 +++++++++++++++ .../queue-form.component.scss} | 0 .../queue-form.component.ts} | 57 +++-- .../wizard/device-wizard-dialog.component.ts | 2 +- .../home/pages/admin/admin-routing.module.ts | 36 +++- .../pages/admin/queue/queue.component.html | 181 ++-------------- .../pages/admin/queue/queue.component.scss | 22 -- .../home/pages/admin/queue/queue.component.ts | 109 ++-------- .../queue/queues-table-config.resolver.ts | 33 ++- .../queue/queue-autocomplete.component.html | 2 +- .../queue/queue-autocomplete.component.ts | 10 +- ui-ngx/src/app/shared/models/device.models.ts | 2 +- .../app/shared/models/entity-type.models.ts | 3 +- .../assets/locale/locale.constant-en_US.json | 6 +- 25 files changed, 382 insertions(+), 580 deletions(-) delete mode 100644 ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queue.component.html create mode 100644 ui-ngx/src/app/modules/home/components/queue/queue-form.component.html rename ui-ngx/src/app/modules/home/components/{profile/queue/tenant-profile-queue.component.scss => queue/queue-form.component.scss} (100%) rename ui-ngx/src/app/modules/home/components/{profile/queue/tenant-profile-queue.component.ts => queue/queue-form.component.ts} (78%) delete mode 100644 ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.scss diff --git a/ui-ngx/src/app/core/http/entity.service.ts b/ui-ngx/src/app/core/http/entity.service.ts index 71e2a3de95..0b0c23edee 100644 --- a/ui-ngx/src/app/core/http/entity.service.ts +++ b/ui-ngx/src/app/core/http/entity.service.ts @@ -87,8 +87,7 @@ import { bodyContentEdgeEventActionTypes, Edge, EdgeEvent, EdgeEventType } from import { RuleChainMetaData, RuleChainType } from '@shared/models/rule-chain.models'; import { WidgetService } from '@core/http/widget.service'; import { DeviceProfileService } from '@core/http/device-profile.service'; -import { QueueService } from "@core/http/queue.service"; -import { ServiceType } from "@shared/models/queue.models"; +import { QueueService } from '@core/http/queue.service'; @Injectable({ providedIn: 'root' diff --git a/ui-ngx/src/app/modules/common/modules-map.ts b/ui-ngx/src/app/modules/common/modules-map.ts index bfc8f60604..a1fca3f603 100644 --- a/ui-ngx/src/app/modules/common/modules-map.ts +++ b/ui-ngx/src/app/modules/common/modules-map.ts @@ -288,7 +288,7 @@ import * as AlarmDurationPredicateValueComponent from '@home/components/profile/ import * as DashboardImageDialogComponent from '@home/components/dashboard-page/dashboard-image-dialog.component'; import * as WidgetContainerComponent from '@home/components/widget/widget-container.component'; import * as TenantProfileQueuesComponent from '@home/components/profile/queue/tenant-profile-queues.component'; -import { TenantProfileQueueComponent } from '@home/components/profile/queue/tenant-profile-queue.component'; +import * as QueueFormComponent from '@home/components/queue/queue-form.component'; import { IModulesMap } from '@modules/common/modules-map.models'; @@ -573,7 +573,7 @@ class ModulesMap implements IModulesMap { '@home/components/dashboard-page/dashboard-image-dialog.component': DashboardImageDialogComponent, '@home/components/widget/widget-container.component': WidgetContainerComponent, '@home/components/profile/queue/tenant-profile-queues.component': TenantProfileQueuesComponent, - '@home/components/profile/queue/tenant-profile-queue.component': TenantProfileQueueComponent + '@home/components/queue/queue-form.component': QueueFormComponent }; init() { diff --git a/ui-ngx/src/app/modules/home/components/home-components.module.ts b/ui-ngx/src/app/modules/home/components/home-components.module.ts index 282a494026..6039cc0553 100644 --- a/ui-ngx/src/app/modules/home/components/home-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/home-components.module.ts @@ -149,7 +149,7 @@ import { import { DashboardStateComponent } from '@home/components/dashboard-page/dashboard-state.component'; import { EntityDetailsPageComponent } from '@home/components/entity/entity-details-page.component'; import { TenantProfileQueuesComponent } from '@home/components/profile/queue/tenant-profile-queues.component'; -import { TenantProfileQueueComponent } from '@home/components/profile/queue/tenant-profile-queue.component'; +import { QueueFormComponent } from '@home/components/queue/queue-form.component'; @NgModule({ declarations: @@ -271,7 +271,7 @@ import { TenantProfileQueueComponent } from '@home/components/profile/queue/tena EmbedDashboardDialogComponent, DisplayWidgetTypesPanelComponent, TenantProfileQueuesComponent, - TenantProfileQueueComponent + QueueFormComponent ], imports: [ CommonModule, @@ -386,7 +386,7 @@ import { TenantProfileQueueComponent } from '@home/components/profile/queue/tena EmbedDashboardDialogComponent, DisplayWidgetTypesPanelComponent, TenantProfileQueuesComponent, - TenantProfileQueueComponent + QueueFormComponent ], providers: [ WidgetComponentService, diff --git a/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts index 2d80e9a25b..79c5a74db3 100644 --- a/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts @@ -50,7 +50,7 @@ import { StepperSelectionEvent } from '@angular/cdk/stepper'; import { deepTrim } from '@core/utils'; import { ServiceType } from '@shared/models/queue.models'; import { DashboardId } from '@shared/models/id/dashboard-id'; -import { QueueId } from "@shared/models/id/queue-id"; +import { QueueId } from '@shared/models/id/queue-id'; export interface AddDeviceProfileDialogData { deviceProfileName: string; @@ -188,7 +188,6 @@ export class AddDeviceProfileDialogComponent extends name: this.deviceProfileDetailsFormGroup.get('name').value, type: this.deviceProfileDetailsFormGroup.get('type').value, image: this.deviceProfileDetailsFormGroup.get('image').value, - // defaultQueueId: this.deviceProfileDetailsFormGroup.get('defaultQueueId').value, transportType: this.transportConfigFormGroup.get('transportType').value, provisionType: deviceProvisionConfiguration.type, provisionDeviceKey, diff --git a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queue.component.html b/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queue.component.html deleted file mode 100644 index 07bcb5d9e8..0000000000 --- a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queue.component.html +++ /dev/null @@ -1,194 +0,0 @@ - - - -
- -
- {{ queueTitle }} -
-
- - -
-
- -
- - - admin.queue-name - - - {{ 'queue.name-required' | translate }} - - - - queue.poll-interval - - - {{ 'queue.poll-interval-required' | translate }} - - - {{ 'queue.poll-interval-min-value' | translate }} - - - - queue.partitions - - - {{ 'queue.partitions-required' | translate }} - - - {{ 'queue.partitions-min-value' | translate }} - - - - -
{{ 'queue.consumer-per-partition' | translate }}
-
{{'queue.consumer-per-partition-hint' | translate}}
-
- - - queue.processing-timeout - - - {{ 'queue.pack-processing-timeout-required' | translate }} - - - {{ 'queue.pack-processing-timeout-min-value' | translate }} - - - - - - - queue.submit-strategy - - - -
- - queue.submit-strategy - - - {{ strategy }} - - - - {{ 'queue.submit-strategy-type-required' | translate }} - - - - queue.batch-size - - - {{ 'queue.batch-size-required' | translate }} - - - {{ 'queue.batch-size-min-value' | translate }} - - -
-
-
- - - - queue.processing-strategy - - - -
- - queue.processing-strategy - - - {{ strategy }} - - - - {{ 'queue.processing-strategy-type-required' | translate }} - - - - queue.retries - - - {{ 'queue.retries-required' | translate }} - - - {{ 'queue.retries-min-value' | translate }} - - - - queue.failure-percentage - - - {{ 'queue.failure-percentage-required' | translate }} - - - {{ 'queue.failure-percentage-min-value' | translate }} - - - {{ 'queue.failure-percentage-max-value' | translate }} - - - - queue.pause-between-retries - - - {{ 'queue.pause-between-retries-required' | translate }} - - - {{ 'queue.pause-between-retries-min-value' | translate }} - - - - queue.max-pause-between-retries - - - {{ 'queue.max-pause-between-retries-required' | translate }} - - - {{ 'queue.max-pause-between-retries-min-value' | translate }} - - -
-
-
-
-
-
-
diff --git a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.html b/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.html index 59b7e063a1..34c43f240c 100644 --- a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.html @@ -17,18 +17,34 @@ -->
- -
- - -
+ + + +
+ + {{ getName(queuesControl.value.name) }} + + + +
+
+ + + + +
-
+
tenant-profile.no-queue
diff --git a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.scss b/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.scss index 9702d807a6..189badf9fd 100644 --- a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.scss +++ b/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.scss @@ -13,15 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@import '../../../../../../scss/constants'; :host { .tb-tenant-profile-queues { - &.mat-padding { - padding: 8px; - @media #{$mat-gt-sm} { - padding: 16px; - } + .mat-expansion-panel-body { + padding-bottom: 0 !important; } } diff --git a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts b/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts index abcde44419..a403f8e82e 100644 --- a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts @@ -14,16 +14,16 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { Component, forwardRef, Input, OnDestroy } from '@angular/core'; import { AbstractControl, ControlValueAccessor, FormArray, FormBuilder, - FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, + ValidationErrors, Validator, Validators } from '@angular/forms'; @@ -32,6 +32,7 @@ import { AppState } from '@app/core/core.state'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { Subscription } from 'rxjs'; import { QueueInfo } from '@shared/models/queue.models'; +import { UtilsService } from '@core/services/utils.service'; @Component({ selector: 'tb-tenant-profile-queues', @@ -50,7 +51,7 @@ import { QueueInfo } from '@shared/models/queue.models'; } ] }) -export class TenantProfileQueuesComponent implements ControlValueAccessor, OnInit, Validator { +export class TenantProfileQueuesComponent implements ControlValueAccessor, Validator, OnDestroy { tenantProfileQueuesFormGroup: FormGroup; newQueue = false; @@ -67,11 +68,12 @@ export class TenantProfileQueuesComponent implements ControlValueAccessor, OnIni @Input() disabled: boolean; - private valueChangeSubscription: Subscription = null; + private valueChangeSubscription$: Subscription = null; private propagateChange = (v: any) => { }; constructor(private store: Store, + private utils: UtilsService, private fb: FormBuilder) { } @@ -79,6 +81,12 @@ export class TenantProfileQueuesComponent implements ControlValueAccessor, OnIni this.propagateChange = fn; } + ngOnDestroy() { + if (this.valueChangeSubscription$) { + this.valueChangeSubscription$.unsubscribe(); + } + } + registerOnTouched(fn: any): void { } @@ -88,7 +96,7 @@ export class TenantProfileQueuesComponent implements ControlValueAccessor, OnIni }); } - queuesFormArray(): FormArray { + get queuesFormArray(): FormArray { return this.tenantProfileQueuesFormGroup.get('queues') as FormArray; } @@ -102,8 +110,8 @@ export class TenantProfileQueuesComponent implements ControlValueAccessor, OnIni } writeValue(queues: Array | null): void { - if (this.valueChangeSubscription) { - this.valueChangeSubscription.unsubscribe(); + if (this.valueChangeSubscription$) { + this.valueChangeSubscription$.unsubscribe(); } const queuesControls: Array = []; if (queues) { @@ -117,7 +125,7 @@ export class TenantProfileQueuesComponent implements ControlValueAccessor, OnIni } else { this.tenantProfileQueuesFormGroup.enable({emitEvent: false}); } - this.valueChangeSubscription = this.tenantProfileQueuesFormGroup.valueChanges.subscribe(() => { + this.valueChangeSubscription$ = this.tenantProfileQueuesFormGroup.valueChanges.subscribe(value => { this.updateModel(); }); } @@ -163,14 +171,18 @@ export class TenantProfileQueuesComponent implements ControlValueAccessor, OnIni } } - public validate(c: FormControl) { - return (this.tenantProfileQueuesFormGroup.valid) ? null : { + public validate(c: AbstractControl): ValidationErrors | null { + return this.tenantProfileQueuesFormGroup.valid ? null : { queues: { valid: false, }, }; } + getName(value) { + return this.utils.customTranslation(value, value); + } + private updateModel() { const queues: Array = this.tenantProfileQueuesFormGroup.get('queues').value; this.propagateChange(queues); diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant-profile-data.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant-profile-data.component.html index 81ca768911..5cf574a0e4 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant-profile-data.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant-profile-data.component.html @@ -16,17 +16,8 @@ -->
- - - -
tenant-profile.profile-configuration
-
-
- - - - -
+ +
diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant-profile.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant-profile.component.html index 4b511037e7..789ba8590a 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant-profile.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant-profile.component.html @@ -68,13 +68,13 @@
{{'tenant.isolated-tb-rule-engine-details' | translate}}
- + -
{{'tenant-profile.queues-with-count' | translate: + {{'tenant-profile.queues-with-count' | translate: {count: entityForm.get('profileData').get('queueConfiguration').value ? - entityForm.get('profileData').get('queueConfiguration').value.length : 0} }}
+ entityForm.get('profileData').get('queueConfiguration').value.length : 0} }}
@@ -83,10 +83,19 @@ >
- - + + + +
tenant-profile.profile-configuration
+
+
+ + + + +
tenant-profile.description diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant-profile.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant-profile.component.ts index 285cecc5e6..6a57ee57d0 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant-profile.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant-profile.component.ts @@ -81,7 +81,7 @@ export class TenantProfileComponent extends EntityComponent { profileData: this.fb.group({ configuration: [entity && !this.isAdd ? entity?.profileData.configuration : createTenantProfileConfiguration(TenantProfileType.DEFAULT), []], - queueConfiguration: [null, []] + queueConfiguration: [entity && !this.isAdd ? entity?.profileData.queueConfiguration : null, []] }), description: [entity ? entity.description : '', []], } diff --git a/ui-ngx/src/app/modules/home/components/queue/queue-form.component.html b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.html new file mode 100644 index 0000000000..9ea9720b7b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.html @@ -0,0 +1,171 @@ + + +
+ + admin.queue-name + + + {{ 'queue.name-required' | translate }} + + + + queue.poll-interval + + + {{ 'queue.poll-interval-required' | translate }} + + + {{ 'queue.poll-interval-min-value' | translate }} + + + + queue.partitions + + + {{ 'queue.partitions-required' | translate }} + + + {{ 'queue.partitions-min-value' | translate }} + + + +
{{ 'queue.consumer-per-partition' | translate }}
+
{{'queue.consumer-per-partition-hint' | translate}}
+
+ + queue.processing-timeout + + + {{ 'queue.pack-processing-timeout-required' | translate }} + + + {{ 'queue.pack-processing-timeout-min-value' | translate }} + + + + + + + queue.submit-strategy + + + +
+ + queue.submit-strategy + + + {{ strategy }} + + + + {{ 'queue.submit-strategy-type-required' | translate }} + + + + queue.batch-size + + + {{ 'queue.batch-size-required' | translate }} + + + {{ 'queue.batch-size-min-value' | translate }} + + +
+
+
+ + + + queue.processing-strategy + + + +
+ + queue.processing-strategy + + + {{ strategy }} + + + + {{ 'queue.processing-strategy-type-required' | translate }} + + + + queue.retries + + + {{ 'queue.retries-required' | translate }} + + + {{ 'queue.retries-min-value' | translate }} + + + + queue.failure-percentage + + + {{ 'queue.failure-percentage-required' | translate }} + + + {{ 'queue.failure-percentage-min-value' | translate }} + + + {{ 'queue.failure-percentage-max-value' | translate }} + + + + queue.pause-between-retries + + + {{ 'queue.pause-between-retries-required' | translate }} + + + {{ 'queue.pause-between-retries-min-value' | translate }} + + + + queue.max-pause-between-retries + + + {{ 'queue.max-pause-between-retries-required' | translate }} + + + {{ 'queue.max-pause-between-retries-min-value' | translate }} + + +
+
+
+
+
diff --git a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queue.component.scss b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.scss similarity index 100% rename from ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queue.component.scss rename to ui-ngx/src/app/modules/home/components/queue/queue-form.component.scss diff --git a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queue.component.ts b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts similarity index 78% rename from ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queue.component.ts rename to ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts index 7eb0062293..c3d4b1273a 100644 --- a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queue.component.ts +++ b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core'; +import { Component, forwardRef, Input, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, @@ -25,46 +25,40 @@ import { Validator, Validators } from '@angular/forms'; -import { DeviceProfileAlarm } from '@shared/models/device.models'; import { MatDialog } from '@angular/material/dialog'; import { UtilsService } from '@core/services/utils.service'; -import { QueueProcessingStrategyTypes, QueueSubmitStrategyTypes } from '@shared/models/queue.models'; +import { QueueInfo, QueueProcessingStrategyTypes, QueueSubmitStrategyTypes } from '@shared/models/queue.models'; +import { isDefinedAndNotNull } from '@core/utils'; @Component({ - selector: 'tb-tenant-profile-queue', - templateUrl: './tenant-profile-queue.component.html', - styleUrls: ['./tenant-profile-queue.component.scss'], + selector: 'tb-queue-form', + templateUrl: './queue-form.component.html', + styleUrls: ['./queue-form.component.scss'], providers: [ { provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TenantProfileQueueComponent), + useExisting: forwardRef(() => QueueFormComponent), multi: true }, { provide: NG_VALIDATORS, - useExisting: forwardRef(() => TenantProfileQueueComponent), + useExisting: forwardRef(() => QueueFormComponent), multi: true, } ] }) -export class TenantProfileQueueComponent implements ControlValueAccessor, OnInit, Validator { +export class QueueFormComponent implements ControlValueAccessor, OnInit, Validator { @Input() disabled: boolean; - @Output() - removeQueue = new EventEmitter(); - @Input() - expanded = false; + newQueue = false; @Input() - mainQueue = false; + systemQueue = false; - @Input() - newQueue = false; - - private modelValue: DeviceProfileAlarm; + private modelValue: QueueInfo; queueFormGroup: FormGroup; @@ -106,7 +100,7 @@ export class TenantProfileQueueComponent implements ControlValueAccessor, OnInit packProcessingTimeout: [2000, [Validators.min(1), Validators.required]], submitStrategy: this.fb.group({ type: [null, [Validators.required]], - batchSize: [0, [Validators.min(1), Validators.required]], + batchSize: [null], }), processingStrategy: this.fb.group({ type: [null, [Validators.required]], @@ -141,20 +135,20 @@ export class TenantProfileQueueComponent implements ControlValueAccessor, OnInit } } - writeValue(value: DeviceProfileAlarm): void { + writeValue(value: QueueInfo): void { this.propagateChangePending = false; this.modelValue = value; - if (!this.modelValue.alarmType) { - this.expanded = true; + if (isDefinedAndNotNull(this.modelValue)) { + this.queueFormGroup.patchValue(this.modelValue, {emitEvent: false}); } - this.queueFormGroup.reset(this.modelValue || undefined, {emitEvent: false}); + this.submitStrategyTypeChanged(); if (!this.disabled && !this.queueFormGroup.valid) { this.updateModel(); } } public validate(c: FormControl) { - if (c.parent) { + if (c.parent && !this.systemQueue) { const queueName = c.value.name; const profileQueues = []; c.parent.getRawValue().forEach((queue) => { @@ -174,11 +168,6 @@ export class TenantProfileQueueComponent implements ControlValueAccessor, OnInit }; } - get queueTitle(): string { - const queueName = this.queueFormGroup.get('name').value; - return this.utils.customTranslation(queueName, queueName); - } - private updateModel() { const value = this.queueFormGroup.value; this.modelValue = {...this.modelValue, ...value}; @@ -194,12 +183,14 @@ export class TenantProfileQueueComponent implements ControlValueAccessor, OnInit const type: QueueSubmitStrategyTypes = form.get('type').value; const batchSizeField = form.get('batchSize'); if (type === QueueSubmitStrategyTypes.BATCH) { - batchSizeField.enable(); - batchSizeField.patchValue(1000); + batchSizeField.enable({emitEvent: false}); + batchSizeField.patchValue(1000, {emitEvent: false}); + batchSizeField.setValidators([Validators.min(1), Validators.required]); this.hideBatchSize = true; } else { - batchSizeField.patchValue(null); - batchSizeField.disable(); + batchSizeField.patchValue(null, {emitEvent: false}); + batchSizeField.disable({emitEvent: false}); + batchSizeField.clearValidators(); this.hideBatchSize = false; } } diff --git a/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts b/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts index 1f1a5266ba..b886fe5711 100644 --- a/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.ts @@ -49,7 +49,7 @@ import { MediaBreakpoints } from '@shared/models/constants'; import { RuleChainId } from '@shared/models/id/rule-chain-id'; import { ServiceType } from '@shared/models/queue.models'; import { deepTrim } from '@core/utils'; -import { QueueId } from "@shared/models/id/queue-id"; +import { QueueId } from '@shared/models/id/queue-id'; @Component({ selector: 'tb-device-wizard', diff --git a/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts b/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts index 3f8b26f105..e5252f915f 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts @@ -187,19 +187,41 @@ const routes: Routes = [ }, { path: 'queues', - component: EntitiesTableComponent, - canDeactivate: [ConfirmOnExitGuard], data: { - auth: [Authority.SYS_ADMIN], - title: 'admin.queues', breadcrumb: { label: 'admin.queues', icon: 'swap_calls' } }, - resolve: { - entitiesTableConfig: QueuesTableConfigResolver - } + children: [ + { + path: '', + component: EntitiesTableComponent, + data: { + auth: [Authority.SYS_ADMIN], + title: 'admin.queues' + }, + resolve: { + entitiesTableConfig: QueuesTableConfigResolver + } + }, + { + path: ':entityId', + component: EntityDetailsPageComponent, + canDeactivate: [ConfirmOnExitGuard], + data: { + breadcrumb: { + labelFunction: entityDetailsPageBreadcrumbLabelFunction, + icon: 'swap_calls' + } as BreadCrumbConfig, + auth: [Authority.SYS_ADMIN], + title: 'admin.queues' + }, + resolve: { + entitiesTableConfig: QueuesTableConfigResolver + } + } + ] } ] } diff --git a/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.html b/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.html index 9d7b9ead45..0432f99966 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.html +++ b/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.html @@ -16,170 +16,33 @@ -->
+ +
+ +
- -
-
-
- - admin.queue-name - - - {{ 'queue.name-required' | translate }} - - - - queue.poll-interval - - - {{ 'queue.poll-interval-required' | translate }} - - - {{ 'queue.poll-interval-min-value' | translate }} - - - - queue.partitions - - - {{ 'queue.partitions-required' | translate }} - - - {{ 'queue.partitions-min-value' | translate }} - - - - -
{{ 'queue.consumer-per-partition' | translate }}
-
{{'queue.consumer-per-partition-hint' | translate}}
-
- - - queue.processing-timeout - - - {{ 'queue.pack-processing-timeout-required' | translate }} - - - {{ 'queue.pack-processing-timeout-min-value' | translate }} - - - - - - - queue.submit-strategy - - - -
- - queue.submit-strategy - - - {{ strategy }} - - - - {{ 'queue.submit-strategy-type-required' | translate }} - - - - queue.batch-size - - - {{ 'queue.batch-size-required' | translate }} - - - {{ 'queue.batch-size-min-value' | translate }} - - -
-
-
- - - - queue.processing-strategy - - - -
- - queue.processing-strategy - - - {{ strategy }} - - - - {{ 'queue.processing-strategy-type-required' | translate }} - - - - queue.retries - - - {{ 'queue.retries-required' | translate }} - - - {{ 'queue.retries-min-value' | translate }} - - - - queue.failure-percentage - - - {{ 'queue.failure-percentage-required' | translate }} - - - {{ 'queue.failure-percentage-min-value' | translate }} - - - {{ 'queue.failure-percentage-max-value' | translate }} - - - - queue.pause-between-retries - - - {{ 'queue.pause-between-retries-required' | translate }} - - - {{ 'queue.pause-between-retries-min-value' | translate }} - - - - queue.max-pause-between-retries - - - {{ 'queue.max-pause-between-retries-required' | translate }} - - - {{ 'queue.max-pause-between-retries-min-value' | translate }} - - -
-
-
-
-
-
+
+ +
diff --git a/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.scss b/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.scss deleted file mode 100644 index c87504819e..0000000000 --- a/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.scss +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright © 2016-2022 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -:host ::ng-deep { - .queue-form { - .mat-expansion-panel-body { - padding-bottom: 0 !important; - } - } -} diff --git a/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.ts b/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.ts index f436264793..d2fbaa1b77 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/queue/queue.component.ts @@ -16,18 +16,19 @@ import { ChangeDetectorRef, Component, Inject } from '@angular/core'; import { EntityType } from '@shared/models/entity-type.models'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup } from '@angular/forms'; import { EntityComponent } from '@home/components/entity/entity.component'; -import { QueueInfo, QueueProcessingStrategyTypes, QueueSubmitStrategyTypes } from '@shared/models/queue.models'; +import { QueueInfo } from '@shared/models/queue.models'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { TranslateService } from '@ngx-translate/core'; import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; +import { ActionNotificationShow } from '@core/notification/notification.actions'; @Component({ selector: 'tb-queue', templateUrl: './queue.component.html', - styleUrls: ['./queue.component.scss'] + styleUrls: [] }) export class QueueComponent extends EntityComponent { entityForm: FormGroup; @@ -36,9 +37,6 @@ export class QueueComponent extends EntityComponent { submitStrategies: string[] = []; processingStrategies: string[] = []; - QueueSubmitStrategyTypes = QueueSubmitStrategyTypes; - hideBatchSize = false; - constructor(protected store: Store, protected translate: TranslateService, @Inject('entity') protected entityValue: QueueInfo, @@ -46,62 +44,16 @@ export class QueueComponent extends EntityComponent { protected cd: ChangeDetectorRef, public fb: FormBuilder) { super(store, fb, entityValue, entitiesTableConfigValue, cd); - this.submitStrategies = Object.values(QueueSubmitStrategyTypes); - this.processingStrategies = Object.values(QueueProcessingStrategyTypes); } ngOnInit() { super.ngOnInit(); - this.entityForm.get('submitStrategy').get('type').valueChanges.subscribe(() => { - this.submitStrategyTypeChanged(); - }); } buildForm(entity: QueueInfo): FormGroup { - return this.fb.group( - { - name: [entity ? entity.name : '', [Validators.required]], - pollInterval: [ - entity && entity.pollInterval ? entity.pollInterval : 25, - [Validators.min(1), Validators.required] - ], - partitions: [ - entity && entity.partitions ? entity.partitions : 10, - [Validators.min(1), Validators.required] - ], - consumerPerPartition: [entity ? entity.consumerPerPartition : false, []], - packProcessingTimeout: [ - entity && entity.packProcessingTimeout ? entity.packProcessingTimeout : 2000, - [Validators.min(1), Validators.required] - ], - submitStrategy: this.fb.group({ - type: [entity ? entity.submitStrategy?.type : null, [Validators.required]], - batchSize: [ - entity && entity.submitStrategy?.batchSize ? entity.submitStrategy?.batchSize : 1000, - [Validators.min(1), Validators.required] - ], - }), - processingStrategy: this.fb.group({ - type: [entity ? entity.processingStrategy?.type : null, [Validators.required]], - retries: [ - entity && entity.processingStrategy?.retries ? entity.processingStrategy?.retries : 3, - [Validators.min(0), Validators.required] - ], - failurePercentage: [ - entity && entity.processingStrategy?.failurePercentage ? entity.processingStrategy?.failurePercentage : 0, - [Validators.min(0), Validators.required, Validators.max(100)] - ], - pauseBetweenRetries: [ - entity && entity.processingStrategy?.pauseBetweenRetries ? entity.processingStrategy?.pauseBetweenRetries : 3, - [Validators.min(1), Validators.required] - ], - maxPauseBetweenRetries: [ - entity && entity.processingStrategy?.maxPauseBetweenRetries ? entity.processingStrategy?.maxPauseBetweenRetries : 3, - [Validators.min(1), Validators.required] - ], - }) - } - ); + return this.fb.group({ + queue: [entity] + }); } hideDelete() { @@ -114,41 +66,22 @@ export class QueueComponent extends EntityComponent { updateForm(entity: QueueInfo) { this.entityForm.patchValue({ - name: entity.name, - pollInterval: entity.pollInterval, - partitions: entity.partitions, - consumerPerPartition: entity.consumerPerPartition, - packProcessingTimeout: entity.packProcessingTimeout, - submitStrategy: { - type: entity.submitStrategy?.type, - batchSize: entity.submitStrategy?.batchSize, - }, - processingStrategy: { - type: entity.processingStrategy?.type, - retries: entity.processingStrategy?.retries, - failurePercentage: entity.processingStrategy?.failurePercentage, - pauseBetweenRetries: entity.processingStrategy?.pauseBetweenRetries, - maxPauseBetweenRetries: entity.processingStrategy?.maxPauseBetweenRetries, - } - }, {emitEvent: true}); + queue: entity + }, {emitEvent: false}); + } - if (!this.isAdd) { - this.entityForm.get('name').disable({emitEvent: false}); - } + prepareFormValue(formValue: any) { + return super.prepareFormValue(formValue.queue); } - submitStrategyTypeChanged() { - const form = this.entityForm.get('submitStrategy') as FormGroup; - const type: QueueSubmitStrategyTypes = form.get('type').value; - const batchSizeField = form.get('batchSize'); - if (type === QueueSubmitStrategyTypes.BATCH) { - batchSizeField.enable(); - batchSizeField.patchValue(1000); - this.hideBatchSize = true; - } else { - batchSizeField.patchValue(null); - batchSizeField.disable(); - this.hideBatchSize = false; - } + onQueueIdCopied($event) { + this.store.dispatch(new ActionNotificationShow( + { + message: this.translate.instant('queue.idCopiedMessage'), + type: 'success', + duration: 750, + verticalPosition: 'bottom', + horizontalPosition: 'right' + })); } } diff --git a/ui-ngx/src/app/modules/home/pages/admin/queue/queues-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/admin/queue/queues-table-config.resolver.ts index aaaac2168f..5af2735a49 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/queue/queues-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/queue/queues-table-config.resolver.ts @@ -15,11 +15,8 @@ /// import { Injectable } from '@angular/core'; -import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; -import { - EntityTableColumn, - EntityTableConfig -} from '@home/models/entity/entities-table-config.models'; +import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router'; +import { EntityTableColumn, EntityTableConfig } from '@home/models/entity/entities-table-config.models'; import { QueueInfo, ServiceType } from '@shared/models/queue.models'; import { select, Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @@ -34,6 +31,7 @@ import { TranslateService } from '@ngx-translate/core'; import { QueueComponent } from './queue.component'; import { QueueService } from '@core/http/queue.service'; import { selectAuthUser } from '@core/auth/auth.selectors'; +import { EntityAction } from '@home/models/entity/entity-component.models'; @Injectable() export class QueuesTableConfigResolver implements Resolve> { @@ -48,6 +46,7 @@ export class QueuesTableConfigResolver implements Resolve this.translate.instant('queue.delete-queue-text'); this.config.deleteEntitiesTitle = count => this.translate.instant('queue.delete-queues-title', {count}); this.config.deleteEntitiesContent = () => this.translate.instant('queue.delete-queues-text'); + + this.config.onEntityAction = action => this.onQueueAction(action); } resolve(route: ActivatedRouteSnapshot): Observable> { @@ -100,16 +101,28 @@ export class QueuesTableConfigResolver implements Resolve this.queueService.getTenantQueuesByServiceType(pageLink, this.queueType); this.config.loadEntity = id => this.queueService.getQueueById(id.id); - this.config.saveEntity = queue => this.queueService.saveQueue(this.addTopicForQueue(queue), this.queueType).pipe( + this.config.saveEntity = queue => this.queueService.saveQueue(queue, this.queueType).pipe( mergeMap((savedQueue) => this.queueService.getQueueById(savedQueue.id.id) )); this.config.deleteEntity = id => this.queueService.deleteQueue(id.id); this.config.deleteEnabled = (queue) => queue && queue.name !== 'Main'; + this.config.entitySelectionEnabled = (queue) => queue && queue.name !== 'Main'; + } + + onQueueAction(action: EntityAction): boolean { + switch (action.action) { + case 'open': + this.openQueue(action.event, action.entity); + return true; + } + return false; } - private addTopicForQueue(queue: QueueInfo): QueueInfo { - const modifiedQueue = Object.assign({}, queue); - modifiedQueue.topic = `tb_rule_engine.${queue.name}`; - return modifiedQueue; + private openQueue($event: Event, queue) { + if ($event) { + $event.stopPropagation(); + } + const url = this.router.createUrlTree(['settings', 'queues', queue.id.id]); + this.router.navigateByUrl(url); } } diff --git a/ui-ngx/src/app/shared/components/queue/queue-autocomplete.component.html b/ui-ngx/src/app/shared/components/queue/queue-autocomplete.component.html index db9e899f1b..b991556b78 100644 --- a/ui-ngx/src/app/shared/components/queue/queue-autocomplete.component.html +++ b/ui-ngx/src/app/shared/components/queue/queue-autocomplete.component.html @@ -42,7 +42,7 @@ {{ translate.get('queue.no-queues-matching', - {entity: truncate.transform(searchText, true, 6, '...')}) | async }} + {queue: truncate.transform(searchText, true, 6, '...')}) | async }}
diff --git a/ui-ngx/src/app/shared/components/queue/queue-autocomplete.component.ts b/ui-ngx/src/app/shared/components/queue/queue-autocomplete.component.ts index 28f40425ea..131e99d6e9 100644 --- a/ui-ngx/src/app/shared/components/queue/queue-autocomplete.component.ts +++ b/ui-ngx/src/app/shared/components/queue/queue-autocomplete.component.ts @@ -27,11 +27,11 @@ import { EntityType } from '@shared/models/entity-type.models'; import { BaseData } from '@shared/models/base-data'; import { EntityService } from '@core/http/entity.service'; import { TruncatePipe } from '@shared/pipe/truncate.pipe'; -import {QueueInfo, ServiceType} from "@shared/models/queue.models"; -import { QueueService } from "@core/http/queue.service"; -import { PageLink } from "@shared/models/page/page-link"; -import { Direction } from "@shared/models/page/sort-order"; -import { emptyPageData } from "@shared/models/page/page-data"; +import { QueueInfo, ServiceType } from '@shared/models/queue.models'; +import { QueueService } from '@core/http/queue.service'; +import { PageLink } from '@shared/models/page/page-link'; +import { Direction } from '@shared/models/page/sort-order'; +import { emptyPageData } from '@shared/models/page/page-data'; @Component({ selector: 'tb-queue-autocomplete', diff --git a/ui-ngx/src/app/shared/models/device.models.ts b/ui-ngx/src/app/shared/models/device.models.ts index c90af9df6a..df28c3bcfc 100644 --- a/ui-ngx/src/app/shared/models/device.models.ts +++ b/ui-ngx/src/app/shared/models/device.models.ts @@ -29,7 +29,7 @@ import * as _moment from 'moment'; import { AbstractControl, ValidationErrors } from '@angular/forms'; import { OtaPackageId } from '@shared/models/id/ota-package-id'; import { DashboardId } from '@shared/models/id/dashboard-id'; -import { QueueId } from "@shared/models/id/queue-id"; +import { QueueId } from '@shared/models/id/queue-id'; import { DataType } from '@shared/models/constants'; import { getDefaultProfileClientLwM2mSettingsConfig, diff --git a/ui-ngx/src/app/shared/models/entity-type.models.ts b/ui-ngx/src/app/shared/models/entity-type.models.ts index 9c97cdaa82..c92c2c43db 100644 --- a/ui-ngx/src/app/shared/models/entity-type.models.ts +++ b/ui-ngx/src/app/shared/models/entity-type.models.ts @@ -428,7 +428,8 @@ export const baseDetailsPageByEntityType = new Map([ [EntityType.EDGE, '/edgeInstances'], [EntityType.ENTITY_VIEW, '/entityViews'], [EntityType.TB_RESOURCE, '/settings/resources-library'], - [EntityType.OTA_PACKAGE, '/otaUpdates'] + [EntityType.OTA_PACKAGE, '/otaUpdates'], + [EntityType.QUEUE, '/settings/queues'] ]); export interface EntitySubtype { diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 880778d6c4..5c73d7a017 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -2719,13 +2719,15 @@ "partitions": "Partitions", "consumer-per-partition": "Consumer per partition", "consumer-per-partition-hint": "Enable separate consumer(s) per each partition", - "processing-timeout": "Processing timeout", + "processing-timeout": "Processing timeout, ms", "batch-size": "Batch size", "retries": "Retries (0 - unlimited)", "failure-percentage": "Failure Percentage", "pause-between-retries": "Pause between retries", "max-pause-between-retries": "Maximal pause between retries", - "delete": "Delete queue" + "delete": "Delete queue", + "copyId": "Copy queue Id", + "idCopiedMessage": "Queue Id has been copied to clipboard" }, "tenant": { "tenant": "Tenant",