Commit Graph

44 Commits

Author SHA1 Message Date
aaverbitskiy
f0c53e2ce9 Выгрузка карты из памяти + фиксы столбца адресов
1) Карта выгружается (map.destroy()) через 2с после ухода в режим «График»
   — освобождает тайлы/canvas/GPU (~350–450 МБ); отменяется при возврате.
   Метод MapView.destroy() (сброс map/objectManager/initPromise/pending);
   в onModeChange сброс mapLoadedKey, иначе refreshMap короткозамыкал render и
   свежий ObjectManager оставался пустым.

2) MIN_LABEL_W 140→200 — три пилюли Город/Адрес/Код не обрезаются на узком
   столбце; container-query прячет подпись «Показывать» при ширине < 255px.

3) Правый/левый отступ 7px у содержимого строки (#timeline .vis-label .vis-inner,
   специфичность выше собственного padding vis-timeline) — адрес не липнет к
   границе столбца.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 05:33:30 +00:00
aaverbitskiy
17b70b1f44 Колонка Город/Адрес/Код + оформление шкалы времени
1) Первая колонка графика: в углу — кнопки «Показывать» Город/Адрес/Код
   (стиль пилюль, активная — фиолетовая). Строка собирается из включённых
   сущностей, разделённых кружком 7px; код без скобок; адрес тёмный, город/код
   приглушённые. «Адрес» (или последний активный) нельзя снять — строка не пустеет.
   Доступно всем ролям, выбор в localStorage. Лёгкое обновление подписей
   (view.refreshLabels — без пересборки баров).

2) Временная шкала: единые 3-буквенные месяцы (format.minorLabels/majorLabels),
   год индиго и жирнее (.vis-text.vis-major), подсветка текущего месяца
   (фон-элемент cur-month-bg). Красная линия «сегодня» без изменений.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 20:56:33 +00:00
aaverbitskiy
3939dbf8f5 Плашка масштаба графика — сворачиваемая с анимацией
По умолчанию плашка свёрнута (65×35) — белая плашка с фиолетовым пилюлем текущего
масштаба («12М» и т.п.). При наведении разворачивается (145×80) в полный контрол
(лейбл + слайдер + баббл) с плавной анимацией размеров (overflow:hidden + фикс.
размеры) и кросс-фейдом содержимого. Сворачивается обратно через 1с после ухода
курсора (JS-таймер в main.ts, класс .expanded; повторное наведение отменяет). В
развёрнутом виде содержимое смещено на 4px вниз для вертикальной центровки.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 12:34:51 +00:00
aaverbitskiy
43bb72de61 Дропдауны: рамка поиска не режется + ширина ≤350px с горизонтальным скроллом
- Поле .dp-search било по специфичности правилом .hgroup-fields input[type=text]
  {width:100%} (0,2,1) — поле всегда было 100% (=padding-box со скроллом), из-за
  чего рамка резалась краем и появлялась фантомная горизонтальная полоса. Селектор
  усилен до .dropdown-panel input.dp-search (0,2,1, позже в источнике), ширина —
  fill-available (заполняет доступную ширину минус вертикальный скролл).
- Панель: max-width 350px + overflow:auto — контент шире 350px даёт горизонтальный
  скролл (убраны overflow-x:hidden и scrollbar-gutter из прошлой правки).

Задеплоено на прод без тега.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 08:50:20 +00:00
aaverbitskiy
691ec36b9e Дропдауны фильтров: убрана горизонтальная прокрутка в раскрывающейся панели
Панель подстраивает ширину под контент (width: max-content, min 220, max 96vw),
overflow-x: hidden убирает фантомную горизонтальную полосу от вертикального
скролла (метки-флексы тянулись на полную ширину под скроллбар), scrollbar-gutter:
stable резервирует место под вертикальный скролл. Задеплоено на прод без тега.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 08:29:20 +00:00
aaverbitskiy
77a36a22d9 Датапикер: открытый диапазон через пилюли-концы «С» / «По»
Над календарём — две пилюли-конца в стиле чипсов фильтров (accent-weak
заливка, индиго-текст, скруглённые). Активная пилюля (куда пишется следующий
клик) с индиго-рамкой; клик по дню пишет в активный конец, фокус авто-переходит
ко второму. У каждой пилюли × — очистить именно этот конец, что даёт ОТКРЫТЫЙ
диапазон: «с X» (без конца) или «по Y» (без начала). «Применить» активна, если
задан хотя бы один конец. Нативные #date-start/#date-end по-прежнему источник
истины, любой из них может быть пустым; фильтр и URL уже читают from/to по
отдельности.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 08:14:45 +00:00
aaverbitskiy
5ac2142c70 Датапикер: дни диапазона — отдельные кружки одного размера (27px)
Промежуточные дни диапазона были сплошной заливкой-пилюлей; теперь каждый — отдельный светлый кружок 27px, вровень с акцентными кружками концов (тоже 27px). Убраны соединяющие полу-градиенты у концов.

Задеплоено на прод поверх v0.2.15 без нового тега.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 05:40:41 +00:00
aaverbitskiy
5902c1e7f0 Микрофикс: убран grid-column span 2 у .field-dates
После унификации полей до 195px «Период» больше не занимает 2 колонки — span 2 оставлял пустоту справа и криво переносил поля (у анонима «Поиск» уезжал на вторую строку). Теперь все поля — обычные колонки 195px, ряд заполняется слева направо.

Задеплоено прямо на прод поверх v0.2.15 без нового тега.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 05:25:06 +00:00
aaverbitskiy
147529c20f Унификация ширины полей-фильтров: все 195px, короткий год в «Период»
- .hgroup-fields: колонки 170→195px (все фильтры одинаковой ширины)
- «Период» (.dr-field) 333→195px, вровень с остальными
- Формат даты в поле «Период» — 2-значный год (05.08.26 — 20.08.26), чтобы диапазон целиком помещался в 195px; в чипсах год остался полным

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 05:13:35 +00:00
aaverbitskiy
5ba5a77f97 UI-доработки: выравнивание тогглов, датапикер с «Применить», степперы 80px, поле поиска, автозакрытие балуна карты
- Тогглы: Бренд+Компания в одну строку, блок выровнен ровно по полосе контролов (верх = верх полей, низ = низ «Поиска»), равномерные зазоры
- Датапикер: выбор диапазона больше не применяется автоматически по второму клику — только кнопкой «Применить» (+ «Сбросить» для незавершённого выбора)
- Степперы «Оформления»: ровно 80px по ширине
- Поле поиска в дропдаунах: равномерная рамка 1px по всем сторонам вместо разноцветных краёв
- Балун на карте: клик по пустой карте закрывает балун (guard от самозакрытия по «своему» клику, клик по другому кластеру открывает новый)
- Полоса фильтров: поля сужены на 10px, «Период» до 333px

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-15 20:39:12 +00:00
aaverbitskiy
e9eee60dab ui: toasts, icon segmented mode switch, steppers, date-range picker (v0.2.13)
Second modernization batch (reference: easystudy ui_elements):
- Toast/snackbar notifications (dark, green check) for actions — copy link.
- Mode switch: icons (horizontal bars / pin / columns) + a sliding active
  indicator; fixed width so the bold active label never resizes the block.
- Appearance number fields became steppers: an editable field with centred −/+
  buttons, ~20% narrower.
- Date filter: the two native date inputs are replaced by a custom range picker
  — one field "Период (даты)" + a calendar popup with month nav and range
  selection (circle endpoints, light band between). The native inputs stay hidden
  as the source of truth so all filter/URL/chip wiring is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-15 19:02:45 +00:00
aaverbitskiy
f5166b888a ui: toggles, stat tiles, dropdown search, bubble scale slider (v0.2.12)
Modernised several controls (reference: easystudy ui_elements catalogue):
- Display checkboxes (Бренд/Компания/Коллизии/Все поверхности) are now toggle
  switches; the option checkboxes inside filter dropdowns stay normal.
- Counters became stat tiles: header "Поверхности N" (accent) and the map
  legend (свободно/занято/всего + dashed "без координат").
- Filter dropdowns gained an in-panel search that filters the option list
  (shown for lists >7, auto-focused on open).
- Timeline scale control restyled as a filled slider with a value bubble, moved
  out of the header to float over the top-right of the chart just below the time
  axis (5px gap), bubble pointing up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-15 14:46:04 +00:00
aaverbitskiy
d7c1ce7b77 ui: fresh panel per cluster click, 5-step scale, unified column resizer (v0.2.11)
- Map panel: every marker/cluster click reopens a fresh panel repositioned next
  to the just-clicked cluster (with a pop-in), instead of leaving it in place and
  only swapping the content.
- Timeline scale slider: 5 fixed stops — 6/12/18/24/30 months; label is now
  "Масштаб графика: <6М|12М|18М|24М|30М>" (default 12М).
- Address-column resizer now matches the timeline/map splitter: a 6px solid bar
  that turns accent on hover/drag, so both dividers look identical.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-15 13:40:10 +00:00
aaverbitskiy
f4c1de70b4 feat: timeline label -> fly map to surface; keep panel inside the window (v0.2.10)
Timeline: clicking a surface in the left column now flies the map to it — it
switches to the combined "Карта и график" view when only the timeline is open,
then centres+zooms on the surface's cluster (deferred focus waits for the map to
render; works for anonymous and manager users). Replaces the old manager-only
board detail panel on that click (the map card already shows photos + bookings).

Map panel: for clusters with many surfaces it now widens (tabs flow into 3-4
columns) and its height is capped to the space available in the window, so it
never overflows the browser window and scrolls inside instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-15 09:59:52 +00:00
aaverbitskiy
78d62ae36c ui: render lone surfaces as donut clusters of 1 for a unified map (v0.2.9)
Set minClusterSize:1 so a solitary surface is drawn with the same donut icon
(showing "1", green when free / red when busy) instead of a small dot, and every
click flows through the single cluster handler into our panel. A cluster of one
keeps the rich single-surface hover tooltip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-15 09:04:27 +00:00
aaverbitskiy
e83bb5ad49 feat: custom map surface panel (fits content, resizable, smart-positioned) (v0.2.8)
Replace the Yandex balloon with our own floating card, opened on marker/cluster
click. It fits its content (no forced scroll), is draggable by the header and
resizable from the bottom-right corner, and — for clusters — carries tabs to
switch between the co-located surfaces. Photo gallery + lightbox are preserved.

On open it positions itself next to the clicked cluster and offsets toward the
free side of the map (the map half the cluster sits in picks the direction, e.g.
bottom-left cluster -> panel opens up and to the right), clamped inside the map.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-15 08:40:48 +00:00
aaverbitskiy
8e6c19e9a4 feat: surface photos in the map balloon + fullscreen lightbox (v0.2.7)
Photos live on disk as photos/<board_key>/<file>.{jpg,jpeg,png} (a read-only
volume). A cached directory index (60s TTL) attaches a `photos` URL list to each
surface in /api/map; a /photos StaticFiles mount serves the files. Photos are
public — shown to anonymous visitors and managers alike.

The balloon renders a gallery (main image + thumbnail strip + "1 / N" counter);
clicking a thumbnail swaps the main image, and clicking the main image / "+N"
opens a fullscreen lightbox over the map (prev/next, Esc, backdrop close).
Surfaces without photos render exactly as before.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-15 08:00:10 +00:00
aaverbitskiy
dec639581b ui: green "Размещено" default + green circle favicon (v0.2.6)
- default colour for status "РК. Размещено" is now green #26c04c (was indigo)
- add a #26c04c circle favicon (inline SVG data URI) for the browser tab

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-14 20:14:01 +00:00
aaverbitskiy
de4cf1743b polish: flip overflowing bar label to the left when it would hit the next bar (v0.2.5)
Extends the bar-label overflow handling: an oversized label defaults to the
right of the bar, but if it would collide with the next bar on the same row it
is placed to the left instead (whichever side has room; larger gap wins when
neither fits). Also make the trigger a debounce (was a throttle) so the layout
runs after a zoom/redraw burst settles, once bar widths are final.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-14 19:31:26 +00:00
aaverbitskiy
9b6ca6f848 polish: appearance menu offsets, anon map badge, bar label overflow (v0.2.4)
- appearance menu opens 20px below the header/chips and 58px from the right edge
- map "no coordinates" badge is manager-only (hidden for anonymous visitors)
- timeline bar label that is wider than its bar now renders just past the bar's
  right edge as dark text on the track, instead of being clipped; labels that
  fit still sit inside the bar in white. Applied post-render (measure overflow),
  re-run on changed/rangechanged with a double rAF so bar widths are settled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-14 19:09:47 +00:00
aaverbitskiy
159590d62e analytics: add Yandex.Metrika counter 111613184 (v0.2.3)
Counter snippet at the top of <body> (webvisor, clickmap, trackLinks).
Lives in index.html only — no change to the JS/CSS bundle.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-14 18:32:11 +00:00
aaverbitskiy
b4d56d0540 polish: chips bar + appearance menu placement + brand title (v0.2.2)
- appearance menu drops below the active-filter chips row when it is shown,
  and sits 10px further from the right edge
- "Скопировать ссылку" moved to the left of the chips, separated by a divider
- enlarge "Green Media" title so it is flush with the "Адресная программа"
  line below it

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-14 16:00:47 +00:00
aaverbitskiy
aeb4651f6f polish: appearance menu + clean status names everywhere (v0.2.1)
Appearance ("Оформление") menu:
- add missing status "РК. Предварительное бронирование" (8 statuses total)
- strip the systemic "РК. " prefix from status names in the UI (menu,
  tooltip, status filter dropdown, active-filter chips); raw values stay
  intact for filtering/URLs
- fixed-position menu: opens 25px below the header, ends >=30px above the
  window bottom, scrolls inside — never overflows the viewport
- drop the "Прочие статусы" row
- per-status grey reset glyph (circular arrows) restoring its default colour

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-14 15:37:03 +00:00
aaverbitskiy
5cabad9c33 feat: all-surfaces timeline + UI polish (v0.2.0)
Timeline can now list the entire inventory (occupied + free + never
booked), not just booked surfaces. New manager-only "Все поверхности"
checkbox (on by default; forced on and hidden for anonymous visitors so
they can spot what is currently free with no future bookings).

/api/boards gains all_surfaces: sources rows from board_info and unions
pf_board so a just-booked surface not yet in the inventory snapshot still
gets a row. Surface facets (city/dimension/search) narrow rows; booking
facets (brand/manager/status) narrow to booked surfaces; dates are a
window that narrows bars, not the surface set.

UI polish:
- timeline tooltip flips up/left near viewport edges
- anonymous "Войти" button filled accent, inverts to white-on-accent hover
- appearance button uses a gear icon instead of "+"
- header counter shows only "Поверхности: N"
- map "всего" counter includes surfaces without coordinates

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-14 14:48:25 +00:00
aaverbitskiy
341bc42778 auth ui: prevent flash of manager-only controls on load
Anonymous visitors briefly saw the manager-only filters (Brand/Manager/Status),
checkboxes and appearance menu on refresh, because applyRoleUi() hides them only
after the async Keycloak check-sso resolves.

Fix: mark those elements .manager-only and hide them pre-paint via a .role-pending
class set on <html> by the inline head script, gated by a render-blocking CSS rule
(html.role-pending .manager-only { display:none }). applyRoleUi() drops
.role-pending once the role is known and then applies the final per-element state.
Default is now fail-closed (hidden until confirmed manager), so anonymous never
flashes them; managers see the controls appear a moment after load.
2026-08-14 11:29:51 +00:00
aaverbitskiy
1eda6c1e9d auth ui: anon tooltip = dates only; move login button to header top-right
- timeline: RenderFlags.managerView drives the tooltip. Anonymous tier shows
  a minimal tooltip (date range + duration only) — no title, task №, status,
  manager or Planfix hint. Manager tier keeps the rich tooltip.
- header: login/logout button pinned to the top-right corner (.auth-wrap,
  absolute) instead of sitting next to the view-mode switch.

Keycloak: register bare origin in post.logout.redirect.uris so keycloak-js
logout (redirectUri without trailing path) is accepted.
2026-08-14 11:22:16 +00:00
aaverbitskiy
b6b9c27cb0 auth: Keycloak OIDC — anonymous (truncated) vs manager (full) tiers
Backend (main.py + auth.py):
- Validate Bearer JWT against the intense-sale realm JWKS (RS256, issuer
  checked, aud skipped). Missing/invalid token = anonymous, never an error,
  so the public map keeps working when Keycloak is down.
- Anonymous truncation: /api/meta hides brand/manager/status facets;
  /api/bookings blanks brand/company_name/manager/task_id/task_status
  (bars stay, one neutral colour); /api/map keeps occupied_now but empties
  booking details. Hidden facet filters are ignored for anonymous callers.
- boards stay visible to all (physical inventory: address/city/dimension).

Frontend (keycloak-js):
- Silent SSO (check-sso) — anonymous by default, Войти/Выйти button.
- Bearer token attached + refreshed on every API call.
- Anonymous UI hides Brand/Manager/Status filters, Brand/Company toggles,
  appearance menu, collisions and labels; board detail panel (Planfix
  deep-links) gated to managers.

Test manager: user / 1234567890 (realm role `manager`).
2026-08-14 11:05:47 +00:00
aaverbitskiy
4425bd394c features: shareable filter links, board detail panel, spacing rhythm on tokens
- Shareable filter links: current filters sync to the URL query
  (?city=&brand=&dimension=&manager=&status=&q=&from=&to=, repeated params for
  multi-selects) and are restored on load; a "Скопировать ссылку" action in the
  chips row copies the current URL.
- Board detail panel: clicking a timeline row label opens a right-side panel with
  the surface's code, city · size, address and the full list of its bookings
  (brand/company, dates, status dot, manager, Planfix link). Close via ✕ /
  backdrop / Esc. Bars still open the Planfix task. Dropdown gains a public
  setOnBoardClick on the timeline view.
- Fix: the panel showed empty on load because .board-panel{display:flex}
  overrode the UA [hidden] rule — added an explicit [hidden]{display:none}.
- Spacing: tokenised the secondary chrome (header groups, fields, dropdown panel,
  appearance menu, legend, map tooltip) onto the Open Props --size-* scale;
  structural density of the header/fields/inputs deliberately kept.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-10 18:08:45 +00:00
aaverbitskiy
52a1a7cb2d ui: active-filter chips, empty/loading states, focus/animation polish
- Active-filter chips row under the header: one chip per selected city / brand /
  dimension / manager / status plus search and date bounds, each removable; a
  "Сбросить всё" clears everything. Dropdown gains setSelected()/clear().
- Empty states for the timeline and map: icon + title + subtitle + "Сбросить
  фильтры" button (wired to the same reset). (empty toggled to display:flex.)
- Delayed indeterminate loading bar (250ms threshold so fast loads don't flash),
  covering both the data and the map fetches via an in-flight counter.
- Polish: pop-in animation for dropdown/appearance menus, :focus-visible accent
  rings, :active press on buttons, thin themed scrollbars in panels, tabular
  figures on the timeline date axis and tooltips. New components use the Open
  Props --size-* spacing scale.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-10 16:28:51 +00:00
aaverbitskiy
17c54db501 design: adopt Open Props tokens, indigo accent + IBM Plex Sans, collision colour
- Add Open Props as the token foundation (@import "open-props/style"). Our
  semantic tokens (--bg/--surface/--border/--text/--shadow-*/--transition) are
  now backed by its gray ramp, shadows and easing; the rest of the CSS is
  untouched since it already references var(--…).
- Accent → indigo #4f46e5 (--accent + derived rings / month-hover), and the
  timeline bar default colours (appearance.ts) move to the same indigo so the
  content and UI share one palette.
- Font → IBM Plex Sans, self-hosted via @fontsource (latin + cyrillic, weights
  400/500/600/700) so there is no runtime Google Fonts dependency. Backed into
  --font-sans (overrides Open Props' :where() default). Tabular figures on the
  counters and map legend.
- Collision default colour → warm amber-orange #e8590c: distinct from the indigo
  bars and from the green/red map status, reads as a conflict warning.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 21:15:50 +00:00
aaverbitskiy
de0c369bb5 map/header UI: unified marker colours, vertical legend, smart tooltip, click fixes
Map (map.ts, styles.css):
- Single markers now use the same donut colours (islands#circleDotIcon +
  iconColor #37b24d / #e24b4a) instead of Yandex's brighter presets, so single
  and cluster markers match.
- Legend is a vertical stack with relabelled live counts: "свободно / занято /
  всего", and the "без координат" badge hides when the count is zero.
- Cluster tooltip shows the brand for occupied surfaces (coral); legend raised
  above the Yandex controls.
- Hover tooltip: smart positioning — flips above/left of the cursor when it would
  overflow the viewport (bottom clusters no longer clip), max-height safety.
- Bug fix: hide the hover tooltip on marker/cluster click — it no longer sticks
  and follows the cursor after a balloon opens.
- Bug fix: clusterDisableClickZoom=true so a cluster click opens its balloon at
  any zoom instead of only at max zoom.

Header (index.html, styles.css):
- Scale + appearance + checkboxes recomposed into one compact block; the
  "Оформление" control is a round "+" button pinned to the header's bottom-right
  corner with a hover tooltip; counters relabelled "Поверхности / Брони"; the
  counters plate and view-mode switch share one borderless grey fill.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 18:48:01 +00:00
aaverbitskiy
a68cac80d1 map: donut clusters, occupancy legend/search/no-coords, styled balloon; header polish
Map (map.ts, styles.css, index.html):
- Cluster icons are now donut charts split green (free) / red (busy) by the
  occupancy of the surfaces they contain, count in the centre. Custom
  clusterIconLayout with a hit-area shape; hover/click preserved.
- gridSize 64 -> 112 so nearby clusters stop overlapping at the overview zoom.
- Live legend: "свободна: X · занята: Y · поверхностей: N", reacts to filters.
- "Без координат" is now a clickable badge opening a compact codes-only panel
  (header "Без координат") so the missing-coordinate surfaces can be fixed.
- Search-to-locate: when a filter narrows to one surface the map flies in and
  opens its balloon.
- Balloon restyled to match the timeline tooltip; muted map tiles (ground-pane
  filter) so the markers stand out.
- Cluster hover tooltip shows the brand for occupied surfaces; legend plate
  raised above the Yandex controls.

Header (index.html, styles.css, main.ts):
- Scale + appearance + checkboxes recomposed into one compact block; shorter
  slider; the "Масштаб" label uses the shared field-label style again.
- "Оформление" is now a round "+" button pinned to the header's bottom-right
  corner with a hover tooltip; opens the same appearance menu.
- Counters relabelled "Поверхности" / "Брони"; the counters plate and the
  view-mode switch now share one borderless grey fill; mode buttons sit on a
  more visible grey frame.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 09:39:11 +00:00
aaverbitskiy
557522afcf ui: visual refresh, richer bar tooltip (+manager), header alignment fixes
Frontend (styles.css, index.html, main.ts):
- Design tokens: single accent/border/radius/shadow/spacing system; flat header
  (dropped the boxed groups) with a subtle bottom divider.
- Unified controls: 36px height, consistent focus ring; search field gets a
  magnifier icon; view-mode switch is now a compact vertical segmented control.
- Fixed the dropdown option font: `.field label` styles were leaking into the
  option <label>s (they're inside .field), forcing uppercase + bold; options are
  now normal weight / normal case.
- Header alignment: mode switch fills the row so its bottom lines up with the
  date fields; the counters block is pinned to the same bottom line.
- Dropdown lists no longer show the column-resizer line bleeding through: the
  header now establishes a stacking context (position:relative + z-index) so its
  panels sit above the timeline.
- Dark theme is implemented (tokens + no-flash) but hidden for now (toggle
  display:none, forced light) until it's polished — easy to re-enable.

Timeline tooltip (timeline.ts, types.ts):
- Replaced the plain multi-line text tooltip with a structured card: bold brand
  title + task №, company subtitle, localized dates + duration, status as a
  coloured dot, manager, a distinct collision section, and a "click to open in
  Planfix" hint. Left accent stripe in the bar colour; matches the map tooltip.
- Values are escaped (escapeHtml) before going into innerHTML.

Backend (main.py):
- /api/bookings now returns `manager` (Array(String)), canonicalized to the
  "Фамилия Имя" form (see canon_manager) so the tooltip can show it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 04:39:55 +00:00
aaverbitskiy
c7eae87660 filters: add faceted Status (task_status) filter — meta.statuses, boards/bookings/map filtering (map marker visibility), UI dropdown under Size in filter grid 2026-07-27 19:40:26 +00:00
aaverbitskiy
053bf2587d header: move counters into brand block, compact 4-col filter grid (dates + search on row 2), unify all block backgrounds 2026-07-26 08:52:36 +00:00
aaverbitskiy
d2ad928948 header: responsive layout — fields wrap to next line at min width, all gray blocks may shrink and reflow instead of overlapping 2026-07-26 05:36:35 +00:00
aaverbitskiy
68417bf45e map: Yandex map section (3 modes + resizable split), green/red markers, hover tooltips for markers+clusters; fix map init race; header keeps counters inline (fields shrink first); add Manager (Менеджер) faceted filter 2026-07-26 05:05:04 +00:00
aaverbitskiy
23f5ce8b1a header layout: checkbox column (3 rows), Оформление under scale slider, counters as inline gray block 2026-07-21 10:24:07 +00:00
aaverbitskiy
66e501ef59 date filters: independent Дата начала (start_date>=) / Дата окончания (end_date<=), header fields under Город/Бренд; qualify pf_board.start_date/end_date to avoid alias shadowing 2026-07-21 10:07:39 +00:00
aaverbitskiy
fe06cdab72 dependent (faceted) filters: city/brand/dimension/search narrow each other 2026-07-21 08:38:53 +00:00
aaverbitskiy
5db77b7a06 brand filter (backend+frontend), compact checkbox grid, two-line counter 2026-07-18 11:15:43 +00:00
aaverbitskiy
b393562c3a frontend UI: header 4 groups, Оформление menu (colors/sizes/fonts), centered bars via inner div, clickable Planfix links 2026-07-17 19:27:22 +00:00
aaverbitskiy
6704a50b33 frontend: full modular migration (collisions/dropdown/timeline/styles), staged at /next/, prod unchanged 2026-07-17 16:17:00 +00:00
aaverbitskiy
c6363cd8cf frontend: Vite+TypeScript scaffold (types, api) — not wired to static yet 2026-07-17 15:41:13 +00:00