mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-08 18:44:14 +00:00
Merge remote-tracking branch 'lotte/search-backend' into w2p-50632_Replace-mock-registry-service-with-implementation
This commit is contained in:
@@ -80,7 +80,8 @@
|
|||||||
"search_dspace": "Search DSpace"
|
"search_dspace": "Search DSpace"
|
||||||
},
|
},
|
||||||
"results": {
|
"results": {
|
||||||
"head": "Search Results"
|
"head": "Search Results",
|
||||||
|
"no-results": "There were no results for this search"
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"close": "Back to results",
|
"close": "Back to results",
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<div class="clearfix toggle-more-filters">
|
<div class="clearfix toggle-more-filters">
|
||||||
<a class="float-left" *ngIf="!(isLastPage() | async)"
|
<a class="float-left" *ngIf="!(isLastPage$ | async)"
|
||||||
(click)="showMore()">{{"search.filters.filter.show-more"
|
(click)="showMore()">{{"search.filters.filter.show-more"
|
||||||
| translate}}</a>
|
| translate}}</a>
|
||||||
<a class="float-right" *ngIf="(currentPage | async) > 1"
|
<a class="float-right" *ngIf="(currentPage | async) > 1"
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
[action]="getCurrentUrl()">
|
[action]="getCurrentUrl()">
|
||||||
<input type="text" [(ngModel)]="filter" [name]="filterConfig.paramName" class="form-control"
|
<input type="text" [(ngModel)]="filter" [name]="filterConfig.paramName" class="form-control"
|
||||||
aria-label="New filter input"
|
aria-label="New filter input"
|
||||||
[placeholder]="'search.filters.filter.' + filterConfig.name + '.placeholder'| translate"/>
|
[placeholder]="'search.filters.filter.' + filterConfig.name + '.placeholder'| translate" [ngModelOptions]="{standalone: true}"/>
|
||||||
<input type="submit" class="d-none"/>
|
<input type="submit" class="d-none"/>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -10,6 +10,15 @@ import { FilterType } from '../../../search-service/filter-type.model';
|
|||||||
import { FacetValue } from '../../../search-service/facet-value.model';
|
import { FacetValue } from '../../../search-service/facet-value.model';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
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 { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||||
|
import { PageInfo } from '../../../../core/shared/page-info.model';
|
||||||
|
|
||||||
describe('SearchFacetFilterComponent', () => {
|
describe('SearchFacetFilterComponent', () => {
|
||||||
let comp: SearchFacetFilterComponent;
|
let comp: SearchFacetFilterComponent;
|
||||||
@@ -40,29 +49,35 @@ describe('SearchFacetFilterComponent', () => {
|
|||||||
search: ''
|
search: ''
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const searchLink = '/search';
|
||||||
|
const selectedValues = [value1, value2];
|
||||||
let filterService;
|
let filterService;
|
||||||
const page = Observable.of(0)
|
let searchService;
|
||||||
|
let router;
|
||||||
|
const page = Observable.of(0);
|
||||||
|
|
||||||
|
const mockValues = Observable.of(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), values)));
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, FormsModule],
|
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],
|
||||||
declarations: [SearchFacetFilterComponent],
|
declarations: [SearchFacetFilterComponent],
|
||||||
providers: [
|
providers: [
|
||||||
|
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
||||||
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
{
|
{
|
||||||
provide: SearchFilterService,
|
provide: SearchFilterService, useValue: {
|
||||||
useValue: {
|
isFilterActiveWithValue: (paramName: string, filterValue: string) => true,
|
||||||
isFilterActiveWithValue: (paramName: string, filterValue: string) => true,
|
getPage: (paramName: string) => page,
|
||||||
getQueryParamsWith: (paramName: string, filterValue: string) => '',
|
/* tslint:disable:no-empty */
|
||||||
getQueryParamsWithout: (paramName: string, filterValue: string) => '',
|
incrementPage: (filterName: string) => {
|
||||||
getPage: (paramName: string) => page,
|
},
|
||||||
/* tslint:disable:no-empty */
|
resetPage: (filterName: string) => {
|
||||||
incrementPage: (filterName: string) => {
|
},
|
||||||
},
|
getSearchOptions: () => Observable.of({}),
|
||||||
resetPage: (filterName: string) => {
|
/* tslint:enable:no-empty */
|
||||||
},
|
}
|
||||||
/* tslint:enable:no-empty */
|
}
|
||||||
searchLink: '/search',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).overrideComponent(SearchFacetFilterComponent, {
|
}).overrideComponent(SearchFacetFilterComponent, {
|
||||||
@@ -74,8 +89,13 @@ describe('SearchFacetFilterComponent', () => {
|
|||||||
fixture = TestBed.createComponent(SearchFacetFilterComponent);
|
fixture = TestBed.createComponent(SearchFacetFilterComponent);
|
||||||
comp = fixture.componentInstance; // SearchPageComponent test instance
|
comp = fixture.componentInstance; // SearchPageComponent test instance
|
||||||
comp.filterConfig = mockFilterConfig;
|
comp.filterConfig = mockFilterConfig;
|
||||||
comp.filterValues = values;
|
comp.filterValues = [mockValues];
|
||||||
|
comp.filterValues$ = new BehaviorSubject(comp.filterValues);
|
||||||
|
comp.selectedValues = selectedValues;
|
||||||
filterService = (comp as any).filterService;
|
filterService = (comp as any).filterService;
|
||||||
|
searchService = (comp as any).searchService;
|
||||||
|
spyOn(searchService, 'getFacetValuesFor').and.returnValue(mockValues);
|
||||||
|
router = (comp as any).router;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -97,62 +117,21 @@ describe('SearchFacetFilterComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should return the value of the searchLink variable in the filter service', () => {
|
it('should return the value of the searchLink variable in the filter service', () => {
|
||||||
expect(link).toEqual(filterService.searchLink);
|
expect(link).toEqual(searchLink);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the getQueryParamsWith method is called wih a value', () => {
|
describe('when the getAddParams method is called wih a value', () => {
|
||||||
beforeEach(() => {
|
it('should return the selectedValue list with the new parameter value', () => {
|
||||||
spyOn(filterService, 'getQueryParamsWith');
|
const result = comp.getAddParams(value3);
|
||||||
comp.getQueryParamsWith(values[1].value);
|
expect(result).toEqual({ [mockFilterConfig.paramName]: [value1, value2, value3] });
|
||||||
});
|
|
||||||
|
|
||||||
it('should call getQueryParamsWith on the filterService with the correct filter parameter name and the passed value', () => {
|
|
||||||
expect(filterService.getQueryParamsWith).toHaveBeenCalledWith(mockFilterConfig, values[1].value)
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the getQueryParamsWithout method is called wih a value', () => {
|
describe('when the getRemoveParams method is called wih a value', () => {
|
||||||
beforeEach(() => {
|
it('should return the selectedValue list with the parameter value left out', () => {
|
||||||
spyOn(filterService, 'getQueryParamsWithout');
|
const result = comp.getRemoveParams(value1);
|
||||||
comp.getQueryParamsWithout(values[1].value);
|
expect(result).toEqual({ [mockFilterConfig.paramName]: [value2] });
|
||||||
});
|
|
||||||
|
|
||||||
it('should call getQueryParamsWithout on the filterService with the correct filter parameter name and the passed value', () => {
|
|
||||||
expect(filterService.getQueryParamsWithout).toHaveBeenCalledWith(mockFilterConfig, values[1].value)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when the facetCount method is triggered when there are less items than the amount of pages should display', () => {
|
|
||||||
let count: Observable<number>;
|
|
||||||
beforeEach(() => {
|
|
||||||
comp.currentPage = Observable.of(3);
|
|
||||||
// 2 x 3 = 6, there are only 3 values
|
|
||||||
count = comp.facetCount;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the correct number of items shown (this equals the total amount of values for this filter)', () => {
|
|
||||||
const sub = count.subscribe((c) => expect(c).toBe(values.length));
|
|
||||||
sub.unsubscribe();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when the facetCount method is triggered when there are more items than the amount of pages should display', () => {
|
|
||||||
let count: Observable<number>;
|
|
||||||
beforeEach(() => {
|
|
||||||
comp.currentPage = Observable.of(1);
|
|
||||||
// 2 x 1 = 2, there are more than 2 (3) items
|
|
||||||
count = comp.facetCount;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the correct number of items shown (this equals the page count x page size)', () => {
|
|
||||||
const sub = count.subscribe((c) => {
|
|
||||||
const subsub = comp.currentPage.subscribe((currentPage) => {
|
|
||||||
expect(c).toBe(currentPage * mockFilterConfig.pageSize);
|
|
||||||
});
|
|
||||||
subsub.unsubscribe()
|
|
||||||
});
|
|
||||||
sub.unsubscribe();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -174,7 +153,7 @@ describe('SearchFacetFilterComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should call resetPage on the filterService with the correct filter parameter name', () => {
|
it('should call resetPage on the filterService with the correct filter parameter name', () => {
|
||||||
expect(filterService.resetPage).toHaveBeenCalledWith(mockFilterConfig.name)
|
expect(filterService.resetPage).toHaveBeenCalledWith(mockFilterConfig.name);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -188,4 +167,76 @@ describe('SearchFacetFilterComponent', () => {
|
|||||||
expect(filterService.getPage).toHaveBeenCalledWith(mockFilterConfig.name)
|
expect(filterService.getPage).toHaveBeenCalledWith(mockFilterConfig.name)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when the getCurrentUrl method is called', () => {
|
||||||
|
const url = 'test.url/test'
|
||||||
|
beforeEach(() => {
|
||||||
|
router.navigateByUrl(url);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call getPage on the filterService with the correct filter parameter name', () => {
|
||||||
|
expect(router.url).toEqual(url);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the onSubmit method is called with data', () => {
|
||||||
|
const searchUrl = '/search/path';
|
||||||
|
const testValue = 'test';
|
||||||
|
const data = { [mockFilterConfig.paramName]: testValue };
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn(comp, 'getSearchLink').and.returnValue(searchUrl);
|
||||||
|
comp.onSubmit(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call navigate on the router with the right searchlink and parameters', () => {
|
||||||
|
expect(router.navigate).toHaveBeenCalledWith([searchUrl], {
|
||||||
|
queryParams: { [mockFilterConfig.paramName]: [...selectedValues, testValue] },
|
||||||
|
queryParamsHandling: 'merge'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when updateFilterValueList is called', () => {
|
||||||
|
const cPage = 10;
|
||||||
|
const searchOptions = new SearchOptions();
|
||||||
|
beforeEach(() => {
|
||||||
|
// spyOn(searchService, 'getFacetValuesFor'); Already spied upon
|
||||||
|
comp.currentPage = Observable.of(cPage);
|
||||||
|
comp.updateFilterValueList(searchOptions);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call getFacetValuesFor on the searchService with the correct parameters', () => {
|
||||||
|
expect(searchService.getFacetValuesFor).toHaveBeenCalledWith(mockFilterConfig, cPage, searchOptions);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when updateFilterValueList is called and pageChange is set to true', () => {
|
||||||
|
const searchOptions = new SearchOptions();
|
||||||
|
beforeEach(() => {
|
||||||
|
comp.pageChange = true;
|
||||||
|
spyOn(comp, 'showFirstPageOnly');
|
||||||
|
comp.updateFilterValueList(searchOptions);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call showFirstPageOnly on the component', () => {
|
||||||
|
expect(comp.showFirstPageOnly).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set pageChange to false', () => {
|
||||||
|
expect(comp.pageChange).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when updateFilterValueList is called and pageChange is set to false', () => {
|
||||||
|
const searchOptions = new SearchOptions();
|
||||||
|
beforeEach(() => {
|
||||||
|
comp.pageChange = false;
|
||||||
|
spyOn(comp, 'showFirstPageOnly');
|
||||||
|
comp.updateFilterValueList(searchOptions);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call showFirstPageOnly on the component', () => {
|
||||||
|
expect(comp.showFirstPageOnly).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -4,7 +4,7 @@ import { SearchFilterConfig } from '../../../search-service/search-filter-config
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { SearchFilterService } from '../search-filter.service';
|
import { SearchFilterService } from '../search-filter.service';
|
||||||
import { hasValue, isNotEmpty } from '../../../../shared/empty.util';
|
import { hasNoValue, hasValue, isNotEmpty } from '../../../../shared/empty.util';
|
||||||
import { RemoteData } from '../../../../core/data/remote-data';
|
import { RemoteData } from '../../../../core/data/remote-data';
|
||||||
import { PaginatedList } from '../../../../core/data/paginated-list';
|
import { PaginatedList } from '../../../../core/data/paginated-list';
|
||||||
import { SearchService } from '../../../search-service/search.service';
|
import { SearchService } from '../../../search-service/search.service';
|
||||||
@@ -30,6 +30,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
|||||||
filterValues: Array<Observable<RemoteData<PaginatedList<FacetValue>>>> = [];
|
filterValues: Array<Observable<RemoteData<PaginatedList<FacetValue>>>> = [];
|
||||||
filterValues$: BehaviorSubject<any> = new BehaviorSubject(this.filterValues);
|
filterValues$: BehaviorSubject<any> = new BehaviorSubject(this.filterValues);
|
||||||
currentPage: Observable<number>;
|
currentPage: Observable<number>;
|
||||||
|
isLastPage$: BehaviorSubject<boolean> = new BehaviorSubject(false);
|
||||||
filter: string;
|
filter: string;
|
||||||
pageChange = false;
|
pageChange = false;
|
||||||
sub: Subscription;
|
sub: Subscription;
|
||||||
@@ -50,14 +51,13 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
|||||||
this.pageChange = false;
|
this.pageChange = false;
|
||||||
|
|
||||||
this.unsubscribe();
|
this.unsubscribe();
|
||||||
|
|
||||||
this.sub = this.currentPage.distinctUntilChanged().map((page) => {
|
this.sub = this.currentPage.distinctUntilChanged().map((page) => {
|
||||||
return this.searchService.getFacetValuesFor(this.filterConfig, page, options);
|
return this.searchService.getFacetValuesFor(this.filterConfig, page, options);
|
||||||
}).subscribe((newValues$) => {
|
}).subscribe((newValues$) => {
|
||||||
this.filterValues = [...this.filterValues, newValues$];
|
this.filterValues = [...this.filterValues, newValues$];
|
||||||
this.filterValues$.next(this.filterValues);
|
this.filterValues$.next(this.filterValues);
|
||||||
|
newValues$.first().subscribe((rd) => this.isLastPage$.next(hasNoValue(rd.payload.next)));
|
||||||
});
|
});
|
||||||
// this.filterValues.subscribe((c) => c.map((a) => a.subscribe((b) => console.log(b))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isChecked(value: FacetValue): Observable<boolean> {
|
isChecked(value: FacetValue): Observable<boolean> {
|
||||||
@@ -99,12 +99,6 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
|||||||
hasValue(o: any): boolean {
|
hasValue(o: any): boolean {
|
||||||
return hasValue(o);
|
return hasValue(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
isLastPage(): Observable<boolean> {
|
|
||||||
return Observable.of(false);
|
|
||||||
// return this.filterValues.flatMap((map) => map.pop().map((rd: RemoteData<PaginatedList<FacetValue>>) => rd.payload.currentPage >= rd.payload.totalPages));
|
|
||||||
}
|
|
||||||
|
|
||||||
getRemoveParams(value: string) {
|
getRemoveParams(value: string) {
|
||||||
return { [this.filterConfig.paramName]: this.selectedValues.filter((v) => v !== value) };
|
return { [this.filterConfig.paramName]: this.selectedValues.filter((v) => v !== value) };
|
||||||
}
|
}
|
||||||
@@ -118,7 +112,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsubscribe(): void {
|
unsubscribe(): void {
|
||||||
if (this.sub !== undefined) {
|
if (hasValue(this.sub)) {
|
||||||
this.sub.unsubscribe();
|
this.sub.unsubscribe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -50,7 +50,7 @@ describe('SearchFilterService', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
service = new SearchFilterService(store, routeServiceStub, searchServiceStub);
|
service = new SearchFilterService(store, routeServiceStub);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the initialCollapse method is triggered', () => {
|
describe('when the initialCollapse method is triggered', () => {
|
||||||
@@ -159,28 +159,6 @@ describe('SearchFilterService', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the getQueryParamsWithout method is called', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
spyOn(routeServiceStub, 'removeQueryParameterValue');
|
|
||||||
service.getQueryParamsWithout(mockFilterConfig, value1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call removeQueryParameterValue on the route service with the same parameters', () => {
|
|
||||||
expect(routeServiceStub.removeQueryParameterValue).toHaveBeenCalledWith(mockFilterConfig.paramName, value1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when the getQueryParamsWith method is called', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
spyOn(routeServiceStub, 'addQueryParameterValue');
|
|
||||||
service.getQueryParamsWith(mockFilterConfig, value1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call addQueryParameterValue on the route service with the same parameters', () => {
|
|
||||||
expect(routeServiceStub.addQueryParameterValue).toHaveBeenCalledWith(mockFilterConfig.paramName, value1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when the getSelectedValuesForFilter method is called', () => {
|
describe('when the getSelectedValuesForFilter method is called', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyOn(routeServiceStub, 'getQueryParameterValues');
|
spyOn(routeServiceStub, 'getQueryParameterValues');
|
||||||
@@ -192,14 +170,4 @@ describe('SearchFilterService', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the uiSearchRoute method is called', () => {
|
|
||||||
let link: string;
|
|
||||||
beforeEach(() => {
|
|
||||||
link = service.searchLink;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the value of uiSearchRoute in the search service', () => {
|
|
||||||
expect(link).toEqual(searchServiceStub.uiSearchRoute);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@@ -79,13 +79,13 @@ export class SearchFilterService {
|
|||||||
this.getCurrentQuery(),
|
this.getCurrentQuery(),
|
||||||
this.getCurrentFilters(),
|
this.getCurrentFilters(),
|
||||||
(pagination, sort, view, scope, query, filters) => {
|
(pagination, sort, view, scope, query, filters) => {
|
||||||
return Object.assign(new SearchOptions(),
|
return Object.assign(new PaginatedSearchOptions(),
|
||||||
defaults,
|
defaults,
|
||||||
{
|
{
|
||||||
pagination: pagination,
|
pagination: pagination,
|
||||||
sort: sort,
|
sort: sort,
|
||||||
view: view,
|
view: view,
|
||||||
scope: scope,
|
scope: scope || defaults.scope,
|
||||||
query: query,
|
query: query,
|
||||||
filters: filters
|
filters: filters
|
||||||
})
|
})
|
||||||
|
@@ -4,4 +4,4 @@
|
|||||||
<ds-search-filter class="d-block mb-3 p-3" [filter]="filter"></ds-search-filter>
|
<ds-search-filter class="d-block mb-3 p-3" [filter]="filter"></ds-search-filter>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a class="btn btn-primary" [routerLink]="[getSearchLink()]" [queryParams]="getClearFiltersQueryParams()" role="button">{{"search.filters.reset" | translate}}</a>
|
<a class="btn btn-primary" [routerLink]="[getSearchLink()]" [queryParams]="clearParams | async" queryParamsHandling="merge" role="button">{{"search.filters.reset" | translate}}</a>
|
@@ -4,6 +4,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { SearchFilterService } from './search-filter/search-filter.service';
|
||||||
import { SearchFiltersComponent } from './search-filters.component';
|
import { SearchFiltersComponent } from './search-filters.component';
|
||||||
import { SearchService } from '../search-service/search.service';
|
import { SearchService } from '../search-service/search.service';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
@@ -22,6 +23,9 @@ describe('SearchFiltersComponent', () => {
|
|||||||
}
|
}
|
||||||
/* tslint:enable:no-empty */
|
/* tslint:enable:no-empty */
|
||||||
};
|
};
|
||||||
|
const searchFilterServiceStub = jasmine.createSpyObj('SearchFilterService', {
|
||||||
|
getCurrentFilters: Observable.of({})
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@@ -29,6 +33,7 @@ describe('SearchFiltersComponent', () => {
|
|||||||
declarations: [SearchFiltersComponent],
|
declarations: [SearchFiltersComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: SearchService, useValue: searchServiceStub },
|
{ provide: SearchService, useValue: searchServiceStub },
|
||||||
|
{ provide: SearchFilterService, useValue: searchFilterServiceStub },
|
||||||
|
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
@@ -44,17 +49,6 @@ describe('SearchFiltersComponent', () => {
|
|||||||
searchService = (comp as any).searchService;
|
searchService = (comp as any).searchService;
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the getClearFiltersQueryParams method is called', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
spyOn(searchService, 'getClearFiltersQueryParams');
|
|
||||||
comp.getClearFiltersQueryParams();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call getClearFiltersQueryParams on the searchService', () => {
|
|
||||||
expect(searchService.getClearFiltersQueryParams).toHaveBeenCalled()
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when the getSearchLink method is called', () => {
|
describe('when the getSearchLink method is called', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyOn(searchService, 'getSearchLink');
|
spyOn(searchService, 'getSearchLink');
|
||||||
|
@@ -3,6 +3,7 @@ import { SearchService } from '../search-service/search.service';
|
|||||||
import { RemoteData } from '../../core/data/remote-data';
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
import { SearchFilterConfig } from '../search-service/search-filter-config.model';
|
import { SearchFilterConfig } from '../search-service/search-filter-config.model';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { SearchFilterService } from './search-filter/search-filter.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component renders a simple item page.
|
* This component renders a simple item page.
|
||||||
@@ -18,12 +19,10 @@ import { Observable } from 'rxjs/Observable';
|
|||||||
|
|
||||||
export class SearchFiltersComponent {
|
export class SearchFiltersComponent {
|
||||||
filters: Observable<RemoteData<SearchFilterConfig[]>>;
|
filters: Observable<RemoteData<SearchFilterConfig[]>>;
|
||||||
constructor(private searchService: SearchService) {
|
clearParams;
|
||||||
|
constructor(private searchService: SearchService, private filterService: SearchFilterService) {
|
||||||
this.filters = searchService.getConfig();
|
this.filters = searchService.getConfig();
|
||||||
}
|
this.clearParams = filterService.getCurrentFilters().map((filters) => {Object.keys(filters).forEach((f) => filters[f] = null); return filters;});
|
||||||
|
|
||||||
getClearFiltersQueryParams(): any {
|
|
||||||
return this.searchService.getClearFiltersQueryParams();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getSearchLink() {
|
getSearchLink() {
|
||||||
|
@@ -1,22 +1,22 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="search-page row">
|
<div class="search-page row">
|
||||||
<ds-search-sidebar *ngIf="!(isMobileView | async)" class="col-3 sidebar-md-sticky"
|
<ds-search-sidebar *ngIf="!(isMobileView$ | async)" class="col-3 sidebar-md-sticky"
|
||||||
id="search-sidebar"
|
id="search-sidebar"
|
||||||
[resultCount]="(resultsRDObs | async)?.pageInfo?.totalElements"></ds-search-sidebar>
|
[resultCount]="(resultsRD$ | async)?.pageInfo?.totalElements"></ds-search-sidebar>
|
||||||
<div class="col-12 col-md-9">
|
<div class="col-12 col-md-9">
|
||||||
<ds-search-form id="search-form"
|
<ds-search-form id="search-form"
|
||||||
[query]="query"
|
[query]="(searchOptions$ | async)?.query"
|
||||||
[scope]="(scopeObjectRDObs | async)?.payload"
|
[scope]="(searchOptions$ | async)?.scope"
|
||||||
[currentParams]="currentParams"
|
[currentParams]="currentParams"
|
||||||
[scopes]="(scopeListRDObs | async)?.payload?.page">
|
[scopes]="(scopeListRD$ | async)?.payload?.page">
|
||||||
</ds-search-form>
|
</ds-search-form>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div id="search-body"
|
<div id="search-body"
|
||||||
class="row-offcanvas row-offcanvas-left"
|
class="row-offcanvas row-offcanvas-left"
|
||||||
[@pushInOut]="(isSidebarCollapsed() | async) ? 'collapsed' : 'expanded'">
|
[@pushInOut]="(isSidebarCollapsed() | async) ? 'collapsed' : 'expanded'">
|
||||||
<ds-search-sidebar *ngIf="(isMobileView | async)" class="col-12"
|
<ds-search-sidebar *ngIf="(isMobileView$ | async)" class="col-12"
|
||||||
id="search-sidebar-sm"
|
id="search-sidebar-sm"
|
||||||
[resultCount]="(resultsRDObs | async)?.pageInfo?.totalElements"
|
[resultCount]="(resultsRD$ | async)?.pageInfo?.totalElements"
|
||||||
(toggleSidebar)="closeSidebar()"
|
(toggleSidebar)="closeSidebar()"
|
||||||
[ngClass]="{'active': !(isSidebarCollapsed() | async)}">
|
[ngClass]="{'active': !(isSidebarCollapsed() | async)}">
|
||||||
</ds-search-sidebar>
|
</ds-search-sidebar>
|
||||||
@@ -29,13 +29,11 @@
|
|||||||
| translate}}
|
| translate}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<ds-search-results [searchResults]="resultsRDObs | async"
|
<ds-search-results [searchResults]="resultsRD$ | async"
|
||||||
[searchConfig]="searchOptions" [sortConfig]="sortConfig"></ds-search-results>
|
[searchConfig]="searchOptions$ | async" [sortConfig]="sortConfig"></ds-search-results>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@@ -4,12 +4,14 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { cold, hot } from 'jasmine-marbles';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model';
|
import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model';
|
||||||
import { CommunityDataService } from '../core/data/community-data.service';
|
import { CommunityDataService } from '../core/data/community-data.service';
|
||||||
import { Community } from '../core/shared/community.model';
|
import { Community } from '../core/shared/community.model';
|
||||||
import { HostWindowService } from '../shared/host-window.service';
|
import { HostWindowService } from '../shared/host-window.service';
|
||||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
||||||
|
import { PaginatedSearchOptions } from './paginated-search-options.model';
|
||||||
import { SearchPageComponent } from './search-page.component';
|
import { SearchPageComponent } from './search-page.component';
|
||||||
import { SearchService } from './search-service/search.service';
|
import { SearchService } from './search-service/search.service';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
@@ -17,6 +19,7 @@ import { ActivatedRoute } from '@angular/router';
|
|||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
|
import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
|
||||||
|
import { SearchFilterService } from './search-filters/search-filter/search-filter.service';
|
||||||
|
|
||||||
describe('SearchPageComponent', () => {
|
describe('SearchPageComponent', () => {
|
||||||
let comp: SearchPageComponent;
|
let comp: SearchPageComponent;
|
||||||
@@ -34,12 +37,17 @@ describe('SearchPageComponent', () => {
|
|||||||
pagination.pageSize = 10;
|
pagination.pageSize = 10;
|
||||||
const sort: SortOptions = new SortOptions();
|
const sort: SortOptions = new SortOptions();
|
||||||
const mockResults = Observable.of(['test', 'data']);
|
const mockResults = Observable.of(['test', 'data']);
|
||||||
const searchServiceStub = {
|
const searchServiceStub = jasmine.createSpyObj('SearchService', {
|
||||||
searchOptions:{ pagination: pagination, sort: sort },
|
search: mockResults
|
||||||
search: () => mockResults
|
});
|
||||||
};
|
|
||||||
const queryParam = 'test query';
|
const queryParam = 'test query';
|
||||||
const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f';
|
const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f';
|
||||||
|
const paginatedSearchOptions = {
|
||||||
|
query: queryParam,
|
||||||
|
scope: scopeParam,
|
||||||
|
pagination,
|
||||||
|
sort
|
||||||
|
};
|
||||||
const activatedRouteStub = {
|
const activatedRouteStub = {
|
||||||
queryParams: Observable.of({
|
queryParams: Observable.of({
|
||||||
query: queryParam,
|
query: queryParam,
|
||||||
@@ -50,20 +58,8 @@ describe('SearchPageComponent', () => {
|
|||||||
isCollapsed: Observable.of(true),
|
isCollapsed: Observable.of(true),
|
||||||
collapse: () => this.isCollapsed = Observable.of(true),
|
collapse: () => this.isCollapsed = Observable.of(true),
|
||||||
expand: () => this.isCollapsed = Observable.of(false)
|
expand: () => this.isCollapsed = Observable.of(false)
|
||||||
}
|
|
||||||
|
|
||||||
const mockCommunityList = [];
|
|
||||||
const communityDataServiceStub = {
|
|
||||||
findAll: () => Observable.of(mockCommunityList),
|
|
||||||
findById: () => Observable.of(new Community())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RouterStub {
|
|
||||||
navigateByUrl(url: string) {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, NgbCollapseModule.forRoot()],
|
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, NgbCollapseModule.forRoot()],
|
||||||
@@ -89,6 +85,14 @@ describe('SearchPageComponent', () => {
|
|||||||
provide: SearchSidebarService,
|
provide: SearchSidebarService,
|
||||||
useValue: sidebarService
|
useValue: sidebarService
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: SearchFilterService,
|
||||||
|
useValue: jasmine.createSpyObj('SearchFilterService', {
|
||||||
|
getPaginatedSearchOptions: hot('a', {
|
||||||
|
a: paginatedSearchOptions
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).overrideComponent(SearchPageComponent, {
|
}).overrideComponent(SearchPageComponent, {
|
||||||
@@ -103,54 +107,10 @@ describe('SearchPageComponent', () => {
|
|||||||
searchServiceObject = (comp as any).service;
|
searchServiceObject = (comp as any).service;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set the scope and query based on the route parameters', () => {
|
it('should get the scope and query from the route parameters', () => {
|
||||||
expect(comp.query).toBe(queryParam);
|
expect(comp.searchOptions$).toBeObservable(cold('b', {
|
||||||
expect((comp as any).scope).toBe(scopeParam);
|
b: paginatedSearchOptions
|
||||||
});
|
}));
|
||||||
|
|
||||||
describe('when update search results is called', () => {
|
|
||||||
let paginationUpdate;
|
|
||||||
let sortUpdate;
|
|
||||||
beforeEach(() => {
|
|
||||||
paginationUpdate = Object.assign(
|
|
||||||
{},
|
|
||||||
new PaginationComponentOptions(),
|
|
||||||
{
|
|
||||||
currentPage: 5,
|
|
||||||
pageSize: 15
|
|
||||||
}
|
|
||||||
);
|
|
||||||
sortUpdate = Object.assign({},
|
|
||||||
new SortOptions(),
|
|
||||||
{
|
|
||||||
direction: SortDirection.Ascending,
|
|
||||||
field: 'test-field'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the search function of the search service with the right parameters', () => {
|
|
||||||
spyOn(searchServiceObject, 'search').and.callThrough();
|
|
||||||
|
|
||||||
(comp as any).updateSearchResults({
|
|
||||||
pagination: pagination,
|
|
||||||
sort: sort
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(searchServiceObject.search).toHaveBeenCalledWith(queryParam, scopeParam, {
|
|
||||||
pagination: pagination,
|
|
||||||
sort: sort
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update the results', () => {
|
|
||||||
spyOn(searchServiceObject, 'search').and.callThrough();
|
|
||||||
|
|
||||||
(comp as any).updateSearchResults({});
|
|
||||||
|
|
||||||
expect(comp.resultsRDObs as any).toBe(mockResults);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the closeSidebar event is emitted clicked in mobile view', () => {
|
describe('when the closeSidebar event is emitted clicked in mobile view', () => {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { flatMap, } from 'rxjs/operators';
|
||||||
import { SortOptions } from '../core/cache/models/sort-options.model';
|
import { SortOptions } from '../core/cache/models/sort-options.model';
|
||||||
import { CommunityDataService } from '../core/data/community-data.service';
|
import { CommunityDataService } from '../core/data/community-data.service';
|
||||||
import { PaginatedList } from '../core/data/paginated-list';
|
import { PaginatedList } from '../core/data/paginated-list';
|
||||||
@@ -8,14 +8,12 @@ import { RemoteData } from '../core/data/remote-data';
|
|||||||
import { Community } from '../core/shared/community.model';
|
import { Community } from '../core/shared/community.model';
|
||||||
import { DSpaceObject } from '../core/shared/dspace-object.model';
|
import { DSpaceObject } from '../core/shared/dspace-object.model';
|
||||||
import { pushInOut } from '../shared/animations/push';
|
import { pushInOut } from '../shared/animations/push';
|
||||||
import { isNotEmpty } from '../shared/empty.util';
|
|
||||||
import { HostWindowService } from '../shared/host-window.service';
|
import { HostWindowService } from '../shared/host-window.service';
|
||||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
import { PaginatedSearchOptions } from './paginated-search-options.model';
|
||||||
import { SearchOptions, ViewMode } from './search-options.model';
|
import { SearchFilterService } from './search-filters/search-filter/search-filter.service';
|
||||||
import { SearchResult } from './search-result.model';
|
import { SearchResult } from './search-result.model';
|
||||||
import { SearchService } from './search-service/search.service';
|
import { SearchService } from './search-service/search.service';
|
||||||
import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
|
import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
|
||||||
import { SearchFilterService } from './search-filters/search-filter/search-filter.service';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component renders a simple item page.
|
* This component renders a simple item page.
|
||||||
@@ -30,19 +28,14 @@ import { SearchFilterService } from './search-filters/search-filter/search-filte
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
animations: [pushInOut]
|
animations: [pushInOut]
|
||||||
})
|
})
|
||||||
export class SearchPageComponent implements OnInit, OnDestroy {
|
export class SearchPageComponent implements OnInit {
|
||||||
|
|
||||||
private sub;
|
resultsRD$: Observable<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>>;
|
||||||
private scope: string;
|
|
||||||
|
|
||||||
query: string;
|
|
||||||
scopeObjectRDObs: Observable<RemoteData<DSpaceObject>>;
|
|
||||||
resultsRDObs: Observable<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>>;
|
|
||||||
currentParams = {};
|
currentParams = {};
|
||||||
searchOptions: SearchOptions;
|
searchOptions$: Observable<PaginatedSearchOptions>;
|
||||||
sortConfig: SortOptions;
|
sortConfig: SortOptions;
|
||||||
scopeListRDObs: Observable<RemoteData<PaginatedList<Community>>>;
|
scopeListRD$: Observable<RemoteData<PaginatedList<Community>>>;
|
||||||
isMobileView: Observable<boolean>;
|
isMobileView$: Observable<boolean>;
|
||||||
pageSize;
|
pageSize;
|
||||||
pageSizeOptions;
|
pageSizeOptions;
|
||||||
defaults = {
|
defaults = {
|
||||||
@@ -50,7 +43,8 @@ export class SearchPageComponent implements OnInit, OnDestroy {
|
|||||||
id: 'search-results-pagination',
|
id: 'search-results-pagination',
|
||||||
pageSize: 10
|
pageSize: 10
|
||||||
},
|
},
|
||||||
query: ''
|
query: '',
|
||||||
|
scope: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(private service: SearchService,
|
constructor(private service: SearchService,
|
||||||
@@ -58,27 +52,19 @@ export class SearchPageComponent implements OnInit, OnDestroy {
|
|||||||
private sidebarService: SearchSidebarService,
|
private sidebarService: SearchSidebarService,
|
||||||
private windowService: HostWindowService,
|
private windowService: HostWindowService,
|
||||||
private filterService: SearchFilterService) {
|
private filterService: SearchFilterService) {
|
||||||
this.isMobileView = Observable.combineLatest(
|
this.isMobileView$ = Observable.combineLatest(
|
||||||
this.windowService.isXs(),
|
this.windowService.isXs(),
|
||||||
this.windowService.isSm(),
|
this.windowService.isSm(),
|
||||||
((isXs, isSm) => isXs || isSm)
|
((isXs, isSm) => isXs || isSm)
|
||||||
);
|
);
|
||||||
this.scopeListRDObs = communityService.findAll();
|
this.scopeListRD$ = communityService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.sub = this.filterService.getPaginatedSearchOptions(this.defaults).subscribe((options) => {
|
this.searchOptions$ = this.filterService.getPaginatedSearchOptions(this.defaults);
|
||||||
this.updateSearchResults(options);
|
this.resultsRD$ = this.searchOptions$.pipe(
|
||||||
});
|
flatMap((searchOptions) => this.service.search(searchOptions))
|
||||||
}
|
);
|
||||||
|
|
||||||
private updateSearchResults(searchOptions) {
|
|
||||||
this.resultsRDObs = this.service.search(searchOptions);
|
|
||||||
this.searchOptions = searchOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.sub.unsubscribe();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeSidebar(): void {
|
public closeSidebar(): void {
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
|
<h2>{{ 'search.results.head' | translate }}</h2>
|
||||||
<div *ngIf="searchResults?.hasSucceeded && !searchResults?.isLoading" @fadeIn>
|
<div *ngIf="searchResults?.hasSucceeded && !searchResults?.isLoading" @fadeIn>
|
||||||
<h2 *ngIf="searchResults?.payload ?.length > 0">{{ 'search.results.head' | translate }}</h2>
|
|
||||||
<ds-viewable-collection
|
<ds-viewable-collection
|
||||||
[config]="searchConfig.pagination"
|
[config]="searchConfig.pagination"
|
||||||
[sortConfig]="searchConfig.sort"
|
[sortConfig]="searchConfig.sort"
|
||||||
[objects]="searchResults"
|
[objects]="searchResults"
|
||||||
[hideGear]="true">
|
[hideGear]="true">
|
||||||
</ds-viewable-collection></div>
|
</ds-viewable-collection></div>
|
||||||
<ds-loading *ngIf="searchResults?.isLoading" message="{{'loading.search-results' | translate}}"></ds-loading>
|
<ds-loading *ngIf="!searchResults || searchResults?.isLoading" message="{{'loading.search-results' | translate}}"></ds-loading>
|
||||||
<ds-error *ngIf="searchResults?.hasFailed" message="{{'error.search-results' | translate}}"></ds-error>
|
<ds-error *ngIf="searchResults?.hasFailed" message="{{'error.search-results' | translate}}"></ds-error>
|
||||||
|
<ds-error *ngIf="searchResults?.payload?.page.length == 0" message="{{'search.results.no-results' | translate}}"></ds-error>
|
@@ -5,6 +5,7 @@ import { fadeIn, fadeInOut } from '../../shared/animations/fade';
|
|||||||
import { SearchOptions, ViewMode } from '../search-options.model';
|
import { SearchOptions, ViewMode } from '../search-options.model';
|
||||||
import { SortOptions } from '../../core/cache/models/sort-options.model';
|
import { SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
import { SearchResult } from '../search-result.model';
|
import { SearchResult } from '../search-result.model';
|
||||||
|
import { PaginatedList } from '../../core/data/paginated-list';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component renders a simple item page.
|
* This component renders a simple item page.
|
||||||
@@ -20,7 +21,7 @@ import { SearchResult } from '../search-result.model';
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class SearchResultsComponent {
|
export class SearchResultsComponent {
|
||||||
@Input() searchResults: RemoteData<Array<SearchResult<DSpaceObject>>>;
|
@Input() searchResults: RemoteData<PaginatedList<SearchResult<DSpaceObject>>>;
|
||||||
@Input() searchConfig: SearchOptions;
|
@Input() searchConfig: SearchOptions;
|
||||||
@Input() sortConfig: SortOptions;
|
@Input() sortConfig: SortOptions;
|
||||||
@Input() viewMode: ViewMode;
|
@Input() viewMode: ViewMode;
|
||||||
|
@@ -10,11 +10,28 @@ import { ViewMode } from '../../+search-page/search-options.model';
|
|||||||
import { RouteService } from '../../shared/route.service';
|
import { RouteService } from '../../shared/route.service';
|
||||||
import { GLOBAL_CONFIG } from '../../../config';
|
import { GLOBAL_CONFIG } from '../../../config';
|
||||||
import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router, UrlTree } from '@angular/router';
|
||||||
import { RequestService } from '../../core/data/request.service';
|
import { RequestService } from '../../core/data/request.service';
|
||||||
import { ResponseCacheService } from '../../core/cache/response-cache.service';
|
import { ResponseCacheService } from '../../core/cache/response-cache.service';
|
||||||
import { ActivatedRouteStub } from '../../shared/testing/active-router-stub';
|
import { ActivatedRouteStub } from '../../shared/testing/active-router-stub';
|
||||||
import { RouterStub } from '../../shared/testing/router-stub';
|
import { RouterStub } from '../../shared/testing/router-stub';
|
||||||
|
import { HALEndpointService } from '../../core/shared/hal-endpoint.service';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { PaginatedSearchOptions } from '../paginated-search-options.model';
|
||||||
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
|
import { PaginatedList } from '../../core/data/paginated-list';
|
||||||
|
import { SearchResult } from '../search-result.model';
|
||||||
|
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
||||||
|
import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer';
|
||||||
|
import { RequestEntry } from '../../core/data/request.reducer';
|
||||||
|
import { getMockRequestService } from '../../shared/mocks/mock-request.service';
|
||||||
|
import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service';
|
||||||
|
import {
|
||||||
|
FacetConfigSuccessResponse, RestResponse,
|
||||||
|
SearchSuccessResponse
|
||||||
|
} from '../../core/cache/response-cache.models';
|
||||||
|
import { SearchQueryResponse } from './search-query-response.model';
|
||||||
|
import { SearchFilterConfig } from './search-filter-config.model';
|
||||||
|
|
||||||
@Component({ template: '' })
|
@Component({ template: '' })
|
||||||
class DummyComponent {
|
class DummyComponent {
|
||||||
@@ -37,14 +54,12 @@ describe('SearchService', () => {
|
|||||||
DummyComponent
|
DummyComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: ItemDataService, useValue: {} },
|
|
||||||
{ provide: RouteService, useValue: {} },
|
|
||||||
{ provide: ResponseCacheService, useValue: {} },
|
|
||||||
{ provide: RequestService, useValue: {} },
|
|
||||||
{ provide: ActivatedRoute, useValue: route },
|
|
||||||
{ provide: RemoteDataBuildService, useValue: {} },
|
|
||||||
{ provide: GLOBAL_CONFIG, useValue: {} },
|
|
||||||
{ provide: Router, useValue: router },
|
{ provide: Router, useValue: router },
|
||||||
|
{ provide: ActivatedRoute, useValue: route },
|
||||||
|
{ provide: ResponseCacheService, useValue: getMockResponseCacheService() },
|
||||||
|
{ provide: RequestService, useValue: getMockRequestService() },
|
||||||
|
{ provide: RemoteDataBuildService, useValue: {} },
|
||||||
|
{ provide: HALEndpointService, useValue: {} },
|
||||||
SearchService
|
SearchService
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@@ -61,6 +76,27 @@ describe('SearchService', () => {
|
|||||||
let searchService: SearchService;
|
let searchService: SearchService;
|
||||||
const router = new RouterStub();
|
const router = new RouterStub();
|
||||||
const route = new ActivatedRouteStub();
|
const route = new ActivatedRouteStub();
|
||||||
|
|
||||||
|
const halService = {
|
||||||
|
/* tslint:disable:no-empty */
|
||||||
|
getEndpoint: () => {
|
||||||
|
}
|
||||||
|
/* tslint:enable:no-empty */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const remoteDataBuildService = {
|
||||||
|
toRemoteDataObservable: (requestEntryObs: Observable<RequestEntry>, responseCacheObs: Observable<ResponseCacheEntry>, payloadObs: Observable<any>) => {
|
||||||
|
return Observable.combineLatest(requestEntryObs,
|
||||||
|
responseCacheObs, payloadObs, (req, res, pay) => {
|
||||||
|
return { req, res, pay };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
aggregate: (input: Array<Observable<RemoteData<any>>>): Observable<RemoteData<any[]>> => {
|
||||||
|
return Observable.of(new RemoteData(false, false, true, null, []));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -73,18 +109,18 @@ describe('SearchService', () => {
|
|||||||
DummyComponent
|
DummyComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: ItemDataService, useValue: {} },
|
|
||||||
{ provide: RouteService, useValue: {} },
|
|
||||||
{ provide: ResponseCacheService, useValue: {} },
|
|
||||||
{ provide: RequestService, useValue: {} },
|
|
||||||
{ provide: ActivatedRoute, useValue: route },
|
|
||||||
{ provide: RemoteDataBuildService, useValue: {} },
|
|
||||||
{ provide: GLOBAL_CONFIG, useValue: {} },
|
|
||||||
{ provide: Router, useValue: router },
|
{ provide: Router, useValue: router },
|
||||||
|
{ provide: ActivatedRoute, useValue: route },
|
||||||
|
{ provide: ResponseCacheService, useValue: getMockResponseCacheService() },
|
||||||
|
{ provide: RequestService, useValue: getMockRequestService() },
|
||||||
|
{ provide: RemoteDataBuildService, useValue: remoteDataBuildService },
|
||||||
|
{ provide: HALEndpointService, useValue: halService },
|
||||||
SearchService
|
SearchService
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
searchService = TestBed.get(SearchService);
|
searchService = TestBed.get(SearchService);
|
||||||
|
const urlTree = Object.assign(new UrlTree(), { root: { children: { primary: 'search' } } });
|
||||||
|
router.parseUrl.and.returnValue(urlTree);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call the navigate method on the Router with view mode list parameter as a parameter when setViewMode is called', () => {
|
it('should call the navigate method on the Router with view mode list parameter as a parameter when setViewMode is called', () => {
|
||||||
@@ -116,5 +152,98 @@ describe('SearchService', () => {
|
|||||||
searchService.getViewMode().subscribe((mode) => viewMode = mode);
|
searchService.getViewMode().subscribe((mode) => viewMode = mode);
|
||||||
expect(viewMode).toEqual(ViewMode.Grid);
|
expect(viewMode).toEqual(ViewMode.Grid);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when search is called', () => {
|
||||||
|
const endPoint = 'http://endpoint.com/test/test';
|
||||||
|
const searchOptions = new PaginatedSearchOptions();
|
||||||
|
const queryResponse = Object.assign(new SearchQueryResponse(), { objects: [] });
|
||||||
|
const response = new SearchSuccessResponse(queryResponse, '200');
|
||||||
|
const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response });
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endPoint));
|
||||||
|
(searchService as any).responseCache.get.and.returnValue(Observable.of(responseEntry));
|
||||||
|
/* tslint:disable:no-empty */
|
||||||
|
searchService.search(searchOptions).subscribe((t) => {
|
||||||
|
}); // subscribe to make sure all methods are called
|
||||||
|
/* tslint:enable:no-empty */
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call getEndpoint on the halService', () => {
|
||||||
|
expect((searchService as any).halService.getEndpoint).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should send out the request on the request service', () => {
|
||||||
|
expect((searchService as any).requestService.configure).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call getByHref on the request service with the correct request url', () => {
|
||||||
|
expect((searchService as any).requestService.getByHref).toHaveBeenCalledWith(endPoint);
|
||||||
|
});
|
||||||
|
it('should call get on the request service with the correct request url', () => {
|
||||||
|
expect((searchService as any).responseCache.get).toHaveBeenCalledWith(endPoint);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when getConfig is called without a scope', () => {
|
||||||
|
const endPoint = 'http://endpoint.com/test/config';
|
||||||
|
const filterConfig = [new SearchFilterConfig()];
|
||||||
|
const response = new FacetConfigSuccessResponse(filterConfig, '200');
|
||||||
|
const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response });
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endPoint));
|
||||||
|
(searchService as any).responseCache.get.and.returnValue(Observable.of(responseEntry));
|
||||||
|
/* tslint:disable:no-empty */
|
||||||
|
searchService.getConfig(null).subscribe((t) => {
|
||||||
|
}); // subscribe to make sure all methods are called
|
||||||
|
/* tslint:enable:no-empty */
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call getEndpoint on the halService', () => {
|
||||||
|
expect((searchService as any).halService.getEndpoint).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should send out the request on the request service', () => {
|
||||||
|
expect((searchService as any).requestService.configure).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call getByHref on the request service with the correct request url', () => {
|
||||||
|
expect((searchService as any).requestService.getByHref).toHaveBeenCalledWith(endPoint);
|
||||||
|
});
|
||||||
|
it('should call get on the request service with the correct request url', () => {
|
||||||
|
expect((searchService as any).responseCache.get).toHaveBeenCalledWith(endPoint);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when getConfig is called with a scope', () => {
|
||||||
|
const endPoint = 'http://endpoint.com/test/config';
|
||||||
|
const scope = 'test';
|
||||||
|
const requestUrl = endPoint + '?scope=' + scope;
|
||||||
|
const filterConfig = [new SearchFilterConfig()];
|
||||||
|
const response = new FacetConfigSuccessResponse(filterConfig, '200');
|
||||||
|
const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response });
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endPoint));
|
||||||
|
(searchService as any).responseCache.get.and.returnValue(Observable.of(responseEntry));
|
||||||
|
/* tslint:disable:no-empty */
|
||||||
|
searchService.getConfig(scope).subscribe((t) => {
|
||||||
|
}); // subscribe to make sure all methods are called
|
||||||
|
/* tslint:enable:no-empty */
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call getEndpoint on the halService', () => {
|
||||||
|
expect((searchService as any).halService.getEndpoint).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should send out the request on the request service', () => {
|
||||||
|
expect((searchService as any).requestService.configure).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call getByHref on the request service with the correct request url', () => {
|
||||||
|
expect((searchService as any).requestService.getByHref).toHaveBeenCalledWith(requestUrl);
|
||||||
|
});
|
||||||
|
it('should call get on the request service with the correct request url', () => {
|
||||||
|
expect((searchService as any).responseCache.get).toHaveBeenCalledWith(requestUrl);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,8 @@
|
|||||||
import { Injectable, OnDestroy } from '@angular/core';
|
import { Injectable, OnDestroy } from '@angular/core';
|
||||||
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
|
import {
|
||||||
|
ActivatedRoute, NavigationExtras, PRIMARY_OUTLET, Router,
|
||||||
|
UrlSegmentGroup
|
||||||
|
} from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { flatMap, map, tap } from 'rxjs/operators';
|
import { flatMap, map, tap } from 'rxjs/operators';
|
||||||
import { ViewMode } from '../../+search-page/search-options.model';
|
import { ViewMode } from '../../+search-page/search-options.model';
|
||||||
@@ -21,14 +24,12 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
|||||||
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
||||||
import { HALEndpointService } from '../../core/shared/hal-endpoint.service';
|
import { HALEndpointService } from '../../core/shared/hal-endpoint.service';
|
||||||
import { URLCombiner } from '../../core/url-combiner/url-combiner';
|
import { URLCombiner } from '../../core/url-combiner/url-combiner';
|
||||||
import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
|
||||||
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
import { RouteService } from '../../shared/route.service';
|
|
||||||
import { NormalizedSearchResult } from '../normalized-search-result.model';
|
import { NormalizedSearchResult } from '../normalized-search-result.model';
|
||||||
import { SearchOptions } from '../search-options.model';
|
import { SearchOptions } from '../search-options.model';
|
||||||
import { SearchResult } from '../search-result.model';
|
import { SearchResult } from '../search-result.model';
|
||||||
import { FacetValue } from './facet-value.model';
|
import { FacetValue } from './facet-value.model';
|
||||||
import { FilterType } from './filter-type.model';
|
|
||||||
import { SearchFilterConfig } from './search-filter-config.model';
|
import { SearchFilterConfig } from './search-filter-config.model';
|
||||||
import { SearchResponseParsingService } from '../../core/data/search-response-parsing.service';
|
import { SearchResponseParsingService } from '../../core/data/search-response-parsing.service';
|
||||||
import { SearchQueryResponse } from './search-query-response.model';
|
import { SearchQueryResponse } from './search-query-response.model';
|
||||||
@@ -37,50 +38,17 @@ import { getSearchResultFor } from './search-result-element-decorator';
|
|||||||
import { ListableObject } from '../../shared/object-collection/shared/listable-object.model';
|
import { ListableObject } from '../../shared/object-collection/shared/listable-object.model';
|
||||||
import { FacetValueResponseParsingService } from '../../core/data/facet-value-response-parsing.service';
|
import { FacetValueResponseParsingService } from '../../core/data/facet-value-response-parsing.service';
|
||||||
import { FacetConfigResponseParsingService } from '../../core/data/facet-config-response-parsing.service';
|
import { FacetConfigResponseParsingService } from '../../core/data/facet-config-response-parsing.service';
|
||||||
import { SearchFilterService } from '../search-filters/search-filter/search-filter.service';
|
|
||||||
import { PaginatedSearchOptions } from '../paginated-search-options.model';
|
import { PaginatedSearchOptions } from '../paginated-search-options.model';
|
||||||
|
import { observable } from 'rxjs/symbol/observable';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SearchService implements OnDestroy {
|
export class SearchService implements OnDestroy {
|
||||||
private searchLinkPath = 'discover/search/objects';
|
private searchLinkPath = 'discover/search/objects';
|
||||||
private facetValueLinkPath = 'discover/search/facets';
|
|
||||||
private facetValueLinkPathPrefix = 'discover/facets/';
|
private facetValueLinkPathPrefix = 'discover/facets/';
|
||||||
private facetConfigLinkPath = 'discover/facets';
|
private facetConfigLinkPath = 'discover/facets';
|
||||||
|
|
||||||
private sub;
|
private sub;
|
||||||
uiSearchRoute = '/search';
|
|
||||||
|
|
||||||
config: SearchFilterConfig[] = [
|
|
||||||
// Object.assign(new SearchFilterConfig(),
|
|
||||||
// {
|
|
||||||
// name: 'scope',
|
|
||||||
// type: FilterType.hierarchical,
|
|
||||||
// hasFacets: true,
|
|
||||||
// isOpenByDefault: true
|
|
||||||
// }),
|
|
||||||
Object.assign(new SearchFilterConfig(),
|
|
||||||
{
|
|
||||||
name: 'author',
|
|
||||||
type: FilterType.text,
|
|
||||||
hasFacets: true,
|
|
||||||
isOpenByDefault: false
|
|
||||||
}),
|
|
||||||
Object.assign(new SearchFilterConfig(),
|
|
||||||
{
|
|
||||||
name: 'dateIssued',
|
|
||||||
type: FilterType.date,
|
|
||||||
hasFacets: true,
|
|
||||||
isOpenByDefault: false
|
|
||||||
}),
|
|
||||||
Object.assign(new SearchFilterConfig(),
|
|
||||||
{
|
|
||||||
name: 'subject',
|
|
||||||
type: FilterType.text,
|
|
||||||
hasFacets: false,
|
|
||||||
isOpenByDefault: false
|
|
||||||
})
|
|
||||||
];
|
|
||||||
// searchOptions: BehaviorSubject<SearchOptions>;
|
|
||||||
searchOptions: SearchOptions;
|
searchOptions: SearchOptions;
|
||||||
|
|
||||||
constructor(private router: Router,
|
constructor(private router: Router,
|
||||||
@@ -101,7 +69,7 @@ export class SearchService implements OnDestroy {
|
|||||||
const requestObs = this.halService.getEndpoint(this.searchLinkPath).pipe(
|
const requestObs = this.halService.getEndpoint(this.searchLinkPath).pipe(
|
||||||
map((url: string) => {
|
map((url: string) => {
|
||||||
if (hasValue(searchOptions)) {
|
if (hasValue(searchOptions)) {
|
||||||
url = searchOptions.toRestUrl(url);
|
url = (searchOptions as PaginatedSearchOptions).toRestUrl(url);
|
||||||
}
|
}
|
||||||
const request = new GetRequest(this.requestService.generateRequestId(), url);
|
const request = new GetRequest(this.requestService.generateRequestId(), url);
|
||||||
return Object.assign(request, {
|
return Object.assign(request, {
|
||||||
@@ -112,7 +80,6 @@ export class SearchService implements OnDestroy {
|
|||||||
}),
|
}),
|
||||||
tap((request: RestRequest) => this.requestService.configure(request)),
|
tap((request: RestRequest) => this.requestService.configure(request)),
|
||||||
);
|
);
|
||||||
|
|
||||||
const requestEntryObs = requestObs.pipe(
|
const requestEntryObs = requestObs.pipe(
|
||||||
flatMap((request: RestRequest) => this.requestService.getByHref(request.href))
|
flatMap((request: RestRequest) => this.requestService.getByHref(request.href))
|
||||||
);
|
);
|
||||||
@@ -138,7 +105,8 @@ export class SearchService implements OnDestroy {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Create search results again with the correct dso objects linked to each result
|
// Create search results again with the correct dso objects linked to each result
|
||||||
const tDomainListObs: Observable<Array<SearchResult<DSpaceObject>>> = Observable.combineLatest(sqrObs, dsoObs, (sqr: SearchQueryResponse, dsos: RemoteData<DSpaceObject[]>) => {
|
const tDomainListObs = Observable.combineLatest(sqrObs, dsoObs, (sqr: SearchQueryResponse, dsos: RemoteData<DSpaceObject[]>) => {
|
||||||
|
|
||||||
return sqr.objects.map((object: NormalizedSearchResult, index: number) => {
|
return sqr.objects.map((object: NormalizedSearchResult, index: number) => {
|
||||||
let co = DSpaceObject;
|
let co = DSpaceObject;
|
||||||
if (dsos.payload[index]) {
|
if (dsos.payload[index]) {
|
||||||
@@ -206,7 +174,6 @@ export class SearchService implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getFacetValuesFor(filterConfig: SearchFilterConfig, valuePage: number, searchOptions?: SearchOptions): Observable<RemoteData<PaginatedList<FacetValue>>> {
|
getFacetValuesFor(filterConfig: SearchFilterConfig, valuePage: number, searchOptions?: SearchOptions): Observable<RemoteData<PaginatedList<FacetValue>>> {
|
||||||
console.log('facetvalues');
|
|
||||||
const requestObs = this.halService.getEndpoint(this.facetValueLinkPathPrefix + filterConfig.name).pipe(
|
const requestObs = this.halService.getEndpoint(this.facetValueLinkPathPrefix + filterConfig.name).pipe(
|
||||||
map((url: string) => {
|
map((url: string) => {
|
||||||
const args: string[] = [`page=${valuePage - 1}`, `size=${filterConfig.pageSize}`];
|
const args: string[] = [`page=${valuePage - 1}`, `size=${filterConfig.pageSize}`];
|
||||||
@@ -265,25 +232,13 @@ export class SearchService implements OnDestroy {
|
|||||||
queryParamsHandling: 'merge'
|
queryParamsHandling: 'merge'
|
||||||
};
|
};
|
||||||
|
|
||||||
this.router.navigate([this.uiSearchRoute], navigationExtras);
|
this.router.navigate([this.getSearchLink()], navigationExtras);
|
||||||
}
|
|
||||||
|
|
||||||
getClearFiltersQueryParams(): any {
|
|
||||||
const params = {};
|
|
||||||
this.sub = this.route.queryParamMap
|
|
||||||
.subscribe((pmap) => {
|
|
||||||
pmap.keys
|
|
||||||
.filter((key) => this.config
|
|
||||||
.findIndex((conf: SearchFilterConfig) => conf.paramName === key) < 0)
|
|
||||||
.forEach((key) => {
|
|
||||||
params[key] = pmap.get(key);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
return params;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getSearchLink() {
|
getSearchLink() {
|
||||||
return this.uiSearchRoute;
|
const urlTree = this.router.parseUrl(this.router.url);
|
||||||
|
const g: UrlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET];
|
||||||
|
return '/' + g.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
@@ -3,11 +3,11 @@ import { getMockResponseCacheService } from '../../shared/mocks/mock-response-ca
|
|||||||
import { BrowseService } from './browse.service';
|
import { BrowseService } from './browse.service';
|
||||||
import { ResponseCacheService } from '../cache/response-cache.service';
|
import { ResponseCacheService } from '../cache/response-cache.service';
|
||||||
import { RequestService } from '../data/request.service';
|
import { RequestService } from '../data/request.service';
|
||||||
import { GlobalConfig } from '../../../config';
|
|
||||||
import { hot, cold, getTestScheduler } from 'jasmine-marbles';
|
import { hot, cold, getTestScheduler } from 'jasmine-marbles';
|
||||||
import { BrowseDefinition } from '../shared/browse-definition.model';
|
import { BrowseDefinition } from '../shared/browse-definition.model';
|
||||||
import { BrowseEndpointRequest } from '../data/request.models';
|
import { BrowseEndpointRequest } from '../data/request.models';
|
||||||
import { TestScheduler } from 'rxjs/Rx';
|
import { TestScheduler } from 'rxjs/Rx';
|
||||||
|
import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service-stub';
|
||||||
|
|
||||||
describe('BrowseService', () => {
|
describe('BrowseService', () => {
|
||||||
let scheduler: TestScheduler;
|
let scheduler: TestScheduler;
|
||||||
@@ -15,8 +15,8 @@ describe('BrowseService', () => {
|
|||||||
let responseCache: ResponseCacheService;
|
let responseCache: ResponseCacheService;
|
||||||
let requestService: RequestService;
|
let requestService: RequestService;
|
||||||
|
|
||||||
const envConfig = {} as GlobalConfig;
|
|
||||||
const browsesEndpointURL = 'https://rest.api/browses';
|
const browsesEndpointURL = 'https://rest.api/browses';
|
||||||
|
const halService: any = new HALEndpointServiceStub(browsesEndpointURL);
|
||||||
const browseDefinitions = [
|
const browseDefinitions = [
|
||||||
Object.assign(new BrowseDefinition(), {
|
Object.assign(new BrowseDefinition(), {
|
||||||
metadataBrowse: false,
|
metadataBrowse: false,
|
||||||
@@ -91,7 +91,7 @@ describe('BrowseService', () => {
|
|||||||
return new BrowseService(
|
return new BrowseService(
|
||||||
responseCache,
|
responseCache,
|
||||||
requestService,
|
requestService,
|
||||||
envConfig
|
halService
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ describe('BrowseService', () => {
|
|||||||
responseCache = initMockResponseCacheService(true);
|
responseCache = initMockResponseCacheService(true);
|
||||||
requestService = getMockRequestService();
|
requestService = getMockRequestService();
|
||||||
service = initTestService();
|
service = initTestService();
|
||||||
spyOn(service, 'getEndpoint').and
|
spyOn(halService, 'getEndpoint').and
|
||||||
.returnValue(hot('--a-', { a: browsesEndpointURL }));
|
.returnValue(hot('--a-', { a: browsesEndpointURL }));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ describe('BrowseService', () => {
|
|||||||
responseCache = initMockResponseCacheService(true);
|
responseCache = initMockResponseCacheService(true);
|
||||||
requestService = getMockRequestService();
|
requestService = getMockRequestService();
|
||||||
service = initTestService();
|
service = initTestService();
|
||||||
spyOn(service, 'getEndpoint').and
|
spyOn(halService, 'getEndpoint').and
|
||||||
.returnValue(hot('----'));
|
.returnValue(hot('----'));
|
||||||
|
|
||||||
const metadatumKey = 'dc.date.issued';
|
const metadatumKey = 'dc.date.issued';
|
||||||
@@ -188,7 +188,7 @@ describe('BrowseService', () => {
|
|||||||
responseCache = initMockResponseCacheService(false);
|
responseCache = initMockResponseCacheService(false);
|
||||||
requestService = getMockRequestService();
|
requestService = getMockRequestService();
|
||||||
service = initTestService();
|
service = initTestService();
|
||||||
spyOn(service, 'getEndpoint').and
|
spyOn(halService, 'getEndpoint').and
|
||||||
.returnValue(hot('--a-', { a: browsesEndpointURL }));
|
.returnValue(hot('--a-', { a: browsesEndpointURL }));
|
||||||
|
|
||||||
const metadatumKey = 'dc.date.issued';
|
const metadatumKey = 'dc.date.issued';
|
||||||
|
@@ -4,7 +4,7 @@ import { map, tap } from 'rxjs/operators';
|
|||||||
import { NormalizedSearchResult } from '../../../+search-page/normalized-search-result.model';
|
import { NormalizedSearchResult } from '../../../+search-page/normalized-search-result.model';
|
||||||
import { SearchResult } from '../../../+search-page/search-result.model';
|
import { SearchResult } from '../../../+search-page/search-result.model';
|
||||||
import { SearchQueryResponse } from '../../../+search-page/search-service/search-query-response.model';
|
import { SearchQueryResponse } from '../../../+search-page/search-service/search-query-response.model';
|
||||||
import { hasValue, isNotEmpty } from '../../../shared/empty.util';
|
import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util';
|
||||||
import { PaginatedList } from '../../data/paginated-list';
|
import { PaginatedList } from '../../data/paginated-list';
|
||||||
import { RemoteData } from '../../data/remote-data';
|
import { RemoteData } from '../../data/remote-data';
|
||||||
import { RemoteDataError } from '../../data/remote-data-error';
|
import { RemoteDataError } from '../../data/remote-data-error';
|
||||||
@@ -200,6 +200,11 @@ export class RemoteDataBuildService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
aggregate<T>(input: Array<Observable<RemoteData<T>>>): Observable<RemoteData<T[]>> {
|
aggregate<T>(input: Array<Observable<RemoteData<T>>>): Observable<RemoteData<T[]>> {
|
||||||
|
|
||||||
|
if (isEmpty(input)) {
|
||||||
|
return Observable.of(new RemoteData(false, false, true, null, []));
|
||||||
|
}
|
||||||
|
|
||||||
return Observable.combineLatest(
|
return Observable.combineLatest(
|
||||||
...input,
|
...input,
|
||||||
(...arr: Array<RemoteData<T>>) => {
|
(...arr: Array<RemoteData<T>>) => {
|
||||||
|
@@ -1,11 +1,12 @@
|
|||||||
import { cold, getTestScheduler, hot } from 'jasmine-marbles';
|
import { cold, getTestScheduler, hot } from 'jasmine-marbles';
|
||||||
import { TestScheduler } from 'rxjs/Rx';
|
import { TestScheduler } from 'rxjs/Rx';
|
||||||
import { GlobalConfig } from '../../../config';
|
|
||||||
import { getMockRequestService } from '../../shared/mocks/mock-request.service';
|
import { getMockRequestService } from '../../shared/mocks/mock-request.service';
|
||||||
import { ResponseCacheService } from '../cache/response-cache.service';
|
import { ResponseCacheService } from '../cache/response-cache.service';
|
||||||
import { ConfigService } from './config.service';
|
import { ConfigService } from './config.service';
|
||||||
import { RequestService } from '../data/request.service';
|
import { RequestService } from '../data/request.service';
|
||||||
import { ConfigRequest, FindAllOptions } from '../data/request.models';
|
import { ConfigRequest, FindAllOptions } from '../data/request.models';
|
||||||
|
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||||
|
import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service-stub';
|
||||||
|
|
||||||
const LINK_NAME = 'test';
|
const LINK_NAME = 'test';
|
||||||
const BROWSE = 'search/findByCollection';
|
const BROWSE = 'search/findByCollection';
|
||||||
@@ -17,8 +18,7 @@ class TestService extends ConfigService {
|
|||||||
constructor(
|
constructor(
|
||||||
protected responseCache: ResponseCacheService,
|
protected responseCache: ResponseCacheService,
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
protected EnvConfig: GlobalConfig
|
protected halService: HALEndpointService) {
|
||||||
) {
|
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,8 +28,8 @@ describe('ConfigService', () => {
|
|||||||
let service: TestService;
|
let service: TestService;
|
||||||
let responseCache: ResponseCacheService;
|
let responseCache: ResponseCacheService;
|
||||||
let requestService: RequestService;
|
let requestService: RequestService;
|
||||||
|
let halService: any;
|
||||||
|
|
||||||
const envConfig = {} as GlobalConfig;
|
|
||||||
const findOptions: FindAllOptions = new FindAllOptions();
|
const findOptions: FindAllOptions = new FindAllOptions();
|
||||||
|
|
||||||
const scopeName = 'traditional';
|
const scopeName = 'traditional';
|
||||||
@@ -51,7 +51,7 @@ describe('ConfigService', () => {
|
|||||||
return new TestService(
|
return new TestService(
|
||||||
responseCache,
|
responseCache,
|
||||||
requestService,
|
requestService,
|
||||||
envConfig
|
halService
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,8 +60,7 @@ describe('ConfigService', () => {
|
|||||||
requestService = getMockRequestService();
|
requestService = getMockRequestService();
|
||||||
service = initTestService();
|
service = initTestService();
|
||||||
scheduler = getTestScheduler();
|
scheduler = getTestScheduler();
|
||||||
spyOn(service, 'getEndpoint').and
|
halService = new HALEndpointServiceStub(configEndpoint);
|
||||||
.returnValue(hot('--a-', { a: serviceEndpoint }));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getConfigByHref', () => {
|
describe('getConfigByHref', () => {
|
||||||
|
@@ -117,8 +117,9 @@ export abstract class BaseResponseParsingService {
|
|||||||
this.objectCache.add(co, this.EnvConfig.cache.msToLive, requestHref);
|
this.objectCache.add(co, this.EnvConfig.cache.msToLive, requestHref);
|
||||||
}
|
}
|
||||||
|
|
||||||
processPageInfo(pageObj: any): PageInfo {
|
processPageInfo(payload: any): PageInfo {
|
||||||
if (isNotEmpty(pageObj)) {
|
if (isNotEmpty(payload.page)) {
|
||||||
|
const pageObj = Object.assign({}, payload.page, {_links: payload._links});
|
||||||
const pageInfoObject = new DSpaceRESTv2Serializer(PageInfo).deserialize(pageObj);
|
const pageInfoObject = new DSpaceRESTv2Serializer(PageInfo).deserialize(pageObj);
|
||||||
if (pageInfoObject.currentPage >= 0) {
|
if (pageInfoObject.currentPage >= 0) {
|
||||||
Object.assign(pageInfoObject, { currentPage: pageInfoObject.currentPage + 1 });
|
Object.assign(pageInfoObject, { currentPage: pageInfoObject.currentPage + 1 });
|
||||||
|
@@ -13,6 +13,7 @@ import { CommunityDataService } from './community-data.service';
|
|||||||
import { FindByIDRequest } from './request.models';
|
import { FindByIDRequest } from './request.models';
|
||||||
import { RequestService } from './request.service';
|
import { RequestService } from './request.service';
|
||||||
import { NormalizedObject } from '../cache/models/normalized-object.model';
|
import { NormalizedObject } from '../cache/models/normalized-object.model';
|
||||||
|
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||||
|
|
||||||
const LINK_NAME = 'test';
|
const LINK_NAME = 'test';
|
||||||
|
|
||||||
@@ -21,7 +22,6 @@ class NormalizedTestObject extends NormalizedObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TestService extends ComColDataService<NormalizedTestObject, any> {
|
class TestService extends ComColDataService<NormalizedTestObject, any> {
|
||||||
protected linkPath = LINK_NAME;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected responseCache: ResponseCacheService,
|
protected responseCache: ResponseCacheService,
|
||||||
@@ -30,7 +30,9 @@ class TestService extends ComColDataService<NormalizedTestObject, any> {
|
|||||||
protected store: Store<CoreState>,
|
protected store: Store<CoreState>,
|
||||||
protected EnvConfig: GlobalConfig,
|
protected EnvConfig: GlobalConfig,
|
||||||
protected cds: CommunityDataService,
|
protected cds: CommunityDataService,
|
||||||
protected objectCache: ObjectCacheService
|
protected objectCache: ObjectCacheService,
|
||||||
|
protected halService: HALEndpointService,
|
||||||
|
protected linkPath: string
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@@ -44,6 +46,7 @@ describe('ComColDataService', () => {
|
|||||||
let requestService: RequestService;
|
let requestService: RequestService;
|
||||||
let cds: CommunityDataService;
|
let cds: CommunityDataService;
|
||||||
let objectCache: ObjectCacheService;
|
let objectCache: ObjectCacheService;
|
||||||
|
const halService: any = {};
|
||||||
|
|
||||||
const rdbService = {} as RemoteDataBuildService;
|
const rdbService = {} as RemoteDataBuildService;
|
||||||
const store = {} as Store<CoreState>;
|
const store = {} as Store<CoreState>;
|
||||||
@@ -90,7 +93,9 @@ describe('ComColDataService', () => {
|
|||||||
store,
|
store,
|
||||||
EnvConfig,
|
EnvConfig,
|
||||||
cds,
|
cds,
|
||||||
objectCache
|
objectCache,
|
||||||
|
halService,
|
||||||
|
LINK_NAME
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,24 +159,5 @@ describe('ComColDataService', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('if the scope is not specified', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cds = initMockCommunityDataService();
|
|
||||||
requestService = getMockRequestService();
|
|
||||||
objectCache = initMockObjectCacheService();
|
|
||||||
responseCache = initMockResponseCacheService(true);
|
|
||||||
service = initTestService();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return this.getEndpoint()', () => {
|
|
||||||
spyOn(service, 'getEndpoint').and.returnValue(cold('--e-', { e: serviceEndpoint }));
|
|
||||||
|
|
||||||
const result = service.getScopedEndpoint(undefined);
|
|
||||||
const expected = cold('--f-', { f: serviceEndpoint });
|
|
||||||
|
|
||||||
expect(result).toBeObservable(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -29,7 +29,7 @@ export class ConfigResponseParsingService extends BaseResponseParsingService imp
|
|||||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && data.statusCode === '200') {
|
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && data.statusCode === '200') {
|
||||||
const configDefinition = this.process<ConfigObject,ConfigType>(data.payload, request.href);
|
const configDefinition = this.process<ConfigObject,ConfigType>(data.payload, request.href);
|
||||||
return new ConfigSuccessResponse(configDefinition[Object.keys(configDefinition)[0]], data.statusCode, this.processPageInfo(data.payload.page));
|
return new ConfigSuccessResponse(configDefinition[Object.keys(configDefinition)[0]], data.statusCode, this.processPageInfo(data.payload));
|
||||||
} else {
|
} else {
|
||||||
return new ErrorResponse(
|
return new ErrorResponse(
|
||||||
Object.assign(
|
Object.assign(
|
||||||
|
@@ -28,7 +28,7 @@ export class DSOResponseParsingService extends BaseResponseParsingService implem
|
|||||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
const processRequestDTO = this.process<NormalizedObject,ResourceType>(data.payload, request.href);
|
const processRequestDTO = this.process<NormalizedObject,ResourceType>(data.payload, request.href);
|
||||||
const selfLinks = this.flattenSingleKeyObject(processRequestDTO).map((no) => no.self);
|
const selfLinks = this.flattenSingleKeyObject(processRequestDTO).map((no) => no.self);
|
||||||
return new DSOSuccessResponse(selfLinks, data.statusCode, this.processPageInfo(data.payload.page))
|
return new DSOSuccessResponse(selfLinks, data.statusCode, this.processPageInfo(data.payload))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ export class FacetValueMapResponseParsingService extends BaseResponseParsingServ
|
|||||||
payload._embedded.facets.map((facet) => {
|
payload._embedded.facets.map((facet) => {
|
||||||
const values = facet._embedded.values.map((value) => {value.search = value._links.search.href; return value;});
|
const values = facet._embedded.values.map((value) => {value.search = value._links.search.href; return value;});
|
||||||
const facetValues = serializer.deserializeArray(values);
|
const facetValues = serializer.deserializeArray(values);
|
||||||
const valuesResponse = new FacetValueSuccessResponse(facetValues, data.statusCode, this.processPageInfo(data.payload.page));
|
const valuesResponse = new FacetValueSuccessResponse(facetValues, data.statusCode, this.processPageInfo(data.payload));
|
||||||
facetMap[facet.name] = valuesResponse;
|
facetMap[facet.name] = valuesResponse;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -30,9 +30,9 @@ export class FacetValueResponseParsingService extends BaseResponseParsingService
|
|||||||
const payload = data.payload;
|
const payload = data.payload;
|
||||||
|
|
||||||
const serializer = new DSpaceRESTv2Serializer(FacetValue);
|
const serializer = new DSpaceRESTv2Serializer(FacetValue);
|
||||||
const values = payload._embedded.values.map((value) => {value.search = value._links.search.href; return value;});
|
// const values = payload._embedded.values.map((value) => {value.search = value._links.search.href; return value;});
|
||||||
|
|
||||||
const facetValues = serializer.deserializeArray(values);
|
const facetValues = serializer.deserializeArray(payload._embedded.values);
|
||||||
return new FacetValueSuccessResponse(facetValues, data.statusCode, this.processPageInfo(data.payload.page));
|
return new FacetValueSuccessResponse(facetValues, data.statusCode, this.processPageInfo(data.payload));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,24 +1,23 @@
|
|||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { cold, getTestScheduler } from 'jasmine-marbles';
|
import { cold, getTestScheduler } from 'jasmine-marbles';
|
||||||
import { TestScheduler } from 'rxjs/Rx';
|
import { TestScheduler } from 'rxjs/Rx';
|
||||||
import { GlobalConfig } from '../../../config/global-config.interface';
|
|
||||||
import { BrowseService } from '../browse/browse.service';
|
import { BrowseService } from '../browse/browse.service';
|
||||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||||
import { ResponseCacheService } from '../cache/response-cache.service';
|
import { ResponseCacheService } from '../cache/response-cache.service';
|
||||||
import { CoreState } from '../core.reducers';
|
import { CoreState } from '../core.reducers';
|
||||||
import { ItemDataService } from './item-data.service';
|
import { ItemDataService } from './item-data.service';
|
||||||
import { RequestService } from './request.service';
|
import { RequestService } from './request.service';
|
||||||
|
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||||
|
|
||||||
describe('ItemDataService', () => {
|
describe('ItemDataService', () => {
|
||||||
let scheduler: TestScheduler;
|
let scheduler: TestScheduler;
|
||||||
let service: ItemDataService;
|
let service: ItemDataService;
|
||||||
let bs: BrowseService;
|
let bs: BrowseService;
|
||||||
|
|
||||||
const requestService = {} as RequestService;
|
const requestService = {} as RequestService;
|
||||||
const responseCache = {} as ResponseCacheService;
|
const responseCache = {} as ResponseCacheService;
|
||||||
const rdbService = {} as RemoteDataBuildService;
|
const rdbService = {} as RemoteDataBuildService;
|
||||||
const store = {} as Store<CoreState>;
|
const store = {} as Store<CoreState>;
|
||||||
const EnvConfig = {} as GlobalConfig;
|
const halEndpointService = {} as HALEndpointService;
|
||||||
|
|
||||||
const scopeID = '4af28e99-6a9c-4036-a199-e1b587046d39';
|
const scopeID = '4af28e99-6a9c-4036-a199-e1b587046d39';
|
||||||
const browsesEndpoint = 'https://rest.api/discover/browses';
|
const browsesEndpoint = 'https://rest.api/discover/browses';
|
||||||
@@ -42,8 +41,8 @@ describe('ItemDataService', () => {
|
|||||||
requestService,
|
requestService,
|
||||||
rdbService,
|
rdbService,
|
||||||
store,
|
store,
|
||||||
EnvConfig,
|
bs,
|
||||||
bs
|
halEndpointService
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,21 +73,5 @@ describe('ItemDataService', () => {
|
|||||||
expect(result).toBeObservable(expected);
|
expect(result).toBeObservable(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('if the scope is not specified', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
bs = initMockBrowseService(true);
|
|
||||||
service = initTestService();
|
|
||||||
spyOn(service, 'getEndpoint').and.returnValue(cold('--b-', { b: serviceEndpoint }))
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return this.getEndpoint()', () => {
|
|
||||||
const result = service.getScopedEndpoint(undefined);
|
|
||||||
const expected = cold('--c-', { c: serviceEndpoint });
|
|
||||||
|
|
||||||
expect(result).toBeObservable(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -45,10 +45,40 @@ export class PaginatedList<T> {
|
|||||||
return this.pageInfo.currentPage;
|
return this.pageInfo.currentPage;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set currentPage(value: number) {
|
set currentPage(value: number) {
|
||||||
this.pageInfo.currentPage = value;
|
this.pageInfo.currentPage = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get first(): string {
|
||||||
|
return this.pageInfo.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
set first(first: string) {
|
||||||
|
this.pageInfo.first = first;
|
||||||
|
}
|
||||||
|
|
||||||
|
get prev(): string {
|
||||||
|
return this.pageInfo.prev;
|
||||||
|
}
|
||||||
|
set prev(prev: string) {
|
||||||
|
this.pageInfo.prev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
get next(): string {
|
||||||
|
return this.pageInfo.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
set next(next: string) {
|
||||||
|
this.pageInfo.next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
get last(): string {
|
||||||
|
return this.pageInfo.last;
|
||||||
|
}
|
||||||
|
|
||||||
|
set last(last: string) {
|
||||||
|
this.pageInfo.last = last;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -56,6 +56,6 @@ export class SearchResponseParsingService implements ResponseParsingService {
|
|||||||
}));
|
}));
|
||||||
payload.objects = objects;
|
payload.objects = objects;
|
||||||
const deserialized = new DSpaceRESTv2Serializer(SearchQueryResponse).deserialize(payload);
|
const deserialized = new DSpaceRESTv2Serializer(SearchQueryResponse).deserialize(payload);
|
||||||
return new SearchSuccessResponse(deserialized, data.statusCode, this.dsoParser.processPageInfo(data.payload.page));
|
return new SearchSuccessResponse(deserialized, data.statusCode, this.dsoParser.processPageInfo(data.payload));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,7 @@ import { Item } from '../../core/shared/item.model';
|
|||||||
import { MockItem } from '../../shared/mocks/mock-item';
|
import { MockItem } from '../../shared/mocks/mock-item';
|
||||||
import { MockTranslateLoader } from '../../shared/mocks/mock-translate-loader';
|
import { MockTranslateLoader } from '../../shared/mocks/mock-translate-loader';
|
||||||
import { BrowseService } from '../browse/browse.service';
|
import { BrowseService } from '../browse/browse.service';
|
||||||
import { PageInfo } from '../shared/page-info.model';
|
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||||
|
|
||||||
/* tslint:disable:max-classes-per-file */
|
/* tslint:disable:max-classes-per-file */
|
||||||
@Component({
|
@Component({
|
||||||
@@ -114,6 +114,7 @@ describe('MetadataService', () => {
|
|||||||
{ provide: RequestService, useValue: requestService },
|
{ provide: RequestService, useValue: requestService },
|
||||||
{ provide: RemoteDataBuildService, useValue: remoteDataBuildService },
|
{ provide: RemoteDataBuildService, useValue: remoteDataBuildService },
|
||||||
{ provide: GLOBAL_CONFIG, useValue: ENV_CONFIG },
|
{ provide: GLOBAL_CONFIG, useValue: ENV_CONFIG },
|
||||||
|
{ provide: HALEndpointService, useValue: {}},
|
||||||
Meta,
|
Meta,
|
||||||
Title,
|
Title,
|
||||||
ItemDataService,
|
ItemDataService,
|
||||||
|
@@ -15,19 +15,7 @@ describe('HALEndpointService', () => {
|
|||||||
const endpointMap = {
|
const endpointMap = {
|
||||||
test: 'https://rest.api/test',
|
test: 'https://rest.api/test',
|
||||||
};
|
};
|
||||||
|
const linkPath = 'test';
|
||||||
/* tslint:disable:no-shadowed-variable */
|
|
||||||
class TestService extends HALEndpointService {
|
|
||||||
protected linkPath = 'test';
|
|
||||||
|
|
||||||
constructor(protected responseCache: ResponseCacheService,
|
|
||||||
protected requestService: RequestService,
|
|
||||||
protected EnvConfig: GlobalConfig) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* tslint:enable:no-shadowed-variable */
|
|
||||||
|
|
||||||
describe('getRootEndpointMap', () => {
|
describe('getRootEndpointMap', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -45,7 +33,7 @@ describe('HALEndpointService', () => {
|
|||||||
rest: { baseUrl: 'https://rest.api/' }
|
rest: { baseUrl: 'https://rest.api/' }
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
service = new TestService(
|
service = new HALEndpointService(
|
||||||
responseCache,
|
responseCache,
|
||||||
requestService,
|
requestService,
|
||||||
envConfig
|
envConfig
|
||||||
@@ -73,7 +61,7 @@ describe('HALEndpointService', () => {
|
|||||||
rest: { baseUrl: 'https://rest.api/' }
|
rest: { baseUrl: 'https://rest.api/' }
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
service = new TestService(
|
service = new HALEndpointService(
|
||||||
responseCache,
|
responseCache,
|
||||||
requestService,
|
requestService,
|
||||||
envConfig
|
envConfig
|
||||||
@@ -83,17 +71,16 @@ describe('HALEndpointService', () => {
|
|||||||
it('should return the endpoint URL for the service\'s linkPath', () => {
|
it('should return the endpoint URL for the service\'s linkPath', () => {
|
||||||
spyOn(service as any, 'getEndpointAt').and
|
spyOn(service as any, 'getEndpointAt').and
|
||||||
.returnValue(hot('a-', { a: 'https://rest.api/test' }));
|
.returnValue(hot('a-', { a: 'https://rest.api/test' }));
|
||||||
const result = service.getEndpoint();
|
const result = service.getEndpoint(linkPath);
|
||||||
|
|
||||||
const expected = cold('b-', { b: endpointMap.test });
|
const expected = cold('b-', { b: endpointMap.test });
|
||||||
expect(result).toBeObservable(expected);
|
expect(result).toBeObservable(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return undefined for a linkPath that isn\'t in the endpoint map', () => {
|
it('should return undefined for a linkPath that isn\'t in the endpoint map', () => {
|
||||||
(service as any).linkPath = 'unknown';
|
|
||||||
spyOn(service as any, 'getEndpointAt').and
|
spyOn(service as any, 'getEndpointAt').and
|
||||||
.returnValue(hot('a-', { a: undefined }));
|
.returnValue(hot('a-', { a: undefined }));
|
||||||
const result = service.getEndpoint();
|
const result = service.getEndpoint('unknown');
|
||||||
const expected = cold('b-', { b: undefined });
|
const expected = cold('b-', { b: undefined });
|
||||||
expect(result).toBeObservable(expected);
|
expect(result).toBeObservable(expected);
|
||||||
});
|
});
|
||||||
@@ -101,7 +88,7 @@ describe('HALEndpointService', () => {
|
|||||||
|
|
||||||
describe('isEnabledOnRestApi', () => {
|
describe('isEnabledOnRestApi', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
service = new TestService(
|
service = new HALEndpointService(
|
||||||
responseCache,
|
responseCache,
|
||||||
requestService,
|
requestService,
|
||||||
envConfig
|
envConfig
|
||||||
@@ -113,7 +100,7 @@ describe('HALEndpointService', () => {
|
|||||||
spyOn(service as any, 'getRootEndpointMap').and
|
spyOn(service as any, 'getRootEndpointMap').and
|
||||||
.returnValue(hot('----'));
|
.returnValue(hot('----'));
|
||||||
|
|
||||||
const result = service.isEnabledOnRestApi();
|
const result = service.isEnabledOnRestApi(linkPath);
|
||||||
const expected = cold('b---', { b: undefined });
|
const expected = cold('b---', { b: undefined });
|
||||||
expect(result).toBeObservable(expected);
|
expect(result).toBeObservable(expected);
|
||||||
});
|
});
|
||||||
@@ -121,8 +108,7 @@ describe('HALEndpointService', () => {
|
|||||||
it('should return true if the service\'s linkPath is in the endpoint map', () => {
|
it('should return true if the service\'s linkPath is in the endpoint map', () => {
|
||||||
spyOn(service as any, 'getRootEndpointMap').and
|
spyOn(service as any, 'getRootEndpointMap').and
|
||||||
.returnValue(hot('--a-', { a: endpointMap }));
|
.returnValue(hot('--a-', { a: endpointMap }));
|
||||||
|
const result = service.isEnabledOnRestApi(linkPath);
|
||||||
const result = service.isEnabledOnRestApi();
|
|
||||||
const expected = cold('b-c-', { b: undefined, c: true });
|
const expected = cold('b-c-', { b: undefined, c: true });
|
||||||
expect(result).toBeObservable(expected);
|
expect(result).toBeObservable(expected);
|
||||||
});
|
});
|
||||||
@@ -131,8 +117,7 @@ describe('HALEndpointService', () => {
|
|||||||
spyOn(service as any, 'getRootEndpointMap').and
|
spyOn(service as any, 'getRootEndpointMap').and
|
||||||
.returnValue(hot('--a-', { a: endpointMap }));
|
.returnValue(hot('--a-', { a: endpointMap }));
|
||||||
|
|
||||||
(service as any).linkPath = 'unknown';
|
const result = service.isEnabledOnRestApi('unknown');
|
||||||
const result = service.isEnabledOnRestApi();
|
|
||||||
const expected = cold('b-c-', { b: undefined, c: false });
|
const expected = cold('b-c-', { b: undefined, c: false });
|
||||||
expect(result).toBeObservable(expected);
|
expect(result).toBeObservable(expected);
|
||||||
});
|
});
|
||||||
|
@@ -14,12 +14,9 @@ import { GLOBAL_CONFIG } from '../../../config';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class HALEndpointService {
|
export class HALEndpointService {
|
||||||
|
|
||||||
protected linkPath: string;
|
|
||||||
|
|
||||||
constructor(private responseCache: ResponseCacheService,
|
constructor(private responseCache: ResponseCacheService,
|
||||||
private requestService: RequestService,
|
private requestService: RequestService,
|
||||||
@Inject(GLOBAL_CONFIG) private EnvConfig: GlobalConfig) {
|
@Inject(GLOBAL_CONFIG) private EnvConfig: GlobalConfig) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getRootHref(): string {
|
protected getRootHref(): string {
|
||||||
@@ -41,9 +38,7 @@ export class HALEndpointService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getEndpoint(linkPath: string): Observable<string> {
|
public getEndpoint(linkPath: string): Observable<string> {
|
||||||
const test = this.getEndpointAt(...linkPath.split('/'));
|
return this.getEndpointAt(...linkPath.split('/'));
|
||||||
// test.subscribe((test) => console.log(linkPath, test));
|
|
||||||
return test;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getEndpointAt(...path: string[]): Observable<string> {
|
private getEndpointAt(...path: string[]): Observable<string> {
|
||||||
|
@@ -28,4 +28,15 @@ export class PageInfo {
|
|||||||
@autoserializeAs(Number, 'number')
|
@autoserializeAs(Number, 'number')
|
||||||
currentPage: number;
|
currentPage: number;
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
last: string;
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
next: string;
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
prev: string;
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
first: string;
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
import { RequestService } from '../../core/data/request.service';
|
import { RequestService } from '../../core/data/request.service';
|
||||||
|
import { RequestEntry } from '../../core/data/request.reducer';
|
||||||
|
|
||||||
export function getMockRequestService(): RequestService {
|
export function getMockRequestService(): RequestService {
|
||||||
return jasmine.createSpyObj('requestService', {
|
return jasmine.createSpyObj('requestService', {
|
||||||
configure: () => false,
|
configure: () => false,
|
||||||
generateRequestId: () => 'clients/b186e8ce-e99c-4183-bc9a-42b4821bdb78'
|
generateRequestId: () => 'clients/b186e8ce-e99c-4183-bc9a-42b4821bdb78',
|
||||||
|
getByHref: (uuid: string) => new RequestEntry()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,12 @@
|
|||||||
import { ResponseCacheService } from '../../core/cache/response-cache.service';
|
import { ResponseCacheService } from '../../core/cache/response-cache.service';
|
||||||
|
import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer';
|
||||||
|
import { RestResponse } from '../../core/cache/response-cache.models';
|
||||||
|
|
||||||
export function getMockResponseCacheService(): ResponseCacheService {
|
export function getMockResponseCacheService(): ResponseCacheService {
|
||||||
return jasmine.createSpyObj('ResponseCacheService', [
|
return jasmine.createSpyObj('ResponseCacheService', {
|
||||||
'add',
|
add: (key: string, response: RestResponse, msToLive: number) => new ResponseCacheEntry(),
|
||||||
'get',
|
get: (key: string) => new ResponseCacheEntry(),
|
||||||
'has',
|
has: (key: string) => false,
|
||||||
]);
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -271,7 +271,7 @@ describe('Pagination component', () => {
|
|||||||
|
|
||||||
changePage(testFixture, 3);
|
changePage(testFixture, 3);
|
||||||
tick();
|
tick();
|
||||||
expect(routerStub.navigate).toHaveBeenCalledWith([], { queryParams: { pageId: 'test', page: 3, pageSize: 10, sortDirection: 'ASC', sortField: 'dc.title' } });
|
expect(routerStub.navigate).toHaveBeenCalledWith([], { queryParams: { pageId: 'test', page: 3, pageSize: 10, sortDirection: 'ASC', sortField: 'dc.title' }, queryParamsHandling: 'merge' });
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -282,7 +282,7 @@ describe('Pagination component', () => {
|
|||||||
|
|
||||||
changePageSize(testFixture, '20');
|
changePageSize(testFixture, '20');
|
||||||
tick();
|
tick();
|
||||||
expect(routerStub.navigate).toHaveBeenCalledWith([], { queryParams: { pageId: 'test', page: 1, pageSize: 20, sortDirection: 'ASC', sortField: 'dc.title' } });
|
expect(routerStub.navigate).toHaveBeenCalledWith([], { queryParams: { pageId: 'test', page: 1, pageSize: 20, sortDirection: 'ASC', sortField: 'dc.title' } , queryParamsHandling: 'merge' });
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should set correct values', fakeAsync(() => {
|
it('should set correct values', fakeAsync(() => {
|
||||||
|
@@ -338,7 +338,8 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
*/
|
*/
|
||||||
private updateRoute(params: {}) {
|
private updateRoute(params: {}) {
|
||||||
this.router.navigate([], {
|
this.router.navigate([], {
|
||||||
queryParams: Object.assign({}, this.currentQueryParams, params)
|
queryParams: Object.assign({}, this.currentQueryParams, params),
|
||||||
|
queryParamsHandling: 'merge'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -67,50 +67,36 @@ describe('RouteService', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('addQueryParameterValue', () => {
|
describe('getQueryParameterValues', () => {
|
||||||
it('should return a list of values that contains the added value when a new value is added and the parameter did not exist yet', () => {
|
it('should return a list of values when the parameter exists', () => {
|
||||||
service.resolveRouteWithParameterValue(nonExistingParamName, nonExistingParamValue).subscribe((params) => {
|
service.getQueryParameterValues(paramName2).subscribe((params) => {
|
||||||
expect(params[nonExistingParamName]).toContain(nonExistingParamValue);
|
expect(params).toEqual([paramValue2a, paramValue2b]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should return a list of values that contains the existing values and the added value when a new value is added and the parameter already has values', () => {
|
|
||||||
service.resolveRouteWithParameterValue(paramName1, nonExistingParamValue).subscribe((params) => {
|
it('should return an empty array when the parameter does not exists', () => {
|
||||||
const values = params[paramName1];
|
service.getQueryParameterValues(nonExistingParamName).subscribe((params) => {
|
||||||
expect(values).toContain(paramValue1);
|
expect(params).toEqual([]);
|
||||||
expect(values).toContain(nonExistingParamValue);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('removeQueryParameterValue', () => {
|
describe('getQueryParameterValue', () => {
|
||||||
it('should return a list of values that does not contain the removed value when the parameter value exists', () => {
|
it('should return a single value when the parameter exists', () => {
|
||||||
service.resolveRouteWithoutParameterValue(paramName2, paramValue2a).subscribe((params) => {
|
service.getQueryParameterValue(paramName1).subscribe((params) => {
|
||||||
const values = params[paramName2];
|
expect(params).toEqual(paramValue1);
|
||||||
expect(values).toContain(paramValue2b);
|
|
||||||
expect(values).not.toContain(paramValue2a);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a list of values that does contain all existing values when the removed parameter does not exist', () => {
|
it('should return only the first value when the parameter exists', () => {
|
||||||
service.resolveRouteWithoutParameterValue(paramName2, nonExistingParamValue).subscribe((params) => {
|
service.getQueryParameterValue(paramName2).subscribe((params) => {
|
||||||
const values = params[paramName2];
|
expect(params).toEqual(paramValue2a);
|
||||||
expect(values).toContain(paramValue2a);
|
|
||||||
expect(values).toContain(paramValue2b);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
describe('getWithoutParameter', () => {
|
it('should return undefined when the parameter exists', () => {
|
||||||
it('should return a list of values that does not contain any values for the parameter anymore when the parameter exists', () => {
|
service.getQueryParameterValue(nonExistingParamName).subscribe((params) => {
|
||||||
service.resolveRouteWithoutParameter(paramName2).subscribe((params) => {
|
expect(params).toBeNull();
|
||||||
const values = params[paramName2];
|
|
||||||
expect(values).toEqual({});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('should return a list of values that does not contain any values for the parameter when the parameter does not exist', () => {
|
|
||||||
service.resolveRouteWithoutParameter(nonExistingParamName).subscribe((params) => {
|
|
||||||
const values = params[nonExistingParamName];
|
|
||||||
expect(values).toEqual({});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<form #form="ngForm" (ngSubmit)="onSubmit(form.value)" class="row" action="/search">
|
<form #form="ngForm" (ngSubmit)="onSubmit(form.value)" class="row" action="/search">
|
||||||
<div *ngIf="isNotEmpty(scopes)" class="col-12 col-sm-3">
|
<div *ngIf="isNotEmpty(scopes)" class="col-12 col-sm-3">
|
||||||
<select [(ngModel)]="selectedId" name="scope" class="form-control" aria-label="Search scope" [compareWith]="byId">
|
<select [(ngModel)]="selectedId" name="scope" class="form-control" aria-label="Search scope">
|
||||||
<option value>{{'search.form.search_dspace' | translate}}</option>
|
<option value>{{'search.form.search_dspace' | translate}}</option>
|
||||||
<option *ngFor="let scopeOption of scopes" [value]="scopeOption.id">{{scopeOption?.name ? scopeOption.name : 'search.form.search_dspace' | translate}}</option>
|
<option *ngFor="let scopeOption of scopes" [value]="scopeOption.id">{{scopeOption?.name ? scopeOption.name : 'search.form.search_dspace' | translate}}</option>
|
||||||
</select>
|
</select>
|
||||||
|
@@ -69,7 +69,7 @@ describe('SearchFormComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const testCommunity = objects[1];
|
const testCommunity = objects[1];
|
||||||
comp.scope = testCommunity;
|
comp.scope = testCommunity.id;
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
tick();
|
tick();
|
||||||
|
@@ -22,10 +22,8 @@ export class SearchFormComponent {
|
|||||||
@Input() scopes: DSpaceObject[];
|
@Input() scopes: DSpaceObject[];
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set scope(dso: DSpaceObject) {
|
set scope(id: string) {
|
||||||
if (hasValue(dso)) {
|
this.selectedId = id;
|
||||||
this.selectedId = dso.id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private router: Router) {
|
constructor(private router: Router) {
|
||||||
@@ -52,11 +50,4 @@ export class SearchFormComponent {
|
|||||||
return isNotEmpty(object);
|
return isNotEmpty(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
byId(id1: string, id2: string) {
|
|
||||||
if (isEmpty(id1) && isEmpty(id2)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return id1 === id2;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
11
src/app/shared/testing/hal-endpoint-service-stub.ts
Normal file
11
src/app/shared/testing/hal-endpoint-service-stub.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { ViewMode } from '../../+search-page/search-options.model';
|
||||||
|
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||||
|
|
||||||
|
export class HALEndpointServiceStub {
|
||||||
|
|
||||||
|
constructor(private url: string) {};
|
||||||
|
getEndpoint(path: string) {
|
||||||
|
return Observable.of(this.url + '/' + path);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,10 @@
|
|||||||
|
|
||||||
export class RouterStub {
|
export class RouterStub {
|
||||||
|
url: string;
|
||||||
//noinspection TypeScriptUnresolvedFunction
|
//noinspection TypeScriptUnresolvedFunction
|
||||||
navigate = jasmine.createSpy('navigate');
|
navigate = jasmine.createSpy('navigate');
|
||||||
|
parseUrl = jasmine.createSpy('parseUrl');
|
||||||
|
navigateByUrl(url): void {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@ export class SearchServiceStub {
|
|||||||
|
|
||||||
viewMode = this.subject.asObservable();
|
viewMode = this.subject.asObservable();
|
||||||
|
|
||||||
constructor() {
|
constructor(private searchLink: string = '/search') {
|
||||||
this.setViewMode(ViewMode.List);
|
this.setViewMode(ViewMode.List);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +21,10 @@ export class SearchServiceStub {
|
|||||||
this.testViewMode = viewMode;
|
this.testViewMode = viewMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFacetValuesFor() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
get testViewMode(): ViewMode {
|
get testViewMode(): ViewMode {
|
||||||
return this._viewMode;
|
return this._viewMode;
|
||||||
}
|
}
|
||||||
@@ -29,4 +33,8 @@ export class SearchServiceStub {
|
|||||||
this._viewMode = viewMode;
|
this._viewMode = viewMode;
|
||||||
this.subject.next(viewMode);
|
this.subject.next(viewMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSearchLink() {
|
||||||
|
return this.searchLink;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user