Skip to content
Snippets Groups Projects
Commit 1231d3eb authored by lotte's avatar lotte
Browse files

53029: almost finished filtered discovery pages

parent b06629c9
No related branches found
No related tags found
No related merge requests found
import { CommunityDataService } from '../core/data/community-data.service';
import { HostWindowService } from '../shared/host-window.service';
import { SearchFilterService } from './search-filters/search-filter/search-filter.service';
import { SearchService } from './search-service/search.service';
import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
import { SearchPageComponent } from './search-page.component';
import { RouteService } from '../shared/route.service';
import { ChangeDetectionStrategy, Component, Injectable } from '@angular/core';
import { pushInOut } from '../shared/animations/push';
/**
* This component renders a simple item page.
* The route parameter 'id' is used to request the item it represents.
* All fields of the item that should be displayed, are defined in its template.
*/
@Component({selector: 'ds-filtered-search-page',
styleUrls: ['./search-page.component.scss'],
templateUrl: './search-page.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
animations: [pushInOut]
})
export class FilteredSearchPageComponent extends SearchPageComponent {
constructor(protected service: SearchService,
protected communityService: CommunityDataService,
protected sidebarService: SearchSidebarService,
protected windowService: HostWindowService,
protected filterService: SearchFilterService,
protected routeService: RouteService) {
super(service, communityService, sidebarService, windowService, filterService, routeService);
}
}
......@@ -20,6 +20,7 @@ import { SortDirection, SortOptions } from '../../../core/cache/models/sort-opti
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
import { SearchOptions } from '../../search-options.model';
import { PaginatedSearchOptions } from '../../paginated-search-options.model';
import { SearchFixedFilterService } from './search-fixed-filter.service';
const filterStateSelector = (state: SearchFiltersState) => state.searchFilter;
......@@ -27,7 +28,8 @@ const filterStateSelector = (state: SearchFiltersState) => state.searchFilter;
export class SearchFilterService {
constructor(private store: Store<SearchFiltersState>,
private routeService: RouteService) {
private routeService: RouteService,
private fixedFilterService: SearchFixedFilterService) {
}
isFilterActiveWithValue(paramName: string, filterValue: string): Observable<boolean> {
......@@ -72,6 +74,11 @@ export class SearchFilterService {
return this.routeService.getQueryParamsWithPrefix('f.');
}
getCurrentFixedFilter(): Observable<string> {
const filter: Observable<string> = this.routeService.getRouteParameterValue('filter');
return filter.flatMap((f) => this.fixedFilterService.getQueryByFilterName(f));
}
getCurrentView() {
return this.routeService.getQueryParameterValue('view');
}
......@@ -83,9 +90,10 @@ export class SearchFilterService {
this.getCurrentView(),
this.getCurrentScope(),
this.getCurrentQuery(),
this.getCurrentFilters()).pipe(
this.getCurrentFilters(),
this.getCurrentFixedFilter()).pipe(
distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),
map(([pagination, sort, view, scope, query, filters]) => {
map(([pagination, sort, view, scope, query, filters, fixedFilter]) => {
return Object.assign(new PaginatedSearchOptions(),
defaults,
{
......@@ -94,7 +102,8 @@ export class SearchFilterService {
view: view,
scope: scope || defaults.scope,
query: query,
filters: filters
filters: filters,
fixedFilter: fixedFilter
})
})
)
......@@ -106,14 +115,16 @@ export class SearchFilterService {
this.getCurrentScope(),
this.getCurrentQuery(),
this.getCurrentFilters(),
(view, scope, query, filters) => {
this.getCurrentFixedFilter(),
(view, scope, query, filters, fixedFilter) => {
return Object.assign(new SearchOptions(),
defaults,
{
view: view,
scope: scope || defaults.scope,
query: query,
filters: filters
filters: filters,
fixedFilter: fixedFilter
})
}
)
......
import { Injectable } from '@angular/core';
import { debounceTime, distinctUntilChanged, flatMap, map } from 'rxjs/operators';
import { SearchFiltersState, SearchFilterState } from './search-filter.reducer';
import { createSelector, MemoizedSelector, Store } from '@ngrx/store';
import { flatMap, map } from 'rxjs/operators';
import { Observable } from 'rxjs/Observable';
import {
SearchFilterCollapseAction,
SearchFilterDecrementPageAction, SearchFilterExpandAction,
SearchFilterIncrementPageAction,
SearchFilterInitialCollapseAction,
SearchFilterInitialExpandAction, SearchFilterResetPageAction,
SearchFilterToggleAction
} from './search-filter.actions';
import { hasValue, isEmpty, isNotEmpty, } from '../../../shared/empty.util';
import { SearchFilterConfig } from '../../search-service/search-filter-config.model';
import { SearchService } from '../../search-service/search.service';
import { RouteService } from '../../../shared/route.service';
import ObjectExpression from 'rollup/dist/typings/ast/nodes/ObjectExpression';
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 { PaginatedSearchOptions } from '../../paginated-search-options.model';
import { RemoteData } from '../../../core/data/remote-data';
import { configureRequest } from '../../../core/shared/operators';
import { HALEndpointService } from '../../../core/shared/hal-endpoint.service';
import { GetRequest, RestRequest } from '../../../core/data/request.models';
import { FacetConfigSuccessResponse } from '../../../core/cache/response-cache.models';
import { FilteredDiscoveryQueryResponse } from '../../../core/cache/response-cache.models';
import { ResponseCacheEntry } from '../../../core/cache/response-cache.reducer';
import { RequestService } from '../../../core/data/request.service';
import { ResponseCacheService } from '../../../core/cache/response-cache.service';
import { SearchResponseParsingService } from '../../../core/data/search-response-parsing.service';
import { ResponseParsingService } from '../../../core/data/parsing.service';
import { GenericConstructor } from '../../../core/shared/generic-constructor';
import { FilteredDiscoveryPageResponseParsingService } from '../../../core/data/filtered-discovery-page-response-parsing.service';
@Injectable()
export class SearchFixedFilterService {
private queryByFilterPath = 'config/filtered-discovery-pages';
private queryByFilterPath = 'filtered-discovery-pages';
constructor(private routeService: RouteService,
protected requestService: RequestService,
......@@ -44,35 +23,31 @@ export class SearchFixedFilterService {
}
getQueryByFilterName(filterName?: string): Observable<RemoteData<SearchFilterConfig[]>> {
getQueryByFilterName(filterName?: string): Observable<string> {
const requestObs = this.halService.getEndpoint(this.queryByFilterPath).pipe(
map((url: string) => {
url += ('/' + filterName);
const request = new GetRequest(this.requestService.generateRequestId(), url);
return Object.assign(request, {
getResponseParser(): GenericConstructor<ResponseParsingService> {
return FilterDiscoveryPageResponseParsingService;
return FilteredDiscoveryPageResponseParsingService;
}
});
}),
);
const requestEntryObs = requestObs.pipe(
flatMap((request: RestRequest) => this.requestService.getByHref(request.href))
);
const responseCacheObs = requestObs.pipe(
flatMap((request: RestRequest) => this.responseCache.get(request.href))
);
// get search results from response cache
const fixedFilterConfigObs: Observable<SearchFilterConfig[]> = responseCacheObs.pipe(
const filterQuery: Observable<string> = responseCacheObs.pipe(
map((entry: ResponseCacheEntry) => entry.response),
map((response: FacetConfigSuccessResponse) =>
response.results.map((result: any) => Object.assign(new SearchFilterConfig(), result)))
);
map((response: FilteredDiscoveryQueryResponse) =>
response.filterQuery
));
return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, facetConfigObs);
return filterQuery;
}
}
......@@ -8,9 +8,12 @@ export class SearchOptions {
scope?: string;
query?: string;
filters?: any;
fixedFilter?: any;
toRestUrl(url: string, args: string[] = []): string {
if (isNotEmpty(this.fixedFilter)) {
args.push(this.fixedFilter);
}
if (isNotEmpty(this.query)) {
args.push(`query=${this.query}`);
}
......
......@@ -2,11 +2,13 @@ import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { SearchPageComponent } from './search-page.component';
import { FilteredSearchPageComponent } from './filtered-search-page.component';
@NgModule({
imports: [
RouterModule.forChild([
{ path: '', component: SearchPageComponent, data: { title: 'search.title' } }
{ path: '', component: SearchPageComponent, data: { title: 'search.title' } },
{ path: ':filter', component: FilteredSearchPageComponent, data: { title: 'search.title.:filter' } }
])
]
})
......
......@@ -14,6 +14,7 @@ import { SearchFilterService } from './search-filters/search-filter/search-filte
import { SearchResult } from './search-result.model';
import { SearchService } from './search-service/search.service';
import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
import { RouteService } from '../shared/route.service';
/**
* This component renders a simple item page.
......@@ -46,12 +47,14 @@ export class SearchPageComponent implements OnInit {
query: '',
scope: ''
};
title;
constructor(private service: SearchService,
private communityService: CommunityDataService,
private sidebarService: SearchSidebarService,
private windowService: HostWindowService,
private filterService: SearchFilterService) {
constructor(protected service: SearchService,
protected communityService: CommunityDataService,
protected sidebarService: SearchSidebarService,
protected windowService: HostWindowService,
protected filterService: SearchFilterService,
protected routeService: RouteService) {
this.isMobileView$ = Observable.combineLatest(
this.windowService.isXs(),
this.windowService.isSm(),
......
......@@ -21,6 +21,8 @@ import { SearchFiltersComponent } from './search-filters/search-filters.componen
import { SearchFilterComponent } from './search-filters/search-filter/search-filter.component';
import { SearchFacetFilterComponent } from './search-filters/search-filter/search-facet-filter/search-facet-filter.component';
import { SearchFilterService } from './search-filters/search-filter/search-filter.service';
import { FilteredSearchPageComponent } from './filtered-search-page.component';
import { SearchFixedFilterService } from './search-filters/search-filter/search-fixed-filter.service';
const effects = [
SearchSidebarEffects
......@@ -36,6 +38,7 @@ const effects = [
],
declarations: [
SearchPageComponent,
FilteredSearchPageComponent,
SearchResultsComponent,
SearchSidebarComponent,
SearchSettingsComponent,
......@@ -53,7 +56,8 @@ const effects = [
providers: [
SearchService,
SearchSidebarService,
SearchFilterService
SearchFilterService,
SearchFixedFilterService
],
entryComponents: [
ItemSearchResultListElementComponent,
......
......@@ -108,4 +108,14 @@ export class ConfigSuccessResponse extends RestResponse {
super(true, statusCode);
}
}
export class FilteredDiscoveryQueryResponse extends RestResponse {
constructor(
public filterQuery: string,
public statusCode: string,
public pageInfo?: PageInfo
) {
super(true, statusCode);
}
}
/* tslint:enable:max-classes-per-file */
import { Inject, Injectable } from '@angular/core';
import { FilteredDiscoveryQueryResponse, RestResponse } from '../cache/response-cache.models';
import { ResponseParsingService } from './parsing.service';
import { RestRequest } from './request.models';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { BaseResponseParsingService } from './base-response-parsing.service';
import { ObjectCacheService } from '../cache/object-cache.service';
import { GlobalConfig } from '../../../config/global-config.interface';
import { GLOBAL_CONFIG } from '../../../config';
@Injectable()
export class FilteredDiscoveryPageResponseParsingService extends BaseResponseParsingService implements ResponseParsingService {
objectFactory = {};
toCache = false;
constructor(
@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig,
protected objectCache: ObjectCacheService,
) { super();
}
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
const query = data.payload['discovery-query'];
return new FilteredDiscoveryQueryResponse(query, data.statusCode);
}
}
......@@ -28,6 +28,10 @@ export class RouteService {
return this.route.params.map((params) => params[paramName]).distinctUntilChanged();
}
getRouteDataValue(datafield: string): Observable<any> {
return this.route.data.map((data) => data[datafield]).distinctUntilChanged();
}
getQueryParamsWithPrefix(prefix: string): Observable<Params> {
return this.route.queryParamMap
.map((map) => {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment