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>
По умолчанию плашка свёрнута (65×35) — белая плашка с фиолетовым пилюлем текущего
масштаба («12М» и т.п.). При наведении разворачивается (145×80) в полный контрол
(лейбл + слайдер + баббл) с плавной анимацией размеров (overflow:hidden + фикс.
размеры) и кросс-фейдом содержимого. Сворачивается обратно через 1с после ухода
курсора (JS-таймер в main.ts, класс .expanded; повторное наведение отменяет). В
развёрнутом виде содержимое смещено на 4px вниз для вертикальной центровки.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Над календарём — две пилюли-конца в стиле чипсов фильтров (accent-weak
заливка, индиго-текст, скруглённые). Активная пилюля (куда пишется следующий
клик) с индиго-рамкой; клик по дню пишет в активный конец, фокус авто-переходит
ко второму. У каждой пилюли × — очистить именно этот конец, что даёт ОТКРЫТЫЙ
диапазон: «с X» (без конца) или «по Y» (без начала). «Применить» активна, если
задан хотя бы один конец. Нативные #date-start/#date-end по-прежнему источник
истины, любой из них может быть пустым; фильтр и URL уже читают from/to по
отдельности.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- .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>
- Тогглы: Бренд+Компания в одну строку, блок выровнен ровно по полосе контролов (верх = верх полей, низ = низ «Поиска»), равномерные зазоры
- Датапикер: выбор диапазона больше не применяется автоматически по второму клику — только кнопкой «Применить» (+ «Сбросить» для незавершённого выбора)
- Степперы «Оформления»: ровно 80px по ширине
- Поле поиска в дропдаунах: равномерная рамка 1px по всем сторонам вместо разноцветных краёв
- Балун на карте: клик по пустой карте закрывает балун (guard от самозакрытия по «своему» клику, клик по другому кластеру открывает новый)
- Полоса фильтров: поля сужены на 10px, «Период» до 333px
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
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>
- 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>
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>
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>
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>
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>
- 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>
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>
- 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>
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>
- 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>
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>
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>
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`).
- 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>