mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
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:
parent
64230b1368
commit
9bf85944a3
9 changed files with 216 additions and 35 deletions
File diff suppressed because one or more lines are too long
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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]"),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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---------*/
|
||||
/*---------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ module.exports = {
|
|||
|
||||
presets: [],
|
||||
darkMode: "class",
|
||||
important: true,
|
||||
theme: {
|
||||
extend: {
|
||||
data: {
|
||||
|
|
|
|||
3
src/ui/templates/account.html
vendored
3
src/ui/templates/account.html
vendored
|
|
@ -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">
|
||||
|
|
|
|||
2
src/ui/templates/global_config.html
vendored
2
src/ui/templates/global_config.html
vendored
|
|
@ -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">
|
||||
|
|
|
|||
98
src/ui/templates/settings_plugins.html
vendored
98
src/ui/templates/settings_plugins.html
vendored
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in a new issue