File: //home/arjun/projects/buyercall/buyercall/assets/vue/widgets/EmailTemplates/components/EditForm.vue
<template>
<div class="height-set">
<div class="spinner-main">
<Loader :loading="loadingSelectedTemplate || imageCapturing"> </Loader>
</div>
<div class="row" v-if="!loadingSelectedTemplate">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<h4 class="card-title mb-4">Create New Template</h4>
<b-form @submit.prevent="formSubmit">
<div class="row">
<div class="col-md-12">
<b-form-group class="mb-3" label="Title" label-for="title">
<b-form-input
id="title"
type="text"
placeholder="Title"
v-model="form.title"
name="title"
:class="{
'is-invalid': submitted && v$.form.title.$error,
}"
></b-form-input>
<div
v-if="submitted && v$.form.title.$error"
class="invalid-feedback"
>
<span>This value is required.</span>
</div>
</b-form-group>
</div>
</div>
<div class="row">
<div class="col-md-12">
<b-form-group class="mb-3" label="Description" label-for="description">
<b-form-textarea
id="description"
rows="3"
placeholder="Enter description"
v-model="form.description"
name="title"
:class="{
'is-invalid': submitted && v$.form.description.$error,
}"
></b-form-textarea>
<div
v-if="submitted && v$.form.description.$error"
class="invalid-feedback"
>
<span>This value is required.</span>
</div>
</b-form-group>
</div>
</div>
<div class="row">
<div class="col-md-12">
<b-form-group class="mb-3" label="Subject" label-for="subject">
<b-form-input
id="subject"
type="text"
placeholder="Subject"
v-model="form.subject"
name="subject"
:class="{
'is-invalid': submitted && v$.form.subject.$error,
}"
></b-form-input>
<div
v-if="submitted && v$.form.subject.$error"
class="invalid-feedback"
>
<span>This value is required.</span>
</div>
</b-form-group>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="d-flex">
<button
type="button"
class="btn btn-success ms-auto mb-2"
@click="showDynamicFieldModal = true"
>
Add Dynamic Field
</button>
</div>
<h5 class="font-size-14 mb-1">Choose type of editor</h5>
<b-form-group class="mb-3 radio-group">
<b-form-radio
v-model="form.isPlainEmail"
class="form-check-right"
:value="false"
plain
style="margin-right: 10px"
>Wysiwyg Editor</b-form-radio
>
<b-form-radio
v-model="form.isPlainEmail"
class="form-check-right"
:value="true"
plain
style="margin-right: 10px"
>Plain</b-form-radio
>
</b-form-group>
<b-form-group class="mb-3" label="Content" label-for="content">
<template v-if="form.isPlainEmail === true">
<textarea
v-model="form.plainEmailContent"
class="form-control"
placeholder="Your message..."
rows="3"
></textarea>
<p
:class="{
'is-invalid': submitted && v$.form.plainEmailContent.$error,
}"
></p>
<div
v-if="submitted && v$.form.plainEmailContent.$error"
class="invalid-feedback"
>
<span>This value is required.</span>
</div>
</template>
<template v-else>
<ckeditor
:editor="editor"
v-model="form.editorData"
:config="editorConfig"
></ckeditor>
<p
:class="{
'is-invalid': submitted && v$.form.editorData.$error,
}"
></p>
<div
v-if="submitted && v$.form.editorData.$error"
class="invalid-feedback"
>
<span>This value is required.</span>
</div>
</template>
</b-form-group>
</div>
</div>
<div>
<b-button variant="primary" type="submit">
<i
class="bx bx-loader bx-spin font-size-16 align-middle me-2"
v-if="loading"
></i>
Save</b-button
>
<b-button
style="margin-left: 10px"
variant="light"
v-if="this.form.isPlainEmail === false"
@click="showPreview = !showPreview"
>Show Preview</b-button
>
</div>
</b-form>
</div>
</div>
</div>
<b-modal
v-model="showPreview"
title="Preview Email template"
hide-footer
id="source-modal"
size="xl"
>
<preview-email
v-if="showPreview"
:bodyText="getemalPreviewData()"
></preview-email>
</b-modal>
<b-modal
v-model="showDynamicFieldModal"
title="Add Dynamic Field"
hide-footer
id="workflow-modal"
>
<form @submit.prevent="handleSubmit">
<div class="row">
<div class="col-12">
<label for="fields">Fields</label>
<multiselect
v-model="dfForm.field"
:options="dynamicFieldoptions"
:multiple="false"
label="label"
:class="{
'is-invalid': dfFormSubmitted && v$.dfForm.field.$error,
}"
></multiselect>
<div
v-if="dfFormSubmitted && v$.dfForm.field.$error"
class="invalid-feedback"
>
<span>This value is required.</span>
</div>
</div>
</div>
<div class="text-end mt-3">
<b-button variant="light" @click="showDynamicFieldModal = false"
>Close</b-button
>
<b-button type="submit" variant="success" class="ms-1">Add Field</b-button>
</div>
</form>
</b-modal>
</div>
<div ref="capture" :style="{}" v-html="htmlData"></div>
<!-- <template v-if="renderImageUrl">
<img
class="rounded-circle header-profile-user avatar-lg"
alt="200x200"
:src="renderImageUrl"
data-holder-rendered="true"
/>
</template> -->
</div>
</template>
<script>
import Multiselect from "vue-multiselect";
//import { required, requiredIf } from "vuelidate/lib/validators";
import { useVuelidate } from "@vuelidate/core";
import {
required,
email,
minLength,
maxLength,
sameAs,
helpers,
requiredIf,
} from "@vuelidate/validators";
import * as _ from "lodash";
import { formvalidationMessages } from "../../../utils/util";
// import Editor from 'ckeditor5-custom-build/build/ckeditor';
import CKEditor from "@ckeditor/ckeditor5-vue";
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
import PreviewEmail from "./PreviewEmail.vue";
import Loader from "../../../components/Loader/loader.vue";
import EmailTemplateService from "../../../service/emailTemplatesService";
import domtoimage from "dom-to-image-more";
import { templateFields } from "../constants";
import {
BForm,
BFormGroup,
BFormInput,
BFormTextarea,
BFormRadioGroup,
BFormRadio,
BButton,
BModal,
} from "bootstrap-vue-next";
export default {
setup() {
const v$ = useVuelidate({
form: {
title: { required },
description: { required },
subject: { required },
plainEmailContent: { required },
editorData: { required },
},
dfForm: {
field: { required },
},
});
return { v$ }; // Ensure to return an object with the 'v$' property
},
validations: {
form: {
title: { required },
description: { required },
subject: { required },
editorData: {
required: requiredIf(function () {
if (this.form.isPlainEmail) {
return false;
}
return true;
}),
},
plainEmailContent: {
required: requiredIf(function () {
if (!this.form.isPlainEmail) {
return false;
}
return true;
}),
},
},
dfForm: {
field: { required },
},
},
props: {
loading: {
type: Boolean,
required: true,
},
AddUser: {
type: Boolean,
required: true,
},
selectedTemplateId: {},
},
mounted() {
if (this.selectedTemplateId) {
this.getTemplateById(this.selectedTemplateId);
}
},
data() {
return {
htmlData: null,
imageCapturing: false,
testImage: null,
loadingSelectedTemplate: false,
editorConfig: {
fontSize: {
options: ["tiny", "default", "big", 9, 11, 13, 17, 19, 21],
},
},
showPreview: false,
dynamicFieldoptions: templateFields,
showDynamicFieldModal: false,
formvalidationMessages,
form: {
title: null,
description: null,
subject: null,
editorData: "<p>Content of the editor.</p>",
isPlainEmail: false,
plainEmailContent: "",
},
previewImage: null,
dfForm: {
field: null,
},
submitted: false,
dfFormSubmitted: false,
editor: ClassicEditor,
};
},
methods: {
clearfield() {
this.form.title = null;
(this.form.description = null),
(this.form.subject = null),
(this.form.editorData = "<p>Content of the editor.</p>"),
(this.form.isPlainEmail = false),
(this.form.plainEmailContent = "");
},
async getTemplateById(id) {
this.loadingSelectedTemplate = true;
const {
data: { data, message, success },
} = await EmailTemplateService.getEmailtemplatebyid(id);
if (!success) {
this.emit("errorMessage", message);
} else {
this.form.title = data.title;
this.form.description = data.description;
this.form.subject = data.subject;
this.form.editorData = data.isPlainEmail ? "" : data.content;
this.form.plainEmailContent = !data.isPlainEmail ? "" : data.content;
this.form.isPlainEmail = data.isPlainEmail;
}
this.loadingSelectedTemplate = false;
},
handleSubmit() {
this.dfFormSubmitted = true;
this.v$?.dfForm.$touch();
if (this.v$?.dfForm.$invalid) {
return;
}
this.showDynamicFieldModal = false;
if (this.form.isPlainEmail) {
this.form.plainEmailContent += this.dfForm.field.value;
} else {
const tasgAppendinline = ["</p>", "</span>", "</h1>"];
const htmlTagsInContent = this.form.editorData.match(
/<((?=!\-\-)!\-\-[\s\S]*\-\-|((?=\?)\?[\s\S]*\?|((?=\/)\/[^.\-\d][^\/\]'"[!#$%&()*+,;<=>?@^`{|}~ ]*|[^.\-\d][^\/\]'"[!#$%&()*+,;<=>?@^`{|}~ ]*(?:\s[^.\-\d][^\/\]'"[!#$%&()*+,;<=>?@^`{|}~ ]*(?:=(?:"[^"]*"|'[^']*'|[^'"<\s]*))?)*)\s?\/?))>/g
);
const lastElem = htmlTagsInContent[htmlTagsInContent.length - 1];
const tagAppendElement = _.find(tasgAppendinline, (e) => e === lastElem);
if (!this.dfForm.field.blockLevel && tagAppendElement) {
let data = this.form.editorData;
data = data.substr(0, data.length - tagAppendElement.length);
data += this.dfForm.field.value + tagAppendElement;
this.form.editorData = data;
} else {
this.form.editorData += this.dfForm.field.value;
}
}
this.dfForm.field = null;
this.dfFormSubmitted = false;
},
formSubmit() {
this.submitted = true;
this.v$?.form.$touch();
if (this.v$.form.$invalid) {
return;
}
this.imageCapturing = true;
this.htmlData = this.form.editorData;
},
getemalPreviewData() {
if (this.form.editorData.length === 0) {
return "";
}
let content = this.form.editorData;
_.forEach(this.dynamicFieldoptions, (e) => {
content = content.replace(e.value, e.dafaultPreviewData);
});
return content;
},
},
computed: {
renderImageUrl() {
if (this.previewImage == null) {
return null;
}
const image =
typeof this.previewImage === "object"
? URL.createObjectURL(this.previewImage)
: this.previewImage;
return image;
},
},
components: {
Multiselect,
PreviewEmail,
Loader,
BForm,
BFormGroup,
BFormInput,
BFormTextarea,
BFormRadioGroup,
BFormRadio,
BButton,
BModal,
ckeditor: CKEditor.component,
},
watch: {
AddUser: {
immediate: true,
handler(newVal) {
if (newVal) {
this.clearfield();
}
},
},
htmlData(v) {
if (v) {
const capture = this.$refs.capture;
domtoimage.toBlob(capture).then((blob) => {
this.imageCapturing = false;
this.htmlData = null;
this.previewImage = new File([blob], "my_image.png", {
type: "image/png",
lastModified: new Date().getTime(),
});
this.$emit("formSubmit", {
postData: this.form,
file: this.previewImage,
});
// const formData = new FormData();
// formData.append(
// 'data',
// JSON.stringify({
// ...this.form,
// }),
// );
// formData.append('file', this.previewImage);
// this.$emit('formSubmit', formData);
});
}
},
},
};
</script>