67478: LookupRelationService, external source tabs, list implementation

This commit is contained in:
Kristof De Langhe
2019-12-02 17:07:28 +01:00
parent de4b32dcad
commit edbc32604d
12 changed files with 239 additions and 62 deletions

View File

@@ -1466,6 +1466,8 @@
"search.results.no-results-link": "quotes around it", "search.results.no-results-link": "quotes around it",
"search.results.empty": "Your search returned no results.",
"search.sidebar.close": "Back to results", "search.sidebar.close": "Back to results",
@@ -1539,13 +1541,21 @@
"submission.sections.describe.relationship-lookup.selected": "Selected {{ size }} items", "submission.sections.describe.relationship-lookup.selected": "Selected {{ size }} items",
"submission.sections.describe.relationship-lookup.search-tab.tab-title.Author": "Search for Authors", "submission.sections.describe.relationship-lookup.search-tab.tab-title.Author": "Local Authors ({{ count }})",
"submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal": "Search for Journals", "submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal": "Local Journals ({{ count }})",
"submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal Issue": "Search for Journal Issues", "submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal Issue": "Local Journal Issues ({{ count }})",
"submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal Volume": "Search for Journal Volumes", "submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal Volume": "Local Journal Volumes ({{ count }})",
"submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaJournal": "Sherpa Journals ({{ count }})",
"submission.sections.describe.relationship-lookup.search-tab.tab-title.sherpaPublisher": "Sherpa Publishers ({{ count }})",
"submission.sections.describe.relationship-lookup.search-tab.tab-title.orcidV2": "ORCID ({{ count }})",
"submission.sections.describe.relationship-lookup.search-tab.tab-title.lcname": "LC Names ({{ count }})",
"submission.sections.describe.relationship-lookup.selection-tab.tab-title": "Current Selection ({{ count }})", "submission.sections.describe.relationship-lookup.selection-tab.tab-title": "Current Selection ({{ count }})",
@@ -1571,6 +1581,14 @@
"submission.sections.describe.relationship-lookup.selection-tab.title.Journal Issue": "Selected Issue", "submission.sections.describe.relationship-lookup.selection-tab.title.Journal Issue": "Selected Issue",
"submission.sections.describe.relationship-lookup.selection-tab.title.sherpaJournal": "Search Results",
"submission.sections.describe.relationship-lookup.selection-tab.title.sherpaPublisher": "Search Results",
"submission.sections.describe.relationship-lookup.selection-tab.title.orcidV2": "Search Results",
"submission.sections.describe.relationship-lookup.selection-tab.title.lcname": "Search Results",
"submission.sections.describe.relationship-lookup.name-variant.notification.content": "Would you like to save \"{{ value }}\" as a name variant for this person so you and others can reuse it for future submissions? If you don\'t you can still use it for this submission.", "submission.sections.describe.relationship-lookup.name-variant.notification.content": "Would you like to save \"{{ value }}\" as a name variant for this person so you and others can reuse it for future submissions? If you don\'t you can still use it for this submission.",
"submission.sections.describe.relationship-lookup.name-variant.notification.confirm": "Save a new name variant", "submission.sections.describe.relationship-lookup.name-variant.notification.confirm": "Save a new name variant",

View File

@@ -137,6 +137,7 @@ import { SidebarService } from '../shared/sidebar/sidebar.service';
import { NormalizedExternalSource } from './cache/models/normalized-external-source.model'; import { NormalizedExternalSource } from './cache/models/normalized-external-source.model';
import { NormalizedExternalSourceEntry } from './cache/models/normalized-external-source-entry.model'; import { NormalizedExternalSourceEntry } from './cache/models/normalized-external-source-entry.model';
import { ExternalSourceService } from './data/external-source.service'; import { ExternalSourceService } from './data/external-source.service';
import { LookupRelationService } from './data/lookup-relation.service';
export const restServiceFactory = (cfg: GlobalConfig, mocks: MockResponseMap, http: HttpClient) => { export const restServiceFactory = (cfg: GlobalConfig, mocks: MockResponseMap, http: HttpClient) => {
if (ENV_CONFIG.production) { if (ENV_CONFIG.production) {
@@ -244,6 +245,7 @@ const PROVIDERS = [
SelectableListService, SelectableListService,
RelationshipTypeService, RelationshipTypeService,
ExternalSourceService, ExternalSourceService,
LookupRelationService,
// register AuthInterceptor as HttpInterceptor // register AuthInterceptor as HttpInterceptor
{ {
provide: HTTP_INTERCEPTORS, provide: HTTP_INTERCEPTORS,

View File

@@ -0,0 +1,94 @@
import { ExternalSourceService } from './external-source.service';
import { SearchService } from '../shared/search/search.service';
import { concat, map, multicast, startWith, take, takeWhile } from 'rxjs/operators';
import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model';
import { ReplaySubject } from 'rxjs/internal/ReplaySubject';
import { RemoteData } from './remote-data';
import { PaginatedList } from './paginated-list';
import { SearchResult } from '../../shared/search/search-result.model';
import { DSpaceObject } from '../shared/dspace-object.model';
import { RelationshipOptions } from '../../shared/form/builder/models/relationship-options.model';
import { Observable } from 'rxjs/internal/Observable';
import { Item } from '../shared/item.model';
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
import { getAllSucceededRemoteData, getRemoteDataPayload } from '../shared/operators';
import { Injectable } from '@angular/core';
import { ExternalSource } from '../shared/external-source.model';
import { ExternalSourceEntry } from '../shared/external-source-entry.model';
/**
* A service for retrieving local and external entries information during a relation lookup
*/
@Injectable()
export class LookupRelationService {
/**
* The search config last used for retrieving local results
*/
public searchConfig: PaginatedSearchOptions;
/**
* Pagination options for retrieving exactly one result
*/
private singleResultOptions = Object.assign(new PaginationComponentOptions(), {
id: 'single-result-options',
pageSize: 1
});
constructor(protected externalSourceService: ExternalSourceService,
protected searchService: SearchService) {
}
/**
* Retrieve the available local entries for a relationship
* @param relationship Relationship options
* @param searchOptions Search options to filter results
* @param setSearchConfig Optionally choose if we should store the used search config in a local variable (defaults to true)
*/
getLocalResults(relationship: RelationshipOptions, searchOptions: PaginatedSearchOptions, setSearchConfig = true): Observable<RemoteData<PaginatedList<SearchResult<Item>>>> {
const newConfig = Object.assign(new PaginatedSearchOptions({}), searchOptions,
{ fixedFilter: relationship.filter, configuration: relationship.searchConfiguration }
);
if (setSearchConfig) {
this.searchConfig = newConfig;
}
return this.searchService.search(newConfig).pipe(
/* Make sure to only listen to the first x results, until loading is finished */
/* TODO: in Rxjs 6.4.0 and up, we can replace this with takeWhile(predicate, true) - see https://stackoverflow.com/a/44644237 */
multicast(
() => new ReplaySubject(1),
(subject) => subject.pipe(
takeWhile((rd: RemoteData<PaginatedList<SearchResult<DSpaceObject>>>) => rd.isLoading),
concat(subject.pipe(take(1)))
)
) as any
)
}
/**
* Calculate the total local entries available for the given relationship
* @param relationship Relationship options
* @param searchOptions Search options to filter results
*/
getTotalLocalResults(relationship: RelationshipOptions, searchOptions: PaginatedSearchOptions): Observable<number> {
return this.getLocalResults(relationship, Object.assign(new PaginatedSearchOptions({}), searchOptions, { pagination: this.singleResultOptions }), false).pipe(
getAllSucceededRemoteData(),
getRemoteDataPayload(),
map((results: PaginatedList<SearchResult<Item>>) => results.totalElements),
startWith(0)
);
}
/**
* Calculate the total external entries available for a given external source
* @param externalSource External Source
* @param searchOptions Search options to filter results
*/
getTotalExternalResults(externalSource: ExternalSource, searchOptions: PaginatedSearchOptions): Observable<number> {
return this.externalSourceService.getExternalSourceEntries(externalSource.id, Object.assign(new PaginatedSearchOptions({}), searchOptions, { pagination: this.singleResultOptions })).pipe(
getAllSucceededRemoteData(),
getRemoteDataPayload(),
map((results: PaginatedList<ExternalSourceEntry>) => results.totalElements),
startWith(0)
);
}
}

View File

@@ -1 +1,2 @@
<div>Listable external source works! Display: {{object.value}}</div> <div>{{object.display}}</div>
<div *ngIf="uri"><a [href]="uri.value">{{uri.value}}</a></div>

View File

@@ -3,7 +3,9 @@ import { ExternalSourceEntry } from '../../../../../core/shared/external-source-
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
import { ViewMode } from '../../../../../core/shared/view-mode.model'; import { ViewMode } from '../../../../../core/shared/view-mode.model';
import { Context } from '../../../../../core/shared/context.model'; import { Context } from '../../../../../core/shared/context.model';
import { Component } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Metadata } from '../../../../../core/shared/metadata.utils';
import { MetadataValue } from '../../../../../core/shared/metadata.models';
@listableObjectComponent(ExternalSourceEntry, ViewMode.ListElement, Context.SubmissionModal) @listableObjectComponent(ExternalSourceEntry, ViewMode.ListElement, Context.SubmissionModal)
@Component({ @Component({
@@ -11,6 +13,13 @@ import { Component } from '@angular/core';
styleUrls: ['./external-source-entry-list-submission-element.component.scss'], styleUrls: ['./external-source-entry-list-submission-element.component.scss'],
templateUrl: './external-source-entry-list-submission-element.component.html' templateUrl: './external-source-entry-list-submission-element.component.html'
}) })
export class ExternalSourceEntryListSubmissionElementComponent extends AbstractListableElementComponent<ExternalSourceEntry> { export class ExternalSourceEntryListSubmissionElementComponent extends AbstractListableElementComponent<ExternalSourceEntry> implements OnInit {
/**
* The metadata value for the object's uri
*/
uri: MetadataValue;
ngOnInit(): void {
this.uri = Metadata.first(this.object.metadata, 'dc.identifier.uri');
}
} }

View File

@@ -7,7 +7,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<ngb-tabset> <ngb-tabset>
<ngb-tab [title]="'submission.sections.describe.relationship-lookup.search-tab.tab-title.' + label | translate"> <ngb-tab [title]="'submission.sections.describe.relationship-lookup.search-tab.tab-title.' + label | translate : {count: (totalInternal$ | async)}">
<ng-template ngbTabContent> <ng-template ngbTabContent>
<ds-dynamic-lookup-relation-search-tab <ds-dynamic-lookup-relation-search-tab
[selection$]="selection$" [selection$]="selection$"
@@ -21,6 +21,20 @@
</ds-dynamic-lookup-relation-search-tab> </ds-dynamic-lookup-relation-search-tab>
</ng-template> </ng-template>
</ngb-tab> </ngb-tab>
<ngb-tab *ngFor="let source of (externalSourcesRD$ | async)?.payload?.page; let idx = index"
[title]="'submission.sections.describe.relationship-lookup.search-tab.tab-title.' + source.id | translate : {count: (totalExternal$ | async)[idx]}">
<ng-template ngbTabContent>
<ds-dynamic-lookup-relation-external-source-tab
[listId]="listId"
[repeatable]="repeatable"
[context]="context"
[externalSource]="source"
(selectObject)="select($event)"
(deselectObject)="deselect($event)"
class="d-block pt-3">
</ds-dynamic-lookup-relation-external-source-tab>
</ng-template>
</ngb-tab>
<ngb-tab [title]="'submission.sections.describe.relationship-lookup.selection-tab.tab-title' | translate : {count: (selection$ | async)?.length}"> <ngb-tab [title]="'submission.sections.describe.relationship-lookup.selection-tab.tab-title' | translate : {count: (selection$ | async)?.length}">
<ng-template ngbTabContent> <ng-template ngbTabContent>
<ds-dynamic-lookup-relation-selection-tab <ds-dynamic-lookup-relation-selection-tab
@@ -42,4 +56,4 @@
<div> <div>
<button type="button" class="btn btn-danger" (click)="close()">{{ ('submission.sections.describe.relationship-lookup.close' | translate) }}</button> <button type="button" class="btn btn-danger" (click)="close()">{{ ('submission.sections.describe.relationship-lookup.close' | translate) }}</button>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,5 @@
import { Component, NgZone, OnDestroy, OnInit } from '@angular/core'; import { Component, NgZone, OnDestroy, OnInit } from '@angular/core';
import { combineLatest, Observable, Subscription } from 'rxjs'; import { combineLatest, Observable, Subscription, zip as observableZip } from 'rxjs';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { hasValue } from '../../../../empty.util'; import { hasValue } from '../../../../empty.util';
import { map, skip, switchMap, take } from 'rxjs/operators'; import { map, skip, switchMap, take } from 'rxjs/operators';
@@ -11,7 +11,11 @@ import { ListableObject } from '../../../../object-collection/shared/listable-ob
import { RelationshipOptions } from '../../models/relationship-options.model'; import { RelationshipOptions } from '../../models/relationship-options.model';
import { SearchResult } from '../../../../search/search-result.model'; import { SearchResult } from '../../../../search/search-result.model';
import { Item } from '../../../../../core/shared/item.model'; import { Item } from '../../../../../core/shared/item.model';
import { getRemoteDataPayload, getSucceededRemoteData } from '../../../../../core/shared/operators'; import {
getAllSucceededRemoteData,
getRemoteDataPayload,
getSucceededRemoteData
} from '../../../../../core/shared/operators';
import { AddRelationshipAction, RemoveRelationshipAction, UpdateRelationshipAction } from './relationship.actions'; import { AddRelationshipAction, RemoveRelationshipAction, UpdateRelationshipAction } from './relationship.actions';
import { RelationshipService } from '../../../../../core/data/relationship.service'; import { RelationshipService } from '../../../../../core/data/relationship.service';
import { RelationshipTypeService } from '../../../../../core/data/relationship-type.service'; import { RelationshipTypeService } from '../../../../../core/data/relationship-type.service';
@@ -20,6 +24,11 @@ import { AppState } from '../../../../../app.reducer';
import { Context } from '../../../../../core/shared/context.model'; import { Context } from '../../../../../core/shared/context.model';
import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model'; import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model';
import { MetadataValue } from '../../../../../core/shared/metadata.models'; import { MetadataValue } from '../../../../../core/shared/metadata.models';
import { LookupRelationService } from '../../../../../core/data/lookup-relation.service';
import { RemoteData } from '../../../../../core/data/remote-data';
import { PaginatedList } from '../../../../../core/data/paginated-list';
import { ExternalSource } from '../../../../../core/shared/external-source.model';
import { ExternalSourceService } from '../../../../../core/data/external-source.service';
@Component({ @Component({
selector: 'ds-dynamic-lookup-relation-modal', selector: 'ds-dynamic-lookup-relation-modal',
@@ -46,11 +55,29 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy
[uuid: string]: Subscription [uuid: string]: Subscription
} = {}; } = {};
/**
* A list of the available external sources configured for this relationship
*/
externalSourcesRD$: Observable<RemoteData<PaginatedList<ExternalSource>>>;
/**
* The total amount of internal items for the current options
*/
totalInternal$: Observable<number>;
/**
* The total amount of results for each external source using the current options
*/
totalExternal$: Observable<number[]>;
constructor( constructor(
public modal: NgbActiveModal, public modal: NgbActiveModal,
private selectableListService: SelectableListService, private selectableListService: SelectableListService,
private relationshipService: RelationshipService, private relationshipService: RelationshipService,
private relationshipTypeService: RelationshipTypeService, private relationshipTypeService: RelationshipTypeService,
private externalSourceService: ExternalSourceService,
private lookupRelationService: LookupRelationService,
private searchConfigService: SearchConfigurationService,
private zone: NgZone, private zone: NgZone,
private store: Store<AppState> private store: Store<AppState>
) { ) {
@@ -67,6 +94,9 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy
this.context = Context.SubmissionModal; this.context = Context.SubmissionModal;
} }
this.externalSourcesRD$ = this.externalSourceService.findAll();
this.setTotals();
// this.setExistingNameVariants(); // this.setExistingNameVariants();
} }
@@ -148,6 +178,28 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy
) )
} }
/**
* Calculate and set the total entries available for each tab
*/
setTotals() {
this.totalInternal$ = this.searchConfigService.paginatedSearchOptions.pipe(
switchMap((options) => this.lookupRelationService.getTotalLocalResults(this.relationshipOptions, options))
);
const externalSourcesAndOptions$ = combineLatest(
this.externalSourcesRD$.pipe(
getAllSucceededRemoteData(),
getRemoteDataPayload()
),
this.searchConfigService.paginatedSearchOptions
);
this.totalExternal$ = externalSourcesAndOptions$.pipe(
switchMap(([sources, options]) =>
observableZip(...sources.page.map((source: ExternalSource) => this.lookupRelationService.getTotalExternalResults(source, options))))
);
}
ngOnDestroy() { ngOnDestroy() {
Object.values(this.subMap).forEach((subscription) => subscription.unsubscribe()); Object.values(this.subMap).forEach((subscription) => subscription.unsubscribe());
} }

View File

@@ -4,20 +4,28 @@
<ds-page-size-selector></ds-page-size-selector> <ds-page-size-selector></ds-page-size-selector>
</div> </div>
<div class="col-8"> <div class="col-8">
<div *ngIf="(entriesRD$ | async)?.payload.page < 1"> <ds-search-form [query]="(searchConfigService.paginatedSearchOptions | async)?.query" [inPlaceSearch]="true"></ds-search-form>
{{'submission.sections.describe.relationship-lookup.selection-tab.no-selection' | translate}} <div>
</div> <h3>{{ 'submission.sections.describe.relationship-lookup.selection-tab.title.' + externalSource.id | translate}}</h3>
<div *ngIf="(entriesRD$ | async)?.payload.page.length >= 1"> <ng-container *ngVar="(entriesRD$ | async) as entriesRD">
<h3>{{ 'submission.sections.describe.relationship-lookup.selection-tab.title.' + label | translate}}</h3> <ds-viewable-collection *ngIf="entriesRD?.hasSucceeded && !entriesRD?.isLoading && entriesRD?.payload?.page.length > 0" @fadeIn
<ds-viewable-collection [objects]="entriesRD$ | async" [objects]="entriesRD"
[selectable]="true" [selectable]="true"
[selectionConfig]="{ repeatable: repeatable, listId: listId }" [selectionConfig]="{ repeatable: repeatable, listId: listId }"
[config]="initialPagination" [config]="initialPagination"
[hideGear]="true" [hideGear]="true"
[context]="context" [context]="context"
(deselectObject)="deselectObject.emit($event)" (deselectObject)="deselectObject.emit($event)"
(selectObject)="selectObject.emit($event)" (selectObject)="selectObject.emit($event)">
></ds-viewable-collection> </ds-viewable-collection>
<ds-loading *ngIf="!entriesRD || !entriesRD?.payload || entriesRD?.isLoading"
message="{{'loading.search-results' | translate}}"></ds-loading>
<ds-error *ngIf="entriesRD?.hasFailed && (!entriesRD?.error || entriesRD?.error?.statusCode != 400)"
message="{{'error.search-results' | translate}}"></ds-error>
<div *ngIf="entriesRD?.payload?.page.length == 0 || entriesRD?.error?.statusCode == 400">
{{ 'search.results.empty' | translate }}
</div>
</ng-container>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -10,9 +10,10 @@ import { ExternalSourceEntry } from '../../../../../../core/shared/external-sour
import { ExternalSource } from '../../../../../../core/shared/external-source.model'; import { ExternalSource } from '../../../../../../core/shared/external-source.model';
import { switchMap } from 'rxjs/operators'; import { switchMap } from 'rxjs/operators';
import { PaginatedSearchOptions } from '../../../../../search/paginated-search-options.model'; import { PaginatedSearchOptions } from '../../../../../search/paginated-search-options.model';
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
import { Context } from '../../../../../../core/shared/context.model'; import { Context } from '../../../../../../core/shared/context.model';
import { ListableObject } from '../../../../../object-collection/shared/listable-object.model'; import { ListableObject } from '../../../../../object-collection/shared/listable-object.model';
import { fadeIn, fadeInOut } from '../../../../../animations/fade';
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
@Component({ @Component({
selector: 'ds-dynamic-lookup-relation-external-source-tab', selector: 'ds-dynamic-lookup-relation-external-source-tab',
@@ -23,6 +24,10 @@ import { ListableObject } from '../../../../../object-collection/shared/listable
provide: SEARCH_CONFIG_SERVICE, provide: SEARCH_CONFIG_SERVICE,
useClass: SearchConfigurationService useClass: SearchConfigurationService
} }
],
animations: [
fadeIn,
fadeInOut
] ]
}) })

View File

@@ -56,8 +56,8 @@
</div> </div>
</div> </div>
<ds-search-results [searchResults]="(resultsRD$ | async)" <ds-search-results [searchResults]="(resultsRD$ | async)"
[sortConfig]="this.searchConfig?.sort" [sortConfig]="this.lookupRelationService.searchConfig?.sort"
[searchConfig]="this.searchConfig" [searchConfig]="this.lookupRelationService.searchConfig"
[selectable]="true" [selectable]="true"
[selectionConfig]="{ repeatable: repeatable, listId: listId }" [selectionConfig]="{ repeatable: repeatable, listId: listId }"
[linkType]="linkTypes.ExternalLink" [linkType]="linkTypes.ExternalLink"
@@ -66,4 +66,4 @@
(selectObject)="selectObject.emit($event)"> (selectObject)="selectObject.emit($event)">
</ds-search-results> </ds-search-results>
</div> </div>
</div> </div>

View File

@@ -11,7 +11,7 @@ import { RelationshipOptions } from '../../../models/relationship-options.model'
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
import { ListableObject } from '../../../../../object-collection/shared/listable-object.model'; import { ListableObject } from '../../../../../object-collection/shared/listable-object.model';
import { SearchService } from '../../../../../../core/shared/search/search.service'; import { SearchService } from '../../../../../../core/shared/search/search.service';
import { Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service'; import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service';
import { hasValue, isNotEmpty } from '../../../../../empty.util'; import { hasValue, isNotEmpty } from '../../../../../empty.util';
import { concat, map, multicast, switchMap, take, takeWhile, tap } from 'rxjs/operators'; import { concat, map, multicast, switchMap, take, takeWhile, tap } from 'rxjs/operators';
@@ -20,6 +20,7 @@ import { getSucceededRemoteData } from '../../../../../../core/shared/operators'
import { RouteService } from '../../../../../../core/services/route.service'; import { RouteService } from '../../../../../../core/services/route.service';
import { CollectionElementLinkType } from '../../../../../object-collection/collection-element-link.type'; import { CollectionElementLinkType } from '../../../../../object-collection/collection-element-link.type';
import { Context } from '../../../../../../core/shared/context.model'; import { Context } from '../../../../../../core/shared/context.model';
import { LookupRelationService } from '../../../../../../core/data/lookup-relation.service';
@Component({ @Component({
selector: 'ds-dynamic-lookup-relation-search-tab', selector: 'ds-dynamic-lookup-relation-search-tab',
@@ -43,7 +44,6 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
@Output() deselectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>(); @Output() deselectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
@Output() selectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>(); @Output() selectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
resultsRD$: Observable<RemoteData<PaginatedList<SearchResult<Item>>>>; resultsRD$: Observable<RemoteData<PaginatedList<SearchResult<Item>>>>;
searchConfig: PaginatedSearchOptions;
allSelected: boolean; allSelected: boolean;
someSelected$: Observable<boolean>; someSelected$: Observable<boolean>;
selectAllLoading: boolean; selectAllLoading: boolean;
@@ -57,9 +57,11 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
constructor( constructor(
private searchService: SearchService, private searchService: SearchService,
private router: Router, private router: Router,
private route: ActivatedRoute,
private selectableListService: SelectableListService, private selectableListService: SelectableListService,
private searchConfigService: SearchConfigurationService, private searchConfigService: SearchConfigurationService,
private routeService: RouteService, private routeService: RouteService,
protected lookupRelationService: LookupRelationService
) { ) {
} }
@@ -70,29 +72,13 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
this.someSelected$ = this.selection$.pipe(map((selection) => isNotEmpty(selection))); this.someSelected$ = this.selection$.pipe(map((selection) => isNotEmpty(selection)));
this.resultsRD$ = this.searchConfigService.paginatedSearchOptions.pipe( this.resultsRD$ = this.searchConfigService.paginatedSearchOptions.pipe(
map((options) => { switchMap((options) => this.lookupRelationService.getLocalResults(this.relationship, options))
return Object.assign(new PaginatedSearchOptions({}), options, { fixedFilter: this.relationship.filter, configuration: this.relationship.searchConfiguration })
}),
switchMap((options) => {
this.searchConfig = options;
return this.searchService.search(options).pipe(
/* Make sure to only listen to the first x results, until loading is finished */
/* TODO: in Rxjs 6.4.0 and up, we can replace this with takeWhile(predicate, true) - see https://stackoverflow.com/a/44644237 */
multicast(
() => new ReplaySubject(1),
(subject) => subject.pipe(
takeWhile((rd: RemoteData<PaginatedList<SearchResult<DSpaceObject>>>) => rd.isLoading),
concat(subject.pipe(take(1)))
)
) as any
)
})
); );
} }
resetRoute() { resetRoute() {
this.router.navigate([], { this.router.navigate([], {
queryParams: Object.assign({}, { page: 1, pageSize: this.initialPagination.pageSize }), queryParams: Object.assign({}, { pageSize: this.initialPagination.pageSize }, this.route.snapshot.queryParams, { page: 1 })
}); });
} }
@@ -124,7 +110,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
currentPage: 1, currentPage: 1,
pageSize: 9999 pageSize: 9999
}); });
const fullSearchConfig = Object.assign(this.searchConfig, { pagination: fullPagination }); const fullSearchConfig = Object.assign(this.lookupRelationService.searchConfig, { pagination: fullPagination });
const results$ = this.searchService.search(fullSearchConfig) as Observable<RemoteData<PaginatedList<SearchResult<Item>>>>; const results$ = this.searchService.search(fullSearchConfig) as Observable<RemoteData<PaginatedList<SearchResult<Item>>>>;
results$.pipe( results$.pipe(
getSucceededRemoteData(), getSucceededRemoteData(),

View File

@@ -35,17 +35,11 @@ export class DsDynamicLookupRelationSelectionTabComponent {
@Output() deselectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>(); @Output() deselectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
@Output() selectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>(); @Output() selectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
initialPagination = Object.assign(new PaginationComponentOptions(), {
id: 'submission-relation-list',
pageSize: 5
});
constructor(private router: Router, constructor(private router: Router,
private searchConfigService: SearchConfigurationService) { private searchConfigService: SearchConfigurationService) {
} }
ngOnInit() { ngOnInit() {
this.resetRoute();
this.selectionRD$ = this.searchConfigService.paginatedSearchOptions this.selectionRD$ = this.searchConfigService.paginatedSearchOptions
.pipe( .pipe(
map((options: PaginatedSearchOptions) => options.pagination), map((options: PaginatedSearchOptions) => options.pagination),
@@ -69,10 +63,4 @@ export class DsDynamicLookupRelationSelectionTabComponent {
}) })
) )
} }
resetRoute() {
this.router.navigate([], {
queryParams: Object.assign({}, { page: 1, pageSize: this.initialPagination.pageSize }),
});
}
} }