diff --git a/src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts b/src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts index d499153cce..137a6d7178 100644 --- a/src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts +++ b/src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts @@ -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 { + 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 { + 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) */ diff --git a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.ts b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.ts index b322f12df1..fb74a6261b 100644 --- a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.ts +++ b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream/item-edit-bitstream.component.ts @@ -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); } diff --git a/src/app/core/data/object-updates/object-updates.actions.ts b/src/app/core/data/object-updates/object-updates.actions.ts index 2c7bbdfdf1..d48d66dbf8 100644 --- a/src/app/core/data/object-updates/object-updates.actions.ts +++ b/src/app/core/data/object-updates/object-updates.actions.ts @@ -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 }; } } diff --git a/src/app/core/data/object-updates/object-updates.reducer.ts b/src/app/core/data/object-updates/object-updates.reducer.ts index acef2542a5..7350ba766f 100644 --- a/src/app/core/data/object-updates/object-updates.reducer.ts +++ b/src/app/core/data/object-updates/object-updates.reducer.ts @@ -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 }) }) }) } diff --git a/src/app/core/data/object-updates/object-updates.service.ts b/src/app/core/data/object-updates/object-updates.service.ts index 2ad1b9aec5..34aa74c576 100644 --- a/src/app/core/data/object-updates/object-updates.service.ts +++ b/src/app/core/data/object-updates/object-updates.service.ts @@ -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 { - 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))); } /**