import { ActionReducer, StateAction } from "../StateManager.js"; import { Action } from "../action/DataUnitAction.js"; import StateManager from "../StateManager.js"; import { getCurrentRecords, getSelectionRecords } from "./SnapshotSlice.js"; import { Record, SavedRecord, SelectionMode } from "../../interfaces/dataUnit.js"; import { SelectionInfo } from "../../SelectionInfo.js"; import { getCurrentRequest, getPaginationInfo } from "./LoadingControlSlice.js"; import { PaginationInfo } from "../../loading/PaginationInfo.js"; class SelectionReducerImpl implements ActionReducer { public sliceName: string = "hist::selection"; public reduce(stateManager: StateManager, currentState: SelectionState, action: StateAction): SelectionState|undefined { switch (action.type) { case Action.DATA_LOADED: return !action.payload?.keepSelection ? undefined : currentState; case Action.RECORDS_ADDED: case Action.RECORDS_COPIED: const lastSelection = currentState?.currentSelection || []; return {currentSelection: action.payload.map((r: Record)=>r.__record__id__), lastSelection}; case Action.DATA_SAVED: return {currentSelection: updateSavedIds(stateManager, action.payload.records)}; case Action.RECORDS_REMOVED: return {currentSelection: action.payload.selectionAfterRemove || []}; case Action.NEXT_SELECTED: case Action.PREVIOUS_SELECTED: const currentRecords = getCurrentRecords(stateManager); const currentSelection = currentState?.currentSelection; if (currentRecords && currentRecords.size > 0) { let index: number; if (!currentState || currentSelection.length === 0) { index = action.type === Action.PREVIOUS_SELECTED ? 0 : Math.min(0, currentRecords.size); } else { index = getItemIndex(currentSelection[0], currentRecords) + (action.type === Action.PREVIOUS_SELECTED ? -1 : 1); } if (index < currentRecords.size && index >= 0) { return { currentSelection: [Array.from(currentRecords.values())[index].__record__id__] }; } } return undefined; case Action.SELECTION_CHANGED: const { type, selection: selectionSource } = action.payload; if(selectionSource === SelectionMode.ALL_RECORDS){ return {currentSelection: [], mode: SelectionMode.ALL_RECORDS}; } if (selectionSource && type === "index") { const currentRecords = getCurrentRecords(stateManager); if (currentRecords) { const records = Array.from(currentRecords.values()); const selectionById: Array = []; selectionSource.forEach((i: number) => { if (i >= 0 && i < currentRecords.size) { selectionById.push(records[i].__record__id__); } }); return {currentSelection: selectionById}; } } return {currentSelection: selectionSource }; case Action.EDITION_CANCELED: if(currentState?.lastSelection){ return { currentSelection: currentState.lastSelection }; } return { currentSelection: currentState?.currentSelection || [] } } return currentState; } } export const SelectionReducer = new SelectionReducerImpl(); export const getSelectionState = (stateManager: StateManager): SelectionState => { return stateManager.select(SelectionReducer.sliceName, (state: SelectionState) => state); } export const getSelection = (stateManager: StateManager): Array => { const selection: Array | undefined = getCurrentSelection(stateManager); if (!selection || selection.length === 0) { return []; } return selection; }; export const getSelectionInfo = (stateManager: StateManager): SelectionInfo => { const selection = getSelectionState(stateManager); const currentRequest = getCurrentRequest(stateManager); if(selection && selection.mode === SelectionMode.ALL_RECORDS){ const paginationInfo: PaginationInfo | undefined = getPaginationInfo(stateManager); return new SelectionInfo( [], SelectionMode.ALL_RECORDS, paginationInfo?.total || 0, currentRequest?.filters, currentRequest?.sort ); } return new SelectionInfo(getSelectionRecords(stateManager) || [], SelectionMode.SOME_RECORDS, undefined, undefined, currentRequest?.sort); } export const hasNext = (stateManager: StateManager): boolean => { const records = getCurrentRecords(stateManager); if (records) { const selection = getCurrentSelection(stateManager); if (!selection || selection.length === 0) { return records.size > 0; } return records.size > (getItemIndex(selection[0], records) + 1); } return false; }; export const hasPrevious = (stateManager: StateManager): boolean => { const records = getCurrentRecords(stateManager); if (records) { const selection = getCurrentSelection(stateManager); if (!selection || selection.length === 0) { return false; } return getItemIndex(selection[0], records) > 0; } return false; }; function getItemIndex(key: string, map: Map): number { return Array.from(map.keys()).indexOf(key); } function updateSavedIds(stateManager:StateManager, savedRecords:Array): Array{ const currentSelection: Array = getSelection(stateManager); if(currentSelection){ const newSelection: Array = []; currentSelection.forEach( id => { const record = savedRecords.find(r => r.__old__id__ === id); if(record){ newSelection.push(record.__record__id__); } else { newSelection.push(id); } }); return newSelection; } return currentSelection; } function getCurrentSelection(stateManager: StateManager):Array | undefined{ const selectionState = getSelectionState(stateManager); return selectionState ? selectionState.currentSelection : undefined; } interface SelectionState{ currentSelection: Array; mode?: SelectionMode; lastSelection?: Array; }