From 6b5e33992182b0825b3dd145f545e4851910b224 Mon Sep 17 00:00:00 2001 From: ArtemDzhereleiko Date: Fri, 3 Oct 2025 16:21:03 +0300 Subject: [PATCH 1/3] UI: fixed and improve geofencing cf --- .../calculated-field-dialog.component.html | 8 +- .../calculated-field-dialog.component.ts | 19 ++ ...-geofencing-zone-groups-table.component.ts | 2 +- ...eofencing-zone-groups-panel.component.html | 168 +++++++++++------- ...eofencing-zone-groups-panel.component.scss | 25 +++ ...-geofencing-zone-groups-panel.component.ts | 79 ++++++-- .../shared/models/calculated-field.models.ts | 14 +- .../assets/locale/locale.constant-en_US.json | 27 ++- 8 files changed, 250 insertions(+), 92 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html index 4b12d9f31a..e235b66fa7 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html @@ -160,12 +160,16 @@ [tenantId]="data.tenantId" [entityName]="data.entityName"/>
-
{{ 'calculated-fields.zone-group-refresh-interval' | translate }}
+ +
+ {{ 'calculated-fields.zone-group-refresh-interval' | translate }} +
+
diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts index 3037b3a4ce..8cca16d4ef 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts @@ -81,6 +81,7 @@ export class CalculatedFieldDialogComponent extends DialogComponent + this.checkScheduledUpdateEnabled(value) + ); + this.checkScheduledUpdateEnabled(this.configFormGroup.get('scheduledUpdateEnabled').value); + } + + private checkScheduledUpdateEnabled(value: boolean) { + if (value) { + this.configFormGroup.get('scheduledUpdateInterval').enable({emitEvent: false}); + } else { + this.configFormGroup.get('scheduledUpdateInterval').disable({emitEvent: false}); + } + } + private checkRelatedEntity(zoneGroups: CalculatedFieldGeofencing) { this.isRelatedEntity = Object.values(zoneGroups).some(zone => zone.refDynamicSourceConfiguration?.type === ArgumentEntityType.RelationQuery); } diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/geofencing-zone-grups-table/calculated-field-geofencing-zone-groups-table.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/geofencing-zone-grups-table/calculated-field-geofencing-zone-groups-table.component.ts index a11ae4cea5..9d2a124d68 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/geofencing-zone-grups-table/calculated-field-geofencing-zone-groups-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/geofencing-zone-grups-table/calculated-field-geofencing-zone-groups-table.component.ts @@ -168,7 +168,7 @@ export class CalculatedFieldGeofencingZoneGroupsTableComponent implements Contro renderer: this.renderer, componentType: CalculatedFieldGeofencingZoneGroupsPanelComponent, hostView: this.viewContainerRef, - preferredPlacement: isExists ? ['left', 'leftTop', 'leftBottom'] : ['topRight', 'right', 'rightTop'], + preferredPlacement: 'right', context: ctx, isModal: true }); diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.html index a660158ab9..1c57cfbc02 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.html @@ -80,12 +80,13 @@ @if (ArgumentEntityTypeParamsMap.has(entityType)) {
{{ ArgumentEntityTypeParamsMap.get(entityType).title | translate }}
-
@@ -94,76 +95,115 @@
- {{ 'calculated-fields.relation-query' | translate }}* - -
-
{{ 'calculated-fields.direction' | translate }}
- - - @for (direction of GeofencingDirectionList; track direction) { - {{ GeofencingDirectionTranslations.get(direction) | translate }} + {{ 'calculated-fields.entity-zone-relationship' | translate }} +
+
+
calculated-fields.level
+
calculated-fields.direction-level
+
calculated-fields.relation-type
+
+
+ @if (levelsFormArray()?.controls?.length) { +
+ @for (keyControl of levelsFormArray().controls; track trackByKey;) { +
+
+
{{ $index+1 }}
+ + + @for (direction of GeofencingDirectionList; track direction) { + {{ GeofencingDirectionLevelTranslations.get(direction) | translate }} + } + + + + +
+
+ + +
+
} - - +
+ } @else { + {{ 'calculated-fields.no-level' | translate }} + } + @if (levelsFormArray().errors) { + + }
-
-
{{ 'calculated-fields.relation-type' | translate }}
- - -
-
-
{{ 'calculated-fields.relation-level' | translate }}
- - - @if (refDynamicSourceFormGroup.get('maxLevel').touched && refDynamicSourceFormGroup.get('maxLevel').hasError('required')) { - - warning - - } @else if (refDynamicSourceFormGroup.get('maxLevel').touched && refDynamicSourceFormGroup.get('maxLevel').hasError('min')) { - - warning - - } @else if (refDynamicSourceFormGroup.get('maxLevel').touched && refDynamicSourceFormGroup.get('maxLevel').hasError('max')) { - - warning - - } - -
-
- - {{ 'calculated-fields.fetch-last-available-level' | translate }} - +
+ @if (maxRelationLevelPerCfArgument && levelsFormArray().length >= maxRelationLevelPerCfArgument) { +
+ warning + {{ 'calculated-fields.max-allowed-levels-error' | translate }} +
+ } @else { + + }
-
-
- {{ 'calculated-fields.perimeter-attribute-key' | translate }} + @if (entityFilter.singleEntity.id) { +
+
+ {{ 'calculated-fields.perimeter-attribute-key' | translate }} +
+ @if (entityType === ArgumentEntityType.RelationQuery) { + + + @if (geofencingFormGroup.get('perimeterKeyName').touched && geofencingFormGroup.get('perimeterKeyName').hasError('required')) { + + warning + + } @else if (geofencingFormGroup.get('perimeterKeyName').touched && geofencingFormGroup.get('perimeterKeyName').hasError('pattern')) { + + warning + + } + + } @else { + + }
- -
+ }
{{ 'calculated-fields.report-strategy' | translate }}
diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.scss b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.scss index bedaf2eeb0..ff6140f12c 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.scss @@ -29,6 +29,26 @@ $panel-width: 520px; } } + .level-text { + width: 25px; + color: rgba(0, 0, 0, 0.54); + } + + .tb-form-table { + .tb-form-row { + gap: 12px; + } + .tb-form-table-body { + gap: unset; + } + } + .tb-form-table-header-cell { + &.tb-actions-header { + width: 80px; + min-width: 80px; + } + } + .limit-field-row { @media screen and (max-width: $panel-width) { display: flex; @@ -48,4 +68,9 @@ $panel-width: 520px; flex-direction: column; } } + tb-entity-autocomplete { + .mat-mdc-form-field-has-icon-suffix .mat-mdc-text-field-wrapper { + padding-right: 0 !important; + } + } } diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.ts index 72ea58919f..8e5921516e 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.ts @@ -16,7 +16,15 @@ import { AfterViewInit, ChangeDetectorRef, Component, Input, OnInit, output, ViewChild } from '@angular/core'; import { TbPopoverComponent } from '@shared/components/popover.component'; -import { FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; +import { + AbstractControl, + FormBuilder, + FormControl, + FormGroup, + UntypedFormArray, + ValidatorFn, + Validators +} from '@angular/forms'; import { charsWithNumRegex, oneSpaceInsideRegex } from '@shared/models/regex.constants'; import { ArgumentEntityType, @@ -25,14 +33,15 @@ import { CalculatedFieldGeofencing, CalculatedFieldGeofencingValue, CalculatedFieldType, + GeofencingDirectionLevelTranslations, GeofencingDirectionTranslations, GeofencingReportStrategy, GeofencingReportStrategyTranslations, getCalculatedFieldCurrentEntityFilter } from '@shared/models/calculated-field.models'; -import { debounceTime, delay, distinctUntilChanged, filter, map } from 'rxjs/operators'; +import { debounceTime, delay, distinctUntilChanged, map } from 'rxjs/operators'; import { EntityType } from '@shared/models/entity-type.models'; -import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; +import { AttributeScope, DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { EntityId } from '@shared/models/id/entity-id'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { EntityFilter } from '@shared/models/query/query.models'; @@ -44,6 +53,7 @@ import { Store } from '@ngrx/store'; import { EntityAutocompleteComponent } from '@shared/components/entity/entity-autocomplete.component'; import { NULL_UUID } from '@shared/models/id/has-uuid'; import { EntitySearchDirection } from '@shared/models/relation.models'; +import { CdkDragDrop } from "@angular/cdk/drag-drop"; @Component({ selector: 'tb-calculated-field-geofencing-zone-groups-panel', @@ -73,12 +83,9 @@ export class CalculatedFieldGeofencingZoneGroupsPanelComponent implements OnInit id: [''] }), refDynamicSourceConfiguration: this.fb.group({ - direction: [EntitySearchDirection.TO], - relationType: ['', [Validators.required]], - maxLevel: [1, [Validators.required, Validators.min(1), Validators.max(this.maxRelationLevelPerCfArgument)]], - fetchLastLevelOnly: [false], + levels: this.fb.array([], [this.levelsRequired()]) }), - perimeterKeyName: ['', [Validators.pattern(oneSpaceInsideRegex)]], + perimeterKeyName: ['', [Validators.required, Validators.pattern(oneSpaceInsideRegex)]], reportStrategy: [GeofencingReportStrategy.REPORT_TRANSITION_EVENTS_AND_PRESENCE_STATUS], createRelationsWithMatchedZones: [false], direction: [EntitySearchDirection.TO], @@ -97,6 +104,8 @@ export class CalculatedFieldGeofencingZoneGroupsPanelComponent implements OnInit readonly GeofencingReportStrategyTranslations = GeofencingReportStrategyTranslations; readonly GeofencingDirectionList = Object.values(EntitySearchDirection) as Array; readonly GeofencingDirectionTranslations = GeofencingDirectionTranslations; + readonly GeofencingDirectionLevelTranslations = GeofencingDirectionLevelTranslations; + readonly AttributeScope = AttributeScope; private currentEntityFilter: EntityFilter; @@ -107,7 +116,6 @@ export class CalculatedFieldGeofencingZoneGroupsPanelComponent implements OnInit private store: Store ) { - this.observeMaxLevelChanges(); this.observeEntityFilterChanges(); this.observeEntityTypeChanges(); this.observeUpdatePosition(); @@ -131,7 +139,16 @@ export class CalculatedFieldGeofencingZoneGroupsPanelComponent implements OnInit if (this.zone.refDynamicSourceConfiguration?.type) { this.refEntityIdFormGroup.get('entityType').setValue(this.zone.refDynamicSourceConfiguration.type, {emitEvent: false}); } - this.validateFetchLastLevelOnly(this.zone?.refDynamicSourceConfiguration?.maxLevel); + if (this.zone?.refDynamicSourceConfiguration?.levels?.length > 0) { + this.zone.refDynamicSourceConfiguration.levels.forEach(level => { + this.levelsFormArray().push(this.fb.group({ + direction: [level.direction], + relationType: [level.relationType, [Validators.required]] + })); + }) + } else { + this.addKey(); + } this.validateDirectionAndRelationType(this.zone?.createRelationsWithMatchedZones); this.validateRefDynamicSourceConfiguration(this.zone?.refEntityId?.entityType || this.zone?.refDynamicSourceConfiguration?.type); @@ -241,17 +258,19 @@ export class CalculatedFieldGeofencingZoneGroupsPanelComponent implements OnInit private observeEntityFilterChanges(): void { merge( this.refEntityIdFormGroup.get('entityType').valueChanges, - this.refEntityIdFormGroup.get('id').valueChanges.pipe(filter(Boolean)), + this.refEntityIdFormGroup.get('id').valueChanges, ) .pipe(debounceTime(50), takeUntilDestroyed()) .subscribe(() => this.updateEntityFilter(this.entityType)); + + this.refEntityIdFormGroup.get('id').valueChanges.pipe(distinctUntilChanged(), takeUntilDestroyed()).subscribe(() => this.geofencingFormGroup.get('perimeterKeyName').reset('')); } private observeEntityTypeChanges(): void { this.refEntityIdFormGroup.get('entityType').valueChanges .pipe(distinctUntilChanged(), takeUntilDestroyed()) .subscribe(type => { - this.geofencingFormGroup.get('refEntityId').get('id').setValue(''); + this.geofencingFormGroup.get('refEntityId').get('id').setValue(null); const isEntityWithId = type !== ArgumentEntityType.Tenant && type !== ArgumentEntityType.Current && type !== ArgumentEntityType.RelationQuery; this.geofencingFormGroup.get('refEntityId') .get('id')[isEntityWithId ? 'enable' : 'disable'](); @@ -271,6 +290,12 @@ export class CalculatedFieldGeofencingZoneGroupsPanelComponent implements OnInit }; } + private levelsRequired(): ValidatorFn { + return (control: FormControl) => { + return control.value.length ? null : { levelsRequired: true }; + }; + } + private forbiddenNameValidator(): ValidatorFn { return (control: FormControl) => { const trimmedValue = control.value.trim().toLowerCase(); @@ -282,10 +307,40 @@ export class CalculatedFieldGeofencingZoneGroupsPanelComponent implements OnInit private observeUpdatePosition(): void { merge( this.refEntityIdFormGroup.get('entityType').valueChanges, + this.refEntityIdFormGroup.get('id').valueChanges, this.geofencingFormGroup.get('createRelationsWithMatchedZones').valueChanges ) .pipe(delay(50), takeUntilDestroyed()) .subscribe(() => this.popover.updatePosition()); } + levelsFormArray(): UntypedFormArray { + return this.refDynamicSourceFormGroup.get('levels') as UntypedFormArray; + } + + trackByKey(index: number, keyControl: AbstractControl): any { + return keyControl; + } + + removeKey(index: number) { + this.levelsFormArray().removeAt(index); + } + + addKey() { + this.levelsFormArray().push(this.fb.group({ + direction: [EntitySearchDirection.TO], + relationType: ['', [Validators.required]] + })); + } + + keyDrop(event: CdkDragDrop) { + const keysArray = this.levelsFormArray(); + const key = keysArray.at(event.previousIndex); + keysArray.removeAt(event.previousIndex); + keysArray.insert(event.currentIndex, key); + } + + get dragEnabled(): boolean { + return this.levelsFormArray().controls.length > 1; + } } diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts index a86943c86e..841baea168 100644 --- a/ui-ngx/src/app/shared/models/calculated-field.models.ts +++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts @@ -73,7 +73,7 @@ export enum ArgumentEntityType { Asset = 'ASSET', Customer = 'CUSTOMER', Tenant = 'TENANT', - RelationQuery = 'RELATION_QUERY', + RelationQuery = 'RELATION_PATH_QUERY', } export const ArgumentEntityTypeTranslations = new Map( @@ -108,6 +108,13 @@ export const GeofencingDirectionTranslations = new Map( + [ + [EntitySearchDirection.FROM, 'calculated-fields.direction-down'], + [EntitySearchDirection.TO, 'calculated-fields.direction-up'], + ] +) + export enum ArgumentType { Attribute = 'ATTRIBUTE', LatestTelemetry = 'TS_LATEST', @@ -167,10 +174,7 @@ export interface CalculatedFieldGeofencing { export interface RefDynamicSourceConfiguration { type?: ArgumentEntityType.RelationQuery; - direction: EntitySearchDirection; - relationType: string; - maxLevel: number; - fetchLastLevelOnly?: boolean; + levels?: Array<{direction: EntitySearchDirection; relationType: string;}>; } export interface CalculatedFieldGeofencingValue extends CalculatedFieldGeofencing { 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 1866ab7d0b..c56d08701c 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1122,17 +1122,28 @@ "report-presence-status-only": "Presence status only", "report-transition-event-and-presence": "Presence status and transition events", "perimeter-attribute-key": "Perimeter attribute key", - "relation-query": "Relations query", - "direction": "Direction", - "direction-from": "From source entity", - "direction-to": "To source entity", + "perimeter-attribute-key-required": "Perimeter attribute key is required.", + "perimeter-attribute-key-pattern": "Perimeter attribute key is invalid.", + "entity-zone-relationship": "Path from Entity to Zones *", + "direction": "Relation direction", + "direction-from": "From entity to zone", + "direction-to": "From zone to entity", "relation-type": "Relation type", - "create-relation-with-matched-zones": "Create relations with matched zones", + "create-relation-with-matched-zones": "Create relations for source entity with matched zones", "relation-level": "Relation level", "fetch-last-available-level": "Fetch last available level only", "zone-group-refresh-interval": "Zone groups refresh interval", "copy-zone-group-name": "Copy zone group name", "open-details-page": "Open entity details page", + "level": "Level", + "direction-level": "Direction", + "direction-up": "Up", + "direction-down": "Down", + "add-level": "Add level", + "delete-level": "Delete level", + "no-level": "No level configured", + "levels-required": "At least one level must be configured.", + "max-allowed-levels-error": "Relation level exceeds the maximum allowed.", "hint": { "arguments-simple-with-rolling": "Simple type calculated field should not contain keys with time series rolling type.", "arguments-empty": "Arguments should not be empty.", @@ -1158,7 +1169,7 @@ "entity-coordinates": "Specify the time series keys that provide entity GPS coordinates (latitude and longitude).", "geofencing-zone-groups": "Define one or more geofencing zones groups to check (e.g. 'allowedZones', 'restrictedZones'). Each group must have a unique name, which is used as a prefix for calculated field output telemetry keys.", "perimeter-attribute-key": "Set the attribute key that contains the geofencing zone perimeter definition. The perimeter is always taken from server-side attributes of the zone entity.", - "report-strategy": "Presence status reports whether the entity is currently INSIDE or OUTSIDE the zone group.Transition events report when the entity ENTERED or LEFT the zone group.", + "report-strategy": "Presence status reports whether the entity is currently INSIDE or OUTSIDE the zone group. Transition events report when the entity ENTERED or LEFT the zone group.", "create-relation-with-matched-zones": "Automatically create and maintain relations between the entity and the zones it is currently inside. Relations are removed when the entity leaves a zone and created when it enters a new one.", "relation-type-required": "Relation type is required.", "relation-level-required": "Relation level is required.", @@ -1167,9 +1178,9 @@ "geofencing-empty": "At least one zone group must be configured.", "geofencing-entity-not-found": "Geofencing target entity not found.", "max-geofencing-zone": "Maximum number of geofencing zones reached.", - "zone-group-refresh-interval": "Defines how often zone groups configured via related entities are refreshed. Set to 0 to disable scheduled refresh.", + "zone-group-refresh-interval": "Defines how often zone groups configured via related entities are refreshed.", "zone-group-refresh-interval-required": "Zone groups refresh interval is required.", - "zone-group-refresh-interval-min": "Zone group refresh interval is below the minimum allowed system interval." + "zone-group-refresh-interval-min": "Zone group refresh interval should be at least {{ min }} second." } }, "ai-models": { From a813cf403e63e7e271fa3007e485ee1664dbb9cd Mon Sep 17 00:00:00 2001 From: ArtemDzhereleiko Date: Fri, 3 Oct 2025 18:02:58 +0300 Subject: [PATCH 2/3] UI: Fixed entity key autocomplete on filter change --- .../components/entity/entity-key-autocomplete.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ui-ngx/src/app/shared/components/entity/entity-key-autocomplete.component.ts b/ui-ngx/src/app/shared/components/entity/entity-key-autocomplete.component.ts index a86fc70115..9bc8d4ced8 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-key-autocomplete.component.ts +++ b/ui-ngx/src/app/shared/components/entity/entity-key-autocomplete.component.ts @@ -133,6 +133,7 @@ export class EntityKeyAutocompleteComponent implements ControlValueAccessor, Val if (filterChanged || keyScopeChanged || keyTypeChanged) { this.keyControl.setValue('', {emitEvent: false}); + this.cachedResult = null; } } From 7609722b308084149e013b1c2790c95715afdf93 Mon Sep 17 00:00:00 2001 From: ArtemDzhereleiko Date: Mon, 6 Oct 2025 16:46:54 +0300 Subject: [PATCH 3/3] UI: Move drag icon button to first column of table --- ...-geofencing-zone-groups-table.component.ts | 2 +- ...eofencing-zone-groups-panel.component.html | 23 +++++++++++-------- ...eofencing-zone-groups-panel.component.scss | 18 +++++++++++---- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/geofencing-zone-grups-table/calculated-field-geofencing-zone-groups-table.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/geofencing-zone-grups-table/calculated-field-geofencing-zone-groups-table.component.ts index 9d2a124d68..a11ae4cea5 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/geofencing-zone-grups-table/calculated-field-geofencing-zone-groups-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/geofencing-zone-grups-table/calculated-field-geofencing-zone-groups-table.component.ts @@ -168,7 +168,7 @@ export class CalculatedFieldGeofencingZoneGroupsTableComponent implements Contro renderer: this.renderer, componentType: CalculatedFieldGeofencingZoneGroupsPanelComponent, hostView: this.viewContainerRef, - preferredPlacement: 'right', + preferredPlacement: isExists ? ['left', 'leftTop', 'leftBottom'] : ['topRight', 'right', 'rightTop'], context: ctx, isModal: true }); diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.html index 1c57cfbc02..a460deaf4e 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.html @@ -97,7 +97,8 @@ {{ 'calculated-fields.entity-zone-relationship' | translate }}
-
+
+
calculated-fields.level
calculated-fields.direction-level
calculated-fields.relation-type
@@ -110,6 +111,17 @@ (cdkDropListDropped)="keyDrop($event)"> @for (keyControl of levelsFormArray().controls; track trackByKey;) {
+
+ +
{{ $index+1 }}
@@ -137,15 +149,6 @@ matTooltipPosition="above"> delete -
} diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.scss b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.scss index ff6140f12c..ac5dc70ef9 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-geofencing-zone-groups-panel.component.scss @@ -30,6 +30,8 @@ $panel-width: 520px; } .level-text { + display: flex; + justify-content: center; width: 25px; color: rgba(0, 0, 0, 0.54); } @@ -38,14 +40,20 @@ $panel-width: 520px; .tb-form-row { gap: 12px; } + .tb-form-table-body { gap: unset; } - } - .tb-form-table-header-cell { - &.tb-actions-header { - width: 80px; - min-width: 80px; + + .tb-form-table-header { + padding: 0; + } + + .tb-form-table-header-cell { + &.tb-actions-header { + width: 40px; + min-width: 40px; + } } }