add filter context on global config page

This commit is contained in:
Jordan Blasenhauer 2024-03-08 17:35:38 +01:00
parent 6fc9bbab02
commit 3f77c085ef
4 changed files with 332 additions and 80 deletions

View file

@ -17,7 +17,7 @@
- [UI] General : dark mode enhancement
- [UI] General : add visual feedback when filtering is matching nothing
- [UI] General : blog news working and add dynamic banner news
- [UI] Global config page : Add the possibility to edit multisite settings as well
- [UI] Global config page : Add multisite edit, add context filter
- [UI] Global config / Service page : remove tabs for select and enhance filtering (plugin name includes)
- [UI] Service page : add the possibility to clone a service in the web UI
- [UI] Service page : add the possibility to set a service as draft in the web UI

View file

@ -7,6 +7,177 @@ import {
showInvalid,
} from "./utils/settings.js";
class Dropdown {
constructor(prefix = "global-config") {
this.prefix = prefix;
this.container = document.querySelector("main");
this.lastDrop = "";
this.initDropdown();
}
initDropdown() {
this.container.addEventListener("click", (e) => {
//SELECT BTN LOGIC
try {
if (
e.target
.closest("button")
.hasAttribute(`data-${this.prefix}-setting-select`) &&
!e.target.closest("button").hasAttribute(`disabled`)
) {
const btnName = e.target
.closest("button")
.getAttribute(`data-${this.prefix}-setting-select`);
if (this.lastDrop !== btnName) {
this.lastDrop = btnName;
this.closeAllDrop();
}
this.toggleSelectBtn(e);
}
} catch (err) {}
//SELECT DROPDOWN BTN LOGIC
try {
if (
e.target
.closest("button")
.hasAttribute(`data-${this.prefix}-setting-select-dropdown-btn`)
) {
const btn = e.target.closest("button");
const btnValue = btn.getAttribute("value");
const btnSetting = btn.getAttribute(
`data-${this.prefix}-setting-select-dropdown-btn`,
);
//stop if same value to avoid new fetching
const isSameVal = this.isSameValue(btnSetting, btnValue);
if (isSameVal) return this.hideDropdown(btnSetting);
//else, add new value to custom
this.setSelectNewValue(btnSetting, btnValue);
//close dropdown and change style
this.hideDropdown(btnSetting);
if (
!e.target.closest("button").hasAttribute(`data-${this.prefix}-file`)
) {
this.changeDropBtnStyle(btnSetting, btn);
}
}
} catch (err) {}
});
}
closeAllDrop() {
const drops = document.querySelectorAll(
`[data-${this.prefix}-setting-select-dropdown]`,
);
drops.forEach((drop) => {
drop.classList.add("hidden");
drop.classList.remove("flex");
document
.querySelector(
`svg[data-${this.prefix}-setting-select="${drop.getAttribute(
`data-${this.prefix}-setting-select-dropdown`,
)}"]`,
)
.classList.remove("rotate-180");
});
}
isSameValue(btnSetting, value) {
const selectCustom = document.querySelector(
`[data-${this.prefix}-setting-select-text="${btnSetting}"]`,
);
const currVal = selectCustom.textContent;
return currVal === value ? true : false;
}
setSelectNewValue(btnSetting, value) {
const selectCustom = document.querySelector(
`[data-${this.prefix}-setting-select="${btnSetting}"]`,
);
selectCustom.querySelector(
`[data-${this.prefix}-setting-select-text]`,
).textContent = value;
}
hideDropdown(btnSetting) {
//hide dropdown
const dropdownEl = document.querySelector(
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`,
);
dropdownEl.classList.add("hidden");
dropdownEl.classList.remove("flex");
//svg effect
const dropdownChevron = document.querySelector(
`svg[data-${this.prefix}-setting-select="${btnSetting}"]`,
);
dropdownChevron.classList.remove("rotate-180");
}
changeDropBtnStyle(btnSetting, selectedBtn) {
const dropdownEl = document.querySelector(
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`,
);
//reset dropdown btns
const btnEls = dropdownEl.querySelectorAll("button");
btnEls.forEach((btn) => {
btn.classList.remove(
"bg-primary",
"dark:bg-primary",
"text-gray-300",
"text-gray-300",
);
btn.classList.add("bg-white", "dark:bg-slate-700", "text-gray-700");
});
//highlight clicked btn
selectedBtn.classList.remove(
"bg-white",
"dark:bg-slate-700",
"text-gray-700",
);
selectedBtn.classList.add("dark:bg-primary", "bg-primary", "text-gray-300");
}
toggleSelectBtn(e) {
const attribute = e.target
.closest("button")
.getAttribute(`data-${this.prefix}-setting-select`);
//toggle dropdown
const dropdownEl = document.querySelector(
`[data-${this.prefix}-setting-select-dropdown="${attribute}"]`,
);
const dropdownChevron = document.querySelector(
`svg[data-${this.prefix}-setting-select="${attribute}"]`,
);
dropdownEl.classList.toggle("hidden");
dropdownEl.classList.toggle("flex");
dropdownChevron.classList.toggle("rotate-180");
}
//hide date filter on local
hideFilterOnLocal(type) {
if (type === "local") {
this.hideInp(`input#from-date`);
this.hideInp(`input#to-date`);
}
if (type !== "local") {
this.showInp(`input#from-date`);
this.showInp(`input#to-date`);
}
}
showInp(selector) {
document.querySelector(selector).closest("div").classList.add("flex");
document.querySelector(selector).closest("div").classList.remove("hidden");
}
hideInp(selector) {
document.querySelector(selector).closest("div").classList.add("hidden");
document.querySelector(selector).closest("div").classList.remove("flex");
}
}
class Multiple {
constructor(prefix) {
this.prefix = prefix;
@ -532,6 +703,7 @@ class Multiple {
}
const setPopover = new Popover("main", "global-config");
const setDrop = new Dropdown();
const setTabsSelect = new TabsSelect(
document.querySelector("[data-global-config-tabs-select-container]"),
document.querySelector("[data-global-config-plugins-container]"),
@ -556,3 +728,17 @@ const checkServiceModalKeyword = new CheckNoMatchFilter(
document.querySelector("[data-global-config-form]"),
document.querySelector("[data-global-config-nomatch]"),
);
try {
const checkServiceCardSelect = new CheckNoMatchFilter(
document.querySelectorAll(
"button[data-global-config-setting-select-dropdown-btn]",
),
"select",
document
.querySelector("[data-global-config-plugins-container]")
.querySelectorAll("[data-plugin-item]"),
document.querySelector("[data-global-config-form]"),
document.querySelector("[data-global-config-nomatch]"),
);
} catch (e) {}

View file

@ -196,102 +196,161 @@ class FormatValue {
class FilterSettings {
constructor(inputID, tabContainer, contentContainer) {
this.input = document.querySelector(`input#${inputID}`);
this.contextTxtEl = document.querySelector(
'span[data-global-config-setting-select-text="context"]',
);
this.tabContainer = tabContainer;
this.contentContainer = contentContainer;
this.tabsEls = this.tabContainer.querySelectorAll(
`[data-tab-select-handler]`,
);
this.init();
}
init() {
this.input.addEventListener("input", () => {
this.resetFilter();
//get inp format
const inpValue = this.input.value.trim().toLowerCase();
//loop all tabs
this.tabsEls.forEach((tab) => {
//get settings of tabs except multiples
const settings = this.getSettingsFromTab(tab);
//compare total count to currCount to determine
//if tabs need to be hidden
const settingCount = settings.length;
let hiddenCount = 0;
settings.forEach((setting) => {
try {
const title = setting
.querySelector("h5")
.textContent.trim()
.toLowerCase();
if (!title.includes(inpValue)) {
setting.classList.add("hidden");
hiddenCount++;
}
} catch (err) {}
window.addEventListener("DOMContentLoaded", () => {
if (this.input) {
this.input.addEventListener("input", () => {
this.runFilter();
});
//case no setting match, check if match at least tab name
//if not, hide tab
if (settingCount === hiddenCount) {
const tabName = tab.getAttribute(`data-tab-select-handler`);
const tabTxt = tab.textContent.trim().toLowerCase();
if (!tabTxt.includes(inpValue)) {
tab.classList.add("!hidden");
}
this.contentContainer
.querySelector(`[data-plugin-item=${tabName}]`)
.classList.add("hidden");
window.addEventListener("click", (e) => {
try {
if (
e.target.hasAttribute(
"data-global-config-setting-select-dropdown-btn",
) &&
e.target.getAttribute(
"data-global-config-setting-select-dropdown-btn",
) === "context"
) {
return this.runFilter();
}
}
} catch (e) {}
});
});
}
// check current tabs states
let isAllHidden = true;
let firstNotHiddenEl = null;
for (let i = 0; i < this.tabsEls.length; i++) {
const tab = this.tabsEls[i];
if (!tab.classList.contains("!hidden")) {
isAllHidden = false;
firstNotHiddenEl = tab;
break;
runFilter() {
this.resetFilter();
//get inp format
const inpValue = this.input.value.trim().toLowerCase();
//loop all tabs
this.tabsEls.forEach((tab) => {
//get settings of tabs except multiples
const settings = this.getSettingsFromTab(tab);
//compare total count to currCount to determine
//if tabs need to be hidden
const settingCount = settings.length;
let hiddenCount = 0;
settings.forEach((setting) => {
try {
let needToHide = false;
const title = setting
.querySelector("h5")
.textContent.trim()
.toLowerCase();
if (!title.includes(inpValue)) {
needToHide = true;
}
// check context if filter exists
try {
if (this.contextTxtEl) {
const currContextFilter =
this.contextTxtEl.textContent.toLowerCase();
if (currContextFilter !== "all") {
const settingContext = setting
.getAttribute("data-global-config-context")
.toLowerCase();
if (settingContext !== currContextFilter) {
needToHide = true;
}
}
}
} catch (e) {}
if (needToHide) {
setting.classList.add("hidden");
hiddenCount++;
}
} catch (err) {}
});
//case no setting match, check if match at least tab name
// if no context, else we don't care about name
if (settingCount === hiddenCount) {
const tabName = tab.getAttribute(`data-tab-select-handler`);
const tabTxt = tab.textContent.trim().toLowerCase();
let needHideTab = false;
try {
if (this.contextTxtEl.textContent.toLowerCase() !== "all")
needHideTab = true;
} catch (e) {}
if (!tabTxt.includes(inpValue)) needHideTab = true;
if (needHideTab) {
tab.classList.add("!hidden");
this.contentContainer
.querySelector(`[data-plugin-item=${tabName}]`)
.classList.add("hidden");
}
}
// case no tab match
if (isAllHidden) {
this.tabContainer
.querySelector("[data-tab-select-dropdown-btn]")
.setAttribute("data-tab-id", "no-match");
return (this.tabContainer.querySelector(
"[data-tab-select-dropdown-btn] span",
).textContent = "No match");
}
// click first not hidden tab
const currTabEl = this.tabContainer.querySelector(
"[data-tab-select-dropdown-btn]",
);
const currTabName = currTabEl.getAttribute("data-tab-id");
// case previously no match
if (currTabName === "no-match" && !isAllHidden) {
return firstNotHiddenEl.click();
}
const currTabBtn = this.tabContainer.querySelector(
`[data-tab-select-handler='${currTabName}']`,
);
if (!currTabBtn.classList.contains("!hidden")) {
return currTabBtn.click();
}
if (currTabBtn.classList.contains("!hidden")) {
return firstNotHiddenEl.click();
}
});
// check current tabs states
let isAllHidden = true;
let firstNotHiddenEl = null;
for (let i = 0; i < this.tabsEls.length; i++) {
const tab = this.tabsEls[i];
if (!tab.classList.contains("!hidden")) {
isAllHidden = false;
firstNotHiddenEl = tab;
break;
}
}
console.log("is all hidden", isAllHidden);
// case no tab match
if (isAllHidden) {
this.tabContainer
.querySelector("[data-tab-select-dropdown-btn]")
.setAttribute("data-tab-id", "no-match");
return (this.tabContainer.querySelector(
"[data-tab-select-dropdown-btn] span",
).textContent = "No match");
}
// click first not hidden tab
const currTabEl = this.tabContainer.querySelector(
"[data-tab-select-dropdown-btn]",
);
const currTabName = currTabEl.getAttribute("data-tab-id");
// case previously no match
if (currTabName === "no-match" && !isAllHidden) {
return firstNotHiddenEl.click();
}
const currTabBtn = this.tabContainer.querySelector(
`[data-tab-select-handler='${currTabName}']`,
);
if (!currTabBtn.classList.contains("!hidden")) {
return currTabBtn.click();
}
if (currTabBtn.classList.contains("!hidden")) {
return firstNotHiddenEl.click();
}
}
resetFilter() {

View file

@ -18,6 +18,13 @@
"id": "keyword",
"placeholder": "keyword",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Context",
"id": "context",
"value": "all",
"values": ["all", "global", "multisite"]
}
] %}
<div data-global-config-filter