-
- {{ $t('WHATSAPP_TEMPLATES.PICKER.LABELS.TEMPLATE_BODY') }}
+
+
+
+ {{ t('WHATSAPP_TEMPLATES.PICKER.HEADER') || 'HEADER' }}
-
{{ getTemplatebody(template) }}
+
+ {{ getTemplateHeader(template).text }}
+
+
+ {{
+ t('WHATSAPP_TEMPLATES.PICKER.MEDIA_CONTENT', {
+ format: getTemplateHeader(template).format,
+ }) ||
+ `${getTemplateHeader(template).format} ${t('WHATSAPP_TEMPLATES.PICKER.MEDIA_CONTENT_FALLBACK')}`
+ }}
+
-
-
- {{ $t('WHATSAPP_TEMPLATES.PICKER.LABELS.CATEGORY') }}
+
+
+
+
+ {{ t('WHATSAPP_TEMPLATES.PICKER.BODY') || 'BODY' }}
-
{{ template.category }}
+
{{ getTemplateBody(template) }}
+
+
+
+
+
+ {{ t('WHATSAPP_TEMPLATES.PICKER.FOOTER') || 'FOOTER' }}
+
+
+ {{ getTemplateFooter(template).text }}
+
+
+
+
+
+
+ {{ t('WHATSAPP_TEMPLATES.PICKER.BUTTONS') || 'BUTTONS' }}
+
+
+
+ {{ button.text }}
+
+
+
+
+
+
+ {{ t('WHATSAPP_TEMPLATES.PICKER.CATEGORY') || 'CATEGORY' }}
+
+
{{ template.category }}
@@ -128,13 +191,13 @@ export default {
- {{ $t('WHATSAPP_TEMPLATES.PICKER.NO_TEMPLATES_FOUND') }}
+ {{ t('WHATSAPP_TEMPLATES.PICKER.NO_TEMPLATES_FOUND') }}
{{ query }}
- {{ $t('WHATSAPP_TEMPLATES.PICKER.NO_TEMPLATES_AVAILABLE') }}
+ {{ t('WHATSAPP_TEMPLATES.PICKER.NO_TEMPLATES_AVAILABLE') }}
diff --git a/app/javascript/dashboard/helper/specs/templateHelper.spec.js b/app/javascript/dashboard/helper/specs/templateHelper.spec.js
new file mode 100644
index 000000000..6e0661152
--- /dev/null
+++ b/app/javascript/dashboard/helper/specs/templateHelper.spec.js
@@ -0,0 +1,368 @@
+import {
+ replaceTemplateVariables,
+ buildTemplateParameters,
+ processVariable,
+ allKeysRequired,
+} from '../templateHelper';
+import { templates } from '../../store/modules/specs/inboxes/templateFixtures';
+
+describe('templateHelper', () => {
+ const technicianTemplate = templates.find(t => t.name === 'technician_visit');
+
+ describe('processVariable', () => {
+ it('should remove curly braces from variables', () => {
+ expect(processVariable('{{name}}')).toBe('name');
+ expect(processVariable('{{1}}')).toBe('1');
+ expect(processVariable('{{customer_id}}')).toBe('customer_id');
+ });
+ });
+
+ describe('allKeysRequired', () => {
+ it('should return true when all keys have values', () => {
+ const obj = { name: 'John', age: '30' };
+ expect(allKeysRequired(obj)).toBe(true);
+ });
+
+ it('should return false when some keys are empty', () => {
+ const obj = { name: 'John', age: '' };
+ expect(allKeysRequired(obj)).toBe(false);
+ });
+
+ it('should return true for empty object', () => {
+ expect(allKeysRequired({})).toBe(true);
+ });
+ });
+
+ describe('replaceTemplateVariables', () => {
+ const templateText =
+ "Hi {{1}}, we're scheduling a technician visit to {{2}} on {{3}} between {{4}} and {{5}}. Please confirm if this time slot works for you.";
+
+ it('should replace all variables with provided values', () => {
+ const processedParams = {
+ body: {
+ 1: 'John',
+ 2: '123 Main St',
+ 3: '2025-01-15',
+ 4: '10:00 AM',
+ 5: '2:00 PM',
+ },
+ };
+
+ const result = replaceTemplateVariables(templateText, processedParams);
+ expect(result).toBe(
+ "Hi John, we're scheduling a technician visit to 123 Main St on 2025-01-15 between 10:00 AM and 2:00 PM. Please confirm if this time slot works for you."
+ );
+ });
+
+ it('should keep original variable format when no replacement value provided', () => {
+ const processedParams = {
+ body: {
+ 1: 'John',
+ 3: '2025-01-15',
+ },
+ };
+
+ const result = replaceTemplateVariables(templateText, processedParams);
+ expect(result).toContain('John');
+ expect(result).toContain('2025-01-15');
+ expect(result).toContain('{{2}}');
+ expect(result).toContain('{{4}}');
+ expect(result).toContain('{{5}}');
+ });
+
+ it('should handle empty processedParams', () => {
+ const result = replaceTemplateVariables(templateText, {});
+ expect(result).toBe(templateText);
+ });
+ });
+
+ describe('buildTemplateParameters', () => {
+ it('should build parameters for template with body variables', () => {
+ const result = buildTemplateParameters(technicianTemplate, false);
+
+ expect(result.body).toEqual({
+ 1: '',
+ 2: '',
+ 3: '',
+ 4: '',
+ 5: '',
+ });
+ });
+
+ it('should include header parameters when hasMediaHeader is true', () => {
+ const imageTemplate = templates.find(
+ t => t.name === 'order_confirmation'
+ );
+ const result = buildTemplateParameters(imageTemplate, true);
+
+ expect(result.header).toEqual({
+ media_url: '',
+ media_type: 'image',
+ });
+ });
+
+ it('should not include header parameters when hasMediaHeader is false', () => {
+ const result = buildTemplateParameters(technicianTemplate, false);
+ expect(result.header).toBeUndefined();
+ });
+
+ it('should handle template with no body component', () => {
+ const templateWithoutBody = {
+ components: [{ type: 'HEADER', format: 'TEXT' }],
+ };
+
+ const result = buildTemplateParameters(templateWithoutBody, false);
+ expect(result).toEqual({});
+ });
+
+ it('should handle template with no variables', () => {
+ const templateWithoutVars = templates.find(
+ t => t.name === 'no_variable_template'
+ );
+ const result = buildTemplateParameters(templateWithoutVars, false);
+
+ expect(result.body).toBeUndefined();
+ });
+
+ it('should handle URL buttons with variables for non-authentication templates', () => {
+ const templateWithUrlButton = {
+ category: 'MARKETING',
+ components: [
+ {
+ type: 'BODY',
+ text: 'Check out our website at {{site_url}}',
+ },
+ {
+ type: 'BUTTONS',
+ buttons: [
+ {
+ type: 'URL',
+ url: 'https://example.com/{{campaign_id}}',
+ text: 'Visit Site',
+ },
+ ],
+ },
+ ],
+ };
+
+ const result = buildTemplateParameters(templateWithUrlButton, false);
+ expect(result.buttons).toEqual([
+ {
+ type: 'url',
+ parameter: '',
+ url: 'https://example.com/{{campaign_id}}',
+ variables: ['campaign_id'],
+ },
+ ]);
+ });
+
+ it('should handle templates with no variables', () => {
+ const emptyTemplate = templates.find(
+ t => t.name === 'no_variable_template'
+ );
+ const result = buildTemplateParameters(emptyTemplate, false);
+ expect(result).toEqual({});
+ });
+
+ it('should build parameters for templates with multiple component types', () => {
+ const complexTemplate = {
+ components: [
+ { type: 'HEADER', format: 'IMAGE' },
+ { type: 'BODY', text: 'Hi {{1}}, your order {{2}} is ready!' },
+ { type: 'FOOTER', text: 'Thank you for your business' },
+ {
+ type: 'BUTTONS',
+ buttons: [{ type: 'URL', url: 'https://example.com/{{3}}' }],
+ },
+ ],
+ };
+
+ const result = buildTemplateParameters(complexTemplate, true);
+
+ expect(result.header).toEqual({
+ media_url: '',
+ media_type: 'image',
+ });
+ expect(result.body).toEqual({ 1: '', 2: '' });
+ expect(result.buttons).toEqual([
+ {
+ type: 'url',
+ parameter: '',
+ url: 'https://example.com/{{3}}',
+ variables: ['3'],
+ },
+ ]);
+ });
+
+ it('should handle copy code buttons correctly', () => {
+ const copyCodeTemplate = templates.find(
+ t => t.name === 'discount_coupon'
+ );
+ const result = buildTemplateParameters(copyCodeTemplate, false);
+
+ expect(result.body).toBeDefined();
+ expect(result.buttons).toEqual([
+ {
+ type: 'copy_code',
+ parameter: '',
+ },
+ ]);
+ });
+
+ it('should handle templates with document headers', () => {
+ const documentTemplate = templates.find(
+ t => t.name === 'purchase_receipt'
+ );
+ const result = buildTemplateParameters(documentTemplate, true);
+
+ expect(result.header).toEqual({
+ media_url: '',
+ media_type: 'document',
+ });
+ expect(result.body).toEqual({
+ 1: '',
+ 2: '',
+ 3: '',
+ });
+ });
+
+ it('should handle video header templates', () => {
+ const videoTemplate = templates.find(t => t.name === 'training_video');
+ const result = buildTemplateParameters(videoTemplate, true);
+
+ expect(result.header).toEqual({
+ media_url: '',
+ media_type: 'video',
+ });
+ expect(result.body).toEqual({
+ name: '',
+ date: '',
+ });
+ });
+ });
+
+ describe('enhanced format validation', () => {
+ it('should validate enhanced format structure', () => {
+ const processedParams = {
+ body: { 1: 'John', 2: 'Order123' },
+ header: {
+ media_url: 'https://example.com/image.jpg',
+ media_type: 'image',
+ },
+ buttons: [{ type: 'copy_code', parameter: 'SAVE20' }],
+ };
+
+ // Test that structure is properly formed
+ expect(processedParams.body).toBeDefined();
+ expect(typeof processedParams.body).toBe('object');
+ expect(processedParams.header).toBeDefined();
+ expect(Array.isArray(processedParams.buttons)).toBe(true);
+ });
+
+ it('should handle empty component sections', () => {
+ const processedParams = {
+ body: {},
+ header: {},
+ buttons: [],
+ };
+
+ expect(allKeysRequired(processedParams.body)).toBe(true);
+ expect(allKeysRequired(processedParams.header)).toBe(true);
+ expect(processedParams.buttons.length).toBe(0);
+ });
+
+ it('should validate parameter completeness', () => {
+ const incompleteParams = {
+ body: { 1: 'John', 2: '' },
+ };
+
+ expect(allKeysRequired(incompleteParams.body)).toBe(false);
+ });
+
+ it('should handle edge cases in processVariable', () => {
+ expect(processVariable('{{')).toBe('');
+ expect(processVariable('}}')).toBe('');
+ expect(processVariable('')).toBe('');
+ expect(processVariable('{{nested{{variable}}}}')).toBe('nestedvariable');
+ });
+
+ it('should handle special characters in template variables', () => {
+ /* eslint-disable no-template-curly-in-string */
+ const templateText =
+ 'Welcome {{user_name}}, your order #{{order_id}} costs ${{amount}}';
+ /* eslint-enable no-template-curly-in-string */
+ const processedParams = {
+ body: {
+ user_name: 'John & Jane',
+ order_id: '12345',
+ amount: '99.99',
+ },
+ };
+
+ const result = replaceTemplateVariables(templateText, processedParams);
+ expect(result).toBe(
+ 'Welcome John & Jane, your order #12345 costs $99.99'
+ );
+ });
+
+ it('should handle templates with mixed parameter types', () => {
+ const mixedTemplate = {
+ components: [
+ { type: 'HEADER', format: 'VIDEO' },
+ { type: 'BODY', text: 'Order {{order_id}} status: {{status}}' },
+ { type: 'FOOTER', text: 'Thank you' },
+ {
+ type: 'BUTTONS',
+ buttons: [
+ { type: 'URL', url: 'https://track.com/{{order_id}}' },
+ { type: 'COPY_CODE' },
+ { type: 'PHONE_NUMBER', phone_number: '+1234567890' },
+ ],
+ },
+ ],
+ };
+
+ const result = buildTemplateParameters(mixedTemplate, true);
+
+ expect(result.header).toEqual({
+ media_url: '',
+ media_type: 'video',
+ });
+ expect(result.body).toEqual({
+ order_id: '',
+ status: '',
+ });
+ expect(result.buttons).toHaveLength(2); // URL and COPY_CODE (PHONE_NUMBER doesn't need parameters)
+ expect(result.buttons[0].type).toBe('url');
+ expect(result.buttons[1].type).toBe('copy_code');
+ });
+
+ it('should handle templates with no processable components', () => {
+ const emptyTemplate = {
+ components: [
+ { type: 'HEADER', format: 'TEXT', text: 'Static Header' },
+ { type: 'BODY', text: 'Static body with no variables' },
+ { type: 'FOOTER', text: 'Static footer' },
+ ],
+ };
+
+ const result = buildTemplateParameters(emptyTemplate, false);
+ expect(result).toEqual({});
+ });
+
+ it('should validate that replaceTemplateVariables preserves unreplaced variables', () => {
+ const templateText = 'Hi {{name}}, order {{order_id}} is {{status}}';
+ const partialParams = {
+ body: {
+ name: 'John',
+ // order_id missing
+ status: 'ready',
+ },
+ };
+
+ const result = replaceTemplateVariables(templateText, partialParams);
+ expect(result).toBe('Hi John, order {{order_id}} is ready');
+ expect(result).toContain('{{order_id}}'); // Unreplaced variable preserved
+ });
+ });
+});
diff --git a/app/javascript/dashboard/helper/templateHelper.js b/app/javascript/dashboard/helper/templateHelper.js
new file mode 100644
index 000000000..5c9bbff05
--- /dev/null
+++ b/app/javascript/dashboard/helper/templateHelper.js
@@ -0,0 +1,91 @@
+// Constants
+export const DEFAULT_LANGUAGE = 'en';
+export const DEFAULT_CATEGORY = 'UTILITY';
+export const COMPONENT_TYPES = {
+ HEADER: 'HEADER',
+ BODY: 'BODY',
+ BUTTONS: 'BUTTONS',
+};
+export const MEDIA_FORMATS = ['IMAGE', 'VIDEO', 'DOCUMENT'];
+
+export const findComponentByType = (template, type) =>
+ template.components?.find(component => component.type === type);
+
+export const processVariable = str => {
+ return str.replace(/{{|}}/g, '');
+};
+
+export const allKeysRequired = value => {
+ const keys = Object.keys(value);
+ return keys.every(key => value[key]);
+};
+
+export const replaceTemplateVariables = (templateText, processedParams) => {
+ return templateText.replace(/{{([^}]+)}}/g, (match, variable) => {
+ const variableKey = processVariable(variable);
+ return processedParams.body?.[variableKey] || `{{${variable}}}`;
+ });
+};
+
+export const buildTemplateParameters = (template, hasMediaHeaderValue) => {
+ const allVariables = {};
+
+ const bodyComponent = findComponentByType(template, COMPONENT_TYPES.BODY);
+ const headerComponent = findComponentByType(template, COMPONENT_TYPES.HEADER);
+
+ if (!bodyComponent) return allVariables;
+
+ const templateString = bodyComponent.text;
+
+ // Process body variables
+ const matchedVariables = templateString.match(/{{([^}]+)}}/g);
+ if (matchedVariables) {
+ allVariables.body = {};
+ matchedVariables.forEach(variable => {
+ const key = processVariable(variable);
+ allVariables.body[key] = '';
+ });
+ }
+
+ if (hasMediaHeaderValue) {
+ if (!allVariables.header) allVariables.header = {};
+ allVariables.header.media_url = '';
+ allVariables.header.media_type = headerComponent.format.toLowerCase();
+ }
+
+ // Process button variables
+ const buttonComponents = template.components.filter(
+ component => component.type === COMPONENT_TYPES.BUTTONS
+ );
+
+ buttonComponents.forEach(buttonComponent => {
+ if (buttonComponent.buttons) {
+ buttonComponent.buttons.forEach((button, index) => {
+ // Handle URL buttons with variables
+ if (button.type === 'URL' && button.url && button.url.includes('{{')) {
+ const buttonVars = button.url.match(/{{([^}]+)}}/g) || [];
+ if (buttonVars.length > 0) {
+ if (!allVariables.buttons) allVariables.buttons = [];
+ allVariables.buttons[index] = {
+ type: 'url',
+ parameter: '',
+ url: button.url,
+ variables: buttonVars.map(v => processVariable(v)),
+ };
+ }
+ }
+
+ // Handle copy code buttons
+ if (button.type === 'COPY_CODE') {
+ if (!allVariables.buttons) allVariables.buttons = [];
+ allVariables.buttons[index] = {
+ type: 'copy_code',
+ parameter: '',
+ };
+ }
+ });
+ }
+ });
+
+ return allVariables;
+};
diff --git a/app/javascript/dashboard/i18n/locale/en/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/en/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/en/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/en/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/store/modules/inboxes.js b/app/javascript/dashboard/store/modules/inboxes.js
index a6b93c923..c4789a7a9 100644
--- a/app/javascript/dashboard/store/modules/inboxes.js
+++ b/app/javascript/dashboard/store/modules/inboxes.js
@@ -44,15 +44,52 @@ export const getters = {
const messagesTemplates =
whatsAppMessageTemplates || apiInboxMessageTemplates;
- // filtering out the whatsapp templates with media
- if (messagesTemplates instanceof Array) {
- return messagesTemplates.filter(template => {
- return !template.components.some(
- i => i.format === 'IMAGE' || i.format === 'VIDEO'
- );
- });
+ return messagesTemplates;
+ },
+ getFilteredWhatsAppTemplates: $state => inboxId => {
+ const [inbox] = $state.records.filter(
+ record => record.id === Number(inboxId)
+ );
+
+ const {
+ message_templates: whatsAppMessageTemplates,
+ additional_attributes: additionalAttributes,
+ } = inbox || {};
+
+ const { message_templates: apiInboxMessageTemplates } =
+ additionalAttributes || {};
+ const templates = whatsAppMessageTemplates || apiInboxMessageTemplates;
+
+ if (!templates || !Array.isArray(templates)) {
+ return [];
}
- return [];
+
+ return templates.filter(template => {
+ // Ensure template has required properties
+ if (!template || !template.status || !template.components) {
+ return false;
+ }
+
+ // Only show approved templates
+ if (template.status.toLowerCase() !== 'approved') {
+ return false;
+ }
+
+ // Filter out interactive templates (LIST, PRODUCT, CATALOG), location templates, and call permission templates
+ const hasUnsupportedComponents = template.components.some(
+ component =>
+ ['LIST', 'PRODUCT', 'CATALOG', 'CALL_PERMISSION_REQUEST'].includes(
+ component.type
+ ) ||
+ (component.type === 'HEADER' && component.format === 'LOCATION')
+ );
+
+ if (hasUnsupportedComponents) {
+ return false;
+ }
+
+ return true;
+ });
},
getNewConversationInboxes($state) {
return $state.records.filter(inbox => {
diff --git a/app/javascript/dashboard/store/modules/specs/inboxes/getters.spec.js b/app/javascript/dashboard/store/modules/specs/inboxes/getters.spec.js
index f9ed57d63..eeb52b1dc 100644
--- a/app/javascript/dashboard/store/modules/specs/inboxes/getters.spec.js
+++ b/app/javascript/dashboard/store/modules/specs/inboxes/getters.spec.js
@@ -1,5 +1,6 @@
import { getters } from '../../inboxes';
import inboxList from './fixtures';
+import { templates } from './templateFixtures';
describe('#getters', () => {
it('getInboxes', () => {
@@ -93,4 +94,269 @@ describe('#getters', () => {
provider: 'default',
});
});
+
+ describe('getFilteredWhatsAppTemplates', () => {
+ it('returns empty array when inbox not found', () => {
+ const state = { records: [] };
+ expect(getters.getFilteredWhatsAppTemplates(state)(999)).toEqual([]);
+ });
+
+ it('returns empty array when templates is null or undefined', () => {
+ const state = {
+ records: [
+ {
+ id: 1,
+ channel_type: 'Channel::Whatsapp',
+ message_templates: null,
+ additional_attributes: { message_templates: undefined },
+ },
+ ],
+ };
+ expect(getters.getFilteredWhatsAppTemplates(state)(1)).toEqual([]);
+ });
+
+ it('returns empty array when templates is not an array', () => {
+ const state = {
+ records: [
+ {
+ id: 1,
+ channel_type: 'Channel::Whatsapp',
+ message_templates: 'invalid',
+ additional_attributes: {},
+ },
+ ],
+ };
+ expect(getters.getFilteredWhatsAppTemplates(state)(1)).toEqual([]);
+ });
+
+ it('filters out templates without required properties', () => {
+ const invalidTemplates = [
+ { name: 'incomplete_template' }, // missing status and components
+ { status: 'approved' }, // missing name and components
+ { name: 'another_incomplete', status: 'approved' }, // missing components
+ ];
+
+ const state = {
+ records: [
+ {
+ id: 1,
+ channel_type: 'Channel::Whatsapp',
+ message_templates: invalidTemplates,
+ },
+ ],
+ };
+ expect(getters.getFilteredWhatsAppTemplates(state)(1)).toEqual([]);
+ });
+
+ it('filters out non-approved templates', () => {
+ const mixedStatusTemplates = [
+ {
+ name: 'pending_template',
+ status: 'pending',
+ components: [{ type: 'BODY', text: 'Test' }],
+ },
+ {
+ name: 'rejected_template',
+ status: 'rejected',
+ components: [{ type: 'BODY', text: 'Test' }],
+ },
+ {
+ name: 'approved_template',
+ status: 'approved',
+ components: [{ type: 'BODY', text: 'Test' }],
+ },
+ ];
+
+ const state = {
+ records: [
+ {
+ id: 1,
+ channel_type: 'Channel::Whatsapp',
+ message_templates: mixedStatusTemplates,
+ },
+ ],
+ };
+
+ const result = getters.getFilteredWhatsAppTemplates(state)(1);
+ expect(result).toHaveLength(1);
+ expect(result[0].name).toBe('approved_template');
+ });
+
+ it('filters out interactive templates (LIST, PRODUCT, CATALOG)', () => {
+ const interactiveTemplates = [
+ {
+ name: 'list_template',
+ status: 'approved',
+ components: [
+ { type: 'BODY', text: 'Choose an option' },
+ { type: 'LIST', sections: [] },
+ ],
+ },
+ {
+ name: 'product_template',
+ status: 'approved',
+ components: [
+ { type: 'BODY', text: 'Product info' },
+ { type: 'PRODUCT', catalog_id: '123' },
+ ],
+ },
+ {
+ name: 'catalog_template',
+ status: 'approved',
+ components: [
+ { type: 'BODY', text: 'Catalog' },
+ { type: 'CATALOG', thumbnail_product_retailer_id: '123' },
+ ],
+ },
+ {
+ name: 'regular_template',
+ status: 'approved',
+ components: [{ type: 'BODY', text: 'Regular message' }],
+ },
+ ];
+
+ const state = {
+ records: [
+ {
+ id: 1,
+ channel_type: 'Channel::Whatsapp',
+ message_templates: interactiveTemplates,
+ },
+ ],
+ };
+
+ const result = getters.getFilteredWhatsAppTemplates(state)(1);
+ expect(result).toHaveLength(1);
+ expect(result[0].name).toBe('regular_template');
+ });
+
+ it('filters out location templates', () => {
+ const locationTemplates = [
+ {
+ name: 'location_template',
+ status: 'approved',
+ components: [
+ { type: 'HEADER', format: 'LOCATION' },
+ { type: 'BODY', text: 'Location message' },
+ ],
+ },
+ {
+ name: 'regular_template',
+ status: 'approved',
+ components: [
+ { type: 'HEADER', format: 'TEXT', text: 'Header' },
+ { type: 'BODY', text: 'Regular message' },
+ ],
+ },
+ ];
+
+ const state = {
+ records: [
+ {
+ id: 1,
+ channel_type: 'Channel::Whatsapp',
+ message_templates: locationTemplates,
+ },
+ ],
+ };
+
+ const result = getters.getFilteredWhatsAppTemplates(state)(1);
+ expect(result).toHaveLength(1);
+ expect(result[0].name).toBe('regular_template');
+ });
+
+ it('returns valid templates from fixture data', () => {
+ const state = {
+ records: [
+ {
+ id: 1,
+ channel_type: 'Channel::Whatsapp',
+ message_templates: templates,
+ },
+ ],
+ };
+
+ const result = getters.getFilteredWhatsAppTemplates(state)(1);
+
+ // All templates in fixtures should be approved and valid
+ expect(result.length).toBeGreaterThan(0);
+
+ // Verify all returned templates are approved
+ result.forEach(template => {
+ expect(template.status).toBe('approved');
+ expect(template.components).toBeDefined();
+ expect(Array.isArray(template.components)).toBe(true);
+ });
+
+ // Verify specific templates from fixtures are included
+ const templateNames = result.map(t => t.name);
+ expect(templateNames).toContain('sample_flight_confirmation');
+ expect(templateNames).toContain('sample_issue_resolution');
+ expect(templateNames).toContain('sample_shipping_confirmation');
+ expect(templateNames).toContain('no_variable_template');
+ expect(templateNames).toContain('order_confirmation');
+ });
+
+ it('prioritizes message_templates over additional_attributes.message_templates', () => {
+ const primaryTemplates = [
+ {
+ name: 'primary_template',
+ status: 'approved',
+ components: [{ type: 'BODY', text: 'Primary' }],
+ },
+ ];
+
+ const fallbackTemplates = [
+ {
+ name: 'fallback_template',
+ status: 'approved',
+ components: [{ type: 'BODY', text: 'Fallback' }],
+ },
+ ];
+
+ const state = {
+ records: [
+ {
+ id: 1,
+ channel_type: 'Channel::Whatsapp',
+ message_templates: primaryTemplates,
+ additional_attributes: {
+ message_templates: fallbackTemplates,
+ },
+ },
+ ],
+ };
+
+ const result = getters.getFilteredWhatsAppTemplates(state)(1);
+ expect(result).toHaveLength(1);
+ expect(result[0].name).toBe('primary_template');
+ });
+
+ it('falls back to additional_attributes.message_templates when message_templates is null', () => {
+ const fallbackTemplates = [
+ {
+ name: 'fallback_template',
+ status: 'approved',
+ components: [{ type: 'BODY', text: 'Fallback' }],
+ },
+ ];
+
+ const state = {
+ records: [
+ {
+ id: 1,
+ channel_type: 'Channel::Whatsapp',
+ message_templates: null,
+ additional_attributes: {
+ message_templates: fallbackTemplates,
+ },
+ },
+ ],
+ };
+
+ const result = getters.getFilteredWhatsAppTemplates(state)(1);
+ expect(result).toHaveLength(1);
+ expect(result[0].name).toBe('fallback_template');
+ });
+ });
});
diff --git a/app/javascript/shared/mixins/specs/whatsappTemplates/fixtures.js b/app/javascript/dashboard/store/modules/specs/inboxes/templateFixtures.js
similarity index 50%
rename from app/javascript/shared/mixins/specs/whatsappTemplates/fixtures.js
rename to app/javascript/dashboard/store/modules/specs/inboxes/templateFixtures.js
index 02c24b2bb..c4c6a0b40 100644
--- a/app/javascript/shared/mixins/specs/whatsappTemplates/fixtures.js
+++ b/app/javascript/dashboard/store/modules/specs/inboxes/templateFixtures.js
@@ -260,4 +260,285 @@ export const templates = [
],
rejected_reason: 'NONE',
},
+ {
+ name: 'order_confirmation',
+ status: 'approved',
+ category: 'TICKET_UPDATE',
+ language: 'en_US',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ type: 'HEADER',
+ format: 'IMAGE',
+ example: {
+ header_handle: ['https://example.com/shoes.jpg'],
+ },
+ },
+ {
+ text: 'Hi your order {{1}} is confirmed. Please wait for further updates',
+ type: 'BODY',
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
+ {
+ name: 'technician_visit',
+ status: 'approved',
+ category: 'UTILITY',
+ language: 'en_US',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ text: 'Technician visit',
+ type: 'HEADER',
+ format: 'TEXT',
+ },
+ {
+ text: "Hi {{1}}, we're scheduling a technician visit to {{2}} on {{3}} between {{4}} and {{5}}. Please confirm if this time slot works for you.",
+ type: 'BODY',
+ },
+ {
+ type: 'BUTTONS',
+ buttons: [
+ {
+ text: 'Confirm',
+ type: 'QUICK_REPLY',
+ },
+ {
+ text: 'Reschedule',
+ type: 'QUICK_REPLY',
+ },
+ ],
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
+ {
+ name: 'event_invitation_static',
+ status: 'approved',
+ category: 'MARKETING',
+ language: 'en',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ text: "You're invited to {{event_name}} at {{location}}, Join us for an amazing experience!",
+ type: 'BODY',
+ },
+ {
+ type: 'BUTTONS',
+ buttons: [
+ {
+ url: 'https://events.example.com/register',
+ text: 'Visit website',
+ type: 'URL',
+ },
+ {
+ url: 'https://maps.app.goo.gl/YoWAzRj1GDuxs6qz8',
+ text: 'Get Directions',
+ type: 'URL',
+ },
+ ],
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
+ {
+ name: 'purchase_receipt',
+ status: 'approved',
+ category: 'UTILITY',
+ language: 'en_US',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ type: 'HEADER',
+ format: 'DOCUMENT',
+ },
+ {
+ text: 'Thank you for using your {{1}} card at {{2}}. Your {{3}} is attached as a PDF.',
+ type: 'BODY',
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
+ {
+ name: 'discount_coupon',
+ status: 'approved',
+ category: 'MARKETING',
+ language: 'en',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ text: '🎉 Special offer for you! Get {{discount_percentage}}% off your next purchase. Use the code below at checkout',
+ type: 'BODY',
+ },
+ {
+ type: 'BUTTONS',
+ buttons: [
+ {
+ text: 'Copy offer code',
+ type: 'COPY_CODE',
+ },
+ ],
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
+ {
+ name: 'support_callback',
+ status: 'approved',
+ category: 'UTILITY',
+ language: 'en',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ text: 'Hello {{name}}, our support team will call you regarding ticket # {{ticket_id}}.',
+ type: 'BODY',
+ },
+ {
+ type: 'BUTTONS',
+ buttons: [
+ {
+ text: 'Call Support',
+ type: 'PHONE_NUMBER',
+ phone_number: '+16506677566',
+ },
+ ],
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
+ {
+ name: 'training_video',
+ status: 'approved',
+ category: 'MARKETING',
+ language: 'en',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ type: 'HEADER',
+ format: 'VIDEO',
+ },
+ {
+ text: "Hi {{name}}, here's your training video. Please watch by{{date}}.",
+ type: 'BODY',
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
+ {
+ name: 'product_launch',
+ status: 'approved',
+ category: 'MARKETING',
+ language: 'en',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ type: 'HEADER',
+ format: 'IMAGE',
+ },
+ {
+ text: 'New arrival! Our stunning coat now available in {{color}} color.',
+ type: 'BODY',
+ },
+ {
+ text: 'Free shipping on orders over $100. Limited time offer.',
+ type: 'FOOTER',
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
+ {
+ name: 'greet',
+ status: 'approved',
+ category: 'MARKETING',
+ language: 'en',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ text: 'Hey {{customer_name}} how may I help you?',
+ type: 'BODY',
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
+ {
+ name: 'hello_world',
+ status: 'approved',
+ category: 'UTILITY',
+ language: 'en_US',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ text: 'Hello World',
+ type: 'HEADER',
+ format: 'TEXT',
+ },
+ {
+ text: 'Welcome and congratulations!! This message demonstrates your ability to send a WhatsApp message notification from the Cloud API, hosted by Meta. Thank you for taking the time to test with us.',
+ type: 'BODY',
+ },
+ {
+ text: 'WhatsApp Business Platform sample message',
+ type: 'FOOTER',
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
+ {
+ name: 'feedback_request',
+ status: 'approved',
+ category: 'MARKETING',
+ language: 'en',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ text: "Hey {{name}}, how was your experience with Puma? We'd love your feedback!",
+ type: 'BODY',
+ },
+ {
+ type: 'BUTTONS',
+ buttons: [
+ {
+ url: 'https://feedback.example.com/survey',
+ text: 'Leave Feedback',
+ type: 'URL',
+ },
+ ],
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
+ {
+ name: 'address_update',
+ status: 'approved',
+ category: 'UTILITY',
+ language: 'en_US',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ text: 'Address update',
+ type: 'HEADER',
+ format: 'TEXT',
+ },
+ {
+ text: 'Hi {{1}}, your delivery address has been successfully updated to {{2}}. Contact {{3}} for any inquiries.',
+ type: 'BODY',
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
+ {
+ name: 'delivery_confirmation',
+ status: 'approved',
+ category: 'UTILITY',
+ language: 'en_US',
+ namespace: 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ components: [
+ {
+ text: '{{1}}, your order was successfully delivered on {{2}}.\n\nThank you for your purchase.\n',
+ type: 'BODY',
+ },
+ ],
+ rejected_reason: 'NONE',
+ },
];
diff --git a/app/javascript/shared/mixins/specs/whatsappTemplates/whatsappTemplates.spec.js b/app/javascript/shared/mixins/specs/whatsappTemplates/whatsappTemplates.spec.js
deleted file mode 100644
index adad15bf7..000000000
--- a/app/javascript/shared/mixins/specs/whatsappTemplates/whatsappTemplates.spec.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import TemplateParser from '../../../../dashboard/components/widgets/conversation/WhatsappTemplates/TemplateParser.vue';
-import { templates } from './fixtures';
-import { nextTick } from 'vue';
-
-const config = {
- global: {
- stubs: {
- NextButton: { template: '
' },
- WootInput: { template: '
' },
- },
- },
-};
-
-describe('#WhatsAppTemplates', () => {
- it('returns all variables from a template string', async () => {
- const wrapper = shallowMount(TemplateParser, {
- ...config,
- props: { template: templates[0] },
- });
- await nextTick();
- expect(wrapper.vm.variables).toEqual(['{{1}}', '{{2}}', '{{3}}']);
- });
-
- it('returns no variables from a template string if it does not contain variables', async () => {
- const wrapper = shallowMount(TemplateParser, {
- ...config,
- props: { template: templates[12] },
- });
- await nextTick();
- expect(wrapper.vm.variables).toBeNull();
- });
-
- it('returns the body of a template', async () => {
- const wrapper = shallowMount(TemplateParser, {
- ...config,
- props: { template: templates[1] },
- });
- await nextTick();
- const expectedOutput =
- templates[1].components.find(i => i.type === 'BODY')?.text || '';
- expect(wrapper.vm.templateString).toEqual(expectedOutput);
- });
-
- it('generates the templates from variable input', async () => {
- const wrapper = shallowMount(TemplateParser, {
- ...config,
- props: { template: templates[0] },
- });
- await nextTick();
-
- // Instead of using `setData`, directly modify the `processedParams` using the component's logic
- await wrapper.vm.$nextTick();
- wrapper.vm.processedParams = { 1: 'abc', 2: 'xyz', 3: 'qwerty' };
- await wrapper.vm.$nextTick();
-
- const expectedOutput =
- 'Esta é a sua confirmação de voo para abc-xyz em qwerty.';
- expect(wrapper.vm.processedString).toEqual(expectedOutput);
- });
-});
From ad4ec9e93b792ca18c73654c07fad354e546bcab Mon Sep 17 00:00:00 2001
From: Sojan Jose
Date: Tue, 12 Aug 2025 16:42:18 +0200
Subject: [PATCH 04/26] fix: Flaky Instagram webhook specs (#12170)
### Summary
Fixed flaky Instagram webhook specs that failed intermittently in cloud
environments due to shared let blocks creating conflicting inboxes. The
Instagram channel factory already creates an inbox automatically, but
tests were adding extra ones in shared contexts.
Moved channel/inbox creation to isolated test contexts to prevent race
conditions between Facebook Page and Instagram Direct tests.
### Testing
```
for i in {1..30}; do
echo "=== Run $i ==="
RAILS_ENV=test bundle exec rspec spec/jobs/webhooks/instagram_events_job_spec.rb --fail-fast || break
done
```
Previously, intermittent failures could be reproduced locally. With
these changes, tests achieve ~100% pass rate.
---
.../webhooks/instagram_events_job_spec.rb | 125 ++++++++----------
1 file changed, 57 insertions(+), 68 deletions(-)
diff --git a/spec/jobs/webhooks/instagram_events_job_spec.rb b/spec/jobs/webhooks/instagram_events_job_spec.rb
index 9edd9a34d..21f042f1f 100644
--- a/spec/jobs/webhooks/instagram_events_job_spec.rb
+++ b/spec/jobs/webhooks/instagram_events_job_spec.rb
@@ -10,23 +10,6 @@ describe Webhooks::InstagramEventsJob do
end
let!(:account) { create(:account) }
- let!(:instagram_messenger_channel) { create(:channel_instagram_fb_page, account: account, instagram_id: 'chatwoot-app-user-id-1') }
- let!(:instagram_messenger_inbox) { create(:inbox, channel: instagram_messenger_channel, account: account, greeting_enabled: false) }
- let!(:instagram_channel) { create(:channel_instagram, account: account, instagram_id: 'chatwoot-app-user-id-1') }
- let!(:instagram_inbox) { create(:inbox, channel: instagram_channel, account: account, greeting_enabled: false) }
- # Combined message events into one helper
- let(:message_events) do
- {
- dm: build(:instagram_message_create_event).with_indifferent_access,
- standby: build(:instagram_message_standby_event).with_indifferent_access,
- unsend: build(:instagram_message_unsend_event).with_indifferent_access,
- attachment: build(:instagram_message_attachment_event).with_indifferent_access,
- story_mention: build(:instagram_story_mention_event).with_indifferent_access,
- story_mention_echo: build(:instagram_story_mention_event_with_echo).with_indifferent_access,
- messaging_seen: build(:messaging_seen_event).with_indifferent_access,
- unsupported: build(:instagram_message_unsupported_event).with_indifferent_access
- }
- end
def return_object_for(sender_id)
{ name: 'Jane',
@@ -38,21 +21,19 @@ describe Webhooks::InstagramEventsJob do
describe '#perform' do
context 'when handling messaging events for Instagram via Facebook page' do
+ let!(:instagram_messenger_channel) { create(:channel_instagram_fb_page, account: account, instagram_id: 'chatwoot-app-user-id-1') }
+ let!(:instagram_messenger_inbox) { create(:inbox, channel: instagram_messenger_channel, account: account, greeting_enabled: false) }
let(:fb_object) { double }
- before do
- instagram_inbox.destroy
- end
-
it 'creates incoming message in the instagram inbox' do
+ dm_event = build(:instagram_message_create_event).with_indifferent_access
+ sender_id = dm_event[:entry][0][:messaging][0][:sender][:id]
+
allow(Koala::Facebook::API).to receive(:new).and_return(fb_object)
- sender_id = message_events[:dm][:entry][0][:messaging][0][:sender][:id]
allow(fb_object).to receive(:get_object).and_return(
return_object_for(sender_id).with_indifferent_access
)
- instagram_webhook.perform_now(message_events[:dm][:entry])
-
- instagram_messenger_inbox.reload
+ instagram_webhook.perform_now(dm_event[:entry])
expect(instagram_messenger_inbox.contacts.count).to be 1
expect(instagram_messenger_inbox.contacts.last.additional_attributes['social_instagram_user_name']).to eq 'some_user_name'
@@ -62,14 +43,14 @@ describe Webhooks::InstagramEventsJob do
end
it 'creates standby message in the instagram inbox' do
+ standby_event = build(:instagram_message_standby_event).with_indifferent_access
+ sender_id = standby_event[:entry][0][:standby][0][:sender][:id]
+
allow(Koala::Facebook::API).to receive(:new).and_return(fb_object)
- sender_id = message_events[:standby][:entry][0][:standby][0][:sender][:id]
allow(fb_object).to receive(:get_object).and_return(
return_object_for(sender_id).with_indifferent_access
)
- instagram_webhook.perform_now(message_events[:standby][:entry])
-
- instagram_messenger_inbox.reload
+ instagram_webhook.perform_now(standby_event[:entry])
expect(instagram_messenger_inbox.contacts.count).to be 1
expect(instagram_messenger_inbox.contacts.last.additional_attributes['social_instagram_user_name']).to eq 'some_user_name'
@@ -81,9 +62,11 @@ describe Webhooks::InstagramEventsJob do
end
it 'handle instagram unsend message event' do
+ unsend_event = build(:instagram_message_unsend_event).with_indifferent_access
+ sender_id = unsend_event[:entry][0][:messaging][0][:sender][:id]
+
message = create(:message, inbox_id: instagram_messenger_inbox.id, source_id: 'message-id-to-delete')
allow(Koala::Facebook::API).to receive(:new).and_return(fb_object)
- sender_id = message_events[:unsend][:entry][0][:messaging][0][:sender][:id]
allow(fb_object).to receive(:get_object).and_return(
{
name: 'Jane',
@@ -96,7 +79,7 @@ describe Webhooks::InstagramEventsJob do
expect(instagram_messenger_inbox.messages.count).to be 1
- instagram_webhook.perform_now(message_events[:unsend][:entry])
+ instagram_webhook.perform_now(unsend_event[:entry])
expect(instagram_messenger_inbox.messages.last.content).to eq 'This message was deleted'
expect(instagram_messenger_inbox.messages.last.deleted).to be true
@@ -105,14 +88,14 @@ describe Webhooks::InstagramEventsJob do
end
it 'creates incoming message with attachments in the instagram inbox' do
+ attachment_event = build(:instagram_message_attachment_event).with_indifferent_access
+ sender_id = attachment_event[:entry][0][:messaging][0][:sender][:id]
+
allow(Koala::Facebook::API).to receive(:new).and_return(fb_object)
- sender_id = message_events[:attachment][:entry][0][:messaging][0][:sender][:id]
allow(fb_object).to receive(:get_object).and_return(
return_object_for(sender_id).with_indifferent_access
)
- instagram_webhook.perform_now(message_events[:attachment][:entry])
-
- instagram_messenger_inbox.reload
+ instagram_webhook.perform_now(attachment_event[:entry])
expect(instagram_messenger_inbox.contacts.count).to be 1
expect(instagram_messenger_inbox.messages.count).to be 1
@@ -120,8 +103,10 @@ describe Webhooks::InstagramEventsJob do
end
it 'creates incoming message with attachments in the instagram inbox for story mention' do
+ story_mention_event = build(:instagram_story_mention_event).with_indifferent_access
+ sender_id = story_mention_event[:entry][0][:messaging][0][:sender][:id]
+
allow(Koala::Facebook::API).to receive(:new).and_return(fb_object)
- sender_id = message_events[:story_mention][:entry][0][:messaging][0][:sender][:id]
allow(fb_object).to receive(:get_object).and_return(
return_object_for(sender_id).with_indifferent_access,
{ story:
@@ -137,9 +122,7 @@ describe Webhooks::InstagramEventsJob do
id: 'instagram-message-id-1234' }.with_indifferent_access
)
- instagram_webhook.perform_now(message_events[:story_mention][:entry])
-
- instagram_messenger_inbox.reload
+ instagram_webhook.perform_now(story_mention_event[:entry])
expect(instagram_messenger_inbox.messages.count).to be 1
expect(instagram_messenger_inbox.messages.last.attachments.count).to be 1
@@ -149,12 +132,12 @@ describe Webhooks::InstagramEventsJob do
end
it 'does not create contact or messages when Facebook API call fails' do
+ story_mention_echo_event = build(:instagram_story_mention_event_with_echo).with_indifferent_access
+
allow(Koala::Facebook::API).to receive(:new).and_return(fb_object)
allow(fb_object).to receive(:get_object).and_raise(Koala::Facebook::ClientError)
- instagram_webhook.perform_now(message_events[:story_mention_echo][:entry])
-
- instagram_messenger_inbox.reload
+ instagram_webhook.perform_now(story_mention_echo_event[:entry])
expect(instagram_messenger_inbox.contacts.count).to be 0
expect(instagram_messenger_inbox.contact_inboxes.count).to be 0
@@ -162,21 +145,23 @@ describe Webhooks::InstagramEventsJob do
end
it 'handle messaging_seen callback' do
- expect(Instagram::ReadStatusService).to receive(:new).with(params: message_events[:messaging_seen][:entry][0][:messaging][0],
+ messaging_seen_event = build(:messaging_seen_event).with_indifferent_access
+
+ expect(Instagram::ReadStatusService).to receive(:new).with(params: messaging_seen_event[:entry][0][:messaging][0],
channel: instagram_messenger_inbox.channel).and_call_original
- instagram_webhook.perform_now(message_events[:messaging_seen][:entry])
+ instagram_webhook.perform_now(messaging_seen_event[:entry])
end
it 'handles unsupported message' do
+ unsupported_event = build(:instagram_message_unsupported_event).with_indifferent_access
+ sender_id = unsupported_event[:entry][0][:messaging][0][:sender][:id]
+
allow(Koala::Facebook::API).to receive(:new).and_return(fb_object)
- sender_id = message_events[:unsupported][:entry][0][:messaging][0][:sender][:id]
allow(fb_object).to receive(:get_object).and_return(
return_object_for(sender_id).with_indifferent_access
)
- instagram_webhook.perform_now(message_events[:unsupported][:entry])
- instagram_messenger_inbox.reload
-
+ instagram_webhook.perform_now(unsupported_event[:entry])
expect(instagram_messenger_inbox.contacts.count).to be 1
expect(instagram_messenger_inbox.contacts.last.additional_attributes['social_instagram_user_name']).to eq 'some_user_name'
expect(instagram_messenger_inbox.conversations.count).to be 1
@@ -186,6 +171,9 @@ describe Webhooks::InstagramEventsJob do
end
context 'when handling messaging events for Instagram via Instagram login' do
+ let!(:instagram_channel) { create(:channel_instagram, account: account, instagram_id: 'chatwoot-app-user-id-1') }
+ let!(:instagram_inbox) { instagram_channel.inbox }
+
before do
instagram_channel.update(access_token: 'valid_instagram_token')
@@ -210,9 +198,8 @@ describe Webhooks::InstagramEventsJob do
end
it 'creates incoming message with correct contact info in the instagram direct inbox' do
- instagram_webhook.perform_now(message_events[:dm][:entry])
- instagram_inbox.reload
-
+ dm_event = build(:instagram_message_create_event).with_indifferent_access
+ instagram_webhook.perform_now(dm_event[:entry])
expect(instagram_inbox.contacts.count).to eq 1
expect(instagram_inbox.contacts.last.additional_attributes['social_instagram_user_name']).to eq 'some_user_name'
expect(instagram_inbox.conversations.count).to eq 1
@@ -221,7 +208,8 @@ describe Webhooks::InstagramEventsJob do
end
it 'sets correct instagram attributes on contact' do
- instagram_webhook.perform_now(message_events[:dm][:entry])
+ dm_event = build(:instagram_message_create_event).with_indifferent_access
+ instagram_webhook.perform_now(dm_event[:entry])
instagram_inbox.reload
contact = instagram_inbox.contacts.last
@@ -233,6 +221,8 @@ describe Webhooks::InstagramEventsJob do
end
it 'handle instagram unsend message event' do
+ unsend_event = build(:instagram_message_unsend_event).with_indifferent_access
+
message = create(:message, inbox_id: instagram_inbox.id, source_id: 'message-id-to-delete', content: 'random_text')
# Create attachment correctly with account association
@@ -244,7 +234,7 @@ describe Webhooks::InstagramEventsJob do
expect(instagram_inbox.messages.count).to be 1
- instagram_webhook.perform_now(message_events[:unsend][:entry])
+ instagram_webhook.perform_now(unsend_event[:entry])
message.reload
@@ -254,9 +244,8 @@ describe Webhooks::InstagramEventsJob do
end
it 'creates incoming message with attachments in the instagram direct inbox' do
- instagram_webhook.perform_now(message_events[:attachment][:entry])
-
- instagram_inbox.reload
+ attachment_event = build(:instagram_message_attachment_event).with_indifferent_access
+ instagram_webhook.perform_now(attachment_event[:entry])
expect(instagram_inbox.contacts.count).to be 1
expect(instagram_inbox.messages.count).to be 1
@@ -264,9 +253,8 @@ describe Webhooks::InstagramEventsJob do
end
it 'handles unsupported message' do
- instagram_webhook.perform_now(message_events[:unsupported][:entry])
- instagram_inbox.reload
-
+ unsupported_event = build(:instagram_message_unsupported_event).with_indifferent_access
+ instagram_webhook.perform_now(unsupported_event[:entry])
expect(instagram_inbox.contacts.count).to be 1
expect(instagram_inbox.contacts.last.additional_attributes['social_instagram_user_name']).to eq 'some_user_name'
expect(instagram_inbox.conversations.count).to be 1
@@ -275,12 +263,12 @@ describe Webhooks::InstagramEventsJob do
end
it 'does not create contact or messages when Instagram API call fails' do
+ story_mention_echo_event = build(:instagram_story_mention_event_with_echo).with_indifferent_access
+
stub_request(:get, %r{https://graph\.instagram\.com/v22\.0/.*\?.*})
.to_return(status: 401, body: { error: { message: 'Invalid OAuth access token' } }.to_json)
- instagram_webhook.perform_now(message_events[:story_mention_echo][:entry])
-
- instagram_inbox.reload
+ instagram_webhook.perform_now(story_mention_echo_event[:entry])
expect(instagram_inbox.contacts.count).to be 0
expect(instagram_inbox.contact_inboxes.count).to be 0
@@ -288,19 +276,20 @@ describe Webhooks::InstagramEventsJob do
end
it 'handles messaging_seen callback' do
- expect(Instagram::ReadStatusService).to receive(:new).with(params: message_events[:messaging_seen][:entry][0][:messaging][0],
+ messaging_seen_event = build(:messaging_seen_event).with_indifferent_access
+
+ expect(Instagram::ReadStatusService).to receive(:new).with(params: messaging_seen_event[:entry][0][:messaging][0],
channel: instagram_inbox.channel).and_call_original
- instagram_webhook.perform_now(message_events[:messaging_seen][:entry])
+ instagram_webhook.perform_now(messaging_seen_event[:entry])
end
it 'creates contact when Instagram API call returns `No matching Instagram user` (9010 error code)' do
stub_request(:get, %r{https://graph\.instagram\.com/v22\.0/.*\?.*})
.to_return(status: 401, body: { error: { message: 'No matching Instagram user', code: 9010 } }.to_json)
- sender_id = message_events[:dm][:entry][0][:messaging][0][:sender][:id]
- instagram_webhook.perform_now(message_events[:dm][:entry])
-
- instagram_inbox.reload
+ dm_event = build(:instagram_message_create_event).with_indifferent_access
+ sender_id = dm_event[:entry][0][:messaging][0][:sender][:id]
+ instagram_webhook.perform_now(dm_event[:entry])
expect(instagram_inbox.contacts.count).to be 1
expect(instagram_inbox.contacts.last.name).to eq "Unknown (IG: #{sender_id})"
From 0c101b1f6b2a07ab898de4a69dd03e3347c351ac Mon Sep 17 00:00:00 2001
From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Date: Tue, 12 Aug 2025 20:21:05 +0530
Subject: [PATCH 05/26] chore: UI improvements to compose new conversation form
(#12173)
---
.../NewConversation/ComposeConversation.vue | 19 ++++++++++++++-----
.../components-next/sidebar/Sidebar.vue | 6 ++----
2 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/app/javascript/dashboard/components-next/NewConversation/ComposeConversation.vue b/app/javascript/dashboard/components-next/NewConversation/ComposeConversation.vue
index 610d11dab..d3686cfd7 100644
--- a/app/javascript/dashboard/components-next/NewConversation/ComposeConversation.vue
+++ b/app/javascript/dashboard/components-next/NewConversation/ComposeConversation.vue
@@ -2,6 +2,7 @@
import { ref, computed, onMounted, watch } from 'vue';
import { useStore, useMapGetter } from 'dashboard/composables/store';
import { useI18n } from 'vue-i18n';
+import { useWindowSize } from '@vueuse/core';
import { useUISettings } from 'dashboard/composables/useUISettings';
import { vOnClickOutside } from '@vueuse/components';
import { useAlert } from 'dashboard/composables';
@@ -15,6 +16,7 @@ import {
processContactableInboxes,
mergeInboxDetails,
} from 'dashboard/components-next/NewConversation/helpers/composeConversationHelper';
+import wootConstants from 'dashboard/constants/globals';
import ComposeNewConversationForm from 'dashboard/components-next/NewConversation/components/ComposeNewConversationForm.vue';
@@ -37,9 +39,16 @@ const emit = defineEmits(['close']);
const store = useStore();
const { t } = useI18n();
+const { width: windowWidth } = useWindowSize();
const { fetchSignatureFlagFromUISettings } = useUISettings();
+const isSmallScreen = computed(
+ () => windowWidth.value < wootConstants.SMALL_SCREEN_BREAKPOINT
+);
+
+const viewInModal = computed(() => props.isModal || isSmallScreen.value);
+
const contacts = ref([]);
const selectedContact = ref(null);
const targetInbox = ref(null);
@@ -67,7 +76,7 @@ const directUploadsEnabled = computed(
const activeContact = computed(() => contactById.value(props.contactId));
const composePopoverClass = computed(() => {
- if (props.isModal) return '';
+ if (viewInModal.value) return '';
return props.alignPosition === 'right'
? 'absolute ltr:left-0 ltr:right-[unset] rtl:right-0 rtl:left-[unset]'
@@ -202,7 +211,7 @@ const handleClickOutside = () => {
};
const onModalBackdropClick = () => {
- if (!props.isModal) return;
+ if (!viewInModal.value) return;
handleClickOutside();
};
@@ -231,7 +240,7 @@ useKeyboardEvents(keyboardEvents);
]"
class="relative"
:class="{
- 'z-40': showComposeNewConversation,
+ 'z-50': showComposeNewConversation && !viewInModal,
}"
>
{
class="bg-n-solid-2 rtl:border-l ltr:border-r border-n-weak flex flex-col text-sm pb-1 fixed top-0 ltr:left-0 rtl:right-0 h-full z-40 transition-transform duration-200 ease-in-out md:static w-[200px] basis-[200px] md:flex-shrink-0 md:ltr:translate-x-0 md:rtl:-translate-x-0"
:class="[
{
- 'ltr:translate-x-0 rtl:-translate-x-0 shadow-lg md:shadow-none':
- isMobileSidebarOpen,
- 'ltr:-translate-x-full rtl:translate-x-full md:translate-x-0':
- !isMobileSidebarOpen,
+ 'shadow-lg md:shadow-none': isMobileSidebarOpen,
+ 'ltr:-translate-x-full rtl:translate-x-full': !isMobileSidebarOpen,
},
]"
>
From 469e724e3a4ec7b70066189f8ab1ae739a146044 Mon Sep 17 00:00:00 2001
From: Muhsin Keloth
Date: Tue, 12 Aug 2025 20:25:09 +0530
Subject: [PATCH 06/26] docs: add swagger spec for whatsapp templates changes
(#12169)
Added swagger changes for the PR
https://github.com/chatwoot/chatwoot/pull/11997
---
.../conversation/create_message_payload.yml | 60 +++++++++++--
.../conversation/messages/create.yml | 52 +++++++++++-
swagger/swagger.json | 84 +++++++++++++++++--
swagger/tag_groups/application_swagger.json | 84 +++++++++++++++++--
swagger/tag_groups/client_swagger.json | 82 ++++++++++++++++--
swagger/tag_groups/other_swagger.json | 82 ++++++++++++++++--
swagger/tag_groups/platform_swagger.json | 82 ++++++++++++++++--
7 files changed, 479 insertions(+), 47 deletions(-)
diff --git a/swagger/definitions/request/conversation/create_message_payload.yml b/swagger/definitions/request/conversation/create_message_payload.yml
index 4b1851293..71d073d75 100644
--- a/swagger/definitions/request/conversation/create_message_payload.yml
+++ b/swagger/definitions/request/conversation/create_message_payload.yml
@@ -30,22 +30,64 @@ properties:
example: 1
template_params:
type: object
- description: The template params for the message in case of whatsapp Channel
+ description: WhatsApp template parameters for sending structured messages
+ required:
+ - name
+ - category
+ - language
+ - processed_params
properties:
name:
type: string
- description: Name of the template
- example: 'sample_issue_resolution'
+ description: Name of the WhatsApp template (must be approved in WhatsApp Business Manager)
+ example: 'purchase_receipt'
category:
type: string
+ enum: ['UTILITY', 'MARKETING', 'SHIPPING_UPDATE', 'TICKET_UPDATE', 'ISSUE_RESOLUTION']
description: Category of the template
- example: UTILITY
+ example: 'UTILITY'
language:
type: string
- description: Language of the template
- example: en_US
+ description: Language code of the template (BCP 47 format)
+ example: 'en_US'
processed_params:
type: object
- description: The processed param values for template variables in template
- example:
- 1: 'Chatwoot'
\ No newline at end of file
+ description: Processed template parameters organized by component type
+ properties:
+ body:
+ type: object
+ description: Body component parameters with variable placeholders
+ additionalProperties:
+ type: string
+ example:
+ '1': 'Visa'
+ '2': 'Nike'
+ '3': 'Bill'
+ header:
+ type: object
+ description: Header component parameters for media templates
+ properties:
+ media_url:
+ type: string
+ format: uri
+ description: Publicly accessible URL for IMAGE, VIDEO, or DOCUMENT headers
+ example: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'
+ media_type:
+ type: string
+ enum: ['image', 'video', 'document']
+ description: Type of media for the header
+ example: 'document'
+ buttons:
+ type: array
+ description: Button component parameters for interactive templates
+ items:
+ type: object
+ properties:
+ type:
+ type: string
+ enum: ['url', 'copy_code']
+ description: Type of button parameter
+ parameter:
+ type: string
+ description: Dynamic parameter value for the button
+ example: 'SSFSDFSD'
\ No newline at end of file
diff --git a/swagger/paths/application/conversation/messages/create.yml b/swagger/paths/application/conversation/messages/create.yml
index f8cd35f3c..1b8272585 100644
--- a/swagger/paths/application/conversation/messages/create.yml
+++ b/swagger/paths/application/conversation/messages/create.yml
@@ -2,7 +2,57 @@ tags:
- Messages
operationId: create-a-new-message-in-a-conversation
summary: Create New Message
-description: Create a new message in the conversation
+description: |
+ Create a new message in the conversation.
+
+ ## WhatsApp Template Messages
+
+ For WhatsApp channels, you can send structured template messages using the `template_params` field.
+ Templates must be pre-approved in WhatsApp Business Manager.
+
+ ### Example Templates
+
+ **Text with Image Header:**
+ ```json
+ {
+ "content": "Hi your order 121212 is confirmed. Please wait for further updates",
+ "template_params": {
+ "name": "order_confirmation",
+ "category": "MARKETING",
+ "language": "en",
+ "processed_params": {
+ "body": {
+ "1": "121212"
+ },
+ "header": {
+ "media_url": "https://picsum.photos/200/300",
+ "media_type": "image"
+ }
+ }
+ }
+ }
+ ```
+
+ **Text with Copy Code Button:**
+ ```json
+ {
+ "content": "Special offer! Get 30% off your next purchase. Use the code below",
+ "template_params": {
+ "name": "discount_coupon",
+ "category": "MARKETING",
+ "language": "en",
+ "processed_params": {
+ "body": {
+ "discount_percentage": "30"
+ },
+ "buttons": [{
+ "type": "copy_code",
+ "parameter": "SAVE20"
+ }]
+ }
+ }
+ }
+ ```
security:
- userApiKey: []
- agentBotApiKey: []
diff --git a/swagger/swagger.json b/swagger/swagger.json
index e849f8119..8da8e2c5b 100644
--- a/swagger/swagger.json
+++ b/swagger/swagger.json
@@ -5937,7 +5937,7 @@
],
"operationId": "create-a-new-message-in-a-conversation",
"summary": "Create New Message",
- "description": "Create a new message in the conversation",
+ "description": "Create a new message in the conversation.\n\n## WhatsApp Template Messages\n\nFor WhatsApp channels, you can send structured template messages using the `template_params` field. \nTemplates must be pre-approved in WhatsApp Business Manager.\n\n### Example Templates\n\n**Text with Image Header:**\n```json\n{\n \"content\": \"Hi your order 121212 is confirmed. Please wait for further updates\",\n \"template_params\": {\n \"name\": \"order_confirmation\",\n \"category\": \"MARKETING\",\n \"language\": \"en\",\n \"processed_params\": {\n \"body\": {\n \"1\": \"121212\"\n },\n \"header\": {\n \"media_url\": \"https://picsum.photos/200/300\",\n \"media_type\": \"image\"\n }\n }\n }\n}\n```\n\n**Text with Copy Code Button:**\n```json\n{\n \"content\": \"Special offer! Get 30% off your next purchase. Use the code below\",\n \"template_params\": {\n \"name\": \"discount_coupon\",\n \"category\": \"MARKETING\",\n \"language\": \"en\",\n \"processed_params\": {\n \"body\": {\n \"discount_percentage\": \"30\"\n },\n \"buttons\": [{\n \"type\": \"copy_code\",\n \"parameter\": \"SAVE20\"\n }]\n }\n }\n}\n```\n",
"security": [
{
"userApiKey": []
@@ -10148,28 +10148,96 @@
},
"template_params": {
"type": "object",
- "description": "The template params for the message in case of whatsapp Channel",
+ "description": "WhatsApp template parameters for sending structured messages",
+ "required": [
+ "name",
+ "category",
+ "language",
+ "processed_params"
+ ],
"properties": {
"name": {
"type": "string",
- "description": "Name of the template",
- "example": "sample_issue_resolution"
+ "description": "Name of the WhatsApp template (must be approved in WhatsApp Business Manager)",
+ "example": "purchase_receipt"
},
"category": {
"type": "string",
+ "enum": [
+ "UTILITY",
+ "MARKETING",
+ "SHIPPING_UPDATE",
+ "TICKET_UPDATE",
+ "ISSUE_RESOLUTION"
+ ],
"description": "Category of the template",
"example": "UTILITY"
},
"language": {
"type": "string",
- "description": "Language of the template",
+ "description": "Language code of the template (BCP 47 format)",
"example": "en_US"
},
"processed_params": {
"type": "object",
- "description": "The processed param values for template variables in template",
- "example": {
- "1": "Chatwoot"
+ "description": "Processed template parameters organized by component type",
+ "properties": {
+ "body": {
+ "type": "object",
+ "description": "Body component parameters with variable placeholders",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "example": {
+ "1": "Visa",
+ "2": "Nike",
+ "3": "Bill"
+ }
+ },
+ "header": {
+ "type": "object",
+ "description": "Header component parameters for media templates",
+ "properties": {
+ "media_url": {
+ "type": "string",
+ "format": "uri",
+ "description": "Publicly accessible URL for IMAGE, VIDEO, or DOCUMENT headers",
+ "example": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
+ },
+ "media_type": {
+ "type": "string",
+ "enum": [
+ "image",
+ "video",
+ "document"
+ ],
+ "description": "Type of media for the header",
+ "example": "document"
+ }
+ }
+ },
+ "buttons": {
+ "type": "array",
+ "description": "Button component parameters for interactive templates",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "url",
+ "copy_code"
+ ],
+ "description": "Type of button parameter"
+ },
+ "parameter": {
+ "type": "string",
+ "description": "Dynamic parameter value for the button",
+ "example": "SSFSDFSD"
+ }
+ }
+ }
+ }
}
}
}
diff --git a/swagger/tag_groups/application_swagger.json b/swagger/tag_groups/application_swagger.json
index f06819d1d..23a9ab0b2 100644
--- a/swagger/tag_groups/application_swagger.json
+++ b/swagger/tag_groups/application_swagger.json
@@ -4334,7 +4334,7 @@
],
"operationId": "create-a-new-message-in-a-conversation",
"summary": "Create New Message",
- "description": "Create a new message in the conversation",
+ "description": "Create a new message in the conversation.\n\n## WhatsApp Template Messages\n\nFor WhatsApp channels, you can send structured template messages using the `template_params` field. \nTemplates must be pre-approved in WhatsApp Business Manager.\n\n### Example Templates\n\n**Text with Image Header:**\n```json\n{\n \"content\": \"Hi your order 121212 is confirmed. Please wait for further updates\",\n \"template_params\": {\n \"name\": \"order_confirmation\",\n \"category\": \"MARKETING\",\n \"language\": \"en\",\n \"processed_params\": {\n \"body\": {\n \"1\": \"121212\"\n },\n \"header\": {\n \"media_url\": \"https://picsum.photos/200/300\",\n \"media_type\": \"image\"\n }\n }\n }\n}\n```\n\n**Text with Copy Code Button:**\n```json\n{\n \"content\": \"Special offer! Get 30% off your next purchase. Use the code below\",\n \"template_params\": {\n \"name\": \"discount_coupon\",\n \"category\": \"MARKETING\",\n \"language\": \"en\",\n \"processed_params\": {\n \"body\": {\n \"discount_percentage\": \"30\"\n },\n \"buttons\": [{\n \"type\": \"copy_code\",\n \"parameter\": \"SAVE20\"\n }]\n }\n }\n}\n```\n",
"security": [
{
"userApiKey": []
@@ -8509,28 +8509,96 @@
},
"template_params": {
"type": "object",
- "description": "The template params for the message in case of whatsapp Channel",
+ "description": "WhatsApp template parameters for sending structured messages",
+ "required": [
+ "name",
+ "category",
+ "language",
+ "processed_params"
+ ],
"properties": {
"name": {
"type": "string",
- "description": "Name of the template",
- "example": "sample_issue_resolution"
+ "description": "Name of the WhatsApp template (must be approved in WhatsApp Business Manager)",
+ "example": "purchase_receipt"
},
"category": {
"type": "string",
+ "enum": [
+ "UTILITY",
+ "MARKETING",
+ "SHIPPING_UPDATE",
+ "TICKET_UPDATE",
+ "ISSUE_RESOLUTION"
+ ],
"description": "Category of the template",
"example": "UTILITY"
},
"language": {
"type": "string",
- "description": "Language of the template",
+ "description": "Language code of the template (BCP 47 format)",
"example": "en_US"
},
"processed_params": {
"type": "object",
- "description": "The processed param values for template variables in template",
- "example": {
- "1": "Chatwoot"
+ "description": "Processed template parameters organized by component type",
+ "properties": {
+ "body": {
+ "type": "object",
+ "description": "Body component parameters with variable placeholders",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "example": {
+ "1": "Visa",
+ "2": "Nike",
+ "3": "Bill"
+ }
+ },
+ "header": {
+ "type": "object",
+ "description": "Header component parameters for media templates",
+ "properties": {
+ "media_url": {
+ "type": "string",
+ "format": "uri",
+ "description": "Publicly accessible URL for IMAGE, VIDEO, or DOCUMENT headers",
+ "example": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
+ },
+ "media_type": {
+ "type": "string",
+ "enum": [
+ "image",
+ "video",
+ "document"
+ ],
+ "description": "Type of media for the header",
+ "example": "document"
+ }
+ }
+ },
+ "buttons": {
+ "type": "array",
+ "description": "Button component parameters for interactive templates",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "url",
+ "copy_code"
+ ],
+ "description": "Type of button parameter"
+ },
+ "parameter": {
+ "type": "string",
+ "description": "Dynamic parameter value for the button",
+ "example": "SSFSDFSD"
+ }
+ }
+ }
+ }
}
}
}
diff --git a/swagger/tag_groups/client_swagger.json b/swagger/tag_groups/client_swagger.json
index c6a3ba408..6bbae4fb2 100644
--- a/swagger/tag_groups/client_swagger.json
+++ b/swagger/tag_groups/client_swagger.json
@@ -3132,28 +3132,96 @@
},
"template_params": {
"type": "object",
- "description": "The template params for the message in case of whatsapp Channel",
+ "description": "WhatsApp template parameters for sending structured messages",
+ "required": [
+ "name",
+ "category",
+ "language",
+ "processed_params"
+ ],
"properties": {
"name": {
"type": "string",
- "description": "Name of the template",
- "example": "sample_issue_resolution"
+ "description": "Name of the WhatsApp template (must be approved in WhatsApp Business Manager)",
+ "example": "purchase_receipt"
},
"category": {
"type": "string",
+ "enum": [
+ "UTILITY",
+ "MARKETING",
+ "SHIPPING_UPDATE",
+ "TICKET_UPDATE",
+ "ISSUE_RESOLUTION"
+ ],
"description": "Category of the template",
"example": "UTILITY"
},
"language": {
"type": "string",
- "description": "Language of the template",
+ "description": "Language code of the template (BCP 47 format)",
"example": "en_US"
},
"processed_params": {
"type": "object",
- "description": "The processed param values for template variables in template",
- "example": {
- "1": "Chatwoot"
+ "description": "Processed template parameters organized by component type",
+ "properties": {
+ "body": {
+ "type": "object",
+ "description": "Body component parameters with variable placeholders",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "example": {
+ "1": "Visa",
+ "2": "Nike",
+ "3": "Bill"
+ }
+ },
+ "header": {
+ "type": "object",
+ "description": "Header component parameters for media templates",
+ "properties": {
+ "media_url": {
+ "type": "string",
+ "format": "uri",
+ "description": "Publicly accessible URL for IMAGE, VIDEO, or DOCUMENT headers",
+ "example": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
+ },
+ "media_type": {
+ "type": "string",
+ "enum": [
+ "image",
+ "video",
+ "document"
+ ],
+ "description": "Type of media for the header",
+ "example": "document"
+ }
+ }
+ },
+ "buttons": {
+ "type": "array",
+ "description": "Button component parameters for interactive templates",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "url",
+ "copy_code"
+ ],
+ "description": "Type of button parameter"
+ },
+ "parameter": {
+ "type": "string",
+ "description": "Dynamic parameter value for the button",
+ "example": "SSFSDFSD"
+ }
+ }
+ }
+ }
}
}
}
diff --git a/swagger/tag_groups/other_swagger.json b/swagger/tag_groups/other_swagger.json
index e2a16245b..414a44e63 100644
--- a/swagger/tag_groups/other_swagger.json
+++ b/swagger/tag_groups/other_swagger.json
@@ -2547,28 +2547,96 @@
},
"template_params": {
"type": "object",
- "description": "The template params for the message in case of whatsapp Channel",
+ "description": "WhatsApp template parameters for sending structured messages",
+ "required": [
+ "name",
+ "category",
+ "language",
+ "processed_params"
+ ],
"properties": {
"name": {
"type": "string",
- "description": "Name of the template",
- "example": "sample_issue_resolution"
+ "description": "Name of the WhatsApp template (must be approved in WhatsApp Business Manager)",
+ "example": "purchase_receipt"
},
"category": {
"type": "string",
+ "enum": [
+ "UTILITY",
+ "MARKETING",
+ "SHIPPING_UPDATE",
+ "TICKET_UPDATE",
+ "ISSUE_RESOLUTION"
+ ],
"description": "Category of the template",
"example": "UTILITY"
},
"language": {
"type": "string",
- "description": "Language of the template",
+ "description": "Language code of the template (BCP 47 format)",
"example": "en_US"
},
"processed_params": {
"type": "object",
- "description": "The processed param values for template variables in template",
- "example": {
- "1": "Chatwoot"
+ "description": "Processed template parameters organized by component type",
+ "properties": {
+ "body": {
+ "type": "object",
+ "description": "Body component parameters with variable placeholders",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "example": {
+ "1": "Visa",
+ "2": "Nike",
+ "3": "Bill"
+ }
+ },
+ "header": {
+ "type": "object",
+ "description": "Header component parameters for media templates",
+ "properties": {
+ "media_url": {
+ "type": "string",
+ "format": "uri",
+ "description": "Publicly accessible URL for IMAGE, VIDEO, or DOCUMENT headers",
+ "example": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
+ },
+ "media_type": {
+ "type": "string",
+ "enum": [
+ "image",
+ "video",
+ "document"
+ ],
+ "description": "Type of media for the header",
+ "example": "document"
+ }
+ }
+ },
+ "buttons": {
+ "type": "array",
+ "description": "Button component parameters for interactive templates",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "url",
+ "copy_code"
+ ],
+ "description": "Type of button parameter"
+ },
+ "parameter": {
+ "type": "string",
+ "description": "Dynamic parameter value for the button",
+ "example": "SSFSDFSD"
+ }
+ }
+ }
+ }
}
}
}
diff --git a/swagger/tag_groups/platform_swagger.json b/swagger/tag_groups/platform_swagger.json
index b4feb0024..215fcd38b 100644
--- a/swagger/tag_groups/platform_swagger.json
+++ b/swagger/tag_groups/platform_swagger.json
@@ -3308,28 +3308,96 @@
},
"template_params": {
"type": "object",
- "description": "The template params for the message in case of whatsapp Channel",
+ "description": "WhatsApp template parameters for sending structured messages",
+ "required": [
+ "name",
+ "category",
+ "language",
+ "processed_params"
+ ],
"properties": {
"name": {
"type": "string",
- "description": "Name of the template",
- "example": "sample_issue_resolution"
+ "description": "Name of the WhatsApp template (must be approved in WhatsApp Business Manager)",
+ "example": "purchase_receipt"
},
"category": {
"type": "string",
+ "enum": [
+ "UTILITY",
+ "MARKETING",
+ "SHIPPING_UPDATE",
+ "TICKET_UPDATE",
+ "ISSUE_RESOLUTION"
+ ],
"description": "Category of the template",
"example": "UTILITY"
},
"language": {
"type": "string",
- "description": "Language of the template",
+ "description": "Language code of the template (BCP 47 format)",
"example": "en_US"
},
"processed_params": {
"type": "object",
- "description": "The processed param values for template variables in template",
- "example": {
- "1": "Chatwoot"
+ "description": "Processed template parameters organized by component type",
+ "properties": {
+ "body": {
+ "type": "object",
+ "description": "Body component parameters with variable placeholders",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "example": {
+ "1": "Visa",
+ "2": "Nike",
+ "3": "Bill"
+ }
+ },
+ "header": {
+ "type": "object",
+ "description": "Header component parameters for media templates",
+ "properties": {
+ "media_url": {
+ "type": "string",
+ "format": "uri",
+ "description": "Publicly accessible URL for IMAGE, VIDEO, or DOCUMENT headers",
+ "example": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
+ },
+ "media_type": {
+ "type": "string",
+ "enum": [
+ "image",
+ "video",
+ "document"
+ ],
+ "description": "Type of media for the header",
+ "example": "document"
+ }
+ }
+ },
+ "buttons": {
+ "type": "array",
+ "description": "Button component parameters for interactive templates",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "url",
+ "copy_code"
+ ],
+ "description": "Type of button parameter"
+ },
+ "parameter": {
+ "type": "string",
+ "description": "Dynamic parameter value for the button",
+ "example": "SSFSDFSD"
+ }
+ }
+ }
+ }
}
}
}
From 48fa7bf72b7b029bb9315f43bd6b9fd0e1872a41 Mon Sep 17 00:00:00 2001
From: Muhsin Keloth
Date: Tue, 12 Aug 2025 22:56:53 +0530
Subject: [PATCH 07/26] fix: Handle nil `processed_params` for WhatsApp
templates without params (#12177)
WhatsApp templates without parameters (body-only templates like
notifications, confirmations) were failing to send with the error:
ArgumentError (Unknown legacy format: NilClass). This affected all
parameter-less templates across marketing messages, notifications, and
utility templates.
---
.../template_parameter_converter_service.rb | 3 +
spec/factories/channel/channel_whatsapp.rb | 19 ++++++
...mplate_parameter_converter_service_spec.rb | 62 +++++++++++++++++++
3 files changed, 84 insertions(+)
diff --git a/app/services/whatsapp/template_parameter_converter_service.rb b/app/services/whatsapp/template_parameter_converter_service.rb
index b9a9d55d9..641a29b95 100644
--- a/app/services/whatsapp/template_parameter_converter_service.rb
+++ b/app/services/whatsapp/template_parameter_converter_service.rb
@@ -86,6 +86,9 @@ class Whatsapp::TemplateParameterConverterService
# Hash format: {"1": "John", "name": "Jane"} → {body: {"1": "John", "name": "Jane"}}
body_params = convert_hash_to_body_params(legacy_params)
enhanced['body'] = body_params unless body_params.empty?
+ when NilClass
+ # Templates without parameters (nil processed_params)
+ # Return empty enhanced structure
else
raise ArgumentError, "Unknown legacy format: #{legacy_params.class}"
end
diff --git a/spec/factories/channel/channel_whatsapp.rb b/spec/factories/channel/channel_whatsapp.rb
index ad2bab241..dae7eb04f 100644
--- a/spec/factories/channel/channel_whatsapp.rb
+++ b/spec/factories/channel/channel_whatsapp.rb
@@ -63,6 +63,25 @@ FactoryBot.define do
],
'sub_category' => 'CUSTOM',
'parameter_format' => 'NAMED'
+ },
+ {
+ 'name' => 'test_no_params_template',
+ 'status' => 'APPROVED',
+ 'category' => 'UTILITY',
+ 'language' => 'en',
+ 'namespace' => 'ed41a221_133a_4558_a1d6_192960e3aee9',
+ 'id' => '9876543210987654',
+ 'length' => 1,
+ 'parameter_format' => 'POSITIONAL',
+ 'previous_category' => 'MARKETING',
+ 'sub_category' => 'CUSTOM',
+ 'components' => [
+ {
+ 'text' => 'Thank you for contacting us! Your request has been processed successfully. Have a great day! 🙂',
+ 'type' => 'BODY'
+ }
+ ],
+ 'rejected_reason' => 'NONE'
}]
end
message_templates_last_updated { Time.now.utc }
diff --git a/spec/services/whatsapp/template_parameter_converter_service_spec.rb b/spec/services/whatsapp/template_parameter_converter_service_spec.rb
index 2994bb472..570c5c6cc 100644
--- a/spec/services/whatsapp/template_parameter_converter_service_spec.rb
+++ b/spec/services/whatsapp/template_parameter_converter_service_spec.rb
@@ -133,6 +133,48 @@ describe Whatsapp::TemplateParameterConverterService do
end
end
+ context 'when processed_params is nil (parameter-less templates)' do
+ let(:nil_params) do
+ {
+ 'processed_params' => nil
+ }
+ end
+
+ let(:parameterless_template) do
+ {
+ 'name' => 'test_no_params_template',
+ 'language' => 'en',
+ 'parameter_format' => 'POSITIONAL',
+ 'id' => '9876543210987654',
+ 'status' => 'APPROVED',
+ 'category' => 'UTILITY',
+ 'previous_category' => 'MARKETING',
+ 'sub_category' => 'CUSTOM',
+ 'components' => [
+ {
+ 'type' => 'BODY',
+ 'text' => 'Thank you for contacting us! Your request has been processed successfully. Have a great day! 🙂'
+ }
+ ]
+ }
+ end
+
+ it 'converts nil to empty enhanced format' do
+ converter = described_class.new(nil_params, parameterless_template)
+ result = converter.normalize_to_enhanced
+
+ expect(result['processed_params']).to eq({})
+ expect(result['format_version']).to eq('legacy')
+ end
+
+ it 'does not raise ArgumentError for nil processed_params' do
+ expect do
+ converter = described_class.new(nil_params, parameterless_template)
+ converter.normalize_to_enhanced
+ end.not_to raise_error
+ end
+ end
+
context 'when invalid format' do
let(:invalid_params) do
{
@@ -174,6 +216,26 @@ describe Whatsapp::TemplateParameterConverterService do
end
describe 'simplified conversion methods' do
+ describe '#convert_legacy_to_enhanced' do
+ it 'handles nil processed_params without raising error' do
+ converter = described_class.new({}, template)
+ result = converter.send(:convert_legacy_to_enhanced, nil, template)
+ expect(result).to eq({})
+ end
+
+ it 'returns empty hash for parameter-less templates' do
+ parameterless_template = {
+ 'name' => 'no_params_template',
+ 'language' => 'en',
+ 'components' => [{ 'type' => 'BODY', 'text' => 'Hello World!' }]
+ }
+
+ converter = described_class.new({}, parameterless_template)
+ result = converter.send(:convert_legacy_to_enhanced, nil, parameterless_template)
+ expect(result).to eq({})
+ end
+ end
+
describe '#convert_array_to_body_params' do
it 'converts empty array' do
converter = described_class.new({}, template)
From 9a7318a9dbf01b4b9d6da8d691f590a886bf576c Mon Sep 17 00:00:00 2001
From: Vishnu Narayanan
Date: Wed, 13 Aug 2025 07:56:58 +0530
Subject: [PATCH 08/26] fix: cw-5411 handle unrepresentable image attachments
(#12178)
# Pull Request Template
## Description
Fixes
https://linear.app/chatwoot/issue/CW-5411/actionviewtemplateerror-activestorageunrepresentableerror
### Problem
API endpoints return 500 errors when conversations contain image
attachments that can't be processed by ActiveStorage (e.g., files with
non-ASCII filenames, corrupted images, or malicious XSS filenames).
Root Cause: Commit 6cab74139 removed the representable? safety check
from thumb_url, causing `ActiveStorage::UnrepresentableError` to bubble
up and crash the API when it encountered a malformed image file.
Fix: Rescue `thumb_url` method to catch UnrepresentableError and return
an empty string while logging problematic names for future debugging.
This ensures the messages/attachments api does not break due to a single
corrupted image file.
## Type of change
- [x] Bug fix (non-breaking change which fixes an issue)
## How Has This Been Tested?
- Added specs
## 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
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] 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
- [x] Any dependent changes have been merged and published in downstream
modules
---
app/models/attachment.rb | 7 ++++++-
spec/models/attachment_spec.rb | 10 ++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/app/models/attachment.rb b/app/models/attachment.rb
index 8c5750148..42ca79d6c 100644
--- a/app/models/attachment.rb
+++ b/app/models/attachment.rb
@@ -62,7 +62,12 @@ class Attachment < ApplicationRecord
def thumb_url
return '' unless file.attached? && image?
- url_for(file.representation(resize_to_fill: [250, nil]))
+ begin
+ url_for(file.representation(resize_to_fill: [250, nil]))
+ rescue ActiveStorage::UnrepresentableError => e
+ Rails.logger.warn "Unrepresentable image attachment: #{id} (#{file.filename}) - #{e.message}"
+ ''
+ end
end
def with_attached_file?
diff --git a/spec/models/attachment_spec.rb b/spec/models/attachment_spec.rb
index 0b03a56ad..cc00eab5d 100644
--- a/spec/models/attachment_spec.rb
+++ b/spec/models/attachment_spec.rb
@@ -82,6 +82,16 @@ RSpec.describe Attachment do
expect(attachment.thumb_url).to be_present
end
+
+ it 'handles unrepresentable images gracefully' do
+ attachment = message.attachments.create!(account_id: message.account_id, file_type: :image)
+ attachment.file.attach(io: StringIO.new('fake image'), filename: 'test.jpg', content_type: 'image/jpeg')
+
+ allow(attachment.file).to receive(:representation).and_raise(ActiveStorage::UnrepresentableError.new('Cannot represent'))
+
+ expect(Rails.logger).to receive(:warn).with(/Unrepresentable image attachment: #{attachment.id}/)
+ expect(attachment.thumb_url).to eq('')
+ end
end
describe 'meta data handling' do
From 42af4b1d01399937dabcf0c95cce872bebe3f5b5 Mon Sep 17 00:00:00 2001
From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Date: Wed, 13 Aug 2025 12:42:57 +0530
Subject: [PATCH 09/26] fix: Reset inbox on conversation switch in compose
conversation modal (#12174)
---
.../NewConversation/ComposeConversation.vue | 14 +++++++++-----
.../components/ComposeNewConversationForm.vue | 2 +-
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/app/javascript/dashboard/components-next/NewConversation/ComposeConversation.vue b/app/javascript/dashboard/components-next/NewConversation/ComposeConversation.vue
index d3686cfd7..fa9102d59 100644
--- a/app/javascript/dashboard/components-next/NewConversation/ComposeConversation.vue
+++ b/app/javascript/dashboard/components-next/NewConversation/ComposeConversation.vue
@@ -188,14 +188,18 @@ const toggle = () => {
watch(
activeContact,
- () => {
- if (activeContact.value && props.contactId) {
- const contactInboxes = activeContact.value?.contactInboxes || [];
+ (currentContact, previousContact) => {
+ if (currentContact && props.contactId) {
+ // Reset on contact change
+ if (currentContact?.id !== previousContact?.id) clearSelectedContact();
+
// First process the contactable inboxes to get the right structure
- const processedInboxes = processContactableInboxes(contactInboxes);
+ const processedInboxes = processContactableInboxes(
+ currentContact.contactInboxes || []
+ );
// Then Merge processedInboxes with the inboxes list
selectedContact.value = {
- ...activeContact.value,
+ ...currentContact,
contactInboxes: mergeInboxDetails(processedInboxes, inboxesList.value),
};
}
diff --git a/app/javascript/dashboard/components-next/NewConversation/components/ComposeNewConversationForm.vue b/app/javascript/dashboard/components-next/NewConversation/components/ComposeNewConversationForm.vue
index 5540940cd..e3e063740 100644
--- a/app/javascript/dashboard/components-next/NewConversation/components/ComposeNewConversationForm.vue
+++ b/app/javascript/dashboard/components-next/NewConversation/components/ComposeNewConversationForm.vue
@@ -265,7 +265,7 @@ const handleSendWhatsappMessage = async ({ message, templateParams }) => {
Date: Wed, 13 Aug 2025 04:27:14 -0300
Subject: [PATCH 10/26] feat: Add automation rule event conversation resolved
(#9669)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
# Description
add automation rule event conversation resolved
---------
Co-authored-by: Sojan
Co-authored-by: Shivam Mishra
Co-authored-by: Muhsin Keloth
---
.../composables/spec/useAutomation.spec.js | 1 +
.../dashboard/constants/automation.js | 2 +-
.../dashboard/helper/automationHelper.js | 9 +-
.../dashboard/i18n/locale/en/automation.json | 1 +
.../settings/automation/constants.js | 104 ++++++++++++++++++
app/listeners/automation_rule_listener.rb | 69 +++++-------
.../automation_rule_listener_spec.rb | 36 ++++++
.../automation_rule/create_update_payload.yml | 1 +
.../definitions/resource/automation_rule.yml | 2 +-
swagger/swagger.json | 1 +
swagger/tag_groups/application_swagger.json | 1 +
swagger/tag_groups/client_swagger.json | 1 +
swagger/tag_groups/other_swagger.json | 1 +
swagger/tag_groups/platform_swagger.json | 1 +
14 files changed, 184 insertions(+), 46 deletions(-)
diff --git a/app/javascript/dashboard/composables/spec/useAutomation.spec.js b/app/javascript/dashboard/composables/spec/useAutomation.spec.js
index 46c0bde50..a66f0c7b4 100644
--- a/app/javascript/dashboard/composables/spec/useAutomation.spec.js
+++ b/app/javascript/dashboard/composables/spec/useAutomation.spec.js
@@ -196,6 +196,7 @@ describe('useAutomation', () => {
automationTypes.conversation_created = { conditions: [] };
automationTypes.conversation_updated = { conditions: [] };
automationTypes.conversation_opened = { conditions: [] };
+ automationTypes.conversation_resolved = { conditions: [] };
automationHelper.generateCustomAttributeTypes.mockReturnValue([]);
automationHelper.generateCustomAttributes.mockReturnValue([]);
diff --git a/app/javascript/dashboard/constants/automation.js b/app/javascript/dashboard/constants/automation.js
index 399dd6153..a903075b8 100644
--- a/app/javascript/dashboard/constants/automation.js
+++ b/app/javascript/dashboard/constants/automation.js
@@ -8,7 +8,7 @@ export const DEFAULT_MESSAGE_CREATED_CONDITION = [
},
];
-export const DEFAULT_CONVERSATION_OPENED_CONDITION = [
+export const DEFAULT_CONVERSATION_CONDITION = [
{
attribute_key: 'browser_language',
filter_operator: 'equal_to',
diff --git a/app/javascript/dashboard/helper/automationHelper.js b/app/javascript/dashboard/helper/automationHelper.js
index c9852814a..3723fd4d5 100644
--- a/app/javascript/dashboard/helper/automationHelper.js
+++ b/app/javascript/dashboard/helper/automationHelper.js
@@ -5,7 +5,7 @@ import {
} from 'dashboard/routes/dashboard/settings/automation/operators';
import {
DEFAULT_MESSAGE_CREATED_CONDITION,
- DEFAULT_CONVERSATION_OPENED_CONDITION,
+ DEFAULT_CONVERSATION_CONDITION,
DEFAULT_OTHER_CONDITION,
DEFAULT_ACTIONS,
} from 'dashboard/constants/automation';
@@ -169,8 +169,11 @@ export const getDefaultConditions = eventName => {
if (eventName === 'message_created') {
return DEFAULT_MESSAGE_CREATED_CONDITION;
}
- if (eventName === 'conversation_opened') {
- return DEFAULT_CONVERSATION_OPENED_CONDITION;
+ if (
+ eventName === 'conversation_opened' ||
+ eventName === 'conversation_resolved'
+ ) {
+ return DEFAULT_CONVERSATION_CONDITION;
}
return DEFAULT_OTHER_CONDITION;
};
diff --git a/app/javascript/dashboard/i18n/locale/en/automation.json b/app/javascript/dashboard/i18n/locale/en/automation.json
index cf63de81c..80274f488 100644
--- a/app/javascript/dashboard/i18n/locale/en/automation.json
+++ b/app/javascript/dashboard/i18n/locale/en/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/routes/dashboard/settings/automation/constants.js b/app/javascript/dashboard/routes/dashboard/settings/automation/constants.js
index dfa6163d8..0a6905039 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/automation/constants.js
+++ b/app/javascript/dashboard/routes/dashboard/settings/automation/constants.js
@@ -468,6 +468,106 @@ export const AUTOMATIONS = {
},
],
},
+ conversation_resolved: {
+ conditions: [
+ {
+ key: 'browser_language',
+ name: 'BROWSER_LANGUAGE',
+ inputType: 'search_select',
+ filterOperators: OPERATOR_TYPES_1,
+ },
+ {
+ key: 'email',
+ name: 'EMAIL',
+ inputType: 'plain_text',
+ filterOperators: OPERATOR_TYPES_2,
+ },
+ {
+ key: 'mail_subject',
+ name: 'MAIL_SUBJECT',
+ inputType: 'plain_text',
+ filterOperators: OPERATOR_TYPES_2,
+ },
+ {
+ key: 'country_code',
+ name: 'COUNTRY_NAME',
+ inputType: 'search_select',
+ filterOperators: OPERATOR_TYPES_1,
+ },
+ {
+ key: 'referer',
+ name: 'REFERER_LINK',
+ inputType: 'plain_text',
+ filterOperators: OPERATOR_TYPES_2,
+ },
+ {
+ key: 'assignee_id',
+ name: 'ASSIGNEE_NAME',
+ inputType: 'search_select',
+ filterOperators: OPERATOR_TYPES_3,
+ },
+ {
+ key: 'phone_number',
+ name: 'PHONE_NUMBER',
+ inputType: 'plain_text',
+ filterOperators: OPERATOR_TYPES_6,
+ },
+ {
+ key: 'team_id',
+ name: 'TEAM_NAME',
+ inputType: 'search_select',
+ filterOperators: OPERATOR_TYPES_3,
+ },
+ {
+ key: 'inbox_id',
+ name: 'INBOX',
+ inputType: 'multi_select',
+ filterOperators: OPERATOR_TYPES_1,
+ },
+ {
+ key: 'conversation_language',
+ name: 'CONVERSATION_LANGUAGE',
+ inputType: 'multi_select',
+ filterOperators: OPERATOR_TYPES_1,
+ },
+ {
+ key: 'priority',
+ name: 'PRIORITY',
+ inputType: 'multi_select',
+ filterOperators: OPERATOR_TYPES_1,
+ },
+ ],
+ actions: [
+ {
+ key: 'assign_agent',
+ name: 'ASSIGN_AGENT',
+ },
+ {
+ key: 'assign_team',
+ name: 'ASSIGN_TEAM',
+ },
+ {
+ key: 'send_email_to_team',
+ name: 'SEND_EMAIL_TO_TEAM',
+ },
+ {
+ key: 'send_message',
+ name: 'SEND_MESSAGE',
+ },
+ {
+ key: 'send_email_transcript',
+ name: 'SEND_EMAIL_TRANSCRIPT',
+ },
+ {
+ key: 'send_webhook_event',
+ name: 'SEND_WEBHOOK_EVENT',
+ },
+ {
+ key: 'send_attachment',
+ name: 'SEND_ATTACHMENT',
+ },
+ ],
+ },
};
export const AUTOMATION_RULE_EVENTS = [
@@ -479,6 +579,10 @@ export const AUTOMATION_RULE_EVENTS = [
key: 'conversation_updated',
value: 'CONVERSATION_UPDATED',
},
+ {
+ key: 'conversation_resolved',
+ value: 'CONVERSATION_RESOLVED',
+ },
{
key: 'message_created',
value: 'MESSAGE_CREATED',
diff --git a/app/listeners/automation_rule_listener.rb b/app/listeners/automation_rule_listener.rb
index 6974e227a..0515d6952 100644
--- a/app/listeners/automation_rule_listener.rb
+++ b/app/listeners/automation_rule_listener.rb
@@ -1,53 +1,18 @@
class AutomationRuleListener < BaseListener
def conversation_updated(event)
- return if performed_by_automation?(event)
-
- conversation = event.data[:conversation]
- account = conversation.account
- changed_attributes = event.data[:changed_attributes]
-
- return unless rule_present?('conversation_updated', account)
-
- rules = current_account_rules('conversation_updated', account)
-
- rules.each do |rule|
- conditions_match = ::AutomationRules::ConditionsFilterService.new(rule, conversation, { changed_attributes: changed_attributes }).perform
- AutomationRules::ActionService.new(rule, account, conversation).perform if conditions_match.present?
- end
+ process_conversation_event(event, 'conversation_updated')
end
def conversation_created(event)
- return if performed_by_automation?(event) || ignore_auto_reply_event?(event)
-
- conversation = event.data[:conversation]
- account = conversation.account
- changed_attributes = event.data[:changed_attributes]
-
- return unless rule_present?('conversation_created', account)
-
- rules = current_account_rules('conversation_created', account)
-
- rules.each do |rule|
- conditions_match = ::AutomationRules::ConditionsFilterService.new(rule, conversation, { changed_attributes: changed_attributes }).perform
- ::AutomationRules::ActionService.new(rule, account, conversation).perform if conditions_match.present?
- end
+ process_conversation_event(event, 'conversation_created')
end
def conversation_opened(event)
- return if performed_by_automation?(event) || ignore_auto_reply_event?(event)
+ process_conversation_event(event, 'conversation_opened')
+ end
- conversation = event.data[:conversation]
- account = conversation.account
- changed_attributes = event.data[:changed_attributes]
-
- return unless rule_present?('conversation_opened', account)
-
- rules = current_account_rules('conversation_opened', account)
-
- rules.each do |rule|
- conditions_match = ::AutomationRules::ConditionsFilterService.new(rule, conversation, { changed_attributes: changed_attributes }).perform
- AutomationRules::ActionService.new(rule, account, conversation).perform if conditions_match.present?
- end
+ def conversation_resolved(event)
+ process_conversation_event(event, 'conversation_resolved')
end
def message_created(event)
@@ -69,6 +34,28 @@ class AutomationRuleListener < BaseListener
end
end
+ private
+
+ def process_conversation_event(event, event_name)
+ return if performed_by_automation?(event)
+
+ auto_reply_skip_events = %w[conversation_created conversation_opened]
+ return if auto_reply_skip_events.include?(event_name) && ignore_auto_reply_event?(event)
+
+ conversation = event.data[:conversation]
+ account = conversation.account
+ changed_attributes = event.data[:changed_attributes]
+
+ return unless rule_present?(event_name, account)
+
+ rules = current_account_rules(event_name, account)
+
+ rules.each do |rule|
+ conditions_match = ::AutomationRules::ConditionsFilterService.new(rule, conversation, { changed_attributes: changed_attributes }).perform
+ AutomationRules::ActionService.new(rule, account, conversation).perform if conditions_match.present?
+ end
+ end
+
def rule_present?(event_name, account)
return if account.blank?
diff --git a/spec/listeners/automation_rule_listener_spec.rb b/spec/listeners/automation_rule_listener_spec.rb
index e1c365f94..57a096a10 100644
--- a/spec/listeners/automation_rule_listener_spec.rb
+++ b/spec/listeners/automation_rule_listener_spec.rb
@@ -130,6 +130,42 @@ describe AutomationRuleListener do
end
end
+ describe 'conversation_resolved' do
+ let!(:automation_rule) { create(:automation_rule, event_name: 'conversation_resolved', account: account) }
+ let(:event) do
+ Events::Base.new('conversation_resolved', Time.zone.now, { conversation: conversation,
+ changed_attributes: { status: %w[Snoozed Open] } })
+ end
+
+ context 'when matching rules are present' do
+ it 'calls AutomationRules::ActionService if conditions match' do
+ allow(condition_match).to receive(:present?).and_return(true)
+ listener.conversation_resolved(event)
+ expect(AutomationRules::ActionService).to have_received(:new).with(automation_rule, account, conversation)
+ end
+
+ it 'does not call AutomationRules::ActionService if conditions do not match' do
+ allow(condition_match).to receive(:present?).and_return(false)
+ listener.conversation_resolved(event)
+ expect(AutomationRules::ActionService).not_to have_received(:new).with(automation_rule, account, conversation)
+ end
+
+ it 'calls AutomationRules::ActionService for each rule when multiple rules are present' do
+ create(:automation_rule, event_name: 'conversation_resolved', account: account)
+ allow(condition_match).to receive(:present?).and_return(true)
+ listener.conversation_resolved(event)
+ expect(AutomationRules::ActionService).to have_received(:new).twice
+ end
+
+ it 'does not call AutomationRules::ActionService if performed by automation' do
+ event.data[:performed_by] = automation_rule
+ allow(condition_match).to receive(:present?).and_return(true)
+ listener.conversation_resolved(event)
+ expect(AutomationRules::ActionService).not_to have_received(:new).with(automation_rule, account, conversation)
+ end
+ end
+ end
+
describe 'message_created' do
let!(:automation_rule) { create(:automation_rule, event_name: 'message_created', account: account) }
let!(:message) { create(:message, account: account, conversation: conversation) }
diff --git a/swagger/definitions/request/automation_rule/create_update_payload.yml b/swagger/definitions/request/automation_rule/create_update_payload.yml
index 091fa2aaa..75aedd41b 100644
--- a/swagger/definitions/request/automation_rule/create_update_payload.yml
+++ b/swagger/definitions/request/automation_rule/create_update_payload.yml
@@ -13,6 +13,7 @@ properties:
enum:
- conversation_created
- conversation_updated
+ - conversation_resolved
- message_created
example: message_created
description: The event when you want to execute the automation actions
diff --git a/swagger/definitions/resource/automation_rule.yml b/swagger/definitions/resource/automation_rule.yml
index b561441ff..ad96c58ff 100644
--- a/swagger/definitions/resource/automation_rule.yml
+++ b/swagger/definitions/resource/automation_rule.yml
@@ -10,4 +10,4 @@ properties:
- type: object
description: Single automation rule (for show/create/update endpoints)
allOf:
- - $ref: '#/components/schemas/automation_rule_item'
\ No newline at end of file
+ - $ref: '#/components/schemas/automation_rule_item'
diff --git a/swagger/swagger.json b/swagger/swagger.json
index 8da8e2c5b..aa7455e7f 100644
--- a/swagger/swagger.json
+++ b/swagger/swagger.json
@@ -10610,6 +10610,7 @@
"enum": [
"conversation_created",
"conversation_updated",
+ "conversation_resolved",
"message_created"
],
"example": "message_created",
diff --git a/swagger/tag_groups/application_swagger.json b/swagger/tag_groups/application_swagger.json
index 23a9ab0b2..a36443f81 100644
--- a/swagger/tag_groups/application_swagger.json
+++ b/swagger/tag_groups/application_swagger.json
@@ -8971,6 +8971,7 @@
"enum": [
"conversation_created",
"conversation_updated",
+ "conversation_resolved",
"message_created"
],
"example": "message_created",
diff --git a/swagger/tag_groups/client_swagger.json b/swagger/tag_groups/client_swagger.json
index 6bbae4fb2..16c1d5bc7 100644
--- a/swagger/tag_groups/client_swagger.json
+++ b/swagger/tag_groups/client_swagger.json
@@ -3594,6 +3594,7 @@
"enum": [
"conversation_created",
"conversation_updated",
+ "conversation_resolved",
"message_created"
],
"example": "message_created",
diff --git a/swagger/tag_groups/other_swagger.json b/swagger/tag_groups/other_swagger.json
index 414a44e63..c8a5294d3 100644
--- a/swagger/tag_groups/other_swagger.json
+++ b/swagger/tag_groups/other_swagger.json
@@ -3009,6 +3009,7 @@
"enum": [
"conversation_created",
"conversation_updated",
+ "conversation_resolved",
"message_created"
],
"example": "message_created",
diff --git a/swagger/tag_groups/platform_swagger.json b/swagger/tag_groups/platform_swagger.json
index 215fcd38b..f816b8c94 100644
--- a/swagger/tag_groups/platform_swagger.json
+++ b/swagger/tag_groups/platform_swagger.json
@@ -3770,6 +3770,7 @@
"enum": [
"conversation_created",
"conversation_updated",
+ "conversation_resolved",
"message_created"
],
"example": "message_created",
From ee9f1d7adb1939442880c6e9faf5534d38452d29 Mon Sep 17 00:00:00 2001
From: Muhsin Keloth
Date: Wed, 13 Aug 2025 13:32:22 +0530
Subject: [PATCH 11/26] chore: Handle WebPush rate limiting in push
notification service (#12184)
Implemented a rescue block for WebPush::TooManyRequests that logs
warnings during rate limiting events. This captures user email and
account ID for better traceability. We will implement a proper
throttling mechanism after identifying patterns across accounts.
---
.../notification/push_notification_service.rb | 23 +++++++++++++------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/app/services/notification/push_notification_service.rb b/app/services/notification/push_notification_service.rb
index 9878107c1..125ad9113 100644
--- a/app/services/notification/push_notification_service.rb
+++ b/app/services/notification/push_notification_service.rb
@@ -68,14 +68,23 @@ class Notification::PushNotificationService
WebPush.payload_send(**browser_push_payload(subscription))
Rails.logger.info("Browser push sent to #{user.email} with title #{push_message[:title]}")
- rescue WebPush::ExpiredSubscription, WebPush::InvalidSubscription, WebPush::Unauthorized => e
- Rails.logger.info "WebPush subscription expired: #{e.message}"
- subscription.destroy!
- rescue Errno::ECONNRESET, Net::OpenTimeout, Net::ReadTimeout => e
- Rails.logger.error "WebPush operation error: #{e.message}"
rescue StandardError => e
- ChatwootExceptionTracker.new(e, account: notification.account).capture_exception
- true
+ handle_browser_push_error(e, subscription)
+ end
+
+ def handle_browser_push_error(error, subscription)
+ case error
+ when WebPush::ExpiredSubscription, WebPush::InvalidSubscription, WebPush::Unauthorized
+ Rails.logger.info "WebPush subscription expired: #{error.message}"
+ subscription.destroy!
+ when WebPush::TooManyRequests
+ Rails.logger.warn "WebPush rate limited for #{user.email} on account #{notification.account.id}: #{error.message}"
+ when Errno::ECONNRESET, Net::OpenTimeout, Net::ReadTimeout
+ Rails.logger.error "WebPush operation error: #{error.message}"
+ else
+ ChatwootExceptionTracker.new(error, account: notification.account).capture_exception
+ true
+ end
end
def send_fcm_push(subscription)
From a88fef2e1d273086f9cc9d6b6d7c525e4eb5b065 Mon Sep 17 00:00:00 2001
From: Shivam Mishra
Date: Wed, 13 Aug 2025 16:39:43 +0530
Subject: [PATCH 12/26] fix: incorrect first response time for reopened
conversations (#12058)
Co-authored-by: Muhsin Keloth
---
app/helpers/reporting_event_helper.rb | 23 ++-
app/listeners/reporting_event_listener.rb | 39 ++++
spec/helpers/reporting_event_helper_spec.rb | 177 ++++++++++++++++++
.../reporting_event_listener_spec.rb | 173 +++++++++++++++++
4 files changed, 407 insertions(+), 5 deletions(-)
create mode 100644 spec/helpers/reporting_event_helper_spec.rb
diff --git a/app/helpers/reporting_event_helper.rb b/app/helpers/reporting_event_helper.rb
index e08b5691c..f0a419cc8 100644
--- a/app/helpers/reporting_event_helper.rb
+++ b/app/helpers/reporting_event_helper.rb
@@ -18,12 +18,25 @@ module ReportingEventHelper
end
def last_non_human_activity(conversation)
- # check if a handoff event already exists
- handoff_event = ReportingEvent.where(conversation_id: conversation.id, name: 'conversation_bot_handoff').last
+ # Try to get either a handoff or reopened event first
+ # These will always take precedence over any other activity
+ # Also, any of these events can happen at any time in the course of a conversation lifecycle.
+ # So we pick the latest event
+ event = ReportingEvent.where(
+ conversation_id: conversation.id,
+ name: %w[conversation_bot_handoff conversation_opened]
+ ).order(event_end_time: :desc).first
- # if a handoff exists, last non human activity is when the handoff ended,
- # otherwise it's when the conversation was created
- handoff_event&.event_end_time || conversation.created_at
+ return event.event_end_time if event&.event_end_time
+
+ # Fallback to bot resolved event
+ # Because this will be closest to the most accurate activity instead of conversation.created_at
+ bot_event = ReportingEvent.where(conversation_id: conversation.id, name: 'conversation_bot_resolved').last
+
+ return bot_event.event_end_time if bot_event&.event_end_time
+
+ # If no events found, return conversation creation time
+ conversation.created_at
end
private
diff --git a/app/listeners/reporting_event_listener.rb b/app/listeners/reporting_event_listener.rb
index 9f22fe8de..9f683a97f 100644
--- a/app/listeners/reporting_event_listener.rb
+++ b/app/listeners/reporting_event_listener.rb
@@ -90,8 +90,47 @@ class ReportingEventListener < BaseListener
reporting_event.save!
end
+ def conversation_opened(event)
+ conversation = extract_conversation_and_account(event)[0]
+
+ # Find the most recent resolved event for this conversation
+ last_resolved_event = ReportingEvent.where(
+ conversation_id: conversation.id,
+ name: 'conversation_resolved'
+ ).order(event_end_time: :desc).first
+
+ # For first-time openings, value is 0
+ # For reopenings, calculate time since resolution
+ if last_resolved_event
+ time_since_resolved = conversation.updated_at.to_i - last_resolved_event.event_end_time.to_i
+ business_hours_value = business_hours(conversation.inbox, last_resolved_event.event_end_time, conversation.updated_at)
+ start_time = last_resolved_event.event_end_time
+ else
+ time_since_resolved = 0
+ business_hours_value = 0
+ start_time = conversation.created_at
+ end
+
+ create_conversation_opened_event(conversation, time_since_resolved, business_hours_value, start_time)
+ end
+
private
+ def create_conversation_opened_event(conversation, time_since_resolved, business_hours_value, start_time)
+ reporting_event = ReportingEvent.new(
+ name: 'conversation_opened',
+ value: time_since_resolved,
+ value_in_business_hours: business_hours_value,
+ account_id: conversation.account_id,
+ inbox_id: conversation.inbox_id,
+ user_id: conversation.assignee_id,
+ conversation_id: conversation.id,
+ event_start_time: start_time,
+ event_end_time: conversation.updated_at
+ )
+ reporting_event.save!
+ end
+
def create_bot_resolved_event(conversation, reporting_event)
return unless conversation.inbox.active_bot?
# We don't want to create a bot_resolved event if there is user interaction on the conversation
diff --git a/spec/helpers/reporting_event_helper_spec.rb b/spec/helpers/reporting_event_helper_spec.rb
new file mode 100644
index 000000000..e4a3c0255
--- /dev/null
+++ b/spec/helpers/reporting_event_helper_spec.rb
@@ -0,0 +1,177 @@
+require 'rails_helper'
+
+RSpec.describe ReportingEventHelper, type: :helper do
+ describe '#last_non_human_activity' do
+ let(:account) { create(:account) }
+ let(:inbox) { create(:inbox, account: account) }
+ let(:user) { create(:user, account: account) }
+ let(:conversation) { create(:conversation, account: account, inbox: inbox, assignee: user) }
+
+ context 'when conversation has no events' do
+ it 'returns conversation created_at' do
+ expect(helper.last_non_human_activity(conversation)).to eq(conversation.created_at)
+ end
+ end
+
+ context 'when conversation has bot handoff event' do
+ let!(:handoff_event) do
+ create(:reporting_event,
+ name: 'conversation_bot_handoff',
+ conversation_id: conversation.id,
+ account_id: account.id,
+ inbox_id: inbox.id,
+ event_end_time: 2.hours.ago)
+ end
+
+ it 'returns handoff event end time' do
+ expect(helper.last_non_human_activity(conversation).to_i).to eq(handoff_event.event_end_time.to_i)
+ end
+ end
+
+ context 'when conversation has bot resolved event' do
+ let!(:bot_resolved_event) do
+ create(:reporting_event,
+ name: 'conversation_bot_resolved',
+ conversation_id: conversation.id,
+ account_id: account.id,
+ inbox_id: inbox.id,
+ event_end_time: 3.hours.ago)
+ end
+
+ it 'returns bot resolved event end time' do
+ expect(helper.last_non_human_activity(conversation).to_i).to eq(bot_resolved_event.event_end_time.to_i)
+ end
+ end
+
+ context 'when conversation is reopened after bot resolution' do
+ let(:creation_time) { 5.days.ago }
+ let(:bot_resolution_time) { 5.days.ago + 5.minutes }
+ let(:reopening_time) { 1.hour.ago }
+
+ let!(:conversation) do
+ create(:conversation,
+ account: account,
+ inbox: inbox,
+ assignee: user,
+ created_at: creation_time)
+ end
+
+ before do
+ # First opened event
+ create(:reporting_event,
+ name: 'conversation_opened',
+ conversation_id: conversation.id,
+ account_id: account.id,
+ inbox_id: inbox.id,
+ value: 0,
+ event_start_time: creation_time,
+ event_end_time: creation_time)
+
+ # Bot resolved event
+ create(:reporting_event,
+ name: 'conversation_bot_resolved',
+ conversation_id: conversation.id,
+ account_id: account.id,
+ inbox_id: inbox.id,
+ event_start_time: creation_time,
+ event_end_time: bot_resolution_time)
+
+ # Resolved event
+ create(:reporting_event,
+ name: 'conversation_resolved',
+ conversation_id: conversation.id,
+ account_id: account.id,
+ inbox_id: inbox.id,
+ event_start_time: creation_time,
+ event_end_time: bot_resolution_time)
+
+ # Reopened event
+ create(:reporting_event,
+ name: 'conversation_opened',
+ conversation_id: conversation.id,
+ account_id: account.id,
+ inbox_id: inbox.id,
+ value: (reopening_time - bot_resolution_time).to_i,
+ event_start_time: bot_resolution_time,
+ event_end_time: reopening_time)
+ end
+
+ it 'returns the reopening event time, not the creation time' do
+ # This is the key test: last_non_human_activity should return the reopening time
+ # so that first response time is calculated from when the conversation was reopened,
+ # not from when it was originally created
+ expect(helper.last_non_human_activity(conversation).to_i).to eq(reopening_time.to_i)
+
+ # Verify it's not returning the creation time or bot resolution time
+ expect(helper.last_non_human_activity(conversation).to_i).not_to eq(creation_time.to_i)
+ expect(helper.last_non_human_activity(conversation).to_i).not_to eq(bot_resolution_time.to_i)
+ end
+ end
+
+ context 'when conversation has multiple types of events' do
+ let(:opened_event_time) { 1.hour.ago }
+
+ before do
+ create(:reporting_event,
+ name: 'conversation_bot_resolved',
+ conversation_id: conversation.id,
+ account_id: account.id,
+ inbox_id: inbox.id,
+ event_end_time: 4.hours.ago)
+
+ create(:reporting_event,
+ name: 'conversation_bot_handoff',
+ conversation_id: conversation.id,
+ account_id: account.id,
+ inbox_id: inbox.id,
+ event_end_time: 3.hours.ago)
+
+ create(:reporting_event,
+ name: 'conversation_opened',
+ conversation_id: conversation.id,
+ account_id: account.id,
+ inbox_id: inbox.id,
+ event_end_time: opened_event_time)
+ end
+
+ it 'returns the most recent handoff or opened event' do
+ # opened_event is more recent than handoff_event
+ expect(helper.last_non_human_activity(conversation).to_i).to eq(opened_event_time.to_i)
+ end
+ end
+
+ context 'when conversation has multiple reopenings' do
+ let(:third_opened_time) { 30.minutes.ago }
+
+ before do
+ create(:reporting_event,
+ name: 'conversation_opened',
+ conversation_id: conversation.id,
+ account_id: account.id,
+ inbox_id: inbox.id,
+ value: 0,
+ event_end_time: 5.days.ago)
+
+ create(:reporting_event,
+ name: 'conversation_opened',
+ conversation_id: conversation.id,
+ account_id: account.id,
+ inbox_id: inbox.id,
+ value: 3600,
+ event_end_time: 2.days.ago)
+
+ create(:reporting_event,
+ name: 'conversation_opened',
+ conversation_id: conversation.id,
+ account_id: account.id,
+ inbox_id: inbox.id,
+ value: 7200,
+ event_end_time: third_opened_time)
+ end
+
+ it 'returns the most recent opened event' do
+ expect(helper.last_non_human_activity(conversation).to_i).to eq(third_opened_time.to_i)
+ end
+ end
+ end
+end
diff --git a/spec/listeners/reporting_event_listener_spec.rb b/spec/listeners/reporting_event_listener_spec.rb
index 0edf79556..8004349bf 100644
--- a/spec/listeners/reporting_event_listener_spec.rb
+++ b/spec/listeners/reporting_event_listener_spec.rb
@@ -267,4 +267,177 @@ describe ReportingEventListener do
end
end
end
+
+ describe '#conversation_opened' do
+ context 'when conversation is opened for the first time' do
+ let(:new_conversation) { create(:conversation, account: account, inbox: inbox, assignee: user) }
+
+ it 'creates conversation_opened event with value 0' do
+ expect(account.reporting_events.where(name: 'conversation_opened').count).to be 0
+ event = Events::Base.new('conversation.opened', Time.zone.now, conversation: new_conversation)
+ listener.conversation_opened(event)
+ expect(account.reporting_events.where(name: 'conversation_opened').count).to be 1
+
+ opened_event = account.reporting_events.where(name: 'conversation_opened').first
+ expect(opened_event.value).to eq 0
+ expect(opened_event.value_in_business_hours).to eq 0
+ expect(opened_event.event_start_time).to be_within(1.second).of(new_conversation.created_at)
+ expect(opened_event.event_end_time).to be_within(1.second).of(new_conversation.updated_at)
+ end
+ end
+
+ context 'when conversation is reopened after being resolved' do
+ let(:resolved_time) { 2.hours.ago }
+ let(:reopened_time) { 1.hour.ago }
+ let(:reopened_conversation) do
+ create(:conversation, account: account, inbox: inbox, assignee: user, updated_at: reopened_time)
+ end
+
+ before do
+ # Create a resolved event first
+ create(:reporting_event,
+ name: 'conversation_resolved',
+ account_id: account.id,
+ inbox_id: inbox.id,
+ conversation_id: reopened_conversation.id,
+ user_id: user.id,
+ value: 3600,
+ event_start_time: reopened_conversation.created_at,
+ event_end_time: resolved_time)
+ end
+
+ it 'creates conversation_opened event' do
+ expect(account.reporting_events.where(name: 'conversation_opened').count).to be 0
+ event = Events::Base.new('conversation.opened', reopened_time, conversation: reopened_conversation)
+ listener.conversation_opened(event)
+ expect(account.reporting_events.where(name: 'conversation_opened').count).to be 1
+ end
+
+ it 'calculates correct time since resolution' do
+ event = Events::Base.new('conversation.opened', reopened_time, conversation: reopened_conversation)
+ listener.conversation_opened(event)
+
+ reopened_event = account.reporting_events.where(name: 'conversation_opened').first
+ expect(reopened_event.value).to be_within(1).of(3600) # 1 hour = 3600 seconds
+ expect(reopened_event.event_start_time).to be_within(1.second).of(resolved_time)
+ expect(reopened_event.event_end_time).to be_within(1.second).of(reopened_time)
+ end
+
+ it 'sets correct attributes for conversation_opened event' do
+ event = Events::Base.new('conversation.opened', reopened_time, conversation: reopened_conversation)
+ listener.conversation_opened(event)
+
+ reopened_event = account.reporting_events.where(name: 'conversation_opened').first
+ expect(reopened_event.account_id).to eq(account.id)
+ expect(reopened_event.inbox_id).to eq(inbox.id)
+ expect(reopened_event.conversation_id).to eq(reopened_conversation.id)
+ expect(reopened_event.user_id).to eq(user.id)
+ end
+
+ context 'when business hours enabled for inbox' do
+ let(:resolved_time) { Time.zone.parse('March 20, 2022 12:00') }
+ let(:reopened_time) { Time.zone.parse('March 21, 2022 14:00') }
+ let!(:business_hours_inbox) { create(:inbox, working_hours_enabled: true, account: account) }
+ let!(:business_hours_conversation) do
+ create(:conversation, account: account, inbox: business_hours_inbox, assignee: user, updated_at: reopened_time)
+ end
+
+ before do
+ create(:reporting_event,
+ name: 'conversation_resolved',
+ account_id: account.id,
+ inbox_id: business_hours_inbox.id,
+ conversation_id: business_hours_conversation.id,
+ user_id: user.id,
+ value: 3600,
+ event_start_time: business_hours_conversation.created_at,
+ event_end_time: resolved_time)
+ end
+
+ it 'creates conversation_opened event with business hour value' do
+ event = Events::Base.new('conversation.opened', reopened_time, conversation: business_hours_conversation)
+ listener.conversation_opened(event)
+
+ reopened_event = account.reporting_events.where(name: 'conversation_opened').first
+ expect(reopened_event.value_in_business_hours).to be 18_000.0 # 5 business hours (26 hours total - 21 non-business hours)
+ end
+ end
+ end
+
+ context 'when conversation has multiple resolutions' do
+ let(:first_resolved_time) { 3.hours.ago }
+ let(:second_resolved_time) { 1.hour.ago }
+ let(:reopened_time) { 30.minutes.ago }
+ let(:multiple_resolution_conversation) do
+ create(:conversation, account: account, inbox: inbox, assignee: user, updated_at: reopened_time)
+ end
+
+ before do
+ # Create first resolved event
+ create(:reporting_event,
+ name: 'conversation_resolved',
+ account_id: account.id,
+ inbox_id: inbox.id,
+ conversation_id: multiple_resolution_conversation.id,
+ user_id: user.id,
+ value: 3600,
+ event_start_time: multiple_resolution_conversation.created_at,
+ event_end_time: first_resolved_time)
+
+ # Create second resolved event (more recent)
+ create(:reporting_event,
+ name: 'conversation_resolved',
+ account_id: account.id,
+ inbox_id: inbox.id,
+ conversation_id: multiple_resolution_conversation.id,
+ user_id: user.id,
+ value: 1800,
+ event_start_time: first_resolved_time,
+ event_end_time: second_resolved_time)
+ end
+
+ it 'uses the most recent resolved event for calculation' do
+ event = Events::Base.new('conversation.opened', reopened_time, conversation: multiple_resolution_conversation)
+ listener.conversation_opened(event)
+
+ reopened_event = account.reporting_events.where(name: 'conversation_opened').first
+ expect(reopened_event.value).to be_within(1).of(1800) # 30 minutes from second resolution
+ expect(reopened_event.event_start_time).to be_within(1.second).of(second_resolved_time)
+ end
+ end
+
+ context 'when agent bot resolves and conversation is reopened' do
+ # This implicitly tests that the first_response time is correctly calculated
+ # By checking that a conversation reopened event is created with the correct values
+ let(:agent_bot) { create(:agent_bot, account: account) }
+ let(:agent_bot_inbox) { create(:inbox, account: account) }
+ let(:bot_resolved_time) { 2.hours.ago }
+ let(:reopened_time) { 1.hour.ago }
+ let(:bot_conversation) do
+ create(:conversation, account: account, inbox: agent_bot_inbox, assignee: user, updated_at: reopened_time)
+ end
+
+ before do
+ create(:agent_bot_inbox, agent_bot: agent_bot, inbox: agent_bot_inbox)
+
+ create(:reporting_event,
+ name: 'conversation_resolved',
+ account_id: account.id,
+ inbox_id: agent_bot_inbox.id,
+ conversation_id: bot_conversation.id,
+ user_id: user.id,
+ event_end_time: bot_resolved_time)
+ end
+
+ it 'creates conversation_opened event for agent bot reopening' do
+ event = Events::Base.new('conversation.opened', reopened_time, conversation: bot_conversation)
+ listener.conversation_opened(event)
+
+ reopened_event = account.reporting_events.where(name: 'conversation_opened').first
+ expect(reopened_event.value).to be_within(1).of(3600) # 1 hour since resolution
+ expect(reopened_event.event_start_time).to be_within(1.second).of(bot_resolved_time)
+ expect(reopened_event.event_end_time).to be_within(1.second).of(reopened_time)
+ end
+ end
+ end
end
From 6b42ff8d39bfbdfb84f433a43149552b5b8bea94 Mon Sep 17 00:00:00 2001
From: Tanmay Deep Sharma <32020192+tds-1@users.noreply.github.com>
Date: Wed, 13 Aug 2025 20:53:31 +0530
Subject: [PATCH 13/26] fix: setup webhook for create and update should be done
after db commit (#12176)
## Reference
https://github.com/chatwoot/chatwoot/pull/12149#issuecomment-3178108388
## Description
setup_webhook was done before the save, and hence the meta webhook
validation might fail because of a race condition where the facebook
validation is done before we saving the entry to the database.
## Type of change
Please delete options that are not relevant.
- [ ] Bug fix (non-breaking change which fixes an issue)
## How Has This Been Tested?
- New inbox creation, webhook validation
- Existing inbox update, webhook validation
-
## Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] 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
---
app/models/channel/whatsapp.rb | 42 +---
.../whatsapp/channel_creation_service.rb | 7 +-
.../whatsapp/embedded_signup_service.rb | 36 ++--
.../whatsapp/channel_creation_service_spec.rb | 5 +
.../whatsapp/embedded_signup_service_spec.rb | 184 +++++++++---------
.../whatsapp/webhook_setup_service_spec.rb | 89 ++++++++-
6 files changed, 223 insertions(+), 140 deletions(-)
diff --git a/app/models/channel/whatsapp.rb b/app/models/channel/whatsapp.rb
index 7471cf807..7318cd978 100644
--- a/app/models/channel/whatsapp.rb
+++ b/app/models/channel/whatsapp.rb
@@ -32,7 +32,6 @@ class Channel::Whatsapp < ApplicationRecord
validates :phone_number, presence: true, uniqueness: true
validate :validate_provider_config
- before_save :setup_webhooks
after_create :sync_templates
before_destroy :teardown_webhooks
@@ -60,6 +59,13 @@ class Channel::Whatsapp < ApplicationRecord
delegate :media_url, to: :provider_service
delegate :api_headers, to: :provider_service
+ def setup_webhooks
+ perform_webhook_setup
+ rescue StandardError => e
+ Rails.logger.error "[WHATSAPP] Webhook setup failed: #{e.message}"
+ prompt_reauthorization!
+ end
+
private
def ensure_webhook_verify_token
@@ -70,34 +76,6 @@ class Channel::Whatsapp < ApplicationRecord
errors.add(:provider_config, 'Invalid Credentials') unless provider_service.validate_provider_config?
end
- def setup_webhooks
- return unless should_setup_webhooks?
-
- perform_webhook_setup
- rescue StandardError => e
- handle_webhook_setup_error(e)
- end
-
- def provider_config_changed?
- will_save_change_to_provider_config?
- end
-
- def should_setup_webhooks?
- whatsapp_cloud_provider? && embedded_signup_source? && webhook_config_present? && provider_config_changed?
- end
-
- def whatsapp_cloud_provider?
- provider == 'whatsapp_cloud'
- end
-
- def embedded_signup_source?
- provider_config['source'] == 'embedded_signup'
- end
-
- def webhook_config_present?
- provider_config['business_account_id'].present? && provider_config['api_key'].present?
- end
-
def perform_webhook_setup
business_account_id = provider_config['business_account_id']
api_key = provider_config['api_key']
@@ -105,12 +83,6 @@ class Channel::Whatsapp < ApplicationRecord
Whatsapp::WebhookSetupService.new(self, business_account_id, api_key).perform
end
- def handle_webhook_setup_error(error)
- Rails.logger.error "[WHATSAPP] Webhook setup failed: #{error.message}"
- # Don't raise the error to prevent channel creation from failing
- # Webhooks can be retried later
- end
-
def teardown_webhooks
Whatsapp::WebhookTeardownService.new(self).perform
end
diff --git a/app/services/whatsapp/channel_creation_service.rb b/app/services/whatsapp/channel_creation_service.rb
index 3039ca003..154f55520 100644
--- a/app/services/whatsapp/channel_creation_service.rb
+++ b/app/services/whatsapp/channel_creation_service.rb
@@ -33,15 +33,14 @@ class Whatsapp::ChannelCreationService
def create_channel_with_inbox
ActiveRecord::Base.transaction do
- channel = create_channel
+ channel = build_channel
create_inbox(channel)
- channel.reload
channel
end
end
- def create_channel
- Channel::Whatsapp.create!(
+ def build_channel
+ Channel::Whatsapp.build(
account: @account,
phone_number: @phone_info[:phone_number],
provider: 'whatsapp_cloud',
diff --git a/app/services/whatsapp/embedded_signup_service.rb b/app/services/whatsapp/embedded_signup_service.rb
index e66506638..1b882b1f1 100644
--- a/app/services/whatsapp/embedded_signup_service.rb
+++ b/app/services/whatsapp/embedded_signup_service.rb
@@ -11,16 +11,34 @@ class Whatsapp::EmbeddedSignupService
def perform
validate_parameters!
- # Exchange code for user access token
- access_token = Whatsapp::TokenExchangeService.new(@code).perform
+ access_token = exchange_code_for_token
+ phone_info = fetch_phone_info(access_token)
+ validate_token_access(access_token)
- # Fetch phone information
- phone_info = Whatsapp::PhoneInfoService.new(@waba_id, @phone_number_id, access_token).perform
+ channel = create_or_reauthorize_channel(access_token, phone_info)
+ channel.setup_webhooks
+ channel
- # Validate token has access to the WABA
+ rescue StandardError => e
+ Rails.logger.error("[WHATSAPP] Embedded signup failed: #{e.message}")
+ raise e
+ end
+
+ private
+
+ def exchange_code_for_token
+ Whatsapp::TokenExchangeService.new(@code).perform
+ end
+
+ def fetch_phone_info(access_token)
+ Whatsapp::PhoneInfoService.new(@waba_id, @phone_number_id, access_token).perform
+ end
+
+ def validate_token_access(access_token)
Whatsapp::TokenValidationService.new(access_token, @waba_id).perform
+ end
- # Reauthorization flow if inbox_id is present
+ def create_or_reauthorize_channel(access_token, phone_info)
if @inbox_id.present?
Whatsapp::ReauthorizationService.new(
account: @account,
@@ -29,17 +47,11 @@ class Whatsapp::EmbeddedSignupService
business_id: @business_id
).perform(access_token, phone_info)
else
- # Create channel for new authorization
waba_info = { waba_id: @waba_id, business_name: phone_info[:business_name] }
Whatsapp::ChannelCreationService.new(@account, waba_info, phone_info, access_token).perform
end
- rescue StandardError => e
- Rails.logger.error("[WHATSAPP] Embedded signup failed: #{e.message}")
- raise e
end
- private
-
def validate_parameters!
missing_params = []
missing_params << 'code' if @code.blank?
diff --git a/spec/services/whatsapp/channel_creation_service_spec.rb b/spec/services/whatsapp/channel_creation_service_spec.rb
index 1c1f46232..403fb71b8 100644
--- a/spec/services/whatsapp/channel_creation_service_spec.rb
+++ b/spec/services/whatsapp/channel_creation_service_spec.rb
@@ -16,6 +16,11 @@ describe Whatsapp::ChannelCreationService do
describe '#perform' do
before do
+ # Stub the webhook teardown service to prevent HTTP calls during cleanup
+ teardown_service = instance_double(Whatsapp::WebhookTeardownService)
+ allow(Whatsapp::WebhookTeardownService).to receive(:new).and_return(teardown_service)
+ allow(teardown_service).to receive(:perform)
+
# Clean up any existing channels to avoid phone number conflicts
Channel::Whatsapp.destroy_all
diff --git a/spec/services/whatsapp/embedded_signup_service_spec.rb b/spec/services/whatsapp/embedded_signup_service_spec.rb
index 12a4d32df..1db94928e 100644
--- a/spec/services/whatsapp/embedded_signup_service_spec.rb
+++ b/spec/services/whatsapp/embedded_signup_service_spec.rb
@@ -10,121 +10,100 @@ describe Whatsapp::EmbeddedSignupService do
phone_number_id: 'test_phone_number_id'
}
end
- let(:service) do
- described_class.new(
- account: account,
- params: params
- )
+ let(:service) { described_class.new(account: account, params: params) }
+ let(:access_token) { 'test_access_token' }
+ let(:phone_info) do
+ {
+ phone_number_id: params[:phone_number_id],
+ phone_number: '+1234567890',
+ verified: true,
+ business_name: 'Test Business'
+ }
end
+ let(:channel) { instance_double(Channel::Whatsapp) }
describe '#perform' do
- let(:access_token) { 'test_access_token' }
- let(:phone_info) do
- {
- phone_number_id: params[:phone_number_id],
- phone_number: '+1234567890',
- verified: true,
- business_name: 'Test Business'
- }
- end
- let(:channel) { instance_double(Channel::Whatsapp) }
- let(:service_doubles) do
- {
- token_exchange: instance_double(Whatsapp::TokenExchangeService),
- phone_info: instance_double(Whatsapp::PhoneInfoService),
- token_validation: instance_double(Whatsapp::TokenValidationService),
- channel_creation: instance_double(Whatsapp::ChannelCreationService)
- }
- end
-
before do
allow(GlobalConfig).to receive(:clear_cache)
- allow(Whatsapp::TokenExchangeService).to receive(:new).with(params[:code]).and_return(service_doubles[:token_exchange])
- allow(service_doubles[:token_exchange]).to receive(:perform).and_return(access_token)
+ # Mock service dependencies
+ token_exchange = instance_double(Whatsapp::TokenExchangeService)
+ allow(Whatsapp::TokenExchangeService).to receive(:new).with(params[:code]).and_return(token_exchange)
+ allow(token_exchange).to receive(:perform).and_return(access_token)
+ phone_service = instance_double(Whatsapp::PhoneInfoService)
allow(Whatsapp::PhoneInfoService).to receive(:new)
- .with(params[:waba_id], params[:phone_number_id], access_token).and_return(service_doubles[:phone_info])
- allow(service_doubles[:phone_info]).to receive(:perform).and_return(phone_info)
+ .with(params[:waba_id], params[:phone_number_id], access_token).and_return(phone_service)
+ allow(phone_service).to receive(:perform).and_return(phone_info)
+ validation_service = instance_double(Whatsapp::TokenValidationService)
allow(Whatsapp::TokenValidationService).to receive(:new)
- .with(access_token, params[:waba_id]).and_return(service_doubles[:token_validation])
- allow(service_doubles[:token_validation]).to receive(:perform)
+ .with(access_token, params[:waba_id]).and_return(validation_service)
+ allow(validation_service).to receive(:perform)
+ channel_creation = instance_double(Whatsapp::ChannelCreationService)
allow(Whatsapp::ChannelCreationService).to receive(:new)
.with(account, { waba_id: params[:waba_id], business_name: 'Test Business' }, phone_info, access_token)
- .and_return(service_doubles[:channel_creation])
- allow(service_doubles[:channel_creation]).to receive(:perform).and_return(channel)
+ .and_return(channel_creation)
+ allow(channel_creation).to receive(:perform).and_return(channel)
- # Webhook setup is now handled in the channel after_create callback
- # So we stub it at the model level
- webhook_service = instance_double(Whatsapp::WebhookSetupService)
- allow(Whatsapp::WebhookSetupService).to receive(:new).and_return(webhook_service)
- allow(webhook_service).to receive(:perform)
+ allow(channel).to receive(:setup_webhooks)
end
- it 'orchestrates all services in the correct order' do
- expect(service_doubles[:token_exchange]).to receive(:perform).ordered
- expect(service_doubles[:phone_info]).to receive(:perform).ordered
- expect(service_doubles[:token_validation]).to receive(:perform).ordered
- expect(service_doubles[:channel_creation]).to receive(:perform).ordered
+ it 'creates channel and sets up webhooks' do
+ expect(channel).to receive(:setup_webhooks)
result = service.perform
expect(result).to eq(channel)
end
- context 'when required parameters are missing' do
- it 'raises error when code is blank' do
- service = described_class.new(
- account: account,
- params: params.merge(code: '')
- )
- expect { service.perform }.to raise_error(ArgumentError, /Required parameters are missing: code/)
- end
-
- it 'raises error when business_id is blank' do
- service = described_class.new(
- account: account,
- params: params.merge(business_id: '')
- )
- expect { service.perform }.to raise_error(ArgumentError, /Required parameters are missing: business_id/)
- end
-
- it 'raises error when waba_id is blank' do
- service = described_class.new(
- account: account,
- params: params.merge(waba_id: '')
- )
- expect { service.perform }.to raise_error(ArgumentError, /Required parameters are missing: waba_id/)
- end
-
- it 'raises error when multiple parameters are blank' do
- service = described_class.new(
- account: account,
- params: params.merge(code: '', business_id: '')
- )
- expect { service.perform }.to raise_error(ArgumentError, /Required parameters are missing: code, business_id/)
+ context 'when parameters are invalid' do
+ it 'raises ArgumentError for missing parameters' do
+ invalid_service = described_class.new(account: account, params: { code: '', business_id: '', waba_id: '' })
+ expect { invalid_service.perform }.to raise_error(ArgumentError, /Required parameters are missing/)
end
end
- context 'when any service fails' do
- it 'logs and re-raises the error' do
- allow(service_doubles[:token_exchange]).to receive(:perform).and_raise('Token error')
+ context 'when service fails' do
+ it 'logs and re-raises errors' do
+ token_exchange = instance_double(Whatsapp::TokenExchangeService)
+ allow(Whatsapp::TokenExchangeService).to receive(:new).and_return(token_exchange)
+ allow(token_exchange).to receive(:perform).and_raise('Token error')
expect(Rails.logger).to receive(:error).with('[WHATSAPP] Embedded signup failed: Token error')
expect { service.perform }.to raise_error('Token error')
end
+
+ it 'prompts reauthorization when webhook setup fails' do
+ # Create a real channel to test the actual webhook failure behavior
+ real_channel = create(:channel_whatsapp, account: account, phone_number: '+1234567890',
+ validate_provider_config: false, sync_templates: false)
+
+ # Mock the channel creation to return our real channel
+ channel_creation = instance_double(Whatsapp::ChannelCreationService)
+ allow(Whatsapp::ChannelCreationService).to receive(:new).and_return(channel_creation)
+ allow(channel_creation).to receive(:perform).and_return(real_channel)
+
+ # Mock webhook setup to fail
+ allow(real_channel).to receive(:perform_webhook_setup).and_raise('Webhook setup error')
+
+ # Verify channel is not marked for reauthorization initially
+ expect(real_channel.reauthorization_required?).to be false
+
+ # The service completes successfully even if webhook fails (webhook error is rescued in setup_webhooks)
+ result = service.perform
+ expect(result).to eq(real_channel)
+
+ # Verify the channel is now marked for reauthorization
+ expect(real_channel.reauthorization_required?).to be true
+ end
end
- context 'when inbox_id is provided (reauthorization flow)' do
+ context 'with reauthorization flow' do
let(:inbox_id) { 123 }
let(:reauth_service) { instance_double(Whatsapp::ReauthorizationService) }
let(:service_with_inbox) do
- described_class.new(
- account: account,
- params: params,
- inbox_id: inbox_id
- )
+ described_class.new(account: account, params: params, inbox_id: inbox_id)
end
before do
@@ -137,16 +116,45 @@ describe Whatsapp::EmbeddedSignupService do
allow(reauth_service).to receive(:perform).with(access_token, phone_info).and_return(channel)
end
- it 'uses ReauthorizationService instead of ChannelCreationService' do
- expect(service_doubles[:token_exchange]).to receive(:perform).ordered
- expect(service_doubles[:phone_info]).to receive(:perform).ordered
- expect(service_doubles[:token_validation]).to receive(:perform).ordered
- expect(reauth_service).to receive(:perform).with(access_token, phone_info).ordered
- expect(service_doubles[:channel_creation]).not_to receive(:perform)
+ it 'uses ReauthorizationService and sets up webhooks' do
+ expect(reauth_service).to receive(:perform)
+ expect(channel).to receive(:setup_webhooks)
result = service_with_inbox.perform
expect(result).to eq(channel)
end
+
+ it 'clears reauthorization flag' do
+ inbox = create(:inbox, account: account)
+ whatsapp_channel = create(:channel_whatsapp, account: account, phone_number: '+1234567890',
+ validate_provider_config: false, sync_templates: false)
+ inbox.update!(channel: whatsapp_channel)
+ whatsapp_channel.prompt_reauthorization!
+
+ service_with_real_inbox = described_class.new(account: account, params: params, inbox_id: inbox.id)
+
+ # Mock the ReauthorizationService to return our test channel
+ reauth_service = instance_double(Whatsapp::ReauthorizationService)
+ allow(Whatsapp::ReauthorizationService).to receive(:new).with(
+ account: account,
+ inbox_id: inbox.id,
+ phone_number_id: params[:phone_number_id],
+ business_id: params[:business_id]
+ ).and_return(reauth_service)
+
+ # Perform the reauthorization and clear the flag
+ allow(reauth_service).to receive(:perform) do
+ whatsapp_channel.reauthorized!
+ whatsapp_channel
+ end
+
+ allow(whatsapp_channel).to receive(:setup_webhooks).and_return(true)
+
+ expect(whatsapp_channel.reauthorization_required?).to be true
+ result = service_with_real_inbox.perform
+ expect(result).to eq(whatsapp_channel)
+ expect(whatsapp_channel.reauthorization_required?).to be false
+ end
end
end
end
diff --git a/spec/services/whatsapp/webhook_setup_service_spec.rb b/spec/services/whatsapp/webhook_setup_service_spec.rb
index 7cee115c2..e6a246e5d 100644
--- a/spec/services/whatsapp/webhook_setup_service_spec.rb
+++ b/spec/services/whatsapp/webhook_setup_service_spec.rb
@@ -5,7 +5,7 @@ describe Whatsapp::WebhookSetupService do
create(:channel_whatsapp,
phone_number: '+1234567890',
provider_config: {
- 'phone_number_id' => 'test_phone_id',
+ 'phone_number_id' => '123456789',
'webhook_verify_token' => 'test_verify_token'
},
provider: 'whatsapp_cloud',
@@ -18,9 +18,14 @@ describe Whatsapp::WebhookSetupService do
let(:api_client) { instance_double(Whatsapp::FacebookApiClient) }
before do
+ # Stub webhook teardown to prevent HTTP calls during cleanup
+ stub_request(:delete, /graph.facebook.com/).to_return(status: 200, body: '{}', headers: {})
+
# Clean up any existing channels to avoid phone number conflicts
Channel::Whatsapp.destroy_all
allow(Whatsapp::FacebookApiClient).to receive(:new).and_return(api_client)
+ # Default stub for phone_number_verified? with any argument
+ allow(api_client).to receive(:phone_number_verified?).and_return(false)
end
describe '#perform' do
@@ -148,5 +153,87 @@ describe Whatsapp::WebhookSetupService do
end
end
end
+
+ context 'when webhook setup fails and should trigger reauthorization' do
+ before do
+ allow(api_client).to receive(:phone_number_verified?).with('123456789').and_return(true)
+ allow(api_client).to receive(:subscribe_waba_webhook).and_raise('Invalid access token')
+ end
+
+ it 'raises error with webhook setup failure message' do
+ with_modified_env FRONTEND_URL: 'https://app.chatwoot.com' do
+ expect { service.perform }.to raise_error(/Webhook setup failed: Invalid access token/)
+ end
+ end
+
+ it 'logs the webhook setup failure' do
+ with_modified_env FRONTEND_URL: 'https://app.chatwoot.com' do
+ expect(Rails.logger).to receive(:error).with('[WHATSAPP] Webhook setup failed: Invalid access token')
+ expect { service.perform }.to raise_error(/Webhook setup failed/)
+ end
+ end
+ end
+
+ context 'when used during reauthorization flow' do
+ let(:existing_channel) do
+ create(:channel_whatsapp,
+ phone_number: '+1234567890',
+ provider_config: {
+ 'phone_number_id' => '123456789',
+ 'webhook_verify_token' => 'existing_verify_token',
+ 'business_id' => 'existing_business_id',
+ 'waba_id' => 'existing_waba_id'
+ },
+ provider: 'whatsapp_cloud',
+ sync_templates: false,
+ validate_provider_config: false)
+ end
+ let(:new_access_token) { 'new_access_token' }
+ let(:service_reauth) { described_class.new(existing_channel, waba_id, new_access_token) }
+
+ before do
+ allow(api_client).to receive(:phone_number_verified?).with('123456789').and_return(true)
+ allow(api_client).to receive(:subscribe_waba_webhook)
+ .with(waba_id, anything, 'existing_verify_token').and_return({ 'success' => true })
+ end
+
+ it 'successfully reauthorizes with new access token' do
+ with_modified_env FRONTEND_URL: 'https://app.chatwoot.com' do
+ expect(api_client).not_to receive(:register_phone_number)
+ expect(api_client).to receive(:subscribe_waba_webhook)
+ .with(waba_id, 'https://app.chatwoot.com/webhooks/whatsapp/+1234567890', 'existing_verify_token')
+ service_reauth.perform
+ end
+ end
+
+ it 'uses the existing webhook verify token during reauthorization' do
+ with_modified_env FRONTEND_URL: 'https://app.chatwoot.com' do
+ expect(api_client).to receive(:subscribe_waba_webhook)
+ .with(waba_id, anything, 'existing_verify_token')
+ service_reauth.perform
+ end
+ end
+ end
+
+ context 'when webhook setup is successful in creation flow' do
+ before do
+ allow(api_client).to receive(:phone_number_verified?).with('123456789').and_return(true)
+ allow(api_client).to receive(:subscribe_waba_webhook)
+ .with(waba_id, anything, 'test_verify_token').and_return({ 'success' => true })
+ end
+
+ it 'completes successfully without errors' do
+ with_modified_env FRONTEND_URL: 'https://app.chatwoot.com' do
+ expect { service.perform }.not_to raise_error
+ end
+ end
+
+ it 'does not log any errors' do
+ with_modified_env FRONTEND_URL: 'https://app.chatwoot.com' do
+ expect(Rails.logger).not_to receive(:error)
+ service.perform
+ end
+ end
+ end
end
end
From 14471cc20c70c027b7d4078299b6bab0834ce7f3 Mon Sep 17 00:00:00 2001
From: Pranav
Date: Wed, 13 Aug 2025 10:23:25 -0700
Subject: [PATCH 14/26] chore: Add bulgarian (bg) language (#12189)
Add bg to supported langauges
---
app/javascript/dashboard/i18n/index.js | 2 ++
app/javascript/survey/i18n/index.js | 2 ++
app/javascript/widget/i18n/index.js | 2 ++
config/initializers/languages.rb | 3 ++-
4 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/app/javascript/dashboard/i18n/index.js b/app/javascript/dashboard/i18n/index.js
index d0e85b43a..17bfab34d 100644
--- a/app/javascript/dashboard/i18n/index.js
+++ b/app/javascript/dashboard/i18n/index.js
@@ -1,4 +1,5 @@
import ar from './locale/ar';
+import bg from './locale/bg';
import ca from './locale/ca';
import cs from './locale/cs';
import da from './locale/da';
@@ -40,6 +41,7 @@ import lt from './locale/lt';
export default {
ar,
+ bg,
ca,
cs,
da,
diff --git a/app/javascript/survey/i18n/index.js b/app/javascript/survey/i18n/index.js
index 372017c5e..1a9ea1a59 100644
--- a/app/javascript/survey/i18n/index.js
+++ b/app/javascript/survey/i18n/index.js
@@ -1,4 +1,5 @@
import ar from './locale/ar.json';
+import bg from './locale/bg.json';
import ca from './locale/ca.json';
import cs from './locale/cs.json';
import da from './locale/da.json';
@@ -40,6 +41,7 @@ import zh_TW from './locale/zh_TW.json';
export default {
ar,
+ bg,
ca,
cs,
da,
diff --git a/app/javascript/widget/i18n/index.js b/app/javascript/widget/i18n/index.js
index 8e602a4b5..93a371391 100644
--- a/app/javascript/widget/i18n/index.js
+++ b/app/javascript/widget/i18n/index.js
@@ -1,4 +1,5 @@
import ar from './locale/ar.json';
+import bg from './locale/bg.json';
import ca from './locale/ca.json';
import cs from './locale/cs.json';
import da from './locale/da.json';
@@ -40,6 +41,7 @@ import zh_TW from './locale/zh_TW.json';
export default {
ar,
+ bg,
ca,
cs,
da,
diff --git a/config/initializers/languages.rb b/config/initializers/languages.rb
index 899359a4c..c34f7a605 100644
--- a/config/initializers/languages.rb
+++ b/config/initializers/languages.rb
@@ -41,7 +41,8 @@ LANGUAGES_CONFIG = {
36 => { name: 'íslenska (is)', iso_639_3_code: 'isl', iso_639_1_code: 'is', enabled: true },
37 => { name: 'עִברִית (he)', iso_639_3_code: 'heb', iso_639_1_code: 'he', enabled: true },
38 => { name: 'lietuvių (lt)', iso_639_3_code: 'lit', iso_639_1_code: 'lt', enabled: true },
- 39 => { name: 'Српски (sr)', iso_639_3_code: 'srp', iso_639_1_code: 'sr', enabled: true }
+ 39 => { name: 'Српски (sr)', iso_639_3_code: 'srp', iso_639_1_code: 'sr', enabled: true },
+ 40 => { name: 'български (bg)', iso_639_3_code: 'bul', iso_639_1_code: 'bg', enabled: true }
}.filter { |_key, val| val[:enabled] }.freeze
Rails.configuration.i18n.available_locales = LANGUAGES_CONFIG.map { |_index, lang| lang[:iso_639_1_code].to_sym }
From c6be04cdc1c30d70cfd39aa47feecd4fe3182125 Mon Sep 17 00:00:00 2001
From: Shivam Mishra
Date: Thu, 14 Aug 2025 12:39:21 +0530
Subject: [PATCH 15/26] feat: scenario agents & runner (#11944)
Co-authored-by: Muhsin Keloth
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Sojan Jose
Co-authored-by: Pranav
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
---
.gitignore | 1 +
Gemfile | 5 +-
Gemfile.lock | 8 +-
config/initializers/ai_agents.rb | 23 ++
.../conversation/response_builder_job.rb | 16 +-
enterprise/app/models/captain/assistant.rb | 30 ++
enterprise/app/models/captain/scenario.rb | 34 ++
enterprise/app/models/concerns/agentable.rb | 56 +++
.../captain/assistant/agent_runner_service.rb | 161 +++++++++
enterprise/lib/captain/prompt_renderer.rb | 25 ++
.../lib/captain/prompts/assistant.liquid | 80 +++++
.../lib/captain/prompts/scenario.liquid | 24 ++
.../captain/prompts/snippets/contact.liquid | 17 +
.../prompts/snippets/conversation.liquid | 18 +
enterprise/lib/captain/response_schema.rb | 6 +
lib/open_ai_constants.rb | 6 +
lib/tasks/captain_chat.rake | 235 +++++++++++++
.../conversation/response_builder_job_spec.rb | 79 ++++-
.../lib/captain/prompt_renderer_spec.rb | 123 +++++++
.../models/concerns/agentable_spec.rb | 186 ++++++++++
.../assistant/agent_runner_service_spec.rb | 320 ++++++++++++++++++
21 files changed, 1437 insertions(+), 16 deletions(-)
create mode 100644 config/initializers/ai_agents.rb
create mode 100644 enterprise/app/models/concerns/agentable.rb
create mode 100644 enterprise/app/services/captain/assistant/agent_runner_service.rb
create mode 100644 enterprise/lib/captain/prompt_renderer.rb
create mode 100644 enterprise/lib/captain/prompts/assistant.liquid
create mode 100644 enterprise/lib/captain/prompts/scenario.liquid
create mode 100644 enterprise/lib/captain/prompts/snippets/contact.liquid
create mode 100644 enterprise/lib/captain/prompts/snippets/conversation.liquid
create mode 100644 enterprise/lib/captain/response_schema.rb
create mode 100644 lib/open_ai_constants.rb
create mode 100644 lib/tasks/captain_chat.rake
create mode 100644 spec/enterprise/lib/captain/prompt_renderer_spec.rb
create mode 100644 spec/enterprise/models/concerns/agentable_spec.rb
create mode 100644 spec/enterprise/services/captain/assistant/agent_runner_service_spec.rb
diff --git a/.gitignore b/.gitignore
index c64fb5c1b..bb0df62a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -94,3 +94,4 @@ yarn-debug.log*
.vscode
.claude/settings.local.json
.cursor
+CLAUDE.local.md
diff --git a/Gemfile b/Gemfile
index 269614d8b..9929575d4 100644
--- a/Gemfile
+++ b/Gemfile
@@ -179,7 +179,10 @@ gem 'reverse_markdown'
gem 'iso-639'
gem 'ruby-openai'
-gem 'ai-agents', '>= 0.2.1'
+gem 'ai-agents', '>= 0.4.3'
+
+# TODO: Move this gem as a dependency of ai-agents
+gem 'ruby_llm-schema'
gem 'shopify_api'
diff --git a/Gemfile.lock b/Gemfile.lock
index 405300a7c..1c64914b3 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -126,7 +126,7 @@ GEM
jbuilder (~> 2)
rails (>= 4.2, < 7.2)
selectize-rails (~> 0.6)
- ai-agents (0.2.1)
+ ai-agents (0.4.3)
ruby_llm (~> 1.3)
annotate (3.2.0)
activerecord (>= 3.2, < 8.0)
@@ -720,7 +720,7 @@ GEM
ruby2ruby (2.5.0)
ruby_parser (~> 3.1)
sexp_processor (~> 4.6)
- ruby_llm (1.3.1)
+ ruby_llm (1.5.1)
base64
event_stream_parser (~> 1)
faraday (>= 1.10.0)
@@ -729,6 +729,7 @@ GEM
faraday-retry (>= 1)
marcel (~> 1.0)
zeitwerk (~> 2)
+ ruby_llm-schema (0.1.0)
ruby_parser (3.20.0)
sexp_processor (~> 4.16)
sass (3.7.4)
@@ -910,7 +911,7 @@ DEPENDENCIES
administrate (>= 0.20.1)
administrate-field-active_storage (>= 1.0.3)
administrate-field-belongs_to_search (>= 0.9.0)
- ai-agents (>= 0.2.1)
+ ai-agents (>= 0.4.3)
annotate
attr_extras
audited (~> 5.4, >= 5.4.1)
@@ -1004,6 +1005,7 @@ DEPENDENCIES
rubocop-rails
rubocop-rspec
ruby-openai
+ ruby_llm-schema
scout_apm
scss_lint
seed_dump
diff --git a/config/initializers/ai_agents.rb b/config/initializers/ai_agents.rb
new file mode 100644
index 000000000..37bdd589f
--- /dev/null
+++ b/config/initializers/ai_agents.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'agents'
+
+Rails.application.config.after_initialize do
+ api_key = InstallationConfig.find_by(name: 'CAPTAIN_OPEN_AI_API_KEY')&.value
+ model = InstallationConfig.find_by(name: 'CAPTAIN_OPEN_AI_MODEL')&.value.presence || OpenAiConstants::DEFAULT_MODEL
+ api_endpoint = InstallationConfig.find_by(name: 'CAPTAIN_OPEN_AI_ENDPOINT')&.value || OpenAiConstants::DEFAULT_ENDPOINT
+
+ if api_key.present?
+ Agents.configure do |config|
+ config.openai_api_key = api_key
+ if api_endpoint.present?
+ api_base = "#{api_endpoint.chomp('/')}/v1"
+ config.openai_api_base = api_base
+ end
+ config.default_model = model
+ config.debug = false
+ end
+ end
+rescue StandardError => e
+ Rails.logger.error "Failed to configure AI Agents SDK: #{e.message}"
+end
diff --git a/enterprise/app/jobs/captain/conversation/response_builder_job.rb b/enterprise/app/jobs/captain/conversation/response_builder_job.rb
index b207bd2a4..7ede1201d 100644
--- a/enterprise/app/jobs/captain/conversation/response_builder_job.rb
+++ b/enterprise/app/jobs/captain/conversation/response_builder_job.rb
@@ -26,9 +26,15 @@ class Captain::Conversation::ResponseBuilderJob < ApplicationJob
delegate :account, :inbox, to: :@conversation
def generate_and_process_response
- @response = Captain::Llm::AssistantChatService.new(assistant: @assistant).generate_response(
- message_history: collect_previous_messages
- )
+ @response = if captain_v2_enabled?
+ Captain::Assistant::AgentRunnerService.new(assistant: @assistant, conversation: @conversation).generate_response(
+ message_history: collect_previous_messages
+ )
+ else
+ Captain::Llm::AssistantChatService.new(assistant: @assistant).generate_response(
+ message_history: collect_previous_messages
+ )
+ end
return process_action('handoff') if handoff_requested?
@@ -104,4 +110,8 @@ class Captain::Conversation::ResponseBuilderJob < ApplicationJob
def log_error(error)
ChatwootExceptionTracker.new(error, account: account).capture_exception
end
+
+ def captain_v2_enabled?
+ return account.feature_enabled?('captain_integration_v2')
+ end
end
diff --git a/enterprise/app/models/captain/assistant.rb b/enterprise/app/models/captain/assistant.rb
index cdf2b53f3..0423abf67 100644
--- a/enterprise/app/models/captain/assistant.rb
+++ b/enterprise/app/models/captain/assistant.rb
@@ -19,6 +19,7 @@
class Captain::Assistant < ApplicationRecord
include Avatarable
include Concerns::CaptainToolsHelpers
+ include Concerns::Agentable
self.table_name = 'captain_assistants'
@@ -35,6 +36,8 @@ class Captain::Assistant < ApplicationRecord
has_many :copilot_threads, dependent: :destroy_async
has_many :scenarios, class_name: 'Captain::Scenario', dependent: :destroy_async
+ store_accessor :config, :temperature, :feature_faq, :feature_memory, :product_name
+
validates :name, presence: true
validates :description, presence: true
validates :account_id, presence: true
@@ -71,6 +74,33 @@ class Captain::Assistant < ApplicationRecord
private
+ def agent_name
+ name
+ end
+
+ def agent_tools
+ [
+ self.class.resolve_tool_class('faq_lookup').new(self),
+ self.class.resolve_tool_class('handoff').new(self)
+ ]
+ end
+
+ def prompt_context
+ {
+ name: name,
+ description: description,
+ product_name: config['product_name'] || 'this product',
+ scenarios: scenarios.enabled.map do |scenario|
+ {
+ key: scenario.title.parameterize.underscore,
+ description: scenario.description
+ }
+ end,
+ response_guidelines: response_guidelines || [],
+ guardrails: guardrails || []
+ }
+ end
+
def default_avatar_url
"#{ENV.fetch('FRONTEND_URL', nil)}/assets/images/dashboard/captain/logo.svg"
end
diff --git a/enterprise/app/models/captain/scenario.rb b/enterprise/app/models/captain/scenario.rb
index ecfba396f..aac7e2411 100644
--- a/enterprise/app/models/captain/scenario.rb
+++ b/enterprise/app/models/captain/scenario.rb
@@ -22,6 +22,7 @@
#
class Captain::Scenario < ApplicationRecord
include Concerns::CaptainToolsHelpers
+ include Concerns::Agentable
self.table_name = 'captain_scenarios'
@@ -37,10 +38,43 @@ class Captain::Scenario < ApplicationRecord
scope :enabled, -> { where(enabled: true) }
+ delegate :temperature, :feature_faq, :feature_memory, :product_name, to: :assistant
+
before_save :resolve_tool_references
+ def prompt_context
+ {
+ title: title,
+ instructions: resolved_instructions,
+ tools: resolved_tools
+ }
+ end
+
private
+ def agent_name
+ "#{title} Agent".titleize
+ end
+
+ def agent_tools
+ resolved_tools.map { |tool| self.class.resolve_tool_class(tool[:id]) }.map { |tool| tool.new(assistant) }
+ end
+
+ def resolved_instructions
+ instruction.gsub(TOOL_REFERENCE_REGEX) do |match|
+ "#{match} tool "
+ end
+ end
+
+ def resolved_tools
+ return [] if tools.blank?
+
+ available_tools = self.class.available_agent_tools
+ tools.filter_map do |tool_id|
+ available_tools.find { |tool| tool[:id] == tool_id }
+ end
+ end
+
# Validates that all tool references in the instruction are valid.
# Parses the instruction for tool references and checks if they exist
# in the available tools configuration.
diff --git a/enterprise/app/models/concerns/agentable.rb b/enterprise/app/models/concerns/agentable.rb
new file mode 100644
index 000000000..dab76a726
--- /dev/null
+++ b/enterprise/app/models/concerns/agentable.rb
@@ -0,0 +1,56 @@
+module Concerns::Agentable
+ extend ActiveSupport::Concern
+
+ def agent
+ Agents::Agent.new(
+ name: agent_name,
+ instructions: ->(context) { agent_instructions(context) },
+ tools: agent_tools,
+ model: agent_model,
+ temperature: temperature.to_f || 0.7,
+ response_schema: agent_response_schema
+ )
+ end
+
+ def agent_instructions(context = nil)
+ enhanced_context = prompt_context
+
+ if context
+ state = context.context[:state] || {}
+ conversation_data = state[:conversation] || {}
+ contact_data = state[:contact] || {}
+ enhanced_context = enhanced_context.merge(
+ conversation: conversation_data,
+ contact: contact_data
+ )
+ end
+
+ Captain::PromptRenderer.render(template_name, enhanced_context.with_indifferent_access)
+ end
+
+ private
+
+ def agent_name
+ raise NotImplementedError, "#{self.class} must implement agent_name"
+ end
+
+ def template_name
+ self.class.name.demodulize.underscore
+ end
+
+ def agent_tools
+ [] # Default implementation, override if needed
+ end
+
+ def agent_model
+ InstallationConfig.find_by(name: 'CAPTAIN_OPEN_AI_MODEL')&.value.presence || OpenAiConstants::DEFAULT_MODEL
+ end
+
+ def agent_response_schema
+ Captain::ResponseSchema
+ end
+
+ def prompt_context
+ raise NotImplementedError, "#{self.class} must implement prompt_context"
+ end
+end
diff --git a/enterprise/app/services/captain/assistant/agent_runner_service.rb b/enterprise/app/services/captain/assistant/agent_runner_service.rb
new file mode 100644
index 000000000..7a35e6d07
--- /dev/null
+++ b/enterprise/app/services/captain/assistant/agent_runner_service.rb
@@ -0,0 +1,161 @@
+require 'agents'
+
+class Captain::Assistant::AgentRunnerService
+ CONVERSATION_STATE_ATTRIBUTES = %i[
+ id display_id inbox_id contact_id status priority
+ label_list custom_attributes additional_attributes
+ ].freeze
+
+ CONTACT_STATE_ATTRIBUTES = %i[
+ id name email phone_number identifier contact_type
+ custom_attributes additional_attributes
+ ].freeze
+
+ def initialize(assistant:, conversation: nil, callbacks: {})
+ @assistant = assistant
+ @conversation = conversation
+ @callbacks = callbacks
+ end
+
+ def generate_response(message_history: [])
+ agents = build_and_wire_agents
+ context = build_context(message_history)
+ message_to_process = extract_last_user_message(message_history)
+ runner = Agents::Runner.with_agents(*agents)
+ runner = add_callbacks_to_runner(runner) if @callbacks.any?
+ result = runner.run(message_to_process, context: context)
+
+ process_agent_result(result)
+ rescue StandardError => e
+ # when running the agent runner service in a rake task, the conversation might not have an account associated
+ # for regular production usage, it will run just fine
+ ChatwootExceptionTracker.new(e, account: @conversation&.account).capture_exception
+ Rails.logger.error "[Captain V2] AgentRunnerService error: #{e.message}"
+ Rails.logger.error e.backtrace.join("\n")
+
+ error_response(e.message)
+ end
+
+ private
+
+ def build_context(message_history)
+ conversation_history = message_history.map do |msg|
+ content = extract_text_from_content(msg[:content])
+
+ {
+ role: msg[:role].to_sym,
+ content: content,
+ agent_name: msg[:agent_name]
+ }
+ end
+
+ {
+ conversation_history: conversation_history,
+ state: build_state
+ }
+ end
+
+ def extract_last_user_message(message_history)
+ last_user_msg = message_history.reverse.find { |msg| msg[:role] == 'user' }
+
+ extract_text_from_content(last_user_msg[:content])
+ end
+
+ def extract_text_from_content(content)
+ # Handle structured output from agents
+ return content[:response] || content['response'] || content.to_s if content.is_a?(Hash)
+
+ return content unless content.is_a?(Array)
+
+ text_parts = content.select { |part| part[:type] == 'text' }.pluck(:text)
+ text_parts.join(' ')
+ end
+
+ # Response formatting methods
+ def process_agent_result(result)
+ Rails.logger.info "[Captain V2] Agent result: #{result.inspect}"
+ format_response(result.output)
+ end
+
+ def format_response(output)
+ return output.with_indifferent_access if output.is_a?(Hash)
+
+ # Fallback for backwards compatibility
+ {
+ 'response' => output.to_s,
+ 'reasoning' => 'Processed by agent'
+ }
+ end
+
+ def error_response(error_message)
+ {
+ 'response' => 'conversation_handoff',
+ 'reasoning' => "Error occurred: #{error_message}"
+ }
+ end
+
+ def build_state
+ state = {
+ account_id: @assistant.account_id,
+ assistant_id: @assistant.id,
+ assistant_config: @assistant.config
+ }
+
+ if @conversation
+ state[:conversation] = @conversation.attributes.symbolize_keys.slice(*CONVERSATION_STATE_ATTRIBUTES)
+ state[:contact] = @conversation.contact.attributes.symbolize_keys.slice(*CONTACT_STATE_ATTRIBUTES) if @conversation.contact
+ end
+
+ state
+ end
+
+ def build_and_wire_agents
+ assistant_agent = @assistant.agent
+ scenario_agents = @assistant.scenarios.enabled.map(&:agent)
+
+ assistant_agent.register_handoffs(*scenario_agents) if scenario_agents.any?
+ scenario_agents.each { |scenario_agent| scenario_agent.register_handoffs(assistant_agent) }
+
+ [assistant_agent] + scenario_agents
+ end
+
+ def add_callbacks_to_runner(runner)
+ runner = add_agent_thinking_callback(runner) if @callbacks[:on_agent_thinking]
+ runner = add_tool_start_callback(runner) if @callbacks[:on_tool_start]
+ runner = add_tool_complete_callback(runner) if @callbacks[:on_tool_complete]
+ runner = add_agent_handoff_callback(runner) if @callbacks[:on_agent_handoff]
+ runner
+ end
+
+ def add_agent_thinking_callback(runner)
+ runner.on_agent_thinking do |*args|
+ @callbacks[:on_agent_thinking].call(*args)
+ rescue StandardError => e
+ Rails.logger.warn "[Captain] Callback error for agent_thinking: #{e.message}"
+ end
+ end
+
+ def add_tool_start_callback(runner)
+ runner.on_tool_start do |*args|
+ @callbacks[:on_tool_start].call(*args)
+ rescue StandardError => e
+ Rails.logger.warn "[Captain] Callback error for tool_start: #{e.message}"
+ end
+ end
+
+ def add_tool_complete_callback(runner)
+ runner.on_tool_complete do |*args|
+ @callbacks[:on_tool_complete].call(*args)
+ rescue StandardError => e
+ Rails.logger.warn "[Captain] Callback error for tool_complete: #{e.message}"
+ end
+ end
+
+ def add_agent_handoff_callback(runner)
+ runner.on_agent_handoff do |*args|
+ @callbacks[:on_agent_handoff].call(*args)
+ rescue StandardError => e
+ Rails.logger.warn "[Captain] Callback error for agent_handoff: #{e.message}"
+ end
+ end
+end
diff --git a/enterprise/lib/captain/prompt_renderer.rb b/enterprise/lib/captain/prompt_renderer.rb
new file mode 100644
index 000000000..1a73ddd15
--- /dev/null
+++ b/enterprise/lib/captain/prompt_renderer.rb
@@ -0,0 +1,25 @@
+require 'liquid'
+
+class Captain::PromptRenderer
+ class << self
+ def render(template_name, context = {})
+ template = load_template(template_name)
+ liquid_template = Liquid::Template.parse(template)
+ liquid_template.render(stringify_keys(context))
+ end
+
+ private
+
+ def load_template(template_name)
+ template_path = Rails.root.join('enterprise', 'lib', 'captain', 'prompts', "#{template_name}.liquid")
+
+ raise "Template not found: #{template_name}" unless File.exist?(template_path)
+
+ File.read(template_path)
+ end
+
+ def stringify_keys(hash)
+ hash.deep_stringify_keys
+ end
+ end
+end
diff --git a/enterprise/lib/captain/prompts/assistant.liquid b/enterprise/lib/captain/prompts/assistant.liquid
new file mode 100644
index 000000000..69c967d73
--- /dev/null
+++ b/enterprise/lib/captain/prompts/assistant.liquid
@@ -0,0 +1,80 @@
+# System Context
+You are part of Captain, a multi-agent AI system designed for seamless agent coordination and task execution. You can transfer conversations to specialized agents using handoff functions (e.g., `handoff_to_[agent_name]`). These transfers happen in the background - never mention or draw attention to them in your responses.
+
+# Your Identity
+You are {{name}}, a helpful and knowledgeable assistant. Your role is to provide accurate information, assist with tasks, and ensure users get the help they need.
+
+{{ description }}
+
+Don't digress away from your instructions, and use all the available tools at your disposal for solving customer issues. If you are to state something factual about {{product_name}} ensure you source that information from the FAQs only. Use the faq_lookup tool for this.
+
+# Current Context
+
+Here's the metadata we have about the current conversation and the contact associated with it:
+
+{% if conversation -%}
+{% render 'conversation' %}
+{% endif -%}
+
+{% if contact -%}
+{% render 'contact' %}
+{% endif -%}
+
+{% if response_guidelines.size > 0 -%}
+# Response Guidelines
+Your responses should follow these guidelines:
+{% for guideline in response_guidelines -%}
+- {{ guideline }}
+{% endfor %}
+{% endif -%}
+
+{% if guardrails.size > 0 -%}
+# Guardrails
+Always respect these boundaries:
+{% for guardrail in guardrails -%}
+- {{ guardrail }}
+{% endfor %}
+{% endif -%}
+
+# Decision Framework
+
+## 1. Analyze the Request
+First, understand what the user is asking:
+- **Intent**: What are they trying to achieve?
+- **Type**: Is it a question, task, complaint, or request?
+- **Complexity**: Can you handle it or does it need specialized expertise?
+
+## 2. Check for Specialized Scenarios First
+Before using any tools, check if the request matches any of these scenarios. If unclear, ask clarifying questions to determine if a scenario applies:
+
+{% for scenario in scenarios -%}
+### handoff_to_{{ scenario.key }}
+{{ scenario.description }}
+{% endfor -%}
+
+## 3. Handle the Request
+If no specialized scenario clearly matches, handle it yourself:
+
+### For Questions and Information Requests
+1. **First, check existing knowledge**: Use `faq_lookup` tool to search for relevant information
+2. **If not found in FAQs**: Provide your best answer based on available context
+3. **If unable to answer**: Use `handoff` tool to transfer to a human expert
+
+### For Complex or Unclear Requests
+1. **Ask clarifying questions**: Gather more information if needed
+2. **Break down complex tasks**: Handle step by step or hand off if too complex
+3. **Escalate when necessary**: Use `handoff` tool for issues beyond your capabilities
+
+## Response Best Practices
+- Be conversational but professional
+- Provide actionable information
+- Include relevant details from tool responses
+
+# Human Handoff Protocol
+Transfer to a human agent when:
+- User explicitly requests human assistance
+- You cannot find needed information after checking FAQs
+- The issue requires specialized knowledge or permissions you don't have
+- Multiple attempts to help have been unsuccessful
+
+When using the `handoff` tool, provide a clear reason that helps the human agent understand the context.
diff --git a/enterprise/lib/captain/prompts/scenario.liquid b/enterprise/lib/captain/prompts/scenario.liquid
new file mode 100644
index 000000000..339820b83
--- /dev/null
+++ b/enterprise/lib/captain/prompts/scenario.liquid
@@ -0,0 +1,24 @@
+# System context
+You are part of a multi-agent system where you've been handed off a conversation to handle a specific task.
+The handoff was seamless - the user is not aware of any transfer. Continue the conversation naturally.
+
+# Your Role
+You are a specialized agent called {{ title }}, your task is to handle the following scenario:
+
+{{ instructions }}
+
+{% if conversation -%}
+{% render 'conversation' %}
+
+{% if contact -%}
+{% render 'contact' %}
+{% endif -%}
+{% endif -%}
+
+{% if tools.size > 0 -%}
+# Available Tools
+You have access to these tools:
+{% for tool in tools -%}
+- {{ tool.id }}: {{ tool.description }}
+{% endfor %}
+{%- endif %}
diff --git a/enterprise/lib/captain/prompts/snippets/contact.liquid b/enterprise/lib/captain/prompts/snippets/contact.liquid
new file mode 100644
index 000000000..372389cbb
--- /dev/null
+++ b/enterprise/lib/captain/prompts/snippets/contact.liquid
@@ -0,0 +1,17 @@
+# Contact Information
+- Contact ID: {{ contact.id }}
+- Name: {{ contact.name || "Unknown" }}
+- Email: {{ contact.email || "None" }}
+- Phone: {{ contact.phone_number || "None" }}
+- Identifier: {{ contact.identifier || "None" }}
+- Type: {{ contact.contact_type || "visitor" }}
+{% if contact.custom_attributes -%}
+ {% for attribute in contact.custom_attributes -%}
+- {{ attribute[0] }}: {{ attribute[1] }}
+ {% endfor -%}
+{% endif -%}
+{% if contact.additional_attributes -%}
+ {% for attribute in contact.additional_attributes -%}
+- {{ attribute[0] }}: {{ attribute[1] }}
+ {% endfor -%}
+{% endif -%}
\ No newline at end of file
diff --git a/enterprise/lib/captain/prompts/snippets/conversation.liquid b/enterprise/lib/captain/prompts/snippets/conversation.liquid
new file mode 100644
index 000000000..b5faee7d6
--- /dev/null
+++ b/enterprise/lib/captain/prompts/snippets/conversation.liquid
@@ -0,0 +1,18 @@
+# Current Conversation Context
+- Conversation ID: {{ conversation.display_id }}
+- Contact ID: {{ conversation.contact_id }}
+- Status: {{ conversation.status }}
+- Priority: {{ conversation.priority || "None" }}
+{% if conversation.label_list.size > 0 -%}
+- Labels: {{ conversation.label_list | join: ", " }}
+{% endif -%}
+{% if conversation.custom_attributes -%}
+ {% for attribute in conversation.custom_attributes -%}
+- {{ attribute[0] }}: {{ attribute[1] }}
+ {% endfor -%}
+{% endif -%}
+{% if conversation.additional_attributes -%}
+ {% for attribute in conversation.additional_attributes -%}
+- {{ attribute[0] }}: {{ attribute[1] }}
+ {% endfor -%}
+{% endif -%}
\ No newline at end of file
diff --git a/enterprise/lib/captain/response_schema.rb b/enterprise/lib/captain/response_schema.rb
new file mode 100644
index 000000000..651eb7e23
--- /dev/null
+++ b/enterprise/lib/captain/response_schema.rb
@@ -0,0 +1,6 @@
+# TODO: Wrap the schema lib under ai-agents
+# So we can extend it as Agents::Schema
+class Captain::ResponseSchema < RubyLLM::Schema
+ string :response, description: 'The message to send to the user'
+ string :reasoning, description: "Agent's thought process"
+end
diff --git a/lib/open_ai_constants.rb b/lib/open_ai_constants.rb
new file mode 100644
index 000000000..2c87f3378
--- /dev/null
+++ b/lib/open_ai_constants.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+module OpenAiConstants
+ DEFAULT_MODEL = 'gpt-4.1-mini'
+ DEFAULT_ENDPOINT = 'https://api.openai.com'
+end
diff --git a/lib/tasks/captain_chat.rake b/lib/tasks/captain_chat.rake
new file mode 100644
index 000000000..cfe257196
--- /dev/null
+++ b/lib/tasks/captain_chat.rake
@@ -0,0 +1,235 @@
+require 'io/console'
+require 'readline'
+
+namespace :captain do
+ desc 'Start interactive chat with Captain assistant - Usage: rake captain:chat[assistant_id] or rake captain:chat -- assistant_id'
+ task :chat, [:assistant_id] => :environment do |_, args|
+ assistant_id = args[:assistant_id] || ARGV[1]
+
+ unless assistant_id
+ puts '❌ Please provide an assistant ID'
+ puts 'Usage: rake captain:chat[assistant_id]'
+ puts "\nAvailable assistants:"
+ Captain::Assistant.includes(:account).each do |assistant|
+ puts " ID: #{assistant.id} - #{assistant.name} (Account: #{assistant.account.name})"
+ end
+ exit 1
+ end
+
+ assistant = Captain::Assistant.find_by(id: assistant_id)
+ unless assistant
+ puts "❌ Assistant with ID #{assistant_id} not found"
+ exit 1
+ end
+
+ # Clear ARGV to prevent gets from reading files
+ ARGV.clear
+
+ chat_session = CaptainChatSession.new(assistant)
+ chat_session.start
+ end
+end
+
+class CaptainChatSession
+ def initialize(assistant)
+ @assistant = assistant
+ @message_history = []
+ end
+
+ def start
+ show_assistant_info
+ show_instructions
+ chat_loop
+ show_exit_message
+ end
+
+ private
+
+ def show_instructions
+ puts "💡 Type 'exit', 'quit', or 'bye' to end the session"
+ puts "💡 Type 'clear' to clear message history"
+ puts('-' * 50)
+ end
+
+ def chat_loop
+ loop do
+ puts '' # Add spacing before prompt
+ user_input = Readline.readline('👤 You: ', true)
+ next unless user_input # Handle Ctrl+D
+
+ break unless handle_user_input(user_input.strip)
+ end
+ end
+
+ def handle_user_input(user_input)
+ case user_input.downcase
+ when 'exit', 'quit', 'bye'
+ false
+ when 'clear'
+ clear_history
+ true
+ when ''
+ true
+ else
+ process_user_message(user_input)
+ true
+ end
+ end
+
+ def show_exit_message
+ puts "\nChat session ended"
+ puts "Final conversation log has #{@message_history.length} messages"
+ end
+
+ def show_assistant_info
+ show_basic_info
+ show_scenarios
+ show_available_tools
+ puts ''
+ end
+
+ def show_basic_info
+ puts "🤖 Starting chat with #{@assistant.name}"
+ puts "🏢 Account: #{@assistant.account.name}"
+ puts "🆔 Assistant ID: #{@assistant.id}"
+ end
+
+ def show_scenarios
+ scenarios = @assistant.scenarios.enabled
+ if scenarios.any?
+ puts "⚡ Enabled Scenarios (#{scenarios.count}):"
+ scenarios.each { |scenario| display_scenario(scenario) }
+ else
+ puts '⚡ No scenarios enabled'
+ end
+ end
+
+ def display_scenario(scenario)
+ tools_count = scenario.tools&.length || 0
+ puts " • #{scenario.title} (#{tools_count} tools)"
+ return if scenario.description.blank?
+
+ description = truncate_description(scenario.description)
+ puts " #{description}"
+ end
+
+ def truncate_description(description)
+ description.length > 60 ? "#{description[0..60]}..." : description
+ end
+
+ def show_available_tools
+ available_tools = Captain::Assistant.available_tool_ids
+ if available_tools.any?
+ puts "🔧 Available Tools (#{available_tools.count}): #{available_tools.join(', ')}"
+ else
+ puts '🔧 No tools available'
+ end
+ end
+
+ def process_user_message(user_input)
+ add_to_history('user', user_input)
+
+ begin
+ print "🤖 #{@assistant.name}: "
+ @current_system_messages = []
+
+ result = generate_assistant_response
+ display_response(result)
+ rescue StandardError => e
+ handle_error(e)
+ end
+ end
+
+ def generate_assistant_response
+ runner = Captain::Assistant::AgentRunnerService.new(assistant: @assistant, callbacks: build_callbacks)
+ runner.generate_response(message_history: @message_history)
+ end
+
+ def build_callbacks
+ {
+ on_agent_thinking: method(:handle_agent_thinking),
+ on_tool_start: method(:handle_tool_start),
+ on_tool_complete: method(:handle_tool_complete),
+ on_agent_handoff: method(:handle_agent_handoff)
+ }
+ end
+
+ def handle_agent_thinking(agent, _input)
+ agent_name = extract_name(agent)
+ @current_system_messages << "#{agent_name} is thinking..."
+ add_to_history('system', "#{agent_name} is thinking...")
+ end
+
+ def handle_tool_start(tool, _args)
+ tool_name = extract_tool_name(tool)
+ @current_system_messages << "Using tool: #{tool_name}"
+ add_to_history('system', "Using tool: #{tool_name}")
+ end
+
+ def handle_tool_complete(tool, _result)
+ tool_name = extract_tool_name(tool)
+ @current_system_messages << "Tool #{tool_name} completed"
+ add_to_history('system', "Tool #{tool_name} completed")
+ end
+
+ def handle_agent_handoff(from, to, reason)
+ @current_system_messages << "Handoff: #{extract_name(from)} → #{extract_name(to)} (#{reason})"
+ add_to_history('system', "Agent handoff: #{extract_name(from)} → #{extract_name(to)} (#{reason})")
+ end
+
+ def display_response(result)
+ response_text = result['response'] || 'No response generated'
+ reasoning = result['reasoning']
+
+ puts dim_text("\n#{@current_system_messages.join("\n")}") if @current_system_messages.any?
+ puts response_text
+ puts dim_italic_text("(Reasoning: #{reasoning})") if reasoning && reasoning != 'Processed by agent'
+
+ add_to_history('assistant', response_text, reasoning: reasoning)
+ end
+
+ def handle_error(error)
+ error_msg = "Error: #{error.message}"
+ puts "❌ #{error_msg}"
+ add_to_history('system', error_msg)
+ end
+
+ def add_to_history(role, content, agent_name: nil, reasoning: nil)
+ message = {
+ role: role,
+ content: content,
+ timestamp: Time.current,
+ agent_name: agent_name || (role == 'assistant' ? @assistant.name : nil)
+ }
+ message[:reasoning] = reasoning if reasoning
+
+ @message_history << message
+ end
+
+ def clear_history
+ @message_history.clear
+ puts 'Message history cleared'
+ end
+
+ def dim_text(text)
+ # ANSI escape code for very dim gray text (bright black/dark gray)
+ "\e[90m#{text}\e[0m"
+ end
+
+ def dim_italic_text(text)
+ # ANSI escape codes for dim gray + italic text
+ "\e[90m\e[3m#{text}\e[0m"
+ end
+
+ def extract_tool_name(tool)
+ return tool if tool.is_a?(String)
+
+ tool.class.name.split('::').last.gsub('Tool', '')
+ rescue StandardError
+ tool.to_s
+ end
+
+ def extract_name(obj)
+ obj.respond_to?(:name) ? obj.name : obj.to_s
+ end
+end
diff --git a/spec/enterprise/jobs/captain/conversation/response_builder_job_spec.rb b/spec/enterprise/jobs/captain/conversation/response_builder_job_spec.rb
index c21205d52..23ed2ecec 100644
--- a/spec/enterprise/jobs/captain/conversation/response_builder_job_spec.rb
+++ b/spec/enterprise/jobs/captain/conversation/response_builder_job_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe Captain::Conversation::ResponseBuilderJob, type: :job do
describe '#perform' do
let(:conversation) { create(:conversation, inbox: inbox, account: account) }
let(:mock_llm_chat_service) { instance_double(Captain::Llm::AssistantChatService) }
+ let(:mock_agent_runner_service) { instance_double(Captain::Assistant::AgentRunnerService) }
before do
create(:message, conversation: conversation, content: 'Hello', message_type: :incoming)
@@ -16,19 +17,79 @@ RSpec.describe Captain::Conversation::ResponseBuilderJob, type: :job do
allow(inbox).to receive(:captain_active?).and_return(true)
allow(Captain::Llm::AssistantChatService).to receive(:new).and_return(mock_llm_chat_service)
allow(mock_llm_chat_service).to receive(:generate_response).and_return({ 'response' => 'Hey, welcome to Captain Specs' })
+ allow(Captain::Assistant::AgentRunnerService).to receive(:new).and_return(mock_agent_runner_service)
+ allow(mock_agent_runner_service).to receive(:generate_response).and_return({ 'response' => 'Hey, welcome to Captain V2' })
end
- it 'generates and processes response' do
- described_class.perform_now(conversation, assistant)
- expect(conversation.messages.count).to eq(2)
- expect(conversation.messages.outgoing.count).to eq(1)
- expect(conversation.messages.last.content).to eq('Hey, welcome to Captain Specs')
+ context 'when captain_v2 is disabled' do
+ before do
+ allow(account).to receive(:feature_enabled?).and_return(false)
+ allow(account).to receive(:feature_enabled?).with('captain_integration_v2').and_return(false)
+ end
+
+ it 'uses Captain::Llm::AssistantChatService' do
+ expect(Captain::Llm::AssistantChatService).to receive(:new).with(assistant: assistant)
+ expect(Captain::Assistant::AgentRunnerService).not_to receive(:new)
+
+ described_class.perform_now(conversation, assistant)
+ expect(conversation.messages.last.content).to eq('Hey, welcome to Captain Specs')
+ end
+
+ it 'generates and processes response' do
+ described_class.perform_now(conversation, assistant)
+ expect(conversation.messages.count).to eq(2)
+ expect(conversation.messages.outgoing.count).to eq(1)
+ expect(conversation.messages.last.content).to eq('Hey, welcome to Captain Specs')
+ end
+
+ it 'increments usage response' do
+ described_class.perform_now(conversation, assistant)
+ account.reload
+ expect(account.usage_limits[:captain][:responses][:consumed]).to eq(1)
+ end
end
- it 'increments usage response' do
- described_class.perform_now(conversation, assistant)
- account.reload
- expect(account.usage_limits[:captain][:responses][:consumed]).to eq(1)
+ context 'when captain_v2 is enabled' do
+ before do
+ allow(account).to receive(:feature_enabled?).and_return(false)
+ allow(account).to receive(:feature_enabled?).with('captain_integration_v2').and_return(true)
+ end
+
+ it 'uses Captain::Assistant::AgentRunnerService' do
+ expect(Captain::Assistant::AgentRunnerService).to receive(:new).with(
+ assistant: assistant,
+ conversation: conversation
+ )
+ expect(Captain::Llm::AssistantChatService).not_to receive(:new)
+
+ described_class.perform_now(conversation, assistant)
+ expect(conversation.messages.last.content).to eq('Hey, welcome to Captain V2')
+ end
+
+ it 'passes message history to agent runner service' do
+ expected_messages = [
+ { content: 'Hello', role: 'user' }
+ ]
+
+ expect(mock_agent_runner_service).to receive(:generate_response).with(
+ message_history: expected_messages
+ )
+
+ described_class.perform_now(conversation, assistant)
+ end
+
+ it 'generates and processes response' do
+ described_class.perform_now(conversation, assistant)
+ expect(conversation.messages.count).to eq(2)
+ expect(conversation.messages.outgoing.count).to eq(1)
+ expect(conversation.messages.last.content).to eq('Hey, welcome to Captain V2')
+ end
+
+ it 'increments usage response' do
+ described_class.perform_now(conversation, assistant)
+ account.reload
+ expect(account.usage_limits[:captain][:responses][:consumed]).to eq(1)
+ end
end
context 'when message contains an image' do
diff --git a/spec/enterprise/lib/captain/prompt_renderer_spec.rb b/spec/enterprise/lib/captain/prompt_renderer_spec.rb
new file mode 100644
index 000000000..761d55f99
--- /dev/null
+++ b/spec/enterprise/lib/captain/prompt_renderer_spec.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Captain::PromptRenderer do
+ let(:template_name) { 'test_template' }
+ let(:template_content) { 'Hello {{name}}, your balance is {{balance}}' }
+ let(:template_path) { Rails.root.join('enterprise', 'lib', 'captain', 'prompts', "#{template_name}.liquid") }
+ let(:context) { { name: 'John', balance: 100 } }
+
+ before do
+ allow(File).to receive(:exist?).and_return(false)
+ allow(File).to receive(:exist?).with(template_path).and_return(true)
+ allow(File).to receive(:read).with(template_path).and_return(template_content)
+ end
+
+ describe '.render' do
+ it 'renders template with context' do
+ result = described_class.render(template_name, context)
+
+ expect(result).to eq('Hello John, your balance is 100')
+ end
+
+ it 'handles string keys in context' do
+ string_context = { 'name' => 'Jane', 'balance' => 200 }
+ result = described_class.render(template_name, string_context)
+
+ expect(result).to eq('Hello Jane, your balance is 200')
+ end
+
+ it 'handles mixed symbol and string keys' do
+ mixed_context = { :name => 'Bob', 'balance' => 300 }
+ result = described_class.render(template_name, mixed_context)
+
+ expect(result).to eq('Hello Bob, your balance is 300')
+ end
+
+ it 'handles nested hash context' do
+ nested_template = 'User: {{user.name}}, Account: {{user.account.type}}'
+ nested_context = { user: { name: 'Alice', account: { type: 'premium' } } }
+
+ allow(File).to receive(:read).with(template_path).and_return(nested_template)
+
+ result = described_class.render(template_name, nested_context)
+
+ expect(result).to eq('User: Alice, Account: premium')
+ end
+
+ it 'handles empty context' do
+ simple_template = 'Hello World'
+ allow(File).to receive(:read).with(template_path).and_return(simple_template)
+
+ result = described_class.render(template_name, {})
+
+ expect(result).to eq('Hello World')
+ end
+
+ it 'loads and parses liquid template' do
+ liquid_template_double = instance_double(Liquid::Template)
+ allow(Liquid::Template).to receive(:parse).with(template_content).and_return(liquid_template_double)
+ allow(liquid_template_double).to receive(:render).with(hash_including('name', 'balance')).and_return('rendered')
+
+ result = described_class.render(template_name, context)
+
+ expect(result).to eq('rendered')
+ expect(Liquid::Template).to have_received(:parse).with(template_content)
+ end
+ end
+
+ describe '.load_template' do
+ it 'reads template file from correct path' do
+ described_class.send(:load_template, template_name)
+
+ expect(File).to have_received(:read).with(template_path)
+ end
+
+ it 'raises error when template does not exist' do
+ allow(File).to receive(:exist?).with(template_path).and_return(false)
+
+ expect { described_class.send(:load_template, template_name) }
+ .to raise_error("Template not found: #{template_name}")
+ end
+
+ it 'constructs correct template path' do
+ expected_path = Rails.root.join('enterprise/lib/captain/prompts/my_template.liquid')
+ allow(File).to receive(:exist?).with(expected_path).and_return(true)
+ allow(File).to receive(:read).with(expected_path).and_return('test content')
+
+ described_class.send(:load_template, 'my_template')
+
+ expect(File).to have_received(:exist?).with(expected_path)
+ end
+ end
+
+ describe '.stringify_keys' do
+ it 'converts symbol keys to strings' do
+ hash = { name: 'John', age: 30 }
+ result = described_class.send(:stringify_keys, hash)
+
+ expect(result).to eq({ 'name' => 'John', 'age' => 30 })
+ end
+
+ it 'handles nested hashes' do
+ hash = { user: { name: 'John', profile: { age: 30 } } }
+ result = described_class.send(:stringify_keys, hash)
+
+ expect(result).to eq({ 'user' => { 'name' => 'John', 'profile' => { 'age' => 30 } } })
+ end
+
+ it 'handles arrays with hashes' do
+ hash = { users: [{ name: 'John' }, { name: 'Jane' }] }
+ result = described_class.send(:stringify_keys, hash)
+
+ expect(result).to eq({ 'users' => [{ 'name' => 'John' }, { 'name' => 'Jane' }] })
+ end
+
+ it 'handles empty hash' do
+ result = described_class.send(:stringify_keys, {})
+
+ expect(result).to eq({})
+ end
+ end
+end
diff --git a/spec/enterprise/models/concerns/agentable_spec.rb b/spec/enterprise/models/concerns/agentable_spec.rb
new file mode 100644
index 000000000..767e51d44
--- /dev/null
+++ b/spec/enterprise/models/concerns/agentable_spec.rb
@@ -0,0 +1,186 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Concerns::Agentable do
+ let(:dummy_class) do
+ Class.new do
+ include Concerns::Agentable
+
+ attr_accessor :temperature
+
+ def initialize(name: 'Test Agent', temperature: 0.8)
+ @name = name
+ @temperature = temperature
+ end
+
+ def self.name
+ 'DummyClass'
+ end
+
+ private
+
+ def agent_name
+ @name
+ end
+
+ def prompt_context
+ { base_key: 'base_value' }
+ end
+ end
+ end
+
+ let(:dummy_instance) { dummy_class.new }
+ let(:mock_agents_agent) { instance_double(Agents::Agent) }
+ let(:mock_installation_config) { instance_double(InstallationConfig, value: 'gpt-4-turbo') }
+
+ before do
+ allow(Agents::Agent).to receive(:new).and_return(mock_agents_agent)
+ allow(InstallationConfig).to receive(:find_by).with(name: 'CAPTAIN_OPEN_AI_MODEL').and_return(mock_installation_config)
+ allow(Captain::PromptRenderer).to receive(:render).and_return('rendered_template')
+ end
+
+ describe '#agent' do
+ it 'creates an Agents::Agent with correct parameters' do
+ expect(Agents::Agent).to receive(:new).with(
+ name: 'Test Agent',
+ instructions: instance_of(Proc),
+ tools: [],
+ model: 'gpt-4-turbo',
+ temperature: 0.8,
+ response_schema: Captain::ResponseSchema
+ )
+
+ dummy_instance.agent
+ end
+
+ it 'converts nil temperature to 0.0' do
+ dummy_instance.temperature = nil
+
+ expect(Agents::Agent).to receive(:new).with(
+ hash_including(temperature: 0.0)
+ )
+
+ dummy_instance.agent
+ end
+
+ it 'converts temperature to float' do
+ dummy_instance.temperature = '0.5'
+
+ expect(Agents::Agent).to receive(:new).with(
+ hash_including(temperature: 0.5)
+ )
+
+ dummy_instance.agent
+ end
+ end
+
+ describe '#agent_instructions' do
+ it 'calls Captain::PromptRenderer with base context' do
+ expect(Captain::PromptRenderer).to receive(:render).with(
+ 'dummy_class',
+ hash_including(base_key: 'base_value')
+ )
+
+ dummy_instance.agent_instructions
+ end
+
+ it 'merges context state when provided' do
+ context_double = instance_double(Agents::RunContext,
+ context: {
+ state: {
+ conversation: { id: 123 },
+ contact: { name: 'John' }
+ }
+ })
+
+ expected_context = {
+ base_key: 'base_value',
+ conversation: { id: 123 },
+ contact: { name: 'John' }
+ }
+
+ expect(Captain::PromptRenderer).to receive(:render).with(
+ 'dummy_class',
+ hash_including(expected_context)
+ )
+
+ dummy_instance.agent_instructions(context_double)
+ end
+
+ it 'handles context without state' do
+ context_double = instance_double(Agents::RunContext, context: {})
+
+ expect(Captain::PromptRenderer).to receive(:render).with(
+ 'dummy_class',
+ hash_including(
+ base_key: 'base_value',
+ conversation: {},
+ contact: {}
+ )
+ )
+
+ dummy_instance.agent_instructions(context_double)
+ end
+ end
+
+ describe '#template_name' do
+ it 'returns underscored class name' do
+ expect(dummy_instance.send(:template_name)).to eq('dummy_class')
+ end
+ end
+
+ describe '#agent_tools' do
+ it 'returns empty array by default' do
+ expect(dummy_instance.send(:agent_tools)).to eq([])
+ end
+ end
+
+ describe '#agent_model' do
+ it 'returns value from InstallationConfig when present' do
+ expect(dummy_instance.send(:agent_model)).to eq('gpt-4-turbo')
+ end
+
+ it 'returns default model when config not found' do
+ allow(InstallationConfig).to receive(:find_by).and_return(nil)
+
+ expect(dummy_instance.send(:agent_model)).to eq('gpt-4.1-mini')
+ end
+
+ it 'returns default model when config value is nil' do
+ allow(mock_installation_config).to receive(:value).and_return(nil)
+
+ expect(dummy_instance.send(:agent_model)).to eq('gpt-4.1-mini')
+ end
+ end
+
+ describe '#agent_response_schema' do
+ it 'returns Captain::ResponseSchema' do
+ expect(dummy_instance.send(:agent_response_schema)).to eq(Captain::ResponseSchema)
+ end
+ end
+
+ describe 'required methods' do
+ let(:incomplete_class) do
+ Class.new do
+ include Concerns::Agentable
+ end
+ end
+
+ let(:incomplete_instance) { incomplete_class.new }
+
+ describe '#agent_name' do
+ it 'raises NotImplementedError when not implemented' do
+ expect { incomplete_instance.send(:agent_name) }
+ .to raise_error(NotImplementedError, /must implement agent_name/)
+ end
+ end
+
+ describe '#prompt_context' do
+ it 'raises NotImplementedError when not implemented' do
+ expect { incomplete_instance.send(:prompt_context) }
+ .to raise_error(NotImplementedError, /must implement prompt_context/)
+ end
+ end
+ end
+end
diff --git a/spec/enterprise/services/captain/assistant/agent_runner_service_spec.rb b/spec/enterprise/services/captain/assistant/agent_runner_service_spec.rb
new file mode 100644
index 000000000..f31177fc2
--- /dev/null
+++ b/spec/enterprise/services/captain/assistant/agent_runner_service_spec.rb
@@ -0,0 +1,320 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Captain::Assistant::AgentRunnerService do
+ let(:account) { create(:account) }
+ let(:inbox) { create(:inbox, account: account) }
+ let(:contact) { create(:contact, account: account) }
+ let(:conversation) { create(:conversation, account: account, inbox: inbox, contact: contact) }
+ let(:assistant) { create(:captain_assistant, account: account) }
+ let(:scenario) { create(:captain_scenario, assistant: assistant, enabled: true) }
+
+ let(:mock_runner) { instance_double(Agents::Runner) }
+ let(:mock_agent) { instance_double(Agents::Agent) }
+ let(:mock_scenario_agent) { instance_double(Agents::Agent) }
+ let(:mock_result) { instance_double(Agents::RunResult, output: { 'response' => 'Test response' }) }
+
+ let(:message_history) do
+ [
+ { role: 'user', content: 'Hello there' },
+ { role: 'assistant', content: 'Hi! How can I help you?', agent_name: 'Assistant' },
+ { role: 'user', content: 'I need help with my account' }
+ ]
+ end
+
+ before do
+ allow(assistant).to receive(:agent).and_return(mock_agent)
+ scenarios_relation = instance_double(Captain::Scenario)
+ allow(scenarios_relation).to receive(:enabled).and_return([scenario])
+ allow(assistant).to receive(:scenarios).and_return(scenarios_relation)
+ allow(scenario).to receive(:agent).and_return(mock_scenario_agent)
+ allow(Agents::Runner).to receive(:with_agents).and_return(mock_runner)
+ allow(mock_runner).to receive(:run).and_return(mock_result)
+ allow(mock_agent).to receive(:register_handoffs)
+ allow(mock_scenario_agent).to receive(:register_handoffs)
+ end
+
+ describe '#initialize' do
+ it 'sets instance variables correctly' do
+ service = described_class.new(assistant: assistant, conversation: conversation)
+
+ expect(service.instance_variable_get(:@assistant)).to eq(assistant)
+ expect(service.instance_variable_get(:@conversation)).to eq(conversation)
+ expect(service.instance_variable_get(:@callbacks)).to eq({})
+ end
+
+ it 'accepts callbacks parameter' do
+ callbacks = { on_agent_thinking: proc { |x| x } }
+ service = described_class.new(assistant: assistant, callbacks: callbacks)
+
+ expect(service.instance_variable_get(:@callbacks)).to eq(callbacks)
+ end
+ end
+
+ describe '#generate_response' do
+ subject(:service) { described_class.new(assistant: assistant, conversation: conversation) }
+
+ it 'builds agents and wires them together' do
+ expect(assistant).to receive(:agent).and_return(mock_agent)
+ scenarios_relation = instance_double(Captain::Scenario)
+ allow(scenarios_relation).to receive(:enabled).and_return([scenario])
+ expect(assistant).to receive(:scenarios).and_return(scenarios_relation)
+ expect(scenario).to receive(:agent).and_return(mock_scenario_agent)
+ expect(mock_agent).to receive(:register_handoffs).with(mock_scenario_agent)
+ expect(mock_scenario_agent).to receive(:register_handoffs).with(mock_agent)
+
+ service.generate_response(message_history: message_history)
+ end
+
+ it 'creates runner with agents' do
+ expect(Agents::Runner).to receive(:with_agents).with(mock_agent, mock_scenario_agent)
+
+ service.generate_response(message_history: message_history)
+ end
+
+ it 'runs agent with extracted user message and context' do
+ expected_context = {
+ conversation_history: [
+ { role: :user, content: 'Hello there', agent_name: nil },
+ { role: :assistant, content: 'Hi! How can I help you?', agent_name: 'Assistant' },
+ { role: :user, content: 'I need help with my account', agent_name: nil }
+ ],
+ state: hash_including(
+ account_id: account.id,
+ assistant_id: assistant.id,
+ conversation: hash_including(id: conversation.id),
+ contact: hash_including(id: contact.id)
+ )
+ }
+
+ expect(mock_runner).to receive(:run).with(
+ 'I need help with my account',
+ context: expected_context
+ )
+
+ service.generate_response(message_history: message_history)
+ end
+
+ it 'processes and formats agent result' do
+ result = service.generate_response(message_history: message_history)
+
+ expect(result).to eq({ 'response' => 'Test response' })
+ end
+
+ context 'when no scenarios are enabled' do
+ before do
+ scenarios_relation = instance_double(Captain::Scenario)
+ allow(scenarios_relation).to receive(:enabled).and_return([])
+ allow(assistant).to receive(:scenarios).and_return(scenarios_relation)
+ end
+
+ it 'only uses assistant agent' do
+ expect(Agents::Runner).to receive(:with_agents).with(mock_agent)
+ expect(mock_agent).not_to receive(:register_handoffs)
+
+ service.generate_response(message_history: message_history)
+ end
+ end
+
+ context 'when agent result is a string' do
+ let(:mock_result) { instance_double(Agents::RunResult, output: 'Simple string response') }
+
+ it 'formats string response correctly' do
+ result = service.generate_response(message_history: message_history)
+
+ expect(result).to eq({
+ 'response' => 'Simple string response',
+ 'reasoning' => 'Processed by agent'
+ })
+ end
+ end
+
+ context 'when an error occurs' do
+ let(:error) { StandardError.new('Test error') }
+
+ before do
+ allow(mock_runner).to receive(:run).and_raise(error)
+ allow(ChatwootExceptionTracker).to receive(:new).and_return(
+ instance_double(ChatwootExceptionTracker, capture_exception: true)
+ )
+ end
+
+ it 'captures exception and returns error response' do
+ expect(ChatwootExceptionTracker).to receive(:new).with(error, account: conversation.account)
+
+ result = service.generate_response(message_history: message_history)
+
+ expect(result).to eq({
+ 'response' => 'conversation_handoff',
+ 'reasoning' => 'Error occurred: Test error'
+ })
+ end
+
+ it 'logs error details' do
+ expect(Rails.logger).to receive(:error).with('[Captain V2] AgentRunnerService error: Test error')
+ expect(Rails.logger).to receive(:error).with(kind_of(String))
+
+ service.generate_response(message_history: message_history)
+ end
+
+ context 'when conversation is nil' do
+ subject(:service) { described_class.new(assistant: assistant, conversation: nil) }
+
+ it 'handles missing conversation gracefully' do
+ expect(ChatwootExceptionTracker).to receive(:new).with(error, account: nil)
+
+ result = service.generate_response(message_history: message_history)
+
+ expect(result).to eq({
+ 'response' => 'conversation_handoff',
+ 'reasoning' => 'Error occurred: Test error'
+ })
+ end
+ end
+ end
+ end
+
+ describe '#build_context' do
+ subject(:service) { described_class.new(assistant: assistant, conversation: conversation) }
+
+ it 'builds context with conversation history and state' do
+ context = service.send(:build_context, message_history)
+
+ expect(context).to include(
+ conversation_history: array_including(
+ { role: :user, content: 'Hello there', agent_name: nil },
+ { role: :assistant, content: 'Hi! How can I help you?', agent_name: 'Assistant' }
+ ),
+ state: hash_including(
+ account_id: account.id,
+ assistant_id: assistant.id
+ )
+ )
+ end
+
+ context 'with multimodal content' do
+ let(:multimodal_message_history) do
+ [
+ {
+ role: 'user',
+ content: [
+ { type: 'text', text: 'Can you help with this image?' },
+ { type: 'image_url', image_url: { url: 'https://example.com/image.jpg' } }
+ ]
+ }
+ ]
+ end
+
+ it 'extracts text content from multimodal messages' do
+ context = service.send(:build_context, multimodal_message_history)
+
+ expect(context[:conversation_history].first[:content]).to eq('Can you help with this image?')
+ end
+ end
+ end
+
+ describe '#extract_last_user_message' do
+ subject(:service) { described_class.new(assistant: assistant, conversation: conversation) }
+
+ it 'extracts the last user message' do
+ result = service.send(:extract_last_user_message, message_history)
+
+ expect(result).to eq('I need help with my account')
+ end
+ end
+
+ describe '#extract_text_from_content' do
+ subject(:service) { described_class.new(assistant: assistant, conversation: conversation) }
+
+ it 'extracts text from string content' do
+ result = service.send(:extract_text_from_content, 'Simple text')
+
+ expect(result).to eq('Simple text')
+ end
+
+ it 'extracts response from hash content' do
+ content = { 'response' => 'Hash response' }
+ result = service.send(:extract_text_from_content, content)
+
+ expect(result).to eq('Hash response')
+ end
+
+ it 'extracts text from multimodal array content' do
+ content = [
+ { type: 'text', text: 'First part' },
+ { type: 'image_url', image_url: { url: 'image.jpg' } },
+ { type: 'text', text: 'Second part' }
+ ]
+
+ result = service.send(:extract_text_from_content, content)
+
+ expect(result).to eq('First part Second part')
+ end
+ end
+
+ describe '#build_state' do
+ subject(:service) { described_class.new(assistant: assistant, conversation: conversation) }
+
+ it 'builds state with assistant and account information' do
+ state = service.send(:build_state)
+
+ expect(state).to include(
+ account_id: account.id,
+ assistant_id: assistant.id,
+ assistant_config: assistant.config
+ )
+ end
+
+ it 'includes conversation attributes when conversation is present' do
+ state = service.send(:build_state)
+
+ expect(state[:conversation]).to include(
+ id: conversation.id,
+ inbox_id: inbox.id,
+ contact_id: contact.id,
+ status: conversation.status
+ )
+ end
+
+ it 'includes contact attributes when contact is present' do
+ state = service.send(:build_state)
+
+ expect(state[:contact]).to include(
+ id: contact.id,
+ name: contact.name,
+ email: contact.email
+ )
+ end
+
+ context 'when conversation is nil' do
+ subject(:service) { described_class.new(assistant: assistant, conversation: nil) }
+
+ it 'builds state without conversation and contact' do
+ state = service.send(:build_state)
+
+ expect(state).to include(
+ account_id: account.id,
+ assistant_id: assistant.id,
+ assistant_config: assistant.config
+ )
+ expect(state).not_to have_key(:conversation)
+ expect(state).not_to have_key(:contact)
+ end
+ end
+ end
+
+ describe 'constants' do
+ it 'defines conversation state attributes' do
+ expect(described_class::CONVERSATION_STATE_ATTRIBUTES).to include(
+ :id, :display_id, :inbox_id, :contact_id, :status, :priority
+ )
+ end
+
+ it 'defines contact state attributes' do
+ expect(described_class::CONTACT_STATE_ATTRIBUTES).to include(
+ :id, :name, :email, :phone_number, :identifier, :contact_type
+ )
+ end
+ end
+end
From a42b99ada0621e2805a39038152dbf211fcac17f Mon Sep 17 00:00:00 2001
From: Shivam Mishra
Date: Thu, 14 Aug 2025 14:33:32 +0530
Subject: [PATCH 16/26] fix(sdk): Ignore messages from a different origin and
sanitize URLs (#8879)
This PR includes some specific security related fixes
1. Validate the origin of any message events
2. Sanitize URLs before opening them
---------
Co-authored-by: Pranav
Co-authored-by: Muhsin Keloth
---
app/javascript/sdk/IFrameHelper.js | 33 ++++++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/app/javascript/sdk/IFrameHelper.js b/app/javascript/sdk/IFrameHelper.js
index 3ab1ba1f5..25f90912d 100644
--- a/app/javascript/sdk/IFrameHelper.js
+++ b/app/javascript/sdk/IFrameHelper.js
@@ -50,11 +50,35 @@ const updateCampaignReadStatus = baseDomain => {
});
};
+const sanitizeURL = url => {
+ if (url === '') return '';
+
+ try {
+ // any invalid url will not be accepted
+ // example - JaVaScRiP%0at:alert(document.domain)"
+ // this has an obfuscated javascript protocol
+ const parsedURL = new URL(url);
+
+ // filter out dangerous protocols like `javascript`, `data`, `vbscript`
+ if (!['https', 'http'].includes(parsedURL.protocol)) {
+ throw new Error('Invalid Protocol');
+ }
+ } catch (e) {
+ // eslint-disable-next-line no-console
+ console.error('Invalid URL', e);
+ }
+
+ return 'about:blank'; // blank page URL
+};
+
export const IFrameHelper = {
getUrl({ baseUrl, websiteToken }) {
+ baseUrl = sanitizeURL(baseUrl);
return `${baseUrl}/widget?website_token=${websiteToken}`;
},
createFrame: ({ baseUrl, websiteToken }) => {
+ baseUrl = sanitizeURL(baseUrl);
+
if (IFrameHelper.getAppFrame()) {
return;
}
@@ -102,10 +126,12 @@ export const IFrameHelper = {
window.onmessage = e => {
if (
typeof e.data !== 'string' ||
- e.data.indexOf('chatwoot-widget:') !== 0
+ e.data.indexOf('chatwoot-widget:') !== 0 ||
+ e.origin !== window.location.origin
) {
return;
}
+
const message = JSON.parse(e.data.replace('chatwoot-widget:', ''));
if (typeof IFrameHelper.events[message.event] === 'function') {
IFrameHelper.events[message.event](message);
@@ -140,7 +166,9 @@ export const IFrameHelper = {
},
setupAudioListeners: () => {
- const { baseUrl = '' } = window.$chatwoot;
+ let { baseUrl = '' } = window.$chatwoot;
+ baseUrl = sanitizeURL(baseUrl);
+
getAlertAudio(baseUrl, { type: 'widget', alertTone: 'ding' }).then(() =>
initOnEvents.forEach(event => {
document.removeEventListener(
@@ -234,6 +262,7 @@ export const IFrameHelper = {
},
popoutChatWindow: ({ baseUrl, websiteToken, locale }) => {
+ baseUrl = sanitizeURL(baseUrl);
const cwCookie = Cookies.get('cw_conversation');
window.$chatwoot.toggle('close');
popoutChatWindow(baseUrl, websiteToken, locale, cwCookie);
From 1f03fc4dc35ec675b65c75ec528ec151b8c10e32 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 14 Aug 2025 11:14:30 +0200
Subject: [PATCH 17/26] chore(deps): bump activerecord from 7.1.5.1 to 7.1.5.2
(#12195)
Bumps [activerecord](https://github.com/rails/rails) from 7.1.5.1 to
7.1.5.2.
Release notes
Sourced from activerecord's
releases.
7.1.5.2
Active Support
Active Model
Active Record
Action View
Action Pack
Active Job
Action Mailer
Action Cable
Active Storage
Remove dangerous transformations
[CVE-2025-24293]
... (truncated)
Commits
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/chatwoot/chatwoot/network/alerts).
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
Gemfile.lock | 112 +++++++++++++++++++++++++--------------------------
1 file changed, 56 insertions(+), 56 deletions(-)
diff --git a/Gemfile.lock b/Gemfile.lock
index 1c64914b3..8a0eb4c48 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -25,35 +25,35 @@ GIT
GEM
remote: https://rubygems.org/
specs:
- actioncable (7.1.5.1)
- actionpack (= 7.1.5.1)
- activesupport (= 7.1.5.1)
+ actioncable (7.1.5.2)
+ actionpack (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
- actionmailbox (7.1.5.1)
- actionpack (= 7.1.5.1)
- activejob (= 7.1.5.1)
- activerecord (= 7.1.5.1)
- activestorage (= 7.1.5.1)
- activesupport (= 7.1.5.1)
+ actionmailbox (7.1.5.2)
+ actionpack (= 7.1.5.2)
+ activejob (= 7.1.5.2)
+ activerecord (= 7.1.5.2)
+ activestorage (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
- actionmailer (7.1.5.1)
- actionpack (= 7.1.5.1)
- actionview (= 7.1.5.1)
- activejob (= 7.1.5.1)
- activesupport (= 7.1.5.1)
+ actionmailer (7.1.5.2)
+ actionpack (= 7.1.5.2)
+ actionview (= 7.1.5.2)
+ activejob (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.2)
- actionpack (7.1.5.1)
- actionview (= 7.1.5.1)
- activesupport (= 7.1.5.1)
+ actionpack (7.1.5.2)
+ actionview (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4)
@@ -61,38 +61,38 @@ GEM
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
- actiontext (7.1.5.1)
- actionpack (= 7.1.5.1)
- activerecord (= 7.1.5.1)
- activestorage (= 7.1.5.1)
- activesupport (= 7.1.5.1)
+ actiontext (7.1.5.2)
+ actionpack (= 7.1.5.2)
+ activerecord (= 7.1.5.2)
+ activestorage (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
- actionview (7.1.5.1)
- activesupport (= 7.1.5.1)
+ actionview (7.1.5.2)
+ activesupport (= 7.1.5.2)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
active_record_query_trace (1.8)
- activejob (7.1.5.1)
- activesupport (= 7.1.5.1)
+ activejob (7.1.5.2)
+ activesupport (= 7.1.5.2)
globalid (>= 0.3.6)
- activemodel (7.1.5.1)
- activesupport (= 7.1.5.1)
- activerecord (7.1.5.1)
- activemodel (= 7.1.5.1)
- activesupport (= 7.1.5.1)
+ activemodel (7.1.5.2)
+ activesupport (= 7.1.5.2)
+ activerecord (7.1.5.2)
+ activemodel (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
timeout (>= 0.4.0)
activerecord-import (2.1.0)
activerecord (>= 4.2)
- activestorage (7.1.5.1)
- actionpack (= 7.1.5.1)
- activejob (= 7.1.5.1)
- activerecord (= 7.1.5.1)
- activesupport (= 7.1.5.1)
+ activestorage (7.1.5.2)
+ actionpack (= 7.1.5.2)
+ activejob (= 7.1.5.2)
+ activerecord (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
marcel (~> 1.0)
- activesupport (7.1.5.1)
+ activesupport (7.1.5.2)
base64
benchmark (>= 0.3)
bigdecimal
@@ -155,10 +155,10 @@ GEM
barnes (0.0.9)
multi_json (~> 1)
statsd-ruby (~> 1.1)
- base64 (0.2.0)
+ base64 (0.3.0)
bcrypt (3.1.20)
- benchmark (0.4.0)
- bigdecimal (3.1.9)
+ benchmark (0.4.1)
+ bigdecimal (3.2.2)
bindex (0.8.1)
bootsnap (1.16.0)
msgpack (~> 1.2)
@@ -599,20 +599,20 @@ GEM
rackup (1.0.1)
rack (< 3)
webrick
- rails (7.1.5.1)
- actioncable (= 7.1.5.1)
- actionmailbox (= 7.1.5.1)
- actionmailer (= 7.1.5.1)
- actionpack (= 7.1.5.1)
- actiontext (= 7.1.5.1)
- actionview (= 7.1.5.1)
- activejob (= 7.1.5.1)
- activemodel (= 7.1.5.1)
- activerecord (= 7.1.5.1)
- activestorage (= 7.1.5.1)
- activesupport (= 7.1.5.1)
+ rails (7.1.5.2)
+ actioncable (= 7.1.5.2)
+ actionmailbox (= 7.1.5.2)
+ actionmailer (= 7.1.5.2)
+ actionpack (= 7.1.5.2)
+ actiontext (= 7.1.5.2)
+ actionview (= 7.1.5.2)
+ activejob (= 7.1.5.2)
+ activemodel (= 7.1.5.2)
+ activerecord (= 7.1.5.2)
+ activestorage (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
bundler (>= 1.15.0)
- railties (= 7.1.5.1)
+ railties (= 7.1.5.2)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
@@ -620,9 +620,9 @@ GEM
rails-html-sanitizer (1.6.1)
loofah (~> 2.21)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
- railties (7.1.5.1)
- actionpack (= 7.1.5.1)
- activesupport (= 7.1.5.1)
+ railties (7.1.5.2)
+ actionpack (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
irb
rackup (>= 1.0.0)
rake (>= 12.2)
From ee773f31eb961cfd01ce9697cd8710c273554e4b Mon Sep 17 00:00:00 2001
From: Chatwoot Bot <92152627+chatwoot-bot@users.noreply.github.com>
Date: Thu, 14 Aug 2025 03:00:00 -0700
Subject: [PATCH 18/26] chore: Update translations (#12167)
Co-authored-by: Muhsin Keloth
---
.../dashboard/i18n/locale/am/automation.json | 1 +
.../i18n/locale/am/integrations.json | 3 +-
.../i18n/locale/am/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/ar/automation.json | 1 +
.../i18n/locale/ar/integrations.json | 3 +-
.../i18n/locale/ar/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/az/automation.json | 1 +
.../i18n/locale/az/integrations.json | 3 +-
.../i18n/locale/az/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/bg/automation.json | 1 +
.../i18n/locale/bg/integrations.json | 3 +-
.../i18n/locale/bg/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/ca/automation.json | 1 +
.../i18n/locale/ca/integrations.json | 3 +-
.../i18n/locale/ca/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/cs/automation.json | 1 +
.../i18n/locale/cs/integrations.json | 3 +-
.../i18n/locale/cs/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/da/automation.json | 1 +
.../i18n/locale/da/integrations.json | 3 +-
.../i18n/locale/da/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/de/automation.json | 1 +
.../i18n/locale/de/integrations.json | 3 +-
.../i18n/locale/de/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/el/automation.json | 1 +
.../i18n/locale/el/integrations.json | 3 +-
.../i18n/locale/el/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/es/automation.json | 1 +
.../i18n/locale/es/integrations.json | 3 +-
.../i18n/locale/es/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/fa/automation.json | 1 +
.../i18n/locale/fa/integrations.json | 3 +-
.../i18n/locale/fa/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/fi/automation.json | 1 +
.../i18n/locale/fi/integrations.json | 3 +-
.../i18n/locale/fi/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/fr/automation.json | 1 +
.../i18n/locale/fr/integrations.json | 3 +-
.../i18n/locale/fr/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/he/automation.json | 1 +
.../i18n/locale/he/integrations.json | 3 +-
.../i18n/locale/he/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/hi/automation.json | 1 +
.../i18n/locale/hi/integrations.json | 3 +-
.../i18n/locale/hi/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/hr/automation.json | 1 +
.../i18n/locale/hr/integrations.json | 3 +-
.../i18n/locale/hr/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/hu/automation.json | 1 +
.../i18n/locale/hu/integrations.json | 3 +-
.../i18n/locale/hu/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/hy/automation.json | 1 +
.../i18n/locale/hy/integrations.json | 3 +-
.../i18n/locale/hy/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/id/automation.json | 1 +
.../i18n/locale/id/integrations.json | 3 +-
.../i18n/locale/id/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/is/automation.json | 1 +
.../i18n/locale/is/integrations.json | 3 +-
.../i18n/locale/is/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/it/automation.json | 1 +
.../i18n/locale/it/integrations.json | 3 +-
.../i18n/locale/it/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/ja/automation.json | 1 +
.../i18n/locale/ja/integrations.json | 3 +-
.../i18n/locale/ja/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/ka/automation.json | 1 +
.../i18n/locale/ka/integrations.json | 3 +-
.../i18n/locale/ka/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/ko/automation.json | 1 +
.../i18n/locale/ko/integrations.json | 3 +-
.../i18n/locale/ko/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/lt/automation.json | 1 +
.../i18n/locale/lt/integrations.json | 3 +-
.../i18n/locale/lt/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/lv/automation.json | 1 +
.../i18n/locale/lv/integrations.json | 3 +-
.../i18n/locale/lv/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/ml/automation.json | 1 +
.../i18n/locale/ml/integrations.json | 3 +-
.../i18n/locale/ml/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/ms/automation.json | 1 +
.../i18n/locale/ms/integrations.json | 3 +-
.../i18n/locale/ms/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/ne/automation.json | 1 +
.../i18n/locale/ne/integrations.json | 3 +-
.../i18n/locale/ne/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/nl/automation.json | 1 +
.../i18n/locale/nl/integrations.json | 3 +-
.../i18n/locale/nl/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/no/automation.json | 1 +
.../i18n/locale/no/integrations.json | 3 +-
.../i18n/locale/no/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/pl/automation.json | 1 +
.../i18n/locale/pl/integrations.json | 3 +-
.../i18n/locale/pl/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/pt/automation.json | 1 +
.../i18n/locale/pt/integrations.json | 3 +-
.../i18n/locale/pt/whatsappTemplates.json | 69 ++++++++++++-------
.../i18n/locale/pt_BR/automation.json | 1 +
.../i18n/locale/pt_BR/integrations.json | 3 +-
.../i18n/locale/pt_BR/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/ro/automation.json | 1 +
.../i18n/locale/ro/integrations.json | 3 +-
.../i18n/locale/ro/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/ru/automation.json | 1 +
.../i18n/locale/ru/integrations.json | 3 +-
.../i18n/locale/ru/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/sh/automation.json | 1 +
.../i18n/locale/sh/integrations.json | 3 +-
.../i18n/locale/sh/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/sk/automation.json | 1 +
.../i18n/locale/sk/integrations.json | 3 +-
.../i18n/locale/sk/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/sl/automation.json | 1 +
.../i18n/locale/sl/integrations.json | 3 +-
.../i18n/locale/sl/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/sq/automation.json | 1 +
.../i18n/locale/sq/integrations.json | 3 +-
.../i18n/locale/sq/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/sr/automation.json | 1 +
.../i18n/locale/sr/integrations.json | 3 +-
.../i18n/locale/sr/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/sv/automation.json | 1 +
.../i18n/locale/sv/integrations.json | 3 +-
.../i18n/locale/sv/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/ta/automation.json | 1 +
.../i18n/locale/ta/integrations.json | 3 +-
.../i18n/locale/ta/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/th/automation.json | 1 +
.../i18n/locale/th/integrations.json | 3 +-
.../i18n/locale/th/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/tl/automation.json | 1 +
.../i18n/locale/tl/integrations.json | 3 +-
.../i18n/locale/tl/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/tr/automation.json | 1 +
.../i18n/locale/tr/integrations.json | 3 +-
.../i18n/locale/tr/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/uk/automation.json | 1 +
.../i18n/locale/uk/integrations.json | 3 +-
.../i18n/locale/uk/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/ur/automation.json | 1 +
.../i18n/locale/ur/integrations.json | 3 +-
.../i18n/locale/ur/whatsappTemplates.json | 69 ++++++++++++-------
.../i18n/locale/ur_IN/automation.json | 1 +
.../i18n/locale/ur_IN/integrations.json | 3 +-
.../i18n/locale/ur_IN/whatsappTemplates.json | 69 ++++++++++++-------
.../dashboard/i18n/locale/vi/automation.json | 1 +
.../i18n/locale/vi/integrations.json | 3 +-
.../i18n/locale/vi/whatsappTemplates.json | 69 ++++++++++++-------
.../i18n/locale/zh_CN/automation.json | 1 +
.../i18n/locale/zh_CN/integrations.json | 3 +-
.../i18n/locale/zh_CN/whatsappTemplates.json | 69 ++++++++++++-------
.../i18n/locale/zh_TW/automation.json | 1 +
.../i18n/locale/zh_TW/integrations.json | 3 +-
.../i18n/locale/zh_TW/whatsappTemplates.json | 69 ++++++++++++-------
app/javascript/widget/i18n/locale/am.json | 5 ++
app/javascript/widget/i18n/locale/ar.json | 5 ++
app/javascript/widget/i18n/locale/az.json | 5 ++
app/javascript/widget/i18n/locale/bg.json | 5 ++
app/javascript/widget/i18n/locale/ca.json | 5 ++
app/javascript/widget/i18n/locale/cs.json | 5 ++
app/javascript/widget/i18n/locale/da.json | 5 ++
app/javascript/widget/i18n/locale/de.json | 5 ++
app/javascript/widget/i18n/locale/el.json | 5 ++
app/javascript/widget/i18n/locale/es.json | 5 ++
app/javascript/widget/i18n/locale/fa.json | 5 ++
app/javascript/widget/i18n/locale/fi.json | 5 ++
app/javascript/widget/i18n/locale/fr.json | 5 ++
app/javascript/widget/i18n/locale/he.json | 5 ++
app/javascript/widget/i18n/locale/hi.json | 5 ++
app/javascript/widget/i18n/locale/hr.json | 5 ++
app/javascript/widget/i18n/locale/hu.json | 5 ++
app/javascript/widget/i18n/locale/hy.json | 5 ++
app/javascript/widget/i18n/locale/id.json | 5 ++
app/javascript/widget/i18n/locale/is.json | 5 ++
app/javascript/widget/i18n/locale/it.json | 5 ++
app/javascript/widget/i18n/locale/ja.json | 5 ++
app/javascript/widget/i18n/locale/ka.json | 5 ++
app/javascript/widget/i18n/locale/ko.json | 5 ++
app/javascript/widget/i18n/locale/lt.json | 5 ++
app/javascript/widget/i18n/locale/lv.json | 5 ++
app/javascript/widget/i18n/locale/ml.json | 5 ++
app/javascript/widget/i18n/locale/ms.json | 5 ++
app/javascript/widget/i18n/locale/ne.json | 5 ++
app/javascript/widget/i18n/locale/nl.json | 5 ++
app/javascript/widget/i18n/locale/no.json | 5 ++
app/javascript/widget/i18n/locale/pl.json | 5 ++
app/javascript/widget/i18n/locale/pt.json | 5 ++
app/javascript/widget/i18n/locale/pt_BR.json | 5 ++
app/javascript/widget/i18n/locale/ro.json | 5 ++
app/javascript/widget/i18n/locale/ru.json | 5 ++
app/javascript/widget/i18n/locale/sh.json | 5 ++
app/javascript/widget/i18n/locale/sk.json | 5 ++
app/javascript/widget/i18n/locale/sl.json | 5 ++
app/javascript/widget/i18n/locale/sq.json | 5 ++
app/javascript/widget/i18n/locale/sr.json | 5 ++
app/javascript/widget/i18n/locale/sv.json | 5 ++
app/javascript/widget/i18n/locale/ta.json | 5 ++
app/javascript/widget/i18n/locale/th.json | 5 ++
app/javascript/widget/i18n/locale/tl.json | 5 ++
app/javascript/widget/i18n/locale/tr.json | 5 ++
app/javascript/widget/i18n/locale/uk.json | 5 ++
app/javascript/widget/i18n/locale/ur.json | 5 ++
app/javascript/widget/i18n/locale/ur_IN.json | 5 ++
app/javascript/widget/i18n/locale/vi.json | 5 ++
app/javascript/widget/i18n/locale/zh_CN.json | 5 ++
app/javascript/widget/i18n/locale/zh_TW.json | 5 ++
208 files changed, 2652 insertions(+), 1404 deletions(-)
diff --git a/app/javascript/dashboard/i18n/locale/am/automation.json b/app/javascript/dashboard/i18n/locale/am/automation.json
index cf63de81c..80274f488 100644
--- a/app/javascript/dashboard/i18n/locale/am/automation.json
+++ b/app/javascript/dashboard/i18n/locale/am/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/am/integrations.json b/app/javascript/dashboard/i18n/locale/am/integrations.json
index 1614931a0..be9281284 100644
--- a/app/javascript/dashboard/i18n/locale/am/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/am/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/am/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/am/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/am/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/am/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ar/automation.json b/app/javascript/dashboard/i18n/locale/ar/automation.json
index be7107f4c..788652a04 100644
--- a/app/javascript/dashboard/i18n/locale/ar/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ar/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "تم إنشاء المحادثة",
"CONVERSATION_UPDATED": "تم تحديث المحادثة",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ar/integrations.json b/app/javascript/dashboard/i18n/locale/ar/integrations.json
index f00d3fe1d..bc17130c1 100644
--- a/app/javascript/dashboard/i18n/locale/ar/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ar/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "الخصائص",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ar/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ar/whatsappTemplates.json
index 110eeb8af..247af32c4 100644
--- a/app/javascript/dashboard/i18n/locale/ar/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ar/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "قوالب الواتساب",
- "SUBTITLE": "حدد القالب الذي تريد إرساله",
- "TEMPLATE_SELECTED_SUBTITLE": "معالجة {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "نماذج البحث",
- "NO_TEMPLATES_FOUND": "لم يتم العثور على قوالب",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "اللغة",
- "TEMPLATE_BODY": "نص القالب",
- "CATEGORY": "الفئة"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "المتغيرات",
- "VARIABLE_PLACEHOLDER": "أدخل قيمة {variable}",
- "GO_BACK_LABEL": "العودة للخلف",
- "SEND_MESSAGE_LABEL": "إرسال الرسالة",
- "FORM_ERROR_MESSAGE": "يرجى ملء جميع المتغيرات قبل الإرسال"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "قوالب الواتساب",
+ "SUBTITLE": "حدد القالب الذي تريد إرساله",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "نماذج البحث",
+ "NO_TEMPLATES_FOUND": "لم يتم العثور على قوالب",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "الفئة",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "اللغة",
+ "TEMPLATE_BODY": "نص القالب",
+ "CATEGORY": "الفئة"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "المتغيرات",
+ "LANGUAGE": "اللغة",
+ "CATEGORY": "الفئة",
+ "VARIABLE_PLACEHOLDER": "أدخل قيمة {variable}",
+ "GO_BACK_LABEL": "العودة للخلف",
+ "SEND_MESSAGE_LABEL": "إرسال الرسالة",
+ "FORM_ERROR_MESSAGE": "يرجى ملء جميع المتغيرات قبل الإرسال",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/az/automation.json b/app/javascript/dashboard/i18n/locale/az/automation.json
index cf63de81c..80274f488 100644
--- a/app/javascript/dashboard/i18n/locale/az/automation.json
+++ b/app/javascript/dashboard/i18n/locale/az/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/az/integrations.json b/app/javascript/dashboard/i18n/locale/az/integrations.json
index 1614931a0..be9281284 100644
--- a/app/javascript/dashboard/i18n/locale/az/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/az/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/az/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/az/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/az/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/az/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/bg/automation.json b/app/javascript/dashboard/i18n/locale/bg/automation.json
index fe4d32743..006369305 100644
--- a/app/javascript/dashboard/i18n/locale/bg/automation.json
+++ b/app/javascript/dashboard/i18n/locale/bg/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/bg/integrations.json b/app/javascript/dashboard/i18n/locale/bg/integrations.json
index 6bcd3b584..1069559a6 100644
--- a/app/javascript/dashboard/i18n/locale/bg/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/bg/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/bg/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/bg/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/bg/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/bg/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ca/automation.json b/app/javascript/dashboard/i18n/locale/ca/automation.json
index e3570b417..d961c762a 100644
--- a/app/javascript/dashboard/i18n/locale/ca/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ca/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversa Creada",
"CONVERSATION_UPDATED": "Conversa Actualitzada",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ca/integrations.json b/app/javascript/dashboard/i18n/locale/ca/integrations.json
index 4607a2fe1..2668ce217 100644
--- a/app/javascript/dashboard/i18n/locale/ca/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ca/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Característiques",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ca/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ca/whatsappTemplates.json
index f078ec706..e0b132286 100644
--- a/app/javascript/dashboard/i18n/locale/ca/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ca/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Plantilles de Whatsapp",
- "SUBTITLE": "Selecciona la plantilla de whatsapp que vols enviar",
- "TEMPLATE_SELECTED_SUBTITLE": "Procés {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Cerca plantilles",
- "NO_TEMPLATES_FOUND": "No s'han trobat plantilles per a",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Idioma",
- "TEMPLATE_BODY": "Cos de la plantilla",
- "CATEGORY": "Categoria"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Introdueix el valor {variable}",
- "GO_BACK_LABEL": "Torna enrere",
- "SEND_MESSAGE_LABEL": "Envia missatge",
- "FORM_ERROR_MESSAGE": "Omple totes les variables abans d'enviar-les"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Plantilles de Whatsapp",
+ "SUBTITLE": "Selecciona la plantilla de whatsapp que vols enviar",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Cerca plantilles",
+ "NO_TEMPLATES_FOUND": "No s'han trobat plantilles per a",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Categoria",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Idioma",
+ "TEMPLATE_BODY": "Cos de la plantilla",
+ "CATEGORY": "Categoria"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Idioma",
+ "CATEGORY": "Categoria",
+ "VARIABLE_PLACEHOLDER": "Introdueix el valor {variable}",
+ "GO_BACK_LABEL": "Torna enrere",
+ "SEND_MESSAGE_LABEL": "Envia missatge",
+ "FORM_ERROR_MESSAGE": "Omple totes les variables abans d'enviar-les",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/cs/automation.json b/app/javascript/dashboard/i18n/locale/cs/automation.json
index d8dd12abd..6733fa929 100644
--- a/app/javascript/dashboard/i18n/locale/cs/automation.json
+++ b/app/javascript/dashboard/i18n/locale/cs/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Zpráva vytvořena",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Konverzace otevřena"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/cs/integrations.json b/app/javascript/dashboard/i18n/locale/cs/integrations.json
index 9b55bf386..26bc11c0c 100644
--- a/app/javascript/dashboard/i18n/locale/cs/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/cs/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Funkce",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/cs/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/cs/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/cs/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/cs/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/da/automation.json b/app/javascript/dashboard/i18n/locale/da/automation.json
index 7910667a9..372422cfc 100644
--- a/app/javascript/dashboard/i18n/locale/da/automation.json
+++ b/app/javascript/dashboard/i18n/locale/da/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Samtale Oprettet",
"CONVERSATION_UPDATED": "Samtale Opdateret",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/da/integrations.json b/app/javascript/dashboard/i18n/locale/da/integrations.json
index 8710dc6d8..c4b498a3a 100644
--- a/app/javascript/dashboard/i18n/locale/da/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/da/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Funktioner",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/da/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/da/whatsappTemplates.json
index 3acb3acb3..34699398c 100644
--- a/app/javascript/dashboard/i18n/locale/da/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/da/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Skabeloner",
- "SUBTITLE": "Vælg den whatsapp skabelon, du vil sende",
- "TEMPLATE_SELECTED_SUBTITLE": "Proces {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Søg Skabeloner",
- "NO_TEMPLATES_FOUND": "Ingen skabeloner fundet for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Sprog",
- "TEMPLATE_BODY": "Skabelon Krop",
- "CATEGORY": "Kategori"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variabler",
- "VARIABLE_PLACEHOLDER": "Indtast {variable} værdi",
- "GO_BACK_LABEL": "Gå Tilbage",
- "SEND_MESSAGE_LABEL": "Send Besked",
- "FORM_ERROR_MESSAGE": "Udfyld venligst alle variabler før afsendelse"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Skabeloner",
+ "SUBTITLE": "Vælg den whatsapp skabelon, du vil sende",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Søg Skabeloner",
+ "NO_TEMPLATES_FOUND": "Ingen skabeloner fundet for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Kategori",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Sprog",
+ "TEMPLATE_BODY": "Skabelon Krop",
+ "CATEGORY": "Kategori"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variabler",
+ "LANGUAGE": "Sprog",
+ "CATEGORY": "Kategori",
+ "VARIABLE_PLACEHOLDER": "Indtast {variable} værdi",
+ "GO_BACK_LABEL": "Gå Tilbage",
+ "SEND_MESSAGE_LABEL": "Send Besked",
+ "FORM_ERROR_MESSAGE": "Udfyld venligst alle variabler før afsendelse",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/de/automation.json b/app/javascript/dashboard/i18n/locale/de/automation.json
index 20e343e0a..b6cef93e1 100644
--- a/app/javascript/dashboard/i18n/locale/de/automation.json
+++ b/app/javascript/dashboard/i18n/locale/de/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Konversation erstellt",
"CONVERSATION_UPDATED": "Konversation aktualisiert",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/de/integrations.json b/app/javascript/dashboard/i18n/locale/de/integrations.json
index fb78159f9..060389c52 100644
--- a/app/javascript/dashboard/i18n/locale/de/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/de/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Funktionen",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/de/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/de/whatsappTemplates.json
index b5f1885ae..87f5c6a2c 100644
--- a/app/javascript/dashboard/i18n/locale/de/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/de/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "WhatsApp-Vorlagen",
- "SUBTITLE": "Wählen Sie die WhatsApp-Vorlage aus, die Sie senden möchten",
- "TEMPLATE_SELECTED_SUBTITLE": "Verarbeite {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Vorlagen suchen",
- "NO_TEMPLATES_FOUND": "Keine Vorlagen gefunden für",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Sprache",
- "TEMPLATE_BODY": "Vorlagenbody",
- "CATEGORY": "Kategorie"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variablen",
- "VARIABLE_PLACEHOLDER": "Geben Sie den Wert {variable} ein",
- "GO_BACK_LABEL": "Zurück",
- "SEND_MESSAGE_LABEL": "Nachricht senden",
- "FORM_ERROR_MESSAGE": "Bitte füllen Sie vor dem Absenden alle Variablen aus"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "WhatsApp-Vorlagen",
+ "SUBTITLE": "Wählen Sie die WhatsApp-Vorlage aus, die Sie senden möchten",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Vorlagen suchen",
+ "NO_TEMPLATES_FOUND": "Keine Vorlagen gefunden für",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Kategorie",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Sprache",
+ "TEMPLATE_BODY": "Vorlagenbody",
+ "CATEGORY": "Kategorie"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variablen",
+ "LANGUAGE": "Sprache",
+ "CATEGORY": "Kategorie",
+ "VARIABLE_PLACEHOLDER": "Geben Sie den Wert {variable} ein",
+ "GO_BACK_LABEL": "Zurück",
+ "SEND_MESSAGE_LABEL": "Nachricht senden",
+ "FORM_ERROR_MESSAGE": "Bitte füllen Sie vor dem Absenden alle Variablen aus",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/el/automation.json b/app/javascript/dashboard/i18n/locale/el/automation.json
index d474d9914..27afa3306 100644
--- a/app/javascript/dashboard/i18n/locale/el/automation.json
+++ b/app/javascript/dashboard/i18n/locale/el/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Δημιουργήθηκε Συνομιλία",
"CONVERSATION_UPDATED": "Η Συνομιλία Ενημερώθηκε",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/el/integrations.json b/app/javascript/dashboard/i18n/locale/el/integrations.json
index 599d1c7e2..488107d41 100644
--- a/app/javascript/dashboard/i18n/locale/el/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/el/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Χαρακτηριστικά",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/el/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/el/whatsappTemplates.json
index d78b9cb12..42b710727 100644
--- a/app/javascript/dashboard/i18n/locale/el/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/el/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Πρότυπα Whatsapp",
- "SUBTITLE": "Επιλέξτε το πρότυπο Whatsapp που θέλετε να στείλετε",
- "TEMPLATE_SELECTED_SUBTITLE": "Επεξεργασία {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Αναζήτηση Προτύπων",
- "NO_TEMPLATES_FOUND": "Δεν βρέθηκαν πρότυπα για",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Γλώσσα",
- "TEMPLATE_BODY": "Σώμα Προτύπου",
- "CATEGORY": "Κατηγορία"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Μεταβλητές",
- "VARIABLE_PLACEHOLDER": "Εισάγετε τιμή για {variable}",
- "GO_BACK_LABEL": "Πίσω",
- "SEND_MESSAGE_LABEL": "Αποστολή μηνύματος",
- "FORM_ERROR_MESSAGE": "Παρακαλώ συμπληρώστε όλες τις μεταβλητές πριν την αποστολή"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Πρότυπα Whatsapp",
+ "SUBTITLE": "Επιλέξτε το πρότυπο Whatsapp που θέλετε να στείλετε",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Αναζήτηση Προτύπων",
+ "NO_TEMPLATES_FOUND": "Δεν βρέθηκαν πρότυπα για",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Κατηγορία",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Γλώσσα",
+ "TEMPLATE_BODY": "Σώμα Προτύπου",
+ "CATEGORY": "Κατηγορία"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Μεταβλητές",
+ "LANGUAGE": "Γλώσσα",
+ "CATEGORY": "Κατηγορία",
+ "VARIABLE_PLACEHOLDER": "Εισάγετε τιμή για {variable}",
+ "GO_BACK_LABEL": "Πίσω",
+ "SEND_MESSAGE_LABEL": "Αποστολή μηνύματος",
+ "FORM_ERROR_MESSAGE": "Παρακαλώ συμπληρώστε όλες τις μεταβλητές πριν την αποστολή",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/es/automation.json b/app/javascript/dashboard/i18n/locale/es/automation.json
index a1f68a375..63b529aee 100644
--- a/app/javascript/dashboard/i18n/locale/es/automation.json
+++ b/app/javascript/dashboard/i18n/locale/es/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversación creada",
"CONVERSATION_UPDATED": "Conversación actualizada",
"MESSAGE_CREATED": "Mensaje creado",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversación abierta"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/es/integrations.json b/app/javascript/dashboard/i18n/locale/es/integrations.json
index fbf4754b8..ee297c2f8 100644
--- a/app/javascript/dashboard/i18n/locale/es/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/es/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Características",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/es/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/es/whatsappTemplates.json
index 49a89e381..06ceacb68 100644
--- a/app/javascript/dashboard/i18n/locale/es/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/es/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Plantillas de Whatsapp",
- "SUBTITLE": "Seleccione la plantilla de Whatsapp que desea enviar",
- "TEMPLATE_SELECTED_SUBTITLE": "Procesar {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Buscar plantillas",
- "NO_TEMPLATES_FOUND": "No se encontraron plantillas para",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Idioma",
- "TEMPLATE_BODY": "Cuerpo de plantilla",
- "CATEGORY": "Categoría"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Introduzca el valor de {variable}",
- "GO_BACK_LABEL": "Volver",
- "SEND_MESSAGE_LABEL": "Enviar mensaje",
- "FORM_ERROR_MESSAGE": "Por favor, rellene todas las variables antes de enviar"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Plantillas de Whatsapp",
+ "SUBTITLE": "Seleccione la plantilla de Whatsapp que desea enviar",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Buscar plantillas",
+ "NO_TEMPLATES_FOUND": "No se encontraron plantillas para",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Categoría",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Idioma",
+ "TEMPLATE_BODY": "Cuerpo de plantilla",
+ "CATEGORY": "Categoría"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Idioma",
+ "CATEGORY": "Categoría",
+ "VARIABLE_PLACEHOLDER": "Introduzca el valor de {variable}",
+ "GO_BACK_LABEL": "Volver",
+ "SEND_MESSAGE_LABEL": "Enviar mensaje",
+ "FORM_ERROR_MESSAGE": "Por favor, rellene todas las variables antes de enviar",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/fa/automation.json b/app/javascript/dashboard/i18n/locale/fa/automation.json
index 3e4ffd18e..3e02e4a69 100644
--- a/app/javascript/dashboard/i18n/locale/fa/automation.json
+++ b/app/javascript/dashboard/i18n/locale/fa/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "گفتگو ایجاد شد",
"CONVERSATION_UPDATED": "گفتگو به روز شد",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/fa/integrations.json b/app/javascript/dashboard/i18n/locale/fa/integrations.json
index 15e4417d5..18c95d245 100644
--- a/app/javascript/dashboard/i18n/locale/fa/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/fa/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "امکانات",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/fa/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/fa/whatsappTemplates.json
index 3b470e99f..ed5d76d1c 100644
--- a/app/javascript/dashboard/i18n/locale/fa/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/fa/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "قالب های واتساپ",
- "SUBTITLE": "قالب واتساپ مورد نظر برای ارسال را انتخاب کنید",
- "TEMPLATE_SELECTED_SUBTITLE": "فرآیند {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "جستجوی الگوها",
- "NO_TEMPLATES_FOUND": "هیچ قالبی برای",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "زبان",
- "TEMPLATE_BODY": "بدنه الگو",
- "CATEGORY": "دستهبندی"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "متغیرها",
- "VARIABLE_PLACEHOLDER": "مقدار {variable} را وارد کنید",
- "GO_BACK_LABEL": "بازگشت",
- "SEND_MESSAGE_LABEL": "ارسال پیام",
- "FORM_ERROR_MESSAGE": "لطفا قبل از ارسال همه متغیرها را پر کنید"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "قالب های واتساپ",
+ "SUBTITLE": "قالب واتساپ مورد نظر برای ارسال را انتخاب کنید",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "جستجوی الگوها",
+ "NO_TEMPLATES_FOUND": "هیچ قالبی برای",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "دستهبندی",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "زبان",
+ "TEMPLATE_BODY": "بدنه الگو",
+ "CATEGORY": "دستهبندی"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "متغیرها",
+ "LANGUAGE": "زبان",
+ "CATEGORY": "دستهبندی",
+ "VARIABLE_PLACEHOLDER": "مقدار {variable} را وارد کنید",
+ "GO_BACK_LABEL": "بازگشت",
+ "SEND_MESSAGE_LABEL": "ارسال پیام",
+ "FORM_ERROR_MESSAGE": "لطفا قبل از ارسال همه متغیرها را پر کنید",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/fi/automation.json b/app/javascript/dashboard/i18n/locale/fi/automation.json
index ec63918e7..740761ca5 100644
--- a/app/javascript/dashboard/i18n/locale/fi/automation.json
+++ b/app/javascript/dashboard/i18n/locale/fi/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/fi/integrations.json b/app/javascript/dashboard/i18n/locale/fi/integrations.json
index 1374fba42..378242517 100644
--- a/app/javascript/dashboard/i18n/locale/fi/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/fi/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Ominaisuudet",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/fi/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/fi/whatsappTemplates.json
index ae8bee085..337134e31 100644
--- a/app/javascript/dashboard/i18n/locale/fi/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/fi/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "WhatsApp-pohjat",
- "SUBTITLE": "Valitse WhatsApp-pohja, jonka haluat lähettää",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Etsi Pohjia",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Muuttujat",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Mene Takaisin",
- "SEND_MESSAGE_LABEL": "Lähetä Viesti",
- "FORM_ERROR_MESSAGE": "Täytä kaikki muuttujat ennen lähettämistä"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "WhatsApp-pohjat",
+ "SUBTITLE": "Valitse WhatsApp-pohja, jonka haluat lähettää",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Etsi Pohjia",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Muuttujat",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Mene Takaisin",
+ "SEND_MESSAGE_LABEL": "Lähetä Viesti",
+ "FORM_ERROR_MESSAGE": "Täytä kaikki muuttujat ennen lähettämistä",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/fr/automation.json b/app/javascript/dashboard/i18n/locale/fr/automation.json
index 500cbbdcf..11a1ddfe6 100644
--- a/app/javascript/dashboard/i18n/locale/fr/automation.json
+++ b/app/javascript/dashboard/i18n/locale/fr/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation créée",
"CONVERSATION_UPDATED": "Conversation mise à jour",
"MESSAGE_CREATED": "Message créé",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation ouverte"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/fr/integrations.json b/app/javascript/dashboard/i18n/locale/fr/integrations.json
index 0ace6565e..9ad0fb8fd 100644
--- a/app/javascript/dashboard/i18n/locale/fr/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/fr/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Fonctionnalités",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/fr/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/fr/whatsappTemplates.json
index 0d4538240..71d0685cb 100644
--- a/app/javascript/dashboard/i18n/locale/fr/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/fr/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Modèles WhatsApp",
- "SUBTITLE": "Sélectionnez le modèle whatsapp que vous souhaitez envoyer",
- "TEMPLATE_SELECTED_SUBTITLE": "Traiter {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Rechercher des modèles",
- "NO_TEMPLATES_FOUND": "Aucun modèle trouvé pour",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Langue",
- "TEMPLATE_BODY": "Corps du modèle",
- "CATEGORY": "Catégorie"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Entrez la valeur de {variable}",
- "GO_BACK_LABEL": "Retour",
- "SEND_MESSAGE_LABEL": "Envoyer un message",
- "FORM_ERROR_MESSAGE": "Veuillez remplir toutes les variables avant d'envoyer"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Modèles WhatsApp",
+ "SUBTITLE": "Sélectionnez le modèle whatsapp que vous souhaitez envoyer",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Rechercher des modèles",
+ "NO_TEMPLATES_FOUND": "Aucun modèle trouvé pour",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Catégorie",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Langue",
+ "TEMPLATE_BODY": "Corps du modèle",
+ "CATEGORY": "Catégorie"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Langue",
+ "CATEGORY": "Catégorie",
+ "VARIABLE_PLACEHOLDER": "Entrez la valeur de {variable}",
+ "GO_BACK_LABEL": "Retour",
+ "SEND_MESSAGE_LABEL": "Envoyer un message",
+ "FORM_ERROR_MESSAGE": "Veuillez remplir toutes les variables avant d'envoyer",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/he/automation.json b/app/javascript/dashboard/i18n/locale/he/automation.json
index e1be1df5c..6166c90a3 100644
--- a/app/javascript/dashboard/i18n/locale/he/automation.json
+++ b/app/javascript/dashboard/i18n/locale/he/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "השיחה נוצרה",
"CONVERSATION_UPDATED": "השיחה עודכנה",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "השיחה נפתחה"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/he/integrations.json b/app/javascript/dashboard/i18n/locale/he/integrations.json
index 16058633b..37388725a 100644
--- a/app/javascript/dashboard/i18n/locale/he/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/he/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "מאפיינים",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/he/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/he/whatsappTemplates.json
index 295b89a23..67b54f91f 100644
--- a/app/javascript/dashboard/i18n/locale/he/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/he/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "תבניות וואטסאפ",
- "SUBTITLE": "בחר את תבנית הווטסאפ שברצונך לשלוח",
- "TEMPLATE_SELECTED_SUBTITLE": "עיבוד {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "חפש תבניות",
- "NO_TEMPLATES_FOUND": "לא נמצאו תבניות עבור",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "שפה",
- "TEMPLATE_BODY": "גוף התבנית",
- "CATEGORY": "קטגוריה"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "משתנים",
- "VARIABLE_PLACEHOLDER": "הזן ערך {variable}",
- "GO_BACK_LABEL": "חזור",
- "SEND_MESSAGE_LABEL": "לשלוח הודעה",
- "FORM_ERROR_MESSAGE": "נא למלא את כל המשתנים לפני השליחה"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "תבניות וואטסאפ",
+ "SUBTITLE": "בחר את תבנית הווטסאפ שברצונך לשלוח",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "חפש תבניות",
+ "NO_TEMPLATES_FOUND": "לא נמצאו תבניות עבור",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "קטגוריה",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "שפה",
+ "TEMPLATE_BODY": "גוף התבנית",
+ "CATEGORY": "קטגוריה"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "משתנים",
+ "LANGUAGE": "שפה",
+ "CATEGORY": "קטגוריה",
+ "VARIABLE_PLACEHOLDER": "הזן ערך {variable}",
+ "GO_BACK_LABEL": "חזור",
+ "SEND_MESSAGE_LABEL": "לשלוח הודעה",
+ "FORM_ERROR_MESSAGE": "נא למלא את כל המשתנים לפני השליחה",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/hi/automation.json b/app/javascript/dashboard/i18n/locale/hi/automation.json
index cf63de81c..80274f488 100644
--- a/app/javascript/dashboard/i18n/locale/hi/automation.json
+++ b/app/javascript/dashboard/i18n/locale/hi/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/hi/integrations.json b/app/javascript/dashboard/i18n/locale/hi/integrations.json
index bbb1c6662..cab231d7d 100644
--- a/app/javascript/dashboard/i18n/locale/hi/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/hi/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/hi/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/hi/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/hi/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/hi/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/hr/automation.json b/app/javascript/dashboard/i18n/locale/hr/automation.json
index 8e1bcd7c4..65722bbf2 100644
--- a/app/javascript/dashboard/i18n/locale/hr/automation.json
+++ b/app/javascript/dashboard/i18n/locale/hr/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/hr/integrations.json b/app/javascript/dashboard/i18n/locale/hr/integrations.json
index 63f5370c1..09eb8edaa 100644
--- a/app/javascript/dashboard/i18n/locale/hr/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/hr/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/hr/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/hr/whatsappTemplates.json
index d943a13c1..ce82b426f 100644
--- a/app/javascript/dashboard/i18n/locale/hr/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/hr/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Predlošci",
- "SUBTITLE": "Izaberi whatsapp predložak koji želiš poslati",
- "TEMPLATE_SELECTED_SUBTITLE": "Proces {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Pretraži Predloške",
- "NO_TEMPLATES_FOUND": "Nije pronađen predložak za",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Jezik",
- "TEMPLATE_BODY": "Tijelo predloška",
- "CATEGORY": "Kategorija"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Varijable",
- "VARIABLE_PLACEHOLDER": "Unesi {variable} vrijednost",
- "GO_BACK_LABEL": "Nazad",
- "SEND_MESSAGE_LABEL": "Šalji poruku",
- "FORM_ERROR_MESSAGE": "Popuniti sve varijable prije slanja"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Predlošci",
+ "SUBTITLE": "Izaberi whatsapp predložak koji želiš poslati",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Pretraži Predloške",
+ "NO_TEMPLATES_FOUND": "Nije pronađen predložak za",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Kategorija",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Jezik",
+ "TEMPLATE_BODY": "Tijelo predloška",
+ "CATEGORY": "Kategorija"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Varijable",
+ "LANGUAGE": "Jezik",
+ "CATEGORY": "Kategorija",
+ "VARIABLE_PLACEHOLDER": "Unesi {variable} vrijednost",
+ "GO_BACK_LABEL": "Nazad",
+ "SEND_MESSAGE_LABEL": "Šalji poruku",
+ "FORM_ERROR_MESSAGE": "Popuniti sve varijable prije slanja",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/hu/automation.json b/app/javascript/dashboard/i18n/locale/hu/automation.json
index fc6accbe1..82873e610 100644
--- a/app/javascript/dashboard/i18n/locale/hu/automation.json
+++ b/app/javascript/dashboard/i18n/locale/hu/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Beszélgetés létrehozva",
"CONVERSATION_UPDATED": "Beszélgetés frissítve",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/hu/integrations.json b/app/javascript/dashboard/i18n/locale/hu/integrations.json
index 00196e987..33904dde3 100644
--- a/app/javascript/dashboard/i18n/locale/hu/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/hu/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Lehetőségek",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/hu/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/hu/whatsappTemplates.json
index 860ef1875..e28c69704 100644
--- a/app/javascript/dashboard/i18n/locale/hu/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/hu/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp sablonok",
- "SUBTITLE": "Válaszd ki a Whatsapp sablont",
- "TEMPLATE_SELECTED_SUBTITLE": "Feldolgozás: {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Sablon keresése",
- "NO_TEMPLATES_FOUND": "Nem található sablon erre:",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Nyelv",
- "TEMPLATE_BODY": "Sablon törzse",
- "CATEGORY": "Kategória"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Változók",
- "VARIABLE_PLACEHOLDER": "Add meg a {variable} értékét",
- "GO_BACK_LABEL": "Vissza",
- "SEND_MESSAGE_LABEL": "Üzenet küldése",
- "FORM_ERROR_MESSAGE": "Kérlek add meg az összes változó értékét küldés előtt"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp sablonok",
+ "SUBTITLE": "Válaszd ki a Whatsapp sablont",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Sablon keresése",
+ "NO_TEMPLATES_FOUND": "Nem található sablon erre:",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Kategória",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Nyelv",
+ "TEMPLATE_BODY": "Sablon törzse",
+ "CATEGORY": "Kategória"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Változók",
+ "LANGUAGE": "Nyelv",
+ "CATEGORY": "Kategória",
+ "VARIABLE_PLACEHOLDER": "Add meg a {variable} értékét",
+ "GO_BACK_LABEL": "Vissza",
+ "SEND_MESSAGE_LABEL": "Üzenet küldése",
+ "FORM_ERROR_MESSAGE": "Kérlek add meg az összes változó értékét küldés előtt",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/hy/automation.json b/app/javascript/dashboard/i18n/locale/hy/automation.json
index cf63de81c..80274f488 100644
--- a/app/javascript/dashboard/i18n/locale/hy/automation.json
+++ b/app/javascript/dashboard/i18n/locale/hy/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/hy/integrations.json b/app/javascript/dashboard/i18n/locale/hy/integrations.json
index 68ce25b15..f0c7abbd3 100644
--- a/app/javascript/dashboard/i18n/locale/hy/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/hy/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/hy/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/hy/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/hy/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/hy/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/id/automation.json b/app/javascript/dashboard/i18n/locale/id/automation.json
index ead34dbdd..e8a688248 100644
--- a/app/javascript/dashboard/i18n/locale/id/automation.json
+++ b/app/javascript/dashboard/i18n/locale/id/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Percakapan Dibuat",
"CONVERSATION_UPDATED": "Percakapan Diperbarui",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/id/integrations.json b/app/javascript/dashboard/i18n/locale/id/integrations.json
index 116557224..98e186693 100644
--- a/app/javascript/dashboard/i18n/locale/id/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/id/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Fitur",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/id/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/id/whatsappTemplates.json
index 88a806522..c9145225c 100644
--- a/app/javascript/dashboard/i18n/locale/id/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/id/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Templat Whatsapp",
- "SUBTITLE": "Pilih templat Whatsapp yang ingin Anda kirim",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Cari Templat",
- "NO_TEMPLATES_FOUND": "Tidak ditemukan templat untuk",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Bahasa",
- "TEMPLATE_BODY": "Isi Templat",
- "CATEGORY": "Kategori"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variabel",
- "VARIABLE_PLACEHOLDER": "Masukkan nilai {variable}",
- "GO_BACK_LABEL": "Kembali",
- "SEND_MESSAGE_LABEL": "Kirim Pesan",
- "FORM_ERROR_MESSAGE": "Harap isi semua variabel sebelum mengirim"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Templat Whatsapp",
+ "SUBTITLE": "Pilih templat Whatsapp yang ingin Anda kirim",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Cari Templat",
+ "NO_TEMPLATES_FOUND": "Tidak ditemukan templat untuk",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Kategori",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Bahasa",
+ "TEMPLATE_BODY": "Isi Templat",
+ "CATEGORY": "Kategori"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variabel",
+ "LANGUAGE": "Bahasa",
+ "CATEGORY": "Kategori",
+ "VARIABLE_PLACEHOLDER": "Masukkan nilai {variable}",
+ "GO_BACK_LABEL": "Kembali",
+ "SEND_MESSAGE_LABEL": "Kirim Pesan",
+ "FORM_ERROR_MESSAGE": "Harap isi semua variabel sebelum mengirim",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/is/automation.json b/app/javascript/dashboard/i18n/locale/is/automation.json
index 145775f1c..8caeb2344 100644
--- a/app/javascript/dashboard/i18n/locale/is/automation.json
+++ b/app/javascript/dashboard/i18n/locale/is/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/is/integrations.json b/app/javascript/dashboard/i18n/locale/is/integrations.json
index d0df69b2d..620ce70cf 100644
--- a/app/javascript/dashboard/i18n/locale/is/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/is/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Fídusar",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/is/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/is/whatsappTemplates.json
index 0be0dfc90..55b7680af 100644
--- a/app/javascript/dashboard/i18n/locale/is/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/is/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Veldu WhatsApp sniðmátið sem þú vilt senda",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Veldu WhatsApp sniðmátið sem þú vilt senda",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/it/automation.json b/app/javascript/dashboard/i18n/locale/it/automation.json
index 2052230e2..df3a5c0a8 100644
--- a/app/javascript/dashboard/i18n/locale/it/automation.json
+++ b/app/javascript/dashboard/i18n/locale/it/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversazione creata",
"CONVERSATION_UPDATED": "Conversazione aggiornata",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/it/integrations.json b/app/javascript/dashboard/i18n/locale/it/integrations.json
index 0697ac873..102539b29 100644
--- a/app/javascript/dashboard/i18n/locale/it/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/it/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Funzionalità",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/it/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/it/whatsappTemplates.json
index 2e1db45c7..b45435cca 100644
--- a/app/javascript/dashboard/i18n/locale/it/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/it/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Modelli Whatsapp",
- "SUBTITLE": "Seleziona il modello whatsapp che vuoi inviare",
- "TEMPLATE_SELECTED_SUBTITLE": "Elabora {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Cerca modelli",
- "NO_TEMPLATES_FOUND": "Nessun modello trovato per",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Lingua",
- "TEMPLATE_BODY": "Corpo modello",
- "CATEGORY": "Categoria"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variabili",
- "VARIABLE_PLACEHOLDER": "Inserisci il valore di {variable}",
- "GO_BACK_LABEL": "Torna indietro",
- "SEND_MESSAGE_LABEL": "Invia messaggio",
- "FORM_ERROR_MESSAGE": "Si prega di compilare tutte le variabili prima di inviare"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Modelli Whatsapp",
+ "SUBTITLE": "Seleziona il modello whatsapp che vuoi inviare",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Cerca modelli",
+ "NO_TEMPLATES_FOUND": "Nessun modello trovato per",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Categoria",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Lingua",
+ "TEMPLATE_BODY": "Corpo modello",
+ "CATEGORY": "Categoria"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variabili",
+ "LANGUAGE": "Lingua",
+ "CATEGORY": "Categoria",
+ "VARIABLE_PLACEHOLDER": "Inserisci il valore di {variable}",
+ "GO_BACK_LABEL": "Torna indietro",
+ "SEND_MESSAGE_LABEL": "Invia messaggio",
+ "FORM_ERROR_MESSAGE": "Si prega di compilare tutte le variabili prima di inviare",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ja/automation.json b/app/javascript/dashboard/i18n/locale/ja/automation.json
index e78b88454..7b113c718 100644
--- a/app/javascript/dashboard/i18n/locale/ja/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ja/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "会話が作成されました",
"CONVERSATION_UPDATED": "会話が更新されました",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ja/integrations.json b/app/javascript/dashboard/i18n/locale/ja/integrations.json
index d9b7442c5..65c471f3e 100644
--- a/app/javascript/dashboard/i18n/locale/ja/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ja/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "機能",
"ALLOW_CONVERSATION_FAQS": "解決済みの会話からFAQを生成",
- "ALLOW_MEMORIES": "顧客とのやり取りから重要な詳細を記憶としてキャプチャ"
+ "ALLOW_MEMORIES": "顧客とのやり取りから重要な詳細を記憶としてキャプチャ",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ja/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ja/whatsappTemplates.json
index de389b44c..3f1a39d1b 100644
--- a/app/javascript/dashboard/i18n/locale/ja/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ja/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp テンプレート",
- "SUBTITLE": "送信したいWhatsappテンプレートを選択してください",
- "TEMPLATE_SELECTED_SUBTITLE": "{templateName} を処理中"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "テンプレートを検索",
- "NO_TEMPLATES_FOUND": "該当するテンプレートが見つかりません:",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "言語",
- "TEMPLATE_BODY": "テンプレート本文",
- "CATEGORY": "カテゴリ"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "変数",
- "VARIABLE_PLACEHOLDER": "{variable} の値を入力",
- "GO_BACK_LABEL": "戻る",
- "SEND_MESSAGE_LABEL": "メッセージを送信",
- "FORM_ERROR_MESSAGE": "送信前に全ての変数を入力してください"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp テンプレート",
+ "SUBTITLE": "送信したいWhatsappテンプレートを選択してください",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "テンプレートを検索",
+ "NO_TEMPLATES_FOUND": "該当するテンプレートが見つかりません:",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "カテゴリ",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "言語",
+ "TEMPLATE_BODY": "テンプレート本文",
+ "CATEGORY": "カテゴリ"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "変数",
+ "LANGUAGE": "言語",
+ "CATEGORY": "カテゴリ",
+ "VARIABLE_PLACEHOLDER": "{variable} の値を入力",
+ "GO_BACK_LABEL": "戻る",
+ "SEND_MESSAGE_LABEL": "メッセージを送信",
+ "FORM_ERROR_MESSAGE": "送信前に全ての変数を入力してください",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ka/automation.json b/app/javascript/dashboard/i18n/locale/ka/automation.json
index cf63de81c..80274f488 100644
--- a/app/javascript/dashboard/i18n/locale/ka/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ka/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ka/integrations.json b/app/javascript/dashboard/i18n/locale/ka/integrations.json
index 68ce25b15..f0c7abbd3 100644
--- a/app/javascript/dashboard/i18n/locale/ka/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ka/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ka/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ka/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/ka/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ka/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ko/automation.json b/app/javascript/dashboard/i18n/locale/ko/automation.json
index e12df529d..a5e1b079c 100644
--- a/app/javascript/dashboard/i18n/locale/ko/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ko/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ko/integrations.json b/app/javascript/dashboard/i18n/locale/ko/integrations.json
index 37335c120..e5935505e 100644
--- a/app/javascript/dashboard/i18n/locale/ko/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ko/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "특징",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ko/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ko/whatsappTemplates.json
index 71fc338da..6f6c098f5 100644
--- a/app/javascript/dashboard/i18n/locale/ko/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ko/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "언어",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "언어",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "언어",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/lt/automation.json b/app/javascript/dashboard/i18n/locale/lt/automation.json
index 54bb9075b..3485c2355 100644
--- a/app/javascript/dashboard/i18n/locale/lt/automation.json
+++ b/app/javascript/dashboard/i18n/locale/lt/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Pokalbis sukurtas",
"CONVERSATION_UPDATED": "Pokalbis atnaujintas",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/lt/integrations.json b/app/javascript/dashboard/i18n/locale/lt/integrations.json
index 90bf8d22d..81cba5fee 100644
--- a/app/javascript/dashboard/i18n/locale/lt/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/lt/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Funkcijos",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/lt/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/lt/whatsappTemplates.json
index 7c9073480..a46abc2a0 100644
--- a/app/javascript/dashboard/i18n/locale/lt/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/lt/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Šablonai",
- "SUBTITLE": "Pasirinkite WhatsApp šabloną, kurį norite siųsti",
- "TEMPLATE_SELECTED_SUBTITLE": "Apdoroti {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Ieškoti šablonų",
- "NO_TEMPLATES_FOUND": "Šablonų nerasta",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Kalba",
- "TEMPLATE_BODY": "Šablono tekstas",
- "CATEGORY": "Kategorija"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Kintamieji",
- "VARIABLE_PLACEHOLDER": "Įveskite {variable} reikšmę",
- "GO_BACK_LABEL": "Grįžti",
- "SEND_MESSAGE_LABEL": "Išsiųsti pranešimą",
- "FORM_ERROR_MESSAGE": "Prieš siųsdami užpildykite visus kintamuosius"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Šablonai",
+ "SUBTITLE": "Pasirinkite WhatsApp šabloną, kurį norite siųsti",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Ieškoti šablonų",
+ "NO_TEMPLATES_FOUND": "Šablonų nerasta",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Kategorija",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Kalba",
+ "TEMPLATE_BODY": "Šablono tekstas",
+ "CATEGORY": "Kategorija"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Kintamieji",
+ "LANGUAGE": "Kalba",
+ "CATEGORY": "Kategorija",
+ "VARIABLE_PLACEHOLDER": "Įveskite {variable} reikšmę",
+ "GO_BACK_LABEL": "Grįžti",
+ "SEND_MESSAGE_LABEL": "Išsiųsti pranešimą",
+ "FORM_ERROR_MESSAGE": "Prieš siųsdami užpildykite visus kintamuosius",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/lv/automation.json b/app/javascript/dashboard/i18n/locale/lv/automation.json
index 193ef9739..9877bb4e3 100644
--- a/app/javascript/dashboard/i18n/locale/lv/automation.json
+++ b/app/javascript/dashboard/i18n/locale/lv/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Saruna izveidota",
"CONVERSATION_UPDATED": "Saruna Atjaunināta",
"MESSAGE_CREATED": "Ziņojums Izveidots",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Saruna Atvērta"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/lv/integrations.json b/app/javascript/dashboard/i18n/locale/lv/integrations.json
index e5a013bd7..b8f109f61 100644
--- a/app/javascript/dashboard/i18n/locale/lv/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/lv/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Īpašības",
"ALLOW_CONVERSATION_FAQS": "Ģenerēt bieži uzdotos jautājumus no atrisinātajām sarunām",
- "ALLOW_MEMORIES": "Pārtvert galvenās nianses kā atmiņas no klientu mijiedarbībām."
+ "ALLOW_MEMORIES": "Pārtvert galvenās nianses kā atmiņas no klientu mijiedarbībām.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/lv/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/lv/whatsappTemplates.json
index 330ab173d..0b51f15f3 100644
--- a/app/javascript/dashboard/i18n/locale/lv/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/lv/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "WhatsApp Veidnes",
- "SUBTITLE": "Izvēlieties WhatsApp veidni, kuru vēlaties nosūtīt",
- "TEMPLATE_SELECTED_SUBTITLE": "Apstrādāt {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Meklēt Veidnes",
- "NO_TEMPLATES_FOUND": "Veidnes nav atrastas",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Valoda",
- "TEMPLATE_BODY": "Veidnes Pamatteksts",
- "CATEGORY": "Kategorija"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Mainīgie",
- "VARIABLE_PLACEHOLDER": "Ievadiet {variable} vērtību",
- "GO_BACK_LABEL": "Atgriezties",
- "SEND_MESSAGE_LABEL": "Sūtīt Ziņojumu",
- "FORM_ERROR_MESSAGE": "Lūdzu, pirms nosūtīšanas aizpildiet visus mainīgos"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "WhatsApp Veidnes",
+ "SUBTITLE": "Izvēlieties WhatsApp veidni, kuru vēlaties nosūtīt",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Meklēt Veidnes",
+ "NO_TEMPLATES_FOUND": "Veidnes nav atrastas",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Kategorija",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Valoda",
+ "TEMPLATE_BODY": "Veidnes Pamatteksts",
+ "CATEGORY": "Kategorija"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Mainīgie",
+ "LANGUAGE": "Valoda",
+ "CATEGORY": "Kategorija",
+ "VARIABLE_PLACEHOLDER": "Ievadiet {variable} vērtību",
+ "GO_BACK_LABEL": "Atgriezties",
+ "SEND_MESSAGE_LABEL": "Sūtīt Ziņojumu",
+ "FORM_ERROR_MESSAGE": "Lūdzu, pirms nosūtīšanas aizpildiet visus mainīgos",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ml/automation.json b/app/javascript/dashboard/i18n/locale/ml/automation.json
index b50618313..6c3cd4517 100644
--- a/app/javascript/dashboard/i18n/locale/ml/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ml/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ml/integrations.json b/app/javascript/dashboard/i18n/locale/ml/integrations.json
index f64124402..f375f9ff2 100644
--- a/app/javascript/dashboard/i18n/locale/ml/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ml/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ml/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ml/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/ml/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ml/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ms/automation.json b/app/javascript/dashboard/i18n/locale/ms/automation.json
index 2bdccfc0e..e3990a8ab 100644
--- a/app/javascript/dashboard/i18n/locale/ms/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ms/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ms/integrations.json b/app/javascript/dashboard/i18n/locale/ms/integrations.json
index 3f5083d30..cb2c4a677 100644
--- a/app/javascript/dashboard/i18n/locale/ms/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ms/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ms/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ms/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/ms/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ms/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ne/automation.json b/app/javascript/dashboard/i18n/locale/ne/automation.json
index a4c0ce10b..4aba66e26 100644
--- a/app/javascript/dashboard/i18n/locale/ne/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ne/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ne/integrations.json b/app/javascript/dashboard/i18n/locale/ne/integrations.json
index bc72dd2e3..56a6766fc 100644
--- a/app/javascript/dashboard/i18n/locale/ne/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ne/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ne/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ne/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/ne/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ne/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/nl/automation.json b/app/javascript/dashboard/i18n/locale/nl/automation.json
index 269bf96ab..dd45ce36d 100644
--- a/app/javascript/dashboard/i18n/locale/nl/automation.json
+++ b/app/javascript/dashboard/i18n/locale/nl/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Gesprek aangemaakt",
"CONVERSATION_UPDATED": "Gesprek bijgewerkt",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/nl/integrations.json b/app/javascript/dashboard/i18n/locale/nl/integrations.json
index 7b971629c..cecc6fac0 100644
--- a/app/javascript/dashboard/i18n/locale/nl/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/nl/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/nl/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/nl/whatsappTemplates.json
index 4061f4090..7e4317fb8 100644
--- a/app/javascript/dashboard/i18n/locale/nl/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/nl/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Selecteer de whatsapp template die u wilt verzenden",
- "TEMPLATE_SELECTED_SUBTITLE": "Verwerk {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Templates zoeken",
- "NO_TEMPLATES_FOUND": "Geen templates gevonden voor",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Taal",
- "TEMPLATE_BODY": "Template bericht",
- "CATEGORY": "Categorie"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variabelen",
- "VARIABLE_PLACEHOLDER": "Voer {variable} waarde in",
- "GO_BACK_LABEL": "Ga terug",
- "SEND_MESSAGE_LABEL": "Verstuur bericht",
- "FORM_ERROR_MESSAGE": "Vul alstublieft alle variabelen in voordat u deze verzendt"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Selecteer de whatsapp template die u wilt verzenden",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Templates zoeken",
+ "NO_TEMPLATES_FOUND": "Geen templates gevonden voor",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Categorie",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Taal",
+ "TEMPLATE_BODY": "Template bericht",
+ "CATEGORY": "Categorie"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variabelen",
+ "LANGUAGE": "Taal",
+ "CATEGORY": "Categorie",
+ "VARIABLE_PLACEHOLDER": "Voer {variable} waarde in",
+ "GO_BACK_LABEL": "Ga terug",
+ "SEND_MESSAGE_LABEL": "Verstuur bericht",
+ "FORM_ERROR_MESSAGE": "Vul alstublieft alle variabelen in voordat u deze verzendt",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/no/automation.json b/app/javascript/dashboard/i18n/locale/no/automation.json
index 4a5b37875..c76e4dc1a 100644
--- a/app/javascript/dashboard/i18n/locale/no/automation.json
+++ b/app/javascript/dashboard/i18n/locale/no/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/no/integrations.json b/app/javascript/dashboard/i18n/locale/no/integrations.json
index 10b668191..033245b58 100644
--- a/app/javascript/dashboard/i18n/locale/no/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/no/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Funksjoner",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/no/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/no/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/no/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/no/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/pl/automation.json b/app/javascript/dashboard/i18n/locale/pl/automation.json
index 3ebfa9550..f4212f70c 100644
--- a/app/javascript/dashboard/i18n/locale/pl/automation.json
+++ b/app/javascript/dashboard/i18n/locale/pl/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Rozpoczęcie rozmowy",
"CONVERSATION_UPDATED": "Aktualizacja rozmowy",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/pl/integrations.json b/app/javascript/dashboard/i18n/locale/pl/integrations.json
index ec149a9e4..7787df954 100644
--- a/app/javascript/dashboard/i18n/locale/pl/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/pl/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Funkcje",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/pl/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/pl/whatsappTemplates.json
index fb87e1425..e1946af25 100644
--- a/app/javascript/dashboard/i18n/locale/pl/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/pl/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Szablony WhatsApp",
- "SUBTITLE": "Wybierz szablon WhatsApp, który chcesz wysłać",
- "TEMPLATE_SELECTED_SUBTITLE": "Przetwarzanie {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Wyszukaj szablony",
- "NO_TEMPLATES_FOUND": "Nie znaleziono szablonów dla",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Język",
- "TEMPLATE_BODY": "Treść szablonu",
- "CATEGORY": "Kategoria"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Zmienne",
- "VARIABLE_PLACEHOLDER": "Wprowadź wartość {variable}",
- "GO_BACK_LABEL": "Powrót",
- "SEND_MESSAGE_LABEL": "Wyślij wiadomość",
- "FORM_ERROR_MESSAGE": "Proszę wypełnić wszystkie zmienne przed wysłaniem"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Szablony WhatsApp",
+ "SUBTITLE": "Wybierz szablon WhatsApp, który chcesz wysłać",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Wyszukaj szablony",
+ "NO_TEMPLATES_FOUND": "Nie znaleziono szablonów dla",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Kategoria",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Język",
+ "TEMPLATE_BODY": "Treść szablonu",
+ "CATEGORY": "Kategoria"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Zmienne",
+ "LANGUAGE": "Język",
+ "CATEGORY": "Kategoria",
+ "VARIABLE_PLACEHOLDER": "Wprowadź wartość {variable}",
+ "GO_BACK_LABEL": "Powrót",
+ "SEND_MESSAGE_LABEL": "Wyślij wiadomość",
+ "FORM_ERROR_MESSAGE": "Proszę wypełnić wszystkie zmienne przed wysłaniem",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/pt/automation.json b/app/javascript/dashboard/i18n/locale/pt/automation.json
index a2740c577..0a720f528 100644
--- a/app/javascript/dashboard/i18n/locale/pt/automation.json
+++ b/app/javascript/dashboard/i18n/locale/pt/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversa criada",
"CONVERSATION_UPDATED": "Conversa atualizada",
"MESSAGE_CREATED": "Mensagem criada",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversa aberta"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/pt/integrations.json b/app/javascript/dashboard/i18n/locale/pt/integrations.json
index 69c3ddb4f..2a86bd97f 100644
--- a/app/javascript/dashboard/i18n/locale/pt/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/pt/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Características",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/pt/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/pt/whatsappTemplates.json
index cba42fd01..45100216d 100644
--- a/app/javascript/dashboard/i18n/locale/pt/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/pt/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Template do WhatsApp",
- "SUBTITLE": "Selecione o template do whatsapp que você deseja enviar",
- "TEMPLATE_SELECTED_SUBTITLE": "Processo {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Buscar templates",
- "NO_TEMPLATES_FOUND": "Nenhum template encontrado para",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Idioma",
- "TEMPLATE_BODY": "Corpo do Template",
- "CATEGORY": "Categoria"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variáveis",
- "VARIABLE_PLACEHOLDER": "Digite o valor {variable}",
- "GO_BACK_LABEL": "Voltar",
- "SEND_MESSAGE_LABEL": "Enviar mensagem",
- "FORM_ERROR_MESSAGE": "Preencha todas as variáveis antes de enviar"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Template do WhatsApp",
+ "SUBTITLE": "Selecione o template do whatsapp que você deseja enviar",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Buscar templates",
+ "NO_TEMPLATES_FOUND": "Nenhum template encontrado para",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Categoria",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Idioma",
+ "TEMPLATE_BODY": "Corpo do Template",
+ "CATEGORY": "Categoria"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variáveis",
+ "LANGUAGE": "Idioma",
+ "CATEGORY": "Categoria",
+ "VARIABLE_PLACEHOLDER": "Digite o valor {variable}",
+ "GO_BACK_LABEL": "Voltar",
+ "SEND_MESSAGE_LABEL": "Enviar mensagem",
+ "FORM_ERROR_MESSAGE": "Preencha todas as variáveis antes de enviar",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/pt_BR/automation.json b/app/javascript/dashboard/i18n/locale/pt_BR/automation.json
index 22a097713..a3ecb50ac 100644
--- a/app/javascript/dashboard/i18n/locale/pt_BR/automation.json
+++ b/app/javascript/dashboard/i18n/locale/pt_BR/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversa Criada",
"CONVERSATION_UPDATED": "Conversa Atualizada",
"MESSAGE_CREATED": "Mensagem Criada",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversa Aberta"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/pt_BR/integrations.json b/app/javascript/dashboard/i18n/locale/pt_BR/integrations.json
index 1b690cb82..67102dbb5 100644
--- a/app/javascript/dashboard/i18n/locale/pt_BR/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/pt_BR/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Funcionalidades",
"ALLOW_CONVERSATION_FAQS": "Gerar perguntas frequentes a partir de conversas resolvidas",
- "ALLOW_MEMORIES": "Capture os principais detalhes como memórias de interações do cliente."
+ "ALLOW_MEMORIES": "Capture os principais detalhes como memórias de interações do cliente.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/pt_BR/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/pt_BR/whatsappTemplates.json
index 1149bc577..27accbaa8 100644
--- a/app/javascript/dashboard/i18n/locale/pt_BR/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/pt_BR/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Templates do Whatsapp",
- "SUBTITLE": "Selecione o template do whatsapp que você deseja enviar",
- "TEMPLATE_SELECTED_SUBTITLE": "Processar {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Pesquisar modelos",
- "NO_TEMPLATES_FOUND": "Não há templates encontrados para",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Idioma",
- "TEMPLATE_BODY": "Conteúdo do Template",
- "CATEGORY": "Categoria"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variáveis",
- "VARIABLE_PLACEHOLDER": "Insira o valor para {variable}",
- "GO_BACK_LABEL": "Voltar",
- "SEND_MESSAGE_LABEL": "Enviar Mensagem",
- "FORM_ERROR_MESSAGE": "Por favor, preencha todas as variáveis antes de enviar"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Templates do Whatsapp",
+ "SUBTITLE": "Selecione o template do whatsapp que você deseja enviar",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Pesquisar modelos",
+ "NO_TEMPLATES_FOUND": "Não há templates encontrados para",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Categoria",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Idioma",
+ "TEMPLATE_BODY": "Conteúdo do Template",
+ "CATEGORY": "Categoria"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variáveis",
+ "LANGUAGE": "Idioma",
+ "CATEGORY": "Categoria",
+ "VARIABLE_PLACEHOLDER": "Insira o valor para {variable}",
+ "GO_BACK_LABEL": "Voltar",
+ "SEND_MESSAGE_LABEL": "Enviar Mensagem",
+ "FORM_ERROR_MESSAGE": "Por favor, preencha todas as variáveis antes de enviar",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ro/automation.json b/app/javascript/dashboard/i18n/locale/ro/automation.json
index 38a4dd0c6..8f18d43fe 100644
--- a/app/javascript/dashboard/i18n/locale/ro/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ro/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversație creată",
"CONVERSATION_UPDATED": "Conversație actualizată",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ro/integrations.json b/app/javascript/dashboard/i18n/locale/ro/integrations.json
index 513b93b64..dae7e2088 100644
--- a/app/javascript/dashboard/i18n/locale/ro/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ro/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Caracteristici",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ro/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ro/whatsappTemplates.json
index fda8d7b10..e1697e19f 100644
--- a/app/javascript/dashboard/i18n/locale/ro/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ro/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Șabloane WhatsApp",
- "SUBTITLE": "Selectați șablonul WhatsApp pe care doriți să trimiteți",
- "TEMPLATE_SELECTED_SUBTITLE": "{templateName} de proces"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Caută Șabloane",
- "NO_TEMPLATES_FOUND": "Nu s-au găsit șabloane pentru",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Limbă",
- "TEMPLATE_BODY": "Corpul șablonului",
- "CATEGORY": "Categorie"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variabile",
- "VARIABLE_PLACEHOLDER": "Introducerea {variable} valoare",
- "GO_BACK_LABEL": "Înapoi",
- "SEND_MESSAGE_LABEL": "Trimite mesaj",
- "FORM_ERROR_MESSAGE": "Vă rugăm să completați toate variabilele înainte de a trimite"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Șabloane WhatsApp",
+ "SUBTITLE": "Selectați șablonul WhatsApp pe care doriți să trimiteți",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Caută Șabloane",
+ "NO_TEMPLATES_FOUND": "Nu s-au găsit șabloane pentru",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Categorie",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Limbă",
+ "TEMPLATE_BODY": "Corpul șablonului",
+ "CATEGORY": "Categorie"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variabile",
+ "LANGUAGE": "Limbă",
+ "CATEGORY": "Categorie",
+ "VARIABLE_PLACEHOLDER": "Introducerea {variable} valoare",
+ "GO_BACK_LABEL": "Înapoi",
+ "SEND_MESSAGE_LABEL": "Trimite mesaj",
+ "FORM_ERROR_MESSAGE": "Vă rugăm să completați toate variabilele înainte de a trimite",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ru/automation.json b/app/javascript/dashboard/i18n/locale/ru/automation.json
index 49e5699c9..08ead85fe 100644
--- a/app/javascript/dashboard/i18n/locale/ru/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ru/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Диалог создан",
"CONVERSATION_UPDATED": "Диалог обновлён",
"MESSAGE_CREATED": "Сообщение создано",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ru/integrations.json b/app/javascript/dashboard/i18n/locale/ru/integrations.json
index 833e9faf5..6de478fb1 100644
--- a/app/javascript/dashboard/i18n/locale/ru/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ru/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Возможности",
"ALLOW_CONVERSATION_FAQS": "Создать FAQ из решённых диалогов",
- "ALLOW_MEMORIES": "Сохраняйте ключевые детали в виде воспоминаний о взаимодействии с клиентами."
+ "ALLOW_MEMORIES": "Сохраняйте ключевые детали в виде воспоминаний о взаимодействии с клиентами.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ru/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ru/whatsappTemplates.json
index 65c55ec5a..a8effa8b8 100644
--- a/app/javascript/dashboard/i18n/locale/ru/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ru/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Шаблоны Whatsapp",
- "SUBTITLE": "Выберите шаблон whatsapp, который вы хотите отправить",
- "TEMPLATE_SELECTED_SUBTITLE": "Обработка {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Найти шаблоны",
- "NO_TEMPLATES_FOUND": "Не найдено шаблонов для",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Язык",
- "TEMPLATE_BODY": "Тело шаблона",
- "CATEGORY": "Категория"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Переменные",
- "VARIABLE_PLACEHOLDER": "Введите значение {variable}",
- "GO_BACK_LABEL": "Вернуться",
- "SEND_MESSAGE_LABEL": "Отправить сообщение",
- "FORM_ERROR_MESSAGE": "Пожалуйста, заполните все переменные перед отправкой"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Шаблоны Whatsapp",
+ "SUBTITLE": "Выберите шаблон whatsapp, который вы хотите отправить",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Найти шаблоны",
+ "NO_TEMPLATES_FOUND": "Не найдено шаблонов для",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Категория",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Язык",
+ "TEMPLATE_BODY": "Тело шаблона",
+ "CATEGORY": "Категория"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Переменные",
+ "LANGUAGE": "Язык",
+ "CATEGORY": "Категория",
+ "VARIABLE_PLACEHOLDER": "Введите значение {variable}",
+ "GO_BACK_LABEL": "Вернуться",
+ "SEND_MESSAGE_LABEL": "Отправить сообщение",
+ "FORM_ERROR_MESSAGE": "Пожалуйста, заполните все переменные перед отправкой",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/sh/automation.json b/app/javascript/dashboard/i18n/locale/sh/automation.json
index cf63de81c..80274f488 100644
--- a/app/javascript/dashboard/i18n/locale/sh/automation.json
+++ b/app/javascript/dashboard/i18n/locale/sh/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/sh/integrations.json b/app/javascript/dashboard/i18n/locale/sh/integrations.json
index 68ce25b15..f0c7abbd3 100644
--- a/app/javascript/dashboard/i18n/locale/sh/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/sh/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/sh/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/sh/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/sh/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/sh/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/sk/automation.json b/app/javascript/dashboard/i18n/locale/sk/automation.json
index 9c2c463bc..2ea93e17a 100644
--- a/app/javascript/dashboard/i18n/locale/sk/automation.json
+++ b/app/javascript/dashboard/i18n/locale/sk/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/sk/integrations.json b/app/javascript/dashboard/i18n/locale/sk/integrations.json
index e0d32c972..55cd79768 100644
--- a/app/javascript/dashboard/i18n/locale/sk/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/sk/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/sk/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/sk/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/sk/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/sk/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/sl/automation.json b/app/javascript/dashboard/i18n/locale/sl/automation.json
index 694902ab5..2f97d7257 100644
--- a/app/javascript/dashboard/i18n/locale/sl/automation.json
+++ b/app/javascript/dashboard/i18n/locale/sl/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/sl/integrations.json b/app/javascript/dashboard/i18n/locale/sl/integrations.json
index 5880a6b3c..e1f8321c5 100644
--- a/app/javascript/dashboard/i18n/locale/sl/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/sl/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/sl/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/sl/whatsappTemplates.json
index eb4acbea6..aa6011859 100644
--- a/app/javascript/dashboard/i18n/locale/sl/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/sl/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Predloge za WhatsApp",
- "SUBTITLE": "Izberite predlogo WhatsApp, ki jo želite poslati",
- "TEMPLATE_SELECTED_SUBTITLE": "Obdelaj {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Išči predloge",
- "NO_TEMPLATES_FOUND": "Ni najdenih predlog za",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Jezik",
- "TEMPLATE_BODY": "Telo predloge",
- "CATEGORY": "Kategorija"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Spremenljivke",
- "VARIABLE_PLACEHOLDER": "Vnesi vrednost {variable}",
- "GO_BACK_LABEL": "Pojdi nazaj",
- "SEND_MESSAGE_LABEL": "Pošlji sporočilo",
- "FORM_ERROR_MESSAGE": "Prosimo, izpolnite vse spremenljivke pred pošiljanjem"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Predloge za WhatsApp",
+ "SUBTITLE": "Izberite predlogo WhatsApp, ki jo želite poslati",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Išči predloge",
+ "NO_TEMPLATES_FOUND": "Ni najdenih predlog za",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Kategorija",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Jezik",
+ "TEMPLATE_BODY": "Telo predloge",
+ "CATEGORY": "Kategorija"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Spremenljivke",
+ "LANGUAGE": "Jezik",
+ "CATEGORY": "Kategorija",
+ "VARIABLE_PLACEHOLDER": "Vnesi vrednost {variable}",
+ "GO_BACK_LABEL": "Pojdi nazaj",
+ "SEND_MESSAGE_LABEL": "Pošlji sporočilo",
+ "FORM_ERROR_MESSAGE": "Prosimo, izpolnite vse spremenljivke pred pošiljanjem",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/sq/automation.json b/app/javascript/dashboard/i18n/locale/sq/automation.json
index 643d3b09a..280c6c65d 100644
--- a/app/javascript/dashboard/i18n/locale/sq/automation.json
+++ b/app/javascript/dashboard/i18n/locale/sq/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/sq/integrations.json b/app/javascript/dashboard/i18n/locale/sq/integrations.json
index 24315dec2..3fe43940a 100644
--- a/app/javascript/dashboard/i18n/locale/sq/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/sq/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/sq/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/sq/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/sq/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/sq/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/sr/automation.json b/app/javascript/dashboard/i18n/locale/sr/automation.json
index f3bee7561..0f15f8e3d 100644
--- a/app/javascript/dashboard/i18n/locale/sr/automation.json
+++ b/app/javascript/dashboard/i18n/locale/sr/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Razgovor je napravljen",
"CONVERSATION_UPDATED": "Razgovor je izmenjen",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/sr/integrations.json b/app/javascript/dashboard/i18n/locale/sr/integrations.json
index 8dada5dc6..77c6d0b7b 100644
--- a/app/javascript/dashboard/i18n/locale/sr/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/sr/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Mogućnosti",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/sr/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/sr/whatsappTemplates.json
index 27fed1503..a3cf57d23 100644
--- a/app/javascript/dashboard/i18n/locale/sr/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/sr/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp šabloni",
- "SUBTITLE": "Izaberite koji whatsapp šablon želite da pošaljete",
- "TEMPLATE_SELECTED_SUBTITLE": "Obrada {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Pretraži šablone",
- "NO_TEMPLATES_FOUND": "Nijedan šablon nije pronađen",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Jezik",
- "TEMPLATE_BODY": "Telo šablona",
- "CATEGORY": "Kategorija"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Promenljive",
- "VARIABLE_PLACEHOLDER": "Unesite vrednost za {variable}",
- "GO_BACK_LABEL": "Povratak",
- "SEND_MESSAGE_LABEL": "Pošalji poruku",
- "FORM_ERROR_MESSAGE": "Molim vas popunite sve promenljive pre slanja"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp šabloni",
+ "SUBTITLE": "Izaberite koji whatsapp šablon želite da pošaljete",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Pretraži šablone",
+ "NO_TEMPLATES_FOUND": "Nijedan šablon nije pronađen",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Kategorija",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Jezik",
+ "TEMPLATE_BODY": "Telo šablona",
+ "CATEGORY": "Kategorija"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Promenljive",
+ "LANGUAGE": "Jezik",
+ "CATEGORY": "Kategorija",
+ "VARIABLE_PLACEHOLDER": "Unesite vrednost za {variable}",
+ "GO_BACK_LABEL": "Povratak",
+ "SEND_MESSAGE_LABEL": "Pošalji poruku",
+ "FORM_ERROR_MESSAGE": "Molim vas popunite sve promenljive pre slanja",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/sv/automation.json b/app/javascript/dashboard/i18n/locale/sv/automation.json
index d50296a86..b21bfe262 100644
--- a/app/javascript/dashboard/i18n/locale/sv/automation.json
+++ b/app/javascript/dashboard/i18n/locale/sv/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/sv/integrations.json b/app/javascript/dashboard/i18n/locale/sv/integrations.json
index 805d3481f..ce27888e4 100644
--- a/app/javascript/dashboard/i18n/locale/sv/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/sv/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Funktioner",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/sv/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/sv/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/sv/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/sv/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ta/automation.json b/app/javascript/dashboard/i18n/locale/ta/automation.json
index b3aa9be50..ba7a725cd 100644
--- a/app/javascript/dashboard/i18n/locale/ta/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ta/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ta/integrations.json b/app/javascript/dashboard/i18n/locale/ta/integrations.json
index 160cb189f..30244bd5a 100644
--- a/app/javascript/dashboard/i18n/locale/ta/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ta/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ta/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ta/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/ta/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ta/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/th/automation.json b/app/javascript/dashboard/i18n/locale/th/automation.json
index eac475926..8df9e274f 100644
--- a/app/javascript/dashboard/i18n/locale/th/automation.json
+++ b/app/javascript/dashboard/i18n/locale/th/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "การสนทนาที่ถูกสร้าง",
"CONVERSATION_UPDATED": "อัปเดตการสนทนาแล้ว",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/th/integrations.json b/app/javascript/dashboard/i18n/locale/th/integrations.json
index 692daf68e..c9ab15529 100644
--- a/app/javascript/dashboard/i18n/locale/th/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/th/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "ฟีเจอร์",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/th/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/th/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/th/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/th/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/tl/automation.json b/app/javascript/dashboard/i18n/locale/tl/automation.json
index cf63de81c..80274f488 100644
--- a/app/javascript/dashboard/i18n/locale/tl/automation.json
+++ b/app/javascript/dashboard/i18n/locale/tl/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/tl/integrations.json b/app/javascript/dashboard/i18n/locale/tl/integrations.json
index 1614931a0..be9281284 100644
--- a/app/javascript/dashboard/i18n/locale/tl/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/tl/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/tl/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/tl/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/tl/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/tl/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/tr/automation.json b/app/javascript/dashboard/i18n/locale/tr/automation.json
index 2a1f9f55a..3bac1c990 100644
--- a/app/javascript/dashboard/i18n/locale/tr/automation.json
+++ b/app/javascript/dashboard/i18n/locale/tr/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Görüşme Oluşturuldu",
"CONVERSATION_UPDATED": "Görüşme Güncellendi",
"MESSAGE_CREATED": "Mesaj Oluşturuldu",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Sohbet Açıldı"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/tr/integrations.json b/app/javascript/dashboard/i18n/locale/tr/integrations.json
index 5e774e07a..d414ea777 100644
--- a/app/javascript/dashboard/i18n/locale/tr/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/tr/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Özellikleri",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/tr/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/tr/whatsappTemplates.json
index da51ff735..47dfd1c55 100644
--- a/app/javascript/dashboard/i18n/locale/tr/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/tr/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "WhatsApp Şablonları",
- "SUBTITLE": "Göndermek istediğiniz WhatsApp şablonunu seçin",
- "TEMPLATE_SELECTED_SUBTITLE": "{templateName} işleniyor"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Şablon Ara",
- "NO_TEMPLATES_FOUND": "İçin hiç şablon bulunamadı",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Dil",
- "TEMPLATE_BODY": "Şablon İçeriği",
- "CATEGORY": "Kategori"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Değişkenler",
- "VARIABLE_PLACEHOLDER": "{variable} değerini girin",
- "GO_BACK_LABEL": "Geri Git",
- "SEND_MESSAGE_LABEL": "Mesaj Gönder",
- "FORM_ERROR_MESSAGE": "Lütfen göndermeden önce tüm değişkenleri doldurun"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "WhatsApp Şablonları",
+ "SUBTITLE": "Göndermek istediğiniz WhatsApp şablonunu seçin",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Şablon Ara",
+ "NO_TEMPLATES_FOUND": "İçin hiç şablon bulunamadı",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Kategori",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Dil",
+ "TEMPLATE_BODY": "Şablon İçeriği",
+ "CATEGORY": "Kategori"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Değişkenler",
+ "LANGUAGE": "Dil",
+ "CATEGORY": "Kategori",
+ "VARIABLE_PLACEHOLDER": "{variable} değerini girin",
+ "GO_BACK_LABEL": "Geri Git",
+ "SEND_MESSAGE_LABEL": "Mesaj Gönder",
+ "FORM_ERROR_MESSAGE": "Lütfen göndermeden önce tüm değişkenleri doldurun",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/uk/automation.json b/app/javascript/dashboard/i18n/locale/uk/automation.json
index 39ad3e474..84617e9f0 100644
--- a/app/javascript/dashboard/i18n/locale/uk/automation.json
+++ b/app/javascript/dashboard/i18n/locale/uk/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Розмову створено",
"CONVERSATION_UPDATED": "Розмову оновлено",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/uk/integrations.json b/app/javascript/dashboard/i18n/locale/uk/integrations.json
index bc7afcfc6..fd1c820fc 100644
--- a/app/javascript/dashboard/i18n/locale/uk/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/uk/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Особливості",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/uk/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/uk/whatsappTemplates.json
index 1246919f5..d181cd3f1 100644
--- a/app/javascript/dashboard/i18n/locale/uk/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/uk/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Шаблони Whatsapp",
- "SUBTITLE": "Виберіть шаблон whatsApp, який Ви хочете надіслати",
- "TEMPLATE_SELECTED_SUBTITLE": "Процес {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Знайти шаблони",
- "NO_TEMPLATES_FOUND": "Шаблонів не знайдено для",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Мова",
- "TEMPLATE_BODY": "Тіло шаблона",
- "CATEGORY": "Категорія"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Змінні",
- "VARIABLE_PLACEHOLDER": "Введіть значення {variable}",
- "GO_BACK_LABEL": "Повернутися",
- "SEND_MESSAGE_LABEL": "Надіслати повідомлення",
- "FORM_ERROR_MESSAGE": "Будь ласка, заповніть всі змінні перед надсиланням"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Шаблони Whatsapp",
+ "SUBTITLE": "Виберіть шаблон whatsApp, який Ви хочете надіслати",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Знайти шаблони",
+ "NO_TEMPLATES_FOUND": "Шаблонів не знайдено для",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Категорія",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Мова",
+ "TEMPLATE_BODY": "Тіло шаблона",
+ "CATEGORY": "Категорія"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Змінні",
+ "LANGUAGE": "Мова",
+ "CATEGORY": "Категорія",
+ "VARIABLE_PLACEHOLDER": "Введіть значення {variable}",
+ "GO_BACK_LABEL": "Повернутися",
+ "SEND_MESSAGE_LABEL": "Надіслати повідомлення",
+ "FORM_ERROR_MESSAGE": "Будь ласка, заповніть всі змінні перед надсиланням",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ur/automation.json b/app/javascript/dashboard/i18n/locale/ur/automation.json
index a129539f8..3ef2ccc5e 100644
--- a/app/javascript/dashboard/i18n/locale/ur/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ur/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ur/integrations.json b/app/javascript/dashboard/i18n/locale/ur/integrations.json
index bcf0c1a33..eaab517a2 100644
--- a/app/javascript/dashboard/i18n/locale/ur/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ur/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ur/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ur/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/ur/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ur/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/ur_IN/automation.json b/app/javascript/dashboard/i18n/locale/ur_IN/automation.json
index cf63de81c..80274f488 100644
--- a/app/javascript/dashboard/i18n/locale/ur_IN/automation.json
+++ b/app/javascript/dashboard/i18n/locale/ur_IN/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/ur_IN/integrations.json b/app/javascript/dashboard/i18n/locale/ur_IN/integrations.json
index 68ce25b15..f0c7abbd3 100644
--- a/app/javascript/dashboard/i18n/locale/ur_IN/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/ur_IN/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/ur_IN/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/ur_IN/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/ur_IN/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/ur_IN/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/vi/automation.json b/app/javascript/dashboard/i18n/locale/vi/automation.json
index cb483e847..1f8d5ea79 100644
--- a/app/javascript/dashboard/i18n/locale/vi/automation.json
+++ b/app/javascript/dashboard/i18n/locale/vi/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Cuộc trò chuyện đã được tạo",
"CONVERSATION_UPDATED": "Cuộc trò chuyện đã được cập nhật",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/vi/integrations.json b/app/javascript/dashboard/i18n/locale/vi/integrations.json
index fdb96d792..10a6df6b9 100644
--- a/app/javascript/dashboard/i18n/locale/vi/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/vi/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Các tính năng",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/vi/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/vi/whatsappTemplates.json
index a4abce833..fefd680ec 100644
--- a/app/javascript/dashboard/i18n/locale/vi/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/vi/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Mẫu Whatsapp",
- "SUBTITLE": "Chọn mẫu whatsapp bạn muốn gửi",
- "TEMPLATE_SELECTED_SUBTITLE": "Xử lý {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Tìm kiếm Mẫu",
- "NO_TEMPLATES_FOUND": "Không tìm thấy mẫu nào cho",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Ngôn ngữ",
- "TEMPLATE_BODY": "Nội dung của Mẫu",
- "CATEGORY": "Loại"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Biến",
- "VARIABLE_PLACEHOLDER": "Nhập giá trị {variable}",
- "GO_BACK_LABEL": "Quay lại",
- "SEND_MESSAGE_LABEL": "Gửi tin nhắn",
- "FORM_ERROR_MESSAGE": "Vui lòng điền vào tất cả các biến trước khi gửi"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Mẫu Whatsapp",
+ "SUBTITLE": "Chọn mẫu whatsapp bạn muốn gửi",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Tìm kiếm Mẫu",
+ "NO_TEMPLATES_FOUND": "Không tìm thấy mẫu nào cho",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Loại",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Ngôn ngữ",
+ "TEMPLATE_BODY": "Nội dung của Mẫu",
+ "CATEGORY": "Loại"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Biến",
+ "LANGUAGE": "Ngôn ngữ",
+ "CATEGORY": "Loại",
+ "VARIABLE_PLACEHOLDER": "Nhập giá trị {variable}",
+ "GO_BACK_LABEL": "Quay lại",
+ "SEND_MESSAGE_LABEL": "Gửi tin nhắn",
+ "FORM_ERROR_MESSAGE": "Vui lòng điền vào tất cả các biến trước khi gửi",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/zh_CN/automation.json b/app/javascript/dashboard/i18n/locale/zh_CN/automation.json
index 5b6872011..206b50103 100644
--- a/app/javascript/dashboard/i18n/locale/zh_CN/automation.json
+++ b/app/javascript/dashboard/i18n/locale/zh_CN/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "对话创建",
"CONVERSATION_UPDATED": "对话已更新",
"MESSAGE_CREATED": "消息已创建",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "对话已打开"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/zh_CN/integrations.json b/app/javascript/dashboard/i18n/locale/zh_CN/integrations.json
index 0132e71c6..24de2da6d 100644
--- a/app/javascript/dashboard/i18n/locale/zh_CN/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/zh_CN/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "特性",
"ALLOW_CONVERSATION_FAQS": "从已解决的对话中生成常见问题",
- "ALLOW_MEMORIES": "从客户互动中捕获关键细节作为记忆"
+ "ALLOW_MEMORIES": "从客户互动中捕获关键细节作为记忆",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/zh_CN/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/zh_CN/whatsappTemplates.json
index cade063c0..9ca1ae234 100644
--- a/app/javascript/dashboard/i18n/locale/zh_CN/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/zh_CN/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp 模板列表",
- "SUBTITLE": "请选择想要发送的 Whatsapp 消息模板",
- "TEMPLATE_SELECTED_SUBTITLE": "{templateName} 处理中"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "查找模板",
- "NO_TEMPLATES_FOUND": "没有找到对应的模版",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "语言",
- "TEMPLATE_BODY": "模板内容",
- "CATEGORY": "类别"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "参数",
- "VARIABLE_PLACEHOLDER": "请填写 {variable}",
- "GO_BACK_LABEL": "返回",
- "SEND_MESSAGE_LABEL": "发送消息",
- "FORM_ERROR_MESSAGE": "你必须填写所有参数才能发送"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp 模板列表",
+ "SUBTITLE": "请选择想要发送的 Whatsapp 消息模板",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "查找模板",
+ "NO_TEMPLATES_FOUND": "没有找到对应的模版",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "类别",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "语言",
+ "TEMPLATE_BODY": "模板内容",
+ "CATEGORY": "类别"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "参数",
+ "LANGUAGE": "语言",
+ "CATEGORY": "类别",
+ "VARIABLE_PLACEHOLDER": "请填写 {variable}",
+ "GO_BACK_LABEL": "返回",
+ "SEND_MESSAGE_LABEL": "发送消息",
+ "FORM_ERROR_MESSAGE": "你必须填写所有参数才能发送",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/dashboard/i18n/locale/zh_TW/automation.json b/app/javascript/dashboard/i18n/locale/zh_TW/automation.json
index d44d241ff..416683ea6 100644
--- a/app/javascript/dashboard/i18n/locale/zh_TW/automation.json
+++ b/app/javascript/dashboard/i18n/locale/zh_TW/automation.json
@@ -131,6 +131,7 @@
"CONVERSATION_CREATED": "Conversation Created",
"CONVERSATION_UPDATED": "Conversation Updated",
"MESSAGE_CREATED": "Message Created",
+ "CONVERSATION_RESOLVED": "Conversation Resolved",
"CONVERSATION_OPENED": "Conversation Opened"
},
"ACTIONS": {
diff --git a/app/javascript/dashboard/i18n/locale/zh_TW/integrations.json b/app/javascript/dashboard/i18n/locale/zh_TW/integrations.json
index df361a65c..598fc185b 100644
--- a/app/javascript/dashboard/i18n/locale/zh_TW/integrations.json
+++ b/app/javascript/dashboard/i18n/locale/zh_TW/integrations.json
@@ -472,7 +472,8 @@
"FEATURES": {
"TITLE": "Features",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
- "ALLOW_MEMORIES": "Capture key details as memories from customer interactions."
+ "ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
+ "ALLOW_CITATIONS": "Include source citations in responses"
}
},
"EDIT": {
diff --git a/app/javascript/dashboard/i18n/locale/zh_TW/whatsappTemplates.json b/app/javascript/dashboard/i18n/locale/zh_TW/whatsappTemplates.json
index 4887d07b6..5f53faaa8 100644
--- a/app/javascript/dashboard/i18n/locale/zh_TW/whatsappTemplates.json
+++ b/app/javascript/dashboard/i18n/locale/zh_TW/whatsappTemplates.json
@@ -1,29 +1,46 @@
{
- "WHATSAPP_TEMPLATES": {
- "MODAL": {
- "TITLE": "Whatsapp Templates",
- "SUBTITLE": "Select the whatsapp template you want to send",
- "TEMPLATE_SELECTED_SUBTITLE": "Process {templateName}"
- },
- "PICKER": {
- "SEARCH_PLACEHOLDER": "Search Templates",
- "NO_TEMPLATES_FOUND": "No templates found for",
- "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
- "REFRESH_BUTTON": "Refresh templates",
- "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
- "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
- "LABELS": {
- "LANGUAGE": "Language",
- "TEMPLATE_BODY": "Template Body",
- "CATEGORY": "Category"
- }
- },
- "PARSER": {
- "VARIABLES_LABEL": "Variables",
- "VARIABLE_PLACEHOLDER": "Enter {variable} value",
- "GO_BACK_LABEL": "Go Back",
- "SEND_MESSAGE_LABEL": "Send Message",
- "FORM_ERROR_MESSAGE": "Please fill all variables before sending"
- }
+ "WHATSAPP_TEMPLATES": {
+ "MODAL": {
+ "TITLE": "Whatsapp Templates",
+ "SUBTITLE": "Select the whatsapp template you want to send",
+ "TEMPLATE_SELECTED_SUBTITLE": "Configure template: {templateName}"
+ },
+ "PICKER": {
+ "SEARCH_PLACEHOLDER": "Search Templates",
+ "NO_TEMPLATES_FOUND": "No templates found for",
+ "HEADER": "Header",
+ "BODY": "Body",
+ "FOOTER": "Footer",
+ "BUTTONS": "Buttons",
+ "CATEGORY": "Category",
+ "MEDIA_CONTENT": "Media Content",
+ "MEDIA_CONTENT_FALLBACK": "media content",
+ "NO_TEMPLATES_AVAILABLE": "No WhatsApp templates available. Click refresh to sync templates from WhatsApp.",
+ "REFRESH_BUTTON": "Refresh templates",
+ "REFRESH_SUCCESS": "Templates refresh initiated. It may take a couple of minutes to update.",
+ "REFRESH_ERROR": "Failed to refresh templates. Please try again.",
+ "LABELS": {
+ "LANGUAGE": "Language",
+ "TEMPLATE_BODY": "Template Body",
+ "CATEGORY": "Category"
+ }
+ },
+ "PARSER": {
+ "VARIABLES_LABEL": "Variables",
+ "LANGUAGE": "Language",
+ "CATEGORY": "Category",
+ "VARIABLE_PLACEHOLDER": "Enter {variable} value",
+ "GO_BACK_LABEL": "Go Back",
+ "SEND_MESSAGE_LABEL": "Send Message",
+ "FORM_ERROR_MESSAGE": "Please fill all variables before sending",
+ "MEDIA_HEADER_LABEL": "{type} Header",
+ "OTP_CODE": "Enter 4-8 digit OTP",
+ "EXPIRY_MINUTES": "Enter expiry minutes",
+ "BUTTON_PARAMETERS": "Button Parameters",
+ "BUTTON_LABEL": "Button {index}",
+ "COUPON_CODE": "Enter coupon code (max 15 chars)",
+ "MEDIA_URL_LABEL": "Enter {type} URL",
+ "BUTTON_PARAMETER": "Enter button parameter"
}
+ }
}
diff --git a/app/javascript/widget/i18n/locale/am.json b/app/javascript/widget/i18n/locale/am.json
index 279ead47e..4f244c566 100644
--- a/app/javascript/widget/i18n/locale/am.json
+++ b/app/javascript/widget/i18n/locale/am.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "We are online",
"OFFLINE": "We are away at the moment"
diff --git a/app/javascript/widget/i18n/locale/ar.json b/app/javascript/widget/i18n/locale/ar.json
index 66f271cdd..21b1c072e 100644
--- a/app/javascript/widget/i18n/locale/ar.json
+++ b/app/javascript/widget/i18n/locale/ar.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "تعذر الإرسال! حاول مرة أخرى"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "متواجدون لخدمتك",
"OFFLINE": "نحن بعيدون في الوقت الحالي"
diff --git a/app/javascript/widget/i18n/locale/az.json b/app/javascript/widget/i18n/locale/az.json
index 279ead47e..4f244c566 100644
--- a/app/javascript/widget/i18n/locale/az.json
+++ b/app/javascript/widget/i18n/locale/az.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "We are online",
"OFFLINE": "We are away at the moment"
diff --git a/app/javascript/widget/i18n/locale/bg.json b/app/javascript/widget/i18n/locale/bg.json
index f289bf5eb..1fd4bc35d 100644
--- a/app/javascript/widget/i18n/locale/bg.json
+++ b/app/javascript/widget/i18n/locale/bg.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "На линия сме",
"OFFLINE": "В момента не сме на линия"
diff --git a/app/javascript/widget/i18n/locale/ca.json b/app/javascript/widget/i18n/locale/ca.json
index 4e464a6eb..6ae69fcb6 100644
--- a/app/javascript/widget/i18n/locale/ca.json
+++ b/app/javascript/widget/i18n/locale/ca.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "No s'ha pogut enviar, torna-ho a provar"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Estem en línia",
"OFFLINE": "Estem fora en aquest moment"
diff --git a/app/javascript/widget/i18n/locale/cs.json b/app/javascript/widget/i18n/locale/cs.json
index e33d963f1..adefb1eb4 100644
--- a/app/javascript/widget/i18n/locale/cs.json
+++ b/app/javascript/widget/i18n/locale/cs.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Odeslání se nezdařilo, zkuste to znovu"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Jsme online",
"OFFLINE": "V současné době jsme pryč"
diff --git a/app/javascript/widget/i18n/locale/da.json b/app/javascript/widget/i18n/locale/da.json
index 0b5cb5722..31303d4d5 100644
--- a/app/javascript/widget/i18n/locale/da.json
+++ b/app/javascript/widget/i18n/locale/da.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Kunne ikke sende, prøv igen"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Vi er online",
"OFFLINE": "Vi er ikke tilgængelige i øjeblikket"
diff --git a/app/javascript/widget/i18n/locale/de.json b/app/javascript/widget/i18n/locale/de.json
index 7508c1f77..b7490c368 100644
--- a/app/javascript/widget/i18n/locale/de.json
+++ b/app/javascript/widget/i18n/locale/de.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Senden nicht möglich, versuchen Sie es noch einmal"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Wir sind online",
"OFFLINE": "Wir sind momentan abwesend"
diff --git a/app/javascript/widget/i18n/locale/el.json b/app/javascript/widget/i18n/locale/el.json
index 5ca095053..1cb35a76b 100644
--- a/app/javascript/widget/i18n/locale/el.json
+++ b/app/javascript/widget/i18n/locale/el.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Αδυναμία αποστολής! Προσπαθήστε ξανά"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Είμαστε online",
"OFFLINE": "Προς το παρόν, είμαστε εκτός"
diff --git a/app/javascript/widget/i18n/locale/es.json b/app/javascript/widget/i18n/locale/es.json
index 62837335b..9c807ed84 100644
--- a/app/javascript/widget/i18n/locale/es.json
+++ b/app/javascript/widget/i18n/locale/es.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "¡No se pudo enviar! intente nuevamente"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Estamos en línea",
"OFFLINE": "Estamos ausentes en este momento"
diff --git a/app/javascript/widget/i18n/locale/fa.json b/app/javascript/widget/i18n/locale/fa.json
index bd1854fc5..982df19ac 100644
--- a/app/javascript/widget/i18n/locale/fa.json
+++ b/app/javascript/widget/i18n/locale/fa.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "ارسال نشد، دوباره امتحان کنید"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "ما آنلاین هستیم",
"OFFLINE": "در حال حاضر دردسترس نیستیم"
diff --git a/app/javascript/widget/i18n/locale/fi.json b/app/javascript/widget/i18n/locale/fi.json
index 59b827bac..a5d742303 100644
--- a/app/javascript/widget/i18n/locale/fi.json
+++ b/app/javascript/widget/i18n/locale/fi.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Ei voitu lähettää, yritä uudestaan"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Olemme online-tilassa",
"OFFLINE": "Olemme tällä hetkellä poissa"
diff --git a/app/javascript/widget/i18n/locale/fr.json b/app/javascript/widget/i18n/locale/fr.json
index 4552a55cc..ff25bbd45 100644
--- a/app/javascript/widget/i18n/locale/fr.json
+++ b/app/javascript/widget/i18n/locale/fr.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Échec de l'envoi, veuillez réessayer"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Nous sommes en ligne",
"OFFLINE": "Nous sommes absents pour le moment"
diff --git a/app/javascript/widget/i18n/locale/he.json b/app/javascript/widget/i18n/locale/he.json
index 8b235cffc..1eaa103db 100644
--- a/app/javascript/widget/i18n/locale/he.json
+++ b/app/javascript/widget/i18n/locale/he.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "לא ניתן לשלוח, נסה שוב"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "אנחנו אונליין",
"OFFLINE": "אנחנו לא זמינים כרגע"
diff --git a/app/javascript/widget/i18n/locale/hi.json b/app/javascript/widget/i18n/locale/hi.json
index 279ead47e..4f244c566 100644
--- a/app/javascript/widget/i18n/locale/hi.json
+++ b/app/javascript/widget/i18n/locale/hi.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "We are online",
"OFFLINE": "We are away at the moment"
diff --git a/app/javascript/widget/i18n/locale/hr.json b/app/javascript/widget/i18n/locale/hr.json
index 7d468f407..37cf7b53e 100644
--- a/app/javascript/widget/i18n/locale/hr.json
+++ b/app/javascript/widget/i18n/locale/hr.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Nismo uspjeli poslati, pokušajte ponovno"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Online smo",
"OFFLINE": "Trenutačno nismo online"
diff --git a/app/javascript/widget/i18n/locale/hu.json b/app/javascript/widget/i18n/locale/hu.json
index 578639c1e..81c4b6886 100644
--- a/app/javascript/widget/i18n/locale/hu.json
+++ b/app/javascript/widget/i18n/locale/hu.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Nem sikerült az elküldés, kérjük próbáld később"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Online vagyunk",
"OFFLINE": "Jelenleg nem vagyunk elérhetőek"
diff --git a/app/javascript/widget/i18n/locale/hy.json b/app/javascript/widget/i18n/locale/hy.json
index 279ead47e..4f244c566 100644
--- a/app/javascript/widget/i18n/locale/hy.json
+++ b/app/javascript/widget/i18n/locale/hy.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "We are online",
"OFFLINE": "We are away at the moment"
diff --git a/app/javascript/widget/i18n/locale/id.json b/app/javascript/widget/i18n/locale/id.json
index 363fff802..e7fbec8ad 100644
--- a/app/javascript/widget/i18n/locale/id.json
+++ b/app/javascript/widget/i18n/locale/id.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Tidak dapat mengirim, coba lagi"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Kami sedang online",
"OFFLINE": "Kami sedang tidak tersedia saat ini"
diff --git a/app/javascript/widget/i18n/locale/is.json b/app/javascript/widget/i18n/locale/is.json
index f2d295418..b794493f4 100644
--- a/app/javascript/widget/i18n/locale/is.json
+++ b/app/javascript/widget/i18n/locale/is.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Tókst ekki að senda skilaboðin, reyndu aftur"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Við erum tengd",
"OFFLINE": "Það er enginn við í augnablikinu"
diff --git a/app/javascript/widget/i18n/locale/it.json b/app/javascript/widget/i18n/locale/it.json
index 0e58af2de..7e0385220 100644
--- a/app/javascript/widget/i18n/locale/it.json
+++ b/app/javascript/widget/i18n/locale/it.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Impossibile inviare, riprova"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Siamo online",
"OFFLINE": "Siamo offline in questo momento"
diff --git a/app/javascript/widget/i18n/locale/ja.json b/app/javascript/widget/i18n/locale/ja.json
index fa97a8d63..17c4beae0 100644
--- a/app/javascript/widget/i18n/locale/ja.json
+++ b/app/javascript/widget/i18n/locale/ja.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "送信できませんでした。もう一度お試しください"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "オンライン",
"OFFLINE": "留守中"
diff --git a/app/javascript/widget/i18n/locale/ka.json b/app/javascript/widget/i18n/locale/ka.json
index 279ead47e..4f244c566 100644
--- a/app/javascript/widget/i18n/locale/ka.json
+++ b/app/javascript/widget/i18n/locale/ka.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "We are online",
"OFFLINE": "We are away at the moment"
diff --git a/app/javascript/widget/i18n/locale/ko.json b/app/javascript/widget/i18n/locale/ko.json
index f1c189070..ef8d15a6e 100644
--- a/app/javascript/widget/i18n/locale/ko.json
+++ b/app/javascript/widget/i18n/locale/ko.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "전송하지 못했습니다. 다시 시도해보세요."
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "온라인",
"OFFLINE": "부재중"
diff --git a/app/javascript/widget/i18n/locale/lt.json b/app/javascript/widget/i18n/locale/lt.json
index 98b89da99..fb61b586e 100644
--- a/app/javascript/widget/i18n/locale/lt.json
+++ b/app/javascript/widget/i18n/locale/lt.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Nepavyko išsiųsti! bandykite dar kartą"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Mes prisijungę",
"OFFLINE": "Šiuo metu esame atsijungę"
diff --git a/app/javascript/widget/i18n/locale/lv.json b/app/javascript/widget/i18n/locale/lv.json
index 19ca42914..5262e87f7 100644
--- a/app/javascript/widget/i18n/locale/lv.json
+++ b/app/javascript/widget/i18n/locale/lv.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Nevarēja nosūtīt. Lūdzu, mēģiniet vēlreiz"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Mēs esam tiešsaistē",
"OFFLINE": "Šobrīd mēs neesam uz vietas"
diff --git a/app/javascript/widget/i18n/locale/ml.json b/app/javascript/widget/i18n/locale/ml.json
index c1071b35a..c4761e99f 100644
--- a/app/javascript/widget/i18n/locale/ml.json
+++ b/app/javascript/widget/i18n/locale/ml.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "അയയ്ക്കാനായില്ല, വീണ്ടും ശ്രമിക്കുക"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "ഞങ്ങൾ ഓൺലൈനിലാണ്",
"OFFLINE": "ഞങ്ങൾ ഇപ്പോൾ അകലെയാണ്"
diff --git a/app/javascript/widget/i18n/locale/ms.json b/app/javascript/widget/i18n/locale/ms.json
index 78747073d..4dcbc5f57 100644
--- a/app/javascript/widget/i18n/locale/ms.json
+++ b/app/javascript/widget/i18n/locale/ms.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "We are online",
"OFFLINE": "We are away at the moment"
diff --git a/app/javascript/widget/i18n/locale/ne.json b/app/javascript/widget/i18n/locale/ne.json
index a6041a758..5201951e5 100644
--- a/app/javascript/widget/i18n/locale/ne.json
+++ b/app/javascript/widget/i18n/locale/ne.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "हामी अनलाइन छौं",
"OFFLINE": "We are away at the moment"
diff --git a/app/javascript/widget/i18n/locale/nl.json b/app/javascript/widget/i18n/locale/nl.json
index 48f62678d..a33be5f90 100644
--- a/app/javascript/widget/i18n/locale/nl.json
+++ b/app/javascript/widget/i18n/locale/nl.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Verzenden mislukt, probeer het opnieuw"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "We zijn online",
"OFFLINE": "We zijn momenteel afwezig"
diff --git a/app/javascript/widget/i18n/locale/no.json b/app/javascript/widget/i18n/locale/no.json
index f9d46a712..fa2c5a2b2 100644
--- a/app/javascript/widget/i18n/locale/no.json
+++ b/app/javascript/widget/i18n/locale/no.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Kunne ikke sende, prøv på nytt"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Vi er pålogget",
"OFFLINE": "Vi er for øyeblikket borte"
diff --git a/app/javascript/widget/i18n/locale/pl.json b/app/javascript/widget/i18n/locale/pl.json
index 704eb0567..c143e3b00 100644
--- a/app/javascript/widget/i18n/locale/pl.json
+++ b/app/javascript/widget/i18n/locale/pl.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Nie udało się wysłać! Spróbuj ponownie"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Jesteśmy dostępni",
"OFFLINE": "W tej chwili jesteśmy niedostępni"
diff --git a/app/javascript/widget/i18n/locale/pt.json b/app/javascript/widget/i18n/locale/pt.json
index fd320fbf9..c1fffb681 100644
--- a/app/javascript/widget/i18n/locale/pt.json
+++ b/app/javascript/widget/i18n/locale/pt.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Não foi possível enviar, tente novamente"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Estamos online",
"OFFLINE": "Estamos ausentes"
diff --git a/app/javascript/widget/i18n/locale/pt_BR.json b/app/javascript/widget/i18n/locale/pt_BR.json
index c3dde21aa..f979fddca 100644
--- a/app/javascript/widget/i18n/locale/pt_BR.json
+++ b/app/javascript/widget/i18n/locale/pt_BR.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Não foi possível enviar, tente novamente"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Estamos conectados",
"OFFLINE": "Estamos ausentes no momento"
diff --git a/app/javascript/widget/i18n/locale/ro.json b/app/javascript/widget/i18n/locale/ro.json
index 35150d67a..e030c50b2 100644
--- a/app/javascript/widget/i18n/locale/ro.json
+++ b/app/javascript/widget/i18n/locale/ro.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Nu s-a putut trimite! Încearcă din nou"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Suntem online",
"OFFLINE": "Suntem plecați în acest moment"
diff --git a/app/javascript/widget/i18n/locale/ru.json b/app/javascript/widget/i18n/locale/ru.json
index de468106d..734a3a035 100644
--- a/app/javascript/widget/i18n/locale/ru.json
+++ b/app/javascript/widget/i18n/locale/ru.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Не удалось отправить! Попробуйте еще раз"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Мы в сети",
"OFFLINE": "В данный момент мы отсутствуем"
diff --git a/app/javascript/widget/i18n/locale/sh.json b/app/javascript/widget/i18n/locale/sh.json
index 279ead47e..4f244c566 100644
--- a/app/javascript/widget/i18n/locale/sh.json
+++ b/app/javascript/widget/i18n/locale/sh.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "We are online",
"OFFLINE": "We are away at the moment"
diff --git a/app/javascript/widget/i18n/locale/sk.json b/app/javascript/widget/i18n/locale/sk.json
index e61b9a498..60dc03162 100644
--- a/app/javascript/widget/i18n/locale/sk.json
+++ b/app/javascript/widget/i18n/locale/sk.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Sme online",
"OFFLINE": "Momentálne nie sme k dispozícii"
diff --git a/app/javascript/widget/i18n/locale/sl.json b/app/javascript/widget/i18n/locale/sl.json
index 365132414..8665e1e1b 100644
--- a/app/javascript/widget/i18n/locale/sl.json
+++ b/app/javascript/widget/i18n/locale/sl.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Ni bilo mogoče poslati, poskusite znova"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Smo na voljo",
"OFFLINE": "Trenutno nismo na voljo"
diff --git a/app/javascript/widget/i18n/locale/sq.json b/app/javascript/widget/i18n/locale/sq.json
index 994317343..34fe645e9 100644
--- a/app/javascript/widget/i18n/locale/sq.json
+++ b/app/javascript/widget/i18n/locale/sq.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Nuk mund të dërgohej, provo sërish"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Ne jemi online",
"OFFLINE": "Nuk jemi online për momentin"
diff --git a/app/javascript/widget/i18n/locale/sr.json b/app/javascript/widget/i18n/locale/sr.json
index 8ac036a95..039982ee6 100644
--- a/app/javascript/widget/i18n/locale/sr.json
+++ b/app/javascript/widget/i18n/locale/sr.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Slanje neuspešno, pokušajte ponovo"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Dostupni smo",
"OFFLINE": "Trenutno nismo dostupni"
diff --git a/app/javascript/widget/i18n/locale/sv.json b/app/javascript/widget/i18n/locale/sv.json
index 91e6c682f..d65e39358 100644
--- a/app/javascript/widget/i18n/locale/sv.json
+++ b/app/javascript/widget/i18n/locale/sv.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Kunde inte skicka, försök igen"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Vi är online",
"OFFLINE": "Vi är borta för tillfället"
diff --git a/app/javascript/widget/i18n/locale/ta.json b/app/javascript/widget/i18n/locale/ta.json
index 5cb9152f9..27e069ea7 100644
--- a/app/javascript/widget/i18n/locale/ta.json
+++ b/app/javascript/widget/i18n/locale/ta.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "We are online",
"OFFLINE": "We are away at the moment"
diff --git a/app/javascript/widget/i18n/locale/th.json b/app/javascript/widget/i18n/locale/th.json
index f562571fe..a1e39c2f5 100644
--- a/app/javascript/widget/i18n/locale/th.json
+++ b/app/javascript/widget/i18n/locale/th.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "ไม่สามารถส่งได้ ลองอีกครั้ง"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "เรากำลังออนไลน์",
"OFFLINE": "เราไม่อยู่"
diff --git a/app/javascript/widget/i18n/locale/tl.json b/app/javascript/widget/i18n/locale/tl.json
index 279ead47e..4f244c566 100644
--- a/app/javascript/widget/i18n/locale/tl.json
+++ b/app/javascript/widget/i18n/locale/tl.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "We are online",
"OFFLINE": "We are away at the moment"
diff --git a/app/javascript/widget/i18n/locale/tr.json b/app/javascript/widget/i18n/locale/tr.json
index be37c488b..b346504fe 100644
--- a/app/javascript/widget/i18n/locale/tr.json
+++ b/app/javascript/widget/i18n/locale/tr.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Gönderilemedi, tekrar deneyin"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Çevrimiçi",
"OFFLINE": "Şu an operatörlerimiz müsait değil"
diff --git a/app/javascript/widget/i18n/locale/uk.json b/app/javascript/widget/i18n/locale/uk.json
index 679761f6a..aed413394 100644
--- a/app/javascript/widget/i18n/locale/uk.json
+++ b/app/javascript/widget/i18n/locale/uk.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Не вдалося надіслати, спробуйте ще раз"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Ми онлайн",
"OFFLINE": "Нас наразі немає"
diff --git a/app/javascript/widget/i18n/locale/ur.json b/app/javascript/widget/i18n/locale/ur.json
index 8e3c7687c..3869ab5d6 100644
--- a/app/javascript/widget/i18n/locale/ur.json
+++ b/app/javascript/widget/i18n/locale/ur.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "We are online",
"OFFLINE": "We are away at the moment"
diff --git a/app/javascript/widget/i18n/locale/ur_IN.json b/app/javascript/widget/i18n/locale/ur_IN.json
index 279ead47e..4f244c566 100644
--- a/app/javascript/widget/i18n/locale/ur_IN.json
+++ b/app/javascript/widget/i18n/locale/ur_IN.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Couldn't send, try again"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "We are online",
"OFFLINE": "We are away at the moment"
diff --git a/app/javascript/widget/i18n/locale/vi.json b/app/javascript/widget/i18n/locale/vi.json
index 952a16f1f..d12dbc8db 100644
--- a/app/javascript/widget/i18n/locale/vi.json
+++ b/app/javascript/widget/i18n/locale/vi.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "Không thể gửi, xin thử lại"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "Chúng tôi đang trực tuyến",
"OFFLINE": "Hiện tại chúng tôi đang bận chút"
diff --git a/app/javascript/widget/i18n/locale/zh_CN.json b/app/javascript/widget/i18n/locale/zh_CN.json
index f7d27c267..dd834af87 100644
--- a/app/javascript/widget/i18n/locale/zh_CN.json
+++ b/app/javascript/widget/i18n/locale/zh_CN.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "无法发送,请重试"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "在线",
"OFFLINE": "当前已离线"
diff --git a/app/javascript/widget/i18n/locale/zh_TW.json b/app/javascript/widget/i18n/locale/zh_TW.json
index 85f08a135..3f46d258f 100644
--- a/app/javascript/widget/i18n/locale/zh_TW.json
+++ b/app/javascript/widget/i18n/locale/zh_TW.json
@@ -12,6 +12,11 @@
"ERROR_MESSAGE": "無法傳送!請重新嘗試。"
}
},
+ "THUMBNAIL": {
+ "AUTHOR": {
+ "NOT_AVAILABLE": "Not available"
+ }
+ },
"TEAM_AVAILABILITY": {
"ONLINE": "我們在線上",
"OFFLINE": "我們目前不在線上"
From b809cd2f15391cac13625471fd4e17f61dc204a1 Mon Sep 17 00:00:00 2001
From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Date: Thu, 14 Aug 2025 19:07:20 +0530
Subject: [PATCH 19/26] chore: Optimize contact page for smaller displays
(#12183)
Co-authored-by: Muhsin Keloth
---
.../Contacts/ContactsDetailsLayout.vue | 74 +++++++++++-
.../Contacts/ContactsHeader/ContactHeader.vue | 111 +++++++++---------
.../ContactListHeaderWrapper.vue | 25 ++--
.../components/ContactSortMenu.vue | 2 +-
.../Contacts/ContactsListLayout.vue | 5 +-
.../ConversationCard/CardMessagePreview.vue | 1 +
.../CardMessagePreviewWithMeta.vue | 1 +
.../components-next/breadcrumb/Breadcrumb.vue | 16 ++-
.../components-next/filter/ConditionRow.vue | 1 +
.../components-next/filter/ContactsFilter.vue | 6 +-
10 files changed, 162 insertions(+), 80 deletions(-)
diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsDetailsLayout.vue b/app/javascript/dashboard/components-next/Contacts/ContactsDetailsLayout.vue
index bb4327816..51d306311 100644
--- a/app/javascript/dashboard/components-next/Contacts/ContactsDetailsLayout.vue
+++ b/app/javascript/dashboard/components-next/Contacts/ContactsDetailsLayout.vue
@@ -1,7 +1,8 @@
@@ -67,7 +79,9 @@ const toggleBlock = () => {
>
-
+
{
+
+
+
+
diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactHeader.vue b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactHeader.vue
index 30717c036..b3590b51e 100644
--- a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactHeader.vue
+++ b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactHeader.vue
@@ -34,13 +34,13 @@ const emit = defineEmits([
{{ headerTitle }}
-
-
+
+
@@ -58,64 +59,66 @@ const emit = defineEmits([
-
-
+
+
+
-
+ @click="emit('createSegment')"
+ />
+
+
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactListHeaderWrapper.vue b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactListHeaderWrapper.vue
index f2927657d..ea5c63ebc 100644
--- a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactListHeaderWrapper.vue
+++ b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/ContactListHeaderWrapper.vue
@@ -291,17 +291,20 @@ defineExpose({
@delete-segment="openDeleteSegmentDialog"
>
-
+
+
+
diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactSortMenu.vue b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactSortMenu.vue
index 7125d8385..a13a7a81d 100644
--- a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactSortMenu.vue
+++ b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/ContactSortMenu.vue
@@ -105,7 +105,7 @@ const handleOrderChange = value => {
diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsListLayout.vue b/app/javascript/dashboard/components-next/Contacts/ContactsListLayout.vue
index 78a69654c..648cd84d6 100644
--- a/app/javascript/dashboard/components-next/Contacts/ContactsListLayout.vue
+++ b/app/javascript/dashboard/components-next/Contacts/ContactsListLayout.vue
@@ -96,10 +96,7 @@ const openFilter = () => {
-
diff --git a/app/javascript/dashboard/components-next/filter/ContactsFilter.vue b/app/javascript/dashboard/components-next/filter/ContactsFilter.vue
index bd588ccbf..a8af5292e 100644
--- a/app/javascript/dashboard/components-next/filter/ContactsFilter.vue
+++ b/app/javascript/dashboard/components-next/filter/ContactsFilter.vue
@@ -104,7 +104,7 @@ const outsideClickHandler = [
{{ filterModalHeaderTitle }}
@@ -146,10 +146,10 @@ const outsideClickHandler = [
-