mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-30 18:47:51 +00:00 
			
		
		
		
	Merge branch 'develop' into snyk-fix-f07a06acd2309e1b311aa94bd2ff524b
This commit is contained in:
		
							
								
								
									
										66
									
								
								app/javascript/dashboard/helper/messageHelper.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								app/javascript/dashboard/helper/messageHelper.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  | const MESSAGE_VARIABLES_REGEX = /{{(.*?)}}/g; | ||||||
|  | export const replaceVariablesInMessage = ({ message, variables }) => { | ||||||
|  |   return message.replace(MESSAGE_VARIABLES_REGEX, (match, replace) => { | ||||||
|  |     return variables[replace.trim()] | ||||||
|  |       ? variables[replace.trim().toLowerCase()] | ||||||
|  |       : ''; | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const capitalizeName = name => { | ||||||
|  |   return (name || '').replace(/\b(\w)/g, s => s.toUpperCase()); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const skipCodeBlocks = str => str.replace(/```(?:.|\n)+?```/g, ''); | ||||||
|  |  | ||||||
|  | export const getFirstName = ({ user }) => { | ||||||
|  |   const firstName = user?.name ? user.name.split(' ').shift() : ''; | ||||||
|  |   return capitalizeName(firstName); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const getLastName = ({ user }) => { | ||||||
|  |   if (user && user.name) { | ||||||
|  |     const lastName = | ||||||
|  |       user.name.split(' ').length > 1 ? user.name.split(' ').pop() : ''; | ||||||
|  |     return capitalizeName(lastName); | ||||||
|  |   } | ||||||
|  |   return ''; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const getMessageVariables = ({ conversation }) => { | ||||||
|  |   const { | ||||||
|  |     meta: { assignee = {}, sender = {} }, | ||||||
|  |     id, | ||||||
|  |   } = conversation; | ||||||
|  |  | ||||||
|  |   return { | ||||||
|  |     'contact.name': capitalizeName(sender?.name), | ||||||
|  |     'contact.first_name': getFirstName({ user: sender }), | ||||||
|  |     'contact.last_name': getLastName({ user: sender }), | ||||||
|  |     'contact.email': sender?.email, | ||||||
|  |     'contact.phone': sender?.phone_number, | ||||||
|  |     'contact.id': sender?.id, | ||||||
|  |     'conversation.id': id, | ||||||
|  |     'agent.name': capitalizeName(assignee?.name || ''), | ||||||
|  |     'agent.first_name': getFirstName({ user: assignee }), | ||||||
|  |     'agent.last_name': getLastName({ user: assignee }), | ||||||
|  |     'agent.email': assignee?.email ?? '', | ||||||
|  |   }; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const getUndefinedVariablesInMessage = ({ message, variables }) => { | ||||||
|  |   const messageWithOutCodeBlocks = skipCodeBlocks(message); | ||||||
|  |   const matches = messageWithOutCodeBlocks.match(MESSAGE_VARIABLES_REGEX); | ||||||
|  |   if (!matches) return []; | ||||||
|  |  | ||||||
|  |   return matches | ||||||
|  |     .map(match => { | ||||||
|  |       return match | ||||||
|  |         .replace('{{', '') | ||||||
|  |         .replace('}}', '') | ||||||
|  |         .trim(); | ||||||
|  |     }) | ||||||
|  |     .filter(variable => { | ||||||
|  |       return !variables[variable]; | ||||||
|  |     }); | ||||||
|  | }; | ||||||
							
								
								
									
										169
									
								
								app/javascript/dashboard/helper/specs/messageHelper.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								app/javascript/dashboard/helper/specs/messageHelper.spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | |||||||
|  | import { | ||||||
|  |   replaceVariablesInMessage, | ||||||
|  |   getFirstName, | ||||||
|  |   getLastName, | ||||||
|  |   getMessageVariables, | ||||||
|  |   getUndefinedVariablesInMessage, | ||||||
|  |   capitalizeName, | ||||||
|  | } from '../messageHelper'; | ||||||
|  |  | ||||||
|  | const variables = { | ||||||
|  |   'contact.name': 'John Doe', | ||||||
|  |   'contact.first_name': 'John', | ||||||
|  |   'contact.last_name': 'Doe', | ||||||
|  |   'contact.email': 'john.p@example.com', | ||||||
|  |   'contact.phone': '1234567890', | ||||||
|  |   'conversation.id': 1, | ||||||
|  |   'agent.first_name': 'Samuel', | ||||||
|  |   'agent.last_name': 'Smith', | ||||||
|  |   'agent.email': 'samuel@gmail.com', | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | describe('#replaceVariablesInMessage', () => { | ||||||
|  |   it('returns the message with variable name', () => { | ||||||
|  |     const message = | ||||||
|  |       'No issues. Hey {{contact.first_name}}, we will send the reset instructions to your email {{ contact.email}}. The {{ agent.first_name }} {{ agent.last_name }} will take care of everything. Your conversation id is {{ conversation.id }}.'; | ||||||
|  |     expect(replaceVariablesInMessage({ message, variables })).toBe( | ||||||
|  |       'No issues. Hey John, we will send the reset instructions to your email john.p@example.com. The Samuel Smith will take care of everything. Your conversation id is 1.' | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('returns the message with variable name having white space', () => { | ||||||
|  |     const message = 'hey {{contact.name}} how may I help you?'; | ||||||
|  |     expect(replaceVariablesInMessage({ message, variables })).toBe( | ||||||
|  |       'hey John Doe how may I help you?' | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('returns the message with variable email', () => { | ||||||
|  |     const message = | ||||||
|  |       'No issues. We will send the reset instructions to your email at {{contact.email}}'; | ||||||
|  |     expect(replaceVariablesInMessage({ message, variables })).toBe( | ||||||
|  |       'No issues. We will send the reset instructions to your email at john.p@example.com' | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('returns the message with multiple variables', () => { | ||||||
|  |     const message = | ||||||
|  |       'hey {{ contact.name }}, no issues. We will send the reset instructions to your email at {{contact.email}}'; | ||||||
|  |     expect(replaceVariablesInMessage({ message, variables })).toBe( | ||||||
|  |       'hey John Doe, no issues. We will send the reset instructions to your email at john.p@example.com' | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('returns the message if the variable is not present in variables', () => { | ||||||
|  |     const message = 'Please dm me at {{contact.twitter}}'; | ||||||
|  |     expect(replaceVariablesInMessage({ message, variables })).toBe( | ||||||
|  |       'Please dm me at ' | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | describe('#getFirstName', () => { | ||||||
|  |   it('returns the first name of the contact', () => { | ||||||
|  |     const assignee = { name: 'John Doe' }; | ||||||
|  |     expect(getFirstName({ user: assignee })).toBe('John'); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('returns the first name of the contact with multiple names', () => { | ||||||
|  |     const assignee = { name: 'John Doe Smith' }; | ||||||
|  |     expect(getFirstName({ user: assignee })).toBe('John'); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | describe('#getLastName', () => { | ||||||
|  |   it('returns the last name of the contact', () => { | ||||||
|  |     const assignee = { name: 'John Doe' }; | ||||||
|  |     expect(getLastName({ user: assignee })).toBe('Doe'); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   it('returns the last name of the contact with multiple names', () => { | ||||||
|  |     const assignee = { name: 'John Doe Smith' }; | ||||||
|  |     expect(getLastName({ user: assignee })).toBe('Smith'); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | describe('#getMessageVariables', () => { | ||||||
|  |   it('returns the variables', () => { | ||||||
|  |     const conversation = { | ||||||
|  |       meta: { | ||||||
|  |         assignee: { | ||||||
|  |           name: 'samuel Smith', | ||||||
|  |           email: 'samuel@example.com', | ||||||
|  |         }, | ||||||
|  |         sender: { | ||||||
|  |           name: 'john Doe', | ||||||
|  |           email: 'john.doe@gmail.com', | ||||||
|  |           phone_number: '1234567890', | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |       id: 1, | ||||||
|  |     }; | ||||||
|  |     expect(getMessageVariables({ conversation })).toEqual({ | ||||||
|  |       'contact.name': 'John Doe', | ||||||
|  |       'contact.first_name': 'John', | ||||||
|  |       'contact.last_name': 'Doe', | ||||||
|  |       'contact.email': 'john.doe@gmail.com', | ||||||
|  |       'contact.phone': '1234567890', | ||||||
|  |       'conversation.id': 1, | ||||||
|  |       'agent.name': 'Samuel Smith', | ||||||
|  |       'agent.first_name': 'Samuel', | ||||||
|  |       'agent.last_name': 'Smith', | ||||||
|  |       'agent.email': 'samuel@example.com', | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | describe('#getUndefinedVariablesInMessage', () => { | ||||||
|  |   it('returns the undefined variables', () => { | ||||||
|  |     const message = 'Please dm me at {{contact.twitter}}'; | ||||||
|  |     expect( | ||||||
|  |       getUndefinedVariablesInMessage({ message, variables }).length | ||||||
|  |     ).toEqual(1); | ||||||
|  |     expect(getUndefinedVariablesInMessage({ message, variables })).toEqual( | ||||||
|  |       expect.arrayContaining(['contact.twitter']) | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  |   it('skip variables in string with code blocks', () => { | ||||||
|  |     const message = | ||||||
|  |       'hey {{contact_name}} how are you? ``` code: {{contact_name}} ```'; | ||||||
|  |     const undefinedVariables = getUndefinedVariablesInMessage({ | ||||||
|  |       message, | ||||||
|  |       variables, | ||||||
|  |     }); | ||||||
|  |     expect(undefinedVariables.length).toEqual(1); | ||||||
|  |     expect(undefinedVariables).toEqual( | ||||||
|  |       expect.arrayContaining(['contact_name']) | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | describe('#capitalizeName', () => { | ||||||
|  |   it('capitalize name if name is passed', () => { | ||||||
|  |     const string = 'john peter'; | ||||||
|  |     expect(capitalizeName(string)).toBe('John Peter'); | ||||||
|  |   }); | ||||||
|  |   it('returns empty string if the name is null', () => { | ||||||
|  |     expect(capitalizeName(null)).toBe(''); | ||||||
|  |   }); | ||||||
|  |   it('capitalize first name if full name is passed', () => { | ||||||
|  |     const string = 'john Doe'; | ||||||
|  |     expect(capitalizeName(string)).toBe('John Doe'); | ||||||
|  |   }); | ||||||
|  |   it('returns empty string if the string is empty', () => { | ||||||
|  |     const string = ''; | ||||||
|  |     expect(capitalizeName(string)).toBe(''); | ||||||
|  |   }); | ||||||
|  |   it('capitalize last name if last name is passed', () => { | ||||||
|  |     const string = 'john doe'; | ||||||
|  |     expect(capitalizeName(string)).toBe('John Doe'); | ||||||
|  |   }); | ||||||
|  |   it('capitalize first name if first name is passed', () => { | ||||||
|  |     const string = 'john'; | ||||||
|  |     expect(capitalizeName(string)).toBe('John'); | ||||||
|  |   }); | ||||||
|  |   it('capitalize last name if last name is passed', () => { | ||||||
|  |     const string = 'doe'; | ||||||
|  |     expect(capitalizeName(string)).toBe('Doe'); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| shared: &shared | shared: &shared | ||||||
|   version: '2.16.0' |   version: '2.16.1' | ||||||
|  |  | ||||||
| development: | development: | ||||||
|   <<: *shared |   <<: *shared | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "@chatwoot/chatwoot", |   "name": "@chatwoot/chatwoot", | ||||||
|   "version": "2.16.0", |   "version": "2.16.1", | ||||||
|   "license": "MIT", |   "license": "MIT", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "eslint": "eslint app/**/*.{js,vue}", |     "eslint": "eslint app/**/*.{js,vue}", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Muhsin Keloth
					Muhsin Keloth