Skip to content

Commit e6086e1

Browse files
115427: Fixed delete item page freezing when it has relationships
1 parent 404ccd9 commit e6086e1

2 files changed

Lines changed: 81 additions & 40 deletions

File tree

src/app/item-page/edit-item-page/item-delete/item-delete.component.html

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,29 @@ <h2>{{headerMessage | translate: {id: item.handle} }}</h2>
66
<p>{{descriptionMessage | translate}}</p>
77
<ds-modify-item-overview [item]="item"></ds-modify-item-overview>
88

9-
<ng-container *ngVar="(types$ | async) as types">
9+
<ng-container *ngVar="(typeDTOs$ | async) as types">
1010

1111
<div *ngIf="types && types.length > 0" class="mb-4">
1212

1313
{{'virtual-metadata.delete-item.info' | translate}}
1414

15-
<div *ngFor="let type of types" class="mb-4">
16-
17-
<div *ngVar="(isSelected(type) | async) as selected"
15+
<div *ngFor="let typeDto of types" class="mb-4">
16+
<div *ngVar="(typeDto.isSelected$ | async) as selected"
1817
class="d-flex flex-row">
1918

20-
<div class="m-2" (click)="setSelected(type, !selected)">
19+
<div class="m-2" (click)="setSelected(typeDto.relationshipType, !selected)">
2120
<label>
22-
<input type="checkbox" [checked]="selected">
21+
<input type="checkbox" [checked]="selected" [disabled]="isDeleting$ | async">
2322
</label>
2423
</div>
2524

2625
<div class="flex-column flex-grow-1">
27-
<h5 (click)="setSelected(type, !selected)">
28-
{{getRelationshipMessageKey(getLabel(type) | async) | translate}}
26+
<h5 (click)="setSelected(typeDto.relationshipType, !selected)">
27+
{{getRelationshipMessageKey(typeDto.label$ | async) | translate}}
2928
</h5>
30-
<div *ngFor="let relationship of (getRelationships(type) | async)"
29+
<div *ngFor="let relationshipDto of (typeDto.relationshipDTOs$ | async)"
3130
class="d-flex flex-row">
32-
<ng-container *ngVar="(getRelatedItem(relationship) | async) as relatedItem">
31+
<ng-container *ngVar="(relationshipDto.relatedItem$ | async) as relatedItem">
3332

3433
<ds-listable-object-component-loader
3534
*ngIf="relatedItem"
@@ -46,7 +45,7 @@ <h5 (click)="setSelected(type, !selected)">
4645
</div>
4746

4847
<ng-template #virtualMetadataModal>
49-
<div>
48+
<div class="thumb-font-1">
5049
<div class="modal-header">
5150
{{'virtual-metadata.delete-item.modal-head' | translate}}
5251
<button type="button" class="close"
@@ -60,7 +59,7 @@ <h5 (click)="setSelected(type, !selected)">
6059
[object]="relatedItem"
6160
[viewMode]="viewMode">
6261
</ds-listable-object-component-loader>
63-
<div *ngFor="let metadata of (getVirtualMetadata(relationship) | async)">
62+
<div *ngFor="let metadata of (relationshipDto.virtualMetadata$ | async)">
6463
<div>
6564
<div class="font-weight-bold">
6665
{{metadata.metadataField}}
@@ -87,10 +86,11 @@ <h5 (click)="setSelected(type, !selected)">
8786
</ng-container>
8887

8988
<div class="space-children-mr">
90-
<button (click)="performAction()"
89+
<button [disabled]="isDeleting$ | async" (click)="performAction()"
9190
class="btn btn-outline-secondary perform-action">{{confirmMessage | translate}}
9291
</button>
93-
<button [routerLink]="[itemPageRoute, 'edit']" class="btn btn-outline-secondary cancel">
92+
<button [disabled]="isDeleting$ | async" [routerLink]="[itemPageRoute, 'edit']"
93+
class="btn btn-outline-secondary cancel">
9494
{{cancelMessage| translate}}
9595
</button>
9696
</div>

src/app/item-page/edit-item-page/item-delete/item-delete.component.ts

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// eslint-disable-next-line max-classes-per-file
12
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
23
import { defaultIfEmpty, filter, map, switchMap, take } from 'rxjs/operators';
34
import {
@@ -37,6 +38,34 @@ import { getItemEditRoute } from '../../item-page-routing-paths';
3738
import { RemoteData } from '../../../core/data/remote-data';
3839
import { NoContent } from '../../../core/shared/NoContent.model';
3940

41+
/**
42+
* Data Transfer Object used to prevent the HTML template to call function returning Observables
43+
*/
44+
class RelationshipTypeDTO {
45+
46+
relationshipType: RelationshipType;
47+
48+
isSelected$: Observable<boolean>;
49+
50+
label$: Observable<string>;
51+
52+
relationshipDTOs$: Observable<RelationshipDTO[]>;
53+
54+
}
55+
56+
/**
57+
* Data Transfer Object used to prevent the HTML template to call function returning Observables
58+
*/
59+
class RelationshipDTO {
60+
61+
relationship: Relationship;
62+
63+
relatedItem$: Observable<Item>;
64+
65+
virtualMetadata$: Observable<VirtualMetadata[]>;
66+
67+
}
68+
4069
@Component({
4170
selector: 'ds-item-delete',
4271
templateUrl: '../item-delete/item-delete.component.html'
@@ -64,7 +93,7 @@ export class ItemDeleteComponent
6493
* A list of the relationship types for which this item has relations as an observable.
6594
* The list doesn't contain duplicates.
6695
*/
67-
types$: BehaviorSubject<RelationshipType[]> = new BehaviorSubject([]);
96+
typeDTOs$: BehaviorSubject<RelationshipTypeDTO[]> = new BehaviorSubject([]);
6897

6998
/**
7099
* A map which stores the relationships of this item for each type as observable lists
@@ -93,6 +122,8 @@ export class ItemDeleteComponent
93122
*/
94123
private subs: Subscription[] = [];
95124

125+
public isDeleting$: BehaviorSubject<boolean> = new BehaviorSubject(false);
126+
96127
constructor(protected route: ActivatedRoute,
97128
protected router: Router,
98129
protected notificationsService: NotificationsService,
@@ -146,14 +177,25 @@ export class ItemDeleteComponent
146177
}, [])
147178
),
148179
);
149-
})
150-
).subscribe((types: RelationshipType[]) => this.types$.next(types)));
180+
}),
181+
).subscribe((types: RelationshipType[]) => this.typeDTOs$.next(types.map((relationshipType: RelationshipType) => Object.assign(new RelationshipTypeDTO(), {
182+
relationshipType: relationshipType,
183+
isSelected$: this.isSelected(relationshipType),
184+
label$: this.getLabel(relationshipType),
185+
relationshipDTOs$: this.getRelationships(relationshipType).pipe(
186+
map((relationships: Relationship[]) => relationships.map((relationship: Relationship) => Object.assign(new RelationshipDTO(), {
187+
relationship: relationship,
188+
relatedItem$: this.getRelatedItem(relationship),
189+
virtualMetadata$: this.getVirtualMetadata(relationship),
190+
} as RelationshipDTO))),
191+
),
192+
})))));
151193
}
152194

153-
this.subs.push(this.types$.pipe(
195+
this.subs.push(this.typeDTOs$.pipe(
154196
take(1),
155-
).subscribe((types) =>
156-
this.objectUpdatesService.initialize(this.url, types, this.item.lastModified)
197+
).subscribe((types: RelationshipTypeDTO[]) =>
198+
this.objectUpdatesService.initialize(this.url, types.map((relationshipTypeDto: RelationshipTypeDTO) => relationshipTypeDto.relationshipType), this.item.lastModified),
157199
));
158200
}
159201

@@ -326,34 +368,33 @@ export class ItemDeleteComponent
326368
* @param selected whether the type should be selected
327369
*/
328370
setSelected(type: RelationshipType, selected: boolean): void {
329-
this.objectUpdatesService.setSelectedVirtualMetadata(this.url, this.item.uuid, type.uuid, selected);
371+
if (this.isDeleting$.value === false) {
372+
this.objectUpdatesService.setSelectedVirtualMetadata(this.url, this.item.uuid, type.uuid, selected);
373+
}
330374
}
331375

332376
/**
333377
* Perform the delete operation
334378
*/
335-
performAction() {
336-
337-
this.subs.push(this.types$.pipe(
338-
switchMap((types) =>
379+
performAction(): void {
380+
this.isDeleting$.next(true);
381+
this.subs.push(this.typeDTOs$.pipe(
382+
switchMap((types: RelationshipTypeDTO[]) =>
339383
combineLatest(
340-
types.map((type) => this.isSelected(type))
384+
types.map((type: RelationshipTypeDTO) => type.isSelected$),
341385
).pipe(
342386
defaultIfEmpty([]),
343-
map((selection) => types.filter(
344-
(type, index) => selection[index]
387+
map((selection: boolean[]) => types.filter(
388+
(type: RelationshipTypeDTO, index: number) => selection[index],
345389
)),
346-
map((selectedTypes) => selectedTypes.map((type) => type.id)),
347-
)
390+
map((selectedDtoTypes: RelationshipTypeDTO[]) => selectedDtoTypes.map((typeDto: RelationshipTypeDTO) => typeDto.relationshipType.id)),
391+
),
348392
),
349-
switchMap((types) =>
350-
this.itemDataService.delete(this.item.id, types).pipe(getFirstCompletedRemoteData())
351-
)
352-
).subscribe(
353-
(rd: RemoteData<NoContent>) => {
354-
this.notify(rd.hasSucceeded);
355-
}
356-
));
393+
switchMap((types: string[]) => this.itemDataService.delete(this.item.id, types)),
394+
getFirstCompletedRemoteData(),
395+
).subscribe((rd: RemoteData<NoContent>) => {
396+
this.notify(rd.hasSucceeded);
397+
}));
357398
}
358399

359400
/**
@@ -363,10 +404,10 @@ export class ItemDeleteComponent
363404
notify(succeeded: boolean) {
364405
if (succeeded) {
365406
this.notificationsService.success(this.translateService.get('item.edit.' + this.messageKey + '.success'));
366-
this.router.navigate(['']);
407+
void this.router.navigate(['']);
367408
} else {
368409
this.notificationsService.error(this.translateService.get('item.edit.' + this.messageKey + '.error'));
369-
this.router.navigate([getItemEditRoute(this.item)]);
410+
void this.router.navigate([getItemEditRoute(this.item)]);
370411
}
371412
}
372413

0 commit comments

Comments
 (0)