mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-17 15:03:07 +00:00
fixed configuration
This commit is contained in:
@@ -30,14 +30,5 @@
|
||||
| translate}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<ds-input-suggestions [suggestions]="(filterSearchResults | async)"
|
||||
[placeholder]="'search.filters.filter.' + filterConfig.name + '.placeholder'| translate"
|
||||
[action]="getCurrentUrl()"
|
||||
[name]="filterConfig.paramName"
|
||||
[(ngModel)]="filter"
|
||||
(submitSuggestion)="onSubmit($event)"
|
||||
(clickSuggestion)="onClick($event)"
|
||||
(findSuggestions)="findSuggestions($event)"
|
||||
ngDefaultControl
|
||||
></ds-input-suggestions>
|
||||
|
||||
</div>
|
||||
|
@@ -21,3 +21,5 @@
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -6,7 +6,6 @@ import {
|
||||
SearchFacetFilterComponent
|
||||
} from '../search-facet-filter/search-facet-filter.component';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-boolean-filter',
|
||||
styleUrls: ['./search-boolean-filter.component.scss'],
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { FILTER_CONFIG, SearchFilterService } from '../search-filter.service';
|
||||
@@ -12,12 +12,12 @@ import { SearchService } from '../../../search-service/search.service';
|
||||
import { SearchServiceStub } from '../../../../shared/testing/search-service-stub';
|
||||
import { RemoteData } from '../../../../core/data/remote-data';
|
||||
import { PaginatedList } from '../../../../core/data/paginated-list';
|
||||
import { SearchOptions } from '../../../search-options.model';
|
||||
import { RouterStub } from '../../../../shared/testing/router-stub';
|
||||
import { Router } from '@angular/router';
|
||||
import { PageInfo } from '../../../../core/shared/page-info.model';
|
||||
import { SearchFacetFilterComponent } from './search-facet-filter.component';
|
||||
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
||||
import { SearchConfigurationService } from '../../../search-service/search-configuration.service';
|
||||
|
||||
describe('SearchFacetFilterComponent', () => {
|
||||
let comp: SearchFacetFilterComponent;
|
||||
@@ -66,6 +66,7 @@ describe('SearchFacetFilterComponent', () => {
|
||||
{ provide: Router, useValue: new RouterStub() },
|
||||
{ provide: FILTER_CONFIG, useValue: new SearchFilterConfig() },
|
||||
{ provide: RemoteDataBuildService, useValue: {aggregate: () => Observable.of({})} },
|
||||
{ provide: SearchConfigurationService, useValue: {getSearchOptions: () => Observable.of({})} },
|
||||
{
|
||||
provide: SearchFilterService, useValue: {
|
||||
getSelectedValuesForFilter: () => Observable.of(selectedValues),
|
||||
@@ -75,8 +76,7 @@ describe('SearchFacetFilterComponent', () => {
|
||||
incrementPage: (filterName: string) => {
|
||||
},
|
||||
resetPage: (filterName: string) => {
|
||||
},
|
||||
getSearchOptions: () => Observable.of({}),
|
||||
}
|
||||
/* tslint:enable:no-empty */
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ import { FacetValue } from '../../../search-service/facet-value.model';
|
||||
import { SearchFilterConfig } from '../../../search-service/search-filter-config.model';
|
||||
import { SearchService } from '../../../search-service/search.service';
|
||||
import { FILTER_CONFIG, SearchFilterService } from '../search-filter.service';
|
||||
import { SearchConfigurationService } from '../../../search-service/search-configuration.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-facet-filter',
|
||||
@@ -68,6 +69,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
||||
|
||||
constructor(protected searchService: SearchService,
|
||||
protected filterService: SearchFilterService,
|
||||
protected searchConfigService: SearchConfigurationService,
|
||||
protected rdbs: RemoteDataBuildService,
|
||||
protected router: Router,
|
||||
@Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig) {
|
||||
@@ -80,7 +82,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
||||
this.filterValues$ = new BehaviorSubject(new RemoteData(true, false, undefined, undefined, undefined));
|
||||
this.currentPage = this.getCurrentPage().distinctUntilChanged();
|
||||
this.selectedValues = this.filterService.getSelectedValuesForFilter(this.filterConfig);
|
||||
const searchOptions = this.filterService.getSearchOptions().distinctUntilChanged();
|
||||
const searchOptions = this.searchConfigService.getSearchOptions().distinctUntilChanged();
|
||||
this.subs.push(searchOptions.subscribe((options) => this.updateFilterValueList()));
|
||||
|
||||
const facetValues = Observable.combineLatest(searchOptions, this.currentPage, (options, page) => {
|
||||
@@ -240,7 +242,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
findSuggestions(data): void {
|
||||
if (isNotEmpty(data)) {
|
||||
this.filterService.getSearchOptions().first().subscribe(
|
||||
this.searchConfigService.getSearchOptions().first().subscribe(
|
||||
(options) => {
|
||||
this.filterSearchResults = this.searchService.getFacetValuesFor(this.filterConfig, 1, options, data.toLowerCase())
|
||||
.first()
|
||||
|
@@ -55,7 +55,7 @@ describe('SearchFilterService', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
service = new SearchFilterService(store, routeServiceStub, activatedRoute);
|
||||
service = new SearchFilterService(store, routeServiceStub);
|
||||
});
|
||||
|
||||
describe('when the initialCollapse method is triggered', () => {
|
||||
|
@@ -33,8 +33,8 @@ export const FILTER_CONFIG: InjectionToken<SearchFilterConfig> = new InjectionTo
|
||||
export class SearchFilterService {
|
||||
|
||||
constructor(private store: Store<SearchFiltersState>,
|
||||
private routeService: RouteService,
|
||||
private route: ActivatedRoute) {
|
||||
private routeService: RouteService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,141 +56,6 @@ export class SearchFilterService {
|
||||
return this.routeService.hasQueryParam(paramName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<string>} Emits the current scope's identifier
|
||||
*/
|
||||
getCurrentScope() {
|
||||
return this.routeService.getQueryParameterValue('scope');
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<string>} Emits the current query string
|
||||
*/
|
||||
getCurrentQuery() {
|
||||
return this.routeService.getQueryParameterValue('query');
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<string>} Emits the current pagination settings
|
||||
*/
|
||||
getCurrentPagination(pagination: any = {}): Observable<PaginationComponentOptions> {
|
||||
const page$ = this.routeService.getQueryParameterValue('page');
|
||||
const size$ = this.routeService.getQueryParameterValue('pageSize');
|
||||
return Observable.combineLatest(page$, size$, (page, size) => {
|
||||
return Object.assign(new PaginationComponentOptions(), pagination, {
|
||||
currentPage: page || 1,
|
||||
pageSize: size || pagination.pageSize
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<string>} Emits the current sorting settings
|
||||
*/
|
||||
getCurrentSort(defaultSort: SortOptions): Observable<SortOptions> {
|
||||
const sortDirection$ = this.routeService.getQueryParameterValue('sortDirection');
|
||||
const sortField$ = this.routeService.getQueryParameterValue('sortField');
|
||||
return Observable.combineLatest(sortDirection$, sortField$, (sortDirection, sortField) => {
|
||||
// Dirty fix because sometimes the observable value is null somehow
|
||||
sortField = this.route.snapshot.queryParamMap.get('sortField');
|
||||
|
||||
const field = sortField || defaultSort.field;
|
||||
const direction = SortDirection[sortDirection] || defaultSort.direction;
|
||||
return new SortOptions(field, direction)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<Params>} Emits the current active filters with their values as they are sent to the backend
|
||||
*/
|
||||
getCurrentFilters(): Observable<Params> {
|
||||
return this.routeService.getQueryParamsWithPrefix('f.').map((filterParams) => {
|
||||
if (isNotEmpty(filterParams)) {
|
||||
const params = {};
|
||||
Object.keys(filterParams).forEach((key) => {
|
||||
if (key.endsWith('.min') || key.endsWith('.max')) {
|
||||
const realKey = key.slice(0, -4);
|
||||
if (isEmpty(params[realKey])) {
|
||||
const min = filterParams[realKey + '.min'] ? filterParams[realKey + '.min'][0] : '*';
|
||||
const max = filterParams[realKey + '.max'] ? filterParams[realKey + '.max'][0] : '*';
|
||||
params[realKey] = ['[' + min + ' TO ' + max + ']'];
|
||||
}
|
||||
} else {
|
||||
params[key] = filterParams[key];
|
||||
}
|
||||
});
|
||||
return params;
|
||||
}
|
||||
return filterParams;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<Params>} Emits the current active filters with their values as they are displayed in the frontend URL
|
||||
*/
|
||||
getCurrentFrontendFilters(): Observable<Params> {
|
||||
return this.routeService.getQueryParamsWithPrefix('f.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<string>} Emits the current UI list view
|
||||
*/
|
||||
getCurrentView() {
|
||||
return this.routeService.getQueryParameterValue('view');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param defaults The default values for the search options, that will be used if nothing is explicitly set
|
||||
* @returns {Observable<PaginatedSearchOptions>} Emits the current paginated search options
|
||||
*/
|
||||
getPaginatedSearchOptions(defaults: any = {}): Observable<PaginatedSearchOptions> {
|
||||
return Observable.combineLatest(
|
||||
this.getCurrentPagination(defaults.pagination),
|
||||
this.getCurrentSort(defaults.sort),
|
||||
this.getCurrentView(),
|
||||
this.getCurrentScope(),
|
||||
this.getCurrentQuery(),
|
||||
this.getCurrentFilters()).pipe(
|
||||
distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),
|
||||
map(([pagination, sort, view, scope, query, filters]) => {
|
||||
return Object.assign(new PaginatedSearchOptions(),
|
||||
defaults,
|
||||
{
|
||||
pagination: pagination,
|
||||
sort: sort,
|
||||
view: view,
|
||||
scope: scope || defaults.scope,
|
||||
query: query,
|
||||
filters: filters
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param defaults The default values for the search options, that will be used if nothing is explicitly set
|
||||
* @returns {Observable<PaginatedSearchOptions>} Emits the current search options
|
||||
*/
|
||||
getSearchOptions(defaults: any = {}): Observable<SearchOptions> {
|
||||
return Observable.combineLatest(
|
||||
this.getCurrentView(),
|
||||
this.getCurrentScope(),
|
||||
this.getCurrentQuery(),
|
||||
this.getCurrentFilters(),
|
||||
(view, scope, query, filters) => {
|
||||
return Object.assign(new SearchOptions(),
|
||||
defaults,
|
||||
{
|
||||
view: view,
|
||||
scope: scope || defaults.scope,
|
||||
query: query,
|
||||
filters: filters
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the active filter values set for a given filter
|
||||
* @param {SearchFilterConfig} filterConfig The configuration for which the filters are active
|
||||
|
@@ -18,6 +18,7 @@ import { PageInfo } from '../../../../core/shared/page-info.model';
|
||||
import { SearchRangeFilterComponent } from './search-range-filter.component';
|
||||
import { RouteService } from '../../../../shared/services/route.service';
|
||||
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
||||
import { SearchConfigurationService } from '../../../search-service/search-configuration.service';
|
||||
|
||||
describe('SearchRangeFilterComponent', () => {
|
||||
let comp: SearchRangeFilterComponent;
|
||||
@@ -72,6 +73,9 @@ describe('SearchRangeFilterComponent', () => {
|
||||
{ provide: FILTER_CONFIG, useValue: mockFilterConfig },
|
||||
{ provide: RemoteDataBuildService, useValue: {aggregate: () => Observable.of({})} },
|
||||
{ provide: RouteService, useValue: {getQueryParameterValue: () => Observable.of({})} },
|
||||
{ provide: SearchConfigurationService, useValue: {
|
||||
getSearchOptions: () => Observable.of({}) }
|
||||
},
|
||||
{
|
||||
provide: SearchFilterService, useValue: {
|
||||
getSelectedValuesForFilter: () => selectedValues,
|
||||
@@ -81,8 +85,7 @@ describe('SearchRangeFilterComponent', () => {
|
||||
incrementPage: (filterName: string) => {
|
||||
},
|
||||
resetPage: (filterName: string) => {
|
||||
},
|
||||
getSearchOptions: () => Observable.of({}),
|
||||
}
|
||||
/* tslint:enable:no-empty */
|
||||
}
|
||||
}
|
||||
@@ -113,7 +116,6 @@ describe('SearchRangeFilterComponent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('when the onSubmit method is called with data', () => {
|
||||
const searchUrl = '/search/path';
|
||||
// const data = { [mockFilterConfig.paramName + minSuffix]: '1900', [mockFilterConfig.paramName + maxSuffix]: '1950' };
|
||||
|
@@ -16,6 +16,7 @@ import { Observable } from 'rxjs/Observable';
|
||||
import { RouteService } from '../../../../shared/services/route.service';
|
||||
import { hasValue } from '../../../../shared/empty.util';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { SearchConfigurationService } from '../../../search-service/search-configuration.service';
|
||||
|
||||
/**
|
||||
* This component renders a simple item page.
|
||||
@@ -61,12 +62,13 @@ export class SearchRangeFilterComponent extends SearchFacetFilterComponent imple
|
||||
|
||||
constructor(protected searchService: SearchService,
|
||||
protected filterService: SearchFilterService,
|
||||
protected searchConfigService: SearchConfigurationService,
|
||||
protected router: Router,
|
||||
protected rdbs: RemoteDataBuildService,
|
||||
@Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig,
|
||||
@Inject(PLATFORM_ID) private platformId: any,
|
||||
private route: RouteService) {
|
||||
super(searchService, filterService, rdbs, router, filterConfig);
|
||||
super(searchService, filterService, searchConfigService, rdbs, router, filterConfig);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -8,6 +8,7 @@ import { SearchFilterService } from './search-filter/search-filter.service';
|
||||
import { SearchFiltersComponent } from './search-filters.component';
|
||||
import { SearchService } from '../search-service/search.service';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { SearchConfigurationService } from '../search-service/search-configuration.service';
|
||||
|
||||
describe('SearchFiltersComponent', () => {
|
||||
let comp: SearchFiltersComponent;
|
||||
@@ -23,7 +24,7 @@ describe('SearchFiltersComponent', () => {
|
||||
}
|
||||
/* tslint:enable:no-empty */
|
||||
};
|
||||
const searchFilterServiceStub = jasmine.createSpyObj('SearchFilterService', {
|
||||
const searchConfigServiceStub = jasmine.createSpyObj('SearchConfigurationService', {
|
||||
getCurrentFrontendFilters: Observable.of({})
|
||||
});
|
||||
|
||||
@@ -33,7 +34,7 @@ describe('SearchFiltersComponent', () => {
|
||||
declarations: [SearchFiltersComponent],
|
||||
providers: [
|
||||
{ provide: SearchService, useValue: searchServiceStub },
|
||||
{ provide: SearchFilterService, useValue: searchFilterServiceStub },
|
||||
{ provide: SearchConfigurationService, useValue: searchConfigServiceStub },
|
||||
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
|
@@ -3,7 +3,7 @@ import { SearchService } from '../search-service/search.service';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { SearchFilterConfig } from '../search-service/search-filter-config.model';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { SearchFilterService } from './search-filter/search-filter.service';
|
||||
import { SearchConfigurationService } from '../search-service/search-configuration.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-filters',
|
||||
@@ -29,11 +29,11 @@ export class SearchFiltersComponent {
|
||||
/**
|
||||
* Initialize instance variables
|
||||
* @param {SearchService} searchService
|
||||
* @param {SearchFilterService} filterService
|
||||
* @param {SearchConfigurationService} searchConfigService
|
||||
*/
|
||||
constructor(private searchService: SearchService, private filterService: SearchFilterService) {
|
||||
constructor(private searchService: SearchService, private searchConfigService: SearchConfigurationService) {
|
||||
this.filters = searchService.getConfig();
|
||||
this.clearParams = filterService.getCurrentFrontendFilters().map((filters) => {Object.keys(filters).forEach((f) => filters[f] = null); return filters;});
|
||||
this.clearParams = searchConfigService.getCurrentFrontendFilters().map((filters) => {Object.keys(filters).forEach((f) => filters[f] = null); return filters;});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -9,7 +9,7 @@ import { SearchServiceStub } from '../../shared/testing/search-service-stub';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Params } from '@angular/router';
|
||||
import { ObjectKeysPipe } from '../../shared/utils/object-keys-pipe';
|
||||
import { SearchFilterService } from '../search-filters/search-filter/search-filter.service';
|
||||
import { SearchConfigurationService } from '../search-service/search-configuration.service';
|
||||
|
||||
describe('SearchLabelsComponent', () => {
|
||||
let comp: SearchLabelsComponent;
|
||||
@@ -35,7 +35,7 @@ describe('SearchLabelsComponent', () => {
|
||||
declarations: [SearchLabelsComponent, ObjectKeysPipe],
|
||||
providers: [
|
||||
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
||||
{ provide: SearchFilterService, useValue: {getCurrentFrontendFilters : () => Observable.of({})} }
|
||||
{ provide: SearchConfigurationService, useValue: {getCurrentFrontendFilters : () => Observable.of({})} }
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).overrideComponent(SearchLabelsComponent, {
|
||||
|
@@ -3,8 +3,8 @@ import { SearchService } from '../search-service/search.service';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Params } from '@angular/router';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { SearchFilterService } from '../search-filters/search-filter/search-filter.service';
|
||||
import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
||||
import { SearchConfigurationService } from '../search-service/search-configuration.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-labels',
|
||||
@@ -23,8 +23,8 @@ export class SearchLabelsComponent {
|
||||
/**
|
||||
* Initialize the instance variable
|
||||
*/
|
||||
constructor(private searchService: SearchService, private filterService: SearchFilterService) {
|
||||
this.appliedFilters = this.filterService.getCurrentFrontendFilters();
|
||||
constructor(private searchService: SearchService, private searchConfigService: SearchConfigurationService) {
|
||||
this.appliedFilters = this.searchConfigService.getCurrentFrontendFilters();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,40 +1,40 @@
|
||||
<div class="container">
|
||||
<div class="search-page row">
|
||||
<div class="search-page row">
|
||||
<ds-search-sidebar *ngIf="!(isXsOrSm$ | async)" class="col-3 sidebar-md-sticky"
|
||||
id="search-sidebar"
|
||||
[resultCount]="(resultsRD$ | async)?.payload.totalElements"></ds-search-sidebar>
|
||||
<div class="col-12 col-md-9">
|
||||
<ds-search-form id="search-form"
|
||||
[query]="(searchOptions$ | async)?.query"
|
||||
[scope]="(searchOptions$ | async)?.scope"
|
||||
[currentUrl]="getSearchLink()"
|
||||
[scopes]="(scopeListRD$ | async)">
|
||||
</ds-search-form>
|
||||
<ds-search-labels></ds-search-labels>
|
||||
<div class="row">
|
||||
<div id="search-body"
|
||||
class="row-offcanvas row-offcanvas-left"
|
||||
[@pushInOut]="(isSidebarCollapsed() | async) ? 'collapsed' : 'expanded'">
|
||||
<ds-search-sidebar *ngIf="(isXsOrSm$ | async)" class="col-12"
|
||||
id="search-sidebar-sm"
|
||||
[resultCount]="(resultsRD$ | async)?.payload.totalElements"
|
||||
(toggleSidebar)="closeSidebar()"
|
||||
[ngClass]="{'active': !(isSidebarCollapsed() | async)}">
|
||||
</ds-search-sidebar>
|
||||
<div id="search-content" class="col-12">
|
||||
<div class="d-block d-md-none search-controls clearfix">
|
||||
<ds-view-mode-switch></ds-view-mode-switch>
|
||||
<button (click)="openSidebar()" aria-controls="#search-body"
|
||||
class="btn btn-outline-primary float-right open-sidebar"><i
|
||||
class="fa fa-sliders"></i> {{"search.sidebar.open"
|
||||
| translate}}
|
||||
</button>
|
||||
<ds-search-form id="search-form"
|
||||
[query]="(searchOptions$ | async)?.query"
|
||||
[scope]="(searchOptions$ | async)?.scope"
|
||||
[currentUrl]="getSearchLink()"
|
||||
[scopes]="(scopeListRD$ | async)">
|
||||
</ds-search-form>
|
||||
<ds-search-labels></ds-search-labels>
|
||||
<div class="row">
|
||||
<div id="search-body"
|
||||
class="row-offcanvas row-offcanvas-left"
|
||||
[@pushInOut]="(isSidebarCollapsed() | async) ? 'collapsed' : 'expanded'">
|
||||
<ds-search-sidebar *ngIf="(isXsOrSm$ | async)" class="col-12"
|
||||
id="search-sidebar-sm"
|
||||
[resultCount]="(resultsRD$ | async)?.payload.totalElements"
|
||||
(toggleSidebar)="closeSidebar()"
|
||||
[ngClass]="{'active': !(isSidebarCollapsed() | async)}">
|
||||
</ds-search-sidebar>
|
||||
<div id="search-content" class="col-12">
|
||||
<div class="d-block d-md-none search-controls clearfix">
|
||||
<ds-view-mode-switch></ds-view-mode-switch>
|
||||
<button (click)="openSidebar()" aria-controls="#search-body"
|
||||
class="btn btn-outline-primary float-right open-sidebar"><i
|
||||
class="fa fa-sliders"></i> {{"search.sidebar.open"
|
||||
| translate}}
|
||||
</button>
|
||||
</div>
|
||||
<ds-search-results [searchResults]="resultsRD$ | async"
|
||||
[searchConfig]="searchOptions$ | async"></ds-search-results>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ds-search-results [searchResults]="resultsRD$ | async"
|
||||
[searchConfig]="searchOptions$ | async"></ds-search-results>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -19,6 +19,7 @@ import { By } from '@angular/platform-browser';
|
||||
import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
|
||||
import { SearchFilterService } from './search-filters/search-filter/search-filter.service';
|
||||
import { SearchConfigurationService } from './search-service/search-configuration.service';
|
||||
|
||||
describe('SearchPageComponent', () => {
|
||||
let comp: SearchPageComponent;
|
||||
@@ -89,7 +90,10 @@ describe('SearchPageComponent', () => {
|
||||
},
|
||||
{
|
||||
provide: SearchFilterService,
|
||||
useValue: jasmine.createSpyObj('SearchFilterService', {
|
||||
useValue: {}
|
||||
},{
|
||||
provide: SearchConfigurationService,
|
||||
useValue: jasmine.createSpyObj('SearchConfigurationService', {
|
||||
getPaginatedSearchOptions: hot('a', {
|
||||
a: paginatedSearchOptions
|
||||
}),
|
||||
|
@@ -15,6 +15,7 @@ import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { hasValue } from '../shared/empty.util';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
import { SearchConfigurationService } from './search-service/search-configuration.service';
|
||||
|
||||
/**
|
||||
* This component renders a simple item page.
|
||||
@@ -55,19 +56,6 @@ export class SearchPageComponent implements OnInit {
|
||||
*/
|
||||
isXsOrSm$: Observable<boolean>;
|
||||
|
||||
/**
|
||||
* Default values for the Search Options
|
||||
*/
|
||||
defaults = {
|
||||
pagination: {
|
||||
id: 'search-results-pagination',
|
||||
pageSize: 10
|
||||
},
|
||||
sort: new SortOptions('score', SortDirection.DESC),
|
||||
query: '',
|
||||
scope: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* Subscription to unsubscribe from
|
||||
*/
|
||||
@@ -76,7 +64,8 @@ export class SearchPageComponent implements OnInit {
|
||||
constructor(private service: SearchService,
|
||||
private sidebarService: SearchSidebarService,
|
||||
private windowService: HostWindowService,
|
||||
private filterService: SearchFilterService) {
|
||||
private filterService: SearchFilterService,
|
||||
private searchConfigService: SearchConfigurationService) {
|
||||
this.isXsOrSm$ = this.windowService.isXsOrSm();
|
||||
}
|
||||
|
||||
@@ -88,11 +77,11 @@ export class SearchPageComponent implements OnInit {
|
||||
* If something changes, update the list of scopes for the dropdown
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.searchOptions$ = this.filterService.getPaginatedSearchOptions(this.defaults);
|
||||
this.searchOptions$ = this.searchConfigService.getPaginatedSearchOptions();
|
||||
this.sub = this.searchOptions$.subscribe((searchOptions) =>
|
||||
this.service.search(searchOptions).filter((rd) => !rd.isLoading).first().subscribe((results) => this.resultsRD$.next(results)));
|
||||
|
||||
this.scopeListRD$ = this.filterService.getCurrentScope().pipe(
|
||||
this.scopeListRD$ = this.searchConfigService.getCurrentScope().pipe(
|
||||
flatMap((scopeId) => this.service.getScopes(scopeId))
|
||||
);
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ import { SearchTextFilterComponent } from './search-filters/search-filter/search
|
||||
import { SearchFacetFilterWrapperComponent } from './search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component';
|
||||
import { SearchBooleanFilterComponent } from './search-filters/search-filter/search-boolean-filter/search-boolean-filter.component';
|
||||
import { SearchHierarchyFilterComponent } from './search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component';
|
||||
import { SearchConfigurationService } from './search-service/search-configuration.service';
|
||||
|
||||
const effects = [
|
||||
SearchSidebarEffects
|
||||
@@ -66,7 +67,8 @@ const effects = [
|
||||
providers: [
|
||||
SearchService,
|
||||
SearchSidebarService,
|
||||
SearchFilterService
|
||||
SearchFilterService,
|
||||
SearchConfigurationService
|
||||
],
|
||||
entryComponents: [
|
||||
ItemSearchResultListElementComponent,
|
||||
|
@@ -0,0 +1,130 @@
|
||||
import { SearchConfigurationService } from './search-configuration.service';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { ActivatedRouteStub } from '../../shared/testing/active-router-stub';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { fakeAsync, tick } from '@angular/core/testing';
|
||||
|
||||
describe('SearchConfigurationService', () => {
|
||||
let service: SearchConfigurationService;
|
||||
const value1 = 'random value';
|
||||
const value2 = 'another value';
|
||||
const prefixFilter = {
|
||||
'f.author': ['another value'],
|
||||
'f.date.min': ['2013'],
|
||||
'f.date.max': ['2018']
|
||||
};
|
||||
const defaults = Observable.of(new RemoteData(false, false, true, null, {}))
|
||||
const backendFilters = { 'f.author': ['another value'], 'f.date': ['[2013 TO 2018]'] };
|
||||
|
||||
const spy = jasmine.createSpyObj('SearchConfigurationService', {
|
||||
getQueryParameterValue: Observable.of([value1, value2])
|
||||
,
|
||||
getQueryParamsWithPrefix: Observable.of(prefixFilter)
|
||||
});
|
||||
|
||||
const activatedRoute: any = new ActivatedRouteStub();
|
||||
|
||||
beforeEach(() => {
|
||||
service = new SearchConfigurationService(spy, activatedRoute);
|
||||
});
|
||||
|
||||
describe('when getCurrentScope is called', () => {
|
||||
beforeEach(() => {
|
||||
service.getCurrentScope();
|
||||
});
|
||||
it('should call getQueryParameterValue on the routeService with parameter name \'scope\'', () => {
|
||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('scope');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when getCurrentQuery is called', () => {
|
||||
beforeEach(() => {
|
||||
service.getCurrentQuery();
|
||||
});
|
||||
it('should call getQueryParameterValue on the routeService with parameter name \'query\'', () => {
|
||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('query');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when getCurrentFrontendFilters is called', () => {
|
||||
beforeEach(() => {
|
||||
service.getCurrentFrontendFilters();
|
||||
});
|
||||
it('should call getQueryParamsWithPrefix on the routeService with parameter prefix \'f.\'', () => {
|
||||
expect((service as any).routeService.getQueryParamsWithPrefix).toHaveBeenCalledWith('f.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when getCurrentFilters is called', () => {
|
||||
let parsedValues$;
|
||||
beforeEach(() => {
|
||||
parsedValues$ = service.getCurrentFilters();
|
||||
});
|
||||
it('should call getQueryParamsWithPrefix on the routeService with parameter prefix \'f.\'', () => {
|
||||
expect((service as any).routeService.getQueryParamsWithPrefix).toHaveBeenCalledWith('f.');
|
||||
parsedValues$.subscribe((values) => {
|
||||
expect(values).toEqual(backendFilters);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when getCurrentSort is called', () => {
|
||||
beforeEach(() => {
|
||||
service.getCurrentSort({} as any);
|
||||
});
|
||||
it('should call getQueryParameterValue on the routeService with parameter name \'sortDirection\'', () => {
|
||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortDirection');
|
||||
});
|
||||
it('should call getQueryParameterValue on the routeService with parameter name \'sortField\'', () => {
|
||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortField');
|
||||
});
|
||||
});
|
||||
describe('when getCurrentPagination is called', () => {
|
||||
beforeEach(() => {
|
||||
service.getCurrentPagination({});
|
||||
});
|
||||
it('should call getQueryParameterValue on the routeService with parameter name \'page\'', () => {
|
||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('page');
|
||||
});
|
||||
it('should call getQueryParameterValue on the routeService with parameter name \'pageSize\'', () => {
|
||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('pageSize');
|
||||
});
|
||||
});
|
||||
fdescribe('when getPaginatedSearchOptions or getSearchOptions is called', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(service, 'getCurrentPagination');
|
||||
spyOn(service, 'getCurrentSort');
|
||||
spyOn(service, 'getCurrentScope');
|
||||
spyOn(service, 'getCurrentQuery');
|
||||
spyOn(service, 'getCurrentFilters');
|
||||
});
|
||||
describe('when getPaginatedSearchOptions is called', () => {
|
||||
beforeEach(() => {
|
||||
service.getPaginatedSearchOptions(defaults);
|
||||
});
|
||||
it('should call all getters it needs', fakeAsync(() => {
|
||||
defaults.subscribe(() => {
|
||||
tick();
|
||||
expect(service.getCurrentPagination).toHaveBeenCalled();
|
||||
expect(service.getCurrentSort).toHaveBeenCalled();
|
||||
expect(service.getCurrentScope).toHaveBeenCalled();
|
||||
expect(service.getCurrentQuery).toHaveBeenCalled();
|
||||
expect(service.getCurrentFilters).toHaveBeenCalled();
|
||||
}
|
||||
)
|
||||
}));
|
||||
});
|
||||
describe('when getSearchOptions is called', () => {
|
||||
beforeEach(() => {
|
||||
service.getSearchOptions();
|
||||
});
|
||||
it('should call all getters it needs', () => {
|
||||
expect(service.getCurrentPagination).not.toHaveBeenCalled();
|
||||
expect(service.getCurrentSort).not.toHaveBeenCalled();
|
||||
expect(service.getCurrentScope).toHaveBeenCalled();
|
||||
expect(service.getCurrentQuery).toHaveBeenCalled();
|
||||
expect(service.getCurrentFilters).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@@ -0,0 +1,174 @@
|
||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||
import { SearchOptions } from '../search-options.model';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { ActivatedRoute, Params } from '@angular/router';
|
||||
import { PaginatedSearchOptions } from '../paginated-search-options.model';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { RouteService } from '../../shared/services/route.service';
|
||||
import { hasNoValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
|
||||
/**
|
||||
* Service that performs all actions that have to do with the current search configuration
|
||||
*/
|
||||
@Injectable()
|
||||
export class SearchConfigurationService {
|
||||
private defaultPagination = { id: 'search-page-configuration', pageSize: 10 };
|
||||
|
||||
private defaultSort = new SortOptions('score', SortDirection.DESC);
|
||||
|
||||
private defaultScope = '';
|
||||
|
||||
private _defaults;
|
||||
|
||||
constructor(private routeService: RouteService,
|
||||
private route: ActivatedRoute) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<string>} Emits the current scope's identifier
|
||||
*/
|
||||
getCurrentScope() {
|
||||
return this.routeService.getQueryParameterValue('scope');
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<string>} Emits the current query string
|
||||
*/
|
||||
getCurrentQuery() {
|
||||
return this.routeService.getQueryParameterValue('query');
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<string>} Emits the current pagination settings
|
||||
*/
|
||||
getCurrentPagination(pagination: any = {}): Observable<PaginationComponentOptions> {
|
||||
const page$ = this.routeService.getQueryParameterValue('page');
|
||||
const size$ = this.routeService.getQueryParameterValue('pageSize');
|
||||
return Observable.combineLatest(page$, size$, (page, size) => {
|
||||
return Object.assign(new PaginationComponentOptions(), pagination, {
|
||||
currentPage: page || 1,
|
||||
pageSize: size || pagination.pageSize
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<string>} Emits the current sorting settings
|
||||
*/
|
||||
getCurrentSort(defaultSort: SortOptions): Observable<SortOptions> {
|
||||
const sortDirection$ = this.routeService.getQueryParameterValue('sortDirection');
|
||||
const sortField$ = this.routeService.getQueryParameterValue('sortField');
|
||||
return Observable.combineLatest(sortDirection$, sortField$, (sortDirection, sortField) => {
|
||||
// Dirty fix because sometimes the observable value is null somehow
|
||||
sortField = this.route.snapshot.queryParamMap.get('sortField');
|
||||
|
||||
const field = sortField || defaultSort.field;
|
||||
const direction = SortDirection[sortDirection] || defaultSort.direction;
|
||||
return new SortOptions(field, direction)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<Params>} Emits the current active filters with their values as they are sent to the backend
|
||||
*/
|
||||
getCurrentFilters(): Observable<Params> {
|
||||
return this.routeService.getQueryParamsWithPrefix('f.').map((filterParams) => {
|
||||
if (isNotEmpty(filterParams)) {
|
||||
const params = {};
|
||||
Object.keys(filterParams).forEach((key) => {
|
||||
if (key.endsWith('.min') || key.endsWith('.max')) {
|
||||
const realKey = key.slice(0, -4);
|
||||
if (isEmpty(params[realKey])) {
|
||||
const min = filterParams[realKey + '.min'] ? filterParams[realKey + '.min'][0] : '*';
|
||||
const max = filterParams[realKey + '.max'] ? filterParams[realKey + '.max'][0] : '*';
|
||||
params[realKey] = ['[' + min + ' TO ' + max + ']'];
|
||||
}
|
||||
} else {
|
||||
params[key] = filterParams[key];
|
||||
}
|
||||
});
|
||||
return params;
|
||||
}
|
||||
return filterParams;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<Params>} Emits the current active filters with their values as they are displayed in the frontend URL
|
||||
*/
|
||||
getCurrentFrontendFilters(): Observable<Params> {
|
||||
return this.routeService.getQueryParamsWithPrefix('f.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param defaults The default values for the search options, that will be used if nothing is explicitly set
|
||||
* @returns {Observable<PaginatedSearchOptions>} Emits the current paginated search options
|
||||
*/
|
||||
getPaginatedSearchOptions(defaults: Observable<RemoteData<any>> = this.defaults): Observable<PaginatedSearchOptions> {
|
||||
return defaults.flatMap((defaultConfig) => {
|
||||
const defaultValues = defaultConfig.payload;
|
||||
return Observable.combineLatest(
|
||||
this.getCurrentPagination(defaultValues.pagination),
|
||||
this.getCurrentSort(defaultValues.sort),
|
||||
this.getCurrentScope(),
|
||||
this.getCurrentQuery(),
|
||||
this.getCurrentFilters()).pipe(
|
||||
distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),
|
||||
map(([pagination, sort, scope, query, filters]) => {
|
||||
return Object.assign(new PaginatedSearchOptions(),
|
||||
defaults,
|
||||
{
|
||||
pagination: pagination,
|
||||
sort: sort,
|
||||
scope: scope || defaultValues.scope,
|
||||
query: query,
|
||||
filters: filters
|
||||
})
|
||||
})
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param defaults The default values for the search options, that will be used if nothing is explicitly set
|
||||
* @returns {Observable<PaginatedSearchOptions>} Emits the current search options
|
||||
*/
|
||||
getSearchOptions(defaults: Observable<RemoteData<any>> = this.defaults): Observable<SearchOptions> {
|
||||
return defaults.flatMap((defaultConfig) => {
|
||||
const defaultValues = defaultConfig.payload;
|
||||
return Observable.combineLatest(
|
||||
this.getCurrentScope(),
|
||||
this.getCurrentQuery(),
|
||||
this.getCurrentFilters(),
|
||||
(scope, query, filters) => {
|
||||
return Object.assign(new SearchOptions(),
|
||||
{
|
||||
scope: scope || defaultValues.scope,
|
||||
query: query,
|
||||
filters: filters
|
||||
})
|
||||
}
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Default values for the Search Options
|
||||
*/
|
||||
get defaults() {
|
||||
if (hasNoValue(this._defaults)) {
|
||||
const options = {
|
||||
pagination: this.defaultPagination,
|
||||
sort: this.defaultSort,
|
||||
scope: this.defaultScope
|
||||
};
|
||||
this._defaults = Observable.of(new RemoteData(false, false, true, null, options));
|
||||
}
|
||||
return this._defaults;
|
||||
}
|
||||
}
|
@@ -25,9 +25,9 @@ import {
|
||||
} from '../../core/cache/response-cache.models';
|
||||
import { SearchQueryResponse } from './search-query-response.model';
|
||||
import { SearchFilterConfig } from './search-filter-config.model';
|
||||
import { CollectionDataService } from '../../core/data/collection-data.service';
|
||||
import { CommunityDataService } from '../../core/data/community-data.service';
|
||||
import { ViewMode } from '../../core/shared/view-mode.model';
|
||||
import { PIDService } from '../../core/data/pid.service';
|
||||
|
||||
@Component({ template: '' })
|
||||
class DummyComponent {
|
||||
@@ -57,7 +57,7 @@ describe('SearchService', () => {
|
||||
{ provide: RemoteDataBuildService, useValue: {} },
|
||||
{ provide: HALEndpointService, useValue: {} },
|
||||
{ provide: CommunityDataService, useValue: {}},
|
||||
{ provide: CollectionDataService, useValue: {}},
|
||||
{ provide: PIDService, useValue: {}},
|
||||
SearchService
|
||||
],
|
||||
});
|
||||
@@ -114,7 +114,7 @@ describe('SearchService', () => {
|
||||
{ provide: RemoteDataBuildService, useValue: remoteDataBuildService },
|
||||
{ provide: HALEndpointService, useValue: halService },
|
||||
{ provide: CommunityDataService, useValue: {}},
|
||||
{ provide: CollectionDataService, useValue: {}},
|
||||
{ provide: PIDService, useValue: {}},
|
||||
SearchService
|
||||
],
|
||||
});
|
||||
|
@@ -26,7 +26,7 @@ import { GenericConstructor } from '../../core/shared/generic-constructor';
|
||||
import { HALEndpointService } from '../../core/shared/hal-endpoint.service';
|
||||
import { configureRequest } from '../../core/shared/operators';
|
||||
import { URLCombiner } from '../../core/url-combiner/url-combiner';
|
||||
import { hasNoValue, hasValue, isNotEmpty } from '../../shared/empty.util';
|
||||
import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
|
||||
import { NormalizedSearchResult } from '../normalized-search-result.model';
|
||||
import { SearchOptions } from '../search-options.model';
|
||||
import { SearchResult } from '../search-result.model';
|
||||
@@ -42,10 +42,9 @@ import { FacetConfigResponseParsingService } from '../../core/data/facet-config-
|
||||
import { PaginatedSearchOptions } from '../paginated-search-options.model';
|
||||
import { Community } from '../../core/shared/community.model';
|
||||
import { CommunityDataService } from '../../core/data/community-data.service';
|
||||
import { CollectionDataService } from '../../core/data/collection-data.service';
|
||||
import { Collection } from '../../core/shared/collection.model';
|
||||
import { ViewMode } from '../../core/shared/view-mode.model';
|
||||
|
||||
import { PIDService } from '../../core/data/pid.service';
|
||||
import { ResourceType } from '../../core/shared/resource-type';
|
||||
|
||||
/**
|
||||
* Service that performs all general actions that have to do with the search page
|
||||
@@ -74,7 +73,8 @@ export class SearchService implements OnDestroy {
|
||||
private rdb: RemoteDataBuildService,
|
||||
private halService: HALEndpointService,
|
||||
private communityService: CommunityDataService,
|
||||
private collectionService: CollectionDataService) {
|
||||
private pidService: PIDService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,7 +258,7 @@ export class SearchService implements OnDestroy {
|
||||
*/
|
||||
getScopes(scopeId?: string): Observable<DSpaceObject[]> {
|
||||
|
||||
if (hasNoValue(scopeId)) {
|
||||
if (isEmpty(scopeId)) {
|
||||
const top: Observable<Community[]> = this.communityService.findTop({ elementsPerPage: 9999 }).pipe(
|
||||
map(
|
||||
(communities: RemoteData<PaginatedList<Community>>) => communities.payload.page
|
||||
@@ -267,24 +267,22 @@ export class SearchService implements OnDestroy {
|
||||
return top;
|
||||
}
|
||||
|
||||
const communityScope: Observable<RemoteData<Community>> = this.communityService.findById(scopeId).filter((communityRD: RemoteData<Community>) => !communityRD.isLoading);
|
||||
const scopeObject: Observable<DSpaceObject[]> = communityScope.pipe(
|
||||
flatMap((communityRD: RemoteData<Community>) => {
|
||||
if (hasValue(communityRD.payload)) {
|
||||
const community: Community = communityRD.payload;
|
||||
// const subcommunities$ = community.subcommunities.filter((subcommunitiesRD: RemoteData<PaginatedList<Community>>) => !subcommunitiesRD.isLoading).first();
|
||||
// const collections$ = community.subcommunities.filter((subcommunitiesRD: RemoteData<PaginatedList<Community>>) => !subcommunitiesRD.isLoading).first();
|
||||
const scopeObject: Observable<RemoteData<DSpaceObject>> = this.pidService.findById(scopeId).filter((dsoRD: RemoteData<DSpaceObject>) => !dsoRD.isLoading);
|
||||
const scopeList: Observable<DSpaceObject[]> = scopeObject.pipe(
|
||||
flatMap((dsoRD: RemoteData<DSpaceObject>) => {
|
||||
if (dsoRD.payload.type === ResourceType.Community) {
|
||||
const community: Community = dsoRD.payload as Community;
|
||||
return Observable.combineLatest(community.subcommunities, community.collections, (subCommunities, collections) => {
|
||||
/*if this is a community, we also need to show the direct children*/
|
||||
return [community, ...subCommunities.payload.page, ...collections.payload.page]
|
||||
})
|
||||
} else {
|
||||
return this.collectionService.findById(scopeId).pipe(map((collectionRD: RemoteData<Collection>) => [collectionRD.payload]));
|
||||
return Observable.of([dsoRD.payload]);
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
return scopeObject;
|
||||
return scopeList;
|
||||
|
||||
}
|
||||
|
||||
|
@@ -14,6 +14,7 @@ import { By } from '@angular/platform-browser';
|
||||
import { SearchFilterService } from '../search-filters/search-filter/search-filter.service';
|
||||
import { hot } from 'jasmine-marbles';
|
||||
import { VarDirective } from '../../shared/utils/var.directive';
|
||||
import { SearchConfigurationService } from '../search-service/search-configuration.service';
|
||||
|
||||
describe('SearchSettingsComponent', () => {
|
||||
|
||||
@@ -68,7 +69,11 @@ describe('SearchSettingsComponent', () => {
|
||||
},
|
||||
{
|
||||
provide: SearchFilterService,
|
||||
useValue: jasmine.createSpyObj('SearchFilterService', {
|
||||
useValue: {}
|
||||
},
|
||||
{
|
||||
provide: SearchConfigurationService,
|
||||
useValue: jasmine.createSpyObj('SearchConfigurationService', {
|
||||
getPaginatedSearchOptions: hot('a', {
|
||||
a: paginatedSearchOptions
|
||||
}),
|
||||
|
@@ -5,6 +5,7 @@ import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
|
||||
import { PaginatedSearchOptions } from '../paginated-search-options.model';
|
||||
import { SearchFilterService } from '../search-filters/search-filter/search-filter.service';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { SearchConfigurationService } from '../search-service/search-configuration.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-settings',
|
||||
@@ -27,30 +28,17 @@ export class SearchSettingsComponent implements OnInit {
|
||||
*/
|
||||
searchOptionPossibilities = [new SortOptions('score', SortDirection.DESC), new SortOptions('dc.title', SortDirection.ASC), new SortOptions('dc.title', SortDirection.DESC)];
|
||||
|
||||
/**
|
||||
* Default values for the Search Options
|
||||
*/
|
||||
defaults = {
|
||||
pagination: {
|
||||
id: 'search-results-pagination',
|
||||
pageSize: 10
|
||||
},
|
||||
sort: new SortOptions('score', SortDirection.DESC),
|
||||
query: '',
|
||||
scope: ''
|
||||
};
|
||||
|
||||
constructor(private service: SearchService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private filterService: SearchFilterService) {
|
||||
private searchConfigurationService: SearchConfigurationService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize paginated search options
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.searchOptions$ = this.filterService.getPaginatedSearchOptions(this.defaults);
|
||||
this.searchOptions$ = this.searchConfigurationService.getPaginatedSearchOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -23,7 +23,6 @@ class DataServiceImpl extends DataService<NormalizedDSpaceObject, DSpaceObject>
|
||||
protected requestService: RequestService,
|
||||
protected rdbService: RemoteDataBuildService,
|
||||
protected store: Store<CoreState>,
|
||||
private bs: BrowseService,
|
||||
protected halService: HALEndpointService) {
|
||||
super();
|
||||
}
|
||||
@@ -46,7 +45,7 @@ export class PIDService {
|
||||
protected requestService: RequestService,
|
||||
protected rdbService: RemoteDataBuildService,
|
||||
protected halService: HALEndpointService) {
|
||||
this.dataService = new DataServiceImpl(null, requestService, rdbService, null, null, halService);
|
||||
this.dataService = new DataServiceImpl(null, requestService, rdbService, null, halService);
|
||||
}
|
||||
|
||||
findById(id: string): Observable<RemoteData<DSpaceObject>> {
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { SearchService } from '../../+search-page/search-service/search.service';
|
||||
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
||||
import { Router } from '@angular/router';
|
||||
import { isNotEmpty, hasValue, isEmpty, hasNoValue } from '../empty.util';
|
||||
@@ -31,6 +30,7 @@ export class SearchFormComponent {
|
||||
*/
|
||||
@Input()
|
||||
scope = '';
|
||||
|
||||
@Input() currentUrl: string;
|
||||
|
||||
/**
|
||||
|
@@ -31,7 +31,6 @@ export class DebounceDirective implements OnInit, OnDestroy {
|
||||
*/
|
||||
private isFirstChange = true;
|
||||
|
||||
|
||||
/**
|
||||
* Subject to unsubscribe from
|
||||
*/
|
||||
|
Reference in New Issue
Block a user