Run pre-commit-config and apply it, also lint jinja template files

This commit is contained in:
Théophile Diot 2024-02-27 18:07:49 +01:00
parent fb06e43861
commit b512f7278d
No known key found for this signature in database
GPG key ID: 248FEA4BAE400D06
50 changed files with 5842 additions and 6244 deletions

View file

@ -1 +1,9 @@
src/ui/templates/profile.html:hashicorp-tf-password:343
src/ui/templates/account.html:hashicorp-tf-password:194
src/ui/templates/account.html:hashicorp-tf-password:255
src/ui/templates/account.html:hashicorp-tf-password:292
src/ui/templates/account.html:hashicorp-tf-password:329
src/ui/templates/account.html:hashicorp-tf-password:417
src/ui/templates/account.html:hashicorp-tf-password:470
src/ui/templates/settings_plugins.html:hashicorp-tf-password:87
src/ui/templates/settings_plugins.html:hashicorp-tf-password:297

View file

@ -17,7 +17,7 @@ repos:
- id: check-case-conflict
- repo: https://github.com/psf/black
rev: e026c93888f91a47a9c9f4e029f3eb07d96375e6 # frozen: 24.1.1
rev: 6fdf8a4af28071ed1d079c01122b34c5d587207a # frozen: 24.2.0
hooks:
- id: black
name: Black Python Formatter

View file

@ -16,5 +16,6 @@ flatpickr.*
src/ui/static/js/editor/*
src/ui/static/js/utils/purify/*
src/ui/templates/*
src/common/core/*/ui/*
datepicker-foundation.css
examples/*

View file

@ -1,23 +1,25 @@
{% extends "base.html" %} {% block outdated %} You're not viewing the
documentation of the latest version.
<a href="{{ '../' ~ base_url }}">
<strong>Click here to view latest.</strong>
</a>
{% endblock %} {% block announce %} 📢 Looking for technical support, tailored
consulting or custom development for BunkerWeb ? Visit the
<a
href="https://panel.bunkerweb.io/?utm_campaign=self&utm_source=doc"
style="color: #3f6ec6; text-decoration: underline"
>BunkerWeb Panel</a
>
for more information on our enterprise offers. {% endblock %} {% block libs %}
<script
async
defer
data-domain="docs.bunkerweb.io"
src="https://data.bunkerity.com/js/script.js"
></script>
<script defer>
{% extends "base.html" %}
{% block outdated %}
You're not viewing the
documentation of the latest version.
<a href="{{ '../' ~ base_url }}">
<strong>Click here to view latest.</strong>
</a>
{% endblock %}
{% block announce %}
📢 Looking for technical support, tailored
consulting or custom development for BunkerWeb ? Visit the
<a href="https://panel.bunkerweb.io/?utm_campaign=self&utm_source=doc"
style="color: #3f6ec6;
text-decoration: underline">BunkerWeb Panel</a>
for more information on our enterprise offers.
{% endblock %}
{% block libs %}
<script async
defer
data-domain="docs.bunkerweb.io"
src="https://data.bunkerity.com/js/script.js"></script>
<script defer>
// Lazy load images and embed youtube videos
window.addEventListener("load", () => {
document.querySelectorAll("[data-src]").forEach((el) => {
@ -30,5 +32,5 @@ for more information on our enterprise offers. {% endblock %} {% block libs %}
.querySelector('div.md-search[data-md-component="search"][role="dialog"]')
.setAttribute("aria-label", "Search in documentation");
} catch (err) {}
</script>
</script>
{% endblock %}

45
misc/format-jinja-files.sh Executable file
View file

@ -0,0 +1,45 @@
#!/bin/bash
first_arg=$1
args=("$@")
if [ "$first_arg" == "manual" ]; then
echo "⏳ Running djLint for web UI Jinja files..."
djlint --reformat --profile=jinja --exclude=src/ui/templates/setup.html src/ui/templates
ret=$?
if [ $ret -ne 0 ]; then
echo "❌ djLint failed for web UI template files. Exiting..."
exit $ret
fi
echo "✅ djLint for web UI template files passed."
echo "⏳ Running djLint for core plugins UI Jinja files..."
djlint --reformat --profile=jinja src/common/core/*/ui
ret=$?
if [ $ret -ne 0 ]; then
echo "❌ djLint failed for core plugins UI template files. Exiting..."
exit $ret
fi
echo "✅ djLint for core plugins UI template files passed."
echo "⏳ Running djLint for documentation Jinja files..."
djlint --reformat --profile=jinja docs/
ret=$?
if [ $ret -ne 0 ]; then
echo "❌ djLint failed for documentation files. Exiting..."
exit $ret
fi
echo "✅ djLint for documentation files passed."
echo "✅ All djLint commands passed"
else
echo "⏳ Running custom djLint command with args: ${args[*]}"
djlint --reformat --profile=jinja "${args[@]}"
ret=$?
if [ $ret -ne 0 ]; then
echo "❌ djLint failed for custom command. Exiting..."
exit $ret
fi
echo "✅ djLint for custom command passed."
fi

View file

@ -1,60 +1,44 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-info-title">INFO</h5>
<div class="core-card-info-list">
<p data-info class="core-card-info-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">Challenges</p>
<h5 data-count class="core-card-title">"unknown"</h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error"
>total failed
</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-metrics-svg-container blue">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-base core-card-metrics-svg"
>
<path
d="M11.7 2.805a.75.75 0 0 1 .6 0A60.65 60.65 0 0 1 22.83 8.72a.75.75 0 0 1-.231 1.337 49.948 49.948 0 0 0-9.902 3.912l-.003.002c-.114.06-.227.119-.34.18a.75.75 0 0 1-.707 0A50.88 50.88 0 0 0 7.5 12.173v-.224c0-.131.067-.248.172-.311a54.615 54.615 0 0 1 4.653-2.52.75.75 0 0 0-.65-1.352 56.123 56.123 0 0 0-4.78 2.589 1.858 1.858 0 0 0-.859 1.228 49.803 49.803 0 0 0-4.634-1.527.75.75 0 0 1-.231-1.337A60.653 60.653 0 0 1 11.7 2.805Z"
/>
<path
d="M13.06 15.473a48.45 48.45 0 0 1 7.666-3.282c.134 1.414.22 2.843.255 4.284a.75.75 0 0 1-.46.711 47.87 47.87 0 0 0-8.105 4.342.75.75 0 0 1-.832 0 47.87 47.87 0 0 0-8.104-4.342.75.75 0 0 1-.461-.71c.035-1.442.121-2.87.255-4.286.921.304 1.83.634 2.726.99v1.27a1.5 1.5 0 0 0-.14 2.508c-.09.38-.222.753-.397 1.11.452.213.901.434 1.346.66a6.727 6.727 0 0 0 .551-1.607 1.5 1.5 0 0 0 .14-2.67v-.645a48.549 48.549 0 0 1 3.44 1.667 2.25 2.25 0 0 0 2.12 0Z"
/>
<path
d="M4.462 19.462c.42-.419.753-.89 1-1.395.453.214.902.435 1.347.662a6.742 6.742 0 0 1-1.286 1.794.75.75 0 0 1-1.06-1.06Z"
/>
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-info-title">INFO</h5>
<div class="core-card-info-list">
<p data-info class="core-card-info-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">Challenges</p>
<h5 data-count class="core-card-title">"unknown"</h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error">total failed</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-metrics-svg-container blue">
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-base core-card-metrics-svg">
<path d="M11.7 2.805a.75.75 0 0 1 .6 0A60.65 60.65 0 0 1 22.83 8.72a.75.75 0 0 1-.231 1.337 49.948 49.948 0 0 0-9.902 3.912l-.003.002c-.114.06-.227.119-.34.18a.75.75 0 0 1-.707 0A50.88 50.88 0 0 0 7.5 12.173v-.224c0-.131.067-.248.172-.311a54.615 54.615 0 0 1 4.653-2.52.75.75 0 0 0-.65-1.352 56.123 56.123 0 0 0-4.78 2.589 1.858 1.858 0 0 0-.859 1.228 49.803 49.803 0 0 0-4.634-1.527.75.75 0 0 1-.231-1.337A60.653 60.653 0 0 1 11.7 2.805Z" />
<path d="M13.06 15.473a48.45 48.45 0 0 1 7.666-3.282c.134 1.414.22 2.843.255 4.284a.75.75 0 0 1-.46.711 47.87 47.87 0 0 0-8.105 4.342.75.75 0 0 1-.832 0 47.87 47.87 0 0 0-8.104-4.342.75.75 0 0 1-.461-.71c.035-1.442.121-2.87.255-4.286.921.304 1.83.634 2.726.99v1.27a1.5 1.5 0 0 0-.14 2.508c-.09.38-.222.753-.397 1.11.452.213.901.434 1.346.66a6.727 6.727 0 0 0 .551-1.607 1.5 1.5 0 0 0 .14-2.67v-.645a48.549 48.549 0 0 1 3.44 1.667 2.25 2.25 0 0 0 2.12 0Z" />
<path d="M4.462 19.462c.42-.419.753-.89 1-1.395.453.214.902.435 1.347.662a6.742 6.742 0 0 1-1.286 1.794.75.75 0 0 1-1.06-1.06Z" />
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -68,39 +52,29 @@
type: "text",
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-deactivated-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-deactivated-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -1,55 +1,44 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div data-fetch-success-show class="hidden core-card-list w-small">
<div class="core-card-list-title-container">
<h5 class="core-card-list-title">BAD BEHAVIOR LIST</h5>
</div>
<div class="core-card-list-container">
<!-- list container-->
<div class="w-small core-card-list-wrap">
<!-- header-->
<p class="core-card-list-header col-span-6">Error code</p>
<p class="core-card-list-header col-span-6">Count</p>
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full">
<li data-item class="core-card-list-item col-span-6">
<p
data-name="code"
class="core-card-list-item-content col-span-6"
></p>
<p
data-name="count"
class="core-card-list-item-content col-span-6"
></p>
</li>
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div data-fetch-success-show class="hidden core-card-list w-small">
<div class="core-card-list-title-container">
<h5 class="core-card-list-title">BAD BEHAVIOR LIST</h5>
</div>
<div class="core-card-list-container">
<!-- list container-->
<div class="w-small core-card-list-wrap">
<!-- header-->
<p class="core-card-list-header col-span-6">Error code</p>
<p class="core-card-list-header col-span-6">Count</p>
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full">
<li data-item class="core-card-list-item col-span-6">
<p data-name="code" class="core-card-list-item-content col-span-6"></p>
<p data-name="count" class="core-card-list-item-content col-span-6"></p>
</li>
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -64,38 +53,29 @@
listNames: ["code", "count"],
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -1,174 +1,130 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used and is_metrics %}
<div class="core-layout">
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">URL</p>
<h5 data-count-url class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error"> denied </span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container red">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-medium core-card-metrics-svg"
>
<path
fill-rule="evenodd"
d="M19.902 4.098a3.75 3.75 0 0 0-5.304 0l-4.5 4.5a3.75 3.75 0 0 0 1.035 6.037.75.75 0 0 1-.646 1.353 5.25 5.25 0 0 1-1.449-8.45l4.5-4.5a5.25 5.25 0 1 1 7.424 7.424l-1.757 1.757a.75.75 0 1 1-1.06-1.06l1.757-1.757a3.75 3.75 0 0 0 0-5.304Zm-7.389 4.267a.75.75 0 0 1 1-.353 5.25 5.25 0 0 1 1.449 8.45l-4.5 4.5a5.25 5.25 0 1 1-7.424-7.424l1.757-1.757a.75.75 0 1 1 1.06 1.06l-1.757 1.757a3.75 3.75 0 1 0 5.304 5.304l4.5-4.5a3.75 3.75 0 0 0-1.035-6.037.75.75 0 0 1-.354-1Z"
clip-rule="evenodd"
/>
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">IP</p>
<h5 data-count-ip class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error"> denied </span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container lime">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-small core-card-metrics-svg"
>
<path
d="M3.53 2.47a.75.75 0 0 0-1.06 1.06l18 18a.75.75 0 1 0 1.06-1.06l-18-18ZM20.25 5.507v11.561L5.853 2.671c.15-.043.306-.075.467-.094a49.255 49.255 0 0 1 11.36 0c1.497.174 2.57 1.46 2.57 2.93ZM3.75 21V6.932l14.063 14.063L12 18.088l-7.165 3.583A.75.75 0 0 1 3.75 21Z"
/>
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">RDNS</p>
<h5 data-count-rdns class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error"> denied </span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-metrics-svg-container indigo">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-medium core-card-metrics-svg"
>
<path
d="M11.625 16.5a1.875 1.875 0 1 0 0-3.75 1.875 1.875 0 0 0 0 3.75Z"
/>
<path
fill-rule="evenodd"
d="M5.625 1.5H9a3.75 3.75 0 0 1 3.75 3.75v1.875c0 1.036.84 1.875 1.875 1.875H16.5a3.75 3.75 0 0 1 3.75 3.75v7.875c0 1.035-.84 1.875-1.875 1.875H5.625a1.875 1.875 0 0 1-1.875-1.875V3.375c0-1.036.84-1.875 1.875-1.875Zm6 16.5c.66 0 1.277-.19 1.797-.518l1.048 1.048a.75.75 0 0 0 1.06-1.06l-1.047-1.048A3.375 3.375 0 1 0 11.625 18Z"
clip-rule="evenodd"
/>
<path
d="M14.25 5.25a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963A5.23 5.23 0 0 0 16.5 7.5h-1.875a.375.375 0 0 1-.375-.375V5.25Z"
/>
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">ASN</p>
<h5 data-count-asn class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error"> denied </span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container blue">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-medium core-card-metrics-svg"
>
<path
d="M21.721 12.752a9.711 9.711 0 0 0-.945-5.003 12.754 12.754 0 0 1-4.339 2.708 18.991 18.991 0 0 1-.214 4.772 17.165 17.165 0 0 0 5.498-2.477ZM14.634 15.55a17.324 17.324 0 0 0 .332-4.647c-.952.227-1.945.347-2.966.347-1.021 0-2.014-.12-2.966-.347a17.515 17.515 0 0 0 .332 4.647 17.385 17.385 0 0 0 5.268 0ZM9.772 17.119a18.963 18.963 0 0 0 4.456 0A17.182 17.182 0 0 1 12 21.724a17.18 17.18 0 0 1-2.228-4.605ZM7.777 15.23a18.87 18.87 0 0 1-.214-4.774 12.753 12.753 0 0 1-4.34-2.708 9.711 9.711 0 0 0-.944 5.004 17.165 17.165 0 0 0 5.498 2.477ZM21.356 14.752a9.765 9.765 0 0 1-7.478 6.817 18.64 18.64 0 0 0 1.988-4.718 18.627 18.627 0 0 0 5.49-2.098ZM2.644 14.752c1.682.971 3.53 1.688 5.49 2.099a18.64 18.64 0 0 0 1.988 4.718 9.765 9.765 0 0 1-7.478-6.816ZM13.878 2.43a9.755 9.755 0 0 1 6.116 3.986 11.267 11.267 0 0 1-3.746 2.504 18.63 18.63 0 0 0-2.37-6.49ZM12 2.276a17.152 17.152 0 0 1 2.805 7.121c-.897.23-1.837.353-2.805.353-.968 0-1.908-.122-2.805-.353A17.151 17.151 0 0 1 12 2.276ZM10.122 2.43a18.629 18.629 0 0 0-2.37 6.49 11.266 11.266 0 0 1-3.746-2.504 9.754 9.754 0 0 1 6.116-3.985Z"
/>
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">User Agent</p>
<h5 data-count-user-agent class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error"> denied </span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container amber">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-small core-card-metrics-svg"
>
<path
fill-rule="evenodd"
d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z"
clip-rule="evenodd"
/>
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used and is_metrics %}
<div class="core-layout">
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">URL</p>
<h5 data-count-url class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error">denied</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container red">
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-medium core-card-metrics-svg">
<path fill-rule="evenodd" d="M19.902 4.098a3.75 3.75 0 0 0-5.304 0l-4.5 4.5a3.75 3.75 0 0 0 1.035 6.037.75.75 0 0 1-.646 1.353 5.25 5.25 0 0 1-1.449-8.45l4.5-4.5a5.25 5.25 0 1 1 7.424 7.424l-1.757 1.757a.75.75 0 1 1-1.06-1.06l1.757-1.757a3.75 3.75 0 0 0 0-5.304Zm-7.389 4.267a.75.75 0 0 1 1-.353 5.25 5.25 0 0 1 1.449 8.45l-4.5 4.5a5.25 5.25 0 1 1-7.424-7.424l1.757-1.757a.75.75 0 1 1 1.06 1.06l-1.757 1.757a3.75 3.75 0 1 0 5.304 5.304l4.5-4.5a3.75 3.75 0 0 0-1.035-6.037.75.75 0 0 1-.354-1Z" clip-rule="evenodd" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">IP</p>
<h5 data-count-ip class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error">denied</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container lime">
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-small core-card-metrics-svg">
<path d="M3.53 2.47a.75.75 0 0 0-1.06 1.06l18 18a.75.75 0 1 0 1.06-1.06l-18-18ZM20.25 5.507v11.561L5.853 2.671c.15-.043.306-.075.467-.094a49.255 49.255 0 0 1 11.36 0c1.497.174 2.57 1.46 2.57 2.93ZM3.75 21V6.932l14.063 14.063L12 18.088l-7.165 3.583A.75.75 0 0 1 3.75 21Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">RDNS</p>
<h5 data-count-rdns class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error">denied</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-metrics-svg-container indigo">
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-medium core-card-metrics-svg">
<path d="M11.625 16.5a1.875 1.875 0 1 0 0-3.75 1.875 1.875 0 0 0 0 3.75Z" />
<path fill-rule="evenodd" d="M5.625 1.5H9a3.75 3.75 0 0 1 3.75 3.75v1.875c0 1.036.84 1.875 1.875 1.875H16.5a3.75 3.75 0 0 1 3.75 3.75v7.875c0 1.035-.84 1.875-1.875 1.875H5.625a1.875 1.875 0 0 1-1.875-1.875V3.375c0-1.036.84-1.875 1.875-1.875Zm6 16.5c.66 0 1.277-.19 1.797-.518l1.048 1.048a.75.75 0 0 0 1.06-1.06l-1.047-1.048A3.375 3.375 0 1 0 11.625 18Z" clip-rule="evenodd" />
<path d="M14.25 5.25a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963A5.23 5.23 0 0 0 16.5 7.5h-1.875a.375.375 0 0 1-.375-.375V5.25Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">ASN</p>
<h5 data-count-asn class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error">denied</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container blue">
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-medium core-card-metrics-svg">
<path d="M21.721 12.752a9.711 9.711 0 0 0-.945-5.003 12.754 12.754 0 0 1-4.339 2.708 18.991 18.991 0 0 1-.214 4.772 17.165 17.165 0 0 0 5.498-2.477ZM14.634 15.55a17.324 17.324 0 0 0 .332-4.647c-.952.227-1.945.347-2.966.347-1.021 0-2.014-.12-2.966-.347a17.515 17.515 0 0 0 .332 4.647 17.385 17.385 0 0 0 5.268 0ZM9.772 17.119a18.963 18.963 0 0 0 4.456 0A17.182 17.182 0 0 1 12 21.724a17.18 17.18 0 0 1-2.228-4.605ZM7.777 15.23a18.87 18.87 0 0 1-.214-4.774 12.753 12.753 0 0 1-4.34-2.708 9.711 9.711 0 0 0-.944 5.004 17.165 17.165 0 0 0 5.498 2.477ZM21.356 14.752a9.765 9.765 0 0 1-7.478 6.817 18.64 18.64 0 0 0 1.988-4.718 18.627 18.627 0 0 0 5.49-2.098ZM2.644 14.752c1.682.971 3.53 1.688 5.49 2.099a18.64 18.64 0 0 0 1.988 4.718 9.765 9.765 0 0 1-7.478-6.816ZM13.878 2.43a9.755 9.755 0 0 1 6.116 3.986 11.267 11.267 0 0 1-3.746 2.504 18.63 18.63 0 0 0-2.37-6.49ZM12 2.276a17.152 17.152 0 0 1 2.805 7.121c-.897.23-1.837.353-2.805.353-.968 0-1.908-.122-2.805-.353A17.151 17.151 0 0 1 12 2.276ZM10.122 2.43a18.629 18.629 0 0 0-2.37 6.49 11.266 11.266 0 0 1-3.746-2.504 9.754 9.754 0 0 1 6.116-3.985Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">User Agent</p>
<h5 data-count-user-agent class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error">denied</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container amber">
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-small core-card-metrics-svg">
<path fill-rule="evenodd" d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z" clip-rule="evenodd" />
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -202,38 +158,29 @@
type: "text",
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -1,43 +1,34 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-status">
<div class="core-card-status-container">
<h5 class="core-card-status-title">STATUS</h5>
<svg
data-status-svg
class="core-card-status-svg info"
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="50" cy="50" r="50" />
</svg>
</div>
<p data-status-text class="core-card-text"></p>
</div>
<!-- end status -->
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-status">
<div class="core-card-status-container">
<h5 class="core-card-status-title">STATUS</h5>
<svg data-status-svg
class="core-card-status-svg info"
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" />
</svg>
</div>
<p data-status-text class="core-card-text"></p>
</div>
<!-- end status -->
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -53,40 +44,29 @@
textEl: document.querySelector("[data-status-text]"),
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -1,59 +1,44 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">CORS</p>
<h5 data-count class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error"
>request blocked</span
>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container red">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="scale-75 leading-none text-lg relative fill-red-700 stroke-white"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M18.364 18.364A9 9 0 0 0 5.636 5.636m12.728 12.728A9 9 0 0 1 5.636 5.636m12.728 12.728L5.636 5.636"
/>
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">CORS</p>
<h5 data-count class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error">request blocked</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container red">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="scale-75 leading-none text-lg relative fill-red-700 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="M18.364 18.364A9 9 0 0 0 5.636 5.636m12.728 12.728A9 9 0 0 1 5.636 5.636m12.728 12.728L5.636 5.636" />
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -67,38 +52,29 @@
type: "text",
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -1,58 +1,44 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">Country</p>
<h5 data-count class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error"
>request blocked</span
>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container red">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="scale-75 leading-none text-lg relative fill-red-700 stroke-white"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M18.364 18.364A9 9 0 0 0 5.636 5.636m12.728 12.728A9 9 0 0 1 5.636 5.636m12.728 12.728L5.636 5.636"
/>
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">Country</p>
<h5 data-count class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error">request blocked</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container red">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="scale-75 leading-none text-lg relative fill-red-700 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="M18.364 18.364A9 9 0 0 0 5.636 5.636m12.728 12.728A9 9 0 0 1 5.636 5.636m12.728 12.728L5.636 5.636" />
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -66,38 +52,29 @@
type: "text",
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -1,58 +1,44 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">DNSBL</p>
<h5 data-count class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error"
>request blocked</span
>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container red">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="scale-75 leading-none text-lg relative fill-red-700 stroke-white"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M18.364 18.364A9 9 0 0 0 5.636 5.636m12.728 12.728A9 9 0 0 1 5.636 5.636m12.728 12.728L5.636 5.636"
/>
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">DNSBL</p>
<h5 data-count class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error">request blocked</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container red">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="scale-75 leading-none text-lg relative fill-red-700 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="M18.364 18.364A9 9 0 0 0 5.636 5.636m12.728 12.728A9 9 0 0 1 5.636 5.636m12.728 12.728L5.636 5.636" />
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -66,39 +52,29 @@
type: "text",
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -1,54 +1,43 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div data-fetch-success-show class="hidden core-card-list w-medium">
<div class="core-card-list-container">
<h5 class="core-card-list-title">ERRORS LIST</h5>
</div>
<div class="core-card-list-container">
<!-- list container-->
<div class="core-card-list-wrap w-medium">
<!-- header-->
<p class="core-card-list-header col-span-8">Code error</p>
<p class="core-card-list-header col-span-4">Count</p>
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full">
<li data-item class="core-card-list-item">
<p
data-name="code"
class="core-card-list-item-content col-span-8"
></p>
<p
data-name="count"
class="core-card-list-item-content col-span-4"
></p>
</li>
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div data-fetch-success-show class="hidden core-card-list w-medium">
<div class="core-card-list-container">
<h5 class="core-card-list-title">ERRORS LIST</h5>
</div>
<div class="core-card-list-container">
<!-- list container-->
<div class="core-card-list-wrap w-medium">
<!-- header-->
<p class="core-card-list-header col-span-8">Code error</p>
<p class="core-card-list-header col-span-4">Count</p>
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full">
<li data-item class="core-card-list-item">
<p data-name="code" class="core-card-list-item-content col-span-8"></p>
<p data-name="count" class="core-card-list-item-content col-span-4"></p>
</li>
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -63,7 +52,6 @@
listNames: ["code", "count"],
},
});
</script>
</div>
</script>
</div>
{% endblock %}

View file

@ -1,58 +1,44 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">GREYLIST</p>
<h5 data-count class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error"
>request blocked</span
>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container red">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="scale-75 leading-none text-lg relative fill-red-700 stroke-white"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M18.364 18.364A9 9 0 0 0 5.636 5.636m12.728 12.728A9 9 0 0 1 5.636 5.636m12.728 12.728L5.636 5.636"
/>
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">GREYLIST</p>
<h5 data-count class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content error">request blocked</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container red">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="scale-75 leading-none text-lg relative fill-red-700 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="M18.364 18.364A9 9 0 0 0 5.636 5.636m12.728 12.728A9 9 0 0 1 5.636 5.636m12.728 12.728L5.636 5.636" />
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -66,38 +52,29 @@
type: "text",
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -124,7 +124,7 @@ function headers:header()
elseif type(set_cookie) == "table" then
new_set_cookie = {}
for _, single_set_cookie in ipairs(set_cookie) do
check_set_cookie = single_set_cookie
local check_set_cookie = single_set_cookie
if not check_set_cookie:find("[Ss]ecure") then
check_set_cookie = check_set_cookie .. "; Secure"
end

View file

@ -1,56 +1,44 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div data-fetch-success-show class="hidden core-card-list w-large">
<div class="core-card-list-container">
<h5 class="core-card-list-title">LIMIT AND REQUEST LIST</h5>
</div>
<div class="core-card-list-container">
<!-- list container-->
<div class="core-card-list-wrap w-large">
<!-- header-->
<p class="core-card-list-header col-span-8">URL</p>
<p class="core-card-list-header col-span-4">Count</p>
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full">
<li data-item class="core-card-list-item">
<p
data-name="url"
class="core-card-list-item-content col-span-8"
></p>
<p
data-name="count"
class="core-card-list-item-content col-span-4"
></p>
</li>
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div data-fetch-success-show class="hidden core-card-list w-large">
<div class="core-card-list-container">
<h5 class="core-card-list-title">LIMIT AND REQUEST LIST</h5>
</div>
<div class="core-card-list-container">
<!-- list container-->
<div class="core-card-list-wrap w-large">
<!-- header-->
<p class="core-card-list-header col-span-8">URL</p>
<p class="core-card-list-header col-span-4">Count</p>
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full">
<li data-item class="core-card-list-item">
<p data-name="url" class="core-card-list-item-content col-span-8"></p>
<p data-name="count" class="core-card-list-item-content col-span-4"></p>
</li>
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -65,38 +53,29 @@
listNames: ["url", "count"],
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -17,8 +17,19 @@ end
function misc:access()
-- Check if we need to redirect to HTTPS
if self.ctx.bw.scheme == "http" and ((self.ctx.bw.https_configured == "yes" and self.variables["AUTO_REDIRECT_HTTP_TO_HTTPS"] == "yes") or self.variables["REDIRECT_HTTP_TO_HTTPS"] == "yes") then
return self:ret(true, "redirect to HTTPS", HTTP_MOVED_PERMANENTLY, "https://" .. self.ctx.bw.http_host .. self.ctx.bw.request_uri)
if
self.ctx.bw.scheme == "http"
and (
(self.ctx.bw.https_configured == "yes" and self.variables["AUTO_REDIRECT_HTTP_TO_HTTPS"] == "yes")
or self.variables["REDIRECT_HTTP_TO_HTTPS"] == "yes"
)
then
return self:ret(
true,
"redirect to HTTPS",
HTTP_MOVED_PERMANENTLY,
"https://" .. self.ctx.bw.http_host .. self.ctx.bw.request_uri
)
end
-- Check if method is valid
local method = self.ctx.bw.request_method

View file

@ -1,87 +1,66 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used and is_metrics %}
<div class="core-layout">
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">DEFAULT SERVER DISABLED</p>
<h5 data-count-server-disabled class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content info"> total </span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container orange">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="scale-[0.55] core-card-metrics-svg"
>
<path
d="M4.08 5.227A3 3 0 0 1 6.979 3H17.02a3 3 0 0 1 2.9 2.227l2.113 7.926A5.228 5.228 0 0 0 18.75 12H5.25a5.228 5.228 0 0 0-3.284 1.153L4.08 5.227Z"
/>
<path
fill-rule="evenodd"
d="M5.25 13.5a3.75 3.75 0 1 0 0 7.5h13.5a3.75 3.75 0 1 0 0-7.5H5.25Zm10.5 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm3.75-.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z"
clip-rule="evenodd"
/>
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">DISALLOWED METHODS</p>
<h5 data-count-disallowed-methods class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content info"> count </span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container lime">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-small core-card-metrics-svg"
>
<path
d="M18.75 12.75h1.5a.75.75 0 0 0 0-1.5h-1.5a.75.75 0 0 0 0 1.5ZM12 6a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 12 6ZM12 18a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 12 18ZM3.75 6.75h1.5a.75.75 0 1 0 0-1.5h-1.5a.75.75 0 0 0 0 1.5ZM5.25 18.75h-1.5a.75.75 0 0 1 0-1.5h1.5a.75.75 0 0 1 0 1.5ZM3 12a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 3 12ZM9 3.75a2.25 2.25 0 1 0 0 4.5 2.25 2.25 0 0 0 0-4.5ZM12.75 12a2.25 2.25 0 1 1 4.5 0 2.25 2.25 0 0 1-4.5 0ZM9 15.75a2.25 2.25 0 1 0 0 4.5 2.25 2.25 0 0 0 0-4.5Z"
/>
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used and is_metrics %}
<div class="core-layout">
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">DEFAULT SERVER DISABLED</p>
<h5 data-count-server-disabled class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content info">total</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container orange">
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="scale-[0.55] core-card-metrics-svg">
<path d="M4.08 5.227A3 3 0 0 1 6.979 3H17.02a3 3 0 0 1 2.9 2.227l2.113 7.926A5.228 5.228 0 0 0 18.75 12H5.25a5.228 5.228 0 0 0-3.284 1.153L4.08 5.227Z" />
<path fill-rule="evenodd" d="M5.25 13.5a3.75 3.75 0 1 0 0 7.5h13.5a3.75 3.75 0 1 0 0-7.5H5.25Zm10.5 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm3.75-.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z" clip-rule="evenodd" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">DISALLOWED METHODS</p>
<h5 data-count-disallowed-methods class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content info">count</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container lime">
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-small core-card-metrics-svg">
<path d="M18.75 12.75h1.5a.75.75 0 0 0 0-1.5h-1.5a.75.75 0 0 0 0 1.5ZM12 6a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 12 6ZM12 18a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 12 18ZM3.75 6.75h1.5a.75.75 0 1 0 0-1.5h-1.5a.75.75 0 0 0 0 1.5ZM5.25 18.75h-1.5a.75.75 0 0 1 0-1.5h1.5a.75.75 0 0 1 0 1.5ZM3 12a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 3 12ZM9 3.75a2.25 2.25 0 1 0 0 4.5 2.25 2.25 0 0 0 0-4.5ZM12.75 12a2.25 2.25 0 1 1 4.5 0 2.25 2.25 0 0 1-4.5 0ZM9 15.75a2.25 2.25 0 1 0 0 4.5 2.25 2.25 0 0 0 0-4.5Z" />
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -100,38 +79,29 @@
type: "text",
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -1,74 +1,57 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">Keys</p>
<h5 data-count class="core-card-title">"unknown"</h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content info"
>total number
</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container sky">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="scale-[0.6] leading-none text-lg relative-sky-700 stroke-white"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M3.75 12h16.5m-16.5 3.75h16.5M3.75 19.5h16.5M5.625 4.5h12.75a1.875 1.875 0 0 1 0 3.75H5.625a1.875 1.875 0 0 1 0-3.75Z"
/>
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-status">
<div class="core-card-status-container">
<h5 class="core-card-status-title">STATUS</h5>
<svg
data-status-svg
class="core-card-status-svg info"
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="50" cy="50" r="50" />
</svg>
</div>
<p data-status-text class="core-card-text"></p>
</div>
<!-- end status -->
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">Keys</p>
<h5 data-count class="core-card-title">"unknown"</h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content info">total number</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container sky">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="scale-[0.6] leading-none text-lg relative-sky-700 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 12h16.5m-16.5 3.75h16.5M3.75 19.5h16.5M5.625 4.5h12.75a1.875 1.875 0 0 1 0 3.75H5.625a1.875 1.875 0 0 1 0-3.75Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-status">
<div class="core-card-status-container">
<h5 class="core-card-status-title">STATUS</h5>
<svg data-status-svg
class="core-card-status-svg info"
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" />
</svg>
</div>
<p data-status-text class="core-card-text"></p>
</div>
<!-- end status -->
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -89,40 +72,29 @@
textEl: document.querySelector("[data-status-text]"),
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -1,57 +1,44 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div data-fetch-success-show class="hidden core-card-list w-large">
<div class="core-card-list-container">
<h5 class="core-card-list-title">REVERSE SCAN LIST</h5>
</div>
<div class="core-card-list-container">
<!-- list container-->
<div class="core-card-list-wrap w-large">
<!-- header-->
<p class="core-card-list-header col-span-5">Port</p>
<p class="core-card-list-header col-span-7">Block count</p>
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full">
<li data-item class="core-card-list-item">
<p
data-name="port"
class="core-card-list-item-content col-span-5"
></p>
<p
data-name="count"
class="core-card-list-item-content col-span-7"
></p>
</li>
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div data-fetch-success-show class="hidden core-card-list w-large">
<div class="core-card-list-container">
<h5 class="core-card-list-title">REVERSE SCAN LIST</h5>
</div>
<div class="core-card-list-container">
<!-- list container-->
<div class="core-card-list-wrap w-large">
<!-- header-->
<p class="core-card-list-header col-span-5">Port</p>
<p class="core-card-list-header col-span-7">Block count</p>
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full">
<li data-item class="core-card-list-item">
<p data-name="port" class="core-card-list-item-content col-span-5"></p>
<p data-name="count" class="core-card-list-item-content col-span-7"></p>
</li>
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -66,38 +53,29 @@
listNames: ["port", "count"],
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -1,57 +1,42 @@
{% extends "base.html" %} {% block content %}
<input
type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden
/>
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">WHITELIST</p>
<h5 data-count class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content text-green-500 mx-0.5"
>request passed</span
>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container green">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-base core-card-metrics-svg"
>
<path
fill-rule="evenodd"
d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm13.36-1.814a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25Z"
clip-rule="evenodd"
/>
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
{% extends "base.html" %}
{% block content %}
<input type="csrf_token"
name="csrf_token"
value="{{ csrf_token }}"
class="hidden"
hidden />
<div class="core-layout">
{% if is_used and is_metrics %}
<!-- info-->
<div class="core-card">
<h5 class="core-card-title">INFO</h5>
<div class="core-card-text-container">
<p data-info class="core-card-text"></p>
</div>
</div>
<!-- end info -->
<div class="core-card-metrics">
<!-- text -->
<div>
<p class="core-card-metrics-name">WHITELIST</p>
<h5 data-count class="core-card-title"></h5>
<p class="core-card-metrics-subtitle">
<span class="core-card-metrics-subtitle-content text-green-500 mx-0.5">request passed</span>
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img" class="core-card-svg-container green">
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="size-base core-card-metrics-svg">
<path fill-rule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm13.36-1.814a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25Z" clip-rule="evenodd" />
</svg>
</div>
<!-- end icon -->
</div>
<script nonce="{{script_nonce}}">
// Use SetupPlugin class that is on static/js/plugins/setup.js
const setPlugin = new SetupPlugin({
info: {
@ -65,38 +50,29 @@
type: "text",
},
});
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
/>
</svg>
</div>
<!-- end icon -->
</script>
{% else %}
<div class="core-card">
<div class="core-card-wrap">
<h5 class="core-card-title">Deactivated</h5>
<!-- icon -->
<div role="img" class="core-card-svg-container">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="core-card-deactivated-svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
</svg>
</div>
<!-- end icon -->
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">This plugin need to be activated to get metrics.</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
<div class="core-card-text-container">
<p data-info class="core-card-text">
This plugin need to be activated to get metrics.
</p>
</div>
</div>
<!-- end info -->
{% endif %}
</div>
{% endblock %}

View file

@ -1,497 +1,497 @@
{% extends "base.html" %}
{% block content %}
<div data-service-content
class="md:max-w-[700px] min-h-[200px] first-letter:w-full overflow-hidden overflow-y-auto overflow-x-auto col-span-12 p-4 relative break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="my-2 font-bold dark:text-white/90 mx-2">SETTINGS</h5>
{% set tabs = [
{
"name": "Global",
"id": "global",
"popover": "Global informations"
},
{
"name": "Username",
"id": "username",
"popover": "Edit your username"
},
{
"name": "Password",
"id": "password",
"popover": "Update your password"
},
{
"name": "TOTP",
"id": "totp",
"popover": "Enabled / Disabled TOTP"
}
] %}
<!-- desktop tabs -->
<div role="tablist"
data-account-tabs-desktop
class="hidden md:block col-span-12 mb-4 mx-2">
<!-- tabs -->
{% for tab in tabs %}
<button role="tab"
data-tab-handler="{{ tab['id'] }}"
class="{% if loop.first %} active {% endif %} settings-tabs-tab-btn">
<span class="w-full flex justify-between items-center">
<!-- text and icon -->
<span class="settings-tabs-name">{{ tab['name'] }}</span>
<svg data-popover-btn="{{ tab['id'] }}"
class="fill-blue-500 h-5 w-5 mr-2 hover:brightness-95"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z" />
</svg>
<!-- end text and icon -->
<!-- popover -->
<span data-popover-content="{{ tab['id'] }}"
class="settings-tabs-popover-container hidden">
<span class="settings-tabs-popover-text">{{ tab['popover'] }}</span>
</span>
<!-- end popover -->
</span>
</button>
{% endfor %}
<!--end tabs-->
</div>
<!-- end desktop tabs -->
<!-- mobile tabs -->
<div class="md:hidden relative col-span-12 mb-4 mt-2 mx-2">
<button data-tab-dropdown-btn
aria-controls="tab-dropdown-mobile"
class="settings-tabs-mobile-btn">
<span aria-description="current tab" class="settings-tabs-mobile-btn-text">{{ tabs[0]['name'] }}</span>
<!-- chevron -->
<svg class="transition-transform h-4 w-4 fill-primary dark:fill-gray-300"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
<!-- end chevron -->
</button>
<!-- dropdown-->
<div id="tab-dropdown-mobile"
role="listbox"
data-tab-dropdown
class="hidden z-100 absolute flex-col w-full overflow-hidden overflow-y-auto max-h-90">
{% for tab in tabs %}
<button role="option"
data-tab-handler-mobile="{{ tab['id'] }}"
data-select="{% if loop.first %}true{% else %}false{% endif %}"
id="edit-account-{{ tab['id'] }}-tab"
class="{% if loop.first %} active first {% endif %} {% if loop.last %}last{% endif %} settings-tabs-mobile-dropdown-btn">
{{ tab['name'] }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end mobile tabs -->
<div data-plugin-item="global"
class="grid grid-cols-12 w-full justify-items-center">
<div class="col-span-12">
<h5 class="text-xl my-1 text-center transition duration-300 ease-in-out font-bold m-0 mb-4 dark:text-gray-200">
VERSION
</h5>
<div class="flex justify-center items-center">
<p class="mb-0 mr-2 dark:text-gray-300">
You are using
{% if is_pro_version %}
pro
{% else %}
free
<div data-service-content
class="md:max-w-[700px] min-h-[200px] first-letter:w-full overflow-hidden overflow-y-auto overflow-x-auto col-span-12 p-4 relative break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="my-2 font-bold dark:text-white/90 mx-2">SETTINGS</h5>
{% set tabs = [
{
"name": "Global",
"id": "global",
"popover": "Global informations"
},
{
"name": "Username",
"id": "username",
"popover": "Edit your username"
},
{
"name": "Password",
"id": "password",
"popover": "Update your password"
},
{
"name": "TOTP",
"id": "totp",
"popover": "Enabled / Disabled TOTP"
}
] %}
<!-- desktop tabs -->
<div role="tablist"
data-account-tabs-desktop
class="hidden md:block col-span-12 mb-4 mx-2">
<!-- tabs -->
{% for tab in tabs %}
<button role="tab"
data-tab-handler="{{ tab['id'] }}"
class="{% if loop.first %} active {% endif %} settings-tabs-tab-btn">
<span class="w-full flex justify-between items-center">
<!-- text and icon -->
<span class="settings-tabs-name">{{ tab['name'] }}</span>
<svg data-popover-btn="{{ tab['id'] }}"
class="fill-blue-500 h-5 w-5 mr-2 hover:brightness-95"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z" />
</svg>
<!-- end text and icon -->
<!-- popover -->
<span data-popover-content="{{ tab['id'] }}"
class="settings-tabs-popover-container hidden">
<span class="settings-tabs-popover-text">{{ tab['popover'] }}</span>
</span>
<!-- end popover -->
</span>
</button>
{% endfor %}
<!--end tabs-->
</div>
<!-- end desktop tabs -->
<!-- mobile tabs -->
<div class="md:hidden relative col-span-12 mb-4 mt-2 mx-2">
<button data-tab-dropdown-btn
aria-controls="tab-dropdown-mobile"
class="settings-tabs-mobile-btn">
<span aria-description="current tab" class="settings-tabs-mobile-btn-text">{{ tabs[0]['name'] }}</span>
<!-- chevron -->
<svg class="transition-transform h-4 w-4 fill-primary dark:fill-gray-300"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
<!-- end chevron -->
</button>
<!-- dropdown-->
<div id="tab-dropdown-mobile"
role="listbox"
data-tab-dropdown
class="hidden z-100 absolute flex-col w-full overflow-hidden overflow-y-auto max-h-90">
{% for tab in tabs %}
<button role="option"
data-tab-handler-mobile="{{ tab['id'] }}"
data-select="{% if loop.first %}true{% else %}false{% endif %}"
id="edit-account-{{ tab['id'] }}-tab"
class="{% if loop.first %} active first {% endif %} {% if loop.last %}last{% endif %} settings-tabs-mobile-dropdown-btn">
{{ tab['name'] }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end mobile tabs -->
<div data-plugin-item="global"
class="grid grid-cols-12 w-full justify-items-center">
<div class="col-span-12">
<h5 class="text-xl my-1 text-center transition duration-300 ease-in-out font-bold m-0 mb-4 dark:text-gray-200">
VERSION
</h5>
<div class="flex justify-center items-center">
<p class="mb-0 mr-2 dark:text-gray-300">
You are using
{% if is_pro_version %}
pro
{% else %}
free
{% endif %}
version
</p>
<div role="img"
aria-label="version"
class="dark:brightness-90 inline-block w-8 h-8 text-center rounded-circle bg-yellow-500">
{% if is_pro_version %}
<svg class="leading-none text-lg relative scale-[0.6]"
viewBox="0 0 48 46"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path class="fill-white" d="M43.218 28.2327L43.6765 23.971C43.921 21.6973 44.0825 20.1957 43.9557 19.2497L44 19.25C46.071 19.25 47.75 17.5711 47.75 15.5C47.75 13.4289 46.071 11.75 44 11.75C41.929 11.75 40.25 13.4289 40.25 15.5C40.25 16.4366 40.5935 17.2931 41.1613 17.9503C40.346 18.4535 39.2805 19.515 37.6763 21.1128C36.4405 22.3438 35.8225 22.9593 35.1333 23.0548C34.7513 23.1075 34.3622 23.0532 34.0095 22.898C33.373 22.6175 32.9485 21.8567 32.0997 20.335L27.6262 12.3135C27.1025 11.3747 26.6642 10.5889 26.2692 9.95662C27.89 9.12967 29 7.44445 29 5.5C29 2.73857 26.7615 0.5 24 0.5C21.2385 0.5 19 2.73857 19 5.5C19 7.44445 20.11 9.12967 21.7308 9.95662C21.3358 10.589 20.8975 11.3746 20.3738 12.3135L15.9002 20.335C15.0514 21.8567 14.627 22.6175 13.9905 22.898C13.6379 23.0532 13.2487 23.1075 12.8668 23.0548C12.1774 22.9593 11.5595 22.3438 10.3238 21.1128C8.71968 19.515 7.6539 18.4535 6.83882 17.9503C7.4066 17.2931 7.75 16.4366 7.75 15.5C7.75 13.4289 6.07107 11.75 4 11.75C1.92893 11.75 0.25 13.4289 0.25 15.5C0.25 17.5711 1.92893 19.25 4 19.25L4.04428 19.2497C3.91755 20.1957 4.07905 21.6973 4.32362 23.971L4.782 28.2327C5.03645 30.5982 5.24802 32.849 5.50717 34.875H42.4928C42.752 32.849 42.9635 30.5982 43.218 28.2327Z" fill="#1C274C" />
<path class="fill-white" d="M21.2803 45.5H26.7198C33.8098 45.5 37.3545 45.5 39.7198 43.383C40.7523 42.4588 41.4057 40.793 41.8775 38.625H6.1224C6.59413 40.793 7.24783 42.4588 8.2802 43.383C10.6454 45.5 14.1903 45.5 21.2803 45.5Z" fill="#1C274C" />
</svg>
{% else %}
<svg class="leading-none fill-white text-yellow-500 text-lg relative scale-[0.6]"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25a3 3 0 0 1 3 3m3 0a6 6 0 0 1-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1 1 21.75 8.25Z" />
</svg>
{% endif %}
</div>
</div>
{% if not is_pro_version %}
<div class="flex justify-center mt-2">
<a class="text-center font-semibold text-yellow-500 underline"
href="https://panel.bunkerweb.io/">Upgrade to pro</a>
</div>
{% endif %}
</div>
</div>
<div data-plugin-item="username"
class="hidden grid grid-cols-12 w-full justify-items-center">
<div class="col-span-12">
<h5 class="text-xl my-1 transition duration-300 ease-in-out font-bold m-0 mb-4 dark:text-gray-200">USERNAME</h5>
</div>
<!-- update username -->
<form class="col-span-12 grid grid-cols-12 w-full justify-items-center"
id="username-form"
action="account"
method="POST"
autocomplete="off">
<input type="hidden" name="operation" value="username" />
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden"
name="next"
value="{{ request.values.get('next', '') }}" />
<!-- username inpt-->
<div class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">Username</h5>
<label class="sr-only" for="admin_username">New username</label>
<input type="text"
id="admin_username"
name="admin_username"
class="col-span-12 regular-input"
placeholder="blank will remain previous username"
pattern="(.*?)"
maxlength="256"
value="{{ username }}"
required />
</div>
<!-- end username inpt-->
<!-- password inpt-->
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">Password</h5>
<label class="sr-only" for="curr_password">Password</label>
<input type="password"
id="curr_password"
name="curr_password"
class="col-span-12 regular-input"
placeholder="enter current password"
value=""
pattern="^(?=.*?\d)(?=.*?[ !\u0022#$%&'\(\)*+,.\/:;<=>?@\[\\\]^_`\u007B\u007C\u007D\u007E\u002D]).{8,}$"
minlength="8"
required />
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[55%]">
<button data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle dark:fill-blue-500 hover:brightness-75 transition-all"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
</div>
<!-- end password inpt-->
<div class="col-span-12 flex justify-center mt-6">
<button type="submit"
id="username-button"
name="username-button"
value="username"
class="edit-btn">Edit</button>
</div>
</form>
<!-- end update username -->
</div>
<form data-plugin-item="password"
class="hidden col-span-12 grid grid-cols-12 w-full justify-items-center mt-4"
id="password-form"
action="account"
method="POST"
autocomplete="off">
<div class="col-span-12">
<h5 class="text-xl my-1 transition duration-300 ease-in-out font-bold m-0 mb-4 dark:text-gray-200">PASSWORD</h5>
</div>
<input type="hidden" name="operation" value="password" />
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden"
name="next"
value="{{ request.values.get('next', '') }}" />
<!-- password inpt-->
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">Password</h5>
<label class="sr-only" for="curr_password">Password</label>
<input type="password"
id="curr_password"
name="curr_password"
class="col-span-12 regular-input"
placeholder="enter current password"
value=""
pattern="^(?=.*?\d)(?=.*?[ !\u0022#$%&'\(\)*+,.\/:;<=>?@\[\\\]^_`\u007B\u007C\u007D\u007E\u002D]).{8,}$"
minlength="8"
required />
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[55%]">
<button data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle dark:fill-blue-500 hover:brightness-75 transition-all"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
</div>
<!-- end password inpt-->
<!-- password inpt-->
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">New password</h5>
<label class="sr-only" for="admin_password">New password</label>
<input type="password"
id="admin_password"
name="admin_password"
class="col-span-12 regular-input"
placeholder="enter new password"
value=""
pattern="^(?=.*?\d)(?=.*?[ !\u0022#$%&'\(\)*+,.\/:;<=>?@\[\\\]^_`\u007B\u007C\u007D\u007E\u002D]).{8,}$"
minlength="8"
required />
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[55%]">
<button data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle dark:fill-blue-500 hover:brightness-75 transition-all"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
</div>
<!-- end password inpt-->
<!-- password inpt-->
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">Confirm new password</h5>
<label class="sr-only" for="admin_password_check">Confirm new password</label>
<input type="password"
id="admin_password_check"
name="admin_password_check"
class="col-span-12 regular-input"
placeholder="confirm new password"
value=""
pattern="^(?=.*?\d)(?=.*?[ !\u0022#$%&'\(\)*+,.\/:;<=>?@\[\\\]^_`\u007B\u007C\u007D\u007E\u002D]).{8,}$"
minlength="8"
required />
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[38%] md:top-[40%]">
<button data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle dark:fill-blue-500 hover:brightness-75 transition-all"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
<strong class="opacity-0 font-normal text-sm text-red-500" data-pw-alert>Value does not match password</strong>
</div>
<div class="col-span-12 flex justify-center">
<button type="submit" id="pw-button" name="pw-button" class="edit-btn">Edit</button>
</div>
</form>
<form data-plugin-item="totp"
class="hidden grid grid-cols-12 w-full justify-items-center"
id="totp-form"
action="account"
method="POST"
autocomplete="off">
<div class="col-span-12">
<h5 class="text-xl my-1 transition duration-300 ease-in-out text-md font-bold m-0 dark:text-gray-200">TOTP</h5>
</div>
<h5 class="{% if not is_totp %} text-red-500 {% else %} text-green-500 {% endif %} uppercase col-span-12 text-sm my-2 font-bold mx-2">
{% if not is_totp %}
TOTP is currently off
{% else %}
TOTP is currently on
{% endif %}
</h5>
<input type="hidden" name="operation" value="totp" />
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden"
name="next"
value="{{ request.values.get('next', '') }}" />
{% if not is_totp %}
<!-- qr secret -->
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title text-center">2FA QR CODE</h5>
<div class="flex justify-center mt-2">
<img src="data:image/png;base64, {{ totp_qr_image }}"
alt="Secret Token"
style="width: 200px;
height: 200px" />
</div>
</div>
<!-- end qr secret -->
<!-- secret -->
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">Secret token</h5>
<label class="sr-only" for="secret_token">secret token</label>
<input type="password"
id="secret_token"
name="secret_token"
class="col-span-12 regular-input"
placeholder="secret token"
value="{{ secret_token }}"
readonly />
<div data-clipboard-copy
class="hidden absolute flex right-[3.25rem] md:right-[3.75rem] h-5.5 w-5.5 top-[52%]">
<button data-clipboard-target="#secret_token"
class="bg-white dark:bg-slate-700 rounded-full h-full w-full flex items-center align-middle hover:brightness-95 transition-all"
type="button">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="stroke-gray-700 dark:stroke-gray-400 pointer-events-none hover:brightness-95 transition-all">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
</svg>
</button>
</div>
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[55%]">
<button data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle dark:fill-blue-500 hover:brightness-75 transition-all"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
</div>
<!-- end secret -->
{% endif %}
version
</p>
<div role="img"
aria-label="version"
class="dark:brightness-90 inline-block w-8 h-8 text-center rounded-circle bg-yellow-500">
{% if is_pro_version %}
<svg class="leading-none text-lg relative scale-[0.6]"
viewBox="0 0 48 46"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path class="fill-white" d="M43.218 28.2327L43.6765 23.971C43.921 21.6973 44.0825 20.1957 43.9557 19.2497L44 19.25C46.071 19.25 47.75 17.5711 47.75 15.5C47.75 13.4289 46.071 11.75 44 11.75C41.929 11.75 40.25 13.4289 40.25 15.5C40.25 16.4366 40.5935 17.2931 41.1613 17.9503C40.346 18.4535 39.2805 19.515 37.6763 21.1128C36.4405 22.3438 35.8225 22.9593 35.1333 23.0548C34.7513 23.1075 34.3622 23.0532 34.0095 22.898C33.373 22.6175 32.9485 21.8567 32.0997 20.335L27.6262 12.3135C27.1025 11.3747 26.6642 10.5889 26.2692 9.95662C27.89 9.12967 29 7.44445 29 5.5C29 2.73857 26.7615 0.5 24 0.5C21.2385 0.5 19 2.73857 19 5.5C19 7.44445 20.11 9.12967 21.7308 9.95662C21.3358 10.589 20.8975 11.3746 20.3738 12.3135L15.9002 20.335C15.0514 21.8567 14.627 22.6175 13.9905 22.898C13.6379 23.0532 13.2487 23.1075 12.8668 23.0548C12.1774 22.9593 11.5595 22.3438 10.3238 21.1128C8.71968 19.515 7.6539 18.4535 6.83882 17.9503C7.4066 17.2931 7.75 16.4366 7.75 15.5C7.75 13.4289 6.07107 11.75 4 11.75C1.92893 11.75 0.25 13.4289 0.25 15.5C0.25 17.5711 1.92893 19.25 4 19.25L4.04428 19.2497C3.91755 20.1957 4.07905 21.6973 4.32362 23.971L4.782 28.2327C5.03645 30.5982 5.24802 32.849 5.50717 34.875H42.4928C42.752 32.849 42.9635 30.5982 43.218 28.2327Z" fill="#1C274C" />
<path class="fill-white" d="M21.2803 45.5H26.7198C33.8098 45.5 37.3545 45.5 39.7198 43.383C40.7523 42.4588 41.4057 40.793 41.8775 38.625H6.1224C6.59413 40.793 7.24783 42.4588 8.2802 43.383C10.6454 45.5 14.1903 45.5 21.2803 45.5Z" fill="#1C274C" />
</svg>
{% else %}
<svg class="leading-none fill-white text-yellow-500 text-lg relative scale-[0.6]"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25a3 3 0 0 1 3 3m3 0a6 6 0 0 1-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1 1 21.75 8.25Z" />
</svg>
{% if is_totp or not is_totp %}
<!-- username inpt-->
<div class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">2FA code</h5>
<label class="sr-only" for="totp_token">totp code</label>
<input type="text"
id="totp_token"
name="totp_token"
class="col-span-12 regular-input"
placeholder="enter code"
pattern="(.*?)"
maxlength="256"
required />
</div>
<!-- password inpt-->
{% endif %}
</div>
</div>
{% if not is_pro_version %}
<div class="flex justify-center mt-2">
<a class="text-center font-semibold text-yellow-500 underline"
href="https://panel.bunkerweb.io/">Upgrade to pro</a>
</div>
{% endif %}
</div>
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">Password</h5>
<label class="sr-only" for="curr_password">Password</label>
<input type="password"
id="curr_password"
name="curr_password"
class="col-span-12 regular-input"
placeholder="enter password"
value=""
pattern="^(?=.*?\d)(?=.*?[ !\u0022#$%&'\(\)*+,.\/:;<=>?@\[\\\]^_`\u007B\u007C\u007D\u007E\u002D]).{8,}$"
minlength="8"
required />
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[55%]">
<button data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle dark:fill-blue-500 hover:brightness-75 transition-all"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
</div>
<!-- end password inpt-->
<div class="col-span-12 flex justify-center mt-6">
<button type="submit"
id="totp-button"
name="totp-button"
value="totp"
class="{% if not is_totp %}valid-btn{% else %}delete-btn{% endif %}">
{% if not is_totp %}
enable totp
{% else %}
disable totp
{% endif %}
</button>
</div>
</form>
</div>
<div data-plugin-item="username"
class="hidden grid grid-cols-12 w-full justify-items-center">
<div class="col-span-12">
<h5 class="text-xl my-1 transition duration-300 ease-in-out font-bold m-0 mb-4 dark:text-gray-200">USERNAME</h5>
</div>
<!-- update username -->
<form class="col-span-12 grid grid-cols-12 w-full justify-items-center"
id="username-form"
action="account"
method="POST"
autocomplete="off">
<input type="hidden" name="operation" value="username" />
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden"
name="next"
value="{{ request.values.get('next', '') }}" />
<!-- username inpt-->
<div class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">Username</h5>
<label class="sr-only" for="admin_username">New username</label>
<input type="text"
id="admin_username"
name="admin_username"
class="col-span-12 regular-input"
placeholder="blank will remain previous username"
pattern="(.*?)"
maxlength="256"
value="{{ username }}"
required />
</div>
<!-- end username inpt-->
<!-- password inpt-->
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">Password</h5>
<label class="sr-only" for="curr_password">Password</label>
<input type="password"
id="curr_password"
name="curr_password"
class="col-span-12 regular-input"
placeholder="enter current password"
value=""
pattern="^(?=.*?\d)(?=.*?[ !\u0022#$%&'\(\)*+,.\/:;<=>?@\[\\\]^_`\u007B\u007C\u007D\u007E\u002D]).{8,}$"
minlength="8"
required />
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[55%]">
<button data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle dark:fill-blue-500 hover:brightness-75 transition-all"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
</div>
<!-- end password inpt-->
<div class="col-span-12 flex justify-center mt-6">
<button type="submit"
id="username-button"
name="username-button"
value="username"
class="edit-btn">Edit</button>
</div>
</form>
<!-- end update username -->
</div>
<form data-plugin-item="password"
class="hidden col-span-12 grid grid-cols-12 w-full justify-items-center mt-4"
id="password-form"
action="account"
method="POST"
autocomplete="off">
<div class="col-span-12">
<h5 class="text-xl my-1 transition duration-300 ease-in-out font-bold m-0 mb-4 dark:text-gray-200">PASSWORD</h5>
</div>
<input type="hidden" name="operation" value="password" />
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden"
name="next"
value="{{ request.values.get('next', '') }}" />
<!-- password inpt-->
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">Password</h5>
<label class="sr-only" for="curr_password">Password</label>
<input type="password"
id="curr_password"
name="curr_password"
class="col-span-12 regular-input"
placeholder="enter current password"
value=""
pattern="^(?=.*?\d)(?=.*?[ !\u0022#$%&'\(\)*+,.\/:;<=>?@\[\\\]^_`\u007B\u007C\u007D\u007E\u002D]).{8,}$"
minlength="8"
required />
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[55%]">
<button data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle dark:fill-blue-500 hover:brightness-75 transition-all"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
</div>
<!-- end password inpt-->
<!-- password inpt-->
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">New password</h5>
<label class="sr-only" for="admin_password">New password</label>
<input type="password"
id="admin_password"
name="admin_password"
class="col-span-12 regular-input"
placeholder="enter new password"
value=""
pattern="^(?=.*?\d)(?=.*?[ !\u0022#$%&'\(\)*+,.\/:;<=>?@\[\\\]^_`\u007B\u007C\u007D\u007E\u002D]).{8,}$"
minlength="8"
required />
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[55%]">
<button data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle dark:fill-blue-500 hover:brightness-75 transition-all"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
</div>
<!-- end password inpt-->
<!-- password inpt-->
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">Confirm new password</h5>
<label class="sr-only" for="admin_password_check">Confirm new password</label>
<input type="password"
id="admin_password_check"
name="admin_password_check"
class="col-span-12 regular-input"
placeholder="confirm new password"
value=""
pattern="^(?=.*?\d)(?=.*?[ !\u0022#$%&'\(\)*+,.\/:;<=>?@\[\\\]^_`\u007B\u007C\u007D\u007E\u002D]).{8,}$"
minlength="8"
required />
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[38%] md:top-[40%]">
<button data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle dark:fill-blue-500 hover:brightness-75 transition-all"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
<strong class="opacity-0 font-normal text-sm text-red-500" data-pw-alert>Value does not match password</strong>
</div>
<div class="col-span-12 flex justify-center">
<button type="submit" id="pw-button" name="pw-button" class="edit-btn">Edit</button>
</div>
</form>
<form data-plugin-item="totp"
class="hidden grid grid-cols-12 w-full justify-items-center"
id="totp-form"
action="account"
method="POST"
autocomplete="off">
<div class="col-span-12">
<h5 class="text-xl my-1 transition duration-300 ease-in-out text-md font-bold m-0 dark:text-gray-200">TOTP</h5>
</div>
<h5 class="{% if not is_totp %} text-red-500 {% else %} text-green-500 {% endif %} uppercase col-span-12 text-sm my-2 font-bold mx-2">
{% if not is_totp %}
TOTP is currently off
{% else %}
TOTP is currently on
{% endif %}
</h5>
<input type="hidden" name="operation" value="totp" />
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden"
name="next"
value="{{ request.values.get('next', '') }}" />
{% if not is_totp %}
<!-- qr secret -->
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title text-center">2FA QR CODE</h5>
<div class="flex justify-center mt-2">
<img src="data:image/png;base64, {{ totp_qr_image }}"
alt="Secret Token"
style="width: 200px;
height: 200px" />
</div>
</div>
<!-- end qr secret -->
<!-- secret -->
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">Secret token</h5>
<label class="sr-only" for="secret_token">secret token</label>
<input type="password"
id="secret_token"
name="secret_token"
class="col-span-12 regular-input"
placeholder="secret token"
value="{{ secret_token }}"
readonly />
<div data-clipboard-copy
class="hidden absolute flex right-[3.25rem] md:right-[3.75rem] h-5.5 w-5.5 top-[52%]">
<button data-clipboard-target="#secret_token"
class="bg-white dark:bg-slate-700 rounded-full h-full w-full flex items-center align-middle hover:brightness-95 transition-all"
type="button">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="stroke-gray-700 dark:stroke-gray-400 pointer-events-none hover:brightness-95 transition-all">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
</svg>
</button>
</div>
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[55%]">
<button data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle dark:fill-blue-500 hover:brightness-75 transition-all"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
</div>
<!-- end secret -->
{% endif %}
{% if is_totp or not is_totp %}
<!-- username inpt-->
<div class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">2FA code</h5>
<label class="sr-only" for="totp_token">totp code</label>
<input type="text"
id="totp_token"
name="totp_token"
class="col-span-12 regular-input"
placeholder="enter code"
pattern="(.*?)"
maxlength="256"
required />
</div>
<!-- password inpt-->
{% endif %}
<div data-input-group
class="flex flex-col relative col-span-12 px-4 my-2 md:px-6 md:my-3 lg:px-6 lg:my-3 max-w-[400px] w-full">
<h5 class="input-title">Password</h5>
<label class="sr-only" for="curr_password">Password</label>
<input type="password"
id="curr_password"
name="curr_password"
class="col-span-12 regular-input"
placeholder="enter password"
value=""
pattern="^(?=.*?\d)(?=.*?[ !\u0022#$%&'\(\)*+,.\/:;<=>?@\[\\\]^_`\u007B\u007C\u007D\u007E\u002D]).{8,}$"
minlength="8"
required />
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[55%]">
<button data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle dark:fill-blue-500 hover:brightness-75 transition-all"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle"
type="button">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
</div>
<!-- end password inpt-->
<div class="col-span-12 flex justify-center mt-6">
<button type="submit"
id="totp-button"
name="totp-button"
value="totp"
class="{% if not is_totp %}valid-btn{% else %}delete-btn{% endif %}">
{% if not is_totp %}
enable totp
{% else %}
disable totp
{% endif %}
</button>
</div>
</form>
</div>
{% endblock content %}

View file

@ -2,37 +2,37 @@
tabindex="-1"
role="list"
class="relative flex justify-center gap-8 px-4 w-full h-[4rem] z-100 overflow-hidden">
<!-- background-->
<div class="absolute left-0 h-[3.5rem] w-full bg-secondary dark:brightness-95"></div>
<!--end background-->
<div role="listitem"
aria-hidden="false"
data-id="0"
class="h-[3.5rem] overflow-hidden flex justify-center items-center w-full left-0 transition-all duration-700 absolute px-1 md:px-4 py-1 bg-secondary dark:brightness-95">
<p class="dark:brightness-125 mb-0 text-center text-xs xs:text-sm text-white">
Need premium support ?
<a class="dark:brightness-125 font-medium underline text-gray-100 hover:no-underline"
href="https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui">Check BunkerWeb Panel</a>
</p>
</div>
<div role="listitem"
aria-hidden="true"
data-id="1"
class="h-[3.5rem] overflow-hidden left-full flex justify-center items-center w-full transition-all duration-700 absolute px-1 md:px-4 py-1 bg-secondary dark:brightness-95">
<p class="dark:brightness-125 mb-0 text-center text-xs xs:text-sm text-white">
Try BunkerWeb on our
<a class="dark:brightness-125 font-medium underline text-gray-100 hover:no-underline"
href="https://demo.bunkerweb.io/link/?utm_campaign=self&utm_source=ui">demo web app !</a>
</p>
</div>
<div role="listitem"
aria-hidden="true"
data-id="2"
class="h-[3.5rem] overflow-hidden left-full flex justify-center items-center w-full transition-all duration-700 absolute px-1 md:px-4 py-1 bg-secondary dark:brightness-95">
<p class="dark:brightness-125 mb-0 text-center text-xs xs:text-sm text-white">
All informations about BunkerWeb on our
<a class="dark:brightness-125 font-medium underline text-gray-100 hover:no-underline"
href="https://www.bunkerweb.io/?utm_campaign=self&utm_source=ui">website !</a>
</p>
</div>
<!-- background-->
<div class="absolute left-0 h-[3.5rem] w-full bg-secondary dark:brightness-95"></div>
<!--end background-->
<div role="listitem"
aria-hidden="false"
data-id="0"
class="h-[3.5rem] overflow-hidden flex justify-center items-center w-full left-0 transition-all duration-700 absolute px-1 md:px-4 py-1 bg-secondary dark:brightness-95">
<p class="dark:brightness-125 mb-0 text-center text-xs xs:text-sm text-white">
Need premium support ?
<a class="dark:brightness-125 font-medium underline text-gray-100 hover:no-underline"
href="https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui">Check BunkerWeb Panel</a>
</p>
</div>
<div role="listitem"
aria-hidden="true"
data-id="1"
class="h-[3.5rem] overflow-hidden left-full flex justify-center items-center w-full transition-all duration-700 absolute px-1 md:px-4 py-1 bg-secondary dark:brightness-95">
<p class="dark:brightness-125 mb-0 text-center text-xs xs:text-sm text-white">
Try BunkerWeb on our
<a class="dark:brightness-125 font-medium underline text-gray-100 hover:no-underline"
href="https://demo.bunkerweb.io/link/?utm_campaign=self&utm_source=ui">demo web app !</a>
</p>
</div>
<div role="listitem"
aria-hidden="true"
data-id="2"
class="h-[3.5rem] overflow-hidden left-full flex justify-center items-center w-full transition-all duration-700 absolute px-1 md:px-4 py-1 bg-secondary dark:brightness-95">
<p class="dark:brightness-125 mb-0 text-center text-xs xs:text-sm text-white">
All informations about BunkerWeb on our
<a class="dark:brightness-125 font-medium underline text-gray-100 hover:no-underline"
href="https://www.bunkerweb.io/?utm_campaign=self&utm_source=ui">website !</a>
</p>
</div>
</div>

View file

@ -1,271 +1,273 @@
{% extends "base.html" %}
{% block content %}
{% set reasons = ["all"] %}
{% set terms = ["all"] %}
{% for ban in bans %}
{% if ban["reason"] not in reasons %}
{% if reasons.append(ban["reason"]) %}{% endif %}
{% endif %}
{% if ban["term"] not in terms %}
{% if terms.append(ban["term"]) %}{% endif %}
{% endif %}
{% endfor %}
<!-- actions -->
<div class="col-span-12 relative flex justify-center min-w-0 break-words rounded-2xl bg-clip-border">
<button data-add-ban
type="button"
class="dark:bg-green-500/90 duration-300 dark:opacity-90 w-80 flex justify-center items-center px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal text-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
<span class="mr-2">Add ban</span>
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-7 h-7">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
</button>
</div>
<!-- end actions -->
<div class=" {% if bans|length == 0 %}w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words{% else %}hidden{% endif %} ">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No bans found</h5>
</div>
</div>
<!-- info-->
{% set bans_info = [
{"name" : "BANS TOTAL", "data" : bans|length|string},
{"name" : "TOP REASON", "data" : top_reason|string},
] %}
<div class="{% if bans|length == 0 %}hidden{% endif %} h-fit col-span-12 md:col-span-4 3xl:col-span-3 p-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="mb-2 font-bold dark:text-white/90">INFO</h5>
{% for info in bans_info %}
<div class="mx-1 flex items-center my-4">
<p class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ info['name'] }}
</p>
<p class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ info['data'] }}
</p>
</div>
{% set reasons = ["all"] %}
{% set terms = ["all"] %}
{% for ban in bans %}
{% if ban["reason"] not in reasons %}
{% if reasons.append(ban["reason"]) %}{% endif %}
{% endif %}
{% if ban["term"] not in terms %}
{% if terms.append(ban["term"]) %}{% endif %}
{% endif %}
{% endfor %}
</div>
<!-- end info -->
<!-- filter -->
{% set filters = [
{
"type": "input",
"name": "Search",
"label": "search",
"id": "keyword",
"placeholder": "ip, ban start, ban end",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Reason",
"id": "reason",
"value": "all",
"values": reasons
},
{
"type": "select",
"name": "Range",
"id": "term",
"value": "all",
"values": terms
}
] %}
<div data-bans-filter
class="{% if bans|length == 0 %}hidden{% endif %} h-fit col-span-12 md:col-span-8 2xl:col-span-6 3xl:col-span-5 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/90">FILTER</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-bans-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="bans-{{ filter['id'] }}"
data-name="bans-{{ filter['id'] }}"
data-bans-setting-select-text="{{ filter['id'] }}">{{ filter['value']}}</span>
<!-- chevron -->
<svg data-bans-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-bans-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-bans-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
<!-- actions -->
<div class="col-span-12 relative flex justify-center min-w-0 break-words rounded-2xl bg-clip-border">
<button data-add-ban
type="button"
class="dark:bg-green-500/90 duration-300 dark:opacity-90 w-80 flex justify-center items-center px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal text-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
<span class="mr-2">Add ban</span>
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-7 h-7">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
</button>
</div>
</div>
<!-- end filter -->
<div data-bans-nomatch
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No bans match</h5>
</div>
</div>
<div data-bans-list-container class=" {% if bans|length == 0 %}hidden{% endif %} w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="col-span-12">
<h5 class="mb-4 mt-2 font-bold dark:text-white/90 mx-2">BANS LIST</h5>
</div>
<div class="col-span-12 overflow-y-auto overflow-x-auto">
<div data-bans-bans-list>
<!-- list container-->
{% set bans_headers = [
{
"name": "Select",
"position": "col-span-1"
},
{
"name": "IP",
"position": "col-span-2"
},
{
"name": "Reason",
"position": "col-span-2"
},
{
"name": "Ban start",
"position": "col-span-2"
},
{
"name": "Ban end",
"position": "col-span-2"
},
{
"name": "Remain",
"position": "col-span-3"
},
{
"name": "Term",
"position": "hidden"
}
] %}
<div class="overflow-hidden min-w-[1150px] w-full grid grid-cols-12 rounded p-2">
<!-- header-->
{% for header in bans_headers %}
<p class="dark:text-gray-300 h-8 text-sm font-bold {{ header['position'] }} m-0 pb-2 border-b border-gray-400">
{{ header['name'] }}
</p>
{% endfor %}
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full" data-bans-list>
{% for ban in bans %}
<li data-bans-item data-bans-list-item="{{ ban }}"
class="items-center grid grid-cols-12 border-b border-gray-300 py-2.5">
<div data-bans-ban-select
data-checkbox-handler="ban-item-{{ loop.index }}"
class="relative mb-7 md:mb-0 z-10 ml-2">
<label class="sr-only" for="ban-item-{{ loop.index }}">Ban ip {{ loop.index }}</label>
<input id="ban-item-{{ loop.index }}"
name="ban-item-{{ loop.index }}"
data-default-method="ui"
data-default-value="no"
data-checked="false"
id="checkbox-ban-item-{{ loop.index }}"
class="checkbox"
type="checkbox"
value="no" />
<svg data-checkbox-handler="ban-item-{{ loop.index }}"
class="pointer-events-none 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 class="pointer-events-none" 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>
<p class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-bans-ip="{{ ban['ip'] }}">{{ ban['ip'] }}</p>
<p class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-bans-reason="{{ ban['reason'] }}">{{ ban['reason'] }}</p>
<p class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-bans-ban_start="{{ ban['ban_start'] }}">{{ ban['ban_start'] }}</p>
<p class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-bans-ban_end="{{ ban['ban_end'] }}">{{ ban['ban_end'] }}</p>
<p class="dark:text-gray-400 dark:opacity-80 text-sm col-span-3 m-0 my-1"
data-bans-remain="{{ ban['remain'] }}">{{ ban['remain'] }}</p>
<p class="hidden" data-bans-term="{{ ban['term'] }}">{{ ban['term'] }}</p>
</li>
{% endfor %}
</ul>
<!-- end list-->
<!-- end actions -->
<div class=" {% if bans|length == 0 %}w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words{% else %}hidden{% endif %} ">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No bans found</h5>
</div>
<!-- end list container-->
</div>
</div>
<form id="unban-items"
action="bans"
method="post"
class="w-full col-span-12 justify-center flex mt-6 mb-3">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="operation" value="unban">
<input data-unban-inp type="hidden" name="data" value="">
<button data-unban-btn
disabled
type="submit"
class="valid-btn mr-3 text-base">UNBAN</button>
</form>
</div>
{% include "bans_modal.html" %}
<!-- info-->
{% set bans_info = [
{"name" : "BANS TOTAL", "data" : bans|length|string},
{"name" : "TOP REASON", "data" : top_reason|string},
] %}
<div class="{% if bans|length == 0 %}hidden{% endif %} h-fit col-span-12 md:col-span-4 3xl:col-span-3 p-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="mb-2 font-bold dark:text-white/90">INFO</h5>
{% for info in bans_info %}
<div class="mx-1 flex items-center my-4">
<p class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ info['name'] }}
</p>
<p class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ info['data'] }}
</p>
</div>
{% endfor %}
</div>
<!-- end info -->
<!-- filter -->
{% set filters = [
{
"type": "input",
"name": "Search",
"label": "search",
"id": "keyword",
"placeholder": "ip, ban start, ban end",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Reason",
"id": "reason",
"value": "all",
"values": reasons
},
{
"type": "select",
"name": "Range",
"id": "term",
"value": "all",
"values": terms
}
] %}
<div data-bans-filter
class="{% if bans|length == 0 %}hidden{% endif %} h-fit col-span-12 md:col-span-8 2xl:col-span-6 3xl:col-span-5 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/90">FILTER</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-bans-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="bans-{{ filter['id'] }}"
data-name="bans-{{ filter['id'] }}"
data-bans-setting-select-text="{{ filter['id'] }}">{{ filter['value'] }}</span>
<!-- chevron -->
<svg data-bans-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-bans-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-bans-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
</div>
<!-- end filter -->
<div data-bans-nomatch
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No bans match</h5>
</div>
</div>
<div data-bans-list-container
class=" {% if bans|length == 0 %}hidden{% endif %} w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="col-span-12">
<h5 class="mb-4 mt-2 font-bold dark:text-white/90 mx-2">BANS LIST</h5>
</div>
<div class="col-span-12 overflow-y-auto overflow-x-auto">
<div data-bans-bans-list>
<!-- list container-->
{% set bans_headers = [
{
"name": "Select",
"position": "col-span-1"
},
{
"name": "IP",
"position": "col-span-2"
},
{
"name": "Reason",
"position": "col-span-2"
},
{
"name": "Ban start",
"position": "col-span-2"
},
{
"name": "Ban end",
"position": "col-span-2"
},
{
"name": "Remain",
"position": "col-span-3"
},
{
"name": "Term",
"position": "hidden"
}
] %}
<div class="overflow-hidden min-w-[1150px] w-full grid grid-cols-12 rounded p-2">
<!-- header-->
{% for header in bans_headers %}
<p class="dark:text-gray-300 h-8 text-sm font-bold {{ header['position'] }} m-0 pb-2 border-b border-gray-400">
{{ header['name'] }}
</p>
{% endfor %}
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full" data-bans-list>
{% for ban in bans %}
<li data-bans-item
data-bans-list-item="{{ ban }}"
class="items-center grid grid-cols-12 border-b border-gray-300 py-2.5">
<div data-bans-ban-select
data-checkbox-handler="ban-item-{{ loop.index }}"
class="relative mb-7 md:mb-0 z-10 ml-2">
<label class="sr-only" for="ban-item-{{ loop.index }}">Ban ip {{ loop.index }}</label>
<input id="ban-item-{{ loop.index }}"
name="ban-item-{{ loop.index }}"
data-default-method="ui"
data-default-value="no"
data-checked="false"
id="checkbox-ban-item-{{ loop.index }}"
class="checkbox"
type="checkbox"
value="no" />
<svg data-checkbox-handler="ban-item-{{ loop.index }}"
class="pointer-events-none 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 class="pointer-events-none" 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>
<p class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-bans-ip="{{ ban['ip'] }}">{{ ban['ip'] }}</p>
<p class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-bans-reason="{{ ban['reason'] }}">{{ ban['reason'] }}</p>
<p class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-bans-ban_start="{{ ban['ban_start'] }}">{{ ban['ban_start'] }}</p>
<p class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-bans-ban_end="{{ ban['ban_end'] }}">{{ ban['ban_end'] }}</p>
<p class="dark:text-gray-400 dark:opacity-80 text-sm col-span-3 m-0 my-1"
data-bans-remain="{{ ban['remain'] }}">{{ ban['remain'] }}</p>
<p class="hidden" data-bans-term="{{ ban['term'] }}">{{ ban['term'] }}</p>
</li>
{% endfor %}
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
<form id="unban-items"
action="bans"
method="post"
class="w-full col-span-12 justify-center flex mt-6 mb-3">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="operation" value="unban">
<input data-unban-inp type="hidden" name="data" value="">
<button data-unban-btn
disabled
type="submit"
class="valid-btn mr-3 text-base">UNBAN</button>
</form>
</div>
{% include "bans_modal.html" %}
{% endblock content %}

View file

@ -1,135 +1,135 @@
<!-- modal -->
<div data-bans-modal
class="dark:brightness-110 hidden w-screen h-screen fixed bg-gray-600/50 z-[1001] top-0 left-0 justify-center items-start">
<div data-bans-modal-card
class="overflow-y-auto mx-0 sm:mx-6 lg:mx-8 my-3 px-4 pt-4 pb-8 w-full sm:min-w-[500px] max-w-[650px] mt-[15vh] max-h-[70vh] flex flex-col justify-between break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div>
<div class="w-full flex justify-between mb-2">
<p data-bans-modal-title
class="transition duration-300 ease-in-out dark:opacity-90 dark:text-gray-200 mb-2 font-sans font-semibold leading-normal uppercase text-md">
ADD BANS
</p>
<button class="-translate-y-1" aria-label="close modal" data-bans-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>
<div data-bans-tabs-header
class="flex flex-col sm:flex-row justify-start items-start sm:items-center gap-x-4 gap-y-2 my-3">
<button data-ban-add-new
type="button"
class="disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0 dark:bg-green-500/90 duration-300 dark:opacity-90 flex justify-center items-center 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-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
<span class="mr-2 pointer-events-none">Entry</span>
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-7 h-7 pointer-events-none">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
</button>
<button data-add-ban-delete-all-item
type="button"
class="disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0 dark:bg-red-500/90 duration-300 dark:opacity-90 flex justify-center items-center 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-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
<span class="mr-2 pointer-events-none">Delete all</span>
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-7 h-7 pointer-events-none">
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
</svg>
</button>
</div>
<div class="col-span-12 overflow-y-auto overflow-x-auto max-h-[250px]">
<div data-bans-bans-list>
<!-- list container-->
<div class="overflow-hidden min-w-[600px] w-full grid grid-cols-12 rounded p-2">
<!-- header-->
<p class="pl-2 dark:text-gray-300 h-8 text-sm font-bold col-span-5 m-0 pb-2 border-b border-gray-400">IP</p>
<p class="pl-2 dark:text-gray-300 h-8 text-sm font-bold col-span-5 m-0 pb-2 border-b border-gray-400">Ban end</p>
<p class="flex justify-center dark:text-gray-300 h-8 text-sm font-bold col-span-2 m-0 pb-2 border-b border-gray-400">
Delete
</p>
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full h-full" data-bans-add-ban-list>
<li data-bans-add-ban-list
class="items-center grid grid-cols-12 border-b border-gray-300 py-2.5">
<div class="mx-1.5 col-span-5">
<label for="ip-0" class="sr-only">ip</label>
<input data-bans-add-ip
type="text"
id="ip-0"
name="ip-0"
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="127.0.0.1"
pattern="((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))$"
required />
</div>
<div class="mx-1.5 col-span-5">
<label for="ban-end-0" class="sr-only">Ban end</label>
<div class="relative">
<input data-bans-add-ban-end
type="text"
id="ban-end-0"
name="ban-end-0"
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="01/01/2021 00:00:00"
pattern="(.*?)"
required />
<div data-bans-modal-card
class="overflow-y-auto mx-0 sm:mx-6 lg:mx-8 my-3 px-4 pt-4 pb-8 w-full sm:min-w-[500px] max-w-[650px] mt-[15vh] max-h-[70vh] flex flex-col justify-between break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div>
<div class="w-full flex justify-between mb-2">
<p data-bans-modal-title
class="transition duration-300 ease-in-out dark:opacity-90 dark:text-gray-200 mb-2 font-sans font-semibold leading-normal uppercase text-md">
ADD BANS
</p>
<button class="-translate-y-1" aria-label="close modal" data-bans-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>
<div data-bans-tabs-header
class="flex flex-col sm:flex-row justify-start items-start sm:items-center gap-x-4 gap-y-2 my-3">
<button data-ban-add-new
type="button"
class="disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0 dark:bg-green-500/90 duration-300 dark:opacity-90 flex justify-center items-center 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-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
<span class="mr-2 pointer-events-none">Entry</span>
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="pointer-events-none absolute top-1 right-2 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />
class="w-7 h-7 pointer-events-none">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
</div>
</div>
<div class="mx-1.5 col-span-2 flex justify-center items-center">
<button data-add-ban-delete-item
type="button"
class="dark:bg-red-500/90 duration-300 dark:opacity-90 flex justify-center items-center p-2 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-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
</button>
<button data-add-ban-delete-all-item
type="button"
class="disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0 dark:bg-red-500/90 duration-300 dark:opacity-90 flex justify-center items-center 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-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
<span class="mr-2 pointer-events-none">Delete all</span>
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-6 h-6 pointer-events-none">
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
class="w-7 h-7 pointer-events-none">
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
</svg>
</button>
</button>
</div>
<div class="col-span-12 overflow-y-auto overflow-x-auto max-h-[250px]">
<div data-bans-bans-list>
<!-- list container-->
<div class="overflow-hidden min-w-[600px] w-full grid grid-cols-12 rounded p-2">
<!-- header-->
<p class="pl-2 dark:text-gray-300 h-8 text-sm font-bold col-span-5 m-0 pb-2 border-b border-gray-400">IP</p>
<p class="pl-2 dark:text-gray-300 h-8 text-sm font-bold col-span-5 m-0 pb-2 border-b border-gray-400">Ban end</p>
<p class="flex justify-center dark:text-gray-300 h-8 text-sm font-bold col-span-2 m-0 pb-2 border-b border-gray-400">
Delete
</p>
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full h-full" data-bans-add-ban-list>
<li data-bans-add-ban-list
class="items-center grid grid-cols-12 border-b border-gray-300 py-2.5">
<div class="mx-1.5 col-span-5">
<label for="ip-0" class="sr-only">ip</label>
<input data-bans-add-ip
type="text"
id="ip-0"
name="ip-0"
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="127.0.0.1"
pattern="((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))$"
required />
</div>
<div class="mx-1.5 col-span-5">
<label for="ban-end-0" class="sr-only">Ban end</label>
<div class="relative">
<input data-bans-add-ban-end
type="text"
id="ban-end-0"
name="ban-end-0"
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="01/01/2021 00:00:00"
pattern="(.*?)"
required />
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="pointer-events-none absolute top-1 right-2 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />
</svg>
</div>
</div>
<div class="mx-1.5 col-span-2 flex justify-center items-center">
<button data-add-ban-delete-item
type="button"
class="dark:bg-red-500/90 duration-300 dark:opacity-90 flex justify-center items-center p-2 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-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-6 h-6 pointer-events-none">
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
</svg>
</button>
</div>
</li>
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</li>
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
</div>
<form data-ban-add-form
class="w-full flex flex-col justify-between"
id="form-new"
action="bans"
method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" name="operation" value="ban" />
<input data-ban-add-inp type="hidden" name="data" value="" />
<!-- action button -->
<div class="w-full justify-center flex mt-6 mb-4">
<button data-bans-modal-close type="button" class="close-btn mr-3 text-base">Close</button>
<button disabled data-bans-modal-submit type="submit" class="valid-btn">Add</button>
</div>
<!-- end action button-->
</form>
</div>
<form data-ban-add-form
class="w-full flex flex-col justify-between"
id="form-new"
action="bans"
method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" name="operation" value="ban" />
<input data-ban-add-inp type="hidden" name="data" value="" />
<!-- action button -->
<div class="w-full justify-center flex mt-6 mb-4">
<button data-bans-modal-close type="button" class="close-btn mr-3 text-base">Close</button>
<button disabled data-bans-modal-submit type="submit" class="valid-btn">Add</button>
</div>
<!-- end action button-->
</form>
</div>
</div>
<!-- end modal -->

View file

@ -1,64 +1,64 @@
{% set template_data = {"javascript": ""} %}
<!DOCTYPE html>
<html class="{% if dark_mode == True %}dark {% endif %}" lang="en">
{% include "head.html" %}
<body class="overflow-x-hidden h-full font-sans z-100 m-0 text-base antialiased font-normal dark:bg-slate-900 leading-default bg-primary text-slate-500">
<noscript class="relative w-full p-4 text-white bg-yellow-500 rounded-lg">Your browser does not support JavaScript!</noscript>
<div data-loader
class="fixed z-[10000] transition duration-300 h-screen w-screen bg-primary flex justify-center align-middle items-center">
<img data-loader-img
src="images/logo-menu-2.png"
class="-translate-x-1.5 duration-300 w-50 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" %}
{% include "flashs.html"
%}
{% include "banner.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" %}
</div>
<!-- info -->
<main class="xl:pl-75 w-full px-2 sm:px-6 pb-0 pt-20 sm:pt-6 min-h-[85vh] flex flex-col justify-between">
<div class="max-w-[1920px] grid gap-y-4 gap-3 sm:gap-4 lg:gap-6 grid-cols-12 w-full">
{% block content %}{% endblock %}
</div>
{% include "footer.html" %}
</main>
<!-- end info -->
{% with messages = get_flashed_messages(with_categories=true) %}
{% if
messages %}
<!-- flash message-->
{% for category, message in messages %}
<div role="alert"
aria-description="login message alert"
data-flash-message
data-flash-message-fixed
class="{% if category == 'error' %} bg-red-500 {% else %} bg-green-500 {% endif %} 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 my-2 border rounded-lg hover:scale-102 transition shadow-md break-words dark:brightness-90">
<div class="flex justify-between align-top items-start">
{% if category == 'error' %}
<h5 class="text-lg mb-0 text-white">Error</h5>
{% else %}
<h5 class="text-lg mb-0 text-white">Success</h5>
{% endif %}
<button aria-label="close flash message"
data-close-flash-message
class="absolute right-8 top-2">
<svg class="cursor-pointer fill-white dark:opacity-80 absolute h-5 w-5"
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>
{% include "head.html" %}
<body class="overflow-x-hidden h-full font-sans z-100 m-0 text-base antialiased font-normal dark:bg-slate-900 leading-default bg-primary text-slate-500">
<noscript class="relative w-full p-4 text-white bg-yellow-500 rounded-lg">Your browser does not support JavaScript!</noscript>
<div data-loader
class="fixed z-[10000] transition duration-300 h-screen w-screen bg-primary flex justify-center align-middle items-center">
<img data-loader-img
src="images/logo-menu-2.png"
class="-translate-x-1.5 duration-300 w-50 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" %}
{% include "flashs.html"
%}
{% include "banner.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" %}
</div>
<!-- info -->
<main class="xl:pl-75 w-full px-2 sm:px-6 pb-0 pt-20 sm:pt-6 min-h-[85vh] flex flex-col justify-between">
<div class="max-w-[1920px] grid gap-y-4 gap-3 sm:gap-4 lg:gap-6 grid-cols-12 w-full">
{% block content %}{% endblock %}
</div>
<p class="text-white mt-2 mb-0 text-sm">{{ message|safe }}</p>
</div>
{% endfor %}
<!-- end flash message-->
{% endif %}
{% endwith %}
</body>
{% include "footer.html" %}
</main>
<!-- end info -->
{% with messages = get_flashed_messages(with_categories=true) %}
{% if
messages %}
<!-- flash message-->
{% for category, message in messages %}
<div role="alert"
aria-description="login message alert"
data-flash-message
data-flash-message-fixed
class="{% if category == 'error' %} bg-red-500 {% else %} bg-green-500 {% endif %} 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 my-2 border rounded-lg hover:scale-102 transition shadow-md break-words dark:brightness-90">
<div class="flex justify-between align-top items-start">
{% if category == 'error' %}
<h5 class="text-lg mb-0 text-white">Error</h5>
{% else %}
<h5 class="text-lg mb-0 text-white">Success</h5>
{% endif %}
<button aria-label="close flash message"
data-close-flash-message
class="absolute right-8 top-2">
<svg class="cursor-pointer fill-white dark:opacity-80 absolute h-5 w-5"
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>
<p class="text-white mt-2 mb-0 text-sm">{{ message|safe }}</p>
</div>
{% endfor %}
<!-- end flash message-->
{% endif %}
{% endwith %}
</body>
</html>

View file

@ -1,112 +1,119 @@
{% extends "base.html" %}
{% block content %}
{% set configs_info = [
{ "id" : "total-conf", "name" : "CONFIGS TOTAL", "data" : "unknown"},
{ "id" : "global-conf", "name" : "CONFIGS GLOBAL", "data" : "unknown"},
] %}
<div class="h-fit col-span-12 md:col-span-4 3xl:col-span-3 p-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="mb-2 font-bold dark:text-white/90">INFO</h5>
{% for info in configs_info %}
<div class="mx-1 flex items-center my-4">
<p class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ info['name'] }}
</p>
<p data-info-{{info['id']}} class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ info['data'] }}
</p>
{% set configs_info = [
{
"id": "total-conf",
"name": "CONFIGS TOTAL",
"data": "unknown"
},
{
"id": "global-conf",
"name": "CONFIGS GLOBAL",
"data": "unknown"
}
] %}
<div class="h-fit col-span-12 md:col-span-4 3xl:col-span-3 p-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="mb-2 font-bold dark:text-white/90">INFO</h5>
{% for info in configs_info %}
<div class="mx-1 flex items-center my-4">
<p class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ info['name'] }}
</p>
<p data-info-{{ info['id'] }} class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ info['data'] }}
</p>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
<!-- end info -->
<!-- filter -->
{% set filters = [
{
"type": "select",
"name": "Path with conf only",
"id": "withconf",
"value": "false",
"values": [
"false",
"true",
]
},
{
"type": "select",
"name": "Show global conf only",
"id": "globalconf",
"value": "false",
"values": [
"false",
"true"
]
},
] %}
<div data-configs-filter
class="h-fit col-span-12 md:col-span-8 lg:col-span-5 2xl:col-span-4 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">
<h5 class="mb-2 font-bold dark:text-white/90">FILTER</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<div class="flex flex-col relative col-span-12">
<h5 class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12">
<h5 class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-configs-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="configs{{ filter['id'] }}"
data-name="configs{{ filter['id'] }}"
data-configs-setting-select-text="{{ filter['id'] }}">{{ filter['value']}}</span>
<!-- chevron -->
<svg data-configs-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-configs-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-configs-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
<!-- end info -->
<!-- filter -->
{% set filters = [
{
"type": "select",
"name": "Path with conf only",
"id": "withconf",
"value": "false",
"values": [
"false",
"true"
]
},
{
"type": "select",
"name": "Show global conf only",
"id": "globalconf",
"value": "false",
"values": [
"false",
"true"
]
}
] %}
<div data-configs-filter
class="h-fit col-span-12 md:col-span-8 lg:col-span-5 2xl:col-span-4 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">
<h5 class="mb-2 font-bold dark:text-white/90">FILTER</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<div class="flex flex-col relative col-span-12">
<h5 class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12">
<h5 class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-configs-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="configs{{ filter['id'] }}"
data-name="configs{{ filter['id'] }}"
data-configs-setting-select-text="{{ filter['id'] }}">{{ filter['value'] }}</span>
<!-- chevron -->
<svg data-configs-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-configs-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-configs-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
</div>
<!-- end filter -->
</div>
<!-- end filter -->
{% include "file_manager.html" %}
{% endblock content %}

View file

@ -1,288 +1,286 @@
{% set current_endpoint = url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
<!-- main container -->
<div data-{{ current_endpoint }}-container class="flex flex-col justify-between :brightness-110 md:min-h-75-screen col-span-12 p-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="max-h-[500px]">
<div class="w-full grid-cols-12 grid">
<div class="col-span-12 md:col-span-8">
<h5 class="mb-2 font-bold dark:text-white/90">
{% if current_endpoint == "configs" %}
SERVICE MANAGER
{% else %}
FILE
MANAGER
{% endif %}
</h5>
<!--breadcrumb -->
<ul data-{{ current_endpoint }}-breadcrumb class="flex flex-wrap bg-transparent rounded-lg md:mb-8">
<li data-{{ current_endpoint }}-breadcrumb-item data-{{ current_endpoint }}-back class="mr-3 cursor-pointer text-sm capitalize leading-normal dark:text-gray-500 text-gray-600" aria-current="page">
<svg class="w-4.5 h-4.5 hover:brigthness-80"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3" />
</svg>
</li>
<li data-{{ current_endpoint }}-breadcrumb-item data-level="0" data-path="{% if current_endpoint == "cache" %}/var/cache/bunkerweb{% elif current_endpoint == "configs" %}/etc/bunkerweb/{{ current_endpoint }}{% endif %}" data-name="{{ current_endpoint }}" class="leading-normal text-sm">
<button class="dark:text-gray-500 text-gray-600 after:float-right after:pl-2 after:text-gray-600 dark:after:text-gray-500 after:content-['/']">
{{ current_endpoint }}
</button>
</li>
</ul>
<!-- end breadcrumb -->
</div>
</div>
<!-- folders-->
<div data-{{ current_endpoint }}-folders class="grid grid-cols-12 gap-3">
{% for folder in folders %}
{% for child in folder['children'] recursive %}
{{ loop(child['children']) }}
<!-- folder -->
<div data-{{ current_endpoint }}-element="{{ child['name'] }}" data-name="{{ child['name'] }}" data-can-create-folder="{{ child['can_create_folders'] }}" data-can-create-file="{{ child['can_create_files'] }}" data-path="{{ child['path'] }}" data-level="{{ loop.depth }}" data-_type="{{ child['type'] }}" class="cursor-pointer {% if loop.depth != 1 %}hidden{% endif %} relative min-h-20 col-span-12 md:col-span-6 2xl:col-span-4 3xl:col-span-3 p-3 flex justify-center items-center h-full transition rounded bg-gray-100 hover:bg-gray-300 dark:bg-slate-700 dark:hover:bg-slate-800">
{% if child['content'] %}
<span data-value="{{ child['content'] }}" data-{{ current_endpoint }}-content class="hidden"></span>
{% endif %}
<div class="w-full items-center grid grid-cols-12 pointer-events-none">
<!-- service root-->
{% if child['type'] == "folder" and current_endpoint == "configs" and loop.depth == 1 %}
<svg class="col-span-2 h-[2.5rem] w-[2.5rem] fill-primary stroke-gray-100 dark:stroke-gray-600 dark:brightness-150"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor">
<path d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" />
<path d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
{% endif %}
<!-- end service root-->
<!-- services folder -->
{% if child['type'] == "folder" and current_endpoint == "configs" and loop.depth != 1 %}
<svg class="col-span-2 h-[2.5rem] w-[2.5rem] fill-primary stroke-gray-100 dark:stroke-gray-600 dark:brightness-150"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 17.25v-.228a4.5 4.5 0 00-.12-1.03l-2.268-9.64a3.375 3.375 0 00-3.285-2.602H7.923a3.375 3.375 0 00-3.285 2.602l-2.268 9.64a4.5 4.5 0 00-.12 1.03v.228m19.5 0a3 3 0 01-3 3H5.25a3 3 0 01-3-3m19.5 0a3 3 0 00-3-3H5.25a3 3 0 00-3 3m16.5 0h.008v.008h-.008v-.008zm-3 0h.008v.008h-.008v-.008z" />
</svg>
{% endif %}
<!-- end services folder-->
<!-- services files -->
{% if child['type'] == "file" and current_endpoint == "configs" and loop.depth != 1 %}
<svg class="col-span-2 h-[2.5rem] w-[2.5rem] fill-primary stroke-gray-100 dark:stroke-gray-600 dark:brightness-150"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
</svg>
{% endif %}
<!-- end services files-->
<!-- cache folder-->
{% if child['type'] == "folder" and current_endpoint == "cache" and loop.depth == 1 %}
<svg class="col-span-2 h-[2.5rem] w-[2.5rem] fill-primary stroke-gray-100 dark:stroke-gray-600 dark:brightness-150"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M20.25 7.5l-.625 10.632a2.25 2.25 0 01-2.247 2.118H6.622a2.25 2.25 0 01-2.247-2.118L3.75 7.5M10 11.25h4M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125z" />
</svg>
{% endif %}
<!-- end cache folder -->
<!-- cache file -->
{% if child['type'] == "file" and current_endpoint == "cache" %}
<svg class="col-span-2 h-[2.5rem] w-[2.5rem] fill-primary stroke-gray-100 dark:stroke-gray-600 dark:brightness-150"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 13.5H9m4.06-7.19l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z" />
</svg>
{% endif %}
<!-- end cache file -->
<span data-{{ current_endpoint }}-element-text class="col-span-10 pointer-events-none transition duration-300 ease-in-out dark:opacity-90 text-center mr-12 mb-0 text-sm xl:text-base text-slate-700 dark:text-gray-300">
{{ child['name'] }}
</span>
<div class="max-h-[500px]">
<div class="w-full grid-cols-12 grid">
<div class="col-span-12 md:col-span-8">
<h5 class="mb-2 font-bold dark:text-white/90">
{% if current_endpoint == "configs" %}
SERVICE MANAGER
{% else %}
FILE
MANAGER
{% endif %}
</h5>
<!--breadcrumb -->
<ul data-{{ current_endpoint }}-breadcrumb class="flex flex-wrap bg-transparent rounded-lg md:mb-8">
<li data-{{ current_endpoint }}-breadcrumb-item data-{{ current_endpoint }}-back class="mr-3 cursor-pointer text-sm capitalize leading-normal dark:text-gray-500 text-gray-600" aria-current="page">
<svg class="w-4.5 h-4.5 hover:brigthness-80"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3" />
</svg>
</li>
<li data-{{ current_endpoint }}-breadcrumb-item data-level="0" data-path="{% if current_endpoint == "cache" %}/var/cache/bunkerweb{% elif current_endpoint == "configs" %}/etc/bunkerweb/{{ current_endpoint }}{% endif %}" data-name="{{ current_endpoint }}" class="leading-normal text-sm">
<button class="dark:text-gray-500 text-gray-600 after:float-right after:pl-2 after:text-gray-600 dark:after:text-gray-500 after:content-['/']">
{{ current_endpoint }}
</button>
</li>
</ul>
<!-- end breadcrumb -->
</div>
<div>
<!-- action button -->
<div data-{{ current_endpoint }}-action-button="{{ child['name'] }}" class="dark:brightness-125 dark:hover:brightness-100 flex justify-center items-center absolute h-full w-10 bg-primary fill-white first-letter:absolute top-0 -right-1 font-bold text-center text-white uppercase transition-all rounded-none rounded-r-lg cursor-pointer leading-normal text-xs ease-in tracking-tight-rem bg-150 bg-x-25 active:opacity-85">
<svg class="h-8 w-8 fill-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.75a.75.75 0 110-1.5.75.75 0 010 1.5zM12 12.75a.75.75 0 110-1.5.75.75 0 010 1.5zM12 18.75a.75.75 0 110-1.5.75.75 0 010 1.5z" />
</svg>
</div>
<!-- end action button -->
</div>
<!-- folders-->
<div data-{{ current_endpoint }}-folders class="grid grid-cols-12 gap-3">
{% for folder in folders %}
{% for child in folder['children'] recursive %}
{{ loop(child['children']) }}
<!-- folder -->
<div data-{{ current_endpoint }}-element="{{ child['name'] }}" data-name="{{ child['name'] }}" data-can-create-folder="{{ child['can_create_folders'] }}" data-can-create-file="{{ child['can_create_files'] }}" data-path="{{ child['path'] }}" data-level="{{ loop.depth }}" data-_type="{{ child['type'] }}" class="cursor-pointer {% if loop.depth != 1 %}hidden{% endif %} relative min-h-20 col-span-12 md:col-span-6 2xl:col-span-4 3xl:col-span-3 p-3 flex justify-center items-center h-full transition rounded bg-gray-100 hover:bg-gray-300 dark:bg-slate-700 dark:hover:bg-slate-800">
{% if child['content'] %}
<span data-value="{{ child['content'] }}" data-{{ current_endpoint }}-content class="hidden"></span>
{% endif %}
<div class="w-full items-center grid grid-cols-12 pointer-events-none">
<!-- service root-->
{% if child['type'] == "folder" and current_endpoint == "configs" and loop.depth == 1 %}
<svg class="col-span-2 h-[2.5rem] w-[2.5rem] fill-primary stroke-gray-100 dark:stroke-gray-600 dark:brightness-150"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor">
<path d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" />
<path d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
{% endif %}
<!-- end service root-->
<!-- services folder -->
{% if child['type'] == "folder" and current_endpoint == "configs" and loop.depth != 1 %}
<svg class="col-span-2 h-[2.5rem] w-[2.5rem] fill-primary stroke-gray-100 dark:stroke-gray-600 dark:brightness-150"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 17.25v-.228a4.5 4.5 0 00-.12-1.03l-2.268-9.64a3.375 3.375 0 00-3.285-2.602H7.923a3.375 3.375 0 00-3.285 2.602l-2.268 9.64a4.5 4.5 0 00-.12 1.03v.228m19.5 0a3 3 0 01-3 3H5.25a3 3 0 01-3-3m19.5 0a3 3 0 00-3-3H5.25a3 3 0 00-3 3m16.5 0h.008v.008h-.008v-.008zm-3 0h.008v.008h-.008v-.008z" />
</svg>
{% endif %}
<!-- end services folder-->
<!-- services files -->
{% if child['type'] == "file" and current_endpoint == "configs" and loop.depth != 1 %}
<svg class="col-span-2 h-[2.5rem] w-[2.5rem] fill-primary stroke-gray-100 dark:stroke-gray-600 dark:brightness-150"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
</svg>
{% endif %}
<!-- end services files-->
<!-- cache folder-->
{% if child['type'] == "folder" and current_endpoint == "cache" and loop.depth == 1 %}
<svg class="col-span-2 h-[2.5rem] w-[2.5rem] fill-primary stroke-gray-100 dark:stroke-gray-600 dark:brightness-150"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M20.25 7.5l-.625 10.632a2.25 2.25 0 01-2.247 2.118H6.622a2.25 2.25 0 01-2.247-2.118L3.75 7.5M10 11.25h4M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125z" />
</svg>
{% endif %}
<!-- end cache folder -->
<!-- cache file -->
{% if child['type'] == "file" and current_endpoint == "cache" %}
<svg class="col-span-2 h-[2.5rem] w-[2.5rem] fill-primary stroke-gray-100 dark:stroke-gray-600 dark:brightness-150"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 13.5H9m4.06-7.19l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z" />
</svg>
{% endif %}
<!-- end cache file -->
<span data-{{ current_endpoint }}-element-text class="col-span-10 pointer-events-none transition duration-300 ease-in-out dark:opacity-90 text-center mr-12 mb-0 text-sm xl:text-base text-slate-700 dark:text-gray-300">
{{ child['name'] }}
</span>
</div>
<div>
<!-- action button -->
<div data-{{ current_endpoint }}-action-button="{{ child['name'] }}" class="dark:brightness-125 dark:hover:brightness-100 flex justify-center items-center absolute h-full w-10 bg-primary fill-white first-letter:absolute top-0 -right-1 font-bold text-center text-white uppercase transition-all rounded-none rounded-r-lg cursor-pointer leading-normal text-xs ease-in tracking-tight-rem bg-150 bg-x-25 active:opacity-85">
<svg class="h-8 w-8 fill-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.75a.75.75 0 110-1.5.75.75 0 010 1.5zM12 12.75a.75.75 0 110-1.5.75.75 0 010 1.5zM12 18.75a.75.75 0 110-1.5.75.75 0 010 1.5z" />
</svg>
</div>
<!-- end action button -->
</div>
<!-- dropdown actions -->
<div role="tablist" data-{{ current_endpoint }}-action-dropdown="{{ child['name'] }}" class="absolute hidden flex-col z-110 w-48 right-0 top-0 translate-y-16">
<!-- view button-->
<button role="tab" value="view" data-{{ current_endpoint }}-action-dropdown-btn="{{ child['name'] }}" class="duration-300 border-gray-300 hover:brightness-90 bg-white 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 w-full border-t rounded-t border-b border-l border-r hover:bg-gray-100">
<span class="flex justify-start items-center">
<svg class="h-5.5 w-5.5 stroke-green-700 dark:brightness-125"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
<span class="transition duration-300 ease-in-out text-gray-700 dark:text-gray-300 dark:opacity-80 ml-4 font-bold uppercase">view</span>
</span>
</button>
<!-- end view button-->
<!-- edit button -->
{% if child['type'] == "file" and child['can_edit'] == True or
child['type'] == "folder" and child['can_edit'] == True %}
<button role="tab" value="edit" data-{{ current_endpoint }}-action-dropdown-btn="{{ child['name'] }}" class="duration-300 border-gray-300 hover:brightness-90 bg-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 w-full border-b border-l border-r hover:bg-gray-100">
<span class="flex justify-start items-center">
<svg class="h-5.5 w-5.5 stroke-yellow-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" />
</svg>
<span class="transition duration-300 ease-in-out text-gray-700 dark:text-gray-300 dark:opacity-80 ml-4 font-bold uppercase">edit</span>
</span>
</button>
{% endif %}
<!-- end edit button -->
<!-- download button -->
{% if child['type'] == "file" and child['can_download'] == True %}
{% if current_endpoint == "cache" %}
<button role="tab" value="download" data-{{ current_endpoint }}-download="{{ child['name'].split("/")[0] }}" data-{{ current_endpoint }}-file="{{ child['name'].split("/")[1] }}" data-{{ current_endpoint }}-setting-select-dropdown-btn="{{ child['name'].split("/")[0] }}" class="duration-300 border-gray-300 hover:brightness-90 bg-white 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 w-full border-b border-l border-r hover:bg-gray-100">
<span class="flex justify-start items-center">
<svg class="h-5.5 w-5.5 stroke-sky-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75l3 3m0 0l3-3m-3 3v-7.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="transition duration-300 ease-in-out text-gray-700 dark:text-gray-300 dark:opacity-80 ml-4 font-bold uppercase">download</span>
</span>
</button>
{% else %}
<button role="tab" value="download" data-{{ current_endpoint }}-action-dropdown-btn="{{ child['name'] }}" class="duration-300 border-gray-300 hover:brightness-90 bg-white 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 w-full border-b border-l border-r hover:bg-gray-100">
<span class="flex justify-start items-center">
<svg class="h-6 w-6 stroke-sky-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75l3 3m0 0l3-3m-3 3v-7.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="transition duration-300 ease-in-out text-gray-700 dark:text-gray-300 dark:opacity-80 ml-4 font-bold uppercase">download</span>
</span>
</button>
{% endif %}
{% endif %}
<!-- end download button -->
<!-- delete button -->
{% if child['can_delete'] == True %}
<button role="tab" value="delete" data-{{ current_endpoint }}-action-dropdown-btn="{{ child['name'] }}" class="bg-white duration-300 border-gray-300 hover:brightness-90 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 w-full border-b border-l border-r hover:bg-gray-100">
<span class="flex justify-start items-center">
<svg class="h-5.5 w-5.5 stroke-red-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
</svg>
<span class="transition duration-300 ease-in-out text-gray-700 dark:text-gray-300 dark:opacity-80 ml-4 font-bold uppercase">delete</span>
</span>
</button>
{% endif %}
<!-- end delete button -->
</div>
<!-- end dropdown actions -->
</div>
<!-- end folder-->
{% endfor %}
</div>
<!-- dropdown actions -->
<div role="tablist" data-{{ current_endpoint }}-action-dropdown="{{ child['name'] }}" class="absolute hidden flex-col z-110 w-48 right-0 top-0 translate-y-16">
<!-- view button-->
<button role="tab" value="view" data-{{ current_endpoint }}-action-dropdown-btn="{{ child['name'] }}" class="duration-300 border-gray-300 hover:brightness-90 bg-white 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 w-full border-t rounded-t border-b border-l border-r hover:bg-gray-100">
<span class="flex justify-start items-center">
<svg class="h-5.5 w-5.5 stroke-green-700 dark:brightness-125"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
<span class="transition duration-300 ease-in-out text-gray-700 dark:text-gray-300 dark:opacity-80 ml-4 font-bold uppercase">view</span>
</span>
</button>
<!-- end view button-->
<!-- edit button -->
{% if child['type'] == "file" and child['can_edit'] == True or
child['type'] == "folder" and child['can_edit'] == True %}
<button role="tab" value="edit" data-{{ current_endpoint }}-action-dropdown-btn="{{ child['name'] }}" class="duration-300 border-gray-300 hover:brightness-90 bg-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 w-full border-b border-l border-r hover:bg-gray-100">
<span class="flex justify-start items-center">
<svg class="h-5.5 w-5.5 stroke-yellow-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" />
</svg>
<span class="transition duration-300 ease-in-out text-gray-700 dark:text-gray-300 dark:opacity-80 ml-4 font-bold uppercase">edit</span>
</span>
</button>
{% endif %}
<!-- end edit button -->
<!-- download button -->
{% if child['type'] == "file" and child['can_download'] == True %}
{% if current_endpoint == "cache" %}
<button role="tab" value="download" data-{{ current_endpoint }}-download="{{ child['name'].split("/")[0] }}" data-{{ current_endpoint }}-file="{{ child['name'].split("/")[1] }}" data-{{ current_endpoint }}-setting-select-dropdown-btn="{{ child['name'].split("/")[0] }}" class="duration-300 border-gray-300 hover:brightness-90 bg-white 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 w-full border-b border-l border-r hover:bg-gray-100">
<span class="flex justify-start items-center">
<svg class="h-5.5 w-5.5 stroke-sky-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75l3 3m0 0l3-3m-3 3v-7.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="transition duration-300 ease-in-out text-gray-700 dark:text-gray-300 dark:opacity-80 ml-4 font-bold uppercase">download</span>
</span>
</button>
{% else %}
<button role="tab" value="download" data-{{ current_endpoint }}-action-dropdown-btn="{{ child['name'] }}" class="duration-300 border-gray-300 hover:brightness-90 bg-white 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 w-full border-b border-l border-r hover:bg-gray-100">
<span class="flex justify-start items-center">
<svg class="h-6 w-6 stroke-sky-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75l3 3m0 0l3-3m-3 3v-7.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="transition duration-300 ease-in-out text-gray-700 dark:text-gray-300 dark:opacity-80 ml-4 font-bold uppercase">download</span>
</span>
</button>
{% endif %}
{% endif %}
<!-- end download button -->
<!-- delete button -->
{% if child['can_delete'] == True %}
<button role="tab" value="delete" data-{{ current_endpoint }}-action-dropdown-btn="{{ child['name'] }}" class="bg-white duration-300 border-gray-300 hover:brightness-90 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 w-full border-b border-l border-r hover:bg-gray-100">
<span class="flex justify-start items-center">
<svg class="h-5.5 w-5.5 stroke-red-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
</svg>
<span class="transition duration-300 ease-in-out text-gray-700 dark:text-gray-300 dark:opacity-80 ml-4 font-bold uppercase">delete</span>
</span>
</button>
{% endif %}
<!-- end delete button -->
</div>
<!-- end dropdown actions -->
</div>
<!-- end folder-->
{% endfor %}
</div>
{% endfor %}
<!-- end folders-->
</div>
{% if current_endpoint == "configs" %}
<!-- actions -->
<ul data-{{ current_endpoint }}-add-container class="col-span-12 md:col-span-4 mt-4 mb-6 md:mt-0 md:mb-3 w-full flex justify-center items-center">
<li class="rounded transition flex-col items-center mx-2 mt-4 relative cursor-pointer hover:bg-gray-100 dark:hover:bg-slate-800">
<button disabled class="file-manager-actions-item-btn"
data-{{ current_endpoint }}-add-file>
<svg class="-translate-x-1 relative dark:brightness-125 h-8 w-8 lg:h-9 lg:w-9 fill-primary stroke-gray-100 dark:stroke-gray-600"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m3.75 9v6m3-3H9m1.5-12H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
</svg>
<span class="dark:text-gray-500 pt-1 mb-0 font-sans font-semibold leading-normal uppercase text-sm lg:text-md">
ADD FILE
</span>
</button>
</li>
</ul>
<!-- end actions -->
{% endif %}
<!-- end folders-->
</div>
{% if current_endpoint == "configs" %}
<!-- actions -->
<ul data-{{ current_endpoint }}-add-container class="col-span-12 md:col-span-4 mt-4 mb-6 md:mt-0 md:mb-3 w-full flex justify-center items-center">
<li class="rounded transition flex-col items-center mx-2 mt-4 relative cursor-pointer hover:bg-gray-100 dark:hover:bg-slate-800">
<button disabled class="file-manager-actions-item-btn" data-{{ current_endpoint }}-add-file>
<svg class="-translate-x-1 relative dark:brightness-125 h-8 w-8 lg:h-9 lg:w-9 fill-primary stroke-gray-100 dark:stroke-gray-600"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m3.75 9v6m3-3H9m1.5-12H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
</svg>
<span class="dark:text-gray-500 pt-1 mb-0 font-sans font-semibold leading-normal uppercase text-sm lg:text-md">
ADD FILE
</span>
</button>
</li>
</ul>
<!-- end actions -->
{% endif %}
</div>
<!-- end main container -->
<!-- modal -->
<div data-{{ current_endpoint }}-modal class="hidden w-full h-screen fixed bg-gray-600/50 z-[1001] top-0 left-0 justify-center items-center">
<div class="mx-1 px-4 py-3 w-full max-w-180 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">
<p data-{{ current_endpoint }}-modal-title class="dark:text-white mb-0 font-sans font-semibold leading-normal uppercase text-sm">
TITLE
</p>
<div class="mx-1 px-4 py-3 w-full max-w-180 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">
<p data-{{ current_endpoint }}-modal-title class="dark:text-white mb-0 font-sans font-semibold leading-normal uppercase text-sm">
TITLE
</p>
</div>
<form data-{{ current_endpoint }}-modal-form class="w-full" id="form-services" method="POST">
<div class="mb-2 flex flex-wrap justify-start items-center" data-{{ current_endpoint }}-modal-path>
<p data-{{ current_endpoint }}-modal-path-prefix class="mb-0 dark:text-white/80 text-gray-700/80 text-sm">
</p>
<input type="text"
name="name"
id="name"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 sm:ml-1 max-w-40 focus:valid:border-green-500 focus:file: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 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"
placeholder="path"
required />
<p data-{{ current_endpoint }}-modal-path-suffix class="ml-1 mb-0 dark:text-white/80 text-gray-700/80 text-sm">
suffix
</p>
</div>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" id="operation" value="" name="operation" />
<input type="hidden" id="path" value="" name="path" />
<input type="hidden" id="old_name" value="" name="old_name" />
<input type="hidden" id="_type" value="file" name="type" />
<textarea class="hidden" id="content" name="content"></textarea>
<!-- editor-->
<div data-{{ current_endpoint }}-modal-editor id="editor" class="text-base w-full h-48 overflow-hidden overflow-y-auto my-2 border border-gray-300 dark:border-slate-800">
</div>
<!-- editor-->
<div class="mt-4 w-full justify-end flex">
<button type="button" data-{{ current_endpoint }}-modal-close class="close-btn text-xs mr-2">
Close
</button>
<button data-{{ current_endpoint }}-modal-submit type="submit" class="valid-btn text-xs">
Save
</button>
</div>
</form>
</div>
<form data-{{ current_endpoint }}-modal-form class="w-full" id="form-services" method="POST">
<div class="mb-2 flex flex-wrap justify-start items-center" data-{{ current_endpoint }}-modal-path>
<p data-{{ current_endpoint }}-modal-path-prefix class="mb-0 dark:text-white/80 text-gray-700/80 text-sm">
</p>
<input type="text"
name="name"
id="name"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 sm:ml-1 max-w-40 focus:valid:border-green-500 focus:file: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 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"
placeholder="path"
required />
<p data-{{ current_endpoint }}-modal-path-suffix class="ml-1 mb-0 dark:text-white/80 text-gray-700/80 text-sm">
suffix
</p>
</div>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" id="operation" value="" name="operation" />
<input type="hidden" id="path" value="" name="path" />
<input type="hidden" id="old_name" value="" name="old_name" />
<input type="hidden" id="_type" value="file" name="type" />
<textarea class="hidden" id="content" name="content"></textarea>
<!-- editor-->
<div data-{{ current_endpoint }}-modal-editor id="editor" class="text-base w-full h-48 overflow-hidden overflow-y-auto my-2 border border-gray-300 dark:border-slate-800">
</div>
<!-- editor-->
<div class="mt-4 w-full justify-end flex">
<button type="button" data-{{ current_endpoint }}-modal-close class="close-btn text-xs mr-2">
Close
</button>
<button data-{{ current_endpoint }}-modal-submit type="submit" class="valid-btn text-xs">
Save
</button>
</div>
</form>
</div>
</div>
<!-- end modal -->

View file

@ -1,24 +1,27 @@
<!-- float button-->
{% with messages = get_flashed_messages(with_categories=true) %}
<div data-flash-group
class="transition-all group group-hover hover:brightness-75 dark:hover:brightness-105 fixed top-[4.5rem] right-20 sm:right-24 xl:right-24 z-990">
<button aria-controls="sidebar-flash"
aria-expanded="false"
aria-label="Open flash action sidebar"
data-flash-sidebar-open
class="transition scale-90 sm:scale-100 dark:brightness-95 p-3 text-xl bg-white shadow-sm cursor-pointer rounded-circle text-slate-700">
<svg class="fill-yellow-500 -translate-y-0.4 h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512">
<path d="M224 0c-17.7 0-32 14.3-32 32V51.2C119 66 64 130.6 64 208v18.8c0 47-17.3 92.4-48.5 127.6l-7.4 8.3c-8.4 9.4-10.4 22.9-5.3 34.4S19.4 416 32 416H416c12.6 0 24-7.4 29.2-18.9s3.1-25-5.3-34.4l-7.4-8.3C401.3 319.2 384 273.9 384 226.8V208c0-77.4-55-142-128-156.8V32c0-17.7-14.3-32-32-32zm45.3 493.3c12-12 18.7-28.3 18.7-45.3H224 160c0 17 6.7 33.3 18.7 45.3s28.3 18.7 45.3 18.7s33.3-6.7 45.3-18.7z" />
</svg>
</button>
<div class="dark:brightness-95 px-2 translate-x-2 bottom-0 right-0 absolute rounded-full bg-white">
<p data-flash-count class="mb-0 text-sm text-bold text-red-500">
{% if messages %}
{{ messages|length }}{% else %} 0 {% endif %}
</p>
</div>
<div data-flash-group
class="transition-all group group-hover hover:brightness-75 dark:hover:brightness-105 fixed top-[4.5rem] right-20 sm:right-24 xl:right-24 z-990">
<button aria-controls="sidebar-flash"
aria-expanded="false"
aria-label="Open flash action sidebar"
data-flash-sidebar-open
class="transition scale-90 sm:scale-100 dark:brightness-95 p-3 text-xl bg-white shadow-sm cursor-pointer rounded-circle text-slate-700">
<svg class="fill-yellow-500 -translate-y-0.4 h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512">
<path d="M224 0c-17.7 0-32 14.3-32 32V51.2C119 66 64 130.6 64 208v18.8c0 47-17.3 92.4-48.5 127.6l-7.4 8.3c-8.4 9.4-10.4 22.9-5.3 34.4S19.4 416 32 416H416c12.6 0 24-7.4 29.2-18.9s3.1-25-5.3-34.4l-7.4-8.3C401.3 319.2 384 273.9 384 226.8V208c0-77.4-55-142-128-156.8V32c0-17.7-14.3-32-32-32zm45.3 493.3c12-12 18.7-28.3 18.7-45.3H224 160c0 17 6.7 33.3 18.7 45.3s28.3 18.7 45.3 18.7s33.3-6.7 45.3-18.7z" />
</svg>
</button>
<div class="dark:brightness-95 px-2 translate-x-2 bottom-0 right-0 absolute rounded-full bg-white">
<p data-flash-count class="mb-0 text-sm text-bold text-red-500">
{% if messages %}
{{ messages|length }}
{% else %}
0
{% endif %}
</p>
</div>
</div>
<!-- end float button-->
<!-- right sidebar -->
@ -26,68 +29,68 @@
data-flash-sidebar
aria-hidden="true"
class="translate-x-90 -right-0 transition z-sticky dark:bg-slate-850 dark:brightness-110 shadow-3xl max-w-full w-90 ease fixed top-0 left-auto flex h-full min-w-0 flex-col break-words rounded-none border-0 bg-white bg-clip-border px-0.5">
<!-- close btn-->
<button aria-controls="sidebar-flash"
aria-expanded="false"
aria-label="close flash sidebar"
data-flash-sidebar-close>
<svg class="fill-gray-600 dark:fill-gray-300 dark:opacity-80 absolute h-8 w-8 top-4 right-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" />
</svg>
</button>
<!-- close btn-->
<!-- header -->
<div class="px-6 pt-4 pb-0 mb-0 border-b-0 rounded-t-2xl">
<div class="float-left">
<h5 class="mt-4 mb-1 dark:text-white font-bold">MESSAGES</h5>
<p class="dark:text-white dark:opacity-80 mb-0">Feedback actions</p>
</div>
<!-- close button -->
<div class="float-right mt-6">
<button data-flash-sidebar-close
class="inline-block p-0 mb-4 text-sm font-bold leading-normal text-center uppercase align-middle transition-all ease-in bg-transparent border-0 rounded-lg shadow-none cursor-pointer hover:-translate-y-px tracking-tight-rem bg-150 bg-x-25 active:opacity-85 dark:text-white text-slate-700">
<i class="fa fa-close"></i>
</button>
</div>
<!-- end close button -->
</div>
<!-- end header -->
<!-- messages-->
<div class="flex flex-col justify-start items-center h-full m-2 overflow-y-auto">
{% if messages %}
<!-- flash message-->
{% for category, message in messages %}
<div role="alert"
aria-description="flash feedback message"
data-flash-message
class="{% if category == 'error' %} bg-red-500 {% else %} bg-green-500 {% endif %} my-2 border relative p-4 w-11/12 min-h-20 rounded-lg hover:scale-102 transition shadow-md break-words dark:brightness-90">
<div class="flex justify-between align-top items-start">
{% if category == 'error' %}
<h5 class="text-lg mb-0 text-white">Error</h5>
{% else %}
<h5 class="text-lg mb-0 text-white">Success</h5>
{% endif %}
<button aria-label="close flash message"
data-close-flash-message
class="absolute right-8 top-2">
<svg class="cursor-pointer fill-white dark:opacity-80 absolute h-5 w-5"
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>
<p class="text-white mt-2 mb-0 text-sm">{{ message|safe }}</p>
<!-- close btn-->
<button aria-controls="sidebar-flash"
aria-expanded="false"
aria-label="close flash sidebar"
data-flash-sidebar-close>
<svg class="fill-gray-600 dark:fill-gray-300 dark:opacity-80 absolute h-8 w-8 top-4 right-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" />
</svg>
</button>
<!-- close btn-->
<!-- header -->
<div class="px-6 pt-4 pb-0 mb-0 border-b-0 rounded-t-2xl">
<div class="float-left">
<h5 class="mt-4 mb-1 dark:text-white font-bold">MESSAGES</h5>
<p class="dark:text-white dark:opacity-80 mb-0">Feedback actions</p>
</div>
{% endfor %}
<!-- end flash message-->
{% endif %}
</div>
<!-- end message-->
<!-- end messages -->
<!-- close button -->
<div class="float-right mt-6">
<button data-flash-sidebar-close
class="inline-block p-0 mb-4 text-sm font-bold leading-normal text-center uppercase align-middle transition-all ease-in bg-transparent border-0 rounded-lg shadow-none cursor-pointer hover:-translate-y-px tracking-tight-rem bg-150 bg-x-25 active:opacity-85 dark:text-white text-slate-700">
<i class="fa fa-close"></i>
</button>
</div>
<!-- end close button -->
</div>
<!-- end header -->
<!-- messages-->
<div class="flex flex-col justify-start items-center h-full m-2 overflow-y-auto">
{% if messages %}
<!-- flash message-->
{% for category, message in messages %}
<div role="alert"
aria-description="flash feedback message"
data-flash-message
class="{% if category == 'error' %} bg-red-500 {% else %} bg-green-500 {% endif %} my-2 border relative p-4 w-11/12 min-h-20 rounded-lg hover:scale-102 transition shadow-md break-words dark:brightness-90">
<div class="flex justify-between align-top items-start">
{% if category == 'error' %}
<h5 class="text-lg mb-0 text-white">Error</h5>
{% else %}
<h5 class="text-lg mb-0 text-white">Success</h5>
{% endif %}
<button aria-label="close flash message"
data-close-flash-message
class="absolute right-8 top-2">
<svg class="cursor-pointer fill-white dark:opacity-80 absolute h-5 w-5"
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>
<p class="text-white mt-2 mb-0 text-sm">{{ message|safe }}</p>
</div>
{% endfor %}
<!-- end flash message-->
{% endif %}
</div>
<!-- end message-->
<!-- end messages -->
</aside>
{% endwith %}
<!-- end right sidebar -->
{% endwith %}
<!-- end right sidebar -->

View file

@ -1,44 +1,44 @@
<footer class="relative w-full mt-16 lg:mt-4">
<div class="w-full px-6 mx-auto">
<div class="flex flex-col items-center lg:flex-row justify-center lg:justify-between">
<div class="order-2 lg:order-1 px-0 mt-3 lg:mt-0 mb-0.5">
<div class="transition duration-300 text-xs tracking-wide leading-normal text-center text-white opacity-100 dark:text-white lg:text-left">
Copyright ©
<script nonce="{{ script_nonce }}">document.write(new Date().getFullYear());</script>
Bunkerity
<div class="w-full px-6 mx-auto">
<div class="flex flex-col items-center lg:flex-row justify-center lg:justify-between">
<div class="order-2 lg:order-1 px-0 mt-3 lg:mt-0 mb-0.5">
<div class="transition duration-300 text-xs tracking-wide leading-normal text-center text-white opacity-100 dark:text-white lg:text-left">
Copyright ©
<script nonce="{{ script_nonce }}">document.write(new Date().getFullYear());</script>
Bunkerity
</div>
</div>
<ul class="order-1 lg:order-2 flex flex-wrap flex-col sm:flex-row items-center justify-center pl-0 mb-0 list-none lg:justify-end">
{% set nav_items = [
{
"name": "BunkerWeb",
"link": "https://www.bunkerweb.io/?utm_campaign=self&utm_source=ui"
},
{
"name": "Docs",
"link": "https://docs.bunkerweb.io/?utm_campaign=self&utm_source=ui"
},
{
"name": "Privacy",
"link": "https://www.bunkerweb.io/privacy-policy"
},
{
"name": "Blog",
"link": "https://www.bunkerity.com/fr/blog/?utm_campaign=self&utm_source=ui"
},
{
"name": "License",
"link": "https://github.com/bunkerity/bunkerweb/blob/master/LICENSE"
}
] %}
{% for item in nav_items %}
<li class="nav-item">
<a href="{{ item['link'] }}"
class="hover:italic hover:brightness-90 block sm:px-4 pt-1 pb-0 lg:pb-1 text-xs tracking-wide font-normal transition duration-300 ease-in-out text-white dark:text-white"
target="_blank">{{ item['name'] }}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
<ul class="order-1 lg:order-2 flex flex-wrap flex-col sm:flex-row items-center justify-center pl-0 mb-0 list-none lg:justify-end">
{% set nav_items = [
{
"name": "BunkerWeb",
"link": "https://www.bunkerweb.io/?utm_campaign=self&utm_source=ui"
},
{
"name": "Docs",
"link": "https://docs.bunkerweb.io/?utm_campaign=self&utm_source=ui"
},
{
"name": "Privacy",
"link": "https://www.bunkerweb.io/privacy-policy"
},
{
"name": "Blog",
"link": "https://www.bunkerity.com/fr/blog/?utm_campaign=self&utm_source=ui"
},
{
"name": "License",
"link": "https://github.com/bunkerity/bunkerweb/blob/master/LICENSE"
}
] %}
{% for item in nav_items %}
<li class="nav-item">
<a href="{{ item['link'] }}"
class="hover:italic hover:brightness-90 block sm:px-4 pt-1 pb-0 lg:pb-1 text-xs tracking-wide font-normal transition duration-300 ease-in-out text-white dark:text-white"
target="_blank">{{ item['name'] }}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</footer>

View file

@ -1,57 +1,57 @@
{% extends "base.html" %}
{% block content %}
<div data-service-content="settings"
class="col-span-12 gap-y-4 grid grid-cols-12">
<div class="p-4 col-span-12 relative flex flex-col min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div data-{{ current_endpoint }}-tabs-header class="flex flex-col xs:flex-row xs:justify-start xs:items-center gap-x-4 gap-y-2 my-3">
<h5 class="transition duration-300 ease-in-out 0 ml-2 font-bold text-md uppercase dark:text-white/90 mb-0">CONFIGS</h5>
<!-- search inpt-->
<div class="flex relative col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3">
<label class="sr-only" for="settings-filter">filter settings</label>
<input type="text"
id="settings-filter"
name="settings-filter"
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="key words"
pattern="(.*?)"
required />
<div data-service-content="settings"
class="col-span-12 gap-y-4 grid grid-cols-12">
<div class="p-4 col-span-12 relative flex flex-col min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div data-{{ current_endpoint }}-tabs-header class="flex flex-col xs:flex-row xs:justify-start xs:items-center gap-x-4 gap-y-2 my-3">
<h5 class="transition duration-300 ease-in-out 0 ml-2 font-bold text-md uppercase dark:text-white/90 mb-0">CONFIGS</h5>
<!-- search inpt-->
<div class="flex relative col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3">
<label class="sr-only" for="settings-filter">filter settings</label>
<input type="text"
id="settings-filter"
name="settings-filter"
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="key words"
pattern="(.*?)"
required />
</div>
<!-- end search inpt-->
</div>
<!-- tabs -->
{% include "settings_tabs.html" %}
<!-- end tabs-->
</div>
<!-- form global conf -->
<form data-global-config-form
id="form-edit-global-configs"
method="POST"
class="flex flex-col justify-between overflow-hidden overflow-y-auto max-h-135 md:max-h-160 dark:brightness-110 col-span-12 break-words bg-white shadow-xl p-4 dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<!-- plugin item -->
{% include "settings_plugins.html" %}
<!-- end plugin item -->
<!-- submit -->
<div class="flex w-full justify-center mt-8 mb-2">
<button type="submit" class="valid-btn">SAVE</button>
</div>
<!-- end submit -->
</form>
<!--end form global conf -->
<div data-global-config-nomatch
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No settings match</h5>
</div>
</div>
<!-- end search inpt-->
</div>
<!-- tabs -->
{% include "settings_tabs.html" %}
<!-- end tabs-->
</div>
<!-- form global conf -->
<form data-global-config-form
id="form-edit-global-configs"
method="POST"
class="flex flex-col justify-between overflow-hidden overflow-y-auto max-h-135 md:max-h-160 dark:brightness-110 col-span-12 break-words bg-white shadow-xl p-4 dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<!-- plugin item -->
{% include "settings_plugins.html" %}
<!-- end plugin item -->
<!-- submit -->
<div class="flex w-full justify-center mt-8 mb-2">
<button type="submit" class="valid-btn">SAVE</button>
</div>
<!-- end submit -->
</form>
<!--end form global conf -->
<div data-global-config-nomatch
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No settings match</h5>
</div>
</div>
</div>
</div>
{% endblock content %}

View file

@ -1,51 +1,51 @@
{% set current_endpoint = current_endpoint or url_for(request.endpoint)[1:].split("/")[-1].strip() %}
<head>
<meta charset="utf-8" />
<base href="{{ url_for("index") }}">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1" />
<meta name="description" content="bunkerweb user interface" />
<meta name="author" content="bunkerity" />
<title>BunkerWeb UI</title>
<link rel="icon" type="image/x-icon" href="images/favicon.ico" />
<!-- tailwind style -->
<link rel="stylesheet" type="text/css" href="./css/plugins.css" />
<link rel="stylesheet" type="text/css" href="./css/dashboard.css" />
<script type="module" src="./js/global.js" nonce="{{ script_nonce }}"></script>
<script src="./js/plugins/setup.js" nonce="{{ script_nonce }}"></script>
<script async
src="./js/utils/purify/purify.min.js"
nonce="{{ script_nonce }}"></script>
<script src="./js/editor/ace.js" nonce="{{ script_nonce }}"></script>
{% if current_endpoint == "global_config" %}
<script type="module" src="./js/global_config.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "configs" %}
<script type="module" src="./js/configs.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "services" %}
<script type="module" src="./js/services.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "plugins" %}
<script type="module" src="./js/plugins.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "cache" %}
<script type="module" src="./js/cache.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "logs" %}
<link rel="stylesheet" type="text/css" href="./css/flatpickr.css" />
<link rel="stylesheet" type="text/css" href="./css/flatpickr.dark.css" />
<script defer src="./js/utils/flatpickr.js" nonce="{{ script_nonce }}"></script>
<script defer src="./js/logs.js" nonce="{{ script_nonce }}"></script>
<link rel="stylesheet"
type="text/css"
href="./css/datepicker-foundation.css" />
{% elif current_endpoint == "jobs" %}
<script type="module" src="./js/jobs.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "account" %}
<script type="module" src="./js/account.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "reports" %}
<script type="module" src="./js/reports.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "bans" %}
<link rel="stylesheet" type="text/css" href="./css/flatpickr.css" />
<link rel="stylesheet" type="text/css" href="./css/flatpickr.dark.css" />
<script defer src="./js/utils/flatpickr.js" nonce="{{ script_nonce }}"></script>
<script type="module" src="./js/bans.js" nonce="{{ script_nonce }}"></script>
{% endif %}
<meta charset="utf-8" />
<base href="{{ url_for("index") }}">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1" />
<meta name="description" content="bunkerweb user interface" />
<meta name="author" content="bunkerity" />
<title>BunkerWeb UI</title>
<link rel="icon" type="image/x-icon" href="images/favicon.ico" />
<!-- tailwind style -->
<link rel="stylesheet" type="text/css" href="./css/plugins.css" />
<link rel="stylesheet" type="text/css" href="./css/dashboard.css" />
<script type="module" src="./js/global.js" nonce="{{ script_nonce }}"></script>
<script src="./js/plugins/setup.js" nonce="{{ script_nonce }}"></script>
<script async
src="./js/utils/purify/purify.min.js"
nonce="{{ script_nonce }}"></script>
<script src="./js/editor/ace.js" nonce="{{ script_nonce }}"></script>
{% if current_endpoint == "global_config" %}
<script type="module" src="./js/global_config.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "configs" %}
<script type="module" src="./js/configs.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "services" %}
<script type="module" src="./js/services.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "plugins" %}
<script type="module" src="./js/plugins.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "cache" %}
<script type="module" src="./js/cache.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "logs" %}
<link rel="stylesheet" type="text/css" href="./css/flatpickr.css" />
<link rel="stylesheet" type="text/css" href="./css/flatpickr.dark.css" />
<script defer src="./js/utils/flatpickr.js" nonce="{{ script_nonce }}"></script>
<script defer src="./js/logs.js" nonce="{{ script_nonce }}"></script>
<link rel="stylesheet"
type="text/css"
href="./css/datepicker-foundation.css" />
{% elif current_endpoint == "jobs" %}
<script type="module" src="./js/jobs.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "account" %}
<script type="module" src="./js/account.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "reports" %}
<script type="module" src="./js/reports.js" nonce="{{ script_nonce }}"></script>
{% elif current_endpoint == "bans" %}
<link rel="stylesheet" type="text/css" href="./css/flatpickr.css" />
<link rel="stylesheet" type="text/css" href="./css/flatpickr.dark.css" />
<script defer src="./js/utils/flatpickr.js" nonce="{{ script_nonce }}"></script>
<script type="module" src="./js/bans.js" nonce="{{ script_nonce }}"></script>
{% endif %}
</head>

View file

@ -1,18 +1,18 @@
{% set current_endpoint = current_endpoint or url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', ' ').replace('-', ' ') %}
<!-- header -->
<header class="relative flex flex-wrap items-center justify-between px-0 pb-2 sm:mx-6 transition-all ease-in shadow-none duration-250 rounded-2xl lg:flex-nowrap lg:justify-start">
<div class="flex items-center justify-between w-full px-4 py-1 mx-auto flex-wrap-inherit">
<nav>
<!-- breadcrumb -->
<h6 class="mb-0 text-lg font-bold text-white capitalize">{{ current_endpoint }}</h6>
<ul class="flex flex-wrap pt-1 mr-12 bg-transparent rounded-lg sm:mr-16">
<li class="text-sm leading-normal">
<a class="text-white opacity-50 dark:opacity-75" href="javascript:;">BunkerWeb</a>
</li>
<li class="hidden sm:inline text-sm pl-0 xs:pl-2 capitalize leading-normal text-white before:float-left before:pr-2 before:text-white before:content-['/']"
aria-current="page">{{ current_endpoint }}</li>
</ul>
</nav>
</div>
<div class="flex items-center justify-between w-full px-4 py-1 mx-auto flex-wrap-inherit">
<nav>
<!-- breadcrumb -->
<h6 class="mb-0 text-lg font-bold text-white capitalize">{{ current_endpoint }}</h6>
<ul class="flex flex-wrap pt-1 mr-12 bg-transparent rounded-lg sm:mr-16">
<li class="text-sm leading-normal">
<a class="text-white opacity-50 dark:opacity-75" href="javascript:;">BunkerWeb</a>
</li>
<li class="hidden sm:inline text-sm pl-0 xs:pl-2 capitalize leading-normal text-white before:float-left before:pr-2 before:text-white before:content-['/']"
aria-current="page">{{ current_endpoint }}</li>
</ul>
</nav>
</div>
</header>
<!-- end header -->

View file

@ -1,92 +1,86 @@
{% extends "base.html" %}
{% block content %}
{% set cards = [
{'name' : 'Version', 'title' : 'PRO' if is_pro_version else 'FREE', 'link' : '#' if is_pro_version else 'https://github.com/bunkerity/bunkerweb', 'subtitle' : 'all features available' if is_pro_version else 'upgrade to pro', 'subtitle_color' : 'success' if is_pro_version else 'warning' },
{'name' : 'Version number', 'title' : version, 'link' : 'https://github.com/bunkerity/bunkerweb', 'subtitle' : "couldn'd fint remote" if not remote_version else "latest version" if remote_version and check_version else 'Update to ' + remote_version , 'subtitle_color' : "error" if not remote_version else "success" if remote_version and check_version else 'warning'},
{'name' : 'Instances', 'title' : instances_number, 'link' : 'loading?next=' + url_for('instances') , 'subtitle' : instance_health_count|string + ' / ' + instances_number|string + ' is working' , 'subtitle_color' : "info",},
{'name' : 'Services', 'title' : services_number, 'link' : 'loading?next=' + url_for('services') , 'subtitle' : services_ui_count|string + ' ui, ' + services_scheduler_count|string + ' scheduler, ' + services_autoconf_count|string + ' autoconf ' , 'subtitle_color' : "info"},
{'name' : 'Plugins', 'title' : config["CONFIG"].get_plugins()|length, 'link' : 'loading?next=' + url_for('plugins') , 'subtitle' : plugins_errors|string + ' errors' if plugins_errors > 0 else 'no error' , 'subtitle_color' : "error" if plugins_errors > 0 else 'success'}
] %}
<div class="col-span-12 grid grid-cols-12 justify-start items-start gap-4">
{% for card in cards %}
<!-- stats card -->
<a href="{{ card['link'] }}"
class="home-card"
target="_blank">
<!-- text -->
<div>
<p class="home-card-name">
{{ card['name'] }}
</p>
<!-- version of user -->
<h5 class="home-card-title">{{ card['title'] }}</h5>
<p class="home-card-subtitle {{card['subtitle_color']}}">
{{ card['subtitle'] }}
</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img"
aria-label="version"
class="home-card-svg-container {{card['name'].replace(' ', '-')|lower}}">
{% if card['name'] == "Version" and is_pro_version %}
<svg class="leading-none text-lg relative scale-[0.6]"
viewBox="0 0 48 46"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path class="fill-white" d="M43.218 28.2327L43.6765 23.971C43.921 21.6973 44.0825 20.1957 43.9557 19.2497L44 19.25C46.071 19.25 47.75 17.5711 47.75 15.5C47.75 13.4289 46.071 11.75 44 11.75C41.929 11.75 40.25 13.4289 40.25 15.5C40.25 16.4366 40.5935 17.2931 41.1613 17.9503C40.346 18.4535 39.2805 19.515 37.6763 21.1128C36.4405 22.3438 35.8225 22.9593 35.1333 23.0548C34.7513 23.1075 34.3622 23.0532 34.0095 22.898C33.373 22.6175 32.9485 21.8567 32.0997 20.335L27.6262 12.3135C27.1025 11.3747 26.6642 10.5889 26.2692 9.95662C27.89 9.12967 29 7.44445 29 5.5C29 2.73857 26.7615 0.5 24 0.5C21.2385 0.5 19 2.73857 19 5.5C19 7.44445 20.11 9.12967 21.7308 9.95662C21.3358 10.589 20.8975 11.3746 20.3738 12.3135L15.9002 20.335C15.0514 21.8567 14.627 22.6175 13.9905 22.898C13.6379 23.0532 13.2487 23.1075 12.8668 23.0548C12.1774 22.9593 11.5595 22.3438 10.3238 21.1128C8.71968 19.515 7.6539 18.4535 6.83882 17.9503C7.4066 17.2931 7.75 16.4366 7.75 15.5C7.75 13.4289 6.07107 11.75 4 11.75C1.92893 11.75 0.25 13.4289 0.25 15.5C0.25 17.5711 1.92893 19.25 4 19.25L4.04428 19.2497C3.91755 20.1957 4.07905 21.6973 4.32362 23.971L4.782 28.2327C5.03645 30.5982 5.24802 32.849 5.50717 34.875H42.4928C42.752 32.849 42.9635 30.5982 43.218 28.2327Z" fill="#1C274C" />
<path class="fill-white" d="M21.2803 45.5H26.7198C33.8098 45.5 37.3545 45.5 39.7198 43.383C40.7523 42.4588 41.4057 40.793 41.8775 38.625H6.1224C6.59413 40.793 7.24783 42.4588 8.2802 43.383C10.6454 45.5 14.1903 45.5 21.2803 45.5Z" fill="#1C274C" />
</svg>
{% endif %}
{% if card['name'] == "Version" and not is_pro_version %}
<svg class="leading-none fill-white text-yellow-500 text-lg relative scale-[0.6]"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25a3 3 0 0 1 3 3m3 0a6 6 0 0 1-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1 1 21.75 8.25Z" />
</svg>
{% endif %}
{% if card['name'] == "Version number" %}
<svg class="translate-x-0.5 -translate-y-0.5 scale-50 leading-none text-lg relative fill-white"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512">
<path d="M80 104c13.3 0 24-10.7 24-24s-10.7-24-24-24S56 66.7 56 80s10.7 24 24 24zm80-24c0 32.8-19.7 61-48 73.3v87.8c18.8-10.9 40.7-17.1 64-17.1h96c35.3 0 64-28.7 64-64v-6.7C307.7 141 288 112.8 288 80c0-44.2 35.8-80 80-80s80 35.8 80 80c0 32.8-19.7 61-48 73.3V160c0 70.7-57.3 128-128 128H176c-35.3 0-64 28.7-64 64v6.7c28.3 12.3 48 40.5 48 73.3c0 44.2-35.8 80-80 80s-80-35.8-80-80c0-32.8 19.7-61 48-73.3V352 153.3C19.7 141 0 112.8 0 80C0 35.8 35.8 0 80 0s80 35.8 80 80zm232 0c0-13.3-10.7-24-24-24s-24 10.7-24 24s10.7 24 24 24s24-10.7 24-24zM80 456c13.3 0 24-10.7 24-24s-10.7-24-24-24s-24 10.7-24 24s10.7 24 24 24z" />
</svg>
{% endif %}
{% if card['name'] == "Instances" %}
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="scale-[0.6] leading-none text-lg relative stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9">
</path>
</svg>
{% endif %}
{% if card['name'] == "Services" %}
<svg class="scale-50 leading-none text-lg relative fill-white"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.3c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64H348.7c2.2 20.4 3.3 41.8 3.3 64zm28.8-64H503.9c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64zm112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6c78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7c10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5c11.6 26 21 58.2 27 94.7zm-209 0H18.6C48.6 85.9 112.2 29.1 190.6 8.4C165.1 42.6 145.3 96.1 135.3 160zM8.1 192H131.2c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64zM194.7 446.6c-11.6-26-20.9-58.2-27-94.6H344.3c-6.1 36.4-15.5 68.6-27 94.6c-10.5 23.6-22.2 40.7-33.5 51.5C272.6 508.8 263.3 512 256 512s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6C112.2 482.9 48.6 426.1 18.6 352H135.3zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6c25.5-34.2 45.2-87.7 55.3-151.6H493.4z" />
</svg>
{% endif %}
{% if card['name'] == "Plugins" %}
<svg class="scale-75 leading-none text-lg relative fill-white text-yellow-400"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.25 6.087c0-.355.186-.676.401-.959.221-.29.349-.634.349-1.003 0-1.036-1.007-1.875-2.25-1.875s-2.25.84-2.25 1.875c0 .369.128.713.349 1.003.215.283.401.604.401.959v0a.64.64 0 01-.657.643 48.39 48.39 0 01-4.163-.3c.186 1.613.293 3.25.315 4.907a.656.656 0 01-.658.663v0c-.355 0-.676-.186-.959-.401a1.647 1.647 0 00-1.003-.349c-1.036 0-1.875 1.007-1.875 2.25s.84 2.25 1.875 2.25c.369 0 .713-.128 1.003-.349.283-.215.604-.401.959-.401v0c.31 0 .555.26.532.57a48.039 48.039 0 01-.642 5.056c1.518.19 3.058.309 4.616.354a.64.64 0 00.657-.643v0c0-.355-.186-.676-.401-.959a1.647 1.647 0 01-.349-1.003c0-1.035 1.008-1.875 2.25-1.875 1.243 0 2.25.84 2.25 1.875 0 .369-.128.713-.349 1.003-.215.283-.4.604-.4.959v0c0 .333.277.599.61.58a48.1 48.1 0 005.427-.63 48.05 48.05 0 00.582-4.717.532.532 0 00-.533-.57v0c-.355 0-.676.186-.959.401-.29.221-.634.349-1.003.349-1.035 0-1.875-1.007-1.875-2.25s.84-2.25 1.875-2.25c.37 0 .713.128 1.003.349.283.215.604.401.96.401v0a.656.656 0 00.658-.663 48.422 48.422 0 00-.37-5.36c-1.886.342-3.81.574-5.766.689a.578.578 0 01-.61-.58v0z" />
</svg>
{% endif %}
</div>
<!-- end icon -->
</a>
<!-- end stats card -->
{% endfor %}
</div>
{% set cards = [
{'name' : 'Version', 'title' : 'PRO' if is_pro_version else 'FREE', 'link' : '#' if is_pro_version else 'https://github.com/bunkerity/bunkerweb', 'subtitle' : 'all features available' if is_pro_version else 'upgrade to pro', 'subtitle_color' : 'success' if is_pro_version else 'warning' },
{'name' : 'Version number', 'title' : version, 'link' : 'https://github.com/bunkerity/bunkerweb', 'subtitle' : "couldn'd fint remote" if not remote_version else "latest version" if remote_version and check_version else 'Update to ' + remote_version , 'subtitle_color' : "error" if not remote_version else "success" if remote_version and check_version else 'warning'},
{'name' : 'Instances', 'title' : instances_number, 'link' : 'loading?next=' + url_for('instances') , 'subtitle' : instance_health_count|string + ' / ' + instances_number|string + ' is working' , 'subtitle_color' : "info",},
{'name' : 'Services', 'title' : services_number, 'link' : 'loading?next=' + url_for('services') , 'subtitle' : services_ui_count|string + ' ui, ' + services_scheduler_count|string + ' scheduler, ' + services_autoconf_count|string + ' autoconf ' , 'subtitle_color' : "info"},
{'name' : 'Plugins', 'title' : config["CONFIG"].get_plugins()|length, 'link' : 'loading?next=' + url_for('plugins') , 'subtitle' : plugins_errors|string + ' errors' if plugins_errors > 0 else 'no error' , 'subtitle_color' : "error" if plugins_errors > 0 else 'success'}
] %}
<div class="col-span-12 grid grid-cols-12 justify-start items-start gap-4">
{% for card in cards %}
<!-- stats card -->
<a href="{{ card['link'] }}" class="home-card" target="_blank">
<!-- text -->
<div>
<p class="home-card-name">{{ card['name'] }}</p>
<!-- version of user -->
<h5 class="home-card-title">{{ card['title'] }}</h5>
<p class="home-card-subtitle {{ card['subtitle_color'] }}">{{ card['subtitle'] }}</p>
</div>
<!-- end text -->
<!-- icon -->
<div role="img"
aria-label="version"
class="home-card-svg-container {{ card['name'].replace(' ', '-') |lower }}">
{% if card['name'] == "Version" and is_pro_version %}
<svg class="leading-none text-lg relative scale-[0.6]"
viewBox="0 0 48 46"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path class="fill-white" d="M43.218 28.2327L43.6765 23.971C43.921 21.6973 44.0825 20.1957 43.9557 19.2497L44 19.25C46.071 19.25 47.75 17.5711 47.75 15.5C47.75 13.4289 46.071 11.75 44 11.75C41.929 11.75 40.25 13.4289 40.25 15.5C40.25 16.4366 40.5935 17.2931 41.1613 17.9503C40.346 18.4535 39.2805 19.515 37.6763 21.1128C36.4405 22.3438 35.8225 22.9593 35.1333 23.0548C34.7513 23.1075 34.3622 23.0532 34.0095 22.898C33.373 22.6175 32.9485 21.8567 32.0997 20.335L27.6262 12.3135C27.1025 11.3747 26.6642 10.5889 26.2692 9.95662C27.89 9.12967 29 7.44445 29 5.5C29 2.73857 26.7615 0.5 24 0.5C21.2385 0.5 19 2.73857 19 5.5C19 7.44445 20.11 9.12967 21.7308 9.95662C21.3358 10.589 20.8975 11.3746 20.3738 12.3135L15.9002 20.335C15.0514 21.8567 14.627 22.6175 13.9905 22.898C13.6379 23.0532 13.2487 23.1075 12.8668 23.0548C12.1774 22.9593 11.5595 22.3438 10.3238 21.1128C8.71968 19.515 7.6539 18.4535 6.83882 17.9503C7.4066 17.2931 7.75 16.4366 7.75 15.5C7.75 13.4289 6.07107 11.75 4 11.75C1.92893 11.75 0.25 13.4289 0.25 15.5C0.25 17.5711 1.92893 19.25 4 19.25L4.04428 19.2497C3.91755 20.1957 4.07905 21.6973 4.32362 23.971L4.782 28.2327C5.03645 30.5982 5.24802 32.849 5.50717 34.875H42.4928C42.752 32.849 42.9635 30.5982 43.218 28.2327Z" fill="#1C274C" />
<path class="fill-white" d="M21.2803 45.5H26.7198C33.8098 45.5 37.3545 45.5 39.7198 43.383C40.7523 42.4588 41.4057 40.793 41.8775 38.625H6.1224C6.59413 40.793 7.24783 42.4588 8.2802 43.383C10.6454 45.5 14.1903 45.5 21.2803 45.5Z" fill="#1C274C" />
</svg>
{% endif %}
{% if card['name'] == "Version" and not is_pro_version %}
<svg class="leading-none fill-white text-yellow-500 text-lg relative scale-[0.6]"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25a3 3 0 0 1 3 3m3 0a6 6 0 0 1-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1 1 21.75 8.25Z" />
</svg>
{% endif %}
{% if card['name'] == "Version number" %}
<svg class="translate-x-0.5 -translate-y-0.5 scale-50 leading-none text-lg relative fill-white"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512">
<path d="M80 104c13.3 0 24-10.7 24-24s-10.7-24-24-24S56 66.7 56 80s10.7 24 24 24zm80-24c0 32.8-19.7 61-48 73.3v87.8c18.8-10.9 40.7-17.1 64-17.1h96c35.3 0 64-28.7 64-64v-6.7C307.7 141 288 112.8 288 80c0-44.2 35.8-80 80-80s80 35.8 80 80c0 32.8-19.7 61-48 73.3V160c0 70.7-57.3 128-128 128H176c-35.3 0-64 28.7-64 64v6.7c28.3 12.3 48 40.5 48 73.3c0 44.2-35.8 80-80 80s-80-35.8-80-80c0-32.8 19.7-61 48-73.3V352 153.3C19.7 141 0 112.8 0 80C0 35.8 35.8 0 80 0s80 35.8 80 80zm232 0c0-13.3-10.7-24-24-24s-24 10.7-24 24s10.7 24 24 24s24-10.7 24-24zM80 456c13.3 0 24-10.7 24-24s-10.7-24-24-24s-24 10.7-24 24s10.7 24 24 24z" />
</svg>
{% endif %}
{% if card['name'] == "Instances" %}
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="scale-[0.6] leading-none text-lg relative stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9">
</path>
</svg>
{% endif %}
{% if card['name'] == "Services" %}
<svg class="scale-50 leading-none text-lg relative fill-white"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.3c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64H348.7c2.2 20.4 3.3 41.8 3.3 64zm28.8-64H503.9c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64zm112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6c78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7c10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5c11.6 26 21 58.2 27 94.7zm-209 0H18.6C48.6 85.9 112.2 29.1 190.6 8.4C165.1 42.6 145.3 96.1 135.3 160zM8.1 192H131.2c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64zM194.7 446.6c-11.6-26-20.9-58.2-27-94.6H344.3c-6.1 36.4-15.5 68.6-27 94.6c-10.5 23.6-22.2 40.7-33.5 51.5C272.6 508.8 263.3 512 256 512s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6C112.2 482.9 48.6 426.1 18.6 352H135.3zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6c25.5-34.2 45.2-87.7 55.3-151.6H493.4z" />
</svg>
{% endif %}
{% if card['name'] == "Plugins" %}
<svg class="scale-75 leading-none text-lg relative fill-white text-yellow-400"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.25 6.087c0-.355.186-.676.401-.959.221-.29.349-.634.349-1.003 0-1.036-1.007-1.875-2.25-1.875s-2.25.84-2.25 1.875c0 .369.128.713.349 1.003.215.283.401.604.401.959v0a.64.64 0 01-.657.643 48.39 48.39 0 01-4.163-.3c.186 1.613.293 3.25.315 4.907a.656.656 0 01-.658.663v0c-.355 0-.676-.186-.959-.401a1.647 1.647 0 00-1.003-.349c-1.036 0-1.875 1.007-1.875 2.25s.84 2.25 1.875 2.25c.369 0 .713-.128 1.003-.349.283-.215.604-.401.959-.401v0c.31 0 .555.26.532.57a48.039 48.039 0 01-.642 5.056c1.518.19 3.058.309 4.616.354a.64.64 0 00.657-.643v0c0-.355-.186-.676-.401-.959a1.647 1.647 0 01-.349-1.003c0-1.035 1.008-1.875 2.25-1.875 1.243 0 2.25.84 2.25 1.875 0 .369-.128.713-.349 1.003-.215.283-.4.604-.4.959v0c0 .333.277.599.61.58a48.1 48.1 0 005.427-.63 48.05 48.05 0 00.582-4.717.532.532 0 00-.533-.57v0c-.355 0-.676.186-.959.401-.29.221-.634.349-1.003.349-1.035 0-1.875-1.007-1.875-2.25s.84-2.25 1.875-2.25c.37 0 .713.128 1.003.349.283.215.604.401.96.401v0a.656.656 0 00.658-.663 48.422 48.422 0 00-.37-5.36c-1.886.342-3.81.574-5.766.689a.578.578 0 01-.61-.58v0z" />
</svg>
{% endif %}
</div>
<!-- end icon -->
</a>
<!-- end stats card -->
{% endfor %}
</div>
{% endblock %}

View file

@ -1,82 +1,82 @@
{% extends "base.html" %}
{% block content %}
{% if instances|length == 0 %}
<div class="col-span-12 sm:col-span-4 sm:col-start-5">
<div class="text-center relative w-full p-4 text-white bg-blue-500 rounded-lg">No instance to show</div>
</div>
{% else %}
{% for instances_batched in instances|batch(2) %}
{% for instance in
instances_batched %}
<!-- instance card -->
<div class="overflow-hidden max-h-none sm:max-h- hover:scale-102 transition col-span-12 lg:col-span-6 3xl:col-span-4 flex p-4 justify-between w-full shadow-md break-words bg-white dark:bg-slate-850 dark:brightness-110 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<form class="w-full" id="form-instance-{{ instance._id }}" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" name="INSTANCE_ID" value="{{ instance._id }}" />
<!-- state and title-->
<div class="grid grid-cols-12">
{% if instance.health %}<div class="col-span-1 mt-2 h-4 w-4 rounded-full bg-green-500"></div>{% endif %}
{% if not instance.health %}<div class="col-span-1 mt-2 h-4 w-4 rounded-full bg-red-500"></div>{% endif %}
<h5 class="col-span-11 break-words font-bold dark:text-white/90 transition duration-300 ease-in-out">
{{ instance.name }}
</h5>
</div>
<!-- end state and title-->
<!-- detail list -->
<div role="grid" class="grid grid-cols-1 gap-2 mt-4 mb-6 ml-1">
{% set instance_details = [{"name" : "TYPE", "value" : instance['_type']},{"name" : "HOSTNAME", "value" : instance['hostname']}] %}
<!-- detail -->
{% for detail in instance_details %}
<div role="row"
class="flex flex-col items-center sm:flex-row col-span-1 py-1 sm:py-0">
<p role="gridcell"
class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ detail['name'] }}
</p>
<p role="gridcell"
class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ detail['value'] }}
</p>
</div>
{% endfor %}
<!-- end detail -->
</div>
<!-- end detail list-->
<!-- button list-->
<div class="relative w-full flex justify-center sm:justify-end">
{% if instance._type == "local" and instance.health %}
<button type="submit"
name="operation"
value="restart"
class="edit-btn mx-1 text-xs">Restart</button>
<button type="submit"
name="operation"
value="stop"
class="delete-btn mx-1 text-xs">Stop</button>
{% endif %}
{% if not instance._type == "local" and instance.health %}
<button type="submit"
name="operation"
value="reload"
class="edit-btn mx-1 text-xs">Reload</button>
<button type="submit"
name="operation"
value="stop"
class="delete-btn mx-1 text-xs">Stop</button>
{% endif %}
{% if instance._type == "local" and not instance.health or not
instance._type == "local" and not instance.health %}
<button type="submit"
name="operation"
value="start"
class="valid-btn mx-1 text-xs">Start</button>
{% endif %}
</div>
<!-- end button list-->
</form>
{% if instances|length == 0 %}
<div class="col-span-12 sm:col-span-4 sm:col-start-5">
<div class="text-center relative w-full p-4 text-white bg-blue-500 rounded-lg">No instance to show</div>
</div>
<!-- end instance card -->
{% endfor %}
{% endfor %}
{% endif %}
{% else %}
{% for instances_batched in instances|batch(2) %}
{% for instance in
instances_batched %}
<!-- instance card -->
<div class="overflow-hidden max-h-none sm:max-h- hover:scale-102 transition col-span-12 lg:col-span-6 3xl:col-span-4 flex p-4 justify-between w-full shadow-md break-words bg-white dark:bg-slate-850 dark:brightness-110 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<form class="w-full" id="form-instance-{{ instance._id }}" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" name="INSTANCE_ID" value="{{ instance._id }}" />
<!-- state and title-->
<div class="grid grid-cols-12">
{% if instance.health %}<div class="col-span-1 mt-2 h-4 w-4 rounded-full bg-green-500"></div>{% endif %}
{% if not instance.health %}<div class="col-span-1 mt-2 h-4 w-4 rounded-full bg-red-500"></div>{% endif %}
<h5 class="col-span-11 break-words font-bold dark:text-white/90 transition duration-300 ease-in-out">
{{ instance.name }}
</h5>
</div>
<!-- end state and title-->
<!-- detail list -->
<div role="grid" class="grid grid-cols-1 gap-2 mt-4 mb-6 ml-1">
{% set instance_details = [{"name" : "TYPE", "value" : instance['_type']},{"name" : "HOSTNAME", "value" : instance['hostname']}] %}
<!-- detail -->
{% for detail in instance_details %}
<div role="row"
class="flex flex-col items-center sm:flex-row col-span-1 py-1 sm:py-0">
<p role="gridcell"
class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ detail['name'] }}
</p>
<p role="gridcell"
class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ detail['value'] }}
</p>
</div>
{% endfor %}
<!-- end detail -->
</div>
<!-- end detail list-->
<!-- button list-->
<div class="relative w-full flex justify-center sm:justify-end">
{% if instance._type == "local" and instance.health %}
<button type="submit"
name="operation"
value="restart"
class="edit-btn mx-1 text-xs">Restart</button>
<button type="submit"
name="operation"
value="stop"
class="delete-btn mx-1 text-xs">Stop</button>
{% endif %}
{% if not instance._type == "local" and instance.health %}
<button type="submit"
name="operation"
value="reload"
class="edit-btn mx-1 text-xs">Reload</button>
<button type="submit"
name="operation"
value="stop"
class="delete-btn mx-1 text-xs">Stop</button>
{% endif %}
{% if instance._type == "local" and not instance.health or not
instance._type == "local" and not instance.health %}
<button type="submit"
name="operation"
value="start"
class="valid-btn mx-1 text-xs">Start</button>
{% endif %}
</div>
<!-- end button list-->
</form>
</div>
<!-- end instance card -->
{% endfor %}
{% endfor %}
{% endif %}
{% endblock content %}

View file

@ -1,280 +1,282 @@
{% extends "base.html" %}
{% block content %}
{% set run_times = ["all"] %}
{% for job_name, value in jobs.items() %}
{% if value['every'] not in run_times %}
{% if run_times.append(value['every']) %}{% endif %}
{% endif %}
{% endfor %}
<!-- info-->
{% set jobs_info = [
{"name" : "JOBS TOTAL", "data" : jobs|length|string},
{"name" : "JOBS ERRORS", "data" : jobs_errors|string},
] %}
<div class="h-fit col-span-12 md:col-span-4 3xl:col-span-3 p-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="mb-2 font-bold dark:text-white/90">INFO</h5>
{% for info in jobs_info %}
<div class="mx-1 flex items-center my-4">
<p class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ info['name'] }}
</p>
<p class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ info['data'] }}
</p>
</div>
{% set run_times = ["all"] %}
{% for job_name, value in jobs.items() %}
{% if value['every'] not in run_times %}
{% if run_times.append(value['every']) %}{% endif %}
{% endif %}
{% endfor %}
</div>
<!-- end info -->
<!-- filter -->
{% set filters = [
{
"type": "input",
"name": "Search",
"label": "search",
"id": "keyword",
"placeholder": "keyword",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Success state",
"id": "success",
"value": "all",
"values": [
"all",
"false",
"true"
]
},
{
"type": "select",
"name": "Reload state",
"id": "reload",
"value": "all",
"values": [
"all",
"false",
"true"
]
},
{
"type": "select",
"name": "Run time",
"id": "every",
"value": "all",
"values": run_times
}
] %}
<div data-jobs-filter
class="h-fit col-span-12 md:col-span-8 2xl:col-span-6 3xl:col-span-5 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/90">FILTER</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-jobs-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="jobs-{{ filter['id'] }}"
data-name="jobs-{{ filter['id'] }}"
data-jobs-setting-select-text="{{ filter['id'] }}">{{ filter['value']}}</span>
<!-- chevron -->
<svg data-jobs-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-jobs-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-jobs-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
{% endfor %}
<!-- info-->
{% set jobs_info = [
{"name" : "JOBS TOTAL", "data" : jobs|length|string},
{"name" : "JOBS ERRORS", "data" : jobs_errors|string},
] %}
<div class="h-fit col-span-12 md:col-span-4 3xl:col-span-3 p-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="mb-2 font-bold dark:text-white/90">INFO</h5>
{% for info in jobs_info %}
<div class="mx-1 flex items-center my-4">
<p class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ info['name'] }}
</p>
<p class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ info['data'] }}
</p>
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
</div>
<!-- end filter -->
<div data-jobs-nomatch
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No jobs match</h5>
</div>
</div>
<div data-jobs-list-container class="w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="col-span-12">
<h5 class="mb-4 mt-2 font-bold dark:text-white/90 mx-2">JOBS LIST</h5>
</div>
<div class="col-span-12 overflow-y-auto overflow-x-auto">
<!-- list container-->
{% set job_headers = [
{
"name": "Name",
"custom_class": "col-span-3"
},
{
"name": "Last run",
"custom_class": "col-span-3"
},
{
"name": "Every",
"custom_class": "col-span-1"
},
{
"name": "Reload",
"custom_class": "flex justify-center col-span-1"
},
{
"name": "Success",
"custom_class": "flex justify-center col-span-1"
},
{
"name": "Files",
"custom_class": "col-span-3"
}
] %}
<div class="min-w-[900px] w-full grid grid-cols-12 rounded p-2">
<!-- header-->
{% for header in job_headers %}
<p class="{{ header['custom_class'] }} dark:text-gray-300 h-8 text-sm font-bold m-0 pb-2 border-b border-gray-400">
{{ header['name'] }}
</p>
{% endfor %}
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full" data-jobs-list>
{% for job_name, value in jobs.items() %}
<!-- job item-->
{% set jobs_data = [
{"type" : "text", "filter_name" : "name", "value" : job_name, "custom_class" : "col-span-3"},
{"type" : "text", "filter_name" : "last_run", "value" : value['last_run'], "custom_class" : "col-span-3"},
{"type" : "text", "filter_name" : "every", "value" : value['every'], "custom_class" : "col-span-1"},
{"type" : "check", "filter_name" : "reload", "value" : value['reload'], "custom_class" : "col-span-1"},
{"type" : "check", "filter_name" : "success", "value" : value['success'], "custom_class" : "col-span-1"},
{"type" : "select", "filter_name" : "success", "value" : value['success'], "custom_class" : "col-span-3"},
] %}
<li data-jobs-item class="items-center grid grid-cols-12 border-b border-gray-300 py-2.5">
{% for data in jobs_data %}
{% if data['type'] == "text" %}
<p class="{{ data['custom_class'] }} dark:text-gray-400 dark:opacity-80 text-sm m-0 my-1" data-jobs-{{ data['filter_name'] }}="{{data['value']}}">
{{ data['value'] }}
</p>
{% endif %}
{% if data['type'] == "check" and data['value'] %}
<p class="{{ data['custom_class'] }} flex justify-center dark:text-gray-400 dark:opacity-80 text-sm m-0 my-1" data-jobs-{{ data['filter_name'] }}="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 data['type'] == "check" and not data['value'] %}
<p class="{{ data['custom_class'] }} flex justify-center dark:text-gray-400 dark:opacity-80 text-sm m-0 my-1" data-jobs-{{ data['filter_name'] }}="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 data['type'] == "select" %}
<div class="{{ data['custom_class'] }} relative dark:text-gray-400 text-sm m-0 my-1"
data-jobs-files>
{% if value['cache'] %}
<button data-jobs-setting-select="{{ job_name }}"
class="py-1 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="jobs-{{ job_name }}"
data-name="jobs-{{ job_name }}"
data-jobs-setting-select-text="{{ job_name }}">files</span>
<!-- chevron -->
<svg data-jobs-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 data-jobs-setting-select-dropdown="{{ job_name }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-0.5">
{% for file in value['cache'] %}
<button data-jobs-download="{{ job_name }}"
data-jobs-file="{{ file['file_name'] }}"
data-jobs-setting-select-dropdown-btn="{{ job_name }}"
value="files"
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">
<span class="flex justify-start items-center">
<svg class="h-5.5 w-5.5 stroke-sky-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75l3 3m0 0l3-3m-3 3v-7.5M21 12a9 9 0 11-18 0 9 9 0 0118 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>
</span>
</button>
{% endfor %}
</div>
<!-- end dropdown-->
{% endif %}
</div>
{% endif %}
{% endfor %}
</li>
<!-- end job item-->
{% endfor %}
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
<!-- end info -->
<!-- filter -->
{% set filters = [
{
"type": "input",
"name": "Search",
"label": "search",
"id": "keyword",
"placeholder": "keyword",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Success state",
"id": "success",
"value": "all",
"values": [
"all",
"false",
"true"
]
},
{
"type": "select",
"name": "Reload state",
"id": "reload",
"value": "all",
"values": [
"all",
"false",
"true"
]
},
{
"type": "select",
"name": "Run time",
"id": "every",
"value": "all",
"values": run_times
}
] %}
<div data-jobs-filter
class="h-fit col-span-12 md:col-span-8 2xl:col-span-6 3xl:col-span-5 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/90">FILTER</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-jobs-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="jobs-{{ filter['id'] }}"
data-name="jobs-{{ filter['id'] }}"
data-jobs-setting-select-text="{{ filter['id'] }}">{{ filter['value'] }}</span>
<!-- chevron -->
<svg data-jobs-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-jobs-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-jobs-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
</div>
<!-- end filter -->
<div data-jobs-nomatch
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No jobs match</h5>
</div>
</div>
<div data-jobs-list-container
class="w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="col-span-12">
<h5 class="mb-4 mt-2 font-bold dark:text-white/90 mx-2">JOBS LIST</h5>
</div>
<div class="col-span-12 overflow-y-auto overflow-x-auto">
<!-- list container-->
{% set job_headers = [
{
"name": "Name",
"custom_class": "col-span-3"
},
{
"name": "Last run",
"custom_class": "col-span-3"
},
{
"name": "Every",
"custom_class": "col-span-1"
},
{
"name": "Reload",
"custom_class": "flex justify-center col-span-1"
},
{
"name": "Success",
"custom_class": "flex justify-center col-span-1"
},
{
"name": "Files",
"custom_class": "col-span-3"
}
] %}
<div class="min-w-[900px] w-full grid grid-cols-12 rounded p-2">
<!-- header-->
{% for header in job_headers %}
<p class="{{ header['custom_class'] }} dark:text-gray-300 h-8 text-sm font-bold m-0 pb-2 border-b border-gray-400">
{{ header['name'] }}
</p>
{% endfor %}
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full" data-jobs-list>
{% for job_name, value in jobs.items() %}
<!-- job item-->
{% set jobs_data = [
{"type" : "text", "filter_name" : "name", "value" : job_name, "custom_class" : "col-span-3"},
{"type" : "text", "filter_name" : "last_run", "value" : value['last_run'], "custom_class" : "col-span-3"},
{"type" : "text", "filter_name" : "every", "value" : value['every'], "custom_class" : "col-span-1"},
{"type" : "check", "filter_name" : "reload", "value" : value['reload'], "custom_class" : "col-span-1"},
{"type" : "check", "filter_name" : "success", "value" : value['success'], "custom_class" : "col-span-1"},
{"type" : "select", "filter_name" : "success", "value" : value['success'], "custom_class" : "col-span-3"},
] %}
<li data-jobs-item
class="items-center grid grid-cols-12 border-b border-gray-300 py-2.5">
{% for data in jobs_data %}
{% if data['type'] == "text" %}
<p class="{{ data['custom_class'] }} dark:text-gray-400 dark:opacity-80 text-sm m-0 my-1" data-jobs-{{ data['filter_name'] }}="{{ data['value'] }}">
{{ data['value'] }}
</p>
{% endif %}
{% if data['type'] == "check" and data['value'] %}
<p class="{{ data['custom_class'] }} flex justify-center dark:text-gray-400 dark:opacity-80 text-sm m-0 my-1" data-jobs-{{ data['filter_name'] }}="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 data['type'] == "check" and not data['value'] %}
<p class="{{ data['custom_class'] }} flex justify-center dark:text-gray-400 dark:opacity-80 text-sm m-0 my-1" data-jobs-{{ data['filter_name'] }}="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 data['type'] == "select" %}
<div class="{{ data['custom_class'] }} relative dark:text-gray-400 text-sm m-0 my-1"
data-jobs-files>
{% if value['cache'] %}
<button data-jobs-setting-select="{{ job_name }}"
class="py-1 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="jobs-{{ job_name }}"
data-name="jobs-{{ job_name }}"
data-jobs-setting-select-text="{{ job_name }}">files</span>
<!-- chevron -->
<svg data-jobs-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 data-jobs-setting-select-dropdown="{{ job_name }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-0.5">
{% for file in value['cache'] %}
<button data-jobs-download="{{ job_name }}"
data-jobs-file="{{ file['file_name'] }}"
data-jobs-setting-select-dropdown-btn="{{ job_name }}"
value="files"
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">
<span class="flex justify-start items-center">
<svg class="h-5.5 w-5.5 stroke-sky-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75l3 3m0 0l3-3m-3 3v-7.5M21 12a9 9 0 11-18 0 9 9 0 0118 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>
</span>
</button>
{% endfor %}
</div>
<!-- end dropdown-->
{% endif %}
</div>
{% endif %}
{% endfor %}
</li>
<!-- end job item-->
{% endfor %}
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
{% endblock content %}

File diff suppressed because one or more lines are too long

View file

@ -1,129 +1,129 @@
<!DOCTYPE html>
{% block content %}
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>BunkerWeb UI | Log in</title>
<link href="images/favicon.ico" rel="icon" type="image/x-icon" />
<link rel="stylesheet" href="css/dashboard.css" />
<link rel="stylesheet" href="css/login.css" />
</head>
<body>
<div data-loader
class="fixed z-[10000] transition duration-300 h-screen w-screen bg-primary flex justify-center align-middle items-center">
<img data-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>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if
messages %}
<!-- flash message-->
{% for category, message in messages %}
<div role="alert"
aria-description="login message alert"
data-flash-message
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">
<button data-close-flash-message
role="close alert message"
class="absolute right-7 top-1.5">
<svg class="cursor-pointer fill-gray-600 dark:fill-gray-300 dark:opacity-80 absolute h-5 w-5"
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>
{% if category == 'error' or (message|safe).startswith("Please log in") %}
<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 %}
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>BunkerWeb UI | Log in</title>
<link href="images/favicon.ico" rel="icon" type="image/x-icon" />
<link rel="stylesheet" href="css/dashboard.css" />
<link rel="stylesheet" href="css/login.css" />
</head>
<body>
<div data-loader
class="fixed z-[10000] transition duration-300 h-screen w-screen bg-primary flex justify-center align-middle items-center">
<img data-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>
{% endfor %}
<!-- end flash message-->
{% endif %}
{% endwith %}
<!-- end flash message-->
<!--content -->
<main class="grid grid-cols-2 align-middle items-center min-h-screen">
<!--form -->
<div class="mx-4 lg:mx-0 col-span-2 lg:col-span-1 bg-none lg:bg-gray-50 h-full flex flex-col items-center justify-center">
<div class="bg-gray-50 rounded px-8 sm:px-12 py-16 w-full max-w-[400px]">
<div class="flex justify-center">
<img class="lg:hidden w-full max-w-60 max-h-30 mb-6"
src="images/BUNKERWEB-print-hd.png"
alt="logo" />
</div>
<h1 class="hidden lg:block text-center font-bold dark:text-white mb-8">Log in</h1>
<form action="login" method="POST" autocomplete="off">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden"
name="next"
value="{{ request.values.get('next', '') }}" />
<!-- username inpt-->
<div class="flex flex-col relative col-span-12 my-3">
<h5 class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-md font-bold m-0 dark:text-gray-300">
Username
</h5>
<label class="sr-only" for="username">username</label>
<input type="text"
id="username"
name="username"
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-4 py-2 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="enter username"
pattern="(.*?)"
required />
</div>
<!-- end username inpt-->
<!-- password inpt-->
<div class="flex flex-col relative col-span-12 my-3">
<h5 class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-md font-bold m-0 dark:text-gray-300">
Password
</h5>
<label class="sr-only" for="password">password</label>
<input type="password"
id="password"
name="password"
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-4 py-2 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="enter password"
pattern="(.*?)"
required />
</div>
<!-- end password inpt-->
<!-- totp -->
<div class="flex justify-center">
<button type="submit"
id="login"
name="login"
value="login"
class="my-4 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">
Log in
</button>
</div>
</form>
</div>
</div>
<!-- end form -->
<!-- particles -->
<div class="-z-10 fixed lg:relative lg:col-span-1 bg-primary">
<div id="particles-js" class="login-img [&>*]:bg-primary"></div>
<div class="hidden lg:flex justify-center">
<img class="max-w-60 max-h-30"
src="images/BUNKERWEB-print-hd-blanc.png"
alt="logo" />
</div>
</div>
</main>
<!-- end particles -->
<!-- end content -->
<script src="js/tsparticles.bundle.min.js" nonce="{{ script_nonce }}"></script>
<script nonce="{{ script_nonce }}">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if
messages %}
<!-- flash message-->
{% for category, message in messages %}
<div role="alert"
aria-description="login message alert"
data-flash-message
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">
<button data-close-flash-message
role="close alert message"
class="absolute right-7 top-1.5">
<svg class="cursor-pointer fill-gray-600 dark:fill-gray-300 dark:opacity-80 absolute h-5 w-5"
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>
{% if category == 'error' or (message|safe).startswith("Please log in") %}
<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-->
{% endif %}
{% endwith %}
<!-- end flash message-->
<!--content -->
<main class="grid grid-cols-2 align-middle items-center min-h-screen">
<!--form -->
<div class="mx-4 lg:mx-0 col-span-2 lg:col-span-1 bg-none lg:bg-gray-50 h-full flex flex-col items-center justify-center">
<div class="bg-gray-50 rounded px-8 sm:px-12 py-16 w-full max-w-[400px]">
<div class="flex justify-center">
<img class="lg:hidden w-full max-w-60 max-h-30 mb-6"
src="images/BUNKERWEB-print-hd.png"
alt="logo" />
</div>
<h1 class="hidden lg:block text-center font-bold dark:text-white mb-8">Log in</h1>
<form action="login" method="POST" autocomplete="off">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden"
name="next"
value="{{ request.values.get('next', '') }}" />
<!-- username inpt-->
<div class="flex flex-col relative col-span-12 my-3">
<h5 class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-md font-bold m-0 dark:text-gray-300">
Username
</h5>
<label class="sr-only" for="username">username</label>
<input type="text"
id="username"
name="username"
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-4 py-2 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="enter username"
pattern="(.*?)"
required />
</div>
<!-- end username inpt-->
<!-- password inpt-->
<div class="flex flex-col relative col-span-12 my-3">
<h5 class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-md font-bold m-0 dark:text-gray-300">
Password
</h5>
<label class="sr-only" for="password">password</label>
<input type="password"
id="password"
name="password"
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-4 py-2 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="enter password"
pattern="(.*?)"
required />
</div>
<!-- end password inpt-->
<!-- totp -->
<div class="flex justify-center">
<button type="submit"
id="login"
name="login"
value="login"
class="my-4 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">
Log in
</button>
</div>
</form>
</div>
</div>
<!-- end form -->
<!-- particles -->
<div class="-z-10 fixed lg:relative lg:col-span-1 bg-primary">
<div id="particles-js" class="login-img [&>*]:bg-primary"></div>
<div class="hidden lg:flex justify-center">
<img class="max-w-60 max-h-30"
src="images/BUNKERWEB-print-hd-blanc.png"
alt="logo" />
</div>
</div>
</main>
<!-- end particles -->
<!-- end content -->
<script src="js/tsparticles.bundle.min.js" nonce="{{ script_nonce }}"></script>
<script nonce="{{ script_nonce }}">
class Loader {
constructor() {
this.menuContainer = document.querySelector("[data-menu-container]");
@ -199,7 +199,7 @@
const setLoader = new Loader();
const setFlash = new FlashMsg();
tsParticles.loadJSON("particles-js", "json/particles.json");
</script>
</body>
</html>
</script>
</body>
</html>
{% endblock content %}

View file

@ -1,266 +1,266 @@
{% extends "base.html" %}
{% block content %}
<!-- settings -->
<div data-logs-settings
class="col-span-12 lg: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/90">SETTINGS</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
<!-- select instance -->
<div class="flex flex-col relative col-span-12">
<h5 class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300">
Select instance
</h5>
<button data-logs-setting-select="instances"
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="logs-instance"
data-name="logs-instance"
data-logs-setting-select-text="instances">
{% for instance in instances %}
{% if loop.first %}
{% if
instance.name %}
{{ instance.name }}
{% else %}
no instance
{% endif %}
{% endif %}
{% endfor %}
</span>
<!-- chevron -->
<svg data-logs-setting-select="instances"
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 data-logs-setting-select-dropdown="instances"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for instance in instances %}
<button data-logs-setting-select-dropdown-btn="instances"
value="{{ instance.name }}"
data-_type="{{ instance._type }}"
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 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">
{{ instance.name }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select instance -->
<!-- from date input -->
<div class="flex flex-col relative col-span-12 sm: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">
From date
</h5>
<div class="relative">
<input 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 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="pick start date"
pattern="(.*?)"
required />
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="pointer-events-none absolute top-1 right-2 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />
</svg>
</div>
</div>
<!-- end from date input -->
<!-- to date input -->
<div class="flex flex-col relative col-span-12 sm: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">
To date (default today)
</h5>
<div class="relative">
<input 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 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="pick end date"
pattern="(.*?)"
required />
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="pointer-events-none absolute top-1 right-2 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />
</svg>
</div>
</div>
<!-- end to date input -->
<!-- refresh delay input -->
<div class="flex flex-col relative col-span-12 sm: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">
Update delay (in seconds)
</h5>
<input 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 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"
data-pattern="(.*?)"
required />
</div>
<!-- end refresh delay input -->
<!-- refresh inp -->
<div 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">
Live update
</h5>
<div data-checkbox-handler="live-update" class="relative mb-7 md:mb-0">
<input id="live-update"
name="live-update"
data-default-method="default"
data-default-value="no"
class="checkbox"
type="checkbox"
data-pattern="^(yes|no)$"
value="no" />
<svg data-checkbox-handler="live-update"
class="pointer-events-none 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 inp-->
<div class="col-span-12 w-full justify-center flex mt-2">
<button data-submit-date
id="submit-data"
class="tracking-widest dark:brightness-125 hover:brightness-75 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-gradient-to-tl bg-primary leading-normal text-xs ease-in shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Submit Date
</button>
<button data-submit-live="no"
id="submit-live"
class="hidden tracking-widest dark:brightness-125 hover:brightness-75 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-gradient-to-tl bg-primary leading-normal text-xs ease-in shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Go Live
</button>
</div>
</div>
</div>
<!-- end settings -->
<!-- filter -->
{% set filters = [
{
"type": "input",
"name": "Search",
"label": "search",
"id": "keyword",
"placeholder": "keyword",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Logs type",
"id": "types",
"value": "all",
"values": [
"all",
"message",
"error",
"warn",
"info",
"misc"
]
}
] %}
<div data-logs-filter
class="h-fit col-span-12 md:col-span-6 lg:col-span-4 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/90">FILTERS</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-logs-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="logs-{{ filter['id'] }}"
data-name="logs-{{ filter['id'] }}"
data-logs-setting-select-text="{{ filter['id'] }}">all</span>
<!-- chevron -->
<svg data-logs-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-logs-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-logs-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
<!-- settings -->
<div data-logs-settings
class="col-span-12 lg: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/90">SETTINGS</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
<!-- select instance -->
<div class="flex flex-col relative col-span-12">
<h5 class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300">
Select instance
</h5>
<button data-logs-setting-select="instances"
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="logs-instance"
data-name="logs-instance"
data-logs-setting-select-text="instances">
{% for instance in instances %}
{% if loop.first %}
{% if
instance.name %}
{{ instance.name }}
{% else %}
no instance
{% endif %}
{% endif %}
{% endfor %}
</span>
<!-- chevron -->
<svg data-logs-setting-select="instances"
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 data-logs-setting-select-dropdown="instances"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for instance in instances %}
<button data-logs-setting-select-dropdown-btn="instances"
value="{{ instance.name }}"
data-_type="{{ instance._type }}"
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 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">
{{ instance.name }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select instance -->
<!-- from date input -->
<div class="flex flex-col relative col-span-12 sm: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">
From date
</h5>
<div class="relative">
<input 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 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="pick start date"
pattern="(.*?)"
required />
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="pointer-events-none absolute top-1 right-2 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />
</svg>
</div>
</div>
<!-- end from date input -->
<!-- to date input -->
<div class="flex flex-col relative col-span-12 sm: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">
To date (default today)
</h5>
<div class="relative">
<input 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 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="pick end date"
pattern="(.*?)"
required />
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="pointer-events-none absolute top-1 right-2 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />
</svg>
</div>
</div>
<!-- end to date input -->
<!-- refresh delay input -->
<div class="flex flex-col relative col-span-12 sm: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">
Update delay (in seconds)
</h5>
<input 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 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"
data-pattern="(.*?)"
required />
</div>
<!-- end refresh delay input -->
<!-- refresh inp -->
<div 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">
Live update
</h5>
<div data-checkbox-handler="live-update" class="relative mb-7 md:mb-0">
<input id="live-update"
name="live-update"
data-default-method="default"
data-default-value="no"
class="checkbox"
type="checkbox"
data-pattern="^(yes|no)$"
value="no" />
<svg data-checkbox-handler="live-update"
class="pointer-events-none 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 inp-->
<div class="col-span-12 w-full justify-center flex mt-2">
<button data-submit-date
id="submit-data"
class="tracking-widest dark:brightness-125 hover:brightness-75 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-gradient-to-tl bg-primary leading-normal text-xs ease-in shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Submit Date
</button>
<button data-submit-live="no"
id="submit-live"
class="hidden tracking-widest dark:brightness-125 hover:brightness-75 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-gradient-to-tl bg-primary leading-normal text-xs ease-in shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Go Live
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
</div>
<!-- end filter -->
<div class="w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="col-span-12">
<h5 class="mb-4 mt-2 font-bold dark:text-white/90 mx-2">LOGS</h5>
</div>
<div class="col-span-12 overflow-y-auto overflow-x-auto">
<div data-logs-bans-list>
<!-- list container-->
<div class="overflow-hidden min-w-[800px] 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">Type</p>
<p class="dark:text-gray-300 h-8 text-sm font-bold col-span-9 m-0 pb-2 border-b border-gray-400">Description</p>
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full" data-logs-list>
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
</div>
<!-- end settings -->
<!-- filter -->
{% set filters = [
{
"type": "input",
"name": "Search",
"label": "search",
"id": "keyword",
"placeholder": "keyword",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Logs type",
"id": "types",
"value": "all",
"values": [
"all",
"message",
"error",
"warn",
"info",
"misc"
]
}
] %}
<div data-logs-filter
class="h-fit col-span-12 md:col-span-6 lg:col-span-4 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/90">FILTERS</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-logs-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="logs-{{ filter['id'] }}"
data-name="logs-{{ filter['id'] }}"
data-logs-setting-select-text="{{ filter['id'] }}">all</span>
<!-- chevron -->
<svg data-logs-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-logs-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-logs-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
</div>
<!-- end filter -->
<div class="w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="col-span-12">
<h5 class="mb-4 mt-2 font-bold dark:text-white/90 mx-2">LOGS</h5>
</div>
<div class="col-span-12 overflow-y-auto overflow-x-auto">
<div data-logs-bans-list>
<!-- list container-->
<div class="overflow-hidden min-w-[800px] 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">Type</p>
<p class="dark:text-gray-300 h-8 text-sm font-bold col-span-9 m-0 pb-2 border-b border-gray-400">Description</p>
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full" data-logs-list>
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
</div>
{% endblock content %}

View file

@ -5,12 +5,12 @@
aria-label="Open menu sidebar"
data-sidebar-menu-toggle
class="transition-all scale-90 sm:scale-100 dark:brightness-95 dark:hover:brightness-105 hover:brightness-75 xl:hidden fixed p-3 text-xl bg-white shadow-sm cursor-pointer top-16 sm:top-[4.5rem] right-5 sm:right-6 z-990 rounded-circle text-slate-700">
<svg fill="#0D6EFD"
class="h-6 w-6 translate-x-0.5"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z" />
</svg>
<svg fill="#0D6EFD"
class="h-6 w-6 translate-x-0.5"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z" />
</svg>
</button>
<!-- end float button-->
<!-- left sidebar -->
@ -18,339 +18,339 @@
class="transition-all mt-[4.5rem] fixed flex inset-y-0 flex-wrap justify-between w-full p-0 my-4 overflow-y-auto antialiased duration-200 -translate-x-full bg-white border-0 shadow-xl dark:shadow-none dark:bg-slate-850 dark:brightness-110 max-w-64 z-[1000] xl:ml-6 rounded-2xl xl:left-0 xl:translate-x-0"
aria-hidden="true"
id="sidebar-menu">
<!-- close btn-->
<button aria-controls="sidebar-menu"
aria-expanded="false"
aria-label="close menu sidebar"
data-sidebar-menu-close>
<svg class="xl:hidden fill-gray-600 dark:fill-gray-300 dark:opacity-80 absolute h-6 w-6 top-4 right-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" />
</svg>
</button>
<!-- close btn-->
<!-- top sidebar -->
<div class="w-full">
<!-- logo and version -->
<div class="h-19">
<a aria-label="link to home"
class="flex justify-center px-8 py-6 m-0 text-sm whitespace-nowrap dark:text-white text-slate-700"
href="{% if current_endpoint == 'home' %}#{% else %}loading?next={{ url_for("home") }}{% endif %}">
<img src="images/logo-menu-2.png"
class="hidden dark:inline w-28 sm:w-36 transition-all duration-200 h-8 sm:h-10"
alt="main logo" />
<img src="images/logo-menu.png"
class="dark:hidden inline w-28 sm:w-36 transition-all duration-200 h-8 sm:h-10"
alt="main logo" />
</a>
</div>
<div class="w-full px-1">
<h1 class="mb-0.5 tracking-normal text-primary text-center text-lg break-words whitespace-normal dark:text-gray-300">
{{ username }}
</h1>
<a class="block underline mb-2 text-gray-600 dark:text-gray-400 text-sm text-center hover:brightness-90"
href="{% if current_endpoint == 'account' %}#{% else %}loading?next={{ url_for("account") }}{% endif %}">manage account
</a>
</div>
<hr class="h-px mt-0 bg-transparent bg-gradient-to-r from-transparent via-black/40 to-transparent dark:bg-gradient-to-r dark:from-transparent dark:via-white dark:to-transparent" />
<!-- end logo version -->
<!-- list items -->
<div class="items-center block w-auto max-h-screen overflow-auto h-sidenav grow basis-full">
<!-- default anchor -->
<ul class="flex flex-col pl-0 mb-0">
{% set paths = [
"home",
"instances",
"global_config",
"services",
"configs",
"plugins",
"cache",
"reports",
"bans",
"jobs",
"logs"
] %}
<!-- loop paths -->
{% for path in paths %}
<li class="mt-0.5 w-full">
<a class="{% if current_endpoint == path %} font-semibold text-slate-700 dark:bg-primary/50 rounded-lg dark:hover:bg-primary/60 bg-primary/10 hover:bg-primary/30 {% else %} dark:hover:bg-primary/20 hover:bg-primary/5 {% endif %} dark:text-white dark:opacity-80 py-1 ease-nav-brand my-0 mx-2 flex items-center whitespace-nowrap rounded-lg px-4 transition text-sm"
href="{% if current_endpoint == path %}#{% else %}loading?next={{ url_for(path) }}{% endif %}">
<div class="mr-2 flex items-center justify-center rounded-lg bg-center stroke-0 text-center p-1 xl:p-1.5">
{% if path == "home" %}
<svg class="stroke-sky-500 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
</svg>
{% endif %}
{% if path == "instances" %}
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="stroke-stone-500 h-5.5 w-5.5 relative">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9" />
</svg>
{% endif %}
{% if path == "global_config" %}
<svg class="stroke-blue-400 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75" />
</svg>
{% endif %}
{% if path == "services" %}
<svg class="stroke-orange-500 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 17.25v-.228a4.5 4.5 0 00-.12-1.03l-2.268-9.64a3.375 3.375 0 00-3.285-2.602H7.923a3.375 3.375 0 00-3.285 2.602l-2.268 9.64a4.5 4.5 0 00-.12 1.03v.228m19.5 0a3 3 0 01-3 3H5.25a3 3 0 01-3-3m19.5 0a3 3 0 00-3-3H5.25a3 3 0 00-3 3m16.5 0h.008v.008h-.008v-.008zm-3 0h.008v.008h-.008v-.008z" />
</svg>
{% endif %}
{% if path == "configs" %}
<svg class="stroke-blue-500 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
{% endif %}
{% if path == "plugins" %}
<svg class="stroke-yellow-400 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.25 6.087c0-.355.186-.676.401-.959.221-.29.349-.634.349-1.003 0-1.036-1.007-1.875-2.25-1.875s-2.25.84-2.25 1.875c0 .369.128.713.349 1.003.215.283.401.604.401.959v0a.64.64 0 01-.657.643 48.39 48.39 0 01-4.163-.3c.186 1.613.293 3.25.315 4.907a.656.656 0 01-.658.663v0c-.355 0-.676-.186-.959-.401a1.647 1.647 0 00-1.003-.349c-1.036 0-1.875 1.007-1.875 2.25s.84 2.25 1.875 2.25c.369 0 .713-.128 1.003-.349.283-.215.604-.401.959-.401v0c.31 0 .555.26.532.57a48.039 48.039 0 01-.642 5.056c1.518.19 3.058.309 4.616.354a.64.64 0 00.657-.643v0c0-.355-.186-.676-.401-.959a1.647 1.647 0 01-.349-1.003c0-1.035 1.008-1.875 2.25-1.875 1.243 0 2.25.84 2.25 1.875 0 .369-.128.713-.349 1.003-.215.283-.4.604-.4.959v0c0 .333.277.599.61.58a48.1 48.1 0 005.427-.63 48.05 48.05 0 00.582-4.717.532.532 0 00-.533-.57v0c-.355 0-.676.186-.959.401-.29.221-.634.349-1.003.349-1.035 0-1.875-1.007-1.875-2.25s.84-2.25 1.875-2.25c.37 0 .713.128 1.003.349.283.215.604.401.96.401v0a.656.656 0 00.658-.663 48.422 48.422 0 00-.37-5.36c-1.886.342-3.81.574-5.766.689a.578.578 0 01-.61-.58v0z" />
</svg>
{% endif %}
{% if path == "cache" %}
<svg class="stroke-pink-600 h-5.5 w-5.5 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M20.25 7.5l-.625 10.632a2.25 2.25 0 01-2.247 2.118H6.622a2.25 2.25 0 01-2.247-2.118L3.75 7.5M10 11.25h4M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125z" />
</svg>
{% endif %}
{% if path == "reports" %}
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="stroke-amber-500 dark:stroke-amber-500 h-6 w-6 relative">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 3v1.5M3 21v-6m0 0 2.77-.693a9 9 0 0 1 6.208.682l.108.054a9 9 0 0 0 6.086.71l3.114-.732a48.524 48.524 0 0 1-.005-10.499l-3.11.732a9 9 0 0 1-6.085-.711l-.108-.054a9 9 0 0 0-6.208-.682L3 4.5M3 15V4.5" />
</svg>
{% endif %}
{% if path == "bans" %}
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="stroke-red-500 dark:stroke-red-500 h-6 w-6 relative">
<path stroke-linecap="round" stroke-linejoin="round" d="M18.364 18.364A9 9 0 0 0 5.636 5.636m12.728 12.728A9 9 0 0 1 5.636 5.636m12.728 12.728L5.636 5.636" />
</svg>
{% endif %}
{% if path == "jobs" %}
<svg class="stroke-emerald-600 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M10.125 2.25h-4.5c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125v-9M10.125 2.25h.375a9 9 0 019 9v.375M10.125 2.25A3.375 3.375 0 0113.5 5.625v1.5c0 .621.504 1.125 1.125 1.125h1.5a3.375 3.375 0 013.375 3.375M9 15l2.25 2.25L15 12" />
</svg>
{% endif %}
{% if path == "logs" %}
<svg class="stroke-gray-600 dark:fill-gray-500 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 6.75h12M8.25 12h12m-12 5.25h12M3.75 6.75h.007v.008H3.75V6.75zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zM3.75 12h.007v.008H3.75V12zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm-.375 5.25h.007v.008H3.75v-.008zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" />
</svg>
{% endif %}
</div>
<span class="ml-1 duration-300 opacity-100 pointer-events-none ease">{{ path[0]|upper }}{{ path[1:].replace('_', ' ') }}</span>
</a>
</li>
{% endfor %}
<!-- end loop paths-->
</ul>
<!-- end default anchor -->
<!-- plugin list -->
{% set isPage = {'value': False} %} {% set plugins = config["CONFIG"].get_plugins() %}
{% for plugin in plugins %}
{% if
plugin['page'] %}
{% if isPage.update({"value": True}) %}{% endif %}
{%
endif %}
{% endfor %}
<div>
<ul>
{% if isPage.value == True %}
<li class="w-full mt-4">
<h6 class="pl-6 ml-2 text-xs font-bold leading-tight uppercase dark:text-white opacity-60">PLUGINS PAGE</h6>
</li>
{% else %}
<li class="w-full mt-8">
<h6 class="text-center pl-6 pr-8 ml-2 text-xs leading-tight uppercase text-gray-600/90 dark:text-white/80">
Want your own plugins ?
<br />
<a class="leading-8 font-bold hover:brightness-75"
target="_blank"
href="https://docs.bunkerweb.io/latest/plugins/?utm_campaign=self&utm_source=ui#writing-a-plugin">check doc</a>
</h6>
</li>
{% endif %}
{% for plugin in plugins %}
{% if plugin['page'] %}
<li class="mt-0.5 w-full">
<a class="dark:hover:bg-primary/20 hover:bg-primary/5 hover:rounded-lg dark:text-white dark:opacity-80 py-1 text-sm ease-nav-brand my-0 mx-2 flex items-center whitespace-nowrap px-4 transition"
href="{{ request.url_root }}plugins/{{ plugin['id'] }}">
<div class="mr-2 flex items-center justify-center rounded-lg bg-center stroke-0 text-center p-1 xl:p-1.5">
<svg class="fill-gray-500 h-5 w-5 relative"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 384 512">
<path d="M0 64C0 28.7 28.7 0 64 0H224V128c0 17.7 14.3 32 32 32H384V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V64zm384 64H256V0L384 128z" />
</svg>
</div>
<span class="ml-1 duration-300 opacity-100 pointer-events-none ease">{{ plugin['name'] }}</span>
</a>
</li>
{% endif %}
{% endfor %}
{% if plugins_pro %}
{% for plugin in plugins_pro %}
<a {% if not is_pro_version %}target="_blank"{% endif %}
class="dark:hover:bg-primary/20 hover:bg-primary/5 hover:rounded-lg dark:text-white dark:opacity-80 py-1 text-sm ease-nav-brand my-0 mx-2 flex items-center whitespace-nowrap px-4 transition"
href="{% if not is_pro_version %}https://panel.bunkerweb.io/{% else %}{{ request.url_root }}plugins/{{ plugin['id'] }}{% endif %}">
<div class="mr-2 flex items-center justify-center rounded-lg bg-center stroke-0 text-center p-1 xl:p-1.5">
<svg class="h-5 w-5 dark:brightness-90"
viewBox="0 0 48 46"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path class="fill-yellow-500" d="M43.218 28.2327L43.6765 23.971C43.921 21.6973 44.0825 20.1957 43.9557 19.2497L44 19.25C46.071 19.25 47.75 17.5711 47.75 15.5C47.75 13.4289 46.071 11.75 44 11.75C41.929 11.75 40.25 13.4289 40.25 15.5C40.25 16.4366 40.5935 17.2931 41.1613 17.9503C40.346 18.4535 39.2805 19.515 37.6763 21.1128C36.4405 22.3438 35.8225 22.9593 35.1333 23.0548C34.7513 23.1075 34.3622 23.0532 34.0095 22.898C33.373 22.6175 32.9485 21.8567 32.0997 20.335L27.6262 12.3135C27.1025 11.3747 26.6642 10.5889 26.2692 9.95662C27.89 9.12967 29 7.44445 29 5.5C29 2.73857 26.7615 0.5 24 0.5C21.2385 0.5 19 2.73857 19 5.5C19 7.44445 20.11 9.12967 21.7308 9.95662C21.3358 10.589 20.8975 11.3746 20.3738 12.3135L15.9002 20.335C15.0514 21.8567 14.627 22.6175 13.9905 22.898C13.6379 23.0532 13.2487 23.1075 12.8668 23.0548C12.1774 22.9593 11.5595 22.3438 10.3238 21.1128C8.71968 19.515 7.6539 18.4535 6.83882 17.9503C7.4066 17.2931 7.75 16.4366 7.75 15.5C7.75 13.4289 6.07107 11.75 4 11.75C1.92893 11.75 0.25 13.4289 0.25 15.5C0.25 17.5711 1.92893 19.25 4 19.25L4.04428 19.2497C3.91755 20.1957 4.07905 21.6973 4.32362 23.971L4.782 28.2327C5.03645 30.5982 5.24802 32.849 5.50717 34.875H42.4928C42.752 32.849 42.9635 30.5982 43.218 28.2327Z" fill="#1C274C" />
<path class="fill-yellow-500" d="M21.2803 45.5H26.7198C33.8098 45.5 37.3545 45.5 39.7198 43.383C40.7523 42.4588 41.4057 40.793 41.8775 38.625H6.1224C6.59413 40.793 7.24783 42.4588 8.2802 43.383C10.6454 45.5 14.1903 45.5 21.2803 45.5Z" fill="#1C274C" />
</svg>
</div>
<span class="ml-1 duration-300 {% if not is_plugin_pro %}opacity-80 dark:opacity-60{% endif %} pointer-events-none ease">{{ plugin['name'] }}</span>
</a>
</li>
{% endfor %}
{% endif %}
</ul>
<!-- end plugin list -->
</div>
</div>
<!-- end list items -->
</div>
<!-- end top sidebar -->
<!-- bottom sidebar -->
<div class="w-full flex flex-col justify-end m-4">
<!-- dark/light mode -->
<div class="min-h-6 my-4 ml-12 flex justify-start">
<input type="hidden"
id="csrf_token"
name="csrf_token"
value="{{ csrf_token() }}" />
<input {% if dark_mode == True %}checked{% endif %}
id="darkMode"
data-dark-toggle
class="dark:brightness-125 hover:brightness-75 rounded-10 duration-300 ease-in-out after:rounded-circle after:shadow-2xl after:duration-300 checked:after:translate-x-5.3 h-5 mt-0.5 relative float-left w-10 cursor-pointer appearance-none border border-solid border-gray-200 bg-slate-800/10 bg-none bg-contain bg-left bg-no-repeat align-top transition-all after:absolute after:top-px after:h-4 after:w-4 after:translate-x-px after:bg-white after:content-[''] checked:border-primary checked:bg-primary checked:bg-none checked:bg-right"
type="checkbox" />
<label for="darkMode"
data-dark-toggle-label
class="dark:text-white dark:opacity-80 transition inline-block pl-3 mb-0 ml-0 font-normal cursor-pointer select-none text-sm text-slate-700">
{% if dark_mode == True %}
dark mode
{% else %}
light mode
{% endif %}
</label>
</div>
<!-- end dark/light mode -->
<!-- social-->
<ul class="mb-3 flex justify-center align-middle w-full">
<li class="mx-2 w-6">
<a aria-label="link to twitter"
href="https://twitter.com/bunkerity"
target="_blank">
<svg class="hover:opacity-80"
fill="#1DA1F2"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z" />
</svg>
</a>
</li>
<li class="mx-2.5 w-6">
<a aria-label="link to linkedin"
href="https://www.linkedin.com/company/bunkerity/"
target="_blank">
<svg fill="#0A63BC"
class="hover:opacity-80 dark:brightness-110"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512">
<path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z" />
</svg>
</a>
</li>
<li class="mx-2.5 w-6 -translate-y-1">
<a aria-label="link to discord"
href="https://discord.gg/fTf46FmtyD"
target="_blank">
<svg class="translate-y-1 hover:opacity-80"
fill="#5562EA"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M524.531,69.836a1.5,1.5,0,0,0-.764-.7A485.065,485.065,0,0,0,404.081,32.03a1.816,1.816,0,0,0-1.923.91,337.461,337.461,0,0,0-14.9,30.6,447.848,447.848,0,0,0-134.426,0,309.541,309.541,0,0,0-15.135-30.6,1.89,1.89,0,0,0-1.924-.91A483.689,483.689,0,0,0,116.085,69.137a1.712,1.712,0,0,0-.788.676C39.068,183.651,18.186,294.69,28.43,404.354a2.016,2.016,0,0,0,.765,1.375A487.666,487.666,0,0,0,176.02,479.918a1.9,1.9,0,0,0,2.063-.676A348.2,348.2,0,0,0,208.12,430.4a1.86,1.86,0,0,0-1.019-2.588,321.173,321.173,0,0,1-45.868-21.853,1.885,1.885,0,0,1-.185-3.126c3.082-2.309,6.166-4.711,9.109-7.137a1.819,1.819,0,0,1,1.9-.256c96.229,43.917,200.41,43.917,295.5,0a1.812,1.812,0,0,1,1.924.233c2.944,2.426,6.027,4.851,9.132,7.16a1.884,1.884,0,0,1-.162,3.126,301.407,301.407,0,0,1-45.89,21.83,1.875,1.875,0,0,0-1,2.611,391.055,391.055,0,0,0,30.014,48.815,1.864,1.864,0,0,0,2.063.7A486.048,486.048,0,0,0,610.7,405.729a1.882,1.882,0,0,0,.765-1.352C623.729,277.594,590.933,167.465,524.531,69.836ZM222.491,337.58c-28.972,0-52.844-26.587-52.844-59.239S193.056,219.1,222.491,219.1c29.665,0,53.306,26.82,52.843,59.239C275.334,310.993,251.924,337.58,222.491,337.58Zm195.38,0c-28.971,0-52.843-26.587-52.843-59.239S388.437,219.1,417.871,219.1c29.667,0,53.307,26.82,52.844,59.239C470.715,310.993,447.538,337.58,417.871,337.58Z" />
</svg>
</a>
</li>
<li class="mx-2.5 w-6">
<a aria-label="link to github"
href="https://github.com/bunkerity"
target="_blank">
<svg class="hover:opacity-80 dark:fill-gray-600"
fill="#171A1F"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 496 512">
<path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z" />
</svg>
</a>
</li>
</ul>
<!-- end social-->
<!-- logout-->
<!-- close btn-->
<button aria-controls="sidebar-menu"
aria-expanded="false"
aria-label="close menu sidebar"
data-sidebar-menu-close>
<svg class="xl:hidden fill-gray-600 dark:fill-gray-300 dark:opacity-80 absolute h-6 w-6 top-4 right-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" />
</svg>
</button>
<!-- close btn-->
<!-- top sidebar -->
<div class="w-full">
<a href="logout"
class="tracking-wide dark:brightness-125 hover:brightness-75 w-full inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-gradient-to-tl bg-primary leading-normal text-xs ease-in shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Logout
</a>
<!-- logo and version -->
<div class="h-19">
<a aria-label="link to home"
class="flex justify-center px-8 py-6 m-0 text-sm whitespace-nowrap dark:text-white text-slate-700"
href="{% if current_endpoint == 'home' %}#{% else %}loading?next={{ url_for("home") }}{% endif %}">
<img src="images/logo-menu-2.png"
class="hidden dark:inline w-28 sm:w-36 transition-all duration-200 h-8 sm:h-10"
alt="main logo" />
<img src="images/logo-menu.png"
class="dark:hidden inline w-28 sm:w-36 transition-all duration-200 h-8 sm:h-10"
alt="main logo" />
</a>
</div>
<div class="w-full px-1">
<h1 class="mb-0.5 tracking-normal text-primary text-center text-lg break-words whitespace-normal dark:text-gray-300">
{{ username }}
</h1>
<a class="block underline mb-2 text-gray-600 dark:text-gray-400 text-sm text-center hover:brightness-90"
href="{% if current_endpoint == 'account' %}#{% else %}loading?next={{ url_for("account") }}{% endif %}">manage account
</a>
</div>
<hr class="h-px mt-0 bg-transparent bg-gradient-to-r from-transparent via-black/40 to-transparent dark:bg-gradient-to-r dark:from-transparent dark:via-white dark:to-transparent" />
<!-- end logo version -->
<!-- list items -->
<div class="items-center block w-auto max-h-screen overflow-auto h-sidenav grow basis-full">
<!-- default anchor -->
<ul class="flex flex-col pl-0 mb-0">
{% set paths = [
"home",
"instances",
"global_config",
"services",
"configs",
"plugins",
"cache",
"reports",
"bans",
"jobs",
"logs"
] %}
<!-- loop paths -->
{% for path in paths %}
<li class="mt-0.5 w-full">
<a class="{% if current_endpoint == path %} font-semibold text-slate-700 dark:bg-primary/50 rounded-lg dark:hover:bg-primary/60 bg-primary/10 hover:bg-primary/30 {% else %} dark:hover:bg-primary/20 hover:bg-primary/5 {% endif %} dark:text-white dark:opacity-80 py-1 ease-nav-brand my-0 mx-2 flex items-center whitespace-nowrap rounded-lg px-4 transition text-sm"
href="{% if current_endpoint == path %}#{% else %}loading?next={{ url_for(path) }}{% endif %}">
<div class="mr-2 flex items-center justify-center rounded-lg bg-center stroke-0 text-center p-1 xl:p-1.5">
{% if path == "home" %}
<svg class="stroke-sky-500 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
</svg>
{% endif %}
{% if path == "instances" %}
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="stroke-stone-500 h-5.5 w-5.5 relative">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9" />
</svg>
{% endif %}
{% if path == "global_config" %}
<svg class="stroke-blue-400 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75" />
</svg>
{% endif %}
{% if path == "services" %}
<svg class="stroke-orange-500 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 17.25v-.228a4.5 4.5 0 00-.12-1.03l-2.268-9.64a3.375 3.375 0 00-3.285-2.602H7.923a3.375 3.375 0 00-3.285 2.602l-2.268 9.64a4.5 4.5 0 00-.12 1.03v.228m19.5 0a3 3 0 01-3 3H5.25a3 3 0 01-3-3m19.5 0a3 3 0 00-3-3H5.25a3 3 0 00-3 3m16.5 0h.008v.008h-.008v-.008zm-3 0h.008v.008h-.008v-.008z" />
</svg>
{% endif %}
{% if path == "configs" %}
<svg class="stroke-blue-500 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
{% endif %}
{% if path == "plugins" %}
<svg class="stroke-yellow-400 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.25 6.087c0-.355.186-.676.401-.959.221-.29.349-.634.349-1.003 0-1.036-1.007-1.875-2.25-1.875s-2.25.84-2.25 1.875c0 .369.128.713.349 1.003.215.283.401.604.401.959v0a.64.64 0 01-.657.643 48.39 48.39 0 01-4.163-.3c.186 1.613.293 3.25.315 4.907a.656.656 0 01-.658.663v0c-.355 0-.676-.186-.959-.401a1.647 1.647 0 00-1.003-.349c-1.036 0-1.875 1.007-1.875 2.25s.84 2.25 1.875 2.25c.369 0 .713-.128 1.003-.349.283-.215.604-.401.959-.401v0c.31 0 .555.26.532.57a48.039 48.039 0 01-.642 5.056c1.518.19 3.058.309 4.616.354a.64.64 0 00.657-.643v0c0-.355-.186-.676-.401-.959a1.647 1.647 0 01-.349-1.003c0-1.035 1.008-1.875 2.25-1.875 1.243 0 2.25.84 2.25 1.875 0 .369-.128.713-.349 1.003-.215.283-.4.604-.4.959v0c0 .333.277.599.61.58a48.1 48.1 0 005.427-.63 48.05 48.05 0 00.582-4.717.532.532 0 00-.533-.57v0c-.355 0-.676.186-.959.401-.29.221-.634.349-1.003.349-1.035 0-1.875-1.007-1.875-2.25s.84-2.25 1.875-2.25c.37 0 .713.128 1.003.349.283.215.604.401.96.401v0a.656.656 0 00.658-.663 48.422 48.422 0 00-.37-5.36c-1.886.342-3.81.574-5.766.689a.578.578 0 01-.61-.58v0z" />
</svg>
{% endif %}
{% if path == "cache" %}
<svg class="stroke-pink-600 h-5.5 w-5.5 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M20.25 7.5l-.625 10.632a2.25 2.25 0 01-2.247 2.118H6.622a2.25 2.25 0 01-2.247-2.118L3.75 7.5M10 11.25h4M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125z" />
</svg>
{% endif %}
{% if path == "reports" %}
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="stroke-amber-500 dark:stroke-amber-500 h-6 w-6 relative">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 3v1.5M3 21v-6m0 0 2.77-.693a9 9 0 0 1 6.208.682l.108.054a9 9 0 0 0 6.086.71l3.114-.732a48.524 48.524 0 0 1-.005-10.499l-3.11.732a9 9 0 0 1-6.085-.711l-.108-.054a9 9 0 0 0-6.208-.682L3 4.5M3 15V4.5" />
</svg>
{% endif %}
{% if path == "bans" %}
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="stroke-red-500 dark:stroke-red-500 h-6 w-6 relative">
<path stroke-linecap="round" stroke-linejoin="round" d="M18.364 18.364A9 9 0 0 0 5.636 5.636m12.728 12.728A9 9 0 0 1 5.636 5.636m12.728 12.728L5.636 5.636" />
</svg>
{% endif %}
{% if path == "jobs" %}
<svg class="stroke-emerald-600 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M10.125 2.25h-4.5c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125v-9M10.125 2.25h.375a9 9 0 019 9v.375M10.125 2.25A3.375 3.375 0 0113.5 5.625v1.5c0 .621.504 1.125 1.125 1.125h1.5a3.375 3.375 0 013.375 3.375M9 15l2.25 2.25L15 12" />
</svg>
{% endif %}
{% if path == "logs" %}
<svg class="stroke-gray-600 dark:fill-gray-500 h-6 w-6 relative"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 6.75h12M8.25 12h12m-12 5.25h12M3.75 6.75h.007v.008H3.75V6.75zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zM3.75 12h.007v.008H3.75V12zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm-.375 5.25h.007v.008H3.75v-.008zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" />
</svg>
{% endif %}
</div>
<span class="ml-1 duration-300 opacity-100 pointer-events-none ease">{{ path[0]|upper }}{{ path[1:].replace('_', ' ') }}</span>
</a>
</li>
{% endfor %}
<!-- end loop paths-->
</ul>
<!-- end default anchor -->
<!-- plugin list -->
{% set isPage = {'value': False} %} {% set plugins = config["CONFIG"].get_plugins() %}
{% for plugin in plugins %}
{% if
plugin['page'] %}
{% if isPage.update({"value": True}) %}{% endif %}
{%
endif %}
{% endfor %}
<div>
<ul>
{% if isPage.value == True %}
<li class="w-full mt-4">
<h6 class="pl-6 ml-2 text-xs font-bold leading-tight uppercase dark:text-white opacity-60">PLUGINS PAGE</h6>
</li>
{% else %}
<li class="w-full mt-8">
<h6 class="text-center pl-6 pr-8 ml-2 text-xs leading-tight uppercase text-gray-600/90 dark:text-white/80">
Want your own plugins ?
<br />
<a class="leading-8 font-bold hover:brightness-75"
target="_blank"
href="https://docs.bunkerweb.io/latest/plugins/?utm_campaign=self&utm_source=ui#writing-a-plugin">check doc</a>
</h6>
</li>
{% endif %}
{% for plugin in plugins %}
{% if plugin['page'] %}
<li class="mt-0.5 w-full">
<a class="dark:hover:bg-primary/20 hover:bg-primary/5 hover:rounded-lg dark:text-white dark:opacity-80 py-1 text-sm ease-nav-brand my-0 mx-2 flex items-center whitespace-nowrap px-4 transition"
href="{{ request.url_root }}plugins/{{ plugin['id'] }}">
<div class="mr-2 flex items-center justify-center rounded-lg bg-center stroke-0 text-center p-1 xl:p-1.5">
<svg class="fill-gray-500 h-5 w-5 relative"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 384 512">
<path d="M0 64C0 28.7 28.7 0 64 0H224V128c0 17.7 14.3 32 32 32H384V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V64zm384 64H256V0L384 128z" />
</svg>
</div>
<span class="ml-1 duration-300 opacity-100 pointer-events-none ease">{{ plugin['name'] }}</span>
</a>
</li>
{% endif %}
{% endfor %}
{% if plugins_pro %}
{% for plugin in plugins_pro %}
<a {% if not is_pro_version %}target="_blank"{% endif %}
class="dark:hover:bg-primary/20 hover:bg-primary/5 hover:rounded-lg dark:text-white dark:opacity-80 py-1 text-sm ease-nav-brand my-0 mx-2 flex items-center whitespace-nowrap px-4 transition"
href="{% if not is_pro_version %}https://panel.bunkerweb.io/{% else %}{{ request.url_root }}plugins/{{ plugin['id'] }}{% endif %}">
<div class="mr-2 flex items-center justify-center rounded-lg bg-center stroke-0 text-center p-1 xl:p-1.5">
<svg class="h-5 w-5 dark:brightness-90"
viewBox="0 0 48 46"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path class="fill-yellow-500" d="M43.218 28.2327L43.6765 23.971C43.921 21.6973 44.0825 20.1957 43.9557 19.2497L44 19.25C46.071 19.25 47.75 17.5711 47.75 15.5C47.75 13.4289 46.071 11.75 44 11.75C41.929 11.75 40.25 13.4289 40.25 15.5C40.25 16.4366 40.5935 17.2931 41.1613 17.9503C40.346 18.4535 39.2805 19.515 37.6763 21.1128C36.4405 22.3438 35.8225 22.9593 35.1333 23.0548C34.7513 23.1075 34.3622 23.0532 34.0095 22.898C33.373 22.6175 32.9485 21.8567 32.0997 20.335L27.6262 12.3135C27.1025 11.3747 26.6642 10.5889 26.2692 9.95662C27.89 9.12967 29 7.44445 29 5.5C29 2.73857 26.7615 0.5 24 0.5C21.2385 0.5 19 2.73857 19 5.5C19 7.44445 20.11 9.12967 21.7308 9.95662C21.3358 10.589 20.8975 11.3746 20.3738 12.3135L15.9002 20.335C15.0514 21.8567 14.627 22.6175 13.9905 22.898C13.6379 23.0532 13.2487 23.1075 12.8668 23.0548C12.1774 22.9593 11.5595 22.3438 10.3238 21.1128C8.71968 19.515 7.6539 18.4535 6.83882 17.9503C7.4066 17.2931 7.75 16.4366 7.75 15.5C7.75 13.4289 6.07107 11.75 4 11.75C1.92893 11.75 0.25 13.4289 0.25 15.5C0.25 17.5711 1.92893 19.25 4 19.25L4.04428 19.2497C3.91755 20.1957 4.07905 21.6973 4.32362 23.971L4.782 28.2327C5.03645 30.5982 5.24802 32.849 5.50717 34.875H42.4928C42.752 32.849 42.9635 30.5982 43.218 28.2327Z" fill="#1C274C" />
<path class="fill-yellow-500" d="M21.2803 45.5H26.7198C33.8098 45.5 37.3545 45.5 39.7198 43.383C40.7523 42.4588 41.4057 40.793 41.8775 38.625H6.1224C6.59413 40.793 7.24783 42.4588 8.2802 43.383C10.6454 45.5 14.1903 45.5 21.2803 45.5Z" fill="#1C274C" />
</svg>
</div>
<span class="ml-1 duration-300 {% if not is_plugin_pro %}opacity-80 dark:opacity-60{% endif %} pointer-events-none ease">{{ plugin['name'] }}</span>
</a>
</li>
{% endfor %}
{% endif %}
</ul>
<!-- end plugin list -->
</div>
</div>
<!-- end list items -->
</div>
<!-- end logout-->
</div>
<!-- end bottom sidebar -->
<!-- end top sidebar -->
<!-- bottom sidebar -->
<div class="w-full flex flex-col justify-end m-4">
<!-- dark/light mode -->
<div class="min-h-6 my-4 ml-12 flex justify-start">
<input type="hidden"
id="csrf_token"
name="csrf_token"
value="{{ csrf_token() }}" />
<input {% if dark_mode == True %}checked{% endif %}
id="darkMode"
data-dark-toggle
class="dark:brightness-125 hover:brightness-75 rounded-10 duration-300 ease-in-out after:rounded-circle after:shadow-2xl after:duration-300 checked:after:translate-x-5.3 h-5 mt-0.5 relative float-left w-10 cursor-pointer appearance-none border border-solid border-gray-200 bg-slate-800/10 bg-none bg-contain bg-left bg-no-repeat align-top transition-all after:absolute after:top-px after:h-4 after:w-4 after:translate-x-px after:bg-white after:content-[''] checked:border-primary checked:bg-primary checked:bg-none checked:bg-right"
type="checkbox" />
<label for="darkMode"
data-dark-toggle-label
class="dark:text-white dark:opacity-80 transition inline-block pl-3 mb-0 ml-0 font-normal cursor-pointer select-none text-sm text-slate-700">
{% if dark_mode == True %}
dark mode
{% else %}
light mode
{% endif %}
</label>
</div>
<!-- end dark/light mode -->
<!-- social-->
<ul class="mb-3 flex justify-center align-middle w-full">
<li class="mx-2 w-6">
<a aria-label="link to twitter"
href="https://twitter.com/bunkerity"
target="_blank">
<svg class="hover:opacity-80"
fill="#1DA1F2"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z" />
</svg>
</a>
</li>
<li class="mx-2.5 w-6">
<a aria-label="link to linkedin"
href="https://www.linkedin.com/company/bunkerity/"
target="_blank">
<svg fill="#0A63BC"
class="hover:opacity-80 dark:brightness-110"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512">
<path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z" />
</svg>
</a>
</li>
<li class="mx-2.5 w-6 -translate-y-1">
<a aria-label="link to discord"
href="https://discord.gg/fTf46FmtyD"
target="_blank">
<svg class="translate-y-1 hover:opacity-80"
fill="#5562EA"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M524.531,69.836a1.5,1.5,0,0,0-.764-.7A485.065,485.065,0,0,0,404.081,32.03a1.816,1.816,0,0,0-1.923.91,337.461,337.461,0,0,0-14.9,30.6,447.848,447.848,0,0,0-134.426,0,309.541,309.541,0,0,0-15.135-30.6,1.89,1.89,0,0,0-1.924-.91A483.689,483.689,0,0,0,116.085,69.137a1.712,1.712,0,0,0-.788.676C39.068,183.651,18.186,294.69,28.43,404.354a2.016,2.016,0,0,0,.765,1.375A487.666,487.666,0,0,0,176.02,479.918a1.9,1.9,0,0,0,2.063-.676A348.2,348.2,0,0,0,208.12,430.4a1.86,1.86,0,0,0-1.019-2.588,321.173,321.173,0,0,1-45.868-21.853,1.885,1.885,0,0,1-.185-3.126c3.082-2.309,6.166-4.711,9.109-7.137a1.819,1.819,0,0,1,1.9-.256c96.229,43.917,200.41,43.917,295.5,0a1.812,1.812,0,0,1,1.924.233c2.944,2.426,6.027,4.851,9.132,7.16a1.884,1.884,0,0,1-.162,3.126,301.407,301.407,0,0,1-45.89,21.83,1.875,1.875,0,0,0-1,2.611,391.055,391.055,0,0,0,30.014,48.815,1.864,1.864,0,0,0,2.063.7A486.048,486.048,0,0,0,610.7,405.729a1.882,1.882,0,0,0,.765-1.352C623.729,277.594,590.933,167.465,524.531,69.836ZM222.491,337.58c-28.972,0-52.844-26.587-52.844-59.239S193.056,219.1,222.491,219.1c29.665,0,53.306,26.82,52.843,59.239C275.334,310.993,251.924,337.58,222.491,337.58Zm195.38,0c-28.971,0-52.843-26.587-52.843-59.239S388.437,219.1,417.871,219.1c29.667,0,53.307,26.82,52.844,59.239C470.715,310.993,447.538,337.58,417.871,337.58Z" />
</svg>
</a>
</li>
<li class="mx-2.5 w-6">
<a aria-label="link to github"
href="https://github.com/bunkerity"
target="_blank">
<svg class="hover:opacity-80 dark:fill-gray-600"
fill="#171A1F"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 496 512">
<path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z" />
</svg>
</a>
</li>
</ul>
<!-- end social-->
<!-- logout-->
<div class="w-full">
<a href="logout"
class="tracking-wide dark:brightness-125 hover:brightness-75 w-full inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-gradient-to-tl bg-primary leading-normal text-xs ease-in shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Logout
</a>
</div>
<!-- end logout-->
</div>
<!-- end bottom sidebar -->
</aside>
<!-- end left sidebar -->

View file

@ -4,11 +4,11 @@
aria-expanded="false"
aria-label="Open news sidebar"
class="transition-all scale-90 sm:scale-100 dark:brightness-95 dark:hover:brightness-105 hover:brightness-75 fixed p-3 text-xl bg-white shadow-sm cursor-pointer top-[4.5rem] right-5 sm:right-40 xl:right-6 z-990 rounded-circle text-slate-700">
<svg class="fill-sky-500 h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M96 96c0-35.3 28.7-64 64-64H448c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H80c-44.2 0-80-35.8-80-80V128c0-17.7 14.3-32 32-32s32 14.3 32 32V400c0 8.8 7.2 16 16 16s16-7.2 16-16V96zm64 24v80c0 13.3 10.7 24 24 24H424c13.3 0 24-10.7 24-24V120c0-13.3-10.7-24-24-24H184c-13.3 0-24 10.7-24 24zm0 184c0 8.8 7.2 16 16 16h96c8.8 0 16-7.2 16-16s-7.2-16-16-16H176c-8.8 0-16 7.2-16 16zm160 0c0 8.8 7.2 16 16 16h96c8.8 0 16-7.2 16-16s-7.2-16-16-16H336c-8.8 0-16 7.2-16 16zM160 400c0 8.8 7.2 16 16 16h96c8.8 0 16-7.2 16-16s-7.2-16-16-16H176c-8.8 0-16 7.2-16 16zm160 0c0 8.8 7.2 16 16 16h96c8.8 0 16-7.2 16-16s-7.2-16-16-16H336c-8.8 0-16 7.2-16 16z" />
</svg>
<svg class="fill-sky-500 h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M96 96c0-35.3 28.7-64 64-64H448c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H80c-44.2 0-80-35.8-80-80V128c0-17.7 14.3-32 32-32s32 14.3 32 32V400c0 8.8 7.2 16 16 16s16-7.2 16-16V96zm64 24v80c0 13.3 10.7 24 24 24H424c13.3 0 24-10.7 24-24V120c0-13.3-10.7-24-24-24H184c-13.3 0-24 10.7-24 24zm0 184c0 8.8 7.2 16 16 16h96c8.8 0 16-7.2 16-16s-7.2-16-16-16H176c-8.8 0-16 7.2-16 16zm160 0c0 8.8 7.2 16 16 16h96c8.8 0 16-7.2 16-16s-7.2-16-16-16H336c-8.8 0-16 7.2-16 16zM160 400c0 8.8 7.2 16 16 16h96c8.8 0 16-7.2 16-16s-7.2-16-16-16H176c-8.8 0-16 7.2-16 16zm160 0c0 8.8 7.2 16 16 16h96c8.8 0 16-7.2 16-16s-7.2-16-16-16H336c-8.8 0-16 7.2-16 16z" />
</svg>
</button>
<!-- end float button-->
<!-- right sidebar -->
@ -16,91 +16,91 @@
aria-hidden="true"
data-sidebar-info
class="translate-x-90 -right-0 transition z-sticky dark:bg-slate-850 dark:brightness-110 shadow-3xl max-w-full w-90 ease fixed top-0 left-auto flex h-full min-w-0 flex-col break-words rounded-none border-0 bg-white bg-clip-border px-0.5">
<!-- close btn-->
<button aria-controls="sidebar-news"
aria-expanded="false"
aria-label="close news sidebar"
data-sidebar-info-close>
<svg class="fill-gray-600 dark:fill-gray-300 dark:opacity-80 absolute h-8 w-8 top-4 right-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" />
</svg>
</button>
<!-- close btn-->
<!-- header -->
<div class="px-6 pt-4 pb-0 mb-0 border-b-0 rounded-t-2xl">
<div class="float-left">
<h5 class="mt-4 mb-0 dark:text-white font-bold">NEWS</h5>
<p class="dark:text-white dark:opacity-80 mb-0">Stay up to date.</p>
</div>
<!-- close button -->
<div class="float-right mt-6">
<button aria-label="close news sidebar"
data-sidebar-info-close
class="inline-block p-0 mb-4 text-sm font-bold leading-normal text-center uppercase align-middle transition-all ease-in bg-transparent border-0 rounded-lg shadow-none cursor-pointer hover:-translate-y-px tracking-tight-rem bg-150 bg-x-25 active:opacity-85 dark:text-white text-slate-700">
<i class="fa fa-close"></i>
</button>
</div>
<!-- end close button -->
</div>
<hr class="h-px mx-0 my-1 bg-transparent bg-gradient-to-r from-transparent via-black/40 to-transparent dark:bg-gradient-to-r dark:from-transparent dark:via-white dark:to-transparent" />
<!-- end header -->
<!-- news-->
<div data-news-container class="flex-auto overflow-auto">
<p class="text-center col-span-12 relative w-full p-4 text-blue-500 rounded-lg">Impossible to connect to blog news.</p>
</div>
<!-- end news-->
<!-- newsletter -->
<hr class="h-px mx-0 my-1 bg-transparent bg-gradient-to-r from-transparent via-black/40 to-transparent dark:bg-gradient-to-r dark:from-transparent dark:via-white dark:to-transparent" />
<form action="https://bunkerity.us1.list-manage.com/subscribe/post?u=ec5b1577cf427972b9bd491a6&amp;id=37076d9d67"
method="POST"
class="px-6 pt-4 pb-0 mb-0 border-b-0 min-h-52"
id="subscribe-newsletter">
<h5 class="mb-4 dark:text-white font-bold">JOIN THE NEWSLETTER</h5>
<div class="flex">
<label for="newsletter-email" class="sr-only">EMAIL</label>
<input type="email"
id="newsletter-email"
name="EMAIL"
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"
placeholder="John.doe@example.com"
required />
</div>
<div class="block mt-2 mb-4">
<div class="relative">
<div data-checkbox-handler="newsletter-check"
class="relative mb-7 md:mb-0">
<label class="hidden" for="newsletter-check">agree privacy</label>
<input id="newsletter-check"
name="newsletter-check"
class="mr-2 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"
data-pattern="^(yes|no)$"
value="no"
required />
<svg data-checkbox-handler="newsletter-check"
class="pointer-events-none 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>
<label class="text-sm dark:text-gray-300" for="newsletter-check">
I've read and agree to the
<a class="italic"
href="https://www.bunkerity.com/privacy-policy/?utm_campaign=self&utm_source=ui"
target="_blank">privacy policy</a>
</label>
</div>
<button type="submit"
formtarget="_blank"
class="dark:brightness-125 hover:brightness-75 w-full inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-gradient-to-tl bg-primary leading-normal text-xs ease-in tracking-wide shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Subscribe
<!-- close btn-->
<button aria-controls="sidebar-news"
aria-expanded="false"
aria-label="close news sidebar"
data-sidebar-info-close>
<svg class="fill-gray-600 dark:fill-gray-300 dark:opacity-80 absolute h-8 w-8 top-4 right-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" />
</svg>
</button>
</form>
<!-- end newsletter -->
<!-- close btn-->
<!-- header -->
<div class="px-6 pt-4 pb-0 mb-0 border-b-0 rounded-t-2xl">
<div class="float-left">
<h5 class="mt-4 mb-0 dark:text-white font-bold">NEWS</h5>
<p class="dark:text-white dark:opacity-80 mb-0">Stay up to date.</p>
</div>
<!-- close button -->
<div class="float-right mt-6">
<button aria-label="close news sidebar"
data-sidebar-info-close
class="inline-block p-0 mb-4 text-sm font-bold leading-normal text-center uppercase align-middle transition-all ease-in bg-transparent border-0 rounded-lg shadow-none cursor-pointer hover:-translate-y-px tracking-tight-rem bg-150 bg-x-25 active:opacity-85 dark:text-white text-slate-700">
<i class="fa fa-close"></i>
</button>
</div>
<!-- end close button -->
</div>
<hr class="h-px mx-0 my-1 bg-transparent bg-gradient-to-r from-transparent via-black/40 to-transparent dark:bg-gradient-to-r dark:from-transparent dark:via-white dark:to-transparent" />
<!-- end header -->
<!-- news-->
<div data-news-container class="flex-auto overflow-auto">
<p class="text-center col-span-12 relative w-full p-4 text-blue-500 rounded-lg">Impossible to connect to blog news.</p>
</div>
<!-- end news-->
<!-- newsletter -->
<hr class="h-px mx-0 my-1 bg-transparent bg-gradient-to-r from-transparent via-black/40 to-transparent dark:bg-gradient-to-r dark:from-transparent dark:via-white dark:to-transparent" />
<form action="https://bunkerity.us1.list-manage.com/subscribe/post?u=ec5b1577cf427972b9bd491a6&amp;id=37076d9d67"
method="POST"
class="px-6 pt-4 pb-0 mb-0 border-b-0 min-h-52"
id="subscribe-newsletter">
<h5 class="mb-4 dark:text-white font-bold">JOIN THE NEWSLETTER</h5>
<div class="flex">
<label for="newsletter-email" class="sr-only">EMAIL</label>
<input type="email"
id="newsletter-email"
name="EMAIL"
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"
placeholder="John.doe@example.com"
required />
</div>
<div class="block mt-2 mb-4">
<div class="relative">
<div data-checkbox-handler="newsletter-check"
class="relative mb-7 md:mb-0">
<label class="hidden" for="newsletter-check">agree privacy</label>
<input id="newsletter-check"
name="newsletter-check"
class="mr-2 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"
data-pattern="^(yes|no)$"
value="no"
required />
<svg data-checkbox-handler="newsletter-check"
class="pointer-events-none 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>
<label class="text-sm dark:text-gray-300" for="newsletter-check">
I've read and agree to the
<a class="italic"
href="https://www.bunkerity.com/privacy-policy/?utm_campaign=self&utm_source=ui"
target="_blank">privacy policy</a>
</label>
</div>
<button type="submit"
formtarget="_blank"
class="dark:brightness-125 hover:brightness-75 w-full inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-gradient-to-tl bg-primary leading-normal text-xs ease-in tracking-wide shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Subscribe
</button>
</form>
<!-- end newsletter -->
</aside>
<!-- end right sidebar -->

View file

@ -1,242 +1,243 @@
{% extends "base.html" %}
{% block content %}
{%
include "plugins_modal.html" %}
<!-- info -->
{% set plugins_info = [
{"name" : "TOTAL PLUGINS", "data" : plugins|length|string},
{"name" : "INTERNAL PLUGINS", "data" : plugins_count_internal|string},
{"name" : "EXTERNAL PLUGINS", "data" : plugins_count_external|string},
{"name" : "PRO PLUGINS", "data" : plugins_count_pro|string},
] %}
<div class="h-fit p-4 col-span-12 md:col-span-5 2xl:col-span-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="col-span-12 mb-4 font-bold dark:text-white/90">INFO</h5>
{% for info in plugins_info %}
<div class="mx-1 flex items-center my-4">
<p class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ info['name'] }}
</p>
<p class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ info['data'] }}
</p>
</div>
{% endfor %}
</div>
<!-- end info -->
<!-- upload layout -->
<div data-plugins-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/90">UPLOAD / RELOAD</h5>
<div class="mx-2 p-0 col-span-12 grid grid-cols-12">
<!-- dropzone -->
<form id="dropzone-form"
action="#"
class="hover:bg-gray-100 dark:hover:bg-slate-700/50 cursor-pointer col-span-12 border-2 rounded-lg p-2 border-dashed border-primary dark:brightness-125 drop-zone">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<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="dark:text-gray-500 text-sm text-center my-3">click or drag and drop</p>
</form>
<div class="col-span-12 progress-area"></div>
<div class="col-span-12 uploaded-area"></div>
<!-- end dropzone -->
<div class="col-span-12 flex flex-col justify-center items-center mt-2">
<form method="post"
class="col-span-12 flex flex-col justify-center align-middle items-cente">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<button data-plugin-reload-btn
disabled
type="submit"
class="disabled:hover:translate-y-0 disabled:cursor-not-allowed 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 tracking-wide dark:brightness-125 hover:brightness-75 w-full inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-gradient-to-tl bg-primary leading-normal text-xs ease-in shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Reload
</button>
</form>
</div>
</div>
</div>
<!-- end upload layout -->
<!-- filter -->
{% set filters = [
{
"type": "input",
"name": "Search",
"label": "search",
"id": "keyword",
"placeholder": "keyword",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Plugin type",
"id": "types",
"value": "all",
"values": [
"all",
"core",
"external",
"pro"
]
}
] %}
<div data-plugins-filter
class="h-fit p-4 col-span-12 md:col-span-6 2xl:col-span-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="mb-2 font-bold dark:text-white/90">FILTER</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-plugins-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="plugins-{{ filter['id'] }}"
data-name="plugins-{{ filter['id'] }}"
data-plugins-setting-select-text="{{ filter['id'] }}">{{ filter['value'] }}</span>
<!-- chevron -->
<svg data-plugins-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-plugins-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-plugins-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
{% endfor %}
{%
include "plugins_modal.html" %}
<!-- info -->
{% set plugins_info = [
{"name" : "TOTAL PLUGINS", "data" : plugins|length|string},
{"name" : "INTERNAL PLUGINS", "data" : plugins_count_internal|string},
{"name" : "EXTERNAL PLUGINS", "data" : plugins_count_external|string},
{"name" : "PRO PLUGINS", "data" : plugins_count_pro|string},
] %}
<div class="h-fit p-4 col-span-12 md:col-span-5 2xl:col-span-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="col-span-12 mb-4 font-bold dark:text-white/90">INFO</h5>
{% for info in plugins_info %}
<div class="mx-1 flex items-center my-4">
<p class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ info['name'] }}
</p>
<p class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ info['data'] }}
</p>
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
</div>
<!-- end filter -->
<div data-plugins-list-container class="min-h-[55vh] max-h-80 overflow-hidden overflow-y-auto p-4 col-span-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="mb-4 mt-2 font-bold dark:text-white/90 mx-2">LIST</h5>
<div data-plugins-list class="grid grid-cols-12 gap-3">
{% for plugin in plugins %}
<div data-plugins-type="{{ plugin['type'] }}"
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 data-plugins-content
class="ml-3 mr-2 break-words mb-0 transition duration-300 ease-in-out dark:opacity-90 text-left text-sm md:text-base text-slate-700 dark:text-gray-200">
{{ plugin['name'] }}
</p>
<div class="flex items-center">
{% if plugin['page'] %}
<a aria-label="plugin page link"
class="hover:-translate-y-px mx-1"
href="{{ request.url_root }}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>
{% endif %}
{% if plugin['type'] == "external" %}
<button data-plugins-action="delete"
name="{{ plugin['id'] }}"
aria-label="delete plugin"
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>
{% endif %}
</div>
</div>
{% endfor %}
{% if plugins_pro %}
{% for plugin in plugins_pro %}
<div data-plugins-type="{{ plugin['type'] }}"
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 {% if is_plugin_pro %}bg-gray-100 hover:bg-gray-300 dark:bg-slate-700 dark:hover:bg-slate-800{% else %} bg-gray-100 dark:bg-slate-700 {% endif %}">
<p data-plugins-content
class="{% if not is_plugin_pro %} opacity-80 dark:opacity-60{% endif %} ml-3 mr-2 break-words mb-0 transition duration-300 ease-in-out text-left text-sm md:text-base text-slate-700 dark:text-gray-200">
{{ plugin['name'] }}
</p>
<div class="flex items-center">
{% if plugin['page'] and is_pro_version %}
<a aria-label="plugin page link"
class="hover:-translate-y-px mx-1"
href="{{ request.url_root }}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>
{% endif %}
<a {% if not is_pro_version %}target="_blank"{% endif %}
aria-label="plugin page link"
class="hover:-translate-y-px mx-1 -translate-y-0.5"
href="{% if not is_pro_version %}https://panel.bunkerweb.io/{% else %}#{% endif %}">
<svg class="h-6 w-6 dark:brightness-90"
viewBox="0 0 48 46"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path class="fill-yellow-500" d="M43.218 28.2327L43.6765 23.971C43.921 21.6973 44.0825 20.1957 43.9557 19.2497L44 19.25C46.071 19.25 47.75 17.5711 47.75 15.5C47.75 13.4289 46.071 11.75 44 11.75C41.929 11.75 40.25 13.4289 40.25 15.5C40.25 16.4366 40.5935 17.2931 41.1613 17.9503C40.346 18.4535 39.2805 19.515 37.6763 21.1128C36.4405 22.3438 35.8225 22.9593 35.1333 23.0548C34.7513 23.1075 34.3622 23.0532 34.0095 22.898C33.373 22.6175 32.9485 21.8567 32.0997 20.335L27.6262 12.3135C27.1025 11.3747 26.6642 10.5889 26.2692 9.95662C27.89 9.12967 29 7.44445 29 5.5C29 2.73857 26.7615 0.5 24 0.5C21.2385 0.5 19 2.73857 19 5.5C19 7.44445 20.11 9.12967 21.7308 9.95662C21.3358 10.589 20.8975 11.3746 20.3738 12.3135L15.9002 20.335C15.0514 21.8567 14.627 22.6175 13.9905 22.898C13.6379 23.0532 13.2487 23.1075 12.8668 23.0548C12.1774 22.9593 11.5595 22.3438 10.3238 21.1128C8.71968 19.515 7.6539 18.4535 6.83882 17.9503C7.4066 17.2931 7.75 16.4366 7.75 15.5C7.75 13.4289 6.07107 11.75 4 11.75C1.92893 11.75 0.25 13.4289 0.25 15.5C0.25 17.5711 1.92893 19.25 4 19.25L4.04428 19.2497C3.91755 20.1957 4.07905 21.6973 4.32362 23.971L4.782 28.2327C5.03645 30.5982 5.24802 32.849 5.50717 34.875H42.4928C42.752 32.849 42.9635 30.5982 43.218 28.2327Z" fill="#1C274C" />
<path class="fill-yellow-500" d="M21.2803 45.5H26.7198C33.8098 45.5 37.3545 45.5 39.7198 43.383C40.7523 42.4588 41.4057 40.793 41.8775 38.625H6.1224C6.59413 40.793 7.24783 42.4588 8.2802 43.383C10.6454 45.5 14.1903 45.5 21.2803 45.5Z" fill="#1C274C" />
</svg>
</a>
</div>
</div>
{% endfor %}
{% endif %}
</div>
</div>
<div data-plugins-nomatch
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No plugins match</h5>
</div>
</div>
<!-- end info -->
<!-- upload layout -->
<div data-plugins-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/90">UPLOAD / RELOAD</h5>
<div class="mx-2 p-0 col-span-12 grid grid-cols-12">
<!-- dropzone -->
<form id="dropzone-form"
action="#"
class="hover:bg-gray-100 dark:hover:bg-slate-700/50 cursor-pointer col-span-12 border-2 rounded-lg p-2 border-dashed border-primary dark:brightness-125 drop-zone">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<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="dark:text-gray-500 text-sm text-center my-3">click or drag and drop</p>
</form>
<div class="col-span-12 progress-area"></div>
<div class="col-span-12 uploaded-area"></div>
<!-- end dropzone -->
<div class="col-span-12 flex flex-col justify-center items-center mt-2">
<form method="post"
class="col-span-12 flex flex-col justify-center align-middle items-cente">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<button data-plugin-reload-btn
disabled
type="submit"
class="disabled:hover:translate-y-0 disabled:cursor-not-allowed 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 tracking-wide dark:brightness-125 hover:brightness-75 w-full inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-gradient-to-tl bg-primary leading-normal text-xs ease-in shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Reload
</button>
</form>
</div>
</div>
</div>
<!-- end upload layout -->
<!-- filter -->
{% set filters = [
{
"type": "input",
"name": "Search",
"label": "search",
"id": "keyword",
"placeholder": "keyword",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Plugin type",
"id": "types",
"value": "all",
"values": [
"all",
"core",
"external",
"pro"
]
}
] %}
<div data-plugins-filter
class="h-fit p-4 col-span-12 md:col-span-6 2xl:col-span-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="mb-2 font-bold dark:text-white/90">FILTER</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-plugins-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="plugins-{{ filter['id'] }}"
data-name="plugins-{{ filter['id'] }}"
data-plugins-setting-select-text="{{ filter['id'] }}">{{ filter['value'] }}</span>
<!-- chevron -->
<svg data-plugins-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-plugins-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-plugins-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
</div>
<!-- end filter -->
<div data-plugins-list-container
class="min-h-[55vh] max-h-80 overflow-hidden overflow-y-auto p-4 col-span-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="mb-4 mt-2 font-bold dark:text-white/90 mx-2">LIST</h5>
<div data-plugins-list class="grid grid-cols-12 gap-3">
{% for plugin in plugins %}
<div data-plugins-type="{{ plugin['type'] }}"
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 data-plugins-content
class="ml-3 mr-2 break-words mb-0 transition duration-300 ease-in-out dark:opacity-90 text-left text-sm md:text-base text-slate-700 dark:text-gray-200">
{{ plugin['name'] }}
</p>
<div class="flex items-center">
{% if plugin['page'] %}
<a aria-label="plugin page link"
class="hover:-translate-y-px mx-1"
href="{{ request.url_root }}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>
{% endif %}
{% if plugin['type'] == "external" %}
<button data-plugins-action="delete"
name="{{ plugin['id'] }}"
aria-label="delete plugin"
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>
{% endif %}
</div>
</div>
{% endfor %}
{% if plugins_pro %}
{% for plugin in plugins_pro %}
<div data-plugins-type="{{ plugin['type'] }}"
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 {% if is_plugin_pro %}bg-gray-100 hover:bg-gray-300 dark:bg-slate-700 dark:hover:bg-slate-800{% else %} bg-gray-100 dark:bg-slate-700 {% endif %}">
<p data-plugins-content
class="{% if not is_plugin_pro %} opacity-80 dark:opacity-60{% endif %} ml-3 mr-2 break-words mb-0 transition duration-300 ease-in-out text-left text-sm md:text-base text-slate-700 dark:text-gray-200">
{{ plugin['name'] }}
</p>
<div class="flex items-center">
{% if plugin['page'] and is_pro_version %}
<a aria-label="plugin page link"
class="hover:-translate-y-px mx-1"
href="{{ request.url_root }}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>
{% endif %}
<a {% if not is_pro_version %}target="_blank"{% endif %}
aria-label="plugin page link"
class="hover:-translate-y-px mx-1 -translate-y-0.5"
href="{% if not is_pro_version %}https://panel.bunkerweb.io/{% else %}#{% endif %}">
<svg class="h-6 w-6 dark:brightness-90"
viewBox="0 0 48 46"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path class="fill-yellow-500" d="M43.218 28.2327L43.6765 23.971C43.921 21.6973 44.0825 20.1957 43.9557 19.2497L44 19.25C46.071 19.25 47.75 17.5711 47.75 15.5C47.75 13.4289 46.071 11.75 44 11.75C41.929 11.75 40.25 13.4289 40.25 15.5C40.25 16.4366 40.5935 17.2931 41.1613 17.9503C40.346 18.4535 39.2805 19.515 37.6763 21.1128C36.4405 22.3438 35.8225 22.9593 35.1333 23.0548C34.7513 23.1075 34.3622 23.0532 34.0095 22.898C33.373 22.6175 32.9485 21.8567 32.0997 20.335L27.6262 12.3135C27.1025 11.3747 26.6642 10.5889 26.2692 9.95662C27.89 9.12967 29 7.44445 29 5.5C29 2.73857 26.7615 0.5 24 0.5C21.2385 0.5 19 2.73857 19 5.5C19 7.44445 20.11 9.12967 21.7308 9.95662C21.3358 10.589 20.8975 11.3746 20.3738 12.3135L15.9002 20.335C15.0514 21.8567 14.627 22.6175 13.9905 22.898C13.6379 23.0532 13.2487 23.1075 12.8668 23.0548C12.1774 22.9593 11.5595 22.3438 10.3238 21.1128C8.71968 19.515 7.6539 18.4535 6.83882 17.9503C7.4066 17.2931 7.75 16.4366 7.75 15.5C7.75 13.4289 6.07107 11.75 4 11.75C1.92893 11.75 0.25 13.4289 0.25 15.5C0.25 17.5711 1.92893 19.25 4 19.25L4.04428 19.2497C3.91755 20.1957 4.07905 21.6973 4.32362 23.971L4.782 28.2327C5.03645 30.5982 5.24802 32.849 5.50717 34.875H42.4928C42.752 32.849 42.9635 30.5982 43.218 28.2327Z" fill="#1C274C" />
<path class="fill-yellow-500" d="M21.2803 45.5H26.7198C33.8098 45.5 37.3545 45.5 39.7198 43.383C40.7523 42.4588 41.4057 40.793 41.8775 38.625H6.1224C6.59413 40.793 7.24783 42.4588 8.2802 43.383C10.6454 45.5 14.1903 45.5 21.2803 45.5Z" fill="#1C274C" />
</svg>
</a>
</div>
</div>
{% endfor %}
{% endif %}
</div>
</div>
<div data-plugins-nomatch
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No plugins match</h5>
</div>
</div>
{% endblock %}

View file

@ -1,47 +1,47 @@
<!-- modal -->
<div data-plugins-modal
class="dark:brightness-110 w-screen h-screen fixed bg-gray-600/50 z-[1001] top-0 left-0 hidden justify-center items-center">
<div data-plugins-modal-card
class="overflow-y-auto mx-0 sm:mx-6 lg:mx-8 my-3 px-4 pt-4 pb-8 w-[50vw] max-w-[700px] sm:min-w-[500px] max-h-[90vh] flex flex-col break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="w-full flex justify-between mb-2">
<p data-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 aria-label="close modal"
class="-translate-y-1"
data-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 data-plugins-modal-card
class="overflow-y-auto mx-0 sm:mx-6 lg:mx-8 my-3 px-4 pt-4 pb-8 w-[50vw] max-w-[700px] sm:min-w-[500px] max-h-[90vh] flex flex-col break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="w-full flex justify-between mb-2">
<p data-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 aria-label="close modal"
class="-translate-y-1"
data-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 data-plugins-modal-form-delete
class="w-full h-full flex flex-col justify-between"
id="form-delete-plugin"
method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" value="name" name="name" id="name" />
<input type="hidden" value="external" name="type" id="type" />
<input type="hidden" value="delete" name="operation" id="operation" />
<div>
<p aria-description="delete plugin message"
data-plugins-modal-text
class="text-center 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 type="button"
data-plugins-modal-close
class="close-btn mb-4 mr-3 text-base">Close</button>
<button type="submit" class="delete-btn mb-4 mr-3 text-base">Delete</button>
</div>
<!-- end action button-->
</form>
<!-- end delete form-->
</div>
<!-- delete form-->
<form data-plugins-modal-form-delete
class="w-full h-full flex flex-col justify-between"
id="form-delete-plugin"
method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" value="name" name="name" id="name" />
<input type="hidden" value="external" name="type" id="type" />
<input type="hidden" value="delete" name="operation" id="operation" />
<div>
<p aria-description="delete plugin message"
data-plugins-modal-text
class="text-center 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 type="button"
data-plugins-modal-close
class="close-btn mb-4 mr-3 text-base">Close</button>
<button type="submit" class="delete-btn mb-4 mr-3 text-base">Delete</button>
</div>
<!-- end action button-->
</form>
<!-- end delete form-->
</div>
</div>
<!-- end modal -->

View file

@ -1,257 +1,259 @@
{% extends "base.html" %}
{% block content %}
{% set methods = ["all"] %}
{% set codes = ["all"] %}
{% set reasons = ["all"] %}
{% set countries = ["all"] %}
{% for report in reports %}
{% if report["method"] not in methods %}
{% if methods.append(report["method"]) %}{% endif %}
{% endif %}
{% if report["status"] not in codes %}
{% if codes.append(report["status"]) %}{% endif %}
{% endif %}
{% if report["reason"] not in reasons %}
{% if reasons.append(report["reason"]) %}{% endif %}
{% endif %}
{% if report["country"] not in countries %}
{% if countries.append(report["country"]) %}{% endif %}
{% endif %}
{% endfor %}
<div class="{% if reports|length == 0 %}w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words {% else %}hidden{% endif %} ">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No reports found</h5>
</div>
</div>
<!-- info-->
{% if reports|length != 0 %}
{% set reports_info = [
{"name" : "REPORTING TOTAL", "data" : total_report|string},
{"name" : "TOP REASON", "data" : total_reason|string},
{"name" : "TOP STATUS CODE", "data" : top_code|string},
] %}
<div class=" h-fit col-span-12 md:col-span-4 3xl:col-span-3 p-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="mb-2 font-bold dark:text-white/90">INFO</h5>
{% for info in reports_info %}
<div class="mx-1 flex items-center my-4">
<p class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ info['name'] }}
</p>
<p class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ info['data'] }}
</p>
{% set methods = ["all"] %}
{% set codes = ["all"] %}
{% set reasons = ["all"] %}
{% set countries = ["all"] %}
{% for report in reports %}
{% if report["method"] not in methods %}
{% if methods.append(report["method"]) %}{% endif %}
{% endif %}
{% if report["status"] not in codes %}
{% if codes.append(report["status"]) %}{% endif %}
{% endif %}
{% if report["reason"] not in reasons %}
{% if reasons.append(report["reason"]) %}{% endif %}
{% endif %}
{% if report["country"] not in countries %}
{% if countries.append(report["country"]) %}{% endif %}
{% endif %}
{% endfor %}
<div class="{% if reports|length == 0 %}w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words {% else %}hidden{% endif %} ">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No reports found</h5>
</div>
{% endfor %}
</div>
<!-- end info -->
<!-- filter -->
{% set filters = [
{
"type": "input",
"name": "Search",
"label": "search",
"id": "keyword",
"placeholder": "ip, url, date, data",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Country",
"id": "country",
"value": "all",
"values": countries
},
{
"type": "select",
"name": "Method",
"id": "method",
"value": "all",
"values": methods
},
{
"type": "select",
"name": "Status code",
"id": "status",
"value": "all",
"values": codes
},
{
"type": "select",
"name": "Reason",
"id": "reason",
"value": "all",
"values": reasons
}
] %}
<div data-reports-filter
class="h-fit col-span-12 md:col-span-8 2xl:col-span-6 3xl:col-span-5 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/90">FILTER</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-reports-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="reports-{{ filter['id'] }}"
data-name="reports-{{ filter['id'] }}"
data-reports-setting-select-text="{{ filter['id'] }}">{{ filter['value'] }}</span>
<!-- chevron -->
<svg data-reports-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-reports-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-reports-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
</div>
<!-- end filter -->
<div data-reports-nomatch
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No reports match</h5>
</div>
</div>
<div data-reports-list-container class="w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="col-span-12">
<h5 class="mb-4 mt-2 font-bold dark:text-white/90 mx-2">REPORTING</h5>
</div>
<div class="col-span-12 overflow-y-auto overflow-x-auto">
<!-- list container-->
<div class="min-w-[1300px] w-full grid grid-cols-12 rounded p-2">
{% set reports_header = [
{
"name": "Date",
"position": "col-span-1"
},
{
"name": "IP",
"position": "col-span-1"
},
{
"name": "Country",
"position": "col-span-1"
},
{
"name": "Method",
"position": "col-span-1"
},
{
"name": "URL",
"position": "col-span-2"
},
{
"name": "Code",
"position": "col-span-1"
},
{
"name": "User agent",
"position": "col-span-2"
},
{
"name": "Reason",
"position": "col-span-1"
},
{
"name": "Data",
"position": "col-span-2"
}
] %}
<!-- header-->
{% for header in reports_header %}
<p class="dark:text-gray-300 flex justify-center h-8 text-sm font-bold {{ header['position'] }} m-0 pb-2 border-b border-gray-400">
{{ header['name'] }}
</p>
{% endfor %}
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full" data-reports-list>
{% for report in reports %}
<li data-reports-item class="items-center grid grid-cols-12 border-b border-gray-300 py-2.5">
<p class="text-center flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1"
data-reports-date="{{ report['date'] }}">{{ report['date'] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1"
data-reports-ip="{{ report['ip'] }}">{{ report['ip'] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1"
data-reports-country="{{ report['country'] }}">{{ report['country'] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1 "
data-reports-method="{{ report['method'] }}">{{ report["method"] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-reports-url="{{ report['url'] }}">{{ report['url'] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1 "
data-reports-status="{{ report['status'] }}">{{ report["status"] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1 "
data-reports-user_agent="{{ report['user_agent'] }}">{{ report["user_agent"] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1 "
data-reports-reason="{{ report['reason'] }}">{{ report["reason"] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-reports-data="{{ report['data'] }}">{{ report["data"] }}</p>
</li>
<!-- info-->
{% if reports|length != 0 %}
{% set reports_info = [
{"name" : "REPORTING TOTAL", "data" : total_report|string},
{"name" : "TOP REASON", "data" : total_reason|string},
{"name" : "TOP STATUS CODE", "data" : top_code|string},
] %}
<div class=" h-fit col-span-12 md:col-span-4 3xl:col-span-3 p-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="mb-2 font-bold dark:text-white/90">INFO</h5>
{% for info in reports_info %}
<div class="mx-1 flex items-center my-4">
<p class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ info['name'] }}
</p>
<p class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ info['data'] }}
</p>
</div>
{% endfor %}
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
{% endif %}
<!-- end info -->
<!-- filter -->
{% set filters = [
{
"type": "input",
"name": "Search",
"label": "search",
"id": "keyword",
"placeholder": "ip, url, date, data",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Country",
"id": "country",
"value": "all",
"values": countries
},
{
"type": "select",
"name": "Method",
"id": "method",
"value": "all",
"values": methods
},
{
"type": "select",
"name": "Status code",
"id": "status",
"value": "all",
"values": codes
},
{
"type": "select",
"name": "Reason",
"id": "reason",
"value": "all",
"values": reasons
}
] %}
<div data-reports-filter
class="h-fit col-span-12 md:col-span-8 2xl:col-span-6 3xl:col-span-5 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/90">FILTER</h5>
<div class="mx-2 grid grid-cols-12 gap-x-4 gap-y-2">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-reports-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="reports-{{ filter['id'] }}"
data-name="reports-{{ filter['id'] }}"
data-reports-setting-select-text="{{ filter['id'] }}">{{ filter['value'] }}</span>
<!-- chevron -->
<svg data-reports-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-reports-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-reports-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
</div>
<!-- end filter -->
<div data-reports-nomatch
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No reports match</h5>
</div>
</div>
<div data-reports-list-container
class="w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="col-span-12">
<h5 class="mb-4 mt-2 font-bold dark:text-white/90 mx-2">REPORTING</h5>
</div>
<div class="col-span-12 overflow-y-auto overflow-x-auto">
<!-- list container-->
<div class="min-w-[1300px] w-full grid grid-cols-12 rounded p-2">
{% set reports_header = [
{
"name": "Date",
"position": "col-span-1"
},
{
"name": "IP",
"position": "col-span-1"
},
{
"name": "Country",
"position": "col-span-1"
},
{
"name": "Method",
"position": "col-span-1"
},
{
"name": "URL",
"position": "col-span-2"
},
{
"name": "Code",
"position": "col-span-1"
},
{
"name": "User agent",
"position": "col-span-2"
},
{
"name": "Reason",
"position": "col-span-1"
},
{
"name": "Data",
"position": "col-span-2"
}
] %}
<!-- header-->
{% for header in reports_header %}
<p class="dark:text-gray-300 flex justify-center h-8 text-sm font-bold {{ header['position'] }} m-0 pb-2 border-b border-gray-400">
{{ header['name'] }}
</p>
{% endfor %}
<!-- end header-->
<!-- list -->
<ul class="col-span-12 w-full" data-reports-list>
{% for report in reports %}
<li data-reports-item
class="items-center grid grid-cols-12 border-b border-gray-300 py-2.5">
<p class="text-center flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1"
data-reports-date="{{ report['date'] }}">{{ report['date'] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1"
data-reports-ip="{{ report['ip'] }}">{{ report['ip'] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1"
data-reports-country="{{ report['country'] }}">{{ report['country'] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1 "
data-reports-method="{{ report['method'] }}">{{ report["method"] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-reports-url="{{ report['url'] }}">{{ report['url'] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1 "
data-reports-status="{{ report['status'] }}">{{ report["status"] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1 "
data-reports-user_agent="{{ report['user_agent'] }}">{{ report["user_agent"] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1 "
data-reports-reason="{{ report['reason'] }}">{{ report["reason"] }}</p>
<p class="flex justify-center dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-reports-data="{{ report['data'] }}">{{ report["data"] }}</p>
</li>
{% endfor %}
</ul>
<!-- end list-->
</div>
<!-- end list container-->
</div>
</div>
{% endif %}
{% endblock content %}

View file

@ -1,395 +1,399 @@
{% extends "base.html" %}
{% block content %}
{% set methods = ["all"] %}
{% set states = ["all", "draft", "online"] %}
{% set draft_count = [] %}
{% set online_count = [] %}
{% for services_batched in services|batch(3) %}
{% for service in
services_batched %}
{% if service['SERVER_NAME']['method'] not in methods %}
{% if methods.append(service['SERVER_NAME']['method']) %}{% endif %}
{% endif %}
{% if service.get('IS_DRAFT', '') == "yes" %}
{% if draft_count.append(1) %}{% endif %}
{% endif %}
{% if service.get('IS_DRAFT', '') == "no" %}
{% if online_count.append(1) %}{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
{% set draft_count = draft_count|length %}
{% set online_count = online_count|length %}
<!-- actions -->
<div data-services-service
class="col-span-12 relative flex justify-center min-w-0 break-words rounded-2xl bg-clip-border">
<div data-is-draft class="hidden" data-value="no"></div>
<div data-service-method class="hidden" data-value="ui"></div>
<button data-services-action="new"
data-services-name="service"
type="button"
class="dark:bg-green-500/90 duration-300 dark:opacity-90 w-80 flex justify-center items-center px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal text-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
<span class="mr-2">new service</span>
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-7 h-7">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
</button>
</div>
<!-- end actions -->
<!-- services container-->
<div class="p-0 my-4 sm:mx-2 md:mx-4 md:px-4 grid grid-cols-12 col-span-12 md:gap-x-4 gap-y-4 relative min-w-0 break-words rounded-2xl bg-clip-border">
{% if services|length == 0 %}
<div class="col-span-12 sm:col-span-4 sm:col-start-5">
<div class="transition duration-300 ease-in-out dark:opacity-90 text-center relative w-full p-4 text-white bg-blue-500 rounded-lg">
No service to show
</div>
</div>
{% endif %}
{% if services|length >= 4 %}
<!-- info-->
{% set services_info = [
{"name" : "SERVICES TOTAL", "data" : services|length|string},
{"name" : "TOTAL DRAFT", "data" : draft_count|string},
{"name" : "TOTAL ONLINE", "data" : online_count|string},
] %}
<div class="h-fit col-span-12 md:col-span-4 3xl:col-span-3 p-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="mb-2 font-bold dark:text-white/90">INFO</h5>
{% for info in services_info %}
<div class="mx-1 flex items-center my-4">
<p class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ info['name'] }}
</p>
<p class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ info['data'] }}
</p>
</div>
{% endfor %}
</div>
<!-- end info -->
<!-- filter -->
{% set filters = [
{
"type": "input",
"name": "Search",
"label": "search",
"id": "service-name-keyword",
"placeholder": "service name",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Method",
"id": "method",
"value": "all",
"values": methods
},
{
"type": "select",
"name": "State",
"id": "state",
"value": "all",
"values": states
}
] %}
<div data-services-filter
class="h-fit col-span-12 md:col-span-8 2xl:col-span-6 3xl:col-span-5 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/90">FILTER</h5>
<div class="mx-2 grid grid-cols-12 gap-4">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<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">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-services-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="services-{{ filter['id'] }}"
data-name="services-{{ filter['id'] }}"
data-services-setting-select-text="{{ filter['id'] }}">{{ filter['value']}}</span>
<!-- chevron -->
<svg data-services-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-services-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-services-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
</div>
<div data-services-nomatch-card
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No services match</h5>
</div>
</div>
{% endif %}
{% if services|length > 0 %}
<!-- end filter -->
{% for services_batched in services|batch(3) %}
{% set methods = ["all"] %}
{% set states = ["all", "draft", "online"] %}
{% set draft_count = [] %}
{% set online_count = [] %}
{% for services_batched in services|batch(3) %}
{% for service in
services_batched %}
{% set id_server_name = service["SERVER_NAME"]['value'].replace(".", "-") %}
<div data-services-card data-services-service="{{ service['SERVER_NAME']['value'] }}"
class="my-2 dark:brightness-110 overflow-hidden hover:scale-102 transition col-span-12 lg:col-span-6 3xl:col-span-4 p-4 w-full shadow-md break-words bg-white dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div data-services-settings
class="hidden"
data-value="{{ service['settings'] }}"></div>
<div data-old-service-name
class="hidden"
data-value="{{ service['SERVER_NAME']['full_value'] }}"></div>
<div data-is-draft
class="hidden"
data-value="{% if service.get('IS_DRAFT', 'no') == 'yes' %}yes{% else %}no{% endif %}"></div>
<div data-service-method
class="hidden"
data-value="{{ service['SERVER_NAME']['method'] }}"></div>
<div class="flex justify-between items-start">
<h5 data-services-name="{{ service["SERVER_NAME"]['value'] }}" class="transition duration-300 ease-in-out text-center sm:text-left mb-1 font-bold dark:text-white/90">
{{ service["SERVER_NAME"]['value'] }}
</h5>
{% if service.get('IS_DRAFT', "no") == "yes" and service["SERVER_NAME"]['method'] in ["ui", "default"] %}
<button class="group relative">
<p data-services-state="draft" class="dark:text-gray-300 -z-10 opacity-0 group-hover:z-10 group-hover:opacity-100 transition fixed bg-white dark:bg-slate-800 rounded right-12 px-1 py-0.5">
Draft
</p>
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-6 h-6 fill-gray-700 dark:fill-gray-300 cursor-pointer-none">
<path fill-rule="evenodd" d="M10.5 3.798v5.02a3 3 0 0 1-.879 2.121l-2.377 2.377a9.845 9.845 0 0 1 5.091 1.013 8.315 8.315 0 0 0 5.713.636l.285-.071-3.954-3.955a3 3 0 0 1-.879-2.121v-5.02a23.614 23.614 0 0 0-3 0Zm4.5.138a.75.75 0 0 0 .093-1.495A24.837 24.837 0 0 0 12 2.25a25.048 25.048 0 0 0-3.093.191A.75.75 0 0 0 9 3.936v4.882a1.5 1.5 0 0 1-.44 1.06l-6.293 6.294c-1.62 1.621-.903 4.475 1.471 4.88 2.686.46 5.447.698 8.262.698 2.816 0 5.576-.239 8.262-.697 2.373-.406 3.092-3.26 1.47-4.881L15.44 9.879A1.5 1.5 0 0 1 15 8.818V3.936Z" clip-rule="evenodd" />
</svg>
</button>
{% else %}
<button class="group relative">
<p data-services-state="online" class="dark:text-gray-300 -z-10 opacity-0 group-hover:z-10 group-hover:opacity-100 transition fixed bg-white dark:bg-slate-800 rounded right-12 px-1 py-0.5">
Online
</p>
<svg data-toggle-draft="false"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-6 h-6 fill-gray-700 dark:fill-gray-300 cursor-pointer-none">
<path d="M21.721 12.752a9.711 9.711 0 0 0-.945-5.003 12.754 12.754 0 0 1-4.339 2.708 18.991 18.991 0 0 1-.214 4.772 17.165 17.165 0 0 0 5.498-2.477ZM14.634 15.55a17.324 17.324 0 0 0 .332-4.647c-.952.227-1.945.347-2.966.347-1.021 0-2.014-.12-2.966-.347a17.515 17.515 0 0 0 .332 4.647 17.385 17.385 0 0 0 5.268 0ZM9.772 17.119a18.963 18.963 0 0 0 4.456 0A17.182 17.182 0 0 1 12 21.724a17.18 17.18 0 0 1-2.228-4.605ZM7.777 15.23a18.87 18.87 0 0 1-.214-4.774 12.753 12.753 0 0 1-4.34-2.708 9.711 9.711 0 0 0-.944 5.004 17.165 17.165 0 0 0 5.498 2.477ZM21.356 14.752a9.765 9.765 0 0 1-7.478 6.817 18.64 18.64 0 0 0 1.988-4.718 18.627 18.627 0 0 0 5.49-2.098ZM2.644 14.752c1.682.971 3.53 1.688 5.49 2.099a18.64 18.64 0 0 0 1.988 4.718 9.765 9.765 0 0 1-7.478-6.816ZM13.878 2.43a9.755 9.755 0 0 1 6.116 3.986 11.267 11.267 0 0 1-3.746 2.504 18.63 18.63 0 0 0-2.37-6.49ZM12 2.276a17.152 17.152 0 0 1 2.805 7.121c-.897.23-1.837.353-2.805.353-.968 0-1.908-.122-2.805-.353A17.151 17.151 0 0 1 12 2.276ZM10.122 2.43a18.629 18.629 0 0 0-2.37 6.49 11.266 11.266 0 0 1-3.746-2.504 9.754 9.754 0 0 1 6.116-3.985Z" />
</svg>
</button>
{% endif %}
</div>
<h6 data-services-method="{{ service["SERVER_NAME"]['method'] }}" class="text-center sm:text-left mb-2 font-semibold text-gray-600 dark:text-white/80">
{{ service["SERVER_NAME"]['method'] }}
</h6>
{% set details = [
{
"name": "Reverse proxy",
"settings": [
"USE_REVERSE_PROXY"
]
},
{
"name": "Serve files",
"settings": [
"SERVE_FILES"
]
},
{
"name": "Remote PHP",
"settings": [
"REMOTE_PHP"
]
},
{
"name": "HTTPS",
"settings": [
"AUTO_LETS_ENCRYPT",
"USE_CUSTOM_SSL",
"GENERATE_SELF_SIGNED_SSL"
]
},
{
"name": "ModSecurity",
"settings": [
"USE_MODSECURITY"
]
},
{
"name": "Bad behavior",
"settings": [
"USE_BAD_BEHAVIOR"
]
},
{
"name": "Limit req",
"settings": [
"USE_LIMIT_REQ"
]
},
{
"name": "DNSBL",
"settings": [
"USE_DNSBL"
]
}
] %}
<!-- detail list -->
<div role="grid"
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">
{% for detail in details %}
{% set use = [] %}
{% for setting in detail['settings'] %}
{% if service[setting]['value'] == 'yes' %}
{% if use.append(1) %}{% endif %}
{% endif %}
{% endfor %}
<!-- detail -->
<div role="row" class="flex items-center col-span-12 sm:col-span-6">
<p role="gridcell"
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 ">
{{ detail['name'] }}
</p>
<p role="gridcell"
class="transition duration-300 ease-in-out dark:opacity-90 pl-2 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-gray-500 ">
{% if use %}
<span class="sr-only">yes</span>
<svg class="h-4 w-4 fill-green-500"
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" />
</svg>
{% else %}
<span class="sr-only">no</span>
<svg class="h-4 w-4 fill-red-500"
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>
{% endif %}
</p>
</div>
<!-- end detail -->
{% endfor %}
</div>
<!-- end detail list-->
<!-- button list-->
<div class="relative w-full flex justify-center sm:justify-end">
<a aria-label="access service url"
href="http://{{ service['SERVER_NAME']['value'] }}"
target="_blank"
class="dark:brightness-90 z-20 mx-1 bg-sky-500 hover:bg-sky-500/80 focus:bg-sky-500/80 inline-block p-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer leading-normal text-xs ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 active:opacity-85 hover:shadow-md">
<svg class="h-6 w-6 fill-white"
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" />
</svg>
</a>
{% set action_buttons = [
{
"name": "clone",
"label": "clone service settings",
"color": "emerald-500"
},
{
"name": "edit",
"label": "edit service settings",
"color": "yellow-500"
}
] %}
{% if service["SERVER_NAME"]['method'] == "ui" %}
{% if action_buttons.append({"name" : "delete", "label" : "delete service settings", "color" : "red-500"}) %}{% endif %}
{% endif %}
{% for button in action_buttons %}
<button data-services-action="{{ button['name'] }}"
aria-label="{{ button['label'] }}"
data-services-name="{{ service['SERVER_NAME']['value'] }}"
class="dark:brightness-90 z-20 mx-1 bg-{{ button['color'] }} hover:bg-{{ button['color'] }}/80 focus:bg-{{ button['color'] }}/80 inline-block p-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer leading-normal text-xs ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 active:opacity-85 hover:shadow-md">
{% if button['name'] == "clone" %}
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-6 h-6 fill-white">
<path fill-rule="evenodd" d="M17.663 3.118c.225.015.45.032.673.05C19.876 3.298 21 4.604 21 6.109v9.642a3 3 0 0 1-3 3V16.5c0-5.922-4.576-10.775-10.384-11.217.324-1.132 1.3-2.01 2.548-2.114.224-.019.448-.036.673-.051A3 3 0 0 1 13.5 1.5H15a3 3 0 0 1 2.663 1.618ZM12 4.5A1.5 1.5 0 0 1 13.5 3H15a1.5 1.5 0 0 1 1.5 1.5H12Z" clip-rule="evenodd" />
<path d="M3 8.625c0-1.036.84-1.875 1.875-1.875h.375A3.75 3.75 0 0 1 9 10.5v1.875c0 1.036.84 1.875 1.875 1.875h1.875A3.75 3.75 0 0 1 16.5 18v2.625c0 1.035-.84 1.875-1.875 1.875h-9.75A1.875 1.875 0 0 1 3 20.625v-12Z" />
<path d="M10.5 10.5a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963 5.23 5.23 0 0 0-3.434-1.279h-1.875a.375.375 0 0 1-.375-.375V10.5Z" />
</svg>
{% endif %}
{% if button['name'] == "edit" %}
<svg class="h-6 w-6 fill-white"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336c44.2 0 80-35.8 80-80s-35.8-80-80-80s-80 35.8-80 80s35.8 80 80 80z" />
</svg>
{% endif %}
{% if button['name'] == "delete" %}
<svg class="h-6 w-6 fill-white"
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>
{% endif %}
</button>
{% endfor %}
</div>
<!-- end button list-->
</div>
services_batched %}
{% if service['SERVER_NAME']['method'] not in methods %}
{% if methods.append(service['SERVER_NAME']['method']) %}{% endif %}
{% endif %}
{% if service.get('IS_DRAFT', '') == "yes" %}
{% if draft_count.append(1) %}{% endif %}
{% endif %}
{% if service.get('IS_DRAFT', '') == "no" %}
{% if online_count.append(1) %}{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}
</div>
<!-- end services container-->
<!-- modal -->
{% include "services_modal.html" %}
{% endfor %}
{% set draft_count = draft_count|length %}
{% set online_count = online_count|length %}
<!-- actions -->
<div data-services-service
class="col-span-12 relative flex justify-center min-w-0 break-words rounded-2xl bg-clip-border">
<div data-is-draft class="hidden" data-value="no"></div>
<div data-service-method class="hidden" data-value="ui"></div>
<button data-services-action="new"
data-services-name="service"
type="button"
class="dark:bg-green-500/90 duration-300 dark:opacity-90 w-80 flex justify-center items-center px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal text-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
<span class="mr-2">new service</span>
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-7 h-7">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
</button>
</div>
<!-- end actions -->
<!-- services container-->
<div class="p-0 my-4 sm:mx-2 md:mx-4 md:px-4 grid grid-cols-12 col-span-12 md:gap-x-4 gap-y-4 relative min-w-0 break-words rounded-2xl bg-clip-border">
{% if services|length == 0 %}
<div class="col-span-12 sm:col-span-4 sm:col-start-5">
<div class="transition duration-300 ease-in-out dark:opacity-90 text-center relative w-full p-4 text-white bg-blue-500 rounded-lg">
No service to show
</div>
</div>
{% endif %}
{% if services|length >= 4 %}
<!-- info-->
{% set services_info = [
{"name" : "SERVICES TOTAL", "data" : services|length|string},
{"name" : "TOTAL DRAFT", "data" : draft_count|string},
{"name" : "TOTAL ONLINE", "data" : online_count|string},
] %}
<div class="h-fit col-span-12 md:col-span-4 3xl:col-span-3 p-4 relative min-w-0 break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<h5 class="mb-2 font-bold dark:text-white/90">INFO</h5>
{% for info in services_info %}
<div class="mx-1 flex items-center my-4">
<p class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80">
{{ info['name'] }}
</p>
<p class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80">
{{ info['data'] }}
</p>
</div>
{% endfor %}
</div>
<!-- end info -->
<!-- filter -->
{% set filters = [
{
"type": "input",
"name": "Search",
"label": "search",
"id": "service-name-keyword",
"placeholder": "service name",
"pattern": "(.*?)"
},
{
"type": "select",
"name": "Method",
"id": "method",
"value": "all",
"values": methods
},
{
"type": "select",
"name": "State",
"id": "state",
"value": "all",
"values": states
}
] %}
<div data-services-filter
class="h-fit col-span-12 md:col-span-8 2xl:col-span-6 3xl:col-span-5 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/90">FILTER</h5>
<div class="mx-2 grid grid-cols-12 gap-4">
{% for filter in filters %}
{% if filter['type'] == 'input' %}
<!-- search inpt-->
<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">
{{ filter['name'] }}
</h5>
<label for="{{ filter['id'] }}" class="sr-only">{{ filter['label'] }}</label>
<input type="text"
id="{{ filter['id'] }}"
name="{{ filter['id'] }}"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="{{ filter['placeholder'] }}"
pattern="{{ filter['pattern'] }}"
required />
</div>
<!-- end search inpt-->
{% endif %}
{% if filter['type'] == 'select' %}
<!-- select -->
<div class="flex flex-col relative col-span-12 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">
{{ filter['name'] }}
</h5>
<button aria-controls="filter-{{ filter['id'] }}"
data-services-setting-select="{{ filter['id'] }}"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="services-{{ filter['id'] }}"
data-name="services-{{ filter['id'] }}"
data-services-setting-select-text="{{ filter['id'] }}">{{ filter['value'] }}</span>
<!-- chevron -->
<svg data-services-setting-select="{{ filter['id'] }}"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-{{ filter['id'] }}"
role="listbox"
data-services-setting-select-dropdown="{{ filter['id'] }}"
class="hidden z-100 absolute h-full flex-col w-full translate-y-16">
{% for value in filter['values'] %}
<button role="option"
data-services-setting-select-dropdown-btn="{{ filter['id'] }}"
value="{{ value }}"
class="{% if loop.first %}dark:bg-primary bg-primary text-gray-300 border-t rounded-t {% else %} bg-white {% endif %} {% if loop.last %}rounded-b{% endif %} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
{{ value }}
</button>
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end select -->
{% endif %}
{% endfor %}
</div>
</div>
<div data-services-nomatch-card
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 stroke-white">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-white">No services match</h5>
</div>
</div>
{% endif %}
{% if services|length > 0 %}
<!-- end filter -->
{% for services_batched in services|batch(3) %}
{% for service in
services_batched %}
{% set id_server_name = service["SERVER_NAME"]['value'].replace(".", "-") %}
<div data-services-card
data-services-service="{{ service['SERVER_NAME']['value'] }}"
class="my-2 dark:brightness-110 overflow-hidden hover:scale-102 transition col-span-12 lg:col-span-6 3xl:col-span-4 p-4 w-full shadow-md break-words bg-white dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div data-services-settings
class="hidden"
data-value="{{ service['settings'] }}"></div>
<div data-old-service-name
class="hidden"
data-value="{{ service['SERVER_NAME']['full_value'] }}"></div>
<div data-is-draft
class="hidden"
data-value="{% if service.get('IS_DRAFT', 'no') == 'yes' %}yes{% else %}no{% endif %}">
</div>
<div data-service-method
class="hidden"
data-value="{{ service['SERVER_NAME']['method'] }}"></div>
<div class="flex justify-between items-start">
<h5 data-services-name="{{ service["SERVER_NAME"]['value'] }}"
class="transition duration-300 ease-in-out text-center sm:text-left mb-1 font-bold dark:text-white/90">
{{ service["SERVER_NAME"]['value'] }}
</h5>
{% if service.get('IS_DRAFT', "no") == "yes" and service["SERVER_NAME"]['method'] in ["ui", "default"] %}
<button class="group relative">
<p data-services-state="draft"
class="dark:text-gray-300 -z-10 opacity-0 group-hover:z-10 group-hover:opacity-100 transition fixed bg-white dark:bg-slate-800 rounded right-12 px-1 py-0.5">
Draft
</p>
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-6 h-6 fill-gray-700 dark:fill-gray-300 cursor-pointer-none">
<path fill-rule="evenodd" d="M10.5 3.798v5.02a3 3 0 0 1-.879 2.121l-2.377 2.377a9.845 9.845 0 0 1 5.091 1.013 8.315 8.315 0 0 0 5.713.636l.285-.071-3.954-3.955a3 3 0 0 1-.879-2.121v-5.02a23.614 23.614 0 0 0-3 0Zm4.5.138a.75.75 0 0 0 .093-1.495A24.837 24.837 0 0 0 12 2.25a25.048 25.048 0 0 0-3.093.191A.75.75 0 0 0 9 3.936v4.882a1.5 1.5 0 0 1-.44 1.06l-6.293 6.294c-1.62 1.621-.903 4.475 1.471 4.88 2.686.46 5.447.698 8.262.698 2.816 0 5.576-.239 8.262-.697 2.373-.406 3.092-3.26 1.47-4.881L15.44 9.879A1.5 1.5 0 0 1 15 8.818V3.936Z" clip-rule="evenodd" />
</svg>
</button>
{% else %}
<button class="group relative">
<p data-services-state="online"
class="dark:text-gray-300 -z-10 opacity-0 group-hover:z-10 group-hover:opacity-100 transition fixed bg-white dark:bg-slate-800 rounded right-12 px-1 py-0.5">
Online
</p>
<svg data-toggle-draft="false"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-6 h-6 fill-gray-700 dark:fill-gray-300 cursor-pointer-none">
<path d="M21.721 12.752a9.711 9.711 0 0 0-.945-5.003 12.754 12.754 0 0 1-4.339 2.708 18.991 18.991 0 0 1-.214 4.772 17.165 17.165 0 0 0 5.498-2.477ZM14.634 15.55a17.324 17.324 0 0 0 .332-4.647c-.952.227-1.945.347-2.966.347-1.021 0-2.014-.12-2.966-.347a17.515 17.515 0 0 0 .332 4.647 17.385 17.385 0 0 0 5.268 0ZM9.772 17.119a18.963 18.963 0 0 0 4.456 0A17.182 17.182 0 0 1 12 21.724a17.18 17.18 0 0 1-2.228-4.605ZM7.777 15.23a18.87 18.87 0 0 1-.214-4.774 12.753 12.753 0 0 1-4.34-2.708 9.711 9.711 0 0 0-.944 5.004 17.165 17.165 0 0 0 5.498 2.477ZM21.356 14.752a9.765 9.765 0 0 1-7.478 6.817 18.64 18.64 0 0 0 1.988-4.718 18.627 18.627 0 0 0 5.49-2.098ZM2.644 14.752c1.682.971 3.53 1.688 5.49 2.099a18.64 18.64 0 0 0 1.988 4.718 9.765 9.765 0 0 1-7.478-6.816ZM13.878 2.43a9.755 9.755 0 0 1 6.116 3.986 11.267 11.267 0 0 1-3.746 2.504 18.63 18.63 0 0 0-2.37-6.49ZM12 2.276a17.152 17.152 0 0 1 2.805 7.121c-.897.23-1.837.353-2.805.353-.968 0-1.908-.122-2.805-.353A17.151 17.151 0 0 1 12 2.276ZM10.122 2.43a18.629 18.629 0 0 0-2.37 6.49 11.266 11.266 0 0 1-3.746-2.504 9.754 9.754 0 0 1 6.116-3.985Z" />
</svg>
</button>
{% endif %}
</div>
<h6 data-services-method="{{ service["SERVER_NAME"]['method'] }}"
class="text-center sm:text-left mb-2 font-semibold text-gray-600 dark:text-white/80">
{{ service["SERVER_NAME"]['method'] }}
</h6>
{% set details = [
{
"name": "Reverse proxy",
"settings": [
"USE_REVERSE_PROXY"
]
},
{
"name": "Serve files",
"settings": [
"SERVE_FILES"
]
},
{
"name": "Remote PHP",
"settings": [
"REMOTE_PHP"
]
},
{
"name": "HTTPS",
"settings": [
"AUTO_LETS_ENCRYPT",
"USE_CUSTOM_SSL",
"GENERATE_SELF_SIGNED_SSL"
]
},
{
"name": "ModSecurity",
"settings": [
"USE_MODSECURITY"
]
},
{
"name": "Bad behavior",
"settings": [
"USE_BAD_BEHAVIOR"
]
},
{
"name": "Limit req",
"settings": [
"USE_LIMIT_REQ"
]
},
{
"name": "DNSBL",
"settings": [
"USE_DNSBL"
]
}
] %}
<!-- detail list -->
<div role="grid"
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">
{% for detail in details %}
{% set use = [] %}
{% for setting in detail['settings'] %}
{% if service[setting]['value'] == 'yes' %}
{% if use.append(1) %}{% endif %}
{% endif %}
{% endfor %}
<!-- detail -->
<div role="row" class="flex items-center col-span-12 sm:col-span-6">
<p role="gridcell"
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 ">
{{ detail['name'] }}
</p>
<p role="gridcell"
class="transition duration-300 ease-in-out dark:opacity-90 pl-2 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-gray-500 ">
{% if use %}
<span class="sr-only">yes</span>
<svg class="h-4 w-4 fill-green-500"
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" />
</svg>
{% else %}
<span class="sr-only">no</span>
<svg class="h-4 w-4 fill-red-500"
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>
{% endif %}
</p>
</div>
<!-- end detail -->
{% endfor %}
</div>
<!-- end detail list-->
<!-- button list-->
<div class="relative w-full flex justify-center sm:justify-end">
<a aria-label="access service url"
href="http://{{ service['SERVER_NAME']['value'] }}"
target="_blank"
class="dark:brightness-90 z-20 mx-1 bg-sky-500 hover:bg-sky-500/80 focus:bg-sky-500/80 inline-block p-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer leading-normal text-xs ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 active:opacity-85 hover:shadow-md">
<svg class="h-6 w-6 fill-white"
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" />
</svg>
</a>
{% set action_buttons = [
{
"name": "clone",
"label": "clone service settings",
"color": "emerald-500"
},
{
"name": "edit",
"label": "edit service settings",
"color": "yellow-500"
}
] %}
{% if service["SERVER_NAME"]['method'] == "ui" %}
{% if action_buttons.append({"name" : "delete", "label" : "delete service settings", "color" : "red-500"}) %}
{% endif %}
{% endif %}
{% for button in action_buttons %}
<button data-services-action="{{ button['name'] }}"
aria-label="{{ button['label'] }}"
data-services-name="{{ service['SERVER_NAME']['value'] }}"
class="dark:brightness-90 z-20 mx-1 bg-{{ button['color'] }} hover:bg-{{ button['color'] }}/80 focus:bg-{{ button['color'] }}/80 inline-block p-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer leading-normal text-xs ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 active:opacity-85 hover:shadow-md">
{% if button['name'] == "clone" %}
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-6 h-6 fill-white">
<path fill-rule="evenodd" d="M17.663 3.118c.225.015.45.032.673.05C19.876 3.298 21 4.604 21 6.109v9.642a3 3 0 0 1-3 3V16.5c0-5.922-4.576-10.775-10.384-11.217.324-1.132 1.3-2.01 2.548-2.114.224-.019.448-.036.673-.051A3 3 0 0 1 13.5 1.5H15a3 3 0 0 1 2.663 1.618ZM12 4.5A1.5 1.5 0 0 1 13.5 3H15a1.5 1.5 0 0 1 1.5 1.5H12Z" clip-rule="evenodd" />
<path d="M3 8.625c0-1.036.84-1.875 1.875-1.875h.375A3.75 3.75 0 0 1 9 10.5v1.875c0 1.036.84 1.875 1.875 1.875h1.875A3.75 3.75 0 0 1 16.5 18v2.625c0 1.035-.84 1.875-1.875 1.875h-9.75A1.875 1.875 0 0 1 3 20.625v-12Z" />
<path d="M10.5 10.5a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963 5.23 5.23 0 0 0-3.434-1.279h-1.875a.375.375 0 0 1-.375-.375V10.5Z" />
</svg>
{% endif %}
{% if button['name'] == "edit" %}
<svg class="h-6 w-6 fill-white"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336c44.2 0 80-35.8 80-80s-35.8-80-80-80s-80 35.8-80 80s35.8 80 80 80z" />
</svg>
{% endif %}
{% if button['name'] == "delete" %}
<svg class="h-6 w-6 fill-white"
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>
{% endif %}
</button>
{% endfor %}
</div>
<!-- end button list-->
</div>
{% endfor %}
{% endfor %}
{% endif %}
</div>
<!-- end services container-->
<!-- modal -->
{% include "services_modal.html" %}
{% endblock content %}

View file

@ -2,123 +2,123 @@
<div data-service-content="settings"
data-services-modal
class="dark:brightness-110 hidden w-screen h-screen fixed bg-gray-600/50 z-[1001] top-0 left-0 justify-center items-center">
<div data-services-modal-card
class="overflow-y-auto mx-0 sm:mx-6 lg:mx-8 my-3 px-4 pt-4 pb-8 w-full sm:min-w-[500px] h-[90vh] flex flex-col break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="w-full flex justify-between mb-2">
<div class="flex justify-start items-center">
<p data-services-modal-title
class="transition duration-300 ease-in-out dark:opacity-90 dark:text-gray-200 mb-1 font-sans font-semibold leading-normal uppercase text-md">
SERVICE MODAL
</p>
<button data-toggle-draft-btn
class="transition hover:brightness-75 dark:hover:brightness-110 ml-4 flex items-center border border-gray-700 dark:border-gray-300 rounded py-1 px-2">
<p data-toggle-draft="true"
class="hidden dark:text-gray-300 mb-0 mr-2 pointer-events-none">Draft</p>
<p data-toggle-draft="false"
class="hidden dark:text-gray-300 mb-0 mr-2 pointer-events-none">Online</p>
<svg data-toggle-draft="true"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="hidden w-5 h-5 fill-gray-700 dark:fill-gray-300 pointer-events-none">
<path fill-rule="evenodd" d="M10.5 3.798v5.02a3 3 0 0 1-.879 2.121l-2.377 2.377a9.845 9.845 0 0 1 5.091 1.013 8.315 8.315 0 0 0 5.713.636l.285-.071-3.954-3.955a3 3 0 0 1-.879-2.121v-5.02a23.614 23.614 0 0 0-3 0Zm4.5.138a.75.75 0 0 0 .093-1.495A24.837 24.837 0 0 0 12 2.25a25.048 25.048 0 0 0-3.093.191A.75.75 0 0 0 9 3.936v4.882a1.5 1.5 0 0 1-.44 1.06l-6.293 6.294c-1.62 1.621-.903 4.475 1.471 4.88 2.686.46 5.447.698 8.262.698 2.816 0 5.576-.239 8.262-.697 2.373-.406 3.092-3.26 1.47-4.881L15.44 9.879A1.5 1.5 0 0 1 15 8.818V3.936Z" clip-rule="evenodd" />
</svg>
<svg data-toggle-draft="false"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="hidden w-5 h-5 fill-gray-700 dark:fill-gray-300 pointer-events-none">
<path d="M21.721 12.752a9.711 9.711 0 0 0-.945-5.003 12.754 12.754 0 0 1-4.339 2.708 18.991 18.991 0 0 1-.214 4.772 17.165 17.165 0 0 0 5.498-2.477ZM14.634 15.55a17.324 17.324 0 0 0 .332-4.647c-.952.227-1.945.347-2.966.347-1.021 0-2.014-.12-2.966-.347a17.515 17.515 0 0 0 .332 4.647 17.385 17.385 0 0 0 5.268 0ZM9.772 17.119a18.963 18.963 0 0 0 4.456 0A17.182 17.182 0 0 1 12 21.724a17.18 17.18 0 0 1-2.228-4.605ZM7.777 15.23a18.87 18.87 0 0 1-.214-4.774 12.753 12.753 0 0 1-4.34-2.708 9.711 9.711 0 0 0-.944 5.004 17.165 17.165 0 0 0 5.498 2.477ZM21.356 14.752a9.765 9.765 0 0 1-7.478 6.817 18.64 18.64 0 0 0 1.988-4.718 18.627 18.627 0 0 0 5.49-2.098ZM2.644 14.752c1.682.971 3.53 1.688 5.49 2.099a18.64 18.64 0 0 0 1.988 4.718 9.765 9.765 0 0 1-7.478-6.816ZM13.878 2.43a9.755 9.755 0 0 1 6.116 3.986 11.267 11.267 0 0 1-3.746 2.504 18.63 18.63 0 0 0-2.37-6.49ZM12 2.276a17.152 17.152 0 0 1 2.805 7.121c-.897.23-1.837.353-2.805.353-.968 0-1.908-.122-2.805-.353A17.151 17.151 0 0 1 12 2.276ZM10.122 2.43a18.629 18.629 0 0 0-2.37 6.49 11.266 11.266 0 0 1-3.746-2.504 9.754 9.754 0 0 1 6.116-3.985Z" />
</svg>
</button>
</div>
<button class="-translate-y-1"
aria-label="close modal"
data-services-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 data-services-modal-card
class="overflow-y-auto mx-0 sm:mx-6 lg:mx-8 my-3 px-4 pt-4 pb-8 w-full sm:min-w-[500px] h-[90vh] flex flex-col break-words bg-white shadow-xl dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border">
<div class="w-full flex justify-between mb-2">
<div class="flex justify-start items-center">
<p data-services-modal-title
class="transition duration-300 ease-in-out dark:opacity-90 dark:text-gray-200 mb-1 font-sans font-semibold leading-normal uppercase text-md">
SERVICE MODAL
</p>
<button data-toggle-draft-btn
class="transition hover:brightness-75 dark:hover:brightness-110 ml-4 flex items-center border border-gray-700 dark:border-gray-300 rounded py-1 px-2">
<p data-toggle-draft="true"
class="hidden dark:text-gray-300 mb-0 mr-2 pointer-events-none">Draft</p>
<p data-toggle-draft="false"
class="hidden dark:text-gray-300 mb-0 mr-2 pointer-events-none">Online</p>
<svg data-toggle-draft="true"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="hidden w-5 h-5 fill-gray-700 dark:fill-gray-300 pointer-events-none">
<path fill-rule="evenodd" d="M10.5 3.798v5.02a3 3 0 0 1-.879 2.121l-2.377 2.377a9.845 9.845 0 0 1 5.091 1.013 8.315 8.315 0 0 0 5.713.636l.285-.071-3.954-3.955a3 3 0 0 1-.879-2.121v-5.02a23.614 23.614 0 0 0-3 0Zm4.5.138a.75.75 0 0 0 .093-1.495A24.837 24.837 0 0 0 12 2.25a25.048 25.048 0 0 0-3.093.191A.75.75 0 0 0 9 3.936v4.882a1.5 1.5 0 0 1-.44 1.06l-6.293 6.294c-1.62 1.621-.903 4.475 1.471 4.88 2.686.46 5.447.698 8.262.698 2.816 0 5.576-.239 8.262-.697 2.373-.406 3.092-3.26 1.47-4.881L15.44 9.879A1.5 1.5 0 0 1 15 8.818V3.936Z" clip-rule="evenodd" />
</svg>
<svg data-toggle-draft="false"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="hidden w-5 h-5 fill-gray-700 dark:fill-gray-300 pointer-events-none">
<path d="M21.721 12.752a9.711 9.711 0 0 0-.945-5.003 12.754 12.754 0 0 1-4.339 2.708 18.991 18.991 0 0 1-.214 4.772 17.165 17.165 0 0 0 5.498-2.477ZM14.634 15.55a17.324 17.324 0 0 0 .332-4.647c-.952.227-1.945.347-2.966.347-1.021 0-2.014-.12-2.966-.347a17.515 17.515 0 0 0 .332 4.647 17.385 17.385 0 0 0 5.268 0ZM9.772 17.119a18.963 18.963 0 0 0 4.456 0A17.182 17.182 0 0 1 12 21.724a17.18 17.18 0 0 1-2.228-4.605ZM7.777 15.23a18.87 18.87 0 0 1-.214-4.774 12.753 12.753 0 0 1-4.34-2.708 9.711 9.711 0 0 0-.944 5.004 17.165 17.165 0 0 0 5.498 2.477ZM21.356 14.752a9.765 9.765 0 0 1-7.478 6.817 18.64 18.64 0 0 0 1.988-4.718 18.627 18.627 0 0 0 5.49-2.098ZM2.644 14.752c1.682.971 3.53 1.688 5.49 2.099a18.64 18.64 0 0 0 1.988 4.718 9.765 9.765 0 0 1-7.478-6.816ZM13.878 2.43a9.755 9.755 0 0 1 6.116 3.986 11.267 11.267 0 0 1-3.746 2.504 18.63 18.63 0 0 0-2.37-6.49ZM12 2.276a17.152 17.152 0 0 1 2.805 7.121c-.897.23-1.837.353-2.805.353-.968 0-1.908-.122-2.805-.353A17.151 17.151 0 0 1 12 2.276ZM10.122 2.43a18.629 18.629 0 0 0-2.37 6.49 11.266 11.266 0 0 1-3.746-2.504 9.754 9.754 0 0 1 6.116-3.985Z" />
</svg>
</button>
</div>
<button class="-translate-y-1"
aria-label="close modal"
data-services-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>
<div data-services-tabs-header
class="flex flex-col sm:flex-row justify-start items-start sm:items-center gap-x-4 gap-y-2 my-3">
<h5 class="transition duration-300 ease-in-out dark:opacity-90 ml-2 font-bold text-md uppercase dark:text-white mb-0">
CONFIGS
</h5>
<!-- search inpt-->
<div class="flex relative">
<label class="sr-only" for="settings-filter">search</label>
<input type="text"
id="settings-filter"
name="settings-filter"
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="key words"
pattern="(.*?)"
required />
</div>
<!-- end search inpt-->
</div>
{% include "settings_tabs.html" %}
<div data-services-nomatch
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 dark:stroke-white/90 stroke-gray-800">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-gray-800">No settings match</h5>
</div>
</div>
<!-- new and edit form -->
<form data-services-modal-form
class="w-full h-full flex flex-col justify-between"
id="form-new"
method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" id="operation" value="new" name="operation" />
<input type="hidden" value="new" name="OLD_SERVER_NAME" />
<input type="hidden" value="no" name="is_draft" />
{% include "settings_plugins.html" %}
<!-- action button -->
<div class="w-full justify-center flex mt-10">
<button data-services-modal-close
type="button"
class="close-btn mb-4 mr-3 text-base">Close</button>
<button data-services-modal-submit type="submit" class="mb-4 valid-btn">Save</button>
</div>
<!-- end action button-->
</form>
<!-- end new and edit form -->
<!-- delete form-->
<form data-services-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="delete" name="operation" />
<input type="hidden" value="no" name="is_draft" />
<input type="hidden" value="" name="SERVER_NAME" />
<div class="flex justify-center">
<p data-services-modal-text
class="text-gray-700 dark:text-gray-500 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 data-services-modal-close
type="button"
class="close-btn mb-4 mr-3 text-base">Close</button>
<button type="submit" class="delete-btn mb-4 mr-3 text-base">Delete</button>
</div>
<!-- end action button-->
</form>
<!-- end delete form-->
</div>
<div data-services-tabs-header
class="flex flex-col sm:flex-row justify-start items-start sm:items-center gap-x-4 gap-y-2 my-3">
<h5 class="transition duration-300 ease-in-out dark:opacity-90 ml-2 font-bold text-md uppercase dark:text-white mb-0">
CONFIGS
</h5>
<!-- search inpt-->
<div class="flex relative">
<label class="sr-only" for="settings-filter">search</label>
<input type="text"
id="settings-filter"
name="settings-filter"
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="key words"
pattern="(.*?)"
required />
</div>
<!-- end search inpt-->
</div>
{% include "settings_tabs.html" %}
<div data-services-nomatch
class="hidden w-full overflow-hidden grid grid-cols-12 max-h-100 sm:max-h-125 col-span-12 p-4 relative break-words">
<div class="col-span-12 flex flex-col justify-center items-center h-fit">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="mb-2 w-8 h-8 dark:stroke-white/90 stroke-gray-800">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
</svg>
<h5 class="font-bold dark:text-white/90 mx-2 text-gray-800">No settings match</h5>
</div>
</div>
<!-- new and edit form -->
<form data-services-modal-form
class="w-full h-full flex flex-col justify-between"
id="form-new"
method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" id="operation" value="new" name="operation" />
<input type="hidden" value="new" name="OLD_SERVER_NAME" />
<input type="hidden" value="no" name="is_draft" />
{% include "settings_plugins.html" %}
<!-- action button -->
<div class="w-full justify-center flex mt-10">
<button data-services-modal-close
type="button"
class="close-btn mb-4 mr-3 text-base">Close</button>
<button data-services-modal-submit type="submit" class="mb-4 valid-btn">Save</button>
</div>
<!-- end action button-->
</form>
<!-- end new and edit form -->
<!-- delete form-->
<form data-services-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="delete" name="operation" />
<input type="hidden" value="no" name="is_draft" />
<input type="hidden" value="" name="SERVER_NAME" />
<div class="flex justify-center">
<p data-services-modal-text
class="text-gray-700 dark:text-gray-500 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 data-services-modal-close
type="button"
class="close-btn mb-4 mr-3 text-base">Close</button>
<button type="submit" class="delete-btn mb-4 mr-3 text-base">Delete</button>
</div>
<!-- end action button-->
</form>
<!-- end delete form-->
</div>
</div>
<!-- end modal -->

View file

@ -3,422 +3,423 @@
{% set plugins = config["CONFIG"].get_plugins() %}
<!-- plugin item -->
{% for plugin in plugins %}
<div data-plugin-item="{{ plugin['id'] }}"
id="{{ plugin['id'] }}"
class="{% if loop.index != 1 %}hidden{% endif %} w-full">
<!-- title and desc -->
<div class="col-span-12" data-setting-header>
<div class="flex justify-start items-center">
<h5 class="transition duration-300 ease-in-out ml-2 font-bold text-md uppercase dark:text-white/90 mb-0">
{{ plugin['name'] }} <span>{{ plugin['version'] }}</span>
</h5>
{% if plugin['page'] %}
<a
aria-label="plugin page link"
class="hover:-translate-y-px mx-2"
href="{{ request.url_root }}plugins/{{ plugin['id'] }}">
<svg class="h-5 w-5 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>
{% endif %}
</div>
<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 -->
<div data-plugin-settings class="w-full grid grid-cols-12">
<!-- plugin settings not multiple -->
{% for setting, value in plugin["settings"].items() %}
{% if setting not in ["IS_LOADING", "IS_DRAFT"] and current_endpoint
== "global-config" and value['context'] == "global" and not value['multiple'] or setting != "IS_DRAFT" and current_endpoint ==
"services" and value['context'] == "multisite" and not value['multiple'] %}
<div data-setting-container
class="mx-0 sm:mx-4 my-2 col-span-12 md:mx-6 md:my-3 md:col-span-6 2xl:mx-6 2xl:my-3 2xl:col-span-4"
id="form-edit-{{ current_endpoint }}-{{ value["id"] }}">
<!-- title and info -->
<div class="flex items-center my-1 relative z-10">
<h5 class="input-title">{{ value["label"] }}</h5>
<svg data-popover-btn="{{ value["label"] }}"
class="popover-settings-svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z" />
</svg>
<!-- popover -->
<div role="alert"
aria-description="show detail"
class="popover-settings-container hidden"
data-popover-content="{{ value["label"] }}">
<p class="popover-settings-text">{{ value['help'] }}</p>
</div>
<!-- end popover -->
</div>
<!-- end title and info -->
<!-- input -->
{% if value["type"] != "select" and value["type"] != "check" %}
<div class="relative flex items-center">
<label class="sr-only" for="{{ setting }}">{{ setting }}</label>
<input {% if setting == "SERVER_NAME" %}required{% endif %}
data-default-value="{{ global_config[setting]['value'] }}"
data-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="regular-input"
value="{% if global_config[setting]['value'] %} {{ global_config[setting]['value'] }} {% else %} {{ value['default'] }} {% endif %}"
type="{{ value['type'] }}"
pattern="{{ value['regex']|safe }}" />
{% if value['type'] == "password" %}
<div data-setting-password-container class="absolute flex right-2 h-5 w-5">
<button type="button"
data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button type="button"
data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
{% endif %}
</div>
{% endif %}
<!-- end input -->
<!-- select -->
{% if value["type"] == "select" %}
<!-- default hidden-->
<select data-default-method="{{ global_config[setting]['method'] }}"
data-default-value="{{ value['default'] }}"
id="{{ setting }}"
name="{{ setting }}"
data-setting-select-default="{{ value['id'] }}"
data-type="form-select"
id="{{ setting }}"
name="{{ setting }}"
class="hidden">
{% for item in value['select'] %}
<option {% if not item %}label="empty"{% endif %}
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 data-select-container class="relative">
<button {% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %}disabled{% endif %}
data-setting-select="{{ value['id'] }}"
data-default-value="{{ global_config[setting]['value'] }}"
data-default-method="{{ global_config[setting]['method'] }}"
aria-controls="{{ value['id'] }}-dropdown"
type="button"
class="custom-select-btn">
{% for item in value['select'] %}
{% if global_config[setting]['value'] and
global_config[setting]['value'] == item %}
<span data-setting-select-text="{{ value['id'] }}"
data-value="{{ global_config[setting]['value'] }}">{{ global_config[setting]['value'] }}</span>
{% elif not global_config[setting]['value'] and value['default'] == item %}
<span aria-description="current value"
data-setting-select-text="{{ value['id'] }}"
data-value="{{ value['default'] }}">{{ value['default'] }}</span>
{% endif %}
{% endfor %}
<!-- chevron -->
<svg data-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 id="{{ value['id'] }}-dropdown"
role="listbox"
data-setting-select-dropdown="{{ value['id'] }}"
class="hidden z-[20] 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 role="option"
value="{{ item }}"
data-setting-select-dropdown-btn="{{ value['id'] }}"
type="button"
class="active custom-dropdown-btn {% if loop.index == 1 %}border-t rounded-t{% endif %} {% if loop.index == loop.length %}rounded-b{% endif %} ">
{{ item }}
</button>
{% else %}
<button role="option"
value="{{ item }}"
data-setting-select-dropdown-btn="{{ value['id'] }}"
type="button"
class="custom-dropdown-btn {% if loop.index == 1 %}border-t rounded-t{% endif %} {% if loop.index == loop.length %}rounded-b{% endif %} ">
{{ item }}
</button>
{% endif %}
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end custom-->
{% endif %}
<!-- checkbox -->
{% if value["type"] == "check" %}
<div data-checkbox-handler="{{ value['id'] }}"
class="relative mb-7 md:mb-0 z-10 ">
<label class="sr-only" for="{{ setting }}">{{ setting }}</label>
<input id="{{ setting }}"
name="{{ setting }}"
data-default-method="{% if setting in ['AUTOCONF_MODE', 'SWARM_MODE', 'KUBERNETES_MODE'] %}mode{% else %}{{ global_config[setting]['method'] }}{% endif %}"
data-default-value="{{ global_config[setting]['value'] }}"
{% if setting in ['AUTOCONF_MODE', 'SWARM_MODE', 'KUBERNETES_MODE'] or global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %} disabled {% endif %}
data-checked="{% if global_config[setting]['value'] == "yes" %}true{% else %}false{% endif %}"
checked
id="checkbox-{{ value['id'] }}"
class="checkbox"
type="checkbox"
data-pattern="{{ value['regex']|safe }}"
value="{{ global_config[setting]['value'] }}" />
<svg data-checkbox-handler="{{ value['id'] }}"
class="pointer-events-none 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 class="pointer-events-none" 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 role="alert"
aria-label="show when invalid input"
class="hidden text-sm dark:text-red-500">
{{ value['label'] }} is invalid and must match this pattern:
{{ value['regex']|safe }}
</div>
<!--end invalid feedback-->
</div>
{% endif %}
{% endfor %}
<!-- end plugin settings -->
</div>
<!-- end plugin settings not multiple -->
{# get number of multiple groups for the plugin #}
{% set multList = [] %}
{% for setting, value in plugin["settings"].items() %}
{% if current_endpoint
== "global-config" and value['context'] == "global" and value['multiple'] and not value['multiple'] in multList or current_endpoint ==
"services" and value['context'] == "multisite" and value['multiple'] and not value['multiple'] in multList %}
{% if multList.append(value['multiple']) %}{% endif %}
{% endif %}
{% endfor %}
{% for multiple in multList %}
<!-- plugin multiple handler -->
<div data-multiple-handler
class="flex items-center mx-0 sm:mx-4 md:mx-6 md:my-3 my-2 2xl:mx-6 2xl:my-3 col-span-12 ">
<h5 class="input-title">{{ multiple }}</h5>
<button data-{{ current_endpoint }}-multiple-add="{{ multiple }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Add
</button>
<button data-{{ current_endpoint }}-multiple-toggle="{{ multiple }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-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">
SHOW / HIDE
</button>
</div>
<!-- end plugin multiple handler-->
<!-- multiple settings -->
<div data-{{ current_endpoint }}-settings-multiple="{{ multiple }}_SCHEMA" class="bg-gray-50 dark:bg-slate-900/30 hidden w-full mb-8 grid-cols-12 border dark:border-gray-700 rounded">
{% for setting, value in plugin["settings"].items() %}
{# render only setting that match the multiple id and context #}
{% if current_endpoint
== "global-config" and value['context'] == "global" and value['multiple'] == multiple or current_endpoint ==
"services" and value['context'] == "multisite" and value['multiple'] == multiple %}
<div data-setting-container="{{ setting }}_SCHEMA"
class="mx-0 sm:mx-4 my-2 col-span-12 md:mx-6 md:my-3 md:col-span-6 2xl:mx-6 2xl:my-3 2xl:col-span-4"
id="form-edit-{{ current_endpoint }}-{{ value["id"] }}_SCHEMA">
<!-- title and info -->
<div class="flex items-center my-1 relative z-10">
<h5 class="input-title">{{ value["label"] }}</h5>
<svg data-popover-btn="{{ value["label"] }}"
class="popover-settings-svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z" />
</svg>
<!-- popover -->
<div role="alert"
aria-description="show detail"
class="popover-settings-container hidden"
data-popover-content="{{ value["label"] }}">
<p class="popover-settings-text">{{ value['help'] }}</p>
</div>
<!-- end popover -->
</div>
<!-- end title and info -->
<!-- input -->
{% if value["type"] != "select" and value["type"] != "check" %}
<div class="relative flex items-center">
<label class="sr-only" for="{{ setting }}_SCHEMA">{{ setting }}</label>
<input data-default-value="{{ value['default'] }}"
data-default-method="default"
id="{{ setting }}_SCHEMA"
name="{{ setting }}_SCHEMA"
class="regular-input"
value="{{ value['default'] }}"
type="{{ value['type'] }}"
pattern="{{ value['regex']|safe }}" />
{% if value['type'] == "password" %}
<div data-setting-password-container class="absolute flex right-2 h-5 w-5">
<button type="button"
data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
<div data-plugin-item="{{ plugin['id'] }}"
id="{{ plugin['id'] }}"
class="{% if loop.index != 1 %}hidden{% endif %} w-full">
<!-- title and desc -->
<div class="col-span-12" data-setting-header>
<div class="flex justify-start items-center">
<h5 class="transition duration-300 ease-in-out ml-2 font-bold text-md uppercase dark:text-white/90 mb-0">
{{ plugin['name'] }} <span>{{ plugin['version'] }}</span>
</h5>
{% if plugin['page'] %}
<a aria-label="plugin page link"
class="hover:-translate-y-px mx-2"
href="{{ request.url_root }}plugins/{{ plugin['id'] }}">
<svg class="h-5 w-5 fill-sky-500 dark dark:brightness-90"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
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>
</button>
<button type="button"
data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
{% endif %}
</div>
{% endif %}
<!-- end input -->
<!-- select -->
{% if value["type"] == "select" %}
<!-- default hidden-->
<select data-default-method="default"
data-default-value="{{ value['default'] }}"
id="{{ setting }}_SCHEMA"
name="{{ setting }}_SCHEMA"
data-select-default="{{ value['id'] }}"
data-type="form-select"
id="{{ setting }}"
name="{{ setting }}"
class="hidden">
{% for item in value['select'] %}
<option {% if not item %}label="empty"{% endif %}
value="{{ item }}"
{% if value['default'] == item %}selected{% endif %}>{{ item }}</option>
{% endfor %}
</select>
<!-- end default hidden-->
<!--custom-->
<div data-select-container class="relative">
<button data-setting-select="{{ value['id'] }}"
data-default-value="{{ value['default'] }}"
aria-controls="{{ value['id'] }}-dropdown"
type="button"
class="custom-select-btn">
{% for item in value['select'] %}
{% if value['default'] == item %}
<span aria-description="current value"
data-setting-select-text="{{ value['id'] }}"
data-value="{{ value['default'] }}">{{ value['default'] }}</span>
{% endif %}
{% endfor %}
<!-- chevron -->
<svg data-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 id="{{ value['id'] }}-dropdown"
role="listbox"
data-setting-select-dropdown="{{ value['id'] }}"
class="hidden z-[20] absolute h-full flex-col w-full mt-2">
{% for item in value['select'] %}
{% if value['default'] == item %}
<button role="option"
value="{{ item }}"
data-setting-select-dropdown-btn="{{ value['id'] }}"
class="active custom-dropdown-btn {% if loop.index == 1 %}border-t rounded-t{% endif %} {% if loop.index == loop.length %}rounded-b{% endif %}">
{{ item }}
</button>
{% else %}
<button role="option"
value="{{ item }}"
data-setting-select-dropdown-btn="{{ value['id'] }}"
class="custom-dropdown-btn {% if loop.index == 1 %}border-t rounded-t{% endif %} {% if loop.index == loop.length %}rounded-b{% endif %}">
{{ item }}
</button>
{% endif %}
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end custom-->
{% endif %}
<!-- checkbox -->
{% if value["type"] == "check" %}
<div data-checkbox-handler="{{ value['id'] }}"
class="relative mb-7 md:mb-0">
<label class="sr-only" for="{{ setting }}_SCHEMA">{{ setting }}</label>
<input id="{{ setting }}_SCHEMA" name="{{ setting }}_SCHEMA"
data-default-method="default"
data-default-value="{{ value['default'] }}" {% if value['default'] == 'yes' %} checked {%
endif %} id="checkbox-{{ value['id'] }}"
class="checkbox" type="checkbox" data-pattern="{{ value['regex']|safe }}"
value="{{ value['default'] }}" />
<svg data-checkbox-handler="{{ value['id'] }}"
class="pointer-events-none 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>
</a>
{% endif %}
<!-- end checkbox -->
<!-- invalid feedback -->
<div role="alert"
aria-label="show when invalid"
class="hidden text-sm dark:text-red-500">
{{ value['label'] }} is invalid and must match this pattern:
{{ value['regex']|safe }}
</div>
<!--end invalid feedback-->
</div>
{% endif %}
{% endfor %}
<div data-multiple-delete-container
class="col-span-12 flex justify-center my-4">
<button data-{{ 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>
<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>
{% endfor %}
<!-- end multiple settings -->
</div>
{% endfor %}
<!-- end plugin item -->
<!-- end title and desc -->
<div data-plugin-settings class="w-full grid grid-cols-12">
<!-- plugin settings not multiple -->
{% for setting, value in plugin["settings"].items() %}
{% if setting not in ["IS_LOADING", "IS_DRAFT"] and current_endpoint
== "global-config" and value['context'] == "global" and not value['multiple'] or setting != "IS_DRAFT" and current_endpoint ==
"services" and value['context'] == "multisite" and not value['multiple'] %}
<div data-setting-container
class="mx-0 sm:mx-4 my-2 col-span-12 md:mx-6 md:my-3 md:col-span-6 2xl:mx-6 2xl:my-3 2xl:col-span-4"
id="form-edit-{{ current_endpoint }}-{{ value["id"] }}">
<!-- title and info -->
<div class="flex items-center my-1 relative z-10">
<h5 class="input-title">{{ value["label"] }}</h5>
<svg data-popover-btn="{{ value["label"] }}"
class="popover-settings-svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z" />
</svg>
<!-- popover -->
<div role="alert"
aria-description="show detail"
class="popover-settings-container hidden"
data-popover-content="{{ value["label"] }}">
<p class="popover-settings-text">{{ value['help'] }}</p>
</div>
<!-- end popover -->
</div>
<!-- end title and info -->
<!-- input -->
{% if value["type"] != "select" and value["type"] != "check" %}
<div class="relative flex items-center">
<label class="sr-only" for="{{ setting }}">{{ setting }}</label>
<input {% if setting == "SERVER_NAME" %}required{% endif %}
data-default-value="{{ global_config[setting]['value'] }}"
data-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="regular-input"
value="{% if global_config[setting]['value'] %} {{ global_config[setting]['value'] }} {% else %} {{ value['default'] }} {% endif %}"
type="{{ value['type'] }}"
pattern="{{ value['regex']|safe }}" />
{% if value['type'] == "password" %}
<div data-setting-password-container class="absolute flex right-2 h-5 w-5">
<button type="button"
data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button type="button"
data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
{% endif %}
</div>
{% endif %}
<!-- end input -->
<!-- select -->
{% if value["type"] == "select" %}
<!-- default hidden-->
<select data-default-method="{{ global_config[setting]['method'] }}"
data-default-value="{{ value['default'] }}"
id="{{ setting }}"
name="{{ setting }}"
data-setting-select-default="{{ value['id'] }}"
data-type="form-select"
id="{{ setting }}"
name="{{ setting }}"
class="hidden">
{% for item in value['select'] %}
<option {% if not item %}label="empty"{% endif %}
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 data-select-container class="relative">
<button {% if global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %}disabled{% endif %}
data-setting-select="{{ value['id'] }}"
data-default-value="{{ global_config[setting]['value'] }}"
data-default-method="{{ global_config[setting]['method'] }}"
aria-controls="{{ value['id'] }}-dropdown"
type="button"
class="custom-select-btn">
{% for item in value['select'] %}
{% if global_config[setting]['value'] and
global_config[setting]['value'] == item %}
<span data-setting-select-text="{{ value['id'] }}"
data-value="{{ global_config[setting]['value'] }}">{{ global_config[setting]['value'] }}</span>
{% elif not global_config[setting]['value'] and value['default'] == item %}
<span aria-description="current value"
data-setting-select-text="{{ value['id'] }}"
data-value="{{ value['default'] }}">{{ value['default'] }}</span>
{% endif %}
{% endfor %}
<!-- chevron -->
<svg data-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 id="{{ value['id'] }}-dropdown"
role="listbox"
data-setting-select-dropdown="{{ value['id'] }}"
class="hidden z-[20] 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 role="option"
value="{{ item }}"
data-setting-select-dropdown-btn="{{ value['id'] }}"
type="button"
class="active custom-dropdown-btn {% if loop.index == 1 %}border-t rounded-t{% endif %} {% if loop.index == loop.length %}rounded-b{% endif %} ">
{{ item }}
</button>
{% else %}
<button role="option"
value="{{ item }}"
data-setting-select-dropdown-btn="{{ value['id'] }}"
type="button"
class="custom-dropdown-btn {% if loop.index == 1 %}border-t rounded-t{% endif %} {% if loop.index == loop.length %}rounded-b{% endif %} ">
{{ item }}
</button>
{% endif %}
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end custom-->
{% endif %}
<!-- checkbox -->
{% if value["type"] == "check" %}
<div data-checkbox-handler="{{ value['id'] }}"
class="relative mb-7 md:mb-0 z-10 ">
<label class="sr-only" for="{{ setting }}">{{ setting }}</label>
<input id="{{ setting }}"
name="{{ setting }}"
data-default-method="{% if setting in ['AUTOCONF_MODE', 'SWARM_MODE', 'KUBERNETES_MODE'] %}mode{% else %}{{ global_config[setting]['method'] }}{% endif %}"
data-default-value="{{ global_config[setting]['value'] }}"
{% if setting in ['AUTOCONF_MODE', 'SWARM_MODE', 'KUBERNETES_MODE'] or global_config[setting]['method'] != 'ui' and global_config[setting]['method'] != 'default' %} disabled {% endif %}
data-checked="{% if global_config[setting]['value'] == "yes" %}true{% else %}false{% endif %}"
checked
id="checkbox-{{ value['id'] }}"
class="checkbox"
type="checkbox"
data-pattern="{{ value['regex']|safe }}"
value="{{ global_config[setting]['value'] }}" />
<svg data-checkbox-handler="{{ value['id'] }}"
class="pointer-events-none 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 class="pointer-events-none" 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 role="alert"
aria-label="show when invalid input"
class="hidden text-sm dark:text-red-500">
{{ value['label'] }} is invalid and must match this pattern:
{{ value['regex']|safe }}
</div>
<!--end invalid feedback-->
</div>
{% endif %}
{% endfor %}
<!-- end plugin settings -->
</div>
<!-- end plugin settings not multiple -->
{# get number of multiple groups for the plugin #}
{% set multList = [] %}
{% for setting, value in plugin["settings"].items() %}
{% if current_endpoint
== "global-config" and value['context'] == "global" and value['multiple'] and not value['multiple'] in multList or current_endpoint ==
"services" and value['context'] == "multisite" and value['multiple'] and not value['multiple'] in multList %}
{% if multList.append(value['multiple']) %}{% endif %}
{% endif %}
{% endfor %}
{% for multiple in multList %}
<!-- plugin multiple handler -->
<div data-multiple-handler
class="flex items-center mx-0 sm:mx-4 md:mx-6 md:my-3 my-2 2xl:mx-6 2xl:my-3 col-span-12 ">
<h5 class="input-title">{{ multiple }}</h5>
<button data-{{ current_endpoint }}-multiple-add="{{ multiple }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Add
</button>
<button data-{{ current_endpoint }}-multiple-toggle="{{ multiple }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-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">
SHOW / HIDE
</button>
</div>
<!-- end plugin multiple handler-->
<!-- multiple settings -->
<div data-{{ current_endpoint }}-settings-multiple="{{ multiple }}_SCHEMA" class="bg-gray-50 dark:bg-slate-900/30 hidden w-full mb-8 grid-cols-12 border dark:border-gray-700 rounded">
{% for setting, value in plugin["settings"].items() %}
{# render only setting that match the multiple id and context #}
{% if current_endpoint
== "global-config" and value['context'] == "global" and value['multiple'] == multiple or current_endpoint ==
"services" and value['context'] == "multisite" and value['multiple'] == multiple %}
<div data-setting-container="{{ setting }}_SCHEMA"
class="mx-0 sm:mx-4 my-2 col-span-12 md:mx-6 md:my-3 md:col-span-6 2xl:mx-6 2xl:my-3 2xl:col-span-4"
id="form-edit-{{ current_endpoint }}-{{ value["id"] }}_SCHEMA">
<!-- title and info -->
<div class="flex items-center my-1 relative z-10">
<h5 class="input-title">{{ value["label"] }}</h5>
<svg data-popover-btn="{{ value["label"] }}"
class="popover-settings-svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z" />
</svg>
<!-- popover -->
<div role="alert"
aria-description="show detail"
class="popover-settings-container hidden"
data-popover-content="{{ value["label"] }}">
<p class="popover-settings-text">{{ value['help'] }}</p>
</div>
<!-- end popover -->
</div>
<!-- end title and info -->
<!-- input -->
{% if value["type"] != "select" and value["type"] != "check" %}
<div class="relative flex items-center">
<label class="sr-only" for="{{ setting }}_SCHEMA">{{ setting }}</label>
<input data-default-value="{{ value['default'] }}"
data-default-method="default"
id="{{ setting }}_SCHEMA"
name="{{ setting }}_SCHEMA"
class="regular-input"
value="{{ value['default'] }}"
type="{{ value['type'] }}"
pattern="{{ value['regex']|safe }}" />
{% if value['type'] == "password" %}
<div data-setting-password-container class="absolute flex right-2 h-5 w-5">
<button type="button"
data-setting-password="visible"
class="h-5 w-5 flex items-center align-middle">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512">
<path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" />
</svg>
</button>
<button type="button"
data-setting-password="invisible"
class="hidden -translate-y-0.2 scale-110 h-5 w-5 items-center align-middle">
<svg class="fill-primary pointer-events-none dark:fill-blue-500 hover:brightness-75 transition-all"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512">
<path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" />
</svg>
</button>
</div>
{% endif %}
</div>
{% endif %}
<!-- end input -->
<!-- select -->
{% if value["type"] == "select" %}
<!-- default hidden-->
<select data-default-method="default"
data-default-value="{{ value['default'] }}"
id="{{ setting }}_SCHEMA"
name="{{ setting }}_SCHEMA"
data-select-default="{{ value['id'] }}"
data-type="form-select"
id="{{ setting }}"
name="{{ setting }}"
class="hidden">
{% for item in value['select'] %}
<option {% if not item %}label="empty"{% endif %}
value="{{ item }}"
{% if value['default'] == item %}selected{% endif %}>
{{ item }}
</option>
{% endfor %}
</select>
<!-- end default hidden-->
<!--custom-->
<div data-select-container class="relative">
<button data-setting-select="{{ value['id'] }}"
data-default-value="{{ value['default'] }}"
aria-controls="{{ value['id'] }}-dropdown"
type="button"
class="custom-select-btn">
{% for item in value['select'] %}
{% if value['default'] == item %}
<span aria-description="current value"
data-setting-select-text="{{ value['id'] }}"
data-value="{{ value['default'] }}">{{ value['default'] }}</span>
{% endif %}
{% endfor %}
<!-- chevron -->
<svg data-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 id="{{ value['id'] }}-dropdown"
role="listbox"
data-setting-select-dropdown="{{ value['id'] }}"
class="hidden z-[20] absolute h-full flex-col w-full mt-2">
{% for item in value['select'] %}
{% if value['default'] == item %}
<button role="option"
value="{{ item }}"
data-setting-select-dropdown-btn="{{ value['id'] }}"
class="active custom-dropdown-btn {% if loop.index == 1 %}border-t rounded-t{% endif %} {% if loop.index == loop.length %}rounded-b{% endif %}">
{{ item }}
</button>
{% else %}
<button role="option"
value="{{ item }}"
data-setting-select-dropdown-btn="{{ value['id'] }}"
class="custom-dropdown-btn {% if loop.index == 1 %}border-t rounded-t{% endif %} {% if loop.index == loop.length %}rounded-b{% endif %}">
{{ item }}
</button>
{% endif %}
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end custom-->
{% endif %}
<!-- checkbox -->
{% if value["type"] == "check" %}
<div data-checkbox-handler="{{ value['id'] }}"
class="relative mb-7 md:mb-0">
<label class="sr-only" for="{{ setting }}_SCHEMA">{{ setting }}</label>
<input id="{{ setting }}_SCHEMA" name="{{ setting }}_SCHEMA"
data-default-method="default"
data-default-value="{{ value['default'] }}" {% if value['default'] == 'yes' %} checked {%
endif %} id="checkbox-{{ value['id'] }}"
class="checkbox" type="checkbox" data-pattern="{{ value['regex']|safe }}"
value="{{ value['default'] }}" />
<svg data-checkbox-handler="{{ value['id'] }}"
class="pointer-events-none 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 role="alert"
aria-label="show when invalid"
class="hidden text-sm dark:text-red-500">
{{ value['label'] }} is invalid and must match this pattern:
{{ value['regex']|safe }}
</div>
<!--end invalid feedback-->
</div>
{% endif %}
{% endfor %}
<div data-multiple-delete-container
class="col-span-12 flex justify-center my-4">
<button data-{{ 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>
{% endfor %}
<!-- end multiple settings -->
</div>
{% endfor %}
<!-- end plugin item -->

View file

@ -1,84 +1,84 @@
{% set current_endpoint = current_endpoint or url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
{% set plugins = config["CONFIG"].get_plugins() %}
<div data-{{ current_endpoint }}-tabs class="col-span-12 grid grid-cols-12 {% if current_endpoint == 'services' %}mb-4{% endif %}">
<!-- desktop tabs -->
<div role="tablist" data-{{ current_endpoint }}-tabs-desktop class="hidden md:block col-span-12">
<!-- tabs -->
{% for plugin in plugins %}
{% if current_endpoint == "services" and plugin["settings"]
and check_settings(plugin["settings"], "multisite") or current_endpoint == "global-config" and plugin["settings"]
and check_settings(plugin["settings"], "global") %}
<button role="tab"
data-tab-handler="{{ plugin['id'] }}"
class="{% if loop.first %}active{% endif %} settings-tabs-tab-btn">
<span class="w-full flex justify-between items-center">
<!-- text and icon -->
<span class="settings-tabs-name">{{ plugin['name'] }}</span>
<svg data-popover-btn="{{ plugin['name'] }}"
class=" fill-blue-500 h-5 w-5 mr-2 hover:brightness-95"
<!-- desktop tabs -->
<div role="tablist" data-{{ current_endpoint }}-tabs-desktop class="hidden md:block col-span-12">
<!-- tabs -->
{% for plugin in plugins %}
{% if current_endpoint == "services" and plugin["settings"]
and check_settings(plugin["settings"], "multisite") or current_endpoint == "global-config" and plugin["settings"]
and check_settings(plugin["settings"], "global") %}
<button role="tab"
data-tab-handler="{{ plugin['id'] }}"
class="{% if loop.first %}active{% endif %} settings-tabs-tab-btn">
<span class="w-full flex justify-between items-center">
<!-- text and icon -->
<span class="settings-tabs-name">{{ plugin['name'] }}</span>
<svg data-popover-btn="{{ plugin['name'] }}"
class=" fill-blue-500 h-5 w-5 mr-2 hover:brightness-95"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z" />
</svg>
<!-- end text and icon -->
<!-- popover -->
<span data-popover-content="{{ plugin['name'] }}"
class="settings-tabs-popover-container hidden">
<span class="settings-tabs-popover-text">{{ plugin['description'] }}</span>
</span>
<!-- end popover -->
</span>
</button>
{% endif %}
{% endfor %}
<!--end tabs-->
</div>
<!-- end desktop tabs -->
<!-- mobile tabs -->
<div class="md:hidden relative col-span-12 h-full">
<button data-tab-dropdown-btn
aria-controls="tab-dropdown-mobile"
class="settings-tabs-mobile-btn">
<span aria-description="current tab" class="settings-tabs-mobile-btn-text">
{% if current_endpoint == "global-config" %}general{% endif %}
</span>
<!-- chevron -->
<svg class="transition-transform h-4 w-4 fill-primary dark:fill-gray-300"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="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" />
<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 text and icon -->
<!-- popover -->
<span data-popover-content="{{ plugin['name'] }}"
class="settings-tabs-popover-container hidden">
<span class="settings-tabs-popover-text">{{ plugin['description'] }}</span>
</span>
<!-- end popover -->
</span>
<!-- end chevron -->
</button>
{% endif %}
{% endfor %}
<!--end tabs-->
</div>
<!-- end desktop tabs -->
<!-- mobile tabs -->
<div class="md:hidden relative col-span-12 h-full">
<button data-tab-dropdown-btn
aria-controls="tab-dropdown-mobile"
class="settings-tabs-mobile-btn">
<span aria-description="current tab" class="settings-tabs-mobile-btn-text">
{% if current_endpoint == "global-config" %}general{% endif %}
</span>
<!-- chevron -->
<svg class="transition-transform h-4 w-4 fill-primary dark:fill-gray-300"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" />
</svg>
<!-- end chevron -->
</button>
<!-- dropdown-->
<div id="tab-dropdown-mobile"
role="listbox"
data-tab-dropdown
class="hidden z-100 absolute flex-col w-full overflow-hidden overflow-y-auto max-h-90">
{% set first_el = "True" %}
{% for plugin in plugins %}
{% if current_endpoint == "services" and plugin["settings"]
and check_settings(plugin["settings"], "multisite") or current_endpoint == "global-config" and plugin["settings"]
and check_settings(plugin["settings"], "global") %}
{% if loop.first %}
<button role="option"
data-tab-handler-mobile="{{ plugin['id'] }}"
data-select="false"
id="edit-{{ current_endpoint }}-{{ plugin['id'] }}-tab"
class="active first settings-tabs-mobile-dropdown-btn">{{ plugin['name'] }}</button>
{% else %}
<button role="option"
data-tab-handler-mobile="{{ plugin['id'] }}"
data-select="false"
id="edit-{{ current_endpoint }}-{{ plugin['id'] }}-tab"
class="settings-tabs-mobile-dropdown-btn {% if loop.index == loop.length %}rounded-b{% endif %}">
{{ plugin['name'] }}
</button>
{% endif %}
{% endif %}
{% endfor %}
<!-- dropdown-->
<div id="tab-dropdown-mobile"
role="listbox"
data-tab-dropdown
class="hidden z-100 absolute flex-col w-full overflow-hidden overflow-y-auto max-h-90">
{% set first_el = "True" %}
{% for plugin in plugins %}
{% if current_endpoint == "services" and plugin["settings"]
and check_settings(plugin["settings"], "multisite") or current_endpoint == "global-config" and plugin["settings"]
and check_settings(plugin["settings"], "global") %}
{% if loop.first %}
<button role="option"
data-tab-handler-mobile="{{ plugin['id'] }}"
data-select="false"
id="edit-{{ current_endpoint }}-{{ plugin['id'] }}-tab"
class="active first settings-tabs-mobile-dropdown-btn">{{ plugin['name'] }}</button>
{% else %}
<button role="option"
data-tab-handler-mobile="{{ plugin['id'] }}"
data-select="false"
id="edit-{{ current_endpoint }}-{{ plugin['id'] }}-tab"
class="settings-tabs-mobile-dropdown-btn {% if loop.index == loop.length %}rounded-b{% endif %}">
{{ plugin['name'] }}
</button>
{% endif %}
{% endif %}
{% endfor %}
</div>
<!-- end dropdown-->
</div>
<!-- end dropdown-->
</div>
<!-- end mobile tabs -->
<!-- end mobile tabs -->
</div>

File diff suppressed because one or more lines are too long

View file

@ -1,118 +1,118 @@
<!DOCTYPE html>
{% block content %}
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>BunkerWeb UI | Log in</title>
<link href="images/favicon.ico" rel="icon" type="image/x-icon" />
<link rel="stylesheet" href="css/dashboard.css" />
<link rel="stylesheet" href="css/login.css" />
<script defer src="./js/totp.js" nonce="{{ script_nonce }}"></script>
</head>
<body>
<div data-loader
class="fixed z-[10000] transition duration-300 h-screen w-screen bg-primary flex justify-center align-middle items-center">
<img data-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>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if
messages %}
<!-- flash message-->
{% for category, message in messages %}
<div role="alert"
aria-description="login message alert"
data-flash-message
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 hover:scale-102 transition shadow-md break-words bg-clip-border">
<button data-close-flash-message
role="close alert message"
class="absolute right-7 top-1.5">
<svg class="cursor-pointer fill-gray-600 absolute h-5 w-5"
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>
{% if category == 'error' or (message|safe).startswith("Please log in") %}
<h5 class="text-lg mb-0 text-red-500">Error</h5>
<p class="text-gray-700 mb-0 text-sm">{{ message|safe }}</p>
{% else %}
<h5 class="text-lg mb-0 text-green-500">Success</h5>
<p class="text-gray-700 mb-0 text-sm">{{ message|safe }}</p>
{% endif %}
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>BunkerWeb UI | Log in</title>
<link href="images/favicon.ico" rel="icon" type="image/x-icon" />
<link rel="stylesheet" href="css/dashboard.css" />
<link rel="stylesheet" href="css/login.css" />
<script defer src="./js/totp.js" nonce="{{ script_nonce }}"></script>
</head>
<body>
<div data-loader
class="fixed z-[10000] transition duration-300 h-screen w-screen bg-primary flex justify-center align-middle items-center">
<img data-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>
{% endfor %}
<!-- end flash message-->
{% endif %}
{% endwith %}
<!-- end flash message-->
<!--content -->
<main class="grid grid-cols-2 align-middle items-center min-h-screen">
<!--form -->
<div class="mx-4 col-span-2 bg-none h-full flex flex-col items-center justify-center">
<div class="bg-gray-50 rounded pb-16 w-full max-w-[400px]">
<a data-back-login
class="hover:brightness-75 text-gray-700 text-sm mx-2 mt-1 flex justify-start items-center"
href="/login">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-4 h-4 stroke-gray-700 mr-1">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" />
</svg>
<span>back to login</span></a>
<div class="mt-12 flex justify-center">
<img class="w-full max-w-60 max-h-30 mb-6"
src="images/BUNKERWEB-print-hd.png"
alt="logo"
class="logo" />
</div>
<h1 class="hidden text-center font-bold mb-8">2FA</h1>
<form class="px-8 sm:px-12" action="totp" method="POST" autocomplete="off">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden"
name="next"
value="{{ request.values.get('next', '') }}" />
<!-- totp -->
<div class="flex flex-col relative col-span-12 my-3">
<h5 class="text-center my-1 transition duration-300 ease-in-out text-md font-bold m-0 ">2FA</h5>
<label class="sr-only" for="totp_token">code totp</label>
<input type="text"
id="totp_token"
name="totp_token"
class="col-span-12 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-4 py-2 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="enter totp"
pattern="(.*?)"
required />
</div>
<!-- end totp-->
<div class="flex justify-center">
<button type="submit"
id="login"
name="login"
value="login"
class="my-4 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">
Log in
</button>
</div>
</form>
</div>
</div>
<!-- end form -->
<!-- particles -->
<div class="-z-10 fixed bg-primary">
<div id="particles-js" class="login-img [&>*]:bg-primary"></div>
</div>
</main>
<script src="js/tsparticles.bundle.min.js" nonce="{{ script_nonce }}"></script>
<script nonce="{{ script_nonce }}">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if
messages %}
<!-- flash message-->
{% for category, message in messages %}
<div role="alert"
aria-description="login message alert"
data-flash-message
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 hover:scale-102 transition shadow-md break-words bg-clip-border">
<button data-close-flash-message
role="close alert message"
class="absolute right-7 top-1.5">
<svg class="cursor-pointer fill-gray-600 absolute h-5 w-5"
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>
{% if category == 'error' or (message|safe).startswith("Please log in") %}
<h5 class="text-lg mb-0 text-red-500">Error</h5>
<p class="text-gray-700 mb-0 text-sm">{{ message|safe }}</p>
{% else %}
<h5 class="text-lg mb-0 text-green-500">Success</h5>
<p class="text-gray-700 mb-0 text-sm">{{ message|safe }}</p>
{% endif %}
</div>
{% endfor %}
<!-- end flash message-->
{% endif %}
{% endwith %}
<!-- end flash message-->
<!--content -->
<main class="grid grid-cols-2 align-middle items-center min-h-screen">
<!--form -->
<div class="mx-4 col-span-2 bg-none h-full flex flex-col items-center justify-center">
<div class="bg-gray-50 rounded pb-16 w-full max-w-[400px]">
<a data-back-login
class="hover:brightness-75 text-gray-700 text-sm mx-2 mt-1 flex justify-start items-center"
href="/login">
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-4 h-4 stroke-gray-700 mr-1">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" />
</svg>
<span>back to login</span></a>
<div class="mt-12 flex justify-center">
<img class="w-full max-w-60 max-h-30 mb-6"
src="images/BUNKERWEB-print-hd.png"
alt="logo"
class="logo" />
</div>
<h1 class="hidden text-center font-bold mb-8">2FA</h1>
<form class="px-8 sm:px-12" action="totp" method="POST" autocomplete="off">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden"
name="next"
value="{{ request.values.get('next', '') }}" />
<!-- totp -->
<div class="flex flex-col relative col-span-12 my-3">
<h5 class="text-center my-1 transition duration-300 ease-in-out text-md font-bold m-0 ">2FA</h5>
<label class="sr-only" for="totp_token">code totp</label>
<input type="text"
id="totp_token"
name="totp_token"
class="col-span-12 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-4 py-2 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="enter totp"
pattern="(.*?)"
required />
</div>
<!-- end totp-->
<div class="flex justify-center">
<button type="submit"
id="login"
name="login"
value="login"
class="my-4 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">
Log in
</button>
</div>
</form>
</div>
</div>
<!-- end form -->
<!-- particles -->
<div class="-z-10 fixed bg-primary">
<div id="particles-js" class="login-img [&>*]:bg-primary"></div>
</div>
</main>
<script src="js/tsparticles.bundle.min.js" nonce="{{ script_nonce }}"></script>
<script nonce="{{ script_nonce }}">
class Loader {
constructor() {
this.menuContainer = document.querySelector("[data-menu-container]");
@ -188,7 +188,7 @@
const setLoader = new Loader();
const setFlash = new FlashMsg();
tsParticles.loadJSON("particles-js", "json/particles.json");
</script>
</body>
</html>
</script>
</body>
</html>
{% endblock content %}