mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
taskid 66076 Keep virtual metadata on item delete - tests & docs & small fixes
This commit is contained in:
@@ -1686,6 +1686,6 @@
|
||||
|
||||
"uploader.queue-length": "Queue length",
|
||||
|
||||
"virtual-metadata-modal.head": "Select the items for which you want to save the virtual metadata as real metadata",
|
||||
"virtual-metadata.delete-relationship.modal-head": "Select the items for which you want to save the virtual metadata as real metadata",
|
||||
}
|
||||
|
||||
|
@@ -99,7 +99,7 @@ export class EditRelationshipComponent implements OnChanges {
|
||||
).pipe(
|
||||
map((items: Item[]) =>
|
||||
items.map((item) => this.objectUpdatesService
|
||||
.isSelectedVirtualMetadataItem(this.url, this.relationship.id, item.uuid))
|
||||
.isSelectedVirtualMetadata(this.url, this.relationship.id, item.uuid))
|
||||
),
|
||||
switchMap((selection$) => observableCombineLatest(selection$)),
|
||||
map((selection: boolean[]) => {
|
||||
|
@@ -110,11 +110,14 @@ describe('ItemRelationshipsComponent', () => {
|
||||
relationships[1].rightItem = observableOf(new RemoteData(false, false, true, undefined, item));
|
||||
|
||||
fieldUpdate1 = {
|
||||
field: author1,
|
||||
field: relationships[0],
|
||||
changeType: undefined
|
||||
};
|
||||
fieldUpdate2 = {
|
||||
field: author2,
|
||||
field: Object.assign(
|
||||
relationships[1],
|
||||
{keepLeftVirtualMetadata: true, keepRightVirtualMetadata: false}
|
||||
),
|
||||
changeType: FieldChangeType.REMOVE
|
||||
};
|
||||
|
||||
@@ -130,12 +133,12 @@ describe('ItemRelationshipsComponent', () => {
|
||||
objectUpdatesService = jasmine.createSpyObj('objectUpdatesService',
|
||||
{
|
||||
getFieldUpdates: observableOf({
|
||||
[author1.uuid]: fieldUpdate1,
|
||||
[author2.uuid]: fieldUpdate2
|
||||
[relationships[0].uuid]: fieldUpdate1,
|
||||
[relationships[1].uuid]: fieldUpdate2
|
||||
}),
|
||||
getFieldUpdatesExclusive: observableOf({
|
||||
[author1.uuid]: fieldUpdate1,
|
||||
[author2.uuid]: fieldUpdate2
|
||||
[relationships[0].uuid]: fieldUpdate1,
|
||||
[relationships[1].uuid]: fieldUpdate2
|
||||
}),
|
||||
saveAddFieldUpdate: {},
|
||||
discardFieldUpdates: {},
|
||||
@@ -227,7 +230,7 @@ describe('ItemRelationshipsComponent', () => {
|
||||
});
|
||||
|
||||
it('it should delete the correct relationship', () => {
|
||||
expect(relationshipService.deleteRelationship).toHaveBeenCalledWith(relationships[1].uuid);
|
||||
expect(relationshipService.deleteRelationship).toHaveBeenCalledWith(relationships[1].uuid, 'left');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -116,8 +116,11 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent impl
|
||||
switchMap((relationships: Relationship[]) => {
|
||||
return this.objectUpdatesService.getFieldUpdatesExclusive(this.url, relationships) as Observable<FieldUpdates>
|
||||
}),
|
||||
map((fieldUpdates: FieldUpdates) => Object.values(fieldUpdates).filter((fieldUpdate: FieldUpdate) => fieldUpdate.changeType === FieldChangeType.REMOVE)),
|
||||
map((fieldUpdates: FieldUpdate[]) => fieldUpdates.map((fieldUpdate: FieldUpdate) => fieldUpdate.field) as DeleteRelationship[]),
|
||||
map((fieldUpdates: FieldUpdates) =>
|
||||
Object.values(fieldUpdates)
|
||||
.filter((fieldUpdate: FieldUpdate) => fieldUpdate.changeType === FieldChangeType.REMOVE)
|
||||
.map((fieldUpdate: FieldUpdate) => fieldUpdate.field as DeleteRelationship)
|
||||
),
|
||||
isNotEmptyOperator(),
|
||||
);
|
||||
removedRelationshipIDs$.pipe(
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<div>
|
||||
<div class="modal-header">{{'virtual-metadata-modal.head' | translate}}
|
||||
<div class="modal-header">{{'virtual-metadata.delete-relationship.modal-head' | translate}}
|
||||
<button type="button" class="close" (click)="close.emit()" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
|
@@ -48,15 +48,27 @@ export class VirtualMetadataComponent implements OnChanges {
|
||||
|
||||
getVirtualMetadata(relationship: Relationship, relatedItem: Item): VirtualMetadata[] {
|
||||
|
||||
return this.objectUpdatesService.getVirtualMetadataList(relationship, relatedItem);
|
||||
return 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));
|
||||
}
|
||||
|
||||
setSelectedVirtualMetadataItem(item: Item, selected: boolean) {
|
||||
this.objectUpdatesService.setSelectedVirtualMetadataItem(this.url, this.relationship.id, item.uuid, selected);
|
||||
this.objectUpdatesService.setSelectedVirtualMetadata(this.url, this.relationship.id, item.uuid, selected);
|
||||
}
|
||||
|
||||
isSelectedVirtualMetadataItem(item: Item): Observable<boolean> {
|
||||
return this.objectUpdatesService.isSelectedVirtualMetadataItem(this.url, this.relationship.id, item.uuid);
|
||||
return this.objectUpdatesService.isSelectedVirtualMetadata(this.url, this.relationship.id, item.uuid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -5,10 +5,11 @@ import {
|
||||
FieldChangeType,
|
||||
InitializeFieldsAction,
|
||||
ReinstateObjectUpdatesAction,
|
||||
RemoveFieldUpdateAction, RemoveObjectUpdatesAction,
|
||||
RemoveFieldUpdateAction, RemoveObjectUpdatesAction, SelectVirtualMetadataAction,
|
||||
SetEditableFieldUpdateAction, SetValidFieldUpdateAction
|
||||
} from './object-updates.actions';
|
||||
import { OBJECT_UPDATES_TRASH_PATH, objectUpdatesReducer } from './object-updates.reducer';
|
||||
import {Relationship} from "../../shared/item-relationships/relationship.model";
|
||||
|
||||
class NullAction extends RemoveFieldUpdateAction {
|
||||
type = null;
|
||||
@@ -44,6 +45,7 @@ const identifiable3 = {
|
||||
language: null,
|
||||
value: 'Unchanged value'
|
||||
};
|
||||
const relationship: Relationship = Object.assign(new Relationship, {uuid: 'test relationship uuid'});
|
||||
|
||||
const modDate = new Date(2010, 2, 11);
|
||||
const uuid = identifiable1.uuid;
|
||||
@@ -80,7 +82,9 @@ describe('objectUpdatesReducer', () => {
|
||||
}
|
||||
},
|
||||
lastModified: modDate,
|
||||
virtualMetadataSources: {},
|
||||
virtualMetadataSources: {
|
||||
[relationship.uuid]: {[identifiable1.uuid]: true}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -103,7 +107,10 @@ describe('objectUpdatesReducer', () => {
|
||||
isValid: true
|
||||
},
|
||||
},
|
||||
lastModified: modDate
|
||||
lastModified: modDate,
|
||||
virtualMetadataSources: {
|
||||
[relationship.uuid]: {[identifiable1.uuid]: true}
|
||||
},
|
||||
},
|
||||
[url + OBJECT_UPDATES_TRASH_PATH]: {
|
||||
fieldStates: {
|
||||
@@ -134,7 +141,10 @@ describe('objectUpdatesReducer', () => {
|
||||
changeType: FieldChangeType.ADD
|
||||
}
|
||||
},
|
||||
lastModified: modDate
|
||||
lastModified: modDate,
|
||||
virtualMetadataSources: {
|
||||
[relationship.uuid]: {[identifiable1.uuid]: true}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -196,6 +206,12 @@ describe('objectUpdatesReducer', () => {
|
||||
objectUpdatesReducer(testState, action);
|
||||
});
|
||||
|
||||
it('should perform the SELECT_VIRTUAL_METADATA action without affecting the previous state', () => {
|
||||
const action = new SelectVirtualMetadataAction(url, relationship.uuid, identifiable1.uuid, true);
|
||||
// testState has already been frozen above
|
||||
objectUpdatesReducer(testState, action);
|
||||
});
|
||||
|
||||
it('should initialize all fields when the INITIALIZE action is dispatched, based on the payload', () => {
|
||||
const action = new InitializeFieldsAction(url, [identifiable1, identifiable3], modDate);
|
||||
|
||||
|
@@ -58,14 +58,24 @@ export interface FieldUpdates {
|
||||
[uuid: string]: FieldUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* The states of all virtual metadata selections available for a single page, mapped by the relationship uuid
|
||||
*/
|
||||
export interface VirtualMetadataSources {
|
||||
[source: string]: VirtualMetadataSource
|
||||
}
|
||||
|
||||
/**
|
||||
* The selection of virtual metadata for a relationship, mapped by the uuid of either the item or the relationship type
|
||||
*/
|
||||
export interface VirtualMetadataSource {
|
||||
[uuid: string]: boolean,
|
||||
}
|
||||
|
||||
/**
|
||||
* A fieldupdate interface which represents a relationship selected to be deleted,
|
||||
* along with a selection of the virtual metadata to keep
|
||||
*/
|
||||
export interface DeleteRelationship extends Relationship {
|
||||
keepLeftVirtualMetadata: boolean,
|
||||
keepRightVirtualMetadata: boolean,
|
||||
@@ -192,7 +202,7 @@ function addFieldUpdate(state: any, action: AddFieldUpdateAction) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new update for a specific field to the store
|
||||
* Update the selected virtual metadata in the store
|
||||
* @param state The current state
|
||||
* @param action The action to perform on the current state
|
||||
*/
|
||||
|
@@ -4,13 +4,14 @@ import { ObjectUpdatesService } from './object-updates.service';
|
||||
import {
|
||||
DiscardObjectUpdatesAction,
|
||||
FieldChangeType,
|
||||
InitializeFieldsAction, ReinstateObjectUpdatesAction, RemoveFieldUpdateAction,
|
||||
InitializeFieldsAction, ReinstateObjectUpdatesAction, RemoveFieldUpdateAction, SelectVirtualMetadataAction,
|
||||
SetEditableFieldUpdateAction
|
||||
} from './object-updates.actions';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { Notification } from '../../../shared/notifications/models/notification.model';
|
||||
import { NotificationType } from '../../../shared/notifications/models/notification-type';
|
||||
import { OBJECT_UPDATES_TRASH_PATH } from './object-updates.reducer';
|
||||
import {Relationship} from "../../shared/item-relationships/relationship.model";
|
||||
|
||||
describe('ObjectUpdatesService', () => {
|
||||
let service: ObjectUpdatesService;
|
||||
@@ -22,6 +23,7 @@ describe('ObjectUpdatesService', () => {
|
||||
const identifiable2 = { uuid: '26cbb5ce-5786-4e57-a394-b9fcf8eaf241' };
|
||||
const identifiable3 = { uuid: 'c5d2c2f7-d757-48bf-84cc-8c9229c8407e' };
|
||||
const identifiables = [identifiable1, identifiable2];
|
||||
const relationship: Relationship = Object.assign(new Relationship, {uuid: 'test relationship uuid'});
|
||||
|
||||
const fieldUpdates = {
|
||||
[identifiable1.uuid]: { field: identifiable1Updated, changeType: FieldChangeType.UPDATE },
|
||||
@@ -38,7 +40,7 @@ describe('ObjectUpdatesService', () => {
|
||||
};
|
||||
|
||||
const objectEntry = {
|
||||
fieldStates, fieldUpdates, lastModified: modDate
|
||||
fieldStates, fieldUpdates, lastModified: modDate, virtualMetadataSources: {}
|
||||
};
|
||||
store = new Store<CoreState>(undefined, undefined, undefined);
|
||||
spyOn(store, 'dispatch');
|
||||
@@ -251,4 +253,10 @@ describe('ObjectUpdatesService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('setSelectedVirtualMetadata', () => {
|
||||
it('should dispatch a SELECT_VIRTUAL_METADATA action with the correct URL, relationship, identifiable and boolean', () => {
|
||||
service.setSelectedVirtualMetadata(url, relationship.uuid, identifiable1.uuid, true);
|
||||
expect(store.dispatch).toHaveBeenCalledWith(new SelectVirtualMetadataAction(url, relationship.uuid, identifiable1.uuid, true));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -204,24 +204,7 @@ export class ObjectUpdatesService {
|
||||
saveChangeFieldUpdate(url: string, field: Identifiable) {
|
||||
this.saveFieldUpdate(url, field, FieldChangeType.UPDATE);
|
||||
}
|
||||
|
||||
getVirtualMetadataList(relationship: Relationship, item: Item): VirtualMetadata[] {
|
||||
return Object.entries(item.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));
|
||||
}
|
||||
|
||||
isSelectedVirtualMetadataItem(url: string, relationship: string, item: string): Observable<boolean> {
|
||||
isSelectedVirtualMetadata(url: string, relationship: string, item: string): Observable<boolean> {
|
||||
|
||||
return this.store
|
||||
.pipe(
|
||||
@@ -231,13 +214,14 @@ export class ObjectUpdatesService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to dispatch an AddFieldUpdateAction to the store
|
||||
* Method to dispatch a SelectVirtualMetadataAction to the store
|
||||
* @param url The page's URL for which the changes are saved
|
||||
* @param field An updated field for the page's object
|
||||
* @param changeType The last type of change applied to this field
|
||||
* @param relationship the relationship for which virtual metadata is selected
|
||||
* @param uuid the selection identifier, can either be the item uuid or the relationship type uuid
|
||||
* @param selected whether or not to select the virtual metadata to be saved
|
||||
*/
|
||||
setSelectedVirtualMetadataItem(url: string, relationship: string, item: string, selected: boolean) {
|
||||
this.store.dispatch(new SelectVirtualMetadataAction(url, relationship, item, selected));
|
||||
setSelectedVirtualMetadata(url: string, relationship: string, uuid: string, selected: boolean) {
|
||||
this.store.dispatch(new SelectVirtualMetadataAction(url, relationship, uuid, selected));
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user