feat(datetime): timezone/time_format в настройках + единый хелпер дат
Часовой пояс и формат времени (24h/12h) перенесены из браузера в настройки приложения: валидация IANA-зоны, сид в db/init.sql + db/migration.sql, отдача в GET /api/public-settings, раздел #sec-datetime в настройках с живым превью. Границы суток в SQL переведены на tzDayStart/tzDayEnd + bindTz ($TZ$) — раньше $n::date по TIMESTAMPTZ считал дни в UTC (у контейнера TimeZone=UTC) и молча сдвигал выборку на день; хардкод Europe/Moscow вычищен, now() заменён на tzWall(). Новый public/js/datetime.js: три семейства хелперов (instant / чистая DATE-строка без Date() / чистая TIME-строка), подключён на всех страницах включая публичные share/report/index, initDateTime() встроен в checkAuth(). Прямые toLocale*/getFullYear/toISOString().slice(0,10) в public/ выпилены. Попутно: bindTz добавляет параметр только при наличии $TZ$ в SQL (иначе запрос виснет вечно без global error handler) — регрессия закрыта в api.smoketest.js; починены off-by-one месяца в report.js и группировка по дате в share.js.
This commit is contained in:
+4
-4
@@ -32,7 +32,7 @@ function entryHTML(e) {
|
||||
<div class="group">${esc(e.group_name)}</div>
|
||||
<div class="desc">${esc(e.description)}</div>
|
||||
${filesHTML(e.files)}
|
||||
<div class="trash-time">Удалена: ${new Date(e.deleted_at).toLocaleString('ru')}</div>
|
||||
<div class="trash-time">Удалена: ${fmtFull(e.deleted_at)}</div>
|
||||
</div>
|
||||
<button class="restore-btn" data-restore="${e.id}" title="Восстановить">Восстановить</button>
|
||||
<button class="del-btn" data-hard="${e.id}" title="Пометить на удаление (через ${purgeDays} дней будет удалена безвозвратно)">×</button>
|
||||
@@ -47,7 +47,7 @@ function groupHTML(g) {
|
||||
<div class="info">
|
||||
<div class="name">${esc(g.name)}</div>
|
||||
${g.branch_name ? `<div class="group">${esc(g.branch_name)}</div>` : ''}
|
||||
<div class="trash-time">Удалена: ${new Date(g.deleted_at).toLocaleString('ru')}</div>
|
||||
<div class="trash-time">Удалена: ${fmtFull(g.deleted_at)}</div>
|
||||
</div>
|
||||
<button class="restore-btn" data-restore-group="${g.id}" title="Восстановить">Восстановить</button>
|
||||
<button class="del-btn" data-hard-group="${g.id}" title="Пометить на удаление (через ${purgeDays} дней будет удалена безвозвратно вместе с записями и фото)">×</button>
|
||||
@@ -64,7 +64,7 @@ function pendingEntryHTML(e) {
|
||||
<div class="group">${esc(e.group_name)}</div>
|
||||
<div class="desc">${esc(e.description)}</div>
|
||||
${filesHTML(e.files)}
|
||||
<div class="trash-time warn">Удаление через ${purgeDays} дн.: ${new Date(e.purge_at).toLocaleString('ru')}</div>
|
||||
<div class="trash-time warn">Удаление через ${purgeDays} дн.: ${fmtFull(e.purge_at)}</div>
|
||||
</div>
|
||||
<button class="restore-btn" data-unschedule="${e.id}" title="Вернуть в корзину">В корзину</button>
|
||||
</div>
|
||||
@@ -78,7 +78,7 @@ function pendingGroupHTML(g) {
|
||||
<div class="info">
|
||||
<div class="name">${esc(g.name)}</div>
|
||||
${g.branch_name ? `<div class="group">${esc(g.branch_name)}</div>` : ''}
|
||||
<div class="trash-time warn">Удаление через ${purgeDays} дн.: ${new Date(g.purge_at).toLocaleString('ru')}</div>
|
||||
<div class="trash-time warn">Удаление через ${purgeDays} дн.: ${fmtFull(g.purge_at)}</div>
|
||||
</div>
|
||||
<button class="restore-btn" data-unschedule-group="${g.id}" title="Вернуть в корзину">В корзину</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user