459 lines
13 KiB
Vue
459 lines
13 KiB
Vue
<template>
|
|
<NuxtLayout name="default" :menu="adminMenu">
|
|
<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">
|
|
<NewFormItem
|
|
:key="changeDetectionCounter"
|
|
@close-new-form-item="closeNewFormItem"
|
|
@add-item-content="addFormItemToFormElements"
|
|
:editFormData="editFormData"
|
|
></NewFormItem>
|
|
</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>
|
|
</NuxtLayout>
|
|
</template>
|
|
<script>
|
|
import keyValueApi from "~/apis/keyValueApi";
|
|
import adminMenu from "~/json/admin/json/menu.json";
|
|
// import HttpService from "@services/httpService";
|
|
// import { mapActions } from "vuex";
|
|
import { mapState, mapActions } from "pinia";
|
|
import { useCommonStore } from "~/stores/commonStore";
|
|
import { defineAsyncComponent } from "vue";
|
|
|
|
export default {
|
|
name: "newForm",
|
|
setup() {
|
|
definePageMeta({
|
|
name: "newForm",
|
|
layout: false,
|
|
});
|
|
},
|
|
beforeMount() {
|
|
// this.httpService = new HttpService();
|
|
this.httpService = useNuxtApp()["$http"];
|
|
},
|
|
mounted() {
|
|
this.checkPermisionBeforGetList();
|
|
},
|
|
data() {
|
|
return {
|
|
adminMenu: adminMenu,
|
|
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"]),
|
|
...mapActions(useCommonStore, ["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.keyValueUrl() + 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) => {
|
|
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.keyValueUrl()+ 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.keyValueUrl() + 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) => {
|
|
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"),
|
|
TabForm: defineAsyncComponent(() =>
|
|
import("@/components/admin/components/TabForm.vue")
|
|
),
|
|
SimpleForm: defineAsyncComponent(() =>
|
|
import("@/components/admin/components/SimpleForm.vue")
|
|
),
|
|
NewFormItem: defineAsyncComponent(() =>
|
|
import("@/components/admin/components/NewFormItem.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>
|