Merge branch 'item-edit-bitstreams-table-7.6' into item-edit-bitstreams-table-7_x

This commit is contained in:
Andreas Awouters
2024-12-11 11:22:56 +01:00
7 changed files with 71 additions and 10 deletions

View File

@@ -31,7 +31,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"
@@ -70,3 +70,5 @@
</div> </div>
</div> </div>
</div> </div>
<ds-themed-loading *ngIf="isProcessingMoveRequest | async" class="loading-overlay"></ds-themed-loading>

View File

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

View File

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

View File

@@ -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', () => {

View File

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

View File

@@ -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,33 @@ 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; 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 +541,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);
}
} }

View File

@@ -2010,6 +2010,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 }}.",