Skip to content

Commit c90d085

Browse files
author
Jens Vannerum
committed
140390: DO show replace button for new versions but not for (unversioned) new submission + cleanup code for nested subscriptions
1 parent b1bf764 commit c90d085

2 files changed

Lines changed: 61 additions & 10 deletions

File tree

src/app/submission/sections/upload/file/section-upload-file.component.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ import {
1313
waitForAsync,
1414
} from '@angular/core/testing';
1515
import { By } from '@angular/platform-browser';
16+
import { LinkService } from '@dspace/core/cache/builders/link.service';
1617
import { AuthorizationDataService } from '@dspace/core/data/feature-authorization/authorization-data.service';
1718
import { JsonPatchOperationPathCombiner } from '@dspace/core/json-patch/builder/json-patch-operation-path-combiner';
1819
import { JsonPatchOperationsBuilder } from '@dspace/core/json-patch/builder/json-patch-operations-builder';
1920
import { HALEndpointService } from '@dspace/core/shared/hal-endpoint.service';
2021
import { SubmissionJsonPatchOperationsService } from '@dspace/core/submission/submission-json-patch-operations.service';
2122
import { AuthorizationDataServiceStub } from '@dspace/core/testing/authorization-service.stub';
2223
import { HALEndpointServiceStub } from '@dspace/core/testing/hal-endpoint-service.stub';
24+
import { getMockLinkService } from '@dspace/core/testing/link-service.mock';
2325
import { getMockSectionUploadService } from '@dspace/core/testing/section-upload.service.mock';
2426
import { SubmissionJsonPatchOperationsServiceStub } from '@dspace/core/testing/submission-json-patch-operations-service.stub';
2527
import { SubmissionServiceStub } from '@dspace/core/testing/submission-service.stub';
@@ -118,6 +120,7 @@ describe('SubmissionSectionUploadFileComponent', () => {
118120
SubmissionSectionUploadFileEditComponent,
119121
FormBuilderService,
120122
{ provide: AuthorizationDataService, useValue: new AuthorizationDataServiceStub() },
123+
{ provide: LinkService, useValue: getMockLinkService() },
121124
],
122125
})
123126
.overrideComponent(SubmissionSectionUploadFileComponent, {

src/app/submission/sections/upload/file/section-upload-file.component.ts

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ import { FeatureID } from '@dspace/core/data/feature-authorization/feature-id';
1414
import { JsonPatchOperationPathCombiner } from '@dspace/core/json-patch/builder/json-patch-operation-path-combiner';
1515
import { JsonPatchOperationsBuilder } from '@dspace/core/json-patch/builder/json-patch-operations-builder';
1616
import { Bitstream } from '@dspace/core/shared/bitstream.model';
17+
import { followLink } from '@dspace/core/shared/follow-link-config.model';
1718
import { HALEndpointService } from '@dspace/core/shared/hal-endpoint.service';
19+
import { Item } from '@dspace/core/shared/item.model';
20+
import {
21+
getAllSucceededRemoteData,
22+
getRemoteDataPayload,
23+
} from '@dspace/core/shared/operators';
1824
import { WorkspaceitemSectionUploadFileObject } from '@dspace/core/submission/models/workspaceitem-section-upload-file.model';
1925
import { SubmissionJsonPatchOperationsService } from '@dspace/core/submission/submission-json-patch-operations.service';
2026
import { SubmissionScopeType } from '@dspace/core/submission/submission-scope-type';
@@ -31,6 +37,7 @@ import { TranslateModule } from '@ngx-translate/core';
3137
import {
3238
BehaviorSubject,
3339
Observable,
40+
of,
3441
Subscription,
3542
} from 'rxjs';
3643
import {
@@ -39,6 +46,7 @@ import {
3946
switchMap,
4047
} from 'rxjs/operators';
4148

49+
import { LinkService } from '../../../../core/cache/builders/link.service';
4250
import { BtnDisabledDirective } from '../../../../shared/btn-disabled.directive';
4351
import { ThemedFileDownloadLinkComponent } from '../../../../shared/file-download-link/themed-file-download-link.component';
4452
import { FormService } from '../../../../shared/form/form.service';
@@ -210,6 +218,7 @@ export class SubmissionSectionUploadFileComponent implements OnChanges, OnInit,
210218
* @param {SectionUploadService} uploadService
211219
* @param {AuthorizationDataService} authorizationService
212220
* @param {HALEndpointService} halService
221+
* @param {LinkService} linkService
213222
*/
214223
constructor(
215224
private formService: FormService,
@@ -220,6 +229,7 @@ export class SubmissionSectionUploadFileComponent implements OnChanges, OnInit,
220229
private uploadService: SectionUploadService,
221230
private authorizationService: AuthorizationDataService,
222231
private halService: HALEndpointService,
232+
private linkService: LinkService,
223233
) {
224234
this.readMode = true;
225235
}
@@ -253,20 +263,58 @@ export class SubmissionSectionUploadFileComponent implements OnChanges, OnInit,
253263
this.subscriptions.push(
254264
this.uploadService.getFileData(this.submissionId, this.sectionId, this.fileId).pipe(
255265
filter(isNotUndefined),
256-
switchMap((fileData) => {
257-
// Replace is only meaningful for archived items being edited, not for fresh submissions.
258-
if (this.submissionService.getSubmissionScope() !== SubmissionScopeType.EditItem) {
259-
return [false];
260-
}
261-
return this.halService.getEndpoint('bitstreams').pipe(
262-
map(endpoint => `${endpoint}/${fileData.uuid}`),
263-
switchMap(bitstreamUrl => this.authorizationService.isAuthorized(FeatureID.CanReplaceBitstreamSubmitter, bitstreamUrl)),
264-
);
265-
}),
266+
switchMap((fileData) => this.canShowReplaceButton(fileData.uuid)),
266267
).subscribe((canReplace) => this.showReplaceButton$.next(canReplace)),
267268
);
268269
}
269270

271+
/**
272+
* Returns an Observable that emits whether the replace button should be shown for the given
273+
* bitstream. WorkflowItems never show the button; WorkspaceItems only show it when the
274+
* submission is a new version of an existing item; Archived items rely solely on backend
275+
* authorization.
276+
*/
277+
private canShowReplaceButton(bitstreamUuid: string): Observable<boolean> {
278+
const scope = this.submissionService.getSubmissionScope();
279+
if (scope === SubmissionScopeType.WorkflowItem) {
280+
return of(false);
281+
}
282+
return this.isVersionedSubmission(scope).pipe(
283+
switchMap((isVersioned) => isVersioned ? this.isAuthorizedToReplace(bitstreamUuid) : of(false)),
284+
);
285+
}
286+
287+
/**
288+
* Returns `true` when the current submission is a new-version workspace item (i.e. its item
289+
* already belongs to a version history), or unconditionally `true` for EditItem scope where
290+
* versioning does not apply.
291+
*/
292+
private isVersionedSubmission(scope: SubmissionScopeType): Observable<boolean> {
293+
if (scope !== SubmissionScopeType.WorkspaceItem) {
294+
return of(true);
295+
}
296+
return this.submissionService.retrieveSubmission(this.submissionId).pipe(
297+
getAllSucceededRemoteData(),
298+
getRemoteDataPayload(),
299+
map((submissionObject) => Object.assign(new Item(), submissionObject.item)),
300+
map((item: Item) => this.linkService.resolveLink(item, followLink('version'))),
301+
switchMap((item: Item) => item.version),
302+
getAllSucceededRemoteData(),
303+
getRemoteDataPayload(),
304+
map((version) => hasValue(version)),
305+
);
306+
}
307+
308+
/**
309+
* Returns whether the current user is authorized to replace the given bitstream.
310+
*/
311+
private isAuthorizedToReplace(bitstreamUuid: string): Observable<boolean> {
312+
return this.halService.getEndpoint('bitstreams').pipe(
313+
map((endpoint) => `${endpoint}/${bitstreamUuid}`),
314+
switchMap((bitstreamUrl) => this.authorizationService.isAuthorized(FeatureID.CanReplaceBitstreamSubmitter, bitstreamUrl)),
315+
);
316+
}
317+
270318
/**
271319
* Show confirmation dialog for delete
272320
*/

0 commit comments

Comments
 (0)