Skip to content

Commit 4162c58

Browse files
milanmajchrakclaude
andcommitted
UoE/datashare: add "Keep embargo policies" option to the move-item screen
Companion to backend PR dataquest-dev/uoe-dspace-datashare-backend#27 (dspace-customers#761 - embargo lost when moving into another collection). When moving an item and inheriting the destination collection's policies, let the user choose whether to keep an existing embargo: - checked (default): inherit everything except the embargo (keepEmbargoPolicies=true) - unchecked: plain DSpace behaviour - inherited default read lifts the embargo The checkbox is shown only when "Inherit policies" is ticked. - item-move.component: keepEmbargoPolicies model (default true), passed to moveToCollection only when inheriting. - item-move.component.html: checkbox + description gated on inheritPolicies. - item-data.service: send &keepEmbargoPolicies= on the owningCollection move. - en.json5: item.edit.move.keepembargopolicies.{checkbox,description,tooltip}. - item-move.component.spec: updated expectation + case for inheriting. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 50e0d31 commit 4162c58

5 files changed

Lines changed: 57 additions & 7 deletions

File tree

src/app/core/data/item-data.service.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,27 +272,36 @@ export abstract class BaseItemDataService extends IdentifiableDataService<Item>
272272
/**
273273
* Get the endpoint to move the item
274274
* @param itemId
275+
* @param inheritPolicies whether to inherit the destination collection's default policies
276+
* @param keepEmbargoPolicies when inheriting, whether to keep an existing embargo (only the
277+
* non-embargo access is inherited) instead of letting the inherited
278+
* default read access lift it
275279
*/
276-
public getMoveItemEndpoint(itemId: string, inheritPolicies: boolean): Observable<string> {
280+
public getMoveItemEndpoint(itemId: string, inheritPolicies: boolean, keepEmbargoPolicies = true): Observable<string> {
277281
return this.halService.getEndpoint(this.linkPath).pipe(
278282
map((endpoint: string) => this.getIDHref(endpoint, itemId)),
279-
map((endpoint: string) => `${endpoint}/owningCollection?inheritPolicies=${inheritPolicies}`),
283+
map((endpoint: string) =>
284+
`${endpoint}/owningCollection?inheritPolicies=${inheritPolicies}&keepEmbargoPolicies=${keepEmbargoPolicies}`),
280285
);
281286
}
282287

283288
/**
284289
* Move the item to a different owning collection
285290
* @param itemId
286291
* @param collection
292+
* @param inheritPolicies whether to inherit the destination collection's default policies
293+
* @param keepEmbargoPolicies when inheriting, whether to keep an existing embargo
287294
*/
288-
public moveToCollection(itemId: string, collection: Collection, inheritPolicies: boolean): Observable<RemoteData<any>> {
295+
public moveToCollection(
296+
itemId: string, collection: Collection, inheritPolicies: boolean, keepEmbargoPolicies = true,
297+
): Observable<RemoteData<any>> {
289298
const options: HttpOptions = Object.create({});
290299
let headers = new HttpHeaders();
291300
headers = headers.append('Content-Type', 'text/uri-list');
292301
options.headers = headers;
293302

294303
const requestId = this.requestService.generateRequestId();
295-
const hrefObs = this.getMoveItemEndpoint(itemId, inheritPolicies);
304+
const hrefObs = this.getMoveItemEndpoint(itemId, inheritPolicies, keepEmbargoPolicies);
296305

297306
hrefObs.pipe(
298307
find((href: string) => hasValue(href)),

src/app/item-page/edit-item-page/item-move/item-move.component.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@ <h1>{{'item.edit.move.head' | translate: {id: (itemRD$ | async)?.payload?.handle
3232
<p>
3333
{{'item.edit.move.inheritpolicies.description' | translate}}
3434
</p>
35+
<p *ngIf="inheritPolicies">
36+
<label for="keepEmbargoPoliciesCheckbox">
37+
<ng-template #keepEmbargoTooltipContent>
38+
{{ 'item.edit.move.keepembargopolicies.tooltip' | translate }}
39+
</ng-template>
40+
<input type="checkbox" name="keepEmbargo" [(ngModel)]="keepEmbargoPolicies" id="keepEmbargoPoliciesCheckbox" [ngbTooltip]="keepEmbargoTooltipContent"
41+
>
42+
{{'item.edit.move.keepembargopolicies.checkbox' | translate}}
43+
</label>
44+
</p>
45+
<p *ngIf="inheritPolicies">
46+
{{'item.edit.move.keepembargopolicies.description' | translate}}
47+
</p>
3548
</div>
3649
</div>
3750

src/app/item-page/edit-item-page/item-move/item-move.component.spec.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,20 @@ describe('ItemMoveComponent', () => {
150150
comp.inheritPolicies = false;
151151
comp.moveToCollection();
152152

153-
expect(itemDataService.moveToCollection).toHaveBeenCalledWith('item-id', collection1, false);
153+
// keepEmbargoPolicies is only meaningful when inheriting; not inheriting always sends true
154+
expect(itemDataService.moveToCollection).toHaveBeenCalledWith('item-id', collection1, false, true);
155+
});
156+
it('should pass keepEmbargoPolicies through when inheriting policies', () => {
157+
comp.item = Object.assign(new Item(), {
158+
id: 'item-id',
159+
uuid: 'item-id',
160+
});
161+
comp.selectedCollection = collection1;
162+
comp.inheritPolicies = true;
163+
comp.keepEmbargoPolicies = false;
164+
comp.moveToCollection();
165+
166+
expect(itemDataService.moveToCollection).toHaveBeenCalledWith('item-id', collection1, true, false);
154167
});
155168
it('should call notificationsService success message on success', () => {
156169
comp.moveToCollection();

src/app/item-page/edit-item-page/item-move/item-move.component.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ export class ItemMoveComponent implements OnInit {
7373
selectorType = DSpaceObjectType.COLLECTION;
7474

7575
inheritPolicies = false;
76+
77+
/**
78+
* When inheriting the destination collection's policies, whether to keep an existing embargo
79+
* (only the non-embargo access is inherited) instead of letting the inherited default read
80+
* access lift it. Only relevant while {@link inheritPolicies} is enabled.
81+
*/
82+
keepEmbargoPolicies = true;
7683
itemRD$: Observable<RemoteData<Item>>;
7784
originalCollection: Collection;
7885

@@ -145,8 +152,10 @@ export class ItemMoveComponent implements OnInit {
145152
*/
146153
moveToCollection() {
147154
this.processing = true;
148-
const move$ = this.itemDataService.moveToCollection(this.item.id, this.selectedCollection, this.inheritPolicies)
149-
.pipe(getFirstCompletedRemoteData());
155+
const move$ = this.itemDataService.moveToCollection(
156+
this.item.id, this.selectedCollection, this.inheritPolicies,
157+
this.inheritPolicies ? this.keepEmbargoPolicies : true,
158+
).pipe(getFirstCompletedRemoteData());
150159

151160
move$.subscribe((response: RemoteData<any>) => {
152161
if (response.hasSucceeded) {

src/assets/i18n/en.json5

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2552,6 +2552,12 @@
25522552

25532553
"item.edit.move.inheritpolicies.tooltip": "Warning: When enabled, the read access policy for the item and any files associated with the item will be replaced by the default read access policy of the collection. This cannot be undone.",
25542554

2555+
"item.edit.move.keepembargopolicies.checkbox": "Keep embargo policies",
2556+
2557+
"item.edit.move.keepembargopolicies.description": "When inheriting policies, keep any existing embargo: only the non-embargo access is inherited from the destination collection.",
2558+
2559+
"item.edit.move.keepembargopolicies.tooltip": "When enabled, inheriting the destination collection's policies preserves an existing embargo, so embargoed files stay embargoed until their original lift date. When disabled, the inherited default read access replaces (and lifts) the embargo.",
2560+
25552561
"item.edit.move.move": "Move",
25562562

25572563
"item.edit.move.processing": "Moving...",

0 commit comments

Comments
 (0)