mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 11:08:04 +00:00 
			
		
		
		
	feat: Rewrite automations/methodsMixin to a composable (#9956)
				
					
				
			Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
This commit is contained in:
		
							
								
								
									
										295
									
								
								app/javascript/dashboard/composables/spec/useAutomation.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								app/javascript/dashboard/composables/spec/useAutomation.spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,295 @@ | |||||||
|  | import { useAutomation } from '../useAutomation'; | ||||||
|  | import { useStoreGetters, useMapGetter } from 'dashboard/composables/store'; | ||||||
|  | import { useAlert } from 'dashboard/composables'; | ||||||
|  | import { useI18n } from '../useI18n'; | ||||||
|  | import * as automationHelper from 'dashboard/helper/automationHelper'; | ||||||
|  | import { | ||||||
|  |   customAttributes, | ||||||
|  |   agents, | ||||||
|  |   teams, | ||||||
|  |   labels, | ||||||
|  |   statusFilterOptions, | ||||||
|  |   campaigns, | ||||||
|  |   contacts, | ||||||
|  |   inboxes, | ||||||
|  |   languages, | ||||||
|  |   countries, | ||||||
|  |   slaPolicies, | ||||||
|  | } from 'dashboard/helper/specs/fixtures/automationFixtures.js'; | ||||||
|  | import { MESSAGE_CONDITION_VALUES } from 'dashboard/constants/automation'; | ||||||
|  |  | ||||||
|  | vi.mock('dashboard/composables/store'); | ||||||
|  | vi.mock('dashboard/composables'); | ||||||
|  | vi.mock('../useI18n'); | ||||||
|  | vi.mock('dashboard/helper/automationHelper'); | ||||||
|  |  | ||||||
|  | describe('useAutomation', () => { | ||||||
|  |   beforeEach(() => { | ||||||
|  |     useStoreGetters.mockReturnValue({ | ||||||
|  |       'attributes/getAttributes': { value: customAttributes }, | ||||||
|  |       'attributes/getAttributesByModel': { | ||||||
|  |         value: model => { | ||||||
|  |           return model === 'conversation_attribute' | ||||||
|  |             ? [{ id: 1, name: 'Conversation Attribute' }] | ||||||
|  |             : [{ id: 2, name: 'Contact Attribute' }]; | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |     useMapGetter.mockImplementation(getter => { | ||||||
|  |       const getterMap = { | ||||||
|  |         'agents/getAgents': agents, | ||||||
|  |         'campaigns/getAllCampaigns': campaigns, | ||||||
|  |         'contacts/getContacts': contacts, | ||||||
|  |         'inboxes/getInboxes': inboxes, | ||||||
|  |         'labels/getLabels': labels, | ||||||
|  |         'teams/getTeams': teams, | ||||||
|  |         'sla/getSLA': slaPolicies, | ||||||
|  |       }; | ||||||
|  |       return { value: getterMap[getter] }; | ||||||
|  |     }); | ||||||
|  |     useI18n.mockReturnValue({ t: key => key }); | ||||||
|  |     useAlert.mockReturnValue(vi.fn()); | ||||||
|  |  | ||||||
|  |     // Mock getConditionOptions for different types | ||||||
|  |     automationHelper.getConditionOptions.mockImplementation(options => { | ||||||
|  |       const { type } = options; | ||||||
|  |       switch (type) { | ||||||
|  |         case 'status': | ||||||
|  |           return statusFilterOptions; | ||||||
|  |         case 'team_id': | ||||||
|  |           return teams; | ||||||
|  |         case 'assignee_id': | ||||||
|  |           return agents; | ||||||
|  |         case 'contact': | ||||||
|  |           return contacts; | ||||||
|  |         case 'inbox_id': | ||||||
|  |           return inboxes; | ||||||
|  |         case 'campaigns': | ||||||
|  |           return campaigns; | ||||||
|  |         case 'browser_language': | ||||||
|  |           return languages; | ||||||
|  |         case 'country_code': | ||||||
|  |           return countries; | ||||||
|  |         case 'message_type': | ||||||
|  |           return MESSAGE_CONDITION_VALUES; | ||||||
|  |         default: | ||||||
|  |           return []; | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     // Mock getActionOptions for different types | ||||||
|  |     automationHelper.getActionOptions.mockImplementation(options => { | ||||||
|  |       const { type } = options; | ||||||
|  |       switch (type) { | ||||||
|  |         case 'add_label': | ||||||
|  |           return labels; | ||||||
|  |         case 'assign_team': | ||||||
|  |           return teams; | ||||||
|  |         case 'assign_agent': | ||||||
|  |           return agents; | ||||||
|  |         case 'send_email_to_team': | ||||||
|  |           return teams; | ||||||
|  |         case 'send_message': | ||||||
|  |           return []; | ||||||
|  |         case 'add_sla': | ||||||
|  |           return slaPolicies; | ||||||
|  |         default: | ||||||
|  |           return []; | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('initializes computed properties correctly', () => { | ||||||
|  |     const { | ||||||
|  |       agents: computedAgents, | ||||||
|  |       campaigns: computedCampaigns, | ||||||
|  |       contacts: computedContacts, | ||||||
|  |       inboxes: computedInboxes, | ||||||
|  |       labels: computedLabels, | ||||||
|  |       teams: computedTeams, | ||||||
|  |       slaPolicies: computedSlaPolicies, | ||||||
|  |     } = useAutomation(); | ||||||
|  |  | ||||||
|  |     expect(computedAgents.value).toEqual(agents); | ||||||
|  |     expect(computedCampaigns.value).toEqual(campaigns); | ||||||
|  |     expect(computedContacts.value).toEqual(contacts); | ||||||
|  |     expect(computedInboxes.value).toEqual(inboxes); | ||||||
|  |     expect(computedLabels.value).toEqual(labels); | ||||||
|  |     expect(computedTeams.value).toEqual(teams); | ||||||
|  |     expect(computedSlaPolicies.value).toEqual(slaPolicies); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('appends new condition and action correctly', () => { | ||||||
|  |     const { appendNewCondition, appendNewAction } = useAutomation(); | ||||||
|  |     const mockAutomation = { | ||||||
|  |       event_name: 'message_created', | ||||||
|  |       conditions: [], | ||||||
|  |       actions: [], | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     automationHelper.getDefaultConditions.mockReturnValue([{}]); | ||||||
|  |     automationHelper.getDefaultActions.mockReturnValue([{}]); | ||||||
|  |  | ||||||
|  |     appendNewCondition(mockAutomation); | ||||||
|  |     appendNewAction(mockAutomation); | ||||||
|  |  | ||||||
|  |     expect(automationHelper.getDefaultConditions).toHaveBeenCalledWith( | ||||||
|  |       'message_created' | ||||||
|  |     ); | ||||||
|  |     expect(automationHelper.getDefaultActions).toHaveBeenCalled(); | ||||||
|  |     expect(mockAutomation.conditions).toHaveLength(1); | ||||||
|  |     expect(mockAutomation.actions).toHaveLength(1); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('removes filter and action correctly', () => { | ||||||
|  |     const { removeFilter, removeAction } = useAutomation(); | ||||||
|  |     const mockAutomation = { | ||||||
|  |       conditions: [{ id: 1 }, { id: 2 }], | ||||||
|  |       actions: [{ id: 1 }, { id: 2 }], | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     removeFilter(mockAutomation, 0); | ||||||
|  |     removeAction(mockAutomation, 0); | ||||||
|  |  | ||||||
|  |     expect(mockAutomation.conditions).toHaveLength(1); | ||||||
|  |     expect(mockAutomation.actions).toHaveLength(1); | ||||||
|  |     expect(mockAutomation.conditions[0].id).toBe(2); | ||||||
|  |     expect(mockAutomation.actions[0].id).toBe(2); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('resets filter and action correctly', () => { | ||||||
|  |     const { resetFilter, resetAction } = useAutomation(); | ||||||
|  |     const mockAutomation = { | ||||||
|  |       event_name: 'message_created', | ||||||
|  |       conditions: [ | ||||||
|  |         { | ||||||
|  |           attribute_key: 'status', | ||||||
|  |           filter_operator: 'equal_to', | ||||||
|  |           values: 'open', | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |       actions: [{ action_name: 'assign_agent', action_params: [1] }], | ||||||
|  |     }; | ||||||
|  |     const mockAutomationTypes = { | ||||||
|  |       message_created: { | ||||||
|  |         conditions: [ | ||||||
|  |           { key: 'status', filterOperators: [{ value: 'not_equal_to' }] }, | ||||||
|  |         ], | ||||||
|  |       }, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     resetFilter( | ||||||
|  |       mockAutomation, | ||||||
|  |       mockAutomationTypes, | ||||||
|  |       0, | ||||||
|  |       mockAutomation.conditions[0] | ||||||
|  |     ); | ||||||
|  |     resetAction(mockAutomation, 0); | ||||||
|  |  | ||||||
|  |     expect(mockAutomation.conditions[0].filter_operator).toBe('not_equal_to'); | ||||||
|  |     expect(mockAutomation.conditions[0].values).toBe(''); | ||||||
|  |     expect(mockAutomation.actions[0].action_params).toEqual([]); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('formats automation correctly', () => { | ||||||
|  |     const { formatAutomation } = useAutomation(); | ||||||
|  |     const mockAutomation = { | ||||||
|  |       conditions: [{ attribute_key: 'status', values: ['open'] }], | ||||||
|  |       actions: [{ action_name: 'assign_agent', action_params: [1] }], | ||||||
|  |     }; | ||||||
|  |     const mockAutomationTypes = {}; | ||||||
|  |     const mockAutomationActionTypes = [ | ||||||
|  |       { key: 'assign_agent', inputType: 'search_select' }, | ||||||
|  |     ]; | ||||||
|  |  | ||||||
|  |     automationHelper.getConditionOptions.mockReturnValue([ | ||||||
|  |       { id: 'open', name: 'open' }, | ||||||
|  |     ]); | ||||||
|  |     automationHelper.getActionOptions.mockReturnValue([ | ||||||
|  |       { id: 1, name: 'Agent 1' }, | ||||||
|  |     ]); | ||||||
|  |  | ||||||
|  |     const result = formatAutomation( | ||||||
|  |       mockAutomation, | ||||||
|  |       customAttributes, | ||||||
|  |       mockAutomationTypes, | ||||||
|  |       mockAutomationActionTypes | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     expect(result.conditions[0].values).toEqual([{ id: 'open', name: 'open' }]); | ||||||
|  |     expect(result.actions[0].action_params).toEqual([ | ||||||
|  |       { id: 1, name: 'Agent 1' }, | ||||||
|  |     ]); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('manifests custom attributes correctly', () => { | ||||||
|  |     const { manifestCustomAttributes } = useAutomation(); | ||||||
|  |     const mockAutomationTypes = { | ||||||
|  |       message_created: { conditions: [] }, | ||||||
|  |       conversation_created: { conditions: [] }, | ||||||
|  |       conversation_updated: { conditions: [] }, | ||||||
|  |       conversation_opened: { conditions: [] }, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     automationHelper.generateCustomAttributeTypes.mockReturnValue([]); | ||||||
|  |     automationHelper.generateCustomAttributes.mockReturnValue([]); | ||||||
|  |  | ||||||
|  |     manifestCustomAttributes(mockAutomationTypes); | ||||||
|  |  | ||||||
|  |     expect(automationHelper.generateCustomAttributeTypes).toHaveBeenCalledTimes( | ||||||
|  |       2 | ||||||
|  |     ); | ||||||
|  |     expect(automationHelper.generateCustomAttributes).toHaveBeenCalledTimes(1); | ||||||
|  |     Object.values(mockAutomationTypes).forEach(type => { | ||||||
|  |       expect(type.conditions).toHaveLength(0); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('gets condition dropdown values correctly', () => { | ||||||
|  |     const { getConditionDropdownValues } = useAutomation(); | ||||||
|  |  | ||||||
|  |     expect(getConditionDropdownValues('status')).toEqual(statusFilterOptions); | ||||||
|  |     expect(getConditionDropdownValues('team_id')).toEqual(teams); | ||||||
|  |     expect(getConditionDropdownValues('assignee_id')).toEqual(agents); | ||||||
|  |     expect(getConditionDropdownValues('contact')).toEqual(contacts); | ||||||
|  |     expect(getConditionDropdownValues('inbox_id')).toEqual(inboxes); | ||||||
|  |     expect(getConditionDropdownValues('campaigns')).toEqual(campaigns); | ||||||
|  |     expect(getConditionDropdownValues('browser_language')).toEqual(languages); | ||||||
|  |     expect(getConditionDropdownValues('country_code')).toEqual(countries); | ||||||
|  |     expect(getConditionDropdownValues('message_type')).toEqual( | ||||||
|  |       MESSAGE_CONDITION_VALUES | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('gets action dropdown values correctly', () => { | ||||||
|  |     const { getActionDropdownValues } = useAutomation(); | ||||||
|  |  | ||||||
|  |     expect(getActionDropdownValues('add_label')).toEqual(labels); | ||||||
|  |     expect(getActionDropdownValues('assign_team')).toEqual(teams); | ||||||
|  |     expect(getActionDropdownValues('assign_agent')).toEqual(agents); | ||||||
|  |     expect(getActionDropdownValues('send_email_to_team')).toEqual(teams); | ||||||
|  |     expect(getActionDropdownValues('send_message')).toEqual([]); | ||||||
|  |     expect(getActionDropdownValues('add_sla')).toEqual(slaPolicies); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('handles event change correctly', () => { | ||||||
|  |     const { onEventChange } = useAutomation(); | ||||||
|  |     const mockAutomation = { | ||||||
|  |       event_name: 'message_created', | ||||||
|  |       conditions: [], | ||||||
|  |       actions: [], | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     automationHelper.getDefaultConditions.mockReturnValue([{}]); | ||||||
|  |     automationHelper.getDefaultActions.mockReturnValue([{}]); | ||||||
|  |  | ||||||
|  |     onEventChange(mockAutomation); | ||||||
|  |  | ||||||
|  |     expect(automationHelper.getDefaultConditions).toHaveBeenCalledWith( | ||||||
|  |       'message_created' | ||||||
|  |     ); | ||||||
|  |     expect(automationHelper.getDefaultActions).toHaveBeenCalled(); | ||||||
|  |     expect(mockAutomation.conditions).toHaveLength(1); | ||||||
|  |     expect(mockAutomation.actions).toHaveLength(1); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| import { describe, it, expect, vi } from 'vitest'; | import { describe, it, expect, vi } from 'vitest'; | ||||||
| import { useMacros } from '../useMacros'; | import { useMacros } from '../useMacros'; | ||||||
| import { useStoreGetters } from 'dashboard/composables/store'; | import { useStoreGetters } from 'dashboard/composables/store'; | ||||||
| import { PRIORITY_CONDITION_VALUES } from 'dashboard/helper/automationHelper.js'; | import { PRIORITY_CONDITION_VALUES } from 'dashboard/constants/automation'; | ||||||
|  |  | ||||||
| vi.mock('dashboard/composables/store'); | vi.mock('dashboard/composables/store'); | ||||||
| vi.mock('dashboard/helper/automationHelper.js'); | vi.mock('dashboard/helper/automationHelper.js'); | ||||||
|   | |||||||
							
								
								
									
										349
									
								
								app/javascript/dashboard/composables/useAutomation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										349
									
								
								app/javascript/dashboard/composables/useAutomation.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,349 @@ | |||||||
|  | import { computed } from 'vue'; | ||||||
|  | import { useStoreGetters, useMapGetter } from 'dashboard/composables/store'; | ||||||
|  | import { useAlert } from 'dashboard/composables'; | ||||||
|  | import { useI18n } from './useI18n'; | ||||||
|  | import languages from 'dashboard/components/widgets/conversation/advancedFilterItems/languages'; | ||||||
|  | import countries from 'shared/constants/countries'; | ||||||
|  | import { | ||||||
|  |   generateCustomAttributeTypes, | ||||||
|  |   getActionOptions, | ||||||
|  |   getConditionOptions, | ||||||
|  |   getCustomAttributeInputType, | ||||||
|  |   getDefaultConditions, | ||||||
|  |   getDefaultActions, | ||||||
|  |   filterCustomAttributes, | ||||||
|  |   getStandardAttributeInputType, | ||||||
|  |   isCustomAttribute, | ||||||
|  |   generateCustomAttributes, | ||||||
|  | } from 'dashboard/helper/automationHelper'; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Composable for handling automation-related functionality. | ||||||
|  |  * @returns {Object} An object containing various automation-related functions and computed properties. | ||||||
|  |  */ | ||||||
|  | export function useAutomation() { | ||||||
|  |   const getters = useStoreGetters(); | ||||||
|  |   const { t } = useI18n(); | ||||||
|  |  | ||||||
|  |   const agents = useMapGetter('agents/getAgents'); | ||||||
|  |   const campaigns = useMapGetter('campaigns/getAllCampaigns'); | ||||||
|  |   const contacts = useMapGetter('contacts/getContacts'); | ||||||
|  |   const inboxes = useMapGetter('inboxes/getInboxes'); | ||||||
|  |   const labels = useMapGetter('labels/getLabels'); | ||||||
|  |   const teams = useMapGetter('teams/getTeams'); | ||||||
|  |   const slaPolicies = useMapGetter('sla/getSLA'); | ||||||
|  |  | ||||||
|  |   const booleanFilterOptions = computed(() => [ | ||||||
|  |     { id: true, name: t('FILTER.ATTRIBUTE_LABELS.TRUE') }, | ||||||
|  |     { id: false, name: t('FILTER.ATTRIBUTE_LABELS.FALSE') }, | ||||||
|  |   ]); | ||||||
|  |  | ||||||
|  |   const statusFilterOptions = computed(() => { | ||||||
|  |     const statusFilters = t('CHAT_LIST.CHAT_STATUS_FILTER_ITEMS'); | ||||||
|  |     return [ | ||||||
|  |       ...Object.keys(statusFilters).map(status => ({ | ||||||
|  |         id: status, | ||||||
|  |         name: statusFilters[status].TEXT, | ||||||
|  |       })), | ||||||
|  |       { id: 'all', name: t('CHAT_LIST.FILTER_ALL') }, | ||||||
|  |     ]; | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Handles the event change for an automation. | ||||||
|  |    * @param {Object} automation - The automation object to update. | ||||||
|  |    */ | ||||||
|  |   const onEventChange = automation => { | ||||||
|  |     automation.conditions = getDefaultConditions(automation.event_name); | ||||||
|  |     automation.actions = getDefaultActions(); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Gets the condition dropdown values for a given type. | ||||||
|  |    * @param {string} type - The type of condition. | ||||||
|  |    * @returns {Array} An array of condition dropdown values. | ||||||
|  |    */ | ||||||
|  |   const getConditionDropdownValues = type => { | ||||||
|  |     return getConditionOptions({ | ||||||
|  |       agents: agents.value, | ||||||
|  |       booleanFilterOptions: booleanFilterOptions.value, | ||||||
|  |       campaigns: campaigns.value, | ||||||
|  |       contacts: contacts.value, | ||||||
|  |       customAttributes: getters['attributes/getAttributes'].value, | ||||||
|  |       inboxes: inboxes.value, | ||||||
|  |       statusFilterOptions: statusFilterOptions.value, | ||||||
|  |       teams: teams.value, | ||||||
|  |       languages, | ||||||
|  |       countries, | ||||||
|  |       type, | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Appends a new condition to the automation. | ||||||
|  |    * @param {Object} automation - The automation object to update. | ||||||
|  |    */ | ||||||
|  |   const appendNewCondition = automation => { | ||||||
|  |     automation.conditions.push(...getDefaultConditions(automation.event_name)); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Appends a new action to the automation. | ||||||
|  |    * @param {Object} automation - The automation object to update. | ||||||
|  |    */ | ||||||
|  |   const appendNewAction = automation => { | ||||||
|  |     automation.actions.push(...getDefaultActions()); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Removes a filter from the automation. | ||||||
|  |    * @param {Object} automation - The automation object to update. | ||||||
|  |    * @param {number} index - The index of the filter to remove. | ||||||
|  |    */ | ||||||
|  |   const removeFilter = (automation, index) => { | ||||||
|  |     if (automation.conditions.length <= 1) { | ||||||
|  |       useAlert(t('AUTOMATION.CONDITION.DELETE_MESSAGE')); | ||||||
|  |     } else { | ||||||
|  |       automation.conditions.splice(index, 1); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Removes an action from the automation. | ||||||
|  |    * @param {Object} automation - The automation object to update. | ||||||
|  |    * @param {number} index - The index of the action to remove. | ||||||
|  |    */ | ||||||
|  |   const removeAction = (automation, index) => { | ||||||
|  |     if (automation.actions.length <= 1) { | ||||||
|  |       useAlert(t('AUTOMATION.ACTION.DELETE_MESSAGE')); | ||||||
|  |     } else { | ||||||
|  |       automation.actions.splice(index, 1); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Resets a filter in the automation. | ||||||
|  |    * @param {Object} automation - The automation object to update. | ||||||
|  |    * @param {Object} automationTypes - The automation types object. | ||||||
|  |    * @param {number} index - The index of the filter to reset. | ||||||
|  |    * @param {Object} currentCondition - The current condition object. | ||||||
|  |    */ | ||||||
|  |   const resetFilter = ( | ||||||
|  |     automation, | ||||||
|  |     automationTypes, | ||||||
|  |     index, | ||||||
|  |     currentCondition | ||||||
|  |   ) => { | ||||||
|  |     automation.conditions[index].filter_operator = automationTypes[ | ||||||
|  |       automation.event_name | ||||||
|  |     ].conditions.find( | ||||||
|  |       condition => condition.key === currentCondition.attribute_key | ||||||
|  |     ).filterOperators[0].value; | ||||||
|  |     automation.conditions[index].values = ''; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Resets an action in the automation. | ||||||
|  |    * @param {Object} automation - The automation object to update. | ||||||
|  |    * @param {number} index - The index of the action to reset. | ||||||
|  |    */ | ||||||
|  |   const resetAction = (automation, index) => { | ||||||
|  |     automation.actions[index].action_params = []; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * This function sets the conditions for automation. | ||||||
|  |    * It help to format the conditions for the automation when we open the edit automation modal. | ||||||
|  |    * @param {Object} automation - The automation object containing conditions to manifest. | ||||||
|  |    * @param {Array} allCustomAttributes - List of all custom attributes. | ||||||
|  |    * @param {Object} automationTypes - Object containing automation type definitions. | ||||||
|  |    * @returns {Array} An array of manifested conditions. | ||||||
|  |    */ | ||||||
|  |   const manifestConditions = ( | ||||||
|  |     automation, | ||||||
|  |     allCustomAttributes, | ||||||
|  |     automationTypes | ||||||
|  |   ) => { | ||||||
|  |     const customAttributes = filterCustomAttributes(allCustomAttributes); | ||||||
|  |     return automation.conditions.map(condition => { | ||||||
|  |       const customAttr = isCustomAttribute( | ||||||
|  |         customAttributes, | ||||||
|  |         condition.attribute_key | ||||||
|  |       ); | ||||||
|  |       let inputType = 'plain_text'; | ||||||
|  |       if (customAttr) { | ||||||
|  |         inputType = getCustomAttributeInputType(customAttr.type); | ||||||
|  |       } else { | ||||||
|  |         inputType = getStandardAttributeInputType( | ||||||
|  |           automationTypes, | ||||||
|  |           automation.event_name, | ||||||
|  |           condition.attribute_key | ||||||
|  |         ); | ||||||
|  |       } | ||||||
|  |       if (inputType === 'plain_text' || inputType === 'date') { | ||||||
|  |         return { ...condition, values: condition.values[0] }; | ||||||
|  |       } | ||||||
|  |       if (inputType === 'comma_separated_plain_text') { | ||||||
|  |         return { ...condition, values: condition.values.join(',') }; | ||||||
|  |       } | ||||||
|  |       return { | ||||||
|  |         ...condition, | ||||||
|  |         query_operator: condition.query_operator || 'and', | ||||||
|  |         values: [...getConditionDropdownValues(condition.attribute_key)].filter( | ||||||
|  |           item => [...condition.values].includes(item.id) | ||||||
|  |         ), | ||||||
|  |       }; | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Gets the action dropdown values for a given type. | ||||||
|  |    * @param {string} type - The type of action. | ||||||
|  |    * @returns {Array} An array of action dropdown values. | ||||||
|  |    */ | ||||||
|  |   const getActionDropdownValues = type => { | ||||||
|  |     return getActionOptions({ | ||||||
|  |       agents: agents.value, | ||||||
|  |       labels: labels.value, | ||||||
|  |       teams: teams.value, | ||||||
|  |       slaPolicies: slaPolicies.value, | ||||||
|  |       languages, | ||||||
|  |       type, | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Generates an array of actions for the automation. | ||||||
|  |    * @param {Object} action - The action object. | ||||||
|  |    * @param {Array} automationActionTypes - List of available automation action types. | ||||||
|  |    * @returns {Array|Object} Generated actions array or object based on input type. | ||||||
|  |    */ | ||||||
|  |   const generateActionsArray = (action, automationActionTypes) => { | ||||||
|  |     const params = action.action_params; | ||||||
|  |     const inputType = automationActionTypes.find( | ||||||
|  |       item => item.key === action.action_name | ||||||
|  |     ).inputType; | ||||||
|  |     if (inputType === 'multi_select' || inputType === 'search_select') { | ||||||
|  |       return [...getActionDropdownValues(action.action_name)].filter(item => | ||||||
|  |         [...params].includes(item.id) | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |     if (inputType === 'team_message') { | ||||||
|  |       return { | ||||||
|  |         team_ids: [...getActionDropdownValues(action.action_name)].filter( | ||||||
|  |           item => [...params[0].team_ids].includes(item.id) | ||||||
|  |         ), | ||||||
|  |         message: params[0].message, | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  |     return [...params]; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * This function sets the actions for automation. | ||||||
|  |    * It help to format the actions for the automation when we open the edit automation modal. | ||||||
|  |    * @param {Object} automation - The automation object containing actions. | ||||||
|  |    * @param {Array} automationActionTypes - List of available automation action types. | ||||||
|  |    * @returns {Array} An array of manifested actions. | ||||||
|  |    */ | ||||||
|  |   const manifestActions = (automation, automationActionTypes) => { | ||||||
|  |     return automation.actions.map(action => ({ | ||||||
|  |       ...action, | ||||||
|  |       action_params: action.action_params.length | ||||||
|  |         ? generateActionsArray(action, automationActionTypes) | ||||||
|  |         : [], | ||||||
|  |     })); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Formats the automation object for use when we edit the automation. | ||||||
|  |    * It help to format the conditions and actions for the automation when we open the edit automation modal. | ||||||
|  |    * @param {Object} automation - The automation object to format. | ||||||
|  |    * @param {Array} allCustomAttributes - List of all custom attributes. | ||||||
|  |    * @param {Object} automationTypes - Object containing automation type definitions. | ||||||
|  |    * @param {Array} automationActionTypes - List of available automation action types. | ||||||
|  |    * @returns {Object} A new object with formatted automation data, including automation conditions and actions. | ||||||
|  |    */ | ||||||
|  |   const formatAutomation = ( | ||||||
|  |     automation, | ||||||
|  |     allCustomAttributes, | ||||||
|  |     automationTypes, | ||||||
|  |     automationActionTypes | ||||||
|  |   ) => { | ||||||
|  |     return { | ||||||
|  |       ...automation, | ||||||
|  |       conditions: manifestConditions( | ||||||
|  |         automation, | ||||||
|  |         allCustomAttributes, | ||||||
|  |         automationTypes | ||||||
|  |       ), | ||||||
|  |       actions: manifestActions(automation, automationActionTypes), | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * This function formats the custom attributes for automation types. | ||||||
|  |    * It retrieves custom attributes for conversations and contacts, | ||||||
|  |    * generates custom attribute types, and adds them to the relevant automation types. | ||||||
|  |    * @param {Object} automationTypes - The automation types object to update with custom attributes. | ||||||
|  |    */ | ||||||
|  |   const manifestCustomAttributes = automationTypes => { | ||||||
|  |     const conversationCustomAttributesRaw = getters[ | ||||||
|  |       'attributes/getAttributesByModel' | ||||||
|  |     ].value('conversation_attribute'); | ||||||
|  |     const contactCustomAttributesRaw = | ||||||
|  |       getters['attributes/getAttributesByModel'].value('contact_attribute'); | ||||||
|  |  | ||||||
|  |     const conversationCustomAttributeTypes = generateCustomAttributeTypes( | ||||||
|  |       conversationCustomAttributesRaw, | ||||||
|  |       'conversation_attribute' | ||||||
|  |     ); | ||||||
|  |     const contactCustomAttributeTypes = generateCustomAttributeTypes( | ||||||
|  |       contactCustomAttributesRaw, | ||||||
|  |       'contact_attribute' | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     const manifestedCustomAttributes = generateCustomAttributes( | ||||||
|  |       conversationCustomAttributeTypes, | ||||||
|  |       contactCustomAttributeTypes, | ||||||
|  |       t('AUTOMATION.CONDITION.CONVERSATION_CUSTOM_ATTR_LABEL'), | ||||||
|  |       t('AUTOMATION.CONDITION.CONTACT_CUSTOM_ATTR_LABEL') | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     automationTypes.message_created.conditions.push( | ||||||
|  |       ...manifestedCustomAttributes | ||||||
|  |     ); | ||||||
|  |     automationTypes.conversation_created.conditions.push( | ||||||
|  |       ...manifestedCustomAttributes | ||||||
|  |     ); | ||||||
|  |     automationTypes.conversation_updated.conditions.push( | ||||||
|  |       ...manifestedCustomAttributes | ||||||
|  |     ); | ||||||
|  |     automationTypes.conversation_opened.conditions.push( | ||||||
|  |       ...manifestedCustomAttributes | ||||||
|  |     ); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   return { | ||||||
|  |     agents, | ||||||
|  |     campaigns, | ||||||
|  |     contacts, | ||||||
|  |     inboxes, | ||||||
|  |     labels, | ||||||
|  |     teams, | ||||||
|  |     slaPolicies, | ||||||
|  |     booleanFilterOptions, | ||||||
|  |     statusFilterOptions, | ||||||
|  |     onEventChange, | ||||||
|  |     getConditionDropdownValues, | ||||||
|  |     appendNewCondition, | ||||||
|  |     appendNewAction, | ||||||
|  |     removeFilter, | ||||||
|  |     removeAction, | ||||||
|  |     resetFilter, | ||||||
|  |     resetAction, | ||||||
|  |     formatAutomation, | ||||||
|  |     getActionDropdownValues, | ||||||
|  |     manifestCustomAttributes, | ||||||
|  |   }; | ||||||
|  | } | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| import { computed } from 'vue'; | import { computed } from 'vue'; | ||||||
| import { useStoreGetters } from 'dashboard/composables/store'; | import { useStoreGetters } from 'dashboard/composables/store'; | ||||||
| import { PRIORITY_CONDITION_VALUES } from 'dashboard/helper/automationHelper.js'; | import { PRIORITY_CONDITION_VALUES } from 'dashboard/constants/automation'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Composable for handling macro-related functionality |  * Composable for handling macro-related functionality | ||||||
|   | |||||||
							
								
								
									
										70
									
								
								app/javascript/dashboard/constants/automation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								app/javascript/dashboard/constants/automation.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | export const DEFAULT_MESSAGE_CREATED_CONDITION = [ | ||||||
|  |   { | ||||||
|  |     attribute_key: 'message_type', | ||||||
|  |     filter_operator: 'equal_to', | ||||||
|  |     values: '', | ||||||
|  |     query_operator: 'and', | ||||||
|  |     custom_attribute_type: '', | ||||||
|  |   }, | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | export const DEFAULT_CONVERSATION_OPENED_CONDITION = [ | ||||||
|  |   { | ||||||
|  |     attribute_key: 'browser_language', | ||||||
|  |     filter_operator: 'equal_to', | ||||||
|  |     values: '', | ||||||
|  |     query_operator: 'and', | ||||||
|  |     custom_attribute_type: '', | ||||||
|  |   }, | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | export const DEFAULT_OTHER_CONDITION = [ | ||||||
|  |   { | ||||||
|  |     attribute_key: 'status', | ||||||
|  |     filter_operator: 'equal_to', | ||||||
|  |     values: '', | ||||||
|  |     query_operator: 'and', | ||||||
|  |     custom_attribute_type: '', | ||||||
|  |   }, | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | export const DEFAULT_ACTIONS = [ | ||||||
|  |   { | ||||||
|  |     action_name: 'assign_agent', | ||||||
|  |     action_params: [], | ||||||
|  |   }, | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | export const MESSAGE_CONDITION_VALUES = [ | ||||||
|  |   { | ||||||
|  |     id: 'incoming', | ||||||
|  |     name: 'Incoming Message', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'outgoing', | ||||||
|  |     name: 'Outgoing Message', | ||||||
|  |   }, | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | export const PRIORITY_CONDITION_VALUES = [ | ||||||
|  |   { | ||||||
|  |     id: 'nil', | ||||||
|  |     name: 'None', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'low', | ||||||
|  |     name: 'Low', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'medium', | ||||||
|  |     name: 'Medium', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'high', | ||||||
|  |     name: 'High', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     id: 'urgent', | ||||||
|  |     name: 'Urgent', | ||||||
|  |   }, | ||||||
|  | ]; | ||||||
| @@ -3,41 +3,16 @@ import { | |||||||
|   OPERATOR_TYPES_3, |   OPERATOR_TYPES_3, | ||||||
|   OPERATOR_TYPES_4, |   OPERATOR_TYPES_4, | ||||||
| } from 'dashboard/routes/dashboard/settings/automation/operators'; | } from 'dashboard/routes/dashboard/settings/automation/operators'; | ||||||
|  | import { | ||||||
|  |   DEFAULT_MESSAGE_CREATED_CONDITION, | ||||||
|  |   DEFAULT_CONVERSATION_OPENED_CONDITION, | ||||||
|  |   DEFAULT_OTHER_CONDITION, | ||||||
|  |   DEFAULT_ACTIONS, | ||||||
|  |   MESSAGE_CONDITION_VALUES, | ||||||
|  |   PRIORITY_CONDITION_VALUES, | ||||||
|  | } from 'dashboard/constants/automation'; | ||||||
| import filterQueryGenerator from './filterQueryGenerator'; | import filterQueryGenerator from './filterQueryGenerator'; | ||||||
| import actionQueryGenerator from './actionQueryGenerator'; | import actionQueryGenerator from './actionQueryGenerator'; | ||||||
| const MESSAGE_CONDITION_VALUES = [ |  | ||||||
|   { |  | ||||||
|     id: 'incoming', |  | ||||||
|     name: 'Incoming Message', |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|     id: 'outgoing', |  | ||||||
|     name: 'Outgoing Message', |  | ||||||
|   }, |  | ||||||
| ]; |  | ||||||
|  |  | ||||||
| export const PRIORITY_CONDITION_VALUES = [ |  | ||||||
|   { |  | ||||||
|     id: 'nil', |  | ||||||
|     name: 'None', |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|     id: 'low', |  | ||||||
|     name: 'Low', |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|     id: 'medium', |  | ||||||
|     name: 'Medium', |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|     id: 'high', |  | ||||||
|     name: 'High', |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|     id: 'urgent', |  | ||||||
|     name: 'Urgent', |  | ||||||
|   }, |  | ||||||
| ]; |  | ||||||
|  |  | ||||||
| export const getCustomAttributeInputType = key => { | export const getCustomAttributeInputType = key => { | ||||||
|   const customAttributeMap = { |   const customAttributeMap = { | ||||||
| @@ -198,45 +173,16 @@ export const getFileName = (action, files = []) => { | |||||||
|  |  | ||||||
| export const getDefaultConditions = eventName => { | export const getDefaultConditions = eventName => { | ||||||
|   if (eventName === 'message_created') { |   if (eventName === 'message_created') { | ||||||
|     return [ |     return DEFAULT_MESSAGE_CREATED_CONDITION; | ||||||
|       { |  | ||||||
|         attribute_key: 'message_type', |  | ||||||
|         filter_operator: 'equal_to', |  | ||||||
|         values: '', |  | ||||||
|         query_operator: 'and', |  | ||||||
|         custom_attribute_type: '', |  | ||||||
|       }, |  | ||||||
|     ]; |  | ||||||
|   } |   } | ||||||
|   if (eventName === 'conversation_opened') { |   if (eventName === 'conversation_opened') { | ||||||
|     return [ |     return DEFAULT_CONVERSATION_OPENED_CONDITION; | ||||||
|       { |  | ||||||
|         attribute_key: 'browser_language', |  | ||||||
|         filter_operator: 'equal_to', |  | ||||||
|         values: '', |  | ||||||
|         query_operator: 'and', |  | ||||||
|         custom_attribute_type: '', |  | ||||||
|       }, |  | ||||||
|     ]; |  | ||||||
|   } |   } | ||||||
|   return [ |   return DEFAULT_OTHER_CONDITION; | ||||||
|     { |  | ||||||
|       attribute_key: 'status', |  | ||||||
|       filter_operator: 'equal_to', |  | ||||||
|       values: '', |  | ||||||
|       query_operator: 'and', |  | ||||||
|       custom_attribute_type: '', |  | ||||||
|     }, |  | ||||||
|   ]; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const getDefaultActions = () => { | export const getDefaultActions = () => { | ||||||
|   return [ |   return DEFAULT_ACTIONS; | ||||||
|     { |  | ||||||
|       action_name: 'assign_agent', |  | ||||||
|       action_params: [], |  | ||||||
|     }, |  | ||||||
|   ]; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const filterCustomAttributes = customAttributes => { | export const filterCustomAttributes = customAttributes => { | ||||||
| @@ -297,3 +243,100 @@ export const generateCustomAttributes = ( | |||||||
|   } |   } | ||||||
|   return customAttributes; |   return customAttributes; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get attributes for a given key from automation types. | ||||||
|  |  * @param {Object} automationTypes - Object containing automation types. | ||||||
|  |  * @param {string} key - The key to get attributes for. | ||||||
|  |  * @returns {Array} Array of condition objects for the given key. | ||||||
|  |  */ | ||||||
|  | export const getAttributes = (automationTypes, key) => { | ||||||
|  |   return automationTypes[key].conditions; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get the automation type for a given key. | ||||||
|  |  * @param {Object} automationTypes - Object containing automation types. | ||||||
|  |  * @param {Object} automation - The automation object. | ||||||
|  |  * @param {string} key - The key to get the automation type for. | ||||||
|  |  * @returns {Object} The automation type object. | ||||||
|  |  */ | ||||||
|  | export const getAutomationType = (automationTypes, automation, key) => { | ||||||
|  |   return automationTypes[automation.event_name].conditions.find( | ||||||
|  |     condition => condition.key === key | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get the input type for a given key. | ||||||
|  |  * @param {Array} allCustomAttributes - Array of all custom attributes. | ||||||
|  |  * @param {Object} automationTypes - Object containing automation types. | ||||||
|  |  * @param {Object} automation - The automation object. | ||||||
|  |  * @param {string} key - The key to get the input type for. | ||||||
|  |  * @returns {string} The input type. | ||||||
|  |  */ | ||||||
|  | export const getInputType = ( | ||||||
|  |   allCustomAttributes, | ||||||
|  |   automationTypes, | ||||||
|  |   automation, | ||||||
|  |   key | ||||||
|  | ) => { | ||||||
|  |   const customAttribute = isACustomAttribute(allCustomAttributes, key); | ||||||
|  |   if (customAttribute) { | ||||||
|  |     return getCustomAttributeInputType(customAttribute.attribute_display_type); | ||||||
|  |   } | ||||||
|  |   const type = getAutomationType(automationTypes, automation, key); | ||||||
|  |   return type.inputType; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get operators for a given key. | ||||||
|  |  * @param {Array} allCustomAttributes - Array of all custom attributes. | ||||||
|  |  * @param {Object} automationTypes - Object containing automation types. | ||||||
|  |  * @param {Object} automation - The automation object. | ||||||
|  |  * @param {string} mode - The mode ('edit' or other). | ||||||
|  |  * @param {string} key - The key to get operators for. | ||||||
|  |  * @returns {Array} Array of operators. | ||||||
|  |  */ | ||||||
|  | export const getOperators = ( | ||||||
|  |   allCustomAttributes, | ||||||
|  |   automationTypes, | ||||||
|  |   automation, | ||||||
|  |   mode, | ||||||
|  |   key | ||||||
|  | ) => { | ||||||
|  |   if (mode === 'edit') { | ||||||
|  |     const customAttribute = isACustomAttribute(allCustomAttributes, key); | ||||||
|  |     if (customAttribute) { | ||||||
|  |       return getOperatorTypes(customAttribute.attribute_display_type); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   const type = getAutomationType(automationTypes, automation, key); | ||||||
|  |   return type.filterOperators; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get the custom attribute type for a given key. | ||||||
|  |  * @param {Object} automationTypes - Object containing automation types. | ||||||
|  |  * @param {Object} automation - The automation object. | ||||||
|  |  * @param {string} key - The key to get the custom attribute type for. | ||||||
|  |  * @returns {string} The custom attribute type. | ||||||
|  |  */ | ||||||
|  | export const getCustomAttributeType = (automationTypes, automation, key) => { | ||||||
|  |   return automationTypes[automation.event_name].conditions.find( | ||||||
|  |     i => i.key === key | ||||||
|  |   ).customAttributeType; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Determine if an action input should be shown. | ||||||
|  |  * @param {Array} automationActionTypes - Array of automation action type objects. | ||||||
|  |  * @param {string} action - The action to check. | ||||||
|  |  * @returns {boolean} True if the action input should be shown, false otherwise. | ||||||
|  |  */ | ||||||
|  | export const showActionInput = (automationActionTypes, action) => { | ||||||
|  |   if (action === 'send_email_to_team' || action === 'send_message') | ||||||
|  |     return false; | ||||||
|  |   const type = automationActionTypes.find(i => i.key === action).inputType; | ||||||
|  |   return !!type; | ||||||
|  | }; | ||||||
|   | |||||||
| @@ -11,11 +11,11 @@ import { | |||||||
|   contactAttrs, |   contactAttrs, | ||||||
|   conversationAttrs, |   conversationAttrs, | ||||||
|   expectedOutputForCustomAttributeGenerator, |   expectedOutputForCustomAttributeGenerator, | ||||||
| } from './automationFixtures'; | } from './fixtures/automationFixtures'; | ||||||
| import { AUTOMATIONS } from 'dashboard/routes/dashboard/settings/automation/constants'; | import { AUTOMATIONS } from 'dashboard/routes/dashboard/settings/automation/constants'; | ||||||
| 
 | 
 | ||||||
| describe('automationMethodsMixin', () => { | describe('getCustomAttributeInputType', () => { | ||||||
|   it('getCustomAttributeInputType returns the attribute input type', () => { |   it('returns the attribute input type', () => { | ||||||
|     expect(helpers.getCustomAttributeInputType('date')).toEqual('date'); |     expect(helpers.getCustomAttributeInputType('date')).toEqual('date'); | ||||||
|     expect(helpers.getCustomAttributeInputType('date')).not.toEqual( |     expect(helpers.getCustomAttributeInputType('date')).not.toEqual( | ||||||
|       'some_random_value' |       'some_random_value' | ||||||
| @@ -31,33 +31,32 @@ describe('automationMethodsMixin', () => { | |||||||
|       'plain_text' |       'plain_text' | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('isACustomAttribute returns the custom attribute value if true', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('isACustomAttribute', () => { | ||||||
|  |   it('returns the custom attribute value if true', () => { | ||||||
|     expect( |     expect( | ||||||
|       helpers.isACustomAttribute(customAttributes, 'signed_up_at') |       helpers.isACustomAttribute(customAttributes, 'signed_up_at') | ||||||
|     ).toBeTruthy(); |     ).toBeTruthy(); | ||||||
|     expect(helpers.isACustomAttribute(customAttributes, 'status')).toBeFalsy(); |     expect(helpers.isACustomAttribute(customAttributes, 'status')).toBeFalsy(); | ||||||
|   }); |   }); | ||||||
|   it('getCustomAttributeListDropdownValues returns the attribute dropdown values', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('getCustomAttributeListDropdownValues', () => { | ||||||
|  |   it('returns the attribute dropdown values', () => { | ||||||
|     const myListValues = [ |     const myListValues = [ | ||||||
|       { |       { id: 'item1', name: 'item1' }, | ||||||
|         id: 'item1', |       { id: 'item2', name: 'item2' }, | ||||||
|         name: 'item1', |       { id: 'item3', name: 'item3' }, | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         id: 'item2', |  | ||||||
|         name: 'item2', |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         id: 'item3', |  | ||||||
|         name: 'item3', |  | ||||||
|       }, |  | ||||||
|     ]; |     ]; | ||||||
|     expect( |     expect( | ||||||
|       helpers.getCustomAttributeListDropdownValues(customAttributes, 'my_list') |       helpers.getCustomAttributeListDropdownValues(customAttributes, 'my_list') | ||||||
|     ).toEqual(myListValues); |     ).toEqual(myListValues); | ||||||
|   }); |   }); | ||||||
|  | }); | ||||||
| 
 | 
 | ||||||
|   it('isCustomAttributeCheckbox checks if attribute is a checkbox', () => { | describe('isCustomAttributeCheckbox', () => { | ||||||
|  |   it('checks if attribute is a checkbox', () => { | ||||||
|     expect( |     expect( | ||||||
|       helpers.isCustomAttributeCheckbox(customAttributes, 'prime_user') |       helpers.isCustomAttributeCheckbox(customAttributes, 'prime_user') | ||||||
|         .attribute_display_type |         .attribute_display_type | ||||||
| @@ -70,13 +69,19 @@ describe('automationMethodsMixin', () => { | |||||||
|       helpers.isCustomAttributeCheckbox(customAttributes, 'my_list') |       helpers.isCustomAttributeCheckbox(customAttributes, 'my_list') | ||||||
|     ).not.toEqual('checkbox'); |     ).not.toEqual('checkbox'); | ||||||
|   }); |   }); | ||||||
|   it('isCustomAttributeList checks if attribute is a list', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('isCustomAttributeList', () => { | ||||||
|  |   it('checks if attribute is a list', () => { | ||||||
|     expect( |     expect( | ||||||
|       helpers.isCustomAttributeList(customAttributes, 'my_list') |       helpers.isCustomAttributeList(customAttributes, 'my_list') | ||||||
|         .attribute_display_type |         .attribute_display_type | ||||||
|     ).toEqual('list'); |     ).toEqual('list'); | ||||||
|   }); |   }); | ||||||
|   it('getOperatorTypes returns the correct custom attribute operators', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('getOperatorTypes', () => { | ||||||
|  |   it('returns the correct custom attribute operators', () => { | ||||||
|     expect(helpers.getOperatorTypes('list')).toEqual(OPERATOR_TYPES_1); |     expect(helpers.getOperatorTypes('list')).toEqual(OPERATOR_TYPES_1); | ||||||
|     expect(helpers.getOperatorTypes('text')).toEqual(OPERATOR_TYPES_3); |     expect(helpers.getOperatorTypes('text')).toEqual(OPERATOR_TYPES_3); | ||||||
|     expect(helpers.getOperatorTypes('number')).toEqual(OPERATOR_TYPES_1); |     expect(helpers.getOperatorTypes('number')).toEqual(OPERATOR_TYPES_1); | ||||||
| @@ -85,93 +90,44 @@ describe('automationMethodsMixin', () => { | |||||||
|     expect(helpers.getOperatorTypes('checkbox')).toEqual(OPERATOR_TYPES_1); |     expect(helpers.getOperatorTypes('checkbox')).toEqual(OPERATOR_TYPES_1); | ||||||
|     expect(helpers.getOperatorTypes('some_random')).toEqual(OPERATOR_TYPES_1); |     expect(helpers.getOperatorTypes('some_random')).toEqual(OPERATOR_TYPES_1); | ||||||
|   }); |   }); | ||||||
|   it('generateConditionOptions returns expected conditions options array', () => { | }); | ||||||
|     const testConditions = [ |  | ||||||
|       { |  | ||||||
|         id: 123, |  | ||||||
|         title: 'Fayaz', |  | ||||||
|         email: 'test@test.com', |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         title: 'John', |  | ||||||
|         id: 324, |  | ||||||
|         email: 'test@john.com', |  | ||||||
|       }, |  | ||||||
|     ]; |  | ||||||
| 
 | 
 | ||||||
|  | describe('generateConditionOptions', () => { | ||||||
|  |   it('returns expected conditions options array', () => { | ||||||
|  |     const testConditions = [ | ||||||
|  |       { id: 123, title: 'Fayaz', email: 'test@test.com' }, | ||||||
|  |       { title: 'John', id: 324, email: 'test@john.com' }, | ||||||
|  |     ]; | ||||||
|     const expectedConditions = [ |     const expectedConditions = [ | ||||||
|       { |       { id: 123, name: 'Fayaz' }, | ||||||
|         id: 123, |       { id: 324, name: 'John' }, | ||||||
|         name: 'Fayaz', |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         id: 324, |  | ||||||
|         name: 'John', |  | ||||||
|       }, |  | ||||||
|     ]; |     ]; | ||||||
|     expect(helpers.generateConditionOptions(testConditions)).toEqual( |     expect(helpers.generateConditionOptions(testConditions)).toEqual( | ||||||
|       expectedConditions |       expectedConditions | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('getActionOptions returns expected actions options array', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('getActionOptions', () => { | ||||||
|  |   it('returns expected actions options array', () => { | ||||||
|     const expectedOptions = [ |     const expectedOptions = [ | ||||||
|       { |       { id: 'testlabel', name: 'testlabel' }, | ||||||
|         id: 'testlabel', |       { id: 'snoozes', name: 'snoozes' }, | ||||||
|         name: 'testlabel', |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         id: 'snoozes', |  | ||||||
|         name: 'snoozes', |  | ||||||
|       }, |  | ||||||
|     ]; |     ]; | ||||||
|     expect(helpers.getActionOptions({ labels, type: 'add_label' })).toEqual( |     expect(helpers.getActionOptions({ labels, type: 'add_label' })).toEqual( | ||||||
|       expectedOptions |       expectedOptions | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('getConditionOptions returns expected conditions options', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('getConditionOptions', () => { | ||||||
|  |   it('returns expected conditions options', () => { | ||||||
|     const testOptions = [ |     const testOptions = [ | ||||||
|       { |       { id: 'open', name: 'Open' }, | ||||||
|         id: 'open', |       { id: 'resolved', name: 'Resolved' }, | ||||||
|         name: 'Open', |       { id: 'pending', name: 'Pending' }, | ||||||
|       }, |       { id: 'snoozed', name: 'Snoozed' }, | ||||||
|       { |       { id: 'all', name: 'All' }, | ||||||
|         id: 'resolved', |  | ||||||
|         name: 'Resolved', |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         id: 'pending', |  | ||||||
|         name: 'Pending', |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         id: 'snoozed', |  | ||||||
|         name: 'Snoozed', |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         id: 'all', |  | ||||||
|         name: 'All', |  | ||||||
|       }, |  | ||||||
|     ]; |  | ||||||
|     const expectedOptions = [ |  | ||||||
|       { |  | ||||||
|         id: 'open', |  | ||||||
|         name: 'Open', |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         id: 'resolved', |  | ||||||
|         name: 'Resolved', |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         id: 'pending', |  | ||||||
|         name: 'Pending', |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         id: 'snoozed', |  | ||||||
|         name: 'Snoozed', |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         id: 'all', |  | ||||||
|         name: 'All', |  | ||||||
|       }, |  | ||||||
|     ]; |     ]; | ||||||
|     expect( |     expect( | ||||||
|       helpers.getConditionOptions({ |       helpers.getConditionOptions({ | ||||||
| @@ -180,14 +136,20 @@ describe('automationMethodsMixin', () => { | |||||||
|         statusFilterOptions: testOptions, |         statusFilterOptions: testOptions, | ||||||
|         type: 'status', |         type: 'status', | ||||||
|       }) |       }) | ||||||
|     ).toEqual(expectedOptions); |     ).toEqual(testOptions); | ||||||
|   }); |   }); | ||||||
|   it('getFileName returns the correct file name', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('getFileName', () => { | ||||||
|  |   it('returns the correct file name', () => { | ||||||
|     expect( |     expect( | ||||||
|       helpers.getFileName(automation.actions[0], automation.files) |       helpers.getFileName(automation.actions[0], automation.files) | ||||||
|     ).toEqual('pfp.jpeg'); |     ).toEqual('pfp.jpeg'); | ||||||
|   }); |   }); | ||||||
|   it('getDefaultConditions returns the resp default condition model', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('getDefaultConditions', () => { | ||||||
|  |   it('returns the resp default condition model', () => { | ||||||
|     const messageCreatedModel = [ |     const messageCreatedModel = [ | ||||||
|       { |       { | ||||||
|         attribute_key: 'message_type', |         attribute_key: 'message_type', | ||||||
| @@ -211,7 +173,10 @@ describe('automationMethodsMixin', () => { | |||||||
|     ); |     ); | ||||||
|     expect(helpers.getDefaultConditions()).toEqual(genericConditionModel); |     expect(helpers.getDefaultConditions()).toEqual(genericConditionModel); | ||||||
|   }); |   }); | ||||||
|   it('getDefaultActions returns the resp default action model', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('getDefaultActions', () => { | ||||||
|  |   it('returns the resp default action model', () => { | ||||||
|     const genericActionModel = [ |     const genericActionModel = [ | ||||||
|       { |       { | ||||||
|         action_name: 'assign_agent', |         action_name: 'assign_agent', | ||||||
| @@ -220,7 +185,10 @@ describe('automationMethodsMixin', () => { | |||||||
|     ]; |     ]; | ||||||
|     expect(helpers.getDefaultActions()).toEqual(genericActionModel); |     expect(helpers.getDefaultActions()).toEqual(genericActionModel); | ||||||
|   }); |   }); | ||||||
|   it('filterCustomAttributes filters the raw custom attributes', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('filterCustomAttributes', () => { | ||||||
|  |   it('filters the raw custom attributes', () => { | ||||||
|     const filteredAttributes = [ |     const filteredAttributes = [ | ||||||
|       { key: 'signed_up_at', name: 'Signed Up At', type: 'date' }, |       { key: 'signed_up_at', name: 'Signed Up At', type: 'date' }, | ||||||
|       { key: 'prime_user', name: 'Prime User', type: 'checkbox' }, |       { key: 'prime_user', name: 'Prime User', type: 'checkbox' }, | ||||||
| @@ -235,7 +203,10 @@ describe('automationMethodsMixin', () => { | |||||||
|       filteredAttributes |       filteredAttributes | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('getStandardAttributeInputType returns the resp default action model', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('getStandardAttributeInputType', () => { | ||||||
|  |   it('returns the resp default action model', () => { | ||||||
|     expect( |     expect( | ||||||
|       helpers.getStandardAttributeInputType( |       helpers.getStandardAttributeInputType( | ||||||
|         AUTOMATIONS, |         AUTOMATIONS, | ||||||
| @@ -258,7 +229,10 @@ describe('automationMethodsMixin', () => { | |||||||
|       ) |       ) | ||||||
|     ).toEqual('plain_text'); |     ).toEqual('plain_text'); | ||||||
|   }); |   }); | ||||||
|   it('generateAutomationPayload returns the resp default action model', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('generateAutomationPayload', () => { | ||||||
|  |   it('returns the resp default action model', () => { | ||||||
|     const testPayload = { |     const testPayload = { | ||||||
|       name: 'Test', |       name: 'Test', | ||||||
|       description: 'This is a test', |       description: 'This is a test', | ||||||
| @@ -300,7 +274,10 @@ describe('automationMethodsMixin', () => { | |||||||
|       expectedPayload |       expectedPayload | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('isCustomAttribute returns the resp default action model', () => { | }); | ||||||
|  | 
 | ||||||
|  | describe('isCustomAttribute', () => { | ||||||
|  |   it('returns the resp default action model', () => { | ||||||
|     const attrs = helpers.filterCustomAttributes(customAttributes); |     const attrs = helpers.filterCustomAttributes(customAttributes); | ||||||
|     expect(helpers.isCustomAttribute(attrs, 'my_list')).toBeTruthy(); |     expect(helpers.isCustomAttribute(attrs, 'my_list')).toBeTruthy(); | ||||||
|     expect(helpers.isCustomAttribute(attrs, 'my_check')).toBeTruthy(); |     expect(helpers.isCustomAttribute(attrs, 'my_check')).toBeTruthy(); | ||||||
| @@ -309,8 +286,10 @@ describe('automationMethodsMixin', () => { | |||||||
|     expect(helpers.isCustomAttribute(attrs, 'prime_user')).toBeTruthy(); |     expect(helpers.isCustomAttribute(attrs, 'prime_user')).toBeTruthy(); | ||||||
|     expect(helpers.isCustomAttribute(attrs, 'hello')).toBeFalsy(); |     expect(helpers.isCustomAttribute(attrs, 'hello')).toBeFalsy(); | ||||||
|   }); |   }); | ||||||
|  | }); | ||||||
| 
 | 
 | ||||||
|   it('generateCustomAttributes generates and returns correct condition attribute', () => { | describe('generateCustomAttributes', () => { | ||||||
|  |   it('generates and returns correct condition attribute', () => { | ||||||
|     expect( |     expect( | ||||||
|       helpers.generateCustomAttributes( |       helpers.generateCustomAttributes( | ||||||
|         conversationAttrs, |         conversationAttrs, | ||||||
| @@ -321,3 +300,116 @@ describe('automationMethodsMixin', () => { | |||||||
|     ).toEqual(expectedOutputForCustomAttributeGenerator); |     ).toEqual(expectedOutputForCustomAttributeGenerator); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|  | 
 | ||||||
|  | describe('getAttributes', () => { | ||||||
|  |   it('returns the conditions for the given automation type', () => { | ||||||
|  |     const result = helpers.getAttributes(AUTOMATIONS, 'message_created'); | ||||||
|  |     expect(result).toEqual(AUTOMATIONS.message_created.conditions); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | describe('getAttributes', () => { | ||||||
|  |   it('returns the conditions for the given automation type', () => { | ||||||
|  |     const result = helpers.getAttributes(AUTOMATIONS, 'message_created'); | ||||||
|  |     expect(result).toEqual(AUTOMATIONS.message_created.conditions); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | describe('getAutomationType', () => { | ||||||
|  |   it('returns the automation type for the given key', () => { | ||||||
|  |     const mockAutomation = { event_name: 'message_created' }; | ||||||
|  |     const result = helpers.getAutomationType( | ||||||
|  |       AUTOMATIONS, | ||||||
|  |       mockAutomation, | ||||||
|  |       'message_type' | ||||||
|  |     ); | ||||||
|  |     expect(result).toEqual( | ||||||
|  |       AUTOMATIONS.message_created.conditions.find(c => c.key === 'message_type') | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | describe('getInputType', () => { | ||||||
|  |   it('returns the input type for a custom attribute', () => { | ||||||
|  |     const mockAutomation = { event_name: 'message_created' }; | ||||||
|  |     const result = helpers.getInputType( | ||||||
|  |       customAttributes, | ||||||
|  |       AUTOMATIONS, | ||||||
|  |       mockAutomation, | ||||||
|  |       'signed_up_at' | ||||||
|  |     ); | ||||||
|  |     expect(result).toEqual('date'); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('returns the input type for a standard attribute', () => { | ||||||
|  |     const mockAutomation = { event_name: 'message_created' }; | ||||||
|  |     const result = helpers.getInputType( | ||||||
|  |       customAttributes, | ||||||
|  |       AUTOMATIONS, | ||||||
|  |       mockAutomation, | ||||||
|  |       'message_type' | ||||||
|  |     ); | ||||||
|  |     expect(result).toEqual('search_select'); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | describe('getOperators', () => { | ||||||
|  |   it('returns operators for a custom attribute in edit mode', () => { | ||||||
|  |     const mockAutomation = { event_name: 'message_created' }; | ||||||
|  |     const result = helpers.getOperators( | ||||||
|  |       customAttributes, | ||||||
|  |       AUTOMATIONS, | ||||||
|  |       mockAutomation, | ||||||
|  |       'edit', | ||||||
|  |       'signed_up_at' | ||||||
|  |     ); | ||||||
|  |     expect(result).toEqual(OPERATOR_TYPES_4); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('returns operators for a standard attribute', () => { | ||||||
|  |     const mockAutomation = { event_name: 'message_created' }; | ||||||
|  |     const result = helpers.getOperators( | ||||||
|  |       customAttributes, | ||||||
|  |       AUTOMATIONS, | ||||||
|  |       mockAutomation, | ||||||
|  |       'create', | ||||||
|  |       'message_type' | ||||||
|  |     ); | ||||||
|  |     expect(result).toEqual( | ||||||
|  |       AUTOMATIONS.message_created.conditions.find(c => c.key === 'message_type') | ||||||
|  |         .filterOperators | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | describe('getCustomAttributeType', () => { | ||||||
|  |   it('returns the custom attribute type for the given key', () => { | ||||||
|  |     const mockAutomation = { event_name: 'message_created' }; | ||||||
|  |     const result = helpers.getCustomAttributeType( | ||||||
|  |       AUTOMATIONS, | ||||||
|  |       mockAutomation, | ||||||
|  |       'message_type' | ||||||
|  |     ); | ||||||
|  |     expect(result).toEqual( | ||||||
|  |       AUTOMATIONS.message_created.conditions.find(c => c.key === 'message_type') | ||||||
|  |         .customAttributeType | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | describe('showActionInput', () => { | ||||||
|  |   it('returns false for send_email_to_team and send_message actions', () => { | ||||||
|  |     expect(helpers.showActionInput([], 'send_email_to_team')).toBe(false); | ||||||
|  |     expect(helpers.showActionInput([], 'send_message')).toBe(false); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('returns true if the action has an input type', () => { | ||||||
|  |     const mockActionTypes = [{ key: 'add_label', inputType: 'select' }]; | ||||||
|  |     expect(helpers.showActionInput(mockActionTypes, 'add_label')).toBe(true); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('returns false if the action does not have an input type', () => { | ||||||
|  |     const mockActionTypes = [{ key: 'some_action', inputType: null }]; | ||||||
|  |     expect(helpers.showActionInput(mockActionTypes, 'some_action')).toBe(false); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| import allLanguages from '../../../dashboard/components/widgets/conversation/advancedFilterItems/languages.js'; | import allLanguages from 'dashboard/components/widgets/conversation/advancedFilterItems/languages'; | ||||||
| 
 | 
 | ||||||
| import allCountries from '../../../shared/constants/countries.js'; | import allCountries from 'shared/constants/countries.js'; | ||||||
| 
 | 
 | ||||||
| export const customAttributes = [ | export const customAttributes = [ | ||||||
|   { |   { | ||||||
| @@ -1,314 +0,0 @@ | |||||||
| import languages from 'dashboard/components/widgets/conversation/advancedFilterItems/languages'; |  | ||||||
| import countries from 'shared/constants/countries'; |  | ||||||
| import { validateAutomation } from 'dashboard/helper/validations'; |  | ||||||
|  |  | ||||||
| import { |  | ||||||
|   generateCustomAttributeTypes, |  | ||||||
|   getActionOptions, |  | ||||||
|   getConditionOptions, |  | ||||||
|   getCustomAttributeInputType, |  | ||||||
|   getOperatorTypes, |  | ||||||
|   isACustomAttribute, |  | ||||||
|   getFileName, |  | ||||||
|   getDefaultConditions, |  | ||||||
|   getDefaultActions, |  | ||||||
|   filterCustomAttributes, |  | ||||||
|   generateAutomationPayload, |  | ||||||
|   getStandardAttributeInputType, |  | ||||||
|   isCustomAttribute, |  | ||||||
|   generateCustomAttributes, |  | ||||||
| } from 'dashboard/helper/automationHelper'; |  | ||||||
| import { mapGetters } from 'vuex'; |  | ||||||
| import { useAlert } from 'dashboard/composables'; |  | ||||||
|  |  | ||||||
| export default { |  | ||||||
|   computed: { |  | ||||||
|     ...mapGetters({ |  | ||||||
|       agents: 'agents/getAgents', |  | ||||||
|       campaigns: 'campaigns/getAllCampaigns', |  | ||||||
|       contacts: 'contacts/getContacts', |  | ||||||
|       inboxes: 'inboxes/getInboxes', |  | ||||||
|       labels: 'labels/getLabels', |  | ||||||
|       teams: 'teams/getTeams', |  | ||||||
|       slaPolicies: 'sla/getSLA', |  | ||||||
|     }), |  | ||||||
|     booleanFilterOptions() { |  | ||||||
|       return [ |  | ||||||
|         { |  | ||||||
|           id: true, |  | ||||||
|           name: this.$t('FILTER.ATTRIBUTE_LABELS.TRUE'), |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|           id: false, |  | ||||||
|           name: this.$t('FILTER.ATTRIBUTE_LABELS.FALSE'), |  | ||||||
|         }, |  | ||||||
|       ]; |  | ||||||
|     }, |  | ||||||
|  |  | ||||||
|     statusFilterOptions() { |  | ||||||
|       const statusFilters = this.$t('CHAT_LIST.CHAT_STATUS_FILTER_ITEMS'); |  | ||||||
|       return [ |  | ||||||
|         ...Object.keys(statusFilters).map(status => { |  | ||||||
|           return { |  | ||||||
|             id: status, |  | ||||||
|             name: statusFilters[status].TEXT, |  | ||||||
|           }; |  | ||||||
|         }), |  | ||||||
|         { |  | ||||||
|           id: 'all', |  | ||||||
|           name: this.$t('CHAT_LIST.FILTER_ALL'), |  | ||||||
|         }, |  | ||||||
|       ]; |  | ||||||
|     }, |  | ||||||
|   }, |  | ||||||
|   methods: { |  | ||||||
|     getFileName, |  | ||||||
|     onEventChange() { |  | ||||||
|       this.automation.conditions = getDefaultConditions( |  | ||||||
|         this.automation.event_name |  | ||||||
|       ); |  | ||||||
|       this.automation.actions = getDefaultActions(); |  | ||||||
|     }, |  | ||||||
|     getAttributes(key) { |  | ||||||
|       return this.automationTypes[key].conditions; |  | ||||||
|     }, |  | ||||||
|     getInputType(key) { |  | ||||||
|       const customAttribute = isACustomAttribute(this.allCustomAttributes, key); |  | ||||||
|       if (customAttribute) { |  | ||||||
|         return getCustomAttributeInputType( |  | ||||||
|           customAttribute.attribute_display_type |  | ||||||
|         ); |  | ||||||
|       } |  | ||||||
|       const type = this.getAutomationType(key); |  | ||||||
|       return type.inputType; |  | ||||||
|     }, |  | ||||||
|     getOperators(key) { |  | ||||||
|       if (this.mode === 'edit') { |  | ||||||
|         const customAttribute = isACustomAttribute( |  | ||||||
|           this.allCustomAttributes, |  | ||||||
|           key |  | ||||||
|         ); |  | ||||||
|         if (customAttribute) { |  | ||||||
|           return getOperatorTypes(customAttribute.attribute_display_type); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       const type = this.getAutomationType(key); |  | ||||||
|       return type.filterOperators; |  | ||||||
|     }, |  | ||||||
|     getAutomationType(key) { |  | ||||||
|       return this.automationTypes[this.automation.event_name].conditions.find( |  | ||||||
|         condition => condition.key === key |  | ||||||
|       ); |  | ||||||
|     }, |  | ||||||
|     getCustomAttributeType(key) { |  | ||||||
|       const type = this.automationTypes[ |  | ||||||
|         this.automation.event_name |  | ||||||
|       ].conditions.find(i => i.key === key).customAttributeType; |  | ||||||
|       return type; |  | ||||||
|     }, |  | ||||||
|     getConditionDropdownValues(type) { |  | ||||||
|       const { |  | ||||||
|         agents, |  | ||||||
|         allCustomAttributes: customAttributes, |  | ||||||
|         booleanFilterOptions, |  | ||||||
|         campaigns, |  | ||||||
|         contacts, |  | ||||||
|         inboxes, |  | ||||||
|         statusFilterOptions, |  | ||||||
|         teams, |  | ||||||
|       } = this; |  | ||||||
|       return getConditionOptions({ |  | ||||||
|         agents, |  | ||||||
|         booleanFilterOptions, |  | ||||||
|         campaigns, |  | ||||||
|         contacts, |  | ||||||
|         customAttributes, |  | ||||||
|         inboxes, |  | ||||||
|         statusFilterOptions, |  | ||||||
|         teams, |  | ||||||
|         languages, |  | ||||||
|         countries, |  | ||||||
|         type, |  | ||||||
|       }); |  | ||||||
|     }, |  | ||||||
|     appendNewCondition() { |  | ||||||
|       this.automation.conditions.push( |  | ||||||
|         ...getDefaultConditions(this.automation.event_name) |  | ||||||
|       ); |  | ||||||
|     }, |  | ||||||
|     appendNewAction() { |  | ||||||
|       this.automation.actions.push(...getDefaultActions()); |  | ||||||
|     }, |  | ||||||
|     removeFilter(index) { |  | ||||||
|       if (this.automation.conditions.length <= 1) { |  | ||||||
|         useAlert(this.$t('AUTOMATION.CONDITION.DELETE_MESSAGE')); |  | ||||||
|       } else { |  | ||||||
|         this.automation.conditions.splice(index, 1); |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     removeAction(index) { |  | ||||||
|       if (this.automation.actions.length <= 1) { |  | ||||||
|         useAlert(this.$t('AUTOMATION.ACTION.DELETE_MESSAGE')); |  | ||||||
|       } else { |  | ||||||
|         this.automation.actions.splice(index, 1); |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     submitAutomation() { |  | ||||||
|       // we assign it to this.errors so that it can be accessed in the template |  | ||||||
|       // it is supposed to be declared in the data function |  | ||||||
|       this.errors = validateAutomation(this.automation); |  | ||||||
|       if (Object.keys(this.errors).length === 0) { |  | ||||||
|         const automation = generateAutomationPayload(this.automation); |  | ||||||
|         this.$emit('saveAutomation', automation, this.mode); |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     resetFilter(index, currentCondition) { |  | ||||||
|       this.automation.conditions[index].filter_operator = this.automationTypes[ |  | ||||||
|         this.automation.event_name |  | ||||||
|       ].conditions.find( |  | ||||||
|         condition => condition.key === currentCondition.attribute_key |  | ||||||
|       ).filterOperators[0].value; |  | ||||||
|       this.automation.conditions[index].values = ''; |  | ||||||
|     }, |  | ||||||
|     showUserInput(type) { |  | ||||||
|       return !(type === 'is_present' || type === 'is_not_present'); |  | ||||||
|     }, |  | ||||||
|     showActionInput(action) { |  | ||||||
|       if (action === 'send_email_to_team' || action === 'send_message') |  | ||||||
|         return false; |  | ||||||
|       const type = this.automationActionTypes.find( |  | ||||||
|         i => i.key === action |  | ||||||
|       ).inputType; |  | ||||||
|       return !!type; |  | ||||||
|     }, |  | ||||||
|     resetAction(index) { |  | ||||||
|       this.automation.actions[index].action_params = []; |  | ||||||
|     }, |  | ||||||
|     manifestConditions(automation) { |  | ||||||
|       const customAttributes = filterCustomAttributes(this.allCustomAttributes); |  | ||||||
|       const conditions = automation.conditions.map(condition => { |  | ||||||
|         const customAttr = isCustomAttribute( |  | ||||||
|           customAttributes, |  | ||||||
|           condition.attribute_key |  | ||||||
|         ); |  | ||||||
|         let inputType = 'plain_text'; |  | ||||||
|         if (customAttr) { |  | ||||||
|           inputType = getCustomAttributeInputType(customAttr.type); |  | ||||||
|         } else { |  | ||||||
|           inputType = getStandardAttributeInputType( |  | ||||||
|             this.automationTypes, |  | ||||||
|             automation.event_name, |  | ||||||
|             condition.attribute_key |  | ||||||
|           ); |  | ||||||
|         } |  | ||||||
|         if (inputType === 'plain_text' || inputType === 'date') { |  | ||||||
|           return { |  | ||||||
|             ...condition, |  | ||||||
|             values: condition.values[0], |  | ||||||
|           }; |  | ||||||
|         } |  | ||||||
|         if (inputType === 'comma_separated_plain_text') { |  | ||||||
|           return { |  | ||||||
|             ...condition, |  | ||||||
|             values: condition.values.join(','), |  | ||||||
|           }; |  | ||||||
|         } |  | ||||||
|         return { |  | ||||||
|           ...condition, |  | ||||||
|           query_operator: condition.query_operator || 'and', |  | ||||||
|           values: [ |  | ||||||
|             ...this.getConditionDropdownValues(condition.attribute_key), |  | ||||||
|           ].filter(item => [...condition.values].includes(item.id)), |  | ||||||
|         }; |  | ||||||
|       }); |  | ||||||
|       return conditions; |  | ||||||
|     }, |  | ||||||
|     generateActionsArray(action) { |  | ||||||
|       const params = action.action_params; |  | ||||||
|       let actionParams = []; |  | ||||||
|       const inputType = this.automationActionTypes.find( |  | ||||||
|         item => item.key === action.action_name |  | ||||||
|       ).inputType; |  | ||||||
|       if (inputType === 'multi_select' || inputType === 'search_select') { |  | ||||||
|         actionParams = [ |  | ||||||
|           ...this.getActionDropdownValues(action.action_name), |  | ||||||
|         ].filter(item => [...params].includes(item.id)); |  | ||||||
|       } else if (inputType === 'team_message') { |  | ||||||
|         actionParams = { |  | ||||||
|           team_ids: [ |  | ||||||
|             ...this.getActionDropdownValues(action.action_name), |  | ||||||
|           ].filter(item => [...params[0].team_ids].includes(item.id)), |  | ||||||
|           message: params[0].message, |  | ||||||
|         }; |  | ||||||
|       } else actionParams = [...params]; |  | ||||||
|       return actionParams; |  | ||||||
|     }, |  | ||||||
|     manifestActions(automation) { |  | ||||||
|       let actionParams = []; |  | ||||||
|       const actions = automation.actions.map(action => { |  | ||||||
|         if (action.action_params.length) { |  | ||||||
|           actionParams = this.generateActionsArray(action); |  | ||||||
|         } |  | ||||||
|         return { |  | ||||||
|           ...action, |  | ||||||
|           action_params: actionParams, |  | ||||||
|         }; |  | ||||||
|       }); |  | ||||||
|       return actions; |  | ||||||
|     }, |  | ||||||
|     formatAutomation(automation) { |  | ||||||
|       this.automation = { |  | ||||||
|         ...automation, |  | ||||||
|         conditions: this.manifestConditions(automation), |  | ||||||
|         actions: this.manifestActions(automation), |  | ||||||
|       }; |  | ||||||
|     }, |  | ||||||
|     getActionDropdownValues(type) { |  | ||||||
|       const { agents, labels, teams, slaPolicies } = this; |  | ||||||
|       return getActionOptions({ |  | ||||||
|         agents, |  | ||||||
|         labels, |  | ||||||
|         teams, |  | ||||||
|         slaPolicies, |  | ||||||
|         languages, |  | ||||||
|         type, |  | ||||||
|       }); |  | ||||||
|     }, |  | ||||||
|     manifestCustomAttributes() { |  | ||||||
|       const conversationCustomAttributesRaw = this.$store.getters[ |  | ||||||
|         'attributes/getAttributesByModel' |  | ||||||
|       ]('conversation_attribute'); |  | ||||||
|  |  | ||||||
|       const contactCustomAttributesRaw = |  | ||||||
|         this.$store.getters['attributes/getAttributesByModel']( |  | ||||||
|           'contact_attribute' |  | ||||||
|         ); |  | ||||||
|       const conversationCustomAttributeTypes = generateCustomAttributeTypes( |  | ||||||
|         conversationCustomAttributesRaw, |  | ||||||
|         'conversation_attribute' |  | ||||||
|       ); |  | ||||||
|       const contactCustomAttributeTypes = generateCustomAttributeTypes( |  | ||||||
|         contactCustomAttributesRaw, |  | ||||||
|         'contact_attribute' |  | ||||||
|       ); |  | ||||||
|       let manifestedCustomAttributes = generateCustomAttributes( |  | ||||||
|         conversationCustomAttributeTypes, |  | ||||||
|         contactCustomAttributeTypes, |  | ||||||
|         this.$t('AUTOMATION.CONDITION.CONVERSATION_CUSTOM_ATTR_LABEL'), |  | ||||||
|         this.$t('AUTOMATION.CONDITION.CONTACT_CUSTOM_ATTR_LABEL') |  | ||||||
|       ); |  | ||||||
|       this.automationTypes.message_created.conditions.push( |  | ||||||
|         ...manifestedCustomAttributes |  | ||||||
|       ); |  | ||||||
|       this.automationTypes.conversation_created.conditions.push( |  | ||||||
|         ...manifestedCustomAttributes |  | ||||||
|       ); |  | ||||||
|       this.automationTypes.conversation_updated.conditions.push( |  | ||||||
|         ...manifestedCustomAttributes |  | ||||||
|       ); |  | ||||||
|       this.automationTypes.conversation_opened.conditions.push( |  | ||||||
|         ...manifestedCustomAttributes |  | ||||||
|       ); |  | ||||||
|     }, |  | ||||||
|   }, |  | ||||||
| }; |  | ||||||
| @@ -1,9 +1,17 @@ | |||||||
| <script> | <script> | ||||||
| import { mapGetters } from 'vuex'; | import { mapGetters } from 'vuex'; | ||||||
| import automationMethodsMixin from 'dashboard/mixins/automations/methodsMixin'; |  | ||||||
| import FilterInputBox from 'dashboard/components/widgets/FilterInput/Index.vue'; | import FilterInputBox from 'dashboard/components/widgets/FilterInput/Index.vue'; | ||||||
| import AutomationActionInput from 'dashboard/components/widgets/AutomationActionInput.vue'; | import AutomationActionInput from 'dashboard/components/widgets/AutomationActionInput.vue'; | ||||||
|  | import { useAutomation } from 'dashboard/composables/useAutomation'; | ||||||
|  | import { validateAutomation } from 'dashboard/helper/validations'; | ||||||
|  | import { | ||||||
|  |   generateAutomationPayload, | ||||||
|  |   getAttributes, | ||||||
|  |   getInputType, | ||||||
|  |   getOperators, | ||||||
|  |   getCustomAttributeType, | ||||||
|  |   showActionInput, | ||||||
|  | } from 'dashboard/helper/automationHelper'; | ||||||
| import { | import { | ||||||
|   AUTOMATION_RULE_EVENTS, |   AUTOMATION_RULE_EVENTS, | ||||||
|   AUTOMATION_ACTION_TYPES, |   AUTOMATION_ACTION_TYPES, | ||||||
| @@ -14,13 +22,38 @@ export default { | |||||||
|     FilterInputBox, |     FilterInputBox, | ||||||
|     AutomationActionInput, |     AutomationActionInput, | ||||||
|   }, |   }, | ||||||
|   mixins: [automationMethodsMixin], |  | ||||||
|   props: { |   props: { | ||||||
|     onClose: { |     onClose: { | ||||||
|       type: Function, |       type: Function, | ||||||
|       default: () => {}, |       default: () => {}, | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|  |   setup() { | ||||||
|  |     const { | ||||||
|  |       onEventChange, | ||||||
|  |       getConditionDropdownValues, | ||||||
|  |       appendNewCondition, | ||||||
|  |       appendNewAction, | ||||||
|  |       removeFilter, | ||||||
|  |       removeAction, | ||||||
|  |       resetFilter, | ||||||
|  |       resetAction, | ||||||
|  |       getActionDropdownValues, | ||||||
|  |       manifestCustomAttributes, | ||||||
|  |     } = useAutomation(); | ||||||
|  |     return { | ||||||
|  |       onEventChange, | ||||||
|  |       getConditionDropdownValues, | ||||||
|  |       appendNewCondition, | ||||||
|  |       appendNewAction, | ||||||
|  |       removeFilter, | ||||||
|  |       removeAction, | ||||||
|  |       resetFilter, | ||||||
|  |       resetAction, | ||||||
|  |       getActionDropdownValues, | ||||||
|  |       manifestCustomAttributes, | ||||||
|  |     }; | ||||||
|  |   }, | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       automationTypes: JSON.parse(JSON.stringify(AUTOMATIONS)), |       automationTypes: JSON.parse(JSON.stringify(AUTOMATIONS)), | ||||||
| @@ -82,12 +115,24 @@ export default { | |||||||
|     this.$store.dispatch('labels/get'); |     this.$store.dispatch('labels/get'); | ||||||
|     this.$store.dispatch('campaigns/get'); |     this.$store.dispatch('campaigns/get'); | ||||||
|     this.allCustomAttributes = this.$store.getters['attributes/getAttributes']; |     this.allCustomAttributes = this.$store.getters['attributes/getAttributes']; | ||||||
|     this.manifestCustomAttributes(); |     this.manifestCustomAttributes(this.automationTypes); | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|  |     getAttributes, | ||||||
|  |     getInputType, | ||||||
|  |     getOperators, | ||||||
|  |     getCustomAttributeType, | ||||||
|  |     showActionInput, | ||||||
|     isFeatureEnabled(flag) { |     isFeatureEnabled(flag) { | ||||||
|       return this.isFeatureEnabledonAccount(this.accountId, flag); |       return this.isFeatureEnabledonAccount(this.accountId, flag); | ||||||
|     }, |     }, | ||||||
|  |     emitSaveAutomation() { | ||||||
|  |       this.errors = validateAutomation(this.automation); | ||||||
|  |       if (Object.keys(this.errors).length === 0) { | ||||||
|  |         const automation = generateAutomationPayload(this.automation); | ||||||
|  |         this.$emit('saveAutomation', automation, this.mode); | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
| @@ -121,7 +166,7 @@ export default { | |||||||
|             <select |             <select | ||||||
|               v-model="automation.event_name" |               v-model="automation.event_name" | ||||||
|               class="m-0" |               class="m-0" | ||||||
|               @change="onEventChange()" |               @change="onEventChange(automation)" | ||||||
|             > |             > | ||||||
|               <option |               <option | ||||||
|                 v-for="event in automationRuleEvents" |                 v-for="event in automationRuleEvents" | ||||||
| @@ -154,9 +199,26 @@ export default { | |||||||
|               v-for="(condition, i) in automation.conditions" |               v-for="(condition, i) in automation.conditions" | ||||||
|               :key="i" |               :key="i" | ||||||
|               v-model="automation.conditions[i]" |               v-model="automation.conditions[i]" | ||||||
|               :filter-attributes="getAttributes(automation.event_name)" |               :filter-attributes=" | ||||||
|               :input-type="getInputType(automation.conditions[i].attribute_key)" |                 getAttributes(automationTypes, automation.event_name) | ||||||
|               :operators="getOperators(automation.conditions[i].attribute_key)" |               " | ||||||
|  |               :input-type=" | ||||||
|  |                 getInputType( | ||||||
|  |                   allCustomAttributes, | ||||||
|  |                   automationTypes, | ||||||
|  |                   automation, | ||||||
|  |                   automation.conditions[i].attribute_key | ||||||
|  |                 ) | ||||||
|  |               " | ||||||
|  |               :operators=" | ||||||
|  |                 getOperators( | ||||||
|  |                   allCustomAttributes, | ||||||
|  |                   automationTypes, | ||||||
|  |                   automation, | ||||||
|  |                   mode, | ||||||
|  |                   automation.conditions[i].attribute_key | ||||||
|  |                 ) | ||||||
|  |               " | ||||||
|               :dropdown-values=" |               :dropdown-values=" | ||||||
|                 getConditionDropdownValues( |                 getConditionDropdownValues( | ||||||
|                   automation.conditions[i].attribute_key |                   automation.conditions[i].attribute_key | ||||||
| @@ -164,15 +226,26 @@ export default { | |||||||
|               " |               " | ||||||
|               :show-query-operator="i !== automation.conditions.length - 1" |               :show-query-operator="i !== automation.conditions.length - 1" | ||||||
|               :custom-attribute-type=" |               :custom-attribute-type=" | ||||||
|                 getCustomAttributeType(automation.conditions[i].attribute_key) |                 getCustomAttributeType( | ||||||
|  |                   automationTypes, | ||||||
|  |                   automation, | ||||||
|  |                   automation.conditions[i].attribute_key | ||||||
|  |                 ) | ||||||
|               " |               " | ||||||
|               :error-message=" |               :error-message=" | ||||||
|                 errors[`condition_${i}`] |                 errors[`condition_${i}`] | ||||||
|                   ? $t(`AUTOMATION.ERRORS.${errors[`condition_${i}`]}`) |                   ? $t(`AUTOMATION.ERRORS.${errors[`condition_${i}`]}`) | ||||||
|                   : '' |                   : '' | ||||||
|               " |               " | ||||||
|               @resetFilter="resetFilter(i, automation.conditions[i])" |               @resetFilter=" | ||||||
|               @removeFilter="removeFilter(i)" |                 resetFilter( | ||||||
|  |                   automation, | ||||||
|  |                   automationTypes, | ||||||
|  |                   i, | ||||||
|  |                   automation.conditions[i] | ||||||
|  |                 ) | ||||||
|  |               " | ||||||
|  |               @removeFilter="removeFilter(automation, i)" | ||||||
|             /> |             /> | ||||||
|             <div class="mt-4"> |             <div class="mt-4"> | ||||||
|               <woot-button |               <woot-button | ||||||
| @@ -180,7 +253,7 @@ export default { | |||||||
|                 color-scheme="success" |                 color-scheme="success" | ||||||
|                 variant="smooth" |                 variant="smooth" | ||||||
|                 size="small" |                 size="small" | ||||||
|                 @click="appendNewCondition" |                 @click="appendNewCondition(automation)" | ||||||
|               > |               > | ||||||
|                 {{ $t('AUTOMATION.ADD.CONDITION_BUTTON_LABEL') }} |                 {{ $t('AUTOMATION.ADD.CONDITION_BUTTON_LABEL') }} | ||||||
|               </woot-button> |               </woot-button> | ||||||
| @@ -205,15 +278,18 @@ export default { | |||||||
|                 getActionDropdownValues(automation.actions[i].action_name) |                 getActionDropdownValues(automation.actions[i].action_name) | ||||||
|               " |               " | ||||||
|               :show-action-input=" |               :show-action-input=" | ||||||
|                 showActionInput(automation.actions[i].action_name) |                 showActionInput( | ||||||
|  |                   automationActionTypes, | ||||||
|  |                   automation.actions[i].action_name | ||||||
|  |                 ) | ||||||
|               " |               " | ||||||
|               :error-message=" |               :error-message=" | ||||||
|                 errors[`action_${i}`] |                 errors[`action_${i}`] | ||||||
|                   ? $t(`AUTOMATION.ERRORS.${errors[`action_${i}`]}`) |                   ? $t(`AUTOMATION.ERRORS.${errors[`action_${i}`]}`) | ||||||
|                   : '' |                   : '' | ||||||
|               " |               " | ||||||
|               @resetAction="resetAction(i)" |               @resetAction="resetAction(automation, i)" | ||||||
|               @removeAction="removeAction(i)" |               @removeAction="removeAction(automation, i)" | ||||||
|             /> |             /> | ||||||
|             <div class="mt-4"> |             <div class="mt-4"> | ||||||
|               <woot-button |               <woot-button | ||||||
| @@ -221,7 +297,7 @@ export default { | |||||||
|                 color-scheme="success" |                 color-scheme="success" | ||||||
|                 variant="smooth" |                 variant="smooth" | ||||||
|                 size="small" |                 size="small" | ||||||
|                 @click="appendNewAction" |                 @click="appendNewAction(automation)" | ||||||
|               > |               > | ||||||
|                 {{ $t('AUTOMATION.ADD.ACTION_BUTTON_LABEL') }} |                 {{ $t('AUTOMATION.ADD.ACTION_BUTTON_LABEL') }} | ||||||
|               </woot-button> |               </woot-button> | ||||||
| @@ -234,7 +310,7 @@ export default { | |||||||
|             <woot-button class="button clear" @click.prevent="onClose"> |             <woot-button class="button clear" @click.prevent="onClose"> | ||||||
|               {{ $t('AUTOMATION.ADD.CANCEL_BUTTON_TEXT') }} |               {{ $t('AUTOMATION.ADD.CANCEL_BUTTON_TEXT') }} | ||||||
|             </woot-button> |             </woot-button> | ||||||
|             <woot-button @click="submitAutomation"> |             <woot-button @click="emitSaveAutomation"> | ||||||
|               {{ $t('AUTOMATION.ADD.SUBMIT') }} |               {{ $t('AUTOMATION.ADD.SUBMIT') }} | ||||||
|             </woot-button> |             </woot-button> | ||||||
|           </div> |           </div> | ||||||
|   | |||||||
| @@ -1,8 +1,18 @@ | |||||||
| <script> | <script> | ||||||
| import { mapGetters } from 'vuex'; | import { mapGetters } from 'vuex'; | ||||||
| import automationMethodsMixin from 'dashboard/mixins/automations/methodsMixin'; | import { useAutomation } from 'dashboard/composables/useAutomation'; | ||||||
| import FilterInputBox from 'dashboard/components/widgets/FilterInput/Index.vue'; | import FilterInputBox from 'dashboard/components/widgets/FilterInput/Index.vue'; | ||||||
| import AutomationActionInput from 'dashboard/components/widgets/AutomationActionInput.vue'; | import AutomationActionInput from 'dashboard/components/widgets/AutomationActionInput.vue'; | ||||||
|  | import { | ||||||
|  |   getFileName, | ||||||
|  |   generateAutomationPayload, | ||||||
|  |   getAttributes, | ||||||
|  |   getInputType, | ||||||
|  |   getOperators, | ||||||
|  |   getCustomAttributeType, | ||||||
|  |   showActionInput, | ||||||
|  | } from 'dashboard/helper/automationHelper'; | ||||||
|  | import { validateAutomation } from 'dashboard/helper/validations'; | ||||||
|  |  | ||||||
| import { | import { | ||||||
|   AUTOMATION_RULE_EVENTS, |   AUTOMATION_RULE_EVENTS, | ||||||
| @@ -15,7 +25,6 @@ export default { | |||||||
|     FilterInputBox, |     FilterInputBox, | ||||||
|     AutomationActionInput, |     AutomationActionInput, | ||||||
|   }, |   }, | ||||||
|   mixins: [automationMethodsMixin], |  | ||||||
|   props: { |   props: { | ||||||
|     onClose: { |     onClose: { | ||||||
|       type: Function, |       type: Function, | ||||||
| @@ -26,6 +35,34 @@ export default { | |||||||
|       default: () => {}, |       default: () => {}, | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|  |   setup() { | ||||||
|  |     const { | ||||||
|  |       onEventChange, | ||||||
|  |       getConditionDropdownValues, | ||||||
|  |       appendNewCondition, | ||||||
|  |       appendNewAction, | ||||||
|  |       removeFilter, | ||||||
|  |       removeAction, | ||||||
|  |       resetFilter, | ||||||
|  |       resetAction, | ||||||
|  |       getActionDropdownValues, | ||||||
|  |       formatAutomation, | ||||||
|  |       manifestCustomAttributes, | ||||||
|  |     } = useAutomation(); | ||||||
|  |     return { | ||||||
|  |       onEventChange, | ||||||
|  |       getConditionDropdownValues, | ||||||
|  |       appendNewCondition, | ||||||
|  |       appendNewAction, | ||||||
|  |       removeFilter, | ||||||
|  |       removeAction, | ||||||
|  |       resetFilter, | ||||||
|  |       resetAction, | ||||||
|  |       getActionDropdownValues, | ||||||
|  |       formatAutomation, | ||||||
|  |       manifestCustomAttributes, | ||||||
|  |     }; | ||||||
|  |   }, | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       automationTypes: JSON.parse(JSON.stringify(AUTOMATIONS)), |       automationTypes: JSON.parse(JSON.stringify(AUTOMATIONS)), | ||||||
| @@ -61,14 +98,33 @@ export default { | |||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|   mounted() { |   mounted() { | ||||||
|     this.manifestCustomAttributes(); |     this.manifestCustomAttributes(this.automationTypes); | ||||||
|     this.allCustomAttributes = this.$store.getters['attributes/getAttributes']; |     this.allCustomAttributes = this.$store.getters['attributes/getAttributes']; | ||||||
|     this.formatAutomation(this.selectedResponse); |  | ||||||
|  |     this.automation = this.formatAutomation( | ||||||
|  |       this.selectedResponse, | ||||||
|  |       this.allCustomAttributes, | ||||||
|  |       this.automationTypes, | ||||||
|  |       this.automationActionTypes | ||||||
|  |     ); | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|  |     getFileName, | ||||||
|  |     getAttributes, | ||||||
|  |     getInputType, | ||||||
|  |     getOperators, | ||||||
|  |     getCustomAttributeType, | ||||||
|  |     showActionInput, | ||||||
|     isFeatureEnabled(flag) { |     isFeatureEnabled(flag) { | ||||||
|       return this.isFeatureEnabledonAccount(this.accountId, flag); |       return this.isFeatureEnabledonAccount(this.accountId, flag); | ||||||
|     }, |     }, | ||||||
|  |     emitSaveAutomation() { | ||||||
|  |       this.errors = validateAutomation(this.automation); | ||||||
|  |       if (Object.keys(this.errors).length === 0) { | ||||||
|  |         const automation = generateAutomationPayload(this.automation); | ||||||
|  |         this.$emit('saveAutomation', automation, this.mode); | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
| @@ -99,7 +155,10 @@ export default { | |||||||
|         <div class="event_wrapper"> |         <div class="event_wrapper"> | ||||||
|           <label :class="{ error: errors.event_name }"> |           <label :class="{ error: errors.event_name }"> | ||||||
|             {{ $t('AUTOMATION.ADD.FORM.EVENT.LABEL') }} |             {{ $t('AUTOMATION.ADD.FORM.EVENT.LABEL') }} | ||||||
|             <select v-model="automation.event_name" @change="onEventChange()"> |             <select | ||||||
|  |               v-model="automation.event_name" | ||||||
|  |               @change="onEventChange(automation)" | ||||||
|  |             > | ||||||
|               <option |               <option | ||||||
|                 v-for="event in automationRuleEvents" |                 v-for="event in automationRuleEvents" | ||||||
|                 :key="event.key" |                 :key="event.key" | ||||||
| @@ -125,16 +184,37 @@ export default { | |||||||
|               v-for="(condition, i) in automation.conditions" |               v-for="(condition, i) in automation.conditions" | ||||||
|               :key="i" |               :key="i" | ||||||
|               v-model="automation.conditions[i]" |               v-model="automation.conditions[i]" | ||||||
|               :filter-attributes="getAttributes(automation.event_name)" |               :filter-attributes=" | ||||||
|               :input-type="getInputType(automation.conditions[i].attribute_key)" |                 getAttributes(automationTypes, automation.event_name) | ||||||
|               :operators="getOperators(automation.conditions[i].attribute_key)" |               " | ||||||
|  |               :input-type=" | ||||||
|  |                 getInputType( | ||||||
|  |                   allCustomAttributes, | ||||||
|  |                   automationTypes, | ||||||
|  |                   automation, | ||||||
|  |                   automation.conditions[i].attribute_key | ||||||
|  |                 ) | ||||||
|  |               " | ||||||
|  |               :operators=" | ||||||
|  |                 getOperators( | ||||||
|  |                   allCustomAttributes, | ||||||
|  |                   automationTypes, | ||||||
|  |                   automation, | ||||||
|  |                   mode, | ||||||
|  |                   automation.conditions[i].attribute_key | ||||||
|  |                 ) | ||||||
|  |               " | ||||||
|               :dropdown-values=" |               :dropdown-values=" | ||||||
|                 getConditionDropdownValues( |                 getConditionDropdownValues( | ||||||
|                   automation.conditions[i].attribute_key |                   automation.conditions[i].attribute_key | ||||||
|                 ) |                 ) | ||||||
|               " |               " | ||||||
|               :custom-attribute-type=" |               :custom-attribute-type=" | ||||||
|                 getCustomAttributeType(automation.conditions[i].attribute_key) |                 getCustomAttributeType( | ||||||
|  |                   automationTypes, | ||||||
|  |                   automation, | ||||||
|  |                   automation.conditions[i].attribute_key | ||||||
|  |                 ) | ||||||
|               " |               " | ||||||
|               :show-query-operator="i !== automation.conditions.length - 1" |               :show-query-operator="i !== automation.conditions.length - 1" | ||||||
|               :error-message=" |               :error-message=" | ||||||
| @@ -142,8 +222,15 @@ export default { | |||||||
|                   ? $t(`AUTOMATION.ERRORS.${errors[`condition_${i}`]}`) |                   ? $t(`AUTOMATION.ERRORS.${errors[`condition_${i}`]}`) | ||||||
|                   : '' |                   : '' | ||||||
|               " |               " | ||||||
|               @resetFilter="resetFilter(i, automation.conditions[i])" |               @resetFilter=" | ||||||
|               @removeFilter="removeFilter(i)" |                 resetFilter( | ||||||
|  |                   automation, | ||||||
|  |                   automationTypes, | ||||||
|  |                   i, | ||||||
|  |                   automation.conditions[i] | ||||||
|  |                 ) | ||||||
|  |               " | ||||||
|  |               @removeFilter="removeFilter(automation, i)" | ||||||
|             /> |             /> | ||||||
|             <div class="mt-4"> |             <div class="mt-4"> | ||||||
|               <woot-button |               <woot-button | ||||||
| @@ -151,7 +238,7 @@ export default { | |||||||
|                 color-scheme="success" |                 color-scheme="success" | ||||||
|                 variant="smooth" |                 variant="smooth" | ||||||
|                 size="small" |                 size="small" | ||||||
|                 @click="appendNewCondition" |                 @click="appendNewCondition(automation)" | ||||||
|               > |               > | ||||||
|                 {{ $t('AUTOMATION.ADD.CONDITION_BUTTON_LABEL') }} |                 {{ $t('AUTOMATION.ADD.CONDITION_BUTTON_LABEL') }} | ||||||
|               </woot-button> |               </woot-button> | ||||||
| @@ -173,15 +260,17 @@ export default { | |||||||
|               v-model="automation.actions[i]" |               v-model="automation.actions[i]" | ||||||
|               :action-types="automationActionTypes" |               :action-types="automationActionTypes" | ||||||
|               :dropdown-values="getActionDropdownValues(action.action_name)" |               :dropdown-values="getActionDropdownValues(action.action_name)" | ||||||
|               :show-action-input="showActionInput(action.action_name)" |               :show-action-input=" | ||||||
|  |                 showActionInput(automationActionTypes, action.action_name) | ||||||
|  |               " | ||||||
|               :error-message=" |               :error-message=" | ||||||
|                 errors[`action_${i}`] |                 errors[`action_${i}`] | ||||||
|                   ? $t(`AUTOMATION.ERRORS.${errors[`action_${i}`]}`) |                   ? $t(`AUTOMATION.ERRORS.${errors[`action_${i}`]}`) | ||||||
|                   : '' |                   : '' | ||||||
|               " |               " | ||||||
|               :initial-file-name="getFileName(action, automation.files)" |               :initial-file-name="getFileName(action, automation.files)" | ||||||
|               @resetAction="resetAction(i)" |               @resetAction="resetAction(automation, i)" | ||||||
|               @removeAction="removeAction(i)" |               @removeAction="removeAction(automation, i)" | ||||||
|             /> |             /> | ||||||
|             <div class="mt-4"> |             <div class="mt-4"> | ||||||
|               <woot-button |               <woot-button | ||||||
| @@ -189,7 +278,7 @@ export default { | |||||||
|                 color-scheme="success" |                 color-scheme="success" | ||||||
|                 variant="smooth" |                 variant="smooth" | ||||||
|                 size="small" |                 size="small" | ||||||
|                 @click="appendNewAction" |                 @click="appendNewAction(automation)" | ||||||
|               > |               > | ||||||
|                 {{ $t('AUTOMATION.ADD.ACTION_BUTTON_LABEL') }} |                 {{ $t('AUTOMATION.ADD.ACTION_BUTTON_LABEL') }} | ||||||
|               </woot-button> |               </woot-button> | ||||||
| @@ -206,7 +295,7 @@ export default { | |||||||
|             > |             > | ||||||
|               {{ $t('AUTOMATION.EDIT.CANCEL_BUTTON_TEXT') }} |               {{ $t('AUTOMATION.EDIT.CANCEL_BUTTON_TEXT') }} | ||||||
|             </woot-button> |             </woot-button> | ||||||
|             <woot-button @click="submitAutomation"> |             <woot-button @click="emitSaveAutomation"> | ||||||
|               {{ $t('AUTOMATION.EDIT.SUBMIT') }} |               {{ $t('AUTOMATION.EDIT.SUBMIT') }} | ||||||
|             </woot-button> |             </woot-button> | ||||||
|           </div> |           </div> | ||||||
|   | |||||||
| @@ -1,450 +0,0 @@ | |||||||
| import methodsMixin from '../../../dashboard/mixins/automations/methodsMixin'; |  | ||||||
| import { |  | ||||||
|   automation, |  | ||||||
|   customAttributes, |  | ||||||
|   agents, |  | ||||||
|   booleanFilterOptions, |  | ||||||
|   teams, |  | ||||||
|   labels, |  | ||||||
|   statusFilterOptions, |  | ||||||
|   campaigns, |  | ||||||
|   contacts, |  | ||||||
|   inboxes, |  | ||||||
|   languages, |  | ||||||
|   countries, |  | ||||||
|   slaPolicies, |  | ||||||
|   MESSAGE_CONDITION_VALUES, |  | ||||||
|   automationToSubmit, |  | ||||||
|   savedAutomation, |  | ||||||
| } from './automationFixtures'; |  | ||||||
| import { |  | ||||||
|   AUTOMATIONS, |  | ||||||
|   AUTOMATION_ACTION_TYPES, |  | ||||||
| } from '../../../dashboard/routes/dashboard/settings/automation/constants.js'; |  | ||||||
|  |  | ||||||
| import { createWrapper, createLocalVue } from '@vue/test-utils'; |  | ||||||
| import Vue from 'vue'; |  | ||||||
| import Vuex from 'vuex'; |  | ||||||
| const localVue = createLocalVue(); |  | ||||||
| localVue.use(Vuex); |  | ||||||
|  |  | ||||||
| // Vuelidate required to test submit method |  | ||||||
|  |  | ||||||
| const createComponent = ( |  | ||||||
|   mixins, |  | ||||||
|   data, |  | ||||||
|   // eslint-disable-next-line default-param-last |  | ||||||
|   computed = {}, |  | ||||||
|   // eslint-disable-next-line default-param-last |  | ||||||
|   methods = {}, |  | ||||||
|   validations |  | ||||||
| ) => { |  | ||||||
|   const Component = { |  | ||||||
|     render() {}, |  | ||||||
|     mixins, |  | ||||||
|     data, |  | ||||||
|     computed, |  | ||||||
|     methods, |  | ||||||
|     validations, |  | ||||||
|   }; |  | ||||||
|   const Constructor = Vue.extend(Component); |  | ||||||
|   const vm = new Constructor().$mount(); |  | ||||||
|   return createWrapper(vm); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| const generateComputedProperties = () => { |  | ||||||
|   return { |  | ||||||
|     statusFilterOptions() { |  | ||||||
|       return statusFilterOptions; |  | ||||||
|     }, |  | ||||||
|     agents() { |  | ||||||
|       return agents; |  | ||||||
|     }, |  | ||||||
|     customAttributes() { |  | ||||||
|       return customAttributes; |  | ||||||
|     }, |  | ||||||
|     labels() { |  | ||||||
|       return labels; |  | ||||||
|     }, |  | ||||||
|     teams() { |  | ||||||
|       return teams; |  | ||||||
|     }, |  | ||||||
|     booleanFilterOptions() { |  | ||||||
|       return booleanFilterOptions; |  | ||||||
|     }, |  | ||||||
|     campaigns() { |  | ||||||
|       return campaigns; |  | ||||||
|     }, |  | ||||||
|     contacts() { |  | ||||||
|       return contacts; |  | ||||||
|     }, |  | ||||||
|     inboxes() { |  | ||||||
|       return inboxes; |  | ||||||
|     }, |  | ||||||
|     languages() { |  | ||||||
|       return languages; |  | ||||||
|     }, |  | ||||||
|     countries() { |  | ||||||
|       return countries; |  | ||||||
|     }, |  | ||||||
|     slaPolicies() { |  | ||||||
|       return slaPolicies; |  | ||||||
|     }, |  | ||||||
|     MESSAGE_CONDITION_VALUES() { |  | ||||||
|       return MESSAGE_CONDITION_VALUES; |  | ||||||
|     }, |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| describe('automationMethodsMixin', () => { |  | ||||||
|   it('getFileName returns the correct file name', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return {}; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     expect( |  | ||||||
|       wrapper.vm.getFileName(automation.actions[0], automation.files) |  | ||||||
|     ).toEqual(automation.files[0].filename); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('getAttributes returns all attributes', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         automationTypes: AUTOMATIONS, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     expect(wrapper.vm.getAttributes('conversation_created')).toEqual( |  | ||||||
|       AUTOMATIONS.conversation_created.conditions |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('getAttributes returns all respective attributes', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         allCustomAttributes: customAttributes, |  | ||||||
|         automationTypes: AUTOMATIONS, |  | ||||||
|         automation, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     expect(wrapper.vm.getInputType('status')).toEqual('multi_select'); |  | ||||||
|     expect(wrapper.vm.getInputType('my_list')).toEqual('search_select'); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('getOperators returns all respective operators', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         allCustomAttributes: customAttributes, |  | ||||||
|         automationTypes: AUTOMATIONS, |  | ||||||
|         automation, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     expect(wrapper.vm.getOperators('status')).toEqual( |  | ||||||
|       AUTOMATIONS.conversation_created.conditions[0].filterOperators |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('getAutomationType returns the correct automationType', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         automationTypes: AUTOMATIONS, |  | ||||||
|         automation, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     expect(wrapper.vm.getAutomationType('status')).toEqual( |  | ||||||
|       AUTOMATIONS[automation.event_name].conditions[0] |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('getConditionDropdownValues returns respective condition dropdown values', () => { |  | ||||||
|     const computed = generateComputedProperties(); |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         allCustomAttributes: customAttributes, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data, computed); |  | ||||||
|     expect(wrapper.vm.getConditionDropdownValues('status')).toEqual( |  | ||||||
|       statusFilterOptions |  | ||||||
|     ); |  | ||||||
|     expect(wrapper.vm.getConditionDropdownValues('team_id')).toEqual(teams); |  | ||||||
|     expect(wrapper.vm.getConditionDropdownValues('assignee_id')).toEqual( |  | ||||||
|       agents |  | ||||||
|     ); |  | ||||||
|     expect(wrapper.vm.getConditionDropdownValues('contact')).toEqual(contacts); |  | ||||||
|     expect(wrapper.vm.getConditionDropdownValues('inbox_id')).toEqual(inboxes); |  | ||||||
|     expect(wrapper.vm.getConditionDropdownValues('campaigns')).toEqual( |  | ||||||
|       campaigns |  | ||||||
|     ); |  | ||||||
|     expect(wrapper.vm.getConditionDropdownValues('browser_language')).toEqual( |  | ||||||
|       languages |  | ||||||
|     ); |  | ||||||
|     expect(wrapper.vm.getConditionDropdownValues('country_code')).toEqual( |  | ||||||
|       countries |  | ||||||
|     ); |  | ||||||
|     expect(wrapper.vm.getConditionDropdownValues('message_type')).toEqual( |  | ||||||
|       MESSAGE_CONDITION_VALUES |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('appendNewCondition appends a new condition to the automation data property', () => { |  | ||||||
|     const condition = { |  | ||||||
|       attribute_key: 'status', |  | ||||||
|       filter_operator: 'equal_to', |  | ||||||
|       values: '', |  | ||||||
|       query_operator: 'and', |  | ||||||
|       custom_attribute_type: '', |  | ||||||
|     }; |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         automation, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     wrapper.vm.appendNewCondition(); |  | ||||||
|     expect(automation.conditions[automation.conditions.length - 1]).toEqual( |  | ||||||
|       condition |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('appendNewAction appends a new condition to the automation data property', () => { |  | ||||||
|     const action = { |  | ||||||
|       action_name: 'assign_agent', |  | ||||||
|       action_params: [], |  | ||||||
|     }; |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         automation, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     wrapper.vm.appendNewAction(); |  | ||||||
|     expect(automation.actions[automation.actions.length - 1]).toEqual(action); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('removeFilter removes the given condition in the automation', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         automation, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     wrapper.vm.removeFilter(0); |  | ||||||
|     expect(automation.conditions.length).toEqual(1); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('removeAction removes the given action in the automation', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         automation, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     wrapper.vm.removeAction(0); |  | ||||||
|     expect(automation.actions.length).toEqual(1); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('resetFilter resets the current automation conditions', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         automation: automationToSubmit, |  | ||||||
|         automationTypes: AUTOMATIONS, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const conditionAfterReset = { |  | ||||||
|       attribute_key: 'status', |  | ||||||
|       filter_operator: 'equal_to', |  | ||||||
|       values: '', |  | ||||||
|       query_operator: 'and', |  | ||||||
|       custom_attribute_type: '', |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     wrapper.vm.resetFilter(0, automationToSubmit.conditions[0]); |  | ||||||
|     expect(automation.conditions[0]).toEqual(conditionAfterReset); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('showUserInput returns boolean value based on the operator type', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return {}; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     expect(wrapper.vm.showUserInput('is_present')).toBeFalsy(); |  | ||||||
|     expect(wrapper.vm.showUserInput('is_not_present')).toBeFalsy(); |  | ||||||
|     expect(wrapper.vm.showUserInput('equal_to')).toBeTruthy(); |  | ||||||
|     expect(wrapper.vm.showUserInput('not_equal_to')).toBeTruthy(); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('showActionInput returns boolean value based on the action type', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         automationActionTypes: AUTOMATION_ACTION_TYPES, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     expect(wrapper.vm.showActionInput('send_email_to_team')).toBeFalsy(); |  | ||||||
|     expect(wrapper.vm.showActionInput('send_message')).toBeFalsy(); |  | ||||||
|     expect(wrapper.vm.showActionInput('send_webhook_event')).toBeTruthy(); |  | ||||||
|     expect(wrapper.vm.showActionInput('resolve_conversation')).toBeFalsy(); |  | ||||||
|     expect(wrapper.vm.showActionInput('add_label')).toBeTruthy(); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('resetAction resets the action to default state', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         automation, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data); |  | ||||||
|     wrapper.vm.resetAction(0); |  | ||||||
|     expect(automation.actions[0].action_params).toEqual([]); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('manifestConditions resets the action to default state', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         automation: {}, |  | ||||||
|         allCustomAttributes: customAttributes, |  | ||||||
|         automationTypes: AUTOMATIONS, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const methods = { |  | ||||||
|       getConditionDropdownValues() { |  | ||||||
|         return statusFilterOptions; |  | ||||||
|       }, |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     const manifestedConditions = [ |  | ||||||
|       { |  | ||||||
|         values: [ |  | ||||||
|           { |  | ||||||
|             id: 'open', |  | ||||||
|             name: 'Open', |  | ||||||
|           }, |  | ||||||
|         ], |  | ||||||
|         attribute_key: 'status', |  | ||||||
|         filter_operator: 'equal_to', |  | ||||||
|         query_operator: 'and', |  | ||||||
|       }, |  | ||||||
|     ]; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data, {}, methods); |  | ||||||
|     expect(wrapper.vm.manifestConditions(savedAutomation)).toEqual( |  | ||||||
|       manifestedConditions |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('generateActionsArray return the manifested actions array', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         automationActionTypes: AUTOMATION_ACTION_TYPES, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const computed = { |  | ||||||
|       agents() { |  | ||||||
|         return agents; |  | ||||||
|       }, |  | ||||||
|       labels() { |  | ||||||
|         return labels; |  | ||||||
|       }, |  | ||||||
|       teams() { |  | ||||||
|         return teams; |  | ||||||
|       }, |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     const methods = { |  | ||||||
|       getActionDropdownValues() { |  | ||||||
|         return [ |  | ||||||
|           { |  | ||||||
|             id: 2, |  | ||||||
|             name: 'testlabel', |  | ||||||
|           }, |  | ||||||
|           { |  | ||||||
|             id: 1, |  | ||||||
|             name: 'snoozes', |  | ||||||
|           }, |  | ||||||
|         ]; |  | ||||||
|       }, |  | ||||||
|     }; |  | ||||||
|     const testAction = { |  | ||||||
|       action_name: 'add_label', |  | ||||||
|       action_params: [2], |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     const expectedActionArray = [ |  | ||||||
|       { |  | ||||||
|         id: 2, |  | ||||||
|         name: 'testlabel', |  | ||||||
|       }, |  | ||||||
|     ]; |  | ||||||
|  |  | ||||||
|     const wrapper = createComponent([methodsMixin], data, computed, methods); |  | ||||||
|     expect(wrapper.vm.generateActionsArray(testAction)).toEqual( |  | ||||||
|       expectedActionArray |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('manifestActions manifest the received action and generate the correct array', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return { |  | ||||||
|         automation: {}, |  | ||||||
|         allCustomAttributes: customAttributes, |  | ||||||
|         automationTypes: AUTOMATIONS, |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     const methods = { |  | ||||||
|       generateActionsArray() { |  | ||||||
|         return [ |  | ||||||
|           { |  | ||||||
|             id: 2, |  | ||||||
|             name: 'testlabel', |  | ||||||
|           }, |  | ||||||
|         ]; |  | ||||||
|       }, |  | ||||||
|     }; |  | ||||||
|     const expectedActions = [ |  | ||||||
|       { |  | ||||||
|         action_name: 'add_label', |  | ||||||
|         action_params: [ |  | ||||||
|           { |  | ||||||
|             id: 2, |  | ||||||
|             name: 'testlabel', |  | ||||||
|           }, |  | ||||||
|         ], |  | ||||||
|       }, |  | ||||||
|     ]; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data, {}, methods); |  | ||||||
|     expect(wrapper.vm.manifestActions(savedAutomation)).toEqual( |  | ||||||
|       expectedActions |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('getActionDropdownValues returns Action dropdown Values', () => { |  | ||||||
|     const data = () => { |  | ||||||
|       return {}; |  | ||||||
|     }; |  | ||||||
|     const computed = { |  | ||||||
|       agents() { |  | ||||||
|         return agents; |  | ||||||
|       }, |  | ||||||
|       labels() { |  | ||||||
|         return labels; |  | ||||||
|       }, |  | ||||||
|       teams() { |  | ||||||
|         return teams; |  | ||||||
|       }, |  | ||||||
|       slaPolicies() { |  | ||||||
|         return slaPolicies; |  | ||||||
|       }, |  | ||||||
|     }; |  | ||||||
|     const expectedActionDropdownValues = [ |  | ||||||
|       { id: 'testlabel', name: 'testlabel' }, |  | ||||||
|       { id: 'snoozes', name: 'snoozes' }, |  | ||||||
|     ]; |  | ||||||
|     const wrapper = createComponent([methodsMixin], data, computed); |  | ||||||
|     expect(wrapper.vm.getActionDropdownValues('add_label')).toEqual( |  | ||||||
|       expectedActionDropdownValues |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
		Reference in New Issue
	
	Block a user
	 Sivin Varghese
					Sivin Varghese