115046: Fixed performance issues in virtual metadata popup

This commit is contained in:
Alexandre Vryghem
2024-05-30 10:58:23 +02:00
parent df80c33e4e
commit 58bcb9b8da
3 changed files with 51 additions and 16 deletions

View File

@@ -5,9 +5,9 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<ng-container *ngFor="let item of items; trackBy: trackItem"> <ng-container *ngFor="let itemDTO of itemDTOs$ | async; trackBy: trackItemDTO">
<div *ngVar="(isSelectedVirtualMetadataItem(item) | async) as selected" <div *ngVar="(itemDTO.isSelectedVirtualMetadataItem$ | async) as selected"
(click)="setSelectedVirtualMetadataItem(item, !selected)" (click)="setSelectedVirtualMetadataItem(itemDTO.item, !selected)"
class="item d-flex flex-row"> class="item d-flex flex-row">
<div class="m-2"> <div class="m-2">
<label> <label>
@@ -15,9 +15,9 @@
</label> </label>
</div> </div>
<div class="flex-column"> <div class="flex-column">
<ds-listable-object-component-loader [object]="item"> <ds-listable-object-component-loader [object]="itemDTO.item">
</ds-listable-object-component-loader> </ds-listable-object-component-loader>
<div *ngFor="let metadata of virtualMetadata.get(item.uuid)"> <div *ngFor="let metadata of virtualMetadata.get(itemDTO.item.uuid)">
<div class="font-weight-bold"> <div class="font-weight-bold">
{{metadata.metadataField}} {{metadata.metadataField}}
</div> </div>
@@ -31,7 +31,7 @@
<div class="d-flex flex-row-reverse m-2"> <div class="d-flex flex-row-reverse m-2">
<button class="btn btn-primary save" <button class="btn btn-primary save"
(click)="save.emit()"> (click)="save.emit()">
<i class="fas fa-save"></i> {{"item.edit.metadata.save-button" | translate}} <i aria-hidden="true" class="fas fa-save"></i> {{ 'item.edit.metadata.save-button' | translate }}
</button> </button>
</div> </div>
</div> </div>

View File

@@ -77,6 +77,7 @@ describe('VirtualMetadataComponent', () => {
comp.url = url; comp.url = url;
comp.leftItem = item; comp.leftItem = item;
comp.rightItem = relatedItem; comp.rightItem = relatedItem;
comp.ngOnChanges();
comp.relationshipId = relationshipId; comp.relationshipId = relationshipId;
fixture.detectChanges(); fixture.detectChanges();

View File

@@ -8,11 +8,17 @@ import {
EventEmitter, EventEmitter,
Inject, Inject,
Input, Input,
OnChanges,
OnDestroy,
OnInit, OnInit,
Output, Output,
} from '@angular/core'; } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { Observable } from 'rxjs'; import {
BehaviorSubject,
Observable,
Subscription,
} from 'rxjs';
import { import {
APP_CONFIG, APP_CONFIG,
@@ -21,9 +27,18 @@ import {
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service'; import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
import { Item } from '../../../core/shared/item.model'; import { Item } from '../../../core/shared/item.model';
import { MetadataValue } from '../../../core/shared/metadata.models'; import { MetadataValue } from '../../../core/shared/metadata.models';
import { hasValue } from '../../../shared/empty.util';
import { ListableObjectComponentLoaderComponent } from '../../../shared/object-collection/shared/listable-object/listable-object-component-loader.component'; import { ListableObjectComponentLoaderComponent } from '../../../shared/object-collection/shared/listable-object/listable-object-component-loader.component';
import { VarDirective } from '../../../shared/utils/var.directive'; import { VarDirective } from '../../../shared/utils/var.directive';
interface ItemDTO {
item: Item;
isSelectedVirtualMetadataItem$: Observable<boolean>;
}
@Component({ @Component({
selector: 'ds-virtual-metadata', selector: 'ds-virtual-metadata',
templateUrl: './virtual-metadata.component.html', templateUrl: './virtual-metadata.component.html',
@@ -42,7 +57,7 @@ import { VarDirective } from '../../../shared/utils/var.directive';
* The component is shown when a relationship is marked to be deleted. * The component is shown when a relationship is marked to be deleted.
* Each item has a checkbox to indicate whether its virtual metadata should be saved as real metadata. * Each item has a checkbox to indicate whether its virtual metadata should be saved as real metadata.
*/ */
export class VirtualMetadataComponent implements OnInit { export class VirtualMetadataComponent implements OnInit, OnChanges, OnDestroy {
/** /**
* The current url of this page * The current url of this page
@@ -83,9 +98,9 @@ export class VirtualMetadataComponent implements OnInit {
/** /**
* Get an array of the left and the right item of the relationship to be deleted. * Get an array of the left and the right item of the relationship to be deleted.
*/ */
get items() { itemDTOs$: BehaviorSubject<ItemDTO[]> = new BehaviorSubject([]);
return [this.leftItem, this.rightItem];
} subs: Subscription[] = [];
public virtualMetadata: Map<string, VirtualMetadata[]> = new Map<string, VirtualMetadata[]>(); public virtualMetadata: Map<string, VirtualMetadata[]> = new Map<string, VirtualMetadata[]>();
@@ -137,14 +152,33 @@ export class VirtualMetadataComponent implements OnInit {
/** /**
* Prevent unnecessary rerendering so fields don't lose focus * Prevent unnecessary rerendering so fields don't lose focus
*/ */
trackItem(index, item: Item) { trackItemDTO(index, itemDTO: ItemDTO): string {
return item && item.uuid; return itemDTO?.item?.uuid;
} }
ngOnInit(): void { ngOnInit(): void {
this.items.forEach((item) => { this.subs.push(this.itemDTOs$.subscribe((itemDTOs: ItemDTO[]) => {
this.virtualMetadata.set(item.uuid, this.getVirtualMetadata(item)); itemDTOs.forEach((itemDTO: ItemDTO) => this.virtualMetadata.set(itemDTO.item.uuid, this.getVirtualMetadata(itemDTO.item)));
}); }));
}
ngOnChanges(): void {
if (hasValue(this.leftItem) && hasValue(this.rightItem)) {
this.itemDTOs$.next([
{
item: this.leftItem,
isSelectedVirtualMetadataItem$: this.isSelectedVirtualMetadataItem(this.leftItem),
},
{
item: this.rightItem,
isSelectedVirtualMetadataItem$: this.isSelectedVirtualMetadataItem(this.rightItem),
},
]);
}
}
ngOnDestroy(): void {
this.subs.forEach((sub: Subscription) => sub.unsubscribe());
} }
} }