96252: Remove unused sidebar filter components

This commit is contained in:
Yury Bondarenko
2023-01-03 17:03:46 +01:00
parent 1c7108e928
commit 67616a5d52
13 changed files with 0 additions and 511 deletions

View File

@@ -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,

View File

@@ -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

View File

@@ -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,

View File

@@ -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>

View File

@@ -1,11 +0,0 @@
a {
color: var(--bs-body-color);
&:hover, &focus {
text-decoration: none;
}
span.badge {
vertical-align: text-top;
}
}

View File

@@ -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>();
}

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
});
});
});

View File

@@ -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;
}
});
}