diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 7b3d31c3e0..07f770825d 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -117,7 +117,7 @@ "placeholder": "Subject", "head": "Subject" }, - "date": { + "dateIssued": { "placeholder": "Date", "head": "Date" } diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-filter.component.ts index ddb21236c5..b51a2d70fa 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.component.ts @@ -6,6 +6,7 @@ import { FacetValue } from '../../search-service/facet-value.model'; import { SearchFilterService } from './search-filter.service'; import { Observable } from 'rxjs/Observable'; import { slide } from '../../../shared/animations/slide'; +import { PaginatedList } from '../../../core/data/paginated-list'; /** * This component renders a simple item page. @@ -22,13 +23,13 @@ import { slide } from '../../../shared/animations/slide'; export class SearchFilterComponent implements OnInit { @Input() filter: SearchFilterConfig; - filterValues: Observable>; + filterValues: Observable>>; constructor(private searchService: SearchService, private filterService: SearchFilterService) { } ngOnInit() { - this.filterValues = this.searchService.getFacetValuesFor(this.filter.name); + this.filterValues = this.searchService.getFacetValuesFor(this.filter.name, '', ''); const sub = this.filterService.isFilterActive(this.filter.paramName).first().subscribe((isActive) => { if (this.filter.isOpenByDefault || isActive) { this.initialExpand(); diff --git a/src/app/+search-page/search-service/facet-value.model.ts b/src/app/+search-page/search-service/facet-value.model.ts index a323970bc7..06eb50bc6b 100644 --- a/src/app/+search-page/search-service/facet-value.model.ts +++ b/src/app/+search-page/search-service/facet-value.model.ts @@ -1,7 +1,13 @@ +import { autoserialize, autoserializeAs } from 'cerialize'; + export class FacetValue { - + @autoserializeAs(String, 'label') value: string; + + @autoserialize count: number; + + @autoserialize search: string; } diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index 66e125bc58..b20d65cf53 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -1,13 +1,14 @@ -import { Inject, Injectable, OnDestroy } from '@angular/core'; +import { Injectable, OnDestroy } from '@angular/core'; import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { flatMap, map, tap } from 'rxjs/operators'; import { ViewMode } from '../../+search-page/search-options.model'; -import { GLOBAL_CONFIG } from '../../../config'; -import { GlobalConfig } from '../../../config/global-config.interface'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; import { SortOptions } from '../../core/cache/models/sort-options.model'; -import { SearchSuccessResponse } from '../../core/cache/response-cache.models'; +import { + FacetValueMapSuccessResponse, FacetValueSuccessResponse, + SearchSuccessResponse +} from '../../core/cache/response-cache.models'; import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; import { ResponseCacheService } from '../../core/cache/response-cache.service'; import { PaginatedList } from '../../core/data/paginated-list'; @@ -33,6 +34,7 @@ import { SearchQueryResponse } from './search-query-response.model'; import { PageInfo } from '../../core/shared/page-info.model'; import { getSearchResultFor } from './search-result-element-decorator'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; +import { FacetResponseParsingService } from '../../core/data/facet-response-parsing.service'; function shuffle(array: any[]) { let i = 0; @@ -49,20 +51,21 @@ function shuffle(array: any[]) { } @Injectable() -export class SearchService extends HALEndpointService implements OnDestroy { - protected linkPath = 'discover/search/objects'; +export class SearchService implements OnDestroy { + private searchLinkPath = 'discover/search/objects'; + private facetLinkPath = 'discover/search/facets'; private sub; uiSearchRoute = '/search'; config: SearchFilterConfig[] = [ - Object.assign(new SearchFilterConfig(), - { - name: 'scope', - type: FilterType.hierarchy, - hasFacets: true, - isOpenByDefault: true - }), + // Object.assign(new SearchFilterConfig(), + // { + // name: 'scope', + // type: FilterType.hierarchy, + // hasFacets: true, + // isOpenByDefault: true + // }), Object.assign(new SearchFilterConfig(), { name: 'author', @@ -72,7 +75,7 @@ export class SearchService extends HALEndpointService implements OnDestroy { }), Object.assign(new SearchFilterConfig(), { - name: 'date', + name: 'dateIssued', type: FilterType.range, hasFacets: true, isOpenByDefault: false @@ -92,10 +95,9 @@ export class SearchService extends HALEndpointService implements OnDestroy { private route: ActivatedRoute, protected responseCache: ResponseCacheService, protected requestService: RequestService, - @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, private routeService: RouteService, - private rdb: RemoteDataBuildService,) { - super(); + private rdb: RemoteDataBuildService, + private halService: HALEndpointService) { const pagination: PaginationComponentOptions = new PaginationComponentOptions(); pagination.id = 'search-results-pagination'; pagination.currentPage = 1; @@ -106,7 +108,7 @@ export class SearchService extends HALEndpointService implements OnDestroy { } search(query: string, scopeId?: string, searchOptions?: SearchOptions): Observable> | PaginatedList>>> { - const requestObs = this.getEndpoint().pipe( + const requestObs = this.halService.getEndpoint(this.searchLinkPath).pipe( map((url: string) => { const args: string[] = []; @@ -219,35 +221,92 @@ export class SearchService extends HALEndpointService implements OnDestroy { )); } - getFacetValuesFor(searchFilterConfigName: string): Observable> { - const filterConfig = this.config.find((config: SearchFilterConfig) => config.name === searchFilterConfigName); - return this.routeService.getQueryParameterValues(filterConfig.paramName).map((selectedValues: string[]) => { - const payload: FacetValue[] = []; - const totalFilters = 13; - for (let i = 0; i < totalFilters; i++) { - const value = searchFilterConfigName + ' ' + (i + 1); - if (!selectedValues.includes(value)) { - payload.push({ - value: value, - count: Math.floor(Math.random() * 20) + 20 * (totalFilters - i), // make sure first results have the highest (random) count - search: (decodeURI(this.router.url) + (this.router.url.includes('?') ? '&' : '?') + filterConfig.paramName + '=' + value) - } - ); - } + getFacetValuesFor(searchFilterConfigName: string, query: string, scopeId: string): Observable>> { + const requestObs = this.halService.getEndpoint(this.facetLinkPath).pipe( + map((url: string) => { + const args: string[] = []; + + if (isNotEmpty(query)) { + args.push(`query=${query}`); } - const requestPending = false; - const responsePending = false; - const isSuccessful = true; - const error = undefined; - return new RemoteData( - requestPending, - responsePending, - isSuccessful, - error, - payload - ) + + if (isNotEmpty(scopeId)) { + args.push(`scope=${scopeId}`); + } + + if (isNotEmpty(args)) { + url = new URLCombiner(url, `?${args.join('&')}`).toString(); + } + + const request = new GetRequest(this.requestService.generateRequestId(), url); + return Object.assign(request, { + getResponseParser(): GenericConstructor { + return FacetResponseParsingService; + } + }); + }), + tap((request: RestRequest) => this.requestService.configure(request)), + ); + + 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 facetValueResponseObs: Observable = responseCacheObs.pipe( + map((entry: ResponseCacheEntry) => entry.response), + map((response: FacetValueMapSuccessResponse) => response.results[searchFilterConfigName]) + ); + + // get search results from response cache + const facetValueObs: Observable = facetValueResponseObs.pipe( + map((response: FacetValueSuccessResponse) => response.results) + ); + + const pageInfoObs: Observable = facetValueResponseObs.pipe( + map((response: FacetValueSuccessResponse) => { console.log(response); return response.pageInfo}) + ); + const payloadObs = Observable.combineLatest(facetValueObs, pageInfoObs, (facetValue, pageInfo) => { + if (hasValue(pageInfo)) { + return new PaginatedList(pageInfo, facetValue); + } else { + return facetValue; } - ) + }); + return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs); + + // const filterConfig = this.config.find((config: SearchFilterConfig) => config.name === searchFilterConfigName); + // return this.routeService.getQueryParameterValues(filterConfig.paramName).map((selectedValues: string[]) => { + // const payload: FacetValue[] = []; + // const totalFilters = 13; + // for (let i = 0; i < totalFilters; i++) { + // const value = searchFilterConfigName + ' ' + (i + 1); + // if (!selectedValues.includes(value)) { + // payload.push({ + // value: value, + // count: Math.floor(Math.random() * 20) + 20 * (totalFilters - i), // make sure first results have the highest (random) count + // search: (decodeURI(this.router.url) + (this.router.url.includes('?') ? '&' : '?') + filterConfig.paramName + '=' + value) + // } + // ); + // } + // } + // const requestPending = false; + // const responsePending = false; + // const isSuccessful = true; + // const error = undefined; + // return new RemoteData( + // requestPending, + // responsePending, + // isSuccessful, + // error, + // payload + // ) + // } + // ) } getViewMode(): Observable { diff --git a/src/app/core/browse/browse.service.ts b/src/app/core/browse/browse.service.ts index 3b283e2d93..a7b7314d54 100644 --- a/src/app/core/browse/browse.service.ts +++ b/src/app/core/browse/browse.service.ts @@ -12,7 +12,7 @@ import { BrowseDefinition } from '../shared/browse-definition.model'; import { HALEndpointService } from '../shared/hal-endpoint.service'; @Injectable() -export class BrowseService extends HALEndpointService { +export class BrowseService { protected linkPath = 'browses'; private static toSearchKeyArray(metadatumKey: string): string[] { @@ -31,13 +31,12 @@ export class BrowseService extends HALEndpointService { constructor( protected responseCache: ResponseCacheService, protected requestService: RequestService, - @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig) { - super(); + protected halService: HALEndpointService) { } getBrowseURLFor(metadatumKey: string, linkPath: string): Observable { const searchKeyArray = BrowseService.toSearchKeyArray(metadatumKey); - return this.getEndpoint() + return this.halService.getEndpoint(linkPath) .filter((href: string) => isNotEmpty(href)) .distinctUntilChanged() .map((endpointURL: string) => new BrowseEndpointRequest(this.requestService.generateRequestId(), endpointURL)) diff --git a/src/app/core/cache/response-cache.models.ts b/src/app/core/cache/response-cache.models.ts index fb9f10ce51..5da328931b 100644 --- a/src/app/core/cache/response-cache.models.ts +++ b/src/app/core/cache/response-cache.models.ts @@ -3,6 +3,7 @@ import { RequestError } from '../data/request.models'; import { PageInfo } from '../shared/page-info.model'; import { BrowseDefinition } from '../shared/browse-definition.model'; import { ConfigObject } from '../shared/config/config.model'; +import { FacetValue } from '../../+search-page/search-service/facet-value.model'; /* tslint:disable:max-classes-per-file */ export class RestResponse { @@ -32,6 +33,28 @@ export class SearchSuccessResponse extends RestResponse { } } +export class FacetValueMap { + [name: string]: FacetValueSuccessResponse +} + +export class FacetValueSuccessResponse extends RestResponse { + constructor( + public results: FacetValue[], + public statusCode: string, + public pageInfo?: PageInfo) { + super(true, statusCode); + } +} + +export class FacetValueMapSuccessResponse extends RestResponse { + constructor( + public results: FacetValueMap, + public statusCode: string, + ) { + super(true, statusCode); + } +} + export class EndpointMap { [linkPath: string]: string } diff --git a/src/app/core/config/config.service.ts b/src/app/core/config/config.service.ts index f1750bca84..bb863ad46f 100644 --- a/src/app/core/config/config.service.ts +++ b/src/app/core/config/config.service.ts @@ -1,10 +1,7 @@ -import { Injectable } from '@angular/core'; - import { Observable } from 'rxjs/Observable'; import { RequestService } from '../data/request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; -import { GlobalConfig } from '../../../config/global-config.interface'; import { ConfigSuccessResponse, ErrorResponse, RestResponse } from '../cache/response-cache.models'; import { ConfigRequest, FindAllOptions, RestRequest } from '../data/request.models'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; @@ -12,13 +9,13 @@ import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { ConfigData } from './config-data'; -export abstract class ConfigService extends HALEndpointService { +export abstract class ConfigService { protected request: ConfigRequest; protected abstract responseCache: ResponseCacheService; protected abstract requestService: RequestService; protected abstract linkPath: string; - protected abstract EnvConfig: GlobalConfig; protected abstract browseEndpoint: string; + protected abstract halService: HALEndpointService; protected getConfig(request: RestRequest): Observable { const [successResponse, errorResponse] = this.responseCache.get(request.href) @@ -68,7 +65,7 @@ export abstract class ConfigService extends HALEndpointService { } public getConfigAll(): Observable { - return this.getEndpoint() + return this.halService.getEndpoint(this.linkPath) .filter((href: string) => isNotEmpty(href)) .distinctUntilChanged() .map((endpointURL: string) => new ConfigRequest(this.requestService.generateRequestId(), endpointURL)) @@ -85,7 +82,7 @@ export abstract class ConfigService extends HALEndpointService { } public getConfigByName(name: string): Observable { - return this.getEndpoint() + return this.halService.getEndpoint(this.linkPath) .map((endpoint: string) => this.getConfigByNameHref(endpoint, name)) .filter((href: string) => isNotEmpty(href)) .distinctUntilChanged() @@ -96,7 +93,7 @@ export abstract class ConfigService extends HALEndpointService { } public getConfigBySearch(options: FindAllOptions = {}): Observable { - return this.getEndpoint() + return this.halService.getEndpoint(this.linkPath) .map((endpoint: string) => this.getConfigSearchHref(endpoint, options)) .filter((href: string) => isNotEmpty(href)) .distinctUntilChanged() diff --git a/src/app/core/config/submission-definitions-config.service.ts b/src/app/core/config/submission-definitions-config.service.ts index 9655576e71..6cbe0c55b5 100644 --- a/src/app/core/config/submission-definitions-config.service.ts +++ b/src/app/core/config/submission-definitions-config.service.ts @@ -1,10 +1,9 @@ -import { Inject, Injectable } from '@angular/core'; +import { Injectable } from '@angular/core'; import { ConfigService } from './config.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from '../data/request.service'; -import { GLOBAL_CONFIG } from '../../../config'; -import { GlobalConfig } from '../../../config/global-config.interface'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; @Injectable() export class SubmissionDefinitionsConfigService extends ConfigService { @@ -14,7 +13,7 @@ export class SubmissionDefinitionsConfigService extends ConfigService { constructor( protected responseCache: ResponseCacheService, protected requestService: RequestService, - @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig) { + protected halService: HALEndpointService) { super(); } diff --git a/src/app/core/config/submission-forms-config.service.ts b/src/app/core/config/submission-forms-config.service.ts index 7209cd0fdf..27eac78218 100644 --- a/src/app/core/config/submission-forms-config.service.ts +++ b/src/app/core/config/submission-forms-config.service.ts @@ -1,10 +1,9 @@ -import { Inject, Injectable } from '@angular/core'; +import { Injectable } from '@angular/core'; import { ConfigService } from './config.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from '../data/request.service'; -import { GLOBAL_CONFIG } from '../../../config'; -import { GlobalConfig } from '../../../config/global-config.interface'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; @Injectable() export class SubmissionFormsConfigService extends ConfigService { @@ -14,7 +13,7 @@ export class SubmissionFormsConfigService extends ConfigService { constructor( protected responseCache: ResponseCacheService, protected requestService: RequestService, - @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig) { + protected halService: HALEndpointService) { super(); } diff --git a/src/app/core/config/submission-sections-config.service.ts b/src/app/core/config/submission-sections-config.service.ts index 108fc30259..6d4d2ca825 100644 --- a/src/app/core/config/submission-sections-config.service.ts +++ b/src/app/core/config/submission-sections-config.service.ts @@ -1,10 +1,9 @@ -import { Inject, Injectable } from '@angular/core'; +import { Injectable } from '@angular/core'; import { ConfigService } from './config.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from '../data/request.service'; -import { GLOBAL_CONFIG } from '../../../config'; -import { GlobalConfig } from '../../../config/global-config.interface'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; @Injectable() export class SubmissionSectionsConfigService extends ConfigService { @@ -14,7 +13,7 @@ export class SubmissionSectionsConfigService extends ConfigService { constructor( protected responseCache: ResponseCacheService, protected requestService: RequestService, - @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig) { + protected halService: HALEndpointService) { super(); } diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 2960918ea7..764e21efba 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -40,6 +40,8 @@ import { SubmissionDefinitionsConfigService } from './config/submission-definiti import { SubmissionFormsConfigService } from './config/submission-forms-config.service'; import { SubmissionSectionsConfigService } from './config/submission-sections-config.service'; import { UUIDService } from './shared/uuid.service'; +import { HALEndpointService } from './shared/hal-endpoint.service'; +import { FacetResponseParsingService } from './data/facet-response-parsing.service'; const IMPORTS = [ CommonModule, @@ -61,6 +63,7 @@ const PROVIDERS = [ CollectionDataService, DSOResponseParsingService, DSpaceRESTv2Service, + HALEndpointService, HostWindowService, ItemDataService, MetadataService, @@ -70,6 +73,7 @@ const PROVIDERS = [ RequestService, ResponseCacheService, EndpointMapResponseParsingService, + FacetResponseParsingService, DebugResponseParsingService, SearchResponseParsingService, ServerResponseService, diff --git a/src/app/core/data/collection-data.service.ts b/src/app/core/data/collection-data.service.ts index a675b7254d..7d1e463dbe 100644 --- a/src/app/core/data/collection-data.service.ts +++ b/src/app/core/data/collection-data.service.ts @@ -10,6 +10,7 @@ import { Collection } from '../shared/collection.model'; import { ComColDataService } from './comcol-data.service'; import { CommunityDataService } from './community-data.service'; import { RequestService } from './request.service'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; @Injectable() export class CollectionDataService extends ComColDataService { @@ -20,9 +21,9 @@ export class CollectionDataService extends ComColDataService, - @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, protected cds: CommunityDataService, - protected objectCache: ObjectCacheService + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService ) { super(); } diff --git a/src/app/core/data/comcol-data.service.ts b/src/app/core/data/comcol-data.service.ts index 24c019c611..112afa0bc8 100644 --- a/src/app/core/data/comcol-data.service.ts +++ b/src/app/core/data/comcol-data.service.ts @@ -10,10 +10,12 @@ import { CommunityDataService } from './community-data.service'; import { DataService } from './data.service'; import { FindByIDRequest } from './request.models'; import { NormalizedObject } from '../cache/models/normalized-object.model'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; export abstract class ComColDataService extends DataService { protected abstract cds: CommunityDataService; protected abstract objectCache: ObjectCacheService; + protected abstract halService: HALEndpointService; /** * Get the scoped endpoint URL by fetching the object with @@ -27,7 +29,7 @@ export abstract class ComColDataService { if (isEmpty(scopeID)) { - return this.getEndpoint(); + return this.halService.getEndpoint(this.linkPath); } else { const scopeCommunityHrefObs = this.cds.getEndpoint() .flatMap((endpoint: string) => this.cds.getFindByIDHref(endpoint, scopeID)) diff --git a/src/app/core/data/community-data.service.ts b/src/app/core/data/community-data.service.ts index 4cb44f4296..88ad3a5287 100644 --- a/src/app/core/data/community-data.service.ts +++ b/src/app/core/data/community-data.service.ts @@ -10,6 +10,7 @@ import { CoreState } from '../core.reducers'; import { Community } from '../shared/community.model'; import { ComColDataService } from './comcol-data.service'; import { RequestService } from './request.service'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; @Injectable() export class CommunityDataService extends ComColDataService { @@ -21,9 +22,13 @@ export class CommunityDataService extends ComColDataService, - @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, - protected objectCache: ObjectCacheService + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService ) { super(); } + + getEndpoint() { + return this.halService.getEndpoint(this.linkPath); + } } diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 1d9d568da3..f532ff05ba 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -1,11 +1,9 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs/Observable'; -import { GlobalConfig } from '../../../config'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; -import { GenericConstructor } from '../shared/generic-constructor'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { URLCombiner } from '../url-combiner/url-combiner'; import { PaginatedList } from './paginated-list'; @@ -14,13 +12,13 @@ import { FindAllOptions, FindAllRequest, FindByIDRequest, GetRequest } from './r import { RequestService } from './request.service'; import { NormalizedObject } from '../cache/models/normalized-object.model'; -export abstract class DataService extends HALEndpointService { +export abstract class DataService { protected abstract responseCache: ResponseCacheService; protected abstract requestService: RequestService; protected abstract rdbService: RemoteDataBuildService; protected abstract store: Store; protected abstract linkPath: string; - protected abstract EnvConfig: GlobalConfig; + protected abstract halService: HALEndpointService; public abstract getScopedEndpoint(scope: string): Observable @@ -55,7 +53,7 @@ export abstract class DataService } findAll(options: FindAllOptions = {}): Observable>> { - const hrefObs = this.getEndpoint().filter((href: string) => isNotEmpty(href)) + const hrefObs = this.halService.getEndpoint(this.linkPath).filter((href: string) => isNotEmpty(href)) .flatMap((endpoint: string) => this.getFindAllHref(endpoint, options)); hrefObs @@ -74,7 +72,7 @@ export abstract class DataService } findById(id: string): Observable> { - const hrefObs = this.getEndpoint() + const hrefObs = this.halService.getEndpoint(this.linkPath) .map((endpoint: string) => this.getFindByIDHref(endpoint, id)); hrefObs diff --git a/src/app/core/data/facet-response-parsing.service.ts b/src/app/core/data/facet-response-parsing.service.ts new file mode 100644 index 0000000000..8295d026a3 --- /dev/null +++ b/src/app/core/data/facet-response-parsing.service.ts @@ -0,0 +1,41 @@ +import { Injectable } from '@angular/core'; +import { + FacetValueMap, + FacetValueMapSuccessResponse, + FacetValueSuccessResponse, + 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 { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; +import { PageInfo } from '../shared/page-info.model'; +import { isNotEmpty } from '../../shared/empty.util'; +import { FacetValue } from '../../+search-page/search-service/facet-value.model'; + +@Injectable() +export class FacetResponseParsingService implements ResponseParsingService { + parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { + + const payload = data.payload; + const facetMap: FacetValueMap = new FacetValueMap(); + + const serializer = new DSpaceRESTv2Serializer(FacetValue); + payload._embedded.facets.map((facet) => { + const values = facet._embedded.values.map((value) => {value.search = value._links.search.href; return value;}); + const facetValues = serializer.deserializeArray(values); + const valuesResponse = new FacetValueSuccessResponse(facetValues, data.statusCode, this.processPageInfo(data.payload.page)); + facetMap[facet.name] = valuesResponse; + }); + + return new FacetValueMapSuccessResponse(facetMap, data.statusCode); + } + + protected processPageInfo(pageObj: any): PageInfo { + if (isNotEmpty(pageObj)) { + return new DSpaceRESTv2Serializer(PageInfo).deserialize(pageObj); + } else { + return undefined; + } + } +} diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index 0e6fcbfd33..6b0937d8e4 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -14,6 +14,7 @@ import { URLCombiner } from '../url-combiner/url-combiner'; import { DataService } from './data.service'; import { RequestService } from './request.service'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; @Injectable() export class ItemDataService extends DataService { @@ -24,15 +25,14 @@ export class ItemDataService extends DataService { protected requestService: RequestService, protected rdbService: RemoteDataBuildService, protected store: Store, - @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, - private bs: BrowseService - ) { + private bs: BrowseService, + protected halService: HALEndpointService) { super(); } public getScopedEndpoint(scopeID: string): Observable { if (isEmpty(scopeID)) { - return this.getEndpoint(); + return this.halService.getEndpoint(this.linkPath); } else { return this.bs.getBrowseURLFor('dc.date.issued', this.linkPath) .filter((href: string) => isNotEmpty(href)) diff --git a/src/app/core/shared/hal-endpoint.service.ts b/src/app/core/shared/hal-endpoint.service.ts index 743179b23c..b9bb1d587c 100644 --- a/src/app/core/shared/hal-endpoint.service.ts +++ b/src/app/core/shared/hal-endpoint.service.ts @@ -8,13 +8,19 @@ import { EndpointMapRequest } from '../data/request.models'; import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { isEmpty, isNotEmpty } from '../../shared/empty.util'; import { RESTURLCombiner } from '../url-combiner/rest-url-combiner'; +import { Inject, Injectable } from '@angular/core'; +import { GLOBAL_CONFIG } from '../../../config'; -export abstract class HALEndpointService { - protected abstract responseCache: ResponseCacheService; - protected abstract requestService: RequestService; - protected abstract linkPath: string; - protected abstract EnvConfig: GlobalConfig; +@Injectable() +export class HALEndpointService { + protected linkPath: string; + + constructor(private responseCache: ResponseCacheService, + private requestService: RequestService, + @Inject(GLOBAL_CONFIG) private EnvConfig: GlobalConfig) { + + } protected getRootHref(): string { return new RESTURLCombiner(this.EnvConfig, '/').toString(); } @@ -33,8 +39,8 @@ export abstract class HALEndpointService { .distinctUntilChanged(); } - public getEndpoint(): Observable { - return this.getEndpointAt(...this.linkPath.split('/')); + public getEndpoint(linkPath: string): Observable { + return this.getEndpointAt(...linkPath.split('/')); } private getEndpointAt(...path: string[]): Observable { @@ -50,10 +56,10 @@ export abstract class HALEndpointService { return Observable.of(this.getRootHref()).pipe(...pipeArguments, distinctUntilChanged()); } - public isEnabledOnRestApi(): Observable { + public isEnabledOnRestApi(linkPath: string): Observable { return this.getRootEndpointMap().pipe( // TODO this only works when there's no / in linkPath - map((endpointMap: EndpointMap) => isNotEmpty(endpointMap[this.linkPath])), + map((endpointMap: EndpointMap) => isNotEmpty(endpointMap[linkPath])), startWith(undefined), distinctUntilChanged() )