mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
118223: Add 'loading' overlay while bitstream is moving
This commit is contained in:
@@ -27,7 +27,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="item && bundles?.length > 0" class="mt-4 table-border scrollable-table">
|
<div *ngIf="item && bundles?.length > 0" class="mt-4 table-border scrollable-table" [ngClass]="{'disabled-overlay': (isProcessingMoveRequest | async)}">
|
||||||
<ds-item-edit-bitstream-bundle *ngFor="let bundle of bundles; first as isFirst"
|
<ds-item-edit-bitstream-bundle *ngFor="let bundle of bundles; first as isFirst"
|
||||||
[bundle]="bundle"
|
[bundle]="bundle"
|
||||||
[item]="item"
|
[item]="item"
|
||||||
@@ -63,3 +63,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ds-themed-loading *ngIf="isProcessingMoveRequest | async" class="loading-overlay"></ds-themed-loading>
|
||||||
|
@@ -43,3 +43,13 @@
|
|||||||
.scrollable-table {
|
.scrollable-table {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.disabled-overlay {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
@@ -59,6 +59,11 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme
|
|||||||
*/
|
*/
|
||||||
itemUpdateSubscription: Subscription;
|
itemUpdateSubscription: Subscription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An observable which emits a boolean which represents whether the service is currently handling a 'move' request
|
||||||
|
*/
|
||||||
|
isProcessingMoveRequest: Observable<boolean>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public itemService: ItemDataService,
|
public itemService: ItemDataService,
|
||||||
public objectUpdatesService: ObjectUpdatesService,
|
public objectUpdatesService: ObjectUpdatesService,
|
||||||
@@ -84,6 +89,7 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme
|
|||||||
*/
|
*/
|
||||||
postItemInit(): void {
|
postItemInit(): void {
|
||||||
const bundlesOptions = this.itemBitstreamsService.getInitialBundlesPaginationOptions();
|
const bundlesOptions = this.itemBitstreamsService.getInitialBundlesPaginationOptions();
|
||||||
|
this.isProcessingMoveRequest = this.itemBitstreamsService.getPerformingMoveRequest$();
|
||||||
|
|
||||||
this.bundles$ = this.itemService.getBundles(this.item.id, new PaginatedSearchOptions({pagination: bundlesOptions})).pipe(
|
this.bundles$ = this.itemService.getBundles(this.item.id, new PaginatedSearchOptions({pagination: bundlesOptions})).pipe(
|
||||||
getFirstSucceededRemoteData(),
|
getFirstSucceededRemoteData(),
|
||||||
|
@@ -573,8 +573,6 @@ describe('ItemBitstreamsService', () => {
|
|||||||
const to = 7;
|
const to = 7;
|
||||||
const callback = createSpy('callbackFunction');
|
const callback = createSpy('callbackFunction');
|
||||||
|
|
||||||
console.log('bundle:', bundle);
|
|
||||||
|
|
||||||
it('should correctly create the Move request', () => {
|
it('should correctly create the Move request', () => {
|
||||||
const expectedOperation: MoveOperation = {
|
const expectedOperation: MoveOperation = {
|
||||||
op: 'move',
|
op: 'move',
|
||||||
@@ -601,6 +599,22 @@ describe('ItemBitstreamsService', () => {
|
|||||||
service.performBitstreamMoveRequest(bundle, from, to, callback);
|
service.performBitstreamMoveRequest(bundle, from, to, callback);
|
||||||
expect(callback).toHaveBeenCalled();
|
expect(callback).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should emit at the start and end of the request', fakeAsync(() => {
|
||||||
|
const emittedActions = [];
|
||||||
|
|
||||||
|
service.getPerformingMoveRequest$().subscribe(selected => emittedActions.push(selected));
|
||||||
|
|
||||||
|
expect(emittedActions.length).toBe(1);
|
||||||
|
expect(emittedActions[0]).toBeFalse();
|
||||||
|
|
||||||
|
service.performBitstreamMoveRequest(bundle, from, to, callback);
|
||||||
|
tick();
|
||||||
|
|
||||||
|
expect(emittedActions.length).toBe(3);
|
||||||
|
expect(emittedActions[1]).toBeTrue();
|
||||||
|
expect(emittedActions[2]).toBeFalse();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('displayNotifications', () => {
|
describe('displayNotifications', () => {
|
||||||
|
@@ -30,6 +30,10 @@ export class ItemBitstreamsServiceStub {
|
|||||||
|
|
||||||
performBitstreamMoveRequest = jasmine.createSpy('performBitstreamMoveRequest');
|
performBitstreamMoveRequest = jasmine.createSpy('performBitstreamMoveRequest');
|
||||||
|
|
||||||
|
getPerformingMoveRequest = jasmine.createSpy('getPerformingMoveRequest').and.returnValue(false);
|
||||||
|
|
||||||
|
getPerformingMoveRequest$ = jasmine.createSpy('getPerformingMoveRequest$').and.returnValue(of(false));
|
||||||
|
|
||||||
getInitialBundlesPaginationOptions = jasmine.createSpy('getInitialBundlesPaginationOptions').and
|
getInitialBundlesPaginationOptions = jasmine.createSpy('getInitialBundlesPaginationOptions').and
|
||||||
.returnValue(new PaginationComponentOptions());
|
.returnValue(new PaginationComponentOptions());
|
||||||
|
|
||||||
|
@@ -119,7 +119,7 @@ export class ItemBitstreamsService {
|
|||||||
*/
|
*/
|
||||||
protected selectionAction$: BehaviorSubject<SelectionAction> = new BehaviorSubject(null);
|
protected selectionAction$: BehaviorSubject<SelectionAction> = new BehaviorSubject(null);
|
||||||
|
|
||||||
protected isPerformingMoveRequest = false;
|
protected isPerformingMoveRequest: BehaviorSubject<boolean> = new BehaviorSubject(false);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
@@ -221,7 +221,7 @@ export class ItemBitstreamsService {
|
|||||||
cancelSelection() {
|
cancelSelection() {
|
||||||
const selected = this.getSelectedBitstream();
|
const selected = this.getSelectedBitstream();
|
||||||
|
|
||||||
if (hasNoValue(selected) || this.isPerformingMoveRequest) {
|
if (hasNoValue(selected) || this.getPerformingMoveRequest()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +247,7 @@ export class ItemBitstreamsService {
|
|||||||
moveSelectedBitstreamUp() {
|
moveSelectedBitstreamUp() {
|
||||||
const selected = this.getSelectedBitstream();
|
const selected = this.getSelectedBitstream();
|
||||||
|
|
||||||
if (hasNoValue(selected) || this.isPerformingMoveRequest) {
|
if (hasNoValue(selected) || this.getPerformingMoveRequest()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +272,7 @@ export class ItemBitstreamsService {
|
|||||||
moveSelectedBitstreamDown() {
|
moveSelectedBitstreamDown() {
|
||||||
const selected = this.getSelectedBitstream();
|
const selected = this.getSelectedBitstream();
|
||||||
|
|
||||||
if (hasNoValue(selected) || this.isPerformingMoveRequest) {
|
if (hasNoValue(selected) || this.getPerformingMoveRequest()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +299,7 @@ export class ItemBitstreamsService {
|
|||||||
* @param finish Optional: Function to execute once the response has been received
|
* @param finish Optional: Function to execute once the response has been received
|
||||||
*/
|
*/
|
||||||
performBitstreamMoveRequest(bundle: Bundle, fromIndex: number, toIndex: number, finish?: () => void) {
|
performBitstreamMoveRequest(bundle: Bundle, fromIndex: number, toIndex: number, finish?: () => void) {
|
||||||
if (this.isPerformingMoveRequest) {
|
if (this.getPerformingMoveRequest()) {
|
||||||
console.warn('Attempted to perform move request while previous request has not completed yet');
|
console.warn('Attempted to perform move request while previous request has not completed yet');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -310,18 +310,34 @@ export class ItemBitstreamsService {
|
|||||||
path: `/_links/bitstreams/${toIndex}/href`,
|
path: `/_links/bitstreams/${toIndex}/href`,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.isPerformingMoveRequest = true;
|
this.announceLoading();
|
||||||
|
this.isPerformingMoveRequest.next(true);
|
||||||
this.bundleService.patch(bundle, [moveOperation]).pipe(
|
this.bundleService.patch(bundle, [moveOperation]).pipe(
|
||||||
getFirstCompletedRemoteData(),
|
getFirstCompletedRemoteData(),
|
||||||
tap((response: RemoteData<Bundle>) => this.displayFailedResponseNotifications(MOVE_KEY, [response])),
|
tap((response: RemoteData<Bundle>) => this.displayFailedResponseNotifications(MOVE_KEY, [response])),
|
||||||
switchMap(() => this.requestService.setStaleByHrefSubstring(bundle.self)),
|
switchMap(() => this.requestService.setStaleByHrefSubstring(bundle.self)),
|
||||||
take(1),
|
take(1),
|
||||||
).subscribe(() => {
|
).subscribe(() => {
|
||||||
this.isPerformingMoveRequest = false;
|
console.log('got here!');
|
||||||
|
this.isPerformingMoveRequest.next(false);
|
||||||
finish?.();
|
finish?.();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the service currently is processing a 'move' request
|
||||||
|
*/
|
||||||
|
getPerformingMoveRequest(): boolean {
|
||||||
|
return this.isPerformingMoveRequest.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an observable which emits when the service starts, or ends, processing a 'move' request
|
||||||
|
*/
|
||||||
|
getPerformingMoveRequest$(): Observable<boolean> {
|
||||||
|
return this.isPerformingMoveRequest;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the pagination options to use when fetching the bundles
|
* Returns the pagination options to use when fetching the bundles
|
||||||
*/
|
*/
|
||||||
@@ -526,4 +542,12 @@ export class ItemBitstreamsService {
|
|||||||
{ bitstream: bitstreamName });
|
{ bitstream: bitstreamName });
|
||||||
this.liveRegionService.addMessage(message);
|
this.liveRegionService.addMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a message to the live region mentioning that the
|
||||||
|
*/
|
||||||
|
announceLoading() {
|
||||||
|
const message = this.translateService.instant('item.edit.bitstreams.edit.live.loading');
|
||||||
|
this.liveRegionService.addMessage(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1954,6 +1954,8 @@
|
|||||||
|
|
||||||
"item.edit.bitstreams.edit.live.clear": "{{ bitstream }} is no longer selected.",
|
"item.edit.bitstreams.edit.live.clear": "{{ bitstream }} is no longer selected.",
|
||||||
|
|
||||||
|
"item.edit.bitstreams.edit.live.loading": "Waiting for move to complete.",
|
||||||
|
|
||||||
"item.edit.bitstreams.edit.live.select": "{{ bitstream }} is selected.",
|
"item.edit.bitstreams.edit.live.select": "{{ bitstream }} is selected.",
|
||||||
|
|
||||||
"item.edit.bitstreams.edit.live.move": "{{ bitstream }} is now in position {{ toIndex }}.",
|
"item.edit.bitstreams.edit.live.move": "{{ bitstream }} is now in position {{ toIndex }}.",
|
||||||
|
Reference in New Issue
Block a user