mirror of
https://github.com/bunkerity/bunkerized-nginx
synced 2023-12-13 21:30:18 +01:00
commit
e988aacf38
30 changed files with 2001 additions and 4026 deletions
13
README.md
13
README.md
|
@ -3,7 +3,10 @@
|
|||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/bunkerweb-1.4.3-blue" />
|
||||
<img src="https://img.shields.io/github/license/bunkerity/bunkerweb?color=40bb6b" />
|
||||
<img src="https://img.shields.io/github/release/bunkerity/bunkerweb?color=085577" />
|
||||
<img src="https://img.shields.io/github/downloads/bunkerity/bunkerweb/total">
|
||||
<img src="https://img.shields.io/docker/pulls/bunkerity/bunkerweb?color=085577">
|
||||
<img src="https://img.shields.io/github/last-commit/bunkerity/bunkerweb" />
|
||||
<img src="https://img.shields.io/github/workflow/status/bunkerity/bunkerweb/Automatic%20test%2C%20build%2C%20push%20and%20deploy%20%28DEV%29?label=CI%2FCD%20dev" />
|
||||
<img src="https://img.shields.io/github/workflow/status/bunkerity/bunkerweb/Automatic%20test%2C%20build%2C%20push%20and%20deploy%20%28PROD%29?label=CI%2FCD%20prod" />
|
||||
|
@ -262,12 +265,12 @@ BunkerWeb comes with a plugin system to make it possible to easily add new featu
|
|||
|
||||
Here is the list of "official" plugins that we maintain (see the [bunkerweb-plugins](https://github.com/bunkerity/bunkerweb-plugins) repository for more information) :
|
||||
|
||||
| Name | Version | Description | Link |
|
||||
| :------------: | :-----: | :------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------: |
|
||||
| Name | Version | Description | Link |
|
||||
| :------------: | :-----: | :------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------: |
|
||||
| **ClamAV** | 0.1 | Automatically scans uploaded files with the ClamAV antivirus engine and denies the request when a file is detected as malicious. | [bunkerweb-plugins/clamav](https://github.com/bunkerity/bunkerweb-plugins/tree/main/clamav) |
|
||||
| **CrowdSec** | 0.1 | CrowdSec bouncer for BunkerWeb. | [bunkerweb-plugins/crowdsec](https://github.com/bunkerity/bunkerweb-plugins/tree/main/crowdsec) |
|
||||
| **Discord** | 0.1 | Send security notifications to a Discord channel using a Webhook. | [bunkerweb-plugins/discord](https://github.com/bunkerity/bunkerweb-plugins/tree/main/discord) |
|
||||
| **Slack** | 0.1 | Send security notifications to a Slack channel using a Webhook. | [bunkerweb-plugins/slack](https://github.com/bunkerity/bunkerweb-plugins/tree/main/slack) |
|
||||
| **Discord** | 0.1 | Send security notifications to a Discord channel using a Webhook. | [bunkerweb-plugins/discord](https://github.com/bunkerity/bunkerweb-plugins/tree/main/discord) |
|
||||
| **Slack** | 0.1 | Send security notifications to a Slack channel using a Webhook. | [bunkerweb-plugins/slack](https://github.com/bunkerity/bunkerweb-plugins/tree/main/slack) |
|
||||
| **VirusTotal** | 0.1 | Automatically scans uploaded files with the VirusTotal API and denies the request when a file is detected as malicious. | [bunkerweb-plugins/virustotal](https://github.com/bunkerity/bunkerweb-plugins/tree/main/virustotal) |
|
||||
|
||||
You will find more information in the [plugins section](https://docs.bunkerweb.io/latest/plugins) of the documentation.
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
{% if USE_CUSTOM_HTTPS == "yes" +%}
|
||||
{% set os_path = import("os.path") %}
|
||||
{% if USE_CUSTOM_HTTPS == "yes" and os_path.isfile("/data/cache/customcert/{}".format(CUSTOM_HTTPS_CERT.replace("/", "_"))) and os_path.isfile("/data/cache/customcert/{}".format(CUSTOM_HTTPS_KEY.replace("/", "_"))) +%}
|
||||
|
||||
# listen on HTTPS PORT
|
||||
listen 0.0.0.0:{{ HTTPS_PORT }} ssl {% if HTTP2 == "yes" %}http2{% endif %} {% if USE_PROXY_PROTOCOL == "yes" %}proxy_protocol{% endif %};
|
||||
|
||||
# TLS config
|
||||
ssl_certificate {{ CUSTOM_HTTPS_CERT }};
|
||||
ssl_certificate_key {{ CUSTOM_HTTPS_KEY }};
|
||||
ssl_certificate /data/cache/customcert/{{ CUSTOM_HTTPS_CERT.replace("/", "_") }};
|
||||
ssl_certificate_key /data/cache/customcert/{{ CUSTOM_HTTPS_KEY.replace("/", "_") }};
|
||||
ssl_protocols {{ HTTPS_PROTOCOLS }};
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_tickets off;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from os import getenv, makedirs
|
||||
from os import environ, getenv, makedirs, remove
|
||||
from os.path import isfile
|
||||
from shutil import copy
|
||||
from sys import exit as sys_exit, path as sys_path
|
||||
from traceback import format_exc
|
||||
|
||||
|
@ -20,29 +21,86 @@ db = Database(
|
|||
)
|
||||
|
||||
|
||||
def check_cert(cert_path, first_server: str = None):
|
||||
def check_cert(cert_path, key_path, first_server: str = None) -> bool:
|
||||
try:
|
||||
cache_path = (
|
||||
if not cert_path or not key_path:
|
||||
logger.warning(
|
||||
"Both variables CUSTOM_HTTPS_CERT and CUSTOM_HTTPS_KEY have to be set to use custom certificates"
|
||||
)
|
||||
return False
|
||||
elif not isfile(cert_path):
|
||||
logger.warning(
|
||||
f"Certificate file {cert_path} is not a valid file, ignoring the custom certificate"
|
||||
)
|
||||
return False
|
||||
|
||||
cert_cache_path = (
|
||||
f"/var/cache/bunkerweb/customcert/{cert_path.replace('/', '_')}.hash"
|
||||
)
|
||||
current_hash = file_hash(cert_path)
|
||||
if not isfile(cache_path):
|
||||
with open(cache_path, "w") as f:
|
||||
f.write(current_hash)
|
||||
old_hash = file_hash(cache_path)
|
||||
if old_hash == current_hash:
|
||||
cert_hash = file_hash(cert_path)
|
||||
|
||||
if not isfile(cert_cache_path):
|
||||
with open(cert_cache_path, "w") as f:
|
||||
f.write(cert_hash)
|
||||
|
||||
old_hash = file_hash(cert_cache_path)
|
||||
if old_hash == cert_hash:
|
||||
return False
|
||||
with open(cache_path, "w") as f:
|
||||
f.write(current_hash)
|
||||
err = db.update_job_cache(
|
||||
"custom-cert",
|
||||
first_server,
|
||||
f"{cert_path.replace('/', '_')}.hash",
|
||||
current_hash.encode("utf-8"),
|
||||
checksum=current_hash,
|
||||
|
||||
with open(cert_cache_path, "w") as f:
|
||||
f.write(cert_hash)
|
||||
|
||||
copy(cert_path, cert_cache_path.replace(".hash", ""))
|
||||
|
||||
if not isfile(key_path):
|
||||
logger.warning(
|
||||
f"Key file {key_path} is not a valid file, removing the custom certificate ..."
|
||||
)
|
||||
remove(cert_path)
|
||||
remove(cert_cache_path)
|
||||
return False
|
||||
|
||||
key_cache_path = (
|
||||
f"/var/cache/bunkerweb/customcert/{key_path.replace('/', '_')}.hash"
|
||||
)
|
||||
key_hash = file_hash(key_path)
|
||||
|
||||
if not isfile(key_cache_path):
|
||||
with open(key_cache_path, "w") as f:
|
||||
f.write(key_hash)
|
||||
|
||||
old_hash = file_hash(key_cache_path)
|
||||
if old_hash != key_hash:
|
||||
copy(key_path, key_cache_path.replace(".hash", ""))
|
||||
|
||||
with open(key_path, "r") as f:
|
||||
err = db.update_job_cache(
|
||||
"custom-cert",
|
||||
first_server,
|
||||
key_cache_path.replace(".hash", "").split("/")[-1],
|
||||
f.read().encode("utf-8"),
|
||||
checksum=key_hash,
|
||||
)
|
||||
|
||||
if err:
|
||||
logger.warning(
|
||||
f"Couldn't update db cache for {key_path.replace('/', '_')}.hash: {err}"
|
||||
)
|
||||
|
||||
with open(cert_path, "r") as f:
|
||||
err = db.update_job_cache(
|
||||
"custom-cert",
|
||||
first_server,
|
||||
cert_cache_path.replace(".hash", "").split("/")[-1],
|
||||
f.read().encode("utf-8"),
|
||||
checksum=cert_hash,
|
||||
)
|
||||
|
||||
if err:
|
||||
logger.warning(f"Couldn't update db cache: {err}")
|
||||
logger.warning(
|
||||
f"Couldn't update db cache for {cert_path.replace('/', '_')}.hash: {err}"
|
||||
)
|
||||
|
||||
return True
|
||||
except:
|
||||
logger.error(
|
||||
|
@ -59,18 +117,25 @@ try:
|
|||
# Multisite case
|
||||
if getenv("MULTISITE") == "yes":
|
||||
for first_server in getenv("SERVER_NAME").split(" "):
|
||||
if (
|
||||
getenv(first_server + "_USE_CUSTOM_HTTPS", getenv("USE_CUSTOM_HTTPS"))
|
||||
if not first_server or (
|
||||
getenv(
|
||||
f"{first_server}_USE_CUSTOM_HTTPS", getenv("USE_CUSTOM_HTTPS", "no")
|
||||
)
|
||||
!= "yes"
|
||||
):
|
||||
continue
|
||||
if first_server == "":
|
||||
continue
|
||||
cert_path = getenv(first_server + "_CUSTOM_HTTPS_CERT")
|
||||
logger.info(
|
||||
f"Checking if certificate {cert_path} changed ...",
|
||||
|
||||
cert_path = getenv(
|
||||
f"{first_server}_CUSTOM_HTTPS_CERT", getenv("CUSTOM_HTTPS_CERT", "")
|
||||
)
|
||||
need_reload = check_cert(cert_path, first_server)
|
||||
key_path = getenv(
|
||||
f"{first_server}_CUSTOM_HTTPS_KEY", getenv("CUSTOM_HTTPS_KEY", "")
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"Checking certificate {cert_path} ...",
|
||||
)
|
||||
need_reload = check_cert(cert_path, key_path, first_server)
|
||||
if need_reload:
|
||||
logger.info(
|
||||
f"Detected change for certificate {cert_path}",
|
||||
|
@ -78,14 +143,15 @@ try:
|
|||
status = 1
|
||||
else:
|
||||
logger.info(
|
||||
"No change for certificate {cert_path}",
|
||||
f"No change for certificate {cert_path}",
|
||||
)
|
||||
|
||||
# Singlesite case
|
||||
elif getenv("USE_CUSTOM_HTTPS") == "yes" and getenv("SERVER_NAME") != "":
|
||||
cert_path = getenv("CUSTOM_HTTPS_CERT")
|
||||
logger.info(f"Checking if certificate {cert_path} changed ...")
|
||||
need_reload = check_cert(cert_path)
|
||||
cert_path = getenv("CUSTOM_HTTPS_CERT", "")
|
||||
key_path = getenv("CUSTOM_HTTPS_KEY", "")
|
||||
|
||||
logger.info(f"Checking certificate {cert_path} ...")
|
||||
need_reload = check_cert(cert_path, key_path)
|
||||
if need_reload:
|
||||
logger.info(f"Detected change for certificate {cert_path}")
|
||||
status = 1
|
||||
|
|
|
@ -12,7 +12,7 @@ import oracledb
|
|||
from os import _exit, getenv, listdir, makedirs
|
||||
from os.path import dirname, exists
|
||||
from pymysql import install_as_MySQLdb
|
||||
from re import search
|
||||
from re import compile as re_compile
|
||||
from sys import modules, path as sys_path
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
from sqlalchemy import create_engine, inspect
|
||||
|
@ -118,6 +118,7 @@ class Database:
|
|||
self.__sql_session.configure(
|
||||
bind=self.__sql_engine, autoflush=False, expire_on_commit=False
|
||||
)
|
||||
self.suffix_rx = re_compile(r"_\d+$")
|
||||
|
||||
def get_database_uri(self) -> str:
|
||||
return self.database_uri
|
||||
|
@ -351,7 +352,7 @@ class Database:
|
|||
|
||||
for key, value in deepcopy(config).items():
|
||||
suffix = 0
|
||||
if search(r"_\d+$", key):
|
||||
if self.suffix_rx.search(key):
|
||||
suffix = int(key.split("_")[-1])
|
||||
key = key[: -len(str(suffix)) - 1]
|
||||
|
||||
|
@ -488,7 +489,7 @@ class Database:
|
|||
|
||||
for key, value in config.items():
|
||||
suffix = 0
|
||||
if search(r"_\d+$", key):
|
||||
if self.suffix_rx.search(key):
|
||||
suffix = int(key.split("_")[-1])
|
||||
key = key[: -len(str(suffix)) - 1]
|
||||
|
||||
|
@ -637,7 +638,7 @@ class Database:
|
|||
"""Get the config from the database"""
|
||||
with self.__db_session() as session:
|
||||
config = {}
|
||||
db_services = session.query(Services).with_entities(Services.id).all()
|
||||
multisite = []
|
||||
for setting in (
|
||||
session.query(Settings)
|
||||
.with_entities(
|
||||
|
@ -681,39 +682,35 @@ class Database:
|
|||
}
|
||||
)
|
||||
|
||||
if setting.context != "multisite":
|
||||
continue
|
||||
if setting.context == "multisite":
|
||||
multisite.append(setting.id)
|
||||
|
||||
for service in db_services:
|
||||
config[f"{service.id}_{setting.id}"] = (
|
||||
config[setting.id]
|
||||
if methods is False
|
||||
else {
|
||||
"value": config[setting.id]["value"],
|
||||
"method": "default",
|
||||
}
|
||||
)
|
||||
for service in session.query(Services).with_entities(Services.id).all():
|
||||
for key, value in deepcopy(config).items():
|
||||
original_key = key
|
||||
if self.suffix_rx.search(key):
|
||||
suffix = int(key.split("_")[-1])
|
||||
key = key[: -len(str(suffix)) - 1]
|
||||
|
||||
service_settings = (
|
||||
if key not in multisite:
|
||||
continue
|
||||
|
||||
config[f"{service.id}_{original_key}"] = value
|
||||
suffix = 0
|
||||
|
||||
service_setting = (
|
||||
session.query(Services_settings)
|
||||
.with_entities(
|
||||
Services_settings.value,
|
||||
Services_settings.suffix,
|
||||
Services_settings.method,
|
||||
)
|
||||
.filter_by(service_id=service.id, setting_id=setting.id)
|
||||
.all()
|
||||
.filter_by(service_id=service.id, setting_id=key, suffix=suffix)
|
||||
.first()
|
||||
)
|
||||
|
||||
for service_setting in service_settings:
|
||||
config[
|
||||
f"{service.id}_{setting.id}"
|
||||
+ (
|
||||
f"_{service_setting.suffix}"
|
||||
if service_setting.suffix > 0
|
||||
else ""
|
||||
)
|
||||
] = (
|
||||
if service_setting:
|
||||
config[f"{service.id}_{original_key}"] = (
|
||||
service_setting.value
|
||||
if methods is False
|
||||
else {
|
||||
|
|
|
@ -175,9 +175,9 @@ six==1.16.0 \
|
|||
# google-auth
|
||||
# kubernetes
|
||||
# python-dateutil
|
||||
urllib3==1.26.12 \
|
||||
--hash=sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e \
|
||||
--hash=sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997
|
||||
urllib3==1.26.13 \
|
||||
--hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \
|
||||
--hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8
|
||||
# via
|
||||
# docker
|
||||
# kubernetes
|
||||
|
@ -190,7 +190,7 @@ websocket-client==1.4.2 \
|
|||
# kubernetes
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
setuptools==65.6.0 \
|
||||
--hash=sha256:6211d2f5eddad8757bd0484923ca7c0a6302ebc4ab32ea5e94357176e0ca0840 \
|
||||
--hash=sha256:d1eebf881c6114e51df1664bc2c9133d022f78d12d5f4f665b9191f084e2862d
|
||||
setuptools==65.6.3 \
|
||||
--hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \
|
||||
--hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75
|
||||
# via kubernetes
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.10-alpine
|
||||
FROM python:3.11-alpine
|
||||
|
||||
# Copy python requirements
|
||||
COPY src/scheduler/requirements.txt /tmp/req/requirements.txt
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
schedule==1.1.0
|
||||
certbot==1.32.0
|
||||
certbot==2.0.0
|
||||
maxminddb==2.2.0
|
|
@ -4,13 +4,13 @@
|
|||
#
|
||||
# pip-compile --allow-unsafe --generate-hashes
|
||||
#
|
||||
acme==1.32.0 \
|
||||
--hash=sha256:c7917e044f4232585c6ce1d46655cf9495bdbe08b0bffac1e4b6f9fa03c9b940 \
|
||||
--hash=sha256:ea2c5f12aca70c645c205ba0ff024f397a3d2e810bcff560fc0faa2b43b9f393
|
||||
acme==2.0.0 \
|
||||
--hash=sha256:17da5a3dc353e56104e9e2f5699c3fc6758e7939cc502f5d71aa045df6f0b244 \
|
||||
--hash=sha256:7106d0bd04fab062eb657d7cf77f76d6c9babca9813603a7435be4382ea6dad8
|
||||
# via certbot
|
||||
certbot==1.32.0 \
|
||||
--hash=sha256:1a86aed518a25af87a5ab43ed4b07375c9ac4db4e756c25d53af44f25dbdd2dd \
|
||||
--hash=sha256:a7f35205953962dbf245d95a30b903c521ab20713a15b89218c72521ddea386e
|
||||
certbot==2.0.0 \
|
||||
--hash=sha256:05a63c25d4a622dfb63b8d346cb97cba86d38ca6e7d71d2bbbc9223995731c13 \
|
||||
--hash=sha256:9e6f16be2a8e007b041099b9b6bc4d92566bc40f1066053ab00afbf4e4ca80de
|
||||
# via -r requirements.in
|
||||
certifi==2022.9.24 \
|
||||
--hash=sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14 \
|
||||
|
@ -172,12 +172,6 @@ pytz==2022.6 \
|
|||
requests==2.28.1 \
|
||||
--hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 \
|
||||
--hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349
|
||||
# via
|
||||
# acme
|
||||
# requests-toolbelt
|
||||
requests-toolbelt==0.10.1 \
|
||||
--hash=sha256:18565aa58116d9951ac39baa288d3adb5b3ff975c4f25eee78555d89e8f247f7 \
|
||||
--hash=sha256:62e09f7ff5ccbda92772a29f394a49c3ad6cb181d568b1337626b2abb628a63d
|
||||
# via acme
|
||||
schedule==1.1.0 \
|
||||
--hash=sha256:617adce8b4bf38c360b781297d59918fbebfb2878f1671d189f4f4af5d0567a4 \
|
||||
|
@ -187,106 +181,16 @@ six==1.16.0 \
|
|||
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
|
||||
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
|
||||
# via configobj
|
||||
urllib3==1.26.12 \
|
||||
--hash=sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e \
|
||||
--hash=sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997
|
||||
urllib3==1.26.13 \
|
||||
--hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \
|
||||
--hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8
|
||||
# via requests
|
||||
zope-component==5.0.1 \
|
||||
--hash=sha256:32cbe426ba8fa7b62ce5b211f80f0718a0c749cc7ff09e3f4b43a57f7ccdf5e5 \
|
||||
--hash=sha256:e955eb9f1e55d30e2d8097c8baa9ee012c356887eef3b0d43e6bfcd4868221e5
|
||||
# via certbot
|
||||
zope-event==4.5.0 \
|
||||
--hash=sha256:2666401939cdaa5f4e0c08cf7f20c9b21423b95e88f4675b1443973bdb080c42 \
|
||||
--hash=sha256:5e76517f5b9b119acf37ca8819781db6c16ea433f7e2062c4afc2b6fbedb1330
|
||||
# via zope-component
|
||||
zope-hookable==5.4 \
|
||||
--hash=sha256:0054539ed839751b7f511193912cba393f0b8b5f7dfe9f3601c65b2d3b74e731 \
|
||||
--hash=sha256:049ef54de127236e555d0864ad3b950b2b6e5048cdf1098cf340c6fb108104c7 \
|
||||
--hash=sha256:06570ed57b22624c7673ff203801bbdece14d2d42dc5d9879c24ef5612c53456 \
|
||||
--hash=sha256:0e9e5adc24954e157e084bee97362346470a06d0305cb095118367a8a776dce4 \
|
||||
--hash=sha256:2e8fd79437c2007020d3faac41e13c49bcbaa6a0738e4142b996c656dcb5bb69 \
|
||||
--hash=sha256:4313b3d282c1c26fcb69569b7988bc2de0b6dc59238ae7189b6b7b29503d47cb \
|
||||
--hash=sha256:448ca90d78bd3aef75fe5d55d19f5d05a217193738b7a8d5fd9e93ecf2c02c84 \
|
||||
--hash=sha256:4b2fd781571336b0b7655826d9a052379a06b62af138085409b2e3fef1e6fb3d \
|
||||
--hash=sha256:5215355203b9583b7f2a8f06fa7df272562cc12bf5be1a960a45ea49c3294426 \
|
||||
--hash=sha256:5cb0e4a23588435c6911bde300158d31e47c73c469fbf59d927e801e1cb457ef \
|
||||
--hash=sha256:71bff8f7c2e223f92a218b0909ccc6f612c075cc3b5ed164cf152f1537cae2ca \
|
||||
--hash=sha256:7241ab28df7288d9a8bf49339a0aabfbf035b93d6a2a843af13d13dfa735c46a \
|
||||
--hash=sha256:7269a0fbcd7c5901e255679f8dac835b628eab58d5490c38cf2b15508f181e64 \
|
||||
--hash=sha256:7401bd6138e58231aef751c63718726259a7aa6875d746d8a87bba70271b9cff \
|
||||
--hash=sha256:761c9bf1b8df6e2b2d5ae87cda27b8e82c33e2f328750e039de4f6f7f35b73cd \
|
||||
--hash=sha256:78c51f04aabd3b77ba8d3b2c2abaff8b7598376fea7bd1af9929e90549f6dd4c \
|
||||
--hash=sha256:93cfda0663d4d3db6b1818619fbc14e3df2e703454983c841b3b95894d559f86 \
|
||||
--hash=sha256:9af06ca83ff1ef9f94a98d08095dd8960fc5b71ffc7ed7db05988dc493e148a1 \
|
||||
--hash=sha256:9cffa01d8ef1172492fd6df0113ff5432006129b9bd6e8265e1e4985362b973d \
|
||||
--hash=sha256:9d398b1de407a5908c8e5f55fb7a26fa177916b1203e697ef0b4c3389dd28e14 \
|
||||
--hash=sha256:9f447ecaf7741257333f4b1cc215de633daaf147dbc87133638142ed88492617 \
|
||||
--hash=sha256:9f5d425eb57dee785e4d32703e45c5d6cf2b9fa7ad37c10214593b5f62daa60b \
|
||||
--hash=sha256:9f7dd1b45cd13976f49ad21f48a8253628c74ad5eefe3f6e14d50f38cc45f613 \
|
||||
--hash=sha256:9fd11381ec66a8569f999dbe11c94870ddf8aecd591300f203a927f18e938a24 \
|
||||
--hash=sha256:acec917178af910959205f98f48bcd0a165bdcd6b4d8b3f4baf06fa393ac5ff5 \
|
||||
--hash=sha256:b65e86a5cb8244d83eabd021f70968d4a80fac01edc99f6e35d29e5458a128bb \
|
||||
--hash=sha256:bad033b8adfe71f650fef2d4fc33452b3310a0e53139a530dbffbcf9fe08c8c8 \
|
||||
--hash=sha256:c39ffe1b1ef7543e8efafdc6472d7b9ece8ed1ebe20be261522346463aa2c8c0 \
|
||||
--hash=sha256:c79da9673a7d704f6ea2a4bbef6e5e161adbba9d8371476de28a0e3416510cc1 \
|
||||
--hash=sha256:d06da931ac88ebb4c02ac89d0b6fdb2e4fff130901edf9c6e7ea0338a2edf6bd \
|
||||
--hash=sha256:d44229a0aa8d3587491f359d7326c55b5db6379f68656785dece792afbcfcbae \
|
||||
--hash=sha256:d5e50bfbcde1afe32f9cf7fa5e8ea42e218090ecb989c31164d708d0491134b7 \
|
||||
--hash=sha256:d822b7ec71ebb5c96df000e2180127e94ba49258335ae796dc4b6201259b2502 \
|
||||
--hash=sha256:eeb4042f9b1771a1dd8377cb1cb307c4a4f5821d1491becbdc69bc9de66d3918 \
|
||||
--hash=sha256:fb601f00ac87e5aa582a81315ed96768ce3513280729d3f51f79312e2b8b94ac \
|
||||
--hash=sha256:fd49da3340339b8aeef31153ce898e93867ee5a7ffcf685e903ceae6717f0cc2
|
||||
# via zope-component
|
||||
zope-interface==5.5.2 \
|
||||
--hash=sha256:008b0b65c05993bb08912f644d140530e775cf1c62a072bf9340c2249e613c32 \
|
||||
--hash=sha256:0217a9615531c83aeedb12e126611b1b1a3175013bbafe57c702ce40000eb9a0 \
|
||||
--hash=sha256:0fb497c6b088818e3395e302e426850f8236d8d9f4ef5b2836feae812a8f699c \
|
||||
--hash=sha256:17ebf6e0b1d07ed009738016abf0d0a0f80388e009d0ac6e0ead26fc162b3b9c \
|
||||
--hash=sha256:311196634bb9333aa06f00fc94f59d3a9fddd2305c2c425d86e406ddc6f2260d \
|
||||
--hash=sha256:3218ab1a7748327e08ef83cca63eea7cf20ea7e2ebcb2522072896e5e2fceedf \
|
||||
--hash=sha256:404d1e284eda9e233c90128697c71acffd55e183d70628aa0bbb0e7a3084ed8b \
|
||||
--hash=sha256:4087e253bd3bbbc3e615ecd0b6dd03c4e6a1e46d152d3be6d2ad08fbad742dcc \
|
||||
--hash=sha256:40f4065745e2c2fa0dff0e7ccd7c166a8ac9748974f960cd39f63d2c19f9231f \
|
||||
--hash=sha256:5334e2ef60d3d9439c08baedaf8b84dc9bb9522d0dacbc10572ef5609ef8db6d \
|
||||
--hash=sha256:604cdba8f1983d0ab78edc29aa71c8df0ada06fb147cea436dc37093a0100a4e \
|
||||
--hash=sha256:6373d7eb813a143cb7795d3e42bd8ed857c82a90571567e681e1b3841a390d16 \
|
||||
--hash=sha256:655796a906fa3ca67273011c9805c1e1baa047781fca80feeb710328cdbed87f \
|
||||
--hash=sha256:65c3c06afee96c654e590e046c4a24559e65b0a87dbff256cd4bd6f77e1a33f9 \
|
||||
--hash=sha256:696f3d5493eae7359887da55c2afa05acc3db5fc625c49529e84bd9992313296 \
|
||||
--hash=sha256:6e972493cdfe4ad0411fd9abfab7d4d800a7317a93928217f1a5de2bb0f0d87a \
|
||||
--hash=sha256:7579960be23d1fddecb53898035a0d112ac858c3554018ce615cefc03024e46d \
|
||||
--hash=sha256:765d703096ca47aa5d93044bf701b00bbce4d903a95b41fff7c3796e747b1f1d \
|
||||
--hash=sha256:7e66f60b0067a10dd289b29dceabd3d0e6d68be1504fc9d0bc209cf07f56d189 \
|
||||
--hash=sha256:8a2ffadefd0e7206adc86e492ccc60395f7edb5680adedf17a7ee4205c530df4 \
|
||||
--hash=sha256:959697ef2757406bff71467a09d940ca364e724c534efbf3786e86eee8591452 \
|
||||
--hash=sha256:9d783213fab61832dbb10d385a319cb0e45451088abd45f95b5bb88ed0acca1a \
|
||||
--hash=sha256:a16025df73d24795a0bde05504911d306307c24a64187752685ff6ea23897cb0 \
|
||||
--hash=sha256:a2ad597c8c9e038a5912ac3cf166f82926feff2f6e0dabdab956768de0a258f5 \
|
||||
--hash=sha256:bfee1f3ff62143819499e348f5b8a7f3aa0259f9aca5e0ddae7391d059dce671 \
|
||||
--hash=sha256:d169ccd0756c15bbb2f1acc012f5aab279dffc334d733ca0d9362c5beaebe88e \
|
||||
--hash=sha256:d514c269d1f9f5cd05ddfed15298d6c418129f3f064765295659798349c43e6f \
|
||||
--hash=sha256:d692374b578360d36568dd05efb8a5a67ab6d1878c29c582e37ddba80e66c396 \
|
||||
--hash=sha256:dbaeb9cf0ea0b3bc4b36fae54a016933d64c6d52a94810a63c00f440ecb37dd7 \
|
||||
--hash=sha256:dc26c8d44472e035d59d6f1177eb712888447f5799743da9c398b0339ed90b1b \
|
||||
--hash=sha256:e1574980b48c8c74f83578d1e77e701f8439a5d93f36a5a0af31337467c08fcf \
|
||||
--hash=sha256:e74a578172525c20d7223eac5f8ad187f10940dac06e40113d62f14f3adb1e8f \
|
||||
--hash=sha256:e945de62917acbf853ab968d8916290548df18dd62c739d862f359ecd25842a6 \
|
||||
--hash=sha256:f0980d44b8aded808bec5059018d64692f0127f10510eca71f2f0ace8fb11188 \
|
||||
--hash=sha256:f98d4bd7bbb15ca701d19b93263cc5edfd480c3475d163f137385f49e5b3a3a7 \
|
||||
--hash=sha256:fb68d212efd057596dee9e6582daded9f8ef776538afdf5feceb3059df2d2e7b
|
||||
# via
|
||||
# certbot
|
||||
# zope-component
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
setuptools==65.6.0 \
|
||||
--hash=sha256:6211d2f5eddad8757bd0484923ca7c0a6302ebc4ab32ea5e94357176e0ca0840 \
|
||||
--hash=sha256:d1eebf881c6114e51df1664bc2c9133d022f78d12d5f4f665b9191f084e2862d
|
||||
setuptools==65.6.3 \
|
||||
--hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \
|
||||
--hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75
|
||||
# via
|
||||
# acme
|
||||
# certbot
|
||||
# josepy
|
||||
# zope-component
|
||||
# zope-event
|
||||
# zope-hookable
|
||||
# zope-interface
|
||||
|
|
|
@ -137,7 +137,7 @@ wtforms==3.0.1 \
|
|||
# via flask-wtf
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
setuptools==65.6.0 \
|
||||
--hash=sha256:6211d2f5eddad8757bd0484923ca7c0a6302ebc4ab32ea5e94357176e0ca0840 \
|
||||
--hash=sha256:d1eebf881c6114e51df1664bc2c9133d022f78d12d5f4f665b9191f084e2862d
|
||||
setuptools==65.6.3 \
|
||||
--hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \
|
||||
--hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75
|
||||
# via gunicorn
|
||||
|
|
|
@ -787,6 +787,10 @@ h6 {
|
|||
z-index: 20;
|
||||
}
|
||||
|
||||
.-z-10 {
|
||||
z-index: -10;
|
||||
}
|
||||
|
||||
.z-10 {
|
||||
z-index: 10;
|
||||
}
|
||||
|
@ -807,8 +811,12 @@ h6 {
|
|||
z-index: 50;
|
||||
}
|
||||
|
||||
.-z-10 {
|
||||
z-index: -10;
|
||||
.z-\[1500\] {
|
||||
z-index: 1500;
|
||||
}
|
||||
|
||||
.z-\[10000\] {
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.order-2 {
|
||||
|
@ -843,10 +851,6 @@ h6 {
|
|||
grid-column: auto;
|
||||
}
|
||||
|
||||
.col-span-6 {
|
||||
grid-column: span 6 / span 6;
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: right;
|
||||
}
|
||||
|
@ -907,24 +911,14 @@ h6 {
|
|||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
.my-1 {
|
||||
margin-top: 0.25rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.my-4 {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.mx-2\.5 {
|
||||
margin-left: 0.625rem;
|
||||
margin-right: 0.625rem;
|
||||
}
|
||||
|
||||
.mx-4 {
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
.my-1 {
|
||||
margin-top: 0.25rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.my-3 {
|
||||
|
@ -932,21 +926,26 @@ h6 {
|
|||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.mx-2\.5 {
|
||||
margin-left: 0.625rem;
|
||||
margin-right: 0.625rem;
|
||||
}
|
||||
|
||||
.mx-3 {
|
||||
margin-left: 0.75rem;
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
|
||||
.mx-4 {
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.my-5 {
|
||||
margin-top: 1.25rem;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.my-6 {
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.mb-1 {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
@ -1011,6 +1010,18 @@ h6 {
|
|||
margin-left: 0.25rem;
|
||||
}
|
||||
|
||||
.ml-6 {
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.ml-2 {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.mb-8 {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.mb-7 {
|
||||
margin-bottom: 1.75rem;
|
||||
}
|
||||
|
@ -1019,14 +1030,6 @@ h6 {
|
|||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.ml-6 {
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.mb-4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.mt-2 {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
@ -1039,14 +1042,14 @@ h6 {
|
|||
margin-top: 0.125rem;
|
||||
}
|
||||
|
||||
.ml-2 {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.ml-0 {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.mb-4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.ml-auto {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
@ -1075,8 +1078,8 @@ h6 {
|
|||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.mb-8 {
|
||||
margin-bottom: 2rem;
|
||||
.mr-4 {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.box-content {
|
||||
|
@ -1143,14 +1146,14 @@ h6 {
|
|||
height: 3rem;
|
||||
}
|
||||
|
||||
.h-3 {
|
||||
height: 0.75rem;
|
||||
}
|
||||
|
||||
.h-16 {
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
.h-3 {
|
||||
height: 0.75rem;
|
||||
}
|
||||
|
||||
.h-19 {
|
||||
height: 4.75rem;
|
||||
}
|
||||
|
@ -1179,10 +1182,6 @@ h6 {
|
|||
height: 25rem;
|
||||
}
|
||||
|
||||
.h-7 {
|
||||
height: 1.75rem;
|
||||
}
|
||||
|
||||
.h-1\/3 {
|
||||
height: 33.333333%;
|
||||
}
|
||||
|
@ -1191,16 +1190,16 @@ h6 {
|
|||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.max-h-135 {
|
||||
max-height: 33.75rem;
|
||||
}
|
||||
|
||||
.max-h-100 {
|
||||
max-height: 25rem;
|
||||
}
|
||||
|
||||
.max-h-60 {
|
||||
max-height: 15rem;
|
||||
}
|
||||
|
||||
.max-h-16 {
|
||||
max-height: 4rem;
|
||||
.max-h-30 {
|
||||
max-height: 7.5rem;
|
||||
}
|
||||
|
||||
.max-h-80 {
|
||||
|
@ -1215,14 +1214,6 @@ h6 {
|
|||
max-height: 2rem;
|
||||
}
|
||||
|
||||
.max-h-30 {
|
||||
max-height: 7.5rem;
|
||||
}
|
||||
|
||||
.max-h-135 {
|
||||
max-height: 33.75rem;
|
||||
}
|
||||
|
||||
.min-h-20 {
|
||||
min-height: 5rem;
|
||||
}
|
||||
|
@ -1235,6 +1226,10 @@ h6 {
|
|||
min-height: 50vh;
|
||||
}
|
||||
|
||||
.min-h-screen {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.min-h-6 {
|
||||
min-height: 1.5rem;
|
||||
}
|
||||
|
@ -1259,18 +1254,6 @@ h6 {
|
|||
min-height: 85vh;
|
||||
}
|
||||
|
||||
.min-h-screen {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.min-h-90 {
|
||||
min-height: 22.5rem;
|
||||
}
|
||||
|
||||
.min-h-80 {
|
||||
min-height: 20rem;
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -1307,14 +1290,14 @@ h6 {
|
|||
width: 1.25rem;
|
||||
}
|
||||
|
||||
.w-3 {
|
||||
width: 0.75rem;
|
||||
}
|
||||
|
||||
.w-60 {
|
||||
width: 15rem;
|
||||
}
|
||||
|
||||
.w-3 {
|
||||
width: 0.75rem;
|
||||
}
|
||||
|
||||
.w-28 {
|
||||
width: 7rem;
|
||||
}
|
||||
|
@ -1335,36 +1318,20 @@ h6 {
|
|||
width: 20rem;
|
||||
}
|
||||
|
||||
.w-7 {
|
||||
width: 1.75rem;
|
||||
.w-40 {
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
.min-w-0 {
|
||||
min-width: 0px;
|
||||
}
|
||||
|
||||
.min-w-\[900\] {
|
||||
min-width: 900;
|
||||
}
|
||||
|
||||
.min-w-\[900px\] {
|
||||
min-width: 900px;
|
||||
}
|
||||
|
||||
.min-w-\[800px\] {
|
||||
min-width: 800px;
|
||||
}
|
||||
|
||||
.min-w-\[700px\] {
|
||||
min-width: 700px;
|
||||
}
|
||||
|
||||
.min-w-\[750px\] {
|
||||
min-width: 750px;
|
||||
}
|
||||
|
||||
.max-w-screen-sm {
|
||||
max-width: 576px;
|
||||
.max-w-\[300px\] {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.max-w-180 {
|
||||
|
@ -1375,8 +1342,16 @@ h6 {
|
|||
max-width: 10rem;
|
||||
}
|
||||
|
||||
.max-w-120 {
|
||||
max-width: 30rem;
|
||||
.max-w-screen-sm {
|
||||
max-width: 576px;
|
||||
}
|
||||
|
||||
.max-w-\[400px\] {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.max-w-60 {
|
||||
max-width: 15rem;
|
||||
}
|
||||
|
||||
.max-w-64 {
|
||||
|
@ -1391,26 +1366,6 @@ h6 {
|
|||
max-width: 32rem;
|
||||
}
|
||||
|
||||
.max-w-\[300px\] {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.max-w-60 {
|
||||
max-width: 15rem;
|
||||
}
|
||||
|
||||
.max-w-\[460px\] {
|
||||
max-width: 460px;
|
||||
}
|
||||
|
||||
.max-w-\[40px\] {
|
||||
max-width: 40px;
|
||||
}
|
||||
|
||||
.max-w-\[400px\] {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.flex-auto {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
@ -1482,11 +1437,6 @@ h6 {
|
|||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.translate-y-12 {
|
||||
--tw-translate-y: 3rem;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.-translate-x-full {
|
||||
--tw-translate-x: -100%;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
|
@ -1563,10 +1513,6 @@ h6 {
|
|||
resize: both;
|
||||
}
|
||||
|
||||
.scroll-m-4 {
|
||||
scroll-margin: 1rem;
|
||||
}
|
||||
|
||||
.list-none {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
@ -1589,6 +1535,10 @@ h6 {
|
|||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.grid-cols-3 {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.flex-col {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
@ -1654,10 +1604,6 @@ h6 {
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.overflow-scroll {
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.overflow-x-auto {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
@ -1670,14 +1616,6 @@ h6 {
|
|||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.overflow-x-scroll {
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.overflow-y-scroll {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.whitespace-nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -1744,6 +1682,16 @@ h6 {
|
|||
border-top-right-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.rounded-b-lg {
|
||||
border-bottom-right-radius: 0.5rem;
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.rounded-t-lg {
|
||||
border-top-left-radius: 0.5rem;
|
||||
border-top-right-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.rounded-b {
|
||||
border-bottom-right-radius: 0.25rem;
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
|
@ -1790,6 +1738,10 @@ h6 {
|
|||
border-style: solid;
|
||||
}
|
||||
|
||||
.border-dashed {
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
.border-white {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(255 255 255 / var(--tw-border-opacity));
|
||||
|
@ -1878,6 +1830,11 @@ h6 {
|
|||
background-color: rgb(94 114 228 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gray-50 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(248 249 250 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-primary\/20 {
|
||||
background-color: rgb(8 85 119 / 0.2);
|
||||
}
|
||||
|
@ -1886,11 +1843,6 @@ h6 {
|
|||
background-color: rgb(58 65 111 / 0.1);
|
||||
}
|
||||
|
||||
.bg-gray-50 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(248 249 250 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-white\/80 {
|
||||
background-color: rgb(255 255 255 / 0.8);
|
||||
}
|
||||
|
@ -1899,8 +1851,8 @@ h6 {
|
|||
background-color: rgb(64 187 107 / 0.8);
|
||||
}
|
||||
|
||||
.bg-opacity-0 {
|
||||
--tw-bg-opacity: 0;
|
||||
.bg-none {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.bg-gradient-to-tl {
|
||||
|
@ -1911,10 +1863,6 @@ h6 {
|
|||
background-image: linear-gradient(to right, var(--tw-gradient-stops));
|
||||
}
|
||||
|
||||
.bg-none {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.from-transparent {
|
||||
--tw-gradient-from: transparent;
|
||||
--tw-gradient-to: rgb(0 0 0 / 0);
|
||||
|
@ -2079,10 +2027,6 @@ h6 {
|
|||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.p-12 {
|
||||
padding: 3rem;
|
||||
}
|
||||
|
||||
.px-2 {
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
|
@ -2133,6 +2077,21 @@ h6 {
|
|||
padding-right: 0.75rem;
|
||||
}
|
||||
|
||||
.py-2\.5 {
|
||||
padding-top: 0.625rem;
|
||||
padding-bottom: 0.625rem;
|
||||
}
|
||||
|
||||
.px-12 {
|
||||
padding-left: 3rem;
|
||||
padding-right: 3rem;
|
||||
}
|
||||
|
||||
.py-16 {
|
||||
padding-top: 4rem;
|
||||
padding-bottom: 4rem;
|
||||
}
|
||||
|
||||
.px-8 {
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
|
@ -2153,6 +2112,11 @@ h6 {
|
|||
padding-right: 0.125rem;
|
||||
}
|
||||
|
||||
.py-1\.5 {
|
||||
padding-top: 0.375rem;
|
||||
padding-bottom: 0.375rem;
|
||||
}
|
||||
|
||||
.py-1\.4 {
|
||||
padding-top: 0.35rem;
|
||||
padding-bottom: 0.35rem;
|
||||
|
@ -2168,16 +2132,6 @@ h6 {
|
|||
padding-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.px-12 {
|
||||
padding-left: 3rem;
|
||||
padding-right: 3rem;
|
||||
}
|
||||
|
||||
.py-16 {
|
||||
padding-top: 4rem;
|
||||
padding-bottom: 4rem;
|
||||
}
|
||||
|
||||
.pb-0 {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
@ -2347,6 +2301,10 @@ h6 {
|
|||
line-height: 1;
|
||||
}
|
||||
|
||||
.leading-6 {
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
.leading-tight {
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
@ -2374,16 +2332,16 @@ h6 {
|
|||
color: rgb(245 57 57 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-green-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(34 197 94 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-gray-700 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(73 80 87 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-green-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(34 197 94 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-slate-700 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(52 71 103 / var(--tw-text-opacity));
|
||||
|
@ -2451,6 +2409,10 @@ h6 {
|
|||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.opacity-0 {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.shadow-md {
|
||||
--tw-shadow: 0 4px 6px rgba(50,50,93,.1),0 1px 3px rgba(0,0,0,.08);
|
||||
--tw-shadow-colored: 0 4px 6px var(--tw-shadow-color), 0 1px 3px var(--tw-shadow-color);
|
||||
|
@ -2960,6 +2922,11 @@ h6 {
|
|||
border-color: rgb(58 65 111 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:border-gray-700 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(73 80 87 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:bg-slate-900 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(5 17 57 / var(--tw-bg-opacity));
|
||||
|
@ -2997,6 +2964,11 @@ h6 {
|
|||
background-color: rgb(17 28 68 / 0.8);
|
||||
}
|
||||
|
||||
.dark .dark\:bg-gray-800 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(37 47 64 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:bg-gradient-to-r {
|
||||
background-image: linear-gradient(to right, var(--tw-gradient-stops));
|
||||
}
|
||||
|
@ -3028,16 +3000,16 @@ h6 {
|
|||
fill: #adb5bd;
|
||||
}
|
||||
|
||||
.dark .dark\:text-white {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-gray-300 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(210 214 218 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-white {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-gray-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(173 181 189 / var(--tw-text-opacity));
|
||||
|
@ -3174,19 +3146,10 @@ h6 {
|
|||
grid-column: span 2 / span 2;
|
||||
}
|
||||
|
||||
.sm\:col-span-8 {
|
||||
grid-column: span 8 / span 8;
|
||||
}
|
||||
|
||||
.sm\:col-start-5 {
|
||||
grid-column-start: 5;
|
||||
}
|
||||
|
||||
.sm\:my-0 {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.sm\:mx-6 {
|
||||
margin-left: 1.5rem;
|
||||
margin-right: 1.5rem;
|
||||
|
@ -3205,10 +3168,6 @@ h6 {
|
|||
margin-right: 4rem;
|
||||
}
|
||||
|
||||
.sm\:block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sm\:hidden {
|
||||
display: none;
|
||||
}
|
||||
|
@ -3225,22 +3184,22 @@ h6 {
|
|||
height: 1.75rem;
|
||||
}
|
||||
|
||||
.sm\:h-16 {
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
.sm\:h-20 {
|
||||
height: 5rem;
|
||||
}
|
||||
|
||||
.sm\:h-14 {
|
||||
height: 3.5rem;
|
||||
}
|
||||
|
||||
.sm\:max-h-28 {
|
||||
max-height: 7rem;
|
||||
}
|
||||
|
||||
.sm\:max-h-0 {
|
||||
max-height: 0px;
|
||||
}
|
||||
|
||||
.sm\:max-h-120 {
|
||||
max-height: 30rem;
|
||||
}
|
||||
|
||||
.sm\:max-h-135 {
|
||||
max-height: 33.75rem;
|
||||
}
|
||||
|
||||
.sm\:max-h-125 {
|
||||
max-height: 31.25rem;
|
||||
}
|
||||
|
@ -3257,6 +3216,14 @@ h6 {
|
|||
width: 1.75rem;
|
||||
}
|
||||
|
||||
.sm\:w-60 {
|
||||
width: 15rem;
|
||||
}
|
||||
|
||||
.sm\:w-50 {
|
||||
width: 12.5rem;
|
||||
}
|
||||
|
||||
.sm\:flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
@ -3316,10 +3283,6 @@ h6 {
|
|||
grid-column: span 7 / span 7;
|
||||
}
|
||||
|
||||
.md\:col-span-1 {
|
||||
grid-column: span 1 / span 1;
|
||||
}
|
||||
|
||||
.md\:my-0 {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
|
@ -3359,6 +3322,14 @@ h6 {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.md\:h-25 {
|
||||
height: 6.25rem;
|
||||
}
|
||||
|
||||
.md\:h-16 {
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
.md\:max-h-160 {
|
||||
max-height: 40rem;
|
||||
}
|
||||
|
@ -3367,21 +3338,20 @@ h6 {
|
|||
min-height: 75vh;
|
||||
}
|
||||
|
||||
.md\:min-h-50-screen {
|
||||
min-height: 50vh;
|
||||
}
|
||||
|
||||
.md\:w-1\/2 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.md\:justify-end {
|
||||
justify-content: flex-end;
|
||||
.md\:w-80 {
|
||||
width: 20rem;
|
||||
}
|
||||
|
||||
.md\:bg-white {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
.md\:w-60 {
|
||||
width: 15rem;
|
||||
}
|
||||
|
||||
.md\:justify-end {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.md\:py-4 {
|
||||
|
@ -3431,8 +3401,8 @@ h6 {
|
|||
grid-column: span 6 / span 6;
|
||||
}
|
||||
|
||||
.lg\:col-span-12 {
|
||||
grid-column: span 12 / span 12;
|
||||
.lg\:col-span-1 {
|
||||
grid-column: span 1 / span 1;
|
||||
}
|
||||
|
||||
.lg\:col-span-8 {
|
||||
|
@ -3443,20 +3413,11 @@ h6 {
|
|||
grid-column: span 3 / span 3;
|
||||
}
|
||||
|
||||
.lg\:col-span-1 {
|
||||
grid-column: span 1 / span 1;
|
||||
}
|
||||
|
||||
.lg\:mx-8 {
|
||||
margin-left: 2rem;
|
||||
margin-right: 2rem;
|
||||
}
|
||||
|
||||
.lg\:mx-0 {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.lg\:mt-0 {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
@ -3485,6 +3446,14 @@ h6 {
|
|||
height: 7.5rem;
|
||||
}
|
||||
|
||||
.lg\:h-20 {
|
||||
height: 5rem;
|
||||
}
|
||||
|
||||
.lg\:h-24 {
|
||||
height: 6rem;
|
||||
}
|
||||
|
||||
.lg\:w-9 {
|
||||
width: 2.25rem;
|
||||
}
|
||||
|
@ -3497,6 +3466,10 @@ h6 {
|
|||
width: 50%;
|
||||
}
|
||||
|
||||
.lg\:w-80 {
|
||||
width: 20rem;
|
||||
}
|
||||
|
||||
.lg\:flex-none {
|
||||
flex: none;
|
||||
}
|
||||
|
@ -3525,16 +3498,6 @@ h6 {
|
|||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.lg\:bg-white {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.lg\:bg-gray-100 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(235 239 244 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.lg\:bg-gray-50 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(248 249 250 / var(--tw-bg-opacity));
|
||||
|
@ -3558,6 +3521,10 @@ h6 {
|
|||
top: 0.75rem;
|
||||
}
|
||||
|
||||
.xl\:col-span-4 {
|
||||
grid-column: span 4 / span 4;
|
||||
}
|
||||
|
||||
.xl\:mx-4 {
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
|
@ -3618,6 +3585,10 @@ h6 {
|
|||
grid-column: span 4 / span 4;
|
||||
}
|
||||
|
||||
.\32xl\:col-span-6 {
|
||||
grid-column: span 6 / span 6;
|
||||
}
|
||||
|
||||
.\32xl\:my-2 {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
|
@ -3643,6 +3614,10 @@ h6 {
|
|||
grid-column: span 4 / span 4;
|
||||
}
|
||||
|
||||
.\33xl\:col-span-6 {
|
||||
grid-column: span 6 / span 6;
|
||||
}
|
||||
|
||||
.\33xl\:col-span-2 {
|
||||
grid-column: span 2 / span 2;
|
||||
}
|
||||
|
|
|
@ -1,274 +0,0 @@
|
|||
/*# sourceMappingURL=basic.css.map */
|
||||
@keyframes passing-through {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(40px);
|
||||
}
|
||||
30%,
|
||||
70% {
|
||||
opacity: 1;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateY(-40px);
|
||||
}
|
||||
}
|
||||
@keyframes slide-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(40px);
|
||||
}
|
||||
30% {
|
||||
opacity: 1;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
}
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
10% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
20% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
.dropzone,
|
||||
.dropzone * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.dropzone {
|
||||
min-height: 100px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.8);
|
||||
border-radius: 5px;
|
||||
padding: 0;
|
||||
}
|
||||
.dropzone.dz-clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
.dropzone.dz-clickable * {
|
||||
cursor: default;
|
||||
}
|
||||
.dropzone.dz-clickable .dz-message,
|
||||
.dropzone.dz-clickable .dz-message * {
|
||||
cursor: pointer;
|
||||
}
|
||||
.dropzone.dz-started .dz-message {
|
||||
display: none;
|
||||
}
|
||||
.dropzone.dz-drag-hover {
|
||||
border-style: solid;
|
||||
}
|
||||
.dropzone.dz-drag-hover .dz-message {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.dropzone .dz-message {
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.dropzone .dz-message .dz-button {
|
||||
background: none;
|
||||
color: inherit;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font: inherit;
|
||||
cursor: pointer;
|
||||
outline: inherit;
|
||||
}
|
||||
.dropzone .dz-preview {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin: 12px;
|
||||
min-height: 100px;
|
||||
}
|
||||
.dropzone .dz-preview:hover {
|
||||
z-index: 1000;
|
||||
}
|
||||
.dropzone .dz-preview:hover .dz-details {
|
||||
opacity: 1;
|
||||
}
|
||||
.dropzone .dz-preview.dz-file-preview .dz-image {
|
||||
border-radius: 20px;
|
||||
background: #999;
|
||||
background: linear-gradient(to bottom, #eee, #ddd);
|
||||
}
|
||||
.dropzone .dz-preview.dz-file-preview .dz-details {
|
||||
opacity: 1;
|
||||
}
|
||||
.dropzone .dz-preview.dz-image-preview {
|
||||
background: #fff;
|
||||
}
|
||||
.dropzone .dz-preview.dz-image-preview .dz-details {
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
.dropzone .dz-preview .dz-remove {
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
.dropzone .dz-preview .dz-remove:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.dropzone .dz-preview:hover .dz-details {
|
||||
opacity: 1;
|
||||
}
|
||||
.dropzone .dz-preview .dz-details {
|
||||
z-index: 20;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
font-size: 13px;
|
||||
min-width: 100%;
|
||||
max-width: 100%;
|
||||
padding: 2em 1em;
|
||||
text-align: center;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
line-height: 150%;
|
||||
}
|
||||
.dropzone .dz-preview .dz-details .dz-size {
|
||||
margin-bottom: 1em;
|
||||
font-size: 16px;
|
||||
}
|
||||
.dropzone .dz-preview .dz-details .dz-filename {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dropzone .dz-preview .dz-details .dz-filename:hover span {
|
||||
border: 1px solid rgba(200, 200, 200, 0.8);
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
.dropzone .dz-preview .dz-details .dz-filename:not(:hover) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
.dropzone .dz-preview .dz-details .dz-filename span,
|
||||
.dropzone .dz-preview .dz-details .dz-size span {
|
||||
background-color: rgba(255, 255, 255, 0.4);
|
||||
padding: 0 0.4em;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.dropzone .dz-preview:hover .dz-image img {
|
||||
transform: scale(1.05, 1.05);
|
||||
filter: blur(8px);
|
||||
}
|
||||
.dropzone .dz-preview .dz-image {
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
position: relative;
|
||||
display: block;
|
||||
z-index: 10;
|
||||
}
|
||||
.dropzone .dz-preview .dz-image img {
|
||||
display: block;
|
||||
}
|
||||
.dropzone .dz-preview.dz-success .dz-success-mark {
|
||||
animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
|
||||
}
|
||||
.dropzone .dz-preview.dz-error .dz-error-mark {
|
||||
opacity: 1;
|
||||
animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
|
||||
}
|
||||
.dropzone .dz-preview .dz-success-mark,
|
||||
.dropzone .dz-preview .dz-error-mark {
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
z-index: 500;
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -27px;
|
||||
margin-top: -27px;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
border-radius: 50%;
|
||||
}
|
||||
.dropzone .dz-preview .dz-success-mark svg,
|
||||
.dropzone .dz-preview .dz-error-mark svg {
|
||||
display: block;
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
fill: #fff;
|
||||
}
|
||||
.dropzone .dz-preview.dz-processing .dz-progress {
|
||||
opacity: 1;
|
||||
transition: all 0.2s linear;
|
||||
}
|
||||
.dropzone .dz-preview.dz-complete .dz-progress {
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s ease-in;
|
||||
}
|
||||
.dropzone .dz-preview:not(.dz-processing) .dz-progress {
|
||||
animation: pulse 6s ease infinite;
|
||||
}
|
||||
.dropzone .dz-preview .dz-progress {
|
||||
opacity: 1;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
height: 20px;
|
||||
top: 50%;
|
||||
margin-top: -10px;
|
||||
left: 15%;
|
||||
right: 15%;
|
||||
border: 3px solid rgba(0, 0, 0, 0.8);
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.dropzone .dz-preview .dz-progress .dz-upload {
|
||||
background: #fff;
|
||||
display: block;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 0;
|
||||
transition: width 300ms ease-in-out;
|
||||
border-radius: 17px;
|
||||
}
|
||||
.dropzone .dz-preview.dz-error .dz-error-message {
|
||||
display: block;
|
||||
}
|
||||
.dropzone .dz-preview.dz-error:hover .dz-error-message {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.dropzone .dz-preview .dz-error-message {
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
position: absolute;
|
||||
display: block;
|
||||
display: none;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
top: 130px;
|
||||
left: -10px;
|
||||
width: 140px;
|
||||
background: #b10606;
|
||||
padding: 0.5em 1em;
|
||||
color: #fff;
|
||||
}
|
||||
.dropzone .dz-preview .dz-error-message:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 64px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #b10606;
|
||||
} /*# sourceMappingURL=dropzone.css.map */
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"sourceRoot":"","sources":["../src/dropzone.scss"],"names":[],"mappings":"AAGA,2BACE,GACE,UACA,2BAGF,QACE,UACA,0BAGF,KACE,UACA,6BAKJ,oBACE,GACE,UACA,2BAEF,IACE,UACA,2BAMJ,iBACE,sBACA,yBACA,wBAKF,sBACE,sBAEF,UAmBE,iBACA,gCACA,kBACA,kBAhBA,uBACE,eAEA,yBACE,eAGA,wEACE,eAWJ,iCACE,aAIJ,wBACE,mBACA,oCACE,WAGJ,sBACE,kBACA,aAEA,iCACE,gBACA,cACA,YACA,UACA,aACA,eACA,gBAMJ,sBACE,kBACA,qBAEA,mBAEA,YACA,iBAEA,4BAEE,aACA,wCACE,UAMF,gDACE,cArEgB,KAsEhB,gBACA,kDAGF,kDACE,UAIJ,uCACE,gBACA,mDACE,8BAIJ,iCACE,eACA,kBACA,cACA,eACA,YACA,uCACE,0BAIJ,wCACE,UAEF,kCAGE,WAEA,kBACA,MACA,OAEA,UAEA,eACA,eACA,eACA,gBACA,kBACA,qBAIA,iBAEA,2CACE,kBACA,eAGF,+CAEE,mBAGE,0DACE,sCACA,sCAGJ,2DAIE,gBACA,uBAJA,gEACE,6BASJ,oGACE,sCACA,eACA,kBASF,0CACE,4BACA,iBAIN,gCACE,cAvKkB,KAwKlB,gBACA,MA3KS,MA4KT,OA5KS,MA6KT,kBACA,cACA,WAEA,oCACE,cAMF,kDACE,6DAIF,8CACE,UACA,sDASJ,4EAKE,oBAEA,UACA,YAEA,kBACA,cACA,QACA,SACA,kBACA,iBAEA,WApBiB,eAqBjB,kBAEA,oFACE,cACA,MAnBY,KAoBZ,OArBa,KAsBb,KA5BY,KAiChB,iDACE,UACA,0BAEF,+CACE,UACA,+BAIA,uDACE,iCAGJ,mCAIE,UACA,aAEA,oBACA,kBACA,YACA,QACA,iBACA,SACA,UAEA,gCACA,WA9DiB,eAgEjB,mBAEA,gBAEA,8CACE,WAtEY,KAwEZ,cACA,kBACA,YACA,QACA,mCAEA,mBAMF,iDACE,cAEF,uDACE,UACA,oBAIJ,wCAIE,oBACA,aACA,kBACA,cACA,aACA,UACA,4BACA,kBACA,eACA,UACA,WACA,MAdQ,MAeR,WAdQ,QAeR,iBACA,WAGA,8CACE,WACA,kBACA,SACA,UACA,QACA,SACA,kCACA,mCACA","file":"dropzone.css"}
|
|
@ -1,4 +1,4 @@
|
|||
import { Checkbox } from "./utils.js";
|
||||
import { Checkbox, Loader } from "./utils.js";
|
||||
|
||||
class Menu {
|
||||
constructor() {
|
||||
|
@ -76,7 +76,30 @@ class darkMode {
|
|||
}
|
||||
}
|
||||
|
||||
class FlashMsg {
|
||||
constructor() {
|
||||
this.delayBeforeRemove = 5000;
|
||||
this.init();
|
||||
}
|
||||
|
||||
//remove flash message after this.delay if exist
|
||||
init() {
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
try {
|
||||
const flashEl = document.querySelector("[flash-message]");
|
||||
setTimeout(() => {
|
||||
try {
|
||||
flashEl.remove();
|
||||
} catch (err) {}
|
||||
}, this.delayBeforeRemove);
|
||||
} catch (err) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const setLoader = new Loader();
|
||||
const setMenu = new Menu();
|
||||
const setNews = new News();
|
||||
const setDarkM = new darkMode();
|
||||
const setCheckbox = new Checkbox("[sidebar-info]");
|
||||
const setFlash = new FlashMsg();
|
||||
|
|
2881
src/ui/static/js/dropzone/dropzone-min.js
vendored
2881
src/ui/static/js/dropzone/dropzone-min.js
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
343
src/ui/static/js/jobs.js
Normal file
343
src/ui/static/js/jobs.js
Normal file
|
@ -0,0 +1,343 @@
|
|||
class Dropdown {
|
||||
constructor(prefix = "jobs") {
|
||||
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(`${this.prefix}-setting-select`) &&
|
||||
!e.target.closest("button").hasAttribute(`disabled`)
|
||||
) {
|
||||
const btnName = e.target
|
||||
.closest("button")
|
||||
.getAttribute(`${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(`${this.prefix}-setting-select-dropdown-btn`)
|
||||
) {
|
||||
const btn = e.target.closest("button");
|
||||
const btnValue = btn.getAttribute("value");
|
||||
const btnSetting = btn.getAttribute(
|
||||
`${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);
|
||||
this.changeDropBtnStyle(btnSetting, btn);
|
||||
//show / hide filter
|
||||
if (btnSetting === "instances") {
|
||||
this.hideFilterOnLocal(btn.getAttribute("_type"));
|
||||
}
|
||||
}
|
||||
} catch (err) {}
|
||||
});
|
||||
}
|
||||
|
||||
closeAllDrop() {
|
||||
const drops = document.querySelectorAll(
|
||||
`[${this.prefix}-setting-select-dropdown]`
|
||||
);
|
||||
drops.forEach((drop) => {
|
||||
drop.classList.add("hidden");
|
||||
drop.classList.remove("flex");
|
||||
document
|
||||
.querySelector(
|
||||
`svg[${this.prefix}-setting-select="${drop.getAttribute(
|
||||
`${this.prefix}-setting-select-dropdown`
|
||||
)}"]`
|
||||
)
|
||||
.classList.remove("rotate-180");
|
||||
});
|
||||
}
|
||||
|
||||
isSameValue(btnSetting, value) {
|
||||
const selectCustom = document.querySelector(
|
||||
`[${this.prefix}-setting-select-text="${btnSetting}"]`
|
||||
);
|
||||
const currVal = selectCustom.textContent;
|
||||
return currVal === value ? true : false;
|
||||
}
|
||||
|
||||
setSelectNewValue(btnSetting, value) {
|
||||
const selectCustom = document.querySelector(
|
||||
`[${this.prefix}-setting-select="${btnSetting}"]`
|
||||
);
|
||||
selectCustom.querySelector(
|
||||
`[${this.prefix}-setting-select-text]`
|
||||
).textContent = value;
|
||||
}
|
||||
|
||||
hideDropdown(btnSetting) {
|
||||
//hide dropdown
|
||||
const dropdownEl = document.querySelector(
|
||||
`[${this.prefix}-setting-select-dropdown="${btnSetting}"]`
|
||||
);
|
||||
dropdownEl.classList.add("hidden");
|
||||
dropdownEl.classList.remove("flex");
|
||||
//svg effect
|
||||
const dropdownChevron = document.querySelector(
|
||||
`svg[${this.prefix}-setting-select="${btnSetting}"]`
|
||||
);
|
||||
dropdownChevron.classList.remove("rotate-180");
|
||||
}
|
||||
|
||||
changeDropBtnStyle(btnSetting, selectedBtn) {
|
||||
const dropdownEl = document.querySelector(
|
||||
`[${this.prefix}-setting-select-dropdown="${btnSetting}"]`
|
||||
);
|
||||
//reset dropdown btns
|
||||
const btnEls = dropdownEl.querySelectorAll("button");
|
||||
|
||||
btnEls.forEach((btn) => {
|
||||
btn.classList.remove(
|
||||
"dark:bg-primary",
|
||||
"bg-primary",
|
||||
"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 attribut = e.target
|
||||
.closest("button")
|
||||
.getAttribute(`${this.prefix}-setting-select`);
|
||||
//toggle dropdown
|
||||
const dropdownEl = document.querySelector(
|
||||
`[${this.prefix}-setting-select-dropdown="${attribut}"]`
|
||||
);
|
||||
const dropdownChevron = document.querySelector(
|
||||
`svg[${this.prefix}-setting-select="${attribut}"]`
|
||||
);
|
||||
dropdownEl.classList.toggle("hidden");
|
||||
dropdownEl.classList.toggle("flex");
|
||||
dropdownChevron.classList.toggle("rotate-180");
|
||||
}
|
||||
|
||||
//hide date filter on local
|
||||
hideFilterOnLocal(type) {
|
||||
console.log(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 Filter {
|
||||
constructor(prefix = "jobs") {
|
||||
this.prefix = prefix;
|
||||
this.container = document.querySelector(`[${this.prefix}-filter]`);
|
||||
this.keyInp = document.querySelector("input#keyword");
|
||||
this.successValue = "all";
|
||||
this.reloadValue = "all";
|
||||
this.sortValue = "name";
|
||||
|
||||
this.initHandler();
|
||||
}
|
||||
|
||||
initHandler() {
|
||||
//SUCCESS HANDLER
|
||||
this.container.addEventListener("click", (e) => {
|
||||
try {
|
||||
if (
|
||||
e.target
|
||||
.closest("button")
|
||||
.getAttribute(`${this.prefix}-setting-select-dropdown-btn`) ===
|
||||
"success"
|
||||
) {
|
||||
setTimeout(() => {
|
||||
const value = document
|
||||
.querySelector(`[${this.prefix}-setting-select-text="success"]`)
|
||||
.textContent.trim();
|
||||
console.log(value);
|
||||
|
||||
this.successValue = value;
|
||||
//run filter
|
||||
this.filter();
|
||||
}, 10);
|
||||
}
|
||||
} catch (err) {}
|
||||
});
|
||||
//RELOAD HANDLER
|
||||
this.container.addEventListener("click", (e) => {
|
||||
try {
|
||||
if (
|
||||
e.target
|
||||
.closest("button")
|
||||
.getAttribute(`${this.prefix}-setting-select-dropdown-btn`) ===
|
||||
"reload"
|
||||
) {
|
||||
setTimeout(() => {
|
||||
const value = document
|
||||
.querySelector(`[${this.prefix}-setting-select-text="reload"]`)
|
||||
.textContent.trim();
|
||||
console.log(value);
|
||||
|
||||
this.reloadValue = value;
|
||||
//run filter
|
||||
this.filter();
|
||||
}, 10);
|
||||
}
|
||||
} catch (err) {}
|
||||
});
|
||||
//KEYWORD HANDLER
|
||||
this.keyInp.addEventListener("input", (e) => {
|
||||
this.filter();
|
||||
});
|
||||
}
|
||||
|
||||
filter() {
|
||||
const jobs = document.querySelector(`[${this.prefix}-list]`).children;
|
||||
if (jobs.length === 0) return;
|
||||
//reset
|
||||
for (let i = 0; i < jobs.length; i++) {
|
||||
const el = jobs[i];
|
||||
el.classList.remove("hidden");
|
||||
}
|
||||
//filter type
|
||||
this.setFilterSuccess(jobs);
|
||||
this.setFilterReload(jobs);
|
||||
this.setFilterKeyword(jobs);
|
||||
}
|
||||
|
||||
setFilterSuccess(jobs) {
|
||||
if (this.successValue === "all") return;
|
||||
for (let i = 0; i < jobs.length; i++) {
|
||||
const el = jobs[i];
|
||||
const type = el
|
||||
.querySelector(`[${this.prefix}-success]`)
|
||||
.getAttribute(`${this.prefix}-success`)
|
||||
.trim();
|
||||
if (type !== this.successValue) el.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
setFilterReload(jobs) {
|
||||
if (this.reloadValue === "all") return;
|
||||
for (let i = 0; i < jobs.length; i++) {
|
||||
const el = jobs[i];
|
||||
const type = el
|
||||
.querySelector(`[${this.prefix}-reload]`)
|
||||
.getAttribute(`${this.prefix}-reload`)
|
||||
.trim();
|
||||
if (type !== this.reloadValue) el.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
setFilterKeyword(jobs) {
|
||||
const keyword = this.keyInp.value.trim().toLowerCase();
|
||||
if (!keyword) return;
|
||||
for (let i = 0; i < jobs.length; i++) {
|
||||
const el = jobs[i];
|
||||
const name = el
|
||||
.querySelector(`[${this.prefix}-name`)
|
||||
.textContent.trim()
|
||||
.toLowerCase();
|
||||
const date = el
|
||||
.querySelector(`[${this.prefix}-last_run`)
|
||||
.textContent.trim()
|
||||
.toLowerCase();
|
||||
const every = el
|
||||
.querySelector(`[${this.prefix}-every`)
|
||||
.textContent.trim()
|
||||
.toLowerCase();
|
||||
|
||||
if (
|
||||
!name.includes(keyword) &&
|
||||
!date.includes(keyword) &&
|
||||
!every.includes(keyword)
|
||||
)
|
||||
el.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Download {
|
||||
constructor(prefix = "jobs") {
|
||||
this.prefix = prefix;
|
||||
this.listContainer = document.querySelector(`[${this.prefix}-list]`);
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.listContainer.addEventListener("click", (e) => {
|
||||
try {
|
||||
if (
|
||||
e.target.closest("button").hasAttribute(`${this.prefix}-download`)
|
||||
) {
|
||||
const btnEl = e.target.closest("button");
|
||||
const jobName = btnEl.getAttribute("jobs-download");
|
||||
const fileName = btnEl.getAttribute("jobs-file");
|
||||
this.sendFileToDL(jobName, fileName);
|
||||
}
|
||||
} catch (err) {}
|
||||
});
|
||||
}
|
||||
|
||||
async sendFileToDL(jobName, fileName) {
|
||||
const response = await fetch(
|
||||
`${location.href}/jobs/download?job_name=${jobName}&file_name=${fileName}`
|
||||
);
|
||||
|
||||
if (response.status === 200) {
|
||||
const res = await response.json();
|
||||
//last update
|
||||
return console.log(res);
|
||||
} else {
|
||||
console.log(`Error: ${response.status}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const setDropdown = new Dropdown("jobs");
|
||||
const setFilter = new Filter("jobs");
|
||||
const setDownload = new Download();
|
|
@ -1,7 +1,7 @@
|
|||
import { Checkbox } from "./utils.js";
|
||||
import Datepicker from "./datepicker/datepicker.js";
|
||||
|
||||
class LogsDropdown {
|
||||
class Dropdown {
|
||||
constructor(prefix = "logs") {
|
||||
this.prefix = prefix;
|
||||
this.container = document.querySelector("main");
|
||||
|
@ -18,6 +18,13 @@ class LogsDropdown {
|
|||
.hasAttribute(`${this.prefix}-setting-select`) &&
|
||||
!e.target.closest("button").hasAttribute(`disabled`)
|
||||
) {
|
||||
const btnName = e.target
|
||||
.closest("button")
|
||||
.getAttribute(`${this.prefix}-setting-select`);
|
||||
if (this.lastDrop !== btnName) {
|
||||
this.lastDrop = btnName;
|
||||
this.closeAllDrop();
|
||||
}
|
||||
this.toggleSelectBtn(e);
|
||||
}
|
||||
} catch (err) {}
|
||||
|
@ -50,6 +57,23 @@ class LogsDropdown {
|
|||
});
|
||||
}
|
||||
|
||||
closeAllDrop() {
|
||||
const drops = document.querySelectorAll(
|
||||
`[${this.prefix}-setting-select-dropdown]`
|
||||
);
|
||||
drops.forEach((drop) => {
|
||||
drop.classList.add("hidden");
|
||||
drop.classList.remove("flex");
|
||||
document
|
||||
.querySelector(
|
||||
`svg[${this.prefix}-setting-select="${drop.getAttribute(
|
||||
`${this.prefix}-setting-select-dropdown`
|
||||
)}"]`
|
||||
)
|
||||
.classList.remove("rotate-180");
|
||||
});
|
||||
}
|
||||
|
||||
isSameValue(btnSetting, value) {
|
||||
const selectCustom = document.querySelector(
|
||||
`[${this.prefix}-setting-select-text="${btnSetting}"]`
|
||||
|
@ -319,7 +343,7 @@ class FetchLogs {
|
|||
}
|
||||
}
|
||||
|
||||
class FilterLogs {
|
||||
class Filter {
|
||||
constructor(prefix = "logs") {
|
||||
this.prefix = prefix;
|
||||
this.container = document.querySelector(`[${this.prefix}-filter]`);
|
||||
|
@ -409,8 +433,8 @@ class LogsDate {
|
|||
}
|
||||
|
||||
const setCheckbox = new Checkbox("[logs-settings]");
|
||||
const dropdown = new LogsDropdown();
|
||||
const dropdown = new Dropdown("logs");
|
||||
const setLogs = new FetchLogs();
|
||||
const setFilter = new FilterLogs();
|
||||
const setFilter = new Filter("logs");
|
||||
const fromDatepicker = new LogsDate(document.querySelector("input#from-date"));
|
||||
const toDatepicker = new LogsDate(document.querySelector("input#to-date"));
|
||||
|
|
|
@ -1,29 +1,4 @@
|
|||
class Upload {
|
||||
constructor() {
|
||||
this.dropEl = document.querySelector("#dropzone");
|
||||
this.drop = new Dropzone(this.dropEl, {
|
||||
paramName: "file",
|
||||
method: "post",
|
||||
maxFiles: 100,
|
||||
autoProcessQueue: false,
|
||||
uploadMultiple: true,
|
||||
parallelUploads: 100,
|
||||
url: "#",
|
||||
});
|
||||
this.submitBtn = this.dropEl.querySelector('button[type="submit"]');
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.submitBtn.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
drop.processQueue();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class PluginsDropdown {
|
||||
class Dropdown {
|
||||
constructor(prefix = "plugins") {
|
||||
this.prefix = prefix;
|
||||
this.container = document.querySelector("main");
|
||||
|
@ -40,6 +15,14 @@ class PluginsDropdown {
|
|||
.hasAttribute(`${this.prefix}-setting-select`) &&
|
||||
!e.target.closest("button").hasAttribute(`disabled`)
|
||||
) {
|
||||
const btnName = e.target
|
||||
.closest("button")
|
||||
.getAttribute(`${this.prefix}-setting-select`);
|
||||
if (this.lastDrop !== btnName) {
|
||||
this.lastDrop = btnName;
|
||||
this.closeAllDrop();
|
||||
}
|
||||
|
||||
this.toggleSelectBtn(e);
|
||||
}
|
||||
} catch (err) {}
|
||||
|
@ -72,6 +55,23 @@ class PluginsDropdown {
|
|||
});
|
||||
}
|
||||
|
||||
closeAllDrop() {
|
||||
const drops = document.querySelectorAll(
|
||||
`[${this.prefix}-setting-select-dropdown]`
|
||||
);
|
||||
drops.forEach((drop) => {
|
||||
drop.classList.add("hidden");
|
||||
drop.classList.remove("flex");
|
||||
document
|
||||
.querySelector(
|
||||
`svg[${this.prefix}-setting-select="${drop.getAttribute(
|
||||
`${this.prefix}-setting-select-dropdown`
|
||||
)}"]`
|
||||
)
|
||||
.classList.remove("rotate-180");
|
||||
});
|
||||
}
|
||||
|
||||
isSameValue(btnSetting, value) {
|
||||
const selectCustom = document.querySelector(
|
||||
`[${this.prefix}-setting-select-text="${btnSetting}"]`
|
||||
|
@ -170,7 +170,7 @@ class PluginsDropdown {
|
|||
}
|
||||
}
|
||||
|
||||
class FilterPlugins {
|
||||
class Filter {
|
||||
constructor(prefix = "plugins") {
|
||||
this.prefix = prefix;
|
||||
this.container = document.querySelector(`[${this.prefix}-filter]`);
|
||||
|
@ -242,6 +242,166 @@ class FilterPlugins {
|
|||
}
|
||||
}
|
||||
|
||||
class Upload {
|
||||
constructor() {
|
||||
this.container = document.querySelector("[plugins-upload]");
|
||||
this.form = document.querySelector("#dropzone-form");
|
||||
this.dropZoneElement = document.querySelector(".drop-zone");
|
||||
this.fileInput = document.querySelector(".file-input");
|
||||
this.progressArea = document.querySelector(".progress-area");
|
||||
this.uploadedArea = document.querySelector(".uploaded-area");
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
//form click launch input file
|
||||
this.form.addEventListener("click", () => {
|
||||
this.fileInput.click();
|
||||
});
|
||||
//dropzone logic
|
||||
this.dropZoneElement.addEventListener("dragover", (e) => {
|
||||
e.preventDefault();
|
||||
this.dropZoneElement.classList.add("bg-gray-100 dark:bg-gray-800");
|
||||
});
|
||||
|
||||
["dragleave", "dragend"].forEach((type) => {
|
||||
this.dropZoneElement.addEventListener(type, (e) => {
|
||||
this.dropZoneElement.classList.remove("bg-gray-100 dark:bg-gray-800");
|
||||
});
|
||||
});
|
||||
|
||||
this.dropZoneElement.addEventListener("drop", (e) => {
|
||||
e.preventDefault();
|
||||
this.fileInput.files = e.dataTransfer.files;
|
||||
this.fileInput.dispatchEvent(new Event("change"));
|
||||
this.dropZoneElement.classList.remove("bg-gray-100 dark:bg-gray-800");
|
||||
});
|
||||
//when added file, set upload logic
|
||||
this.fileInput.addEventListener("change", () => {
|
||||
const timeout = 500;
|
||||
for (let i = 0; i < this.fileInput.files.length; i++) {
|
||||
setTimeout(() => this.uploadFile(this.fileInput.files[i]), timeout * i);
|
||||
}
|
||||
});
|
||||
//close fail/success log
|
||||
this.container.addEventListener("click", (e) => {
|
||||
try {
|
||||
if (e.target.closest("button").hasAttribute("upload-message-delete")) {
|
||||
const message = e.target.closest("div[upload-message]");
|
||||
message.remove();
|
||||
}
|
||||
} catch (err) {}
|
||||
});
|
||||
}
|
||||
|
||||
uploadFile(file) {
|
||||
let name = file.name;
|
||||
if (name.length >= 12) {
|
||||
let splitName = name.split(".");
|
||||
name = splitName[0].substring(0, 13) + "... ." + splitName[1];
|
||||
}
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "plugins/upload");
|
||||
let fileSize;
|
||||
|
||||
xhr.upload.addEventListener("progress", ({ loaded, total }) => {
|
||||
let fileLoaded = Math.floor((loaded / total) * 100);
|
||||
let fileTotal = Math.floor(total / 1000);
|
||||
|
||||
fileTotal < 1024
|
||||
? (fileSize = fileTotal + " KB")
|
||||
: (fileSize = (loaded / (1024 * 1024)).toFixed(2) + " MB");
|
||||
|
||||
const progressHTML = this.fileLoad(name, fileSize);
|
||||
|
||||
this.uploadedArea.classList.add("onprogress");
|
||||
this.progressArea.innerHTML = progressHTML;
|
||||
});
|
||||
|
||||
xhr.addEventListener("readystatechange", () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
this.progressArea.innerHTML = "";
|
||||
let uploadedHTML =
|
||||
xhr.status == 201
|
||||
? this.fileSuccess(name, fileSize)
|
||||
: this.fileFail(name, fileSize);
|
||||
this.uploadedArea.insertAdjacentHTML("afterbegin", uploadedHTML);
|
||||
}
|
||||
});
|
||||
|
||||
let data = new FormData();
|
||||
data.set("file", file);
|
||||
data.set("csrf_token", document.querySelector("#csrf_token").value);
|
||||
xhr.send(data);
|
||||
}
|
||||
|
||||
fileLoad(name, fileSize) {
|
||||
const str = `<div u class="mt-2 rounded p-2 w-full bg-gray-100 dark:bg-gray-800">
|
||||
<div class="flex items-center justify-between">
|
||||
<svg class="fill-sky-500 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM385 215c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-71-71V392c0 13.3-10.7 24-24 24s-24-10.7-24-24V177.9l-71 71c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9L239 103c9.4-9.4 24.6-9.4 33.9 0L385 215z"/></svg>
|
||||
<span class="text-sm text-slate-700 dark:text-gray-300 mr-4">${name} </span>
|
||||
<span class="text-sm text-slate-700 dark:text-gray-300">${fileSize}</span>
|
||||
<svg class="cursor-pointer fill-gray-600 dark:fill-gray-300 dark:opacity-80 h-3 w-3 " xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512z"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
return str;
|
||||
}
|
||||
|
||||
fileSuccess(name, fileSize) {
|
||||
const str = `<div upload-message class="mt-2 rounded p-2 w-full bg-gray-100 dark:bg-gray-800">
|
||||
<div class="flex items-center justify-between">
|
||||
<svg
|
||||
class="fill-green-500 h-5 w-5"
|
||||
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 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="text-sm text-slate-700 dark:text-gray-300 mr-4">${name} </span>
|
||||
<span class="text-sm text-slate-700 dark:text-gray-300">${fileSize}</span>
|
||||
<button type="button" upload-message-delete>
|
||||
<svg class="cursor-pointer fill-gray-600 dark:fill-gray-300 dark:opacity-80 h-4 w-4 " xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
|
||||
<path d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
return str;
|
||||
}
|
||||
|
||||
fileFail(name, fileSize) {
|
||||
const str = `<div upload-message class="mt-2 rounded p-2 w-full bg-gray-100 dark:bg-gray-800">
|
||||
<div class="flex items-center justify-between">
|
||||
<svg
|
||||
class="fill-red-500 h-5 w-5 mr-4"
|
||||
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 512zM175 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="text-sm text-slate-700 dark:text-gray-300 mr-4">${name} </span>
|
||||
<span class="text-sm text-slate-700 dark:text-gray-300">${fileSize}</span>
|
||||
<button type="button" upload-message-delete>
|
||||
|
||||
<svg class="cursor-pointer fill-gray-600 dark:fill-gray-300 dark:opacity-80 h-4 w-4 " xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
|
||||
<path d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
const setDropdown = new Dropdown("plugins");
|
||||
const setFilter = new Filter("plugins");
|
||||
const setUpload = new Upload();
|
||||
const setDropdown = new PluginsDropdown();
|
||||
const setFilter = new FilterPlugins();
|
||||
|
|
|
@ -233,9 +233,291 @@ class ServiceModal {
|
|||
}
|
||||
}
|
||||
|
||||
class Multiple {
|
||||
constructor(prefix) {
|
||||
this.prefix = prefix;
|
||||
this.container = document.querySelector("main");
|
||||
this.modalForm = document.querySelector(`[${this.prefix}-modal-form]`);
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.container.addEventListener("click", (e) => {
|
||||
//edit button
|
||||
try {
|
||||
if (
|
||||
e.target.closest("button").getAttribute("services-action") === "edit"
|
||||
) {
|
||||
//remove all multiples
|
||||
this.removeMultiples();
|
||||
//set multiple service values
|
||||
const servicesSettings = e.target
|
||||
.closest("[services-service]")
|
||||
.querySelector("[services-settings]")
|
||||
.getAttribute("value");
|
||||
const obj = JSON.parse(servicesSettings);
|
||||
this.updateModalMultiples(obj);
|
||||
}
|
||||
} catch (err) {}
|
||||
});
|
||||
|
||||
this.modalForm.addEventListener("click", (e) => {
|
||||
//ADD BTN
|
||||
try {
|
||||
if (
|
||||
e.target.closest("button").hasAttribute(`${this.prefix}-multiple-add`)
|
||||
) {
|
||||
//get plugin from btn
|
||||
const btn = e.target.closest("button");
|
||||
const serviceName = btn.getAttribute(`${this.prefix}-multiple-add`);
|
||||
//get all multiple groups
|
||||
const multipleEls = document.querySelectorAll(
|
||||
`[${this.prefix}-settings-multiple*="${serviceName}"]`
|
||||
);
|
||||
const count = Number(
|
||||
multipleEls[1]
|
||||
.getAttribute(`${this.prefix}-settings-multiple`)
|
||||
.substring(
|
||||
multipleEls[1].getAttribute(`${this.prefix}-settings-multiple`)
|
||||
.length - 1
|
||||
)
|
||||
);
|
||||
//the default (schema) group is the last group
|
||||
const schema = document.querySelector(
|
||||
`[${this.prefix}-settings-multiple="${serviceName}_SCHEMA"]`
|
||||
);
|
||||
//clone it and change name by total - 1 (schema is hidden)
|
||||
const clone = schema.cloneNode(true);
|
||||
console.log(clone.getAttribute("services-settings-multiple"));
|
||||
const name = clone
|
||||
.getAttribute("services-settings-multiple")
|
||||
.replace(`SCHEMA`, `${count + 1}`);
|
||||
clone.setAttribute("services-settings-multiple", name);
|
||||
this.showMultiple(clone);
|
||||
try {
|
||||
const cloneContainer = clone.querySelectorAll(
|
||||
"[setting-container]"
|
||||
);
|
||||
cloneContainer.forEach((ctnr) => {
|
||||
const newName = ctnr
|
||||
.getAttribute("setting-container")
|
||||
.replace("SCHEMA", `${count + 1}`);
|
||||
ctnr.setAttribute("setting-container", newName);
|
||||
});
|
||||
} catch (err) {}
|
||||
|
||||
try {
|
||||
const cloneTitles = clone.querySelectorAll("h5");
|
||||
cloneTitles.forEach((title) => {
|
||||
title.textContent = `${title.textContent} #${count + 1}`;
|
||||
});
|
||||
} catch (err) {}
|
||||
|
||||
const setNameID = ["input", "select"];
|
||||
|
||||
setNameID.forEach((name) => {
|
||||
try {
|
||||
this.setNameIDloop(clone.querySelectorAll(name), count + 1);
|
||||
} catch (err) {}
|
||||
});
|
||||
|
||||
//insert new group before first one
|
||||
schema.insertAdjacentElement("afterend", clone);
|
||||
}
|
||||
} catch (err) {}
|
||||
|
||||
//REMOVE BTN
|
||||
try {
|
||||
if (
|
||||
e.target
|
||||
.closest("button")
|
||||
.hasAttribute(`${this.prefix}-multiple-delete`)
|
||||
) {
|
||||
const multContainer = e.target.closest(
|
||||
"[services-settings-multiple]"
|
||||
);
|
||||
multContainer.remove();
|
||||
}
|
||||
//remove last child
|
||||
} catch (err) {}
|
||||
});
|
||||
}
|
||||
|
||||
updateModalMultiples(settings) {
|
||||
//keep only multiple settings value
|
||||
const multipleSettings = this.filterMultiple(settings);
|
||||
//put multiple on the right plugin, on schema container
|
||||
this.setMultipleToDOM(multipleSettings);
|
||||
//for each schema container, check if custom multiple (ending with _num)
|
||||
//and sort them on containers by nums
|
||||
//and check to keep default data (schema) or custom multiple value if exists
|
||||
this.sortMultiplesByNum();
|
||||
//remove custom multiple from schema to avoid them on add btn using schema container
|
||||
this.removeCustomFromSchema();
|
||||
}
|
||||
|
||||
//keep only multiple settings value
|
||||
filterMultiple(settings) {
|
||||
const multiple = {};
|
||||
for (const [key, data] of Object.entries(settings)) {
|
||||
if (!isNaN(key[key.length - 1]) && key[key.length - 2] === "_") {
|
||||
multiple[key] = {
|
||||
value: data["value"],
|
||||
method: data["method"],
|
||||
};
|
||||
}
|
||||
}
|
||||
return multiple;
|
||||
}
|
||||
|
||||
//put multiple on the right plugin, on schema container
|
||||
setMultipleToDOM(multiples) {
|
||||
//add them to the right plugin
|
||||
for (const [key, data] of Object.entries(multiples)) {
|
||||
const num = key[key.length - 1];
|
||||
const getSchemaKey = key.substring(0, key.length - 2);
|
||||
const getSchemaSetting = document.querySelector(
|
||||
`[setting-container="${getSchemaKey}_SCHEMA"]`
|
||||
);
|
||||
const cloneSchemaSetting = getSchemaSetting.cloneNode(true);
|
||||
//replace info
|
||||
cloneSchemaSetting.setAttribute("setting-container", key);
|
||||
const title = cloneSchemaSetting.querySelector("h5");
|
||||
title.textContent = `${title.textContent} #${num}`;
|
||||
//replace input info
|
||||
try {
|
||||
const inp = cloneSchemaSetting.querySelector("input");
|
||||
this.setNameID(inp, key);
|
||||
} catch (err) {}
|
||||
//or select
|
||||
try {
|
||||
const select = cloneSchemaSetting.querySelector("select");
|
||||
this.setNameID(select, key);
|
||||
} catch (err) {}
|
||||
getSchemaSetting.insertAdjacentElement("beforebegin", cloneSchemaSetting);
|
||||
}
|
||||
}
|
||||
|
||||
//for each schema container, check if custom multiple (ending with _num)
|
||||
//and sort them on containers by nums
|
||||
//and check to keep default data (schema) or custom multiple value if exists
|
||||
sortMultiplesByNum() {
|
||||
const multiPlugins = document.querySelectorAll(
|
||||
`[${this.prefix}-settings-multiple*='SCHEMA']`
|
||||
);
|
||||
multiPlugins.forEach((defaultGrp) => {
|
||||
//get group number for the multiples settings
|
||||
const multipleEls = defaultGrp.querySelectorAll("[setting-container]");
|
||||
const multNum = new Set();
|
||||
multipleEls.forEach((setting) => {
|
||||
const name = setting.getAttribute("setting-container");
|
||||
if (!isNaN(name[name.length - 1])) multNum.add(name[name.length - 1]);
|
||||
});
|
||||
//create a different group for each number
|
||||
multNum.forEach((num) => {
|
||||
const newGroup = defaultGrp.cloneNode(true);
|
||||
this.showMultiple(newGroup);
|
||||
//change groupe name
|
||||
const currName = newGroup.getAttribute(
|
||||
`${this.prefix}-settings-multiple`
|
||||
);
|
||||
newGroup.setAttribute(
|
||||
`${this.prefix}-settings-multiple`,
|
||||
currName.replace("SCHEMA", num)
|
||||
);
|
||||
|
||||
//remove elements that not fit num unless schema if no custom value
|
||||
const newGroupSettings = newGroup.querySelectorAll(
|
||||
"[setting-container]"
|
||||
);
|
||||
newGroupSettings.forEach((setting) => {
|
||||
//remove logic
|
||||
const settingName = setting.getAttribute("setting-container");
|
||||
if (
|
||||
(!settingName.endsWith(num) && !settingName.endsWith("SCHEMA")) ||
|
||||
(settingName.endsWith("SCHEMA") &&
|
||||
document.querySelector(`${settingName.replace("SCHEMA", num)}`))
|
||||
) {
|
||||
return setting.remove();
|
||||
}
|
||||
//else update info by num
|
||||
setting.setAttribute(
|
||||
"setting-container",
|
||||
setting.getAttribute("setting-container").replace(`SCHEMA`, num)
|
||||
);
|
||||
const title = setting.querySelector("h5");
|
||||
if (!title.textContent.includes(`#${num}`))
|
||||
title.textContent = `${title.textContent} #${num}`;
|
||||
//replace input info
|
||||
|
||||
const setNameID = ["input", "select"];
|
||||
|
||||
setNameID.forEach((name) => {
|
||||
try {
|
||||
this.setNameID(
|
||||
setting.querySelector(name),
|
||||
setting.getAttribute("setting-container")
|
||||
);
|
||||
} catch (err) {}
|
||||
});
|
||||
});
|
||||
defaultGrp.insertAdjacentElement("afterend", newGroup);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
removeCustomFromSchema() {
|
||||
const multiPlugins = document.querySelectorAll(
|
||||
`[${this.prefix}-settings-multiple*='SCHEMA']`
|
||||
);
|
||||
|
||||
multiPlugins.forEach((defaultGrp) => {
|
||||
const multipleEls = defaultGrp.querySelectorAll("[setting-container]");
|
||||
multipleEls.forEach((setting) => {
|
||||
const settingName = setting.getAttribute("setting-container");
|
||||
if (!settingName.endsWith("SCHEMA")) setting.remove();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//UTILS
|
||||
|
||||
removeMultiples() {
|
||||
const multiPlugins = document.querySelectorAll(
|
||||
`[${this.prefix}-settings-multiple]`
|
||||
);
|
||||
multiPlugins.forEach((multiGrp) => {
|
||||
if (
|
||||
!multiGrp.getAttribute("services-settings-multiple").includes("SCHEMA")
|
||||
)
|
||||
multiGrp.remove();
|
||||
});
|
||||
}
|
||||
|
||||
showMultiple(el) {
|
||||
el.classList.add("grid");
|
||||
el.classList.remove("hidden");
|
||||
}
|
||||
|
||||
setNameIDloop(iterable, value) {
|
||||
iterable.forEach((item) => {
|
||||
const currID = item.getAttribute("id");
|
||||
const currName = item.getAttribute("name");
|
||||
item.setAttribute("id", `${currID}_${value}`);
|
||||
item.setAttribute("name", `${currName}_${value}`);
|
||||
});
|
||||
}
|
||||
|
||||
setNameID(el, value) {
|
||||
el.setAttribute("id", `${value}`);
|
||||
el.setAttribute("name", `${value}`);
|
||||
}
|
||||
}
|
||||
|
||||
const setCheckbox = new Checkbox("[services-modal-form]");
|
||||
const setSelect = new Select("[services-modal-form]", "services");
|
||||
const setPopover = new Popover("main", "services");
|
||||
const setTabs = new Tabs("[services-tabs]", "services");
|
||||
const setModal = new ServiceModal();
|
||||
const format = new FormatValue();
|
||||
const setMultiple = new Multiple("services");
|
||||
|
|
|
@ -907,11 +907,48 @@ class FormatValue {
|
|||
|
||||
init() {
|
||||
this.inputs.forEach((inp) => {
|
||||
console.log(inp);
|
||||
inp.setAttribute("value", inp.getAttribute("value").trim());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class Loader {
|
||||
constructor() {
|
||||
this.menuContainer = document.querySelector("[menu-container]");
|
||||
this.logoContainer = document.querySelector("[loader]");
|
||||
this.logoEl = document.querySelector("[loader-img]");
|
||||
this.isLoading = true;
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.loading();
|
||||
window.addEventListener("load", (e) => {
|
||||
setTimeout(() => {
|
||||
this.logoContainer.classList.add("opacity-0");
|
||||
}, 350);
|
||||
|
||||
setTimeout(() => {
|
||||
this.isLoading = false;
|
||||
this.logoContainer.classList.add("hidden");
|
||||
}, 650);
|
||||
|
||||
setTimeout(() => {
|
||||
this.logoContainer.remove();
|
||||
}, 800);
|
||||
});
|
||||
}
|
||||
|
||||
loading() {
|
||||
if ((this.isLoading = true)) {
|
||||
setTimeout(() => {
|
||||
this.logoEl.classList.toggle("scale-105");
|
||||
this.loading();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
Checkbox,
|
||||
Popover,
|
||||
|
@ -922,4 +959,5 @@ export {
|
|||
FolderEditor,
|
||||
FolderDropdown,
|
||||
FormatValue,
|
||||
Loader,
|
||||
};
|
||||
|
|
|
@ -9,34 +9,46 @@
|
|||
<noscript class="relative w-full p-4 text-white bg-yellow-500 rounded-lg"
|
||||
>Your browser does not support JavaScript!</noscript
|
||||
>
|
||||
|
||||
<!--fixed background-->
|
||||
<div class="absolute w-full dark:hidden bg-primary"></div>
|
||||
<!-- end fixed background-->
|
||||
<div
|
||||
loader
|
||||
class="fixed z-[10000] transition duration-300 h-screen w-screen bg-primary flex justify-center align-middle items-center"
|
||||
>
|
||||
<img
|
||||
loader-img
|
||||
src="images/logo-menu-2.png"
|
||||
class="duration-300 w-40 h-12 sm:w-50 sm:h-14 md:w-60 md:h-16 lg:w-80 lg:h-24 inline transition-all"
|
||||
alt="main logo"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{% include "menu.html" %} {% include "news.html" %}
|
||||
|
||||
<div
|
||||
class="w-full relative h-full max-h-screen transition-all duration-200 ease-in-out xl:ml-68 rounded-xl"
|
||||
>
|
||||
{% include "header.html" %}
|
||||
{% include "header.html" %} {% with messages =
|
||||
get_flashed_messages(with_categories=true) %} {% if messages %}
|
||||
<!-- flash message-->
|
||||
{% with messages = get_flashed_messages(with_categories=true) %} {% if
|
||||
messages %} {% for category, message in messages %}
|
||||
{% for category, message in messages %}
|
||||
<div
|
||||
flash-message
|
||||
class="hidden p-4 mb-1 md:mb-3 md:mr-3 z-[1001] flex flex-col fixed bottom-0 right-0 w-full md:w-1/2 max-w-screen-sm min-h-20 bg-white rounded-lg dark:brightness-110 hover:scale-102 transition shadow-md break-words dark:bg-slate-850 dark:shadow-dark-xl bg-clip-border"
|
||||
class="p-4 mb-1 md:mb-3 md:mr-3 z-[1001] flex flex-col fixed bottom-0 right-0 w-full md:w-1/2 max-w-[300px] min-h-20 bg-white rounded-lg dark:brightness-110 hover:scale-102 transition shadow-md break-words dark:bg-slate-850 dark:shadow-dark-xl bg-clip-border"
|
||||
>
|
||||
{% if category == 'error' %}
|
||||
<h5 class="text-lg mb-0 text-red-500">error</h5>
|
||||
<p class="text-red-500 mb-0 text-sm">{{ message|safe }}</p>
|
||||
{% endif %} {% if category == 'success' %}
|
||||
<h5 class="text-lg mb-0 text-green-500">success</h5>
|
||||
<p class="text-green-500 mb-0 text-sm">{{ message|safe }}</p>
|
||||
<h5 class="text-lg mb-0 text-red-500">Error</h5>
|
||||
<p class="text-gray-700 dark:text-gray-300 mb-0 text-sm">
|
||||
{{ message|safe }}
|
||||
</p>
|
||||
{% else %}
|
||||
<h5 class="text-lg mb-0 text-green-500">Success</h5>
|
||||
<p class="text-gray-700 dark:text-gray-300 mb-0 text-sm">
|
||||
{{ message|safe }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
<!-- end flash message-->
|
||||
{% endfor %} {% endif %} {% endwith %}
|
||||
{% endif %} {% endwith %}
|
||||
</div>
|
||||
<!-- info -->
|
||||
<main
|
||||
|
|
|
@ -34,24 +34,19 @@
|
|||
{% elif current_endpoint == "services" %}
|
||||
<script defer type="module" src="./js/services.js"></script>
|
||||
{% elif current_endpoint == "plugins" %}
|
||||
<script type="module" defer src="./js/dropzone/dropzone-min.js"></script>
|
||||
<script
|
||||
type="application"
|
||||
defer
|
||||
src="./js/dropzone/dropzone-min.js.map"
|
||||
></script>
|
||||
<script type="module" defer src="./js/plugins.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="./css/dropzone/dropzone.css" />
|
||||
{% elif current_endpoint == "cache" %}
|
||||
<script defer type="module" src="./js/cache.js"></script>
|
||||
{% elif current_endpoint == "logs" %}
|
||||
<script type="module" defer src="./js/logs.js"></script>
|
||||
<script type="module" defer src="./js/datepicker/Datepicker.js"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="./css/datepicker-foundation.css"
|
||||
/>
|
||||
{% elif current_endpoint == "jobs" %}
|
||||
<script defer type="module" src="./js/jobs.js"></script>
|
||||
|
||||
<script type="module" defer src="./js/logs.js"></script>
|
||||
{% endif %}
|
||||
</head>
|
||||
|
|
|
@ -47,7 +47,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
<!-- filter -->
|
||||
<div
|
||||
{{current_endpoint}}-filter
|
||||
class="col-span-12 md:col-span-8 3xl:col-span-3 p-4 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"
|
||||
class="col-span-12 md:col-span-8 2xl:col-span-6 p-4 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"
|
||||
>
|
||||
<h5 class="mb-2 font-bold dark:text-white">FILTER</h5>
|
||||
<div class="grid grid-cols-12 gap-x-4 gap-y-2">
|
||||
|
@ -63,82 +63,19 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
id="keyword"
|
||||
name="keyword"
|
||||
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="key words"
|
||||
placeholder="keyword"
|
||||
pattern="(.*?)"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<!-- end search inpt-->
|
||||
<!-- select sort -->
|
||||
<div class="flex flex-col relative col-span-12 md:col-span-6">
|
||||
<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"
|
||||
>
|
||||
Sort by
|
||||
</h5>
|
||||
<button
|
||||
{{current_endpoint}}-setting-select="sort"
|
||||
type="button"
|
||||
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
|
||||
id="{{current_endpoint}}-sort"
|
||||
name="{{current_endpoint}}-sort"
|
||||
{{current_endpoint}}-setting-select-text="sort"
|
||||
>name</span
|
||||
>
|
||||
<!-- chevron -->
|
||||
<svg
|
||||
{{current_endpoint}}-setting-select="sort"
|
||||
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
|
||||
{{current_endpoint}}-setting-select-dropdown="sort"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-12"
|
||||
>
|
||||
<button
|
||||
{{current_endpoint}}-setting-select-dropdown-btn="sort"
|
||||
type="button"
|
||||
value="name"
|
||||
class="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 dark:bg-primary bg-primary text-gray-300"
|
||||
>
|
||||
name
|
||||
</button>
|
||||
<button
|
||||
{{current_endpoint}}-setting-select-dropdown-btn="sort"
|
||||
type="button"
|
||||
value="last run"
|
||||
class="border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 bg-white text-gray-700 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:bg-slate-700 dark:text-gray-300"
|
||||
>
|
||||
last run
|
||||
</button>
|
||||
<button
|
||||
{{current_endpoint}}-setting-select-dropdown-btn="sort"
|
||||
type="button"
|
||||
value="true"
|
||||
class="border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 bg-white text-gray-700 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:bg-slate-700 dark:text-gray-300"
|
||||
>
|
||||
true
|
||||
</button>
|
||||
</div>
|
||||
<!-- end dropdown-->
|
||||
</div>
|
||||
<!-- end select success -->
|
||||
|
||||
<!-- select success -->
|
||||
<div class="flex flex-col relative col-span-12 md:col-span-6">
|
||||
<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"
|
||||
>
|
||||
Select success
|
||||
Success state
|
||||
</h5>
|
||||
<button
|
||||
{{current_endpoint}}-setting-select="success"
|
||||
|
@ -167,7 +104,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
<!-- dropdown-->
|
||||
<div
|
||||
{{current_endpoint}}-setting-select-dropdown="success"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-12"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-16"
|
||||
>
|
||||
<button
|
||||
{{current_endpoint}}-setting-select-dropdown-btn="success"
|
||||
|
@ -202,7 +139,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
<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"
|
||||
>
|
||||
Select reload
|
||||
Reload state
|
||||
</h5>
|
||||
<button
|
||||
{{current_endpoint}}-setting-select="reload"
|
||||
|
@ -231,7 +168,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
<!-- dropdown-->
|
||||
<div
|
||||
{{current_endpoint}}-setting-select-dropdown="reload"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-12"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-16"
|
||||
>
|
||||
<button
|
||||
{{current_endpoint}}-setting-select-dropdown-btn="reload"
|
||||
|
@ -270,7 +207,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
>
|
||||
<h5 class="mb-2 font-bold dark:text-white">{{current_endpoint}}</h5>
|
||||
<!-- list container-->
|
||||
<div class="min-w-[750px] w-full grid grid-cols-12 rounded p-2">
|
||||
<div class="min-w-[900px] w-full grid grid-cols-12 rounded p-2">
|
||||
<!-- header-->
|
||||
<p
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-3 m-0 pb-2 border-b border-gray-400"
|
||||
|
@ -278,120 +215,180 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
Name
|
||||
</p>
|
||||
<p
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-2 m-0 pb-2 border-b border-gray-400"
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-3 m-0 pb-2 border-b border-gray-400"
|
||||
>
|
||||
Last run
|
||||
</p>
|
||||
<p
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-2 m-0 pb-2 border-b border-gray-400"
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-1 m-0 pb-2 border-b border-gray-400"
|
||||
>
|
||||
Every
|
||||
</p>
|
||||
<p
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-2 m-0 pb-2 border-b border-gray-400"
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-1 m-0 pb-2 border-b border-gray-400"
|
||||
>
|
||||
Reload
|
||||
</p>
|
||||
<p
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-2 m-0 pb-2 border-b border-gray-400"
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-1 m-0 pb-2 border-b border-gray-400"
|
||||
>
|
||||
Success
|
||||
</p>
|
||||
<p
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-1 m-0 pb-2 border-b border-gray-400"
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-3 m-0 pb-2 border-b border-gray-400"
|
||||
>
|
||||
Files
|
||||
</p>
|
||||
<!-- end header-->
|
||||
<!-- list -->
|
||||
<ul class="col-span-12 w-full" {{current_endpoint}}-list>
|
||||
{% for job in jobs %} {{job['every']}}
|
||||
{% for job_name, value in jobs.items() %}
|
||||
<!-- job item-->
|
||||
<li class="grid grid-cols-12 border-b border-gray-300 py-2">
|
||||
<li class="grid grid-cols-12 border-b border-gray-300 py-2.5">
|
||||
<p
|
||||
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-3 m-0"
|
||||
{{current_endpoint}}-name
|
||||
>
|
||||
{{job}}
|
||||
{{job_name}}
|
||||
</p>
|
||||
<p
|
||||
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0"
|
||||
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-3 m-0"
|
||||
{{current_endpoint}}-last_run
|
||||
>
|
||||
{{job['last_run']}}
|
||||
</p>
|
||||
<p
|
||||
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0"
|
||||
{{current_endpoint}}-every
|
||||
>
|
||||
{{job["every"]}}
|
||||
</p>
|
||||
<p
|
||||
class="ml-6 dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0"
|
||||
{{current_endpoint}}-reload
|
||||
>
|
||||
{% if job["reload"] %}
|
||||
<svg
|
||||
class="fill-green-500 h-5 w-5"
|
||||
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 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"
|
||||
/>
|
||||
</svg>
|
||||
{%endif %} {% if not job["reload"] %}
|
||||
<svg
|
||||
class="fill-red-500 h-5 w-5"
|
||||
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 512zM175 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"
|
||||
/>
|
||||
</svg>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p
|
||||
class="ml-6 dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0"
|
||||
{{current_endpoint}}-success
|
||||
>
|
||||
{% if job["success"] == True %}
|
||||
<svg
|
||||
class="fill-green-500 h-5 w-5"
|
||||
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 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"
|
||||
/>
|
||||
</svg>
|
||||
{% elif not job["success"] %}
|
||||
<svg
|
||||
class="fill-red-500 h-5 w-5"
|
||||
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 512zM175 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"
|
||||
/>
|
||||
</svg>
|
||||
{% else %}
|
||||
<svg
|
||||
class="fill-sky-500 h-5 w-5"
|
||||
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 512zM169.8 165.3c7.9-22.3 29.1-37.3 52.8-37.3h58.3c34.9 0 63.1 28.3 63.1 63.1c0 22.6-12.1 43.5-31.7 54.8L280 264.4c-.2 13-10.9 23.6-24 23.6c-13.3 0-24-10.7-24-24V250.5c0-8.6 4.6-16.5 12.1-20.8l44.3-25.4c4.7-2.7 7.6-7.7 7.6-13.1c0-8.4-6.8-15.1-15.1-15.1H222.6c-3.4 0-6.4 2.1-7.5 5.3l-.4 1.2c-4.4 12.5-18.2 19-30.6 14.6s-19-18.2-14.6-30.6l.4-1.2zM288 352c0 17.7-14.3 32-32 32s-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32z"
|
||||
/>
|
||||
</svg>
|
||||
{% endif %}
|
||||
{{value['last_run']}}
|
||||
</p>
|
||||
<p
|
||||
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0"
|
||||
{{current_endpoint}}-every
|
||||
>
|
||||
{{value["every"]}}
|
||||
</p>
|
||||
{% if value["reload"] %}
|
||||
<p
|
||||
class="ml-6 dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0"
|
||||
{{current_endpoint}}-reload="true"
|
||||
>
|
||||
<svg
|
||||
class="fill-green-500 h-5 w-5"
|
||||
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 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
|
||||
{%endif %} {% if not value["reload"] %}
|
||||
<p
|
||||
class="ml-6 dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0"
|
||||
{{current_endpoint}}-reload="false"
|
||||
>
|
||||
<svg
|
||||
class="fill-red-500 h-5 w-5"
|
||||
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 512zM175 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
{% endif %} {% if value["success"] %}
|
||||
<p
|
||||
class="ml-6 dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0"
|
||||
{{current_endpoint}}-success="true"
|
||||
>
|
||||
<svg
|
||||
class="fill-green-500 h-5 w-5"
|
||||
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 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
{% elif not value["success"] %}
|
||||
<p
|
||||
class="ml-6 dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0"
|
||||
{{current_endpoint}}-success="false"
|
||||
>
|
||||
<svg
|
||||
class="fill-red-500 h-5 w-5"
|
||||
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 512zM175 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
{% endif %}
|
||||
<div
|
||||
class="relative dark:text-gray-400 text-sm col-span-3 m-0"
|
||||
{{current_endpoint}}-files
|
||||
></p>
|
||||
>
|
||||
{% if value['cache']%}
|
||||
<button
|
||||
{{current_endpoint}}-setting-select="{{job_name}}"
|
||||
type="button"
|
||||
class="text-sm 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 leading-6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500"
|
||||
>
|
||||
<span
|
||||
id="{{current_endpoint}}-{{job_name}}"
|
||||
name="{{current_endpoint}}-{{job_name}}"
|
||||
{{current_endpoint}}-setting-select-text="{{job_name}}"
|
||||
>list</span
|
||||
>
|
||||
<!-- chevron -->
|
||||
<svg
|
||||
{{current_endpoint}}-setting-select="{{job_name}}"
|
||||
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
|
||||
{{current_endpoint}}-setting-select-dropdown="{{job_name}}"
|
||||
class="hidden z-100 absolute h-full flex-col w-full"
|
||||
>
|
||||
{% for file in value['cache'] %}
|
||||
<button
|
||||
{{current_endpoint}}-download="{{job_name}}"
|
||||
{{current_endpoint}}-file="{{file['file_name']}}"
|
||||
{{current_endpoint}}-setting-select-dropdown-btn="{{job_name}}"
|
||||
type="button"
|
||||
value="list"
|
||||
class="{% if loop.index == loop.length %}rounded-b-lg {% endif %}{% if loop.first %}rounded-t-lg{% 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 bg-white dark:bg-slate-700 text-gray-700"
|
||||
>
|
||||
<div class="flex justify-start items-center">
|
||||
<svg
|
||||
class="h-6 w-6 fill-sky-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
<path
|
||||
d="M256 0C114.6 0 0 114.6 0 256S114.6 512 256 512s256-114.6 256-256S397.4 0 256 0zM244.7 395.3l-112-112c-4.6-4.6-5.9-11.5-3.5-17.4s8.3-9.9 14.8-9.9l64 0 0-96c0-17.7 14.3-32 32-32l32 0c17.7 0 32 14.3 32 32l0 96 64 0c6.5 0 12.3 3.9 14.8 9.9s1.1 12.9-3.5 17.4l-112 112c-6.2 6.2-16.4 6.2-22.6 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="transition duration-300 ease-in-out text-gray-700 dark:text-gray-300 dark:opacity-80 ml-2"
|
||||
>{{file['file_name']}}</span
|
||||
>
|
||||
</div>
|
||||
</button>
|
||||
{%endfor %}
|
||||
</div>
|
||||
<!-- end dropdown-->
|
||||
{%endif%}
|
||||
</div>
|
||||
</li>
|
||||
<!-- end job item-->
|
||||
{% endfor %}
|
||||
|
|
|
@ -9,19 +9,15 @@
|
|||
href="data:image/svg+xml, %%3Csvg version='1.0' xmlns='http://www.w3.org/2000/svg' width='96.000000pt' height='96.000000pt' viewBox='0 0 96.000000 96.000000' preserveAspectRatio='xMidYMid meet'%%3E%%3Cg transform='translate(0.000000,96.000000) scale(0.100000,-0.100000)'%%0Afill='%%23085577' stroke='none'%%3E%%3Cpath d='M535 863 c-22 -2 -139 -17 -260 -34 -228 -31 -267 -43 -272 -85 -2%%0A-10 23 -181 55 -379 l57 -360 400 0 400 0 20 40 c16 31 20 59 19 125 -1 100%%0A-24 165 -73 199 -41 29 -46 57 -22 111 30 67 29 188 -3 256 -13 28 -37 60 -53%%0A72 -55 39 -169 62 -268 55z m-15 -348 c30 -16 60 -61 60 -90 0 -10 -8 -33 -17%%0A-52 -16 -34 -16 -41 0 -116 9 -44 15 -82 12 -85 -6 -7 -92 -21 -131 -21 l-31%%0A-1 -6 85 c-4 75 -8 89 -31 112 -20 20 -26 36 -26 70 0 38 5 50 34 79 39 39 86%%0A45 136 19z'/%%3E%%3C/g%%3E%%3C/svg%%3E"
|
||||
type="image/svg+xml"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="http://127.0.0.1:5501/static/css/dashboard.css"
|
||||
/>
|
||||
<link rel="stylesheet" type="text/css" href="./css/dashboard.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div
|
||||
class="h-screen w-screen bg-primary flex justify-center align-middle items-center"
|
||||
class="fixed h-screen w-screen bg-primary flex justify-center align-middle items-center"
|
||||
>
|
||||
<img
|
||||
src="images/logo-menu-2.png"
|
||||
class="duration-300 w-60 h-16 sm:w-80 sm:h-24 lg:w-90 lg:h-30 inline transition-all"
|
||||
class="duration-300 w-40 h-12 sm:w-50 sm:h-14 md:w-60 md:h-16 lg:w-80 lg:h-24 inline transition-all"
|
||||
alt="main logo"
|
||||
/>
|
||||
</div>
|
||||
|
@ -36,7 +32,7 @@
|
|||
|
||||
async function check_reloading() {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 3000);
|
||||
const timeoutId = setTimeout(() => controller.abort(), 500);
|
||||
const response = await fetch(
|
||||
`${location.href.replace("/loading", "/check_reloading")}`,
|
||||
{ signal: controller.signal }
|
||||
|
|
|
@ -16,23 +16,25 @@
|
|||
<link rel="stylesheet" href="css/dashboard.css" />
|
||||
</head>
|
||||
<body>
|
||||
{% if error %}
|
||||
{% if error %} {% with messages = get_flashed_messages(with_categories=true)
|
||||
%} {% if messages %}
|
||||
<!-- flash message-->
|
||||
{% with messages = get_flashed_messages(with_categories=true) %} {% if
|
||||
messages %} {% for category, message in messages %}
|
||||
{% for category, message in messages %}
|
||||
<div
|
||||
flash-message
|
||||
class="hidden p-4 mb-1 md:mb-3 md:mr-3 z-[1001] flex flex-col fixed bottom-0 right-0 w-full md:w-1/2 max-w-screen-sm min-h-20 bg-white rounded-lg dark:brightness-110 hover:scale-102 transition shadow-md break-words dark:bg-slate-850 dark:shadow-dark-xl bg-clip-border"
|
||||
class="p-4 mb-1 md:mb-3 md:mr-3 z-[1001] flex flex-col fixed bottom-0 right-0 w-full md:w-1/2 max-w-screen-sm min-h-20 bg-white rounded-lg dark:brightness-110 hover:scale-102 transition shadow-md break-words dark:bg-slate-850 dark:shadow-dark-xl bg-clip-border"
|
||||
>
|
||||
{% if category == 'error' %}
|
||||
<h5 class="text-lg mb-0 text-red-500">error</h5>
|
||||
<h5 class="text-lg mb-0 text-red-500">Error</h5>
|
||||
<p class="text-red-500 mb-0 text-sm">{{ message|safe }}</p>
|
||||
{% endif %} {% if category == 'success' %}
|
||||
<h5 class="text-lg mb-0 text-green-500">success</h5>
|
||||
{% else %}
|
||||
<h5 class="text-lg mb-0 text-green-500">Success</h5>
|
||||
<p class="text-green-500 mb-0 text-sm">{{ message|safe }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %} {% endif %} {% endwith %} {%endif %}
|
||||
{% endfor %}
|
||||
<!-- end flash message-->
|
||||
{% endif %} {% endwith %} {%endif %}
|
||||
<!-- end flash message-->
|
||||
<!--content -->
|
||||
<main class="grid grid-cols-2 align-middle items-center min-h-screen">
|
||||
|
|
|
@ -10,7 +10,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
|
|||
<div class="grid grid-cols-12 gap-x-4 gap-y-2">
|
||||
<!-- select instance -->
|
||||
<div
|
||||
class="flex flex-col relative col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3"
|
||||
class="flex flex-col relative col-span-12 sm:col-span-6 2xl:col-span-4 3xl:col-span-3"
|
||||
>
|
||||
<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"
|
||||
|
@ -44,7 +44,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
|
|||
<!-- dropdown-->
|
||||
<div
|
||||
{{current_endpoint}}-setting-select-dropdown="instances"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-12"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-16"
|
||||
>
|
||||
{% for instance in instances %}
|
||||
<button
|
||||
|
@ -63,7 +63,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
|
|||
<!-- end select instance -->
|
||||
<!-- from date input -->
|
||||
<div
|
||||
class="flex flex-col relative col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3"
|
||||
class="flex flex-col relative col-span-12 sm:col-span-6 2xl:col-span-4 3xl:col-span-3"
|
||||
>
|
||||
<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"
|
||||
|
@ -74,7 +74,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
|
|||
type="text"
|
||||
id="from-date"
|
||||
name="from-date"
|
||||
class="disabled:bg-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 dark:disabled:text-gray-300 disabled:text-gray-700 col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3 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"
|
||||
class="disabled:bg-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 dark:disabled:text-gray-300 disabled:text-gray-700 col-span-12 sm:col-span-6 2xl:col-span-4 3xl:col-span-3 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="dd/mm/yyyy or yyyy/mm/dd"
|
||||
pattern="(.*?)"
|
||||
required
|
||||
|
@ -83,7 +83,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
|
|||
<!-- end from date input -->
|
||||
<!-- to date input -->
|
||||
<div
|
||||
class="flex flex-col relative col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3"
|
||||
class="flex flex-col relative col-span-12 sm:col-span-6 2xl:col-span-4 3xl:col-span-3"
|
||||
>
|
||||
<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"
|
||||
|
@ -94,46 +94,17 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
|
|||
type="text"
|
||||
id="to-date"
|
||||
name="to-date"
|
||||
class="disabled:bg-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 dark:disabled:text-gray-300 disabled:text-gray-700 col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3 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"
|
||||
class="disabled:bg-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 dark:disabled:text-gray-300 disabled:text-gray-700 col-span-12 sm:col-span-6 2xl:col-span-4 3xl:col-span-3 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="dd/mm/yyyy or yyyy/mm/dd"
|
||||
pattern="(.*?)"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<!-- end to date input -->
|
||||
<!-- refresh input -->
|
||||
<div
|
||||
class="flex flex-col relative col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3"
|
||||
>
|
||||
<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"
|
||||
>
|
||||
Update auto
|
||||
</h5>
|
||||
<div checkbox-handler="live-update" class="relative mb-7 md:mb-0">
|
||||
<input
|
||||
id="live-update"
|
||||
class="relative cursor-pointer dark:border-slate-600 dark:bg-slate-700 z-10 checked:z-0 w-5 h-5 ease text-base rounded-1.4 checked:bg-primary checked:border-primary dark:checked:bg-primary dark:checked:border-primary duration-250 float-left mt-1 appearance-none border border-gray-300 bg-white bg-contain bg-center bg-no-repeat align-top transition-all disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 disabled:text-gray-700 dark:disabled:text-gray-300"
|
||||
type="checkbox"
|
||||
pattern=""
|
||||
value="no"
|
||||
/>
|
||||
<svg
|
||||
checkbox-handler="live-update"
|
||||
class="cursor-pointer absolute fill-white dark:fill-gray-300 left-0 top-0 translate-x-1 translate-y-2 h-3 w-3"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
<path
|
||||
d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end refresh input -->
|
||||
|
||||
<!-- refresh delay input -->
|
||||
<div
|
||||
class="flex flex-col relative col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3"
|
||||
class="flex flex-col relative col-span-12 sm:col-span-6 2xl:col-span-4 3xl:col-span-3"
|
||||
>
|
||||
<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"
|
||||
|
@ -144,13 +115,14 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
|
|||
type="number"
|
||||
id="update-delay"
|
||||
name="update-delay"
|
||||
class="disabled:bg-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 dark:disabled:text-gray-300 disabled:text-gray-700 col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3 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"
|
||||
class="disabled:bg-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 dark:disabled:text-gray-300 disabled:text-gray-700 col-span-12 sm:col-span-6 2xl:col-span-4 3xl:col-span-3 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="2"
|
||||
pattern="(.*?)"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<!-- end refresh delay input -->
|
||||
|
||||
<div class="col-span-12 w-full justify-center flex mt-2">
|
||||
<button
|
||||
type="button"
|
||||
|
@ -223,7 +195,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
|
|||
<!-- dropdown-->
|
||||
<div
|
||||
{{current_endpoint}}-setting-select-dropdown="types"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-12"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-16"
|
||||
>
|
||||
<button
|
||||
{{current_endpoint}}-setting-select-dropdown-btn="types"
|
||||
|
|
66
src/ui/templates/plugins-modal.html
Normal file
66
src/ui/templates/plugins-modal.html
Normal file
|
@ -0,0 +1,66 @@
|
|||
<!-- modal -->
|
||||
<div
|
||||
plugins-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
|
||||
plugins-modal-card
|
||||
class="overflow-y-auto mx-3 ml-2 mr-6 sm:mx-6 lg:mx-8 my-3 px-4 pt-4 pb-8 w-full 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">
|
||||
<p
|
||||
plugins-modal-title
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 dark:text-gray-300 mb-2 font-sans font-semibold leading-normal uppercase text-md"
|
||||
>
|
||||
DELETE PLUGINS
|
||||
</p>
|
||||
<button class="-translate-y-1" type="button" plugins-modal-close>
|
||||
<svg
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 h-6 w-6 sm:h-7 sm:w-7 fill-slate-800 dark:fill-gray-300"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 320 512"
|
||||
>
|
||||
<path
|
||||
d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<!-- delete form-->
|
||||
<form
|
||||
plugins-modal-form-delete
|
||||
class="w-full h-full flex flex-col justify-between"
|
||||
id="form-delete-server_name"
|
||||
method="POST"
|
||||
>
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
||||
<input type="hidden" value="server_name" name="SERVER_NAME" />
|
||||
<input type="hidden" value="delete" name="operation" />
|
||||
<div>
|
||||
<p
|
||||
plugins-modal-text
|
||||
class="mx-2 mb-2 mt-8 font-semibold font-sans leading-normal uppercase text-sm"
|
||||
></p>
|
||||
</div>
|
||||
<!-- action button -->
|
||||
<div class="w-full justify-center flex mt-10">
|
||||
<button
|
||||
plugins-modal-close
|
||||
type="button"
|
||||
class="dark:brightness-90 mr-3 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 text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="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 text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
<!-- end action button-->
|
||||
</form>
|
||||
<!-- end delete form-->
|
||||
</div>
|
||||
</div>
|
||||
<!-- end modal -->
|
|
@ -59,34 +59,41 @@ plugins = config["CONFIG"].get_plugins() %}
|
|||
|
||||
<!-- upload layout -->
|
||||
<div
|
||||
{{current_endpoint}}-upload
|
||||
class="p-4 col-span-12 md:col-span-7 2xl:col-span-4 grid grid-cols-12 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="col-span-12 mb-4 font-bold dark:text-white">UPLOAD PLUGIN</h5>
|
||||
<h5 class="col-span-12 mb-4 font-bold dark:text-white">UPLOAD / RELOAD</h5>
|
||||
|
||||
<div class="p-0 col-span-12 grid">
|
||||
<form id="dropzone" class="col-span-12 dropzone max-h-16 overflow-y-auto">
|
||||
<!-- Now setup your input fields -->
|
||||
<div class="p-0 col-span-12 grid grid-cols-12">
|
||||
<!-- dropzone -->
|
||||
<form
|
||||
id="dropzone-form"
|
||||
action="#"
|
||||
class="cursor-pointer col-span-12 border-2 rounded-lg p-2 border-dashed border-primary drop-zone"
|
||||
>
|
||||
<input
|
||||
name="upload-csrf"
|
||||
class="hidden"
|
||||
type="hidden"
|
||||
id="csrf_token"
|
||||
name="csrf_token"
|
||||
value="{{ csrf_token() }}"
|
||||
/>
|
||||
<button name="upload-submit" class="hidden" type="submit">
|
||||
Submit data and files!
|
||||
</button>
|
||||
<input
|
||||
class="file-input drop-zone__input"
|
||||
type="file"
|
||||
name="file"
|
||||
multiple="multiple"
|
||||
hidden
|
||||
/>
|
||||
<i class="fa-solid fa-cloud-upload-alt"></i>
|
||||
<p class="text-sm text-center my-3">click or drag and drop</p>
|
||||
</form>
|
||||
<div
|
||||
class="col-span-12 flex flex-col sm:flex-row justify-center items-center mt-3"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="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-primary hover:bg-primary/80 focus:bg-primary/80 leading-normal text-sm ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md"
|
||||
>
|
||||
Upload
|
||||
</button>
|
||||
<section class="col-span-12 progress-area"></section>
|
||||
<section class="col-span-12 uploaded-area"></section>
|
||||
|
||||
<!-- end dropzone -->
|
||||
<div class="col-span-12 flex flex-col justify-center items-center">
|
||||
<p
|
||||
class="mx-4 my-3 sm:my-0 font-sans font-semibold leading-normal uppercase text-sm"
|
||||
class="mx-4 my-3 font-sans font-semibold leading-normal uppercase text-sm"
|
||||
>
|
||||
or
|
||||
</p>
|
||||
|
@ -167,7 +174,7 @@ plugins = config["CONFIG"].get_plugins() %}
|
|||
<!-- dropdown-->
|
||||
<div
|
||||
{{current_endpoint}}-setting-select-dropdown="types"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-12"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-16"
|
||||
>
|
||||
<button
|
||||
{{current_endpoint}}-setting-select-dropdown-btn="types"
|
||||
|
@ -208,35 +215,55 @@ plugins = config["CONFIG"].get_plugins() %}
|
|||
|
||||
<div {{current_endpoint}}-list class="grid grid-cols-12 gap-3">
|
||||
{% for plugin in plugins %} {% if plugin['page'] %}
|
||||
<a
|
||||
<div
|
||||
{{current_endpoint}}-external="{% if plugin['external'] %} external {%else%} internal {%endif%}"
|
||||
href="/plugins?{{plugin['id']}}"
|
||||
class="py-3 cursor-pointer min-h-12 relative col-span-12 sm:col-span-6 md:col-span-4 lg:col-span-3 3xl:col-span-2 p-1 flex justify-between items-center transition rounded bg-gray-100 hover:bg-gray-300 dark:bg-slate-700 dark:hover:bg-slate-800"
|
||||
class="py-3 min-h-12 relative col-span-12 sm:col-span-6 2xl:col-span-4 3xl:col-span-3 p-1 flex justify-between items-center transition rounded bg-gray-100 hover:bg-gray-300 dark:bg-slate-700 dark:hover:bg-slate-800"
|
||||
>
|
||||
<p
|
||||
{{current_endpoint}}-content
|
||||
class="ml-3 mb-0 transition duration-300 ease-in-out dark:opacity-90 text-center text-sm md:text-base text-slate-700 dark:text-gray-300"
|
||||
class="ml-3 mr-2 mb-0 transition duration-300 ease-in-out dark:opacity-90 text-left text-sm md:text-base text-slate-700 dark:text-gray-300"
|
||||
>
|
||||
{{plugin['name']}}
|
||||
</p>
|
||||
<svg
|
||||
class="h-6 w-6 fill-sky-500 dark dark:brightness-90"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 448 512"
|
||||
>
|
||||
<path
|
||||
d="M288 32c-17.7 0-32 14.3-32 32s14.3 32 32 32h50.7L169.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L384 141.3V192c0 17.7 14.3 32 32 32s32-14.3 32-32V64c0-17.7-14.3-32-32-32H288zM80 64C35.8 64 0 99.8 0 144V400c0 44.2 35.8 80 80 80H336c44.2 0 80-35.8 80-80V320c0-17.7-14.3-32-32-32s-32 14.3-32 32v80c0 8.8-7.2 16-16 16H80c-8.8 0-16-7.2-16-16V144c0-8.8 7.2-16 16-16h80c17.7 0 32-14.3 32-32s-14.3-32-32-32H80z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
<div class="flex items-center">
|
||||
<a class="hover:-translate-y-px" href="/plugins?{{plugin['id']}}">
|
||||
<svg
|
||||
class="h-6 w-6 fill-sky-500 dark dark:brightness-90"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 448 512"
|
||||
>
|
||||
<path
|
||||
d="M288 32c-17.7 0-32 14.3-32 32s14.3 32 32 32h50.7L169.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L384 141.3V192c0 17.7 14.3 32 32 32s32-14.3 32-32V64c0-17.7-14.3-32-32-32H288zM80 64C35.8 64 0 99.8 0 144V400c0 44.2 35.8 80 80 80H336c44.2 0 80-35.8 80-80V320c0-17.7-14.3-32-32-32s-32 14.3-32 32v80c0 8.8-7.2 16-16 16H80c-8.8 0-16-7.2-16-16V144c0-8.8 7.2-16 16-16h80c17.7 0 32-14.3 32-32s-14.3-32-32-32H80z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
<button
|
||||
{{current_endpoint}}-action="delete"
|
||||
name="{{plugin['id']}}"
|
||||
type="button"
|
||||
class="z-20 mx-2 inline-block font-bold text-left text-white uppercase align-middle transition-all cursor-pointer text-xs ease-in tracking-tight-rem hover:-translate-y-px"
|
||||
>
|
||||
<svg
|
||||
class="h-5 w-5 fill-red-500 dark:brightness-90"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 448 512"
|
||||
>
|
||||
<path
|
||||
d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
|
||||
<div
|
||||
{{current_endpoint}}-external="{% if plugin['external'] %} external {%else%} internal {%endif%}"
|
||||
class="py-3 cursor-pointer min-h-12 relative col-span-12 sm:col-span-6 md:col-span-4 lg:col-span-3 3xl:col-span-2 p-1 flex justify-start items-center transition rounded bg-gray-100 hover:bg-gray-300 dark:bg-slate-700 dark:hover:bg-slate-800"
|
||||
class="py-3 min-h-12 relative col-span-12 sm:col-span-6 2xl:col-span-4 3xl:col-span-3 p-1 flex justify-between items-center transition rounded bg-gray-100 hover:bg-gray-300 dark:bg-slate-700 dark:hover:bg-slate-800"
|
||||
>
|
||||
<p
|
||||
{{current_endpoint}}-content
|
||||
class="ml-3 mb-0 transition duration-300 ease-in-out dark:opacity-90 text-center text-sm md:text-base text-slate-700 dark:text-gray-300"
|
||||
class="ml-3 mb-0 transition duration-300 ease-in-out dark:opacity-90 text-left text-sm md:text-base text-slate-700 dark:text-gray-300"
|
||||
>
|
||||
{{plugin['name']}}
|
||||
</p>
|
||||
|
|
|
@ -37,10 +37,10 @@
|
|||
|
||||
<!-- detail list -->
|
||||
<div
|
||||
class="w-full grid grid-cols-2 justify-items-center sm:justify-items-start gap-2 mt-4 mb-6 ml-3 sm:ml-1"
|
||||
class="w-full grid grid-cols-12 justify-items-center sm:justify-items-start gap-2 mt-4 mb-6 ml-3 sm:ml-1"
|
||||
>
|
||||
<!-- detail -->
|
||||
<div class="flex items-center col-span-2 sm:col-span-1">
|
||||
<div class="flex items-center col-span-12 sm:col-span-6 2xl:col-span-4">
|
||||
<p
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 "
|
||||
>
|
||||
|
@ -75,7 +75,7 @@
|
|||
</div>
|
||||
<!-- end detail -->
|
||||
<!-- detail -->
|
||||
<div class="flex items-center col-span-2 sm:col-span-1">
|
||||
<div class="flex items-center col-span-12 sm:col-span-6 2xl:col-span-4">
|
||||
<p
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 "
|
||||
>
|
||||
|
@ -109,7 +109,7 @@
|
|||
</div>
|
||||
<!-- end detail -->
|
||||
<!-- detail -->
|
||||
<div class="flex items-center col-span-2 sm:col-span-1">
|
||||
<div class="flex items-center col-span-12 sm:col-span-6 2xl:col-span-4">
|
||||
<p
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 "
|
||||
>
|
||||
|
@ -143,7 +143,7 @@
|
|||
</div>
|
||||
<!-- end detail -->
|
||||
<!-- detail -->
|
||||
<div class="flex items-center col-span-2 sm:col-span-1">
|
||||
<div class="flex items-center col-span-12 sm:col-span-6 2xl:col-span-4">
|
||||
<p
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 "
|
||||
>
|
||||
|
@ -178,7 +178,7 @@
|
|||
</div>
|
||||
<!-- end detail -->
|
||||
<!-- detail -->
|
||||
<div class="flex items-center col-span-2 sm:col-span-1">
|
||||
<div class="flex items-center col-span-12 sm:col-span-6 2xl:col-span-4">
|
||||
<p
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 "
|
||||
>
|
||||
|
@ -212,7 +212,7 @@
|
|||
</div>
|
||||
<!-- end detail -->
|
||||
<!-- detail -->
|
||||
<div class="flex items-center col-span-2 sm:col-span-1">
|
||||
<div class="flex items-center col-span-12 sm:col-span-6 2xl:col-span-4">
|
||||
<p
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 "
|
||||
>
|
||||
|
@ -246,7 +246,7 @@
|
|||
</div>
|
||||
<!-- end detail -->
|
||||
<!-- detail -->
|
||||
<div class="flex items-center col-span-2 sm:col-span-1">
|
||||
<div class="flex items-center col-span-12 sm:col-span-6 2xl:col-span-4">
|
||||
<p
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 "
|
||||
>
|
||||
|
@ -280,7 +280,7 @@
|
|||
</div>
|
||||
<!-- end detail -->
|
||||
<!-- detail -->
|
||||
<div class="flex items-center col-span-2 sm:col-span-1">
|
||||
<div class="flex items-center col-span-12 sm:col-span-6 2xl:col-span-4">
|
||||
<p
|
||||
class="font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500"
|
||||
>
|
||||
|
|
|
@ -4,155 +4,404 @@
|
|||
config["CONFIG"].get_config() %}
|
||||
{% set plugins = config["CONFIG"].get_plugins() %}
|
||||
<!-- plugin item -->
|
||||
{% for plugin in plugins %}
|
||||
<div {{current_endpoint}}-item="{{plugin['id']}}" id="{{plugin['id']}}" class="hidden w-full">
|
||||
{% for plugin in plugins %}
|
||||
|
||||
<div
|
||||
{{current_endpoint}}-item="{{plugin['id']}}"
|
||||
id="{{plugin['id']}}"
|
||||
class="hidden w-full"
|
||||
>
|
||||
<!-- title and desc -->
|
||||
<div class="col-span-12">
|
||||
<h5 class="transition duration-300 ease-in-out dark:opacity-90 ml-2 font-bold text-md uppercase dark:text-white mb-0">{{plugin['name']}} <span>{{plugin['version']}}</span></h5>
|
||||
<div class="transition duration-300 ease-in-out dark:opacity-90 ml-2 text-sm mb-2 dark:text-gray-400">
|
||||
{{plugin['description']}}
|
||||
</div>
|
||||
<h5
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 ml-2 font-bold text-md uppercase dark:text-white mb-0"
|
||||
>
|
||||
{{plugin['name']}} <span>{{plugin['version']}}</span>
|
||||
</h5>
|
||||
<div
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 ml-2 text-sm mb-2 dark:text-gray-400"
|
||||
>
|
||||
{{plugin['description']}}
|
||||
</div>
|
||||
</div>
|
||||
<!-- end title and desc -->
|
||||
<!-- plugin settings -->
|
||||
<div
|
||||
class="w-full grid grid-cols-12"
|
||||
>
|
||||
{% for setting, value in plugin["settings"].items() %}{% if current_endpoint == "global-config" and
|
||||
value['context'] == "global" or current_endpoint == "services" and value['context'] == "multisite" %}
|
||||
<div
|
||||
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"
|
||||
id="form-edit-{{current_endpoint}}-{{ value["id"] }}"
|
||||
>
|
||||
<!-- title and info -->
|
||||
<div class="flex items-center my-1 relative">
|
||||
<h5 class="transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300">{{value["label"]}}</h5>
|
||||
<svg
|
||||
{{current_endpoint}}-info-btn="{{ value["label"] }}"
|
||||
class="cursor-pointer fill-blue-500 h-5 w-5 ml-2 hover:brightness-75"
|
||||
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 -->
|
||||
<div class="hidden transition z-50 rounded-md p-3 left-0 -translate-y-7 bottom-0 absolute bg-blue-500"
|
||||
{{current_endpoint}}-info-popover="{{ value["label"] }}"
|
||||
>
|
||||
<p class="transition duration-300 ease-in-out dark:opacity-90 font-bold text-sm text-white m-0" >{{value['help']}}
|
||||
</p>
|
||||
<!-- plugin settings not multiple -->
|
||||
<div {{current_endpoint}}-settings class="w-full grid grid-cols-12">
|
||||
{% for setting, value in plugin["settings"].items() %}{% if current_endpoint
|
||||
== "global-config" and value['context'] == "global" and not value['multiple'] or current_endpoint ==
|
||||
"services" and value['context'] == "multisite" and not value['multiple'] %}
|
||||
<div
|
||||
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"
|
||||
id="form-edit-{{current_endpoint}}-{{ value["id"] }}">
|
||||
<!-- title and info -->
|
||||
<div class="flex items-center my-1 relative">
|
||||
<h5
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300"
|
||||
>
|
||||
{{value["label"]}}
|
||||
</h5>
|
||||
<svg
|
||||
{{current_endpoint}}-info-btn="{{ value["label"] }}"
|
||||
class="cursor-pointer fill-blue-500 h-5 w-5 ml-2 hover:brightness-75"
|
||||
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 -->
|
||||
<div class="hidden transition z-50 rounded-md p-3 left-0 -translate-y-7 bottom-0 absolute bg-blue-500"
|
||||
{{current_endpoint}}-info-popover="{{ value["label"] }}"
|
||||
>
|
||||
<p class="transition duration-300 ease-in-out dark:opacity-90 font-bold text-sm text-white m-0" >{{value['help']}}
|
||||
</p>
|
||||
</div>
|
||||
<!-- end popover -->
|
||||
</div>
|
||||
<!-- end popover -->
|
||||
<!-- end title and info -->
|
||||
|
||||
<!-- input -->
|
||||
{% if value["type"] != "select" and value["type"] != "check" %}
|
||||
<input
|
||||
default-value="{{global_config[setting]['value']}}" default-method="{{global_config[setting]['method']}}"
|
||||
{% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %} disabled {% endif %} id="{{setting}}" name="{{setting}}"
|
||||
class="duration-300 ease-in-out dark:opacity-90 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-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"
|
||||
value="{% if global_config[setting]['value'] %} {{global_config[setting]['value']}} {% else %} {{value['default']}} {% endif %}" type="{{value['type']}}" pattern="{{value['regex']|safe}}" />
|
||||
{% endif %}
|
||||
<!-- end input -->
|
||||
|
||||
<!-- select -->
|
||||
{% if value["type"] == "select" %}
|
||||
<!-- default hidden-->
|
||||
<select default-method="{{global_config[setting]['method']}}" default-value="{{value['default']}}"
|
||||
id="{{setting}}" name="{{setting}}" {{current_endpoint}}-setting-select-default="{{value['id']}}" type="form-select" id="{{setting}}" name="{{setting}}"
|
||||
class="hidden">
|
||||
{% for item in value['select'] %}
|
||||
<option value="{{item}}" {% if global_config[setting]['value'] and global_config[setting]['value'] == item or not global_config[setting]['value'] and value['default'] == item %} selected{% endif %}>{{item}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<!-- end default hidden-->
|
||||
|
||||
<!--custom-->
|
||||
<div class="relative">
|
||||
<button
|
||||
{% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %} disabled {% endif %} {{current_endpoint}}-setting-select="{{value['id']}}"
|
||||
default-value="{{global_config[setting]['value']}}"
|
||||
type="button"
|
||||
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 md:py-2 font-normal text-gray-700 transition-all placeholder:text-gray-500"
|
||||
>
|
||||
{% for item in value['select'] %} {% if global_config[setting]['value'] and
|
||||
global_config[setting]['value'] == item %}
|
||||
<span
|
||||
{{current_endpoint}}-setting-select-text="{{value['id']}}"
|
||||
value="{{global_config[setting]['value']}}"
|
||||
>{{global_config[setting]['value']}}</span
|
||||
>
|
||||
{% elif not global_config[setting]['value'] and value['default'] == item %}
|
||||
<span
|
||||
{{current_endpoint}}-setting-select-text="{{value['id']}}"
|
||||
value="{{value['default']}}"
|
||||
>{{value['default']}}</span
|
||||
>
|
||||
{% endif %} {% endfor %}
|
||||
<!-- chevron -->
|
||||
<svg
|
||||
{{current_endpoint}}-setting-select="{{value['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>
|
||||
<!-- end chevron -->
|
||||
</button>
|
||||
<!-- dropdown-->
|
||||
<div
|
||||
{{current_endpoint}}-setting-select-dropdown="{{value['id']}}"
|
||||
class="hidden z-100 absolute h-full flex-col w-full mt-2"
|
||||
>
|
||||
{% for item in value['select'] %} {% if global_config[setting]['value'] and
|
||||
global_config[setting]['value'] == item or not global_config[setting]['value']
|
||||
and value['default'] == item %}
|
||||
<button
|
||||
type="button"
|
||||
value="{{item}}"
|
||||
{{current_endpoint}}-setting-select-dropdown-btn="{{value['id']}}"
|
||||
type="button"
|
||||
class="{% if loop.index == 1 %} border-t rounded-t {% endif %} {% if loop.index == loop.length %}rounded-b {% endif %} border-b border-l border-r border-gray-300 hover:brightness-90 bg-primary text-white 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"
|
||||
>
|
||||
{{item}}
|
||||
</button>
|
||||
{% else %}
|
||||
<button
|
||||
type="button"
|
||||
value="{{item}}"
|
||||
{{current_endpoint}}-setting-select-dropdown-btn="{{value['id']}}"
|
||||
type="button"
|
||||
class="{% if loop.index == 1 %} border-t rounded-t {% endif %} {% if loop.index == loop.length %}rounded-b {% endif %} border-b border-l border-r border-gray-300 hover:bg-gray-100 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"
|
||||
>
|
||||
{{item}}
|
||||
</button>
|
||||
{% endif %} {% endfor %}
|
||||
</div>
|
||||
<!-- end dropdown-->
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- end custom-->
|
||||
{% endif %}
|
||||
|
||||
<!-- checkbox -->
|
||||
{% if value["type"] == "check" %}
|
||||
<div checkbox-handler="{{value['id']}}" class="relative mb-7 md:mb-0">
|
||||
<input id="{{setting}}" name="{{setting}}"
|
||||
default-method="{{global_config[setting]['method']}}"
|
||||
default-value="{{global_config[setting]['value']}}" {% if
|
||||
global_config[setting]['method'] != 'ui' or global_config[setting]['method']
|
||||
!= 'default' %} disabled {% endif %} {% if global_config[setting]['value'] and
|
||||
global_config[setting]['value'] == 'yes' or not
|
||||
global_config[setting]['value'] and value['default'] == 'yes' %} checked {%
|
||||
endif %} id="checkbox-{{value['id']}}" class="relative {% if
|
||||
global_config[setting]['method'] != 'ui' and global_config[setting]['method']
|
||||
!= 'default' %} pointer-events-none {% else %} cursor-pointer {% endif %}
|
||||
dark:border-slate-600 dark:bg-slate-700 z-10 checked:z-0 w-5 h-5 ease
|
||||
text-base rounded-1.4 checked:bg-primary checked:border-primary
|
||||
dark:checked:bg-primary dark:checked:border-primary duration-250 float-left
|
||||
mt-1 appearance-none border border-gray-300 bg-white bg-contain bg-center
|
||||
bg-no-repeat align-top transition-all disabled:bg-gray-400
|
||||
disabled:border-gray-400 dark:disabled:bg-gray-800
|
||||
dark:disabled:border-gray-800 disabled:text-gray-700
|
||||
dark:disabled:text-gray-300" type="checkbox" pattern="{{value['regex']|safe}}"
|
||||
value="{% if global_config[setting]['value'] %}
|
||||
{{global_config[setting]['value']}} {% else %} {{value['default']}} {% endif
|
||||
%}" />
|
||||
<svg
|
||||
checkbox-handler="{{value['id']}}"
|
||||
class="{% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %} pointer-events-none {% else %} cursor-pointer {% endif %} absolute fill-white dark:fill-gray-300 left-0 top-0 translate-x-1 translate-y-2 h-3 w-3"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
<path
|
||||
d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- end checkbox -->
|
||||
|
||||
<!-- invalid feedback -->
|
||||
<div class="hidden text-sm dark:text-red-500">
|
||||
{{value['label']}} is invalid and must match this pattern:
|
||||
{{value['regex']|safe}}
|
||||
</div>
|
||||
<!--end invalid feedback-->
|
||||
</div>
|
||||
<!-- end title and info -->
|
||||
|
||||
<!-- input -->
|
||||
{% if value["type"] != "select" and value["type"] != "check" %}
|
||||
<input
|
||||
default-value="{{global_config[setting]['value']}}" default-method="{{global_config[setting]['method']}}"
|
||||
{% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %} disabled {% endif %} id="{{setting}}" name="{{setting}}"
|
||||
class="duration-300 ease-in-out dark:opacity-90 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-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"
|
||||
value="{% if global_config[setting]['value'] %} {{global_config[setting]['value']}} {% else %} {{value['default']}} {% endif %}" type="{{value['type']}}" pattern="{{value['regex']|safe}}" />
|
||||
{% endif %}
|
||||
<!-- end input -->
|
||||
|
||||
<!-- select -->
|
||||
{% if value["type"] == "select" %}
|
||||
<!-- default hidden-->
|
||||
<select default-method="{{global_config[setting]['method']}}" default-value="{{value['default']}}"
|
||||
id="{{setting}}" name="{{setting}}" {{current_endpoint}}-setting-select-default="{{value['id']}}" type="form-select" id="{{setting}}" name="{{setting}}"
|
||||
class="hidden">
|
||||
{% for item in value['select'] %}
|
||||
<option value="{{item}}" {% if global_config[setting]['value'] and global_config[setting]['value'] == item or not global_config[setting]['value'] and value['default'] == item %} selected{% endif %}>{{item}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<!-- end default hidden-->
|
||||
|
||||
<!--custom-->
|
||||
<div class="relative">
|
||||
<button default-value="{{global_config[setting]['value']}}"
|
||||
{% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %} disabled {% endif %} {{current_endpoint}}-setting-select="{{value['id']}}"
|
||||
type="button"
|
||||
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 md:py-2 font-normal text-gray-700 transition-all placeholder:text-gray-500"
|
||||
>
|
||||
{% for item in value['select'] %}
|
||||
{% if global_config[setting]['value'] and global_config[setting]['value'] == item %}
|
||||
<span {{current_endpoint}}-setting-select-text="{{value['id']}}"
|
||||
value="{{global_config[setting]['value']}}">{{global_config[setting]['value']}}</span>
|
||||
{% elif not global_config[setting]['value'] and value['default'] == item %}
|
||||
<span {{current_endpoint}}-setting-select-text="{{value['id']}}"
|
||||
value="{{value['default']}}">{{value['default']}}</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<!-- chevron -->
|
||||
<svg
|
||||
{{current_endpoint}}-setting-select="{{value['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>
|
||||
<!-- end chevron -->
|
||||
|
||||
</button>
|
||||
<!-- dropdown-->
|
||||
<div
|
||||
{{current_endpoint}}-setting-select-dropdown="{{value['id']}}"
|
||||
class="hidden z-100 absolute h-full flex-col w-full mt-2 "
|
||||
>
|
||||
{% for item in value['select'] %}
|
||||
{% if global_config[setting]['value'] and global_config[setting]['value'] == item or not global_config[setting]['value'] and value['default'] == item %}
|
||||
<button type="button" value="{{item}}" {{current_endpoint}}-setting-select-dropdown-btn="{{value['id']}}" type="button" class="{% if loop.index == 1 %} border-t rounded-t {% endif %} {% if loop.index == loop.length %}rounded-b {% endif %} border-b border-l border-r border-gray-300 hover:brightness-90 bg-primary text-white 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"
|
||||
>{{item}}</button>
|
||||
{% else %}
|
||||
<button type="button" value="{{item}}" {{current_endpoint}}-setting-select-dropdown-btn="{{value['id']}}" type="button" class="{% if loop.index == 1 %} border-t rounded-t {% endif %} {% if loop.index == loop.length %}rounded-b {% endif %} border-b border-l border-r border-gray-300 hover:bg-gray-100 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"
|
||||
>{{item}}</button>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
<!-- end dropdown-->
|
||||
</div>
|
||||
<!-- end custom-->
|
||||
{% endif %}
|
||||
|
||||
<!-- checkbox -->
|
||||
{% if value["type"] == "check" %}
|
||||
<div checkbox-handler="{{value['id']}}" class="relative mb-7 md:mb-0">
|
||||
<input id="{{setting}}" name="{{setting}}"
|
||||
default-method="{{global_config[setting]['method']}}" default-value="{{global_config[setting]['value']}}"
|
||||
{% if global_config[setting]['method'] != 'ui' or global_config[setting]['method'] != 'default' %} disabled {% endif %}
|
||||
{% if global_config[setting]['value'] and global_config[setting]['value'] == 'yes' or not global_config[setting]['value'] and value['default'] == 'yes' %} checked {% endif %} id="checkbox-{{value['id']}}"
|
||||
class="relative {% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %} pointer-events-none {% else %} cursor-pointer {% endif %} dark:border-slate-600 dark:bg-slate-700 z-10 checked:z-0 w-5 h-5 ease text-base rounded-1.4 checked:bg-primary checked:border-primary dark:checked:bg-primary dark:checked:border-primary duration-250 float-left mt-1 appearance-none border border-gray-300 bg-white bg-contain bg-center bg-no-repeat align-top transition-all disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 disabled:text-gray-700 dark:disabled:text-gray-300"
|
||||
type="checkbox"
|
||||
pattern="{{value['regex']|safe}}"
|
||||
value="{% if global_config[setting]['value'] %} {{global_config[setting]['value']}} {% else %} {{value['default']}} {% endif %}"
|
||||
/>
|
||||
<svg checkbox-handler="{{value['id']}}" class="{% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %} pointer-events-none {% else %} cursor-pointer {% endif %} absolute fill-white dark:fill-gray-300 left-0 top-0 translate-x-1 translate-y-2 h-3 w-3 " xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<path d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- end checkbox -->
|
||||
|
||||
<!-- invalid feedback -->
|
||||
<div class="hidden text-sm dark:text-red-500">
|
||||
{{value['label']}} is invalid and must match this pattern: {{value['regex']|safe}}
|
||||
{% endif %} {% endfor %}
|
||||
<!-- end plugin settings -->
|
||||
</div>
|
||||
<!--end invalid feedback -->
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<!-- end plugin settings -->
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<!-- end plugin item -->
|
||||
|
||||
|
||||
<!-- end plugin settings not multiple -->
|
||||
|
||||
<!-- plugin multiple -->
|
||||
{% if not plugin['multiple'] %}
|
||||
<div 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="transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300"
|
||||
>
|
||||
{{plugin['name']}}
|
||||
</h5>
|
||||
<button {{current_endpoint}}-multiple-add="{{plugin['name']}}" 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>
|
||||
</div>
|
||||
<div {{current_endpoint}}-settings-multiple="{{plugin['name']}}_SCHEMA" class="hidden w-full mb-8 grid-cols-12 border dark:border-gray-700">
|
||||
|
||||
{% for setting, value in plugin["settings"].items() %}
|
||||
{% if current_endpoint
|
||||
== "global-config" and value['context'] == "global" and value['multiple'] or current_endpoint ==
|
||||
"services" and value['context'] == "multisite" and value['multiple'] %}
|
||||
<div 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"
|
||||
id="form-edit-{{current_endpoint}}-{{ value["id"] }}">
|
||||
<!-- title and info -->
|
||||
<div class="flex items-center my-1 relative">
|
||||
<h5
|
||||
class="transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300"
|
||||
>
|
||||
{{value["label"]}}
|
||||
</h5>
|
||||
<svg
|
||||
{{current_endpoint}}-info-btn="{{ value["label"] }}"
|
||||
class="cursor-pointer fill-blue-500 h-5 w-5 ml-2 hover:brightness-75"
|
||||
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 -->
|
||||
<div class="hidden transition z-50 rounded-md p-3 left-0 -translate-y-7 bottom-0 absolute bg-blue-500"
|
||||
{{current_endpoint}}-info-popover="{{ value["label"] }}"
|
||||
>
|
||||
<p class="transition duration-300 ease-in-out dark:opacity-90 font-bold text-sm text-white m-0" >{{value['help']}}
|
||||
</p>
|
||||
</div>
|
||||
<!-- end popover -->
|
||||
</div>
|
||||
<!-- end title and info -->
|
||||
|
||||
<!-- input -->
|
||||
{% if value["type"] != "select" and value["type"] != "check" %}
|
||||
<input
|
||||
default-value="{{global_config[setting]['value']}}" default-method="{{global_config[setting]['method']}}"
|
||||
{% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %} disabled {% endif %} id="{{setting}}" name="{{setting}}"
|
||||
class="duration-300 ease-in-out dark:opacity-90 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-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"
|
||||
value="{% if global_config[setting]['value'] %} {{global_config[setting]['value']}} {% else %} {{value['default']}} {% endif %}" type="{{value['type']}}" pattern="{{value['regex']|safe}}" />
|
||||
{% endif %}
|
||||
<!-- end input -->
|
||||
|
||||
<!-- select -->
|
||||
{% if value["type"] == "select" %}
|
||||
<!-- default hidden-->
|
||||
<select default-method="{{global_config[setting]['method']}}" default-value="{{value['default']}}"
|
||||
id="{{setting}}" name="{{setting}}" {{current_endpoint}}-setting-select-default="{{value['id']}}" type="form-select" id="{{setting}}" name="{{setting}}"
|
||||
class="hidden">
|
||||
{% for item in value['select'] %}
|
||||
<option value="{{item}}" {% if global_config[setting]['value'] and global_config[setting]['value'] == item or not global_config[setting]['value'] and value['default'] == item %} selected{% endif %}>{{item}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<!-- end default hidden-->
|
||||
|
||||
<!--custom-->
|
||||
<div class="relative">
|
||||
<button
|
||||
{% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %} disabled {% endif %} {{current_endpoint}}-setting-select="{{value['id']}}"
|
||||
default-value="{{global_config[setting]['value']}}"
|
||||
type="button"
|
||||
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 md:py-2 font-normal text-gray-700 transition-all placeholder:text-gray-500"
|
||||
>
|
||||
{% for item in value['select'] %} {% if global_config[setting]['value'] and
|
||||
global_config[setting]['value'] == item %}
|
||||
<span
|
||||
{{current_endpoint}}-setting-select-text="{{value['id']}}"
|
||||
value="{{global_config[setting]['value']}}"
|
||||
>{{global_config[setting]['value']}}</span
|
||||
>
|
||||
{% elif not global_config[setting]['value'] and value['default'] == item %}
|
||||
<span
|
||||
{{current_endpoint}}-setting-select-text="{{value['id']}}"
|
||||
value="{{value['default']}}"
|
||||
>{{value['default']}}</span
|
||||
>
|
||||
{% endif %} {% endfor %}
|
||||
<!-- chevron -->
|
||||
<svg
|
||||
{{current_endpoint}}-setting-select="{{value['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>
|
||||
<!-- end chevron -->
|
||||
</button>
|
||||
<!-- dropdown-->
|
||||
<div
|
||||
{{current_endpoint}}-setting-select-dropdown="{{value['id']}}"
|
||||
class="hidden z-100 absolute h-full flex-col w-full mt-2"
|
||||
>
|
||||
{% for item in value['select'] %} {% if global_config[setting]['value'] and
|
||||
global_config[setting]['value'] == item or not global_config[setting]['value']
|
||||
and value['default'] == item %}
|
||||
<button
|
||||
type="button"
|
||||
value="{{item}}"
|
||||
{{current_endpoint}}-setting-select-dropdown-btn="{{value['id']}}"
|
||||
type="button"
|
||||
class="{% if loop.index == 1 %} border-t rounded-t {% endif %} {% if loop.index == loop.length %}rounded-b {% endif %} border-b border-l border-r border-gray-300 hover:brightness-90 bg-primary text-white 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"
|
||||
>
|
||||
{{item}}
|
||||
</button>
|
||||
{% else %}
|
||||
<button
|
||||
type="button"
|
||||
value="{{item}}"
|
||||
{{current_endpoint}}-setting-select-dropdown-btn="{{value['id']}}"
|
||||
type="button"
|
||||
class="{% if loop.index == 1 %} border-t rounded-t {% endif %} {% if loop.index == loop.length %}rounded-b {% endif %} border-b border-l border-r border-gray-300 hover:bg-gray-100 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"
|
||||
>
|
||||
{{item}}
|
||||
</button>
|
||||
{% endif %} {% endfor %}
|
||||
</div>
|
||||
<!-- end dropdown-->
|
||||
</div>
|
||||
<!-- end custom-->
|
||||
{% endif %}
|
||||
|
||||
<!-- checkbox -->
|
||||
{% if value["type"] == "check" %}
|
||||
<div checkbox-handler="{{value['id']}}" class="relative mb-7 md:mb-0">
|
||||
<input id="{{setting}}" name="{{setting}}"
|
||||
default-method="{{global_config[setting]['method']}}"
|
||||
default-value="{{global_config[setting]['value']}}" {% if
|
||||
global_config[setting]['method'] != 'ui' or global_config[setting]['method']
|
||||
!= 'default' %} disabled {% endif %} {% if global_config[setting]['value'] and
|
||||
global_config[setting]['value'] == 'yes' or not
|
||||
global_config[setting]['value'] and value['default'] == 'yes' %} checked {%
|
||||
endif %} id="checkbox-{{value['id']}}" class="relative {% if
|
||||
global_config[setting]['method'] != 'ui' and global_config[setting]['method']
|
||||
!= 'default' %} pointer-events-none {% else %} cursor-pointer {% endif %}
|
||||
dark:border-slate-600 dark:bg-slate-700 z-10 checked:z-0 w-5 h-5 ease
|
||||
text-base rounded-1.4 checked:bg-primary checked:border-primary
|
||||
dark:checked:bg-primary dark:checked:border-primary duration-250 float-left
|
||||
mt-1 appearance-none border border-gray-300 bg-white bg-contain bg-center
|
||||
bg-no-repeat align-top transition-all disabled:bg-gray-400
|
||||
disabled:border-gray-400 dark:disabled:bg-gray-800
|
||||
dark:disabled:border-gray-800 disabled:text-gray-700
|
||||
dark:disabled:text-gray-300" type="checkbox" pattern="{{value['regex']|safe}}"
|
||||
value="{% if global_config[setting]['value'] %}
|
||||
{{global_config[setting]['value']}} {% else %} {{value['default']}} {% endif
|
||||
%}" />
|
||||
<svg
|
||||
checkbox-handler="{{value['id']}}"
|
||||
class="{% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %} pointer-events-none {% else %} cursor-pointer {% endif %} absolute fill-white dark:fill-gray-300 left-0 top-0 translate-x-1 translate-y-2 h-3 w-3"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
<path
|
||||
d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- end checkbox -->
|
||||
|
||||
<!-- invalid feedback -->
|
||||
<div class="hidden text-sm dark:text-red-500">
|
||||
{{value['label']}} is invalid and must match this pattern:
|
||||
{{value['regex']|safe}}
|
||||
</div>
|
||||
<!--end invalid feedback-->
|
||||
</div>
|
||||
{% endif %} {% endfor %}
|
||||
<div class="col-span-12 flex justify-center my-4">
|
||||
<button {{current_endpoint}}-multiple-delete="{{plugin['name']}}" 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-red-500 hover:bg-red-500/80 focus:bg-red-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">
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
<!-- end plugin settings -->
|
||||
</div>
|
||||
{%endif %}
|
||||
<!-- end plugin multiple -->
|
||||
</div>
|
||||
{% endfor %}
|
||||
<!-- end plugin item -->
|
||||
|
|
Loading…
Reference in a new issue