started multiple settings with simple method

* update template to render base multiple setting
* add and remove multiple setting from simple mode working
* update Multiple class to avoid conflict between advance mode form and simple mode form
This commit is contained in:
Jordan Blasenhauer 2024-04-23 17:05:58 +02:00
parent 8b1e543d02
commit 8663d239e3
3 changed files with 116 additions and 71 deletions

View file

@ -915,10 +915,10 @@ class ServiceModal {
}
class Multiple {
constructor(prefix) {
constructor(prefix, formContainerSelector) {
this.prefix = prefix;
this.container = document.querySelector("main");
this.modalForm = document.querySelector(`[data-${this.prefix}-modal-form]`);
this.formContainer = document.querySelector(formContainerSelector);
this.init();
}
@ -931,17 +931,19 @@ class Multiple {
//edit service button
try {
if (
e.target.closest("button").getAttribute("data-services-action") ===
"edit" ||
e.target.closest("button").getAttribute("data-services-action") ===
"clone"
e.target
.closest("button")
.getAttribute(`data-${this.prefix}-action`) === "edit" ||
e.target
.closest("button")
.getAttribute(`data-${this.prefix}-action`) === "clone"
) {
//remove all multiples
this.removePrevMultiples();
//get multiple service values and parse as obj
const servicesSettings = e.target
.closest("[data-services-service]")
.querySelector("[data-services-settings]")
.closest(`[data-${this.prefix}-service]`)
.querySelector(`[data-${this.prefix}-settings]`)
.getAttribute("data-value");
const obj = JSON.parse(servicesSettings);
//keep only multiple settings value
@ -950,8 +952,9 @@ class Multiple {
this.sortMultipleByContainerAndSuffixe(multipleSettings);
// Need to set method as ui if clone
const isClone =
e.target.closest("button").getAttribute("data-services-action") ===
"clone"
e.target
.closest("button")
.getAttribute(`data-${this.prefix}-action`) === "clone"
? true
: false;
@ -961,8 +964,9 @@ class Multiple {
//new service button
try {
if (
e.target.closest("button").getAttribute("data-services-action") ===
"new"
e.target
.closest("button")
.getAttribute(`data-${this.prefix}-action`) === "new"
) {
this.removePrevMultiples();
this.addOneMultGroup();
@ -970,7 +974,7 @@ class Multiple {
} catch (err) {}
});
this.modalForm.addEventListener("click", (e) => {
this.formContainer.addEventListener("click", (e) => {
//ADD BTN
try {
if (
@ -982,7 +986,7 @@ class Multiple {
const btn = e.target.closest("button");
const attName = btn.getAttribute(`data-${this.prefix}-multiple-add`);
//get all multiple groups
const multipleEls = document.querySelectorAll(
const multipleEls = this.formContainer.querySelectorAll(
`[data-${this.prefix}-settings-multiple*="${attName}"]`,
);
//case no schema
@ -995,7 +999,7 @@ class Multiple {
//and keep the highest num
multipleEls.forEach((container) => {
const ctnrName = container.getAttribute(
"data-services-settings-multiple",
`data-${this.prefix}-settings-multiple`,
);
const num = this.getSuffixNumOrFalse(ctnrName);
if (!isNaN(num) && num > topNum) topNum = num;
@ -1005,11 +1009,12 @@ class Multiple {
const currNum = `${multipleEls.length >= 2 ? topNum + 1 : topNum}`;
const setNum = +currNum === 0 ? `` : `_${currNum}`;
//the default (schema) group is the last group
const schema = document.querySelector(
const schema = this.formContainer.querySelector(
`[data-${this.prefix}-settings-multiple="${attName}_SCHEMA"]`,
);
//clone schema to create a group with new num
const schemaClone = schema.cloneNode(true);
//add special attribute for disabled logic
this.changeCloneSuffix(schemaClone, setNum);
//set disabled / enabled state
@ -1087,7 +1092,7 @@ class Multiple {
.setAttribute("data-value", defaultVal);
select.querySelector("data-setting-select-text").textContent =
defaultVal;
const dropdown = document.querySelector(
const dropdown = this.formContainer.querySelector(
`[data-setting-select-dropdown="${select.getAttribute(
"data-setting-select",
)}"]`,
@ -1114,14 +1119,15 @@ class Multiple {
const nameSuffixLess = isSuffixe
? name.replace(`_${splitName[splitName.length - 1]}`, "").trim()
: name.trim();
const relateSetting = document.querySelector(
const relateSetting = this.formContainer.querySelector(
`[data-setting-container=${nameSuffixLess}_SCHEMA]`,
);
if (!relateSetting) continue;
const relateCtnr = relateSetting.closest(
"[data-services-settings-multiple]",
`[data-${this.prefix}-settings-multiple]`,
);
const relateCtnrName = relateCtnr.getAttribute(
"data-services-settings-multiple",
`data-${this.prefix}-settings-multiple`,
);
//then we sort the setting on the right container name by suffixe number
if (!(relateCtnrName in sortMultiples)) {
@ -1137,29 +1143,30 @@ class Multiple {
}
addOneMultGroup() {
const settings = document.querySelector("[data-services-modal-form]");
const multAddBtns = settings.querySelectorAll(
"[data-services-multiple-add]",
const multAddBtns = this.formContainer.querySelectorAll(
`[data-${this.prefix}-multiple-add]`,
);
multAddBtns.forEach((btn) => {
//check if already one (SCHEMA exclude so length >= 2)
const plugin = btn.closest("[data-plugin-item]");
if (
plugin.querySelectorAll("[data-services-settings-multiple]").length >= 2
plugin.querySelectorAll(`[data-${this.prefix}-settings-multiple]`)
.length >= 2
)
return;
btn.click();
});
}
showMultByAtt(att) {
const multContainers = document.querySelectorAll(
`[data-services-settings-multiple^=${att}]`,
const multContainers = this.formContainer.querySelectorAll(
`[data-${this.prefix}-settings-multiple^=${att}]`,
);
multContainers.forEach((container) => {
if (
!container
.getAttribute("data-services-settings-multiple")
.getAttribute(`data-${this.prefix}-settings-multiple`)
.includes("SCHEMA")
)
container.classList.remove("hidden");
@ -1167,13 +1174,13 @@ class Multiple {
}
toggleMultByAtt(att) {
const multContainers = document.querySelectorAll(
`[data-services-settings-multiple^=${att}]`,
const multContainers = this.formContainer.querySelectorAll(
`[data-${this.prefix}-settings-multiple^=${att}]`,
);
multContainers.forEach((container) => {
if (
!container
.getAttribute("data-services-settings-multiple")
.getAttribute(`data-${this.prefix}-settings-multiple`)
.includes("SCHEMA")
)
container.classList.toggle("hidden");
@ -1183,7 +1190,7 @@ class Multiple {
getMultiplesOnly(settings) {
//get schema settings
const multiples = {};
const schemaSettings = document.querySelectorAll(
const schemaSettings = this.formContainer.querySelectorAll(
`[data-setting-container$="SCHEMA"]`,
);
// loop on every schema settings
@ -1213,8 +1220,8 @@ class Multiple {
sortMultObj,
)) {
//we need to access the DOM schema container
const schemaCtnr = document.querySelector(
`[data-services-settings-multiple="${schemaCtnrName}"]`,
const schemaCtnr = this.formContainer.querySelector(
`[data-${this.prefix}-settings-multiple="${schemaCtnrName}"]`,
);
//now we have to loop on each multiple settings group
for (const [suffix, settings] of Object.entries(multGroupBySuffix)) {
@ -1249,9 +1256,9 @@ class Multiple {
changeCloneSuffix(schemaCtnrClone, suffix) {
//rename multiple container
schemaCtnrClone.setAttribute(
"data-services-settings-multiple",
`data-${this.prefix}-settings-multiple`,
schemaCtnrClone
.getAttribute("data-services-settings-multiple")
.getAttribute(`data-${this.prefix}-settings-multiple`)
.replace("_SCHEMA", suffix),
);
@ -1401,7 +1408,7 @@ class Multiple {
.click();
//set state to custom visible el
const btnCustom = document.querySelector(
const btnCustom = this.formContainer.querySelector(
`[data-setting-select=${select.getAttribute(
"data-setting-select-default",
)}]`,
@ -1440,10 +1447,10 @@ class Multiple {
selects.forEach((select) => {
const method = select.getAttribute("data-default-method");
const name = select.getAttribute(
"data-services-setting-select-default",
`data-${this.prefix}-setting-select-default`,
);
const selDOM = document.querySelector(
`button[data-services-setting-select='${name}']`,
const selDOM = this.formContainer.querySelector(
`button[data-${this.prefix}-setting-select='${name}']`,
);
if (method === "ui" || method === "default") {
selDOM.removeAttribute("disabled", "");
@ -1477,7 +1484,7 @@ class Multiple {
hiddenIfNoMultiples() {
//hide multiple btn if no multiple exist on a plugin
const multiples = document.querySelectorAll(
const multiples = this.formContainer.querySelectorAll(
`[data-${this.prefix}-settings-multiple]`,
);
multiples.forEach((container) => {
@ -1489,13 +1496,13 @@ class Multiple {
}
removePrevMultiples() {
const multiPlugins = document.querySelectorAll(
const multiPlugins = this.formContainer.querySelectorAll(
`[data-${this.prefix}-settings-multiple]`,
);
multiPlugins.forEach((multiGrp) => {
if (
!multiGrp
.getAttribute("data-services-settings-multiple")
.getAttribute(`data-${this.prefix}-settings-multiple`)
.includes("SCHEMA")
)
multiGrp.remove();
@ -1838,7 +1845,14 @@ const setFilterGlobal = new FilterSettings(
"services",
);
const setMultiple = new Multiple("services");
const setAdvancedMultiple = new Multiple(
"services",
`[data-advanced][data-services-modal-form]`,
);
const setSimpleMultiple = new Multiple(
"services",
`[data-simple][data-services-modal-form]`,
);
const checkServiceModalKeyword = new CheckNoMatchFilter(
document.querySelector("input#settings-filter"),

View file

@ -1,12 +1,34 @@
{% set security_levels = ['standard', 'advanced', 'high'] %}
{# When multiple, setting_id need to be a setting that is part of a multiple to get all settings on the same group #}
{# On levels, we should set a list of dict with setting_id as key and value as value #}
{% set steps = [
{
"name" : "STEP 1 - STARTING UP",
"description" : "we need some information to get started.",
"settings" : [
{"plugin_id" : "general", "setting_id": "SERVER_NAME", "title" : "DEFINE HOST", "subtitle" : "We need this to connect BunkerWeb to your application. You need to set your domain name.", "levels" : {} },
{"plugin_id" : "security-level", "setting_id": "SECURITY_LEVEL", "title" : "DEFINE SECURITY LEVEL", "subtitle" : "This will determine default settings value for the next steps. You'll be allow to modify settings to match your case if needed.", "levels" : {}, "setting" : {'context': 'global', 'default': 'standard', 'help': 'Determine the default settings value. You can override them.', 'id': 'security-level', 'label': 'Security level', 'regex': '^(security_levels[0]|security_levels[1]|security_levels[2])$', 'type': 'select', 'select': [security_levels[0], security_levels[1], security_levels[2]]} }
],
{"plugin_id" : "security-level", "setting_id": "SECURITY_LEVEL", "title" : "DEFINE SECURITY LEVEL", "subtitle" : "This will determine default settings value for the next steps. You'll be allow to modify settings to match your case if needed.", "levels" : {}, "setting" : {'context': 'global', 'default': 'standard', 'help': 'Determine the default settings value. You can override them.', 'id': 'security-level', 'label': 'Security level', 'regex': '^(security_levels[0]|security_levels[1]|security_levels[2])$', 'type': 'select', 'select': [security_levels[0], security_levels[1], security_levels[2]]} },
{"plugin_id" : "limit", "setting_id": "LIMIT_REQ_URL", "title" : "Define header", "subtitle" : "test header multiple rendering", "levels" : [{
security_levels[0] : [
{
"LIMIT_REQ_URL": "/",
"LIMIT_REQ_RATE": "2r/s"
}
], security_levels[1] : [
{
"LIMIT_REQ_URL": "/",
"LIMIT_REQ_RATE": "2r/s"
}
], security_levels[2] : [
{
"LIMIT_REQ_URL": "/",
"LIMIT_REQ_RATE": "2r/s"
}
]}]
},
],
"configs": []
},
{
@ -24,12 +46,26 @@
%}
{# Get setting for each settings on steps #}
{% for step in steps %}
{% for setting in step.get('settings') %}
{% for plugin in plugins %}
{% if setting["plugin_id"] == plugin["id"]%}
{% if setting.update({"setting" : plugin["settings"][setting["setting_id"]]})%}{%endif%}
{# Case multiple, get all settings on same group #}
{% set is_multiple = plugin["settings"][setting["setting_id"]].get("multiple", "") %}
{% if is_multiple %}
{% set multiples = {"multiples" : []}%}
{% for mult_setting, value in plugin["settings"].items() %}
{% if value.get("multiple", "") == is_multiple %}
{% set mult_value = value %}
{% if mult_value.update({"name" : mult_setting}) %}{%endif%}
{% if multiples["multiples"].append(mult_value) %}{%endif%}
{% endif %}
{% endfor %}
{% if setting.update(multiples)%}{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}

View file

@ -2,9 +2,9 @@
<!-- plugin item -->
<div class="w-full grid grid-cols-12">
{% for setting_simple in plugin_simple %}
{% set setting_input = { "name" : setting_simple.get('setting_id'), "method" : setting_simple.get('setting').get("method", "default"), "help" : setting_simple.get('setting').get("help"), "label" : setting_simple.get('setting').get("label"), "id" : setting_simple.get('setting').get("id"), "type" : setting_simple.get('setting').get("type"), "default" : setting_simple.get('setting').get("default", "default"), "select" : setting_simple.get('setting').get("select"), "regex" : setting_simple.get('setting').get("regex"), "value" : setting_simple.get('setting').get("value"), "is_multiple" : True if setting_simple.get('setting').get("type") == "multiple" else False, "levels" : setting_simple.get('levels', {}) } %}
{% set setting_input = { "name" : setting_simple.get('setting_id'), "multiples" : setting_simple.get("multiples", {}), "method" : setting_simple.get('setting').get("method", "default"), "help" : setting_simple.get('setting').get("help"), "label" : setting_simple.get('setting').get("label"), "id" : setting_simple.get('setting').get("id"), "type" : setting_simple.get('setting').get("type"), "default" : setting_simple.get('setting').get("default", "default"), "select" : setting_simple.get('setting').get("select"), "regex" : setting_simple.get('setting').get("regex"), "value" : setting_simple.get('setting').get("value"), "is_multiple" : True if setting_simple.get('setting').get("multiple", "") else False, "levels" : setting_simple.get('levels', {}) if not setting_simple.get('setting').get("multiples", "") else {}, "multiple_name" : setting_simple.get('setting').get('multiple') } %}
<div data-simple id="{{ setting_simple['plugin_id'] }}-simple"
class="w-full h-full px-1 mb-2 col-span-12 md:col-span-6 grid grid-cols-12 h-full items-end">
class="w-full h-full px-1 mb-2 col-span-12 {% if not setting_input['is_multiple'] %} md:col-span-6 {% endif %} grid grid-cols-12 h-full items-end">
<!-- title and desc -->
<div class="col-span-12" data-setting-header>
<div class="flex flex-col justify-start items-start">
@ -29,29 +29,25 @@
<!-- end plugin settings not multiple -->
{% endif %}
{% if setting_input.get('is_multiple') %}
<h5 data-multiple-title
class="transition duration-300 ease-in-out ml-2 font-bold text-[1.1rem] uppercase dark:text-white/90 mt-2 mb-0">
multiple settings
</h5>
{% for multiple in multiple_settings %}
<!-- plugin multiple handler -->
<div data-multiple-handler="{{ multiple }}"
class="flex items-center mx-2 mb-2 mt-5 col-span-12 ">
<h5 class="input-title max-w-[150px] sm:max-w-[350px]">{{ multiple.replace('-', ' ').replace('_', ' ')|upper }}</h5>
<button data--simple-{{ current_endpoint }}-multiple-add="{{ multiple }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Add
</button>
<button data--simple-{{ current_endpoint }}-multiple-toggle="{{ multiple }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-sky-500 hover:bg-sky-500/80 focus:bg-sky-500/80 leading-normal text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
SHOW / HIDE
</button>
</div>
<!-- end plugin multiple handler-->
<!-- plugin multiple handler -->
<div data-multiple-handler="{{ setting_input['multiple_name'] }}" data-multiple-levels="{{ setting_input['levels'] }}"
class="flex items-center mx-4 mb-2 mt-5 col-span-12 ">
<h5 class="input-title max-w-[150px] sm:max-w-[350px]">{{ setting_simple['plugin_id'] }}</h5>
<button data-{{ attribute_name }}-multiple-add="{{ setting_input['multiple_name'] }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Add
</button>
<button data-{{ attribute_name }}-multiple-toggle="{{ setting_input['multiple_name'] }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-sky-500 hover:bg-sky-500/80 focus:bg-sky-500/80 leading-normal text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
SHOW / HIDE
</button>
</div>
<!-- end plugin multiple handler-->
<!-- multiple settings -->
<div data--simple-{{ current_endpoint }}-settings-multiple="{{ multiple }}_SCHEMA" class="bg-gray-50 dark:bg-slate-900/30 hidden w-full my-4 grid-cols-12 border dark:border-gray-700 rounded">
{% for setting, value in plugin["settings"].items() %}
{% set setting_input = { "name" : setting, "context" : value.get("context"), "help" : value.get("help"), "label" : value.get("label"), "id" : value.get("id"), "type" : value.get("type"), "default" : value.get("default", "default"), "select" : value.get("select"), "regex" : value.get("regex"), "value" : value.get("value"), "is_multiple" : True} %}
<div data-setting-container="{{ setting }}_SCHEMA" data--simple-{{ current_endpoint }}-type="{{ plugin['type'] }}" data--simple-{{ current_endpoint }}-context="{{ value['context'] }}" class="relative mx-2 md:mx-3 my-2 md:my-3 col-span-12 md:col-span-6 2xl:col-span-4" id="form-edit--simple-{{ current_endpoint }}-{{ value["id"] }}_SCHEMA">
<div data-{{ attribute_name }}-settings-multiple="{{ setting_input['multiple_name'] }}_SCHEMA" class=" col-span-12 bg-gray-50 dark:bg-slate-900/30 hidden w-full my-4 grid-cols-12 border dark:border-gray-700 rounded">
{% for setting in setting_input.get("multiples") %}
{% set setting_input = { "name" : setting.get("name"), "context" : setting.get("context"), "method" : setting.get("method", "default"), "help" : setting.get("help"), "label" : setting.get("label"), "id" : setting.get("id"), "type" : setting.get("type"), "default" : setting.get("default", "default"), "select" : setting.get("select"), "regex" : setting.get("regex"), "value" : setting.get("value", setting.get('default')), "is_multiple" : True, "levels" : {} } %}
<div data-setting-container="{{ setting }}_SCHEMA" data-{{ attribute_name }}-type="{{ setting_input['type'] }}" data-{{ attribute_name }}-context="{{ setting_input['context'] }}" class="relative mx-2 md:mx-3 my-2 md:my-3 col-span-12 md:col-span-6 2xl:col-span-4" id="form-edit-{{ attribute_name }}-{{ setting }}_SCHEMA">
<!-- title and info -->
{% include "setting_header.html" %}
{% include "setting_input.html" %}
@ -62,13 +58,12 @@
{% endfor %}
<div data-multiple-delete-container
class="col-span-12 flex justify-center my-4">
<button data--simple-{{ current_endpoint }}-multiple-delete="{{ plugin['name'] }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-red-500 hover:bg-red-500/80 focus:bg-red-500/80 leading-normal text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
<button data-{{ attribute_name }}-multiple-delete="{{ setting_simple['plugin_id'] }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-red-500 hover:bg-red-500/80 focus:bg-red-500/80 leading-normal text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Remove
</button>
</div>
<!-- end plugin settings -->
</div>
{% endfor %}
<!-- end multiple settings -->
{% endif %}
</div>