mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
96252: Remove unused sidebar filter components
This commit is contained in:
@@ -42,10 +42,6 @@ import {
|
||||
filterReducer,
|
||||
SearchFiltersState
|
||||
} from './shared/search/search-filters/search-filter/search-filter.reducer';
|
||||
import {
|
||||
sidebarFilterReducer,
|
||||
SidebarFiltersState
|
||||
} from './shared/sidebar/filter/sidebar-filter.reducer';
|
||||
import { sidebarReducer, SidebarState } from './shared/sidebar/sidebar.reducer';
|
||||
import { truncatableReducer, TruncatablesState } from './shared/truncatable/truncatable.reducer';
|
||||
import { ThemeState, themeReducer } from './shared/theme-support/theme.reducer';
|
||||
@@ -59,7 +55,6 @@ export interface AppState {
|
||||
metadataRegistry: MetadataRegistryState;
|
||||
notifications: NotificationsState;
|
||||
sidebar: SidebarState;
|
||||
sidebarFilter: SidebarFiltersState;
|
||||
searchFilter: SearchFiltersState;
|
||||
truncatable: TruncatablesState;
|
||||
cssVariables: CSSVariablesState;
|
||||
@@ -81,7 +76,6 @@ export const appReducers: ActionReducerMap<AppState> = {
|
||||
metadataRegistry: metadataRegistryReducer,
|
||||
notifications: notificationsReducer,
|
||||
sidebar: sidebarReducer,
|
||||
sidebarFilter: sidebarFilterReducer,
|
||||
searchFilter: filterReducer,
|
||||
truncatable: truncatableReducer,
|
||||
cssVariables: cssVariablesReducer,
|
||||
|
@@ -7,7 +7,6 @@ import { ConfigurationSearchPageGuard } from './configuration-search-page.guard'
|
||||
import { SearchTrackerComponent } from './search-tracker.component';
|
||||
import { StatisticsModule } from '../statistics/statistics.module';
|
||||
import { SearchPageComponent } from './search-page.component';
|
||||
import { SidebarFilterService } from '../shared/sidebar/filter/sidebar-filter.service';
|
||||
import { SearchFilterService } from '../core/shared/search/search-filter.service';
|
||||
import { SearchConfigurationService } from '../core/shared/search/search-configuration.service';
|
||||
import { JournalEntitiesModule } from '../entity-groups/journal-entities/journal-entities.module';
|
||||
@@ -34,7 +33,6 @@ const components = [
|
||||
declarations: components,
|
||||
providers: [
|
||||
SidebarService,
|
||||
SidebarFilterService,
|
||||
SearchFilterService,
|
||||
ConfigurationSearchPageGuard,
|
||||
SearchConfigurationService
|
||||
|
@@ -186,8 +186,6 @@ import {
|
||||
} from './object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component';
|
||||
import { PageWithSidebarComponent } from './sidebar/page-with-sidebar.component';
|
||||
import { SidebarDropdownComponent } from './sidebar/sidebar-dropdown.component';
|
||||
import { SidebarFilterComponent } from './sidebar/filter/sidebar-filter.component';
|
||||
import { SidebarFilterSelectedOptionComponent } from './sidebar/filter/sidebar-filter-selected-option.component';
|
||||
import {
|
||||
SelectableListItemControlComponent
|
||||
} from './object-collection/shared/selectable-list-item-control/selectable-list-item-control.component';
|
||||
@@ -322,8 +320,6 @@ const COMPONENTS = [
|
||||
SearchFormComponent,
|
||||
PageWithSidebarComponent,
|
||||
SidebarDropdownComponent,
|
||||
SidebarFilterComponent,
|
||||
SidebarFilterSelectedOptionComponent,
|
||||
ThumbnailComponent,
|
||||
ViewModeSwitchComponent,
|
||||
TruncatableComponent,
|
||||
|
@@ -1,6 +0,0 @@
|
||||
<a class="d-flex flex-row" (click)="click.emit($event)">
|
||||
<label>
|
||||
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value pl-1 text-capitalize">{{label}}</span>
|
||||
</label>
|
||||
</a>
|
@@ -1,11 +0,0 @@
|
||||
a {
|
||||
color: var(--bs-body-color);
|
||||
|
||||
&:hover, &focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
span.badge {
|
||||
vertical-align: text-top;
|
||||
}
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-sidebar-filter-selected-option',
|
||||
styleUrls: ['./sidebar-filter-selected-option.component.scss'],
|
||||
templateUrl: './sidebar-filter-selected-option.component.html',
|
||||
})
|
||||
|
||||
/**
|
||||
* Represents a single selected option in a sidebar filter
|
||||
*/
|
||||
export class SidebarFilterSelectedOptionComponent {
|
||||
@Input() label: string;
|
||||
@Output() click: EventEmitter<any> = new EventEmitter<any>();
|
||||
}
|
@@ -1,73 +0,0 @@
|
||||
/* eslint-disable max-classes-per-file */
|
||||
import { Action } from '@ngrx/store';
|
||||
|
||||
import { type } from '../../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 SidebarFilterActionTypes = {
|
||||
INITIALIZE: type('dspace/sidebar-filter/INITIALIZE'),
|
||||
COLLAPSE: type('dspace/sidebar-filter/COLLAPSE'),
|
||||
EXPAND: type('dspace/sidebar-filter/EXPAND'),
|
||||
TOGGLE: type('dspace/sidebar-filter/TOGGLE'),
|
||||
};
|
||||
|
||||
export class SidebarFilterAction implements Action {
|
||||
/**
|
||||
* Name of the filter the action is performed on, used to identify the filter
|
||||
*/
|
||||
filterName: string;
|
||||
|
||||
/**
|
||||
* Type of action that will be performed
|
||||
*/
|
||||
type;
|
||||
|
||||
/**
|
||||
* Initialize with the filter's name
|
||||
* @param {string} name of the filter
|
||||
*/
|
||||
constructor(name: string) {
|
||||
this.filterName = name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to initialize a filter
|
||||
*/
|
||||
export class FilterInitializeAction extends SidebarFilterAction {
|
||||
type = SidebarFilterActionTypes.INITIALIZE;
|
||||
initiallyExpanded;
|
||||
|
||||
constructor(name: string, initiallyExpanded: boolean) {
|
||||
super(name);
|
||||
this.initiallyExpanded = initiallyExpanded;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to collapse a filter
|
||||
*/
|
||||
export class FilterCollapseAction extends SidebarFilterAction {
|
||||
type = SidebarFilterActionTypes.COLLAPSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to expand a filter
|
||||
*/
|
||||
export class FilterExpandAction extends SidebarFilterAction {
|
||||
type = SidebarFilterActionTypes.EXPAND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to collapse a filter when it's expanded and expand it when it's collapsed
|
||||
*/
|
||||
export class FilterToggleAction extends SidebarFilterAction {
|
||||
type = SidebarFilterActionTypes.TOGGLE;
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
<div class="facet-filter d-block mb-3 p-3">
|
||||
<div (click)="toggle()" class="filter-name" [attr.data-test]="'filter-toggle' | dsBrowserOnly">
|
||||
<h5 class="d-inline-block mb-0">
|
||||
{{ label | translate }}
|
||||
</h5>
|
||||
<span class="filter-toggle fas float-right"
|
||||
[ngClass]="(collapsed$ | async) ? 'fa-plus' : 'fa-minus'">
|
||||
</span>
|
||||
</div>
|
||||
<div [@slide]="(collapsed$ | async) ? 'collapsed' : 'expanded'"
|
||||
(@slide.start)="startSlide($event)" (@slide.done)="finishSlide($event)"
|
||||
class="sidebar-filter-wrapper" [ngClass]="{'closed' : closed}">
|
||||
<div>
|
||||
<div class="filters py-2">
|
||||
<ng-template *ngIf="!singleValue">
|
||||
<ds-sidebar-filter-selected-option
|
||||
*ngFor="let value of (selectedValues | async)"
|
||||
[label]="value"
|
||||
(click)="removeValue.emit(value)">
|
||||
</ds-sidebar-filter-selected-option>
|
||||
</ng-template>
|
||||
</div>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -1,12 +0,0 @@
|
||||
:host .facet-filter {
|
||||
border: 1px solid var(--bs-light);
|
||||
cursor: pointer;
|
||||
|
||||
.sidebar-filter-wrapper.closed {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.filter-toggle {
|
||||
line-height: var(--bs-line-height-base);
|
||||
}
|
||||
}
|
@@ -1,89 +0,0 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { SidebarFilterService } from './sidebar-filter.service';
|
||||
import { slide } from '../../animations/slide';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-sidebar-filter',
|
||||
styleUrls: ['./sidebar-filter.component.scss'],
|
||||
templateUrl: './sidebar-filter.component.html',
|
||||
animations: [slide],
|
||||
})
|
||||
/**
|
||||
* This components renders a sidebar filter including the label and the selected values.
|
||||
* The filter input itself should still be provided in the content.
|
||||
*/
|
||||
export class SidebarFilterComponent implements OnInit {
|
||||
|
||||
@Input() name: string;
|
||||
@Input() type: string;
|
||||
@Input() label: string;
|
||||
@Input() expanded = true;
|
||||
@Input() singleValue = false;
|
||||
@Input() selectedValues: Observable<string[]>;
|
||||
@Output() removeValue: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
/**
|
||||
* True when the filter is 100% collapsed in the UI
|
||||
*/
|
||||
closed = true;
|
||||
|
||||
/**
|
||||
* Emits true when the filter is currently collapsed in the store
|
||||
*/
|
||||
collapsed$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
protected filterService: SidebarFilterService,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the state for this filter to collapsed when it's expanded and to expanded it when it's collapsed
|
||||
*/
|
||||
toggle() {
|
||||
this.filterService.toggle(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change this.collapsed to false when the slide animation ends and is sliding open
|
||||
* @param event The animation event
|
||||
*/
|
||||
finishSlide(event: any): void {
|
||||
if (event.fromState === 'collapsed') {
|
||||
this.closed = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change this.collapsed to true when the slide animation starts and is sliding closed
|
||||
* @param event The animation event
|
||||
*/
|
||||
startSlide(event: any): void {
|
||||
if (event.toState === 'collapsed') {
|
||||
this.closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.closed = !this.expanded;
|
||||
this.initializeFilter();
|
||||
this.collapsed$ = this.isCollapsed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the initial state of the filter
|
||||
*/
|
||||
initializeFilter() {
|
||||
this.filterService.initializeFilter(this.name, this.expanded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the filter is currently collapsed
|
||||
* @returns {Observable<boolean>} Emits true when the current state of the filter is collapsed, false when it's expanded
|
||||
*/
|
||||
private isCollapsed(): Observable<boolean> {
|
||||
return this.filterService.isCollapsed(this.name);
|
||||
}
|
||||
|
||||
}
|
@@ -1,70 +0,0 @@
|
||||
import {
|
||||
FilterInitializeAction,
|
||||
SidebarFilterAction,
|
||||
SidebarFilterActionTypes
|
||||
} from './sidebar-filter.actions';
|
||||
|
||||
/**
|
||||
* Interface that represents the state for a single filters
|
||||
*/
|
||||
export interface SidebarFilterState {
|
||||
filterCollapsed: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface that represents the state for all available filters
|
||||
*/
|
||||
export interface SidebarFiltersState {
|
||||
[name: string]: SidebarFilterState;
|
||||
}
|
||||
|
||||
const initialState: SidebarFiltersState = Object.create(null);
|
||||
|
||||
/**
|
||||
* Performs a filter action on the current state
|
||||
* @param {SidebarFiltersState} state The state before the action is performed
|
||||
* @param {SidebarFilterAction} action The action that should be performed
|
||||
* @returns {SidebarFiltersState} The state after the action is performed
|
||||
*/
|
||||
export function sidebarFilterReducer(state = initialState, action: SidebarFilterAction): SidebarFiltersState {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
case SidebarFilterActionTypes.INITIALIZE: {
|
||||
const initAction = (action as FilterInitializeAction);
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: !initAction.initiallyExpanded,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
case SidebarFilterActionTypes.COLLAPSE: {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: true,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
case SidebarFilterActionTypes.EXPAND: {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: false,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
case SidebarFilterActionTypes.TOGGLE: {
|
||||
return Object.assign({}, state, {
|
||||
[action.filterName]: {
|
||||
filterCollapsed: !state[action.filterName].filterCollapsed,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,107 +0,0 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { Store, StoreModule } from '@ngrx/store';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { cold } from 'jasmine-marbles';
|
||||
|
||||
import { sidebarFilterReducer } from './sidebar-filter.reducer';
|
||||
import { SidebarFilterService } from './sidebar-filter.service';
|
||||
import {
|
||||
FilterCollapseAction,
|
||||
FilterExpandAction,
|
||||
FilterInitializeAction,
|
||||
FilterToggleAction
|
||||
} from './sidebar-filter.actions';
|
||||
import { storeModuleConfig } from '../../../app.reducer';
|
||||
|
||||
describe('SidebarFilterService', () => {
|
||||
let service: SidebarFilterService;
|
||||
let store: any;
|
||||
let initialState;
|
||||
|
||||
function init() {
|
||||
|
||||
initialState = {
|
||||
sidebarFilter: {
|
||||
filter_1: {
|
||||
filterCollapsed: true
|
||||
},
|
||||
filter_2: {
|
||||
filterCollapsed: false
|
||||
},
|
||||
filter_3: {
|
||||
filterCollapsed: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
init();
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
StoreModule.forRoot({ sidebarFilter: sidebarFilterReducer }, storeModuleConfig)
|
||||
],
|
||||
providers: [
|
||||
provideMockStore({ initialState }),
|
||||
{ provide: SidebarFilterService, useValue: service }
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
store = TestBed.inject(Store);
|
||||
service = new SidebarFilterService(store);
|
||||
spyOn(store, 'dispatch');
|
||||
});
|
||||
|
||||
describe('initializeFilter', () => {
|
||||
it('should dispatch an FilterInitializeAction with the correct arguments', () => {
|
||||
service.initializeFilter('fakeFilter', true);
|
||||
expect(store.dispatch).toHaveBeenCalledWith(new FilterInitializeAction('fakeFilter', true));
|
||||
});
|
||||
});
|
||||
|
||||
describe('collapse', () => {
|
||||
it('should dispatch an FilterInitializeAction with the correct arguments', () => {
|
||||
service.collapse('fakeFilter');
|
||||
expect(store.dispatch).toHaveBeenCalledWith(new FilterCollapseAction('fakeFilter'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('expand', () => {
|
||||
it('should dispatch an FilterInitializeAction with the correct arguments', () => {
|
||||
service.expand('fakeFilter');
|
||||
expect(store.dispatch).toHaveBeenCalledWith(new FilterExpandAction('fakeFilter'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggle', () => {
|
||||
it('should dispatch an FilterInitializeAction with the correct arguments', () => {
|
||||
service.toggle('fakeFilter');
|
||||
expect(store.dispatch).toHaveBeenCalledWith(new FilterToggleAction('fakeFilter'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('isCollapsed', () => {
|
||||
it('should return true', () => {
|
||||
|
||||
const result = service.isCollapsed('filter_1');
|
||||
const expected = cold('b', {
|
||||
b: true
|
||||
});
|
||||
|
||||
expect(result).toBeObservable(expected);
|
||||
});
|
||||
|
||||
it('should return false', () => {
|
||||
|
||||
const result = service.isCollapsed('filter_2');
|
||||
const expected = cold('b', {
|
||||
b: false
|
||||
});
|
||||
|
||||
expect(result).toBeObservable(expected);
|
||||
});
|
||||
});
|
||||
});
|
@@ -1,90 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {
|
||||
FilterCollapseAction,
|
||||
FilterExpandAction, FilterInitializeAction,
|
||||
FilterToggleAction
|
||||
} from './sidebar-filter.actions';
|
||||
import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
|
||||
import { SidebarFiltersState, SidebarFilterState } from './sidebar-filter.reducer';
|
||||
import { Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { hasValue } from '../../empty.util';
|
||||
|
||||
/**
|
||||
* Service that performs all actions that have to do with sidebar filters like collapsing or expanding them.
|
||||
*/
|
||||
@Injectable()
|
||||
export class SidebarFilterService {
|
||||
|
||||
constructor(private store: Store<SidebarFiltersState>) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches an initialize action to the store for a given filter
|
||||
* @param {string} filter The filter for which the action is dispatched
|
||||
* @param {boolean} expanded If the filter should be open from the start
|
||||
*/
|
||||
public initializeFilter(filter: string, expanded: boolean): void {
|
||||
this.store.dispatch(new FilterInitializeAction(filter, expanded));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a collapse action to the store for a given filter
|
||||
* @param {string} filterName The filter for which the action is dispatched
|
||||
*/
|
||||
public collapse(filterName: string): void {
|
||||
this.store.dispatch(new FilterCollapseAction(filterName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches an expand action to the store for a given filter
|
||||
* @param {string} filterName The filter for which the action is dispatched
|
||||
*/
|
||||
public expand(filterName: string): void {
|
||||
this.store.dispatch(new FilterExpandAction(filterName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a toggle action to the store for a given filter
|
||||
* @param {string} filterName The filter for which the action is dispatched
|
||||
*/
|
||||
public toggle(filterName: string): void {
|
||||
this.store.dispatch(new FilterToggleAction(filterName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the state of a given filter is currently collapsed or not
|
||||
* @param {string} filterName The filtername for which the collapsed state is checked
|
||||
* @returns {Observable<boolean>} Emits the current collapsed state of the given filter, if it's unavailable, return false
|
||||
*/
|
||||
isCollapsed(filterName: string): Observable<boolean> {
|
||||
return this.store.pipe(
|
||||
select(filterByNameSelector(filterName)),
|
||||
map((object: SidebarFilterState) => {
|
||||
if (object) {
|
||||
return object.filterCollapsed;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const filterStateSelector = (state: SidebarFiltersState) => state.sidebarFilter;
|
||||
|
||||
function filterByNameSelector(name: string): MemoizedSelector<SidebarFiltersState, SidebarFilterState> {
|
||||
return keySelector<SidebarFilterState>(name);
|
||||
}
|
||||
|
||||
export function keySelector<T>(key: string): MemoizedSelector<SidebarFiltersState, T> {
|
||||
return createSelector(filterStateSelector, (state: SidebarFilterState) => {
|
||||
if (hasValue(state)) {
|
||||
return state[key];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user