From 76f2aba35b4e8945456ca2a2857bbe2836b866d7 Mon Sep 17 00:00:00 2001 From: Anu-Ujin Bat-Ulzii Date: Mon, 7 Nov 2022 18:35:08 +0800 Subject: [PATCH 1/5] fix marketplace permission --- .../src/modules/layout/components/navigation/NavigationItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-ui/src/modules/layout/components/navigation/NavigationItem.tsx b/packages/core-ui/src/modules/layout/components/navigation/NavigationItem.tsx index 8bd6427a1f..44610e095b 100644 --- a/packages/core-ui/src/modules/layout/components/navigation/NavigationItem.tsx +++ b/packages/core-ui/src/modules/layout/components/navigation/NavigationItem.tsx @@ -80,7 +80,7 @@ export default function NavigationItem(props: Props) { ); }; - if (plugin.text === 'Settings') { + if (plugin.text === 'Settings' || plugin.text === 'Marketplace') { return {renderItem()}; } From fdae34eca9f9b93b577153678afd10fc68584a58 Mon Sep 17 00:00:00 2001 From: Bat-Amgalan Nasan-Ochir <56122037+Mambatukaa@users.noreply.github.com> Date: Mon, 7 Nov 2022 18:51:31 +0800 Subject: [PATCH 2/5] feat(automations): refactor and make triggers and actions dynamic. (#3721) --- packages/api-utils/src/automations.ts | 150 ++------------ packages/api-utils/src/commonUtils.ts | 21 +- packages/core/src/automations.ts | 14 ++ packages/core/src/index.ts | 2 + .../plugin-automations-api/src/constants.ts | 60 ++++-- .../graphql/resolvers/queries/automations.ts | 100 +++++++-- .../src/graphql/schema/automation.ts | 1 + .../src/components/forms/AutomationForm.tsx | 61 ++++-- .../forms/actions/ActionDetailForm.tsx | 22 +- .../components/forms/actions/ActionsForm.tsx | 11 +- .../src/components/forms/actions/constants.ts | 31 --- .../src/components/forms/actions/index.tsx | 53 +++-- .../src/components/forms/actions/styles.ts | 8 +- .../forms/actions/subForms/CustomCode.tsx | 8 +- .../forms/actions/subForms/Delay.tsx | 6 +- .../forms/actions/subForms/IfForm.tsx | 4 +- .../forms/actions/subForms/SetProperty.tsx | 17 +- .../forms/triggers/TriggerDetailForm.tsx | 5 +- .../components/forms/triggers/TriggerForm.tsx | 12 +- .../src/components/forms/triggers/index.tsx | 2 +- .../src/components/histories/Histories.tsx | 11 +- .../src/components/histories/Row.tsx | 88 +++----- .../src/components/histories/Wrapper.tsx | 9 +- .../plugin-automations-ui/src/constants.ts | 166 --------------- .../src/containers/Histories.tsx | 13 +- .../src/containers/forms/EditAutomation.tsx | 23 ++- .../containers/forms/actions/ActionsForm.tsx | 3 +- .../forms/actions/subForms/IfForm.tsx | 2 +- .../forms/actions/subForms/SetProperty.tsx | 5 +- .../containers/forms/triggers/TriggerForm.tsx | 1 + .../src/graphql/queries.ts | 9 +- packages/plugin-automations-ui/src/styles.ts | 26 --- packages/plugin-automations-ui/src/types.ts | 26 ++- .../src/{utils.ts => utils.tsx} | 27 ++- packages/plugin-cards-api/src/automations.ts | 191 +++++++++++++++++- .../plugin-cards-api/src/messageBroker.ts | 31 +++ .../src/automations/automation.tsx | 27 +++ .../automations/components/ActionResult.tsx | 17 ++ .../automations/components}/BoardItemForm.tsx | 6 +- .../automations/components}/SelectBoard.tsx | 2 +- .../automations/containers}/BoardItemForm.tsx | 4 +- .../plugin-cards-ui/src/automations/styles.ts | 8 + packages/plugin-cards-ui/src/configs.js | 2 + .../plugin-contacts-api/src/automations.ts | 144 ++++++++++--- .../plugin-contacts-api/src/messageBroker.ts | 12 ++ .../src/automations/automation.tsx | 16 ++ .../automations/components/HistoryName.tsx | 31 +++ packages/plugin-contacts-ui/src/configs.js | 2 + packages/plugin-inbox-api/src/automations.ts | 14 ++ packages/plugin-inbox-api/src/configs.ts | 2 + .../plugin-inbox-api/src/messageBroker.ts | 23 +++ .../src/automations/automation.tsx | 16 ++ .../automations/components/HistoryName.tsx | 20 ++ packages/plugin-inbox-ui/src/configs.js | 2 + .../plugin-loyalties-api/src/automations.ts | 18 ++ .../src/automations/automation.tsx | 27 +++ .../automations/components}/ChangeScore.tsx | 13 +- .../automations/components}/LoyaltyForm.tsx | 15 +- .../automations/containers}/LoyaltyForm.tsx | 13 +- packages/plugin-loyalties-ui/src/configs.js | 3 + packages/ui-automations/package.json | 12 ++ .../src/components/forms/actions/Common.tsx | 0 .../forms/actions/placeHolder/Attribution.tsx | 0 .../actions/placeHolder/PlaceHolderInput.tsx | 45 +++-- .../forms/actions/placeHolder/SelectDate.tsx | 0 .../actions/placeHolder/SelectOption.tsx | 0 .../src/components/forms/actions/styles.ts | 39 ++++ .../containers/forms/actions/Attribution.tsx | 0 packages/ui-automations/src/styles.ts | 28 +++ packages/ui-automations/src/types.ts | 13 ++ .../.erxes/webpack.config.js | 1 + 71 files changed, 1143 insertions(+), 651 deletions(-) create mode 100644 packages/core/src/automations.ts rename packages/plugin-automations-ui/src/{utils.ts => utils.tsx} (88%) create mode 100644 packages/plugin-cards-ui/src/automations/automation.tsx create mode 100644 packages/plugin-cards-ui/src/automations/components/ActionResult.tsx rename packages/{plugin-automations-ui/src/components/forms/actions/subForms => plugin-cards-ui/src/automations/components}/BoardItemForm.tsx (95%) rename packages/{plugin-automations-ui/src/components/forms/actions/placeHolder => plugin-cards-ui/src/automations/components}/SelectBoard.tsx (97%) rename packages/{plugin-automations-ui/src/containers/forms/actions/subForms => plugin-cards-ui/src/automations/containers}/BoardItemForm.tsx (93%) create mode 100644 packages/plugin-cards-ui/src/automations/styles.ts create mode 100644 packages/plugin-contacts-ui/src/automations/automation.tsx create mode 100644 packages/plugin-contacts-ui/src/automations/components/HistoryName.tsx create mode 100644 packages/plugin-inbox-api/src/automations.ts create mode 100644 packages/plugin-inbox-ui/src/automations/automation.tsx create mode 100644 packages/plugin-inbox-ui/src/automations/components/HistoryName.tsx create mode 100644 packages/plugin-loyalties-ui/src/automations/automation.tsx rename packages/{plugin-automations-ui/src/components/forms/actions/subForms => plugin-loyalties-ui/src/automations/components}/ChangeScore.tsx (82%) rename packages/{plugin-automations-ui/src/components/forms/actions/subForms => plugin-loyalties-ui/src/automations/components}/LoyaltyForm.tsx (80%) rename packages/{plugin-automations-ui/src/containers/forms/actions/subForms => plugin-loyalties-ui/src/automations/containers}/LoyaltyForm.tsx (75%) create mode 100644 packages/ui-automations/package.json rename packages/{plugin-automations-ui => ui-automations}/src/components/forms/actions/Common.tsx (100%) rename packages/{plugin-automations-ui => ui-automations}/src/components/forms/actions/placeHolder/Attribution.tsx (100%) rename packages/{plugin-automations-ui => ui-automations}/src/components/forms/actions/placeHolder/PlaceHolderInput.tsx (87%) rename packages/{plugin-automations-ui => ui-automations}/src/components/forms/actions/placeHolder/SelectDate.tsx (100%) rename packages/{plugin-automations-ui => ui-automations}/src/components/forms/actions/placeHolder/SelectOption.tsx (100%) create mode 100644 packages/ui-automations/src/components/forms/actions/styles.ts rename packages/{plugin-automations-ui => ui-automations}/src/containers/forms/actions/Attribution.tsx (100%) create mode 100644 packages/ui-automations/src/styles.ts create mode 100644 packages/ui-automations/src/types.ts diff --git a/packages/api-utils/src/automations.ts b/packages/api-utils/src/automations.ts index a0e4174a4d..aaa330ba67 100644 --- a/packages/api-utils/src/automations.ts +++ b/packages/api-utils/src/automations.ts @@ -1,4 +1,5 @@ import * as moment from 'moment'; +import { pluralFormation } from './commonUtils'; export const replacePlaceHolders = async ({ models, @@ -118,16 +119,23 @@ export const OPERATORS = { const getPerValue = async (args: { models; subdomain; - conformity; + relatedItem; rule; target; getRelatedValue; }) => { - const { models, subdomain, conformity, rule, target, getRelatedValue } = args; + const { + models, + subdomain, + relatedItem, + rule, + target, + getRelatedValue + } = args; const { field, operator, value } = rule; - const op1Type = typeof conformity[field]; + const op1Type = typeof relatedItem[field]; - let op1 = conformity[field]; + let op1 = relatedItem[field]; let updatedValue = ( await replacePlaceHolders({ @@ -207,140 +215,22 @@ const getPerValue = async (args: { return updatedValue; }; -const replaceServiceTypes = value => { - return value.replace('cards:', '').replace('contacts:', ''); -}; - -const getRelatedTargets = async ( - subdomain, - triggerType, - action, - execution, - sendCommonMessage -) => { - const { config } = action; - const { target } = execution; - - const { module } = config; - - if (module === triggerType) { - return [target]; - } - - if ( - triggerType === 'inbox:conversation' && - ['cards:task', 'cards:ticket', 'cards:deal'].includes(module) - ) { - return sendCommonMessage({ - subdomain, - serviceName: 'cards', - action: `${module.replace('cards:', '')}s.find`, - data: { - sourceConversationIds: { $in: [target._id] } - }, - isRPC: true - }); - } - - if ( - ['contacts:customer', 'contacts:lead'].includes(triggerType) && - target.isFormSubmission && - ['cards:task', 'cards:ticket', 'cards:deal'].includes(module) - ) { - return sendCommonMessage({ - subdomain, - serviceName: 'cards', - action: `${module.replace('cards:', '')}s.find`, - data: { - sourceConversationIds: { $in: [target.conversationId] } - }, - isRPC: true - }); - } - - if ( - triggerType === 'inbox:conversation' && - ['contacts:customer', 'contacts:company'].includes(module) - ) { - return sendCommonMessage({ - subdomain, - serviceName: 'contacts', - action: `${module.includes('customer') ? 'customers' : 'companies'}.find`, - data: { - _id: target[module.includes('customer') ? 'customerId' : 'companyId'] - }, - isRPC: true - }); - } - - if ( - [ - 'cards:task', - 'cards:ticket', - 'cards:deal', - 'contacts:customer', - 'contacts:company' - ].includes(triggerType) && - [ - 'cards:task', - 'cards:ticket', - 'cards:deal', - 'contacts:customer', - 'contacts:company' - ].includes(module) - ) { - const relType = replaceServiceTypes(module); - - const relTypeIds = await sendCommonMessage({ - subdomain, - serviceName: 'core', - action: 'conformities.savedConformity', - data: { - mainType: replaceServiceTypes(triggerType), - mainTypeId: target._id, - relTypes: [relType] - }, - isRPC: true - }); - - const [serviceName, collectionType] = module.split(':'); - - return sendCommonMessage({ - subdomain, - serviceName, - action: `${collectionType}s.find`, - data: { _id: { $in: relTypeIds } }, - isRPC: true - }); - } - - return []; -}; - export const setProperty = async ({ models, subdomain, - action, + module, + rules, execution, getRelatedValue, - triggerType, + relatedItems, sendCommonMessage }) => { - const { module, rules } = action.config; const { target } = execution; const [serviceName, collectionType] = module.split(':'); const result: any[] = []; - const conformities = await getRelatedTargets( - subdomain, - triggerType, - action, - execution, - sendCommonMessage - ); - - for (const conformity of conformities) { + for (const relatedItem of relatedItems) { const setDoc = {}; const pushDoc = {}; @@ -348,7 +238,7 @@ export const setProperty = async ({ const value = await getPerValue({ models, subdomain, - conformity, + relatedItem, rule, target, getRelatedValue @@ -393,8 +283,8 @@ export const setProperty = async ({ const response = await sendCommonMessage({ subdomain, serviceName, - action: `${collectionType}s.updateMany`, - data: { selector: { _id: conformity._id }, modifier }, + action: `${pluralFormation(collectionType)}.updateMany`, + data: { selector: { _id: relatedItem._id }, modifier }, isRPC: true }); @@ -404,7 +294,7 @@ export const setProperty = async ({ } result.push({ - _id: conformity._id, + _id: relatedItem._id, rules: (Object as any) .values(setDoc) .map(v => String(v)) diff --git a/packages/api-utils/src/commonUtils.ts b/packages/api-utils/src/commonUtils.ts index 20cd2ceb7c..a754b218e1 100644 --- a/packages/api-utils/src/commonUtils.ts +++ b/packages/api-utils/src/commonUtils.ts @@ -8,7 +8,6 @@ export interface IOrderInput { } export const updateOrder = async (collection: any, orders: IOrderInput[]) => { - if (orders.length === 0) { return []; } @@ -29,8 +28,8 @@ export const updateOrder = async (collection: any, orders: IOrderInput[]) => { bulkOps.push({ updateOne: { filter: { _id }, - update: selector, - }, + update: selector + } }); } @@ -59,7 +58,7 @@ export const encryptText = (text: string): IEncryptionData => { algorithm, key, iv: iv.toString('hex'), - encryptedData: encrypted.toString('hex'), + encryptedData: encrypted.toString('hex') }; } catch (e) { throw new Error(e); @@ -71,7 +70,11 @@ export const decryptText = (data: IEncryptionData): string => { const encryptedText = Buffer.from(data.encryptedData, 'hex'); - const decipher = crypto.createDecipheriv(data.algorithm, Buffer.from(data.key), iv); + const decipher = crypto.createDecipheriv( + data.algorithm, + Buffer.from(data.key), + iv + ); // decipher let decrypted = decipher.update(encryptedText); @@ -81,3 +84,11 @@ export const decryptText = (data: IEncryptionData): string => { return decrypted.toString(); }; + +export const pluralFormation = (type: string) => { + if (type[type.length - 1] === 'y') { + return type.slice(0, -1) + 'ies'; + } + + return type + 's'; +}; diff --git a/packages/core/src/automations.ts b/packages/core/src/automations.ts new file mode 100644 index 0000000000..d9c4afd37c --- /dev/null +++ b/packages/core/src/automations.ts @@ -0,0 +1,14 @@ +export default { + constants: { + triggers: [ + { + type: 'core:user', + img: 'automation4.svg', + icon: 'users', + label: 'Team member', + description: + 'Start with a blank workflow that enralls and is triggered off team members' + } + ] + } +}; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index a425884b5c..ecbb7cbe6a 100755 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -50,6 +50,7 @@ import forms from './forms'; import { generateModels } from './connectionResolver'; import { authCookieOptions, getSubdomain } from '@erxes/api-utils/src/core'; import segments from './segments'; +import automations from './automations'; import { moduleObjects } from './data/permissions/actions/permission'; const { @@ -301,6 +302,7 @@ httpServer.listen(PORT, async () => { logs: { providesActivityLog: true, consumers: logs }, forms, segments, + automations, permissions: moduleObjects } }); diff --git a/packages/plugin-automations-api/src/constants.ts b/packages/plugin-automations-api/src/constants.ts index a8349d3caf..f78e8324f7 100644 --- a/packages/plugin-automations-api/src/constants.ts +++ b/packages/plugin-automations-api/src/constants.ts @@ -1,20 +1,46 @@ export const ACTIONS = { - WAIT: "wait", - IF: "if", - SET_PROPERTY: "setProperty", - CREATE_TASK: "cards:task.create", - CREATE_TICKET: "cards:ticket.create", - CREATE_DEAL: "cards:deal.create", - CREATE_VOUCHER: "loyalties:voucher.create", - CHANGE_SCORE: "loyalties:scoreLog.create" + WAIT: 'wait', + IF: 'if', + SET_PROPERTY: 'setProperty' }; -export const TRIGGER_TYPES = { - LEAD: 'contacts:lead', - CUSTOMER: 'contacts:customer', - COMPANY: 'contacts:company', - DEAL: 'cards:deal', - TASK: 'cards:task', - TICKET: 'cards:ticket', - CONVERSATIONS: 'inbox:conversations', -} +export const UI_ACTIONS = [ + { + type: 'if', + icon: 'sitemap-1', + label: 'Branches', + description: 'Create simple or if/then branches', + isAvailable: true + }, + { + type: 'setProperty', + icon: 'flask', + label: 'Manage properties', + description: + 'Update existing default or custom properties for Contacts, Companies, Cards, Conversations', + isAvailable: true + }, + { + type: 'delay', + icon: 'hourglass', + label: 'Delay', + description: + 'Delay the next action with a timeframe, a specific event or activity', + isAvailable: true + }, + { + type: 'workflow', + icon: 'glass-martini-alt', + label: 'Workflow', + description: + 'Enroll in another workflow, trigger outgoing webhook or write custom code', + isAvailable: false + }, + { + type: 'externalCommunications', + icon: 'fast-mail', + label: 'External communications', + description: 'Send email, SMS or in-app messenger messages to Contacts', + isAvailable: false + } +]; diff --git a/packages/plugin-automations-api/src/graphql/resolvers/queries/automations.ts b/packages/plugin-automations-api/src/graphql/resolvers/queries/automations.ts index c69ffd70c8..5a9ff525f8 100644 --- a/packages/plugin-automations-api/src/graphql/resolvers/queries/automations.ts +++ b/packages/plugin-automations-api/src/graphql/resolvers/queries/automations.ts @@ -1,7 +1,13 @@ import { paginate } from '@erxes/api-utils/src'; -import { checkPermission, requireLogin } from '@erxes/api-utils/src/permissions'; +import { + checkPermission, + requireLogin +} from '@erxes/api-utils/src/permissions'; import { IContext } from '../../../connectionResolver'; import { sendSegmentsMessage } from '../../../messageBroker'; +import { ITrigger } from '../../../models/definitions/automaions'; +import { serviceDiscovery } from '../../../configs'; +import { UI_ACTIONS } from '../../../constants'; interface IListArgs { status: string; @@ -39,7 +45,7 @@ const generateFilter = (params: IListArgs) => { filter.name = new RegExp(`.*${searchValue}.*`, 'i'); } return filter; -} +}; const automationQueries = { /** @@ -77,15 +83,25 @@ const automationQueries = { /** * Get one automation */ - async automationDetail(_root, { _id }: { _id: string }, { models }: IContext) { + async automationDetail( + _root, + { _id }: { _id: string }, + { models }: IContext + ) { return models.Automations.getAutomation(_id); }, /** * Automations note list */ - automationNotes(_root, params: { automationId: string }, { models }: IContext) { - return models.Notes.find({ automationId: params.automationId }).sort({ createdAt: -1 }); + automationNotes( + _root, + params: { automationId: string }, + { models }: IContext + ) { + return models.Notes.find({ automationId: params.automationId }).sort({ + createdAt: -1 + }); }, /** @@ -125,13 +141,17 @@ const automationQueries = { filter.createdAt = { $lte: endDate }; } - return paginate( - models.Executions.find(filter).sort({ createdAt: -1 }), - { page, perPage } - ) + return paginate(models.Executions.find(filter).sort({ createdAt: -1 }), { + page, + perPage + }); }, - async automationConfigPrievewCount(_root, params: { config: any }, { subdomain }: IContext) { + async automationConfigPrievewCount( + _root, + params: { config: any }, + { subdomain }: IContext + ) { const config = params.config; if (!config) { return; @@ -142,7 +162,12 @@ const automationQueries = { return; } - const segment = await sendSegmentsMessage({ subdomain, action: 'findOne', data: { _id: contentId }, isRPC: true }); + const segment = await sendSegmentsMessage({ + subdomain, + action: 'findOne', + data: { _id: contentId }, + isRPC: true + }); if (!segment) { return; @@ -150,18 +175,22 @@ const automationQueries = { const result = await sendSegmentsMessage({ subdomain, - action: "fetchSegment", + action: 'fetchSegment', data: { segmentId: segment._id, - options: { returnCount: true }, + options: { returnCount: true } }, - isRPC: true, + isRPC: true }); return result; }, - async automationsTotalCount(_root, { status }: { status: string }, { models }: IContext) { + async automationsTotalCount( + _root, + { status }: { status: string }, + { models }: IContext + ) { const filter: any = {}; if (status) { @@ -169,6 +198,47 @@ const automationQueries = { } return models.Automations.find(filter).countDocuments(); + }, + + async automationConstants(_root, {}) { + const services = await serviceDiscovery.getServices(); + + const constants: { + triggersConst: ITrigger[]; + triggerTypesConst: string[]; + actionsConst: any[]; + propertyTypesConst: Array<{ value: string; label: string }>; + } = { + triggersConst: [], + triggerTypesConst: [], + actionsConst: [...UI_ACTIONS], + propertyTypesConst: [] + }; + + for (const serviceName of services) { + const service = await serviceDiscovery.getService(serviceName, true); + const meta = service.config?.meta || {}; + + if (meta && meta.automations && meta.automations.constants) { + const pluginConstants = meta.automations.constants || {}; + const { triggers = [], actions = [] } = pluginConstants; + + for (const trigger of triggers) { + constants.triggersConst.push(trigger); + constants.triggerTypesConst.push(trigger.type); + constants.propertyTypesConst.push({ + value: trigger.type, + label: trigger.label + }); + } + + for (const action of actions) { + constants.actionsConst.push(action); + } + } + } + + return constants; } }; diff --git a/packages/plugin-automations-api/src/graphql/schema/automation.ts b/packages/plugin-automations-api/src/graphql/schema/automation.ts index fcad3416be..c5c3d956f8 100644 --- a/packages/plugin-automations-api/src/graphql/schema/automation.ts +++ b/packages/plugin-automations-api/src/graphql/schema/automation.ts @@ -133,6 +133,7 @@ export const queries = ` automationHistories(${historiesParams}): [AutomationHistory] automationConfigPrievewCount(config: JSON): Int automationsTotalCount(status: String): automationsTotalCountResponse + automationConstants: JSON `; const commonFields = ` diff --git a/packages/plugin-automations-ui/src/components/forms/AutomationForm.tsx b/packages/plugin-automations-ui/src/components/forms/AutomationForm.tsx index ccdd5c132e..f12e5676e5 100644 --- a/packages/plugin-automations-ui/src/components/forms/AutomationForm.tsx +++ b/packages/plugin-automations-ui/src/components/forms/AutomationForm.tsx @@ -1,3 +1,9 @@ +import { jsPlumb } from 'jsplumb'; +import jquery from 'jquery'; +import RTG from 'react-transition-group'; +import React from 'react'; +import { AutomationConstants } from '../../types'; +import { IAction } from '@erxes/ui-automations/src/types'; import { ActionBarButtonsWrapper, AutomationFormContainer, @@ -6,15 +12,15 @@ import { CenterBar, Container, RightDrawerContainer, - ScrolledContent, Title, ToggleWrapper, ZoomActions, ZoomIcon } from '../../styles'; +import { ScrolledContent } from '@erxes/ui-automations/src/styles'; import { Alert, __ } from 'coreui/utils'; import { BarItems, HeightedWrapper } from '@erxes/ui/src/layout/styles'; -import { IAction, IAutomation, IAutomationNote, ITrigger } from '../../types'; +import { IAutomation, IAutomationNote, ITrigger } from '../../types'; import { TabTitle, Tabs } from '@erxes/ui/src/components/tabs'; import { connection, @@ -30,6 +36,7 @@ import { yesEndPoint } from '../../utils'; +import TemplateForm from '../../containers/forms/TemplateForm'; import ActionDetailForm from './actions/ActionDetailForm'; import ActionsForm from '../../containers/forms/actions/ActionsForm'; import Button from '@erxes/ui/src/components/Button'; @@ -43,16 +50,10 @@ import { Link } from 'react-router-dom'; import Modal from 'react-bootstrap/Modal'; import NoteFormContainer from '../../containers/forms/NoteForm'; import PageContent from '@erxes/ui/src/layout/components/PageContent'; -import RTG from 'react-transition-group'; -import React from 'react'; -import { TRIGGER_TYPES } from '../../constants'; -import TemplateForm from '../../containers/forms/TemplateForm'; import Toggle from '@erxes/ui/src/components/Toggle'; import TriggerDetailForm from './triggers/TriggerDetailForm'; import TriggerForm from '../../containers/forms/triggers/TriggerForm'; import Wrapper from '@erxes/ui/src/layout/components/Wrapper'; -import jquery from 'jquery'; -import { jsPlumb } from 'jsplumb'; const plumb: any = jsPlumb; let instance; @@ -65,6 +66,7 @@ type Props = { id: string; history: any; queryParams: any; + constants: AutomationConstants; }; type State = { @@ -536,7 +538,11 @@ class AutomationForm extends React.Component { } renderCount(item: ITrigger | IAction) { - if (item.count && TRIGGER_TYPES.includes(item.type)) { + const { + constants: { triggerTypesConst } + } = this.props; + + if (item.count && triggerTypesConst.includes(item.type)) { return `(${item.count})`; } @@ -588,7 +594,7 @@ class AutomationForm extends React.Component { if (instance.getSelector(`#${idElm}`).length > 0) { instance.draggable(instance.getSelector(`#${idElm}`), { cursor: 'move', - stop: function(params) { + stop(params) { item.style = jquery(`#${idElm}`).attr('style'); } }); @@ -615,7 +621,7 @@ class AutomationForm extends React.Component { instance.draggable(instance.getSelector(`#${idElm}`), { cursor: 'move', - stop: function(params) { + stop(params) { item.style = jquery(`#${idElm}`).attr('style'); } }); @@ -734,6 +740,10 @@ class AutomationForm extends React.Component { selectedContentId } = this.state; + const { + constants: { triggersConst, actionsConst, propertyTypesConst } + } = this.props; + const onBack = () => this.setState({ showTrigger: false }); const onBackAction = () => this.setState({ showAction: false }); @@ -756,7 +766,12 @@ class AutomationForm extends React.Component { ); } - return ; + return ( + + ); } if (currentTab === 'actions') { @@ -773,12 +788,19 @@ class AutomationForm extends React.Component { addAction={this.addAction} closeModal={onBackAction} triggerType={getTriggerType(actions, triggers, activeAction.id)} + actionsConst={actionsConst} + propertyTypesConst={propertyTypesConst} /> ); } - return ; + return ( + + ); } return null; @@ -825,14 +847,23 @@ class AutomationForm extends React.Component { ); } - const { automation } = this.props; + const { + automation, + constants: { triggersConst, actionsConst } + } = this.props; if (!this.state.isActionTab) { if (!automation) { return
; } - return ; + return ( + + ); } return ( diff --git a/packages/plugin-automations-ui/src/components/forms/actions/ActionDetailForm.tsx b/packages/plugin-automations-ui/src/components/forms/actions/ActionDetailForm.tsx index 9dddf7a7a9..afbb23b035 100644 --- a/packages/plugin-automations-ui/src/components/forms/actions/ActionDetailForm.tsx +++ b/packages/plugin-automations-ui/src/components/forms/actions/ActionDetailForm.tsx @@ -1,4 +1,4 @@ -import { IAction } from '../../../types'; +import { IAction } from '@erxes/ui-automations/src/types'; import React from 'react'; import { ActionForms } from './'; @@ -7,6 +7,8 @@ type Props = { triggerType: string; addAction: (action: IAction, actionId?: string, config?: any) => void; closeModal: () => void; + actionsConst: any[]; + propertyTypesConst: any[]; }; class ActionDetailForm extends React.Component { @@ -21,23 +23,9 @@ class ActionDetailForm extends React.Component { render() { const { activeAction } = this.props; - let { type } = activeAction; + const { type } = activeAction; - if (['cards:deal.create', 'cards:task.create', 'cards:ticket.create'].includes(type)) { - type = 'boardItem'; - } - - if ('loyalties:voucher.create' === type ) { - type = 'voucher' - } - - if ('loyalties:scoreLog.create' === type ) { - type = 'changeScore' - } - - const Content = ActionForms[type] || ActionForms.default; - - return ; + return <>{ActionForms({ onSave: this.onSave, ...this.props })[type]}; } } diff --git a/packages/plugin-automations-ui/src/components/forms/actions/ActionsForm.tsx b/packages/plugin-automations-ui/src/components/forms/actions/ActionsForm.tsx index 862c5f81b0..f2deacd837 100644 --- a/packages/plugin-automations-ui/src/components/forms/actions/ActionsForm.tsx +++ b/packages/plugin-automations-ui/src/components/forms/actions/ActionsForm.tsx @@ -1,9 +1,9 @@ import { __ } from '@erxes/ui/src/utils/core'; import React from 'react'; -import { TriggerTabs, ScrolledContent } from '../../../styles'; +import { TriggerTabs } from '../../../styles'; +import { ScrolledContent } from '@erxes/ui-automations/src/styles'; import Icon from '@erxes/ui/src/components/Icon'; -import { ACTIONS } from '../../../constants'; -import { IAction } from '../../../types'; +import { IAction } from '@erxes/ui-automations/src/types'; import { TabTitle, Tabs } from '@erxes/ui/src/components/tabs'; import Tip from '@erxes/ui/src/components/Tip'; import EmptyState from '@erxes/ui/src/components/EmptyState'; @@ -11,6 +11,7 @@ import { ActionBox } from './styles'; type Props = { onClickAction: (action: IAction) => void; + actionsConst: any[]; }; type State = { @@ -91,7 +92,9 @@ class ActionsForm extends React.Component { ); const actions = - this.state.currentTab === 'favourite' ? localStorageActions : ACTIONS; + this.state.currentTab === 'favourite' + ? localStorageActions + : this.props.actionsConst; if (actions.length === 0 && localStorageActions.length === 0) { return ( diff --git a/packages/plugin-automations-ui/src/components/forms/actions/constants.ts b/packages/plugin-automations-ui/src/components/forms/actions/constants.ts index 4f4f397c07..cdbfa86f65 100644 --- a/packages/plugin-automations-ui/src/components/forms/actions/constants.ts +++ b/packages/plugin-automations-ui/src/components/forms/actions/constants.ts @@ -1,34 +1,3 @@ -export const PROPERTY_TYPES = [ - { - value: 'contacts:customer', - label: 'Contact' - }, - { - value: 'contacts:company', - label: 'Company' - }, - { - value: 'cards:deal', - label: 'Deal' - }, - { - value: 'cards:task', - label: 'Task' - }, - { - value: 'cards:ticket', - label: 'Ticket' - }, - { - value: 'inbox:conversation', - label: 'Conversation' - }, - { - value: 'core:user', - label: 'Team Member' - } -]; - export const PROPERTY_FIELD = [ { value: 'size', diff --git a/packages/plugin-automations-ui/src/components/forms/actions/index.tsx b/packages/plugin-automations-ui/src/components/forms/actions/index.tsx index 18220c6d48..3665b9c334 100644 --- a/packages/plugin-automations-ui/src/components/forms/actions/index.tsx +++ b/packages/plugin-automations-ui/src/components/forms/actions/index.tsx @@ -1,30 +1,56 @@ -import { ACTIONS } from '../../../constants'; -import BoardItemForm from '../../../containers/forms/actions/subForms/BoardItemForm'; import IfForm from '../../../containers/forms/actions/subForms/IfForm'; import SetProperty from '../../../containers/forms/actions/subForms/SetProperty'; -import { IAction } from '../../../types'; +import { IAction } from '@erxes/ui-automations/src/types'; import Button from '@erxes/ui/src/components/Button'; import { ModalFooter } from '@erxes/ui/src/styles/main'; import { __ } from '@erxes/ui/src/utils/core'; import React from 'react'; -import Common from './Common'; +import Common from '@erxes/ui-automations/src/components/forms/actions/Common'; import CustomCode from './subForms/CustomCode'; import Delay from './subForms/Delay'; -import LoyaltyForm from '../../../containers/forms/actions/subForms/LoyaltyForm'; -import ChangeScore from './subForms/ChangeScore'; +import { renderDynamicComponent } from '../../../utils'; type Props = { onSave: () => void; closeModal: () => void; activeAction: IAction; addAction: (action: IAction, actionId?: string, config?: any) => void; + actionsConst: any[]; + propertyTypesConst: any[]; }; +const renderExtraContent = props => { + const { + activeAction: { type } + } = props; + + const response = { + default: , + delay: , + setProperty: , + if: , + customCode: + }; + + const Component = renderDynamicComponent( + { + ...props, + componentType: 'actionForm' + }, + type + ); + + if (Component) { + response[type] = Component; + } + + return response; +}; class DefaultForm extends React.Component { render() { - const { activeAction, onSave, closeModal } = this.props; + const { activeAction, onSave, closeModal, actionsConst } = this.props; - const currentAction = ACTIONS.find( + const currentAction = actionsConst.find( action => action.type === activeAction.type && action.component ); @@ -57,13 +83,4 @@ class DefaultForm extends React.Component { } } -export const ActionForms = { - default: DefaultForm, - delay: Delay, - setProperty: SetProperty, - if: IfForm, - boardItem: BoardItemForm, - customCode: CustomCode, - voucher: LoyaltyForm, - changeScore: ChangeScore -}; +export const ActionForms = renderExtraContent; diff --git a/packages/plugin-automations-ui/src/components/forms/actions/styles.ts b/packages/plugin-automations-ui/src/components/forms/actions/styles.ts index 2de829a04b..a91ad2d875 100644 --- a/packages/plugin-automations-ui/src/components/forms/actions/styles.ts +++ b/packages/plugin-automations-ui/src/components/forms/actions/styles.ts @@ -1,7 +1,7 @@ import styled from 'styled-components'; import styledTS from 'styled-components-ts'; import { dimensions, colors } from '@erxes/ui/src/styles'; -import { TriggerBox, DrawerDetail } from '../../../styles'; +import { TriggerBox } from '../../../styles'; import { rgba } from '@erxes/ui/src/styles/ecolor'; export const ActionFooter = styled.div` @@ -90,9 +90,3 @@ export const ActionBox = styledTS<{ } } `; - -export const BoardItemWrapper = styled(DrawerDetail)` - > div > div { - padding: 0; - } -`; diff --git a/packages/plugin-automations-ui/src/components/forms/actions/subForms/CustomCode.tsx b/packages/plugin-automations-ui/src/components/forms/actions/subForms/CustomCode.tsx index 5a96b20007..30403f12b4 100644 --- a/packages/plugin-automations-ui/src/components/forms/actions/subForms/CustomCode.tsx +++ b/packages/plugin-automations-ui/src/components/forms/actions/subForms/CustomCode.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import { IAction } from '../../../../types'; -import Common from '../Common'; -import { BoardHeader, DrawerDetail } from '../../../../styles'; -import { __ } from '@erxes/ui/src/utils/core'; +import { IAction } from '@erxes/ui-automations/src/types'; +import Common from '@erxes/ui-automations/src/components/forms/actions/Common'; +import { BoardHeader, DrawerDetail } from '@erxes/ui-automations/src/styles'; +import { __ } from 'coreui/utils'; import Editor from 'react-simple-code-editor'; import { highlight, languages } from 'prismjs/components/prism-core'; import 'prismjs/components/prism-clike'; diff --git a/packages/plugin-automations-ui/src/components/forms/actions/subForms/Delay.tsx b/packages/plugin-automations-ui/src/components/forms/actions/subForms/Delay.tsx index f865274fda..292d893e1c 100644 --- a/packages/plugin-automations-ui/src/components/forms/actions/subForms/Delay.tsx +++ b/packages/plugin-automations-ui/src/components/forms/actions/subForms/Delay.tsx @@ -1,8 +1,8 @@ import React from 'react'; import Select from 'react-select-plus'; -import { IAction } from '../../../../types'; -import Common from '../Common'; -import { BoardHeader, DrawerDetail } from '../../../../styles'; +import { IAction } from '@erxes/ui-automations/src/types'; +import Common from '@erxes/ui-automations/src/components/forms/actions/Common'; +import { BoardHeader, DrawerDetail } from '@erxes/ui-automations/src/styles'; import FormGroup from '@erxes/ui/src/components/form/Group'; import ControlLabel from '@erxes/ui/src/components/form/Label'; import { __ } from '@erxes/ui/src/utils/core'; diff --git a/packages/plugin-automations-ui/src/components/forms/actions/subForms/IfForm.tsx b/packages/plugin-automations-ui/src/components/forms/actions/subForms/IfForm.tsx index 5da2e2a645..acde4bab2b 100644 --- a/packages/plugin-automations-ui/src/components/forms/actions/subForms/IfForm.tsx +++ b/packages/plugin-automations-ui/src/components/forms/actions/subForms/IfForm.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import { IAction } from '../../../../types'; +import { IAction } from '@erxes/ui-automations/src/types'; import SegmentsForm from '@erxes/ui-segments/src/containers/form/SegmentsForm'; -import { ScrolledContent } from '../../../../styles'; +import { ScrolledContent } from '@erxes/ui-automations/src/styles'; type Props = { activeAction: IAction; diff --git a/packages/plugin-automations-ui/src/components/forms/actions/subForms/SetProperty.tsx b/packages/plugin-automations-ui/src/components/forms/actions/subForms/SetProperty.tsx index ece23884f7..009609b5ee 100644 --- a/packages/plugin-automations-ui/src/components/forms/actions/subForms/SetProperty.tsx +++ b/packages/plugin-automations-ui/src/components/forms/actions/subForms/SetProperty.tsx @@ -1,17 +1,18 @@ +import { DrawerDetail } from '@erxes/ui-automations/src/styles'; +import { IAction } from '@erxes/ui-automations/src/types'; import { Alert, __ } from 'coreui/utils'; -import { PROPERTY_OPERATOR, PROPERTY_TYPES } from '../constants'; import Button from '@erxes/ui/src/components/Button'; -import Common from '../Common'; import ControlLabel from '@erxes/ui/src/components/form/Label'; -import { DrawerDetail } from '../../../../styles'; import { FieldsCombinedByType } from '@erxes/ui-forms/src/settings/properties/types'; import FormGroup from '@erxes/ui/src/components/form/Group'; -import { GroupWrapper } from '@erxes/ui-segments/src/styles'; -import { IAction } from '../../../../types'; -import PlaceHolderInput from '../placeHolder/PlaceHolderInput'; import React from 'react'; import Select from 'react-select-plus'; + +import Common from '@erxes/ui-automations/src/components/forms/actions/Common'; +import { PROPERTY_OPERATOR } from '../constants'; +import PlaceHolderInput from '@erxes/ui-automations/src/components/forms/actions/placeHolder/PlaceHolderInput'; +import { GroupWrapper } from '@erxes/ui-segments/src/styles'; import Tip from '@erxes/ui/src/components/Tip'; import client from '@erxes/ui/src/apolloClient'; import { excludedNames } from '../../../../containers/forms/actions/subForms/SetProperty'; @@ -24,6 +25,7 @@ type Props = { triggerType: string; addAction: (action: IAction, actionId?: string, config?: any) => void; fields: FieldsCombinedByType[]; + propertyTypesConst: any[]; }; type State = { @@ -206,6 +208,7 @@ class SetProperty extends React.Component { renderContent() { const { type } = this.state; + const { propertyTypesConst } = this.props; return ( @@ -215,7 +218,7 @@ class SetProperty extends React.Component {