/// /// Copyright © 2016-2025 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 { Injectable } from '@angular/core'; import { CellActionDescriptor, DateEntityTableColumn, EntityTableColumn, EntityTableConfig } from '@home/models/entity/entities-table-config.models'; import { ActivatedRouteSnapshot } from '@angular/router'; import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared/models/entity-type.models'; import { Direction } from '@shared/models/page/sort-order'; import { DatePipe } from '@angular/common'; import { TranslateService } from '@ngx-translate/core'; import { MatDialog } from '@angular/material/dialog'; import { Observable } from 'rxjs'; import { AiModel, AiProviderTranslations } from '@shared/models/ai-model.models'; import { AiModelService } from '@core/http/ai-model.service'; import { AiModelTableHeaderComponent } from '@home/pages/ai-model/ai-model-table-header.component'; import { AIModelDialogComponent, AIModelDialogData } from '@shared/components/ai-model/ai-model-dialog.component'; import { map } from 'rxjs/operators'; @Injectable() export class AiModelsTableConfigResolver { private readonly config: EntityTableConfig = new EntityTableConfig(); constructor( private datePipe: DatePipe, private aiModelService: AiModelService, private translate : TranslateService, private dialog: MatDialog ) { this.config.selectionEnabled = true; this.config.entityType = EntityType.AI_MODEL; this.config.addAsTextButton = true; this.config.detailsPanelEnabled = false; this.config.entityTranslations = entityTypeTranslations.get(EntityType.AI_MODEL); this.config.entityResources = entityTypeResources.get(EntityType.AI_MODEL); this.config.headerComponent = AiModelTableHeaderComponent; this.config.addDialogStyle = {width: '850px', maxHeight: '100vh'}; this.config.defaultSortOrder = {property: 'createdTime', direction: Direction.DESC}; this.config.addEntity = () => this.addModel(null, true); this.config.columns.push( new DateEntityTableColumn('createdTime', 'common.created-time', this.datePipe, '170px'), new EntityTableColumn('name', 'ai-models.name', '33%'), new EntityTableColumn('provider', 'ai-models.ai-provider', '33%', entity => this.translate.instant(AiProviderTranslations.get(entity.configuration.provider)) ), new EntityTableColumn('aiModel', 'ai-models.ai-model', '33%', entity => entity.configuration.modelId, () => ({}), false ) ) this.config.deleteEntityTitle = model => this.translate.instant('ai-models.delete-model-title', {modelName: model.name}); this.config.deleteEntityContent = () => this.translate.instant('ai-models.delete-model-text'); this.config.deleteEntitiesTitle = count => this.translate.instant('ai-models.delete-models-title', {count}); this.config.deleteEntitiesContent = () => this.translate.instant('ai-models.delete-models-text'); this.config.deleteEntity = id => this.aiModelService.deleteAiModel(id.id); this.config.entitiesFetchFunction = pageLink => this.aiModelService.getAiModels(pageLink); this.config.cellActionDescriptors = this.configureCellActions(); } resolve(_route: ActivatedRouteSnapshot): EntityTableConfig { return this.config; } private configureCellActions(): Array> { return [ { name: this.translate.instant('action.edit'), icon: 'edit', isEnabled: () => true, onAction: ($event, entity) => this.editModel(entity) } ]; } private editModel(AIModel: AiModel): void { this.addModel(AIModel, false).subscribe((res) => { if (res) { this.config.updateData(); } }); } private addModel(AIModel: AiModel, isAdd = false): Observable { return this.dialog.open(AIModelDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { isAdd, AIModel } }).afterClosed().pipe(map(res => { if (res) { this.config.updateData(); return res; } else { return null; } })); } }