add mail sender in setting

This commit is contained in:
yashkanakiya
2023-03-11 18:58:59 +05:30
parent b4aa254b68
commit 959aa257b4
23 changed files with 1718 additions and 110 deletions

View File

@ -256,6 +256,31 @@
/> </template
></BaseInput>
</BaseInputGroup>
<!-- && setPasswordMethod !== 'manual' -->
<BaseInputGroup
v-show="customerStore.currentCustomer.enable_portal"
:label="$t('customers.select_sender')"
class="pt-5"
:error="
v$.currentCustomer.mail_sender_id.$error &&
v$.currentCustomer.mail_sender_id.$errors[0].$message
"
:content-loading="isFetchingInitialData"
required
>
<BaseMultiselect
v-model="customerStore.currentCustomer.mail_sender_id"
label="name"
value-prop="id"
:options="mailSenderStore.mailSenders"
:can-deselect="false"
:can-clear="false"
searchable
track-by="name"
:invalid="v$.currentCustomer.mail_sender_id.$error"
@input="v$.currentCustomer.mail_sender_id.$touch()"
/>
</BaseInputGroup>
</BaseInputGrid>
</div>
@ -601,11 +626,13 @@ import CustomerCustomFields from '@/scripts/admin/components/custom-fields/Creat
import { useGlobalStore } from '@/scripts/admin/stores/global'
import CopyInputField from '@/scripts/admin/components/CopyInputField.vue'
import { useCompanyStore } from '@/scripts/admin/stores/company'
import { useMailSenderStore } from '@/scripts/admin/stores/mail-sender'
const customerStore = useCustomerStore()
const customFieldStore = useCustomFieldStore()
const globalStore = useGlobalStore()
const companyStore = useCompanyStore()
const mailSenderStore = useMailSenderStore()
const customFieldValidationScope = 'customFields'
@ -617,6 +644,7 @@ const route = useRoute()
let isFetchingInitialData = ref(false)
let isShowPassword = ref(false)
let isShowConfirmPassword = ref(false)
const mailSenders = ref(null)
let active = ref(false)
const isSaving = ref(false)
@ -679,6 +707,9 @@ const rules = computed(() => {
website: {
url: helpers.withMessage(t('validation.invalid_url'), url),
},
mail_sender_id: {
required: helpers.withMessage(t('validation.required'), required),
},
billing: {
address_street_1: {
maxLength: helpers.withMessage(
@ -722,6 +753,20 @@ const v$ = useVuelidate(rules, customerStore, {
$scope: customFieldValidationScope,
})
onMounted(async () => {
await mailSenderStore.fetchMailSenders()
let mailSenderData = await mailSenderStore.fetchMailSenderList()
if (mailSenderData.data) {
mailSenders.value = mailSenderData.data.data
let defaultMailSender = mailSenderData.data.data.find(
(mailSender) => mailSender.is_default == true
)
customerStore.currentCustomer.mail_sender_id = defaultMailSender
? defaultMailSender.id
: null
}
})
customerStore.resetCurrentCustomer()
customerStore.fetchCustomerInitialSettings(isEdit.value)

View 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>

View File

@ -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>

View 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>

View File

@ -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>

View File

@ -128,6 +128,29 @@
</BaseInput>
</BaseInputGroup>
<BaseInputGroup
:label="$t('users.select_sender')"
:error="
v$.userData.mail_sender_id.$error &&
v$.userData.mail_sender_id.$errors[0].$message
"
:content-loading="isFetchingInitialData"
required
>
<BaseMultiselect
v-model="userStore.userData.mail_sender_id"
label="name"
value-prop="id"
:options="mailSenderStore.mailSenders"
:can-deselect="false"
:can-clear="false"
searchable
track-by="name"
:invalid="v$.userData.mail_sender_id.$error"
@input="v$.userData.mail_sender_id.$touch()"
/>
</BaseInputGroup>
<BaseInputGroup
:content-loading="isFetchingInitialData"
:label="$t('users.phone')"
@ -162,7 +185,7 @@
</template>
<script setup>
import { ref, computed, reactive } from 'vue'
import { ref, computed, reactive, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useCompanyStore } from '@/scripts/admin/stores/company'
import {
@ -176,6 +199,7 @@ import useVuelidate from '@vuelidate/core'
import { ValidateEach } from '@vuelidate/components'
import { useI18n } from 'vue-i18n'
import { useUsersStore } from '@/scripts/admin/stores/users'
import { useMailSenderStore } from '@/scripts/admin/stores/mail-sender'
const userStore = useUsersStore()
@ -183,11 +207,13 @@ const { t } = useI18n()
const route = useRoute()
const router = useRouter()
const companyStore = useCompanyStore()
const mailSenderStore = useMailSenderStore()
let isSaving = ref(false)
let isFetchingInitialData = ref(false)
let selectedCompanies = ref([])
let companies = ref([])
const mailSenders = ref(null)
const isEdit = computed(() => route.name === 'users.edit')
@ -222,6 +248,9 @@ const rules = computed(() => {
companies: {
required: helpers.withMessage(t('validation.required'), required),
},
mail_sender_id: {
required: helpers.withMessage(t('validation.required'), required),
},
},
}
})
@ -236,6 +265,20 @@ const v$ = useVuelidate(rules, userStore, {
$scope: true,
})
onMounted(async () => {
await mailSenderStore.fetchMailSenders()
let mailSenderData = await mailSenderStore.fetchMailSenderList()
if (mailSenderData.data) {
mailSenders.value = mailSenderData.data.data
let defaultMailSender = mailSenderData.data.data.find(
(mailSender) => mailSender.is_default == true
)
userStore.userData.mail_sender_id = defaultMailSender
? defaultMailSender.id
: null
}
})
loadInitialData()
userStore.resetUserData()