Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed creation & deletion of relationships not working correctly & added same entity type relationship support #3060

Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
Observable,
} from 'rxjs';
import {
delay,
distinctUntilChanged,
take,
withLatestFrom,
Expand Down Expand Up @@ -136,7 +137,10 @@ export class AppComponent implements OnInit, AfterViewInit {
}

ngAfterViewInit() {
this.router.events.subscribe((event) => {
this.router.events.pipe(
// delay(0) to prevent "Expression has changed after it was checked" errors
delay(0),
).subscribe((event) => {
if (event instanceof NavigationStart) {
distinctNext(this.isRouteLoading$, true);
} else if (
Expand Down
2 changes: 2 additions & 0 deletions src/app/core/data/object-updates/object-updates.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export interface VirtualMetadataSource {

export interface RelationshipIdentifiable extends Identifiable {
nameVariant?: string;
originalItem: Item;
originalIsLeft: boolean
relatedItem: Item;
relationship: Relationship;
type: RelationshipType;
Expand Down
40 changes: 33 additions & 7 deletions src/app/core/data/relationship-data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,11 @@
* @param id the ID of the relationship to delete
* @param copyVirtualMetadata whether to copy this relationship's virtual metadata to the related Items
* accepted values: none, all, left, right, configured
* @param shouldRefresh refresh the cache for the items in the relationship after creating
* it. Disable this if you want to add relationships in bulk, and
* want to refresh the cachemanually at the end
*/
deleteRelationship(id: string, copyVirtualMetadata: string): Observable<RemoteData<NoContent>> {
deleteRelationship(id: string, copyVirtualMetadata: string, shouldRefresh = true): Observable<RemoteData<NoContent>> {
return this.getRelationshipEndpoint(id).pipe(
isNotEmptyOperator(),
take(1),
Expand All @@ -167,7 +170,11 @@
sendRequest(this.requestService),
switchMap((restRequest: RestRequest) => this.rdbService.buildFromRequestUUID(restRequest.uuid)),
getFirstCompletedRemoteData(),
tap(() => this.refreshRelationshipItemsInCacheByRelationship(id)),
tap(() => {
if (shouldRefresh) {
this.refreshRelationshipItemsInCacheByRelationship(id);
}
}),
);
}

Expand All @@ -178,8 +185,11 @@
* @param item2 The second item of the relationship
* @param leftwardValue The leftward value of the relationship
* @param rightwardValue The rightward value of the relationship
* @param shouldRefresh refresh the cache for the items in the relationship after creating it.
* Disable this if you want to add relationships in bulk, and want to refresh
* the cache manually at the end
*/
addRelationship(typeId: string, item1: Item, item2: Item, leftwardValue?: string, rightwardValue?: string): Observable<RemoteData<Relationship>> {
addRelationship(typeId: string, item1: Item, item2: Item, leftwardValue?: string, rightwardValue?: string, shouldRefresh = true): Observable<RemoteData<Relationship>> {
const options: HttpOptions = Object.create({});
let headers = new HttpHeaders();
headers = headers.append('Content-Type', 'text/uri-list');
Expand All @@ -194,8 +204,12 @@
sendRequest(this.requestService),
switchMap((restRequest: RestRequest) => this.rdbService.buildFromRequestUUID(restRequest.uuid)),
getFirstCompletedRemoteData(),
tap(() => this.refreshRelationshipItemsInCache(item1)),
tap(() => this.refreshRelationshipItemsInCache(item2)),
tap(() => {
if (shouldRefresh) {
this.refreshRelationshipItemsInCache(item1);
this.refreshRelationshipItemsInCache(item2);

Check warning on line 210 in src/app/core/data/relationship-data.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/core/data/relationship-data.service.ts#L209-L210

Added lines #L209 - L210 were not covered by tests
}
}),
) as Observable<RemoteData<Relationship>>;
}

Expand Down Expand Up @@ -223,7 +237,7 @@
* Method to remove an item that's part of a relationship from the cache
* @param item The item to remove from the cache
*/
public refreshRelationshipItemsInCache(item) {
public refreshRelationshipItemsInCache(item: Item): void {
this.objectCache.remove(item._links.self.href);
this.requestService.removeByHrefSubstring(item.uuid);
observableCombineLatest([
Expand Down Expand Up @@ -336,7 +350,19 @@
} else {
findListOptions.searchParams = searchParams;
}
return this.searchBy('byLabel', findListOptions, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);

// always set reRequestOnStale to false here, so it doesn't happen automatically in BaseDataService
const result$ = this.searchBy('byLabel', findListOptions, useCachedVersionIfAvailable, false, ...linksToFollow);

Check warning on line 355 in src/app/core/data/relationship-data.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/core/data/relationship-data.service.ts#L355

Added line #L355 was not covered by tests

// add this result as a dependency of the item, meaning that if the item is invalided, this
// result will be as well
this.addDependency(result$, item._links.self.href);

Check warning on line 359 in src/app/core/data/relationship-data.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/core/data/relationship-data.service.ts#L359

Added line #L359 was not covered by tests

// do the reRequestOnStale call here, to ensure any re-requests also get added as dependencies
return result$.pipe(

Check warning on line 362 in src/app/core/data/relationship-data.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/core/data/relationship-data.service.ts#L362

Added line #L362 was not covered by tests
this.reRequestStaleRemoteData(reRequestOnStale, () =>
this.getItemRelationshipsByLabel(item, label, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow)),

Check warning on line 364 in src/app/core/data/relationship-data.service.ts

View check run for this annotation

Codecov / codecov/patch

src/app/core/data/relationship-data.service.ts#L364

Added line #L364 was not covered by tests
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl
*/
updates$: Observable<FieldUpdates>;

hasChanges$: Observable<boolean>;

isReinstatable$: Observable<boolean>;

/**
* Route to the item's page
*/
Expand Down Expand Up @@ -101,10 +105,9 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl
}

this.discardTimeOut = environment.item.edit.undoTimeout;
this.url = this.router.url;
if (this.url.indexOf('?') > 0) {
this.url = this.url.substr(0, this.url.indexOf('?'));
}
this.url = this.router.url.split('?')[0];
this.hasChanges$ = this.hasChanges();
this.isReinstatable$ = this.isReinstatable();
this.hasChanges().pipe(first()).subscribe((hasChanges) => {
if (!hasChanges) {
this.initializeOriginalFields();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@
class="fas fa-upload"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.upload-button" | translate}}</span>
</button>
<button class="btn btn-warning" *ngIf="isReinstatable() | async"
<button class="btn btn-warning" *ngIf="isReinstatable$ | async"
[attr.aria-label]="'item.edit.bitstreams.reinstate-button' | translate"
(click)="reinstate()"><i
class="fas fa-undo-alt"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.reinstate-button" | translate}}</span>
</button>
<button class="btn btn-primary" [disabled]="(hasChanges() | async) !== true || submitting"
<button class="btn btn-primary" [disabled]="(hasChanges$ | async) !== true || submitting"
[attr.aria-label]="'item.edit.bitstreams.save-button' | translate"
(click)="submit()"><i
class="fas fa-save"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.save-button" | translate}}</span>
</button>
<button class="btn btn-danger" *ngIf="(isReinstatable() | async) !== true"
<button class="btn btn-danger" *ngIf="(isReinstatable$ | async) !== true"
[attr.aria-label]="'item.edit.bitstreams.discard-button' | translate"
[disabled]="(hasChanges() | async) !== true || submitting"
[disabled]="(hasChanges$ | async) !== true || submitting"
(click)="discard()"><i
class="fas fa-times"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.discard-button" | translate}}</span>
Expand Down Expand Up @@ -52,21 +52,21 @@

<div class="button-row bottom">
<div class="mt-4 float-right space-children-mr ml-gap">
<button class="btn btn-warning" *ngIf="isReinstatable() | async"
<button class="btn btn-warning" *ngIf="isReinstatable$ | async"
[attr.aria-label]="'item.edit.bitstreams.reinstate-button' | translate"
(click)="reinstate()"><i
class="fas fa-undo-alt"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.reinstate-button" | translate}}</span>
</button>
<button class="btn btn-primary" [disabled]="(hasChanges() | async) !== true || submitting"
<button class="btn btn-primary" [disabled]="(hasChanges$ | async) !== true || submitting"
[attr.aria-label]="'item.edit.bitstreams.save-button' | translate"
(click)="submit()"><i
class="fas fa-save"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.save-button" | translate}}</span>
</button>
<button class="btn btn-danger" *ngIf="(isReinstatable() | async) !== true"
<button class="btn btn-danger" *ngIf="(isReinstatable$ | async) !== true"
[attr.aria-label]="'item.edit.bitstreams.discard-button' | translate"
[disabled]="(hasChanges() | async) !== true || submitting"
[disabled]="(hasChanges$ | async) !== true || submitting"
(click)="discard()"><i
class="fas fa-times"></i>
<span class="d-none d-sm-inline">&nbsp;{{"item.edit.bitstreams.discard-button" | translate}}</span>
Expand Down
Loading
Loading