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

sagas.conditions.ts Maven / Gradle / Ivy

The newest version!
import {
    fork,
    takeEvery,
    call,
    select,
} from 'redux-saga/effects'
import get from 'lodash/get'

import evalExpression from '../utils/evalExpression'
import {
    setModel,
    clearModel,
    appendFieldToArray,
    removeFieldFromArray,
    copyFieldArray,
    updateModel,
    combineModels,
} from '../ducks/models/store'
import { MergeModelAction } from '../ducks/models/Actions'
import { registerButton } from '../ducks/toolbar/store'
import { RegisterButton } from '../ducks/toolbar/Actions'
import { toolbarSelector } from '../ducks/toolbar/selectors'
import { State as ToolbarState, Condition } from '../ducks/toolbar/Toolbar'
// eslint-disable-next-line import/no-cycle
import { resolveButton } from '../ducks/toolbar/sagas'
import { State as GlobalState } from '../ducks/State'

/**
 * резолв кондишена, резолв message из expression
 * @param conditions
 * @param state
 * @returns {object}
 */
export const resolveConditions = (
    state: GlobalState,
    conditions: Condition[] = [],
): { resolve: boolean, message: string | undefined } => {
    let resolve = true

    for (const { expression, modelLink, message } of conditions) {
        const context = get(state, modelLink, {})
        const evalResult = evalExpression(expression, context)

        resolve = resolve && !!evalResult

        // until find first message
        if (!evalResult && message) {
            return { resolve: false, message }
        }
    }

    return { resolve, message: undefined }
}

function* callConditionHandlers(
    prefix: string,
    key: string,
) {
    const modelLink = `models.${prefix}['${key}']`
    const toolbar: ToolbarState = yield select(toolbarSelector)

    for (const buttons of Object.values(toolbar)) {
        const temp = new Set()

        for (const [buttonId, button] of Object.entries(buttons)) {
            if (
                (button.conditions?.enabled?.some(c => c.modelLink === modelLink)) ||
                (button.conditions?.visible?.some(c => c.modelLink === modelLink))
            ) {
                if (!temp.has(buttonId)) {
                    yield fork(resolveButton, button)
                }

                temp.add(buttonId)
            }
        }
    }
}

interface WatchModelPayload {
    prefix: string
    prefixes: string
    key: string
}

function* watchModel(action: { payload: WatchModelPayload }) {
    const { prefix, prefixes, key } = action.payload

    // setModel пришлет prefix
    if (prefix) {
        yield call(callConditionHandlers, prefix, key)

        // clearModel пришлет prefixes
    } else if (prefixes) {
        for (const prefix of prefixes) {
            yield call(callConditionHandlers, prefix, key)
        }
    }
}

function* watchCombineModels({ payload: { combine } }: MergeModelAction) {
    for (const [prefix, models] of Object.entries(combine)) {
        for (const key of Object.keys(models)) {
            yield call(callConditionHandlers, prefix, key)
        }
    }
}

function* conditionWatchers() {
    yield takeEvery(registerButton, watchRegister)
    // @ts-ignore проблема с типизацией saga
    yield takeEvery([
        setModel,
        clearModel,
        updateModel,
        appendFieldToArray,
        removeFieldFromArray,
        copyFieldArray,
    ], watchModel)
    yield takeEvery(combineModels, watchCombineModels)
}

function* watchRegister({ payload }: RegisterButton) {
    yield fork(resolveButton, payload)
}

export const conditionsSaga = [fork(conditionWatchers)]




© 2015 - 2024 Weber Informatics LLC | Privacy Policy