Fix jobs download on jobs page in web UI

This commit is contained in:
Théophile Diot 2024-04-18 10:29:17 +02:00
parent 23a88f5104
commit 65fe15dab4
No known key found for this signature in database
GPG key ID: 248FEA4BAE400D06
16 changed files with 363 additions and 391 deletions

View file

@ -9,3 +9,4 @@ src/ui/templates/settings_plugins.html:hashicorp-tf-password:87
src/ui/templates/settings_plugins.html:hashicorp-tf-password:297
src/ui/templates/settings_plugins.html:hashicorp-tf-password:106
src/ui/templates/account.html:hashicorp-tf-password:154
src/ui/templates/account.html:hashicorp-tf-password:162

View file

@ -1876,6 +1876,7 @@ class Database:
with self.__db_session() as session:
return {
job.name: {
"plugin_id": job.plugin_id,
"every": job.every,
"reload": job.reload,
"success": job.success,
@ -1898,6 +1899,7 @@ class Database:
for job in (
session.query(Jobs).with_entities(
Jobs.name,
Jobs.plugin_id,
Jobs.every,
Jobs.reload,
Jobs.success,

View file

@ -360,17 +360,18 @@ class Download {
.hasAttribute(`data-${this.prefix}-download`)
) {
const btnEl = e.target.closest("button");
const pluginId = btnEl.getAttribute("data-jobs-plugin");
const jobName = btnEl.getAttribute("data-jobs-download");
const fileName = btnEl.getAttribute("data-jobs-file");
this.sendFileToDL(jobName, fileName);
this.sendFileToDL(pluginId, jobName, fileName);
}
} catch (err) {}
});
}
async sendFileToDL(jobName, fileName) {
async sendFileToDL(pluginId, jobName, fileName) {
window.open(
`${location.href}/download?job_name=${jobName}&file_name=${fileName}`,
`${location.href}/download?plugin_id=${pluginId}&job_name=${jobName}&file_name=${fileName}`,
);
}
}

View file

@ -103,7 +103,9 @@
<p class="my-2 mr-2 dark:text-gray-300 text-center font-bold">{{ pro_services }} services allowed</p>
{% endif %}
{% if pro_expire %}
<p class="my-2 mr-2 dark:text-gray-300 text-center">License expiration date : <span data-expire class="font-bold">{{ pro_expire }}</span></p>
<p class="my-2 mr-2 dark:text-gray-300 text-center">
License expiration date : <span data-expire class="font-bold">{{ pro_expire }}</span>
</p>
{% endif %}
</div>
{% endif %}
@ -115,60 +117,66 @@
</div>
{% endif %}
</div>
<form class="mt-6 relative col-span-12 grid grid-cols-12 w-full justify-items-center"
id="activate-key-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">{%if is_pro_version %}UPDATE KEY {% else %} ACTIVATE KEY {% endif %}</h5>
<form class="mt-6 relative col-span-12 grid grid-cols-12 w-full justify-items-center"
id="activate-key-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">
{% if is_pro_version %}
UPDATE KEY
{% else %}
ACTIVATE KEY
{% endif %}
</h5>
</div>
<input type="hidden" name="operation" value="activate-key" />
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden"
name="next"
value="{{ request.values.get('next', '') }}" />
<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">License key</h5>
<label class="sr-only" for="license">License key</label>
<input type="password"
id="license"
name="license"
class="col-span-12 regular-input"
placeholder="enter new license key"
value=""
pattern="^.*$"
required />
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[55%] md:top-[53%]">
<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>
<input type="hidden" name="operation" value="activate-key" />
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden"
name="next"
value="{{ request.values.get('next', '') }}" />
<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">License key</h5>
<label class="sr-only" for="license">License key</label>
<input type="password"
id="license"
name="license"
class="col-span-12 regular-input"
placeholder="enter new license key"
value=""
pattern="^.*$"
required />
<div data-setting-password-container
class="absolute flex right-6 md:right-8 h-5 w-5 top-[55%] md:top-[53%]">
<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>
<div class="col-span-12 flex justify-center mt-6">
<button type="submit"
id="activate-key-button"
name="activate-key-button"
class="valid-btn">SAVE</button>
</div>
</form>
</div>
<div class="col-span-12 flex justify-center mt-6">
<button type="submit"
id="activate-key-button"
name="activate-key-button"
class="valid-btn">SAVE</button>
</div>
</form>
</div>
<div data-tab-item="username"
class="hidden grid grid-cols-12 w-full justify-items-center">

View file

@ -48,19 +48,12 @@
<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>
<div role="grid" class="card-detail-container">
{% for info in bans_info %}
<div role="row"
class="card-detail-item">
<p role="gridcell"
class="card-detail-item-title">
{{ info['name'] }}
</p>
<p role="gridcell"
class="card-detail-item-subtitle">
{{ info['data'] }}
</p>
</div>
{% endfor %}
{% for info in bans_info %}
<div role="row" class="card-detail-item">
<p role="gridcell" class="card-detail-item-title">{{ info['name'] }}</p>
<p role="gridcell" class="card-detail-item-subtitle">{{ info['data'] }}</p>
</div>
{% endfor %}
</div>
</div>
<!-- end info -->

View file

@ -125,7 +125,9 @@
<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="dark:bg-slate-800 close-btn mr-3 text-base">Close</button>
<button data-bans-modal-close
type="button"
class="dark:bg-slate-800 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-->

View file

@ -14,21 +14,16 @@
] %}
<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>
<div role="grid" class="card-detail-container">
{% for info in configs_info %}
<div role="row"
class="card-detail-item">
<p role="gridcell"
class="card-detail-item-title">
{{ info['name'] }}
</p>
<p data-info-{{ info['id'] }} role="gridcell"
class="card-detail-item-subtitle">
{{ info['data'] }}
</p>
<div role="grid" class="card-detail-container">
{% for info in configs_info %}
<div role="row" class="card-detail-item">
<p role="gridcell" class="card-detail-item-title">{{ info['name'] }}</p>
<p data-info-{{ info['id'] }} role="gridcell" class="card-detail-item-subtitle">
{{ info['data'] }}
</p>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
</div>
<!-- end info -->
<!-- filter -->

View file

@ -92,7 +92,6 @@
role="listbox"
data-global-config-setting-select-dropdown="{{ filter['id'] }}"
class="mt-1 hidden z-100 absolute flex-col w-full translate-y-16 max-h-[350px] overflow-hidden overflow-y-auto">
{% for value in filter['values'] %}
<button role="option"
data-global-config-setting-select-dropdown-btn="{{ filter['id'] }}"

View file

@ -27,16 +27,9 @@
{% set instance_details = [{"name" : "TYPE", "value" : instance['_type']},{"name" : "HOSTNAME", "value" : instance['hostname']}] %}
<!-- detail -->
{% for detail in instance_details %}
<div role="row"
class="card-detail-item">
<p role="gridcell"
class="card-detail-item-title">
{{ detail['name'] }}
</p>
<p role="gridcell"
class="card-detail-item-subtitle">
{{ detail['value'] }}
</p>
<div role="row" class="card-detail-item">
<p role="gridcell" class="card-detail-item-title">{{ detail['name'] }}</p>
<p role="gridcell" class="card-detail-item-subtitle">{{ detail['value'] }}</p>
</div>
{% endfor %}
<!-- end detail -->

View file

@ -14,19 +14,12 @@
<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>
<div role="grid" class="card-detail-container">
{% for info in jobs_info %}
<div role="row"
class="card-detail-item">
<p role="gridcell"
class="card-detail-item-title">
{{ info['name'] }}
</p>
<p role="gridcell"
class="card-detail-item-subtitle">
{{ info['data'] }}
</p>
</div>
{% endfor %}
{% for info in jobs_info %}
<div role="row" class="card-detail-item">
<p role="gridcell" class="card-detail-item-title">{{ info['name'] }}</p>
<p role="gridcell" class="card-detail-item-subtitle">{{ info['data'] }}</p>
</div>
{% endfor %}
</div>
</div>
<!-- end info -->
@ -251,7 +244,8 @@
<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 }}"
<button data-jobs-plugin="{{ value['plugin_id'] }}"
data-jobs-download="{{ job_name }}"
data-jobs-file="{{ file['file_name'] }}"
data-jobs-setting-select-dropdown-btn="{{ job_name }}"
value="files"

View file

@ -35,14 +35,14 @@
<!-- logo and version -->
<div class="w-full">
<a aria-label="link to home"
class="flex justify-center px-8 m-0 text-sm whitespace-nowrap dark:text-white text-slate-700"
href="{% if current_endpoint == 'home' %}#{% else %}loading?next={{ url_for("home") }}{% endif %}">
class="flex justify-center px-8 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" />
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" />
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="mt-2 w-full px-1">
@ -50,197 +50,194 @@
{{ 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
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 -->
</div>
<!-- list items -->
<div class="items-center block w-auto overflow-auto 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-gray-200 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 dark:text-gray-200 pointer-events-none ease">{{ path[0]|upper }}{{ path[1:].replace('_', ' ') }}</span>
</a>
</li>
{% endfor %}
<!-- end loop paths-->
</ul>
<!-- end default anchor -->
<ul>
<li class="w-full mt-4">
<h6 class="pl-6 ml-2 text-xs font-bold leading-tight uppercase dark:text-gray-400 dark:opacity-100 opacity-60">
PLUGINS PAGE
</h6>
<!-- list items -->
<div class="items-center block w-auto overflow-auto 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-gray-200 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 dark:text-gray-200 pointer-events-none ease">{{ path[0]|upper }}{{ path[1:].replace('_', ' ') }}</span>
</a>
</li>
{% 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-gray-200 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 flex-wrap items-center justify-center rounded-lg bg-center stroke-0 text-center p-1 xl:p-1.5">
{% if plugin['type'] != "pro" %}
{% endfor %}
<!-- end loop paths-->
</ul>
<!-- end default anchor -->
<ul>
<li class="w-full mt-4">
<h6 class="pl-6 ml-2 text-xs font-bold leading-tight uppercase dark:text-gray-400 dark:opacity-100 opacity-60">
PLUGINS PAGE
</h6>
</li>
{% 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-gray-200 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 flex-wrap items-center justify-center rounded-lg bg-center stroke-0 text-center p-1 xl:p-1.5">
{% if plugin['type'] != "pro" %}
<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>
{% endif %}
{% if plugin['type'] == "pro" %}
{% endif %}
{% if plugin['type'] == "pro" %}
<svg class="h-5 w-5 dark:brightness-90 relative"
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>
{% endif %}
</div>
<span class="ml-1 duration-300 opacity-100 pointer-events-none ease">{{ plugin['name'] }}</span>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
<!-- end plugin list -->
</div>
<!-- end top sidebar -->
<!-- end list items -->
<!-- bottom sidebar -->
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>
{% endif %}
</div>
<span class="ml-1 duration-300 opacity-100 pointer-events-none ease">{{ plugin['name'] }}</span>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
<!-- end plugin list -->
</div>
<!-- end top sidebar -->
<!-- end list items -->
<!-- bottom sidebar -->
<div class="flex flex-col justify-end mx-4 mt-2 mb-4">
<!-- dark/light mode -->
<div class="min-h-6 ml-12 my-4 flex justify-start">

View file

@ -11,20 +11,12 @@
] %}
<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>
<div role="grid" class="card-detail-container">
{% for info in plugins_info %}
<div role="row"
class="card-detail-item">
<p role="gridcell"
class="card-detail-item-title">
{{ info['name'] }}
</p>
<p role="gridcell"
class="card-detail-item-subtitle">
{{ info['data'] }}
</p>
</div>
{% for info in plugins_info %}
<div role="row" class="card-detail-item">
<p role="gridcell" class="card-detail-item-title">{{ info['name'] }}</p>
<p role="gridcell" class="card-detail-item-subtitle">{{ info['data'] }}</p>
</div>
{% endfor %}
</div>
</div>

View file

@ -4,64 +4,53 @@
{% set codes = ["all"] %}
{% set reasons = ["all"] %}
{% set countries = ["all"] %}
{% set reasons_count = {} %}
{% set reasons_count = {} %}
{% set codes_count = {} %}
{% set countries_count = {} %}
{% set methods_count = {} %}
{% for report in reports %}
{% if reasons_count.update({report["reason"]|string : reasons_count.get(report["reason"], 0) + 1}) %}{% endif %}
{% if codes_count.update({report["status"]|string : codes_count.get(report["status"], 0) + 1}) %}{% endif %}
{% if countries_count.update({report["country"]|string : codes_count.get(report["country"], 0) + 1}) %}{% endif %}
{% if methods_count.update({report["method"]|string : methods_count.get(report["method"], 0) + 1}) %}{% endif %}
{% 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 %}
{% set top_reason = { "count" : 0, "name" : "unknown"} %}
{% set top_reason = {"count": 0, "name": "unknown"} %}
{% for key, value in reasons_count.items() %}
{% if value|int > top_reason["count"]|int %}
{% if top_reason.update({"count": value, "name" : key|string}) %}{% endif %}
{% endif %}
{% endfor %}
{% set top_code = { "count" : 0, "name" : "unknown"} %}
{% set top_code = {"count": 0, "name": "unknown"} %}
{% for key, value in codes_count.items() %}
{% if value|int > top_code["count"]|int %}
{% if top_code.update({ "count" : value|string, "name" : key}) %}{% endif %}
{% endif %}
{% endfor %}
{% set top_country = { "count" : 0, "name" : "unknown"} %}
{% set top_country = {"count": 0, "name": "unknown"} %}
{% for key, value in countries_count.items() %}
{% if value|int > top_country["count"]|int %}
{% if top_country.update({ "count" : value|string, "name" : key}) %}{% endif %}
{% endif %}
{% endfor %}
{% set top_method = { "count" : 0, "name" : "unknown"} %}
{% set top_method = {"count": 0, "name": "unknown"} %}
{% for key, value in methods_count.items() %}
{% if value|int > top_method["count"]|int %}
{% if top_method.update({ "count" : value|string, "name" : key}) %}{% endif %}
{% endif %}
{% endfor %}
{% set total_report = reports|length %}
<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"
@ -87,18 +76,11 @@
<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>
<div role="grid" class="card-detail-container">
{% for info in reports_info %}
<div role="row"
class="card-detail-item">
<p role="gridcell"
class="card-detail-item-title">
{{ info['name'] }}
</p>
<p role="gridcell"
class="card-detail-item-subtitle">
{{ info['data'] }}
</p>
</div>
{% for info in reports_info %}
<div role="row" class="card-detail-item">
<p role="gridcell" class="card-detail-item-title">{{ info['name'] }}</p>
<p role="gridcell" class="card-detail-item-subtitle">{{ info['data'] }}</p>
</div>
{% endfor %}
</div>
</div>

View file

@ -48,17 +48,10 @@
<h5 class="mb-2 font-bold dark:text-white/90">INFO</h5>
<div role="grid" class="card-detail-container">
{% for info in services_info %}
<div role="row"
class="card-detail-item">
<p role="gridcell"
class="card-detail-item-title">
{{ info['name'] }}
</p>
<p role="gridcell"
class="card-detail-item-subtitle">
{{ info['data'] }}
</p>
</div>
<div role="row" class="card-detail-item">
<p role="gridcell" class="card-detail-item-title">{{ info['name'] }}</p>
<p role="gridcell" class="card-detail-item-subtitle">{{ info['data'] }}</p>
</div>
{% endfor %}
</div>
</div>

View file

@ -46,59 +46,75 @@
<div class="flex flex-col md:flex-row justify-start w-full items-start md:items-end gap-y-3 gap-x-4">
<div class="w-full sm:min-w-[250px] max-w-[300px]">{% include "settings_tabs_select.html" %}</div>
<div class="flex flex-col sm:flex-row">
<!-- search inpt-->
<div class="sm:mx-2 mb-1 min-w-[200px] flex flex-col relative col-span-12 md:col-span-6">
<h5 class="hidden sm:block my-1 transition duration-300 ease-in-out text-sm sm:text-md font-bold m-0 dark:text-gray-200">
Search
</h5>
<label class="sr-only" for="settings-filter">search</label>
<input type="text"
id="settings-filter"
name="settings-filter"
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="keyword"
pattern="(.*?)"
required />
</div>
<!-- end search inpt-->
<!-- type plugin -->
<div class="hidden mx-2 mb-1 min-w-[200px] sm:flex flex-col relative col-span-12 md:col-span-6">
<h5 class="my-1 transition duration-300 ease-in-out text-sm sm:text-md font-bold m-0 dark:text-gray-200">
Type
</h5>
<button aria-controls="filter-type" data-services-setting-select="type" class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value" id="services-type" data-name="services-type" data-services-setting-select-text="type">all</span>
<!-- chevron -->
<svg data-services-setting-select="type" class="transition-transform h-4 w-4 fill-gray-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z"></path>
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-type" role="listbox" data-services-setting-select-dropdown="type" class="mt-1 hidden z-100 absolute flex-col w-full translate-y-16 max-h-[350px] overflow-hidden overflow-y-auto">
<button role="option" data-services-setting-select-dropdown-btn="type" value="all" class="dark:bg-primary bg-primary text-gray-300 border-t rounded-t border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
<!-- search inpt-->
<div class="sm:mx-2 mb-1 min-w-[200px] flex flex-col relative col-span-12 md:col-span-6">
<h5 class="hidden sm:block my-1 transition duration-300 ease-in-out text-sm sm:text-md font-bold m-0 dark:text-gray-200">
Search
</h5>
<label class="sr-only" for="settings-filter">search</label>
<input type="text"
id="settings-filter"
name="settings-filter"
class="col-span-12 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="keyword"
pattern="(.*?)"
required />
</div>
<!-- end search inpt-->
<!-- type plugin -->
<div class="hidden mx-2 mb-1 min-w-[200px] sm:flex flex-col relative col-span-12 md:col-span-6">
<h5 class="my-1 transition duration-300 ease-in-out text-sm sm:text-md font-bold m-0 dark:text-gray-200">Type</h5>
<button aria-controls="filter-type"
data-services-setting-select="type"
class="disabled:opacity-75 dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 duration-300 ease-in-out dark:opacity-90 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 focus:border-green-500 flex justify-between align-middle items-center text-left text-sm leading-5.6 ease w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-3 font-normal text-gray-700 transition-all placeholder:text-gray-500">
<span aria-description="current filter state value"
id="services-type"
data-name="services-type"
data-services-setting-select-text="type">all</span>
<!-- chevron -->
<svg data-services-setting-select="type"
class="transition-transform h-4 w-4 fill-gray-500"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z">
</path>
</svg>
</button>
<!-- end chevron -->
<!-- dropdown-->
<div id="filter-type"
role="listbox"
data-services-setting-select-dropdown="type"
class="mt-1 hidden z-100 absolute flex-col w-full translate-y-16 max-h-[350px] overflow-hidden overflow-y-auto">
<button role="option"
data-services-setting-select-dropdown-btn="type"
value="all"
class="dark:bg-primary bg-primary text-gray-300 border-t rounded-t border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
all
</button>
<button role="option" data-services-setting-select-dropdown-btn="type" value="core" class=" bg-white dark:bg-slate-700 border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
<button role="option"
data-services-setting-select-dropdown-btn="type"
value="core"
class=" bg-white dark:bg-slate-700 border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
core
</button>
<button role="option" data-services-setting-select-dropdown-btn="type" value="external" class=" bg-white dark:bg-slate-700 border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
<button role="option"
data-services-setting-select-dropdown-btn="type"
value="external"
class=" bg-white dark:bg-slate-700 border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
external
</button>
<button role="option" data-services-setting-select-dropdown-btn="type" value="pro" class=" bg-white dark:bg-slate-700 rounded-b border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
<button role="option"
data-services-setting-select-dropdown-btn="type"
value="pro"
class=" bg-white dark:bg-slate-700 rounded-b border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300">
pro
</button>
</div>
<!-- end dropdown-->
</div>
<!-- end dropdown-->
<!-- end type plugin-->
</div>
<!-- end type plugin-->
</div>
</div>
<div class="w-full min-w-[300px] my-1 sm:my-0">
<hr class="separator" />

View file

@ -22,7 +22,11 @@
role="listbox"
data-tab-select-dropdown
class="hidden z-100 absolute flex-col w-full overflow-hidden overflow-y-auto max-h-[350px]">
<input data-focus="true" data-combobox type="text" placeholder="Search plugin" class="cursor-text first border rounded-t border-gray-100 text-left focus:outline outline-none text-sm leading-5.6 ease block w-full appearance-none border-gray-300 dark:border-gray-200 bg-white dark:bg-gray-400 bg-clip-padding px-6 py-1.5 font-normal text-gray-800 transition-all placeholder:text-gray-500 dark:placeholder:text-gray-600">
<input data-focus="true"
data-combobox
type="text"
placeholder="Search plugin"
class="cursor-text first border rounded-t border-gray-100 text-left focus:outline outline-none text-sm leading-5.6 ease block w-full appearance-none border-gray-300 dark:border-gray-200 bg-white dark:bg-gray-400 bg-clip-padding px-6 py-1.5 font-normal text-gray-800 transition-all placeholder:text-gray-500 dark:placeholder:text-gray-600">
{% set first_el = "True" %}
{% for plugin in plugins %}
{% if current_endpoint == "services" and plugin["settings"]