65717: Remove object updates on page url (only bundles now) and added support for tracking custom order changes, discard and reinstate

This commit is contained in:
Kristof De Langhe
2019-10-23 14:28:19 +02:00
parent 9113a08796
commit 7adb50a9b8
5 changed files with 60 additions and 23 deletions

View File

@@ -20,7 +20,6 @@ import { Item } from '../../../core/shared/item.model';
import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list';
import { Bundle } from '../../../core/shared/bundle.model';
import { CdkDragDrop } from '@angular/cdk/drag-drop';
@Component({
selector: 'ds-item-bitstreams',
@@ -85,13 +84,6 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme
this.notificationsPrefix = 'item.edit.bitstreams.notifications.';
}
/**
* Initialize the original fields for the object-updates-service
*/
initializeOriginalFields(): void {
this.objectUpdatesService.initialize(this.url, [], this.item.lastModified);
}
/**
* Update the item (and view) when it's removed in the request cache
* Also re-initialize the original fields and updates
@@ -166,7 +158,6 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme
* Request the object updates service to undo discarding all changes to this item
*/
reinstate() {
super.reinstate();
this.bundles$.pipe(take(1)).subscribe((bundles: Bundle[]) => {
bundles.forEach((bundle: Bundle) => {
this.objectUpdatesService.reinstateFieldUpdates(bundle.self);
@@ -174,6 +165,26 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme
});
}
/**
* Checks whether or not the object is currently reinstatable
*/
isReinstatable(): Observable<boolean> {
return this.bundles$.pipe(
switchMap((bundles: Bundle[]) => observableZip(...bundles.map((bundle: Bundle) => this.objectUpdatesService.isReinstatable(bundle.self)))),
map((reinstatable: boolean[]) => reinstatable.includes(true))
);
}
/**
* Checks whether or not there are currently updates for this object
*/
hasChanges(): Observable<boolean> {
return this.bundles$.pipe(
switchMap((bundles: Bundle[]) => observableZip(...bundles.map((bundle: Bundle) => this.objectUpdatesService.hasUpdates(bundle.self)))),
map((hasChanges: boolean[]) => hasChanges.includes(true))
);
}
/**
* De-cache the current item (it should automatically reload due to itemUpdateSubscription)
*/

View File

@@ -72,7 +72,6 @@ export class ItemEditBitstreamComponent implements OnChanges, OnInit {
* Sends a new remove update for this field to the object updates service
*/
remove(): void {
this.objectUpdatesService.saveRemoveFieldUpdate(this.url, this.bitstream);
this.objectUpdatesService.saveRemoveFieldUpdate(this.bundleUrl, this.bitstream);
}
@@ -80,7 +79,6 @@ export class ItemEditBitstreamComponent implements OnChanges, OnInit {
* Cancels the current update for this field in the object updates service
*/
undo(): void {
this.objectUpdatesService.removeSingleFieldUpdate(this.url, this.bitstream.uuid);
this.objectUpdatesService.removeSingleFieldUpdate(this.bundleUrl, this.bitstream.uuid);
}

View File

@@ -39,7 +39,7 @@ export class InitializeFieldsAction implements Action {
url: string,
fields: Identifiable[],
lastModified: Date,
customOrder: string[]
order: string[]
};
/**
@@ -49,15 +49,15 @@ export class InitializeFieldsAction implements Action {
* the unique url of the page for which the fields are being initialized
* @param fields The identifiable fields of which the updates are kept track of
* @param lastModified The last modified date of the object that belongs to the page
* @param customOrder A custom order to keep track of objects moving around
* @param order A custom order to keep track of objects moving around
*/
constructor(
url: string,
fields: Identifiable[],
lastModified: Date,
customOrder: string[] = []
order: string[] = []
) {
this.payload = { url, fields, lastModified, customOrder };
this.payload = { url, fields, lastModified, order };
}
}

View File

@@ -55,6 +55,15 @@ export interface FieldUpdates {
[uuid: string]: FieldUpdate;
}
/**
* A custom order given to the list of objects
*/
export interface CustomOrder {
initialOrder: string[],
newOrder: string[],
changed: boolean
}
/**
* The updated state of a single page
*/
@@ -62,7 +71,7 @@ export interface ObjectUpdatesEntry {
fieldStates: FieldStates;
fieldUpdates: FieldUpdates
lastModified: Date;
customOrder: string[]
customOrder: CustomOrder
}
/**
@@ -137,7 +146,7 @@ function initializeFieldsUpdate(state: any, action: InitializeFieldsAction) {
const url: string = action.payload.url;
const fields: Identifiable[] = action.payload.fields;
const lastModifiedServer: Date = action.payload.lastModified;
const customorder = action.payload.customOrder;
const order = action.payload.order;
const fieldStates = createInitialFieldStates(fields);
const newPageState = Object.assign(
{},
@@ -145,7 +154,7 @@ function initializeFieldsUpdate(state: any, action: InitializeFieldsAction) {
{ fieldStates: fieldStates },
{ fieldUpdates: {} },
{ lastModified: lastModifiedServer },
{ customOrder: customorder }
{ customOrder: { initialOrder: order, newOrder: order, changed: false } }
);
return Object.assign({}, state, { [url]: newPageState });
}
@@ -213,9 +222,19 @@ function discardObjectUpdatesFor(url: string, state: any) {
}
});
const newCustomOrder = Object.assign({}, pageState.customOrder);
if (pageState.customOrder.changed) {
const initialOrder = pageState.customOrder.initialOrder;
if (isNotEmpty(initialOrder)) {
newCustomOrder.newOrder = initialOrder;
newCustomOrder.changed = false;
}
}
const discardedPageState = Object.assign({}, pageState, {
fieldUpdates: {},
fieldStates: newFieldStates
fieldStates: newFieldStates,
customOrder: newCustomOrder
});
return Object.assign({}, state, { [url]: discardedPageState }, { [url + OBJECT_UPDATES_TRASH_PATH]: pageState });
}
@@ -381,10 +400,19 @@ function moveFieldUpdate(state: any, action: MoveFieldUpdateAction) {
const to = action.payload.to;
const pageState: ObjectUpdatesEntry = state[url];
const customOrder = [...pageState.customOrder];
const initialOrder = pageState.customOrder.initialOrder;
const customOrder = [...pageState.customOrder.newOrder];
if (isNotEmpty(customOrder) && isNotEmpty(customOrder[from]) && isNotEmpty(customOrder[to])) {
moveItemInArray(customOrder, from, to);
}
return Object.assign({}, state, { [url]: Object.assign({}, pageState, { customOrder: customOrder }) })
let changed = false;
initialOrder.forEach((id: string, index: number) => {
if (id !== customOrder[index]) {
changed = true;
return;
}
});
return Object.assign({}, state, { [url]: Object.assign({}, pageState, { customOrder: Object.assign({}, pageState.customOrder, { newOrder: customOrder, changed: changed }) }) })
}

View File

@@ -138,7 +138,7 @@ export class ObjectUpdatesService {
const objectUpdates = this.getObjectEntry(url);
return objectUpdates.pipe(map((objectEntry) => {
const fieldUpdates: FieldUpdates = {};
for (const uuid of objectEntry.customOrder) {
for (const uuid of objectEntry.customOrder.newOrder) {
let fieldUpdate = objectEntry.fieldUpdates[uuid];
if (isEmpty(fieldUpdate)) {
const identifiable = initialFields.find((object: Identifiable) => object.uuid === uuid);
@@ -315,7 +315,7 @@ export class ObjectUpdatesService {
* @param url The page's url to check for in the store
*/
hasUpdates(url: string): Observable<boolean> {
return this.getObjectEntry(url).pipe(map((objectEntry) => hasValue(objectEntry) && isNotEmpty(objectEntry.fieldUpdates)));
return this.getObjectEntry(url).pipe(map((objectEntry) => hasValue(objectEntry) && (isNotEmpty(objectEntry.fieldUpdates) || objectEntry.customOrder.changed)));
}
/**