Support datetime input for filters, improve date parsing logic, and update UI labels and button states in monitoring app.
This commit is contained in:
parent
39e07ddb15
commit
cfc562eae6
@ -697,16 +697,22 @@ def _ts_str(ts: float) -> str:
|
||||
|
||||
|
||||
def _parse_date(s: str, end: bool = False) -> Optional[float]:
|
||||
s = (s or "").strip()
|
||||
s = (s or "").strip().replace("T", " ")
|
||||
if not s:
|
||||
return None
|
||||
try:
|
||||
d = datetime.strptime(s, "%Y-%m-%d").replace(tzinfo=timezone.utc)
|
||||
except ValueError:
|
||||
return None
|
||||
if end:
|
||||
d += timedelta(days=1)
|
||||
return d.timestamp()
|
||||
# Принимаем как дату, так и дату со временем (datetime-local), всё в UTC.
|
||||
for fmt, has_time in (("%Y-%m-%d %H:%M:%S", True),
|
||||
("%Y-%m-%d %H:%M", True),
|
||||
("%Y-%m-%d", False)):
|
||||
try:
|
||||
d = datetime.strptime(s, fmt).replace(tzinfo=timezone.utc)
|
||||
except ValueError:
|
||||
continue
|
||||
# Для верхней границы без времени берём весь день целиком.
|
||||
if end and not has_time:
|
||||
d += timedelta(days=1)
|
||||
return d.timestamp()
|
||||
return None
|
||||
|
||||
|
||||
def _opt(value: str, current: str, label: str = "") -> str:
|
||||
@ -1127,11 +1133,11 @@ def admin_dashboard(
|
||||
<label>Тип<select name=type>{type_opts}</select></label>
|
||||
<label>Event<input name=event value="{html_lib.escape(event)}" placeholder="task_error…"></label>
|
||||
<label>Поиск в тексте<input name=q value="{html_lib.escape(q)}" placeholder="подстрока"></label>
|
||||
<label>Дата с<input name=date_from type=date value="{html_lib.escape(date_from)}"></label>
|
||||
<label>Дата по<input name=date_to type=date value="{html_lib.escape(date_to)}"></label>
|
||||
<label>С (UTC)<input name=date_from type=datetime-local step=1 value="{html_lib.escape(date_from)}"></label>
|
||||
<label>По (UTC)<input name=date_to type=datetime-local step=1 value="{html_lib.escape(date_to)}"></label>
|
||||
<button type=submit>Фильтр</button>
|
||||
<a href="/admin"><button type=button class=sec>Сброс</button></a>
|
||||
<button id=arBtn type=button class=sec onclick="_arToggle()" style="min-width:90px">⏸ Стоп</button>
|
||||
<button id=arBtn type=button class=sec onclick="_arToggle()" style="min-width:90px">▶ Старт</button>
|
||||
<span id=arStatus class=muted style="font-size:12px;align-self:center"></span>
|
||||
</form>
|
||||
<form id=bulkForm class=bulkbar method=post action="/admin/entries/delete"
|
||||
@ -1151,10 +1157,11 @@ def admin_dashboard(
|
||||
{_LOCAL_TIME_JS}
|
||||
<script>
|
||||
(function(){{
|
||||
var running = true;
|
||||
var running = false;
|
||||
var timer = null;
|
||||
var btn = document.getElementById('arBtn');
|
||||
var stat = document.getElementById('arStatus');
|
||||
stat.textContent='выключено';
|
||||
|
||||
function applyLocalTimes(scope){{
|
||||
var pad=function(n){{return(n<10?'0':'')+n;}};
|
||||
@ -1199,8 +1206,6 @@ def admin_dashboard(
|
||||
stat.textContent='на паузе';
|
||||
}}
|
||||
}};
|
||||
|
||||
tick();
|
||||
}})();
|
||||
</script>
|
||||
</body></html>"""
|
||||
@ -1630,8 +1635,8 @@ def admin_desktops(request: Request, date_from: str = "", date_to: str = "") ->
|
||||
<title>ARC monitoring — десктопы</title>{_STYLE}{_DESK_STYLE}</head><body>
|
||||
{_header('desktops')}
|
||||
<form class=filters method=get action="/admin/desktops">
|
||||
<label>Дата с<input name=date_from type=date value="{html_lib.escape(date_from)}"></label>
|
||||
<label>Дата по<input name=date_to type=date value="{html_lib.escape(date_to)}"></label>
|
||||
<label>С (UTC)<input name=date_from type=datetime-local step=1 value="{html_lib.escape(date_from)}"></label>
|
||||
<label>По (UTC)<input name=date_to type=datetime-local step=1 value="{html_lib.escape(date_to)}"></label>
|
||||
<button type=submit>Фильтр</button>
|
||||
<a href="/admin/desktops"><button type=button class=sec>Сброс</button></a>
|
||||
<button type=button class=sec onclick="return _collapseAll()">Свернуть всё</button>
|
||||
@ -1838,8 +1843,8 @@ def admin_screens(request: Request, device: str = "",
|
||||
{_header('screens')}
|
||||
<form class=filters method=get action="/admin/screens">
|
||||
<label>Девайс<select name=device onchange="this.form.submit()">{''.join(dev_opts)}</select></label>
|
||||
<label>Дата с<input name=date_from type=date value="{html_lib.escape(date_from)}"></label>
|
||||
<label>Дата по<input name=date_to type=date value="{html_lib.escape(date_to)}"></label>
|
||||
<label>С (UTC)<input name=date_from type=datetime-local step=1 value="{html_lib.escape(date_from)}"></label>
|
||||
<label>По (UTC)<input name=date_to type=datetime-local step=1 value="{html_lib.escape(date_to)}"></label>
|
||||
<button type=submit>Фильтр</button>
|
||||
<a href="/admin/screens"><button type=button class=sec>Сброс</button></a>
|
||||
<span class=muted>история экрана · хранение {SCREENSHOT_RETENTION_HOURS} ч · время UTC</span>
|
||||
@ -1995,8 +2000,8 @@ def admin_dumps(request: Request, device: str = "",
|
||||
{_header('dumps')}
|
||||
<form class=filters method=get action="/admin/dumps">
|
||||
<label>Девайс<select name=device onchange="this.form.submit()">{''.join(dev_opts)}</select></label>
|
||||
<label>Дата с<input name=date_from type=date value="{html_lib.escape(date_from)}"></label>
|
||||
<label>Дата по<input name=date_to type=date value="{html_lib.escape(date_to)}"></label>
|
||||
<label>С (UTC)<input name=date_from type=datetime-local step=1 value="{html_lib.escape(date_from)}"></label>
|
||||
<label>По (UTC)<input name=date_to type=datetime-local step=1 value="{html_lib.escape(date_to)}"></label>
|
||||
<button type=submit>Фильтр</button>
|
||||
<a href="/admin/dumps"><button type=button class=sec>Сброс</button></a>
|
||||
<span class=muted>XML + скриншот · хранение {SCREEN_DUMP_RETENTION_DAYS} сут · время UTC</span>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user