taskid 66076 Keep virtual metadata on item delete - tests & docs & small fixes

This commit is contained in:
Samuel
2019-12-03 16:52:41 +01:00
parent 2eac2a20bb
commit 891415daae
10 changed files with 81 additions and 45 deletions

View File

@@ -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",
}

View File

@@ -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[]) => {

View File

@@ -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');
});
});
});

View File

@@ -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(

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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
*/

View File

@@ -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));
});
});
});

View File

@@ -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));
}
/**