import { ActionReducer, StateAction } from "../StateManager.js"; import { Action } from "../action/DataUnitAction.js"; import StateManager from "../StateManager.js"; import { getSelection } from "./SelectionSlice.js"; import { getRecords } from "./RecordsSlice.js"; import { getRemovedRecords } from "./RemovedRecordsSlice.js"; import { getAddedRecords, isAddedRecord } from "./AddedRecordsSlice.js"; import { ChangeOperation, Record } from "../../interfaces/dataUnit.js"; import { Change } from "../../Changes.js"; import { getWaitingChanges } from "./WaitingChangesSlice.js"; import { getSelectionRecords } from "./SnapshotSlice.js"; class ChangesReducerImpl implements ActionReducer{ public sliceName: string = "hist::changes"; public reduce(stateManager:StateManager, currentState: Map, action: StateAction): Map|undefined { switch(action.type){ case Action.RECORDS_COPIED: const records: Array = action.payload; const changes = new Map(getChanges(stateManager)); records.forEach( r => { const rChanges = {...changes.get(r.__record__id__), ...r}; delete rChanges.__old__id__; delete rChanges.__record__id__; delete rChanges.__parent__record__id__; delete rChanges.__record__source__id__; delete rChanges.__record__label__; delete rChanges.__copy__; delete rChanges.__owner__dataunit__name__; changes.set(r.__record__id__, rChanges); } ); return changes; case Action.DATA_CHANGED: const selection: Array = action.payload.records || getSelection(stateManager); if(selection){ const newState = new Map(currentState); selection.forEach(recordId => { const newChanges = {...newState.get(recordId), ...action.payload}; delete newChanges.records; newState.set(recordId, newChanges); }); return newState; } return currentState; case Action.DATA_SAVED: case Action.EDITION_CANCELED: return undefined; } return currentState; } } export const ChangesReducer = new ChangesReducerImpl(); export const getChanges = (stateManager: StateManager): Map => { return stateManager.select(ChangesReducer.sliceName, (state: Map) => state); } export const isDirty = (stateManager: StateManager): boolean => { if (getAddedRecords(stateManager) !== undefined) { return true; } if (getRemovedRecords(stateManager) !== undefined) { return true; } return hasDirtyRecords(stateManager); } export const hasDirtyRecords = (stateManager: StateManager): boolean => { if(getWaitingChanges(stateManager) !== undefined){ return true; } return getChanges(stateManager) !== undefined; } export const getChangedFieldValue = (fieldName: string, record: Record, stateManager: StateManager): any => { const changes = getChanges(stateManager); if(changes){ const recordChanges = changes.get(record.__record__id__); if (recordChanges && Object.hasOwn(recordChanges, fieldName)) { return recordChanges[fieldName]; } } return record[fieldName]; } export const getChangesToSave = (dataUnit: string, stateManager: StateManager): Array => { const changes = getChanges(stateManager); const selectedRecords = getSelectionRecords(stateManager) || []; const records: Map = new Map( getRecords(stateManager) .concat( selectedRecords.filter(record => !isAddedRecord(record.__record__id__, stateManager)) ) .map(r => [r.__record__id__, r]) ); const result: Array = []; if(changes != undefined){ Array.from(changes.entries()) .forEach(([recordId, change]) =>{ const record = records.get(recordId); if(record != undefined){ result.push(new Change(dataUnit, record, change, ChangeOperation.UPDATE, record.__record__source__id__)); } }); } const addedRecords = getAddedRecords(stateManager); if (addedRecords) { addedRecords.forEach(r => { const operation: ChangeOperation = r.__copy__ ? ChangeOperation.COPY : ChangeOperation.INSERT; const changedFields = {...changes?.get(r.__record__id__)}; if(operation === ChangeOperation.INSERT){ Object.keys(r).forEach(fieldName => { if(!fieldName.startsWith("__") && !Object.keys(changedFields)?.includes(fieldName)){ changedFields[fieldName] = r[fieldName]; } }); } result.push(new Change(dataUnit, r, changedFields, operation, r.__record__source__id__)); }); } const removedRecords = getRemovedRecords(stateManager); const recordsById: any = {}; records?.forEach(r=>recordsById[r.__record__id__] = r); if (removedRecords) { removedRecords.forEach(id => { result.push(new Change(dataUnit, recordsById[id], undefined, ChangeOperation.DELETE)); }); } return result; }