import _groupBy from 'lodash/groupBy' import _last from 'lodash/last' import _uniq from 'lodash/uniq' import { assert } from '../../utils' import { updatePipeline } from '../pipeline/pipeline.slice' import { updateRelation } from '../relations/relations.slice' import { selectAction, selectAllProducedAttributesBeforeActionRelation, selectNormalizedActionRelationsSequence, } from '../selectors' import { Store } from '../store' /** * Connect two actions in the store * And update the relation * @param store * @returns */ export const connect = (store: Store) => ( leftRelId: string, rightRelId: string ) => { assert(!!leftRelId, 'leftId is required') assert(!!rightRelId, 'rightId is required') assert(leftRelId !== rightRelId, 'leftId cannot be equal to rightId') const { relations } = store.getState() const [left] = relations.filter(({ id }) => id === leftRelId) const [right] = relations.filter(({ id }) => id === rightRelId) assert(!!left, `relation with id=${leftRelId} not found`) assert(!!right, `relation with id=${rightRelId} not found`) store.dispatch( updateRelation({ id: leftRelId, rel: _uniq([...left.rel, right.id]), }) ) } /** * Auto-assigns a compatible attributes of previous pipeline rels * @param store * @returns */ export const autoAssignLeftAttributes = (store: Store) => (relId: string) => { assert(!!relId, 'relId is required') const state = store.getState() const action = selectAction(relId)(state) const requiredAttrs = action.lAttributes.filter(attr => attr.required) let attrs = selectAllProducedAttributesBeforeActionRelation(relId)(state) // TODO: Should be smart if consume attrGlobalId doesn't exist only then replace // TODO: get a current relation pipeline consume and procced const entries = requiredAttrs .map(requiredAttr => { const _attrsMap = _groupBy(attrs, attr => attr.datatype) const _attr = _last(_attrsMap[requiredAttr.datatype] || []) if (!_attr) { return [] } attrs = attrs.filter(attr => attr.globalId !== _attr.globalId) return [requiredAttr.id, _attr.globalId] }) .filter(entry => !!entry.length) store.dispatch( updatePipeline({ id: relId, consume: Object.fromEntries(entries), }) ) } /** * Two relations connection checking function * @param store * @returns */ export const canConnect = (store: Store) => ( leftRelId: string, rightRelId: string ): boolean => { assert(!!leftRelId, 'leftId is required') assert(!!rightRelId, 'rightId is required') assert(leftRelId !== rightRelId, 'leftId cannot be equal to rightId') const state = store.getState() const relations = selectNormalizedActionRelationsSequence()(state) const leftRelIndex = relations.findIndex(rel => rel.id === leftRelId) const rightRelIndex = relations.findIndex(rel => rel.id === rightRelId) assert(leftRelIndex !== -1, `relation with id=${leftRelId} not found`) return rightRelIndex > leftRelIndex || rightRelIndex === -1 }