Resolved more caching issues for relationships

This commit is contained in:
lotte
2019-08-22 16:04:08 +02:00
parent 37072dc01e
commit 0bf4c57a43
5 changed files with 74 additions and 39 deletions

View File

@@ -161,7 +161,6 @@ export abstract class DataService<T extends CacheableObject> {
} }
findByHref(href: string, options?: HttpOptions): Observable<RemoteData<T>> { findByHref(href: string, options?: HttpOptions): Observable<RemoteData<T>> {
console.log('perform request for:', href)
this.requestService.configure(new GetRequest(this.requestService.generateRequestId(), href, null, options), this.forceBypassCache); this.requestService.configure(new GetRequest(this.requestService.generateRequestId(), href, null, options), this.forceBypassCache);
return this.rdbService.buildSingle<T>(href); return this.rdbService.buildSingle<T>(href);
} }

View File

@@ -68,7 +68,7 @@ export class RelationshipService extends DataService<Relationship> {
deleteRelationship(id: string): Observable<RestResponse> { deleteRelationship(id: string): Observable<RestResponse> {
return this.getRelationshipEndpoint(id).pipe( return this.getRelationshipEndpoint(id).pipe(
isNotEmptyOperator(), isNotEmptyOperator(),
distinctUntilChanged(), take(1),
map((endpointURL: string) => new DeleteRequest(this.requestService.generateRequestId(), endpointURL)), map((endpointURL: string) => new DeleteRequest(this.requestService.generateRequestId(), endpointURL)),
configureRequest(this.requestService), configureRequest(this.requestService),
switchMap((restRequest: RestRequest) => this.requestService.getByUUID(restRequest.uuid)), switchMap((restRequest: RestRequest) => this.requestService.getByUUID(restRequest.uuid)),
@@ -84,7 +84,7 @@ export class RelationshipService extends DataService<Relationship> {
options.headers = headers; options.headers = headers;
return this.halService.getEndpoint(this.linkPath).pipe( return this.halService.getEndpoint(this.linkPath).pipe(
isNotEmptyOperator(), isNotEmptyOperator(),
distinctUntilChanged(), take(1),
map((endpointUrl: string) => `${endpointUrl}?relationshipType=${typeId}`), map((endpointUrl: string) => `${endpointUrl}?relationshipType=${typeId}`),
map((endpointURL: string) => new PostRequest(this.requestService.generateRequestId(), endpointURL, `${item1.self} \n ${item2.self}`, options)), map((endpointURL: string) => new PostRequest(this.requestService.generateRequestId(), endpointURL, `${item1.self} \n ${item2.self}`, options)),
configureRequest(this.requestService), configureRequest(this.requestService),
@@ -267,7 +267,7 @@ export class RelationshipService extends DataService<Relationship> {
); );
})) }))
}), }),
map((relationships: Relationship[]) => relationships.find((relationship => hasValue(relationship)))), map((relationships: Relationship[]) => relationships.find((relationship => hasValue(relationship))))
) )
} }

View File

@@ -308,6 +308,7 @@ export class RequestService {
*/ */
hasByHref(href: string): boolean { hasByHref(href: string): boolean {
let result = false; let result = false;
/* NB: that this is only a solution because the select method is synchronous, see: https://github.com/ngrx/store/issues/296#issuecomment-269032571*/
this.getByHref(href).pipe( this.getByHref(href).pipe(
take(1) take(1)
).subscribe((requestEntry: RequestEntry) => result = this.isValid(requestEntry)); ).subscribe((requestEntry: RequestEntry) => result = this.isValid(requestEntry));

View File

@@ -44,15 +44,16 @@
<div ngbDropdown class="input-group-append"> <div ngbDropdown class="input-group-append">
<button *ngIf="selectAllLoading" type="button" <button *ngIf="selectAllLoading" type="button"
class="btn btn-outline-secondary rounded-right"> class="btn btn-outline-secondary rounded-right">
<span class="spinner-border spinner-border-sm" role="status" <span class="spinner-border spinner-border-sm" role="status"
aria-hidden="true"></span> aria-hidden="true"></span>
<span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.loading' | translate) }}</span> <span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.loading' | translate) }}</span>
</button> </button>
<button *ngIf="!selectAllLoading" id="resultdropdown" type="button" <button id="resultdropdown" type="button"
ngbDropdownToggle ngbDropdownToggle
class="btn btn-outline-secondary dropdown-toggle-split" class="btn btn-outline-secondary dropdown-toggle-split"
data-toggle="dropdown" aria-haspopup="true" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false"> aria-expanded="false"
[hidden]="selectAllLoading">
<span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.toggle-dropdown' | translate) }}</span> <span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.toggle-dropdown' | translate) }}</span>
</button> </button>
<div ngbDropdownMenu aria-labelledby="resultdropdown"> <div ngbDropdownMenu aria-labelledby="resultdropdown">

View File

@@ -2,13 +2,13 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
import { PaginatedList } from '../../../../../core/data/paginated-list'; import { PaginatedList } from '../../../../../core/data/paginated-list';
import { SearchResult } from '../../../../search/search-result.model'; import { SearchResult } from '../../../../search/search-result.model';
import { RemoteData } from '../../../../../core/data/remote-data'; import { RemoteData } from '../../../../../core/data/remote-data';
import { Observable, ReplaySubject } from 'rxjs'; import { from, Observable, ReplaySubject } from 'rxjs';
import { SearchService } from '../../../../../core/shared/search/search.service'; import { SearchService } from '../../../../../core/shared/search/search.service';
import { PaginatedSearchOptions } from '../../../../search/paginated-search-options.model'; import { PaginatedSearchOptions } from '../../../../search/paginated-search-options.model';
import { DSpaceObject } from '../../../../../core/shared/dspace-object.model'; import { DSpaceObject } from '../../../../../core/shared/dspace-object.model';
import { PaginationComponentOptions } from '../../../../pagination/pagination-component-options.model'; import { PaginationComponentOptions } from '../../../../pagination/pagination-component-options.model';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { hasValue, isNotEmpty } from '../../../../empty.util'; import { hasValue, hasValueOperator, isNotEmpty } from '../../../../empty.util';
import { concat, map, mergeMap, multicast, switchMap, take, takeWhile, tap } from 'rxjs/operators'; import { concat, map, mergeMap, multicast, switchMap, take, takeWhile, tap } from 'rxjs/operators';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { SEARCH_CONFIG_SERVICE } from '../../../../../+my-dspace-page/my-dspace-page.component'; import { SEARCH_CONFIG_SERVICE } from '../../../../../+my-dspace-page/my-dspace-page.component';
@@ -117,12 +117,24 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy
}); });
} }
selectPage(page: SearchResult<DSpaceObject>[]) { selectPage(page: SearchResult<Item>[]) {
this.selection$
.pipe(take(1))
.subscribe((selection: SearchResult<Item>[]) => {
const filteredPage = page.filter((pageItem) => selection.findIndex((selected) => selected.equals(pageItem)) < 0)
this.select(...filteredPage);
});
this.selectableListService.select(this.listId, page); this.selectableListService.select(this.listId, page);
} }
deselectPage(page: SearchResult<DSpaceObject>[]) { deselectPage(page: SearchResult<Item>[]) {
this.allSelected = false; this.allSelected = false;
this.selection$
.pipe(take(1))
.subscribe((selection: SearchResult<Item>[]) => {
const filteredPage = page.filter((pageItem) => selection.findIndex((selected) => selected.equals(pageItem)) >= 0)
this.deselect(...filteredPage);
});
this.selectableListService.deselect(this.listId, page); this.selectableListService.deselect(this.listId, page);
} }
@@ -132,62 +144,84 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy
const fullPagination = Object.assign(new PaginationComponentOptions(), { const fullPagination = Object.assign(new PaginationComponentOptions(), {
query: this.searchQuery, query: this.searchQuery,
currentPage: 1, currentPage: 1,
pageSize: Number.POSITIVE_INFINITY pageSize: 9999
}); });
const fullSearchConfig = Object.assign(this.searchConfig, { pagination: fullPagination }); const fullSearchConfig = Object.assign(this.searchConfig, { pagination: fullPagination });
const results = this.searchService.search(fullSearchConfig); const results$ = this.searchService.search(fullSearchConfig) as Observable<RemoteData<PaginatedList<SearchResult<Item>>>>;
results.pipe( results$.pipe(
getSucceededRemoteData(), getSucceededRemoteData(),
map((resultsRD) => resultsRD.payload.page), map((resultsRD) => resultsRD.payload.page),
tap(() => this.selectAllLoading = false), tap(() => this.selectAllLoading = false),
).subscribe((results) => ).subscribe((results) => {
this.selectableListService.select(this.listId, results) this.selection$
.pipe(take(1))
.subscribe((selection: SearchResult<Item>[]) => {
const filteredResults = results.filter((pageItem) => selection.findIndex((selected) => selected.equals(pageItem)) < 0);
this.select(...filteredResults);
});
this.selectableListService.select(this.listId, results);
}
); );
} }
deselectAll() { deselectAll() {
this.allSelected = false; this.allSelected = false;
this.selection$
.pipe(take(1))
.subscribe((selection: SearchResult<Item>[]) => this.deselect(...selection));
this.selectableListService.deselectAll(this.listId); this.selectableListService.deselectAll(this.listId);
} }
select(selectableObject: SearchResult<Item>) { select(...selectableObjects: SearchResult<Item>[]) {
setTimeout(() => this.itemRD$ setTimeout(() => this.itemRD$
.pipe( .pipe(
getSucceededRemoteData(), getSucceededRemoteData(),
mergeMap((itemRD: RemoteData<Item>) => { switchMap((itemRD: RemoteData<Item>) => {
const type1: string = itemRD.payload.firstMetadataValue('relationship.type'); const type1: string = itemRD.payload.firstMetadataValue('relationship.type');
const type2: string = selectableObject.indexableObject.firstMetadataValue('relationship.type'); return from(selectableObjects).pipe(
return this.relationshipTypeService.getRelationshipTypeByLabelAndTypes(this.relationship.relationshipType, type1, type2) mergeMap((object) => {
.pipe( const type2: string = object.indexableObject.firstMetadataValue('relationship.type');
mergeMap((type: RelationshipType) => { return this.relationshipTypeService.getRelationshipTypeByLabelAndTypes(this.relationship.relationshipType, type1, type2)
const isSwitched = type.rightLabel === this.relationship.relationshipType; .pipe(
if (isSwitched) { mergeMap((type: RelationshipType) => {
return this.relationshipService.addRelationship(type.id, selectableObject.indexableObject, itemRD.payload); const isSwitched = type.rightLabel === this.relationship.relationshipType;
} else { if (isSwitched) {
return this.relationshipService.addRelationship(type.id, itemRD.payload, selectableObject.indexableObject); return this.relationshipService.addRelationship(type.id, object.indexableObject, itemRD.payload);
} } else {
} return this.relationshipService.addRelationship(type.id, itemRD.payload, object.indexableObject);
) }
); }
)
).pipe(take(1));
}));
}), }),
take(1) ).subscribe(), 0
) );
.subscribe(), 0);
} }
deselect(selectableObject: SearchResult<Item>) { deselect(...selectableObjects: SearchResult<Item>[]) {
setTimeout(() => this.itemRD$.pipe( setTimeout(() => this.itemRD$.pipe(
getSucceededRemoteData(), getSucceededRemoteData(),
switchMap((itemRD: RemoteData<Item>) => this.relationshipService.getRelationshipByItemsAndLabel(itemRD.payload, selectableObject.indexableObject, this.relationship.relationshipType)), switchMap((itemRD: RemoteData<Item>) => {
switchMap((relationship: Relationship) => this.relationshipService.deleteRelationship(relationship.id)), return from(selectableObjects).pipe(
tap(t => console.log(itemRD)),
mergeMap((object) => this.relationshipService.getRelationshipByItemsAndLabel(itemRD.payload, object.indexableObject, this.relationship.relationshipType)),
take(1),
hasValueOperator(),
mergeMap((relationship: Relationship) => this.relationshipService.deleteRelationship(relationship.id))
)
}),
take(1), take(1),
).subscribe(), 0); ).subscribe(), 0);
} }
ngOnDestroy(): void { ngOnDestroy()
if (hasValue(this.subscription)) { :
void {
if (hasValue(this.subscription)
) {
this.subscription.unsubscribe(); this.subscription.unsubscribe();
} }
} }