added calculated fields typing

This commit is contained in:
mpetrov 2025-01-24 17:20:55 +02:00
parent b169dfab27
commit be4ea19b91
7 changed files with 103 additions and 22 deletions

View File

@ -19,6 +19,7 @@ import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { PageData } from '@shared/models/page/page-data'; import { PageData } from '@shared/models/page/page-data';
import { CalculatedField } from '@shared/models/calculated-field.models';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -30,7 +31,11 @@ export class CalculatedFieldsService {
{ {
name: 'Calculated Field 1', name: 'Calculated Field 1',
type: 'Simple', type: 'Simple',
configuration: {
expression: '1 + 2', expression: '1 + 2',
type: 'SIMPLE',
},
entityId: '1',
id: { id: {
id: '1', id: '1',
} }
@ -38,23 +43,27 @@ export class CalculatedFieldsService {
{ {
name: 'Calculated Field 2', name: 'Calculated Field 2',
type: 'Script', type: 'Script',
entityId: '2',
configuration: {
expression: '${power}', expression: '${power}',
type: 'SIMPLE',
},
id: { id: {
id: '2', id: '2',
} }
} }
]; ] as any[];
constructor( constructor(
private http: HttpClient private http: HttpClient
) { } ) { }
public getCalculatedField(calculatedFieldId: string, config?: RequestConfig): Observable<any> { public getCalculatedField(calculatedFieldId: string, config?: RequestConfig): Observable<CalculatedField> {
return of(this.fieldsMock[0]); return of(this.fieldsMock[0]);
// return this.http.get<any>(`/api/calculated-field/${calculatedFieldId}`, defaultHttpOptionsFromConfig(config)); // return this.http.get<any>(`/api/calculated-field/${calculatedFieldId}`, defaultHttpOptionsFromConfig(config));
} }
public saveCalculatedField(calculatedField: any, config?: RequestConfig): Observable<any> { public saveCalculatedField(calculatedField: any, config?: RequestConfig): Observable<CalculatedField> {
return of(this.fieldsMock[1]); return of(this.fieldsMock[1]);
// return this.http.post<any>('/api/calculated-field', calculatedField, defaultHttpOptionsFromConfig(config)); // return this.http.post<any>('/api/calculated-field', calculatedField, defaultHttpOptionsFromConfig(config));
} }
@ -65,7 +74,7 @@ export class CalculatedFieldsService {
} }
public getCalculatedFields(query: any, public getCalculatedFields(query: any,
config?: RequestConfig): Observable<PageData<any>> { config?: RequestConfig): Observable<PageData<CalculatedField>> {
return of({ return of({
data: this.fieldsMock, data: this.fieldsMock,
totalPages: 1, totalPages: 1,

View File

@ -39,8 +39,9 @@ import { TbPopoverService } from '@shared/components/popover.service';
import { EntityDebugSettingsPanelComponent } from '@home/components/entity/debug/entity-debug-settings-panel.component'; import { EntityDebugSettingsPanelComponent } from '@home/components/entity/debug/entity-debug-settings-panel.component';
import { CalculatedFieldsService } from '@core/http/calculated-fields.service'; import { CalculatedFieldsService } from '@core/http/calculated-fields.service';
import { catchError, switchMap } from 'rxjs/operators'; import { catchError, switchMap } from 'rxjs/operators';
import { CalculatedField } from '@shared/models/calculated-field.models';
export class CalculatedFieldsTableConfig extends EntityTableConfig<any, TimePageLink> { export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedField, TimePageLink> {
readonly calculatedFieldsDebugPerTenantLimitsConfiguration = readonly calculatedFieldsDebugPerTenantLimitsConfiguration =
getCurrentAuthState(this.store)['calculatedFieldsDebugPerTenantLimitsConfiguration'] || '1:1'; getCurrentAuthState(this.store)['calculatedFieldsDebugPerTenantLimitsConfiguration'] || '1:1';
@ -62,31 +63,31 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<any, TimePage
private destroyRef: DestroyRef, private destroyRef: DestroyRef,
) { ) {
super(); super();
this.tableTitle = this.translate.instant('calculated-fields.label'); this.tableTitle = this.translate.instant('entity.type-calculated-fields');
this.detailsPanelEnabled = false; this.detailsPanelEnabled = false;
this.selectionEnabled = true; this.selectionEnabled = true;
this.searchEnabled = true; this.searchEnabled = true;
this.addEnabled = true; this.addEnabled = true;
this.entitiesDeleteEnabled = true; this.entitiesDeleteEnabled = true;
this.actionsColumnTitle = ''; this.actionsColumnTitle = '';
this.entityType = EntityType.CALCULATED_FIELDS; this.entityType = EntityType.CALCULATED_FIELD;
this.entityTranslations = entityTypeTranslations.get(EntityType.CALCULATED_FIELDS); this.entityTranslations = entityTypeTranslations.get(EntityType.CALCULATED_FIELD);
this.entitiesFetchFunction = pageLink => this.fetchCalculatedFields(pageLink); this.entitiesFetchFunction = pageLink => this.fetchCalculatedFields(pageLink);
this.defaultSortOrder = {property: 'name', direction: Direction.DESC}; this.defaultSortOrder = {property: 'name', direction: Direction.DESC};
this.columns.push( this.columns.push(
new EntityTableColumn<any>('name', 'common.name', '33%')); new EntityTableColumn<CalculatedField>('name', 'common.name', '33%'));
this.columns.push( this.columns.push(
new EntityTableColumn<any>('type', 'common.type', '50px')); new EntityTableColumn<CalculatedField>('type', 'common.type', '50px'));
this.columns.push( this.columns.push(
new EntityTableColumn<any>('expression', 'calculated-fields.expression', '50%')); new EntityTableColumn<CalculatedField>('expression', 'calculated-fields.expression', '50%', entity => entity.configuration.expression));
this.cellActionDescriptors.push( this.cellActionDescriptors.push(
{ {
name: '', name: '',
nameFunction: (entity) => this.getDebugConfigLabel(entity?.debugSettings), nameFunction: entity => this.getDebugConfigLabel(entity?.debugSettings),
icon: 'mdi:bug', icon: 'mdi:bug',
isEnabled: () => true, isEnabled: () => true,
iconFunction: ({ debugSettings }) => this.isDebugActive(debugSettings?.allEnabledUntil) || debugSettings?.failuresEnabled ? 'mdi:bug' : 'mdi:bug-outline', iconFunction: ({ debugSettings }) => this.isDebugActive(debugSettings?.allEnabledUntil) || debugSettings?.failuresEnabled ? 'mdi:bug' : 'mdi:bug-outline',
@ -102,11 +103,11 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<any, TimePage
); );
} }
fetchCalculatedFields(pageLink: TimePageLink): Observable<PageData<any>> { fetchCalculatedFields(pageLink: TimePageLink): Observable<PageData<CalculatedField>> {
return this.calculatedFieldsService.getCalculatedFields(pageLink); return this.calculatedFieldsService.getCalculatedFields(pageLink);
} }
onOpenDebugConfig($event: Event, { debugSettings = {}, id }: any): void { onOpenDebugConfig($event: Event, { debugSettings = {}, id }: CalculatedField): void {
const { renderer, viewContainerRef } = this.getTable(); const { renderer, viewContainerRef } = this.getTable();
if ($event) { if ($event) {
$event.stopPropagation(); $event.stopPropagation();

View File

@ -33,7 +33,7 @@
</tb-attribute-table> </tb-attribute-table>
</mat-tab> </mat-tab>
<mat-tab *ngIf="entity" <mat-tab *ngIf="entity"
label="{{ 'calculated-fields.label' | translate }}" #calculatedFieldsTab="matTab"> label="{{ 'entity.type-calculated-fields' | translate }}" #calculatedFieldsTab="matTab">
<tb-calculated-fields-table [active]="calculatedFieldsTab.isActive" [entityId]="entity.id"/> <tb-calculated-fields-table [active]="calculatedFieldsTab.isActive" [entityId]="entity.id"/>
</mat-tab> </mat-tab>
<mat-tab *ngIf="entity" <mat-tab *ngIf="entity"

View File

@ -0,0 +1,44 @@
///
/// Copyright © 2016-2024 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.
///
import { EntityDebugSettings, HasTenantId, HasVersion } from '@shared/models/entity.models';
import { BaseData } from '@shared/models/base-data';
import { CalculatedFieldId } from '@shared/models/id/calculated-field-id';
export interface CalculatedField extends BaseData<CalculatedFieldId>, HasVersion, HasTenantId {
entityId: string;
type: CalculatedFieldType;
name: string;
debugSettings?: EntityDebugSettings;
externalId?: string;
createdTime?: number;
configuration: CalculatedFieldConfiguration;
}
export enum CalculatedFieldType {
SIMPLE = 'SIMPLE',
COMPLEX = 'COMPLEX',
}
export interface CalculatedFieldConfiguration {
type: CalculatedFieldConfigType;
expression: string;
arguments: Record<string, unknown>;
}
export enum CalculatedFieldConfigType {
SIMPLE = 'SIMPLE',
SCRIPT = 'SCRIPT',
}

View File

@ -50,7 +50,7 @@ export enum EntityType {
DOMAIN = 'DOMAIN', DOMAIN = 'DOMAIN',
MOBILE_APP_BUNDLE = 'MOBILE_APP_BUNDLE', MOBILE_APP_BUNDLE = 'MOBILE_APP_BUNDLE',
MOBILE_APP = 'MOBILE_APP', MOBILE_APP = 'MOBILE_APP',
CALCULATED_FIELDS = 'CALCULATED_FIELDS', CALCULATED_FIELD = 'CALCULATED_FIELD',
} }
export enum AliasEntityType { export enum AliasEntityType {
@ -481,10 +481,10 @@ export const entityTypeTranslations = new Map<EntityType | AliasEntityType, Enti
} }
], ],
[ [
EntityType.CALCULATED_FIELDS, EntityType.CALCULATED_FIELD,
{ {
type: 'calculated-fields.label', type: 'entity.type-calculated-field',
typePlural: 'calculated-fields.label', typePlural: 'entity.type-calculated-fields',
list: 'calculated-fields.list', list: 'calculated-fields.list',
add: 'action.add', add: 'action.add',
noEntities: 'calculated-fields.no-found', noEntities: 'calculated-fields.no-found',

View File

@ -0,0 +1,26 @@
///
/// Copyright © 2016-2024 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.
///
import { EntityId } from './entity-id';
import { EntityType } from '@shared/models/entity-type.models';
export class CalculatedFieldId implements EntityId {
entityType = EntityType.CALCULATED_FIELD;
id: string;
constructor(id: string) {
this.id = id;
}
}

View File

@ -1004,7 +1004,6 @@
} }
}, },
"calculated-fields": { "calculated-fields": {
"label": "Calculated fields",
"expression": "Expression", "expression": "Expression",
"no-found": "No calculated fields found", "no-found": "No calculated fields found",
"list": "{ count, plural, =1 {One calculated field} other {List of # calculated fields} }", "list": "{ count, plural, =1 {One calculated field} other {List of # calculated fields} }",
@ -2436,6 +2435,8 @@
"type-current-tenant": "Current Tenant", "type-current-tenant": "Current Tenant",
"type-current-user": "Current User", "type-current-user": "Current User",
"type-current-user-owner": "Current User Owner", "type-current-user-owner": "Current User Owner",
"type-calculated-field": "Calculated Field",
"type-calculated-fields": "Calculated Fields",
"type-widgets-bundle": "Widgets bundle", "type-widgets-bundle": "Widgets bundle",
"type-widgets-bundles": "Widgets bundles", "type-widgets-bundles": "Widgets bundles",
"list-of-widgets-bundles": "{ count, plural, =1 {One widgets bundle} other {List of # widget bundles} }", "list-of-widgets-bundles": "{ count, plural, =1 {One widgets bundle} other {List of # widget bundles} }",