mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
65717: Ability to discard all field-updates at once (fixes discard and reinstate issues)
This commit is contained in:
@@ -157,13 +157,8 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme
|
||||
* Shows a notification to remind the user that they can undo this
|
||||
*/
|
||||
discard() {
|
||||
super.discard();
|
||||
const undoNotification = this.notificationsService.info(this.getNotificationTitle('discarded'), this.getNotificationContent('discarded'), {timeOut: this.discardTimeOut});
|
||||
this.bundles$.pipe(take(1)).subscribe((bundles: Bundle[]) => {
|
||||
bundles.forEach((bundle: Bundle) => {
|
||||
this.objectUpdatesService.discardFieldUpdates(bundle.self, undoNotification);
|
||||
});
|
||||
});
|
||||
this.objectUpdatesService.discardAllFieldUpdates(this.url, undoNotification);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -26,6 +26,11 @@ export class ItemEditBitstreamBundleComponent implements OnInit {
|
||||
*/
|
||||
@Input() bundle: Bundle;
|
||||
|
||||
/**
|
||||
* The current url of this page
|
||||
*/
|
||||
@Input() url: string;
|
||||
|
||||
/**
|
||||
* The updates to the current bundle
|
||||
*/
|
||||
|
@@ -14,6 +14,7 @@ export const ObjectUpdatesActionTypes = {
|
||||
DISCARD: type('dspace/core/cache/object-updates/DISCARD'),
|
||||
REINSTATE: type('dspace/core/cache/object-updates/REINSTATE'),
|
||||
REMOVE: type('dspace/core/cache/object-updates/REMOVE'),
|
||||
REMOVE_ALL: type('dspace/core/cache/object-updates/REMOVE_ALL'),
|
||||
REMOVE_FIELD: type('dspace/core/cache/object-updates/REMOVE_FIELD'),
|
||||
};
|
||||
|
||||
@@ -144,7 +145,8 @@ export class DiscardObjectUpdatesAction implements Action {
|
||||
type = ObjectUpdatesActionTypes.DISCARD;
|
||||
payload: {
|
||||
url: string,
|
||||
notification: INotification
|
||||
notification: INotification,
|
||||
discardAll: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -153,12 +155,14 @@ export class DiscardObjectUpdatesAction implements Action {
|
||||
* @param url
|
||||
* the unique url of the page for which the changes should be discarded
|
||||
* @param notification The notification that is raised when changes are discarded
|
||||
* @param discardAll discard all
|
||||
*/
|
||||
constructor(
|
||||
url: string,
|
||||
notification: INotification
|
||||
notification: INotification,
|
||||
discardAll = false
|
||||
) {
|
||||
this.payload = { url, notification };
|
||||
this.payload = { url, notification, discardAll };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +210,13 @@ export class RemoveObjectUpdatesAction implements Action {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An ngrx action to remove all previously discarded updates in the ObjectUpdates state
|
||||
*/
|
||||
export class RemoveAllObjectUpdatesAction implements Action {
|
||||
type = ObjectUpdatesActionTypes.REMOVE_ALL;
|
||||
}
|
||||
|
||||
/**
|
||||
* An ngrx action to remove a single field update in the ObjectUpdates state for a certain page url and field uuid
|
||||
*/
|
||||
|
@@ -3,12 +3,12 @@ import { Actions, Effect, ofType } from '@ngrx/effects';
|
||||
import {
|
||||
DiscardObjectUpdatesAction,
|
||||
ObjectUpdatesAction,
|
||||
ObjectUpdatesActionTypes,
|
||||
ObjectUpdatesActionTypes, RemoveAllObjectUpdatesAction,
|
||||
RemoveObjectUpdatesAction
|
||||
} from './object-updates.actions';
|
||||
import { delay, filter, map, switchMap, take, tap } from 'rxjs/operators';
|
||||
import { of as observableOf, race as observableRace, Subject } from 'rxjs';
|
||||
import { hasNoValue } from '../../../shared/empty.util';
|
||||
import { hasNoValue, hasValue } from '../../../shared/empty.util';
|
||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||
import { INotification } from '../../../shared/notifications/models/notification.model';
|
||||
import {
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
NotificationsActionTypes,
|
||||
RemoveNotificationAction
|
||||
} from '../../../shared/notifications/notifications.actions';
|
||||
import { Action } from '@ngrx/store';
|
||||
|
||||
/**
|
||||
* NGRX effects for ObjectUpdatesActions
|
||||
@@ -53,13 +54,14 @@ export class ObjectUpdatesEffects {
|
||||
.pipe(
|
||||
ofType(...Object.values(ObjectUpdatesActionTypes)),
|
||||
map((action: ObjectUpdatesAction) => {
|
||||
if (hasValue(action.payload)) {
|
||||
const url: string = action.payload.url;
|
||||
if (hasNoValue(this.actionMap$[url])) {
|
||||
this.actionMap$[url] = new Subject<ObjectUpdatesAction>();
|
||||
}
|
||||
this.actionMap$[url].next(action);
|
||||
}
|
||||
)
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -91,9 +93,15 @@ export class ObjectUpdatesEffects {
|
||||
const url: string = action.payload.url;
|
||||
const notification: INotification = action.payload.notification;
|
||||
const timeOut = notification.options.timeOut;
|
||||
|
||||
let removeAction: Action = new RemoveObjectUpdatesAction(action.payload.url);
|
||||
if (action.payload.discardAll) {
|
||||
removeAction = new RemoveAllObjectUpdatesAction();
|
||||
}
|
||||
|
||||
return observableRace(
|
||||
// Either wait for the delay and perform a remove action
|
||||
observableOf(new RemoveObjectUpdatesAction(action.payload.url)).pipe(delay(timeOut)),
|
||||
observableOf(removeAction).pipe(delay(timeOut)),
|
||||
// Or wait for a a user action
|
||||
this.actionMap$[url].pipe(
|
||||
take(1),
|
||||
@@ -106,19 +114,19 @@ export class ObjectUpdatesEffects {
|
||||
return { type: 'NO_ACTION' }
|
||||
}
|
||||
// If someone performed another action, assume the user does not want to reinstate and remove all changes
|
||||
return new RemoveObjectUpdatesAction(action.payload.url);
|
||||
return removeAction
|
||||
})
|
||||
),
|
||||
this.notificationActionMap$[notification.id].pipe(
|
||||
filter((notificationsAction: NotificationsActions) => notificationsAction.type === NotificationsActionTypes.REMOVE_NOTIFICATION),
|
||||
map(() => {
|
||||
return new RemoveObjectUpdatesAction(action.payload.url);
|
||||
return removeAction;
|
||||
})
|
||||
),
|
||||
this.notificationActionMap$[this.allIdentifier].pipe(
|
||||
filter((notificationsAction: NotificationsActions) => notificationsAction.type === NotificationsActionTypes.REMOVE_ALL_NOTIFICATIONS),
|
||||
map(() => {
|
||||
return new RemoveObjectUpdatesAction(action.payload.url);
|
||||
return removeAction;
|
||||
})
|
||||
)
|
||||
)
|
||||
|
@@ -105,6 +105,9 @@ export function objectUpdatesReducer(state = initialState, action: ObjectUpdates
|
||||
case ObjectUpdatesActionTypes.REMOVE: {
|
||||
return removeObjectUpdates(state, action as RemoveObjectUpdatesAction);
|
||||
}
|
||||
case ObjectUpdatesActionTypes.REMOVE_ALL: {
|
||||
return removeAllObjectUpdates(state);
|
||||
}
|
||||
case ObjectUpdatesActionTypes.REMOVE_FIELD: {
|
||||
return removeFieldUpdate(state, action as RemoveFieldUpdateAction);
|
||||
}
|
||||
@@ -175,7 +178,24 @@ function addFieldUpdate(state: any, action: AddFieldUpdateAction) {
|
||||
* @param action The action to perform on the current state
|
||||
*/
|
||||
function discardObjectUpdates(state: any, action: DiscardObjectUpdatesAction) {
|
||||
const url: string = action.payload.url;
|
||||
if (action.payload.discardAll) {
|
||||
let newState = Object.assign({}, state);
|
||||
Object.keys(state).filter((path: string) => !path.endsWith(OBJECT_UPDATES_TRASH_PATH)).forEach((path: string) => {
|
||||
newState = discardObjectUpdatesFor(path, newState);
|
||||
});
|
||||
return newState;
|
||||
} else {
|
||||
const url: string = action.payload.url;
|
||||
return discardObjectUpdatesFor(url, state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard all updates for a specific action's url in the store
|
||||
* @param url The action's url
|
||||
* @param state The current state
|
||||
*/
|
||||
function discardObjectUpdatesFor(url: string, state: any) {
|
||||
const pageState: ObjectUpdatesEntry = state[url];
|
||||
const newFieldStates = {};
|
||||
Object.keys(pageState.fieldStates).forEach((uuid: string) => {
|
||||
@@ -228,6 +248,18 @@ function removeObjectUpdatesByURL(state: any, url: string) {
|
||||
return newState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all updates in the store
|
||||
* @param state The current state
|
||||
*/
|
||||
function removeAllObjectUpdates(state: any) {
|
||||
const newState = Object.assign({}, state);
|
||||
Object.keys(state).filter((path: string) => path.endsWith(OBJECT_UPDATES_TRASH_PATH)).forEach((path: string) => {
|
||||
delete newState[path];
|
||||
});
|
||||
return newState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard the update for a specific action's url and field UUID in the store
|
||||
* @param state The current state
|
||||
|
@@ -225,6 +225,15 @@ export class ObjectUpdatesService {
|
||||
this.store.dispatch(new DiscardObjectUpdatesAction(url, undoNotification));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to dispatch a DiscardObjectUpdatesAction to the store with discardAll set to true
|
||||
* @param url The page's URL for which the changes should be discarded
|
||||
* @param undoNotification The notification which is should possibly be canceled
|
||||
*/
|
||||
discardAllFieldUpdates(url: string, undoNotification: INotification) {
|
||||
this.store.dispatch(new DiscardObjectUpdatesAction(url, undoNotification, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to dispatch an ReinstateObjectUpdatesAction to the store
|
||||
* @param url The page's URL for which the changes should be reinstated
|
||||
|
Reference in New Issue
Block a user