Merge pull request #754 from frappe/mergify/bp/main-hotfix/pr-753
fix: dark mode email account css (backport #753)
This commit is contained in:
commit
1f1090c2e6
@ -1,55 +1,50 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center justify-between p-1 border-b border-gray-200 cursor-pointer">
|
<div
|
||||||
|
class="flex items-center justify-between p-1 py-3 border-b border-gray-200 dark:border-gray-700 cursor-pointer"
|
||||||
|
>
|
||||||
<!-- avatar and name -->
|
<!-- avatar and name -->
|
||||||
<div class="flex items-center justify-between gap-2">
|
<div class="flex items-center justify-between gap-2">
|
||||||
<EmailProviderIcon :logo="emailIcon[emailAccount.service]" />
|
<EmailProviderIcon :logo="emailIcon[emailAccount.service]" />
|
||||||
<div>
|
<div>
|
||||||
<p class="text-sm font-semibold text-gray-700">
|
<p class="text-sm font-semibold text-ink-gray-9">
|
||||||
{{ emailAccount.email_account_name }}
|
{{ emailAccount.email_account_name }}
|
||||||
</p>
|
</p>
|
||||||
<div class="text-sm text-gray-500">{{ emailAccount.email_id }}</div>
|
<div class="text-sm text-gray-500">{{ emailAccount.email_id }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Badge variant="subtle" :label="badgeTitleColor[0]" :theme="badgeTitleColor[1]" />
|
<Badge variant="subtle" :label="badgeTitleColor" :theme="gray" />
|
||||||
</div>
|
</div>
|
||||||
<!-- email id -->
|
<!-- email id -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { emailIcon } from "./emailConfig";
|
import { emailIcon } from './emailConfig'
|
||||||
import EmailProviderIcon from "./EmailProviderIcon.vue";
|
import EmailProviderIcon from './EmailProviderIcon.vue'
|
||||||
import { computed } from "vue";
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
emailAccount: {
|
emailAccount: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
const badgeTitleColor = computed(() => {
|
const badgeTitleColor = computed(() => {
|
||||||
if (
|
if (
|
||||||
props.emailAccount.default_incoming &&
|
props.emailAccount.default_incoming &&
|
||||||
props.emailAccount.default_outgoing
|
props.emailAccount.default_outgoing
|
||||||
) {
|
) {
|
||||||
const color =
|
return 'Default Sending and Inbox'
|
||||||
props.emailAccount.enable_incoming && props.emailAccount.enable_outgoing
|
|
||||||
? "blue"
|
|
||||||
: "gray";
|
|
||||||
return ["Default Sending and Inbox", color];
|
|
||||||
} else if (props.emailAccount.default_incoming) {
|
} else if (props.emailAccount.default_incoming) {
|
||||||
const color = props.emailAccount.enable_incoming ? "blue" : "gray";
|
return 'Default Inbox'
|
||||||
return ["Default Inbox", color];
|
|
||||||
} else if (props.emailAccount.default_outgoing) {
|
} else if (props.emailAccount.default_outgoing) {
|
||||||
const color = props.emailAccount.enable_outgoing ? "blue" : "gray";
|
return 'Default Sending'
|
||||||
return ["Default Sending", color];
|
|
||||||
} else {
|
} else {
|
||||||
const color = props.emailAccount.enable_incoming ? "blue" : "gray";
|
return 'Inbox'
|
||||||
return ["Inbox", color];
|
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
@ -1,18 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!-- header -->
|
<!-- header -->
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between text-ink-gray-9">
|
||||||
<h1 class="text-xl font-semibold">Email Accounts</h1>
|
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
|
||||||
<Button label="Add Account" theme="gray" variant="solid" @click="emit('update:step', 'email-add')" class="mr-8">
|
Email Accounts
|
||||||
|
</h2>
|
||||||
|
<Button
|
||||||
|
label="Add Account"
|
||||||
|
theme="gray"
|
||||||
|
variant="solid"
|
||||||
|
@click="emit('update:step', 'email-add')"
|
||||||
|
class="mr-8"
|
||||||
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<LucidePlus class="w-4 h-4" />
|
<LucidePlus class="w-4 h-4" />
|
||||||
</template>
|
</template>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<!-- list accounts -->
|
<!-- list accounts -->
|
||||||
<div v-if="!emailAccounts.loading && Boolean(emailAccounts.data?.length)" class="mt-4">
|
<div
|
||||||
|
v-if="!emailAccounts.loading && Boolean(emailAccounts.data?.length)"
|
||||||
|
class="mt-4"
|
||||||
|
>
|
||||||
<div v-for="emailAccount in emailAccounts.data" :key="emailAccount.name">
|
<div v-for="emailAccount in emailAccounts.data" :key="emailAccount.name">
|
||||||
<EmailAccountCard :emailAccount="emailAccount" @click="emit('update:step', 'email-edit', emailAccount)" />
|
<EmailAccountCard
|
||||||
|
:emailAccount="emailAccount"
|
||||||
|
@click="emit('update:step', 'email-edit', emailAccount)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- fallback if no email accounts -->
|
<!-- fallback if no email accounts -->
|
||||||
@ -23,28 +37,28 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { createListResource } from "frappe-ui";
|
import { createListResource } from 'frappe-ui'
|
||||||
import EmailAccountCard from "./EmailAccountCard.vue";
|
import EmailAccountCard from './EmailAccountCard.vue'
|
||||||
|
|
||||||
const emit = defineEmits(["update:step"]);
|
const emit = defineEmits(['update:step'])
|
||||||
|
|
||||||
const emailAccounts = createListResource({
|
const emailAccounts = createListResource({
|
||||||
doctype: "Email Account",
|
doctype: 'Email Account',
|
||||||
cache: true,
|
cache: true,
|
||||||
fields: ["*"],
|
fields: ['*'],
|
||||||
filters: {
|
filters: {
|
||||||
email_id: ["Not Like", "%example%"],
|
email_id: ['Not Like', '%example%'],
|
||||||
},
|
},
|
||||||
pageLength: 10,
|
pageLength: 10,
|
||||||
auto: true,
|
auto: true,
|
||||||
onSuccess: (accounts) => {
|
onSuccess: (accounts) => {
|
||||||
// convert 0 to false to handle boolean fields
|
// convert 0 to false to handle boolean fields
|
||||||
accounts.forEach((account) => {
|
accounts.forEach((account) => {
|
||||||
account.enable_incoming = Boolean(account.enable_incoming);
|
account.enable_incoming = Boolean(account.enable_incoming)
|
||||||
account.enable_outgoing = Boolean(account.enable_outgoing);
|
account.enable_outgoing = Boolean(account.enable_outgoing)
|
||||||
account.default_incoming = Boolean(account.default_incoming);
|
account.default_incoming = Boolean(account.default_incoming)
|
||||||
account.default_outgoing = Boolean(account.default_outgoing);
|
account.default_outgoing = Boolean(account.default_outgoing)
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -2,39 +2,68 @@
|
|||||||
<div class="flex flex-col h-full gap-4">
|
<div class="flex flex-col h-full gap-4">
|
||||||
<!-- title and desc -->
|
<!-- title and desc -->
|
||||||
<div role="heading" aria-level="1" class="flex flex-col gap-1">
|
<div role="heading" aria-level="1" class="flex flex-col gap-1">
|
||||||
<h5 class="text-xl font-semibold">Setup Email</h5>
|
<h2 class="text-xl font-semibold text-ink-gray-9">Setup Email</h2>
|
||||||
<p class="text-sm text-gray-600">
|
<p class="text-sm text-gray-600">
|
||||||
Choose the email service provider you want to configure.
|
Choose the email service provider you want to configure.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<!-- email service provider selection -->
|
<!-- email service provider selection -->
|
||||||
<div class="flex flex-wrap items-center gap-4">
|
<div class="flex flex-wrap items-center">
|
||||||
<div v-for="s in services" :key="s.name" class="flex flex-col items-center gap-1 mt-4 min-w-3"
|
<div
|
||||||
@click="handleSelect(s)">
|
v-for="s in services"
|
||||||
<EmailProviderIcon :service-name="s.name" :logo="s.icon" :selected="selectedService?.name === s?.name" />
|
:key="s.name"
|
||||||
|
class="flex flex-col items-center gap-1 mt-4 w-[70px]"
|
||||||
|
@click="handleSelect(s)"
|
||||||
|
>
|
||||||
|
<EmailProviderIcon
|
||||||
|
:service-name="s.name"
|
||||||
|
:logo="s.icon"
|
||||||
|
:selected="selectedService?.name === s?.name"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="selectedService" class="flex flex-col gap-4">
|
<div v-if="selectedService" class="flex flex-col gap-4">
|
||||||
<!-- email service provider info -->
|
<!-- email service provider info -->
|
||||||
<div class="flex items-center gap-2 p-2 rounded-md ring-1 ring-gray-200">
|
<div
|
||||||
<CircleAlert class="w-5 h-6 text-blue-500 w-min-5 w-max-5 min-h-5 max-w-5" />
|
class="flex items-center gap-2 p-2 rounded-md ring-1 ring-gray-400 dark:ring-gray-700 text-gray-700 dark:text-gray-500"
|
||||||
<div class="text-xs text-gray-700 text-wrap">
|
>
|
||||||
|
<CircleAlert class="w-5 h-6 w-min-5 w-max-5 min-h-5 max-w-5" />
|
||||||
|
<div class="text-xs text-wrap">
|
||||||
{{ selectedService.info }}
|
{{ selectedService.info }}
|
||||||
<a :href="selectedService.link" target="_blank" class="text-blue-500 underline">here</a>
|
<a :href="selectedService.link" target="_blank" class="underline"
|
||||||
.
|
>here</a
|
||||||
|
>.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- service provider fields -->
|
<!-- service provider fields -->
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="grid grid-cols-1 gap-4">
|
<div class="grid grid-cols-1 gap-4">
|
||||||
<div v-for="field in fields" :key="field.name" class="flex flex-col gap-1">
|
<div
|
||||||
<FormControl v-model="state[field.name]" :label="field.label" :name="field.name" :type="field.type"
|
v-for="field in fields"
|
||||||
:placeholder="field.placeholder" />
|
:key="field.name"
|
||||||
|
class="flex flex-col gap-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
v-model="state[field.name]"
|
||||||
|
:label="field.label"
|
||||||
|
:name="field.name"
|
||||||
|
:type="field.type"
|
||||||
|
:placeholder="field.placeholder"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="grid grid-cols-2 gap-4">
|
||||||
<div v-for="field in incomingOutgoingFields" :key="field.name" class="flex flex-col gap-1">
|
<div
|
||||||
<FormControl v-model="state[field.name]" :label="field.label" :name="field.name" :type="field.type" />
|
v-for="field in incomingOutgoingFields"
|
||||||
|
:key="field.name"
|
||||||
|
class="flex flex-col gap-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
v-model="state[field.name]"
|
||||||
|
:label="field.label"
|
||||||
|
:name="field.name"
|
||||||
|
:type="field.type"
|
||||||
|
/>
|
||||||
<p class="text-gray-500 text-p-sm">{{ field.description }}</p>
|
<p class="text-gray-500 text-p-sm">{{ field.description }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -43,79 +72,89 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- action button -->
|
<!-- action button -->
|
||||||
<div v-if="selectedService" class="flex justify-between mt-auto">
|
<div v-if="selectedService" class="flex justify-between mt-auto">
|
||||||
<Button label="Back" theme="gray" variant="outline" :disabled="addEmailRes.loading"
|
<Button
|
||||||
@click="emit('update:step', 'email-list')" />
|
label="Back"
|
||||||
<Button label="Create" variant="solid" :loading="addEmailRes.loading" @click="createEmailAccount" />
|
theme="gray"
|
||||||
|
variant="outline"
|
||||||
|
:disabled="addEmailRes.loading"
|
||||||
|
@click="emit('update:step', 'email-list')"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
label="Create"
|
||||||
|
variant="solid"
|
||||||
|
:loading="addEmailRes.loading"
|
||||||
|
@click="createEmailAccount"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, reactive, ref } from "vue";
|
import { computed, reactive, ref } from 'vue'
|
||||||
import { createResource } from "frappe-ui";
|
import { createResource } from 'frappe-ui'
|
||||||
import CircleAlert from "~icons/lucide/circle-alert";
|
import CircleAlert from '~icons/lucide/circle-alert'
|
||||||
import { createToast } from "@/utils";
|
import { createToast } from '@/utils'
|
||||||
import {
|
import {
|
||||||
customProviderFields,
|
customProviderFields,
|
||||||
popularProviderFields,
|
popularProviderFields,
|
||||||
services,
|
services,
|
||||||
validateInputs,
|
validateInputs,
|
||||||
incomingOutgoingFields,
|
incomingOutgoingFields,
|
||||||
} from "./emailConfig";
|
} from './emailConfig'
|
||||||
import EmailProviderIcon from "./EmailProviderIcon.vue";
|
import EmailProviderIcon from './EmailProviderIcon.vue'
|
||||||
|
|
||||||
const emit = defineEmits();
|
const emit = defineEmits()
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
service: "",
|
service: '',
|
||||||
email_account_name: "",
|
email_account_name: '',
|
||||||
email_id: "",
|
email_id: '',
|
||||||
password: "",
|
password: '',
|
||||||
api_key: "",
|
api_key: '',
|
||||||
api_secret: "",
|
api_secret: '',
|
||||||
frappe_mail_site: "",
|
frappe_mail_site: '',
|
||||||
enable_incoming: false,
|
enable_incoming: false,
|
||||||
enable_outgoing: false,
|
enable_outgoing: false,
|
||||||
default_incoming: false,
|
default_incoming: false,
|
||||||
default_outgoing: false,
|
default_outgoing: false,
|
||||||
});
|
})
|
||||||
|
|
||||||
const selectedService = ref(null);
|
const selectedService = ref(null)
|
||||||
const fields = computed(() =>
|
const fields = computed(() =>
|
||||||
selectedService.value.custom ? customProviderFields : popularProviderFields
|
selectedService.value.custom ? customProviderFields : popularProviderFields,
|
||||||
);
|
)
|
||||||
|
|
||||||
function handleSelect(service) {
|
function handleSelect(service) {
|
||||||
selectedService.value = service;
|
selectedService.value = service
|
||||||
state.service = service.name;
|
state.service = service.name
|
||||||
}
|
}
|
||||||
|
|
||||||
const addEmailRes = createResource({
|
const addEmailRes = createResource({
|
||||||
url: "crm.api.settings.create_email_account",
|
url: 'crm.api.settings.create_email_account',
|
||||||
makeParams: (val) => {
|
makeParams: (val) => {
|
||||||
return {
|
return {
|
||||||
...val,
|
...val,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
createToast({
|
createToast({
|
||||||
title: "Email account created successfully",
|
title: 'Email account created successfully',
|
||||||
icon: "check",
|
icon: 'check',
|
||||||
iconClasses: "text-green-600",
|
iconClasses: 'text-green-600',
|
||||||
});
|
})
|
||||||
emit("update:step", "email-list");
|
emit('update:step', 'email-list')
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
error.value = "Failed to create email account, Invalid credentials";
|
error.value = 'Failed to create email account, Invalid credentials'
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
const error = ref();
|
const error = ref()
|
||||||
function createEmailAccount() {
|
function createEmailAccount() {
|
||||||
error.value = validateInputs(state, selectedService.value.custom);
|
error.value = validateInputs(state, selectedService.value.custom)
|
||||||
if (error.value) return;
|
if (error.value) return
|
||||||
|
|
||||||
addEmailRes.submit({ data: state });
|
addEmailRes.submit({ data: state })
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -2,31 +2,56 @@
|
|||||||
<div class="flex flex-col h-full gap-4">
|
<div class="flex flex-col h-full gap-4">
|
||||||
<!-- title and desc -->
|
<!-- title and desc -->
|
||||||
<div role="heading" aria-level="1" class="flex justify-between gap-1">
|
<div role="heading" aria-level="1" class="flex justify-between gap-1">
|
||||||
<h5 class="text-lg font-semibold">Edit Email</h5>
|
<h2 class="text-xl font-semibold text-ink-gray-9">Edit Email</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-fit">
|
<div class="w-fit">
|
||||||
<EmailProviderIcon :logo="emailIcon[accountData.service]" :service-name="accountData.service" />
|
<EmailProviderIcon
|
||||||
|
:logo="emailIcon[accountData.service]"
|
||||||
|
:service-name="accountData.service"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- banner for setting up email account -->
|
<!-- banner for setting up email account -->
|
||||||
<div class="flex items-center gap-2 p-2 rounded-md ring-1 ring-gray-200">
|
<div
|
||||||
<CircleAlert class="w-5 h-6 text-blue-500 w-min-5 w-max-5 min-h-5 max-w-5" />
|
class="flex items-center gap-2 p-2 rounded-md ring-1 ring-gray-400 dark:ring-gray-700"
|
||||||
<div class="text-xs text-gray-700 text-wrap">
|
>
|
||||||
|
<CircleAlert
|
||||||
|
class="size-6 text-gray-500 w-min-5 w-max-5 min-h-5 max-w-5"
|
||||||
|
/>
|
||||||
|
<div class="text-xs text-gray-700 dark:text-gray-500 text-wrap">
|
||||||
{{ info.description }}
|
{{ info.description }}
|
||||||
<a :href="info.link" target="_blank" class="text-blue-500 underline">here</a>
|
<a :href="info.link" target="_blank" class="underline">here</a>
|
||||||
.
|
.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- fields -->
|
<!-- fields -->
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="grid grid-cols-1 gap-4">
|
<div class="grid grid-cols-1 gap-4">
|
||||||
<div v-for="field in fields" :key="field.name" class="flex flex-col gap-1">
|
<div
|
||||||
<FormControl v-model="state[field.name]" :label="field.label" :name="field.name" :type="field.type"
|
v-for="field in fields"
|
||||||
:placeholder="field.placeholder" />
|
:key="field.name"
|
||||||
|
class="flex flex-col gap-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
v-model="state[field.name]"
|
||||||
|
:label="field.label"
|
||||||
|
:name="field.name"
|
||||||
|
:type="field.type"
|
||||||
|
:placeholder="field.placeholder"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="grid grid-cols-2 gap-4">
|
||||||
<div v-for="field in incomingOutgoingFields" :key="field.name" class="flex flex-col gap-1">
|
<div
|
||||||
<FormControl v-model="state[field.name]" :label="field.label" :name="field.name" :type="field.type" />
|
v-for="field in incomingOutgoingFields"
|
||||||
|
:key="field.name"
|
||||||
|
class="flex flex-col gap-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
v-model="state[field.name]"
|
||||||
|
:label="field.label"
|
||||||
|
:name="field.name"
|
||||||
|
:type="field.type"
|
||||||
|
/>
|
||||||
<p class="text-gray-500 text-p-sm">{{ field.description }}</p>
|
<p class="text-gray-500 text-p-sm">{{ field.description }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -34,17 +59,27 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- action buttons -->
|
<!-- action buttons -->
|
||||||
<div class="flex justify-between mt-auto">
|
<div class="flex justify-between mt-auto">
|
||||||
<Button label="Back" theme="gray" variant="outline" :disabled="loading"
|
<Button
|
||||||
@click="emit('update:step', 'email-list')" />
|
label="Back"
|
||||||
<Button label="Update Account" variant="solid" @click="updateAccount" :loading="loading" />
|
theme="gray"
|
||||||
|
variant="outline"
|
||||||
|
:disabled="loading"
|
||||||
|
@click="emit('update:step', 'email-list')"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
label="Update Account"
|
||||||
|
variant="solid"
|
||||||
|
@click="updateAccount"
|
||||||
|
:loading="loading"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, reactive, ref } from "vue";
|
import { computed, reactive, ref } from 'vue'
|
||||||
import { call } from "frappe-ui";
|
import { call } from 'frappe-ui'
|
||||||
import EmailProviderIcon from "./EmailProviderIcon.vue";
|
import EmailProviderIcon from './EmailProviderIcon.vue'
|
||||||
import {
|
import {
|
||||||
emailIcon,
|
emailIcon,
|
||||||
services,
|
services,
|
||||||
@ -52,88 +87,87 @@ import {
|
|||||||
customProviderFields,
|
customProviderFields,
|
||||||
validateInputs,
|
validateInputs,
|
||||||
incomingOutgoingFields,
|
incomingOutgoingFields,
|
||||||
} from "./emailConfig";
|
} from './emailConfig'
|
||||||
import { createToast } from "@/utils";
|
import { createToast } from '@/utils'
|
||||||
import CircleAlert from "~icons/lucide/circle-alert";
|
import CircleAlert from '~icons/lucide/circle-alert'
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
accountData: null,
|
accountData: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits();
|
const emit = defineEmits()
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
email_account_name: props.accountData.email_account_name || "",
|
email_account_name: props.accountData.email_account_name || '',
|
||||||
service: props.accountData.service || "",
|
service: props.accountData.service || '',
|
||||||
email_id: props.accountData.email_id || "",
|
email_id: props.accountData.email_id || '',
|
||||||
api_key: props.accountData?.api_key || null,
|
api_key: props.accountData?.api_key || null,
|
||||||
api_secret: props.accountData?.api_secret || null,
|
api_secret: props.accountData?.api_secret || null,
|
||||||
password: props.accountData?.password || null,
|
password: props.accountData?.password || null,
|
||||||
frappe_mail_site: props.accountData?.frappe_mail_site || "",
|
frappe_mail_site: props.accountData?.frappe_mail_site || '',
|
||||||
enable_incoming: props.accountData.enable_incoming || false,
|
enable_incoming: props.accountData.enable_incoming || false,
|
||||||
enable_outgoing: props.accountData.enable_outgoing || false,
|
enable_outgoing: props.accountData.enable_outgoing || false,
|
||||||
default_outgoing: props.accountData.default_outgoing || false,
|
default_outgoing: props.accountData.default_outgoing || false,
|
||||||
default_incoming: props.accountData.default_incoming || false,
|
default_incoming: props.accountData.default_incoming || false,
|
||||||
});
|
})
|
||||||
|
|
||||||
const info = {
|
const info = {
|
||||||
description: "To know more about setting up email accounts, click",
|
description: 'To know more about setting up email accounts, click',
|
||||||
link: "https://docs.erpnext.com/docs/user/manual/en/email-account",
|
link: 'https://docs.erpnext.com/docs/user/manual/en/email-account',
|
||||||
};
|
}
|
||||||
|
|
||||||
const isCustomService = computed(() => {
|
const isCustomService = computed(() => {
|
||||||
return services.find((s) => s.name === props.accountData.service).custom;
|
return services.find((s) => s.name === props.accountData.service).custom
|
||||||
});
|
})
|
||||||
|
|
||||||
const fields = computed(() => {
|
const fields = computed(() => {
|
||||||
if (isCustomService.value) {
|
if (isCustomService.value) {
|
||||||
return customProviderFields;
|
return customProviderFields
|
||||||
}
|
}
|
||||||
return popularProviderFields;
|
return popularProviderFields
|
||||||
});
|
})
|
||||||
|
|
||||||
const error = ref();
|
const error = ref()
|
||||||
const loading = ref(false);
|
const loading = ref(false)
|
||||||
async function updateAccount() {
|
async function updateAccount() {
|
||||||
error.value = validateInputs(state, isCustomService.value);
|
error.value = validateInputs(state, isCustomService.value)
|
||||||
if (error.value) return;
|
if (error.value) return
|
||||||
const old = { ...props.accountData };
|
const old = { ...props.accountData }
|
||||||
const updatedEmailAccount = { ...state };
|
const updatedEmailAccount = { ...state }
|
||||||
|
|
||||||
const nameChanged =
|
const nameChanged =
|
||||||
old.email_account_name !== updatedEmailAccount.email_account_name;
|
old.email_account_name !== updatedEmailAccount.email_account_name
|
||||||
delete old.email_account_name;
|
delete old.email_account_name
|
||||||
delete updatedEmailAccount.email_account_name;
|
delete updatedEmailAccount.email_account_name
|
||||||
|
|
||||||
const otherFieldsChanged = isDirty.value;
|
const otherFieldsChanged = isDirty.value
|
||||||
const values = updatedEmailAccount;
|
const values = updatedEmailAccount
|
||||||
|
|
||||||
if (!nameChanged && !otherFieldsChanged) {
|
if (!nameChanged && !otherFieldsChanged) {
|
||||||
createToast({
|
createToast({
|
||||||
title: "No changes made",
|
title: 'No changes made',
|
||||||
icon: "info",
|
icon: 'info',
|
||||||
iconClasses: "text-blue-600",
|
iconClasses: 'text-blue-600',
|
||||||
});
|
})
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nameChanged) {
|
if (nameChanged) {
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true
|
||||||
await callRenameDoc();
|
await callRenameDoc()
|
||||||
succesHandler();
|
succesHandler()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errorHandler();
|
errorHandler()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (otherFieldsChanged) {
|
if (otherFieldsChanged) {
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true
|
||||||
await callSetValue(values);
|
await callSetValue(values)
|
||||||
succesHandler();
|
succesHandler()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errorHandler();
|
errorHandler()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,38 +183,38 @@ const isDirty = computed(() => {
|
|||||||
state.default_outgoing !== props.accountData.default_outgoing ||
|
state.default_outgoing !== props.accountData.default_outgoing ||
|
||||||
state.default_incoming !== props.accountData.default_incoming ||
|
state.default_incoming !== props.accountData.default_incoming ||
|
||||||
state.frappe_mail_site !== props.accountData.frappe_mail_site
|
state.frappe_mail_site !== props.accountData.frappe_mail_site
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
|
|
||||||
async function callRenameDoc() {
|
async function callRenameDoc() {
|
||||||
const d = await call("frappe.client.rename_doc", {
|
const d = await call('frappe.client.rename_doc', {
|
||||||
doctype: "Email Account",
|
doctype: 'Email Account',
|
||||||
old_name: props.accountData.email_account_name,
|
old_name: props.accountData.email_account_name,
|
||||||
new_name: state.email_account_name,
|
new_name: state.email_account_name,
|
||||||
});
|
})
|
||||||
return d;
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
async function callSetValue(values) {
|
async function callSetValue(values) {
|
||||||
const d = await call("frappe.client.set_value", {
|
const d = await call('frappe.client.set_value', {
|
||||||
doctype: "Email Account",
|
doctype: 'Email Account',
|
||||||
name: state.email_account_name,
|
name: state.email_account_name,
|
||||||
fieldname: values,
|
fieldname: values,
|
||||||
});
|
})
|
||||||
return d.name;
|
return d.name
|
||||||
}
|
}
|
||||||
|
|
||||||
function succesHandler() {
|
function succesHandler() {
|
||||||
emit("update:step", "email-list");
|
emit('update:step', 'email-list')
|
||||||
createToast({
|
createToast({
|
||||||
title: "Email account updated successfully",
|
title: 'Email account updated successfully',
|
||||||
icon: "check",
|
icon: 'check',
|
||||||
iconClasses: "text-green-600",
|
iconClasses: 'text-green-600',
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function errorHandler() {
|
function errorHandler() {
|
||||||
loading.value = false;
|
loading.value = false
|
||||||
error.value = "Failed to update email account, Invalid credentials";
|
error.value = 'Failed to update email account, Invalid credentials'
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,28 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center justify-center w-8 h-8 bg-gray-100 cursor-pointer rounded-xl hover:bg-gray-200"
|
<div
|
||||||
:class="{ 'ring-2 ring-blue-500': selected }">
|
class="flex items-center justify-center w-8 h-8 bg-gray-100 cursor-pointer rounded-xl hover:bg-gray-200"
|
||||||
|
:class="{ 'ring-2 ring-gray-500 dark:ring-gray-100': selected }"
|
||||||
|
>
|
||||||
<img :src="logo" class="w-4 h-4" />
|
<img :src="logo" class="w-4 h-4" />
|
||||||
</div>
|
</div>
|
||||||
<p v-if="serviceName" class="text-xs text-center text-gray-700">
|
<p
|
||||||
|
v-if="serviceName"
|
||||||
|
class="text-xs text-center text-gray-700 dark:text-gray-500 mt-2"
|
||||||
|
>
|
||||||
{{ serviceName }}
|
{{ serviceName }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
logo: {
|
logo: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
serviceName: {
|
serviceName: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: '',
|
||||||
},
|
},
|
||||||
selected: {
|
selected: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user