mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
111731: Minimize the facet filters when updating applied filters
This commit is contained in:
@@ -13,7 +13,8 @@ import {
|
||||
SearchFilterIncrementPageAction,
|
||||
SearchFilterInitializeAction,
|
||||
SearchFilterResetPageAction,
|
||||
SearchFilterToggleAction
|
||||
SearchFilterToggleAction,
|
||||
SearchFilterMinimizeAllPageAction,
|
||||
} from '../../../shared/search/search-filters/search-filter/search-filter.actions';
|
||||
import { hasValue, isNotEmpty, } from '../../../shared/empty.util';
|
||||
import { SearchFilterConfig } from '../../../shared/search/models/search-filter-config.model';
|
||||
@@ -202,7 +203,7 @@ export class SearchFilterService {
|
||||
select(filterByNameSelector(filterName)),
|
||||
map((object: SearchFilterState) => {
|
||||
if (object) {
|
||||
return object.filterCollapsed;
|
||||
return object.filterCollapsed || object.minimized;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -284,6 +285,10 @@ export class SearchFilterService {
|
||||
public resetPage(filterName: string): void {
|
||||
this.store.dispatch(new SearchFilterResetPageAction(filterName));
|
||||
}
|
||||
|
||||
public minimizeAll(): void {
|
||||
this.store.dispatch(new SearchFilterMinimizeAllPageAction());
|
||||
}
|
||||
}
|
||||
|
||||
function filterByNameSelector(name: string): MemoizedSelector<SearchFiltersState, SearchFilterState> {
|
||||
|
@@ -1,7 +1,8 @@
|
||||
<a *ngIf="isVisible | async" class="d-flex flex-row"
|
||||
[tabIndex]="-1"
|
||||
[routerLink]="[searchLink]"
|
||||
[queryParams]="addQueryParams$ | async">
|
||||
[queryParams]="addQueryParams$ | async"
|
||||
(click)="filterService.minimizeAll()">
|
||||
<label class="mb-0 d-flex w-100">
|
||||
<input type="checkbox" [checked]="false" class="my-1 align-self-stretch filter-checkbox"/>
|
||||
<span class="w-100 pl-1 break-facet">
|
||||
|
@@ -1,4 +1,5 @@
|
||||
<a *ngIf="isVisible | async" class="d-flex flex-row"
|
||||
(click)="filterService.minimizeAll()"
|
||||
[routerLink]="[searchLink]"
|
||||
[queryParams]="changeQueryParams" queryParamsHandling="merge">
|
||||
<span class="filter-value px-1">{{filterValue.label}}</span>
|
||||
|
@@ -1,7 +1,8 @@
|
||||
<a class="d-flex flex-row"
|
||||
[tabIndex]="-1"
|
||||
[routerLink]="[searchLink]"
|
||||
[queryParams]="removeQueryParams | async">
|
||||
[queryParams]="removeQueryParams | async"
|
||||
(click)="searchFilterService.minimizeAll()">
|
||||
<label class="mb-0 d-flex w-100">
|
||||
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch filter-checkbox"/>
|
||||
<span class="filter-value pl-1 text-capitalize break-facet">
|
||||
|
@@ -7,6 +7,7 @@ import { SearchConfigurationService } from '../../../../../../core/shared/search
|
||||
import { currentPath } from '../../../../../utils/route.utils';
|
||||
import { AppliedFilter } from '../../../../models/applied-filter.model';
|
||||
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
|
||||
import { SearchFilterService } from '../../../../../../core/shared/search/search-filter.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-facet-selected-option',
|
||||
@@ -46,6 +47,7 @@ export class SearchFacetSelectedOptionComponent implements OnInit {
|
||||
constructor(
|
||||
protected paginationService: PaginationService,
|
||||
protected router: Router,
|
||||
protected searchFilterService: SearchFilterService,
|
||||
protected searchService: SearchService,
|
||||
protected searchConfigService: SearchConfigurationService,
|
||||
) {
|
||||
|
@@ -19,7 +19,8 @@ export const SearchFilterActionTypes = {
|
||||
TOGGLE: type('dspace/search-filter/TOGGLE'),
|
||||
DECREMENT_PAGE: type('dspace/search-filter/DECREMENT_PAGE'),
|
||||
INCREMENT_PAGE: type('dspace/search-filter/INCREMENT_PAGE'),
|
||||
RESET_PAGE: type('dspace/search-filter/RESET_PAGE')
|
||||
RESET_PAGE: type('dspace/search-filter/RESET_PAGE'),
|
||||
MINIMIZE_ALL: type('dspace/search-filters/MINIMIZE_ALL'),
|
||||
};
|
||||
|
||||
export class SearchFilterAction implements Action {
|
||||
@@ -37,7 +38,7 @@ export class SearchFilterAction implements Action {
|
||||
* Initialize with the filter's name
|
||||
* @param {string} name of the filter
|
||||
*/
|
||||
constructor(name: string) {
|
||||
constructor(name?: string) {
|
||||
this.filterName = name;
|
||||
}
|
||||
}
|
||||
@@ -95,3 +96,7 @@ export class SearchFilterIncrementPageAction extends SearchFilterAction {
|
||||
export class SearchFilterResetPageAction extends SearchFilterAction {
|
||||
type = SearchFilterActionTypes.RESET_PAGE;
|
||||
}
|
||||
|
||||
export class SearchFilterMinimizeAllPageAction extends SearchFilterAction {
|
||||
type = SearchFilterActionTypes.MINIMIZE_ALL;
|
||||
}
|
||||
|
@@ -9,7 +9,10 @@ import {
|
||||
SearchFilterResetPageAction,
|
||||
SearchFilterToggleAction
|
||||
} from './search-filter.actions';
|
||||
import { filterReducer } from './search-filter.reducer';
|
||||
import {
|
||||
filterReducer,
|
||||
SearchFiltersState,
|
||||
} from './search-filter.reducer';
|
||||
|
||||
const filterName1 = 'author';
|
||||
const filterName2 = 'scope';
|
||||
@@ -25,7 +28,7 @@ class NullAction extends SearchFilterCollapseAction {
|
||||
describe('filterReducer', () => {
|
||||
|
||||
it('should return the current state when no valid actions have been made', () => {
|
||||
const state = { author: { filterCollapsed: true, page: 1 } };
|
||||
const state: SearchFiltersState = { author: { filterCollapsed: true, minimized: false, page: 1 } };
|
||||
const action = new NullAction();
|
||||
const newState = filterReducer(state, action);
|
||||
|
||||
@@ -122,7 +125,7 @@ describe('filterReducer', () => {
|
||||
|
||||
it('should not change the state in response to the INITIALIZE action with isOpenByDefault to false when the state has already been set for this filter', () => {
|
||||
const state = {};
|
||||
state[filterName1] = { filterCollapsed: false, page: 1 };
|
||||
state[filterName1] = { filterCollapsed: false, minimized: false, page: 1 };
|
||||
const filterConfig = { isOpenByDefault: true, name: filterName1 } as any;
|
||||
const action = new SearchFilterInitializeAction(filterConfig);
|
||||
const newState = filterReducer(state, action);
|
||||
@@ -131,7 +134,7 @@ describe('filterReducer', () => {
|
||||
|
||||
it('should not change the state in response to the INITIALIZE action with isOpenByDefault to true when the state has already been set for this filter', () => {
|
||||
const state = {};
|
||||
state[filterName1] = { filterCollapsed: true, page: 1 };
|
||||
state[filterName1] = { filterCollapsed: true, minimized: false, page: 1 };
|
||||
const filterConfig = { isOpenByDefault: false, name: filterName1 } as any;
|
||||
const action = new SearchFilterInitializeAction(filterConfig);
|
||||
const newState = filterReducer(state, action);
|
||||
|
@@ -5,6 +5,7 @@ import { SearchFilterAction, SearchFilterActionTypes, SearchFilterInitializeActi
|
||||
*/
|
||||
export interface SearchFilterState {
|
||||
filterCollapsed: boolean;
|
||||
minimized: boolean;
|
||||
page: number;
|
||||
}
|
||||
|
||||
@@ -23,7 +24,7 @@ const initialState: SearchFiltersState = Object.create(null);
|
||||
* @param {SearchFilterAction} action The action that should be performed
|
||||
* @returns {SearchFiltersState} The state after the action is performed
|
||||
*/
|
||||
export function filterReducer(state = initialState, action: SearchFilterAction): SearchFiltersState {
|
||||
export function filterReducer(state: SearchFiltersState = initialState, action: SearchFilterAction): SearchFiltersState {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
@@ -32,18 +33,19 @@ export function filterReducer(state = initialState, action: SearchFilterAction):
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: !initAction.initiallyExpanded,
|
||||
minimized: false,
|
||||
page: 1
|
||||
}
|
||||
} as SearchFilterState,
|
||||
});
|
||||
return state;
|
||||
}
|
||||
|
||||
case SearchFilterActionTypes.COLLAPSE: {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: true,
|
||||
minimized: state[action.filterName].minimized,
|
||||
page: state[action.filterName].page
|
||||
}
|
||||
} as SearchFilterState,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -51,10 +53,10 @@ export function filterReducer(state = initialState, action: SearchFilterAction):
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: false,
|
||||
minimized: state[action.filterName].minimized,
|
||||
page: state[action.filterName].page
|
||||
}
|
||||
} as SearchFilterState,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
case SearchFilterActionTypes.DECREMENT_PAGE: {
|
||||
@@ -62,8 +64,9 @@ export function filterReducer(state = initialState, action: SearchFilterAction):
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: state[action.filterName].filterCollapsed,
|
||||
minimized: state[action.filterName].minimized,
|
||||
page: (page >= 1 ? page : 1)
|
||||
}
|
||||
} as SearchFilterState,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -71,29 +74,34 @@ export function filterReducer(state = initialState, action: SearchFilterAction):
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: state[action.filterName].filterCollapsed,
|
||||
minimized: state[action.filterName].minimized,
|
||||
page: state[action.filterName].page + 1
|
||||
}
|
||||
} as SearchFilterState,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
case SearchFilterActionTypes.MINIMIZE_ALL: {
|
||||
return Object.assign({}, ...Object.entries(state).map(([key, value]) => ({ [key]: { ...value, minimized: true } })));
|
||||
}
|
||||
|
||||
case SearchFilterActionTypes.RESET_PAGE: {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: state[action.filterName].filterCollapsed,
|
||||
minimized: false,
|
||||
page: 1
|
||||
}
|
||||
} as SearchFilterState,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
case SearchFilterActionTypes.TOGGLE: {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: !state[action.filterName].filterCollapsed,
|
||||
minimized: state[action.filterName].minimized,
|
||||
page: state[action.filterName].page
|
||||
}
|
||||
} as SearchFilterState,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
default: {
|
||||
|
@@ -9,7 +9,6 @@
|
||||
</span>
|
||||
<input type="text" [(ngModel)]="range[0]" [name]="filterConfig.paramName + '.min'"
|
||||
class="form-control" (blur)="onSubmit()"
|
||||
aria-label="Mininum value"
|
||||
[placeholder]="'search.filters.filter.' + filterConfig.name + '.min.placeholder' | translate"
|
||||
/>
|
||||
</label>
|
||||
@@ -21,7 +20,6 @@
|
||||
</span>
|
||||
<input type="text" [(ngModel)]="range[1]" [name]="filterConfig.paramName + '.max'"
|
||||
class="form-control" (blur)="onSubmit()"
|
||||
aria-label="Maximum value"
|
||||
[placeholder]="'search.filters.filter.' + filterConfig.name + '.max.placeholder' | translate"
|
||||
/>
|
||||
</label>
|
||||
|
@@ -4,4 +4,4 @@
|
||||
<ds-search-filter [filter]="filter" [inPlaceSearch]="inPlaceSearch" [refreshFilters]="refreshFilters"></ds-search-filter>
|
||||
</div>
|
||||
</div>
|
||||
<a class="btn btn-primary" [routerLink]="[searchLink]" [queryParams]="clearParams | async" queryParamsHandling="merge" role="button"><i class="fas fa-undo"></i> {{"search.filters.reset" | translate}}</a>
|
||||
<button class="btn btn-primary" [routerLink]="[searchLink]" [queryParams]="clearParams | async" (click)="minimizeFilters()" queryParamsHandling="merge" role="button"><i class="fas fa-undo"></i> {{"search.filters.reset" | translate}}</button>
|
||||
|
@@ -11,6 +11,7 @@ import { SearchConfigurationService } from '../../../core/shared/search/search-c
|
||||
import { SEARCH_CONFIG_SERVICE } from '../../../my-dspace-page/my-dspace-page.component';
|
||||
import { currentPath } from '../../utils/route.utils';
|
||||
import { AppliedFilter } from '../models/applied-filter.model';
|
||||
import { SearchFilterService } from '../../../core/shared/search/search-filter.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-filters',
|
||||
@@ -69,9 +70,11 @@ export class SearchFiltersComponent implements OnInit {
|
||||
* @param {SearchConfigurationService} searchConfigService
|
||||
*/
|
||||
constructor(
|
||||
private searchService: SearchService,
|
||||
private router: Router,
|
||||
@Inject(SEARCH_CONFIG_SERVICE) private searchConfigService: SearchConfigurationService) {
|
||||
protected searchService: SearchService,
|
||||
protected searchFilterService: SearchFilterService,
|
||||
protected router: Router,
|
||||
@Inject(SEARCH_CONFIG_SERVICE) protected searchConfigService: SearchConfigurationService,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -99,4 +102,9 @@ export class SearchFiltersComponent implements OnInit {
|
||||
return config ? config.name : undefined;
|
||||
}
|
||||
|
||||
minimizeFilters(): void {
|
||||
if (this.searchService.appliedFilters$.value.length > 0) {
|
||||
this.searchFilterService.minimizeAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
<a *ngIf="min !== '*'"
|
||||
[routerLink]="searchLink"
|
||||
[queryParams]="(removeParametersMin$ | async)"
|
||||
(click)="searchFilterService.minimizeAll()"
|
||||
class="badge badge-primary mr-1 mb-1">
|
||||
{{('search.filters.applied.f.' + appliedFilter.filter + '.min') | translate}}: {{ min }}
|
||||
<span> ×</span>
|
||||
@@ -8,6 +9,7 @@
|
||||
<a *ngIf="max !== '*'"
|
||||
[routerLink]="searchLink"
|
||||
[queryParams]="(removeParametersMax$ | async)"
|
||||
(click)="searchFilterService.minimizeAll()"
|
||||
class="badge badge-primary mr-1 mb-1">
|
||||
{{('search.filters.applied.f.' + appliedFilter.filter + '.max') | translate}}: {{ max }}
|
||||
<span> ×</span>
|
||||
|
@@ -13,6 +13,8 @@ import { SearchConfigurationServiceStub } from '../../../testing/search-configur
|
||||
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||
import { PaginationServiceStub } from '../../../testing/pagination-service.stub';
|
||||
import { PaginationComponentOptions } from '../../../pagination/pagination-component-options.model';
|
||||
import { SearchFilterService } from '../../../../core/shared/search/search-filter.service';
|
||||
import { SearchFilterServiceStub } from '../../../testing/search-filter-service.stub';
|
||||
|
||||
describe('SearchLabelRangeComponent', () => {
|
||||
let comp: SearchLabelRangeComponent;
|
||||
@@ -20,6 +22,7 @@ describe('SearchLabelRangeComponent', () => {
|
||||
|
||||
let route: ActivatedRouteStub;
|
||||
let searchConfigurationService: SearchConfigurationServiceStub;
|
||||
let searchFilterService: SearchFilterServiceStub;
|
||||
let paginationService: PaginationServiceStub;
|
||||
|
||||
const searchLink = '/search';
|
||||
@@ -51,6 +54,7 @@ describe('SearchLabelRangeComponent', () => {
|
||||
init();
|
||||
route = new ActivatedRouteStub(initialRouteParams);
|
||||
searchConfigurationService = new SearchConfigurationServiceStub();
|
||||
searchFilterService = new SearchFilterServiceStub();
|
||||
paginationService = new PaginationServiceStub(pagination);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
@@ -65,6 +69,7 @@ describe('SearchLabelRangeComponent', () => {
|
||||
{ provide: PaginationService, useValue: paginationService },
|
||||
{ provide: SearchConfigurationService, useValue: searchConfigurationService },
|
||||
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
||||
{ provide: SearchFilterService, useValue: searchFilterService },
|
||||
{ provide: ActivatedRoute, useValue: route },
|
||||
],
|
||||
}).compileComponents();
|
||||
|
@@ -7,6 +7,7 @@ import { AppliedFilter } from '../../models/applied-filter.model';
|
||||
import { renderSearchLabelFor } from '../search-label-loader/search-label-loader.decorator';
|
||||
import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service';
|
||||
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||
import { SearchFilterService } from '../../../../core/shared/search/search-filter.service';
|
||||
|
||||
/**
|
||||
* Component that represents the label containing the currently active filters
|
||||
@@ -37,6 +38,7 @@ export class SearchLabelRangeComponent implements OnInit {
|
||||
protected router: Router,
|
||||
protected searchConfigurationService: SearchConfigurationService,
|
||||
protected searchService: SearchService,
|
||||
protected searchFilterService: SearchFilterService,
|
||||
) {
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
<a class="badge badge-primary mr-1 mb-1"
|
||||
[routerLink]="searchLink"
|
||||
[queryParams]="(removeParameters$ | async)">
|
||||
[queryParams]="(removeParameters$ | async)"
|
||||
(click)="searchFilterService.minimizeAll()">
|
||||
{{('search.filters.applied.f.' + appliedFilter.filter) | translate}}{{'search.filters.applied.operator.' + appliedFilter.operator | translate}}: {{'search.filters.' + appliedFilter.filter + '.' + appliedFilter.label | translate: {default: appliedFilter.label} }}
|
||||
<span> ×</span>
|
||||
</a>
|
||||
|
@@ -13,6 +13,8 @@ import { SearchConfigurationServiceStub } from '../../../testing/search-configur
|
||||
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||
import { PaginationServiceStub } from '../../../testing/pagination-service.stub';
|
||||
import { PaginationComponentOptions } from '../../../pagination/pagination-component-options.model';
|
||||
import { SearchFilterServiceStub } from '../../../testing/search-filter-service.stub';
|
||||
import { SearchFilterService } from '../../../../core/shared/search/search-filter.service';
|
||||
|
||||
describe('SearchLabelComponent', () => {
|
||||
let comp: SearchLabelComponent;
|
||||
@@ -20,6 +22,7 @@ describe('SearchLabelComponent', () => {
|
||||
|
||||
let route: ActivatedRouteStub;
|
||||
let searchConfigurationService: SearchConfigurationServiceStub;
|
||||
let searchFilterService: SearchFilterServiceStub;
|
||||
let paginationService: PaginationServiceStub;
|
||||
|
||||
const searchLink = '/search';
|
||||
@@ -51,6 +54,7 @@ describe('SearchLabelComponent', () => {
|
||||
init();
|
||||
route = new ActivatedRouteStub(initialRouteParams);
|
||||
searchConfigurationService = new SearchConfigurationServiceStub();
|
||||
searchFilterService = new SearchFilterServiceStub();
|
||||
paginationService = new PaginationServiceStub(pagination);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
@@ -64,6 +68,7 @@ describe('SearchLabelComponent', () => {
|
||||
providers: [
|
||||
{ provide: PaginationService, useValue: paginationService },
|
||||
{ provide: SearchConfigurationService, useValue: searchConfigurationService },
|
||||
{ provide: SearchFilterService, useValue: searchFilterService },
|
||||
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
||||
{ provide: ActivatedRoute, useValue: route },
|
||||
],
|
||||
|
@@ -7,6 +7,7 @@ import { AppliedFilter } from '../../models/applied-filter.model';
|
||||
import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service';
|
||||
import { renderSearchLabelFor } from '../search-label-loader/search-label-loader.decorator';
|
||||
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||
import { SearchFilterService } from '../../../../core/shared/search/search-filter.service';
|
||||
|
||||
/**
|
||||
* Component that represents the label containing the currently active filters
|
||||
@@ -30,6 +31,7 @@ export class SearchLabelComponent implements OnInit {
|
||||
protected router: Router,
|
||||
protected searchConfigurationService: SearchConfigurationService,
|
||||
protected searchService: SearchService,
|
||||
protected searchFilterService: SearchFilterService,
|
||||
) {
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user