446 lines
12 KiB
Vue
446 lines
12 KiB
Vue
![]() |
<template>
|
||
|
<div class="container-fluid">
|
||
|
<div class="row justify-content-center">
|
||
|
<template v-if="canView">
|
||
|
<!--start: show content if user entered the from title or is edit mode -->
|
||
|
<div v-if="isFormTitleEntered" class="col">
|
||
|
<h5 class="mb-4">
|
||
|
{{ keyValue?.value ?? "عنوان فرم وارد نشده است." }}
|
||
|
|
||
|
<button-component
|
||
|
classes="d-inline-flex"
|
||
|
@click="openNewFormModal"
|
||
|
buttonText=""
|
||
|
>
|
||
|
<span class="tavasi tavasi-Component-242--1"></span>
|
||
|
</button-component>
|
||
|
</h5>
|
||
|
|
||
|
<div class="row no-gutters justify-content-center">
|
||
|
<div class="col">
|
||
|
<div class="list-and-actions-container">
|
||
|
<!-- load Simple/Tab component -->
|
||
|
<keep-alive>
|
||
|
<component
|
||
|
:ref="formMode"
|
||
|
:is="formMode"
|
||
|
:formTitleData="form"
|
||
|
:newFormItem="newFormItem"
|
||
|
@open-new-form-item="openNewFormItem"
|
||
|
></component>
|
||
|
</keep-alive>
|
||
|
|
||
|
<!--start: form actions ( save/preview form) -->
|
||
|
<div class="d-flex justify-content-end mt-5 ms-3 form-actions">
|
||
|
<button-component
|
||
|
classes="btn btn-secondary mx-2"
|
||
|
@click="showFormPreView"
|
||
|
buttonText="پیش نمایش فرم"
|
||
|
>
|
||
|
</button-component>
|
||
|
|
||
|
<button-component
|
||
|
classes="btn btn-primary"
|
||
|
@click="saveFinalForm"
|
||
|
buttonText="ذخیره"
|
||
|
>
|
||
|
</button-component>
|
||
|
</div>
|
||
|
<!--end: form actions ( save/preview form) -->
|
||
|
</div>
|
||
|
</div>
|
||
|
<!-- start: create new form element -->
|
||
|
<div class="col-auto" v-if="showNewFormItem">
|
||
|
<new-form-item
|
||
|
:key="changeDetectionCounter"
|
||
|
@close-new-form-item="closeNewFormItem"
|
||
|
@add-item-content="addFormItemToFormElements"
|
||
|
:editFormData="editFormData"
|
||
|
></new-form-item>
|
||
|
</div>
|
||
|
<!-- end: create new form element -->
|
||
|
</div>
|
||
|
</div>
|
||
|
<!--end: show content if user entered the from title or is edit mode -->
|
||
|
</template>
|
||
|
<no-data v-else>
|
||
|
<the-content-loading v-if="fetchingData"></the-content-loading>
|
||
|
|
||
|
<div v-else class="d-flex justify-content-center align-items-center">
|
||
|
<div
|
||
|
class="alert alert-warning d-flex justify-content-center align-items-center"
|
||
|
>
|
||
|
<span
|
||
|
class="tavasi tavasi-warning-circle color-inherit ms-1 text__32"
|
||
|
></span>
|
||
|
عدم دسترسی
|
||
|
</div>
|
||
|
</div>
|
||
|
</no-data>
|
||
|
</div>
|
||
|
|
||
|
<!-- create new form modal -->
|
||
|
<base-modal
|
||
|
v-if="showNewFormTitleModal"
|
||
|
modalSize="modal-md"
|
||
|
modalTitle="فرم جدید"
|
||
|
@close="closeFormModal"
|
||
|
@save="saveFormTitle"
|
||
|
>
|
||
|
<form-builder
|
||
|
ref="titleFormBuilder"
|
||
|
:formElements="formItem"
|
||
|
:formData="form"
|
||
|
></form-builder>
|
||
|
</base-modal>
|
||
|
|
||
|
<!--form preview modal -->
|
||
|
<base-modal
|
||
|
v-if="showPreviewModal"
|
||
|
:showSaveButton="false"
|
||
|
modalSize="modal-lg"
|
||
|
modalTitle="فرم پیش نمایش"
|
||
|
@close="closePreviewModal"
|
||
|
@save="saveFinalForm"
|
||
|
>
|
||
|
<!-- displayMode : horizontal | vertical -->
|
||
|
<form-builder
|
||
|
ref="previewFormBuilder"
|
||
|
displayMode="horizontal"
|
||
|
:formElements="previewFormItems"
|
||
|
:formData="previewFormItemsData"
|
||
|
></form-builder>
|
||
|
</base-modal>
|
||
|
</div>
|
||
|
</template>
|
||
|
<script>
|
||
|
import keyValueApi from "@apis/keyValueApi";
|
||
|
import HttpService from "@services/httpService";
|
||
|
import { mapActions } from "vuex";
|
||
|
|
||
|
export default {
|
||
|
name: "newForm",
|
||
|
setup() {
|
||
|
definePageMeta({
|
||
|
name: "newForm",
|
||
|
});
|
||
|
},
|
||
|
beforeMount() {
|
||
|
this.httpService = new HttpService();
|
||
|
},
|
||
|
mounted() {
|
||
|
this.checkPermisionBeforGetList();
|
||
|
},
|
||
|
data() {
|
||
|
return {
|
||
|
canView: false,
|
||
|
changeDetectionCounter: 0,
|
||
|
isFormTitleEntered: false,
|
||
|
|
||
|
fetchingData: false,
|
||
|
httpService: undefined,
|
||
|
|
||
|
// show/hide preview modal
|
||
|
showPreviewModal: false,
|
||
|
previewFormItems: [],
|
||
|
previewFormItemsData: {},
|
||
|
|
||
|
// show/hide new form title
|
||
|
showNewFormTitleModal: false,
|
||
|
|
||
|
showNewFormItem: false,
|
||
|
newFormItem: undefined,
|
||
|
|
||
|
formMode: "SimpleForm",
|
||
|
// formMode: "TabForm",
|
||
|
// store form-item when user clicked on the table edit button in the simple/tab.
|
||
|
editFormData: undefined,
|
||
|
changeDetection: true,
|
||
|
|
||
|
// form model.
|
||
|
form: {
|
||
|
title: "",
|
||
|
comment: null,
|
||
|
type: 1,
|
||
|
},
|
||
|
keyValue: {
|
||
|
key: "",
|
||
|
value: "",
|
||
|
value_json: null,
|
||
|
project_id: 0,
|
||
|
organ_code: 0,
|
||
|
},
|
||
|
// FormItem model.
|
||
|
formItem: {
|
||
|
title: "",
|
||
|
items: [
|
||
|
{
|
||
|
key: "title",
|
||
|
label: "عنوان",
|
||
|
type: "string",
|
||
|
placeholder: "عنوان را وارد کنید",
|
||
|
required: "1",
|
||
|
validation_regex: "{3-100}",
|
||
|
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
|
||
|
multi_select: "0",
|
||
|
options: [],
|
||
|
},
|
||
|
{
|
||
|
key: "comment",
|
||
|
label: "توضیحات",
|
||
|
type: "textarea",
|
||
|
placeholder: "توضیحات را وارد کنید",
|
||
|
required: "1",
|
||
|
validation_regex: "{3-100}",
|
||
|
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
|
||
|
multi_select: "0",
|
||
|
options: [],
|
||
|
},
|
||
|
{
|
||
|
key: "type",
|
||
|
label: "نوع",
|
||
|
type: "select",
|
||
|
placeholder: "نوع را وارد کنید",
|
||
|
required: "1",
|
||
|
validation_regex: "{3-100}",
|
||
|
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
|
||
|
multi_select: "0",
|
||
|
options: [
|
||
|
{
|
||
|
value: 1,
|
||
|
title: "فرم ساده",
|
||
|
},
|
||
|
{
|
||
|
value: 2,
|
||
|
title: "فرم چند بخشی",
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
};
|
||
|
},
|
||
|
methods: {
|
||
|
...mapActions(["checkPermissions"]),
|
||
|
checkPermisionBeforGetList() {
|
||
|
const isEditMode = Boolean(this.$route.params.id);
|
||
|
this.checkPermissions({
|
||
|
permission: isEditMode ? "forms_edit" : "forms_new",
|
||
|
_this: this,
|
||
|
})
|
||
|
.then(() => {
|
||
|
if (this.$route.params.id) {
|
||
|
this.getForm(this.$route.params.id)
|
||
|
.then(() => {
|
||
|
this.canView = true;
|
||
|
})
|
||
|
.catch(() => {
|
||
|
this.canView = false;
|
||
|
})
|
||
|
.finally(() => {
|
||
|
this.fetchingData = false;
|
||
|
});
|
||
|
} else this.openNewFormModal();
|
||
|
})
|
||
|
.catch(() => {
|
||
|
this.canView = false;
|
||
|
});
|
||
|
},
|
||
|
/*
|
||
|
summary: save final form
|
||
|
|
||
|
description: saving the edited/created form with its meta and table_columns.
|
||
|
|
||
|
@fires when user clicks on the save button.
|
||
|
|
||
|
@return void.
|
||
|
*/
|
||
|
saveFinalForm() {
|
||
|
if (this.buttonLoading) return;
|
||
|
this.buttonLoading = true;
|
||
|
|
||
|
const url =
|
||
|
this.keyValueMicroServiceName + this.$route.params.id
|
||
|
? keyValueApi.forms.edit
|
||
|
: keyValueApi.forms.add;
|
||
|
|
||
|
// const formData = this.$refs[this.formMode].localMainFormElements;
|
||
|
const formData = {};
|
||
|
|
||
|
formData.value = this.form.title;
|
||
|
formData.value_json = {
|
||
|
type: this.formMode == "SimpleForm" ? 1 : 2,
|
||
|
table_columns: JSON.stringify(formData.table_columns),
|
||
|
form: JSON.stringify(this.$refs[this.formMode].localMainFormElements),
|
||
|
};
|
||
|
// formData.table_columns = null;
|
||
|
// formData.table_columns = JSON.stringify(formData.table_columns);
|
||
|
|
||
|
this.httpService
|
||
|
.postRequest(url, formData)
|
||
|
.then((res) => {
|
||
|
this.mySwalToast({
|
||
|
title: res.message,
|
||
|
html: null,
|
||
|
icon: "success",
|
||
|
});
|
||
|
this.form.meta = JSON.parse(this.form.meta);
|
||
|
this.form.table_columns = JSON.parse(this.form.table_columns);
|
||
|
})
|
||
|
|
||
|
.finally(() => {
|
||
|
this.buttonLoading = false;
|
||
|
});
|
||
|
},
|
||
|
showFormPreView() {
|
||
|
this.previewFormItems = this.$refs[this.formMode].localMainFormElements;
|
||
|
this.showPreviewModal = true;
|
||
|
|
||
|
setTimeout(() => {
|
||
|
$("#base-modal").modal({ backdrop: "static", keyboard: false }, "show");
|
||
|
}, 500);
|
||
|
},
|
||
|
// close preview modal
|
||
|
closePreviewModal() {
|
||
|
$("#base-modal").modal("hide");
|
||
|
|
||
|
setTimeout(() => {
|
||
|
this.showPreviewModal = false;
|
||
|
}, 500);
|
||
|
},
|
||
|
|
||
|
// open new form modal
|
||
|
openNewFormModal() {
|
||
|
this.showNewFormTitleModal = true;
|
||
|
setTimeout(() => {
|
||
|
$("#base-modal").modal({ backdrop: "static", keyboard: false }, "show");
|
||
|
}, 500);
|
||
|
},
|
||
|
// close new form modal
|
||
|
closeFormModal() {
|
||
|
if (!this.$route.params.id) this.$router.push({ name: "formList" });
|
||
|
|
||
|
$("#base-modal").modal("hide");
|
||
|
|
||
|
setTimeout(() => {
|
||
|
this.showNewFormTitleModal = false;
|
||
|
}, 500);
|
||
|
},
|
||
|
// get form details
|
||
|
async getForm(formId) {
|
||
|
if (this.fetchingData) return;
|
||
|
this.fetchingData = true;
|
||
|
|
||
|
const url = this.keyValueMicroServiceName + keyValueApi.forms.get;
|
||
|
return await this.httpService
|
||
|
.getRequest(url + "/" + formId)
|
||
|
.then((res) => {
|
||
|
this.keyValue = res.data;
|
||
|
// this.form.type = "TabForm";
|
||
|
// this.openNewFormModal();
|
||
|
|
||
|
this.form.title = this.keyValue.value;
|
||
|
|
||
|
let meta = JSON.parse(this.keyValue.value_json);
|
||
|
this.form.table_columns = meta.table_columns;
|
||
|
this.form.meta = meta.form;
|
||
|
|
||
|
if (meta.type == 1) this.formMode = "SimpleForm";
|
||
|
else if (meta.type == 2) this.formMode = "TabForm";
|
||
|
|
||
|
this.isFormTitleEntered = true;
|
||
|
});
|
||
|
},
|
||
|
// save new form title
|
||
|
saveFormTitle() {
|
||
|
if (this.buttonLoading) return;
|
||
|
this.buttonLoading = true;
|
||
|
|
||
|
this.form = this.$refs.titleFormBuilder.localFormData;
|
||
|
const url =
|
||
|
this.keyValueMicroServiceName + this.$route.params.id
|
||
|
? keyValueApi.forms.edit
|
||
|
: keyValueApi.forms.add;
|
||
|
|
||
|
const { title, comment, id = undefined, type } = this.form;
|
||
|
const formData = {
|
||
|
title,
|
||
|
comment,
|
||
|
id,
|
||
|
type,
|
||
|
};
|
||
|
|
||
|
this.httpService
|
||
|
.postRequest(url, formData)
|
||
|
.then((res) => {
|
||
|
this.mySwalToast({
|
||
|
title: "تبریک",
|
||
|
html: res.message,
|
||
|
icon: "success",
|
||
|
});
|
||
|
|
||
|
this.form = res.data;
|
||
|
|
||
|
this.form.meta = this.form.meta ? JSON.parse(this.form.meta) : null;
|
||
|
this.form.table_columns = this.form.table_columns
|
||
|
? JSON.parse(this.form.table_columns)
|
||
|
: null;
|
||
|
|
||
|
if (type == 1) this.formMode = "SimpleForm";
|
||
|
else if (type == 2) this.formMode = "TabForm";
|
||
|
|
||
|
this.isFormTitleEntered = true;
|
||
|
|
||
|
this.closeFormModal();
|
||
|
})
|
||
|
|
||
|
.finally(() => {
|
||
|
this.buttonLoading = false;
|
||
|
});
|
||
|
},
|
||
|
|
||
|
// new form item methods
|
||
|
addFormItemToFormElements(newFormItem) {
|
||
|
this.newFormItem = structuredClone(newFormItem);
|
||
|
},
|
||
|
// open new form item panel
|
||
|
openNewFormItem(data = undefined) {
|
||
|
this.showNewFormItem = true;
|
||
|
this.editFormData = data;
|
||
|
this.changeDetectionCounter += 1;
|
||
|
},
|
||
|
// close new form item panel
|
||
|
closeNewFormItem() {
|
||
|
this.showNewFormItem = false;
|
||
|
},
|
||
|
},
|
||
|
components: {
|
||
|
NewFormItem: () =>
|
||
|
import(
|
||
|
"@forms/forms/NewFormItem.vue"
|
||
|
),
|
||
|
SimpleForm: () =>
|
||
|
import(
|
||
|
"@forms/components/SimpleForm.vue"
|
||
|
),
|
||
|
TabForm: () =>
|
||
|
import( "@forms/components/TabForm.vue"),
|
||
|
|
||
|
},
|
||
|
};
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss">
|
||
|
.list-and-actions-container {
|
||
|
position: relative;
|
||
|
|
||
|
.form-actions {
|
||
|
// position: absolute;
|
||
|
// bottom: 1em;
|
||
|
// left: 2em;
|
||
|
|
||
|
background-image: linear-gradient(to bottom, transparent, #fff);
|
||
|
}
|
||
|
}
|
||
|
</style>
|