mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 02:57:57 +00:00 
			
		
		
		
	 55633ab063
			
		
	
	55633ab063
	
	
	
		
			
			# Pull Request Template ## Description This PR incudes new Agent assignment policy index page with CRUD actions. Fixes https://linear.app/chatwoot/issue/CW-5570/feat-assignment-policy-index-page-with-actions ## Type of change - [x] New feature (non-breaking change which adds functionality) ## How Has This Been Tested? ### Loom https://www.loom.com/share/17ab5ceca4854f179628a3b53f347e5a?sid=cb64e881-57fd-4ae1-921b-7648653cca33 ### Screenshots **Light mode** <img width="1428" height="888" alt="image" src="https://github.com/user-attachments/assets/fdbb83e9-1f4f-4432-9e8a-4a8f1b810d31" /> **Dark mode** <img width="1428" height="888" alt="image" src="https://github.com/user-attachments/assets/f1fb38b9-1150-482c-ba62-3fe63ee1c7d4" /> <img width="726" height="495" alt="image" src="https://github.com/user-attachments/assets/90a6ad55-9ab6-4adb-93a7-2327f5f09c79" /> ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules --------- Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
		
			
				
	
	
		
			114 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* eslint no-param-reassign: 0 */
 | |
| 
 | |
| import getUuid from 'widget/helpers/uuid';
 | |
| import { MESSAGE_STATUS, MESSAGE_TYPE } from 'shared/constants/messages';
 | |
| 
 | |
| export default () => {
 | |
|   if (!Array.prototype.last) {
 | |
|     Object.assign(Array.prototype, {
 | |
|       last() {
 | |
|         return this[this.length - 1];
 | |
|       },
 | |
|     });
 | |
|   }
 | |
| };
 | |
| 
 | |
| export const isEmptyObject = obj =>
 | |
|   Object.keys(obj).length === 0 && obj.constructor === Object;
 | |
| 
 | |
| export const isJSONValid = value => {
 | |
|   try {
 | |
|     JSON.parse(value);
 | |
|   } catch (e) {
 | |
|     return false;
 | |
|   }
 | |
|   return true;
 | |
| };
 | |
| 
 | |
| export const getTypingUsersText = (users = []) => {
 | |
|   const count = users.length;
 | |
|   const [firstUser, secondUser] = users;
 | |
| 
 | |
|   if (count === 1) {
 | |
|     return ['TYPING.ONE', { user: firstUser.name }];
 | |
|   }
 | |
| 
 | |
|   if (count === 2) {
 | |
|     return [
 | |
|       'TYPING.TWO',
 | |
|       { user: firstUser.name, secondUser: secondUser.name },
 | |
|     ];
 | |
|   }
 | |
| 
 | |
|   return ['TYPING.MULTIPLE', { user: firstUser.name, count: count - 1 }];
 | |
| };
 | |
| 
 | |
| export const createPendingMessage = data => {
 | |
|   const timestamp = Math.floor(new Date().getTime() / 1000);
 | |
|   const tempMessageId = getUuid();
 | |
|   const { message, file } = data;
 | |
|   const tempAttachments = [{ id: tempMessageId }];
 | |
|   const pendingMessage = {
 | |
|     ...data,
 | |
|     content: message || null,
 | |
|     id: tempMessageId,
 | |
|     echo_id: tempMessageId,
 | |
|     status: MESSAGE_STATUS.PROGRESS,
 | |
|     created_at: timestamp,
 | |
|     message_type: MESSAGE_TYPE.OUTGOING,
 | |
|     conversation_id: data.conversationId,
 | |
|     attachments: file ? tempAttachments : null,
 | |
|   };
 | |
| 
 | |
|   return pendingMessage;
 | |
| };
 | |
| 
 | |
| export const convertToAttributeSlug = text => {
 | |
|   return text
 | |
|     .toLowerCase()
 | |
|     .replace(/[^\w ]+/g, '')
 | |
|     .replace(/ +/g, '_');
 | |
| };
 | |
| 
 | |
| export const convertToCategorySlug = text => {
 | |
|   return text
 | |
|     .toLowerCase()
 | |
|     .replace(/[^\w ]+/g, '')
 | |
|     .replace(/ +/g, '-');
 | |
| };
 | |
| 
 | |
| export const convertToPortalSlug = text => {
 | |
|   return text
 | |
|     .toLowerCase()
 | |
|     .replace(/[^\w ]+/g, '')
 | |
|     .replace(/ +/g, '-');
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Strip curly braces, commas and leading/trailing whitespace from a search key.
 | |
|  * Eg. "{{contact.name}}," => "contact.name"
 | |
|  * @param {string} searchKey
 | |
|  * @returns {string}
 | |
|  */
 | |
| export const sanitizeVariableSearchKey = (searchKey = '') => {
 | |
|   return searchKey
 | |
|     .replace(/[{}]/g, '') // remove all curly braces
 | |
|     .replace(/,/g, '') // remove commas
 | |
|     .trim();
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Convert underscore-separated string to title case.
 | |
|  * Eg. "round_robin" => "Round Robin"
 | |
|  * @param {string} str
 | |
|  * @returns {string}
 | |
|  */
 | |
| export const formatToTitleCase = str => {
 | |
|   return (
 | |
|     str
 | |
|       ?.replace(/_/g, ' ')
 | |
|       .replace(/\b\w/g, l => l.toUpperCase())
 | |
|       .trim() || ''
 | |
|   );
 | |
| };
 |