mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-17 15:03:07 +00:00
45621: ngrx filter facets
This commit is contained in:
@@ -96,14 +96,18 @@
|
||||
"reset": "Reset filters",
|
||||
"facet-filter": {
|
||||
"show-more": "Show more",
|
||||
"show-less": "Show less",
|
||||
"author": {
|
||||
"placeholder": "Author name"
|
||||
"placeholder": "Author name",
|
||||
"head": "Author"
|
||||
},
|
||||
"scope": {
|
||||
"placeholder": "Scope filter"
|
||||
"placeholder": "Scope filter",
|
||||
"head": "Scope"
|
||||
},
|
||||
"subject": {
|
||||
"placeholder": "Subject"
|
||||
"placeholder": "Subject",
|
||||
"head": "Subject"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,15 @@
|
||||
<a *ngFor="let value of filterValues" class="d-block" [routerLink]="[getSearchLink()]" [queryParams]="getQueryParams(value) | async">
|
||||
<input type="checkbox" [checked]="isChecked(value)"/>
|
||||
<span class="filter-value">{{value.value}}</span>
|
||||
<span class="filter-value-count float-right">({{value.count}})</span>
|
||||
<a *ngFor="let value of filterValues; let i=index" class="d-block" [routerLink]="[getSearchLink()]"
|
||||
[queryParams]="getQueryParams(value)">
|
||||
<ng-template [ngIf]="i < (facetCount | async)">
|
||||
<input type="checkbox" [checked]="isChecked(value)"/>
|
||||
<span class="filter-value">{{value.value}}</span>
|
||||
<span class="filter-value-count float-right">({{value.count}})</span>
|
||||
</ng-template>
|
||||
</a>
|
||||
<a href="">{{"search.filters.facet-filter.show-more" | translate}}</a>
|
||||
<a *ngIf="filterValues.length > (facetCount | async)" (click)="showMore()">{{"search.filters.facet-filter.show-more"
|
||||
| translate}}</a>
|
||||
<a *ngIf="(currentPage | async) > 1" (click)="showLess()">{{"search.filters.facet-filter.show-less" |
|
||||
translate}}</a>
|
||||
|
||||
<input type="text" [placeholder]="'search.filters.facet-filter.' + filterConfig.name + '.placeholder'| translate"/>
|
||||
<input type="text"
|
||||
[placeholder]="'search.filters.facet-filter.' + filterConfig.name + '.placeholder'| translate"/>
|
@@ -1,9 +1,10 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { FacetValue } from '../../../search-service/facet-value.model';
|
||||
import { SearchFilterConfig } from '../../../search-service/search-filter-config.model';
|
||||
import { SearchService } from '../../../search-service/search.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Params } from '@angular/router';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { SearchFilterService } from '../search-filter.service';
|
||||
|
||||
/**
|
||||
* This component renders a simple item page.
|
||||
@@ -17,25 +18,48 @@ import { Observable } from 'rxjs/Observable';
|
||||
templateUrl: './search-facet-filter.component.html',
|
||||
})
|
||||
|
||||
export class SidebarFacetFilterComponent {
|
||||
export class SidebarFacetFilterComponent implements OnInit {
|
||||
@Input() filterValues: FacetValue[];
|
||||
@Input() filterConfig: SearchFilterConfig;
|
||||
currentPage: Observable<number>;
|
||||
|
||||
constructor(private searchService: SearchService, private route: ActivatedRoute) {
|
||||
constructor(private filterService: SearchFilterService) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.currentPage = this.filterService.getPage(this.filterConfig.name);
|
||||
}
|
||||
|
||||
isChecked(value: FacetValue) {
|
||||
return this.searchService.isFilterActive(this.filterConfig.name, value.value);
|
||||
return this.filterService.isFilterActive(this.filterConfig.name, value.value);
|
||||
}
|
||||
|
||||
getSearchLink() {
|
||||
return this.searchService.getSearchLink();
|
||||
return this.filterService.searchLink;
|
||||
}
|
||||
|
||||
getQueryParams(value: FacetValue): Observable<any> {
|
||||
const params = {};
|
||||
params[this.filterConfig.paramName] = value.value;
|
||||
return this.route.queryParams.map((p) => Object.assign({}, p, params))
|
||||
getQueryParams(value: FacetValue): Params {
|
||||
return this.filterService.switchFilterInURL(this.filterConfig, value.value);
|
||||
}
|
||||
|
||||
get facetCount(): Observable<number> {
|
||||
const resultCount = this.filterValues.length;
|
||||
return this.currentPage.map((page: number) => {
|
||||
const max = page * this.filterConfig.pageSize;
|
||||
return max > resultCount ? resultCount : max;
|
||||
});
|
||||
}
|
||||
|
||||
showMore() {
|
||||
this.filterService.increasePage(this.filterConfig.name);
|
||||
}
|
||||
|
||||
showLess() {
|
||||
this.filterService.decreasePage(this.filterConfig.name);
|
||||
}
|
||||
|
||||
getCurrentPage(): Observable<number> {
|
||||
return this.filterService.getPage(this.filterConfig.name);
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,58 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
|
||||
import { type } from '../../../shared/ngrx/type';
|
||||
|
||||
/**
|
||||
* For each action type in an action group, make a simple
|
||||
* enum object for all of this group's action types.
|
||||
*
|
||||
* The 'type' utility function coerces strings into string
|
||||
* literal types and runs a simple check to guarantee all
|
||||
* action types in the application are unique.
|
||||
*/
|
||||
export const SearchFilterActionTypes = {
|
||||
COLLAPSE: type('dspace/search-filter/COLLAPSE'),
|
||||
INITIAL_COLLAPSE: type('dspace/search-filter/INITIAL_COLLAPSE'),
|
||||
EXPAND: type('dspace/search-filter/EXPAND'),
|
||||
INITIAL_EXPAND: type('dspace/search-filter/INITIAL_EXPAND'),
|
||||
TOGGLE: type('dspace/search-filter/TOGGLE'),
|
||||
DECREASE_PAGE: type('dspace/search-filter/DECREASE_PAGE'),
|
||||
INCREASE_PAGE: type('dspace/search-filter/INCREASE_PAGE')
|
||||
};
|
||||
|
||||
export class SearchFilterAction implements Action {
|
||||
filterName: string;
|
||||
type;
|
||||
constructor(name: string) {
|
||||
this.filterName = name;
|
||||
}
|
||||
}
|
||||
|
||||
/* tslint:disable:max-classes-per-file */
|
||||
export class SearchFilterCollapseAction extends SearchFilterAction {
|
||||
type = SearchFilterActionTypes.COLLAPSE;
|
||||
}
|
||||
|
||||
export class SearchFilterExpandAction extends SearchFilterAction {
|
||||
type = SearchFilterActionTypes.EXPAND;
|
||||
}
|
||||
|
||||
export class SearchFilterToggleAction extends SearchFilterAction {
|
||||
type = SearchFilterActionTypes.TOGGLE;
|
||||
}
|
||||
|
||||
export class SearchFilterInitialCollapseAction extends SearchFilterAction {
|
||||
type = SearchFilterActionTypes.INITIAL_COLLAPSE;
|
||||
}
|
||||
|
||||
export class SearchFilterInitialExpandAction extends SearchFilterAction {
|
||||
type = SearchFilterActionTypes.INITIAL_EXPAND;
|
||||
}
|
||||
export class SearchFilterDecreasePageAction extends SearchFilterAction {
|
||||
type = SearchFilterActionTypes.DECREASE_PAGE;
|
||||
}
|
||||
|
||||
export class SearchFilterIncreasePageAction extends SearchFilterAction {
|
||||
type = SearchFilterActionTypes.INCREASE_PAGE;
|
||||
}
|
||||
/* tslint:enable:max-classes-per-file */
|
@@ -1,4 +1,8 @@
|
||||
<div>
|
||||
<div (click)="toggle()" class="filter-name">{{filter.name}} <span class="fa float-right" [ngClass]="isCollapsed ? 'fa-plus' : 'fa-minus'"></span></div>
|
||||
<ds-search-facet-filter [filterConfig]="filter" [filterValues]="filterValues.payload | async"></ds-search-facet-filter>
|
||||
<div (click)="toggle()" class="filter-name">{{filter.name}} <span class="fa float-right"
|
||||
[ngClass]="(isCollapsed() | async) ? 'fa-plus' : 'fa-minus'"></span></div>
|
||||
<div [@slide]="(isCollapsed() | async) ? 'collapsed' : 'expanded'" class="search-filter-wrapper">
|
||||
<ds-search-facet-filter [filterConfig]="filter"
|
||||
[filterValues]="filterValues.payload | async"></ds-search-facet-filter>
|
||||
</div>
|
||||
</div>
|
@@ -1,2 +1,6 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.search-filter-wrapper {
|
||||
overflow: hidden;
|
||||
}
|
@@ -3,6 +3,9 @@ import { SearchFilterConfig } from '../../search-service/search-filter-config.mo
|
||||
import { SearchService } from '../../search-service/search.service';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { FacetValue } from '../../search-service/facet-value.model';
|
||||
import { SearchFilterService } from './search-filter.service';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { slide } from '../../../shared/animations/slide';
|
||||
|
||||
/**
|
||||
* This component renders a simple item page.
|
||||
@@ -14,21 +17,38 @@ import { FacetValue } from '../../search-service/facet-value.model';
|
||||
selector: 'ds-search-filter',
|
||||
styleUrls: ['./search-filter.component.scss'],
|
||||
templateUrl: './search-filter.component.html',
|
||||
animations: [slide]
|
||||
})
|
||||
|
||||
export class SidebarFilterComponent implements OnInit {
|
||||
@Input() filter: SearchFilterConfig;
|
||||
filterValues: RemoteData<FacetValue[]>;
|
||||
isCollapsed = false;
|
||||
|
||||
constructor(private searchService: SearchService) {
|
||||
constructor(private searchService: SearchService, private filterService: SearchFilterService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.filterValues = this.searchService.getFacetValuesFor(this.filter.name);
|
||||
if (this.filter.isOpenByDefault) {
|
||||
this.initialExpand();
|
||||
} else {
|
||||
this.initialCollapse();
|
||||
}
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.isCollapsed = !this.isCollapsed;
|
||||
this.filterService.toggle(this.filter.name);
|
||||
}
|
||||
|
||||
isCollapsed(): Observable<boolean> {
|
||||
return this.filterService.isCollapsed(this.filter.name);
|
||||
}
|
||||
|
||||
initialCollapse() {
|
||||
this.filterService.initialCollapse(this.filter.name);
|
||||
}
|
||||
|
||||
initialExpand() {
|
||||
this.filterService.initialExpand(this.filter.name);
|
||||
}
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
import { SearchFilterAction, SearchFilterActionTypes } from './search-filter.actions';
|
||||
import { isEmpty } from '../../../shared/empty.util';
|
||||
|
||||
export interface SearchFilterState {
|
||||
filterCollapsed: boolean,
|
||||
page: number
|
||||
}
|
||||
|
||||
export interface SearchFiltersState {
|
||||
[name: string]: SearchFilterState
|
||||
}
|
||||
|
||||
const initialState: SearchFiltersState = Object.create(null);
|
||||
|
||||
export function filterReducer(state = initialState, action: SearchFilterAction): SearchFiltersState {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
case SearchFilterActionTypes.INITIAL_COLLAPSE: {
|
||||
if (isEmpty(state) || isEmpty(state[action.filterName])) {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: true,
|
||||
page: 1
|
||||
}
|
||||
});
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
case SearchFilterActionTypes.INITIAL_EXPAND: {
|
||||
if (isEmpty(state) || isEmpty(state[action.filterName])) {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: false,
|
||||
page: 1
|
||||
}
|
||||
});
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
case SearchFilterActionTypes.COLLAPSE: {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: true,
|
||||
page: state[action.filterName].page
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
case SearchFilterActionTypes.EXPAND: {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: false,
|
||||
page: state[action.filterName].page
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
case SearchFilterActionTypes.DECREASE_PAGE: {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: state[action.filterName].filterCollapsed,
|
||||
page: state[action.filterName].page - 1
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
case SearchFilterActionTypes.INCREASE_PAGE: {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: state[action.filterName].filterCollapsed,
|
||||
page: state[action.filterName].page + 1
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
case SearchFilterActionTypes.TOGGLE: {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: !state[action.filterName].filterCollapsed,
|
||||
page: state[action.filterName].page
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,136 @@
|
||||
import { Injectable, OnDestroy } from '@angular/core';
|
||||
import { SearchFiltersState, SearchFilterState } from './search-filter.reducer';
|
||||
import { createSelector, MemoizedSelector, Store } from '@ngrx/store';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { AppState } from '../../../app.reducer';
|
||||
import {
|
||||
SearchFilterCollapseAction, SearchFilterDecreasePageAction, SearchFilterIncreasePageAction,
|
||||
SearchFilterInitialCollapseAction,
|
||||
SearchFilterInitialExpandAction,
|
||||
SearchFilterToggleAction
|
||||
} from './search-filter.actions';
|
||||
import { hasValue, isNotEmpty } from '../../../shared/empty.util';
|
||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||
import { SearchFilterConfig } from '../../search-service/search-filter-config.model';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { PageInfo } from '../../../core/shared/page-info.model';
|
||||
import { FacetValue } from '../../search-service/facet-value.model';
|
||||
import { FilterType } from '../../search-service/filter-type.model';
|
||||
import { SearchService } from '../../search-service/search.service';
|
||||
|
||||
const filterStateSelector = (state: SearchFiltersState) => state.searchFilter;
|
||||
|
||||
@Injectable()
|
||||
export class SearchFilterService implements OnDestroy {
|
||||
private sub;
|
||||
|
||||
constructor(private store: Store<SearchFiltersState>,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private searchService: SearchService) {
|
||||
}
|
||||
|
||||
isFilterActive(filterName: string, filterValue: string): boolean {
|
||||
let filterConfig: SearchFilterConfig;
|
||||
this.sub = this.searchService.getConfig().payload
|
||||
.subscribe((configuration) => filterConfig = configuration
|
||||
.find((config: SearchFilterConfig) => config.name === filterName));
|
||||
return isNotEmpty(this.route.snapshot.queryParams[filterConfig.paramName]) && [...this.route.snapshot.queryParams[filterConfig.paramName]].indexOf(filterValue, 0) > -1;
|
||||
}
|
||||
|
||||
switchFilterInURL(filterConfig: SearchFilterConfig, value: string) {
|
||||
console.log(this.route.snapshot.queryParams);
|
||||
if (this.isFilterActive(filterConfig.name, value)) {
|
||||
return this.removeQueryParameter(filterConfig.paramName, value);
|
||||
} else {
|
||||
return this.addQueryParameter(filterConfig.paramName, value);
|
||||
}
|
||||
}
|
||||
|
||||
addQueryParameter(paramName: string, value: string): Params {
|
||||
const currentParams = this.route.snapshot.queryParams;
|
||||
const newParam = {};
|
||||
if ((currentParams[paramName])) {
|
||||
newParam[paramName] = [...currentParams[paramName], value];
|
||||
} else {
|
||||
newParam[paramName] = [value];
|
||||
}
|
||||
return Object.assign({}, currentParams, newParam);
|
||||
}
|
||||
|
||||
removeQueryParameter(paramName: string, value: string): Params {
|
||||
const currentParams = this.route.snapshot.queryParams;
|
||||
const newParam = {};
|
||||
let currentFilterParams = [...currentParams[paramName]];
|
||||
if (isNotEmpty(currentFilterParams)) {
|
||||
const index = currentFilterParams.indexOf(value, 0);
|
||||
if (index > -1) {
|
||||
currentFilterParams = currentFilterParams.splice(index, 1);
|
||||
}
|
||||
newParam[paramName] = currentFilterParams;
|
||||
}
|
||||
return Object.assign({}, currentParams, newParam);
|
||||
}
|
||||
|
||||
get searchLink() {
|
||||
return this.searchService.searchLink;
|
||||
}
|
||||
|
||||
isCollapsed(filterName: string): Observable<boolean> {
|
||||
return this.store.select(filterByNameSelector(filterName))
|
||||
.map((object: SearchFilterState) => object.filterCollapsed);
|
||||
}
|
||||
|
||||
getPage(filterName: string): Observable<number> {
|
||||
return this.store.select(filterByNameSelector(filterName))
|
||||
.map((object: SearchFilterState) => object.page);
|
||||
}
|
||||
|
||||
public collapse(filterName: string): void {
|
||||
this.store.dispatch(new SearchFilterCollapseAction(filterName));
|
||||
}
|
||||
|
||||
public expand(filterName: string): void {
|
||||
this.store.dispatch(new SearchFilterCollapseAction(filterName));
|
||||
}
|
||||
|
||||
public toggle(filterName: string): void {
|
||||
this.store.dispatch(new SearchFilterToggleAction(filterName));
|
||||
}
|
||||
|
||||
public initialCollapse(filterName: string): void {
|
||||
this.store.dispatch(new SearchFilterInitialCollapseAction(filterName));
|
||||
}
|
||||
|
||||
public initialExpand(filterName: string): void {
|
||||
this.store.dispatch(new SearchFilterInitialExpandAction(filterName));
|
||||
}
|
||||
|
||||
public decreasePage(filterName: string): void {
|
||||
this.store.dispatch(new SearchFilterDecreasePageAction(filterName));
|
||||
}
|
||||
|
||||
public increasePage(filterName: string): void {
|
||||
this.store.dispatch(new SearchFilterIncreasePageAction(filterName));
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.sub !== undefined) {
|
||||
this.sub.unsubscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function filterByNameSelector(name: string): MemoizedSelector<SearchFiltersState, SearchFilterState> {
|
||||
return keySelector<SearchFilterState>(name);
|
||||
}
|
||||
|
||||
export function keySelector<T>(key: string): MemoizedSelector<SearchFiltersState, T> {
|
||||
return createSelector(filterStateSelector, (state: SearchFilterState) => {
|
||||
if (hasValue(state)) {
|
||||
return state[key];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
}
|
@@ -13,7 +13,7 @@
|
||||
<div class="row">
|
||||
<div id="search-body"
|
||||
class="row-offcanvas row-offcanvas-left"
|
||||
[@slideInOut]="(isSidebarCollapsed() | async) ? 'collapsed' : 'expanded'">
|
||||
[@pushInOut]="(isSidebarCollapsed() | async) ? 'collapsed' : 'expanded'">
|
||||
<ds-search-sidebar *ngIf="(isMobileView | async)" class="col-12"
|
||||
id="search-sidebar-xs"
|
||||
resultCount="{{(results.pageInfo | async)?.totalElements}}"
|
||||
|
@@ -11,7 +11,7 @@ import { CommunityDataService } from '../core/data/community-data.service';
|
||||
import { isNotEmpty } from '../shared/empty.util';
|
||||
import { Community } from '../core/shared/community.model';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { slideInOut } from '../shared/animations/slide';
|
||||
import { pushInOut } from '../shared/animations/push';
|
||||
import { HostWindowService } from '../shared/host-window.service';
|
||||
import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
|
||||
|
||||
@@ -25,7 +25,7 @@ import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
|
||||
selector: 'ds-search-page',
|
||||
styleUrls: ['./search-page.component.scss'],
|
||||
templateUrl: './search-page.component.html',
|
||||
animations: [slideInOut]
|
||||
animations: [pushInOut]
|
||||
})
|
||||
export class SearchPageComponent implements OnInit, OnDestroy {
|
||||
|
||||
|
@@ -15,6 +15,7 @@ import { EffectsModule } from '@ngrx/effects';
|
||||
import { SidebarFiltersComponent } from './search-filters/search-filters.component';
|
||||
import { SidebarFilterComponent } from './search-filters/search-filter/search-filter.component';
|
||||
import { SidebarFacetFilterComponent } from './search-filters/search-filter/search-facet-filter/search-facet-filter.component';
|
||||
import { SearchFilterService } from './search-filters/search-filter/search-filter.service';
|
||||
|
||||
const effects = [
|
||||
SearchSidebarEffects
|
||||
@@ -40,7 +41,8 @@ const effects = [
|
||||
],
|
||||
providers: [
|
||||
SearchService,
|
||||
SearchSidebarService
|
||||
SearchSidebarService,
|
||||
SearchFilterService
|
||||
],
|
||||
entryComponents: [
|
||||
ItemSearchResultListElementComponent,
|
||||
|
@@ -5,6 +5,7 @@ export class SearchFilterConfig {
|
||||
name: string;
|
||||
type: FilterType;
|
||||
hasFacets: boolean;
|
||||
pageSize = 3;
|
||||
isOpenByDefault: boolean;
|
||||
/**
|
||||
* Name of this configuration that can be used in a url
|
||||
|
@@ -235,11 +235,6 @@ export class SearchService implements OnDestroy {
|
||||
return params;
|
||||
}
|
||||
|
||||
isFilterActive(filterName: string, filterValue: string): boolean {
|
||||
const filterConfig = this.config.find((config: SearchFilterConfig) => config.name === filterName);
|
||||
return isNotEmpty(this.router.url.match(filterConfig.paramName + '=' + encodeURI(filterValue) + '(&(.*))?$'));
|
||||
}
|
||||
|
||||
getSearchLink() {
|
||||
return this.searchLink;
|
||||
}
|
||||
@@ -249,5 +244,4 @@ export class SearchService implements OnDestroy {
|
||||
this.sub.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@ import { Injectable } from '@angular/core';
|
||||
import { Effect, Actions } from '@ngrx/effects'
|
||||
import * as fromRouter from '@ngrx/router-store';
|
||||
|
||||
import { HostWindowActionTypes } from '../../shared/host-window.actions';
|
||||
import { SearchSidebarCollapseAction } from './search-sidebar.actions';
|
||||
|
||||
@Injectable()
|
||||
|
@@ -7,12 +7,17 @@ import {
|
||||
SearchSidebarState,
|
||||
sidebarReducer
|
||||
} from './+search-page/search-sidebar/search-sidebar.reducer';
|
||||
import {
|
||||
filterReducer,
|
||||
SearchFiltersState
|
||||
} from './+search-page/search-filters/search-filter/search-filter.reducer';
|
||||
|
||||
export interface AppState {
|
||||
router: fromRouter.RouterReducerState;
|
||||
hostWindow: HostWindowState;
|
||||
header: HeaderState;
|
||||
searchSidebar: SearchSidebarState;
|
||||
searchFilter: SearchFiltersState;
|
||||
}
|
||||
|
||||
export const appReducers: ActionReducerMap<AppState> = {
|
||||
@@ -20,4 +25,5 @@ export const appReducers: ActionReducerMap<AppState> = {
|
||||
hostWindow: hostWindowReducer,
|
||||
header: headerReducer,
|
||||
searchSidebar: sidebarReducer,
|
||||
searchFilter: filterReducer
|
||||
};
|
||||
|
16
src/app/shared/animations/push.ts
Normal file
16
src/app/shared/animations/push.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { animate, state, transition, trigger, style } from '@angular/animations';
|
||||
|
||||
export const pushInOut = trigger('pushInOut', [
|
||||
|
||||
/*
|
||||
state('expanded', style({ right: '100%' }));
|
||||
|
||||
state('collapsed', style({ right: 0 }));
|
||||
*/
|
||||
|
||||
state('expanded', style({ left: '100%' })),
|
||||
|
||||
state('collapsed', style({ left: 0 })),
|
||||
|
||||
transition('expanded <=> collapsed', animate(250)),
|
||||
]);
|
@@ -1,16 +1,10 @@
|
||||
import { animate, state, transition, trigger, style } from '@angular/animations';
|
||||
|
||||
export const slideInOut = trigger('slideInOut', [
|
||||
export const slide = trigger('slide', [
|
||||
|
||||
/*
|
||||
state('expanded', style({ right: '100%' }));
|
||||
state('expanded', style({ height: '*' })),
|
||||
|
||||
state('collapsed', style({ right: 0 }));
|
||||
*/
|
||||
|
||||
state('expanded', style({ left: '100%' })),
|
||||
|
||||
state('collapsed', style({ left: 0 })),
|
||||
state('collapsed', style({ height: 0 })),
|
||||
|
||||
transition('expanded <=> collapsed', animate(250)),
|
||||
]);
|
||||
|
Reference in New Issue
Block a user