Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 208x 208x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 132x 12x 12x 12x 12x 12x 12x 12x 12x 12x 132x 132x 132x 132x 143x 131x 143x 132x 132x 132x 131x 132x 132x 132x 132x 132x 132x 132x 132x 132x 143x 143x 132x 132x 132x 132x 132x 132x 132x | import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';
import { Node } from '../../store/flow-definition.d';
import { validateWith } from '../utils';
import { buildCategoriesExitsCases } from './shared';
export const split_by_random: NodeConfig = {
type: 'split_by_random',
name: 'Random Split',
group: SPLIT_GROUPS.split,
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
form: {
categories: {
type: 'array',
helpText: 'Define the buckets to randomly split contacts into',
required: true,
itemLabel: 'Bucket',
sortable: true,
minItems: 2,
maxItems: 10,
isEmptyItem: (item: any) => {
return !item.name || item.name.trim() === '';
},
itemConfig: {
name: {
type: 'text',
placeholder: 'Bucket name',
required: true,
maxLength: 36
}
}
}
},
layout: ['categories'],
validate: validateWith((formData, errors) => {
if (!formData.categories || !Array.isArray(formData.categories)) return;
const categories = formData.categories.filter(
(item: any) => item?.name && item.name.trim() !== ''
);
if (categories.length < 2) {
errors.categories = 'At least 2 buckets are required for random split';
}
const duplicateCategories: string[] = [];
const lowerCaseMap = new Map<string, string[]>();
categories.forEach((category) => {
const lowerName = category.name.trim().toLowerCase();
if (!lowerCaseMap.has(lowerName)) {
lowerCaseMap.set(lowerName, []);
}
lowerCaseMap.get(lowerName).push(category.name.trim());
});
lowerCaseMap.forEach((originalNames) => {
if (originalNames.length > 1) {
duplicateCategories.push(...originalNames);
}
});
if (duplicateCategories.length > 0) {
const uniqueDuplicates = [...new Set(duplicateCategories)];
errors.categories = `Duplicate bucket names found: ${uniqueDuplicates.join(
', '
)}`;
}
}),
toFormData: (node: Node) => {
// Extract categories from the existing node structure
const categories =
node.router?.categories?.map((cat) => ({ name: cat.name })) || [];
return {
uuid: node.uuid,
categories: categories
};
},
fromFormData: (formData: FormData, originalNode: Node): Node => {
const userCategories = (formData.categories || [])
.filter((item: any) => item?.name?.trim())
.map((item: any) => item.name.trim());
const existingCategories = originalNode.router?.categories || [];
const existingExits = originalNode.exits || [];
const { categories, exits } = buildCategoriesExitsCases(
userCategories.map((name) => ({ name })),
existingCategories,
existingExits
);
return {
uuid: originalNode.uuid,
actions: originalNode.actions || [],
router: {
type: 'random',
categories
},
exits
};
},
router: {
type: 'random'
},
// Localization support for categories
localizable: 'categories'
};
|