mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-13 13:03:04 +00:00
added more documentation and cleaned everything up a bit
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
|
||||
import { FilterType } from '../../search-service/filter-type.model';
|
||||
|
||||
/**
|
||||
* Contains the mapping between a facet component and a FilterType
|
||||
*/
|
||||
const filterTypeMap = new Map();
|
||||
|
||||
/**
|
||||
* Sets the mapping for a component in relation to a filter type
|
||||
* Sets the mapping for a facet component in relation to a filter type
|
||||
* @param {FilterType} type The type for which the matching component is mapped
|
||||
* @returns Decorator function that performs the actual mapping on initialization of the component
|
||||
* @returns Decorator function that performs the actual mapping on initialization of the facet component
|
||||
*/
|
||||
export function renderFacetFor(type: FilterType) {
|
||||
return function decorator(objectElement: any) {
|
||||
@@ -18,9 +21,9 @@ export function renderFacetFor(type: FilterType) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the matching component based on a given filter type
|
||||
* @param {FilterType} type The filter type for which the component is requested
|
||||
* @returns The component's constructor that matches the given filter type
|
||||
* Requests the matching facet component based on a given filter type
|
||||
* @param {FilterType} type The filter type for which the facet component is requested
|
||||
* @returns The facet component's constructor that matches the given filter type
|
||||
*/
|
||||
export function renderFilterType(type: FilterType) {
|
||||
return filterTypeMap.get(type);
|
||||
|
@@ -26,6 +26,9 @@ const filterStateSelector = (state: SearchFiltersState) => state.searchFilter;
|
||||
|
||||
export const FILTER_CONFIG: InjectionToken<SearchFilterConfig> = new InjectionToken<SearchFilterConfig>('filterConfig');
|
||||
|
||||
/**
|
||||
* Service that performs all actions that have to do with search filters and facets
|
||||
*/
|
||||
@Injectable()
|
||||
export class SearchFilterService {
|
||||
|
||||
|
@@ -35,13 +35,30 @@ import { hasValue } from '../shared/empty.util';
|
||||
*/
|
||||
export class SearchPageComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* The current search results
|
||||
*/
|
||||
resultsRD$: Subject<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>> = new Subject();
|
||||
|
||||
/**
|
||||
* The current paginated search options
|
||||
*/
|
||||
searchOptions$: Observable<PaginatedSearchOptions>;
|
||||
sortConfig: SortOptions;
|
||||
|
||||
/**
|
||||
* The current relevant scopes
|
||||
*/
|
||||
scopeListRD$: Observable<DSpaceObject[]>;
|
||||
|
||||
/**
|
||||
* Emits true if were on a small screen
|
||||
*/
|
||||
isXsOrSm$: Observable<boolean>;
|
||||
pageSize;
|
||||
pageSizeOptions;
|
||||
|
||||
/**
|
||||
* Default values for the Search Options
|
||||
*/
|
||||
defaults = {
|
||||
pagination: {
|
||||
id: 'search-results-pagination',
|
||||
@@ -51,6 +68,10 @@ export class SearchPageComponent implements OnInit {
|
||||
query: '',
|
||||
scope: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* Subscription to unsubscribe from
|
||||
*/
|
||||
sub: Subscription;
|
||||
|
||||
constructor(private service: SearchService,
|
||||
@@ -93,7 +114,7 @@ export class SearchPageComponent implements OnInit {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the sidebar is correct
|
||||
* Check if the sidebar is collapsed
|
||||
* @returns {Observable<boolean>} emits true if the sidebar is currently collapsed, false if it is expanded
|
||||
*/
|
||||
public isSidebarCollapsed(): Observable<boolean> {
|
||||
@@ -107,6 +128,9 @@ export class SearchPageComponent implements OnInit {
|
||||
return this.service.getSearchLink();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from the subscription
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
if (hasValue(this.sub)) {
|
||||
this.sub.unsubscribe();
|
||||
|
@@ -2,19 +2,31 @@
|
||||
import { autoserialize, autoserializeAs } from 'cerialize';
|
||||
|
||||
/**
|
||||
*
|
||||
* The configuration for a search filter
|
||||
*/
|
||||
export class SearchFilterConfig {
|
||||
|
||||
/**
|
||||
* The name of this filter
|
||||
*/
|
||||
@autoserialize
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* The FilterType of this filter
|
||||
*/
|
||||
@autoserializeAs(String, 'facetType')
|
||||
type: FilterType;
|
||||
|
||||
/**
|
||||
* True if the filter has facets
|
||||
*/
|
||||
@autoserialize
|
||||
hasFacets: boolean;
|
||||
|
||||
/**
|
||||
* @type {number} The page size used for this facet
|
||||
*/
|
||||
@autoserializeAs(String, 'facetLimit')
|
||||
pageSize = 5;
|
||||
|
||||
@@ -35,6 +47,7 @@
|
||||
*/
|
||||
@autoserialize
|
||||
minValue: string;
|
||||
|
||||
/**
|
||||
* Name of this configuration that can be used in a url
|
||||
* @returns Parameter name
|
||||
|
@@ -2,46 +2,88 @@ import { autoserialize, autoserializeAs } from 'cerialize';
|
||||
import { PageInfo } from '../../core/shared/page-info.model';
|
||||
import { NormalizedSearchResult } from '../normalized-search-result.model';
|
||||
|
||||
/**
|
||||
* Class representing the response returned by the server when performing a search request
|
||||
*/
|
||||
export class SearchQueryResponse {
|
||||
/**
|
||||
* The scope used in the search request represented by the UUID of a DSpaceObject
|
||||
*/
|
||||
@autoserialize
|
||||
scope: string;
|
||||
|
||||
/**
|
||||
* The search query used in the search request
|
||||
*/
|
||||
@autoserialize
|
||||
query: string;
|
||||
|
||||
/**
|
||||
* The currently active filters used in the search request
|
||||
*/
|
||||
@autoserialize
|
||||
appliedFilters: any[]; // TODO
|
||||
|
||||
/**
|
||||
* The sort parameters used in the search request
|
||||
*/
|
||||
@autoserialize
|
||||
sort: any; // TODO
|
||||
|
||||
/**
|
||||
* The sort parameters used in the search request
|
||||
*/
|
||||
@autoserialize
|
||||
configurationName: string;
|
||||
|
||||
/**
|
||||
* The sort parameters used in the search request
|
||||
*/
|
||||
@autoserialize
|
||||
public type: string;
|
||||
|
||||
/**
|
||||
* Pagination configuration for this response
|
||||
*/
|
||||
@autoserialize
|
||||
page: PageInfo;
|
||||
|
||||
/**
|
||||
* The results for this query
|
||||
*/
|
||||
@autoserializeAs(NormalizedSearchResult)
|
||||
objects: NormalizedSearchResult[];
|
||||
|
||||
@autoserialize
|
||||
facets: any; // TODO
|
||||
|
||||
/**
|
||||
* The REST url to retrieve the current response
|
||||
*/
|
||||
@autoserialize
|
||||
self: string;
|
||||
|
||||
/**
|
||||
* The REST url to retrieve the next response
|
||||
*/
|
||||
@autoserialize
|
||||
next: string;
|
||||
|
||||
/**
|
||||
* The REST url to retrieve the previous response
|
||||
*/
|
||||
@autoserialize
|
||||
previous: string;
|
||||
|
||||
/**
|
||||
* The REST url to retrieve the first response
|
||||
*/
|
||||
@autoserialize
|
||||
first: string;
|
||||
|
||||
/**
|
||||
* The REST url to retrieve the last response
|
||||
*/
|
||||
@autoserialize
|
||||
last: string;
|
||||
}
|
||||
|
@@ -1,8 +1,16 @@
|
||||
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
||||
import { ListableObject } from '../../shared/object-collection/shared/listable-object.model';
|
||||
|
||||
/**
|
||||
* Contains the mapping between a search result component and a DSpaceObject
|
||||
*/
|
||||
const searchResultMap = new Map();
|
||||
|
||||
/**
|
||||
* Used to map Search Result components to their matching DSpaceObject
|
||||
* @param {GenericConstructor<ListableObject>} domainConstructor The constructor of the DSpaceObject
|
||||
* @returns Decorator function that performs the actual mapping on initialization of the component
|
||||
*/
|
||||
export function searchResultFor(domainConstructor: GenericConstructor<ListableObject>) {
|
||||
return function decorator(searchResult: any) {
|
||||
if (!searchResult) {
|
||||
@@ -12,6 +20,11 @@ export function searchResultFor(domainConstructor: GenericConstructor<ListableOb
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the matching component based on a given DSpaceObject's constructor
|
||||
* @param {GenericConstructor<ListableObject>} domainConstructor The DSpaceObject's constructor for which the search result component is requested
|
||||
* @returns The component's constructor that matches the given DSpaceObject
|
||||
*/
|
||||
export function getSearchResultFor(domainConstructor: GenericConstructor<ListableObject>) {
|
||||
return searchResultMap.get(domainConstructor);
|
||||
}
|
||||
|
@@ -45,16 +45,27 @@ import { CommunityDataService } from '../../core/data/community-data.service';
|
||||
import { CollectionDataService } from '../../core/data/collection-data.service';
|
||||
import { Collection } from '../../core/shared/collection.model';
|
||||
|
||||
|
||||
/**
|
||||
* Service that performs all general actions that have to do with the search page
|
||||
*/
|
||||
@Injectable()
|
||||
export class SearchService implements OnDestroy {
|
||||
/**
|
||||
* Endpoint link path for retrieving general search results
|
||||
*/
|
||||
private searchLinkPath = 'discover/search/objects';
|
||||
private facetValueLinkPathPrefix = 'discover/facets/';
|
||||
private facetConfigLinkPath = 'discover/facets';
|
||||
|
||||
/**
|
||||
* Endpoint link path for retrieving facet config incl values
|
||||
*/
|
||||
private facetLinkPathPrefix = 'discover/facets/';
|
||||
|
||||
/**
|
||||
* Subscription to unsubscribe from
|
||||
*/
|
||||
private sub;
|
||||
|
||||
searchOptions: SearchOptions;
|
||||
|
||||
constructor(private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
protected responseCache: ResponseCacheService,
|
||||
@@ -63,14 +74,13 @@ export class SearchService implements OnDestroy {
|
||||
private halService: HALEndpointService,
|
||||
private communityService: CommunityDataService,
|
||||
private collectionService: CollectionDataService) {
|
||||
const pagination: PaginationComponentOptions = new PaginationComponentOptions();
|
||||
pagination.id = 'search-results-pagination';
|
||||
pagination.currentPage = 1;
|
||||
pagination.pageSize = 10;
|
||||
const sort: SortOptions = new SortOptions('score', SortDirection.DESC);
|
||||
this.searchOptions = Object.assign(new SearchOptions(), { pagination: pagination, sort: sort });
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to retrieve a paginated list of search results from the server
|
||||
* @param {PaginatedSearchOptions} searchOptions The configuration necessary to perform this search
|
||||
* @returns {Observable<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>>} Emits a paginated list with all search results found
|
||||
*/
|
||||
search(searchOptions?: PaginatedSearchOptions): Observable<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>> {
|
||||
const requestObs = this.halService.getEndpoint(this.searchLinkPath).pipe(
|
||||
map((url: string) => {
|
||||
@@ -139,8 +149,13 @@ export class SearchService implements OnDestroy {
|
||||
return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the filter configuration for a given scope or the whole repository
|
||||
* @param {string} scope UUID of the object for which config the filter config is requested, when no scope is provided the configuration for the whole repository is loaded
|
||||
* @returns {Observable<RemoteData<SearchFilterConfig[]>>} The found filter configuration
|
||||
*/
|
||||
getConfig(scope?: string): Observable<RemoteData<SearchFilterConfig[]>> {
|
||||
const requestObs = this.halService.getEndpoint(this.facetConfigLinkPath).pipe(
|
||||
const requestObs = this.halService.getEndpoint(this.facetLinkPathPrefix).pipe(
|
||||
map((url: string) => {
|
||||
const args: string[] = [];
|
||||
|
||||
@@ -180,12 +195,19 @@ export class SearchService implements OnDestroy {
|
||||
return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, facetConfigObs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to request a single page of filter values for a given value
|
||||
* @param {SearchFilterConfig} filterConfig The filter config for which we want to request filter values
|
||||
* @param {number} valuePage The page number of the filter values
|
||||
* @param {SearchOptions} searchOptions The search configuration for the current search
|
||||
* @param {string} filterQuery The optional query used to filter out filter values
|
||||
* @returns {Observable<RemoteData<PaginatedList<FacetValue>>>} Emits the given page of facet values
|
||||
*/
|
||||
getFacetValuesFor(filterConfig: SearchFilterConfig, valuePage: number, searchOptions?: SearchOptions, filterQuery?: string): Observable<RemoteData<PaginatedList<FacetValue>>> {
|
||||
const requestObs = this.halService.getEndpoint(this.facetValueLinkPathPrefix + filterConfig.name).pipe(
|
||||
const requestObs = this.halService.getEndpoint(this.facetLinkPathPrefix + filterConfig.name).pipe(
|
||||
map((url: string) => {
|
||||
const args: string[] = [`page=${valuePage - 1}`, `size=${filterConfig.pageSize}`];
|
||||
if (hasValue(filterQuery)) {
|
||||
// args.push(`${filterConfig.paramName}=${filterQuery},query`);
|
||||
args.push(`prefix=${filterQuery}`);
|
||||
}
|
||||
if (hasValue(searchOptions)) {
|
||||
@@ -228,7 +250,12 @@ export class SearchService implements OnDestroy {
|
||||
return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs);
|
||||
}
|
||||
|
||||
getScopes(scopeId: string): Observable<DSpaceObject[]> {
|
||||
/**
|
||||
* Request a list of DSpaceObjects that can be used as a scope, based on the current scope
|
||||
* @param {string} scopeId UUID of the current scope, if the scope is empty, the repository wide scopes will be returned
|
||||
* @returns {Observable<DSpaceObject[]>} Emits a list of DSpaceObjects which represent possible scopes
|
||||
*/
|
||||
getScopes(scopeId?: string): Observable<DSpaceObject[]> {
|
||||
|
||||
if (hasNoValue(scopeId)) {
|
||||
const top: Observable<Community[]> = this.communityService.findTop({ elementsPerPage: 9999 }).pipe(
|
||||
@@ -260,6 +287,10 @@ export class SearchService implements OnDestroy {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the current view mode based on the current URL
|
||||
* @returns {Observable<ViewMode>} The current view mode
|
||||
*/
|
||||
getViewMode(): Observable<ViewMode> {
|
||||
return this.route.queryParams.map((params) => {
|
||||
if (isNotEmpty(params.view) && hasValue(params.view)) {
|
||||
@@ -270,6 +301,10 @@ export class SearchService implements OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the current view mode in the current URL
|
||||
* @param {ViewMode} viewMode Mode to switch to
|
||||
*/
|
||||
setViewMode(viewMode: ViewMode) {
|
||||
const navigationExtras: NavigationExtras = {
|
||||
queryParams: { view: viewMode },
|
||||
@@ -279,12 +314,18 @@ export class SearchService implements OnDestroy {
|
||||
this.router.navigate([this.getSearchLink()], navigationExtras);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string} The base path to the search page
|
||||
*/
|
||||
getSearchLink(): string {
|
||||
const urlTree = this.router.parseUrl(this.router.url);
|
||||
const g: UrlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET];
|
||||
return '/' + g.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from the subscription
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
if (this.sub !== undefined) {
|
||||
this.sub.unsubscribe();
|
||||
|
@@ -1,22 +1,24 @@
|
||||
<h3>{{ 'search.sidebar.settings.title' | translate}}</h3>
|
||||
<div *ngIf="[searchOptions].sort" class="setting-option result-order-settings mb-3 p-3">
|
||||
<ng-container *ngVar="(searchOptions$ | async) as config">
|
||||
<h3>{{ 'search.sidebar.settings.title' | translate}}</h3>
|
||||
<div *ngIf="config?.sort" class="setting-option result-order-settings mb-3 p-3">
|
||||
<h5>{{ 'search.sidebar.settings.sort-by' | translate}}</h5>
|
||||
<select class="form-control" (change)="reloadOrder($event)">
|
||||
<option *ngFor="let sortOption of searchOptionPossibilities"
|
||||
[value]="sortOption.field + ',' + sortOption.direction.toString()"
|
||||
[selected]="sortOption.field === field && sortOption.direction === direction? 'selected': null">
|
||||
[selected]="sortOption.field === config?.sort.field && sortOption.direction === (config?.sort.direction)? 'selected': null">
|
||||
{{'sorting.' + sortOption.field + '.' + sortOption.direction | translate}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="setting-option page-size-settings mb-3 p-3">
|
||||
<div class="setting-option page-size-settings mb-3 p-3">
|
||||
<h5>{{ 'search.sidebar.settings.rpp' | translate}}</h5>
|
||||
|
||||
<select class="form-control" (change)="reloadRPP($event)">
|
||||
<option *ngFor="let pageSizeOption of pageSizeOptions" [value]="pageSizeOption"
|
||||
[selected]="pageSizeOption === pageSize ? 'selected': null">
|
||||
<option *ngFor="let pageSizeOption of config?.pagination.pageSizeOptions"
|
||||
[value]="pageSizeOption"
|
||||
[selected]="pageSizeOption === +config?.pagination.pageSize ? 'selected': null">
|
||||
{{pageSizeOption}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
@@ -1,34 +1,35 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { SearchService } from '../search-service/search.service';
|
||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
|
||||
import { PaginatedSearchOptions } from '../paginated-search-options.model';
|
||||
import { SearchFilterService } from '../search-filters/search-filter/search-filter.service';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-settings',
|
||||
styleUrls: ['./search-settings.component.scss'],
|
||||
templateUrl: './search-settings.component.html'
|
||||
})
|
||||
|
||||
/**
|
||||
* This component represents the part of the search sidebar that contains the general search settings.
|
||||
*/
|
||||
export class SearchSettingsComponent implements OnInit {
|
||||
|
||||
@Input() searchOptions: PaginatedSearchOptions;
|
||||
/**
|
||||
* Declare SortDirection enumeration to use it in the template
|
||||
* The configuration for the current paginated search results
|
||||
*/
|
||||
public sortDirections = SortDirection;
|
||||
/**
|
||||
* Number of items per page.
|
||||
*/
|
||||
public pageSize;
|
||||
@Input() public pageSizeOptions;
|
||||
searchOptions$: Observable<PaginatedSearchOptions>;
|
||||
|
||||
query: string;
|
||||
page: number;
|
||||
direction: SortDirection;
|
||||
field: string;
|
||||
currentParams = {};
|
||||
/**
|
||||
* All sort options that are shown in the settings
|
||||
*/
|
||||
searchOptionPossibilities = [new SortOptions('score', SortDirection.DESC), new SortOptions('dc.title', SortDirection.ASC), new SortOptions('dc.title', SortDirection.DESC)];
|
||||
|
||||
/**
|
||||
* Default values for the Search Options
|
||||
*/
|
||||
defaults = {
|
||||
pagination: {
|
||||
id: 'search-results-pagination',
|
||||
@@ -38,22 +39,24 @@ export class SearchSettingsComponent implements OnInit {
|
||||
query: '',
|
||||
scope: ''
|
||||
};
|
||||
|
||||
constructor(private service: SearchService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private filterService: SearchFilterService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize paginated search options
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.filterService.getPaginatedSearchOptions(this.defaults).subscribe((options) => {
|
||||
this.direction = options.sort.direction;
|
||||
this.field = options.sort.field;
|
||||
this.searchOptions = options;
|
||||
this.pageSize = options.pagination.pageSize;
|
||||
this.pageSizeOptions = options.pagination.pageSizeOptions
|
||||
})
|
||||
this.searchOptions$ = this.filterService.getPaginatedSearchOptions(this.defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the current page size (results per page)
|
||||
* @param {Event} event Change event containing the new page size value
|
||||
*/
|
||||
reloadRPP(event: Event) {
|
||||
const value = (event.target as HTMLInputElement).value;
|
||||
const navigationExtras: NavigationExtras = {
|
||||
@@ -65,6 +68,10 @@ export class SearchSettingsComponent implements OnInit {
|
||||
this.router.navigate([ '/search' ], navigationExtras);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the current sort field and direction
|
||||
* @param {Event} event Change event containing the sort direction and sort field
|
||||
*/
|
||||
reloadOrder(event: Event) {
|
||||
const values = (event.target as HTMLInputElement).value.split(',');
|
||||
const navigationExtras: NavigationExtras = {
|
||||
|
@@ -17,14 +17,23 @@ export const SearchSidebarActionTypes = {
|
||||
};
|
||||
|
||||
/* tslint:disable:max-classes-per-file */
|
||||
/**
|
||||
* Used to collapse the sidebar
|
||||
*/
|
||||
export class SearchSidebarCollapseAction implements Action {
|
||||
type = SearchSidebarActionTypes.COLLAPSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to expand the sidebar
|
||||
*/
|
||||
export class SearchSidebarExpandAction implements Action {
|
||||
type = SearchSidebarActionTypes.EXPAND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to collapse the sidebar when it's expanded and expand it when it's collapsed
|
||||
*/
|
||||
export class SearchSidebarToggleAction implements Action {
|
||||
type = SearchSidebarActionTypes.TOGGLE;
|
||||
}
|
||||
|
@@ -12,7 +12,18 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
templateUrl: './search-sidebar.component.html',
|
||||
})
|
||||
|
||||
/**
|
||||
* Component representing the sidebar on the search page
|
||||
*/
|
||||
export class SearchSidebarComponent {
|
||||
|
||||
/**
|
||||
* The total amount of result
|
||||
*/
|
||||
@Input() resultCount;
|
||||
|
||||
/**
|
||||
* Emits event when the user clicks a button to open or close the sidebar
|
||||
*/
|
||||
@Output() toggleSidebar = new EventEmitter<boolean>();
|
||||
}
|
||||
|
@@ -5,6 +5,9 @@ import * as fromRouter from '@ngrx/router-store';
|
||||
import { SearchSidebarCollapseAction } from './search-sidebar.actions';
|
||||
import { URLBaser } from '../../core/url-baser/url-baser';
|
||||
|
||||
/**
|
||||
* Makes sure that if the user navigates to another route, the sidebar is collapsed
|
||||
*/
|
||||
@Injectable()
|
||||
export class SearchSidebarEffects {
|
||||
private previousPath: string;
|
||||
|
@@ -1,5 +1,8 @@
|
||||
import { SearchSidebarAction, SearchSidebarActionTypes } from './search-sidebar.actions';
|
||||
|
||||
/**
|
||||
* Interface that represents the state of the sidebar
|
||||
*/
|
||||
export interface SearchSidebarState {
|
||||
sidebarCollapsed: boolean;
|
||||
}
|
||||
@@ -8,6 +11,12 @@ const initialState: SearchSidebarState = {
|
||||
sidebarCollapsed: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs a search sidebar action on the current state
|
||||
* @param {SearchSidebarState} state The state before the action is performed
|
||||
* @param {SearchSidebarAction} action The action that should be performed
|
||||
* @returns {SearchSidebarState} The state after the action is performed
|
||||
*/
|
||||
export function sidebarReducer(state = initialState, action: SearchSidebarAction): SearchSidebarState {
|
||||
switch (action.type) {
|
||||
|
||||
|
@@ -9,27 +9,47 @@ import { HostWindowService } from '../../shared/host-window.service';
|
||||
const sidebarStateSelector = (state: AppState) => state.searchSidebar;
|
||||
const sidebarCollapsedSelector = createSelector(sidebarStateSelector, (sidebar: SearchSidebarState) => sidebar.sidebarCollapsed);
|
||||
|
||||
/**
|
||||
* Service that performs all actions that have to do with the search sidebar
|
||||
*/
|
||||
@Injectable()
|
||||
export class SearchSidebarService {
|
||||
/**
|
||||
* Emits true is the current screen size is mobile
|
||||
*/
|
||||
private isXsOrSm$: Observable<boolean>;
|
||||
private isCollapsdeInStored: Observable<boolean>;
|
||||
|
||||
/**
|
||||
* Emits true is the sidebar's state in the store is currently collapsed
|
||||
*/
|
||||
private isCollapsedInStore: Observable<boolean>;
|
||||
|
||||
constructor(private store: Store<AppState>, private windowService: HostWindowService) {
|
||||
this.isXsOrSm$ = this.windowService.isXsOrSm();
|
||||
this.isCollapsdeInStored = this.store.select(sidebarCollapsedSelector);
|
||||
this.isCollapsedInStore = this.store.select(sidebarCollapsedSelector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the sidebar should currently be collapsed
|
||||
* @returns {Observable<boolean>} Emits true if our screen size is mobile or when the state in the store is currently collapsed
|
||||
*/
|
||||
get isCollapsed(): Observable<boolean> {
|
||||
return Observable.combineLatest(
|
||||
this.isXsOrSm$,
|
||||
this.isCollapsdeInStored,
|
||||
this.isCollapsedInStore,
|
||||
(mobile, store) => mobile ? store : true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a collapse action to the store
|
||||
*/
|
||||
public collapse(): void {
|
||||
this.store.dispatch(new SearchSidebarCollapseAction());
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a expand action to the store
|
||||
*/
|
||||
public expand(): void {
|
||||
this.store.dispatch(new SearchSidebarExpandAction());
|
||||
}
|
||||
|
4
src/app/core/cache/response-cache.models.ts
vendored
4
src/app/core/cache/response-cache.models.ts
vendored
@@ -1,8 +1,6 @@
|
||||
import { SearchQueryResponse } from '../../+search-page/search-service/search-query-response.model';
|
||||
import { RequestError } from '../data/request.models';
|
||||
import { BrowseEntry } from '../shared/browse-entry.model';
|
||||
import { PageInfo } from '../shared/page-info.model';
|
||||
import { BrowseDefinition } from '../shared/browse-definition.model';
|
||||
import { ConfigObject } from '../shared/config/config.model';
|
||||
import { FacetValue } from '../../+search-page/search-service/facet-value.model';
|
||||
import { SearchFilterConfig } from '../../+search-page/search-service/search-filter-config.model';
|
||||
@@ -10,8 +8,6 @@ import { RegistryMetadataschemasResponse } from '../registry/registry-metadatasc
|
||||
import { MetadataSchema } from '../metadata/metadataschema.model';
|
||||
import { RegistryMetadatafieldsResponse } from '../registry/registry-metadatafields-response.model';
|
||||
import { RegistryBitstreamformatsResponse } from '../registry/registry-bitstreamformats-response.model';
|
||||
import { AuthTokenInfo } from '../auth/models/auth-token-info.model';
|
||||
import { NormalizedAuthStatus } from '../auth/models/normalized-auth-status.model';
|
||||
import { AuthStatus } from '../auth/models/auth-status.model';
|
||||
|
||||
/* tslint:disable:max-classes-per-file */
|
||||
|
Reference in New Issue
Block a user