Commit Graph

282 Commits

Author SHA1 Message Date
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
b981614095 MCP: инструмент update_task_fields — обновление кастомных полей задачи
- Merge-семантика как POST /api/tasks/:id/field-values: upsert/delete, поля типа task пересоздают связи
- Аудит field.changed с актором ключа (бот + metadata.source='mcp'), side-эффекты: автопереходы, заголовок, кэши, SSE
- Доступен только в режиме full, как update_task
2026-07-23 16:31:45 +03:00
affbdeee1e Upload-тикеты: загрузка файлов через REST без знания API-ключа
- MCP create_upload_ticket → короткоживущий uploadUrl (10 мин, in-memory)
- POST /api/upload/ticket/:token — тот же пайплайн (processUploadRequest вынесен из /api/upload), авторизация тикетом, проверки скоупов
- get_api_guide: флоу без ключа — ticket → curl → привязка по fileUrl
2026-07-23 15:53:17 +03:00
af119d1cdc MCP: удалён base64-вариант загрузки файлов — только REST upload + привязка по fileUrl
- upload_file удалён; upload_task_file/upload_message_file/upload_directory_file/upload_table_row_file принимают только fileUrl (+fileName)
- descriptions указывают на REST POST /api/upload и get_api_guide
- server/services/file-upload.service.ts удалён (без base64 не используется)
2026-07-22 16:22:26 +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
8cfd49fd9f Атрибуция от бота в MCP/REST + REST API по ключу (этап 2)
- MCP: getActor (владелец ключа + бот), аудит changedByName=бот/label ключа, botId, metadata.source='mcp'; аудит для update_task/update_task_status
- sendTaskMessage: botId (messageType 'bot'), починен путь isBotToken без req.user
- authenticateTokenOrApiKey: JWT или X-Api-Key с белым списком endpoint'ов (/api/upload, messages, field-values, create task), проверки скоупов, аудит source='api'
- Лимиты файлов через env: UPLOAD_IMAGE_MAX_MB=25, UPLOAD_DOC_MAX_MB=100, UPLOAD_MAX_MB=100
- MCP upload-инструменты: параметр fileUrl для привязки уже загруженного файла; новый инструмент get_api_guide
2026-07-22 15:18:04 +03:00
68153caef2 API-ключи привязаны к ботам 1:1 (этап 1)
- Миграция 0064: organization_api_keys.bot_id (unique partial), task_audit_log.bot_id, file_uploads.bot_id
- POST/PUT /api/bots: apiAccess {enabled, mode, formIds, tableIds} — ключ создаётся/обновляется/деактивируется вместе с ботом, сырой ключ показывается один раз
- POST /api/bots/:id/api-key/regenerate; GET /api/bots возвращает apiKey summary
2026-07-22 14:42:32 +03:00
1fae441a09 Безопасность: bot-токены выделены в отдельный тип bot_login (этап 0)
- POST /api/bot/auth/login выдаёт bot_login/bot_login_refresh (audience workflow-bots, TTL 30d/90d)
- authenticateBot принимает bot_login и bot_service
- authenticateToken/authenticateFileToken отклоняют bot-токены (401) — закрыта коллизия bot.id с user.id
2026-07-22 14:32:11 +03:00
72de9a25fb fix: шаблон названия резолвит массив id справочника в отображаемые значения 2026-07-22 14:04:39 +03:00
52bec07413 fix: отображение множественного выбора справочника + переименование типа в Справочник 2026-07-22 11:53:05 +03:00
936bce2ba9 MCP: загрузка файлов (base64) в file-поля, комментарии, справочники и таб-таблицы задач
- server/services/file-upload.service.ts: uploadFileFromBase64 (whitelist расширений, magic bytes, лимиты 10/50 МБ, S3/MinIO или локальный диск, запись file_uploads)
- Инструменты (write/full): upload_file, upload_task_file, upload_message_file, upload_directory_file, upload_table_row_file
- Проверки доступа isFormAllowed/isTableAllowed
2026-07-22 11:28:45 +03:00
25f84ee532 MCP: напоминания, уведомления, inbox, агрегации, update_form, дерево задач, поля пользователей, DaData — этап 3
- read: list_task_reminders, list_notifications, get_inbox, aggregate_tasks, get_task_tree, get_user_field_values, dadata_suggest
- write: set_task_reminder, send_notification, mark_notifications_read
- full: delete_task_reminder, update_form, set_user_field_value
2026-07-21 17:30:50 +03:00
05e09fa08b MCP: сообщения задач, исполнители, документы, файлы, аудит — этап 2
- list_task_messages, get_task_assignees, list_document_templates, get_task_file, get_task_audit_log (read)
- send_task_message, generate_document (write); set_task_assignees (full)
- Логика POST /api/tasks/:id/messages вынесена в server/services/task-message.service.ts (переиспользуется route и MCP)
- get_task_file: нативный S3 presigned URL или локальный путь с пояснением
2026-07-21 17:19:22 +03:00
002ce152be MCP: инструменты справочников (data tables) — этап 1
- 15 инструментов: list/get_directory, list_directory_rows (flat/tree), get_directory_row, get_directory_column_values (read); create/bulk_create_directory_row (write); create/update/delete_directory, update/delete/move_directory_row, link/unlink_directories (full)
- Объектные проверки isTableAllowed по scopes.tableIds
- Логика дерева строк вынесена в server/utils/data-table-tree.ts (переиспользуется REST-эндпоинтом и MCP)
- bulkCreateDataTableRows: поддержка parentId и position
2026-07-21 17:02:04 +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
e2f8a41029 fix: надёжное удаление контейнеров в автодеплое 2026-07-21 11:09:53 +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
aea0e9c3fe feat(vpn): монитор актуальности Яндекс Телемост + инструкция про выход из встречи
- INSTRUCTIONS_TEXT: добавлено требование выйти из встречи, а не завершать её
- vpn.db.ts: findAllActiveVpnTasks для поиска активных VPN-задач
- vpn.service.ts: checkVpnRoomsValidity — периодическая проверка комнат, concurrency=5
- vpn-bot.service.ts: findVpnBotConversationId и notifyVpnRoomExpired
- server/index.ts: worker каждые 6 часов, уведомление пользователю о протухшей ссылке
2026-07-17 13:08:24 +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
586a591773 fix(vpn): восстановление VPN-модуля после затирания chat/push fix'ом
- Добавлена ветка bot.type === 'vpn' в messenger.messages.routes.ts
- Добавлен полный модуль server/vpn/ (routes, service, db, bot, config)
- Подключены VPN-маршруты в server/routes/index.ts
- Добавлена раздача /apps статики и COPY в Dockerfile
- apps/ пока содержит .gitkeep и README; APK/IPA нужно добавить отдельно
2026-07-17 09:32:43 +03:00
0a5f4516ef fix(push.routes): req.user!.userId -> req.user!.id
У объекта пользователя из authenticateToken поле id, а не userId.

Это чинит 500 на /api/devices/active-chat и других device-эндпоинтах.
2026-07-16 20:42:55 +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
509eb05c0b fix(contract-number): input шифра заказчика снова редактируемый
- Убрано локальное состояние customerValue, теперь значение берётся напрямую из parsed.value

- Убран лишний useEffect, который мог сбрасывать ввод при глобальном редактировании

- Состояние mode продолжает синхронизироваться с value prop
2026-07-16 15:21:50 +03:00
iisultanov
c76649b79f fix(TaskDetail): inline editors horizontal alignment
- inputClass: w-full → w-auto (prevents input from wrapping below label)
- textareaClass: flex-1 → w-auto min-w-[200px]
- Increases max-w from 280px to 320px for longer values
- Fixes text/select inputs appearing on new line instead of inline with label
2026-07-15 22:22:47 +03:00
iisultanov
c4421702b8 fix(ContractNumberField): wider select, prevent text truncation
- compact: max-w-[180px] → w-auto (fit content)
- SelectTrigger: + w-auto min-w-0 (shrink to fit)
- Preview: + whitespace-nowrap, w-auto
- flex-wrap → flex-nowrap (prevent line breaks)
- Switch: scale-75 → scale-[0.65] (more compact)
- Fixes '#8 ООО...' truncation and label wrapping
2026-07-15 22:22:28 +03:00
iisultanov
d3b1869612 fix(ContractNumberField): clean up compact inline layout
- Hide 'Номер заказчика' label in compact mode (only switch shown)
- Shrink switch to scale-75 in compact mode
- Shorten placeholders: 'Юрлицо' / 'Шифр'
- Reduce min-widths: select 180px, input 160px, preview 180px
- Use gap-1.5 instead of space-x-2 in preview block
- Fixes cluttered inline edit appearance next to field label
2026-07-15 22:12:37 +03:00
iisultanov
807c2c8680 fix(FieldOverlay): vertically center editor content
- add flex items-center to fitContainer overlay
- fixes editor appearing at top edge instead of centering on field label
2026-07-15 21:42:39 +03:00
iisultanov
dfdcd4c160 fix(ContractNumberField): fallback to current value on preview error
- catch block: use parsed.value as fallback instead of empty string
- remove error display in UI — show current value instead
- add parsed.value as fallback before 'Select legal entity' message
- fixes 'Не удалось загрузить номер' on first edit
2026-07-15 21:42:15 +03:00
agent
f59409fba1 fix: restore original flex layout in FieldValueRow
- Revert NotionFieldRow grid layout back to original flex layout
- Keep StickyActionBar at bottom (not top)
- Add pencil icon on hover in left column
- Keep all original overlay logic (wide overlay for contract-number, date+prolongation)
- Preserve inline horizontal layout for extra elements (checkbox, calendar icon)

Fixes: vertical stacking of extra elements, misaligned fields
2026-07-16 01:38:29 +08:00
agent
2331dc00a5 ui: Notion-style inline editing for task detail fields
- Add useInlineEdit hook for per-field editing (double-click to edit)
- Add useDirtyFields hook for tracking unsaved changes
- Add NotionFieldRow component with CSS Grid layout (140px label + 1fr value)
- Add StickyActionBar component (fixed bottom bar with Save/Cancel)
- Remove editModeBar from top (was shifting content down)
- Replace field flex layout with notion-field-row grid
- Add unified input styles (h-8, centered text) in CSS
- Add safe-area-bottom for iOS PWA
- Buttons now appear at bottom only when fields are dirty

Refs: TaskTitan CRM UI refactor
2026-07-16 01:22:56 +08:00
a4a3a9ca18 fix(ui): синхронизация contract-number и горизонтальная дата
- ContractNumberField: mode и customerValue теперь синхронизируются с value prop через useEffect

- TaskDetail: date/datetime input используют w-auto, чтобы чекбокс автопролонгации шёл в одну строку
2026-07-15 17:22:37 +03:00
0ea3d8c49e fix(ui): оверлей inline-редактора растягивается по content
- FieldOverlay: при fitOverlay=false добавлен w-max, чтобы оверлей растягивался по ширине редактора, а не обрезался по read-view

- TaskDetail: date/datetime с автопролонгацией используют fitOverlay=false и overlayMinWidth=280
2026-07-15 16:58:37 +03:00
9e388fb644 fix(ui): горизонтальное расположение подполей в inline-редакторе
- ContractNumberField compact: переключатель, select юрлица и input/preview в одну строку

- TaskDetail: date/datetime с автопролонгацией — input и чекбокс в одну строку

- Увеличена max-width обёртки contract-number до 640px
2026-07-15 16:46:48 +03:00
2b3a9f768b fix(ui): плоский inline-оверлей и компактный редактор номера договора
- FieldOverlay: border-input, shadow-sm, убран overflow-hidden по умолчанию

- TaskDetail: input-редакторы h-7 leading-6, для contract-number fitOverlay=false

- ContractNumberField: добавлен compact-режим, подполя не обрезаются

- Создание задачи оставлено с вертикальным layout
2026-07-15 15:38:22 +03:00