import { Injectable } from '@angular/core'; import { createSelector, MemoizedSelector, Store, } from '@ngrx/store'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { AppState } from '../../app.reducer'; import { hasValue } from '../empty.util'; import { ObjectSelectionDeselectAction, ObjectSelectionInitialDeselectAction, ObjectSelectionInitialSelectAction, ObjectSelectionResetAction, ObjectSelectionSelectAction, ObjectSelectionSwitchAction, } from './object-select.actions'; import { ObjectSelectionListState, ObjectSelectionsState, ObjectSelectionState, } from './object-select.reducer'; const objectSelectionsStateSelector = (state: ObjectSelectionListState) => state.objectSelection; const objectSelectionListStateSelector = (state: AppState) => state.objectSelection; /** * Service that takes care of selecting and deselecting objects */ @Injectable({ providedIn: 'root' }) export class ObjectSelectService { constructor( private store: Store<ObjectSelectionListState>, private appStore: Store<AppState>, ) { } /** * Request the current selection of a given object in a given list * @param {string} key The key of the list where the selection resides in * @param {string} id The UUID of the object * @returns {Observable<boolean>} Emits the current selection state of the given object, if it's unavailable, return false */ getSelected(key: string, id: string): Observable<boolean> { return this.store.select(selectionByKeyAndIdSelector(key, id)).pipe( map((object: ObjectSelectionState) => { if (object) { return object.checked; } else { return false; } }), ); } /** * Request the current selection of all objects within a specific list * @returns {Observable<boolean>} Emits the current selection state of all objects */ getAllSelected(key: string): Observable<string[]> { return this.appStore.select(objectSelectionListStateSelector).pipe( map((state: ObjectSelectionListState) => { if (hasValue(state[key])) { return Object.keys(state[key]).filter((id) => state[key][id].checked); } else { return []; } }), ); } /** * Dispatches an initial select action to the store for a given object in a given list * @param {string} key The key of the list to select the object in * @param {string} id The UUID of the object to select */ public initialSelect(key: string, id: string): void { this.store.dispatch(new ObjectSelectionInitialSelectAction(key, id)); } /** * Dispatches an initial deselect action to the store for a given object in a given list * @param {string} key The key of the list to deselect the object in * @param {string} id The UUID of the object to deselect */ public initialDeselect(key: string, id: string): void { this.store.dispatch(new ObjectSelectionInitialDeselectAction(key, id)); } /** * Dispatches a select action to the store for a given object in a given list * @param {string} key The key of the list to select the object in * @param {string} id The UUID of the object to select */ public select(key: string, id: string): void { this.store.dispatch(new ObjectSelectionSelectAction(key, id)); } /** * Dispatches a deselect action to the store for a given object in a given list * @param {string} key The key of the list to deselect the object in * @param {string} id The UUID of the object to deselect */ public deselect(key: string, id: string): void { this.store.dispatch(new ObjectSelectionDeselectAction(key, id)); } /** * Dispatches a switch action to the store for a given object in a given list * @param {string} key The key of the list to select the object in * @param {string} id The UUID of the object to select */ public switch(key: string, id: string): void { this.store.dispatch(new ObjectSelectionSwitchAction(key, id)); } /** * Dispatches a reset action to the store for all objects (in a list) * @param {string} key The key of the list to clear all selections for */ public reset(key?: string): void { this.store.dispatch(new ObjectSelectionResetAction(key, null)); } } function selectionByKeyAndIdSelector(key: string, id: string): MemoizedSelector<ObjectSelectionListState, ObjectSelectionState> { return keyAndIdSelector<ObjectSelectionState>(key, id); } export function keyAndIdSelector<T>(key: string, id: string): MemoizedSelector<ObjectSelectionListState, T> { return createSelector(objectSelectionsStateSelector, (state: ObjectSelectionsState) => { if (hasValue(state) && hasValue(state[key])) { return state[key][id]; } else { return undefined; } }); }