mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
update block request page
*fix dropdown active value style issue *add top reason + top status code *add ip on table *add reason filter
This commit is contained in:
parent
e21aec6d72
commit
7707aab9a8
6 changed files with 223 additions and 4186 deletions
|
|
@ -1599,10 +1599,41 @@ def logs_container(container_id):
|
|||
@login_required
|
||||
def block_requests():
|
||||
# TODO : Get block requests from database to send it
|
||||
# Dummy value : [{"url": "/test", "date": "12/51/9851", "reason": "antibot", "method": "GET", "status": 403, "data": "{fesfmk fesfsf sfesfes}"}]
|
||||
requests = [
|
||||
{"ip": "124.0.0.1", "url": "/test", "date": "12/51/9851", "reason": "antibot", "method": "GET", "status": 403, "data": "{fesfmk fesfsf sfesfes}"},
|
||||
{"ip": "124.0.0.2", "url": "/test", "date": "12/51/9851", "reason": "test", "method": "GET", "status": 403, "data": "{fesfmk fesfsf sfesfes}"},
|
||||
{"ip": "124.0.0.3", "url": "/test", "date": "12/51/9851", "reason": "antibot", "method": "GET", "status": 403, "data": "{fesfmk fesfsf sfesfes}"},
|
||||
]
|
||||
|
||||
# Get top reasons
|
||||
reasons = {}
|
||||
for request in requests:
|
||||
if not request["reason"] in reasons:
|
||||
reasons[request["reason"]] = 0
|
||||
reasons[request["reason"]] = reasons[request["reason"]] + 1
|
||||
|
||||
top_reason = [k for k, v in reasons.items() if v == max(reasons.values())][0]
|
||||
|
||||
# Get top status code
|
||||
codes = {}
|
||||
for request in requests:
|
||||
if not request["status"] in codes:
|
||||
codes[request["status"]] = 0
|
||||
codes[request["status"]] = codes[request["status"]] + 1
|
||||
|
||||
top_code = [k for k, v in codes.items() if v == max(codes.values())][0]
|
||||
|
||||
# Get top reason and status
|
||||
|
||||
return render_template(
|
||||
"block_requests.html",
|
||||
block_requests=[],
|
||||
block_requests=[
|
||||
{"ip": "124.0.0.1", "url": "/test", "date": "12/51/9851", "reason": "antibot", "method": "GET", "status": "403", "data": "{fesfmk fesfsf sfesfes}"},
|
||||
{"ip": "124.0.0.2", "url": "/test", "date": "12/51/9851", "reason": "test", "method": "GET", "status": "403", "data": "{fesfmk fesfsf sfesfes}"},
|
||||
{"ip": "124.0.0.3", "url": "/test", "date": "12/51/9851", "reason": "antibot", "method": "GET", "status": "403", "data": "{fesfmk fesfsf sfesfes}"},
|
||||
],
|
||||
top_code=top_code,
|
||||
top_reason=top_reason,
|
||||
username=current_user.get_id(),
|
||||
dark_mode=app.config["DARK_MODE"],
|
||||
)
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -37,7 +37,7 @@ class Dropdown {
|
|||
const btn = e.target.closest("button");
|
||||
const btnValue = btn.getAttribute("value");
|
||||
const btnSetting = btn.getAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`,
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`
|
||||
);
|
||||
//stop if same value to avoid new fetching
|
||||
const isSameVal = this.isSameValue(btnSetting, btnValue);
|
||||
|
|
@ -47,7 +47,9 @@ class Dropdown {
|
|||
//close dropdown and change style
|
||||
this.hideDropdown(btnSetting);
|
||||
|
||||
if (!e.target.closest("button").hasAttribute(`data-${prefix}-file`)) {
|
||||
if (
|
||||
!e.target.closest("button").hasAttribute(`data-${this.prefix}-file`)
|
||||
) {
|
||||
this.changeDropBtnStyle(btnSetting, btn);
|
||||
}
|
||||
//show / hide filter
|
||||
|
|
@ -61,7 +63,7 @@ class Dropdown {
|
|||
|
||||
closeAllDrop() {
|
||||
const drops = document.querySelectorAll(
|
||||
`[data-${this.prefix}-setting-select-dropdown]`,
|
||||
`[data-${this.prefix}-setting-select-dropdown]`
|
||||
);
|
||||
drops.forEach((drop) => {
|
||||
drop.classList.add("hidden");
|
||||
|
|
@ -69,8 +71,8 @@ class Dropdown {
|
|||
document
|
||||
.querySelector(
|
||||
`svg[data-${this.prefix}-setting-select="${drop.getAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown`,
|
||||
)}"]`,
|
||||
`data-${this.prefix}-setting-select-dropdown`
|
||||
)}"]`
|
||||
)
|
||||
.classList.remove("rotate-180");
|
||||
});
|
||||
|
|
@ -78,7 +80,7 @@ class Dropdown {
|
|||
|
||||
isSameValue(btnSetting, value) {
|
||||
const selectCustom = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-text="${btnSetting}"]`,
|
||||
`[data-${this.prefix}-setting-select-text="${btnSetting}"]`
|
||||
);
|
||||
const currVal = selectCustom.textContent;
|
||||
return currVal === value ? true : false;
|
||||
|
|
@ -86,30 +88,30 @@ class Dropdown {
|
|||
|
||||
setSelectNewValue(btnSetting, value) {
|
||||
const selectCustom = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select="${btnSetting}"]`,
|
||||
`[data-${this.prefix}-setting-select="${btnSetting}"]`
|
||||
);
|
||||
selectCustom.querySelector(
|
||||
`[data-${this.prefix}-setting-select-text]`,
|
||||
`[data-${this.prefix}-setting-select-text]`
|
||||
).textContent = value;
|
||||
}
|
||||
|
||||
hideDropdown(btnSetting) {
|
||||
//hide dropdown
|
||||
const dropdownEl = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`,
|
||||
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`
|
||||
);
|
||||
dropdownEl.classList.add("hidden");
|
||||
dropdownEl.classList.remove("flex");
|
||||
//svg effect
|
||||
const dropdownChevron = document.querySelector(
|
||||
`svg[data-${this.prefix}-setting-select="${btnSetting}"]`,
|
||||
`svg[data-${this.prefix}-setting-select="${btnSetting}"]`
|
||||
);
|
||||
dropdownChevron.classList.remove("rotate-180");
|
||||
}
|
||||
|
||||
changeDropBtnStyle(btnSetting, selectedBtn) {
|
||||
const dropdownEl = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`,
|
||||
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`
|
||||
);
|
||||
//reset dropdown btns
|
||||
const btnEls = dropdownEl.querySelectorAll("button");
|
||||
|
|
@ -119,7 +121,7 @@ class Dropdown {
|
|||
"bg-primary",
|
||||
"dark:bg-primary",
|
||||
"text-gray-300",
|
||||
"text-gray-300",
|
||||
"text-gray-300"
|
||||
);
|
||||
btn.classList.add("bg-white", "dark:bg-slate-700", "text-gray-700");
|
||||
});
|
||||
|
|
@ -127,7 +129,7 @@ class Dropdown {
|
|||
selectedBtn.classList.remove(
|
||||
"bg-white",
|
||||
"dark:bg-slate-700",
|
||||
"text-gray-700",
|
||||
"text-gray-700"
|
||||
);
|
||||
selectedBtn.classList.add("dark:bg-primary", "bg-primary", "text-gray-300");
|
||||
}
|
||||
|
|
@ -138,10 +140,10 @@ class Dropdown {
|
|||
.getAttribute(`data-${this.prefix}-setting-select`);
|
||||
//toggle dropdown
|
||||
const dropdownEl = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-dropdown="${attribute}"]`,
|
||||
`[data-${this.prefix}-setting-select-dropdown="${attribute}"]`
|
||||
);
|
||||
const dropdownChevron = document.querySelector(
|
||||
`svg[data-${this.prefix}-setting-select="${attribute}"]`,
|
||||
`svg[data-${this.prefix}-setting-select="${attribute}"]`
|
||||
);
|
||||
dropdownEl.classList.toggle("hidden");
|
||||
dropdownEl.classList.toggle("flex");
|
||||
|
|
@ -197,7 +199,7 @@ class Filter {
|
|||
setTimeout(() => {
|
||||
const value = document
|
||||
.querySelector(
|
||||
`[data-${this.prefix}-setting-select-text="success"]`,
|
||||
`[data-${this.prefix}-setting-select-text="success"]`
|
||||
)
|
||||
.textContent.trim();
|
||||
|
||||
|
|
@ -220,7 +222,7 @@ class Filter {
|
|||
setTimeout(() => {
|
||||
const value = document
|
||||
.querySelector(
|
||||
`[data-${this.prefix}-setting-select-text="reload"]`,
|
||||
`[data-${this.prefix}-setting-select-text="reload"]`
|
||||
)
|
||||
.textContent.trim();
|
||||
|
||||
|
|
@ -329,7 +331,7 @@ class Download {
|
|||
|
||||
async sendFileToDL(jobName, fileName) {
|
||||
window.open(
|
||||
`${location.href}/download?job_name=${jobName}&file_name=${fileName}`,
|
||||
`${location.href}/download?job_name=${jobName}&file_name=${fileName}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class Dropdown {
|
|||
const btn = e.target.closest("button");
|
||||
const btnValue = btn.getAttribute("value");
|
||||
const btnSetting = btn.getAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`,
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`
|
||||
);
|
||||
//stop if same value to avoid new fetching
|
||||
const isSameVal = this.isSameValue(btnSetting, btnValue);
|
||||
|
|
@ -57,7 +57,7 @@ class Dropdown {
|
|||
|
||||
closeAllDrop() {
|
||||
const drops = document.querySelectorAll(
|
||||
`[data-${this.prefix}-setting-select-dropdown]`,
|
||||
`[data-${this.prefix}-setting-select-dropdown]`
|
||||
);
|
||||
drops.forEach((drop) => {
|
||||
drop.classList.add("hidden");
|
||||
|
|
@ -65,8 +65,8 @@ class Dropdown {
|
|||
document
|
||||
.querySelector(
|
||||
`svg[data-${this.prefix}-setting-select="${drop.getAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown`,
|
||||
)}"]`,
|
||||
`data-${this.prefix}-setting-select-dropdown`
|
||||
)}"]`
|
||||
)
|
||||
.classList.remove("rotate-180");
|
||||
});
|
||||
|
|
@ -74,7 +74,7 @@ class Dropdown {
|
|||
|
||||
isSameValue(btnSetting, value) {
|
||||
const selectCustom = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-text="${btnSetting}"]`,
|
||||
`[data-${this.prefix}-setting-select-text="${btnSetting}"]`
|
||||
);
|
||||
const currVal = selectCustom.textContent;
|
||||
return currVal === value ? true : false;
|
||||
|
|
@ -82,49 +82,43 @@ class Dropdown {
|
|||
|
||||
setSelectNewValue(btnSetting, value) {
|
||||
const selectCustom = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select="${btnSetting}"]`,
|
||||
`[data-${this.prefix}-setting-select="${btnSetting}"]`
|
||||
);
|
||||
selectCustom.querySelector(
|
||||
`[data-${this.prefix}-setting-select-text]`,
|
||||
`[data-${this.prefix}-setting-select-text]`
|
||||
).textContent = value;
|
||||
}
|
||||
|
||||
hideDropdown(btnSetting) {
|
||||
//hide dropdown
|
||||
const dropdownEl = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`,
|
||||
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`
|
||||
);
|
||||
dropdownEl.classList.add("hidden");
|
||||
dropdownEl.classList.remove("flex");
|
||||
//svg effect
|
||||
const dropdownChevron = document.querySelector(
|
||||
`svg[data-${this.prefix}-setting-select="${btnSetting}"]`,
|
||||
`svg[data-${this.prefix}-setting-select="${btnSetting}"]`
|
||||
);
|
||||
dropdownChevron.classList.remove("rotate-180");
|
||||
}
|
||||
|
||||
changeDropBtnStyle(btnSetting, selectedBtn) {
|
||||
const dropdownEl = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`,
|
||||
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`
|
||||
);
|
||||
//reset dropdown btns
|
||||
const btnEls = dropdownEl.querySelectorAll("button");
|
||||
|
||||
btnEls.forEach((btn) => {
|
||||
btn.classList.remove(
|
||||
"dark:bg-primary",
|
||||
"bg-primary",
|
||||
"bg-primary",
|
||||
"text-gray-300",
|
||||
"text-gray-300",
|
||||
);
|
||||
btn.classList.remove("dark:bg-primary", "bg-primary", "text-gray-300");
|
||||
btn.classList.add("bg-white", "dark:bg-slate-700", "text-gray-700");
|
||||
});
|
||||
//highlight clicked btn
|
||||
selectedBtn.classList.remove(
|
||||
"bg-white",
|
||||
"dark:bg-slate-700",
|
||||
"text-gray-700",
|
||||
"text-gray-700"
|
||||
);
|
||||
selectedBtn.classList.add("dark:bg-primary", "bg-primary", "text-gray-300");
|
||||
}
|
||||
|
|
@ -135,10 +129,10 @@ class Dropdown {
|
|||
.getAttribute(`data-${this.prefix}-setting-select`);
|
||||
//toggle dropdown
|
||||
const dropdownEl = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-dropdown="${attribute}"]`,
|
||||
`[data-${this.prefix}-setting-select-dropdown="${attribute}"]`
|
||||
);
|
||||
const dropdownChevron = document.querySelector(
|
||||
`svg[data-${this.prefix}-setting-select="${attribute}"]`,
|
||||
`svg[data-${this.prefix}-setting-select="${attribute}"]`
|
||||
);
|
||||
dropdownEl.classList.toggle("hidden");
|
||||
dropdownEl.classList.toggle("flex");
|
||||
|
|
@ -300,7 +294,7 @@ class Upload {
|
|||
this.dropZoneElement.classList.remove(
|
||||
"border-solid",
|
||||
"bg-gray-100",
|
||||
"dark:bg-slate-700/50",
|
||||
"dark:bg-slate-700/50"
|
||||
);
|
||||
this.dropZoneElement.classList.add("border-dashed");
|
||||
}
|
||||
|
|
@ -309,7 +303,7 @@ class Upload {
|
|||
this.dropZoneElement.classList.add(
|
||||
"border-solid",
|
||||
"bg-gray-100",
|
||||
"dark:bg-slate-700/50",
|
||||
"dark:bg-slate-700/50"
|
||||
);
|
||||
this.dropZoneElement.classList.remove("border-dashed");
|
||||
}
|
||||
|
|
@ -346,13 +340,13 @@ class Upload {
|
|||
if (xhr.status == 201) {
|
||||
this.uploadedArea.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
this.fileSuccess(name, fileSize),
|
||||
this.fileSuccess(name, fileSize)
|
||||
);
|
||||
this.allowReload();
|
||||
} else {
|
||||
this.uploadedArea.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
this.fileFail(name, fileSize),
|
||||
this.fileFail(name, fileSize)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -451,10 +445,10 @@ class Modal {
|
|||
this.modalExtInp = this.modal.querySelector("input#external");
|
||||
|
||||
this.modalTitle = this.modal.querySelector(
|
||||
`[data-${this.prefix}-modal-title]`,
|
||||
`[data-${this.prefix}-modal-title]`
|
||||
);
|
||||
this.modalTxt = this.modal.querySelector(
|
||||
`[data-${this.prefix}-modal-text]`,
|
||||
`[data-${this.prefix}-modal-text]`
|
||||
);
|
||||
this.init();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ class Filter {
|
|||
this.keyInp = document.querySelector("input#keyword");
|
||||
this.methodValue = "all";
|
||||
this.statusValue = "all";
|
||||
|
||||
this.reasonValue = "all";
|
||||
this.initHandler();
|
||||
}
|
||||
|
||||
|
|
@ -56,6 +56,29 @@ class Filter {
|
|||
}
|
||||
} catch (err) {}
|
||||
});
|
||||
// REASON HANDLER
|
||||
+this.container.addEventListener("click", (e) => {
|
||||
try {
|
||||
if (
|
||||
e.target
|
||||
.closest("button")
|
||||
.getAttribute(`data-${this.prefix}-setting-select-dropdown-btn`) ===
|
||||
"reason"
|
||||
) {
|
||||
setTimeout(() => {
|
||||
const value = document
|
||||
.querySelector(
|
||||
`[data-${this.prefix}-setting-select-text="reason"]`
|
||||
)
|
||||
.textContent.trim();
|
||||
|
||||
this.reasonValue = value;
|
||||
//run filter
|
||||
this.filter();
|
||||
}, 10);
|
||||
}
|
||||
} catch (err) {}
|
||||
});
|
||||
//KEYWORD HANDLER
|
||||
this.keyInp.addEventListener("input", (e) => {
|
||||
this.filter();
|
||||
|
|
@ -76,6 +99,7 @@ class Filter {
|
|||
this.setFilterMethod(requests);
|
||||
this.setFilterKeyword(requests);
|
||||
this.setFilterStatus(requests);
|
||||
this.setFilterReason(requests);
|
||||
}
|
||||
|
||||
setFilterMethod(requests) {
|
||||
|
|
@ -95,13 +119,13 @@ class Filter {
|
|||
|
||||
const url = this.getElAttribut(el, "url");
|
||||
const date = this.getElAttribut(el, "date");
|
||||
const reason = this.getElAttribut(el, "reason");
|
||||
const ip = this.getElAttribut(el, "ip");
|
||||
const data = this.getElAttribut(el, "data");
|
||||
|
||||
if (
|
||||
!url.includes(keyword) &&
|
||||
!date.includes(keyword) &&
|
||||
!reason.includes(keyword) &&
|
||||
!ip.includes(keyword) &&
|
||||
!data.includes(keyword)
|
||||
)
|
||||
el.classList.add("hidden");
|
||||
|
|
@ -117,6 +141,15 @@ class Filter {
|
|||
}
|
||||
}
|
||||
|
||||
setFilterReason(requests) {
|
||||
if (this.reasonValue === "all") return;
|
||||
for (let i = 0; i < requests.length; i++) {
|
||||
const el = requests[i];
|
||||
const type = this.getElAttribut(el, "reason");
|
||||
if (type !== this.reasonValue) el.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
getElAttribut(el, attr) {
|
||||
return el
|
||||
.querySelector(`[data-${this.prefix}-${attr}]`)
|
||||
|
|
@ -174,7 +207,9 @@ class Dropdown {
|
|||
//close dropdown and change style
|
||||
this.hideDropdown(btnSetting);
|
||||
|
||||
if (!e.target.closest("button").hasAttribute(`data-${prefix}-file`)) {
|
||||
if (
|
||||
!e.target.closest("button").hasAttribute(`data-${this.prefix}-file`)
|
||||
) {
|
||||
this.changeDropBtnStyle(btnSetting, btn);
|
||||
}
|
||||
//show / hide filter
|
||||
|
|
|
|||
117
src/ui/templates/block_requests.html
vendored
117
src/ui/templates/block_requests.html
vendored
|
|
@ -3,6 +3,8 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
|
||||
{% set methods = [] %}
|
||||
{% set codes = [] %}
|
||||
{% set reasons = [] %}
|
||||
|
||||
|
||||
{% for request in block_requests %}
|
||||
{% if request["method"] not in methods %}
|
||||
|
|
@ -11,6 +13,9 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
{% if request["status"] not in codes %}
|
||||
{% set codes = codes.append(request["status"]) %}
|
||||
{% endif %}
|
||||
{% if request["reason"] not in reasons %}
|
||||
{% set reasons = reasons.append(request["reason"]) %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<!-- info-->
|
||||
|
|
@ -30,6 +35,30 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
{{block_requests|length}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="mx-1 flex items-center my-4">
|
||||
<p
|
||||
class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80"
|
||||
>
|
||||
TOP REASON
|
||||
</p>
|
||||
<p
|
||||
class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80"
|
||||
>
|
||||
{{top_reason}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="mx-1 flex items-center my-4">
|
||||
<p
|
||||
class="transition duration-300 ease-in-out font-bold mb-0 font-sans text-sm leading-normal uppercase dark:text-gray-500 dark:opacity-80"
|
||||
>
|
||||
TOP STATUS CODE
|
||||
</p>
|
||||
<p
|
||||
class="transition duration-300 ease-in-out pl-2 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-white dark:opacity-80"
|
||||
>
|
||||
{{top_code}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end info -->
|
||||
|
||||
|
|
@ -53,7 +82,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
id="keyword"
|
||||
name="keyword"
|
||||
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
|
||||
placeholder="url, date, reason, data"
|
||||
placeholder="ip, url, date, data"
|
||||
pattern="(.*?)"
|
||||
required
|
||||
/>
|
||||
|
|
@ -182,7 +211,69 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
</div>
|
||||
<!-- end dropdown-->
|
||||
</div>
|
||||
<!-- end select method -->
|
||||
<!-- end select status -->
|
||||
|
||||
<!-- select reason -->
|
||||
<div class="flex flex-col relative col-span-12 md:col-span-6">
|
||||
<h5
|
||||
class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300"
|
||||
>
|
||||
Reason
|
||||
</h5>
|
||||
<button
|
||||
aria-controls="filter-state"
|
||||
data-{{current_endpoint}}-setting-select="reason"
|
||||
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="{{current_endpoint}}-reason"
|
||||
data-name="{{current_endpoint}}-reason"
|
||||
data-{{current_endpoint}}-setting-select-text="reason"
|
||||
>all</span
|
||||
>
|
||||
<!-- chevron -->
|
||||
<svg
|
||||
data-{{current_endpoint}}-setting-select="reason"
|
||||
class="transition-transform h-4 w-4 fill-gray-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
<path
|
||||
d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- end chevron -->
|
||||
<!-- dropdown-->
|
||||
<div
|
||||
id="filter-state"
|
||||
role="listbox"
|
||||
data-{{current_endpoint}}-setting-select-dropdown="reason"
|
||||
class="hidden z-100 absolute h-full flex-col w-full translate-y-16"
|
||||
>
|
||||
<button
|
||||
role="option"
|
||||
data-{{current_endpoint}}-setting-select-dropdown-btn="reason"
|
||||
value="all"
|
||||
class="border-t rounded-t border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:text-gray-300 dark:bg-primary bg-primary text-gray-300"
|
||||
>
|
||||
all
|
||||
</button>
|
||||
{% for reason in reasons %}
|
||||
<button
|
||||
role="option"
|
||||
data-{{current_endpoint}}-setting-select-dropdown-btn="reason"
|
||||
value="{{reason}}"
|
||||
class="{% if loop.last %}rounded-b{%endif%} border-b border-l border-r border-gray-300 dark:hover:brightness-90 hover:brightness-90 bg-white text-gray-700 my-0 relative py-2 px-3 text-left align-middle transition-all rounded-none cursor-pointer leading-normal text-sm ease-in tracking-tight-rem dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300"
|
||||
>
|
||||
{{reason}}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<!-- end dropdown-->
|
||||
</div>
|
||||
<!-- end select reason -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- end filter -->
|
||||
|
|
@ -192,10 +283,15 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
>
|
||||
<h5 class="mb-4 mt-2 font-bold dark:text-white/90 mx-2">BLOCK REQUESTS</h5>
|
||||
<!-- list container-->
|
||||
<div class="min-w-[900px] w-full grid grid-cols-12 rounded p-2">
|
||||
<div class="min-w-[1024px] w-full grid grid-cols-12 rounded p-2">
|
||||
<!-- header-->
|
||||
<p
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-3 m-0 pb-2 border-b border-gray-400"
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-2 m-0 pb-2 border-b border-gray-400"
|
||||
>
|
||||
IP
|
||||
</p>
|
||||
<p
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-2 m-0 pb-2 border-b border-gray-400"
|
||||
>
|
||||
Url
|
||||
</p>
|
||||
|
|
@ -220,7 +316,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
Reason
|
||||
</p>
|
||||
<p
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-3 m-0 pb-2 border-b border-gray-400"
|
||||
class="dark:text-gray-300 h-8 text-sm font-bold col-span-2 m-0 pb-2 border-b border-gray-400"
|
||||
>
|
||||
Data
|
||||
</p>
|
||||
|
|
@ -232,9 +328,16 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
|
||||
class="items-center grid grid-cols-12 border-b border-gray-300 py-2.5"
|
||||
>
|
||||
<p
|
||||
|
||||
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
|
||||
data-{{current_endpoint}}-ip="{{request['ip']}}"
|
||||
>
|
||||
{{request['ip']}}
|
||||
</p>
|
||||
<p
|
||||
|
||||
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-3 m-0 my-1"
|
||||
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
|
||||
data-{{current_endpoint}}-url="{{request['url']}}"
|
||||
>
|
||||
{{request['url']}}
|
||||
|
|
@ -269,7 +372,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
|
|||
</p>
|
||||
<p
|
||||
|
||||
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-3 m-0 my-1"
|
||||
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
|
||||
data-{{current_endpoint}}-data="{{request['data']}}"
|
||||
>
|
||||
{{request["data"]}}
|
||||
|
|
|
|||
Loading…
Reference in a new issue