Browse Source

Merge with feature/iot-hub

pull/15540/head
Igor Kulikov 4 months ago
parent
commit
c4cc787197
  1. 19
      ui-ngx/src/app/modules/home/components/entity/entity-details-page.component.ts
  2. 2
      ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts
  3. 4
      ui-ngx/src/app/modules/home/components/entity/entity-tabs.component.ts
  4. 54
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-components.models.ts
  5. 8
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.ts
  6. 42
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.ts
  7. 31
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.ts
  8. 8
      ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-update-dialog.component.ts
  9. 8
      ui-ngx/src/app/modules/home/pages/asset-profile/asset-profile-tabs.component.ts
  10. 8
      ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.ts
  11. 8
      ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts
  12. 8
      ui-ngx/src/app/modules/home/pages/device/device-tabs.component.ts
  13. 43
      ui-ngx/src/app/shared/models/iot-hub/iot-hub-installed-item.models.ts

19
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'); const id = paramMap.get('entityId');
this.currentEntityId = { id, entityType }; this.currentEntityId = { id, entityType };
this.reload(); 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;
} }
})); }));
} }

2
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 (entityTabs) {
if (this.viewInited) { if (this.viewInited) {
this.matTabGroup._tabs.reset([...this.inclusiveTabs.toArray(), ...entityTabs]); this.matTabGroup._tabs.reset([...this.inclusiveTabs.toArray(), ...entityTabs]);
this.matTabGroup.selectedIndex = this.selectedTab;
this.matTabGroup._tabs.notifyOnChanges(); this.matTabGroup._tabs.notifyOnChanges();
} else { } else {
this.pendingTabs = entityTabs; this.pendingTabs = entityTabs;
@ -321,6 +322,7 @@ export class EntityDetailsPanelComponent extends PageComponent implements AfterV
this.viewInited = true; this.viewInited = true;
if (this.pendingTabs) { if (this.pendingTabs) {
this.matTabGroup._tabs.reset([...this.inclusiveTabs.toArray(), ...this.pendingTabs]); this.matTabGroup._tabs.reset([...this.inclusiveTabs.toArray(), ...this.pendingTabs]);
this.matTabGroup.selectedIndex = this.selectedTab;
this.matTabGroup._tabs.notifyOnChanges(); this.matTabGroup._tabs.notifyOnChanges();
this.pendingTabs = null; this.pendingTabs = null;
} }

4
ui-ngx/src/app/modules/home/components/entity/entity-tabs.component.ts

@ -119,6 +119,10 @@ export abstract class EntityTabsComponent<T extends BaseData<HasId>,
); );
} }
resolveTabIndex(tab: string): number {
return 0;
}
protected setEntity(entity: T) { protected setEntity(entity: T) {
this.entityValue = entity; this.entityValue = entity;
} }

54
ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-components.models.ts

@ -1,54 +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<string, EntityType> = {
'WIDGET': EntityType.WIDGET_TYPE,
'DASHBOARD': EntityType.DASHBOARD,
'CALCULATED_FIELD': 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;
}
// Alarm rules share the CalculatedField data structure but live at a different
// route, so resolve their URL directly instead of going through the entity-type map.
if (itemType === 'ALARM_RULE' && descriptor.type === 'ALARM_RULE') {
const id = descriptor.calculatedFieldId?.id;
return id ? `/alarms/alarm-rules/${id}` : 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 'RULE_CHAIN': entityId = descriptor.ruleChainId?.id; break;
}
if (!entityId) {
return null;
}
return getEntityDetailsPageURL(entityId, entityType) || null;
}

8
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 { DialogComponent } from '@shared/components/dialog.component';
import { MpItemVersionView } from '@shared/models/iot-hub/iot-hub-version.models'; import { MpItemVersionView } from '@shared/models/iot-hub/iot-hub-version.models';
import { ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.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 { IotHubApiService } from '@core/http/iot-hub-api.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { EntityId } from '@shared/models/id/entity-id'; 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 { SolutionInstallDialogComponent } from '@home/components/iot-hub/solution-install-dialog.component';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
@ -262,7 +264,7 @@ export class TbIotHubInstallDialogComponent extends DialogComponent<TbIotHubInst
} }
} else { } else {
this.state = 'success'; this.state = 'success';
this.entityDetailsUrl = resolveEntityDetailsUrl(result.descriptor, this.item.type); this.entityDetailsUrl = getInstalledItemUrl(result.descriptor);
} }
} else { } else {
this.state = 'error'; this.state = 'error';

42
ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-installed-items-table.component.ts

@ -40,13 +40,12 @@ import { PageLink } from '@shared/models/page/page-link';
import { Direction, SortOrder } from '@shared/models/page/sort-order'; import { Direction, SortOrder } from '@shared/models/page/sort-order';
import { import {
DeviceInstalledItemDescriptor, DeviceInstalledItemDescriptor,
getInstalledItemUrl,
IotHubInstalledItem, IotHubInstalledItem,
ItemPublishedVersionInfo ItemPublishedVersionInfo
} from '@shared/models/iot-hub/iot-hub-installed-item.models'; } from '@shared/models/iot-hub/iot-hub-installed-item.models';
import { MpItemVersionView } from '@shared/models/iot-hub/iot-hub-version.models'; import { MpItemVersionView } from '@shared/models/iot-hub/iot-hub-version.models';
import { getItemTypeIcon, ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.models'; import { getItemTypeIcon, ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.models';
import { EntityType } from '@shared/models/entity-type.models';
import { getEntityDetailsPageURL } from '@core/utils';
import { IotHubActionsService } from '@home/components/iot-hub/iot-hub-actions.service'; import { IotHubActionsService } from '@home/components/iot-hub/iot-hub-actions.service';
@Component({ @Component({
@ -209,42 +208,11 @@ export class TbIotHubInstalledItemsTableComponent implements OnInit, OnChanges,
}); });
} }
getEntityId(item: IotHubInstalledItem): string | null {
const descriptor = item.descriptor;
switch (descriptor.type) {
case 'WIDGET': return descriptor.widgetTypeId?.id;
case 'DASHBOARD': return descriptor.dashboardId?.id;
case 'CALCULATED_FIELD': return descriptor.calculatedFieldId?.id;
case 'ALARM_RULE': return descriptor.calculatedFieldId?.id;
case 'RULE_CHAIN': return descriptor.ruleChainId?.id;
case 'DEVICE': return descriptor.dashboardId?.id ?? null;
case 'SOLUTION_TEMPLATE': return descriptor.dashboardId?.id;
default: return null;
}
}
getEntityType(item: IotHubInstalledItem): EntityType | null {
const descriptor = item.descriptor;
switch (descriptor.type) {
case 'WIDGET': return EntityType.WIDGET_TYPE;
case 'DASHBOARD': return EntityType.DASHBOARD;
case 'CALCULATED_FIELD': return EntityType.CALCULATED_FIELD;
case 'ALARM_RULE': return EntityType.CALCULATED_FIELD;
case 'RULE_CHAIN': return EntityType.RULE_CHAIN;
case 'DEVICE': return descriptor.dashboardId ? EntityType.DASHBOARD : null;
case 'SOLUTION_TEMPLATE': return EntityType.DASHBOARD;
default: return null;
}
}
openEntity(item: IotHubInstalledItem): void { openEntity(item: IotHubInstalledItem): void {
const entityType = this.getEntityType(item); const url = getInstalledItemUrl(item?.descriptor);
const entityId = this.getEntityId(item); if (url) {
if (entityType && entityId) { const urlTree = this.router.parseUrl(url);
const url = getEntityDetailsPageURL(entityId, entityType); window.open(this.router.serializeUrl(urlTree), '_blank');
if (url) {
window.open(this.router.serializeUrl(this.router.parseUrl(url)), '_blank');
}
} }
} }

31
ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.ts

@ -22,11 +22,9 @@ import { AppState } from '@core/core.state';
import { DialogComponent } from '@shared/components/dialog.component'; import { DialogComponent } from '@shared/components/dialog.component';
import { MpItemVersionView, cfTypeTranslations, cfTypeIcons, ruleChainTypeTranslations, widgetTypeTranslations, NodeInfo } from '@shared/models/iot-hub/iot-hub-version.models'; import { MpItemVersionView, cfTypeTranslations, cfTypeIcons, ruleChainTypeTranslations, widgetTypeTranslations, NodeInfo } from '@shared/models/iot-hub/iot-hub-version.models';
import { getItemTypeIcon, ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.models'; import { getItemTypeIcon, ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.models';
import { IotHubInstalledItem } from '@shared/models/iot-hub/iot-hub-installed-item.models'; import { getInstalledItemUrl, IotHubInstalledItem } from '@shared/models/iot-hub/iot-hub-installed-item.models';
import { IotHubApiService } from '@core/http/iot-hub-api.service'; import { IotHubApiService } from '@core/http/iot-hub-api.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { EntityType } from '@shared/models/entity-type.models';
import { getEntityDetailsPageURL } from '@core/utils';
import { SolutionInstallDialogComponent } from '@home/components/iot-hub/solution-install-dialog.component'; import { SolutionInstallDialogComponent } from '@home/components/iot-hub/solution-install-dialog.component';
import { SolutionTemplateInstalledItemDescriptor } from '@shared/models/iot-hub/iot-hub-installed-item.models'; import { SolutionTemplateInstalledItemDescriptor } from '@shared/models/iot-hub/iot-hub-installed-item.models';
import { IotHubActionsService } from '@home/components/iot-hub/iot-hub-actions.service'; import { IotHubActionsService } from '@home/components/iot-hub/iot-hub-actions.service';
@ -199,29 +197,10 @@ export class TbIotHubItemDetailDialogComponent extends DialogComponent<TbIotHubI
} }
openEntityDetails(): void { openEntityDetails(): void {
const descriptor = this.installedItem?.descriptor; const url = getInstalledItemUrl(this.installedItem?.descriptor);
if (!descriptor) { if (url) {
return; this.dialogRef.close();
} void this.router.navigateByUrl(url);
let entityId: string | null = null;
let entityType: EntityType | 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.calculatedFieldId?.id;
entityType = EntityType.CALCULATED_FIELD;
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) {
const url = getEntityDetailsPageURL(entityId, entityType);
if (url) {
this.dialogRef.close();
void this.router.navigateByUrl(url);
}
} }
} }

8
ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-update-dialog.component.ts

@ -21,11 +21,13 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { DialogComponent } from '@shared/components/dialog.component'; import { DialogComponent } from '@shared/components/dialog.component';
import { ItemType, itemTypeTranslations } from '@shared/models/iot-hub/iot-hub-item.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 { IotHubApiService } from '@core/http/iot-hub-api.service';
import { DialogService } from '@core/services/dialog.service'; import { DialogService } from '@core/services/dialog.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { resolveEntityDetailsUrl } from './iot-hub-components.models';
import { SolutionInstallDialogComponent } from '@home/components/iot-hub/solution-install-dialog.component'; import { SolutionInstallDialogComponent } from '@home/components/iot-hub/solution-install-dialog.component';
export interface IotHubUpdateDialogData { export interface IotHubUpdateDialogData {
@ -86,7 +88,7 @@ export class TbIotHubUpdateDialogComponent extends DialogComponent<TbIotHubUpdat
}); });
} else { } else {
this.state = 'success'; this.state = 'success';
this.entityDetailsUrl = resolveEntityDetailsUrl(result.descriptor, this.data.itemType); this.entityDetailsUrl = getInstalledItemUrl(result.descriptor);
} }
} else if (result.entityModified) { } else if (result.entityModified) {
this.state = 'confirm'; this.state = 'confirm';

8
ui-ngx/src/app/modules/home/pages/asset-profile/asset-profile-tabs.component.ts

@ -36,4 +36,12 @@ export class AssetProfileTabsComponent extends EntityTabsComponent<AssetProfile>
super.ngOnInit(); super.ngOnInit();
} }
resolveTabIndex(tab: string): number {
if (tab === 'cf') {
return 1;
} else {
return super.resolveTabIndex(tab);
}
}
} }

8
ui-ngx/src/app/modules/home/pages/asset/asset-tabs.component.ts

@ -39,6 +39,14 @@ export class AssetTabsComponent extends EntityTabsComponent<AssetInfo> {
super.ngOnInit(); super.ngOnInit();
} }
resolveTabIndex(tab: string): number {
if (tab === 'cf') {
return 3;
} else {
return super.resolveTabIndex(tab);
}
}
protected setEntity(entity: AssetInfo) { protected setEntity(entity: AssetInfo) {
this.ownerId = entity.customerId.id !== this.nullUid ? entity.customerId : entity.tenantId; this.ownerId = entity.customerId.id !== this.nullUid ? entity.customerId : entity.tenantId;
super.setEntity(entity); super.setEntity(entity);

8
ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts

@ -59,6 +59,14 @@ export class DeviceProfileTabsComponent extends EntityTabsComponent<DeviceProfil
}); });
} }
resolveTabIndex(tab: string): number {
if (tab === 'cf') {
return 2;
} else {
return super.resolveTabIndex(tab);
}
}
protected setEntity(entity: DeviceProfile) { protected setEntity(entity: DeviceProfile) {
this.isTransportTypeChanged = false; this.isTransportTypeChanged = false;
this.hasOldRules = !!entity?.profileData?.alarms?.length; this.hasOldRules = !!entity?.profileData?.alarms?.length;

8
ui-ngx/src/app/modules/home/pages/device/device-tabs.component.ts

@ -39,6 +39,14 @@ export class DeviceTabsComponent extends EntityTabsComponent<DeviceInfo> {
super.ngOnInit(); super.ngOnInit();
} }
resolveTabIndex(tab: string): number {
if (tab === 'cf') {
return 3;
} else {
return super.resolveTabIndex(tab);
}
}
protected setEntity(entity: DeviceInfo) { protected setEntity(entity: DeviceInfo) {
this.ownerId = entity.customerId.id !== this.nullUid ? entity.customerId : entity.tenantId; this.ownerId = entity.customerId.id !== this.nullUid ? entity.customerId : entity.tenantId;
super.setEntity(entity); super.setEntity(entity);

43
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 { BaseData } from '@shared/models/base-data';
import { EntityType } from '@shared/models/entity-type.models';
import { getEntityDetailsPageURL } from '@core/utils';
export interface WidgetInstalledItemDescriptor { export interface WidgetInstalledItemDescriptor {
type: 'WIDGET'; type: 'WIDGET';
@ -97,3 +99,44 @@ export interface IotHubInstalledItem extends BaseData<{id: string}> {
version: string; version: string;
descriptor: IotHubInstalledItemDescriptor; descriptor: IotHubInstalledItemDescriptor;
} }
export const getInstalledItemUrl = (descriptor?: IotHubInstalledItemDescriptor): string | null => {
if (!descriptor) {
return null;
}
let entityId: string | null = null;
let entityType: EntityType | 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.calculatedFieldId?.id;
entityType = EntityType.CALCULATED_FIELD;
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: string | null;
if (descriptor.type === 'ALARM_RULE') {
url = `/alarms/alarm-rules/${entityId}`;
} else {
url = getEntityDetailsPageURL(entityId, entityType);
}
return url;
}
return null;
}

Loading…
Cancel
Save