# Changelog ## [statistica vibe 3] — 2026-03-23 > Правки и улучшения статистики после `statistica vibe 2` ### Улучшения - **График открытых заявок** — переключатель **«По неделям»** / **«По дням»**: 16 недель (как раньше) или 112 дней с тем же смыслом точки (снимок «сколько было открыто» на момент); боковая панель сравнения в режиме дней подписывает вторую строку «день назад». - **Тепловая карта по месяцам** переработана: вместо сетки месяц×день-недели теперь отображается одна строка из 12 ячеек (по одной на месяц), каждая окрашена по числу заявок. Значение показывается при наведении. - **Блок сравнения** («сейчас / неделю назад / начало месяца») теперь растягивается в высоту графика (`align-items: stretch`), элементы равномерно распределяются по высоте — цифры больше не выступают за пределы графика. - **Повторные клиенты** — один счётчик «открытых» через `isTaskOpen` (в т.ч. «в работе», «новая», «назначена» и т.п.); одна акцентная полоса и бейдж `N откр.` без разделения цветов. ### Исправления - **Карточка «Клиенты» + «Только с открытыми»**: при включённом фильтре внутренняя полоса теперь заполняет внешнюю полностью (`opPct = 100%`), чтобы не было двойного масштабирования и визуально «другой» закраски относительно режима без фильтра. ### Затронутые файлы | Файл | Изменения | | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | `public/js/statistics.js` | `MONTH_COUNTS` вместо `MONTH_HM`; новый HTML месячной тепловой карты; `renderClientsList` с единой логикой `open` и правкой `opPct` для `clientsOnlyOpen`; переключатель недели/дни для графика открытых (`openChartByDays`, `lineOpen` / `lineSlot`) | | `public/css/app.css` | `.stats-month-hm`*; `align-items: stretch` в `.stats-open-wrap`; уменьшен `.soc-val`; стили бейджа клиентов без раздельных полос | --- ## [123 → statistica vibe 2] — 2026-03-23 > Коммиты: `fc2b7f7 (123)` · `232a6b4 (sync2 vibe)` · `45773f1 (statistica vibe 1)` · `77d3ac9 (statistica vibe 2)` --- ### Новые функции #### Колонка «Служ. статус в интре» — двусторонняя синхронизация с IntraDesk - Добавлена колонка **«Служ. статус в интре»** (`servstatus`) в таблице заявок — отображает значение дополнительного поля `addfield_2f6eaa2vnutrennij_statusSingleSelect` из IntraDesk; цвет подбирается по совпадению с label внутреннего статуса - Колонка интерактивная: при наведении открывается пикер для смены значения поля напрямую в IntraDesk (независимо от внутреннего статуса), с пунктом «— очистить» - **Исходящая синхронизация**: при смене внутреннего статуса через `POST /api/marks` значение автоматически записывается в доп. поле IntraDesk через `PUT /changes/v3/tasks/`; при снятии статуса — поле очищается (`null`) - **Входящая синхронизация**: при каждом обновлении задачи значение доп. поля сравнивается с label активных внутренних статусов — при совпадении статус выставляется автоматически - Новый эндпоинт `POST /api/tasks/:taskId/intra-addfield` для прямой записи значения поля без смены внутреннего статуса - SSE-событие `intra_addfield` рассылается всем клиентам при изменении — обновление отображается в реальном времени, тост-уведомление для других пользователей - Настройка **«Синхронизировать служебный статус с доп. полем IntraDesk»** в панели администратора → Status Automation (ключ `sync_addfield_status`, по умолчанию выключена) #### Страница статистики — новые элементы - **Тепловая карта по месяцам** (месяц × день недели) — 12×7 сетка, показывает распределение нагрузки по месяцам и дням недели; размещена в одном ряду с картой «час × день» - **Блок сравнения** в карточке «Открытых заявок на конец недели» — три значения: сейчас / неделю назад / начало месяца; цветной бейдж роста (↑ красный) или снижения (↓ зелёный); расположен справа от графика как компактная боковая панель - **Кликабельные клиенты** в карточке «Клиенты» — клик по строке клиента закрывает статистику и открывает главную страницу с автоматически выставленным фильтром «Объекты» по данному клиенту #### Страница статистики — улучшения UX - При наведении на столбик в графике «Создано / Закрыто по неделям»: столбики подсвечиваются (`brightness`), над ними появляется метка со значениями (создано / закрыто) #### Фильтры на главной странице - Поиск внутри выпадающего фильтра **«Объекты»** — текстовое поле для быстрой фильтрации длинного списка объектов; появляется при открытии дропдауна, автофокус #### Локальный запуск - `docker-compose.local.yml` — compose-файл для сборки образа из исходников (вместо пулла из registry), данные монтируются из `./data` - `start-local.bat` — батник для Windows: проверяет наличие `.env`, создаёт `./data`, запускает `docker compose ... up -d --build` одним двойным кликом --- ### Исправления - **Тепловая карта (час × день)**: CSS-селектор `[style*="--hi:0"]` некорректно совпадал с любым значением начинающимся с `0` (т.е. `0.200`, `0.400` и т.д.) — в результате окрашивался только один максимальный квадрат. Исправлено на `[style*="--hi:0.000"]` - **Кнопка тёмной темы**: скрыта (`display:none`); логика `toggleTheme` и состояние темы сохранены - **Клиенты с кавычками в названии** (напр. `БЦ "Луч"`): двойные кавычки разрушали HTML-атрибут `data-client`, из-за чего фильтр не применялся. Добавлен `escAttr` с экранированием `"` → `"` --- ### Затронутые файлы | Файл | Изменения | | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `refresh-service.js` | Константа `INTRA_ADDFIELD_ALIAS`; извлечение `_addfield_status` при fetch; `updateIntraAdditionalField()`; inbound-синхронизация в `applyStatusAutomationForChangedTasks`; `sync_addfield_status` в `normalizeSettings` | | `server.js` | Outbound-вызов после `POST /api/marks`; новый эндпоинт `POST /api/tasks/:taskId/intra-addfield`; настройка `sync_addfield_status` в `ALLOWED_SETTINGS` и `GET/POST /api/settings` | | `public/js/ui.js` | Колонка `servstatus` в `ALL_COLS`; `intraAddfieldBadge`, `intraAddfieldPickerHtml`, `setIntraAddfield`; `hasSearch: true` для фильтра «Объекты»; поисковый блок в `buildAdvancedFilterPanel` | | `public/js/sse.js` | Обработчик события `intra_addfield` | | `public/js/auth.js` | Загрузка и сохранение чекбокса `sync_addfield_status` | | `public/js/statistics.js` | Блок сравнения открытых заявок (wDiffBadge, openAtMonthStart); тепловая карта по месяцам (MONTH_HM, MONTH_NAMES); кликабельные клиенты (`filterByClient`, `escAttr`); hover-label на столбиках активности | | `public/css/app.css` | Стили блока сравнения (`.stats-open-wrap`, `.stats-open-compare`, `.soc-`*, `.stats-wdiff`); hover-label (`.stats-act-hover-label`, `.sahl-*`); поиск фильтра (`.adv-filter-search-wrap`, `.adv-filter-search`); кликабельные строки клиентов; исправление тепловой карты (`--hi:0.000`) | | `public/index.html` | Чекбокс настройки `sync_addfield_status`; `display:none` на кнопке темы | | `docker-compose.local.yml` | Новый файл — compose для локальной разработки | | `start-local.bat` | Новый файл — скрипт запуска локального Docker |