2023-11-23 17:56:04 +02:00
|
|
|
///
|
2024-01-09 10:46:16 +02:00
|
|
|
/// Copyright © 2016-2024 The Thingsboard Authors
|
2023-11-23 17:56:04 +02:00
|
|
|
///
|
|
|
|
|
/// 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 { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
|
|
|
|
import { Store } from '@ngrx/store';
|
|
|
|
|
import { AppState } from '@core/core.state';
|
|
|
|
|
import { ImageReferences } from '@shared/models/resource.models';
|
|
|
|
|
import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
|
|
|
|
|
import { TranslateService } from '@ngx-translate/core';
|
|
|
|
|
import { getEntityDetailsPageURL } from '@core/utils';
|
|
|
|
|
import { getCurrentAuthUser } from '@core/auth/auth.selectors';
|
|
|
|
|
import { NULL_UUID } from '@shared/models/id/has-uuid';
|
|
|
|
|
import { Authority } from '@shared/models/authority.enum';
|
|
|
|
|
import { Observable } from 'rxjs';
|
|
|
|
|
import { EntityService } from '@core/http/entity.service';
|
|
|
|
|
import { BaseData, HasId } from '@shared/models/base-data';
|
|
|
|
|
import { HasTenantId } from '@shared/models/entity.models';
|
|
|
|
|
import { map } from 'rxjs/operators';
|
|
|
|
|
import { TbPopoverComponent } from '@shared/components/popover.component';
|
|
|
|
|
|
|
|
|
|
interface ReferencedEntityInfo {
|
|
|
|
|
entity: BaseData<HasId> & HasTenantId;
|
|
|
|
|
typeName: string;
|
|
|
|
|
detailsUrl: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface TenantReferencedEntities {
|
|
|
|
|
tenantName?: string;
|
|
|
|
|
tenantDetailsUrl?: string;
|
|
|
|
|
entities: ReferencedEntityInfo[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ReferencedEntities = {[tenantId: string]: TenantReferencedEntities};
|
|
|
|
|
type ReferencedEntitiesEntry = [string, TenantReferencedEntities];
|
|
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
|
selector: 'tb-image-references',
|
|
|
|
|
templateUrl: './image-references.component.html',
|
2023-11-27 14:56:22 +02:00
|
|
|
styleUrls: ['./image-references.component.scss']
|
2023-11-23 17:56:04 +02:00
|
|
|
})
|
|
|
|
|
export class ImageReferencesComponent implements OnInit {
|
|
|
|
|
|
|
|
|
|
@Input()
|
|
|
|
|
references: ImageReferences;
|
|
|
|
|
|
|
|
|
|
popoverComponent: TbPopoverComponent<ImageReferencesComponent>;
|
|
|
|
|
|
|
|
|
|
contentReady = false;
|
|
|
|
|
|
|
|
|
|
authUser = getCurrentAuthUser(this.store);
|
|
|
|
|
|
|
|
|
|
simpleList = true;
|
|
|
|
|
|
|
|
|
|
referencedEntitiesList: ReferencedEntityInfo[];
|
|
|
|
|
|
|
|
|
|
referencedEntitiesEntries: ReferencedEntitiesEntry[];
|
|
|
|
|
|
|
|
|
|
constructor(protected store: Store<AppState>,
|
|
|
|
|
private entityService: EntityService,
|
|
|
|
|
private cd: ChangeDetectorRef,
|
|
|
|
|
private translate: TranslateService) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ngOnInit(): void {
|
|
|
|
|
if (this.authUser.authority === Authority.SYS_ADMIN && this.hasNonSystemEntities(this.references)) {
|
|
|
|
|
this.simpleList = false;
|
|
|
|
|
this.toReferencedEntitiesEntries(this.references).subscribe(
|
|
|
|
|
(entries) => {
|
|
|
|
|
this.referencedEntitiesEntries = entries;
|
|
|
|
|
this.contentReady = true;
|
|
|
|
|
this.cd.detectChanges();
|
|
|
|
|
if (this.popoverComponent) {
|
|
|
|
|
Promise.resolve().then(() => {
|
|
|
|
|
this.popoverComponent.updatePosition();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
this.referencedEntitiesList = this.toReferencedEntitiesList(this.references);
|
|
|
|
|
this.contentReady = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isSystem(tenantId: string): boolean {
|
|
|
|
|
return tenantId === NULL_UUID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private hasNonSystemEntities(references: ImageReferences): boolean {
|
|
|
|
|
for (const entityTypeStr of Object.keys(references)) {
|
|
|
|
|
const entities = this.references[entityTypeStr];
|
|
|
|
|
if (entities.some(e => e.tenantId && e.tenantId.id && e.tenantId.id !== NULL_UUID)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private toReferencedEntitiesList(references: ImageReferences): ReferencedEntityInfo[] {
|
|
|
|
|
const result: ReferencedEntityInfo[] = [];
|
|
|
|
|
for (const entityTypeStr of Object.keys(references)) {
|
|
|
|
|
const entityType = entityTypeStr as EntityType;
|
|
|
|
|
const entityTypeName = this.translate.instant(entityTypeTranslations.get(entityType).type);
|
|
|
|
|
const entities = references[entityTypeStr];
|
|
|
|
|
for (const entity of entities) {
|
|
|
|
|
const detailsUrl = getEntityDetailsPageURL(entity.id.id, entityType);
|
|
|
|
|
result.push({
|
|
|
|
|
entity,
|
|
|
|
|
typeName: entityTypeName,
|
|
|
|
|
detailsUrl
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private toReferencedEntitiesEntries(references: ImageReferences): Observable<ReferencedEntitiesEntry[]> {
|
|
|
|
|
let referencedEntities: ReferencedEntities = {};
|
|
|
|
|
const referencedEntitiesList = this.toReferencedEntitiesList(references);
|
|
|
|
|
for (const referencedEntityInfo of referencedEntitiesList) {
|
|
|
|
|
const tenantId = referencedEntityInfo.entity.tenantId?.id || NULL_UUID;
|
|
|
|
|
let tenantEntitiesInfo = referencedEntities[tenantId];
|
|
|
|
|
if (!tenantEntitiesInfo) {
|
|
|
|
|
tenantEntitiesInfo = {
|
|
|
|
|
entities: []
|
|
|
|
|
};
|
|
|
|
|
referencedEntities[tenantId] = tenantEntitiesInfo;
|
|
|
|
|
}
|
|
|
|
|
tenantEntitiesInfo.entities.push(referencedEntityInfo);
|
|
|
|
|
}
|
|
|
|
|
referencedEntities = Object.keys(referencedEntities).sort((tenantId1, tenantId2) => {
|
|
|
|
|
if (tenantId1 === NULL_UUID) {
|
|
|
|
|
return -1;
|
|
|
|
|
} else if (tenantId2 === NULL_UUID) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}).reduce(
|
|
|
|
|
(obj, key) => {
|
|
|
|
|
obj[key] = referencedEntities[key];
|
|
|
|
|
return obj;
|
|
|
|
|
},
|
|
|
|
|
{}
|
|
|
|
|
);
|
|
|
|
|
const tenantIds = Object.keys(referencedEntities).filter(id => id !== NULL_UUID);
|
|
|
|
|
return this.entityService.getEntities(EntityType.TENANT, tenantIds).pipe(
|
|
|
|
|
map((tenants) => {
|
|
|
|
|
for (const tenant of tenants) {
|
|
|
|
|
const tenantEntitiesInfo = referencedEntities[tenant.id.id];
|
|
|
|
|
tenantEntitiesInfo.tenantName = tenant.name;
|
|
|
|
|
tenantEntitiesInfo.tenantDetailsUrl = getEntityDetailsPageURL(tenant.id.id, EntityType.TENANT);
|
|
|
|
|
}
|
|
|
|
|
return Object.entries(referencedEntities);
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|