mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 19:17:48 +00:00 
			
		
		
		
	 c553997af8
			
		
	
	c553997af8
	
	
	
		
			
			# Pull Request Template ## Description With these fixes, I could improve some translations in portuguese, and also I added some improvements to make some drowpdown values, that were not translatable into translatable strings, into the Automations, Macros and Custom Attributes page. I also fixed some typos. Here are the main improvements. - ~Fixed typo in portuguese into `Reports > Agents` page:~ ~Before:  After: ~ - Added the possibility to make the `Priority` and `Message types` translatables in other languages, into Macros and Automations page. Also added the same feature for Custom attributes page at `applies to` and `type` fields: Before:     After:     - ~Improve Bots page. In the Brazilian portuguese is very common and widely used bots to refer to chatbots, using `robô` as a direct translations sounds weird, `robô` is used more often when we are talking about robots, not chatbots. Before:  After: ~ - Added multiselect both `no options` and `Select` placeholder translatable strings: Before:   After:  - Added `.pnpm-store` to `.gitignore`, when I'm using docker, the pnpm always creates this folder into my root directory, so I imagine the same could happens with others, so I fixed it. ## Type of change Please delete options that are not relevant. - [x] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality not to work as expected) - [ ] This change requires a documentation update ## How Has This Been Tested? I've added some translations for my language (brazilian portuguese), so i just switched the languages between the original in EN to PT_BR. ## Checklist: - [x] My code follows the style guidelines of this project - [x] 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 - [x] 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 - [x] Any dependent changes have been merged and published in downstream modules --------- Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: iamsivin <iamsivin@gmail.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
		
			
				
	
	
		
			297 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			297 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <script>
 | |
| import AutomationActionTeamMessageInput from './AutomationActionTeamMessageInput.vue';
 | |
| import AutomationActionFileInput from './AutomationFileInput.vue';
 | |
| import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
 | |
| import NextButton from 'dashboard/components-next/button/Button.vue';
 | |
| 
 | |
| export default {
 | |
|   components: {
 | |
|     AutomationActionTeamMessageInput,
 | |
|     AutomationActionFileInput,
 | |
|     WootMessageEditor,
 | |
|     NextButton,
 | |
|   },
 | |
|   props: {
 | |
|     modelValue: {
 | |
|       type: Object,
 | |
|       default: () => null,
 | |
|     },
 | |
|     actionTypes: {
 | |
|       type: Array,
 | |
|       default: () => [],
 | |
|     },
 | |
|     dropdownValues: {
 | |
|       type: Array,
 | |
|       default: () => [],
 | |
|     },
 | |
|     errorMessage: {
 | |
|       type: String,
 | |
|       default: '',
 | |
|     },
 | |
|     showActionInput: {
 | |
|       type: Boolean,
 | |
|       default: true,
 | |
|     },
 | |
|     initialFileName: {
 | |
|       type: String,
 | |
|       default: '',
 | |
|     },
 | |
|     isMacro: {
 | |
|       type: Boolean,
 | |
|       default: false,
 | |
|     },
 | |
|   },
 | |
|   emits: ['update:modelValue', 'input', 'removeAction', 'resetAction'],
 | |
|   computed: {
 | |
|     action_name: {
 | |
|       get() {
 | |
|         if (!this.modelValue) return null;
 | |
|         return this.modelValue.action_name;
 | |
|       },
 | |
|       set(value) {
 | |
|         const payload = this.modelValue || {};
 | |
|         this.$emit('update:modelValue', { ...payload, action_name: value });
 | |
|         this.$emit('input', { ...payload, action_name: value });
 | |
|       },
 | |
|     },
 | |
|     action_params: {
 | |
|       get() {
 | |
|         if (!this.modelValue) return null;
 | |
|         return this.modelValue.action_params;
 | |
|       },
 | |
|       set(value) {
 | |
|         const payload = this.modelValue || {};
 | |
|         this.$emit('update:modelValue', { ...payload, action_params: value });
 | |
|         this.$emit('input', { ...payload, action_params: value });
 | |
|       },
 | |
|     },
 | |
|     inputType() {
 | |
|       return this.actionTypes.find(action => action.key === this.action_name)
 | |
|         .inputType;
 | |
|     },
 | |
|     actionInputStyles() {
 | |
|       return {
 | |
|         'has-error': this.errorMessage,
 | |
|         'is-a-macro': this.isMacro,
 | |
|       };
 | |
|     },
 | |
|     castMessageVmodel: {
 | |
|       get() {
 | |
|         if (Array.isArray(this.action_params)) {
 | |
|           return this.action_params[0];
 | |
|         }
 | |
|         return this.action_params;
 | |
|       },
 | |
|       set(value) {
 | |
|         this.action_params = value;
 | |
|       },
 | |
|     },
 | |
|   },
 | |
|   methods: {
 | |
|     removeAction() {
 | |
|       this.$emit('removeAction');
 | |
|     },
 | |
|     resetAction() {
 | |
|       this.$emit('resetAction');
 | |
|     },
 | |
|   },
 | |
| };
 | |
| </script>
 | |
| 
 | |
| <template>
 | |
|   <div class="filter" :class="actionInputStyles">
 | |
|     <div class="filter-inputs">
 | |
|       <select
 | |
|         v-model="action_name"
 | |
|         class="action__question"
 | |
|         :class="{ 'full-width': !showActionInput }"
 | |
|         @change="resetAction()"
 | |
|       >
 | |
|         <option
 | |
|           v-for="attribute in actionTypes"
 | |
|           :key="attribute.key"
 | |
|           :value="attribute.key"
 | |
|         >
 | |
|           {{ attribute.label }}
 | |
|         </option>
 | |
|       </select>
 | |
|       <div v-if="showActionInput" class="filter__answer--wrap">
 | |
|         <div v-if="inputType" class="w-full">
 | |
|           <div
 | |
|             v-if="inputType === 'search_select'"
 | |
|             class="multiselect-wrap--small"
 | |
|           >
 | |
|             <multiselect
 | |
|               v-model="action_params"
 | |
|               track-by="id"
 | |
|               label="name"
 | |
|               :placeholder="$t('FORMS.MULTISELECT.SELECT')"
 | |
|               selected-label
 | |
|               :select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
 | |
|               deselect-label=""
 | |
|               :max-height="160"
 | |
|               :options="dropdownValues"
 | |
|               :allow-empty="false"
 | |
|               :option-height="104"
 | |
|             >
 | |
|               <template #noOptions>
 | |
|                 {{ $t('FORMS.MULTISELECT.NO_OPTIONS') }}
 | |
|               </template>
 | |
|             </multiselect>
 | |
|           </div>
 | |
|           <div
 | |
|             v-else-if="inputType === 'multi_select'"
 | |
|             class="multiselect-wrap--small"
 | |
|           >
 | |
|             <multiselect
 | |
|               v-model="action_params"
 | |
|               track-by="id"
 | |
|               label="name"
 | |
|               :placeholder="$t('FORMS.MULTISELECT.SELECT')"
 | |
|               multiple
 | |
|               selected-label
 | |
|               :select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
 | |
|               deselect-label=""
 | |
|               :max-height="160"
 | |
|               :options="dropdownValues"
 | |
|               :allow-empty="false"
 | |
|               :option-height="104"
 | |
|             >
 | |
|               <template #noOptions>
 | |
|                 {{ $t('FORMS.MULTISELECT.NO_OPTIONS') }}
 | |
|               </template>
 | |
|             </multiselect>
 | |
|           </div>
 | |
|           <input
 | |
|             v-else-if="inputType === 'email'"
 | |
|             v-model="action_params"
 | |
|             type="email"
 | |
|             class="answer--text-input"
 | |
|             :placeholder="$t('AUTOMATION.ACTION.EMAIL_INPUT_PLACEHOLDER')"
 | |
|           />
 | |
|           <input
 | |
|             v-else-if="inputType === 'url'"
 | |
|             v-model="action_params"
 | |
|             type="url"
 | |
|             class="answer--text-input"
 | |
|             :placeholder="$t('AUTOMATION.ACTION.URL_INPUT_PLACEHOLDER')"
 | |
|           />
 | |
|           <AutomationActionFileInput
 | |
|             v-if="inputType === 'attachment'"
 | |
|             v-model="action_params"
 | |
|             :initial-file-name="initialFileName"
 | |
|           />
 | |
|         </div>
 | |
|       </div>
 | |
|       <NextButton
 | |
|         v-if="!isMacro"
 | |
|         icon="i-lucide-x"
 | |
|         slate
 | |
|         ghost
 | |
|         class="flex-shrink-0"
 | |
|         @click="removeAction"
 | |
|       />
 | |
|     </div>
 | |
|     <AutomationActionTeamMessageInput
 | |
|       v-if="inputType === 'team_message'"
 | |
|       v-model="action_params"
 | |
|       :teams="dropdownValues"
 | |
|     />
 | |
|     <WootMessageEditor
 | |
|       v-if="inputType === 'textarea'"
 | |
|       v-model="castMessageVmodel"
 | |
|       rows="4"
 | |
|       enable-variables
 | |
|       :placeholder="$t('AUTOMATION.ACTION.TEAM_MESSAGE_INPUT_PLACEHOLDER')"
 | |
|       class="action-message"
 | |
|     />
 | |
|     <p v-if="errorMessage" class="filter-error">
 | |
|       {{ errorMessage }}
 | |
|     </p>
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
| .filter {
 | |
|   @apply bg-n-background p-2 border border-solid border-n-strong dark:border-n-strong rounded-lg mb-2;
 | |
| 
 | |
|   &.is-a-macro {
 | |
|     @apply mb-0 bg-n-background dark:bg-n-solid-1 p-0 border-0 rounded-none;
 | |
|   }
 | |
| }
 | |
| 
 | |
| .no-margin-bottom {
 | |
|   @apply mb-0;
 | |
| }
 | |
| 
 | |
| .filter.has-error {
 | |
|   @apply bg-n-ruby-8/20 border-n-ruby-5 dark:border-n-ruby-5;
 | |
| 
 | |
|   &.is-a-macro {
 | |
|     @apply bg-transparent;
 | |
|   }
 | |
| }
 | |
| 
 | |
| .filter-inputs {
 | |
|   @apply flex gap-1;
 | |
| }
 | |
| 
 | |
| .filter-error {
 | |
|   @apply text-n-ruby-9 dark:text-n-ruby-9 block my-1 mx-0;
 | |
| }
 | |
| 
 | |
| .action__question,
 | |
| .filter__operator {
 | |
|   @apply mb-0 mr-1;
 | |
| }
 | |
| 
 | |
| .action__question {
 | |
|   @apply max-w-[50%];
 | |
| }
 | |
| 
 | |
| .action__question.full-width {
 | |
|   @apply max-w-full;
 | |
| }
 | |
| 
 | |
| .filter__answer--wrap {
 | |
|   @apply max-w-[50%] flex-grow mr-1 flex w-full items-center justify-start;
 | |
| 
 | |
|   input {
 | |
|     @apply mb-0;
 | |
|   }
 | |
| }
 | |
| .filter__answer {
 | |
|   &.answer--text-input {
 | |
|     @apply mb-0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| .filter__join-operator-wrap {
 | |
|   @apply relative z-20 m-0;
 | |
| }
 | |
| 
 | |
| .filter__join-operator {
 | |
|   @apply flex items-center justify-center relative my-2.5 mx-0;
 | |
| 
 | |
|   .operator__line {
 | |
|     @apply absolute w-full border-b border-solid border-n-weak;
 | |
|   }
 | |
| 
 | |
|   .operator__select {
 | |
|     margin-bottom: 0 !important;
 | |
|     @apply relative w-auto;
 | |
|   }
 | |
| }
 | |
| 
 | |
| .multiselect {
 | |
|   @apply mb-0;
 | |
| }
 | |
| .action-message {
 | |
|   @apply mt-2 mx-0 mb-0;
 | |
| }
 | |
| // Prosemirror does not have a native way of hiding the menu bar, hence
 | |
| ::v-deep .ProseMirror-menubar {
 | |
|   @apply hidden;
 | |
| }
 | |
| </style>
 |