mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-16 22:43:03 +00:00
[CST-4633] Change dynamic-lookup-relation-search-tab.component in order to use search-component
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
[toRemove]="toRemove"
|
||||
(selectObject)="select($event)"
|
||||
(deselectObject)="deselect($event)"
|
||||
(resultFound)="setTotalInternals($event.pageInfo.totalElements)"
|
||||
class="d-block pt-3">
|
||||
</ds-dynamic-lookup-relation-search-tab>
|
||||
</ng-template>
|
||||
@@ -81,7 +82,7 @@
|
||||
<i class="fas fa-times"></i>
|
||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.discard-button" | translate}}</span>
|
||||
</button>
|
||||
<button class="btn btn-primary submit"
|
||||
<button class="btn btn-primary submit"
|
||||
[disabled]="(toAdd.length == 0 && toRemove.length == 0) || isPending"
|
||||
(click)="submitEv()">
|
||||
<span *ngIf="isPending" class="spinner-border spinner-border-sm" role="status"
|
||||
|
@@ -29,6 +29,7 @@ import { RemoteDataBuildService } from '../../../../../core/cache/builders/remot
|
||||
import { getAllSucceededRemoteDataPayload } from '../../../../../core/shared/operators';
|
||||
import { followLink } from '../../../../utils/follow-link-config.model';
|
||||
import { RelationshipType } from '../../../../../core/shared/item-relationships/relationship-type.model';
|
||||
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-dynamic-lookup-relation-modal',
|
||||
@@ -111,7 +112,7 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy
|
||||
/**
|
||||
* The total amount of internal items for the current options
|
||||
*/
|
||||
totalInternal$: Observable<number>;
|
||||
totalInternal$: BehaviorSubject<number> = new BehaviorSubject<number>(0);
|
||||
|
||||
/**
|
||||
* The total amount of results for each external source using the current options
|
||||
@@ -219,7 +220,7 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy
|
||||
select(...selectableObjects: SearchResult<Item>[]) {
|
||||
this.zone.runOutsideAngular(
|
||||
() => {
|
||||
const obs: Observable<any[]> = observableCombineLatest(...selectableObjects.map((sri: SearchResult<Item>) => {
|
||||
const obs: Observable<any[]> = observableCombineLatest([...selectableObjects.map((sri: SearchResult<Item>) => {
|
||||
this.addNameVariantSubscription(sri);
|
||||
return this.relationshipService.getNameVariant(this.listId, sri.indexableObject.uuid)
|
||||
.pipe(
|
||||
@@ -232,7 +233,7 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
]);
|
||||
obs
|
||||
.subscribe((arr: any[]) => {
|
||||
return arr.forEach((object: any) => {
|
||||
@@ -281,21 +282,22 @@ 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$ = observableCombineLatest(
|
||||
const externalSourcesAndOptions$ = observableCombineLatest([
|
||||
this.externalSourcesRD$,
|
||||
this.searchConfigService.paginatedSearchOptions
|
||||
);
|
||||
]);
|
||||
|
||||
this.totalExternal$ = externalSourcesAndOptions$.pipe(
|
||||
switchMap(([sources, options]) =>
|
||||
observableCombineLatest(...sources.map((source: ExternalSource) => this.lookupRelationService.getTotalExternalResults(source, options))))
|
||||
observableCombineLatest([...sources.map((source: ExternalSource) => this.lookupRelationService.getTotalExternalResults(source, options))]))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
setTotalInternals(totalPages: number) {
|
||||
this.totalInternal$.next(totalPages);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.router.navigate([], {});
|
||||
Object.values(this.subMap).forEach((subscription) => subscription.unsubscribe());
|
||||
|
@@ -1,73 +1,62 @@
|
||||
<div class="row">
|
||||
<ds-search-sidebar class="col-4" id="search-sidebar"
|
||||
[resultCount]="(resultsRD$ | async)?.payload?.totalElements"
|
||||
[inPlaceSearch]="true" [showViewModes]="false"></ds-search-sidebar>
|
||||
<div class="col-8">
|
||||
<ds-search-form [query]="(searchConfigService.paginatedSearchOptions | async)?.query"
|
||||
[inPlaceSearch]="true"
|
||||
[searchPlaceholder]="'submission.sections.describe.relationship-lookup.search-tab.search-form.placeholder' | translate">
|
||||
</ds-search-form>
|
||||
<ds-search *ngIf="this.relationship.searchConfiguration && context"
|
||||
[configuration]="this.relationship.searchConfiguration"
|
||||
[context]="context"
|
||||
[fixedFilterQuery]="this.relationship.filter"
|
||||
[inPlaceSearch]="true"
|
||||
[linkType]="linkTypes.ExternalLink"
|
||||
[searchFormPlaceholder]="'submission.sections.describe.relationship-lookup.search-tab.search-form.placeholder'"
|
||||
[selectable]="true"
|
||||
[selectionConfig]="{ repeatable: repeatable, listId: listId }"
|
||||
(resultFound)="onResultFound($event)"
|
||||
(deselectObject)="deselectObject.emit($event)"
|
||||
(selectObject)="selectObject.emit($event)">
|
||||
<div additionalSearchOptions *ngIf="repeatable" class="position-absolute">
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<!-- In theory we don't need separate checkboxes for this,
|
||||
but I wasn't able to get this to work correctly without them.
|
||||
Checkboxes that are in the indeterminate state always switch to checked when clicked
|
||||
This seemed like the cleanest and clearest solution to solve this issue for now. -->
|
||||
|
||||
<ds-search-labels [inPlaceSearch]="true"></ds-search-labels>
|
||||
|
||||
<div *ngIf="repeatable" class="position-absolute">
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<!-- In theory we don't need separate checkboxes for this,
|
||||
but I wasn't able to get this to work correctly without them.
|
||||
Checkboxes that are in the indeterminate state always switch to checked when clicked
|
||||
This seemed like the cleanest and clearest solution to solve this issue for now.
|
||||
-->
|
||||
<input *ngIf="!allSelected && !(someSelected$ | async)"
|
||||
type="checkbox"
|
||||
[indeterminate]="false"
|
||||
(change)="selectAll()">
|
||||
<input *ngIf="!allSelected && (someSelected$ | async)"
|
||||
type="checkbox"
|
||||
[indeterminate]="true"
|
||||
(change)="deselectAll()">
|
||||
<input *ngIf="allSelected" type="checkbox"
|
||||
[checked]="true"
|
||||
(change)="deselectAll()">
|
||||
</div>
|
||||
</div>
|
||||
<div ngbDropdown class="input-group-append">
|
||||
<button *ngIf="selectAllLoading" type="button"
|
||||
class="btn btn-outline-secondary rounded-right">
|
||||
<input *ngIf="!allSelected && !(someSelected$ | async)"
|
||||
type="checkbox"
|
||||
[indeterminate]="false"
|
||||
(change)="selectAll()">
|
||||
<input *ngIf="!allSelected && (someSelected$ | async)"
|
||||
type="checkbox"
|
||||
[indeterminate]="true"
|
||||
(change)="deselectAll()">
|
||||
<input *ngIf="allSelected" type="checkbox"
|
||||
[checked]="true"
|
||||
(change)="deselectAll()">
|
||||
</div>
|
||||
</div>
|
||||
<div ngbDropdown class="input-group-append">
|
||||
<button *ngIf="selectAllLoading" type="button"
|
||||
class="btn btn-outline-secondary rounded-right">
|
||||
<span class="spinner-border spinner-border-sm" role="status"
|
||||
aria-hidden="true"></span>
|
||||
<span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.search-tab.loading' | translate) }}</span>
|
||||
</button>
|
||||
<button id="resultdropdown" type="button"
|
||||
ngbDropdownToggle
|
||||
class="btn btn-outline-secondary dropdown-toggle-split"
|
||||
data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
[hidden]="selectAllLoading">
|
||||
<span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.toggle-dropdown' | translate) }}</span>
|
||||
</button>
|
||||
<div ngbDropdownMenu aria-labelledby="resultdropdown" *ngVar="(resultsRD$ | async) as resultsRD">
|
||||
<button class="dropdown-item"
|
||||
(click)="selectPage(resultsRD?.payload?.page)">{{ ('submission.sections.describe.relationship-lookup.search-tab.select-page' | translate) }}</button>
|
||||
<button class="dropdown-item"
|
||||
(click)="deselectPage(resultsRD?.payload?.page)">{{ ('submission.sections.describe.relationship-lookup.search-tab.deselect-page' | translate) }}</button>
|
||||
<button class="dropdown-item" (click)="selectAll()">{{ ('submission.sections.describe.relationship-lookup.search-tab.select-all' | translate) }}</button>
|
||||
<button class="dropdown-item" (click)="deselectAll()">{{ ('submission.sections.describe.relationship-lookup.search-tab.deselect-all' | translate) }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.search-tab.loading' | translate) }}</span>
|
||||
</button>
|
||||
<button id="resultdropdown" type="button"
|
||||
ngbDropdownToggle
|
||||
class="btn btn-outline-secondary dropdown-toggle-split"
|
||||
data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
[hidden]="selectAllLoading">
|
||||
<span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.toggle-dropdown' | translate) }}</span>
|
||||
</button>
|
||||
<div ngbDropdownMenu aria-labelledby="resultdropdown" *ngVar="(resultsRD$ | async) as resultsRD">
|
||||
<button class="dropdown-item"
|
||||
(click)="selectPage(resultsRD?.page)">{{ ('submission.sections.describe.relationship-lookup.search-tab.select-page' | translate) }}</button>
|
||||
<button class="dropdown-item"
|
||||
(click)="deselectPage(resultsRD?.page)">{{ ('submission.sections.describe.relationship-lookup.search-tab.deselect-page' | translate) }}</button>
|
||||
<button class="dropdown-item" (click)="selectAll()">{{ ('submission.sections.describe.relationship-lookup.search-tab.select-all' | translate) }}</button>
|
||||
<button class="dropdown-item" (click)="deselectAll()">{{ ('submission.sections.describe.relationship-lookup.search-tab.deselect-all' | translate) }}</button>
|
||||
</div>
|
||||
|
||||
<ds-search-results [searchResults]="(resultsRD$ | async)"
|
||||
[sortConfig]="this.lookupRelationService.searchConfig?.sort"
|
||||
[searchConfig]="this.lookupRelationService.searchConfig"
|
||||
[selectable]="true"
|
||||
[selectionConfig]="{ repeatable: repeatable, listId: listId }"
|
||||
[linkType]="linkTypes.ExternalLink"
|
||||
[context]="context"
|
||||
(deselectObject)="deselectObject.emit($event)"
|
||||
(selectObject)="selectObject.emit($event)">
|
||||
</ds-search-results>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</ds-search>
|
||||
|
@@ -4,7 +4,6 @@ import { DsDynamicLookupRelationSearchTabComponent } from './dynamic-lookup-rela
|
||||
import { SearchService } from '../../../../../../core/shared/search/search.service';
|
||||
import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service';
|
||||
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
|
||||
import { RouteService } from '../../../../../../core/services/route.service';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { VarDirective } from '../../../../../utils/var.directive';
|
||||
@@ -15,13 +14,13 @@ import { createSuccessfulRemoteDataObject$ } from '../../../../../remote-data.ut
|
||||
import { buildPaginatedList } from '../../../../../../core/data/paginated-list.model';
|
||||
import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model';
|
||||
import { Item } from '../../../../../../core/shared/item.model';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { LookupRelationService } from '../../../../../../core/data/lookup-relation.service';
|
||||
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
|
||||
import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub';
|
||||
import { RelationshipService } from '../../../../../../core/data/relationship.service';
|
||||
import { relatedRelationships } from '../../../../../testing/related-relationships.mock';
|
||||
import { RelationshipType } from '../../../../../../core/shared/item-relationships/relationship-type.model';
|
||||
import { SearchObjects } from '../../../../../search/models/search-objects.model';
|
||||
|
||||
|
||||
describe('DsDynamicLookupRelationSearchTabComponent', () => {
|
||||
@@ -41,6 +40,7 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => {
|
||||
let selection$;
|
||||
|
||||
let results;
|
||||
let searchResult;
|
||||
let selectableListService;
|
||||
let lookupRelationService;
|
||||
const relationshipService = jasmine.createSpyObj('searchByItemsAndType',{
|
||||
@@ -79,6 +79,9 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => {
|
||||
selection$ = observableOf([searchResult1, searchResult2]);
|
||||
|
||||
results = buildPaginatedList(undefined, [searchResult1, searchResult2, searchResult3]);
|
||||
searchResult = Object.assign(new SearchObjects(), {
|
||||
page: [searchResult1, searchResult2, searchResult3]
|
||||
});
|
||||
selectableListService = jasmine.createSpyObj('selectableListService', ['deselect', 'select', 'deselectAll']);
|
||||
lookupRelationService = jasmine.createSpyObj('lookupRelationService', {
|
||||
getLocalResults: createSuccessfulRemoteDataObject$(results)
|
||||
@@ -101,14 +104,6 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => {
|
||||
paginatedSearchOptions: observableOf(pSearchOptions)
|
||||
}
|
||||
},
|
||||
{
|
||||
provide: RouteService, useValue: {
|
||||
setParameter: () => {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
},
|
||||
{ provide: ActivatedRoute, useValue: { snapshot: { queryParams: {} } } },
|
||||
{ provide: LookupRelationService, useValue: lookupRelationService },
|
||||
{ provide: PaginationService, useValue: new PaginationServiceStub() },
|
||||
{ provide: RelationshipService, useValue: relationshipService }
|
||||
@@ -186,6 +181,7 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => {
|
||||
|
||||
describe('check searchByItemsAndType', () => {
|
||||
it('should call relationshipService.searchByItemsAndType', () => {
|
||||
component.onResultFound(searchResult);
|
||||
expect(relationshipService.searchByItemsAndType).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@@ -4,18 +4,15 @@ import { SearchConfigurationService } from '../../../../../../core/shared/search
|
||||
import { Item } from '../../../../../../core/shared/item.model';
|
||||
import { SearchResult } from '../../../../../search/models/search-result.model';
|
||||
import { PaginatedList } from '../../../../../../core/data/paginated-list.model';
|
||||
import { RemoteData } from '../../../../../../core/data/remote-data';
|
||||
import { Observable } from 'rxjs';
|
||||
import { RelationshipOptions } from '../../../models/relationship-options.model';
|
||||
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
|
||||
import { ListableObject } from '../../../../../object-collection/shared/listable-object.model';
|
||||
import { SearchService } from '../../../../../../core/shared/search/search.service';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service';
|
||||
import { hasValue } from '../../../../../empty.util';
|
||||
import { map, mapTo, startWith, switchMap, take, tap } from 'rxjs/operators';
|
||||
import { map, mapTo, switchMap, take, tap } from 'rxjs/operators';
|
||||
import { getFirstSucceededRemoteData, getRemoteDataPayload } from '../../../../../../core/shared/operators';
|
||||
import { RouteService } from '../../../../../../core/services/route.service';
|
||||
import { CollectionElementLinkType } from '../../../../../object-collection/collection-element-link.type';
|
||||
import { Context } from '../../../../../../core/shared/context.model';
|
||||
import { LookupRelationService } from '../../../../../../core/data/lookup-relation.service';
|
||||
@@ -24,6 +21,9 @@ import { RelationshipService } from '../../../../../../core/data/relationship.se
|
||||
import { RelationshipType } from '../../../../../../core/shared/item-relationships/relationship-type.model';
|
||||
|
||||
import { Relationship } from '../../../../../../core/shared/item-relationships/relationship.model';
|
||||
import { SearchObjects } from '../../../../../search/models/search-objects.model';
|
||||
import { DSpaceObject } from '../../../../../../core/shared/dspace-object.model';
|
||||
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
|
||||
|
||||
|
||||
@Component({
|
||||
@@ -107,7 +107,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
/**
|
||||
* Search results
|
||||
*/
|
||||
resultsRD$: Observable<RemoteData<PaginatedList<SearchResult<Item>>>>;
|
||||
resultsRD$: BehaviorSubject<SearchObjects<DSpaceObject>> = new BehaviorSubject<SearchObjects<DSpaceObject>>(null);
|
||||
|
||||
/**
|
||||
* Are all results selected?
|
||||
@@ -142,13 +142,15 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
*/
|
||||
linkTypes = CollectionElementLinkType;
|
||||
|
||||
/**
|
||||
* Emits an event with the current search result entries
|
||||
*/
|
||||
@Output() resultFound: EventEmitter<SearchObjects<DSpaceObject>> = new EventEmitter<SearchObjects<DSpaceObject>>();
|
||||
|
||||
constructor(
|
||||
private searchService: SearchService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private selectableListService: SelectableListService,
|
||||
public searchConfigService: SearchConfigurationService,
|
||||
private routeService: RouteService,
|
||||
public lookupRelationService: LookupRelationService,
|
||||
private relationshipService: RelationshipService,
|
||||
private paginationService: PaginationService
|
||||
@@ -160,21 +162,6 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.resetRoute();
|
||||
this.routeService.setParameter('fixedFilterQuery', this.relationship.filter);
|
||||
this.routeService.setParameter('configuration', this.relationship.searchConfiguration);
|
||||
this.resultsRD$ = this.searchConfigService.paginatedSearchOptions.pipe(
|
||||
switchMap((options) => this.lookupRelationService.getLocalResults(this.relationship, options).pipe(
|
||||
tap( res => {
|
||||
if ( !!res && res.hasSucceeded && this.isEditRelationship ) {
|
||||
const idOfItems = res.payload.page.map( itemSearchResult => {
|
||||
return itemSearchResult.indexableObject.uuid;
|
||||
});
|
||||
this.setSelectedIds(idOfItems,res.payload.page);
|
||||
}
|
||||
}),
|
||||
startWith(undefined),
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,7 +175,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
* Selects a page in the store
|
||||
* @param page The page to select
|
||||
*/
|
||||
selectPage(page: SearchResult<Item>[]) {
|
||||
selectPage(page: SearchResult<DSpaceObject>[]) {
|
||||
this.selection$
|
||||
.pipe(take(1))
|
||||
.subscribe((selection: SearchResult<Item>[]) => {
|
||||
@@ -202,7 +189,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
* Deselects a page in the store
|
||||
* @param page the page to deselect
|
||||
*/
|
||||
deselectPage(page: SearchResult<Item>[]) {
|
||||
deselectPage(page: SearchResult<DSpaceObject>[]) {
|
||||
this.allSelected = false;
|
||||
this.selection$
|
||||
.pipe(take(1))
|
||||
@@ -306,4 +293,16 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
onResultFound($event: SearchObjects<DSpaceObject>) {
|
||||
console.log($event);
|
||||
this.resultsRD$.next($event);
|
||||
this.resultFound.emit($event);
|
||||
if (this.isEditRelationship ) {
|
||||
const idOfItems = $event.page.map( itemSearchResult => {
|
||||
return itemSearchResult.indexableObject.uuid;
|
||||
});
|
||||
this.setSelectedIds(idOfItems, $event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user