diff --git a/ui-ngx/src/app/modules/home/components/entity/entity-details-page.component.ts b/ui-ngx/src/app/modules/home/components/entity/entity-details-page.component.ts index 8988a02380..7d9b9e07f7 100644 --- a/ui-ngx/src/app/modules/home/components/entity/entity-details-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/entity-details-page.component.ts @@ -98,7 +98,24 @@ export class EntityDetailsPageComponent extends EntityDetailsPanelComponent impl const id = paramMap.get('entityId'); this.currentEntityId = { id, entityType }; this.reload(); - this.selectedTab = 0; + const queryParams = this.route.snapshot.queryParams; + let selectedTabIndex = 0; + if (queryParams['selectedTab']) { + this.router.navigate([], { + queryParams: { + selectedTab: null + }, + queryParamsHandling: 'merge', + replaceUrl: true + }); + if (this.entityTabsComponent) { + const selectedTab: string = queryParams['selectedTab']; + if (selectedTab) { + selectedTabIndex = this.entityTabsComponent.resolveTabIndex(selectedTab); + } + } + } + this.selectedTab = selectedTabIndex; } })); } diff --git a/ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts b/ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts index 8c6fc004d8..b9ed698a47 100644 --- a/ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts @@ -215,6 +215,7 @@ export class EntityDetailsPanelComponent extends PageComponent implements AfterV if (entityTabs) { if (this.viewInited) { this.matTabGroup._tabs.reset([...this.inclusiveTabs.toArray(), ...entityTabs]); + this.matTabGroup.selectedIndex = this.selectedTab; this.matTabGroup._tabs.notifyOnChanges(); } else { this.pendingTabs = entityTabs; @@ -321,6 +322,7 @@ export class EntityDetailsPanelComponent extends PageComponent implements AfterV this.viewInited = true; if (this.pendingTabs) { this.matTabGroup._tabs.reset([...this.inclusiveTabs.toArray(), ...this.pendingTabs]); + this.matTabGroup.selectedIndex = this.selectedTab; this.matTabGroup._tabs.notifyOnChanges(); this.pendingTabs = null; } diff --git a/ui-ngx/src/app/modules/home/components/entity/entity-tabs.component.ts b/ui-ngx/src/app/modules/home/components/entity/entity-tabs.component.ts index ec6e46fb72..c5b2eebeb4 100644 --- a/ui-ngx/src/app/modules/home/components/entity/entity-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/entity-tabs.component.ts @@ -117,6 +117,10 @@ export abstract class EntityTabsComponent, ); } + resolveTabIndex(tab: string): number { + return 0; + } + protected setEntity(entity: T) { this.entityValue = entity; } diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-components.models.ts b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-components.models.ts deleted file mode 100644 index 1233dfa89c..0000000000 --- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-components.models.ts +++ /dev/null @@ -1,50 +0,0 @@ -/// -/// Copyright © 2016-2026 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 { EntityType } from '@shared/models/entity-type.models'; -import { IotHubInstalledItemDescriptor } from '@shared/models/iot-hub/iot-hub-installed-item.models'; -import { getEntityDetailsPageURL } from '@core/utils'; - -export const ITEM_TYPE_TO_ENTITY_TYPE: Record = { - 'WIDGET': EntityType.WIDGET_TYPE, - 'DASHBOARD': EntityType.DASHBOARD, - 'CALCULATED_FIELD': EntityType.CALCULATED_FIELD, - 'ALARM_RULE': EntityType.CALCULATED_FIELD, - 'RULE_CHAIN': EntityType.RULE_CHAIN, - 'DEVICE': EntityType.DEVICE_PROFILE -}; - -export function resolveEntityDetailsUrl(descriptor: IotHubInstalledItemDescriptor, itemType: string): string | null { - if (!descriptor) { - return null; - } - const entityType = ITEM_TYPE_TO_ENTITY_TYPE[itemType]; - if (!entityType) { - return null; - } - let entityId: string | null = null; - switch (descriptor.type) { - case 'WIDGET': entityId = descriptor.widgetTypeId?.id; break; - case 'DASHBOARD': entityId = descriptor.dashboardId?.id; break; - case 'CALCULATED_FIELD': entityId = descriptor.calculatedFieldId?.id; break; - case 'ALARM_RULE': entityId = descriptor.calculatedFieldId?.id; break; - case 'RULE_CHAIN': entityId = descriptor.ruleChainId?.id; break; - } - if (!entityId) { - return null; - } - return getEntityDetailsPageURL(entityId, entityType) || null; -} diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.ts b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.ts index 6484a32c4b..34056abbfe 100644 --- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.ts @@ -24,12 +24,14 @@ import { AppState } from '@core/core.state'; import { DialogComponent } from '@shared/components/dialog.component'; import { MpItemVersionView } from '@shared/models/iot-hub/iot-hub-version.models'; import { ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.models'; -import { SolutionTemplateInstalledItemDescriptor } from '@shared/models/iot-hub/iot-hub-installed-item.models'; +import { + getInstalledItemUrl, + SolutionTemplateInstalledItemDescriptor +} from '@shared/models/iot-hub/iot-hub-installed-item.models'; import { IotHubApiService } from '@core/http/iot-hub-api.service'; import { TranslateService } from '@ngx-translate/core'; import { EntityType } from '@shared/models/entity-type.models'; import { EntityId } from '@shared/models/id/entity-id'; -import { resolveEntityDetailsUrl } from './iot-hub-components.models'; import { SolutionInstallDialogComponent } from '@home/components/iot-hub/solution-install-dialog.component'; import { Observable, of } from 'rxjs'; import { map, switchMap } from 'rxjs/operators'; @@ -256,7 +258,7 @@ export class TbIotHubInstallDialogComponent extends DialogComponent super.ngOnInit(); } + resolveTabIndex(tab: string): number { + if (tab === 'cf') { + return 1; + } else { + return super.resolveTabIndex(tab); + } + } + } diff --git a/ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.ts index 10ef434755..03aa7a1fa1 100644 --- a/ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.ts @@ -36,4 +36,12 @@ export class AssetTabsComponent extends EntityTabsComponent { super.ngOnInit(); } + resolveTabIndex(tab: string): number { + if (tab === 'cf') { + return 3; + } else { + return super.resolveTabIndex(tab); + } + } + } diff --git a/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts index 1a762ac881..bfefdf5d4c 100644 --- a/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts @@ -56,6 +56,14 @@ export class DeviceProfileTabsComponent extends EntityTabsComponent { super.ngOnInit(); } + resolveTabIndex(tab: string): number { + if (tab === 'cf') { + return 3; + } else { + return super.resolveTabIndex(tab); + } + } + } diff --git a/ui-ngx/src/app/shared/models/iot-hub/iot-hub-installed-item.models.ts b/ui-ngx/src/app/shared/models/iot-hub/iot-hub-installed-item.models.ts index 25ac09d161..b46bdb2829 100644 --- a/ui-ngx/src/app/shared/models/iot-hub/iot-hub-installed-item.models.ts +++ b/ui-ngx/src/app/shared/models/iot-hub/iot-hub-installed-item.models.ts @@ -15,6 +15,8 @@ /// import { BaseData } from '@shared/models/base-data'; +import { EntityType } from '@shared/models/entity-type.models'; +import { getEntityDetailsPageURL } from '@core/utils'; export interface WidgetInstalledItemDescriptor { type: 'WIDGET'; @@ -97,3 +99,35 @@ export interface IotHubInstalledItem extends BaseData<{id: string}> { version: string; descriptor: IotHubInstalledItemDescriptor; } + +export const getInstalledItemUrl = (descriptor?: IotHubInstalledItemDescriptor): string | null => { + let entityId: string | null = null; + let entityType: EntityType | null = null; + let query: string | null = null; + switch (descriptor.type) { + case 'WIDGET': entityId = descriptor.widgetTypeId?.id; entityType = EntityType.WIDGET_TYPE; break; + case 'DASHBOARD': entityId = descriptor.dashboardId?.id; entityType = EntityType.DASHBOARD; break; + case 'CALCULATED_FIELD': + case 'ALARM_RULE': + entityId = descriptor.entityId?.id; + entityType = descriptor.entityId?.entityType as EntityType; + if (descriptor.type === 'CALCULATED_FIELD') { + query = 'selectedTab=cf'; + } + break; + case 'RULE_CHAIN': entityId = descriptor.ruleChainId?.id; entityType = EntityType.RULE_CHAIN; break; + case 'SOLUTION_TEMPLATE': entityId = descriptor.dashboardId?.id; entityType = EntityType.DASHBOARD; break; + } + if (entityType && entityId) { + let url = getEntityDetailsPageURL(entityId, entityType); + if (url) { + if (query) { + url = `${url}?${query}`; + } + return url; + } else { + return null; + } + } + return null; +}