Merge branch 'develop' into feat/new-auth-screens

This commit is contained in:
Muhsin Keloth 2022-03-21 17:19:36 +05:30 committed by GitHub
commit 21efdf5c56
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 489 additions and 211 deletions

View file

@ -42,7 +42,7 @@ gem 'down', '~> 5.0'
gem 'aws-sdk-s3', require: false
gem 'azure-storage-blob', require: false
gem 'google-cloud-storage', require: false
gem 'image_processing'
gem 'image_processing', '~> 1.12.2'
##-- gems for database --#
gem 'groupdate'

View file

@ -688,7 +688,7 @@ DEPENDENCIES
hairtrigger
hashie
html2text
image_processing
image_processing (~> 1.12.2)
jbuilder
json_refs
json_schemer

View file

@ -34,7 +34,7 @@ class Api::V1::Accounts::AutomationRulesController < Api::V1::Accounts::BaseCont
params.permit(
:name, :description, :event_name, :account_id, :active,
conditions: [:attribute_key, :filter_operator, :query_operator, { values: [] }],
actions: [:action_name, { action_params: [] }]
actions: [:action_name, { action_params: [{}] }]
)
end

View file

@ -22,7 +22,7 @@
"is_not_present": "غير موجود",
"is_greater_than": "هو أكبر من",
"is_less_than": "هو أقل من",
"days_before": "Is x days before"
"days_before": "قبل x أيام"
},
"ATTRIBUTE_LABELS": {
"TRUE": "صحيح",
@ -44,7 +44,7 @@
"CUSTOM_ATTRIBUTE_NUMBER": "العدد",
"CUSTOM_ATTRIBUTE_LINK": "الرابط",
"CUSTOM_ATTRIBUTE_CHECKBOX": "مربع",
"CREATED_AT": "Created At",
"CREATED_AT": "تم إنشاؤها في",
"LAST_ACTIVITY": "آخر نشاط"
},
"GROUPS": {

View file

@ -23,7 +23,7 @@
"is_not_present": "غير موجود",
"is_greater_than": "هو أكبر من",
"is_lesser_than": "هو أقل من",
"days_before": "Is x days before"
"days_before": "قبل x أيام"
},
"ATTRIBUTES": {
"NAME": "الاسم",
@ -37,7 +37,7 @@
"CUSTOM_ATTRIBUTE_NUMBER": "العدد",
"CUSTOM_ATTRIBUTE_LINK": "الرابط",
"CUSTOM_ATTRIBUTE_CHECKBOX": "مربع",
"CREATED_AT": "Created At",
"CREATED_AT": "تم إنشاؤها في",
"LAST_ACTIVITY": "آخر نشاط"
},
"GROUPS": {

View file

@ -48,7 +48,7 @@
}
},
"UPDATE_CHATWOOT": "يتوفر تحديث %{latestChatwootVersion} لـ Chatwoot. الرجاء التحديث.",
"LEARN_MORE": "Learn more"
"LEARN_MORE": "اعرف المزيد"
},
"FORMS": {
"MULTISELECT": {

View file

@ -186,7 +186,7 @@
"NO_CONTACTS": "There are no available contacts",
"TABLE_HEADER": {
"NAME": "Nome",
"PHONE_NUMBER": "Phone Number",
"PHONE_NUMBER": "Numero di telefono",
"CONVERSATIONS": "Conversazioni",
"LAST_ACTIVITY": "Last Activity",
"COUNTRY": "Country",

View file

@ -2,7 +2,7 @@
"GENERAL_SETTINGS": {
"TITLE": "Impostazioni account",
"SUBMIT": "Aggiorna le impostazioni",
"BACK": "Back",
"BACK": "Indietro",
"UPDATE": {
"ERROR": "Impossibile aggiornare le impostazioni, riprova!",
"SUCCESS": "Impostazioni account aggiornate con successo"
@ -14,8 +14,8 @@
"NOTE": ""
},
"ACCOUNT_ID": {
"TITLE": "Account ID",
"NOTE": "This ID is required if you are building an API based integration"
"TITLE": "ID Account",
"NOTE": "Questo ID è richiesto se si sta costruendo un'integrazione basata su API"
},
"NAME": {
"LABEL": "Nome account",
@ -28,8 +28,8 @@
"ERROR": ""
},
"DOMAIN": {
"LABEL": "Incoming Email Domain",
"PLACEHOLDER": "The domain where you will receive the emails",
"LABEL": "Dominio email in entrata",
"PLACEHOLDER": "Il dominio in cui riceverai le email",
"ERROR": ""
},
"SUPPORT_EMAIL": {
@ -38,95 +38,95 @@
"ERROR": ""
},
"AUTO_RESOLVE_DURATION": {
"LABEL": "Number of days after a ticket should auto resolve if there is no activity",
"LABEL": "Numero di giorni dopo che un ticket dovrebbe risolvere automaticamente se non c'è attività",
"PLACEHOLDER": "30",
"ERROR": "Please enter a valid auto resolve duration (minimum 1 day and maximum 999 days)"
"ERROR": "Inserisci una durata di risoluzione automatica valida (minimo 1 giorno e massimo 999 giorni)"
},
"FEATURES": {
"INBOUND_EMAIL_ENABLED": "Conversation continuity with emails is enabled for your account.",
"CUSTOM_EMAIL_DOMAIN_ENABLED": "You can receive emails in your custom domain now."
"INBOUND_EMAIL_ENABLED": "La continuità della conversazione con le email è abilitata per il tuo account.",
"CUSTOM_EMAIL_DOMAIN_ENABLED": "Puoi ricevere email nel tuo dominio personalizzato ora."
}
},
"UPDATE_CHATWOOT": "An update %{latestChatwootVersion} for Chatwoot is available. Please update your instance.",
"LEARN_MORE": "Learn more"
"UPDATE_CHATWOOT": "È disponibile un aggiornamento %{latestChatwootVersion} per Chatwoot. Aggiorna la tua istanza.",
"LEARN_MORE": "Scopri di più"
},
"FORMS": {
"MULTISELECT": {
"ENTER_TO_SELECT": "Press enter to select",
"ENTER_TO_REMOVE": "Press enter to remove",
"SELECT_ONE": "Select one"
"ENTER_TO_SELECT": "Premi Invio per selezionare",
"ENTER_TO_REMOVE": "Premi Invio per rimuovere",
"SELECT_ONE": "Selezionane uno"
}
},
"NOTIFICATIONS_PAGE": {
"HEADER": "Notifiche",
"MARK_ALL_DONE": "Mark All Done",
"MARK_ALL_DONE": "Contrassegna tutto come fatto",
"LIST": {
"LOADING_MESSAGE": "Loading notifications...",
"404": "No Notifications",
"LOADING_MESSAGE": "Caricamento notifiche...",
"404": "Nessuna notifica",
"TABLE_HEADER": [
"Nome",
"Phone Number",
"Numero di telefono",
"Conversazioni",
"Last Contacted"
"Ultimo contattato"
]
},
"TYPE_LABEL": {
"conversation_creation": "New conversation",
"conversation_assignment": "Conversation Assigned",
"assigned_conversation_new_message": "New Message",
"conversation_mention": "Mention"
"conversation_creation": "Nuova conversazione",
"conversation_assignment": "Conversazione assegnata",
"assigned_conversation_new_message": "Nuovo messaggio",
"conversation_mention": "Menzione"
}
},
"NETWORK": {
"NOTIFICATION": {
"TEXT": "Disconnected from Chatwoot"
"TEXT": "Disconnesso da Chatwoot"
},
"BUTTON": {
"REFRESH": "Refresh"
"REFRESH": "Aggiorna"
}
},
"COMMAND_BAR": {
"SEARCH_PLACEHOLDER": "Search or jump to",
"SEARCH_PLACEHOLDER": "Cerca o salta a",
"SECTIONS": {
"GENERAL": "General",
"GENERAL": "Generale",
"REPORTS": "Segnalazioni",
"CONVERSATION": "Conversazioni",
"CHANGE_ASSIGNEE": "Change Assignee",
"CHANGE_TEAM": "Change Team",
"ADD_LABEL": "Add label to the conversation",
"REMOVE_LABEL": "Remove label from the conversation",
"CHANGE_ASSIGNEE": "Cambia assegnatario",
"CHANGE_TEAM": "Cambia Team",
"ADD_LABEL": "Aggiungi etichetta alla conversazione",
"REMOVE_LABEL": "Rimuovi etichetta dalla conversazione",
"SETTINGS": "Impostazioni"
},
"COMMANDS": {
"GO_TO_CONVERSATION_DASHBOARD": "Vai alla dashboard Conversazioni",
"GO_TO_CONTACTS_DASHBOARD": "Vai alla dashboard Contatti",
"GO_TO_REPORTS_OVERVIEW": "Go to Reports Overview",
"GO_TO_AGENT_REPORTS": "Go to Agent Reports",
"GO_TO_LABEL_REPORTS": "Go to Label Reports",
"GO_TO_INBOX_REPORTS": "Go to Inbox Reports",
"GO_TO_TEAM_REPORTS": "Go to Team Reports",
"GO_TO_SETTINGS_AGENTS": "Go to Agent Settings",
"GO_TO_SETTINGS_TEAMS": "Go to Team Settings",
"GO_TO_SETTINGS_INBOXES": "Go to Inbox Settings",
"GO_TO_SETTINGS_LABELS": "Go to Label Settings",
"GO_TO_SETTINGS_CANNED_RESPONSES": "Go to Canned Response Settings",
"GO_TO_SETTINGS_APPLICATIONS": "Go to Application Settings",
"GO_TO_SETTINGS_ACCOUNT": "Go to Account Settings",
"GO_TO_SETTINGS_PROFILE": "Go to Profile Settings",
"GO_TO_NOTIFICATIONS": "Go to Notifications",
"ADD_LABELS_TO_CONVERSATION": "Add label to the conversation",
"ASSIGN_AN_AGENT": "Assign an agent",
"ASSIGN_A_TEAM": "Assign a team",
"MUTE_CONVERSATION": "Mute conversation",
"UNMUTE_CONVERSATION": "Unmute conversation",
"REMOVE_LABEL_FROM_CONVERSATION": "Remove label from the conversation",
"GO_TO_REPORTS_OVERVIEW": "Vai alla panoramica dei report",
"GO_TO_AGENT_REPORTS": "Vai ai report degli agenti",
"GO_TO_LABEL_REPORTS": "Vai ai report delle etichette",
"GO_TO_INBOX_REPORTS": "Vai ai report delle caselle",
"GO_TO_TEAM_REPORTS": "Vai ai report dei team",
"GO_TO_SETTINGS_AGENTS": "Vai alle impostazioni dell'agente",
"GO_TO_SETTINGS_TEAMS": "Vai alle impostazioni del team",
"GO_TO_SETTINGS_INBOXES": "Vai alle impostazioni delle caselle",
"GO_TO_SETTINGS_LABELS": "Vai alle impostazioni delle etichette",
"GO_TO_SETTINGS_CANNED_RESPONSES": "Vai alle impostazioni delle risposte predefinite",
"GO_TO_SETTINGS_APPLICATIONS": "Vai alle impostazioni dell'applicazione",
"GO_TO_SETTINGS_ACCOUNT": "Vai alle impostazioni dell'account",
"GO_TO_SETTINGS_PROFILE": "Vai alle impostazioni del profilo",
"GO_TO_NOTIFICATIONS": "Vai alle notifiche",
"ADD_LABELS_TO_CONVERSATION": "Aggiungi etichetta alla conversazione",
"ASSIGN_AN_AGENT": "Assegna un agente",
"ASSIGN_A_TEAM": "Assegna un team",
"MUTE_CONVERSATION": "Silenzia conversazione",
"UNMUTE_CONVERSATION": "Riattiva conversazione",
"REMOVE_LABEL_FROM_CONVERSATION": "Rimuovi etichetta dalla conversazione",
"REOPEN_CONVERSATION": "Riapri la conversazione",
"RESOLVE_CONVERSATION": "Risolvi la conversazione",
"SEND_TRANSCRIPT": "Send an email transcript",
"SNOOZE_CONVERSATION": "Snooze Conversation",
"UNTIL_NEXT_REPLY": "Until next reply",
"UNTIL_NEXT_WEEK": "Until next week",
"UNTIL_TOMORROW": "Until tomorrow"
"SEND_TRANSCRIPT": "Invia una trascrizione email",
"SNOOZE_CONVERSATION": "Posticipa conversazione",
"UNTIL_NEXT_REPLY": "Fino alla prossima risposta",
"UNTIL_NEXT_WEEK": "Fino alla prossima settimana",
"UNTIL_TOMORROW": "Fino a domani"
}
}
}

View file

@ -148,7 +148,7 @@
},
"BANDWIDTH": {
"ACCOUNT_ID": {
"LABEL": "Account ID",
"LABEL": "ID Account",
"PLACEHOLDER": "Please enter your Bandwidth Account ID",
"ERROR": "Questo campo è obbligatorio"
},

View file

@ -22,11 +22,11 @@
"is_not_present": "Não está presente",
"is_greater_than": "É maior do que",
"is_less_than": "É menor do que",
"days_before": "Is x days before"
"days_before": "É x dias antes"
},
"ATTRIBUTE_LABELS": {
"TRUE": "True",
"FALSE": "False"
"TRUE": "Verdadeiro",
"FALSE": "Falso"
},
"ATTRIBUTES": {
"STATUS": "SItuação",
@ -44,7 +44,7 @@
"CUSTOM_ATTRIBUTE_NUMBER": "Número",
"CUSTOM_ATTRIBUTE_LINK": "Endereço",
"CUSTOM_ATTRIBUTE_CHECKBOX": "Caixa de Seleção",
"CREATED_AT": "Created At",
"CREATED_AT": "Criado Em",
"LAST_ACTIVITY": "Última atividade"
},
"GROUPS": {

View file

@ -29,7 +29,7 @@
"PLACEHOLDER": "Por favor, selecione um tipo",
"ERROR": "Tipo é obrigatório",
"LIST": {
"LABEL": "List Values",
"LABEL": "Listar Valores",
"PLACEHOLDER": "Por favor insira um valor e pressione Enter",
"ERROR": "Deve possuir pelo menos um valor"
}
@ -42,7 +42,7 @@
}
},
"API": {
"SUCCESS_MESSAGE": "Custom Attribute added successfully",
"SUCCESS_MESSAGE": "Atributo Personalizado adicionado com sucesso",
"ERROR_MESSAGE": "Could not able to create a custom attribute, Please try again later"
}
},

View file

@ -1,38 +1,38 @@
{
"AUTOMATION": {
"HEADER": "Automations",
"HEADER_BTN_TXT": "Add Automation Rule",
"HEADER": "Automatizações",
"HEADER_BTN_TXT": "Adicionar Regra de Automação",
"LOADING": "Fetching automation rules",
"SIDEBAR_TXT": "<p><b>Automation Rules</b> <p>Automation can replace and automate existing processes that require manual effort. You can do many things with automation, including adding labels and assigning conversation to the best agent. So the team focuses on what they do best and spends more little time on manual tasks.</p>",
"ADD": {
"TITLE": "Add Automation Rule",
"TITLE": "Adicionar Regra de Automação",
"SUBMIT": "Criar",
"CANCEL_BUTTON_TEXT": "cancelar",
"FORM": {
"NAME": {
"LABEL": "Rule Name",
"PLACEHOLDER": "Enter rule name",
"LABEL": "Nome da Regra",
"PLACEHOLDER": "Insira nome da regra",
"ERROR": "Nome é obrigatório"
},
"DESC": {
"LABEL": "Descrição",
"PLACEHOLDER": "Enter rule description",
"PLACEHOLDER": "Insera descrição da regra",
"ERROR": "Descrição é obrigatória"
},
"EVENT": {
"LABEL": "Event",
"LABEL": "Evento",
"PLACEHOLDER": "Por favor selecione um",
"ERROR": "Event is required"
"ERROR": "Evento é necessário"
},
"CONDITIONS": {
"LABEL": "Conditions"
"LABEL": "Condições"
},
"ACTIONS": {
"LABEL": "Ações."
}
},
"CONDITION_BUTTON_LABEL": "Add Condition",
"ACTION_BUTTON_LABEL": "Add Action",
"CONDITION_BUTTON_LABEL": "Adicionar Condição",
"ACTION_BUTTON_LABEL": "Adicionar Ação",
"API": {
"SUCCESS_MESSAGE": "Automation rule added successfully",
"ERROR_MESSAGE": "Could not able to create a automation rule, Please try again later"
@ -43,12 +43,12 @@
"Nome:",
"Descrição",
"Ativa",
"Created on"
"Criado em"
],
"404": "No automation rules found"
"404": "Nenhuma regra de automação encontrada"
},
"DELETE": {
"TITLE": "Delete Automation Rule",
"TITLE": "Apagar Regra de Automação",
"SUBMIT": "excluir",
"CANCEL_BUTTON_TEXT": "cancelar",
"CONFIRM": {
@ -63,7 +63,7 @@
}
},
"EDIT": {
"TITLE": "Edit Automation Rule",
"TITLE": "Editar Regra de Automação",
"SUBMIT": "Atualização",
"CANCEL_BUTTON_TEXT": "cancelar",
"API": {
@ -74,8 +74,8 @@
"CLONE": {
"TOOLTIP": "Clone",
"API": {
"SUCCESS_MESSAGE": "Automation cloned successfully",
"ERROR_MESSAGE": "Could not clone automation rule, Please try again later"
"SUCCESS_MESSAGE": "Automação clonada com sucesso",
"ERROR_MESSAGE": "Não foi possível clonar regra de automação, por favor, tente novamente mais tarde"
}
},
"FORM": {
@ -86,20 +86,20 @@
"RESET_MESSAGE": "Changing event type will reset the conditions and events you have added below"
},
"CONDITION": {
"DELETE_MESSAGE": "You need to have atleast one condition to save"
"DELETE_MESSAGE": "É necessário ter pelo menos uma condição para salvar"
},
"ACTION": {
"DELETE_MESSAGE": "You need to have atleast one action to save"
"DELETE_MESSAGE": "É necessário ter pelo menos uma ação para salvar"
},
"TOGGLE": {
"ACTIVATION_TITLE": "Activate Automation Rule",
"DEACTIVATION_TITLE": "Deactivate Automation Rule",
"ACTIVATION_DESCRIPTION": "This action will activate the automation rule '{automationName}'. Are you sure you want to proceed?",
"DEACTIVATION_DESCRIPTION": "This action will deactivate the automation rule '{automationName}'. Are you sure you want to proceed?",
"ACTIVATION_SUCCESFUL": "Automation Rule Activated Successfully",
"DEACTIVATION_SUCCESFUL": "Automation Rule Deactivated Successfully",
"ACTIVATION_ERROR": "Could not Activate Automation, Please try again later",
"DEACTIVATION_ERROR": "Could not Deactivate Automation, Please try again later",
"ACTIVATION_TITLE": "Ativar Regra de Automação",
"DEACTIVATION_TITLE": "Desativar Regra de Automação",
"ACTIVATION_DESCRIPTION": "Esta ação irá ativar a regra de automação '{automationName}'. Tem a certeza que deseja continuar?",
"DEACTIVATION_DESCRIPTION": "Esta ação irá desativar a regra de automação '{automationName}'. Tem a certeza que deseja continuar?",
"ACTIVATION_SUCCESFUL": "Regra de Automação Ativada com Sucesso",
"DEACTIVATION_SUCCESFUL": "Regra de Automação Desativada com Sucesso",
"ACTIVATION_ERROR": "Não foi possível Ativar a Automação, por favor, tente novamente mais tarde",
"DEACTIVATION_ERROR": "Não foi possível Desativar a Automação, por favor, tente novamente mais tarde",
"CONFIRMATION_LABEL": "Sim",
"CANCEL_LABEL": "Não"
}

View file

@ -54,7 +54,7 @@
"ERROR": "O tempo na página é obrigatório"
},
"ENABLED": "Ativar a campanha",
"TRIGGER_ONLY_BUSINESS_HOURS": "Trigger only during business hours",
"TRIGGER_ONLY_BUSINESS_HOURS": "Ativar apenas durante o horário de trabalho",
"SUBMIT": "Adicionar Campanha"
},
"API": {

View file

@ -1,15 +1,15 @@
{
"CONTACTS_FILTER": {
"TITLE": "Filter Contacts",
"SUBTITLE": "Add filters below and hit 'Submit' to filter contacts.",
"TITLE": "Filtrar Contactos",
"SUBTITLE": "Adicionar filtros abaixo e clicar 'Submeter' para filtrar contactos.",
"ADD_NEW_FILTER": "Adicionar Filtro",
"CLEAR_ALL_FILTERS": "Clear All Filters",
"CLEAR_ALL_FILTERS": "Limpar Todos os Filtros",
"FILTER_DELETE_ERROR": "Você deve ter pelo menos um filtro para guardar",
"SUBMIT_BUTTON_LABEL": "submeter",
"CANCEL_BUTTON_LABEL": "cancelar",
"CLEAR_BUTTON_LABEL": "Limpar Filtros",
"EMPTY_VALUE_ERROR": "Valor obrigatório",
"TOOLTIP_LABEL": "Filter contacts",
"TOOLTIP_LABEL": "Filtrar contactos",
"QUERY_DROPDOWN_LABELS": {
"AND": "E",
"OR": "OU"
@ -23,13 +23,13 @@
"is_not_present": "Não está presente",
"is_greater_than": "É maior do que",
"is_lesser_than": "É menor do que",
"days_before": "Is x days before"
"days_before": "É x dias antes"
},
"ATTRIBUTES": {
"NAME": "Nome:",
"EMAIL": "e-mail",
"PHONE_NUMBER": "Número de telefone",
"IDENTIFIER": "Identifier",
"IDENTIFIER": "Identificador",
"CITY": "Cidade",
"COUNTRY": "País",
"CUSTOM_ATTRIBUTE_LIST": "Lista",
@ -37,7 +37,7 @@
"CUSTOM_ATTRIBUTE_NUMBER": "Número",
"CUSTOM_ATTRIBUTE_LINK": "Endereço",
"CUSTOM_ATTRIBUTE_CHECKBOX": "Caixa de Seleção",
"CREATED_AT": "Created At",
"CREATED_AT": "Criado Em",
"LAST_ACTIVITY": "Última atividade"
},
"GROUPS": {

View file

@ -57,9 +57,9 @@
}
},
"FOOTER": {
"MESSAGE_SIGN_TOOLTIP": "Message signature",
"ENABLE_SIGN_TOOLTIP": "Enable signature",
"DISABLE_SIGN_TOOLTIP": "Disable signature",
"MESSAGE_SIGN_TOOLTIP": "Assinatura da mensagem",
"ENABLE_SIGN_TOOLTIP": "Habilitar assinatura",
"DISABLE_SIGN_TOOLTIP": "Desativar assinatura",
"MSG_INPUT": "Shift + enter para nova linha. Comece com '/' para selecionar uma Resposta Pronta.",
"PRIVATE_MSG_INPUT": "Shift + Enter para a nova linha. Isto será visível apenas para Agentes",
"MESSAGE_SIGNATURE_NOT_CONFIGURED": "Message signature is not configured, please configure it in profile settings.",
@ -166,7 +166,7 @@
},
"ACCORDION": {
"CONTACT_DETAILS": "Detalhes do Contacto",
"CONVERSATION_ACTIONS": "Conversation Actions",
"CONVERSATION_ACTIONS": "Ações de Conversa",
"CONVERSATION_LABELS": "Etiquetas da conversa",
"CONVERSATION_INFO": "Conversation Information",
"CONTACT_ATTRIBUTES": "Atributos do Contato",

View file

@ -48,7 +48,7 @@
}
},
"UPDATE_CHATWOOT": "Está disponível uma nova atualização %{latestChatwootVersion} para o ChatWoot. Por favor, atualize a sua versão.",
"LEARN_MORE": "Learn more"
"LEARN_MORE": "Saiba mais"
},
"FORMS": {
"MULTISELECT": {
@ -79,7 +79,7 @@
},
"NETWORK": {
"NOTIFICATION": {
"TEXT": "Disconnected from Chatwoot"
"TEXT": "Desconectado do Chatwoot"
},
"BUTTON": {
"REFRESH": "Atualizar"
@ -116,17 +116,17 @@
"GO_TO_NOTIFICATIONS": "Ir para Notificações",
"ADD_LABELS_TO_CONVERSATION": "Adicionar etiqueta à conversa",
"ASSIGN_AN_AGENT": "Atribuir um agente",
"ASSIGN_A_TEAM": "Assign a team",
"ASSIGN_A_TEAM": "Atribuir uma equipa",
"MUTE_CONVERSATION": "Silenciar Conversa",
"UNMUTE_CONVERSATION": "Unmute conversation",
"UNMUTE_CONVERSATION": "Reativar conversa",
"REMOVE_LABEL_FROM_CONVERSATION": "Remover etiqueta da conversa",
"REOPEN_CONVERSATION": "Reopen conversation",
"RESOLVE_CONVERSATION": "Resolve conversation",
"SEND_TRANSCRIPT": "Send an email transcript",
"REOPEN_CONVERSATION": "Reabrir conversa",
"RESOLVE_CONVERSATION": "Resolver conversa",
"SEND_TRANSCRIPT": "Enviar transcrição por e-mail",
"SNOOZE_CONVERSATION": "Snooze Conversation",
"UNTIL_NEXT_REPLY": "Until next reply",
"UNTIL_NEXT_WEEK": "Until next week",
"UNTIL_TOMORROW": "Until tomorrow"
"UNTIL_NEXT_REPLY": "Até à próxima resposta",
"UNTIL_NEXT_WEEK": "Até à próxima semana",
"UNTIL_TOMORROW": "Até amanhã"
}
}
}

View file

@ -61,7 +61,7 @@
},
"CHANNEL_WEBHOOK_URL": {
"LABEL": "URL do Webhook",
"PLACEHOLDER": "Enter your Webhook URL",
"PLACEHOLDER": "Introduza o seu URL Webhook",
"ERROR": "Por favor, insira uma URL válida"
},
"CHANNEL_DOMAIN": {
@ -118,7 +118,7 @@
},
"CHANNEL_NAME": {
"LABEL": "Nome Caixa de Entrada",
"PLACEHOLDER": "Please enter a inbox name",
"PLACEHOLDER": "Por favor, insira um nome para a caixa de entrada",
"ERROR": "Este campo é obrigatório"
},
"PHONE_NUMBER": {
@ -137,14 +137,14 @@
},
"SMS": {
"TITLE": "Canal SMS",
"DESC": "Start supporting your customers via SMS.",
"DESC": "Comece a apoiar os seus clientes via SMS.",
"PROVIDERS": {
"LABEL": "API Provider",
"TWILIO": "Twilio",
"BANDWIDTH": "Banda"
},
"API": {
"ERROR_MESSAGE": "We were not able to save the SMS channel"
"ERROR_MESSAGE": "Não conseguimos salvar o canal de SMS"
},
"BANDWIDTH": {
"ACCOUNT_ID": {
@ -469,7 +469,7 @@
"TITLE": "IMAP",
"SUBTITLE": "Defina os seus dados IMAP",
"UPDATE": "Atualizar configurações IMAP",
"TOGGLE_AVAILABILITY": "Enable IMAP configuration for this inbox",
"TOGGLE_AVAILABILITY": "Ativar a configuração IMAP para esta caixa de entrada",
"TOGGLE_HELP": "Enabling IMAP will help the user to recieve email",
"EDIT": {
"SUCCESS_MESSAGE": "IMAP settings updated successfully",

View file

@ -30,7 +30,7 @@
},
"LIST": {
"FETCHING": "Procurando Hooks de integração",
"INBOX": "Recebidas",
"INBOX": "Caixa de Entrada",
"DELETE": {
"BUTTON_TEXT": "excluir"
}

View file

@ -240,7 +240,7 @@
"HEADER": "Visão Geral da Caixa de Entrada",
"LOADING_CHART": "Carregando dados da carta...",
"NO_ENOUGH_DATA": "Não recebemos pontos de dados suficientes para gerar o relatório. Por favor, tente novamente mais tarde.",
"DOWNLOAD_INBOX_REPORTS": "Download inbox reports",
"DOWNLOAD_INBOX_REPORTS": "Descarregar relatórios de caixa de entrada",
"FILTER_DROPDOWN_LABEL": "Escolher caixa de entrada",
"METRICS": {
"CONVERSATIONS": {
@ -300,11 +300,11 @@
}
},
"TEAM_REPORTS": {
"HEADER": "Team Overview",
"HEADER": "Resumo de Equipa",
"LOADING_CHART": "Carregando dados da carta...",
"NO_ENOUGH_DATA": "Não recebemos pontos de dados suficientes para gerar o relatório. Por favor, tente novamente mais tarde.",
"DOWNLOAD_TEAM_REPORTS": "Download team reports",
"FILTER_DROPDOWN_LABEL": "Select Team",
"DOWNLOAD_TEAM_REPORTS": "Descarregar relatórios de equipa",
"FILTER_DROPDOWN_LABEL": "Escolher Equipa",
"METRICS": {
"CONVERSATIONS": {
"NAME": "Conversas",
@ -367,7 +367,7 @@
"NO_RECORDS": "Sem dados CSAT disponíveis para reposta.",
"FILTERS": {
"AGENTS": {
"PLACEHOLDER": "Choose Agents"
"PLACEHOLDER": "Escolher Agentes"
}
},
"TABLE": {

View file

@ -101,21 +101,21 @@
"PLACEHOLDER": "Por favor, digite a password atual"
},
"PASSWORD": {
"LABEL": "New password",
"LABEL": "Nova senha",
"ERROR": "Por favor, digite uma senha de comprimento 6 ou mais",
"PLACEHOLDER": "Por favor, digite uma nova senha"
},
"PASSWORD_CONFIRMATION": {
"LABEL": "Confirme a nova senha",
"ERROR": "Confirme a senha deve corresponder à senha",
"PLACEHOLDER": "Please re-enter your new password"
"PLACEHOLDER": "Por favor, digite novamente a sua senha nova"
}
}
},
"SIDEBAR_ITEMS": {
"CHANGE_AVAILABILITY_STATUS": "Trocar",
"CHANGE_ACCOUNTS": "Trocar de conta",
"CONTACT_SUPPORT": "Contact Support",
"CONTACT_SUPPORT": "Contactar Suporte",
"SELECTOR_SUBTITLE": "Escolha uma conta da lista a seguir",
"PROFILE_SETTINGS": "Configurações do perfil",
"KEYBOARD_SHORTCUTS": "Atalhos do teclado",
@ -124,7 +124,7 @@
"APP_GLOBAL": {
"TRIAL_MESSAGE": "dias de teste restantes.",
"TRAIL_BUTTON": "Comprar agora",
"DELETED_USER": "Deleted User"
"DELETED_USER": "Usuário Excluído"
},
"COMPONENTS": {
"CODE": {
@ -164,15 +164,15 @@
"APPLICATIONS": "Aplicações",
"LABELS": "Etiquetas",
"CUSTOM_ATTRIBUTES": "Atributos personalizados",
"AUTOMATION": "Automation",
"AUTOMATION": "Automatização",
"TEAMS": "Equipas",
"CUSTOM_VIEWS_FOLDER": "Folders",
"CUSTOM_VIEWS_SEGMENTS": "Segments",
"CUSTOM_VIEWS_FOLDER": "Pastas",
"CUSTOM_VIEWS_SEGMENTS": "Segmentos",
"ALL_CONTACTS": "Todos os contatos",
"TAGGED_WITH": "Etiquetada com",
"NEW_LABEL": "New label",
"NEW_TEAM": "New team",
"NEW_INBOX": "New inbox",
"NEW_LABEL": "Nova etiqueta",
"NEW_TEAM": "Nova equipa",
"NEW_INBOX": "Nova caixa de entrada",
"REPORTS_OVERVIEW": "Visão geral",
"CSAT": "CSAT",
"CAMPAIGNS": "Campanhas",
@ -181,8 +181,8 @@
"REPORTS_AGENT": "Agentes",
"REPORTS_LABEL": "Etiquetas",
"REPORTS_INBOX": "Caixa de Entrada",
"REPORTS_TEAM": "Team",
"SET_AVAILABILITY_TITLE": "Set yourself as",
"REPORTS_TEAM": "Equipa",
"SET_AVAILABILITY_TITLE": "Defina-se como",
"BETA": "Beta"
},
"CREATE_ACCOUNT": {
@ -215,7 +215,7 @@
"GO_TO_REPORTS_SIDEBAR": "Ir para barra lateral de Relatórios",
"MOVE_TO_NEXT_TAB": "Mover para próximo separador da lista de conversas",
"GO_TO_SETTINGS": "Ir para as configurações",
"SWITCH_CONVERSATION_STATUS": "Switch to the next conversation status",
"SWITCH_CONVERSATION_STATUS": "Mudar para o próximo estado de conversa",
"SWITCH_TO_PRIVATE_NOTE": "Alterar para nota privada",
"TOGGLE_RICH_CONTENT_EDITOR": "Ativar/desativar editor de conteúdo",
"SWITCH_TO_REPLY": "Mudar para resposta",

View file

@ -80,7 +80,11 @@ export default {
return false;
},
},
watch: {
conversationId() {
this.fetchConversationIfUnavailable();
},
},
mounted() {
this.$store.dispatch('agents/get');
this.initialize();

View file

@ -79,7 +79,7 @@ export const AUTOMATIONS = {
// {
// key: 'send_email_to_team',
// name: 'Send an email to team',
// attributeI18nKey: 'SEND_MESSAGE',
// attributeI18nKey: 'SEND_EMAIL_TO_TEAM',
// },
],
},
@ -186,7 +186,7 @@ export const AUTOMATIONS = {
// {
// key: 'send_email_to_team',
// name: 'Send an email to team',
// attributeI18nKey: 'SEND_MESSAGE',
// attributeI18nKey: 'SEND_EMAIL_TO_TEAM',
// },
{
key: 'assign_agent',

View file

@ -66,9 +66,6 @@ export const actions = {
id: contactId,
data: response.data.payload,
});
commit(types.default.SET_ALL_CONVERSATION, response.data.payload, {
root: true,
});
commit(types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG, {
isFetching: false,
});

View file

@ -19,7 +19,6 @@ describe('#actions', () => {
types.default.SET_CONTACT_CONVERSATIONS,
{ id: 1, data: conversationList },
],
[types.default.SET_ALL_CONVERSATION, conversationList, { root: true }],
[
types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG,
{ isFetching: false },

View file

@ -22,7 +22,7 @@
"IN_A_DAY": "عادة نقوم بالرد خلال يوم واحد"
},
"START_CONVERSATION": "ابدأ المحادثة",
"END_CONVERSATION": "End Conversation",
"END_CONVERSATION": "إنهاء المحادثة",
"CONTINUE_CONVERSATION": "متابعة المحادثة",
"START_NEW_CONVERSATION": "ابدأ محادثة جديدة",
"UNREAD_VIEW": {

View file

@ -22,7 +22,7 @@
"IN_A_DAY": "Normalmente respondemos num dia"
},
"START_CONVERSATION": "Iniciar Conversa",
"END_CONVERSATION": "End Conversation",
"END_CONVERSATION": "Terminar Conversa",
"CONTINUE_CONVERSATION": "Continuar conversa",
"START_NEW_CONVERSATION": "Iniciar uma nova conversa",
"UNREAD_VIEW": {

View file

@ -1,51 +1,58 @@
class AutomationRuleListener < BaseListener
def conversation_updated(event_obj)
conversation = event_obj.data[:conversation]
return unless rule_present?('conversation_updated', conversation)
account = conversation.account
return unless rule_present?('conversation_updated', account)
@rules.each do |rule|
conditions_match = ::AutomationRules::ConditionsFilterService.new(rule, conversation).perform
AutomationRules::ActionService.new(rule, conversation).perform if conditions_match.present?
AutomationRules::ActionService.new(rule, account, conversation).perform if conditions_match.present?
end
end
def conversation_status_changed(event_obj)
conversation = event_obj.data[:conversation]
return unless rule_present?('conversation_status_changed', conversation)
account = conversation.account
return unless rule_present?('conversation_status_changed', account)
@rules.each do |rule|
conditions_match = ::AutomationRules::ConditionsFilterService.new(rule, conversation).perform
AutomationRules::ActionService.new(rule, conversation).perform if conditions_match.present?
AutomationRules::ActionService.new(rule, account, conversation).perform if conditions_match.present?
end
end
def conversation_created(event_obj)
conversation = event_obj.data[:conversation]
return unless rule_present?('conversation_created', conversation)
account = conversation.account
return unless rule_present?('conversation_created', account)
@rules.each do |rule|
conditions_match = ::AutomationRules::ConditionsFilterService.new(rule, conversation).perform
::AutomationRules::ActionService.new(rule, conversation).perform if conditions_match.present?
::AutomationRules::ActionService.new(rule, account, conversation).perform if conditions_match.present?
end
end
def message_created(event_obj)
message = event_obj.data[:message]
conversation = message.conversation
return unless rule_present?('message_created', conversation)
account = message.try(:account)
return unless rule_present?('message_created', account)
@rules.each do |rule|
conditions_match = ::AutomationRules::ConditionsFilterService.new(rule, conversation).message_conditions(message)
::AutomationRules::ActionService.new(rule, conversation).perform if conditions_match.present?
conditions_match = ::AutomationRules::ConditionsFilterService.new(rule, message.conversation).message_conditions
::AutomationRules::ActionService.new(rule, account, message.conversation).perform if conditions_match.present?
end
end
def rule_present?(event_name, conversation)
return if conversation.blank?
def rule_present?(event_name, account)
return if account.blank?
@rules = AutomationRule.where(
event_name: event_name,
account_id: conversation.account_id,
account_id: account.id,
active: true
)
@rules.any?

View file

@ -4,50 +4,57 @@ class TeamNotifications::AutomationNotificationMailer < ApplicationMailer
@agents = team.team_members
@conversation = conversation
@message = message
@custom_message = message
@action_url = app_account_conversation_url(account_id: @conversation.account_id, id: @conversation.display_id)
send_an_email_to_team
send_an_email_to_team and return
end
def conversation_updated(conversation, team)
def conversation_updated(conversation, team, message)
return unless smtp_config_set_or_development?
@agents = team.team_members
@conversation = conversation
@message = message
@custom_message = message
@action_url = app_account_conversation_url(account_id: @conversation.account_id, id: @conversation.display_id)
send_an_email_to_team
send_an_email_to_team and return
end
def message_created(message, agent)
def message_created(conversation, team, message)
return unless smtp_config_set_or_development?
@agent = agent
@conversation = message.conversation
@message = message
subject = "#{@agent.available_name}, You have been mentioned in conversation [ID - #{@conversation.display_id}]"
@agents = team.team_members
@conversation = conversation
@custom_message = message
@action_url = app_account_conversation_url(account_id: @conversation.account_id, id: @conversation.display_id)
send_mail_with_liquid(to: @agent.email, subject: subject)
send_an_email_to_team and return
end
private
def send_an_email_to_team
@agents.each do |agent|
subject = "#{@agent.available_name}, A new conversation [ID - #{@conversation.display_id}] has been created in #{@conversation.inbox&.name}."
subject = "#{agent.user.available_name}, This email has been sent via automation rule actions."
@action_url = app_account_conversation_url(account_id: @conversation.account_id, id: @conversation.display_id)
send_mail_with_liquid(to: agent.email, subject: subject)
@agent = agent
send_mail_with_liquid(to: @agent.user.email, subject: subject)
end
end
def liquid_droppables
super.merge({
user: @agent,
conversation: @conversation,
inbox: @conversation.inbox,
message: @message
})
super.merge!({
user: @agent.user,
conversation: @conversation,
inbox: @conversation.inbox
})
end
def liquid_locals
super.merge!({
custom_message: @custom_message
})
end
end

View file

@ -20,9 +20,9 @@
class AutomationRule < ApplicationRecord
belongs_to :account
validates :account, presence: true
validate :json_conditions_format
validate :json_actions_format
validates :account_id, presence: true
scope :active, -> { where(active: true) }

View file

@ -210,6 +210,8 @@ class Conversation < ApplicationRecord
end
def dispatcher_dispatch(event_name)
return if Current.executed_by.present? && Current.executed_by.instance_of?(AutomationRule)
Rails.configuration.dispatcher.dispatch(event_name, Time.zone.now, conversation: self, notifiable_assignee_change: notifiable_assignee_change?)
end

View file

@ -166,6 +166,8 @@ class Message < ApplicationRecord
end
def dispatch_create_events
return if Current.executed_by.present? && Current.executed_by.instance_of?(AutomationRule)
Rails.configuration.dispatcher.dispatch(MESSAGE_CREATED, Time.zone.now, message: self)
if outgoing? && conversation.messages.outgoing.count == 1
@ -174,6 +176,8 @@ class Message < ApplicationRecord
end
def dispatch_update_event
return if Current.executed_by.present? && Current.executed_by.instance_of?(AutomationRule)
Rails.configuration.dispatcher.dispatch(MESSAGE_UPDATED, Time.zone.now, message: self)
end

View file

@ -1,40 +1,68 @@
class AutomationRules::ActionService
def initialize(rule, conversation)
def initialize(rule, account, conversation)
@rule = rule
@account = account
@conversation = conversation
@account = @conversation.account
Current.executed_by = rule
end
def perform
@rule.actions.each do |action, _current_index|
@rule.actions.each do |action|
action = action.with_indifferent_access
send(action[:action_name], action[:action_params])
begin
send(action[:action_name], action[:action_params])
rescue StandardError => e
Sentry.capture_exception(e)
end
end
ensure
Current.reset
end
private
def send_email_transcript(email)
ConversationReplyMailer.with(account: conversation.account).conversation_transcript(@conversation, email)&.deliver_later
end
def mute_conversation(_params)
@conversation.mute!
end
def change_status(status)
@conversation.update!(status: status[0])
end
def send_webhook_events(webhook_url)
payload = @conversation.webhook_data.merge(event: "automation_event: #{@rule.event_name}")
WebhookJob.perform_later(webhook_url, payload)
end
def send_message(message)
# params = { content: message, private: false }
# mb = Messages::MessageBuilder.new(@administrator, @conversation, params)
# mb.perform
return if @rule.event_name == 'message_created'
params = { content: message[0], private: false }
mb = Messages::MessageBuilder.new(@administrator, @conversation, params)
mb.perform
end
def assign_team(team_ids = [])
return unless team_belongs_to_account?(team_ids)
@account.teams.find_by(id: team_ids)
@conversation.update!(team_id: team_ids[0])
end
def assign_best_agents(agent_ids = [])
def assign_best_agent(agent_ids = [])
return unless agent_belongs_to_account?(agent_ids)
@agent = @account.users.find_by(id: agent_ids)
@conversation.update_assignee(@agent)
@conversation.update!(assignee_id: @agent.id) if @agent.present?
end
def add_label(labels = [])
def add_label(labels)
return if labels.empty?
@conversation.add_labels(labels)
end
@ -43,11 +71,11 @@ class AutomationRules::ActionService
case @rule.event_name
when 'conversation_created', 'conversation_status_changed'
TeamNotifications::AutomationNotificationMailer.conversation_creation(@conversation, team, params[:message])
TeamNotifications::AutomationNotificationMailer.conversation_creation(@conversation, team, params[:message])&.deliver_now
when 'conversation_updated'
TeamNotifications::AutomationNotificationMailer.conversation_updated(@conversation, team, params[:message])
TeamNotifications::AutomationNotificationMailer.conversation_updated(@conversation, team, params[:message])&.deliver_now
when 'message_created'
TeamNotifications::AutomationNotificationMailer.message_created(@conversation, team, params[:message])
TeamNotifications::AutomationNotificationMailer.message_created(@conversation, team, params[:message])&.deliver_now
end
end

View file

@ -1,7 +1,7 @@
require 'json'
class AutomationRules::ConditionsFilterService < FilterService
def initialize(rule, conversation)
def initialize(rule, conversation = nil)
super([], nil)
@rule = rule
@conversation = conversation
@ -21,14 +21,14 @@ class AutomationRules::ConditionsFilterService < FilterService
records.any?
end
def message_conditions(message)
def message_conditions
message_filters = @filters['messages']
@rule.conditions.each_with_index do |query_hash, current_index|
current_filter = message_filters[query_hash['attribute_key']]
@query_string += message_query_string(current_filter, query_hash.with_indifferent_access, current_index)
end
records = Message.where(id: message.id).where(@query_string, @filter_values.with_indifferent_access)
records = Message.where(conversation: @conversation).where(@query_string, @filter_values.with_indifferent_access)
records.any?
end
@ -44,6 +44,19 @@ class AutomationRules::ConditionsFilterService < FilterService
end
end
# This will be used in future for contact automation rule
def contact_conditions(_contact)
conversation_filters = @filters['conversations']
@rule.conditions.each_with_index do |query_hash, current_index|
current_filter = conversation_filters[query_hash['attribute_key']]
@query_string += conversation_query_string(current_filter, query_hash.with_indifferent_access, current_index)
end
records = base_relation.where(@query_string, @filter_values.with_indifferent_access)
records.any?
end
def conversation_query_string(current_filter, query_hash, current_index)
attribute_key = query_hash['attribute_key']
query_operator = query_hash['query_operator']
@ -63,6 +76,6 @@ class AutomationRules::ConditionsFilterService < FilterService
end
def base_relation
Conversation.where(id: @conversation)
Conversation.where(id: @conversation.id)
end
end

View file

@ -20,6 +20,8 @@ class Instagram::MessageText < Instagram::WebhooksBaseService
# person can connect the channel and then delete the inbox
return if @inbox.blank?
return unsend_message if message_is_deleted?
ensure_contact(contact_id)
create_message
@ -46,6 +48,19 @@ class Instagram::MessageText < Instagram::WebhooksBaseService
@messaging[:message][:is_echo].present?
end
def message_is_deleted?
@messaging[:message][:is_deleted].present?
end
def unsend_message
message_to_delete = @inbox.messages.find_by(
source_id: @messaging[:message][:mid]
)
return if message_to_delete.blank?
message_to_delete.update!(content: I18n.t('conversations.messages.deleted'), deleted: true)
end
def create_message
Messages::Instagram::MessageBuilder.new(@messaging, @inbox, outgoing_echo: agent_message_via_echo?).perform
end

View file

@ -1,7 +1,7 @@
<p>Hi {{user.available_name}}</p>
<p>Time to save the world. A new conversation has been created in {{ inbox.name }}</p>
<p>{{ custom_message }}</p>
<p>
Click <a href="{{ action_url }}">here</a> to get cracking.

View file

@ -0,0 +1,8 @@
<p>Hi {{user.available_name}}</p>
<p>{{ custom_message }}</p>
<p>
Click <a href="{{ action_url }}">here</a> to get cracking.
</p>

View file

@ -0,0 +1,8 @@
<p>Hi {{user.available_name}}</p>
<p>{{ custom_message }}</p>
<p>
Click <a href="{{ action_url }}">here</a> to get cracking.
</p>

View file

@ -56,7 +56,7 @@ ar:
activity:
status:
resolved: "تم تحديث حالة المحادثة لـ\"مغلقة\" بواسطة %{user_name}"
contact_resolved: "Conversation was resolved by %{contact_name}"
contact_resolved: "تم حل المحادثة بواسطة %{contact_name}"
open: "تم إعادة فتح المحادثة بواسطة %{user_name}"
pending: "تم تحديث حالة المحادثة لـ\"معلقة\" بواسطة %{user_name}"
snoozed: "تم تأجيل المحادثة بواسطة %{user_name}"

View file

@ -56,7 +56,7 @@ pt:
activity:
status:
resolved: "Conversa foi marcada como resolvida por %{user_name}"
contact_resolved: "Conversation was resolved by %{contact_name}"
contact_resolved: "Conversa foi resolvida por %{contact_name}"
open: "Conversa foi reaberta por %{user_name}"
pending: "Conversa marcada como pendente por %{user_name}"
snoozed: "Conversa adiada por %{user_name}"

View file

@ -2,12 +2,14 @@ module Current
thread_mattr_accessor :user
thread_mattr_accessor :account
thread_mattr_accessor :account_user
thread_mattr_accessor :executed_by
thread_mattr_accessor :contact
def self.reset
Current.user = nil
Current.account = nil
Current.account_user = nil
Current.executed_by = nil
Current.contact = nil
end
end

View file

@ -56,6 +56,33 @@ FactoryBot.define do
initialize_with { attributes }
end
factory :instagram_message_unsend_event, class: Hash do
entry do
[
{
'id': 'instagram-message-id-123',
'time': '2021-09-08T06:34:04+0000',
'messaging': [
{
'sender': {
'id': 'Sender-id-1'
},
'recipient': {
'id': 'chatwoot-app-user-id-1'
},
'timestamp': '2021-09-08T06:34:04+0000',
'message': {
'mid': 'message-id-to-delete',
'is_deleted': true
}
}
]
}
]
end
initialize_with { attributes }
end
factory :instagram_message_attachment_event, class: Hash do
entry do
[

View file

@ -28,6 +28,7 @@ describe Webhooks::InstagramEventsJob do
let!(:instagram_inbox) { create(:inbox, channel: instagram_channel, account: account, greeting_enabled: false) }
let!(:dm_params) { build(:instagram_message_create_event).with_indifferent_access }
let!(:test_params) { build(:instagram_test_text_event).with_indifferent_access }
let!(:unsend_event) { build(:instagram_message_unsend_event).with_indifferent_access }
let!(:attachment_params) { build(:instagram_message_attachment_event).with_indifferent_access }
let!(:story_mention_params) { build(:instagram_story_mention_event).with_indifferent_access }
let(:fb_object) { double }
@ -61,6 +62,26 @@ describe Webhooks::InstagramEventsJob do
expect(instagram_inbox.messages.last.content).to eq('This is a test message from facebook.')
end
it 'handle instagram unsend message event' do
create(:message,
source_id: 'message-id-to-delete',
inbox_id: instagram_inbox.id)
allow(Koala::Facebook::API).to receive(:new).and_return(fb_object)
allow(fb_object).to receive(:get_object).and_return(
{
name: 'Jane',
id: 'Sender-id-1',
account_id: instagram_inbox.account_id,
profile_pic: 'https://chatwoot-assets.local/sample.png'
}.with_indifferent_access
)
expect(instagram_inbox.messages.count).to be 1
instagram_webhook.perform_now(unsend_event[:entry])
expect(instagram_inbox.messages.last.content).to eq 'This message was deleted'
expect(instagram_inbox.messages.last.reload.deleted).to eq true
end
it 'creates incoming message with attachments in the instagram inbox' do
allow(Koala::Facebook::API).to receive(:new).and_return(fb_object)
allow(fb_object).to receive(:get_object).and_return(

View file

@ -31,16 +31,36 @@ describe AutomationRuleListener do
},
{ 'action_name' => 'assign_team', 'action_params' => [team.id] },
{ 'action_name' => 'add_label', 'action_params' => %w[support priority_customer] },
{ 'action_name' => 'assign_best_agents', 'action_params' => [user_1.id] }
{ 'action_name' => 'send_webhook_events', 'action_params' => 'https://www.example.com' },
{ 'action_name' => 'assign_best_agent', 'action_params' => [user_1.id] },
{ 'action_name' => 'send_email_transcript', 'action_params' => 'new_agent@example.com' },
{ 'action_name' => 'mute_conversation', 'action_params' => nil },
{ 'action_name' => 'change_status', 'action_params' => ['snoozed'] },
{ 'action_name' => 'send_message', 'action_params' => ['Send this message.'] }
])
end
describe '#conversation_status_changed' do
context 'when rule matches' do
it 'triggers automation rule send webhook events' do
payload = conversation.webhook_data.merge(event: "automation_event: #{automation_rule.event_name}")
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:conversation_creation)
expect(WebhookJob).to receive(:perform_later).with('https://www.example.com', payload).once
listener.conversation_status_changed(event)
end
it 'triggers automation rule to assign team' do
expect(conversation.team_id).not_to eq(team.id)
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:conversation_creation)
listener.conversation_status_changed(event)
conversation.reload
@ -51,6 +71,9 @@ describe AutomationRuleListener do
expect(conversation.labels).to eq([])
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:conversation_creation)
listener.conversation_status_changed(event)
conversation.reload
@ -61,12 +84,65 @@ describe AutomationRuleListener do
expect(conversation.assignee).to be_nil
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:conversation_creation)
listener.conversation_status_changed(event)
conversation.reload
expect(conversation.assignee).to eq(user_1)
end
it 'triggers automation rule send message to the contacts' do
expect(conversation.messages).to be_empty
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:conversation_creation)
listener.conversation_status_changed(event)
conversation.reload
expect(conversation.messages.last.content).to eq('Send this message.')
end
it 'triggers automation rule changes status to snoozed' do
expect(conversation.status).to eq('resolved')
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:conversation_creation)
listener.conversation_status_changed(event)
conversation.reload
expect(conversation.status).to eq('snoozed')
end
it 'triggers automation rule send email transcript to the mentioned email' do
mailer = double
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:conversation_creation)
listener.conversation_status_changed(event)
conversation.reload
allow(mailer).to receive(:conversation_transcript)
end
it 'triggers automation rule send email to the team' do
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:conversation_creation)
listener.conversation_status_changed(event)
end
end
end
@ -114,6 +190,42 @@ describe AutomationRuleListener do
expect(conversation.assignee).to eq(user_1)
end
it 'triggers automation rule send email transcript to the mentioned email' do
mailer = double
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:conversation_updated)
listener.conversation_updated(event)
conversation.reload
allow(mailer).to receive(:conversation_transcript)
end
it 'triggers automation rule send email to the team' do
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:conversation_updated)
listener.conversation_updated(event)
end
it 'triggers automation rule send message to the contacts' do
expect(conversation.messages).to be_empty
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:conversation_updated)
listener.conversation_updated(event)
conversation.reload
expect(conversation.messages.last.content).to eq('Send this message.')
end
end
end
@ -137,6 +249,9 @@ describe AutomationRuleListener do
expect(conversation.team_id).not_to eq(team.id)
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:message_created)
listener.message_created(event)
conversation.reload
@ -147,22 +262,41 @@ describe AutomationRuleListener do
expect(conversation.labels).to eq([])
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:message_created)
listener.message_created(event)
conversation.reload
expect(conversation.labels.pluck(:name)).to eq(%w[support priority_customer])
end
it 'triggers automation rule to assign best agents' do
it 'triggers automation rule to assign best agent' do
expect(conversation.assignee).to be_nil
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:message_created)
listener.message_created(event)
conversation.reload
expect(conversation.assignee).to eq(user_1)
end
it 'triggers automation rule send email transcript to the mentioned email' do
mailer = double
automation_rule
expect(TeamNotifications::AutomationNotificationMailer).to receive(:message_created)
listener.message_created(event)
conversation.reload
allow(mailer).to receive(:conversation_transcript)
end
end
end
end

View file

@ -2,11 +2,13 @@ require 'rails_helper'
RSpec.describe AutomationRule, type: :model do
describe 'associations' do
let(:account) { create(:account) }
let(:params) do
{
name: 'Notify Conversation Created and mark priority query',
description: 'Notify all administrator about conversation created and mark priority query',
event_name: 'conversation_created',
account_id: account.id,
conditions: [
{
attribute_key: 'browser_language',