mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
update plugins and tests
* remove tabs and update by select component for better UX * update script to make new elements work * update keyword filter settings script * no longer max-h with overflow on global config page * update service modal to fit new elements, enhance responsive and add separator *remove error actions on test utils * enhance some base components like button size, service card data position, modal size...
This commit is contained in:
parent
f7a5c3a6b6
commit
df3c16c120
12 changed files with 304 additions and 224 deletions
File diff suppressed because one or more lines are too long
|
|
@ -534,7 +534,7 @@ const setSelect = new Select();
|
|||
const setPassword = new Password();
|
||||
const setDisabledPop = new DisabledPop();
|
||||
const setNews = new News();
|
||||
// const setBanner = new Banner();
|
||||
const setBanner = new Banner();
|
||||
const setDarkM = new darkMode();
|
||||
const setFlash = new FlashMsg();
|
||||
const setLoader = new Loader();
|
||||
|
|
|
|||
|
|
@ -27,20 +27,25 @@ class Multiple {
|
|||
}
|
||||
|
||||
const setPopover = new Popover("main", "global-config");
|
||||
const setTabs = new Tabs("[global-config-tabs]", "global-config");
|
||||
const setTabs = new Tabs(
|
||||
document.querySelector("[data-global-config-tabs-container]"),
|
||||
document.querySelector("[data-global-config-plugins-container]"),
|
||||
);
|
||||
const format = new FormatValue();
|
||||
const setMultiple = new Multiple("global-config");
|
||||
|
||||
const setFilterGlobal = new FilterSettings(
|
||||
"settings-filter",
|
||||
"[data-service-content='settings']",
|
||||
"keyword",
|
||||
document.querySelector("[data-global-config-tabs-container]"),
|
||||
document.querySelector("[data-global-config-plugins-container]"),
|
||||
);
|
||||
|
||||
const checkServiceModalKeyword = new CheckNoMatchFilter(
|
||||
document.querySelector("input#settings-filter"),
|
||||
document.querySelector("input#keyword"),
|
||||
"input",
|
||||
document
|
||||
.querySelector("[data-global-config-tabs]")
|
||||
.querySelectorAll("[data-tab-handler]"),
|
||||
.querySelector("[data-global-config-plugins-container]")
|
||||
.querySelectorAll("[data-plugin-item]"),
|
||||
document.querySelector("[data-global-config-form]"),
|
||||
document.querySelector("[data-global-config-nomatch]"),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1406,14 +1406,19 @@ class Filter {
|
|||
|
||||
const setDropdown = new Dropdown();
|
||||
const setFilter = new Filter();
|
||||
const setTabs = new Tabs(
|
||||
document.querySelector("[data-services-tabs]"),
|
||||
document.querySelector("[data-services-modal-form]"),
|
||||
);
|
||||
|
||||
const setPopover = new Popover();
|
||||
const setTabs = new Tabs();
|
||||
const setModal = new ServiceModal();
|
||||
const format = new FormatValue();
|
||||
|
||||
const setFilterGlobal = new FilterSettings(
|
||||
"settings-filter",
|
||||
"[data-service-content='settings']",
|
||||
document.querySelector("[data-services-tabs]"),
|
||||
document.querySelector("[data-services-modal-form]"),
|
||||
);
|
||||
|
||||
const setMultiple = new Multiple("services");
|
||||
|
|
@ -1422,8 +1427,8 @@ const checkServiceModalKeyword = new CheckNoMatchFilter(
|
|||
document.querySelector("input#settings-filter"),
|
||||
"input",
|
||||
document
|
||||
.querySelector("[data-services-tabs-desktop]")
|
||||
.querySelectorAll("[data-tab-handler]"),
|
||||
.querySelector("[data-services-modal-form]")
|
||||
.querySelectorAll("[data-plugin-item]"),
|
||||
document.querySelector("[data-services-modal-form]"),
|
||||
document.querySelector("[data-services-nomatch]"),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -44,101 +44,105 @@ class Popover {
|
|||
}
|
||||
|
||||
class Tabs {
|
||||
constructor() {
|
||||
constructor(tabContainer, contentContainer) {
|
||||
this.tabContainer = tabContainer;
|
||||
this.contentContainer = contentContainer;
|
||||
this.tabArrow = tabContainer
|
||||
.querySelector("[data-tab-dropdown-btn]")
|
||||
.querySelector("[data-tab-dropdown-arrow]");
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
window.addEventListener("click", (e) => {
|
||||
try {
|
||||
if (
|
||||
e.target.closest("button").hasAttribute("data-tab-handler") ||
|
||||
e.target.closest("button").hasAttribute("data-tab-handler-mobile")
|
||||
) {
|
||||
if (e.target.closest("button").hasAttribute("data-tab-handler")) {
|
||||
//get needed data
|
||||
const tab = e.target.closest("button");
|
||||
const tabAtt =
|
||||
tab.getAttribute("data-tab-handler") ||
|
||||
tab.getAttribute("data-tab-handler-mobile");
|
||||
const container = tab.closest("div[data-service-content]");
|
||||
const tabAtt = tab.getAttribute("data-tab-handler");
|
||||
// change style
|
||||
this.resetTabsStyle(container);
|
||||
this.highlightClicked(container, tabAtt);
|
||||
this.resetTabsStyle();
|
||||
this.highlightClicked(tabAtt);
|
||||
//show content
|
||||
this.hideAllSettings(container);
|
||||
this.showSettingClicked(container, tabAtt);
|
||||
this.hideAllSettings();
|
||||
this.showSettingClicked(tabAtt);
|
||||
//close dropdown and change btn textcontent on mobile
|
||||
this.setDropBtnText(container, tabAtt);
|
||||
this.closeDropdown(container);
|
||||
this.setDropBtnText(tabAtt);
|
||||
this.closeDropdown();
|
||||
}
|
||||
} catch (err) {}
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
if (e.target.closest("button").hasAttribute("data-tab-dropdown-btn")) {
|
||||
const dropBtn = e.target.closest("button");
|
||||
const container = dropBtn.closest("div[data-service-content]");
|
||||
this.toggleDropdown(container);
|
||||
this.toggleDropdown();
|
||||
}
|
||||
} catch (err) {}
|
||||
});
|
||||
}
|
||||
|
||||
resetTabsStyle(container) {
|
||||
//reset desktop style
|
||||
const tabsDesktop = container.querySelectorAll("button[data-tab-handler]");
|
||||
tabsDesktop.forEach((tab) => {
|
||||
tab.classList.remove("active");
|
||||
});
|
||||
//reset mobile style
|
||||
const tabsMobile = container.querySelectorAll(
|
||||
"button[data-tab-handler-mobile]",
|
||||
resetTabsStyle() {
|
||||
const tabsMobile = this.tabContainer.querySelectorAll(
|
||||
"button[data-tab-handler]",
|
||||
);
|
||||
tabsMobile.forEach((tab) => {
|
||||
tab.classList.remove("active");
|
||||
});
|
||||
}
|
||||
|
||||
highlightClicked(container, tabAtt) {
|
||||
//desktop case
|
||||
const tabDesktop = container.querySelector(
|
||||
highlightClicked(tabAtt) {
|
||||
const tabMobile = this.tabContainer.querySelector(
|
||||
`button[data-tab-handler='${tabAtt}']`,
|
||||
);
|
||||
tabDesktop.classList.add("active");
|
||||
|
||||
//mobile case
|
||||
const tabMobile = container.querySelector(
|
||||
`button[data-tab-handler-mobile='${tabAtt}']`,
|
||||
);
|
||||
tabMobile.classList.add("active");
|
||||
}
|
||||
|
||||
hideAllSettings(container) {
|
||||
const plugins = container.querySelectorAll("[data-plugin-item]");
|
||||
hideAllSettings() {
|
||||
const plugins =
|
||||
this.contentContainer.querySelectorAll("[data-plugin-item]");
|
||||
plugins.forEach((plugin) => {
|
||||
plugin.classList.add("hidden");
|
||||
});
|
||||
}
|
||||
|
||||
showSettingClicked(container, tabAtt) {
|
||||
const plugin = container.querySelector(`[data-plugin-item='${tabAtt}']`);
|
||||
showSettingClicked(tabAtt) {
|
||||
const plugin = this.contentContainer.querySelector(
|
||||
`[data-plugin-item='${tabAtt}']`,
|
||||
);
|
||||
plugin.classList.remove("hidden");
|
||||
}
|
||||
|
||||
setDropBtnText(container, tabAtt) {
|
||||
const dropBtn = container.querySelector("[data-tab-dropdown-btn]");
|
||||
setDropBtnText(tabAtt) {
|
||||
const dropBtn = this.tabContainer.querySelector("[data-tab-dropdown-btn]");
|
||||
dropBtn.querySelector("span").textContent = tabAtt;
|
||||
}
|
||||
|
||||
closeDropdown(container) {
|
||||
const dropdown = container.querySelector("[data-tab-dropdown]");
|
||||
closeDropdown() {
|
||||
const dropdown = this.tabContainer.querySelector("[data-tab-dropdown]");
|
||||
dropdown.classList.add("hidden");
|
||||
dropdown.classList.remove("flex");
|
||||
|
||||
this.updateTabArrow();
|
||||
}
|
||||
|
||||
toggleDropdown(container) {
|
||||
const dropdown = container.querySelector("[data-tab-dropdown]");
|
||||
toggleDropdown() {
|
||||
const dropdown = this.tabContainer.querySelector("[data-tab-dropdown]");
|
||||
dropdown.classList.toggle("hidden");
|
||||
dropdown.classList.toggle("flex");
|
||||
|
||||
this.updateTabArrow();
|
||||
}
|
||||
|
||||
updateTabArrow() {
|
||||
const dropdown = this.tabContainer.querySelector("[data-tab-dropdown]");
|
||||
|
||||
if (dropdown.classList.contains("hidden")) {
|
||||
this.tabArrow.classList.remove("rotate-180");
|
||||
}
|
||||
|
||||
if (dropdown.classList.contains("flex")) {
|
||||
this.tabArrow.classList.add("rotate-180");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,11 +163,11 @@ class FormatValue {
|
|||
}
|
||||
|
||||
class FilterSettings {
|
||||
constructor(inputID, container) {
|
||||
constructor(inputID, tabContainer, contentContainer) {
|
||||
this.input = document.querySelector(`input#${inputID}`);
|
||||
//DESKTOP
|
||||
this.container = document.querySelector(container);
|
||||
this.deskTabs = this.container.querySelectorAll(`[data-tab-handler]`);
|
||||
this.tabContainer = tabContainer;
|
||||
this.contentContainer = contentContainer;
|
||||
this.tabsEls = this.tabContainer.querySelectorAll(`[data-tab-handler]`);
|
||||
this.init();
|
||||
}
|
||||
|
||||
|
|
@ -172,8 +176,9 @@ class FilterSettings {
|
|||
this.resetFilter();
|
||||
//get inp format
|
||||
const inpValue = this.input.value.trim().toLowerCase();
|
||||
|
||||
//loop all tabs
|
||||
this.deskTabs.forEach((tab) => {
|
||||
this.tabsEls.forEach((tab) => {
|
||||
//get settings of tabs except multiples
|
||||
const settings = this.getSettingsFromTab(tab);
|
||||
|
||||
|
|
@ -196,31 +201,65 @@ class FilterSettings {
|
|||
//case no setting match, hidden tab and content
|
||||
if (settingCount === hiddenCount) {
|
||||
const tabName = tab.getAttribute(`data-tab-handler`);
|
||||
//hide mobile and desk tabs
|
||||
tab.classList.add("hidden");
|
||||
this.container
|
||||
.querySelector(`[data-tab-handler-mobile="${tabName}"]`)
|
||||
.classList.add("hidden");
|
||||
this.container
|
||||
tab.classList.add("!hidden");
|
||||
|
||||
this.contentContainer
|
||||
.querySelector(`[data-plugin-item=${tabName}]`)
|
||||
.querySelector("[data-setting-header]")
|
||||
.classList.add("hidden");
|
||||
}
|
||||
});
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// case no tab match
|
||||
if (isAllHidden) {
|
||||
return (this.tabContainer.querySelector(
|
||||
"[data-tab-dropdown-btn] span",
|
||||
).textContent = "No match");
|
||||
}
|
||||
|
||||
// click first not hidden tab
|
||||
const currTabEl = this.tabContainer.querySelector(
|
||||
"[data-tab-dropdown-btn] span",
|
||||
);
|
||||
const currTabName = currTabEl.textContent.toLowerCase().trim();
|
||||
|
||||
// case previously no match
|
||||
if (currTabName.toLowerCase() === "no match") {
|
||||
return firstNotHiddenEl.click();
|
||||
}
|
||||
|
||||
const currTabBtn = this.tabContainer.querySelector(
|
||||
`[data-tab-handler='${currTabName}']`,
|
||||
);
|
||||
if (!currTabBtn) return;
|
||||
|
||||
if (!currTabBtn.classList.contains("!hidden")) {
|
||||
return currTabBtn.click();
|
||||
}
|
||||
if (currTabBtn.classList.contains("!hidden")) {
|
||||
return firstNotHiddenEl.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
resetFilter() {
|
||||
this.deskTabs.forEach((tab) => {
|
||||
this.tabsEls.forEach((tab) => {
|
||||
const tabName = tab.getAttribute(`data-tab-handler`);
|
||||
//hide mobile and desk tabs
|
||||
tab.classList.remove("hidden");
|
||||
this.container
|
||||
.querySelector(`[data-tab-handler-mobile="${tabName}"]`)
|
||||
.classList.remove("hidden");
|
||||
this.container
|
||||
tab.classList.remove("!hidden");
|
||||
this.contentContainer
|
||||
.querySelector(`[data-plugin-item=${tabName}]`)
|
||||
.querySelector("[data-setting-header]")
|
||||
.classList.remove("hidden");
|
||||
const settings = this.getSettingsFromTab(tab);
|
||||
settings.forEach((setting) => {
|
||||
|
|
@ -231,7 +270,7 @@ class FilterSettings {
|
|||
|
||||
getSettingsFromTab(tabEl) {
|
||||
const tabName = tabEl.getAttribute(`data-tab-handler`);
|
||||
const settingContainer = this.container
|
||||
const settingContainer = this.contentContainer
|
||||
.querySelector(`[data-plugin-item="${tabName}"]`)
|
||||
.querySelector(`[data-plugin-settings]`);
|
||||
const settings = settingContainer.querySelectorAll(
|
||||
|
|
@ -242,12 +281,20 @@ class FilterSettings {
|
|||
}
|
||||
|
||||
class CheckNoMatchFilter {
|
||||
constructor(input, type, elsToCheck, elContainer, noMatchEl) {
|
||||
constructor(
|
||||
input,
|
||||
type,
|
||||
elsToCheck,
|
||||
elContainer,
|
||||
noMatchEl,
|
||||
classToCheck = "hidden",
|
||||
) {
|
||||
this.input = input;
|
||||
this.type = type;
|
||||
this.elsToCheck = elsToCheck;
|
||||
this.elContainer = elContainer;
|
||||
this.noMatchEl = noMatchEl;
|
||||
this.classToCheck = classToCheck;
|
||||
this.init();
|
||||
}
|
||||
|
||||
|
|
@ -276,20 +323,24 @@ class CheckNoMatchFilter {
|
|||
let isAllHidden = true;
|
||||
for (let i = 0; i < this.elsToCheck.length; i++) {
|
||||
const el = this.elsToCheck[i];
|
||||
if (!el.classList.contains("hidden")) {
|
||||
if (!el.classList.contains(this.classToCheck)) {
|
||||
isAllHidden = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isAllHidden) {
|
||||
this.noMatchEl.classList.remove("hidden");
|
||||
this.elContainer ? this.elContainer.classList.add("hidden") : false;
|
||||
this.noMatchEl.classList.remove(this.classToCheck);
|
||||
this.elContainer
|
||||
? this.elContainer.classList.add(this.classToCheck)
|
||||
: false;
|
||||
}
|
||||
|
||||
if (!isAllHidden) {
|
||||
this.elContainer ? this.elContainer.classList.remove("hidden") : false;
|
||||
this.noMatchEl.classList.add("hidden");
|
||||
this.elContainer
|
||||
? this.elContainer.classList.remove(this.classToCheck)
|
||||
: false;
|
||||
this.noMatchEl.classList.add(this.classToCheck);
|
||||
}
|
||||
}, 20);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,24 +23,28 @@
|
|||
@apply hidden;
|
||||
}
|
||||
|
||||
.separator {
|
||||
@apply h-px mx-0 mt-3 mb-2 bg-transparent bg-gradient-to-r from-transparent via-black/40 to-transparent dark:bg-gradient-to-r dark:from-transparent dark:via-white dark:to-transparent;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
@apply dark:brightness-90 inline-block px-6 py-3 font-bold text-center text-red-500 border border-red-500 uppercase align-middle transition-all rounded-lg cursor-pointer dark:bg-gray-200 dark:hover:brightness-75 bg-white hover:bg-white/80 focus:bg-white/80 leading-normal ease-in tracking-tight-rem shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
|
||||
@apply dark:brightness-90 inline-block px-4 py-2 md:px-5 md:py-2.5 font-bold text-center text-red-500 border border-red-500 uppercase align-middle transition-all rounded-lg cursor-pointer dark:bg-gray-200 dark:hover:brightness-75 bg-white hover:bg-white/80 focus:bg-white/80 leading-normal ease-in tracking-tight-rem shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
|
||||
}
|
||||
|
||||
.valid-btn {
|
||||
@apply tracking-wide dark:brightness-90 inline-block px-6 py-3 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 ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
|
||||
@apply tracking-wide dark:brightness-90 inline-block px-4 py-2 md:px-5 md:py-2.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 ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
@apply tracking-wide dark:brightness-90 inline-block px-6 py-3 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 ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
|
||||
@apply tracking-wide dark:brightness-90 inline-block px-4 py-2 md:px-5 md:py-2.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 ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
|
||||
}
|
||||
|
||||
.edit-btn {
|
||||
@apply tracking-wide dark:brightness-90 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-yellow-500 hover:bg-yellow-500/80 focus:bg-yellow-500/80 leading-normal ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
|
||||
@apply tracking-wide dark:brightness-90 inline-block px-4 py-2 md:px-5 md:py-2.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-yellow-500 hover:bg-yellow-500/80 focus:bg-yellow-500/80 leading-normal ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
|
||||
}
|
||||
|
||||
.info-btn {
|
||||
@apply tracking-wide dark:brightness-90 inline-block px-6 py-3 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 ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
|
||||
@apply tracking-wide dark:brightness-90 inline-block px-4 py-2 md:px-5 md:py-2.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 ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------*/
|
||||
|
|
@ -102,43 +106,27 @@
|
|||
/*---------------SETTINGS_TABS-----------------*/
|
||||
/*---------------------------------------------*/
|
||||
|
||||
.active.settings-tabs-tab-btn {
|
||||
@apply border-primary dark:hover:bg-slate-800 dark:border-slate-600 dark:bg-slate-700 border my-1 relative px-3 py-3 font-bold text-center uppercase align-middle transition-all rounded-none cursor-pointer bg-white hover:bg-gray-100 leading-normal text-sm ease-in tracking-tight-rem shadow-xs hover:shadow-md brightness-90 z-10;
|
||||
.settings-tabs-btn {
|
||||
@apply dark:hover:brightness-95 dark:border-slate-600 dark:bg-slate-700 border-primary border w-full flex items-center justify-between rounded-lg hover:-translate-y-px my-1 px-4 py-2 md:px-6 md:py-3 font-bold text-center uppercase align-middle transition-all cursor-pointer bg-white hover:bg-gray-50 leading-normal text-sm ease-in tracking-tight-rem shadow-xs hover:shadow-md;
|
||||
}
|
||||
|
||||
.settings-tabs-tab-btn {
|
||||
@apply border-primary dark:hover:bg-slate-800 dark:border-slate-600 dark:bg-slate-700 border my-1 relative px-3 py-3 font-bold text-center uppercase align-middle transition-all rounded-none cursor-pointer bg-white hover:bg-gray-100 leading-normal text-sm ease-in tracking-tight-rem shadow-xs hover:shadow-md;
|
||||
}
|
||||
|
||||
.settings-tabs-name {
|
||||
@apply text-primary transition duration-300 ease-in-out dark:opacity-90 pl-3 pr-2 dark:text-gray-300;
|
||||
}
|
||||
|
||||
.settings-tabs-popover-container {
|
||||
@apply top-[60px] min-w-[150px] dark:brightness-90 bg-blue-500 transition z-50 rounded-md p-3 left-0 absolute;
|
||||
}
|
||||
|
||||
.settings-tabs-popover-text {
|
||||
@apply font-bold text-sm text-white m-0;
|
||||
}
|
||||
|
||||
.settings-tabs-mobile-btn {
|
||||
@apply dark:hover:brightness-95 dark:border-slate-600 dark:bg-slate-700 border-primary border w-full flex items-center justify-between rounded-lg hover:-translate-y-px my-1 px-6 py-3 font-bold text-center uppercase align-middle transition-all cursor-pointer bg-white hover:bg-gray-50 leading-normal text-sm ease-in tracking-tight-rem shadow-xs hover:shadow-md;
|
||||
}
|
||||
|
||||
.settings-tabs-mobile-btn-text {
|
||||
.settings-tabs-btn-text {
|
||||
@apply transition duration-300 ease-in-out dark:opacity-90 dark:text-gray-300 text-primary;
|
||||
}
|
||||
|
||||
.active.settings-tabs-mobile-dropdown-btn {
|
||||
.active.settings-tabs-dropdown-btn {
|
||||
@apply border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative px-6 py-2 text-center align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300 z-[1000] dark:bg-primary bg-primary text-gray-300;
|
||||
}
|
||||
|
||||
.first.settings-tabs-mobile-dropdown-btn {
|
||||
.first.settings-tabs-dropdown-btn {
|
||||
@apply border-t rounded-t border-b border-l border-r;
|
||||
}
|
||||
|
||||
.settings-tabs-mobile-dropdown-btn {
|
||||
.last.settings-tabs-dropdown-btn {
|
||||
@apply rounded-b;
|
||||
}
|
||||
|
||||
.settings-tabs-dropdown-btn {
|
||||
@apply flex justify-between border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 bg-white text-gray-700 my-0 relative px-6 py-2 text-center align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300;
|
||||
}
|
||||
|
||||
|
|
|
|||
111
src/ui/templates/global_config.html
vendored
111
src/ui/templates/global_config.html
vendored
|
|
@ -1,32 +1,99 @@
|
|||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div data-service-content="settings"
|
||||
class="col-span-12 gap-y-4 grid grid-cols-12">
|
||||
<div class="p-4 col-span-12 relative flex flex-col min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
|
||||
<div data-{{ current_endpoint }}-tabs-header class="flex flex-col xs:flex-row xs:justify-start xs:items-center gap-x-4 gap-y-2 my-3">
|
||||
<h5 class="transition duration-300 ease-in-out 0 ml-2 font-bold text-md uppercase dark:text-white/90 mb-0">CONFIGS</h5>
|
||||
<!-- search inpt-->
|
||||
<div class="flex relative col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3">
|
||||
<label class="sr-only" for="settings-filter">filter settings</label>
|
||||
<input type="text"
|
||||
id="settings-filter"
|
||||
name="settings-filter"
|
||||
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
|
||||
placeholder="key words"
|
||||
pattern="(.*?)"
|
||||
required />
|
||||
</div>
|
||||
<!-- end search inpt-->
|
||||
</div>
|
||||
<!-- tabs -->
|
||||
{% include "settings_tabs.html" %}
|
||||
<!-- end tabs-->
|
||||
<div data-global-config-tabs-container
|
||||
class="z-100 w-full grid grid-cols-12 h-fit max-h-100 sm:max-h-125 col-span-12 md:col-span-6 lg:col-span-4 p-4 relative break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
|
||||
<div data-{{ current_endpoint }}-tabs-header class="col-span-12">
|
||||
<div class="flex flex-col xs:flex-row xs:justify-start xs:items-center gap-x-4 gap-y-2 my-3">
|
||||
<h5 class="transition duration-300 ease-in-out 0 ml-2 font-bold text-md uppercase dark:text-white/90 mb-0">PLUGINS</h5>
|
||||
</div>
|
||||
{% include "settings_tabs.html" %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- filter -->
|
||||
{% set filters = [
|
||||
{
|
||||
"type": "input",
|
||||
"name": "Search",
|
||||
"label": "search",
|
||||
"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">
|
||||
<h5 class="mb-2 font-bold dark:text-white/90">FILTER</h5>
|
||||
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
|
||||
{% for filter in filters %}
|
||||
{% if filter['type'] == 'input' %}
|
||||
<!-- search inpt-->
|
||||
<div class="flex flex-col relative col-span-12">
|
||||
<h5 class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300">
|
||||
{{ filter['name'] }}
|
||||
</h5>
|
||||
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
|
||||
<input type="text"
|
||||
id="{{ filter['id'] }}"
|
||||
name="{{ filter['id'] }}"
|
||||
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
|
||||
placeholder="{{ filter['placeholder'] }}"
|
||||
pattern="{{ filter['pattern'] }}"
|
||||
required />
|
||||
</div>
|
||||
<!-- end search inpt-->
|
||||
{% endif %}
|
||||
{% if filter['type'] == 'select' %}
|
||||
<!-- select -->
|
||||
<div class="flex flex-col relative col-span-12">
|
||||
<h5 class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300">
|
||||
{{ filter['name'] }}
|
||||
</h5>
|
||||
<button aria-controls="filter-{{ filter['id'] }}"
|
||||
data-global-config-setting-select="{{ filter['id'] }}"
|
||||
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
|
||||
<span aria-description="current filter state value"
|
||||
id="global-config-{{ filter['id'] }}"
|
||||
data-name="global-config-{{ filter['id'] }}"
|
||||
data-global-config-setting-select-text="{{ filter['id'] }}">{{ filter['value'] }}</span>
|
||||
<!-- chevron -->
|
||||
<svg data-global-config-setting-select="{{ filter['id'] }}"
|
||||
class="transition-transform h-4 w-4 fill-gray-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512">
|
||||
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
|
||||
</svg>
|
||||
</button>
|
||||
<!-- end chevron -->
|
||||
<!-- dropdown-->
|
||||
<div id="filter-{{ filter['id'] }}"
|
||||
role="listbox"
|
||||
data-global-config-setting-select-dropdown="{{ filter['id'] }}"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
|
||||
{% for value in filter['values'] %}
|
||||
<button role="option"
|
||||
data-global-config-setting-select-dropdown-btn="{{ filter['id'] }}"
|
||||
value="{{ value }}"
|
||||
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
|
||||
{{ value }}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<!-- end dropdown-->
|
||||
</div>
|
||||
<!-- end select -->
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- end filter -->
|
||||
|
||||
<div data-global-config-plugins-container
|
||||
class="col-span-12 gap-y-4 grid grid-cols-12">
|
||||
<!-- form global conf -->
|
||||
<form data-global-config-form
|
||||
id="form-edit-global-configs"
|
||||
method="POST"
|
||||
class="flex flex-col justify-between overflow-hidden overflow-y-auto max-h-135 md:max-h-160 dark:brightness-110 col-span-12 break-words bg-white shadow-xl p-4 dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
|
||||
class="flex flex-col justify-between overflow-hidden overflow-y-auto dark:brightness-110 col-span-12 break-words bg-white shadow-xl p-4 dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
||||
<!-- plugin item -->
|
||||
{% include "settings_plugins.html" %}
|
||||
|
|
|
|||
2
src/ui/templates/services.html
vendored
2
src/ui/templates/services.html
vendored
|
|
@ -228,7 +228,7 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
<h6 data-services-method="{{ service["SERVER_NAME"]['method'] }}"
|
||||
class="text-center sm:text-left mb-2 font-semibold text-gray-600 dark:text-white/80">
|
||||
class="text-left sm:mb-2 font-semibold text-gray-600 dark:text-white/80">
|
||||
{{ service["SERVER_NAME"]['method'] }}
|
||||
</h6>
|
||||
{% set details = [
|
||||
|
|
|
|||
54
src/ui/templates/services_modal.html
vendored
54
src/ui/templates/services_modal.html
vendored
|
|
@ -1,17 +1,17 @@
|
|||
<!-- modal -->
|
||||
<div data-service-content="settings"
|
||||
<div data-services-plugins-container
|
||||
data-services-modal
|
||||
class="dark:brightness-110 hidden w-screen h-screen fixed bg-gray-600/50 z-[1001] top-0 left-0 justify-center items-center">
|
||||
<div data-services-modal-card
|
||||
class="overflow-y-auto mx-0 sm:mx-6 lg:mx-8 my-3 px-4 pt-4 pb-8 w-full sm:min-w-[500px] h-[90vh] flex flex-col break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
|
||||
<div class="w-full flex justify-between mb-2">
|
||||
<div class="flex justify-start items-center">
|
||||
class="overflow-y-auto mx-0 sm:mx-6 lg:mx-8 my-3 px-3 sm:px-4 pt-4 pb-8 w-full h-fit sm:min-w-[500px] max-w-[1000px] max-h-[95vh] md:max-h-[90vh] flex flex-col break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
|
||||
<div class="w-full flex justify-between items-start mb-2">
|
||||
<div class="flex flex-col sm:flex-row justify-start items-start sm:items-center">
|
||||
<p data-services-modal-title
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 dark:text-gray-200 mb-1 font-sans font-semibold leading-normal uppercase text-md">
|
||||
SERVICE MODAL
|
||||
</p>
|
||||
<button data-toggle-draft-btn
|
||||
class="transition hover:brightness-75 dark:hover:brightness-110 ml-4 flex items-center border border-gray-700 dark:border-gray-300 rounded py-1 px-2">
|
||||
class="transition hover:brightness-75 dark:hover:brightness-110 sm:ml-4 flex items-center border border-gray-700 dark:border-gray-300 rounded py-1 px-2">
|
||||
<p data-toggle-draft="true"
|
||||
class="hidden dark:text-gray-300 mb-0 mr-2 pointer-events-none">Draft</p>
|
||||
<p data-toggle-draft="false"
|
||||
|
|
@ -43,26 +43,33 @@
|
|||
</button>
|
||||
</div>
|
||||
<div data-services-tabs-header
|
||||
class="flex flex-col sm:flex-row justify-start items-start sm:items-center gap-x-4 gap-y-2 my-3">
|
||||
<h5 class="transition duration-300 ease-in-out dark:opacity-90 ml-2 font-bold text-md uppercase dark:text-white mb-0">
|
||||
CONFIGS
|
||||
</h5>
|
||||
<!-- search inpt-->
|
||||
<div class="flex relative">
|
||||
<label class="sr-only" for="settings-filter">search</label>
|
||||
<input type="text"
|
||||
id="settings-filter"
|
||||
name="settings-filter"
|
||||
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
|
||||
placeholder="key words"
|
||||
pattern="(.*?)"
|
||||
required />
|
||||
class="flex flex-col">
|
||||
<div class="flex flex-col sm:flex-row justify-start w-full items-start sm:items-center gap-y-3 gap-x-4">
|
||||
<div class="w-full sm:min-w-[250px] max-w-[300px]">
|
||||
{% include "settings_tabs.html" %}
|
||||
</div>
|
||||
<!-- search inpt-->
|
||||
<div class="flex relative w-full max-w-[200px]">
|
||||
<label class="sr-only" for="settings-filter">search</label>
|
||||
<input type="text"
|
||||
id="settings-filter"
|
||||
name="settings-filter"
|
||||
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
|
||||
placeholder="search by keyword"
|
||||
pattern="(.*?)"
|
||||
required />
|
||||
</div>
|
||||
<!-- end search inpt-->
|
||||
</div>
|
||||
|
||||
<div class="w-full min-w-[300px] my-1 sm:my-0">
|
||||
<hr class="separator" />
|
||||
</div>
|
||||
<!-- end search inpt-->
|
||||
</div>
|
||||
{% include "settings_tabs.html" %}
|
||||
|
||||
|
||||
<div data-services-nomatch
|
||||
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
|
||||
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
|
||||
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
|
|
@ -77,13 +84,14 @@
|
|||
</div>
|
||||
<!-- new and edit form -->
|
||||
<form data-services-modal-form
|
||||
class="w-full h-full flex flex-col justify-between"
|
||||
class="w-full h-[90vh] overflow-auto flex flex-col justify-between"
|
||||
id="form-new"
|
||||
method="POST">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
||||
<input type="hidden" id="operation" value="new" name="operation" />
|
||||
<input type="hidden" value="new" name="OLD_SERVER_NAME" />
|
||||
<input type="hidden" value="no" name="is_draft" />
|
||||
|
||||
{% include "settings_plugins.html" %}
|
||||
<!-- action button -->
|
||||
<div class="w-full justify-center flex mt-10">
|
||||
|
|
|
|||
13
src/ui/templates/settings_plugins.html
vendored
13
src/ui/templates/settings_plugins.html
vendored
|
|
@ -3,7 +3,7 @@
|
|||
{% for plugin in plugins %}
|
||||
<div data-plugin-item="{{ plugin['id'] }}"
|
||||
id="{{ plugin['id'] }}"
|
||||
class="{% if loop.index != 1 %}hidden{% endif %} w-full">
|
||||
class="{% if loop.index != 1 %}hidden{% endif %} w-full px-1">
|
||||
<!-- title and desc -->
|
||||
<div class="col-span-12" data-setting-header>
|
||||
{% if (plugin['type'] == "pro" and not is_pro_version) or (plugin['type'] == "pro" and is_pro_version and not pro_status) %}
|
||||
|
|
@ -56,7 +56,8 @@
|
|||
== "global-config" and value['context'] == "global" and not value['multiple'] or setting != "IS_DRAFT" and current_endpoint ==
|
||||
"services" and value['context'] == "multisite" and not value['multiple'] %}
|
||||
<div data-setting-container
|
||||
class="mx-0 sm:mx-4 my-2 col-span-12 md:mx-6 md:my-3 md:col-span-6 2xl:mx-6 2xl:my-3 2xl:col-span-4"
|
||||
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"] }}">
|
||||
<!-- title and info -->
|
||||
<div class="flex items-center my-1 relative z-10">
|
||||
|
|
@ -250,8 +251,8 @@
|
|||
{% for multiple in multList %}
|
||||
<!-- plugin multiple handler -->
|
||||
<div data-multiple-handler
|
||||
class="flex items-center mx-0 sm:mx-4 md:mx-6 md:my-3 my-2 2xl:mx-6 2xl:my-3 col-span-12 ">
|
||||
<h5 class="input-title">{{ multiple }}</h5>
|
||||
class="flex items-center mx-0 sm:mx-4 md:mx-6 mb-2 mt-5 2xl:mx-6 col-span-12 ">
|
||||
<h5 class="input-title max-w-[150px] sm:max-w-[350px]">{{ multiple }}</h5>
|
||||
<button data-{{ 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>
|
||||
|
|
@ -261,14 +262,14 @@
|
|||
</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-8 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 mb-4 mt-2 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 current_endpoint
|
||||
== "global-config" and value['context'] == "global" and value['multiple'] == multiple or current_endpoint ==
|
||||
"services" and value['context'] == "multisite" and value['multiple'] == multiple %}
|
||||
<div data-setting-container="{{ setting }}_SCHEMA"
|
||||
class="mx-0 sm:mx-4 my-2 col-span-12 md:mx-6 md:my-3 md:col-span-6 2xl:mx-6 2xl:my-3 2xl:col-span-4"
|
||||
class="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">
|
||||
|
|
|
|||
66
src/ui/templates/settings_tabs.html
vendored
66
src/ui/templates/settings_tabs.html
vendored
|
|
@ -1,48 +1,14 @@
|
|||
{% set current_endpoint = current_endpoint or url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
|
||||
<div data-{{ current_endpoint }}-tabs class="col-span-12 grid grid-cols-12 {% if current_endpoint == 'services' %}mb-4{% endif %}">
|
||||
<!-- desktop tabs -->
|
||||
<div role="tablist" data-{{ current_endpoint }}-tabs-desktop class="hidden md:block col-span-12">
|
||||
<!-- tabs -->
|
||||
{% for plugin in plugins %}
|
||||
{% if current_endpoint == "services" and plugin["settings"]
|
||||
and check_settings(plugin["settings"], "multisite") or current_endpoint == "global-config" and plugin["settings"]
|
||||
and check_settings(plugin["settings"], "global") %}
|
||||
<button role="tab"
|
||||
data-tab-handler="{{ plugin['id'] }}"
|
||||
class="{% if loop.first %}active{% endif %} settings-tabs-tab-btn">
|
||||
<span class="w-full flex justify-between items-center">
|
||||
<!-- text and icon -->
|
||||
<span class="settings-tabs-name">{{ plugin['name'] }}</span>
|
||||
<svg data-popover-btn="{{ plugin['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">
|
||||
<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>
|
||||
<!-- end text and icon -->
|
||||
<!-- popover -->
|
||||
<span data-popover-content="{{ plugin['name'] }}"
|
||||
class="settings-tabs-popover-container hidden">
|
||||
<span class="settings-tabs-popover-text">{{ plugin['description'] }}</span>
|
||||
</span>
|
||||
<!-- end popover -->
|
||||
</span>
|
||||
</button>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<!--end tabs-->
|
||||
</div>
|
||||
<!-- end desktop tabs -->
|
||||
<!-- mobile tabs -->
|
||||
<div class="md:hidden relative col-span-12 h-full">
|
||||
<div data-{{ current_endpoint }}-tabs class="col-span-12 grid grid-cols-12">
|
||||
<div class="relative col-span-12 h-full">
|
||||
<button data-tab-dropdown-btn
|
||||
aria-controls="tab-dropdown-mobile"
|
||||
class="settings-tabs-mobile-btn">
|
||||
<span aria-description="current tab" class="settings-tabs-mobile-btn-text">
|
||||
aria-controls="tab-dropdown"
|
||||
class="settings-tabs-btn">
|
||||
<span aria-description="current tab" class="settings-tabs-btn-text">
|
||||
{% if current_endpoint == "global-config" %}general{% endif %}
|
||||
</span>
|
||||
<!-- chevron -->
|
||||
<svg class="transition-transform h-4 w-4 fill-primary dark:fill-gray-300"
|
||||
<svg data-tab-dropdown-arrow class="transition-transform h-4 w-4 fill-primary dark:fill-gray-300"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512">
|
||||
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
|
||||
|
|
@ -50,34 +16,24 @@
|
|||
<!-- end chevron -->
|
||||
</button>
|
||||
<!-- dropdown-->
|
||||
<div id="tab-dropdown-mobile"
|
||||
<div id="tab-dropdown"
|
||||
role="listbox"
|
||||
data-tab-dropdown
|
||||
class="hidden z-100 absolute flex-col w-full overflow-hidden overflow-y-auto max-h-90">
|
||||
class="hidden z-100 absolute flex-col w-full overflow-hidden overflow-y-auto h-90 max-h-[50vh]">
|
||||
{% set first_el = "True" %}
|
||||
{% for plugin in plugins %}
|
||||
{% if current_endpoint == "services" and plugin["settings"]
|
||||
and check_settings(plugin["settings"], "multisite") or current_endpoint == "global-config" and plugin["settings"]
|
||||
and check_settings(plugin["settings"], "global") %}
|
||||
{% if loop.first %}
|
||||
<button role="option"
|
||||
data-tab-handler-mobile="{{ plugin['id'] }}"
|
||||
data-tab-handler="{{ plugin['id'] }}"
|
||||
data-select="false"
|
||||
id="edit-{{ current_endpoint }}-{{ plugin['id'] }}-tab"
|
||||
class="active first settings-tabs-mobile-dropdown-btn">{{ plugin['name'] }}</button>
|
||||
{% else %}
|
||||
<button role="option"
|
||||
data-tab-handler-mobile="{{ plugin['id'] }}"
|
||||
data-select="false"
|
||||
id="edit-{{ current_endpoint }}-{{ plugin['id'] }}-tab"
|
||||
class="settings-tabs-mobile-dropdown-btn {% if loop.index == loop.length %}rounded-b{% endif %}">
|
||||
{{ plugin['name'] }}
|
||||
</button>
|
||||
{% endif %}
|
||||
class=" {% if loop.first %}
|
||||
active first{% endif%} {% if loop.last%} last {% endif%} settings-tabs-dropdown-btn">{{ plugin['name'] }}</button>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<!-- end dropdown-->
|
||||
</div>
|
||||
<!-- end mobile tabs -->
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ from selenium.webdriver.support.ui import WebDriverWait
|
|||
from selenium.webdriver.remote.webelement import WebElement
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.common.exceptions import ElementClickInterceptedException, TimeoutException, WebDriverException
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
|
||||
|
||||
def safe_get_element(driver, by: str, selector: str, *, driver_wait: Optional[WebDriverWait] = None, multiple: bool = False, error: bool = False) -> Union[WebElement, List[WebElement]]:
|
||||
|
|
@ -61,7 +60,7 @@ def assert_button_click(driver, button: Union[str, WebElement], by: str = "xpath
|
|||
|
||||
sleep(0.5)
|
||||
|
||||
ActionChains(driver).move_to_element(button).click(button).perform()
|
||||
button.click()
|
||||
|
||||
clicked = True
|
||||
return clicked
|
||||
|
|
|
|||
Loading…
Reference in a new issue