mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
precommit + filter plugin by type
This commit is contained in:
parent
6f17203b4d
commit
393f557d52
27 changed files with 209 additions and 64 deletions
|
|
@ -15,7 +15,10 @@ def pre_render(**kwargs):
|
|||
}
|
||||
except BaseException:
|
||||
print(format_exc(), flush=True)
|
||||
return {"counter_failed_challenges": {"value": "unknown", "title": "Challenge", "subtitle": "Failed", "subtitle_color": "info", "svg_color": "blue"}, "error" : format_exc()}
|
||||
return {
|
||||
"counter_failed_challenges": {"value": "unknown", "title": "Challenge", "subtitle": "Failed", "subtitle_color": "info", "svg_color": "blue"},
|
||||
"error": format_exc(),
|
||||
}
|
||||
|
||||
|
||||
def antibot(**kwargs):
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from datetime import datetime
|
|||
from json import loads
|
||||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(app, *args, **kwargs):
|
||||
try:
|
||||
data = loads(app.config["DB"].get_job_cache_file("backup-data", "backup.json") or "{}")
|
||||
|
|
@ -12,7 +13,8 @@ def pre_render(app, *args, **kwargs):
|
|||
return data
|
||||
except BaseException:
|
||||
print(format_exc(), flush=True)
|
||||
return {"date": None, "files": [], "error" : format_exc()}
|
||||
return {"date": None, "files": [], "error": format_exc()}
|
||||
|
||||
|
||||
def backup(**kwargs):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from operator import itemgetter
|
||||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
try:
|
||||
# Here we will have a list { 'counter_403': X, 'counter_401': Y ... }
|
||||
|
|
@ -10,7 +11,7 @@ def pre_render(**kwargs):
|
|||
format_data.sort(key=itemgetter("count"), reverse=True)
|
||||
return {"top_bad_behavior": format_data}
|
||||
except BaseException:
|
||||
print(format_exc(), flush=True)
|
||||
print(format_exc(), flush=True)
|
||||
return {"top_bad_behavior": "unknown", "error": format_exc()}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
metrics = {
|
||||
"counter_blacklist_url": {"value": "unknown", "title": "URL", "subtitle": "denied", "subtitle_color": "error", "svg_color": "red"},
|
||||
|
|
@ -15,7 +16,7 @@ def pre_render(**kwargs):
|
|||
metrics[key]["value"] = data.get(key, 0)
|
||||
return metrics
|
||||
except BaseException:
|
||||
print(format_exc(), flush=True)
|
||||
print(format_exc(), flush=True)
|
||||
metrics["error"] = format_exc()
|
||||
return metrics
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
try:
|
||||
ping_data = kwargs["app"].config["INSTANCES"].get_ping("bunkernet")
|
||||
return {"ping_status": {"title": "BUNKERNET STATUS", "value": ping_data["status"]}}
|
||||
except BaseException:
|
||||
print(format_exc(), flush=True)
|
||||
print(format_exc(), flush=True)
|
||||
return {"ping_status": {"title": "BUNKERNET STATUS", "value": "error"}, "error": format_exc()}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
try:
|
||||
data = kwargs["app"].config["INSTANCES"].get_metrics("cors")
|
||||
|
|
@ -14,8 +15,11 @@ def pre_render(**kwargs):
|
|||
}
|
||||
|
||||
except BaseException:
|
||||
print(format_exc(), flush=True)
|
||||
return {"counter_failed_cors": {"value": "unknown", "title": "CORS", "subtitle": "request blocked", "subtitle_color": "error", "svg_color": "red"}, "error" : format_exc()}
|
||||
print(format_exc(), flush=True)
|
||||
return {
|
||||
"counter_failed_cors": {"value": "unknown", "title": "CORS", "subtitle": "request blocked", "subtitle_color": "error", "svg_color": "red"},
|
||||
"error": format_exc(),
|
||||
}
|
||||
|
||||
|
||||
def cors(**kwargs):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
try:
|
||||
data = kwargs["app"].config["INSTANCES"].get_metrics("country")
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
try:
|
||||
data = kwargs["app"].config["INSTANCES"].get_metrics("dnsbl")
|
||||
|
|
@ -13,8 +14,11 @@ def pre_render(**kwargs):
|
|||
}
|
||||
}
|
||||
except BaseException:
|
||||
print(format_exc(), flush=True)
|
||||
return {"counter_failed_dnsbl": {"value": "unknown", "title": "DNSBL", "subtitle": "request blocked", "subtitle_color": "error", "svg_color": "red"}, "error" : format_exc()}
|
||||
print(format_exc(), flush=True)
|
||||
return {
|
||||
"counter_failed_dnsbl": {"value": "unknown", "title": "DNSBL", "subtitle": "request blocked", "subtitle_color": "error", "svg_color": "red"},
|
||||
"error": format_exc(),
|
||||
}
|
||||
|
||||
|
||||
def dnsbl(**kwargs):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from operator import itemgetter
|
||||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
try:
|
||||
# Here we will have a list { 'counter_403': X, 'counter_401': Y ... }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
try:
|
||||
data = kwargs["app"].config["INSTANCES"].get_metrics("greylist")
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from operator import itemgetter
|
||||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
try:
|
||||
# Here we will have a list { 'limit_uri_url1': X, 'limit_uri_url2': Y ... }
|
||||
|
|
@ -17,7 +18,7 @@ def pre_render(**kwargs):
|
|||
format_data.sort(key=itemgetter("count"), reverse=True)
|
||||
return {"top_limit": format_data}
|
||||
except BaseException:
|
||||
print(format_exc(), flush=True)
|
||||
print(format_exc(), flush=True)
|
||||
return {"top_limit": [], "error": format_exc()}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
try:
|
||||
data = kwargs["app"].config["INSTANCES"].get_metrics("misc")
|
||||
|
|
@ -21,7 +22,7 @@ def pre_render(**kwargs):
|
|||
},
|
||||
}
|
||||
except BaseException:
|
||||
print(format_exc(), flush=True)
|
||||
print(format_exc(), flush=True)
|
||||
return {
|
||||
"counter_failed_default": {
|
||||
"value": "unknown",
|
||||
|
|
@ -31,7 +32,7 @@ def pre_render(**kwargs):
|
|||
"svg_color": "sky",
|
||||
},
|
||||
"counter_failed_method": {"value": "unknown", "title": "DISALLOWED METHODS", "subtitle": "count", "subtitle_color": "info", "svg_color": "lime"},
|
||||
"error" : format_exc()
|
||||
"error": format_exc(),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
ping = {}
|
||||
data = {}
|
||||
|
|
@ -25,13 +26,13 @@ def pre_render(**kwargs):
|
|||
}
|
||||
|
||||
except BaseException:
|
||||
print(format_exc(), flush=True)
|
||||
error += format_exc()
|
||||
print(format_exc(), flush=True)
|
||||
error += format_exc()
|
||||
data = {"counter_redis_nb_keys": {"value": "unknown", "title": "REDIS KEYS", "subtitle": "total number", "subtitle_color": "info", "svg_color": "sky"}}
|
||||
|
||||
if error:
|
||||
return ping | data | {"error": error}
|
||||
|
||||
|
||||
return ping | data
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from operator import itemgetter
|
||||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
try:
|
||||
# Here we will have a list { 'counter_403': X, 'counter_401': Y ... }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from traceback import format_exc
|
||||
|
||||
|
||||
def pre_render(**kwargs):
|
||||
try:
|
||||
data = kwargs["app"].config["INSTANCES"].get_metrics("whitelist")
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ def generate_external_plugins(plugins: List[Dict[str, Any]], *, original_path: U
|
|||
if not ret:
|
||||
logger.error(f"Sending {'pro ' if pro else ''}external plugins failed, configuration will not work as expected...")
|
||||
|
||||
|
||||
def generate_caches(plugins: List[Any], db: Database):
|
||||
for plugin in plugins:
|
||||
job_cache_files = db.get_jobs_cache_files(plugin_id=plugin["id"])
|
||||
|
|
@ -250,6 +251,7 @@ def generate_caches(plugins: List[Any], db: Database):
|
|||
logger.debug(f"Removing empty directory {file}")
|
||||
rmtree(file, ignore_errors=True)
|
||||
|
||||
|
||||
def api_to_instance(api):
|
||||
hostname_port = api.endpoint.replace("http://", "").replace("https://", "").replace("/", "").split(":")
|
||||
return {
|
||||
|
|
@ -257,6 +259,7 @@ def api_to_instance(api):
|
|||
"env": {"API_HTTP_PORT": int(hostname_port[1]), "API_SERVER_NAME": api.host},
|
||||
}
|
||||
|
||||
|
||||
def run_in_slave_mode(db: Database, dotenv_env: Dict[str, Any]):
|
||||
# Instantiate db
|
||||
db = Database(logger, sqlalchemy_string=dotenv_env.get("DATABASE_URI", getenv("DATABASE_URI", None)))
|
||||
|
|
@ -272,7 +275,7 @@ def run_in_slave_mode(db: Database, dotenv_env: Dict[str, Any]):
|
|||
logger.warning("Database doesn't have any config saved yet, retrying in 5s ...")
|
||||
sleep(5)
|
||||
env = db.get_config()
|
||||
|
||||
|
||||
# Download plugins
|
||||
pro_plugins = db.get_plugins(_type="pro", with_data=True)
|
||||
generate_external_plugins(pro_plugins, original_path=PRO_PLUGINS_PATH)
|
||||
|
|
@ -314,6 +317,7 @@ def run_in_slave_mode(db: Database, dotenv_env: Dict[str, Any]):
|
|||
while True:
|
||||
sleep(5)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
# Don't execute if pid file exists
|
||||
|
|
@ -393,7 +397,7 @@ if __name__ == "__main__":
|
|||
|
||||
# Override instances if needed
|
||||
override_instances = env.get("OVERRIDE_INSTANCES", "")
|
||||
apis=[]
|
||||
apis = []
|
||||
if override_instances:
|
||||
for instance in override_instances.split(" "):
|
||||
apis.append(API(instance))
|
||||
|
|
|
|||
|
|
@ -637,7 +637,7 @@ def home():
|
|||
config = app.config["CONFIG"].get_config(with_drafts=True)
|
||||
override_instances = config["OVERRIDE_INSTANCES"]["value"] != ""
|
||||
instances = app.config["INSTANCES"].get_instances(override_instances=override_instances)
|
||||
|
||||
|
||||
instance_health_count = 0
|
||||
|
||||
for instance in instances:
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ from typing import Any, List, Optional, Tuple, Union
|
|||
|
||||
from API import API # type: ignore
|
||||
from ApiCaller import ApiCaller # type: ignore
|
||||
from dotenv import dotenv_values # type: ignore
|
||||
from Database import Database # type: ignore
|
||||
from dotenv import dotenv_values # type: ignore
|
||||
|
||||
|
||||
class Instance:
|
||||
|
|
@ -168,13 +167,12 @@ class Instances:
|
|||
ApiCaller(
|
||||
[
|
||||
API(
|
||||
f"http://{instance['hostname']}:{str(instance['port'])}",
|
||||
f"http://{instance['hostname']}:{instance['port']}",
|
||||
instance["server_name"],
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
)
|
||||
return instances
|
||||
# Docker instances (containers or services)
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -61,7 +61,6 @@ class TabPopover {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class SubmitAccount {
|
||||
constructor() {
|
||||
this.pwEl = document.querySelector("#admin_password");
|
||||
|
|
@ -107,7 +106,7 @@ class SubmitAccount {
|
|||
"focus:valid:!ring-red-500",
|
||||
"active:!border-red-500",
|
||||
"active:valid:!border-red-500",
|
||||
"valid:!border-red-500"
|
||||
"valid:!border-red-500",
|
||||
);
|
||||
this.pwAlertEl.classList.add("opacity-0");
|
||||
this.pwAlertEl.setAttribute("aria-hidden", "true");
|
||||
|
|
@ -121,7 +120,7 @@ class SubmitAccount {
|
|||
"focus:valid:!ring-red-500",
|
||||
"active:!border-red-500",
|
||||
"active:valid:!border-red-500",
|
||||
"valid:!border-red-500"
|
||||
"valid:!border-red-500",
|
||||
);
|
||||
this.pwAlertEl.classList.remove("opacity-0");
|
||||
this.pwAlertEl.setAttribute("aria-hidden", "false");
|
||||
|
|
@ -139,14 +138,14 @@ class PwBtn {
|
|||
const passwordContainer = e.target.closest("[data-input-group]");
|
||||
const inpEl = passwordContainer.querySelector("input");
|
||||
const invBtn = passwordContainer.querySelector(
|
||||
'[data-setting-password="invisible"]'
|
||||
'[data-setting-password="invisible"]',
|
||||
);
|
||||
const visBtn = passwordContainer.querySelector(
|
||||
'[data-setting-password="visible"]'
|
||||
'[data-setting-password="visible"]',
|
||||
);
|
||||
inpEl.setAttribute(
|
||||
"type",
|
||||
inpEl.getAttribute("type") === "password" ? "text" : "password"
|
||||
inpEl.getAttribute("type") === "password" ? "text" : "password",
|
||||
);
|
||||
|
||||
if (inpEl.getAttribute("type") === "password") {
|
||||
|
|
|
|||
|
|
@ -1523,6 +1523,18 @@ const checkServiceModalKeyword = new CheckNoMatchFilter(
|
|||
document.querySelector("[data-services-nomatch]"),
|
||||
);
|
||||
|
||||
const checkServiceModalSelect = new CheckNoMatchFilter(
|
||||
document.querySelectorAll(
|
||||
"button[data-services-setting-select-dropdown-btn]",
|
||||
),
|
||||
"select",
|
||||
document
|
||||
.querySelector("[data-services-modal-form]")
|
||||
.querySelectorAll("[data-plugin-item]"),
|
||||
document.querySelector("[data-services-modal-form]"),
|
||||
document.querySelector("[data-services-nomatch]"),
|
||||
);
|
||||
|
||||
try {
|
||||
const checkServiceCardKeyword = new CheckNoMatchFilter(
|
||||
document.querySelectorAll("input#service-name-keyword"),
|
||||
|
|
|
|||
|
|
@ -6,13 +6,15 @@ class Popover {
|
|||
}
|
||||
|
||||
init() {
|
||||
window.addEventListener("scroll", (e) => {
|
||||
try {
|
||||
this.hidePopover(this.relateBtn);
|
||||
}catch(e) {
|
||||
|
||||
}
|
||||
}, true);
|
||||
window.addEventListener(
|
||||
"scroll",
|
||||
(e) => {
|
||||
try {
|
||||
this.hidePopover(this.relateBtn);
|
||||
} catch (e) {}
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
window.addEventListener("pointerover", (e) => {
|
||||
//POPOVER LOGIC
|
||||
|
|
@ -48,7 +50,7 @@ class Popover {
|
|||
const popover = btn.parentElement.querySelector(
|
||||
`[data-popover-content=${popoverName}]`,
|
||||
);
|
||||
|
||||
|
||||
popover.classList.add("transition-all", "delay-200", "opacity-0");
|
||||
popover.classList.remove("hidden");
|
||||
|
||||
|
|
@ -82,10 +84,13 @@ class Popover {
|
|||
const btnTop = btnRect.y;
|
||||
const btnLeft = btnRect.x;
|
||||
|
||||
popover.style.top = `${btnTop - popover.getBoundingClientRect().height + 20}px`;
|
||||
popover.style.left = `${btnLeft - popover.getBoundingClientRect().width / 3}px`;
|
||||
popover.style.top = `${
|
||||
btnTop - popover.getBoundingClientRect().height + 20
|
||||
}px`;
|
||||
popover.style.left = `${
|
||||
btnLeft - popover.getBoundingClientRect().width / 3
|
||||
}px`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TabsSelect {
|
||||
|
|
@ -157,10 +162,7 @@ class TabsSelect {
|
|||
}, 100);
|
||||
}
|
||||
}
|
||||
}catch(e) {
|
||||
|
||||
}
|
||||
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
resetTabsStyle() {
|
||||
|
|
@ -265,6 +267,9 @@ class FilterSettings {
|
|||
this.contextTxtEl = document.querySelector(
|
||||
`span[data-${this.prefix}-setting-select-text="context"]`,
|
||||
);
|
||||
this.typeTxtEl = document.querySelector(
|
||||
`span[data-${this.prefix}-setting-select-text="type"]`,
|
||||
);
|
||||
this.tabContainer = tabContainer;
|
||||
this.contentContainer = contentContainer;
|
||||
this.tabsEls = this.tabContainer.querySelectorAll(
|
||||
|
|
@ -285,12 +290,18 @@ class FilterSettings {
|
|||
window.addEventListener("click", (e) => {
|
||||
try {
|
||||
if (
|
||||
e.target.hasAttribute(
|
||||
"data-global-config-setting-select-dropdown-btn",
|
||||
(e.target.hasAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`,
|
||||
) &&
|
||||
e.target.getAttribute(
|
||||
"data-global-config-setting-select-dropdown-btn",
|
||||
) === "context"
|
||||
e.target.getAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`,
|
||||
) === `context`) ||
|
||||
(e.target.hasAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`,
|
||||
) &&
|
||||
e.target.getAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`,
|
||||
) === `type`)
|
||||
) {
|
||||
return this.runFilter();
|
||||
}
|
||||
|
|
@ -333,7 +344,7 @@ class FilterSettings {
|
|||
|
||||
if (currContextFilter !== "all") {
|
||||
const settingContext = setting
|
||||
.getAttribute("data-global-config-context")
|
||||
.getAttribute(`data-${this.prefix}-context`)
|
||||
.toLowerCase();
|
||||
if (settingContext !== currContextFilter) {
|
||||
needToHide = true;
|
||||
|
|
@ -342,6 +353,22 @@ class FilterSettings {
|
|||
}
|
||||
} catch (e) {}
|
||||
|
||||
// check type if filter exists
|
||||
try {
|
||||
if (this.typeTxtEl) {
|
||||
const currTypeFilter = this.typeTxtEl.textContent.toLowerCase();
|
||||
|
||||
if (currTypeFilter !== "all") {
|
||||
const settingContext = setting
|
||||
.getAttribute(`data-${this.prefix}-type`)
|
||||
.toLowerCase();
|
||||
if (settingContext !== currTypeFilter) {
|
||||
needToHide = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
if (needToHide) {
|
||||
setting.classList.add("hidden");
|
||||
settingHiddenCount++;
|
||||
|
|
@ -373,7 +400,7 @@ class FilterSettings {
|
|||
|
||||
if (currContextFilter !== "all") {
|
||||
const settingContext = multSetting
|
||||
.getAttribute("data-global-config-context")
|
||||
.getAttribute(`data-${this.prefix}-context`)
|
||||
.toLowerCase();
|
||||
if (settingContext !== currContextFilter) {
|
||||
needToHideMult = true;
|
||||
|
|
@ -382,6 +409,21 @@ class FilterSettings {
|
|||
}
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
if (this.typeTxtEl) {
|
||||
const currtypeFilter = this.typeTxtEl.textContent.toLowerCase();
|
||||
|
||||
if (currtypeFilter !== "all") {
|
||||
const settingtype = multSetting
|
||||
.getAttribute(`data-${this.prefix}-type`)
|
||||
.toLowerCase();
|
||||
if (settingtype !== currtypeFilter) {
|
||||
needToHideMult = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
if (needToHideMult) {
|
||||
multSetting.classList.add("hidden");
|
||||
multSettingHiddenCount++;
|
||||
|
|
@ -443,7 +485,7 @@ class FilterSettings {
|
|||
multTitle.classList.add("hidden");
|
||||
}
|
||||
|
||||
//case no setting or no multiple match, check if match at least tab name
|
||||
// case no setting or no multiple match, check if match at least tab name
|
||||
// if no context, else we don't care about name
|
||||
if (
|
||||
settingCount === settingHiddenCount &&
|
||||
|
|
@ -451,9 +493,21 @@ class FilterSettings {
|
|||
) {
|
||||
const tabName = tab.getAttribute(`data-tab-select-handler`);
|
||||
const tabTxt = tab.textContent.trim().toLowerCase();
|
||||
const tabType = tab.getAttribute(`data-tab-plugin-type`);
|
||||
let needHideTab = false;
|
||||
try {
|
||||
if (this.contextTxtEl.textContent.toLowerCase() !== "all")
|
||||
if (
|
||||
this.contextTxtEl &&
|
||||
this.contextTxtEl.textContent.toLowerCase() !== "all"
|
||||
)
|
||||
needHideTab = true;
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
if (
|
||||
this.typeTxtEl &&
|
||||
this.typeTxtEl.textContent.toLowerCase() !== tabType
|
||||
)
|
||||
needHideTab = true;
|
||||
} catch (e) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@
|
|||
@apply z-[1000] h-fit max-w-[250px] transition-all duration-500 dark:brightness-90 transition rounded-md p-3 -translate-y-7 fixed bg-blue-500;
|
||||
}
|
||||
|
||||
|
||||
.popover-tab {
|
||||
@apply transition-all duration-500 dark:brightness-90 transition z-50 rounded-md p-3 left-0 -translate-y-7 bottom-0 absolute bg-blue-500;
|
||||
}
|
||||
|
|
|
|||
18
src/ui/templates/global_config.html
vendored
18
src/ui/templates/global_config.html
vendored
|
|
@ -29,16 +29,28 @@
|
|||
"global",
|
||||
"multisite"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"name": "Type",
|
||||
"id": "type",
|
||||
"value": "all",
|
||||
"values": [
|
||||
"all",
|
||||
"core",
|
||||
"external",
|
||||
"pro"
|
||||
]
|
||||
}
|
||||
] %}
|
||||
<div data-global-config-filter
|
||||
class="h-fit p-4 col-span-12 md:col-span-6 lg:col-span-5 2xl:col-span-4 3xl: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">
|
||||
class="h-fit p-4 col-span-12 md:col-span-6 3xl:col-span-4 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">
|
||||
<div class="flex flex-col relative col-span-12 md:col-span-6">
|
||||
<h5 class="my-1 transition duration-300 ease-in-out text-sm sm:text-md font-bold m-0 dark:text-gray-200">
|
||||
{{ filter['name'] }}
|
||||
</h5>
|
||||
|
|
@ -55,7 +67,7 @@
|
|||
{% endif %}
|
||||
{% if filter['type'] == 'select' %}
|
||||
<!-- select -->
|
||||
<div class="flex flex-col relative col-span-12">
|
||||
<div class="flex flex-col relative col-span-12 md:col-span-6">
|
||||
<h5 class="my-1 transition duration-300 ease-in-out text-sm sm:text-md font-bold m-0 dark:text-gray-200">
|
||||
{{ filter['name'] }}
|
||||
</h5>
|
||||
|
|
|
|||
48
src/ui/templates/services_modal.html
vendored
48
src/ui/templates/services_modal.html
vendored
|
|
@ -43,20 +43,62 @@
|
|||
</button>
|
||||
</div>
|
||||
<div data-services-tabs-select-header 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="flex flex-col md:flex-row justify-start w-full items-start md:items-end gap-y-3 gap-x-4">
|
||||
<div class="w-full sm:min-w-[250px] max-w-[300px]">{% include "settings_tabs_select.html" %}</div>
|
||||
<div class="flex flex-col sm:flex-row">
|
||||
<!-- search inpt-->
|
||||
<div class="flex relative w-full max-w-[200px]">
|
||||
<div class="sm:mx-2 mb-1 min-w-[200px] flex flex-col relative col-span-12 md:col-span-6">
|
||||
<h5 class="hidden sm:block my-1 transition duration-300 ease-in-out text-sm sm:text-md font-bold m-0 dark:text-gray-200">
|
||||
Search
|
||||
</h5>
|
||||
<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"
|
||||
placeholder="keyword"
|
||||
pattern="(.*?)"
|
||||
required />
|
||||
</div>
|
||||
<!-- end search inpt-->
|
||||
<!-- type plugin -->
|
||||
<div class="hidden mx-2 mb-1 min-w-[200px] sm:flex flex-col relative col-span-12 md:col-span-6">
|
||||
<h5 class="my-1 transition duration-300 ease-in-out text-sm sm:text-md font-bold m-0 dark:text-gray-200">
|
||||
Type
|
||||
</h5>
|
||||
<button aria-controls="filter-type" data-services-setting-select="type" 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="services-type" data-name="services-type" data-services-setting-select-text="type">all</span>
|
||||
<!-- chevron -->
|
||||
<svg data-services-setting-select="type" 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"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- end chevron -->
|
||||
<!-- dropdown-->
|
||||
<div id="filter-type" role="listbox" data-services-setting-select-dropdown="type" class="mt-1 hidden z-100 absolute flex-col w-full translate-y-16 max-h-[350px] overflow-hidden overflow-y-auto">
|
||||
|
||||
<button role="option" data-services-setting-select-dropdown-btn="type" value="all" class="dark:bg-primary bg-primary text-gray-300 border-t rounded-t 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">
|
||||
all
|
||||
</button>
|
||||
|
||||
<button role="option" data-services-setting-select-dropdown-btn="type" value="core" class=" bg-white dark:bg-slate-700 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">
|
||||
core
|
||||
</button>
|
||||
|
||||
<button role="option" data-services-setting-select-dropdown-btn="type" value="external" class=" bg-white dark:bg-slate-700 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">
|
||||
external
|
||||
</button>
|
||||
|
||||
<button role="option" data-services-setting-select-dropdown-btn="type" value="pro" class=" bg-white dark:bg-slate-700 rounded-b 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">
|
||||
pro
|
||||
</button>
|
||||
|
||||
</div>
|
||||
<!-- end dropdown-->
|
||||
</div>
|
||||
<!-- end type plugin-->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="w-full min-w-[300px] my-1 sm:my-0">
|
||||
<hr class="separator" />
|
||||
|
|
|
|||
4
src/ui/templates/settings_plugins.html
vendored
4
src/ui/templates/settings_plugins.html
vendored
|
|
@ -57,7 +57,7 @@
|
|||
{% if multList.append(value['multiple']) %}{% endif %}
|
||||
{% endif %}
|
||||
{% if not value['multiple'] %}
|
||||
<div data-setting-container data-{{ current_endpoint }}-context="{{ value['context'] }}" class="relative mx-0 sm:mx-2 md:mx-3 lg:mx-4 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 }}-type="{{ plugin['type'] }}" data-{{ current_endpoint }}-context="{{ value['context'] }}" class="relative mx-0 sm:mx-2 md:mx-3 lg:mx-4 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>
|
||||
|
|
@ -290,7 +290,7 @@
|
|||
current_endpoint == "global-config"
|
||||
or current_endpoint == "services" and value['context'] == "multisite"
|
||||
) %}
|
||||
<div data-setting-container="{{ setting }}_SCHEMA" data-{{ current_endpoint }}-context="{{ value['context'] }}" class="relative mx-2 md:mx-3 my-2 md:my-3 col-span-12 md:col-span-6 2xl:col-span-4" id="form-edit-{{ current_endpoint }}-{{ value["id"] }}_SCHEMA">
|
||||
<div data-setting-container="{{ setting }}_SCHEMA" data-{{ current_endpoint }}-type="{{ plugin['type'] }}" data-{{ current_endpoint }}-context="{{ value['context'] }}" class="relative mx-2 md:mx-3 my-2 md:my-3 col-span-12 md:col-span-6 2xl:col-span-4" id="form-edit-{{ 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>
|
||||
|
|
|
|||
3
src/ui/templates/settings_tabs_select.html
vendored
3
src/ui/templates/settings_tabs_select.html
vendored
|
|
@ -28,9 +28,10 @@
|
|||
and check_settings(plugin["settings"], "multisite") or current_endpoint == "global-config" %}
|
||||
<button role="option"
|
||||
data-tab-select-handler="{{ plugin['id'] }}"
|
||||
data-tab-plugin-type="{{ plugin['type'] }}"
|
||||
data-select="false"
|
||||
id="edit-{{ current_endpoint }}-{{ plugin['id'] }}-tab"
|
||||
class=" {% if loop.first %}active first{% endif %} {% if loop.last %}last{% endif %} settings-tabs-select-dropdown-btn">
|
||||
class="{% if loop.first %}active first{% endif %} {% if loop.last %}last{% endif %} settings-tabs-select-dropdown-btn">
|
||||
{{ plugin['name'] }}
|
||||
</button>
|
||||
{% endif %}
|
||||
|
|
|
|||
Loading…
Reference in a new issue