mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
67478: LookupRelationService, external source tabs, list implementation
This commit is contained in:
@@ -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",
|
||||||
|
@@ -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,
|
||||||
|
94
src/app/core/data/lookup-relation.service.ts
Normal file
94
src/app/core/data/lookup-relation.service.ts
Normal 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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -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>
|
||||||
|
@@ -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');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
@@ -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());
|
||||||
}
|
}
|
||||||
|
@@ -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>
|
||||||
|
@@ -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
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -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"
|
||||||
|
@@ -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(),
|
||||||
|
@@ -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 }),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user