enhance settings

* invalid input display message and keep ring red
* too long title settings no longer modify popover width
* show on global config when setting is multisite with popover
* update multiple settings to handle all of this
This commit is contained in:
Jordan Blasenhauer 2024-03-08 16:10:42 +01:00
parent 64230b1368
commit 9bf85944a3
9 changed files with 216 additions and 35 deletions

File diff suppressed because one or more lines are too long

View file

@ -4,6 +4,7 @@ import {
FormatValue,
FilterSettings,
CheckNoMatchFilter,
showInvalid,
} from "./utils/settings.js";
class Multiple {
@ -300,6 +301,36 @@ class Multiple {
);
});
//rename popover
const popoverBtns = schemaCtnrClone.querySelectorAll("[data-popover-btn]");
popoverBtns.forEach((popoverBtn) => {
popoverBtn.setAttribute(
"data-popover-btn",
popoverBtn.getAttribute("data-popover-btn").replace("_SCHEMA", suffix),
);
});
const popoverContents = schemaCtnrClone.querySelectorAll(
"[data-popover-content]",
);
popoverContents.forEach((popoverContent) => {
popoverContent.setAttribute(
"data-popover-content",
popoverContent
.getAttribute("data-popover-content")
.replace("_SCHEMA", suffix),
);
});
//rename invalid
const invalidEls = schemaCtnrClone.querySelectorAll("[data-invalid]");
invalidEls.forEach((invalidEl) => {
invalidEl.setAttribute(
"data-invalid",
invalidEl.getAttribute("data-invalid").replace("_SCHEMA", suffix),
);
});
//rename input
try {
const inps = schemaCtnrClone.querySelectorAll("input");
@ -505,6 +536,7 @@ const setTabsSelect = new TabsSelect(
document.querySelector("[data-global-config-tabs-select-container]"),
document.querySelector("[data-global-config-plugins-container]"),
);
const setInvalid = new showInvalid();
const format = new FormatValue();
const setFilterGlobal = new FilterSettings(

View file

@ -4,6 +4,7 @@ import {
FormatValue,
FilterSettings,
CheckNoMatchFilter,
showInvalid,
} from "./utils/settings.js";
class ServiceModal {
@ -906,6 +907,36 @@ class Multiple {
);
});
//rename popover
const popoverBtns = schemaCtnrClone.querySelectorAll("[data-popover-btn]");
popoverBtns.forEach((popoverBtn) => {
popoverBtn.setAttribute(
"data-popover-btn",
popoverBtn.getAttribute("data-popover-btn").replace("_SCHEMA", suffix),
);
});
const popoverContents = schemaCtnrClone.querySelectorAll(
"[data-popover-content]",
);
popoverContents.forEach((popoverContent) => {
popoverContent.setAttribute(
"data-popover-content",
popoverContent
.getAttribute("data-popover-content")
.replace("_SCHEMA", suffix),
);
});
//rename invalid
const invalidEls = schemaCtnrClone.querySelectorAll("[data-invalid]");
invalidEls.forEach((invalidEl) => {
invalidEl.setAttribute(
"data-invalid",
invalidEl.getAttribute("data-invalid").replace("_SCHEMA", suffix),
);
});
//rename input
try {
const inps = schemaCtnrClone.querySelectorAll("input");
@ -1414,7 +1445,7 @@ const setTabsSelect = new TabsSelect(
const setPopover = new Popover();
const setModal = new ServiceModal();
const format = new FormatValue();
const invalid = new showInvalid();
const setFilterGlobal = new FilterSettings(
"settings-filter",
document.querySelector("[data-services-tabs-select]"),

View file

@ -7,7 +7,10 @@ class Popover {
window.addEventListener("pointerover", (e) => {
//POPOVER LOGIC
try {
if (e.target.closest("svg").hasAttribute(`data-popover-btn`)) {
if (
e.target.closest("button").hasAttribute(`data-popover-btn`) ||
e.target.closest("svg").hasAttribute(`data-popover-btn`)
) {
this.showPopover(e.target);
}
} catch (err) {}
@ -16,7 +19,10 @@ class Popover {
window.addEventListener("pointerout", (e) => {
//POPOVER LOGIC
try {
if (e.target.closest("svg").hasAttribute(`data-popover-btn`)) {
if (
e.target.closest("button").hasAttribute(`data-popover-btn`) ||
e.target.closest("svg").hasAttribute(`data-popover-btn`)
) {
this.hidePopover(e.target);
}
} catch (err) {}
@ -24,9 +30,14 @@ class Popover {
}
showPopover(el) {
const btn = el.closest("svg");
const btn = el.closest("button").hasAttribute("data-popover-btn")
? el.closest("button")
: el.closest("svg");
const popoverName = btn.getAttribute("data-popover-btn");
//toggle curr popover
const popover = btn.parentElement.querySelector(`[data-popover-content]`);
const popover = btn.parentElement.querySelector(
`[data-popover-content=${popoverName}]`,
);
popover.classList.add("transition-all", "delay-200", "opacity-0");
popover.classList.remove("hidden");
setTimeout(() => {
@ -35,9 +46,14 @@ class Popover {
}
hidePopover(el) {
const btn = el.closest("svg");
const btn = el.closest("button").hasAttribute("data-popover-btn")
? el.closest("button")
: el.closest("svg");
const popoverName = btn.getAttribute("data-popover-btn");
//toggle curr popover
const popover = btn.parentElement.querySelector(`[data-popover-content]`);
const popover = btn.parentElement.querySelector(
`[data-popover-content=${popoverName}]`,
);
popover.classList.add("hidden");
popover.classList.remove("transition-all", "delay-200");
}
@ -422,6 +438,49 @@ class CheckNoMatchFilter {
}
}
class showInvalid {
constructor() {
this.init();
}
init() {
window.addEventListener("change", (e) => {
this.setInvalidState(e);
});
window.addEventListener("input", (e) => {
this.setInvalidState(e);
});
window.addEventListener("click", (e) => {
this.setInvalidState(e);
});
}
setInvalidState(e) {
try {
if (e.target.hasAttribute("data-setting-input")) {
const settingName = e.target.getAttribute("id");
const invalidEl = document.querySelector(
`[data-invalid=${settingName}]`,
);
const isValid = e.target.validity.valid;
if (isValid) {
e.target.classList.remove("invalid");
invalidEl.classList.add("hidden", "md:hidden");
return;
}
if (!isValid) {
e.target.classList.add("invalid");
invalidEl.classList.remove("hidden", "md:hidden");
return;
}
}
} catch (e) {}
}
}
export {
Popover,
Tabs,
@ -429,4 +488,5 @@ export {
FormatValue,
FilterSettings,
CheckNoMatchFilter,
showInvalid,
};

View file

@ -83,6 +83,10 @@
@apply outline-none dark:border-slate-600 dark:bg-slate-700 dark:text-gray-200 disabled:opacity-75 focus:border-gray-300/0 focus:ring-1 focus:valid:ring-green-500 focus:invalid:ring-red-500 text-sm leading-5.6 ease-in block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 md:py-2 font-normal text-gray-700 transition-all placeholder:text-gray-500 disabled:bg-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 dark:disabled:text-gray-300 disabled:text-gray-700;
}
.invalid.regular-input {
@apply !ring-1 !ring-red-500;
}
.input-title {
@apply transition duration-300 ease-in-out text-sm font-bold m-0 dark:text-gray-200;
}
@ -98,6 +102,10 @@
.popover-settings-svg {
@apply cursor-pointer fill-blue-500 h-5 w-5 ml-2 hover:brightness-75;
}
.popover-settings-svg-multiple {
@apply cursor-pointer fill-orange-500 dark:stroke-gray-500 stroke-gray-700 h-5.5 w-5.5 ml-2 hover:brightness-75;
}
/*--------------------------------------------*/
/*---------------END SETTINGS_PLUGINS---------*/
/*---------------------------------------------*/

View file

@ -71,6 +71,7 @@ module.exports = {
presets: [],
darkMode: "class",
important: true,
theme: {
extend: {
data: {

View file

@ -35,7 +35,8 @@
<span class="w-full flex justify-between items-center">
<!-- text and icon -->
<span class="tabs-name">{{ tab['name'] }}</span>
<svg data-popover-btn="{{ tab['name'] }}"
<svg role="button"
data-popover-btn="{{ tab['name'] }}"
class=" fill-blue-500 h-5 w-5 mr-2 hover:brightness-95"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">

View file

@ -18,7 +18,7 @@
"id": "keyword",
"placeholder": "keyword",
"pattern": "(.*?)"
}
},
] %}
<div data-global-config-filter
class="h-fit p-4 col-span-12 md:col-span-6 lg:col-span-5 xl:col-span-4 2xl:col-span-3 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">

View file

@ -57,24 +57,45 @@
{% if multList.append(value['multiple']) %}{% endif %}
{% endif %}
{% if not value['multiple'] %}
<div data-setting-container data-{{ current_endpoint }}-context="{{ value['context'] }}" class="mx-0 sm:mx-2 my-2 col-span-12 md:my-3 md:col-span-6 2xl:my-3 2xl:col-span-4" id="form-edit-{{ current_endpoint }}-{{ value["id"] }}">
<div data-setting-container data-{{ current_endpoint }}-context="{{ value['context'] }}" class="relative mx-0 sm:mx-2 my-2 col-span-12 md:my-3 md:col-span-6 2xl:my-3 2xl:col-span-4" id="form-edit-{{ current_endpoint }}-{{ value["id"] }}">
<!-- title and info -->
<div class="flex items-center my-1 relative z-10">
<h5 class="input-title">{{ value["label"] }}</h5>
<svg data-popover-btn="{{ value["label"] }}"
class="popover-settings-svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z" />
</svg>
<!-- popover -->
<button type="button" data-popover-btn="{{ setting }}">
<svg class="popover-settings-svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z" />
</svg>
</button>
<div role="alert"
aria-description="show detail"
class="popover-settings-container hidden"
data-popover-content="{{ value["label"] }}">
data-popover-content="{{ setting }}">
<p class="popover-settings-text">{{ value['help'] }}</p>
</div>
<!-- end popover -->
{% if value["context"] == "multisite" and current_endpoint == "global-config" %}
<!-- popover -->
<button type="button" data-popover-btn="{{ setting }}-multiple">
<svg class="popover-settings-svg-multiple"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 17.25v-.228a4.5 4.5 0 00-.12-1.03l-2.268-9.64a3.375 3.375 0 00-3.285-2.602H7.923a3.375 3.375 0 00-3.285 2.602l-2.268 9.64a4.5 4.5 0 00-.12 1.03v.228m19.5 0a3 3 0 01-3 3H5.25a3 3 0 01-3-3m19.5 0a3 3 0 00-3-3H5.25a3 3 0 00-3 3m16.5 0h.008v.008h-.008v-.008zm-3 0h.008v.008h-.008v-.008z" />
</svg>
</button>
<div role="alert"
aria-description="show detail"
class="popover-settings-container hidden"
data-popover-content="{{ setting }}-multiple">
<p class="popover-settings-text">Multisite (apply as default to services without specific value).</p>
</div>
<!-- end popover -->
{% endif %}
</div>
<!-- end title and info -->
<!-- input -->
@ -86,6 +107,7 @@
data-default-method="{{ global_config[setting]['method'] }}"
{% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %}disabled{% endif %}
id="{{ setting }}"
data-setting-input
name="{{ setting }}"
class="regular-input"
value="{% if global_config[setting]['value'] %} {{ global_config[setting]['value'] }} {% else %} {{ value['default'] }} {% endif %}"
@ -226,10 +248,12 @@
<!-- end checkbox -->
<!-- invalid feedback -->
<div role="alert"
data-invalid="{{ setting }}"
aria-label="show when invalid input"
class="hidden text-sm dark:text-red-500">
{{ value['label'] }} is invalid and must match this pattern:
{{ value['regex']|safe }}
class="block md:absolute hidden md:hidden text-sm text-red-500">
Invalid value
<span class="sr-only"> {{ value['label'] }} is invalid and must match this pattern:
{{ value['regex']|safe }}</span>
</div>
<!--end invalid feedback-->
</div>
@ -258,7 +282,7 @@
</div>
<!-- end plugin multiple handler-->
<!-- multiple settings -->
<div data-{{ current_endpoint }}-settings-multiple="{{ multiple }}_SCHEMA" class="bg-gray-50 dark:bg-slate-900/30 hidden w-full mb-4 mt-2 grid-cols-12 border dark:border-gray-700 rounded">
<div data-{{ 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() %}
{# render only setting that match the multiple id and context #}
{% if value['multiple'] == multiple and (
@ -266,25 +290,46 @@
or current_endpoint == "services" and value['context'] == "multisite"
) %}
<div data-setting-container="{{ setting }}_SCHEMA"
class="mx-2 md:mx-3 my-2 md:my-3 col-span-12 md:col-span-6 2xl:col-span-4"
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-{{ current_endpoint }}-{{ value["id"] }}_SCHEMA">
<!-- title and info -->
<div class="flex items-center my-1 relative z-10">
<h5 class="input-title">{{ value["label"] }}</h5>
<svg data-popover-btn="{{ value["label"] }}"
class="popover-settings-svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z" />
</svg>
<!-- popover -->
<button type="button" data-popover-btn="{{ setting }}_SCHEMA">
<svg class="popover-settings-svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z" />
</svg>
</button>
<div role="alert"
aria-description="show detail"
class="popover-settings-container hidden"
data-popover-content="{{ value["label"] }}">
class="popover-settings-container hidden"
data-popover-content="{{ setting }}_SCHEMA">
<p class="popover-settings-text">{{ value['help'] }}</p>
</div>
<!-- end popover -->
{% if value["context"] == "multisite" and current_endpoint == "global-config" %}
<!-- popover -->
<button type="button" data-popover-btn="{{ setting }}-multiple_SCHEMA">
<svg class="popover-settings-svg-multiple"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 17.25v-.228a4.5 4.5 0 00-.12-1.03l-2.268-9.64a3.375 3.375 0 00-3.285-2.602H7.923a3.375 3.375 0 00-3.285 2.602l-2.268 9.64a4.5 4.5 0 00-.12 1.03v.228m19.5 0a3 3 0 01-3 3H5.25a3 3 0 01-3-3m19.5 0a3 3 0 00-3-3H5.25a3 3 0 00-3 3m16.5 0h.008v.008h-.008v-.008zm-3 0h.008v.008h-.008v-.008z" />
</svg>
</button>
<div role="alert"
aria-description="show detail"
class="popover-settings-container hidden"
data-popover-content="{{ setting }}-multiple_SCHEMA">
<p class="popover-settings-text">Multisite (apply as default to services without specific value).</p>
</div>
<!-- end popover -->
{% endif %}
</div>
<!-- end title and info -->
<!-- input -->
@ -293,6 +338,7 @@
<label class="sr-only" for="{{ setting }}_SCHEMA">{{ setting }}</label>
<input data-default-value="{{ value['default'] }}"
data-default-method="default"
data-setting-input
id="{{ setting }}_SCHEMA"
name="{{ setting }}_SCHEMA"
class="regular-input"
@ -418,10 +464,12 @@
<!-- end checkbox -->
<!-- invalid feedback -->
<div role="alert"
aria-label="show when invalid"
class="hidden text-sm dark:text-red-500">
{{ value['label'] }} is invalid and must match this pattern:
{{ value['regex']|safe }}
data-invalid="{{ setting }}_SCHEMA"
aria-label="show when invalid input"
class="block md:absolute hidden md:hidden text-sm text-red-500">
Invalid value
<span class="sr-only"> {{ value['label'] }} is invalid and must match this pattern:
{{ value['regex']|safe }}</span>
</div>
<!--end invalid feedback-->
</div>