All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ducks.models.store.ts Maven / Gradle / Ivy

The newest version!
import { createSlice } from '@reduxjs/toolkit'
import {
    merge,
    omit,
    set,
    get,
} from 'lodash'

import { ModelPrefix } from '../../core/datasource/const'
import { id } from '../../utils/id'

import type { State } from './Models'
import type {
    ClearModelAction, CopyAction, MergeModelAction,
    RemoveAllModelAction, RemoveModelAction, SetModelAction,
    UpdateModelAction, AppendFieldToArrayAction, CopyFieldArrayAction,
    RemoveFieldFromArrayAction,
} from './Actions'

export const initialState: State = {
    datasource: {},
    filter: {},
    multi: {}, // selected
    resolve: {},
    edit: {},
}

export const modelsSlice = createSlice({
    name: 'n2o/models',
    initialState,
    reducers: {
        SET: {
            prepare(
                prefix: Prefix,
                key: string,
                model: Prefix extends (ModelPrefix.source | ModelPrefix.selected)
                    ? Array>
                    : Record,
                isDefault?: boolean,
            ) {
                return ({
                    payload: { prefix, key, model, isDefault },
                    meta: { prefix, key, model },
                })
            },

            /**
             * Установка значений модели по префиксу и ключу
             */
            reducer(state, action: SetModelAction) {
                const { key, model, prefix } = action.payload

                set(state, [prefix, key], model)
            },
        },

        REMOVE: {
            prepare(prefix: ModelPrefix, key: string) {
                return ({
                    payload: { prefix, key },
                })
            },

            /**
             * Удаление модели
             */
            reducer(state, action: RemoveModelAction) {
                const { key, prefix } = action.payload

                state[prefix] = omit(state[prefix], key)
            },
        },

        UPDATE: {
            prepare(prefix: ModelPrefix, key: string, field: string, value: unknown) {
                return ({
                    payload: { prefix, key, field, value },
                    meta: { prefix, key, field },
                })
            },

            reducer(state, action: UpdateModelAction) {
                const { prefix, key, field, value } = action.payload

                set(state, `${prefix}.${key}.${field}`, value)
            },
        },

        /**
         * Очистка моделей. которая учитывает список исключений (поля которые не нужно очищать)
         */
        CLEAR(state, action: ClearModelAction) {
            const { prefixes, key } = action.payload

            prefixes.forEach((prefix) => {
                const model = state[prefix][key]

                if (model) {
                    state[prefix][key] = Array.isArray(model) ? [] : {}
                }
            })
        },

        MERGE: {
            prepare(combine: Partial) {
                return ({
                    payload: { combine },
                })
            },

            reducer(state, action: MergeModelAction) {
                const { combine } = action.payload

                return merge(state, combine)
            },
        },

        /**
         * Копирование модели по префиксу и ключу в другую модель, по префиксу и ключу
         */
        COPY: {
            prepare(
                source: CopyAction['payload']['source'],
                target: CopyAction['payload']['target'],
                { mode, sourceMapper }: Pick,
            ) {
                return {
                    payload: {
                        sourceMapper,
                        source,
                        target,
                        mode,
                    },
                }
            },

            reducer() {

            },
        },

        REMOVE_ALL: {
            // eslint-disable-next-line sonarjs/no-identical-functions
            prepare(key: string) {
                return ({
                    payload: { key },
                })
            },

            /**
             * Удаление всех моделей из хранилища
             */
            reducer(state, action: RemoveAllModelAction) {
                const { key } = action.payload

                Object.values(ModelPrefix).forEach((prefix) => {
                    delete state[prefix][key]
                })
            },
        },

        appendFieldToArray: {
            prepare({ key, fieldName, ...options }) {
                return ({
                    meta: { key, field: fieldName, ...options },
                    payload: { key, field: fieldName, ...options },
                })
            },

            reducer(state, action: AppendFieldToArrayAction) {
                const { prefix, key, field, value = {}, primaryKey } = action.payload
                const arrayValue = get(state, `${prefix}.${key}.${field}`)
                const item = primaryKey ? { [primaryKey]: id(), ...value } : value

                if (arrayValue) {
                    arrayValue.push(item)
                } else {
                    set(state, `${prefix}.${key}.${field}`, [item])
                }
            },
        },

        removeFieldFromArray: {
            prepare(prefix: ModelPrefix, key: string, field: string, start: number, end?: number) {
                return ({
                    meta: { prefix, key, field },
                    payload: { prefix, key, field, start, end },
                })
            },

            reducer(state, action: RemoveFieldFromArrayAction) {
                const { prefix, key, field, start, end } = action.payload
                const arrayValue = get(state, `${prefix}.${key}.${field}`, [])

                if (end === undefined) {
                    arrayValue.splice(start, 1)

                    return
                }

                arrayValue.splice(start, end)
            },
        },

        copyFieldArray: {
            prepare(prefix: ModelPrefix, key: string, field: string, index: number, primaryKey?: string) {
                return ({
                    meta: { prefix, key, field, primaryKey },
                    payload: { prefix, key, field, index, primaryKey },
                })
            },

            reducer(state, action: CopyFieldArrayAction) {
                const { prefix, key, field, index, primaryKey } = action.payload
                const arrayValue = get(state, `${prefix}.${key}.${field}`, [])
                let item = arrayValue[index]

                if (primaryKey) {
                    item = { ...item, [primaryKey]: id() }
                }

                arrayValue.push(item)
            },
        },
    },
})

export default modelsSlice.reducer

export const {
    SET: setModel,
    REMOVE: removeModel,
    UPDATE: updateModel,
    CLEAR: clearModel,
    MERGE: combineModels,
    COPY: copyModel,
    REMOVE_ALL: removeAllModel,
    appendFieldToArray,
    removeFieldFromArray,
    copyFieldArray,
} = modelsSlice.actions




© 2015 - 2024 Weber Informatics LLC | Privacy Policy