mirror of
				https://github.com/crater-invoice/crater.git
				synced 2025-10-30 21:21:09 -04:00 
			
		
		
		
	add mail sender in setting
This commit is contained in:
		
							
								
								
									
										136
									
								
								resources/scripts/admin/views/settings/mail-sender/Index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								resources/scripts/admin/views/settings/mail-sender/Index.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,136 @@ | ||||
| <template> | ||||
|   <BaseSettingCard | ||||
|     :title="$tc(`${pre_t}.title`, 2)" | ||||
|     :description="$t(`${pre_t}.description`)" | ||||
|   > | ||||
|     <MailSenderModal /> | ||||
|     <MailSenderTestModal /> | ||||
|  | ||||
|     <template #action> | ||||
|       <BaseButton | ||||
|         type="submit" | ||||
|         variant="primary-outline" | ||||
|         @click="openMailSenderModal" | ||||
|       > | ||||
|         <template #left="slotProps"> | ||||
|           <BaseIcon :class="slotProps.class" name="PlusIcon" /> | ||||
|         </template> | ||||
|         {{ $t(`${pre_t}.add_new_mail_sender`) }} | ||||
|       </BaseButton> | ||||
|     </template> | ||||
|  | ||||
|     <BaseTable | ||||
|       ref="table" | ||||
|       class="mt-16" | ||||
|       :data="fetchData" | ||||
|       :columns="mailSenderColumns" | ||||
|     > | ||||
|       <template #cell-is_default="{ row }"> | ||||
|         <BaseBadge | ||||
|           :bg-color=" | ||||
|             utils.getBadgeStatusColor(row.data.is_default ? 'YES' : 'NO') | ||||
|               .bgColor | ||||
|           " | ||||
|           :color=" | ||||
|             utils.getBadgeStatusColor(row.data.is_default ? 'YES' : 'NO').color | ||||
|           " | ||||
|         > | ||||
|           {{ row.data.is_default ? $t('general.yes') : $t('general.no') }} | ||||
|         </BaseBadge> | ||||
|       </template> | ||||
|  | ||||
|       <template #cell-actions="{ row }"> | ||||
|         <MailSenderDropdown | ||||
|           :row="row.data" | ||||
|           :table="table" | ||||
|           :load-data="refreshTable" | ||||
|         /> | ||||
|       </template> | ||||
|     </BaseTable> | ||||
|   </BaseSettingCard> | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import { computed, ref, inject } from 'vue' | ||||
| import { useI18n } from 'vue-i18n' | ||||
| import { useModalStore } from '@/scripts/stores/modal' | ||||
| import MailSenderModal from '@/scripts/admin/components/modal-components/MailSenderModal.vue' | ||||
| import { useMailSenderStore } from '@/scripts/admin/stores/mail-sender' | ||||
| import MailSenderDropdown from '@/scripts/admin/components/dropdowns/MailSenderIndexDropdown.vue' | ||||
| import MailSenderTestModal from '@/scripts/admin/components/modal-components/MailSenderTestModal.vue' | ||||
|  | ||||
| const pre_t = 'settings.mail_sender' | ||||
| const modalStore = useModalStore() | ||||
| const mailSenderStore = useMailSenderStore() | ||||
| const { t } = useI18n() | ||||
| const table = ref(null) | ||||
| const utils = inject('utils') | ||||
|  | ||||
| function openMailSenderModal() { | ||||
|   modalStore.openModal({ | ||||
|     title: t(`${pre_t}.add_new_mail_sender`), | ||||
|     componentName: 'MailSenderModal', | ||||
|     size: 'md', | ||||
|     refreshData: refreshTable, | ||||
|   }) | ||||
| } | ||||
|  | ||||
| const mailSenderColumns = computed(() => { | ||||
|   return [ | ||||
|     { | ||||
|       key: 'name', | ||||
|       label: t(`${pre_t}.name`), | ||||
|       thClass: 'extra', | ||||
|       tdClass: 'font-medium text-gray-900', | ||||
|     }, | ||||
|     { | ||||
|       key: 'driver', | ||||
|       label: t(`${pre_t}.driver`), | ||||
|       thClass: 'extra', | ||||
|       tdClass: 'font-medium text-gray-900', | ||||
|     }, | ||||
|     { | ||||
|       key: 'from_address', | ||||
|       label: t(`${pre_t}.from_address`), | ||||
|       thClass: 'extra', | ||||
|       tdClass: 'font-medium text-gray-900', | ||||
|     }, | ||||
|     { | ||||
|       key: 'is_default', | ||||
|       label: t(`${pre_t}.is_default`), | ||||
|       thClass: 'extra', | ||||
|       tdClass: 'font-medium text-gray-900', | ||||
|     }, | ||||
|     { | ||||
|       key: 'actions', | ||||
|       label: '', | ||||
|       tdClass: 'text-right text-sm font-medium', | ||||
|       sortable: false, | ||||
|     }, | ||||
|   ] | ||||
| }) | ||||
|  | ||||
| async function fetchData({ page, filter, sort }) { | ||||
|   let data = { | ||||
|     orderByField: sort.fieldName || 'created_at', | ||||
|     orderBy: sort.order || 'desc', | ||||
|     page, | ||||
|   } | ||||
|  | ||||
|   let response = await mailSenderStore.fetchMailSenders(data) | ||||
|  | ||||
|   return { | ||||
|     data: response.data.data, | ||||
|     pagination: { | ||||
|       totalPages: response.data.meta.last_page, | ||||
|       currentPage: page, | ||||
|       totalCount: response.data.meta.total, | ||||
|       limit: response.data.meta.per_page ? response.data.meta.per_page : 10, | ||||
|     }, | ||||
|   } | ||||
| } | ||||
|  | ||||
| async function refreshTable() { | ||||
|   table.value && table.value.refresh() | ||||
| } | ||||
| </script> | ||||
| @ -0,0 +1,104 @@ | ||||
| <template> | ||||
|   <!-- Domain --> | ||||
|   <BaseInputGroup | ||||
|     :label="$t(`${pre_t}.domain`)" | ||||
|     :error="v$.domain.$error && v$.domain.$errors[0].$message" | ||||
|     required | ||||
|   > | ||||
|     <BaseInput | ||||
|       v-model.trim="mailSenderStore.mailgunConfig.domain" | ||||
|       :invalid="v$.domain.$error" | ||||
|       type="text" | ||||
|       @input="v$.domain.$touch()" | ||||
|     /> | ||||
|   </BaseInputGroup> | ||||
|  | ||||
|   <!-- Mailgun Secret --> | ||||
|   <BaseInputGroup | ||||
|     :label="$t(`${pre_t}.secret`)" | ||||
|     :error="v$.secret.$error && v$.secret.$errors[0].$message" | ||||
|     required | ||||
|   > | ||||
|     <BaseInput | ||||
|       v-model="mailSenderStore.mailgunConfig.secret" | ||||
|       :type="getInputType" | ||||
|       autocomplete="off" | ||||
|       :invalid="v$.secret.$error" | ||||
|       @input="v$.secret.$touch()" | ||||
|     > | ||||
|       <template #right> | ||||
|         <BaseIcon | ||||
|           v-if="isShowPassword" | ||||
|           class="mr-1 text-gray-500 cursor-pointer" | ||||
|           name="EyeOffIcon" | ||||
|           @click="isShowPassword = !isShowPassword" | ||||
|         /> | ||||
|         <BaseIcon | ||||
|           v-else | ||||
|           class="mr-1 text-gray-500 cursor-pointer" | ||||
|           name="EyeIcon" | ||||
|           @click="isShowPassword = !isShowPassword" | ||||
|         /> | ||||
|       </template> | ||||
|     </BaseInput> | ||||
|   </BaseInputGroup> | ||||
|  | ||||
|   <!-- Mailgun Endpoint --> | ||||
|   <BaseInputGroup | ||||
|     :label="$t(`${pre_t}.endpoint`)" | ||||
|     :error="v$.endpoint.$error && v$.endpoint.$errors[0].$message" | ||||
|     required | ||||
|   > | ||||
|     <BaseInput | ||||
|       v-model.trim="mailSenderStore.mailgunConfig.endpoint" | ||||
|       type="text" | ||||
|       :invalid="v$.endpoint.$error" | ||||
|       @input="v$.endpoint.$touch()" | ||||
|     /> | ||||
|   </BaseInputGroup> | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import { computed, ref } from "vue" | ||||
| import { useI18n } from "vue-i18n" | ||||
| import { required, email, numeric, helpers } from "@vuelidate/validators" | ||||
| import { useVuelidate } from "@vuelidate/core" | ||||
|  | ||||
| const pre_t = "settings.mail_sender.mailgun_config" | ||||
| const { t } = useI18n() | ||||
|  | ||||
| const props = defineProps({ | ||||
|   mailSenderStore: { | ||||
|     type: Object, | ||||
|     require: true, | ||||
|     default: Object, | ||||
|   }, | ||||
| }) | ||||
|  | ||||
| let isShowPassword = ref(false) | ||||
| const getInputType = computed(() => { | ||||
|   if (isShowPassword.value) { | ||||
|     return "text" | ||||
|   } | ||||
|   return "password" | ||||
| }) | ||||
|  | ||||
| const rules = computed(() => { | ||||
|   return { | ||||
|     domain: { | ||||
|       required: helpers.withMessage(t("validation.required"), required), | ||||
|     }, | ||||
|     endpoint: { | ||||
|       required: helpers.withMessage(t("validation.required"), required), | ||||
|     }, | ||||
|     secret: { | ||||
|       required: helpers.withMessage(t("validation.required"), required), | ||||
|     }, | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const v$ = useVuelidate( | ||||
|   rules, | ||||
|   computed(() => props.mailSenderStore.mailgunConfig) | ||||
| ) | ||||
| </script> | ||||
							
								
								
									
										143
									
								
								resources/scripts/admin/views/settings/mail-sender/SesDriver.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								resources/scripts/admin/views/settings/mail-sender/SesDriver.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,143 @@ | ||||
| <template> | ||||
|   <!-- Host --> | ||||
|   <BaseInputGroup | ||||
|     :label="$t(`${pre_t}.host`)" | ||||
|     :error="v$.host.$error && v$.host.$errors[0].$message" | ||||
|     required | ||||
|   > | ||||
|     <BaseInput | ||||
|       v-model.trim="mailSenderStore.sesConfig.host" | ||||
|       :invalid="v$.host.$error" | ||||
|       type="text" | ||||
|       @input="v$.host.$touch()" | ||||
|     /> | ||||
|   </BaseInputGroup> | ||||
|  | ||||
|   <!-- Port --> | ||||
|   <BaseInputGroup | ||||
|     :label="$t(`${pre_t}.port`)" | ||||
|     :error="v$.port.$error && v$.port.$errors[0].$message" | ||||
|     required | ||||
|   > | ||||
|     <BaseInput | ||||
|       v-model.trim="mailSenderStore.sesConfig.port" | ||||
|       type="text" | ||||
|       :invalid="v$.port.$error" | ||||
|       @input="v$.port.$touch()" | ||||
|     /> | ||||
|   </BaseInputGroup> | ||||
|  | ||||
|   <!-- Encryption --> | ||||
|   <BaseInputGroup | ||||
|     :label="$t(`${pre_t}.encryption`)" | ||||
|     :error="v$.encryption.$error && v$.encryption.$errors[0].$message" | ||||
|     required | ||||
|   > | ||||
|     <BaseMultiselect | ||||
|       v-model.trim="mailSenderStore.sesConfig.encryption" | ||||
|       :options="encryptions" | ||||
|       :searchable="true" | ||||
|       :show-labels="false" | ||||
|       :placeholder="$t('general.select_option')" | ||||
|       :invalid="v$.encryption.$error" | ||||
|       @input="v$.encryption.$touch()" | ||||
|     /> | ||||
|   </BaseInputGroup> | ||||
|  | ||||
|   <!-- SES Key --> | ||||
|   <BaseInputGroup | ||||
|     :label="$t(`${pre_t}.ses_key`)" | ||||
|     :error="v$.ses_key.$error && v$.ses_key.$errors[0].$message" | ||||
|     required | ||||
|   > | ||||
|     <BaseInput | ||||
|       v-model.trim="mailSenderStore.sesConfig.ses_key" | ||||
|       type="text" | ||||
|       :invalid="v$.ses_key.$error" | ||||
|       @input="v$.ses_key.$touch()" | ||||
|     /> | ||||
|   </BaseInputGroup> | ||||
|  | ||||
|   <!-- SES Secret --> | ||||
|   <BaseInputGroup | ||||
|     :label="$t(`${pre_t}.ses_secret`)" | ||||
|     :error="v$.ses_secret.$error && v$.ses_secret.$errors[0].$message" | ||||
|     required | ||||
|   > | ||||
|     <BaseInput | ||||
|       v-model="mailSenderStore.sesConfig.ses_secret" | ||||
|       :type="getInputType" | ||||
|       autocomplete="off" | ||||
|       :invalid="v$.ses_secret.$error" | ||||
|       @input="v$.ses_secret.$touch()" | ||||
|     > | ||||
|       <template #right> | ||||
|         <BaseIcon | ||||
|           v-if="isShowPassword" | ||||
|           class="mr-1 text-gray-500 cursor-pointer" | ||||
|           name="EyeOffIcon" | ||||
|           @click="isShowPassword = !isShowPassword" | ||||
|         /> | ||||
|         <BaseIcon | ||||
|           v-else | ||||
|           class="mr-1 text-gray-500 cursor-pointer" | ||||
|           name="EyeIcon" | ||||
|           @click="isShowPassword = !isShowPassword" | ||||
|         /> | ||||
|       </template> | ||||
|     </BaseInput> | ||||
|   </BaseInputGroup> | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import { computed, ref, reactive } from 'vue' | ||||
| import { useI18n } from 'vue-i18n' | ||||
| import { required, email, numeric, helpers } from '@vuelidate/validators' | ||||
| import { useVuelidate } from '@vuelidate/core' | ||||
|  | ||||
| const pre_t = 'settings.mail_sender.ses_config' | ||||
| const { t } = useI18n() | ||||
|  | ||||
| const props = defineProps({ | ||||
|   mailSenderStore: { | ||||
|     type: Object, | ||||
|     require: true, | ||||
|     default: Object, | ||||
|   }, | ||||
| }) | ||||
|  | ||||
| let isShowPassword = ref(false) | ||||
| const getInputType = computed(() => { | ||||
|   if (isShowPassword.value) { | ||||
|     return 'text' | ||||
|   } | ||||
|   return 'password' | ||||
| }) | ||||
| const encryptions = props.mailSenderStore.mail_encryptions | ||||
|  | ||||
| const rules = computed(() => { | ||||
|   return { | ||||
|     host: { | ||||
|       required: helpers.withMessage(t('validation.required'), required), | ||||
|     }, | ||||
|     port: { | ||||
|       required: helpers.withMessage(t('validation.required'), required), | ||||
|       numeric, | ||||
|     }, | ||||
|     encryption: { | ||||
|       required: helpers.withMessage(t('validation.required'), required), | ||||
|     }, | ||||
|     ses_key: { | ||||
|       required: helpers.withMessage(t('validation.required'), required), | ||||
|     }, | ||||
|     ses_secret: { | ||||
|       required: helpers.withMessage(t('validation.required'), required), | ||||
|     }, | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const v$ = useVuelidate( | ||||
|   rules, | ||||
|   computed(() => props.mailSenderStore.sesConfig) | ||||
| ) | ||||
| </script> | ||||
| @ -0,0 +1,120 @@ | ||||
| <template> | ||||
|   <!-- Host --> | ||||
|   <BaseInputGroup | ||||
|     :label="$t(`${pre_t}.host`)" | ||||
|     :error="v$.host.$error && v$.host.$errors[0].$message" | ||||
|     required | ||||
|   > | ||||
|     <BaseInput | ||||
|       v-model.trim="mailSenderStore.smtpConfig.host" | ||||
|       :invalid="v$.host.$error" | ||||
|       type="text" | ||||
|       @input="v$.host.$touch()" | ||||
|     /> | ||||
|   </BaseInputGroup> | ||||
|  | ||||
|   <!-- Port --> | ||||
|   <BaseInputGroup | ||||
|     :label="$t(`${pre_t}.port`)" | ||||
|     :error="v$.port.$error && v$.port.$errors[0].$message" | ||||
|     required | ||||
|   > | ||||
|     <BaseInput | ||||
|       v-model.trim="mailSenderStore.smtpConfig.port" | ||||
|       type="text" | ||||
|       :invalid="v$.port.$error" | ||||
|       @input="v$.port.$touch()" | ||||
|     /> | ||||
|   </BaseInputGroup> | ||||
|  | ||||
|   <!-- Username --> | ||||
|   <BaseInputGroup :label="$t(`${pre_t}.username`)"> | ||||
|     <BaseInput v-model.trim="mailSenderStore.smtpConfig.username" type="text" /> | ||||
|   </BaseInputGroup> | ||||
|  | ||||
|   <!-- Password --> | ||||
|   <BaseInputGroup :label="$t(`${pre_t}.password`)"> | ||||
|     <BaseInput | ||||
|       v-model="mailSenderStore.smtpConfig.password" | ||||
|       :type="getInputType" | ||||
|     > | ||||
|       <template #right> | ||||
|         <BaseIcon | ||||
|           v-if="isShowPassword" | ||||
|           class="mr-1 text-gray-500 cursor-pointer" | ||||
|           name="EyeOffIcon" | ||||
|           @click="isShowPassword = !isShowPassword" | ||||
|         /> | ||||
|         <BaseIcon | ||||
|           v-else | ||||
|           class="mr-1 text-gray-500 cursor-pointer" | ||||
|           name="EyeIcon" | ||||
|           @click="isShowPassword = !isShowPassword" | ||||
|         /> | ||||
|       </template> | ||||
|     </BaseInput> | ||||
|   </BaseInputGroup> | ||||
|  | ||||
|   <!-- Encryption --> | ||||
|   <BaseInputGroup | ||||
|     :label="$t(`${pre_t}.encryption`)" | ||||
|     :error="v$.encryption.$error && v$.encryption.$errors[0].$message" | ||||
|     required | ||||
|   > | ||||
|     <BaseMultiselect | ||||
|       v-model.trim="mailSenderStore.smtpConfig.encryption" | ||||
|       :options="encryptions" | ||||
|       :searchable="true" | ||||
|       :show-labels="false" | ||||
|       :placeholder="$t('general.select_option')" | ||||
|       :invalid="v$.encryption.$error" | ||||
|       @input="v$.encryption.$touch()" | ||||
|     /> | ||||
|   </BaseInputGroup> | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import { computed, ref, reactive } from 'vue' | ||||
| import { useI18n } from 'vue-i18n' | ||||
| import { required, numeric, helpers } from '@vuelidate/validators' | ||||
| import { useVuelidate } from '@vuelidate/core' | ||||
|  | ||||
| const pre_t = 'settings.mail_sender.smtp_config' | ||||
| const { t } = useI18n() | ||||
|  | ||||
| const props = defineProps({ | ||||
|   mailSenderStore: { | ||||
|     type: Object, | ||||
|     require: true, | ||||
|     default: Object, | ||||
|   }, | ||||
| }) | ||||
| let isShowPassword = ref(false) | ||||
| const getInputType = computed(() => { | ||||
|   if (isShowPassword.value) { | ||||
|     return 'text' | ||||
|   } | ||||
|   return 'password' | ||||
| }) | ||||
| const encryptions = props.mailSenderStore.mail_encryptions | ||||
|  | ||||
| const rules = computed(() => { | ||||
|   return { | ||||
|     host: { | ||||
|       required: helpers.withMessage(t('validation.required'), required), | ||||
|     }, | ||||
|     port: { | ||||
|       required: helpers.withMessage(t('validation.required'), required), | ||||
|       numeric: helpers.withMessage(t('validation.numbers_only'), numeric), | ||||
|     }, | ||||
|     encryption: { | ||||
|       required: helpers.withMessage(t('validation.required'), required), | ||||
|     }, | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const v$ = useVuelidate( | ||||
|   rules, | ||||
|   computed(() => props.mailSenderStore.smtpConfig) | ||||
| ) | ||||
| </script> | ||||
		Reference in New Issue
	
	Block a user