1
0
forked from test/crm
Pratik 5b9539245d feat: add email account
(cherry picked from commit 87174f207dc4fe60706b9c1d9b6be7b5a19628f9)
2025-04-22 08:40:28 +00:00

187 lines
5.7 KiB
Vue

<template>
<div class="flex flex-col h-full gap-4">
<!-- title and desc -->
<div role="heading" aria-level="1" class="flex justify-between gap-1">
<h5 class="text-lg font-semibold">Edit Email</h5>
</div>
<div class="w-fit">
<EmailProviderIcon :logo="emailIcon[accountData.service]" :service-name="accountData.service" />
</div>
<!-- banner for setting up email account -->
<div class="flex items-center gap-2 p-2 rounded-md ring-1 ring-gray-200">
<CircleAlert class="w-5 h-6 text-blue-500 w-min-5 w-max-5 min-h-5 max-w-5" />
<div class="text-xs text-gray-700 text-wrap">
{{ info.description }}
<a :href="info.link" target="_blank" class="text-blue-500 underline">here</a>
.
</div>
</div>
<!-- fields -->
<div class="flex flex-col 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">
<FormControl v-model="state[field.name]" :label="field.label" :name="field.name" :type="field.type"
:placeholder="field.placeholder" />
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div 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>
</div>
</div>
<ErrorMessage v-if="error" class="ml-1" :message="error" />
</div>
<!-- action buttons -->
<div class="flex justify-between mt-auto">
<Button label="Back" theme="gray" variant="outline" :disabled="loading"
@click="emit('update:step', 'email-list')" />
<Button label="Update Account" variant="solid" @click="updateAccount" :loading="loading" />
</div>
</div>
</template>
<script setup>
import { computed, reactive, ref } from "vue";
import { call } from "frappe-ui";
import EmailProviderIcon from "./EmailProviderIcon.vue";
import {
emailIcon,
services,
popularProviderFields,
customProviderFields,
validateInputs,
incomingOutgoingFields,
} from "./emailConfig";
import { createToast } from "@/utils";
import CircleAlert from "~icons/lucide/circle-alert";
const props = defineProps({
accountData: null,
})
const emit = defineEmits();
const state = reactive({
email_account_name: props.accountData.email_account_name || "",
service: props.accountData.service || "",
email_id: props.accountData.email_id || "",
api_key: props.accountData?.api_key || null,
api_secret: props.accountData?.api_secret || null,
password: props.accountData?.password || null,
frappe_mail_site: props.accountData?.frappe_mail_site || "",
enable_incoming: props.accountData.enable_incoming || false,
enable_outgoing: props.accountData.enable_outgoing || false,
default_outgoing: props.accountData.default_outgoing || false,
default_incoming: props.accountData.default_incoming || false,
});
const info = {
description: "To know more about setting up email accounts, click",
link: "https://docs.erpnext.com/docs/user/manual/en/email-account",
};
const isCustomService = computed(() => {
return services.find((s) => s.name === props.accountData.service).custom;
});
const fields = computed(() => {
if (isCustomService.value) {
return customProviderFields;
}
return popularProviderFields;
});
const error = ref();
const loading = ref(false);
async function updateAccount() {
error.value = validateInputs(state, isCustomService.value);
if (error.value) return;
const old = { ...props.accountData };
const updatedEmailAccount = { ...state };
const nameChanged =
old.email_account_name !== updatedEmailAccount.email_account_name;
delete old.email_account_name;
delete updatedEmailAccount.email_account_name;
const otherFieldsChanged = isDirty.value;
const values = updatedEmailAccount;
if (!nameChanged && !otherFieldsChanged) {
createToast({
title: "No changes made",
icon: "info",
iconClasses: "text-blue-600",
});
return;
}
if (nameChanged) {
try {
loading.value = true;
await callRenameDoc();
succesHandler();
} catch (err) {
errorHandler();
}
}
if (otherFieldsChanged) {
try {
loading.value = true;
await callSetValue(values);
succesHandler();
} catch (err) {
errorHandler();
}
}
}
const isDirty = computed(() => {
return (
state.email_id !== props.accountData.email_id ||
state.api_key !== props.accountData.api_key ||
state.api_secret !== props.accountData.api_secret ||
state.password !== props.accountData.password ||
state.enable_incoming !== props.accountData.enable_incoming ||
state.enable_outgoing !== props.accountData.enable_outgoing ||
state.default_outgoing !== props.accountData.default_outgoing ||
state.default_incoming !== props.accountData.default_incoming ||
state.frappe_mail_site !== props.accountData.frappe_mail_site
);
});
async function callRenameDoc() {
const d = await call("frappe.client.rename_doc", {
doctype: "Email Account",
old_name: props.accountData.email_account_name,
new_name: state.email_account_name,
});
return d;
}
async function callSetValue(values) {
const d = await call("frappe.client.set_value", {
doctype: "Email Account",
name: state.email_account_name,
fieldname: values,
});
return d.name;
}
function succesHandler() {
emit("update:step", "email-list");
createToast({
title: "Email account updated successfully",
icon: "check",
iconClasses: "text-green-600",
});
}
function errorHandler() {
loading.value = false;
error.value = "Failed to update email account, Invalid credentials";
}
</script>