From de0992bf85e95014671d4bc749907591d29e0a35 Mon Sep 17 00:00:00 2001 From: Samuel Date: Fri, 10 Jan 2020 16:00:06 +0100 Subject: [PATCH 1/5] PR-533 Virtual metadata on item delete --- resources/i18n/en.json5 | 8 +- .../item-delete/item-delete.component.html | 96 ++++++ .../item-delete/item-delete.component.spec.ts | 112 +++++-- .../item-delete/item-delete.component.ts | 313 +++++++++++++++++- src/app/core/data/data.service.ts | 13 +- 5 files changed, 503 insertions(+), 39 deletions(-) create mode 100644 src/app/+item-page/edit-item-page/item-delete/item-delete.component.html diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index 16b4fa1dd9..0cb3a8e135 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -813,7 +813,7 @@ "item.edit.tabs.relationships.head": "Item Relationships", - "item.edit.tabs.relationships.title": "Item Edit - Relationships", + "item.edit.tabs.relationships.title": "Item Edit - Relationships", "item.edit.tabs.status.buttons.authorizations.button": "Authorizations...", @@ -1853,12 +1853,16 @@ "uploader.drag-message": "Drag & Drop your files here", - "uploader.or": ", or ", + "uploader.or": ", or", "uploader.processing": "Processing", "uploader.queue-length": "Queue length", + "virtual-metadata.delete-item.info": "Select the types for which you want to save the virtual metadata as real metadata", + + "virtual-metadata.delete-item.modal-head": "The virtual metadata of this relation", + "virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata", } diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.html b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.html new file mode 100644 index 0000000000..baaa239ba9 --- /dev/null +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.html @@ -0,0 +1,96 @@ +
+
+
+ +

{{headerMessage | translate: {id: item.handle} }}

+

{{descriptionMessage | translate}}

+ + + + +
+ {{'virtual-metadata.delete-item.info' | translate}} +
+ +
+ +
+ +
+ +
+ +
+
+ {{getRelationshipMessageKey(getLabel(type) | async) | translate}} +
+
+ + + + +
+
+ +
+
+ + +
+ + +
+
+ +
+
+
+ +
+ +
+ +
+ + + + +
+
+
diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts index 82d03f1f1b..dbf2bd0fa9 100644 --- a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts @@ -1,44 +1,70 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Item } from '../../../core/shared/item.model'; -import { RouterStub } from '../../../shared/testing/router-stub'; -import { of as observableOf } from 'rxjs'; -import { RemoteData } from '../../../core/data/remote-data'; -import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; -import { RouterTestingModule } from '@angular/router/testing'; -import { TranslateModule } from '@ngx-translate/core'; -import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; -import { ActivatedRoute, Router } from '@angular/router'; -import { ItemDataService } from '../../../core/data/item-data.service'; -import { NotificationsService } from '../../../shared/notifications/notifications.service'; -import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; -import { By } from '@angular/platform-browser'; -import { ItemDeleteComponent } from './item-delete.component'; -import { getItemEditPath } from '../../item-page-routing.module'; -import { RestResponse } from '../../../core/cache/response.models'; -import { createSuccessfulRemoteDataObject } from '../../../shared/testing/utils'; +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; +import {Item} from '../../../core/shared/item.model'; +import {RouterStub} from '../../../shared/testing/router-stub'; +import {of as observableOf} from 'rxjs'; +import {NotificationsServiceStub} from '../../../shared/testing/notifications-service-stub'; +import {CommonModule} from '@angular/common'; +import {FormsModule} from '@angular/forms'; +import {RouterTestingModule} from '@angular/router/testing'; +import {TranslateModule} from '@ngx-translate/core'; +import {NgbModule} from '@ng-bootstrap/ng-bootstrap'; +import {ActivatedRoute, Router} from '@angular/router'; +import {ItemDataService} from '../../../core/data/item-data.service'; +import {NotificationsService} from '../../../shared/notifications/notifications.service'; +import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; +import {By} from '@angular/platform-browser'; +import {ItemDeleteComponent} from './item-delete.component'; +import {getItemEditPath} from '../../item-page-routing.module'; +import {createSuccessfulRemoteDataObject} from '../../../shared/testing/utils'; +import {VarDirective} from '../../../shared/utils/var.directive'; +import {ObjectUpdatesService} from '../../../core/data/object-updates/object-updates.service'; +import {RelationshipService} from '../../../core/data/relationship.service'; +import {RelationshipType} from '../../../core/shared/item-relationships/relationship-type.model'; +import {RemoteData} from '../../../core/data/remote-data'; +import {PaginatedList} from '../../../core/data/paginated-list'; +import {PageInfo} from '../../../core/shared/page-info.model'; +import {EntityTypeService} from '../../../core/data/entity-type.service'; let comp: ItemDeleteComponent; let fixture: ComponentFixture; let mockItem; +let type1; +let type2; +let types; let itemPageUrl; let routerStub; let mockItemDataService: ItemDataService; let routeStub; +let objectUpdatesServiceStub; +let relationshipService; +let entityTypeService; let notificationsServiceStub; +let typesSelection; describe('ItemDeleteComponent', () => { beforeEach(async(() => { mockItem = Object.assign(new Item(), { id: 'fake-id', + uuid: 'fake-uuid', handle: 'fake/handle', lastModified: '2018', isWithdrawn: true }); + type1 = Object.assign(new RelationshipType(), { + id: '1', + uuid: 'type-1', + }); + + type2 = Object.assign(new RelationshipType(), { + id: '2', + uuid: 'type-2', + }); + + types = [type1, type2]; + itemPageUrl = `fake-url/${mockItem.id}`; routerStub = Object.assign(new RouterStub(), { url: `${itemPageUrl}/edit` @@ -54,16 +80,57 @@ describe('ItemDeleteComponent', () => { }) }; + typesSelection = { + type1: false, + type2: true, + }; + + entityTypeService = jasmine.createSpyObj('entityTypeService', + { + getEntityTypeByLabel: observableOf(new RemoteData( + false, + false, + true, + null, + {}, + )), + getEntityTypeRelationships: observableOf(new RemoteData( + false, + false, + true, + null, + new PaginatedList(new PageInfo(), [{}]), + )), + } + ); + + objectUpdatesServiceStub = { + initialize: () => { + // do nothing + }, + isSelectedVirtualMetadata: (type) => observableOf(typesSelection[type]), + }; + + relationshipService = jasmine.createSpyObj('relationshipService', + { + getItemRelationshipTypesArray: observableOf([type1, type2, type2]), + getItemRelationshipsArray: observableOf([]), + } + ); + notificationsServiceStub = new NotificationsServiceStub(); TestBed.configureTestingModule({ imports: [CommonModule, FormsModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()], - declarations: [ItemDeleteComponent], + declarations: [ItemDeleteComponent, VarDirective], providers: [ { provide: ActivatedRoute, useValue: routeStub }, { provide: Router, useValue: routerStub }, { provide: ItemDataService, useValue: mockItemDataService }, { provide: NotificationsService, useValue: notificationsServiceStub }, + { provide: ObjectUpdatesService, useValue: objectUpdatesServiceStub }, + { provide: RelationshipService, useValue: relationshipService }, + { provide: EntityTypeService, useValue: entityTypeService }, ], schemas: [ CUSTOM_ELEMENTS_SCHEMA ] @@ -91,7 +158,8 @@ describe('ItemDeleteComponent', () => { it('should call delete function from the ItemDataService', () => { spyOn(comp, 'notify'); comp.performAction(); - expect(mockItemDataService.delete).toHaveBeenCalledWith(mockItem); + expect(mockItemDataService.delete) + .toHaveBeenCalledWith(mockItem, types.filter((type) => typesSelection[type]).map((type) => type.id)); expect(comp.notify).toHaveBeenCalled(); }); }); diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts index 2700b45475..d427ce2b34 100644 --- a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts @@ -1,29 +1,316 @@ -import { Component } from '@angular/core'; -import { first } from 'rxjs/operators'; -import { AbstractSimpleItemActionComponent } from '../simple-item-action/abstract-simple-item-action.component'; -import { getItemEditPath } from '../../item-page-routing.module'; -import { RestResponse } from '../../../core/cache/response.models'; +import {Component, Input, OnInit} from '@angular/core'; +import {filter, first, map, switchMap, take} from 'rxjs/operators'; +import {AbstractSimpleItemActionComponent} from '../simple-item-action/abstract-simple-item-action.component'; +import {getItemEditPath} from '../../item-page-routing.module'; +import {NgbModal, NgbModalRef} from '@ng-bootstrap/ng-bootstrap'; +import {combineLatest as observableCombineLatest, combineLatest, Observable} from 'rxjs'; +import {RelationshipType} from '../../../core/shared/item-relationships/relationship-type.model'; +import {VirtualMetadata} from '../virtual-metadata/virtual-metadata.component'; +import {Relationship} from '../../../core/shared/item-relationships/relationship.model'; +import {getRemoteDataPayload, getSucceededRemoteData} from '../../../core/shared/operators'; +import {hasValue, isNotEmpty} from '../../../shared/empty.util'; +import {Item} from '../../../core/shared/item.model'; +import {MetadataValue} from '../../../core/shared/metadata.models'; +import {ViewMode} from '../../../core/shared/view-mode.model'; +import {ActivatedRoute, Router} from '@angular/router'; +import {NotificationsService} from '../../../shared/notifications/notifications.service'; +import {ItemDataService} from '../../../core/data/item-data.service'; +import {TranslateService} from '@ngx-translate/core'; +import {ObjectUpdatesService} from '../../../core/data/object-updates/object-updates.service'; +import {RelationshipService} from '../../../core/data/relationship.service'; +import {EntityTypeService} from '../../../core/data/entity-type.service'; @Component({ selector: 'ds-item-delete', - templateUrl: '../simple-item-action/abstract-simple-item-action.component.html' + templateUrl: '../item-delete/item-delete.component.html' }) /** * Component responsible for rendering the item delete page */ -export class ItemDeleteComponent extends AbstractSimpleItemActionComponent { +export class ItemDeleteComponent + extends AbstractSimpleItemActionComponent + implements OnInit { + + /** + * The current url of this page + */ + @Input() url: string; protected messageKey = 'delete'; /** - * Perform the delete action to the item + * The view-mode we're currently on + */ + viewMode = ViewMode.ListElement; + + /** + * A list of the relationship types for which this item has relations as an observable. + * The list doesn't contain duplicates. + */ + types$: Observable; + + /** + * A map which stores the relationships of this item for each type as observable lists + */ + relationships$: Map> + = new Map>(); + + /** + * A map which stores the related item of each relationship of this item as an observable + */ + relatedItems$: Map> = new Map>(); + + /** + * A map which stores the virtual metadata (of the related) item corresponding to each relationship of this item + * as an observable list + */ + virtualMetadata$: Map> = new Map>(); + + /** + * Reference to NgbModal + */ + public modalRef: NgbModalRef; + + constructor(protected route: ActivatedRoute, + protected router: Router, + protected notificationsService: NotificationsService, + protected itemDataService: ItemDataService, + protected translateService: TranslateService, + protected modalService: NgbModal, + protected objectUpdatesService: ObjectUpdatesService, + protected relationshipService: RelationshipService, + protected entityTypeService: EntityTypeService, + ) { + super( + route, + router, + notificationsService, + itemDataService, + translateService, + ); + } + + /** + * Set up and initialize all fields + */ + ngOnInit() { + + super.ngOnInit(); + this.url = this.router.url; + + this.types$ = this.entityTypeService.getEntityTypeByLabel( + this.item.firstMetadataValue('relationship.type') + ).pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + switchMap((entityType) => this.entityTypeService.getEntityTypeRelationships(entityType.id)), + getSucceededRemoteData(), + getRemoteDataPayload(), + map((relationshipTypes) => relationshipTypes.page), + map((types) => types.reduce((includedTypes, type) => { + if (!includedTypes.some((includedType) => includedType.id === type.id)) { + return [...includedTypes, type]; + } else { + return includedTypes; + } + }, [])), + ); + + this.types$.pipe( + take(1), + ).subscribe((types) => + this.objectUpdatesService.initialize(this.url, types, this.item.lastModified) + ); + } + + /** + * Open the modal which lists the virtual metadata of a relation + * @param content the html content of the modal + */ + openVirtualMetadataModal(content: any) { + this.modalRef = this.modalService.open(content); + } + + /** + * Close the modal which lists the virtual metadata of a relation + */ + closeVirtualMetadataModal() { + this.modalRef.close(); + } + + /** + * Get the i18n message key for a relationship + * @param label The relationship type's label + */ + getRelationshipMessageKey(label: string): string { + if (hasValue(label) && label.indexOf('Of') > -1) { + return `relationships.${label.substring(0, label.indexOf('Of') + 2)}` + } else { + return label; + } + } + + /** + * Get the relationship type label relevant for this item as an observable + * @param relationshipType the relationship type to get the label for + */ + getLabel(relationshipType: RelationshipType): Observable { + + return this.getRelationships(relationshipType).pipe( + switchMap((relationships) => + this.isLeftItem(relationships[0]).pipe( + map((isLeftItem) => isLeftItem ? relationshipType.leftwardType : relationshipType.rightwardType), + ) + ), + ) + } + + /** + * Get the relationships of this item with a given type as an observable + * @param relationshipType the relationship type to filter the item's relationships on + */ + getRelationships(relationshipType: RelationshipType): Observable { + + if (!this.relationships$.has(relationshipType)) { + this.relationships$.set( + relationshipType, + this.relationshipService.getItemRelationshipsArray(this.item).pipe( + // filter on type + switchMap((relationships) => + observableCombineLatest( + relationships.map((relationship) => this.getRelationshipType(relationship)) + ).pipe( + map((types) => relationships.filter( + (relationship, index) => relationshipType.id === types[index].id + )), + ) + ), + ) + ); + } + + return this.relationships$.get(relationshipType); + } + + /** + * Get the type of a given relationship as an observable + * @param relationship the relationship to get the type for + */ + private getRelationshipType(relationship: Relationship): Observable { + + return relationship.relationshipType.pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + filter((relationshipType: RelationshipType) => hasValue(relationshipType) && isNotEmpty(relationshipType.uuid)) + ); + } + + /** + * Get the item this item is related to through a given relationship as an observable + * @param relationship the relationship to get the other item for + */ + getRelatedItem(relationship: Relationship): Observable { + + if (!this.relatedItems$.has(relationship)) { + + this.relatedItems$.set( + relationship, + this.isLeftItem(relationship).pipe( + switchMap((isLeftItem) => isLeftItem ? relationship.rightItem : relationship.leftItem), + getSucceededRemoteData(), + getRemoteDataPayload(), + ), + ); + } + + return this.relatedItems$.get(relationship); + } + + /** + * Get the virtual metadata for a given relationship of the related item. + * @param relationship the relationship to get the virtual metadata for + */ + getVirtualMetadata(relationship: Relationship): Observable { + + if (!this.virtualMetadata$.has(relationship)) { + + this.virtualMetadata$.set( + relationship, + this.getRelatedItem(relationship).pipe( + map((relatedItem) => + Object.entries(relatedItem.metadata) + .map(([key, value]) => value + .filter((metadata: MetadataValue) => + metadata.authority && metadata.authority.endsWith(relationship.id)) + .map((metadata: MetadataValue) => { + return { + metadataField: key, + metadataValue: metadata, + } + })) + .reduce((previous, current) => previous.concat(current)) + ), + ) + ); + } + + return this.virtualMetadata$.get(relationship); + } + + /** + * Check whether this item is the left item of a given relationship, as an observable boolean + * @param relationship the relationship for which to check whether this item is the left item + */ + private isLeftItem(relationship: Relationship): Observable { + + return relationship.leftItem.pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + filter((item: Item) => hasValue(item) && isNotEmpty(item.uuid)), + map((leftItem) => leftItem.uuid === this.item.uuid) + ); + } + + /** + * Check whether a given relationship type is selected to save the corresponding virtual metadata + * @param type the relationship type for which to check whether it is selected + */ + isSelected(type: RelationshipType): Observable { + return this.objectUpdatesService.isSelectedVirtualMetadata(this.url, this.item.uuid, type.uuid); + } + + /** + * Select/deselect a given relationship type to save the corresponding virtual metadata + * @param type the relationship type to select/deselect + * @param selected whether the type should be selected + */ + setSelected(type: RelationshipType, selected: boolean): void { + this.objectUpdatesService.setSelectedVirtualMetadata(this.url, this.item.uuid, type.uuid, selected); + } + + /** + * Perform the delete operation */ performAction() { - this.itemDataService.delete(this.item).pipe(first()).subscribe( - (succeeded: boolean) => { - this.notify(succeeded); - } - ); + + this.types$.pipe( + switchMap((types) => + combineLatest( + types.map((type) => this.isSelected(type)) + ).pipe( + map((selection) => types.filter( + (type, index) => selection[index] + )), + map((selectedTypes) => selectedTypes.map((type) => type.id)), + ) + ), + ).subscribe((types) => { + this.itemDataService.delete(this.item, types).pipe(first()).subscribe( + (succeeded: boolean) => { + this.notify(succeeded); + } + ); + }); } /** diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 997ccec49f..2872a4083c 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -305,9 +305,11 @@ export abstract class DataService { /** * Delete an existing DSpace Object on the server * @param dso The DSpace Object to be removed - * Return an observable that emits true when the deletion was successful, false when it failed + * @param copyVirtualMetadata (optional parameter) the identifiers of the relationship types for which the virtual + * metadata should be saved as real metadata + * @return an observable that emits true when the deletion was successful, false when it failed */ - delete(dso: T): Observable { + delete(dso: T, copyVirtualMetadata?: string[]): Observable { const requestId = this.requestService.generateRequestId(); const hrefObs = this.halService.getEndpoint(this.linkPath).pipe( @@ -316,6 +318,13 @@ export abstract class DataService { hrefObs.pipe( find((href: string) => hasValue(href)), map((href: string) => { + if (copyVirtualMetadata) { + copyVirtualMetadata.forEach((id) => + href += (href.includes('?') ? '&' : '?') + + 'copyVirtualMetadata=' + + id + ); + } const request = new DeleteByIDRequest(requestId, href, dso.uuid); this.requestService.configure(request); }) From b352690ccab57f68c97a2c1de7fb32f89989428a Mon Sep 17 00:00:00 2001 From: Samuel Date: Tue, 28 Jan 2020 15:35:55 +0100 Subject: [PATCH 2/5] Virtual metadata on item delete - filter relationship types without relationships --- .../item-delete/item-delete.component.ts | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts index d427ce2b34..6fe44c109b 100644 --- a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts @@ -107,13 +107,20 @@ export class ItemDeleteComponent getSucceededRemoteData(), getRemoteDataPayload(), map((relationshipTypes) => relationshipTypes.page), - map((types) => types.reduce((includedTypes, type) => { - if (!includedTypes.some((includedType) => includedType.id === type.id)) { - return [...includedTypes, type]; - } else { - return includedTypes; - } - }, [])), + switchMap((types) => + combineLatest(types.map((type) => this.getRelationships(type))).pipe( + map((relationships) => + types.reduce((includedTypes, type, index) => { + if (!includedTypes.some((includedType) => includedType.id === type.id) + && !(relationships[index].length === 0)) { + return [...includedTypes, type]; + } else { + return includedTypes; + } + }, []) + ), + ) + ), ); this.types$.pipe( From 0387c5f15b5f6e53eb732e12283433144770f6fe Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 29 Jan 2020 12:27:41 +0100 Subject: [PATCH 3/5] Virtual metadata on item delete - filter relationship types without relationships - fix tests --- .../item-delete/item-delete.component.spec.ts | 69 +++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts index dbf2bd0fa9..00ae038dae 100644 --- a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts @@ -1,4 +1,6 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing'; +import { ItemType } from '../../../core/shared/item-relationships/item-type.model'; +import { Relationship } from '../../../core/shared/item-relationships/relationship.model'; import {Item} from '../../../core/shared/item.model'; import {RouterStub} from '../../../shared/testing/router-stub'; import {of as observableOf} from 'rxjs'; @@ -29,9 +31,11 @@ let comp: ItemDeleteComponent; let fixture: ComponentFixture; let mockItem; +let itemType; let type1; let type2; let types; +let relationships; let itemPageUrl; let routerStub; let mockItemDataService: ItemDataService; @@ -53,6 +57,11 @@ describe('ItemDeleteComponent', () => { isWithdrawn: true }); + itemType = Object.assign(new ItemType(), { + id: 'itemType', + uuid: 'itemType', + }); + type1 = Object.assign(new RelationshipType(), { id: '1', uuid: 'type-1', @@ -65,6 +74,59 @@ describe('ItemDeleteComponent', () => { types = [type1, type2]; + relationships = [ + Object.assign(new Relationship(), { + id: '1', + uuid: 'relationship-1', + relationshipType: observableOf(new RemoteData( + false, + false, + true, + null, + type1 + )), + leftItem: observableOf(new RemoteData( + false, + false, + true, + null, + mockItem, + )), + rightItem: observableOf(new RemoteData( + false, + false, + true, + null, + Object.assign(new Item(), {}) + )), + }), + Object.assign(new Relationship(), { + id: '2', + uuid: 'relationship-2', + relationshipType: observableOf(new RemoteData( + false, + false, + true, + null, + type2 + )), + leftItem: observableOf(new RemoteData( + false, + false, + true, + null, + mockItem, + )), + rightItem: observableOf(new RemoteData( + false, + false, + true, + null, + Object.assign(new Item(), {}) + )), + }), + ]; + itemPageUrl = `fake-url/${mockItem.id}`; routerStub = Object.assign(new RouterStub(), { url: `${itemPageUrl}/edit` @@ -92,14 +154,14 @@ describe('ItemDeleteComponent', () => { false, true, null, - {}, + itemType, )), getEntityTypeRelationships: observableOf(new RemoteData( false, false, true, null, - new PaginatedList(new PageInfo(), [{}]), + new PaginatedList(new PageInfo(), types), )), } ); @@ -113,8 +175,7 @@ describe('ItemDeleteComponent', () => { relationshipService = jasmine.createSpyObj('relationshipService', { - getItemRelationshipTypesArray: observableOf([type1, type2, type2]), - getItemRelationshipsArray: observableOf([]), + getItemRelationshipsArray: observableOf(relationships), } ); From d0680e2aa87106c96f52bce98bee325b891b83a1 Mon Sep 17 00:00:00 2001 From: Samuel Date: Thu, 30 Jan 2020 15:33:01 +0100 Subject: [PATCH 4/5] delete codestyle --- src/Typescript-codestyle.xml | 50 ------------------------------------ 1 file changed, 50 deletions(-) delete mode 100644 src/Typescript-codestyle.xml diff --git a/src/Typescript-codestyle.xml b/src/Typescript-codestyle.xml deleted file mode 100644 index 04358bf0c0..0000000000 --- a/src/Typescript-codestyle.xml +++ /dev/null @@ -1,50 +0,0 @@ - - From db7ecb0f53f1d49e9c8b352bb959c35c980b8a93 Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 5 Feb 2020 16:28:43 +0100 Subject: [PATCH 5/5] safety check --- .../item-delete/item-delete.component.html | 108 +++++++++--------- 1 file changed, 55 insertions(+), 53 deletions(-) diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.html b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.html index baaa239ba9..5e7297409b 100644 --- a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.html +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.html @@ -8,74 +8,76 @@ -
+
+ {{'virtual-metadata.delete-item.info' | translate}} -
-
+
-
+
-
- -
+
+ +
-
-
- {{getRelationshipMessageKey(getLabel(type) | async) | translate}} -
-
- +
+
+ {{getRelationshipMessageKey(getLabel(type) | async) | translate}} +
+
+ - - -
-
- -
-
- - -
- -
+