Commit Graph

89 Commits

Author SHA1 Message Date
8b713e66c0 Исправлено дублирование сообщений в task-чате: защита от двойного Enter/клика по кнопке отправки 2026-08-24 16:50:05 +03:00
422eafd41f Дополнительное ускорение появления просмотренных задач во вкладке Последние: refetchOnMount always и refetch при переключении на recent 2026-08-24 16:35:01 +03:00
709d4cbfa3 Ускорено появление просмотренных задач во вкладке Последние: фоновый refetch всех home-запросов и refetchOnWindowFocus для recent 2026-08-24 16:22:56 +03:00
a4eaf65915 Отслеживание просмотров задач: task_views, POST /api/tasks/:id/view и обновление /api/home/recent 2026-08-24 15:40:30 +03:00
74abd8fad5 Исправлен клик по push-уведомлению: открытие задачи/чата из тела, Ответить и Прочитано; controlled-clients + fallback openWindow 2026-08-21 16:03:47 +03:00
5eb98c399a Кнопка create_task открывает CreateTaskDialog вместо несуществующего маршрута 2026-08-21 14:00:39 +03:00
e24df563df Добавлен выбор режима условия для table-полей в переходах: по значению или пользователь из колонки 2026-08-20 15:11:27 +03:00
47869971e6 feat: объединение страниц профиля — /profile рендерит карточку пользователя
- /profile теперь обёртка MyProfilePage над UserProfilePage (один экран для своего и чужого профиля)
- self-вкладки из ProfileSettings перенесены: Уведомления, Offline, Интерфейс, Безопасность (components/profile/*)
- ProfileSettings.tsx удалён
- админ видит вкладки Уведомления и Offline на чужой карточке с данными целевого пользователя
  (userId-параметр в GET/POST /api/subscriptions, PATCH/DELETE по владельцу, GET /api/sync/config?userId=; проверка canManageUser)
- Роль/Активен/Статус disabled для не-админа (сервер их и раньше игнорировал)
- пункт меню «Настройки профиля» переименован в «Мой профиль»
2026-08-05 11:48:07 +03:00
667bddeac9 feat: замещение пользователей (substitution) — заместители по умолчанию и по формам, контур ознакомления, inbox reasons
- таблица user_delegations (миграция 0067) + колонки delegated_from_user_id/pending_review в task_assignees
- delegation.service: резолвер с цепочкой и защитой от циклов, bulk-до-назначение чанками, чистка истёкших замещений
- центральный хук в addTaskAssignee: заместитель добавляется при любом назначении (ручном, автопереходе, user-поле, MCP)
- контур ознакомления: после перехода отсутствующий остаётся в исполнителях с pending_review, снимается кнопкой «Ознакомлен»
- inbox reasons delegation/delegation_review + фильтр «Замещение» на главной
- блок «Замещение» в профиле пользователя, бейдж «за <имя>» и баннер ознакомления в карточке задачи
2026-08-05 10:44:55 +03:00
17a8dc42f2 fix(ui): второй пакет ревью better-interface — каркас, чат, реестр, настройки
HIGH:
- chat: действия над сообщением доступны на мобильном (меню ⋯)
- iOS-зум: базовые input/textarea text-base, auth-экраны 16px
- контент не перекрыт нижней навигацией на iPhone (safe-area)
- контрасты: billing-оверлей, бот-кнопка, заголовки задач (text-primary)
- клавиатура: входящие на Главной, aria-label нижней навигации, триггер чата button
- confirm() → AlertDialog (сайдбар, чат, настройки)
- счётчики непрочитанных 7-8px → 10px

MEDIUM:
- офлайн-баннеры и бейджи на токенах warning/success/info/destructive
- transition-all → точечные свойства в примитивах ui
- шрифты: Inter без дублей (24 семейства → 2), letter-spacing с body убран
- prefers-reduced-motion kill-switch
- autocomplete + aria на auth/профиле, ошибки пароля у поля
- SPA: document.title + фокус на main при навигации, тост с action без таймера
- FormEditor: превью на Dialog, табы скроллятся на мобильном, без инлайн-стилей
- empty states с запросом и «Сбросить фильтры», UX-тексты
2026-08-04 19:20:59 +03:00
7d975b0b00 fix(ui): пакет фиксов по ревью better-interface (HIGH+MEDIUM)
HIGH:
- mobile: поля задачи доступны для форм без вкладок (fallback-аккордеон)
- удаление вложений доступно на тач-устройствах (кнопка всегда видна)
- бейдж статуса: контрастный текст по яркости (statusColor.ts), также в реестре и канбане
- кнопки согласования: контрастные дефолты #15803d/#b91c1c + текст по яркости
- клавиатура: focus-visible у карандаша, focus-ring у поиска, InlineField с клавиатуры

MEDIUM:
- iOS: инпуты text-base на мобильном (убран зум при фокусе)
- системные поля унифицированы с кастомными (inline label+value)
- тач-таргеты ≥32px, кнопка удаления задачи отделена ms-auto
- токены --warning/--success/--info во всех скинах, хардкод-цвета → семантика
- заголовок задачи крупнее + title с полным текстом; мелкий текст ≥11px
- UX-тексты: «Не удалось …» вместо «Ошибка», имена вместо ID
- button.tsx: без transition-all, глобальный active:scale-[0.96]
- ARIA: aria-label инпутам, role=alert ошибкам, Escape в dropdown
2026-08-04 09:36:13 +03:00
d562735eca fix(TaskDetail): фиксы per-field редактирования по тестам прода
- server: rich-text/company/task разрешены в PATCH field-values (была 400, поля не сохранялись)
- user-поле: дропдаун открывается сразу при редактировании, текущее значение всегда в списке
- select.tsx: viewport max-h-60 вместо высоты триггера (список показывал 1 пункт)
- плотность строк: min-h 28/36px, leading-5, read-only системные строки — py-1 как раньше
- вход в редактирование: double-click/double-tap (одиночный клик — только карандаш)
- textarea/table/task/company: компактная ширина редакторов, h-7
- сброс pendingAutofillRef при отмене; нативный select не отменяется по blur
2026-08-03 22:20:30 +03:00
8a8c798eb7 feat(TaskDetail): per-field inline-редактирование вместо глобального режима
- Клик по полю редактирует только его; автосохранение по blur/Enter/выбору, Esc — отмена
- Одиночный PATCH /api/tasks/:id/field-values/:fieldId + optimistic-кэш + офлайн-очередь
- Строка поля: фиксированные метрики read=edit (min-h 32/40px), редактор в потоке — ноль layout shift
- Удалены глобальный edit-режим, draft-машинерия, batch-сохранение и StickyActionBar
- Удалён мёртвый код components/task-detail/ (NotionFieldRow, useInlineEdit, useDirtyFields)
- Новый редактор checklist; составные редакторы сохраняют по закрытию
- Полировка: hover-подсветка, карандаш по hover, fade-in, семантические токены, тач-таргеты 40px
2026-08-03 17:17:59 +03:00
9a387c5db0 fix: бесконечный ретрай upload 400, скобки в именах файлов, тост batch-create
- useOfflineSync: tryUploadFile/trySendAttachmentMessage бросали ошибку без
  кода статуса — постоянная 400 не распознавалась regex \b400\b и вложение
  ретраилось бесконечно (спам POST /api/upload каждые ~30 сек).
- validateFilename: разрешены скобки () в именах (типично для фото с
  телефонов; сохраняемое имя всё равно генерируется), в текст 400 добавлено
  само имя файла для диагностики.
- BatchCreateDialog: тост ошибки показывает текст сервера (из BadRequestError
  или JSON в message 5xx) вместо общего «Ошибка создания задач».
2026-08-03 15:25:11 +03:00
1d5321ed0c feat: чанкинг batch-create >100 задач + журнал ошибок API
B: BatchCreateDialog режет список на чанки ≤100 (лимит сервера), каждый
чанк со своим idempotency-key (requestId-N) — повтор после ошибки не
создаёт дублей; 10-минутный лок армируется только при полном успехе,
а не до запроса (раньше блокировал даже после 400).

D: таблица error_logs (миграция 0066), захват ответов >=400 в request
middleware (без 401/health/events, дедуп 60с), admin API GET/DELETE
/api/error-logs и вкладка «Журнал ошибок» в Настройках.
2026-08-03 14:55:29 +03:00
1bb6a53226 feat: закрытые задачи в глобальном поиске зачёркнуты + бейдж статуса
searchTasksByKeyword теперь возвращает isCompleted и через leftJoin
formStatuses — statusName/statusColor/statusIsFinal. В HomeGlobalSearch
закрытые задачи (isCompleted || statusIsFinal) зачёркнуты и приглушены,
у каждой задачи цветной бейдж текущего статуса.
2026-08-03 13:29:36 +03:00
4ace1369ca fix: согласующие перехода — только авторизация, без автоназначения
assigneeUserId/assigneeConditions перехода раньше и давали право нажать
кнопку, и молча переназначали задачу на согласующего; кликнувший также
всегда добавлялся в task_assignees (список «Ответственный»).
Теперь ответственный при переходе всегда сохраняется, кликнувший в
ответственные не добавляется (доступ трекается через recordTransitionAccess).
В FormEditor добавлена подсказка о семантике блока «Согласующие».
2026-08-03 11:18:14 +03:00
a701b06394 fix: явный flex-row для горизонтального расположения бейджей 2026-07-24 16:35:18 +03:00
fd8d27e3d2 fix: поле 200px, бейджи в отдельном flex-контейнере рядом 2026-07-24 16:25:45 +03:00
e5f8dbce42 fix: ограничена максимальная ширина поля справочника для размещения бейджей рядом 2026-07-24 16:13:40 +03:00
d72cdc8af1 fix: адаптивная ширина поля справочника, бейджи рядом 2026-07-24 15:53:04 +03:00
a969af9086 fix: w-auto контейнер для компактного отображения поля и бейджей 2026-07-24 15:37:48 +03:00
0c5e95a201 fix: inline-flex контейнер для компактного отображения поля и бейджей 2026-07-24 15:20:34 +03:00
b08b906222 fix: фиксированная ширина поля справочника 200px, бейджи рядом 2026-07-24 15:04:33 +03:00
1a89ab50ef fix: поле справочника не растягивается на всю ширину, бейджи рядом 2026-07-24 14:45:45 +03:00
031d477630 fix: выбранные позиции справочника отображаются горизонтально рядом с полем 2026-07-24 14:14:56 +03:00
b4bded2ffb feat: триггер schedule для автоматизаций — ежедневный запуск по МСК
- планировщик server/workers/automation-scheduler.ts (тик 60 сек, все организации)
- защита от дублей: automations.last_scheduled_run_at (миграция 0065), catch-up в пределах суток
- UI: выбор триггера 'По расписанию' и времени запуска в Automations.tsx
- MCP: create_automation/update_automation принимают trigger 'schedule'
- triggerData: { trigger: 'schedule', scheduledAt }
2026-07-24 13:52:03 +03:00
59079992dc Фикс предпросмотра файлов с абсолютными self-URL
- extractFileKey понимает абсолютные URL (по pathname) — превью работает для уже записанных файлов
- normalizeFileUrl: абсолютные self-URL нормализуются в относительные при записи file-полей (REST field-values, MCP update_task_fields/upload-инструменты, bot-api, create task)
2026-07-24 11:10:55 +03:00
b3818852df UI: API/MCP-доступ в карточке бота, legacy-ключи в Settings, бот и канал в истории (этап 3)
- ApiScopesEditor — общий редактор скоупов (режим + формы/справочники)
- Bots.tsx: секция «Доступ к API и MCP» при создании и в настройках бота, показ ключа один раз, перевыпуск с подтверждением
- Settings.tsx: управление ключами убрано, read-only список legacy-ключей
- TaskHistory/TaskDetail: иконка бота + бейдж канала MCP/API у записей аудита
- GET /api/bots/:id возвращает apiKey
2026-07-22 15:35:34 +03:00
52bec07413 fix: отображение множественного выбора справочника + переименование типа в Справочник 2026-07-22 11:53:05 +03:00
a7733b4a03 Права доступа API-ключей: скоупы read/write/full и выборочный доступ к формам и справочникам
- organization_api_keys.scopes (jsonb, NULL = полный доступ для legacy-ключей)
- MCP: фильтрация инструментов по режиму и проверка formIds в handler'ах
- PATCH /api/mcp-keys/:id, валидация скоупов в server/utils/api-key.ts
- UI Settings: диалог создания/редактирования ключа с режимом и мультивыбором форм/справочников
2026-07-21 16:12:55 +03:00
08b0979ca2 feat: группа без детей с пустым отображением становится конечной строкой в дереве 2026-07-21 15:17:38 +03:00
9e1612c4c3 fix: отображение последнего заполненного значения в дереве справочника 2026-07-21 15:00:17 +03:00
dee9ae7ad6 feat: автоматический выбор подсправочника по привязке к строке родителя 2026-07-21 14:24:35 +03:00
2e1652e7ee feat: подсправочник показывается целиком при выборе привязанной строки 2026-07-21 12:01:07 +03:00
b086ff4513 fix: валидация пустых parentRowIds в редакторе подсправочника 2026-07-21 11:21:32 +03:00
9edd90211f feat: привязка подсправочника к строкам родителя (parentRowIds) 2026-07-21 10:43:28 +03:00
eff91bffad fix: прокрутка колёсиком и tooltip для длинных названий в поле справочника 2026-07-20 22:27:12 +03:00
7cf5ffff9a feat: многоуровневое дерево справочника и настраиваемое отображение колонок 2026-07-20 21:59:36 +03:00
9fff937209 fix: горизонтальная раскладка GeoField/ContactField и убран max-width у обёрток в TaskDetail 2026-07-20 11:32:26 +03:00
219c7a6203 fix(ui): блочные редакторы geo/contact в потоке вместо строгого оверлея
- в режиме редактирования карточки задачи редакторы geo (~90px) и contact
  (~300px) переполняли inset-0 оверлей поверх однострочного read-view (~28px)
  и наезжали на соседние поля (форма «Объект», «Наши Юрики»)
- теперь для типов geo/contact редактор рендерится в потоке, строка растёт
  до высоты редактора; остальные типы — без изменений
2026-07-18 11:55:32 +03:00
8b607e7156 feat(skins): улучшен Twenty-скин по референсу twentyhq/twenty
- Обновлены цвета Twenty light/dark ближе к оригиналу (display-p3 → sRGB).
- Темная тема: фон #101010, карточки #141414, границы #1c1c1c, primary #3c63de.
- Добавлены токены: backgroundQuaternary, прозрачные фоны danger/blue/orange/success,
  overlay-фоны, blur-эффекты, box-shadow underline/super-heavy.
- Добавлены радиусы: xxl, pill, rounded, smRound, mdRound.
- Добавлены line-height токены.
- Все встроенные скины (iistwin, omegaprom) приведены к новой схеме токенов.
- Tailwind config расширен новыми utility-классами.
- Перегенерирован generated-skins.css.
2026-07-17 18:41:23 +03:00
240dcd2f7e fix(TaskDetail): system fields layout and ContractNumberField wrapper
- Increase system field label width w-22 -> w-24, add text-[11px]
- Increase system field row spacing gap-1 -> gap-1.5, py-0.5 -> py-1
- Fix ContractNumberField wrapper to flex items-center gap-1.5
- Fix FieldValueRow flex-wrap -> flex-nowrap, add text-[13px] to label
2026-07-17 18:24:35 +03:00
9f1c2e5b45 perf(vpn-bot): фоновая подготовка подписки, оптимизация запросов, анимация кнопок
- validateTelemostRoom: таймаут 3 сек + кэш 10 мин
- createVpnTask: транзакция + batch insert field values
- prepareVpnSubscription: валидация и создание подписки в фоне при получении ссылки
- sendVpnBotMessage: кэш botId, Promise.all для enrich/members/orgMap
- processPlatformSelection: одно сообщение с файлом и подпиской вместо двух
- Chat.tsx: нажатая кнопка становится зелёной галочкой, остальные disabled
2026-07-17 12:38:33 +03:00
6bb89b4cf8 feat(chat): typing indicator для ботов, кнопки ботов в мессенджере, VPN-бот с кнопками
- Добавлены SSE-события conv_typing_started/stopped и их обработка в Chat.tsx
- AI-бот публикует typing events перед/после генерации ответа
- Боты могут отправлять сообщения с кнопками через /api/bot/conversations/:id/messages
- Добавлен callback /api/messenger/messages/:id/callback для нажатий кнопок
- VPN-бот использует кнопки Android/iOS вместо текстового prompt
- Оптимистичное обновление unread count, ускоренный reportActiveChat, polling fallback,
  логирование SSE, push suppression для bot_direct
2026-07-17 11:25:25 +03:00
7672dd98df fix(chat): подавлять push-уведомления при открытом активном чате и автоотметка прочтения в task chat
- Добавлены active_chat_* поля в user_presence и endpoint /api/devices/active-chat

- Сервер не шлёт Web Push/Pushy, если получатель смотрит в тот же чат на видимой вкладке

- Клиент сообщает серверу и Service Worker об активном чате из Chat.tsx и TaskChat.tsx

- TaskChat: входящие сообщения автоматически отмечаются прочитанными при видимой вкладке

- SW: подавляет foreground/system push, если активный чат совпадает
2026-07-16 18:59:00 +03:00
63c83a059d fix(contract-number): сделать mode controlled, исправить редактирование шифра заказчика
- Убран локальный useState mode; режим всегда берется из value.
- Добавлена синхронизация customerInput с внешним value.
- При переключении на 'Мой номер' value сбрасывается для генерации номера.
- При переключении на 'Номер заказчика' используется локальный шифр.
2026-07-16 16:34:25 +03:00
1e0f811f11 fix(contract-number): локальный mode и отдельный customerInput без сброса value 2026-07-16 15:54:56 +03:00
45475691cc fix(contract-number): isGenerated не блокирует редактирование Switch и Select 2026-07-16 15:41:07 +03:00
ff74dd1852 Merge branch 'main' of https://github.com/iisultanov/iistwin 2026-07-16 15:22:48 +03:00