mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
enhance bans page
*hide term table *add svg to datepicker *rename some text (entry, range...) *change remaining text
This commit is contained in:
parent
4f9fd8a6a0
commit
b1c59bc1ea
9 changed files with 7119 additions and 79 deletions
|
|
@ -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
|
|
@ -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");
|
||||
|
|
|
|||
12
src/ui/templates/bans.html
vendored
12
src/ui/templates/bans.html
vendored
|
|
@ -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>
|
||||
|
|
|
|||
33
src/ui/templates/bans_modal.html
vendored
33
src/ui/templates/bans_modal.html
vendored
|
|
@ -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
|
||||
|
|
|
|||
11
src/ui/templates/logs.html
vendored
11
src/ui/templates/logs.html
vendored
|
|
@ -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"
|
||||
|
|
|
|||
59
src/ui/templates/menu.html
vendored
59
src/ui/templates/menu.html
vendored
|
|
@ -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 -->
|
||||
|
||||
|
|
|
|||
|
|
@ -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)):
|
||||
|
|
|
|||
Loading…
Reference in a new issue