end merging easy and advanced format

This commit is contained in:
Jordan Blasenhauer 2024-07-22 16:52:14 +02:00
parent a2d6dfc129
commit 3540903f47
5 changed files with 273 additions and 903 deletions

View file

@ -11,7 +11,7 @@ import Text from "@components/Widget/Text.vue";
import Filter from "@components/Widget/Filter.vue";
import GroupMultiple from "@components/Forms/Group/Multiple.vue";
import { plugin_types } from "@utils/variables";
import { useAdvancedForm } from "@store/advanced.js";
import { useAdvancedForm } from "@store/form.js";
import { useCheckPluginsValidity } from "@utils/form.js";
import { v4 as uuidv4 } from "uuid";
/**

View file

@ -8,7 +8,7 @@ import Button from "@components/Widget/Button.vue";
import Text from "@components/Widget/Text.vue";
import { v4 as uuidv4 } from "uuid";
import { useCheckPluginsValidity } from "@utils/form.js";
import { useEasyForm } from "@store/easy.js";
import { useEasyForm } from "@store/form.js";
/**
@name Form/Easy.vue
@ -138,7 +138,7 @@ onUnmounted(() => {
<Title type="card" :title="'dashboard_easy_mode'" />
<Subtitle type="card" :subtitle="'dashboard_easy_mode_subtitle'" />
<template v-for="(step, id) in easyForm.templateUI">
<template v-for="(step, id) in easyForm.templateUIFormat">
<Container
data-is="content"
data-easy-form-step

View file

@ -1,285 +0,0 @@
import { defineStore } from "pinia";
import { ref } from "vue";
/**
@name useAdvancedForm
@description Store to share the template and others form data.
*/
export const useAdvancedForm = defineStore("advanced", () => {
// Default template, don't touch it. It will be used to reset the template.
const template = ref({});
// Base template will keep every data (data that doesn't need to be render on UI but need to be there for backend).
const templateBase = ref({});
// UI template will keep the data that will be render on UI.
const templateUI = ref({});
// UI template will keep the data that will be render on UI with additionnal format like filtering.
const templateUIFormat = ref({});
const updateCount = ref(0);
/**
@name setTemplate
@description Set the template we are going to use to generate the form and update it (like adding multiples).
@param template - Template with plugins list and detail settings
*/
function setTemplate(template) {
template.value = template;
templateBase.value = template;
templateUI.value = JSON.parse(JSON.stringify(template));
templateUIFormat.value = JSON.parse(JSON.stringify(template));
}
/**
@name delMultiple
@description This function will delete a group of multiples in the template.
The way the backend is working is that to delete a group, we need to send the group name with all default values.
This function needs to be call from the multiples component parent with the template and the group name to delete.
We will update the values of the group to default values.
@param pluginId - id of the plugin on the template array.
@param multName - Input id to update
@param groupName - Input value to update
*/
function delMultiple(pluginId, multName, groupName) {
// Get the index of plugin using pluginId
const index = templateBase.value.findIndex(
(plugin) => plugin.id === pluginId
);
// For back end, we need to keep the group but updating values to default in order to delete it
for (const [key, value] of Object.entries(
templateBase.value[index].multiples[multName][groupName]
)) {
value.value = value.default;
}
// For UI, we can delete the group to avoid rendering it
delete templateUI.value[index].multiples[multName][groupName];
updateCount.value++;
}
/**
@name addMultiple
@description This function will add a group of multiple in the template with default values.
Each plugin has a key "multiples_schema" with each multiples group and their default values.
We will retrieve the wanted multiple group and add it on the "multiples" key that contains the multiples that apply to the plugin.
@param pluginId - id of the plugin on the template array.
@param multName - multiple group name to add
*/
function addMultiple(pluginId, multName) {
// Get the index of plugin using pluginId
const index = templateBase.value.findIndex(
(plugin) => plugin.id === pluginId
);
// Get the right multiple schema
const multipleSchema = JSON.parse(
JSON.stringify(templateBase.value[index]?.multiples_schema[multName])
);
const newMultiple = {};
// Get the highest id in Object.keys(plugin?.multiples[multName])
const nextGroupId =
Math.max(...Object.keys(templateBase.value[index]?.multiples[multName])) +
1;
// Set the default values as value
for (const [key, value] of Object.entries(multipleSchema)) {
value.value = value.default;
newMultiple[`${key}${nextGroupId > 0 ? "_" + nextGroupId : ""}`] = value;
}
// Add new group as first key of plugin.multiples.multName
templateBase.value[index].multiples[multName][nextGroupId] = newMultiple;
// We need to show the new group on UI too
templateUI.value[index].multiples[multName][nextGroupId] = newMultiple;
updateCount.value++;
}
/**
@name useListenTempFields
@description This will add an handler to all needed event listeners to listen to input, select... fields in order to update the template settings.
@example
function hander(e) {
// some code before calling useUpdateTemp
if (!e.target.closest("[data-advanced-form-plugin]")) return;
useUpdateTemp(e, data.base);
}
*/
function useListenTempFields() {
window.addEventListener("input", useUpdateTemp);
window.addEventListener("change", useUpdateTemp);
window.addEventListener("click", useUpdateTemp);
}
/**
@name useUnlistenTempFields
@description This will stop listening to input, select... fields. Performance optimization and avoid duplicate calls conflicts.
@example
function hander(e) {
// some code before calling useUpdateTemp
if (!e.target.closest("[data-advanced-form-plugin]")) return;
useUpdateTemp(e, data.base);
}
*/
function useUnlistenTempFields() {
window.removeEventListener("change", useUpdateTemp);
window.removeEventListener("click", useUpdateTemp);
}
/**
@name useUpdateTemp
@description This function will check if the target is a setting input-like field.
In case it is, it will get the id and value for each field case, this will allow to update the template settings.
@example
template = [
{
name: "test",
settings: {
test: {
required: true,
value: "",
pattern: "^[a-zA-Z0-9]*$",
},
},
},
];
@param e - Event object, get it by default in the event listener.
@param templates - Array of templates to update
*/
function useUpdateTemp(e, templates) {
templates = [templateBase.value, templateUI.value];
// Filter to avoid multiple calls
if (!e.target.closest("[data-advanced-form-plugin]")) return;
if (e.type === "change" && e.target.tagName === "INPUT") return;
// Wait some ms that previous update logic is done like datepicker
setTimeout(() => {
let inpId, inpValue;
// Case target is input (a little different for datepicker)
if (e.target.tagName === "INPUT") {
inpId = e.target.id;
inpValue = e.target.hasAttribute("data-timestamp")
? e.target.getAttribute("data-timestamp")
: e.target.value;
}
// Case target is select
if (
e.target.closest("[data-field-container]") &&
e.target.hasAttribute("data-setting-id") &&
e.target.hasAttribute("data-setting-value")
) {
inpId = e.target.getAttribute("data-setting-id");
inpValue = e.target.getAttribute("data-setting-value");
}
// Case target is not an input-like
if (!inpId) return;
// update settings
useUpdateTempSettings(templates, inpId, inpValue, e.target);
useUpdateTempMultiples(templates, inpId, inpValue, e.target);
}, 50);
}
/**
@name useUpdateTempSettings
@description This function will loop on template settings in order to update the setting value.
This will check each plugin.settings (what I call regular) instead of other type of settings like multiples (in plugin.multiples).
This function needs to be call in useUpdateTemp.
@param templates - Templates array with plugins list and detail settings
@param inpId - Input id to update
@param inpValue - Input value to update
*/
function useUpdateTempSettings(templates, inpId, inpValue, target) {
// Case get data-group attribut, this is not a regular setting
if (target.closest("[data-group]")) return;
for (let i = 0; i < templates.length; i++) {
const template = templates[i];
// Try to update settings
let isSettingUpdated = false;
for (let i = 0; i < template.length; i++) {
const plugin = template[i];
const settings = plugin?.settings;
if (!settings) continue;
for (const [key, value] of Object.entries(settings)) {
if (value.id === inpId) {
value.value = inpValue;
isSettingUpdated = true;
break;
}
}
if (isSettingUpdated) break;
}
}
}
/**
@name useUpdateTempMultiples
@description This function will loop on template multiples in order to update the setting value.
This will check each plugin.multiples that can be found in the template.
This function needs to be call in useUpdateTemp.
@param templates - Templates array with plugins list and detail settings
@param inpId - Input id to update
@param inpValue - Input value to update
*/
function useUpdateTempMultiples(templates, inpId, inpValue, target) {
// Case get data-group attribut, this is not a regular setting
if (!target.closest("[data-group='multiple']")) return;
const multName =
target
.closest("[data-group='multiple']")
.getAttribute("data-mult-name") || "";
const groupName =
target
.closest("[data-group='multiple']")
.getAttribute("data-group-name") || "";
for (let i = 0; i < templates.length; i++) {
const template = templates[i];
// Check at the same time the inpId without prefix group he is part of
// And try to update an existing inpId
// Case we found the inpId, we update the value
// Case we didn't find existing inpId, we create a new one
let isSettingUpdated = false;
for (let i = 0; i < template.length; i++) {
const plugin = template[i];
const multiples = plugin?.multiples;
// Case no multiples, continue
if (!multiples || Object.keys(multiples).length <= 0) continue;
// Check if can find mult name in multiples
if (!(multName in multiples)) continue;
// Check if can find group name in multiples
if (!(groupName in multiples[multName])) continue;
const settings = multiples[multName][groupName];
for (const [key, value] of Object.entries(settings)) {
if (value.id !== inpId) continue;
value.value = inpValue;
isSettingUpdated = true;
break;
}
if (isSettingUpdated) break;
}
}
}
/**
@name $reset
@description Will reset the template to the original one using the default template. The default template need to be set once.
*/
function $reset() {
templateBase.value = template.value;
templateUI.value = template.value;
updateCount.value++;
}
return {
templateBase,
templateUI,
templateUIFormat,
setTemplate,
addMultiple,
delMultiple,
useListenTempFields,
useUnlistenTempFields,
$reset,
};
});

View file

@ -1,294 +0,0 @@
import { defineStore } from "pinia";
import { ref } from "vue";
/**
@name useEasyForm
@description Store to share the template and others form data.
*/
export const useEasyForm = defineStore("easy", () => {
// Default template, don't touch it. It will be used to reset the template.
const template = ref({});
// Base template will keep every data (data that doesn't need to be render on UI but need to be there for backend).
const templateBase = ref({});
// UI template will keep the data that will be render on UI.
const templateUI = ref({});
// UI template will keep the data that will be render on UI with additionnal format like filtering.
const templateUIFormat = ref({});
const updateCount = ref(0);
/**
@name setTemplate
@description Set the template we are going to use to generate the form and update it (like adding multiples).
@param template - Template with plugins list and detail settings
*/
function setTemplate(template) {
template.value = template;
templateBase.value = template;
templateUI.value = JSON.parse(JSON.stringify(template));
templateUIFormat.value = JSON.parse(JSON.stringify(template));
}
/**
@name delMultiple
@description This function will delete a group of multiples in the template.
The way the backend is working is that to delete a group, we need to send the group name with all default values.
This function needs to be call from the multiples component parent with the template and the group name to delete.
We will update the values of the group to default values.
@param pluginId - id of the plugin on the template array.
@param multName - Input id to update
@param groupName - Input value to update
*/
function delMultiple(pluginId, multName, groupName) {
// Get the index of plugin using pluginId
const index = templateBase.value.findIndex(
(plugin) => plugin.id === pluginId
);
// For back end, we need to keep the group but updating values to default in order to delete it
for (const [key, value] of Object.entries(
templateBase.value[index].multiples[multName][groupName]
)) {
value.value = value.default;
}
// For UI, we can delete the group to avoid rendering it
delete templateUI.value[index].multiples[multName][groupName];
updateCount.value++;
}
/**
@name addMultiple
@description This function will add a group of multiple in the template with default values.
Each plugin has a key "multiples_schema" with each multiples group and their default values.
We will retrieve the wanted multiple group and add it on the "multiples" key that contains the multiples that apply to the plugin.
@param pluginId - id of the plugin on the template array.
@param multName - multiple group name to add
*/
function addMultiple(pluginId, multName) {
// Get the index of plugin using pluginId
const index = templateBase.value.findIndex(
(plugin) => plugin.id === pluginId
);
// Get the right multiple schema
const multipleSchema = JSON.parse(
JSON.stringify(templateBase.value[index]?.multiples_schema[multName])
);
const newMultiple = {};
// Get the highest id in Object.keys(plugin?.multiples[multName])
const nextGroupId =
Math.max(...Object.keys(templateBase.value[index]?.multiples[multName])) +
1;
// Set the default values as value
for (const [key, value] of Object.entries(multipleSchema)) {
value.value = value.default;
newMultiple[`${key}${nextGroupId > 0 ? "_" + nextGroupId : ""}`] = value;
}
// Add new group as first key of plugin.multiples.multName
templateBase.value[index].multiples[multName][nextGroupId] = newMultiple;
// We need to show the new group on UI too
templateUI.value[index].multiples[multName][nextGroupId] = newMultiple;
updateCount.value++;
}
/**
@name useListenTempFields
@description This will add an handler to all needed event listeners to listen to input, select... fields in order to update the template settings.
@example
function hander(e) {
// some code before calling useUpdateTemp
if (!e.target.closest("[data-easy-form-plugin]")) return;
useUpdateTemp(e, data.base);
}
*/
function useListenTempFields() {
window.addEventListener("input", useUpdateTemp);
window.addEventListener("change", useUpdateTemp);
window.addEventListener("click", useUpdateTemp);
}
/**
@name useUnlistenTempFields
@description This will stop listening to input, select... fields. Performance optimization and avoid duplicate calls conflicts.
@example
function hander(e) {
// some code before calling useUpdateTemp
if (!e.target.closest("[data-easy-form-plugin]")) return;
useUpdateTemp(e, data.base);
}
*/
function useUnlistenTempFields() {
window.removeEventListener("change", useUpdateTemp);
window.removeEventListener("click", useUpdateTemp);
}
/**
@name useUpdateTemp
@description This function will check if the target is a setting input-like field.
In case it is, it will get the id and value for each field case, this will allow to update the template settings.
@example
template = [
{
name: "test",
settings: {
test: {
required: true,
value: "",
pattern: "^[a-zA-Z0-9]*$",
},
},
},
];
@param e - Event object, get it by default in the event listener.
@param templates - Array of templates to update
*/
function useUpdateTemp(e, templates) {
templates = [templateBase.value, templateUI.value];
// Avoid event that are not in the form
if (!e.target.closest("[data-easy-form]")) return;
// Avoid multiple calls on datepicker
if (e.type === "change" && e.target.tagName === "INPUT") return;
// Avoid multiple calls on checkbox
if (
e.type !== "input" &&
e.target.tagName === "INPUT" &&
e.target.type === "checkbox"
)
return;
// Wait some ms that previous update logic is done like datepicker
setTimeout(() => {
let inpId, inpValue;
// Case target is input (a little different for datepicker)
if (e.target.tagName === "INPUT") {
inpId = e.target.id;
inpValue = e.target.hasAttribute("data-timestamp")
? e.target.getAttribute("data-timestamp")
: e.target.value;
}
// Case target is select
if (
e.target.closest("[data-field-container]") &&
e.target.hasAttribute("data-setting-id") &&
e.target.hasAttribute("data-setting-value")
) {
inpId = e.target.getAttribute("data-setting-id");
inpValue = e.target.getAttribute("data-setting-value");
}
// Case target is not an input-like
if (!inpId) return;
// update settings
useUpdateTempSettings(templates, inpId, inpValue, e.target);
useUpdateTempMultiples(templates, inpId, inpValue, e.target);
}, 50);
}
/**
@name useUpdateTempSettings
@description This function will loop on template settings in order to update the setting value.
This will check each plugin.settings (what I call regular) instead of other type of settings like multiples (in plugin.multiples).
This function needs to be call in useUpdateTemp.
@param templates - Templates array with plugins list and detail settings
@param inpId - Input id to update
@param inpValue - Input value to update
*/
function useUpdateTempSettings(templates, inpId, inpValue, target) {
// Case get data-group attribut, this is not a regular setting
if (target.closest("[data-group]")) return;
for (let i = 0; i < templates.length; i++) {
const template = templates[i];
// Try to update settings
let isSettingUpdated = false;
for (let i = 0; i < template.length; i++) {
const plugin = template[i];
const settings = plugin?.settings;
if (!settings) continue;
for (const [key, value] of Object.entries(settings)) {
if (value.id === inpId) {
value.value = inpValue;
isSettingUpdated = true;
break;
}
}
if (isSettingUpdated) break;
}
}
}
/**
@name useUpdateTempMultiples
@description This function will loop on template multiples in order to update the setting value.
This will check each plugin.multiples that can be found in the template.
This function needs to be call in useUpdateTemp.
@param templates - Templates array with plugins list and detail settings
@param inpId - Input id to update
@param inpValue - Input value to update
*/
function useUpdateTempMultiples(templates, inpId, inpValue, target) {
// Case get data-group attribut, this is not a regular setting
if (!target.closest("[data-group='multiple']")) return;
const multName =
target
.closest("[data-group='multiple']")
.getAttribute("data-mult-name") || "";
const groupName =
target
.closest("[data-group='multiple']")
.getAttribute("data-group-name") || "";
for (let i = 0; i < templates.length; i++) {
const template = templates[i];
// Check at the same time the inpId without prefix group he is part of
// And try to update an existing inpId
// Case we found the inpId, we update the value
// Case we didn't find existing inpId, we create a new one
let isSettingUpdated = false;
for (let i = 0; i < template.length; i++) {
const plugin = template[i];
const multiples = plugin?.multiples;
// Case no multiples, continue
if (!multiples || Object.keys(multiples).length <= 0) continue;
// Check if can find mult name in multiples
if (!(multName in multiples)) continue;
// Check if can find group name in multiples
if (!(groupName in multiples[multName])) continue;
const settings = multiples[multName][groupName];
for (const [key, value] of Object.entries(settings)) {
if (value.id !== inpId) continue;
value.value = inpValue;
isSettingUpdated = true;
break;
}
if (isSettingUpdated) break;
}
}
}
/**
@name $reset
@description Will reset the template to the original one using the default template. The default template need to be set once.
*/
function $reset() {
templateBase.value = template.value;
templateUI.value = template.value;
updateCount.value++;
}
return {
templateBase,
templateUI,
templateUIFormat,
setTemplate,
addMultiple,
delMultiple,
useListenTempFields,
useUnlistenTempFields,
$reset,
};
});

View file

@ -2,349 +2,298 @@ import { defineStore } from "pinia";
import { ref } from "vue";
/**
@name Form
@description Class to share form utils functions. You need to send a template format to use it. You'll access to functions to update the template, reset it, add multiples, delete multiples...
@param type - Type of form (advanced, easy, raw). This will change some logic when calling functions.
@name createFormStore
@description This is a factory function that will create a form store.
This store contains all the logic to manage the form template and update it.
By defining the form type, this will update some function to avoid errors.
@param storeName - Name of the store, must be unique.
@param formType - Type of form, can be "advanced", "raw" or "easy".
*/
class Form {
constructor(
type,
template,
templateBase,
templateUI,
templateUIFormat,
updateCount
) {
this.type = type;
this.template = template;
this.templateBase = templateBase;
this.templateUI = templateUI;
this.templateUIFormat = templateUIFormat;
this.updateCount = updateCount;
}
/**
@name setTemplate
@description Set the template we are going to use to generate the form and update it (like adding multiples).
@param template - Template with plugins list and detail settings
*/
setTemplate(data) {
this.template.value = data;
this.templateBase.value = data;
this.templateUI.value = JSON.parse(JSON.stringify(data));
this.templateUIFormat.value = JSON.parse(JSON.stringify(data));
}
/**
@name _delMultiple
@description This function will delete a group of multiples in the template.
The way the backend is working is that to delete a group, we need to send the group name with all default values.
This function needs to be call from the multiples component parent with the template and the group name to delete.
We will update the values of the group to default values.
@param pluginId - id of the plugin on the template array.
@param multName - Input id to update
@param groupName - Input value to update
*/
_delMultiple(pluginId, multName, groupName) {
// Get the index of plugin using pluginId
const index = this.templateBase.value.findIndex(
(plugin) => plugin.id === pluginId
);
// For back end, we need to keep the group but updating values to default in order to delete it
for (const [key, value] of Object.entries(
this.templateBase.value[index].multiples[multName][groupName]
)) {
value.value = value.default;
export const createFormStore = (storeName, formType) => {
return defineStore(storeName, () => {
// Define the type of form we are going to use.
// This will change some logic.
const type = ref(formType);
// Default template, don't touch it. It will be used to reset the template.
const template = ref({});
// Base template will keep every data (data that doesn't need to be render on UI but need to be there for backend).
const templateBase = ref({});
// UI template will keep the data that will be render on UI.
const templateUI = ref({});
// UI template will keep the data that will be render on UI with additionnal format like filtering.
const templateUIFormat = ref({});
const updateCount = ref(0);
/**
@name setTemplate
@description Set the template we are going to use to generate the form and update it (like adding multiples).
@param template - Template with plugins list and detail settings
*/
function setTemplate(template) {
template.value = template;
templateBase.value = template;
templateUI.value = JSON.parse(JSON.stringify(template));
templateUIFormat.value = JSON.parse(JSON.stringify(template));
}
// For UI, we can delete the group to avoid rendering it
delete this.templateUI.value[index].multiples[multName][groupName];
this.updateCount.value++;
}
/**
@name delMultiple
@description This function will delete a group of multiples in the template.
The way the backend is working is that to delete a group, we need to send the group name with all default values.
This function needs to be call from the multiples component parent with the template and the group name to delete.
We will update the values of the group to default values.
@param pluginId - id of the plugin on the template array.
@param multName - Input id to update
@param groupName - Input value to update
*/
function delMultiple(pluginId, multName, groupName) {
// Get the index of plugin using pluginId
const index = templateBase.value.findIndex(
(plugin) => plugin.id === pluginId
);
/**
@name _addMultiple
@description This function will add a group of multiple in the template with default values.
Each plugin has a key "multiples_schema" with each multiples group and their default values.
We will retrieve the wanted multiple group and add it on the "multiples" key that contains the multiples that apply to the plugin.
@param pluginId - id of the plugin on the template array.
@param multName - multiple group name to add
*/
_addMultiple(pluginId, multName) {
// Get the index of plugin using pluginId
const index = this.templateBase.value.findIndex(
(plugin) => plugin.id === pluginId
);
// Get the right multiple schema
const multipleSchema = JSON.parse(
JSON.stringify(this.templateBase.value[index]?.multiples_schema[multName])
);
const newMultiple = {};
// For back end, we need to keep the group but updating values to default in order to delete it
for (const [key, value] of Object.entries(
templateBase.value[index].multiples[multName][groupName]
)) {
value.value = value.default;
}
// Get the highest id in Object.keys(plugin?.multiples[multName])
const nextGroupId =
Math.max(
...Object.keys(this.templateBase.value[index]?.multiples[multName])
) + 1;
// Set the default values as value
for (const [key, value] of Object.entries(multipleSchema)) {
value.value = value.default;
newMultiple[`${key}${nextGroupId > 0 ? "_" + nextGroupId : ""}`] = value;
// For UI, we can delete the group to avoid rendering it
delete templateUI.value[index].multiples[multName][groupName];
updateCount.value++;
}
// Add new group as first key of plugin.multiples.multName
this.templateBase.value[index].multiples[multName][nextGroupId] =
newMultiple;
// We need to show the new group on UI too
this.templateUI.value[index].multiples[multName][nextGroupId] = newMultiple;
this.updateCount.value++;
}
/**
@name useListenTempFields
@description This will add an handler to all needed event listeners to listen to input, select... fields in order to update the template settings.
@example
function hander(e) {
// some code before calling useUpdateTemp
if (!e.target.closest("[data-advanced-form-plugin]")) return;
useUpdateTemp(e, data.base);
}
*/
useListenTempFields() {
window.addEventListener("input", this._useUpdateTemp);
window.addEventListener("change", this._useUpdateTemp);
window.addEventListener("click", this._useUpdateTemp);
}
/**
@name addMultiple
@description This function will add a group of multiple in the template with default values.
Each plugin has a key "multiples_schema" with each multiples group and their default values.
We will retrieve the wanted multiple group and add it on the "multiples" key that contains the multiples that apply to the plugin.
@param pluginId - id of the plugin on the template array.
@param multName - multiple group name to add
*/
function addMultiple(pluginId, multName) {
// Get the index of plugin using pluginId
const index = templateBase.value.findIndex(
(plugin) => plugin.id === pluginId
);
// Get the right multiple schema
const multipleSchema = JSON.parse(
JSON.stringify(templateBase.value[index]?.multiples_schema[multName])
);
const newMultiple = {};
/**
@name useUnlistenTempFields
@description This will stop listening to input, select... fields. Performance optimization and avoid duplicate calls conflicts.
@example
function hander(e) {
// some code before calling useUpdateTemp
if (!e.target.closest("[data-advanced-form-plugin]")) return;
useUpdateTemp(e, data.base);
}
*/
useUnlistenTempFields() {
window.removeEventListener("change", this._useUpdateTemp);
window.removeEventListener("click", this._useUpdateTemp);
}
// Get the highest id in Object.keys(plugin?.multiples[multName])
const nextGroupId =
Math.max(
...Object.keys(templateBase.value[index]?.multiples[multName])
) + 1;
/**
@name _useUpdateTemp
@description This function will check if the target is a setting input-like field.
In case it is, it will get the id and value for each field case, this will allow to update the template settings.
@example
template = [
{
name: "test",
settings: {
test: {
required: true,
value: "",
pattern: "^[a-zA-Z0-9]*$",
// Set the default values as value
for (const [key, value] of Object.entries(multipleSchema)) {
value.value = value.default;
newMultiple[`${key}${nextGroupId > 0 ? "_" + nextGroupId : ""}`] =
value;
}
// Add new group as first key of plugin.multiples.multName
templateBase.value[index].multiples[multName][nextGroupId] = newMultiple;
// We need to show the new group on UI too
templateUI.value[index].multiples[multName][nextGroupId] = newMultiple;
updateCount.value++;
}
/**
@name useListenTempFields
@description This will add an handler to all needed event listeners to listen to input, select... fields in order to update the template settings.
@example
function hander(e) {
// some code before calling useUpdateTemp
if (!e.target.closest("[data-advanced-form-plugin]")) return;
useUpdateTemp(e, data.base);
}
*/
function useListenTempFields() {
window.addEventListener("input", useUpdateTemp);
window.addEventListener("change", useUpdateTemp);
window.addEventListener("click", useUpdateTemp);
}
/**
@name useUnlistenTempFields
@description This will stop listening to input, select... fields. Performance optimization and avoid duplicate calls conflicts.
@example
function hander(e) {
// some code before calling useUpdateTemp
if (!e.target.closest("[data-advanced-form-plugin]")) return;
useUpdateTemp(e, data.base);
}
*/
function useUnlistenTempFields() {
window.removeEventListener("change", useUpdateTemp);
window.removeEventListener("click", useUpdateTemp);
}
/**
@name useUpdateTemp
@description This function will check if the target is a setting input-like field.
In case it is, it will get the id and value for each field case, this will allow to update the template settings.
@example
template = [
{
name: "test",
settings: {
test: {
required: true,
value: "",
pattern: "^[a-zA-Z0-9]*$",
},
},
},
},
},
];
@param e - Event object, get it by default in the event listener.
@param templates - Array of templates to update
*/
_useUpdateTemp(e) {
const templates = [this.templateBase.value, this.templateUI.value];
// Filter to avoid multiple calls
if (
!e.target.closest("[data-advanced-form-plugin]") &&
this.type === "advanced"
)
return;
if (!e.target.closest("[data-easy-form]") && this.type === "easy") return;
if (e.type === "change" && e.target.tagName === "INPUT") return;
// Wait some ms that previous update logic is done like datepicker
setTimeout(() => {
let inpId, inpValue;
];
@param e - Event object, get it by default in the event listener.
@param templates - Array of templates to update
*/
function useUpdateTemp(e, templates) {
templates = [templateBase.value, templateUI.value];
// Filter to avoid multiple calls
if (!e.target.closest("[data-advanced-form-plugin]")) return;
if (e.type === "change" && e.target.tagName === "INPUT") return;
// Wait some ms that previous update logic is done like datepicker
setTimeout(() => {
let inpId, inpValue;
// Case target is input (a little different for datepicker)
if (e.target.tagName === "INPUT") {
inpId = e.target.id;
inpValue = e.target.hasAttribute("data-timestamp")
? e.target.getAttribute("data-timestamp")
: e.target.value;
// Case target is input (a little different for datepicker)
if (e.target.tagName === "INPUT") {
inpId = e.target.id;
inpValue = e.target.hasAttribute("data-timestamp")
? e.target.getAttribute("data-timestamp")
: e.target.value;
}
// Case target is select
if (
e.target.closest("[data-field-container]") &&
e.target.hasAttribute("data-setting-id") &&
e.target.hasAttribute("data-setting-value")
) {
inpId = e.target.getAttribute("data-setting-id");
inpValue = e.target.getAttribute("data-setting-value");
}
// Case target is not an input-like
if (!inpId) return;
// update settings
useUpdateTempSettings(templates, inpId, inpValue, e.target);
useUpdateTempMultiples(templates, inpId, inpValue, e.target);
}, 50);
}
/**
@name useUpdateTempSettings
@description This function will loop on template settings in order to update the setting value.
This will check each plugin.settings (what I call regular) instead of other type of settings like multiples (in plugin.multiples).
This function needs to be call in useUpdateTemp.
@param templates - Templates array with plugins list and detail settings
@param inpId - Input id to update
@param inpValue - Input value to update
*/
function useUpdateTempSettings(templates, inpId, inpValue, target) {
// Case get data-group attribut, this is not a regular setting
if (target.closest("[data-group]")) return;
for (let i = 0; i < templates.length; i++) {
const template = templates[i];
// Try to update settings
let isSettingUpdated = false;
for (let i = 0; i < template.length; i++) {
const plugin = template[i];
const settings = plugin?.settings;
if (!settings) continue;
for (const [key, value] of Object.entries(settings)) {
if (value.id === inpId) {
value.value = inpValue;
isSettingUpdated = true;
break;
}
}
if (isSettingUpdated) break;
}
}
}
// Case target is select
if (
e.target.closest("[data-field-container]") &&
e.target.hasAttribute("data-setting-id") &&
e.target.hasAttribute("data-setting-value")
) {
inpId = e.target.getAttribute("data-setting-id");
inpValue = e.target.getAttribute("data-setting-value");
}
/**
@name useUpdateTempMultiples
@description This function will loop on template multiples in order to update the setting value.
This will check each plugin.multiples that can be found in the template.
This function needs to be call in useUpdateTemp.
@param templates - Templates array with plugins list and detail settings
@param inpId - Input id to update
@param inpValue - Input value to update
*/
function useUpdateTempMultiples(templates, inpId, inpValue, target) {
// Case get data-group attribut, this is not a regular setting
if (!target.closest("[data-group='multiple']")) return;
const multName =
target
.closest("[data-group='multiple']")
.getAttribute("data-mult-name") || "";
const groupName =
target
.closest("[data-group='multiple']")
.getAttribute("data-group-name") || "";
// Case target is not an input-like
if (!inpId) return;
// update settings
_useUpdateTempSettings(templates, inpId, inpValue, e.target);
_useUpdateTempMultiples(templates, inpId, inpValue, e.target);
}, 50);
}
/**
@name _useUpdateTempSettings
@description This function will loop on template settings in order to update the setting value.
This will check each plugin.settings (what I call regular) instead of other type of settings like multiples (in plugin.multiples).
This function needs to be call in useUpdateTemp.
@param templates - Templates array with plugins list and detail settings
@param inpId - Input id to update
@param inpValue - Input value to update
*/
_useUpdateTempSettings(templates, inpId, inpValue, target) {
// Case get data-group attribut, this is not a regular setting
if (target.closest("[data-group]")) return;
for (let i = 0; i < templates.length; i++) {
const template = templates[i];
// Try to update settings
let isSettingUpdated = false;
for (let i = 0; i < template.length; i++) {
const plugin = template[i];
const settings = plugin?.settings;
if (!settings) continue;
for (const [key, value] of Object.entries(settings)) {
if (value.id === inpId) {
for (let i = 0; i < templates.length; i++) {
const template = templates[i];
// Check at the same time the inpId without prefix group he is part of
// And try to update an existing inpId
// Case we found the inpId, we update the value
// Case we didn't find existing inpId, we create a new one
let isSettingUpdated = false;
for (let i = 0; i < template.length; i++) {
const plugin = template[i];
const multiples = plugin?.multiples;
// Case no multiples, continue
if (!multiples || Object.keys(multiples).length <= 0) continue;
// Check if can find mult name in multiples
if (!(multName in multiples)) continue;
// Check if can find group name in multiples
if (!(groupName in multiples[multName])) continue;
const settings = multiples[multName][groupName];
for (const [key, value] of Object.entries(settings)) {
if (value.id !== inpId) continue;
value.value = inpValue;
isSettingUpdated = true;
break;
}
if (isSettingUpdated) break;
}
if (isSettingUpdated) break;
}
}
}
/**
@name _useUpdateTempMultiples
@description This function will loop on template multiples in order to update the setting value.
This will check each plugin.multiples that can be found in the template.
This function needs to be call in useUpdateTemp.
@param templates - Templates array with plugins list and detail settings
@param inpId - Input id to update
@param inpValue - Input value to update
*/
_useUpdateTempMultiples(templates, inpId, inpValue, target) {
// Case get data-group attribut, this is not a regular setting
if (!target.closest("[data-group='multiple']")) return;
const multName =
target
.closest("[data-group='multiple']")
.getAttribute("data-mult-name") || "";
const groupName =
target
.closest("[data-group='multiple']")
.getAttribute("data-group-name") || "";
for (let i = 0; i < templates.length; i++) {
const template = templates[i];
// Check at the same time the inpId without prefix group he is part of
// And try to update an existing inpId
// Case we found the inpId, we update the value
// Case we didn't find existing inpId, we create a new one
let isSettingUpdated = false;
for (let i = 0; i < template.length; i++) {
const plugin = template[i];
const multiples = plugin?.multiples;
// Case no multiples, continue
if (!multiples || Object.keys(multiples).length <= 0) continue;
// Check if can find mult name in multiples
if (!(multName in multiples)) continue;
// Check if can find group name in multiples
if (!(groupName in multiples[multName])) continue;
const settings = multiples[multName][groupName];
for (const [key, value] of Object.entries(settings)) {
if (value.id !== inpId) continue;
value.value = inpValue;
isSettingUpdated = true;
break;
}
if (isSettingUpdated) break;
}
/**
@name $reset
@description Will reset the template to the original one using the default template. The default template need to be set once.
*/
function $reset() {
templateBase.value = template.value;
templateUI.value = template.value;
updateCount.value++;
}
}
/**
@name $reset
@description Will reset the template to the original one using the default template. The default template need to be set once.
*/
$reset() {
this.templateBase.value = template.value;
this.templateUI.value = template.value;
this.updateCount.value++;
}
}
return {
templateBase,
templateUI,
templateUIFormat,
setTemplate,
addMultiple,
delMultiple,
useListenTempFields,
useUnlistenTempFields,
$reset,
};
});
};
/**
@name useAdvancedForm
@description Store to share the template and others form data.
*/
export const useAdvancedForm = defineStore("advanced", () => {
// Default template, don't touch it. It will be used to reset the template.
const template = ref({});
// Base template will keep every data (data that doesn't need to be render on UI but need to be there for backend).
const templateBase = ref({});
// UI template will keep the data that will be render on UI.
const templateUI = ref({});
// UI template will keep the data that will be render on UI with additionnal format like filtering.
const templateUIFormat = ref({});
const updateCount = ref(0);
const utils = new Form(
"advanced",
template,
templateBase,
templateUI,
templateUIFormat,
updateCount
);
return {
templateBase,
templateUI,
templateUIFormat,
utils,
};
});
/**
@name useEasyForm
@description Store to share the template and others form data.
*/
export const useEasyForm = defineStore("easy", () => {
// Default template, don't touch it. It will be used to reset the template.
const template = ref({});
// Base template will keep every data (data that doesn't need to be render on UI but need to be there for backend).
const templateBase = ref({});
// UI template will keep the data that will be render on UI.
const templateUI = ref({});
// UI template will keep the data that will be render on UI with additionnal format like filtering.
const templateUIFormat = ref({});
const updateCount = ref(0);
const utils = new Form(
"easy",
template,
templateBase,
templateUI,
templateUIFormat,
updateCount
);
return {
templateBase,
templateUI,
templateUIFormat,
utils,
};
});
export const useAdvancedForm = createFormStore("advanced", "advanced");
export const useEasyForm = createFormStore("easy", "easy");