mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Optimize and fix stuff in web UI
This commit is contained in:
parent
c021b24082
commit
4f9e0e1fea
14 changed files with 766 additions and 514 deletions
|
|
@ -1,8 +1,11 @@
|
|||
from flask import Blueprint, render_template
|
||||
from json import JSONDecodeError, loads
|
||||
from flask import Blueprint, flash, redirect, render_template, request, url_for
|
||||
from flask_login import login_required
|
||||
|
||||
from app.dependencies import DB
|
||||
|
||||
from app.routes.utils import handle_error, verify_data_in_form
|
||||
|
||||
jobs = Blueprint("jobs", __name__)
|
||||
|
||||
|
||||
|
|
@ -10,3 +13,34 @@ jobs = Blueprint("jobs", __name__)
|
|||
@login_required
|
||||
def jobs_page():
|
||||
return render_template("jobs.html", jobs=DB.get_jobs())
|
||||
|
||||
|
||||
@jobs.route("/jobs/run", methods=["POST"])
|
||||
@login_required
|
||||
def jobs_run():
|
||||
verify_data_in_form(
|
||||
data={"jobs": None},
|
||||
err_message="Missing jobs parameter on /jobs/run.",
|
||||
redirect_url="jobs",
|
||||
next=True,
|
||||
)
|
||||
jobs = request.form["jobs"]
|
||||
if not jobs:
|
||||
return handle_error("No jobs selected.", "jobs", True)
|
||||
try:
|
||||
jobs = loads(jobs)
|
||||
except JSONDecodeError:
|
||||
return handle_error("Invalid jobs parameter on /jobs/run.", "jobs", True)
|
||||
|
||||
ret = DB.checked_changes(["config"], [job.get("plugin") for job in jobs if job.get("plugin")], True)
|
||||
if ret:
|
||||
return handle_error(ret, "jobs", True)
|
||||
|
||||
flash(f"Job{'s' if len(jobs) > 1 else ''}'s plugins will be run in the background by the scheduler.", "success")
|
||||
return redirect(
|
||||
url_for(
|
||||
"loading",
|
||||
next=url_for("jobs.jobs_page"),
|
||||
message=f"Run selected job{'s' if len(jobs) > 1 else ''}'s plugins: {', '.join([job.get('plugin') + '/' + job.get('name') for job in jobs])}",
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ def logs_page():
|
|||
files.append(file.name)
|
||||
|
||||
current_file = secure_filename(request.args.get("file", ""))
|
||||
page = request.args.get("page")
|
||||
page = request.args.get("page", 0)
|
||||
|
||||
if current_file and current_file not in files:
|
||||
return Response("No such file", 404)
|
||||
|
|
@ -31,7 +31,11 @@ def logs_page():
|
|||
if isabs(current_file) or ".." in current_file:
|
||||
return error_message("Invalid file path", 400)
|
||||
|
||||
raw_logs = "Select a log file to view its contents"
|
||||
raw_logs = (
|
||||
"Select a log file to view its contents"
|
||||
if files
|
||||
else "There are no log files to display, check the documentation for more information on how to enable logging"
|
||||
)
|
||||
page_num = 1
|
||||
if current_file:
|
||||
with logs_path.joinpath(current_file).open(encoding="utf-8") as f:
|
||||
|
|
@ -41,4 +45,4 @@ def logs_page():
|
|||
page = page_num
|
||||
raw_logs = "\n".join(raw_logs[int(page) * 10000 - 10000 : int(page) * 10000]) # noqa: E203
|
||||
|
||||
return render_template("logs.html", logs=raw_logs, files=files, current_file=current_file, current_page=int(page), page_num=page_num)
|
||||
return render_template("logs.html", logs=raw_logs, files=files, current_file=current_file, current_page=int(page) or page_num, page_num=page_num)
|
||||
|
|
|
|||
|
|
@ -142,485 +142,3 @@
|
|||
text-align: center;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Custom
|
||||
******************************************************************************/
|
||||
|
||||
:root {
|
||||
--dt-row-selected: 29, 123, 167;
|
||||
}
|
||||
|
||||
.badge-dot {
|
||||
padding: 0.35rem;
|
||||
font-size: 0.6rem;
|
||||
animation: pulsate 1.7s infinite;
|
||||
}
|
||||
|
||||
.badge-dot-text {
|
||||
font-size: 0.6rem;
|
||||
animation: pulsate 1.7s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulsate {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.5);
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.w-30 {
|
||||
width: 30% !important;
|
||||
}
|
||||
|
||||
.badge-center-sm {
|
||||
padding: 2.5px;
|
||||
line-height: 1.2;
|
||||
height: 1.25rem;
|
||||
width: 1.25rem;
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.badge-center-sm i {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.bg-bw-green {
|
||||
background-color: var(--bs-bw-green);
|
||||
}
|
||||
|
||||
/* .pro-icon {
|
||||
position: relative;
|
||||
width: 18px;
|
||||
height: 15.5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pro-icon::before,
|
||||
.pro-icon::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
transition: opacity 1.5s ease-in-out;
|
||||
}
|
||||
|
||||
.pro-icon::before {
|
||||
background-image: url("../img/diamond.svg");
|
||||
opacity: 1;
|
||||
animation: fadeOut 1.5s infinite alternate;
|
||||
}
|
||||
|
||||
.pro-icon::after {
|
||||
background-image: url("../img/diamond-blue.svg");
|
||||
opacity: 0;
|
||||
animation: fadeIn 1.5s infinite alternate;
|
||||
} */
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.btn-responsive {
|
||||
padding: 4px 9px;
|
||||
font-size: 80%;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* .pro-icon {
|
||||
width: 9px;
|
||||
height: 7.75px;
|
||||
} */
|
||||
}
|
||||
|
||||
@media (min-width: 769px) and (max-width: 992px) {
|
||||
.btn-responsive {
|
||||
padding: 8px 18px;
|
||||
font-size: 90%;
|
||||
line-height: 1.2;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.min-vh-70 {
|
||||
min-height: 70vh !important;
|
||||
}
|
||||
|
||||
.max-vh-60 {
|
||||
max-height: 60vh !important;
|
||||
}
|
||||
|
||||
td.highlight {
|
||||
background-color: rgba(var(--bs-primary-rgb), 0.1) !important;
|
||||
}
|
||||
|
||||
.text-bw-green {
|
||||
color: var(--bs-bw-green) !important;
|
||||
}
|
||||
|
||||
.btn-bw-green {
|
||||
color: #fff;
|
||||
background-color: var(--bs-bw-green);
|
||||
border-color: var(--bs-bw-green);
|
||||
}
|
||||
|
||||
.btn-outline-bw-green {
|
||||
color: var(--bs-bw-green);
|
||||
border-color: var(--bs-bw-green);
|
||||
}
|
||||
|
||||
.btn-bw-green:hover,
|
||||
.btn-outline-bw-green:hover {
|
||||
color: #fff;
|
||||
background-color: var(--bs-bw-green);
|
||||
}
|
||||
|
||||
.btn-text-bw-green,
|
||||
.btn-text-bw-green:hover {
|
||||
color: var(--bs-bw-green) !important;
|
||||
}
|
||||
|
||||
.btn-text-secondary,
|
||||
.btn-text-secondary:hover {
|
||||
color: var(--bs-secondary) !important;
|
||||
}
|
||||
|
||||
.btn-text-danger,
|
||||
.btn-text-danger.disabled,
|
||||
.btn-text-danger:hover {
|
||||
color: var(--bs-danger) !important;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.col.form-floating > .form-control-sm,
|
||||
.col-auto.form-floating > .form-select.form-select-sm {
|
||||
height: calc(1.9em + 0.9rem + 1px);
|
||||
min-height: calc(1.9em + 0.9rem + 1px);
|
||||
font-size: 0.85rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.form-floating > .form-control:focus ~ label {
|
||||
transform: scale(0.8) translateY(-0.7rem) translateX(0.15rem);
|
||||
}
|
||||
|
||||
.col.form-floating > label,
|
||||
.col-auto.form-floating > label {
|
||||
padding: 0.8rem 0.9375rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.form-floating > .form-select:focus {
|
||||
padding-top: 1.2rem;
|
||||
}
|
||||
|
||||
.col-auto.form-floating > .form-select.form-select-sm,
|
||||
.col-auto.form-floating > .form-select.form-select-sm:focus {
|
||||
padding-top: calc(-2px + 1.2rem);
|
||||
}
|
||||
|
||||
.form-floating > .form-control.form-control-sm:focus {
|
||||
padding-top: 1.1rem !important;
|
||||
}
|
||||
|
||||
.shine {
|
||||
background-image: linear-gradient(
|
||||
120deg,
|
||||
rgba(46, 172, 104, 0) 0%,
|
||||
rgba(46, 172, 104, 0.8) 50%,
|
||||
rgba(46, 172, 104, 0) 100%
|
||||
);
|
||||
background-size: 40%;
|
||||
background-position: -100% center;
|
||||
background-repeat: no-repeat;
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
color: transparent;
|
||||
animation: shine 8s linear infinite;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
.shine-sm {
|
||||
animation: shineSm 5s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes shine {
|
||||
0% {
|
||||
background-position: -200% center;
|
||||
}
|
||||
100% {
|
||||
background-position: 200% center;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shineSm {
|
||||
0% {
|
||||
background-position: -200% center;
|
||||
}
|
||||
60% {
|
||||
background-position: 200% center;
|
||||
}
|
||||
100% {
|
||||
background-position: 200% center;
|
||||
}
|
||||
}
|
||||
|
||||
.text-primary.shine {
|
||||
color: rgba(var(--bs-primary-rgb), 0.1) !important;
|
||||
background-color: var(--bs-primary) !important;
|
||||
}
|
||||
|
||||
.form-floating > :disabled ~ label::after,
|
||||
.form-floating > .form-control:disabled ~ label::after {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.chevron-icon {
|
||||
padding-bottom: 0.125rem !important;
|
||||
}
|
||||
|
||||
.chevron-rotate {
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.chevron-rotate-back {
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.multiple-container:not(:first-child) {
|
||||
border-top: 1px solid var(--bs-primary);
|
||||
}
|
||||
|
||||
a.badge:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.setting-checkbox-label {
|
||||
font-size: calc(var(--bs-body-font-size) * 0.85);
|
||||
}
|
||||
|
||||
.sticky-card {
|
||||
position: sticky;
|
||||
background-color: rgba(255, 255, 255, 0.88) !important;
|
||||
backdrop-filter: saturate(200%) blur(6px);
|
||||
top: 85px;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#floating-modes-menu {
|
||||
bottom: 2.1rem !important;
|
||||
left: 1.5rem !important;
|
||||
z-index: 1080;
|
||||
}
|
||||
|
||||
.setting-highlight {
|
||||
background-color: rgba(var(--bs-bw-green-rgb), 0.5);
|
||||
transition:
|
||||
background-color 2s ease,
|
||||
opacity 2s ease;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.setting-highlight-fade {
|
||||
background-color: transparent;
|
||||
opacity: 1; /* You can set this to 0 if you want it to fade out */
|
||||
}
|
||||
|
||||
.template-steps-container {
|
||||
--bs-breadcrumb-divider: url("../img/bxs-chevron-right.svg");
|
||||
}
|
||||
|
||||
.template-steps-container .breadcrumb-item + .breadcrumb-item::before {
|
||||
padding: 0 1rem 0 1rem;
|
||||
}
|
||||
|
||||
.h-vh-40 {
|
||||
height: 40vh;
|
||||
}
|
||||
|
||||
/* Base styles for the ModSecurity mode */
|
||||
.ace-modsecurity .ace_editor {
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Comments */
|
||||
.ace-modsecurity .ace_comment {
|
||||
color: #6a9955; /* Green color for comments */
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Strings */
|
||||
.ace-modsecurity .ace_string {
|
||||
color: #ce9178; /* Orange color for strings */
|
||||
}
|
||||
|
||||
/* Keywords */
|
||||
.ace-modsecurity .ace_keyword {
|
||||
color: #569cd6; /* Blue color for keywords */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Constants (numbers, IP addresses) */
|
||||
.ace-modsecurity .ace_constant {
|
||||
color: #b5cea8; /* Light green color for constants */
|
||||
}
|
||||
|
||||
/* Variables */
|
||||
.ace-modsecurity .ace_variable {
|
||||
color: #9cdcfe; /* Light blue color for variables */
|
||||
}
|
||||
|
||||
/* Operators */
|
||||
.ace-modsecurity .ace_keyword.ace_operator {
|
||||
color: #c586c0; /* Purple color for operators */
|
||||
}
|
||||
|
||||
/* Functions (actions) */
|
||||
.ace-modsecurity .ace_support.ace_function {
|
||||
color: #dcdcaa; /* Yellow color for functions */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Invalid or illegal syntax */
|
||||
.ace-modsecurity .ace_invalid {
|
||||
color: #ffffff;
|
||||
background-color: #e51400; /* Red background for errors */
|
||||
}
|
||||
|
||||
/* Text */
|
||||
.ace-modsecurity .ace_text {
|
||||
color: #d4d4d4; /* Default text color */
|
||||
}
|
||||
|
||||
/* Specific token styles based on the highlight rules */
|
||||
|
||||
/* ModSecurity directives */
|
||||
.ace-modsecurity .ace_keyword\.headers\.modsecurity\.directive,
|
||||
.ace-modsecurity .ace_keyword\.headers\.modsecurity\.directive\.marker {
|
||||
color: #569cd6;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* ModSecurity variables */
|
||||
.ace-modsecurity .ace_variable\.parameter\.modsecurity,
|
||||
.ace-modsecurity .ace_keyword\.macro\.modsecurity {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
/* ModSecurity actions */
|
||||
.ace-modsecurity .ace_keyword\.operator\.modsecurity\.action,
|
||||
.ace-modsecurity .ace_keyword\.operator\.modsecurity\.action\.ctl,
|
||||
.ace-modsecurity .ace_keyword\.operator\.modsecurity\.action\.phase,
|
||||
.ace-modsecurity .ace_keyword\.operator\.modsecurity\.action\.severity {
|
||||
color: #c586c0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* ModSecurity action parameters */
|
||||
.ace-modsecurity .ace_string\.modsecurity\.action_parameter,
|
||||
.ace-modsecurity .ace_constant\.numeric\.modsecurity\.action\.phase_name,
|
||||
.ace-modsecurity .ace_constant\.numeric\.modsecurity\.action\.severity_name,
|
||||
.ace-modsecurity .ace_constant\.numeric\.modsecurity\.action\.ctl\.parameter,
|
||||
.ace-modsecurity .ace_constant\.numeric\.modsecurity\.action\.transform_name {
|
||||
color: #ce9178;
|
||||
}
|
||||
|
||||
/* Disruptive actions */
|
||||
.ace-modsecurity
|
||||
.ace_entity\.name\.function\.modsecurity\.action\.disruptive_pass {
|
||||
color: #d16969; /* Light red color for disruptive actions */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Regular expressions and strings */
|
||||
.ace-modsecurity .ace_string\.regexp\.modsecurity,
|
||||
.ace-modsecurity .ace_string\.unquoted\.modsecurity,
|
||||
.ace-modsecurity .ace_string\.quoted\.modsecurity {
|
||||
color: #ce9178;
|
||||
}
|
||||
|
||||
/* Operators */
|
||||
.ace-modsecurity .ace_keyword\.control\.modsecurity {
|
||||
color: #c586c0;
|
||||
}
|
||||
|
||||
/* IP addresses */
|
||||
.ace-modsecurity .ace_constant\.other\.modsecurity\.ip {
|
||||
color: #b5cea8;
|
||||
}
|
||||
|
||||
/* Numbers */
|
||||
.ace-modsecurity .ace_constant\.numeric\.modsecurity {
|
||||
color: #b5cea8;
|
||||
}
|
||||
|
||||
/* Invalid syntax */
|
||||
.ace-modsecurity .ace_invalid\.illegal\.modsecurity {
|
||||
color: #ffffff;
|
||||
background-color: #e51400;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Punctuation */
|
||||
.ace-modsecurity .ace_punctuation\.definition\.tag\.apacheconf,
|
||||
.ace-modsecurity .ace_punctuation\.colon\.modsecurity,
|
||||
.ace-modsecurity .ace_punctuation\.equals\.modsecurity {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
/* Apache configuration tags */
|
||||
.ace-modsecurity .ace_entity\.tag\.apacheconf {
|
||||
color: #569cd6;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Comments in Apache configuration */
|
||||
.ace-modsecurity .ace_punctuation\.definition\.comment\.apacheconf,
|
||||
.ace-modsecurity .ace_comment\.line\.hash\.ini {
|
||||
color: #6a9955;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
table.table.dataTable > tbody > tr.selected a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
table.table.dataTable > tbody > tr.selected .btn-outline-secondary {
|
||||
color: #fff !important;
|
||||
border-color: #fff !important;
|
||||
}
|
||||
|
||||
table.table.dataTable > tbody > tr.selected .btn-outline-secondary:hover {
|
||||
color: black !important;
|
||||
background-color: #fff !important;
|
||||
border-color: #fff !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
/*
|
||||
* Core overrides
|
||||
******************************************************************************/
|
||||
|
||||
@charset "UTF-8";
|
||||
:root,
|
||||
[data-bs-theme="light"] {
|
||||
|
|
@ -190,3 +194,489 @@ button.list-group-item-secondary.active {
|
|||
.navbar.bg-secondary .search-input-wrapper .search-toggler {
|
||||
background-color: var(--bs-secondary) !important;
|
||||
}
|
||||
|
||||
.toast-container {
|
||||
z-index: 1100;
|
||||
}
|
||||
|
||||
/*
|
||||
* Main overrides
|
||||
******************************************************************************/
|
||||
|
||||
:root {
|
||||
--dt-row-selected: 29, 123, 167;
|
||||
}
|
||||
|
||||
.badge-dot {
|
||||
padding: 0.35rem;
|
||||
font-size: 0.6rem;
|
||||
animation: pulsate 1.7s infinite;
|
||||
}
|
||||
|
||||
.badge-dot-text {
|
||||
font-size: 0.6rem;
|
||||
animation: pulsate 1.7s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulsate {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.5);
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.w-30 {
|
||||
width: 30% !important;
|
||||
}
|
||||
|
||||
.badge-center-sm {
|
||||
padding: 2.5px;
|
||||
line-height: 1.2;
|
||||
height: 1.25rem;
|
||||
width: 1.25rem;
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.badge-center-sm i {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.bg-bw-green {
|
||||
background-color: var(--bs-bw-green);
|
||||
}
|
||||
|
||||
/* .pro-icon {
|
||||
position: relative;
|
||||
width: 18px;
|
||||
height: 15.5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pro-icon::before,
|
||||
.pro-icon::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
transition: opacity 1.5s ease-in-out;
|
||||
}
|
||||
|
||||
.pro-icon::before {
|
||||
background-image: url("../img/diamond.svg");
|
||||
opacity: 1;
|
||||
animation: fadeOut 1.5s infinite alternate;
|
||||
}
|
||||
|
||||
.pro-icon::after {
|
||||
background-image: url("../img/diamond-blue.svg");
|
||||
opacity: 0;
|
||||
animation: fadeIn 1.5s infinite alternate;
|
||||
} */
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.btn-responsive {
|
||||
padding: 4px 9px;
|
||||
font-size: 80%;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* .pro-icon {
|
||||
width: 9px;
|
||||
height: 7.75px;
|
||||
} */
|
||||
}
|
||||
|
||||
@media (min-width: 769px) and (max-width: 992px) {
|
||||
.btn-responsive {
|
||||
padding: 8px 18px;
|
||||
font-size: 90%;
|
||||
line-height: 1.2;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.min-vh-70 {
|
||||
min-height: 70vh !important;
|
||||
}
|
||||
|
||||
.max-vh-60 {
|
||||
max-height: 60vh !important;
|
||||
}
|
||||
|
||||
td.highlight {
|
||||
background-color: rgba(var(--bs-primary-rgb), 0.1) !important;
|
||||
}
|
||||
|
||||
.text-bw-green {
|
||||
color: var(--bs-bw-green) !important;
|
||||
}
|
||||
|
||||
.btn-bw-green {
|
||||
color: #fff;
|
||||
background-color: var(--bs-bw-green);
|
||||
border-color: var(--bs-bw-green);
|
||||
}
|
||||
|
||||
.btn-outline-bw-green {
|
||||
color: var(--bs-bw-green);
|
||||
border-color: var(--bs-bw-green);
|
||||
}
|
||||
|
||||
.btn-bw-green:hover,
|
||||
.btn-outline-bw-green:hover {
|
||||
color: #fff;
|
||||
background-color: var(--bs-bw-green);
|
||||
}
|
||||
|
||||
.btn-text-bw-green,
|
||||
.btn-text-bw-green:hover {
|
||||
color: var(--bs-bw-green) !important;
|
||||
}
|
||||
|
||||
.btn-text-secondary,
|
||||
.btn-text-secondary:hover {
|
||||
color: var(--bs-secondary) !important;
|
||||
}
|
||||
|
||||
.btn-text-danger,
|
||||
.btn-text-danger.disabled,
|
||||
.btn-text-danger:hover {
|
||||
color: var(--bs-danger) !important;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.col.form-floating > .form-control-sm,
|
||||
.col-auto.form-floating > .form-select.form-select-sm {
|
||||
height: calc(1.9em + 0.9rem + 1px);
|
||||
min-height: calc(1.9em + 0.9rem + 1px);
|
||||
font-size: 0.85rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.form-floating > .form-control:focus ~ label {
|
||||
transform: scale(0.8) translateY(-0.7rem) translateX(0.15rem);
|
||||
}
|
||||
|
||||
.col.form-floating > label,
|
||||
.col-auto.form-floating > label {
|
||||
padding: 0.8rem 0.9375rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.form-floating > .form-select:focus {
|
||||
padding-top: 1.2rem;
|
||||
}
|
||||
|
||||
.col-auto.form-floating > .form-select.form-select-sm,
|
||||
.col-auto.form-floating > .form-select.form-select-sm:focus {
|
||||
padding-top: calc(-2px + 1.2rem);
|
||||
}
|
||||
|
||||
.form-floating > .form-control.form-control-sm:focus {
|
||||
padding-top: 1.1rem !important;
|
||||
}
|
||||
|
||||
.shine {
|
||||
background-image: linear-gradient(
|
||||
120deg,
|
||||
rgba(46, 172, 104, 0) 0%,
|
||||
rgba(46, 172, 104, 0.8) 50%,
|
||||
rgba(46, 172, 104, 0) 100%
|
||||
);
|
||||
background-size: 40%;
|
||||
background-position: -100% center;
|
||||
background-repeat: no-repeat;
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
color: transparent;
|
||||
animation: shine 8s linear infinite;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
.shine-sm {
|
||||
animation: shineSm 5s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes shine {
|
||||
0% {
|
||||
background-position: -200% center;
|
||||
}
|
||||
100% {
|
||||
background-position: 200% center;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shineSm {
|
||||
0% {
|
||||
background-position: -200% center;
|
||||
}
|
||||
60% {
|
||||
background-position: 200% center;
|
||||
}
|
||||
100% {
|
||||
background-position: 200% center;
|
||||
}
|
||||
}
|
||||
|
||||
.text-primary.shine {
|
||||
color: rgba(var(--bs-primary-rgb), 0.1) !important;
|
||||
background-color: var(--bs-primary) !important;
|
||||
}
|
||||
|
||||
.form-floating > :disabled ~ label::after,
|
||||
.form-floating > .form-control:disabled ~ label::after {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.chevron-icon {
|
||||
padding-bottom: 0.125rem !important;
|
||||
}
|
||||
|
||||
.chevron-rotate {
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.chevron-rotate-back {
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.multiple-container:not(:first-child) {
|
||||
border-top: 1px solid var(--bs-primary);
|
||||
}
|
||||
|
||||
a.badge:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.setting-checkbox-label {
|
||||
font-size: calc(var(--bs-body-font-size) * 0.85);
|
||||
}
|
||||
|
||||
.sticky-card {
|
||||
position: sticky;
|
||||
background-color: rgba(255, 255, 255, 0.88) !important;
|
||||
backdrop-filter: saturate(200%) blur(6px);
|
||||
top: 85px;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#floating-modes-menu {
|
||||
bottom: 2.1rem !important;
|
||||
left: 1.5rem !important;
|
||||
z-index: 1080;
|
||||
}
|
||||
|
||||
.setting-highlight {
|
||||
background-color: rgba(var(--bs-bw-green-rgb), 0.5);
|
||||
transition:
|
||||
background-color 2s ease,
|
||||
opacity 2s ease;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.setting-highlight-fade {
|
||||
background-color: transparent;
|
||||
opacity: 1; /* You can set this to 0 if you want it to fade out */
|
||||
}
|
||||
|
||||
.template-steps-container {
|
||||
--bs-breadcrumb-divider: url("../img/bxs-chevron-right.svg");
|
||||
}
|
||||
|
||||
.template-steps-container .breadcrumb-item + .breadcrumb-item::before {
|
||||
padding: 0 1rem 0 1rem;
|
||||
}
|
||||
|
||||
.h-vh-40 {
|
||||
height: 40vh;
|
||||
}
|
||||
|
||||
/* Base styles for the ModSecurity mode */
|
||||
.ace-modsecurity .ace_editor {
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Comments */
|
||||
.ace-modsecurity .ace_comment {
|
||||
color: #6a9955; /* Green color for comments */
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Strings */
|
||||
.ace-modsecurity .ace_string {
|
||||
color: #ce9178; /* Orange color for strings */
|
||||
}
|
||||
|
||||
/* Keywords */
|
||||
.ace-modsecurity .ace_keyword {
|
||||
color: #569cd6; /* Blue color for keywords */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Constants (numbers, IP addresses) */
|
||||
.ace-modsecurity .ace_constant {
|
||||
color: #b5cea8; /* Light green color for constants */
|
||||
}
|
||||
|
||||
/* Variables */
|
||||
.ace-modsecurity .ace_variable {
|
||||
color: #9cdcfe; /* Light blue color for variables */
|
||||
}
|
||||
|
||||
/* Operators */
|
||||
.ace-modsecurity .ace_keyword.ace_operator {
|
||||
color: #c586c0; /* Purple color for operators */
|
||||
}
|
||||
|
||||
/* Functions (actions) */
|
||||
.ace-modsecurity .ace_support.ace_function {
|
||||
color: #dcdcaa; /* Yellow color for functions */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Invalid or illegal syntax */
|
||||
.ace-modsecurity .ace_invalid {
|
||||
color: #ffffff;
|
||||
background-color: #e51400; /* Red background for errors */
|
||||
}
|
||||
|
||||
/* Text */
|
||||
.ace-modsecurity .ace_text {
|
||||
color: #d4d4d4; /* Default text color */
|
||||
}
|
||||
|
||||
/* Specific token styles based on the highlight rules */
|
||||
|
||||
/* ModSecurity directives */
|
||||
.ace-modsecurity .ace_keyword\.headers\.modsecurity\.directive,
|
||||
.ace-modsecurity .ace_keyword\.headers\.modsecurity\.directive\.marker {
|
||||
color: #569cd6;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* ModSecurity variables */
|
||||
.ace-modsecurity .ace_variable\.parameter\.modsecurity,
|
||||
.ace-modsecurity .ace_keyword\.macro\.modsecurity {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
/* ModSecurity actions */
|
||||
.ace-modsecurity .ace_keyword\.operator\.modsecurity\.action,
|
||||
.ace-modsecurity .ace_keyword\.operator\.modsecurity\.action\.ctl,
|
||||
.ace-modsecurity .ace_keyword\.operator\.modsecurity\.action\.phase,
|
||||
.ace-modsecurity .ace_keyword\.operator\.modsecurity\.action\.severity {
|
||||
color: #c586c0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* ModSecurity action parameters */
|
||||
.ace-modsecurity .ace_string\.modsecurity\.action_parameter,
|
||||
.ace-modsecurity .ace_constant\.numeric\.modsecurity\.action\.phase_name,
|
||||
.ace-modsecurity .ace_constant\.numeric\.modsecurity\.action\.severity_name,
|
||||
.ace-modsecurity .ace_constant\.numeric\.modsecurity\.action\.ctl\.parameter,
|
||||
.ace-modsecurity .ace_constant\.numeric\.modsecurity\.action\.transform_name {
|
||||
color: #ce9178;
|
||||
}
|
||||
|
||||
/* Disruptive actions */
|
||||
.ace-modsecurity
|
||||
.ace_entity\.name\.function\.modsecurity\.action\.disruptive_pass {
|
||||
color: #d16969; /* Light red color for disruptive actions */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Regular expressions and strings */
|
||||
.ace-modsecurity .ace_string\.regexp\.modsecurity,
|
||||
.ace-modsecurity .ace_string\.unquoted\.modsecurity,
|
||||
.ace-modsecurity .ace_string\.quoted\.modsecurity {
|
||||
color: #ce9178;
|
||||
}
|
||||
|
||||
/* Operators */
|
||||
.ace-modsecurity .ace_keyword\.control\.modsecurity {
|
||||
color: #c586c0;
|
||||
}
|
||||
|
||||
/* IP addresses */
|
||||
.ace-modsecurity .ace_constant\.other\.modsecurity\.ip {
|
||||
color: #b5cea8;
|
||||
}
|
||||
|
||||
/* Numbers */
|
||||
.ace-modsecurity .ace_constant\.numeric\.modsecurity {
|
||||
color: #b5cea8;
|
||||
}
|
||||
|
||||
/* Invalid syntax */
|
||||
.ace-modsecurity .ace_invalid\.illegal\.modsecurity {
|
||||
color: #ffffff;
|
||||
background-color: #e51400;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Punctuation */
|
||||
.ace-modsecurity .ace_punctuation\.definition\.tag\.apacheconf,
|
||||
.ace-modsecurity .ace_punctuation\.colon\.modsecurity,
|
||||
.ace-modsecurity .ace_punctuation\.equals\.modsecurity {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
/* Apache configuration tags */
|
||||
.ace-modsecurity .ace_entity\.tag\.apacheconf {
|
||||
color: #569cd6;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Comments in Apache configuration */
|
||||
.ace-modsecurity .ace_punctuation\.definition\.comment\.apacheconf,
|
||||
.ace-modsecurity .ace_comment\.line\.hash\.ini {
|
||||
color: #6a9955;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
table.table.dataTable > tbody > tr.selected a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
table.table.dataTable > tbody > tr.selected .btn-outline-secondary {
|
||||
color: #fff !important;
|
||||
border-color: #fff !important;
|
||||
}
|
||||
|
||||
table.table.dataTable > tbody > tr.selected .btn-outline-secondary:hover {
|
||||
color: black !important;
|
||||
background-color: #fff !important;
|
||||
border-color: #fff !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,8 +151,19 @@ $(document).ready(function () {
|
|||
};
|
||||
|
||||
if (banNumber > 10) {
|
||||
const menu = [10];
|
||||
if (banNumber > 25) {
|
||||
menu.push(25);
|
||||
}
|
||||
if (banNumber > 50) {
|
||||
menu.push(50);
|
||||
}
|
||||
if (banNumber > 100) {
|
||||
menu.push(100);
|
||||
}
|
||||
menu.push({ label: "All", value: -1 });
|
||||
layout.topStart.pageLength = {
|
||||
menu: [10, 25, 50, 100, { label: "All", value: -1 }],
|
||||
menu: menu,
|
||||
};
|
||||
layout.bottomEnd.paging = true;
|
||||
}
|
||||
|
|
@ -534,14 +545,13 @@ $(document).ready(function () {
|
|||
});
|
||||
});
|
||||
|
||||
console.log(bans);
|
||||
const form = $("<form>", {
|
||||
method: "POST",
|
||||
action: `${window.location.pathname}/ban`,
|
||||
class: "visually-hidden",
|
||||
});
|
||||
|
||||
// Add CSRF token and instances as hidden inputs
|
||||
// Add CSRF token and bans as hidden inputs
|
||||
form.append(
|
||||
$("<input>", {
|
||||
type: "hidden",
|
||||
|
|
|
|||
|
|
@ -7,8 +7,19 @@ $(document).ready(function () {
|
|||
};
|
||||
|
||||
if (cacheNumber > 10) {
|
||||
const menu = [10];
|
||||
if (cacheNumber > 25) {
|
||||
menu.push(25);
|
||||
}
|
||||
if (cacheNumber > 50) {
|
||||
menu.push(50);
|
||||
}
|
||||
if (cacheNumber > 100) {
|
||||
menu.push(100);
|
||||
}
|
||||
menu.push({ label: "All", value: -1 });
|
||||
layout.topStart.pageLength = {
|
||||
menu: [10, 25, 50, 100, { label: "All", value: -1 }],
|
||||
menu: menu,
|
||||
};
|
||||
layout.bottomEnd.paging = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -174,12 +174,6 @@ $(document).ready(function () {
|
|||
return;
|
||||
}
|
||||
|
||||
console.log("Saving configuration...");
|
||||
console.log("Service:", selectedService);
|
||||
console.log("Type:", selectedType);
|
||||
console.log("Name:", configName);
|
||||
console.log("Value:", value);
|
||||
|
||||
const form = $("<form>", {
|
||||
method: "POST",
|
||||
action: window.location.href,
|
||||
|
|
|
|||
|
|
@ -84,8 +84,19 @@ $(document).ready(function () {
|
|||
};
|
||||
|
||||
if (configNumber > 10) {
|
||||
const menu = [10];
|
||||
if (configNumber > 25) {
|
||||
menu.push(25);
|
||||
}
|
||||
if (configNumber > 50) {
|
||||
menu.push(50);
|
||||
}
|
||||
if (configNumber > 100) {
|
||||
menu.push(100);
|
||||
}
|
||||
menu.push({ label: "All", value: -1 });
|
||||
layout.topStart.pageLength = {
|
||||
menu: [10, 25, 50, 100, { label: "All", value: -1 }],
|
||||
menu: menu,
|
||||
};
|
||||
layout.bottomEnd.paging = true;
|
||||
}
|
||||
|
|
@ -312,7 +323,6 @@ $(document).ready(function () {
|
|||
type: $(this).data("config-type"),
|
||||
service: $(this).data("config-service"),
|
||||
};
|
||||
console.log(config);
|
||||
setupDeletionModal([config]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -95,8 +95,19 @@ $(document).ready(function () {
|
|||
};
|
||||
|
||||
if (instanceNumber > 10) {
|
||||
const menu = [10];
|
||||
if (instanceNumber > 25) {
|
||||
menu.push(25);
|
||||
}
|
||||
if (instanceNumber > 50) {
|
||||
menu.push(50);
|
||||
}
|
||||
if (instanceNumber > 100) {
|
||||
menu.push(100);
|
||||
}
|
||||
menu.push({ label: "All", value: -1 });
|
||||
layout.topStart.pageLength = {
|
||||
menu: [10, 25, 50, 100, { label: "All", value: -1 }],
|
||||
menu: menu,
|
||||
};
|
||||
layout.bottomEnd.paging = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
$(document).ready(function () {
|
||||
let actionLock = false;
|
||||
const jobNumber = parseInt($("#job_number").val());
|
||||
|
||||
const layout = {
|
||||
|
|
@ -7,8 +8,19 @@ $(document).ready(function () {
|
|||
};
|
||||
|
||||
if (jobNumber > 10) {
|
||||
const menu = [10];
|
||||
if (jobNumber > 25) {
|
||||
menu.push(25);
|
||||
}
|
||||
if (jobNumber > 50) {
|
||||
menu.push(50);
|
||||
}
|
||||
if (jobNumber > 100) {
|
||||
menu.push(100);
|
||||
}
|
||||
menu.push({ label: "All", value: -1 });
|
||||
layout.topStart.pageLength = {
|
||||
menu: [10, 25, 50, 100, { label: "All", value: -1 }],
|
||||
menu: menu,
|
||||
};
|
||||
layout.bottomEnd.paging = true;
|
||||
}
|
||||
|
|
@ -65,8 +77,77 @@ $(document).ready(function () {
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
extend: "collection",
|
||||
text: '<span class="tf-icons bx bx-play bx-18px me-2"></span>Actions',
|
||||
className: "btn btn-sm btn-outline-primary",
|
||||
buttons: [
|
||||
{
|
||||
extend: "run_jobs",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const getSelectedJobs = () => {
|
||||
const jobs = [];
|
||||
$("tr.selected").each(function () {
|
||||
const $this = $(this);
|
||||
const name = $this.find("td:eq(1)").text().trim();
|
||||
const plugin = $this.find("td:eq(2)").text().trim();
|
||||
jobs.push({ name: name, plugin: plugin });
|
||||
});
|
||||
return jobs;
|
||||
};
|
||||
|
||||
const executeForm = (jobs) => {
|
||||
const form = $("<form>", {
|
||||
method: "POST",
|
||||
action: `${window.location.pathname}/run`,
|
||||
class: "visually-hidden",
|
||||
});
|
||||
|
||||
// Add CSRF token and jobs as hidden inputs
|
||||
form.append(
|
||||
$("<input>", {
|
||||
type: "hidden",
|
||||
name: "csrf_token",
|
||||
value: $("#csrf_token").val(),
|
||||
}),
|
||||
);
|
||||
form.append(
|
||||
$("<input>", {
|
||||
type: "hidden",
|
||||
name: "jobs",
|
||||
value: JSON.stringify(jobs),
|
||||
}),
|
||||
);
|
||||
|
||||
// Append the form to the body and submit it
|
||||
form.appendTo("body").submit();
|
||||
};
|
||||
|
||||
$.fn.dataTable.ext.buttons.run_jobs = {
|
||||
text: '<span class="tf-icons bx bx-play bx-18px me-2"></span>Run selected jobs',
|
||||
action: function (e, dt, node, config) {
|
||||
if (actionLock) {
|
||||
return;
|
||||
}
|
||||
actionLock = true;
|
||||
$(".dt-button-background").click();
|
||||
|
||||
const jobs = getSelectedJobs();
|
||||
if (jobs.length === 0) {
|
||||
actionLock = false;
|
||||
return;
|
||||
}
|
||||
|
||||
executeForm(jobs);
|
||||
|
||||
actionLock = false;
|
||||
},
|
||||
};
|
||||
|
||||
$(".history-start-date, .history-end-date").each(function () {
|
||||
const isoDateStr = $(this).text().trim();
|
||||
|
||||
|
|
@ -89,6 +170,11 @@ $(document).ready(function () {
|
|||
|
||||
const jobs_table = new DataTable("#jobs", {
|
||||
columnDefs: [
|
||||
{
|
||||
orderable: false,
|
||||
render: DataTable.render.select(),
|
||||
targets: 0,
|
||||
},
|
||||
{
|
||||
orderable: false,
|
||||
targets: -1,
|
||||
|
|
@ -103,6 +189,11 @@ $(document).ready(function () {
|
|||
order: [[1, "asc"]],
|
||||
autoFill: false,
|
||||
responsive: true,
|
||||
select: {
|
||||
style: "multi+shift",
|
||||
selector: "td:first-child",
|
||||
headerCheckbox: false,
|
||||
},
|
||||
layout: layout,
|
||||
language: {
|
||||
info: "Showing _START_ to _END_ of _TOTAL_ jobs",
|
||||
|
|
@ -110,6 +201,13 @@ $(document).ready(function () {
|
|||
infoFiltered: "(filtered from _MAX_ total jobs)",
|
||||
lengthMenu: "Display _MENU_ jobs",
|
||||
zeroRecords: "No matching jobs found",
|
||||
select: {
|
||||
rows: {
|
||||
_: "Selected %d jobs",
|
||||
0: "No jobs selected",
|
||||
1: "Selected 1 job",
|
||||
},
|
||||
},
|
||||
},
|
||||
initComplete: function (settings, json) {
|
||||
$("#jobs_wrapper .btn-secondary").removeClass("btn-secondary");
|
||||
|
|
@ -142,17 +240,45 @@ $(document).ready(function () {
|
|||
.each((el) => el.classList.remove("highlight"));
|
||||
});
|
||||
|
||||
// Event listener for the select-all checkbox
|
||||
$("#select-all-rows").on("change", function () {
|
||||
const isChecked = $(this).prop("checked");
|
||||
|
||||
if (isChecked) {
|
||||
// Select all rows on the current page
|
||||
jobs_table.rows({ page: "current" }).select();
|
||||
} else {
|
||||
// Deselect all rows on the current page
|
||||
jobs_table.rows({ page: "current" }).deselect();
|
||||
}
|
||||
});
|
||||
|
||||
$(".show-history").on("click", function () {
|
||||
const historyModal = $("#modal-job-history");
|
||||
const job = $(this).data("job");
|
||||
const plugin = $(this).data("plugin");
|
||||
|
||||
historyModal.find(".modal-title").text(`Job ${job} History`);
|
||||
const history = $(`#job-${job}-${plugin}-history`).clone();
|
||||
const historyCount = history.find("ul").length - 1;
|
||||
historyModal
|
||||
.find(".modal-title")
|
||||
.html(
|
||||
`Last${historyCount > 1 ? " " + historyCount : ""} execution${
|
||||
historyCount > 1 ? "s" : ""
|
||||
} of Job <span class="fw-bold fst-italic">${job}</span> from plugin <span class="fw-bold fst-italic">${plugin}</span>`,
|
||||
);
|
||||
history.removeClass("visually-hidden");
|
||||
historyModal.find(".modal-body").html(history);
|
||||
|
||||
const modal = new bootstrap.Modal(historyModal);
|
||||
modal.show();
|
||||
});
|
||||
|
||||
$(".run-job").on("click", function () {
|
||||
const job = {
|
||||
name: $(this).data("job"),
|
||||
plugin: $(this).data("plugin"),
|
||||
};
|
||||
executeForm([job]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,8 +7,19 @@ $(document).ready(function () {
|
|||
};
|
||||
|
||||
if (reportsNumber > 10) {
|
||||
const menu = [10];
|
||||
if (reportsNumber > 25) {
|
||||
menu.push(25);
|
||||
}
|
||||
if (reportsNumber > 50) {
|
||||
menu.push(50);
|
||||
}
|
||||
if (reportsNumber > 100) {
|
||||
menu.push(100);
|
||||
}
|
||||
menu.push({ label: "All", value: -1 });
|
||||
layout.topStart.pageLength = {
|
||||
menu: [10, 25, 50, 100, { label: "All", value: -1 }],
|
||||
menu: menu,
|
||||
};
|
||||
layout.bottomEnd.paging = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,8 +89,19 @@ $(document).ready(function () {
|
|||
};
|
||||
|
||||
if (serviceNumber > 10) {
|
||||
const menu = [10];
|
||||
if (serviceNumber > 25) {
|
||||
menu.push(25);
|
||||
}
|
||||
if (serviceNumber > 50) {
|
||||
menu.push(50);
|
||||
}
|
||||
if (serviceNumber > 100) {
|
||||
menu.push(100);
|
||||
}
|
||||
menu.push({ label: "All", value: -1 });
|
||||
layout.topStart.pageLength = {
|
||||
menu: [10, 25, 50, 100, { label: "All", value: -1 }],
|
||||
menu: menu,
|
||||
};
|
||||
layout.bottomEnd.paging = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,15 +44,15 @@
|
|||
<link rel="stylesheet"
|
||||
href="{{ url_for('static', filename='css/core.css') }}"
|
||||
nonce="{{ style_nonce }}" />
|
||||
<link rel="stylesheet"
|
||||
href="{{ url_for('static', filename='css/overrides.css') }}"
|
||||
nonce="{{ style_nonce }}" />
|
||||
<link rel="stylesheet"
|
||||
href="{{ url_for('static', filename='css/theme-default.css') }}"
|
||||
nonce="{{ style_nonce }}" />
|
||||
<link rel="stylesheet"
|
||||
href="{{ url_for('static', filename='css/main.css') }}"
|
||||
nonce="{{ style_nonce }}" />
|
||||
<link rel="stylesheet"
|
||||
href="{{ url_for('static', filename='css/overrides.css') }}"
|
||||
nonce="{{ style_nonce }}" />
|
||||
<!-- Vendors CSS -->
|
||||
<link rel="stylesheet"
|
||||
href="{{ url_for('static', filename='libs/perfect-scrollbar/perfect-scrollbar.css') }}"
|
||||
|
|
|
|||
|
|
@ -3,9 +3,20 @@
|
|||
<!-- Content -->
|
||||
<div class="card table-responsive text-nowrap p-4 min-vh-70">
|
||||
<input type="hidden" id="job_number" value="{{ jobs|length }}" />
|
||||
<table id="jobs" class="table position-relative w-100">
|
||||
<input type="hidden"
|
||||
id="csrf_token"
|
||||
name="csrf_token"
|
||||
value="{{ csrf_token() }}" />
|
||||
<table id="jobs" class="table w-100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<input id="select-all-rows"
|
||||
aria-label="Select all rows"
|
||||
class="dt-select-checkbox mb-1"
|
||||
type="checkbox">
|
||||
Select All
|
||||
</th>
|
||||
<th data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom"
|
||||
data-bs-original-title="The Job's name">Name</th>
|
||||
|
|
@ -23,12 +34,13 @@
|
|||
data-bs-original-title="Does the last Job's execution was successful?">Last run</th>
|
||||
<th data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom"
|
||||
data-bs-original-title="The Job's information">Information</th>
|
||||
data-bs-original-title="The actions that can be performed on the Job">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for job, job_data in jobs.items() %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>{{ job }}</td>
|
||||
<td>{{ job_data["plugin_id"] }}</td>
|
||||
<td>
|
||||
|
|
@ -46,6 +58,16 @@
|
|||
</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom"
|
||||
data-bs-original-title="Run the Job">
|
||||
<button type="button"
|
||||
data-job="{{ job }}"
|
||||
data-plugin="{{ job_data['plugin_id'] }}"
|
||||
class="btn btn-primary btn-sm me-1 run-job">
|
||||
<i class="bx bx-play bx-xs"></i> Run
|
||||
</button>
|
||||
</div>
|
||||
{% if job_data['history'] %}
|
||||
<div id="job-{{ job }}-{{ job_data['plugin_id'] }}-history"
|
||||
class="visually-hidden mb-3">
|
||||
|
|
@ -118,9 +140,6 @@
|
|||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<span class="position-absolute bottom-0 start-50 translate-middle badge rounded-pill bg-secondary">
|
||||
TZ: <script nonce="{{ script_nonce }}">document.write(Intl.DateTimeFormat().resolvedOptions().timeZone);</script>
|
||||
</span>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal modal-lg fade"
|
||||
|
|
@ -130,15 +149,18 @@
|
|||
aria-hidden="true"
|
||||
role="dialog">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-content position-relative">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Job History</h5>
|
||||
<h5 class="modal-title">Last 10 Job's executions</h5>
|
||||
<button type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body"></div>
|
||||
<div class="modal-body mb-2"></div>
|
||||
<span class="position-absolute bottom-0 start-50 translate-middle badge rounded-pill bg-secondary">
|
||||
TZ: <script nonce="{{ script_nonce }}">document.write(Intl.DateTimeFormat().resolvedOptions().timeZone);</script>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue