enhance bans page

*hide term table
*add svg to datepicker
*rename some text (entry, range...)
*change remaining text
This commit is contained in:
Jordan Blasenhauer 2024-01-22 12:45:00 +01:00
parent 4f9fd8a6a0
commit b1c59bc1ea
9 changed files with 7119 additions and 79 deletions

View file

@ -48,7 +48,7 @@ from src.Config import Config
from src.ReverseProxied import ReverseProxied
from src.User import AnonymousUser, User
from utils import check_settings, get_b64encoded_qr_image, path_to_dict, get_remain, get_term_from_remain
from utils import check_settings, get_b64encoded_qr_image, path_to_dict, get_remain, get_range_from_remain
from Database import Database # type: ignore
from logging import getLogger
@ -1718,7 +1718,7 @@ def bans():
# Add remain
remain = "unknown" if ban["ban_end"] - now_stamp < 0 else get_remain(ban["ban_end"] - now_stamp)
ban["remain"] = remain
ban["term"] = get_term_from_remain(remain)
ban["term"] = get_range_from_remain(remain)
# Convert stamp to date
ban["ban_start"] = datetime.fromtimestamp(ban["ban_start"])
ban["ban_end"] = datetime.fromtimestamp(ban["ban_end"])

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -23,7 +23,7 @@ class Filter {
setTimeout(() => {
const value = document
.querySelector(
`[data-${this.prefix}-setting-select-text="method"]`
`[data-${this.prefix}-setting-select-text="method"]`,
)
.textContent.trim();
@ -46,7 +46,7 @@ class Filter {
setTimeout(() => {
const value = document
.querySelector(
`[data-${this.prefix}-setting-select-text="country"]`
`[data-${this.prefix}-setting-select-text="country"]`,
)
.textContent.trim();
@ -69,7 +69,7 @@ class Filter {
setTimeout(() => {
const value = document
.querySelector(
`[data-${this.prefix}-setting-select-text="status"]`
`[data-${this.prefix}-setting-select-text="status"]`,
)
.textContent.trim();
@ -92,7 +92,7 @@ class Filter {
setTimeout(() => {
const value = document
.querySelector(
`[data-${this.prefix}-setting-select-text="reason"]`
`[data-${this.prefix}-setting-select-text="reason"]`,
)
.textContent.trim();
@ -111,7 +111,7 @@ class Filter {
filter() {
const requests = document.querySelector(
`[data-${this.prefix}-list]`
`[data-${this.prefix}-list]`,
).children;
if (requests.length === 0) return;
//reset
@ -231,7 +231,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);
@ -257,7 +257,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");
@ -265,8 +265,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");
});
@ -274,7 +274,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;
@ -282,30 +282,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");
@ -315,7 +315,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");
});
@ -323,7 +323,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");
}
@ -334,10 +334,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");

View file

@ -158,7 +158,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
<h5
class="my-1 transition duration-300 ease-in-out dark:opacity-90 text-sm sm:text-md font-bold m-0 dark:text-gray-300"
>
Term
Range
</h5>
<button
aria-controls="filter-state"
@ -242,7 +242,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
IP
</p>
<p
class="dark:text-gray-300 h-8 text-sm font-bold col-span-1 m-0 pb-2 border-b border-gray-400"
class="dark:text-gray-300 h-8 text-sm font-bold col-span-2 m-0 pb-2 border-b border-gray-400"
>
Reason
</p>
@ -262,7 +262,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
Remain
</p>
<p
class="dark:text-gray-300 h-8 text-sm font-bold col-span-1 m-0 pb-2 border-b border-gray-400"
class="hidden"
>
Term
</p>
@ -309,7 +309,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
</p>
<p
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1"
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-2 m-0 my-1"
data-{{current_endpoint}}-reason="{{ban["reason"]}}"
>
{{ban["reason"]}}
@ -335,7 +335,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
{{ban["remain"]}}
</p>
<p
class="dark:text-gray-400 dark:opacity-80 text-sm col-span-1 m-0 my-1"
class="hidden"
data-{{current_endpoint}}-term="{{ban["term"]}}"
>
{{ban["term"]}}
@ -354,7 +354,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
<input type="hidden" name="operation" value="unban">
<input data-unban-inp type="hidden" name="data" value="">
<button data-unban-btn disabled type="submit" class="valid-btn mr-3 text-base">
UNBAN SELECTED
UNBAN
</button>
</form>
</div>

View file

@ -40,7 +40,7 @@
type="button"
class="disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0 dark:bg-green-500/90 duration-300 dark:opacity-90 flex justify-center items-center px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal text-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md"
>
<span class="mr-2 pointer-events-none">Add field</span>
<span class="mr-2 pointer-events-none">Entry</span>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -88,17 +88,17 @@
>
<!-- header-->
<p
class="dark:text-gray-300 h-8 text-sm font-bold col-span-5 m-0 pb-2 border-b border-gray-400"
class="pl-2 dark:text-gray-300 h-8 text-sm font-bold col-span-5 m-0 pb-2 border-b border-gray-400"
>
IP
</p>
<p
class="dark:text-gray-300 h-8 text-sm font-bold col-span-5 m-0 pb-2 border-b border-gray-400"
class="pl-2 dark:text-gray-300 h-8 text-sm font-bold col-span-5 m-0 pb-2 border-b border-gray-400"
>
Ban end
</p>
<p
class="dark:text-gray-300 h-8 text-sm font-bold col-span-2 m-0 pb-2 pl-4 border-b border-gray-400"
class="flex justify-center dark:text-gray-300 h-8 text-sm font-bold col-span-2 m-0 pb-2 border-b border-gray-400"
>
Delete
</p>
@ -124,16 +124,21 @@
</div>
<div class="mx-1.5 col-span-5">
<label for="ban-end-0" class="sr-only">Ban end</label>
<input
data-bans-add-ban-end
type="text"
id="ban-end-0"
name="ban-end-0"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="01/01/2021 00:00:00"
pattern="(.*?)"
required
/>
<div class="relative">
<input
data-bans-add-ban-end
type="text"
id="ban-end-0"
name="ban-end-0"
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="01/01/2021 00:00:00"
pattern="(.*?)"
required
/>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="pointer-events-none absolute top-1 right-2 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />
</svg>
</div>
</div>
<div class="mx-1.5 col-span-2 flex justify-center items-center">
<button

View file

@ -67,6 +67,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
>
From date
</h5>
<div class="relative">
<input
type="text"
id="from-date"
@ -76,6 +77,10 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
pattern="(.*?)"
required
/>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="pointer-events-none absolute top-1 right-2 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />
</svg>
</div>
</div>
<!-- end from date input -->
<!-- to date input -->
@ -85,6 +90,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
>
To date (default today)
</h5>
<div class="relative">
<input
type="text"
id="to-date"
@ -94,6 +100,10 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
pattern="(.*?)"
required
/>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="pointer-events-none absolute top-1 right-2 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5" />
</svg>
</div>
</div>
<!-- end to date input -->
@ -104,6 +114,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
>
Update delay (in seconds)
</h5>
<input
type="number"
id="update-delay"

View file

@ -350,6 +350,36 @@
</a>
</li>
<!-- end item -->
<!-- item -->
<li class="mt-0.5 w-full">
<a
class="{% if current_endpoint == 'jobs' %}font-semibold text-slate-700 dark:bg-primary/50 rounded-lg dark:hover:bg-primary/60 bg-primary/20 hover:bg-primary/30{% else %}dark:hover:bg-primary/20 hover:bg-primary/5 {% endif %} hover:rounded-lg dark:text-white dark:opacity-80 py-1 text-sm ease-nav-brand my-0 mx-2 flex items-center whitespace-nowrap px-4 transition"
href="{% if current_endpoint == 'jobs' %}#{% else %}loading?next={{ url_for('jobs') }}{% endif %}"
>
<div
class="mr-2 flex items-center justify-center rounded-lg bg-center stroke-0 text-center p-1 xl:p-1.5"
>
<svg
class="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>
</div>
<span class="ml-1 duration-300 opacity-100 pointer-events-none ease"
>Jobs</span
>
</a>
</li>
<!-- item -->
<li class="mt-0.5 w-full">
<a
@ -381,35 +411,6 @@
</a>
</li>
<!-- end item -->
<!-- item -->
<li class="mt-0.5 w-full">
<a
class="{% if current_endpoint == 'jobs' %}font-semibold text-slate-700 dark:bg-primary/50 rounded-lg dark:hover:bg-primary/60 bg-primary/20 hover:bg-primary/30{% else %}dark:hover:bg-primary/20 hover:bg-primary/5 {% endif %} hover:rounded-lg dark:text-white dark:opacity-80 py-1 text-sm ease-nav-brand my-0 mx-2 flex items-center whitespace-nowrap px-4 transition"
href="{% if current_endpoint == 'jobs' %}#{% else %}loading?next={{ url_for('jobs') }}{% endif %}"
>
<div
class="mr-2 flex items-center justify-center rounded-lg bg-center stroke-0 text-center p-1 xl:p-1.5"
>
<svg
class="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>
</div>
<span class="ml-1 duration-300 opacity-100 pointer-events-none ease"
>Jobs</span
>
</a>
</li>
</ul>
<!-- end default anchor -->

View file

@ -25,20 +25,34 @@ def get_remain(remain_time):
hours %= 24
days %= 30
months %= 12
return f"{f'{years}y' if years else ''} {f'{months}m' if months else ''} {f'{days}d' if days else ''} {f'{hours}h' if hours else ''} {f'{minutes}min' if minutes else ''} {f'{seconds}s' if seconds else ''}"
remain = f'{format_remain(years, "year")} {format_remain(months, "month")} {format_remain(days, "day")} {format_remain(hours, "hour")} {format_remain(minutes, "minute")} {format_remain(seconds, "second")}'
return remain
def get_term_from_remain(remain):
# Data, need format <n>y <n>m <n>d <n>h <n>min <n>s
terms = remain.split(" ")
term = ""
formats = ["years", "months", "days", "hours", "minutes", "seconds"]
chars = ["y", "min", "m", "d", "h", "s"]
def format_remain(num, singular):
if not num:
return ""
if num == 1:
return f"{num} {singular}"
if num > 1:
return f"{num} {singular}s"
def get_range_from_remain(remain):
# Not handle
if remain == "unknown":
return remain
# Data, need format <n>y <n>m <n>d <n>h <n>min <n>s
split_remain = remain.split(" ")
terms = [num for num in split_remain if num.isdigit()]
term = ""
formats = ["year(s)", "month(s)", "day(s)", "hour(s)", "minute(s)", "second(s)"]
chars = ["year", "month", "day", "hour", "second", "s"]
# start from seconds to years, stop when first 0 occurence
# The remain term is first 0 occurence - 1
for i in range(len(terms)):