АРХ - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: roadmap двусторонней доски внешних контуров
This commit is contained in:
+148
@@ -0,0 +1,148 @@
|
||||
# Шаг 11. Единый shell карточки внешнего контура
|
||||
|
||||
## Зачем нужен этот шаг
|
||||
|
||||
Сейчас карточка деталей во `Внешних контурах` решает прикладную задачу, но UX-паттерн у нее другой, чем во `Внутреннем контуре`.
|
||||
|
||||
Из-за этого:
|
||||
- у пользователя ломается ожидаемая логика открытия карточки
|
||||
- верхний action-bar живет по другим правилам
|
||||
- повторяется UI-логика, которая уже есть у стандартного peek-shell
|
||||
- дальнейшее развитие `Внешних контуров` начинает расходиться с остальным продуктом
|
||||
|
||||
Следующий шаг должен выровнять не данные, а каркас взаимодействия.
|
||||
|
||||
## Целевой результат
|
||||
|
||||
По клику на карточку во `Внешних контурах` пользователь получает тот же класс панели, что и во `Внутреннем контуре`:
|
||||
- закрытие просмотра
|
||||
- полноэкранный режим
|
||||
- переключение макета
|
||||
- подписка или отписка
|
||||
- копирование ссылки
|
||||
- меню дополнительных действий
|
||||
|
||||
При этом тело карточки остается отдельным и специфичным для `Внешних контуров`.
|
||||
|
||||
## Что обязательно сохраняем
|
||||
|
||||
Карточка внешнего контура не должна деградировать до обычной карточки `Issue`.
|
||||
|
||||
Нужно сохранить:
|
||||
- source-side режим без обязательного membership в target project
|
||||
- блок `Маршрутизация`
|
||||
- зеркалирование комментариев, вложений и activity
|
||||
- внешний lifecycle `Принять / Отклонить / Ответ во внешний контур`
|
||||
- правила доступа, отличающиеся от обычного внутреннего рабочего элемента
|
||||
|
||||
Иначе мы потеряем главный смысл модуля.
|
||||
|
||||
## Что меняем
|
||||
|
||||
Меняем только shell и верхний UX-паттерн:
|
||||
- каркас панели
|
||||
- поведение открытия и закрытия
|
||||
- поведение полноэкранного режима
|
||||
- верхний блок действий
|
||||
- раскладку заголовка и служебных controls
|
||||
|
||||
То есть цель шага — унификация оболочки, а не унификация доменной модели.
|
||||
|
||||
## Что не входит
|
||||
|
||||
В этот шаг не входят:
|
||||
- новые колонки `Исходящие / Входящие`
|
||||
- drag-and-drop
|
||||
- пользовательские кастомные представления
|
||||
- перенос всех операций внешнего контура на стандартные issue services
|
||||
- удаление запроса как обязательное действие из header action set
|
||||
|
||||
## Архитектурный принцип
|
||||
|
||||
Нельзя копировать целиком реализацию `peek overview` внутреннего контура и натягивать ее поверх внешней сущности.
|
||||
|
||||
Правильный путь:
|
||||
- переиспользовать shell-контракт
|
||||
- переиспользовать header action pattern
|
||||
- оставить внешний data-flow отдельным
|
||||
- оставить body карточки отдельным
|
||||
|
||||
То есть нужен не clone существующей карточки, а повторное использование общего слоя представления.
|
||||
|
||||
## Рекомендуемое разбиение реализации
|
||||
|
||||
### 1. Общий слой shell
|
||||
|
||||
Нужен общий контракт боковой карточки, который умеет:
|
||||
- sidebar-режим
|
||||
- full-screen режим
|
||||
- общий overlay и поведение закрытия
|
||||
- общий header slot
|
||||
- общий body slot
|
||||
|
||||
### 2. Отдельный adapter для `Внешних контуров`
|
||||
|
||||
Нужен внешний adapter, который подает в shell:
|
||||
- title
|
||||
- служебные действия
|
||||
- доступные действия меню
|
||||
- состояние source-only или target-access
|
||||
- body контент внешнего контура
|
||||
|
||||
### 3. Отдельный action set
|
||||
|
||||
Нельзя слепо использовать меню обычной задачи.
|
||||
|
||||
Нужно отдельное правило доступных действий для внешнего контура:
|
||||
- закрыть
|
||||
- fullscreen
|
||||
- layout toggle
|
||||
- subscribe/unsubscribe
|
||||
- copy link
|
||||
- `...`
|
||||
|
||||
При этом `...` для внешнего контура должен быть ограничен собственным набором действий и не обязан повторять delete-flow внутреннего рабочего элемента.
|
||||
|
||||
## Риски, которые надо избежать
|
||||
|
||||
### 1. Смешение доменных сущностей
|
||||
|
||||
Если внешний запрос начать вести как обычный `Issue`, то быстро сломаются:
|
||||
- source-side права
|
||||
- логика bridge
|
||||
- роутинг действий `Принять / Отклонить`
|
||||
- зеркальная история
|
||||
|
||||
### 2. Дублирование shell-кода
|
||||
|
||||
Если сделать второй независимый peek-shell только для `Внешних контуров`, то дальше появятся:
|
||||
- рассинхрон верхних action-bar
|
||||
- повторная поддержка полноэкранного режима
|
||||
- повторная поддержка keyboard и close behavior
|
||||
|
||||
### 3. Преждевременная универсальная платформа
|
||||
|
||||
Не нужно ради одного шага строить абстрактный UI-framework на все возможные будущие сущности.
|
||||
|
||||
Нужен только тот общий контракт, который уже доказан двумя режимами:
|
||||
- `Внутренний контур`
|
||||
- `Внешние контуры`
|
||||
|
||||
## Критерий приемки
|
||||
|
||||
- карточка `Внешних контуров` открывается по тому же UX-паттерну, что и во `Внутреннем контуре`
|
||||
- верхняя панель действий выглядит и ведет себя единообразно
|
||||
- body карточки остается внешнеконтурным
|
||||
- source-only сценарий не ломается
|
||||
- без прямого доступа в target project пользователь все равно видит рабочую карточку
|
||||
|
||||
## Зависимость следующего шага
|
||||
|
||||
Этот шаг желательно сделать до полной двусторонней доски.
|
||||
|
||||
Причина простая:
|
||||
- доска `Исходящие / Входящие` увеличит число точек входа в карточку
|
||||
- если shell не унифицирован заранее, новый board-layer закрепит текущую раздвоенную архитектуру
|
||||
|
||||
Следующий связанный шаг описан в:
|
||||
- [12_STEP_external-contours-bidirectional-board.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/12_STEP_external-contours-bidirectional-board.md)
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
# Шаг 12. Двусторонняя доска внешних контуров
|
||||
|
||||
## Главная продуктовая задача
|
||||
|
||||
Во `Внешних контурах` пользователь должен видеть не только прилетевшие или уже принятые задачи, но и те запросы, которые его проект сам отправил в другие контуры.
|
||||
|
||||
Без этого теряется управляемость:
|
||||
- пользователь отправляет запрос
|
||||
- но не может нормально наблюдать его как отдельную рабочую сущность
|
||||
- и не получает полноценный рабочий экран для исходящих запросов
|
||||
|
||||
Поэтому следующий обязательный этап — двусторонняя доска.
|
||||
|
||||
## Обязательный состав первой версии
|
||||
|
||||
В первой версии должны быть только две системные зоны:
|
||||
- `Исходящие`
|
||||
- `Входящие`
|
||||
|
||||
Это фиксированные рабочие представления, а не свободный конструктор колонок.
|
||||
|
||||
## Что означает каждая зона
|
||||
|
||||
### Исходящие
|
||||
|
||||
Запросы, которые текущий проект отправил в другие контуры.
|
||||
|
||||
Для них пользователь должен видеть:
|
||||
- текущий статус исполнения
|
||||
- целевой контур
|
||||
- назначенного
|
||||
- последнее изменение
|
||||
- признаки новых изменений
|
||||
|
||||
### Входящие
|
||||
|
||||
Запросы, которые пришли в текущий проект из других контуров.
|
||||
|
||||
Они должны оставаться видимыми во `Внешних контурах` как отдельный контекст межконтурной работы, даже если фактическая работа по исполнению идет во `Внутреннем контуре`.
|
||||
|
||||
Это не отменяет текущий lifecycle появления задачи во `Внутреннем контуре`.
|
||||
|
||||
Наоборот, это добавляет отдельный рабочий слой наблюдения и управления межконтурным потоком.
|
||||
|
||||
## Обязательное ограничение
|
||||
|
||||
Во `Внешних контурах` нельзя реализовывать перетаскивание карточек между блоками.
|
||||
|
||||
Причина:
|
||||
- блоки здесь не равны стадиям workflow
|
||||
- это не kanban статусов
|
||||
- это представления по направлению и фильтрам
|
||||
|
||||
Следовательно:
|
||||
- никаких drag-and-drop переходов между `Исходящими` и `Входящими`
|
||||
- никаких попыток “перетащить” запрос в другой блок как способ смены состояния
|
||||
|
||||
Смена состояния остается доменной операцией, а не визуальным переносом.
|
||||
|
||||
## Требования к фильтрации
|
||||
|
||||
Обе системные зоны должны поддерживать гибкую фильтрацию по аналогии с `Внутренним контуром`.
|
||||
|
||||
Минимально нужно уметь фильтровать:
|
||||
- по пользователям
|
||||
- по назначенным
|
||||
- по автору
|
||||
- по статусам
|
||||
- по связанным контурам или проектам
|
||||
- по приоритету
|
||||
- по срокам и датам
|
||||
|
||||
Если часть фильтров недоступна на первой итерации из-за backend-модели, это нужно закрывать адаптером или агрегированным endpoint, а не урезать целевой продуктовый контракт.
|
||||
|
||||
## Текущее архитектурное препятствие
|
||||
|
||||
На сегодня `Исходящие` и `Входящие` живут в разных подсистемах:
|
||||
- source-side отправленные запросы приходят из модуля `external-contours`
|
||||
- входящие рабочие объекты и bridge-история живут вокруг `intake` и связанной target issue
|
||||
|
||||
Поэтому полноценная двусторонняя доска не собирается простым склеиванием текущего UI.
|
||||
|
||||
Нужен единый слой представления данных.
|
||||
|
||||
## Рекомендуемое архитектурное решение
|
||||
|
||||
### 1. Не собирать эту доску фронтовыми хаками
|
||||
|
||||
Можно временно склеить две разные выдачи на frontend, но это быстро упрется в:
|
||||
- сортировки
|
||||
- пагинацию
|
||||
- счетчики
|
||||
- консистентность фильтров
|
||||
- unread-индикаторы
|
||||
|
||||
Поэтому базовый путь должен вести к агрегированному data contract.
|
||||
|
||||
### 2. Ввести единый board-level view model
|
||||
|
||||
Нужна единая проекция, условно:
|
||||
- `direction`
|
||||
- `source_project`
|
||||
- `target_project`
|
||||
- `status`
|
||||
- `assignee`
|
||||
- `created_by`
|
||||
- `updated_at`
|
||||
- `unread`
|
||||
- `target_issue_id`
|
||||
- `external_request_id`
|
||||
|
||||
Этот view model не обязан ломать существующие доменные сущности.
|
||||
|
||||
Он нужен как стабильный контракт уровня доски.
|
||||
|
||||
### 3. Сделать board как фиксированные системные представления
|
||||
|
||||
Первая версия не должна строиться как свободный пользовательский конструктор.
|
||||
|
||||
Нужны два системных блока:
|
||||
- блок `Исходящие`
|
||||
- блок `Входящие`
|
||||
|
||||
И только поверх этого позже можно добавлять дополнительные пользовательские представления.
|
||||
|
||||
## Как не уйти в крайности
|
||||
|
||||
### Плохой путь 1
|
||||
|
||||
Сделать поверх текущего экрана несколько разрозненных переоберток и локальных фильтров.
|
||||
|
||||
Результат:
|
||||
- быстрое накопление технического долга
|
||||
- отсутствие общего контракта
|
||||
- трудная интеграция следующих board-type модулей
|
||||
|
||||
### Плохой путь 2
|
||||
|
||||
Остановить проект и начать строить универсальную платформу на все будущие доски сразу.
|
||||
|
||||
Результат:
|
||||
- высокий срок поставки
|
||||
- риск поломать текущий runtime
|
||||
- потеря фокуса на реальной продуктовой потребности
|
||||
|
||||
### Рабочий путь
|
||||
|
||||
Сделать ограниченный, но расширяемый board contract именно для межконтурных задач:
|
||||
- фиксированные системные зоны
|
||||
- единый тип board item
|
||||
- единый фильтровый слой
|
||||
- переиспользуемый detail-shell из шага 11
|
||||
|
||||
## Связь с будущими пользовательскими колонками
|
||||
|
||||
Пользовательские представления нужны, но не должны быть частью первой двусторонней доски.
|
||||
|
||||
Их нужно проектировать как следующий слой поверх уже введенного board contract:
|
||||
- пользователь создает свой блок
|
||||
- задает имя
|
||||
- задает фильтр
|
||||
- получает еще одно представление рядом с системными блоками
|
||||
|
||||
Но это именно представление.
|
||||
|
||||
Это не новая стадия исполнения и не область для drag-and-drop.
|
||||
|
||||
## Связь с будущими типами досок
|
||||
|
||||
Архитектура этого шага должна допускать расширение на:
|
||||
- агентные доски
|
||||
- специализированные operational boards
|
||||
- гибридные наблюдательные представления по нескольким контурам
|
||||
|
||||
Из этого следуют два правила:
|
||||
- доска должна собираться вокруг контракта представления, а не вокруг одной конкретной сущности `Issue`
|
||||
- колонка должна означать выборку или представление, а не обязательно статус workflow
|
||||
|
||||
## Критерий приемки
|
||||
|
||||
- пользователь видит во `Внешних контурах` две системные зоны: `Исходящие` и `Входящие`
|
||||
- отправленные запросы не теряются после отправки и остаются видимыми как рабочие объекты
|
||||
- обе зоны фильтруются через единый механизм
|
||||
- открытие карточки из любой зоны ведет в единый shell шага 11
|
||||
- между зонами нет drag-and-drop
|
||||
|
||||
## Что идет следующим шагом после этого
|
||||
|
||||
После стабилизации двусторонней доски можно переходить к пользовательским представлениям поверх того же контракта.
|
||||
|
||||
Но только после того, как:
|
||||
- подтверждена стабильность системных зон
|
||||
- подтверждена консистентность фильтров
|
||||
- подтверждена работа detail-shell в обоих направлениях
|
||||
|
||||
Связанный документ:
|
||||
- [11_STEP_external-contours-detail-shell.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/11_STEP_external-contours-detail-shell.md)
|
||||
@@ -0,0 +1,491 @@
|
||||
# Межпроектная маршрутизация задач
|
||||
|
||||
## Цель
|
||||
|
||||
Добавить в `NODE.DC TM` отдельный сценарий межпроектной постановки задач между контурами без перепрошивки штатного `Intake`.
|
||||
|
||||
Базовая идея:
|
||||
- `Рабочие элементы` переименовываются в `Внутренний контур`
|
||||
- рядом появляется новый модуль `Внешние контуры`
|
||||
- пользователь из проекта-источника создает внешний запрос
|
||||
- запрос уходит в целевой проект
|
||||
- в целевом проекте он становится обычной задачей
|
||||
- в проекте-источнике сохраняется видимый объект маршрутизации со статусом, историей и материалами
|
||||
|
||||
## Почему выбран именно этот путь
|
||||
|
||||
Не трогаем штатный `Intake` как пользовательский модуль.
|
||||
|
||||
Используем его только как внутренний backend-мост, потому что:
|
||||
- механизм уже умеет создавать bridge между `Issue` и `IntakeIssue`
|
||||
- уже есть переход из `TRIAGE` в default-state проекта
|
||||
- уже есть `extra JSON` для метаданных маршрутизации
|
||||
- это самый безопасный путь для форка и дальнейших обновлений
|
||||
|
||||
## Термины
|
||||
|
||||
### Внутренний контур
|
||||
|
||||
То, что сейчас в UI является обычными рабочими элементами проекта.
|
||||
|
||||
### Внешние контуры
|
||||
|
||||
Новый отдельный модуль проекта, через который задача отправляется в другой проект внутри того же workspace.
|
||||
|
||||
### Проект-источник
|
||||
|
||||
Проект, из которого инициируется запрос.
|
||||
|
||||
### Целевой проект
|
||||
|
||||
Проект, в котором задача реально исполняется.
|
||||
|
||||
### Исходная карточка внешнего контура
|
||||
|
||||
Карточка или запись в проекте-источнике, где инициатор видит:
|
||||
- текущий статус
|
||||
- целевой проект
|
||||
- назначенного исполнителя
|
||||
- историю обработки
|
||||
- файлы
|
||||
- уведомления о ходе работы
|
||||
|
||||
### Целевая задача
|
||||
|
||||
Обычная задача в целевом проекте, которая попадает в обычный workflow этого проекта.
|
||||
|
||||
## Ключевой продуктовый результат
|
||||
|
||||
Пользователь из `Менеджеры` должен иметь возможность:
|
||||
- открыть `Внешние контуры`
|
||||
- выбрать целевой проект, например `Бухгалтерия`
|
||||
- описать запрос
|
||||
- назначить исполнителя из `Бухгалтерия`
|
||||
- отправить запрос
|
||||
|
||||
После этого:
|
||||
- у `Бухгалтерия` появляется обычная задача в их проекте
|
||||
- у отправителя в `Менеджеры` появляется запись во `Внешних контурах`
|
||||
- у этой записи есть статусная пришлепка
|
||||
- при любом изменении статуса в целевом проекте статус в источнике обновляется
|
||||
- если в целевом проекте меняют описание, прикладывают файлы, комментируют или закрывают задачу, это отражается в источнике
|
||||
- инициатор получает уведомления о существенных изменениях
|
||||
|
||||
## Текущий статус реализации
|
||||
|
||||
На текущем этапе уже реализовано:
|
||||
- отдельный модуль `Внешние контуры`
|
||||
- отдельный backend endpoint маршрутизации
|
||||
- создание target issue в целевом проекте через intake bridge
|
||||
- немедленный перевод target issue в обычный workflow целевого проекта
|
||||
- source-side список отправленных запросов
|
||||
- source-side детальный экран на базе shell `Предложений`
|
||||
- status pill по фактическому состоянию target issue
|
||||
- workspace-wide выбор целевого внешнего контура по policy:
|
||||
- тот же `workspace`
|
||||
- у целевого проекта включен модуль
|
||||
- прямой membership в target project не требуется
|
||||
- source-side карточка как основная точка работы отправителя, если у него нет доступа в целевой проект
|
||||
- source-side редактирование открытого запроса:
|
||||
- `заголовок`
|
||||
- `описание`
|
||||
- source-side действия:
|
||||
- `Принять`
|
||||
- `Отклонить`
|
||||
- `Ответ во внешний контур`
|
||||
- зеркалирование из целевой задачи в source-side карточку:
|
||||
- комментарии
|
||||
- вложения
|
||||
- activity
|
||||
- обновления статуса
|
||||
- proxy download для вложений без прямого membership в target project
|
||||
- unread-индикатор новых изменений по source-side карточке
|
||||
- блок `Маршрутизация` в фиксированном формате `3 x 3`
|
||||
|
||||
## Freeze point на 2026-04-19
|
||||
|
||||
Текущий этап временно заморожен.
|
||||
|
||||
Заморозка делается после достижения рабочего вертикального среза:
|
||||
- запрос можно отправить из проекта-источника в другой проект того же `workspace`
|
||||
- в целевом проекте создается обычная задача и сразу попадает в обычный workflow
|
||||
- отправитель видит свой source-side список и карточку без обязательного доступа в чужой проект
|
||||
- в source-side карточке видны статус, маршрут, назначенный, срок, комментарии, вложения и activity из целевого контура
|
||||
- отправитель может поправить ошибку в `заголовке` и `описании`, пока запрос открыт
|
||||
- отправитель может принять результат во внутренний контур или вернуть запрос обратно во внешний контур с комментарием причины
|
||||
|
||||
На этом месте разработка следующего шага останавливается до фиксации продуктовых решений.
|
||||
|
||||
## Зафиксированные продуктовые решения на 2026-04-20
|
||||
|
||||
После freeze point приняты дополнительные продуктовые решения по следующему циклу развития `Внешних контуров`.
|
||||
|
||||
### 1. Нужны две обязательные системные зоны
|
||||
|
||||
Во `Внешних контурах` должны появиться:
|
||||
- `Исходящие`
|
||||
- `Входящие`
|
||||
|
||||
`Исходящие` обязательны, потому что пользователь должен видеть запросы, которые он сам отправил в другие контуры, до и после обработки.
|
||||
|
||||
`Входящие` обязательны, потому что проект должен видеть запросы, пришедшие к нему из других контуров, в отдельном специализированном режиме работы, а не только как обычные задачи `Внутреннего контура`.
|
||||
|
||||
### 2. Обе зоны должны фильтроваться так же гибко, как во `Внутреннем контуре`
|
||||
|
||||
Минимальный целевой принцип:
|
||||
- фильтрация по пользователям
|
||||
- фильтрация по статусам
|
||||
- фильтрация по назначенным
|
||||
- фильтрация по автору
|
||||
- фильтрация по контурам и связанным проектам
|
||||
|
||||
То есть `Внешние контуры` должны получить не просто статичный список, а управляемое рабочее представление.
|
||||
|
||||
### 3. Карточка деталей внешнего контура должна перейти на тот же UX-паттерн, что и во `Внутреннем контуре`
|
||||
|
||||
При клике по карточке должна открываться панель того же класса:
|
||||
- закрыть просмотр
|
||||
- открыть на весь экран
|
||||
- переключить макет
|
||||
- подписка или отписка
|
||||
- копирование ссылки
|
||||
- меню дополнительных действий
|
||||
|
||||
При этом:
|
||||
- действие удаления в этом shell не является обязательным
|
||||
- тело карточки остается внешнеконтурным, а не превращается в обычную карточку внутренней задачи
|
||||
|
||||
### 4. Внешний контур — это не workflow-kanban
|
||||
|
||||
Важно зафиксировать заранее:
|
||||
- пользователь не должен перетаскивать задачи между блоками
|
||||
- блоки во `Внешних контурах` — это представления и выборки, а не стадии исполнения
|
||||
- нельзя переносить сюда механику drag-and-drop из `Внутреннего контура`
|
||||
|
||||
### 5. Пользовательские колонки нужны, но не входят в ближайший обязательный срез
|
||||
|
||||
Собственные пользовательские блоки и сортировки нужны как следующий этап развития, но не должны размыть ближайшие обязательные поставки:
|
||||
1. единый shell карточки внешнего контура
|
||||
2. двусторонняя доска `Исходящие / Входящие`
|
||||
|
||||
### 6. Архитектура должна остаться расширяемой
|
||||
|
||||
Следующий слой развития не ограничивается только внешними контурами.
|
||||
|
||||
Дальше в проекте могут появиться:
|
||||
- новые типы досок
|
||||
- агентные доски
|
||||
- специализированные мониторинговые представления
|
||||
- пользовательские рабочие поверхности под разные роли
|
||||
|
||||
Поэтому нельзя решать следующий этап только переобертками и точечными хаками.
|
||||
|
||||
Но и полный демонтаж текущего проекта ради абстрактной платформы тоже недопустим.
|
||||
|
||||
Рабочий принцип:
|
||||
- не ломать текущий runtime
|
||||
- не дублировать уже существующие механики без причины
|
||||
- выносить только те контракты, которые реально переиспользуются дальше
|
||||
|
||||
## Что нужно решить перед продолжением
|
||||
|
||||
- Что именно делает действие `Принять`:
|
||||
- только фиксирует решение источника
|
||||
- создает отдельную сущность во `Внутреннем контуре`
|
||||
- или переводит внешний запрос в отдельный внутренний режим без дублирования сущностей
|
||||
- Должен ли принятый запрос оставаться во `Внешних контурах` как историческая карточка, или он должен исчезать из рабочего списка и жить только во `Внутреннем контуре`
|
||||
- Нужен ли отдельный статус или отдельная вкладка для запросов, которые уже приняты во `Внутренний контур`
|
||||
- Должна ли коммуникация по комментариям быть полностью двусторонней, или source-side ответов достаточно только для возврата и уточнений
|
||||
- Нужно ли физически копировать файлы в source-side представление, или для PoC достаточно proxy-доступа к файлам целевой задачи
|
||||
- Нужно ли переводить обновление карточки с polling на realtime/push уже в следующем этапе, или polling пока приемлем
|
||||
- Нужны ли отдельные счетчики непрочитанных изменений по вкладкам `Открытые` и `Завершенные`
|
||||
- Должен ли отправитель после создания запроса иметь право менять только `заголовок` и `описание`, или еще и `назначенного`, `срок`, `приоритет`, `метки`
|
||||
- Нужно ли сохранять запрет на прямой переход в целевую задачу для пользователей без membership в target project как постоянное правило
|
||||
- Какой финальный lifecycle должен быть у запроса после возврата, принятия, завершения и отмены, чтобы source-side карточка не стала второй несогласованной системой учета
|
||||
|
||||
## Обязательные требования
|
||||
|
||||
### 1. Отдельный модуль
|
||||
|
||||
`Внешние контуры` не должны быть переименованным `Intake`.
|
||||
|
||||
Это отдельная новая вкладка проекта.
|
||||
|
||||
### 2. Обычная задача в целевом проекте
|
||||
|
||||
Задача не должна висеть в ручном triage.
|
||||
|
||||
После отправки она должна сразу попадать в обычный workflow целевого проекта, в его default-state.
|
||||
|
||||
### 3. Статусная пришлепка в источнике
|
||||
|
||||
У каждой записи во `Внешних контурах` в списке должен быть видимый статус.
|
||||
|
||||
Для первой версии правильнее показывать фактическое имя текущего статуса целевой задачи:
|
||||
- `В плане`
|
||||
- `К выполнению`
|
||||
- `В работе`
|
||||
- `Готово`
|
||||
- `Отменено`
|
||||
- либо любой другой кастомный статус целевого проекта
|
||||
|
||||
То есть источник видит не абстрактное `accepted`, а реальный текущий статус исполнения.
|
||||
|
||||
### 4. Зеркалирование изменений из целевого проекта в источник
|
||||
|
||||
Изменения в целевой задаче должны отражаться в исходной карточке внешнего контура.
|
||||
|
||||
Минимальный обязательный набор:
|
||||
- изменение статуса
|
||||
- изменение названия
|
||||
- изменение описания
|
||||
- добавление/удаление файлов
|
||||
- комментарии и служебные заметки по задаче
|
||||
- закрытие/отмена задачи
|
||||
|
||||
### 5. Уведомления инициатору
|
||||
|
||||
Инициатор должен получать уведомления, когда:
|
||||
- задача принята в работу
|
||||
- задача переведена в другой статус
|
||||
- добавлен файл
|
||||
- добавлен комментарий
|
||||
- задача завершена
|
||||
- задача отменена
|
||||
|
||||
### 6. Трассировка между источником и целью
|
||||
|
||||
Связь между источником и целевой задачей должна быть явной и восстановимой.
|
||||
|
||||
Нельзя делать фичу как “создали задачу и забыли”.
|
||||
|
||||
## Архитектурный подход
|
||||
|
||||
## Общая схема
|
||||
|
||||
Используем существующий intake bridge как транспортный слой:
|
||||
- создаем `Issue` в целевом проекте
|
||||
- создаем `IntakeIssue`
|
||||
- сразу переводим bridge в `ACCEPTED`
|
||||
- целевая задача попадает в default-state проекта
|
||||
|
||||
Но только этого уже недостаточно.
|
||||
|
||||
Из-за требований на статусную пришлепку, зеркалирование файлов и уведомления нужен еще source-side слой отображения.
|
||||
|
||||
## Что остается от текущей идеи варианта 2
|
||||
|
||||
Сохраняем:
|
||||
- reuse intake backend-механики
|
||||
- отдельный orchestration endpoint
|
||||
- отдельный фронтовый модуль `Внешние контуры`
|
||||
|
||||
Расширяем:
|
||||
- добавляем источник правды для source-side карточки
|
||||
- добавляем синхронизацию изменений из target issue в source representation
|
||||
- добавляем уведомления
|
||||
|
||||
## Рекомендуемая модель данных для первой итерации
|
||||
|
||||
### Обязательная связь
|
||||
|
||||
Нужна явная пара:
|
||||
- `source_project_id`
|
||||
- `source_request_id`
|
||||
- `target_project_id`
|
||||
- `target_issue_id`
|
||||
|
||||
### Метаданные bridge
|
||||
|
||||
В `IntakeIssue.extra` храним:
|
||||
- тип моста: `external-contours`
|
||||
- источник
|
||||
- цель
|
||||
- автора
|
||||
- временные метки
|
||||
|
||||
Пример:
|
||||
|
||||
```json
|
||||
{
|
||||
"bridge": "external-contours",
|
||||
"source_project_id": "uuid",
|
||||
"source_project_name": "Менеджеры",
|
||||
"target_project_id": "uuid",
|
||||
"target_project_name": "Бухгалтерия",
|
||||
"requested_by_id": "uuid",
|
||||
"requested_by_name": "Иван Петров",
|
||||
"requested_at": "2026-04-18T19:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Source-side представление
|
||||
|
||||
Для source-side части есть два пути:
|
||||
|
||||
1. Легкая проекция без отдельной таблицы
|
||||
- список `Отправленные` собирается по `IntakeIssue.extra`
|
||||
- детали берутся из целевой задачи
|
||||
|
||||
2. Отдельная source-side сущность или shadow-record
|
||||
- отдельная запись для внешнего контура в проекте-источнике
|
||||
- в ней хранится mirrored state
|
||||
|
||||
Для требований текущего этапа безопаснее считать, что source-side проекция понадобится.
|
||||
|
||||
Причина:
|
||||
- нужен список со статусом
|
||||
- нужны файлы в источнике
|
||||
- нужна история изменений
|
||||
- нужны уведомления
|
||||
|
||||
Простого “читать target issue на лету” для этого, скорее всего, будет мало.
|
||||
|
||||
## UX первой рабочей вертикали
|
||||
|
||||
## Модуль `Внешние контуры`
|
||||
|
||||
В проекте появляется новая вкладка:
|
||||
- `Внешние контуры`
|
||||
|
||||
Внутри:
|
||||
- кнопка `Новый внешний запрос`
|
||||
- список `Открытые`
|
||||
- список `Завершенные`
|
||||
|
||||
## Форма создания
|
||||
|
||||
Поля:
|
||||
- целевой проект
|
||||
- название
|
||||
- описание
|
||||
- исполнитель из целевого проекта
|
||||
- приоритет
|
||||
- срок
|
||||
- метки
|
||||
|
||||
Вложения можно заложить сразу в спецификацию, но в первую техническую поставку лучше включать аккуратно.
|
||||
|
||||
## Карточка в списке
|
||||
|
||||
В строке списка должны быть:
|
||||
- название
|
||||
- целевой проект
|
||||
- исполнитель
|
||||
- дата создания
|
||||
- статусная пришлепка
|
||||
- индикатор новых изменений
|
||||
|
||||
## Детальный экран внешнего контура
|
||||
|
||||
Детальный экран источника не должен быть просто копией target issue.
|
||||
|
||||
Правильнее собрать его из блоков:
|
||||
- исходный запрос
|
||||
- текущий статус
|
||||
- целевой проект и исполнитель
|
||||
- история изменений
|
||||
- синхронизированные файлы
|
||||
- комментарии/обновления
|
||||
|
||||
Это безопаснее, чем пытаться перетирать исходное описание данными целевого проекта.
|
||||
|
||||
## Правила синхронизации
|
||||
|
||||
## Направления
|
||||
|
||||
### Источник -> цель
|
||||
|
||||
На этапе создания отправляем:
|
||||
- название
|
||||
- описание
|
||||
- исполнителя
|
||||
- приоритет
|
||||
- срок
|
||||
- метки
|
||||
|
||||
### Цель -> источник
|
||||
|
||||
После создания отражаем обратно:
|
||||
- текущий статус
|
||||
- изменения описания
|
||||
- комментарии
|
||||
- файлы
|
||||
- итоговый результат
|
||||
|
||||
## Что должно быть синхронизировано в обязательном порядке
|
||||
|
||||
- `target issue state.name`
|
||||
- `target issue updated_at`
|
||||
- файлы target issue
|
||||
- пользовательские комментарии
|
||||
- итоговый resolution state
|
||||
|
||||
## Что пока не нужно считать обязательным
|
||||
|
||||
- полная двусторонняя редакция из источника после отправки
|
||||
- редактирование чужих project labels через источник
|
||||
- полный realtime-collab режим
|
||||
|
||||
## Уведомления
|
||||
|
||||
Минимальный набор событий:
|
||||
- запрос создан
|
||||
- задача принята
|
||||
- статус изменен
|
||||
- добавлен файл
|
||||
- добавлен комментарий
|
||||
- задача завершена
|
||||
- задача отменена
|
||||
|
||||
Каналы первой версии:
|
||||
- in-app notifications
|
||||
|
||||
Каналы последующих итераций:
|
||||
- email
|
||||
- внешние integrations
|
||||
|
||||
## Ограничения текущего этапа
|
||||
|
||||
### 1. Вложения сейчас хрупкие
|
||||
|
||||
Текущий runtime уже показывал хрупкость attachment flow.
|
||||
|
||||
Поэтому вложения нужно учитывать в дизайне, но внедрять аккуратно и тестировать отдельно.
|
||||
|
||||
### 2. Права сложнее, чем кажется
|
||||
|
||||
Отправитель должен иметь право отправлять запрос из source project, но не обязан быть участником target project.
|
||||
|
||||
При этом:
|
||||
- target assignee должен быть участником target project
|
||||
- target issue создается в target project
|
||||
- источник должен иметь возможность видеть результат обработки без полного membership в target project
|
||||
|
||||
### 3. Простая “копия intake” уже недостаточна
|
||||
|
||||
Как только добавляются:
|
||||
- статусная пришлепка
|
||||
- файлы
|
||||
- история
|
||||
- уведомления
|
||||
|
||||
фича перестает быть просто формой создания.
|
||||
|
||||
Нужен отдельный источник правды для source-side представления.
|
||||
|
||||
## Что считаем текущим этапом
|
||||
|
||||
Текущий этап — это не финальная реализация, а проектирование и запуск вертикального среза.
|
||||
|
||||
В этот этап входят:
|
||||
- фиксация терминологии
|
||||
- фиксация архитектурного подхода
|
||||
- разбиение на поставки
|
||||
- определение обязательных требований для первой версии
|
||||
- определение границ MVP
|
||||
|
||||
Подробная поэтапная разработка описана в:
|
||||
- [phase-roadmap.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/phase-roadmap.md)
|
||||
- [11_STEP_external-contours-detail-shell.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/11_STEP_external-contours-detail-shell.md)
|
||||
- [12_STEP_external-contours-bidirectional-board.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/12_STEP_external-contours-bidirectional-board.md)
|
||||
@@ -0,0 +1,465 @@
|
||||
# Этапы разработки
|
||||
|
||||
## Общий принцип
|
||||
|
||||
Не делаем сразу тяжелую доменную платформу.
|
||||
|
||||
Идем вертикальными поставками:
|
||||
1. сначала транспорт и создание задачи
|
||||
2. потом source-side представление
|
||||
3. потом синхронизация
|
||||
4. потом уведомления и полировка
|
||||
|
||||
## Freeze point на 2026-04-19
|
||||
|
||||
Текущий вертикальный срез временно заморожен.
|
||||
|
||||
На момент freeze point уже есть:
|
||||
- отправка запроса из source project в target project того же `workspace`
|
||||
- отсутствие требования прямого membership в target project для отправки
|
||||
- source-side список `Открытые / Завершенные`
|
||||
- source-side карточка на shell `Предложений`
|
||||
- source-side редактирование открытого запроса по `заголовку` и `описанию`
|
||||
- зеркалирование статуса, комментариев, вложений и activity из целевого контура
|
||||
- source-side действия `Принять`, `Отклонить`, `Ответ во внешний контур`
|
||||
- индикатор непрочитанных изменений
|
||||
- карточка `Маршрутизация` в целевом формате `3 x 3`
|
||||
|
||||
Дальше по roadmap пока не идем, пока не приняты продуктовые решения по внутреннему жизненному циклу принятого запроса.
|
||||
|
||||
## Новая рамка после freeze point на 2026-04-20
|
||||
|
||||
После дополнительной продуктовой фиксации следующий цикл делится на три слоя:
|
||||
1. единый shell карточки внешнего контура
|
||||
2. двусторонняя доска `Исходящие / Входящие`
|
||||
3. пользовательские представления поверх той же доски
|
||||
|
||||
При этом обязательное архитектурное ограничение фиксируется заранее:
|
||||
- во `Внешних контурах` нет drag-and-drop между блоками
|
||||
- блоки здесь означают представления, а не стадии workflow
|
||||
|
||||
Подробные архитектурные шаги вынесены в:
|
||||
- [11_STEP_external-contours-detail-shell.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/11_STEP_external-contours-detail-shell.md)
|
||||
- [12_STEP_external-contours-bidirectional-board.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/12_STEP_external-contours-bidirectional-board.md)
|
||||
|
||||
## Этап 0. Термины и навигация
|
||||
|
||||
### Цель
|
||||
|
||||
Подготовить интерфейс и словарь сущностей без ломки backend-логики.
|
||||
|
||||
### Что входит
|
||||
|
||||
- `Рабочие элементы` -> `Внутренний контур`
|
||||
- новая вкладка `Внешние контуры`
|
||||
- подготовка i18n-ключей и текстов
|
||||
- фиксация терминов в продуктовой документации
|
||||
|
||||
### Результат
|
||||
|
||||
В проекте уже есть новая структура навигации, но бизнес-логика еще не внедрена.
|
||||
|
||||
## Этап 1. Маршрутизация запроса в целевой проект
|
||||
|
||||
### Цель
|
||||
|
||||
Сделать рабочий сценарий отправки задачи из source project в target project.
|
||||
|
||||
### Что входит
|
||||
|
||||
- новая create-form во `Внешних контурах`
|
||||
- выбор целевого проекта
|
||||
- выбор исполнителя из целевого проекта
|
||||
- orchestration endpoint
|
||||
- использование intake bridge как backend-моста
|
||||
- немедленный перевод в default-state целевого проекта
|
||||
- создание target issue
|
||||
- запись source/target metadata
|
||||
|
||||
### Что не входит
|
||||
|
||||
- полноценная синхронизация файлов
|
||||
- полноценная зеркальная история
|
||||
- сложные уведомления
|
||||
|
||||
### Критерий приемки
|
||||
|
||||
- пользователь отправляет внешний запрос
|
||||
- в целевом проекте появляется обычная задача
|
||||
- задача не зависает в triage
|
||||
- source-side список уже видит факт отправки
|
||||
|
||||
### Статус
|
||||
|
||||
Реализовано.
|
||||
|
||||
Что работает фактически:
|
||||
- `POST /external-contours/` создает target issue в целевом проекте
|
||||
- target issue сразу попадает в обычный workflow целевого проекта
|
||||
- source-side `GET /external-contours/` возвращает отправленные запросы с metadata источника и цели
|
||||
- target contour теперь выбирается по policy `same workspace + intake enabled`, а не только из joined projects
|
||||
- прямое membership в target project для отправки не требуется
|
||||
|
||||
## Этап 2. Source-side список и статусная пришлепка
|
||||
|
||||
### Цель
|
||||
|
||||
Дать инициатору читаемый контроль за отправленными запросами.
|
||||
|
||||
### Что входит
|
||||
|
||||
- список `Открытые`
|
||||
- список `Завершенные`
|
||||
- текущий статус задачи как пришлепка
|
||||
- отображение целевого проекта
|
||||
- отображение исполнителя
|
||||
- отображение даты обновления
|
||||
- индикатор новых изменений
|
||||
|
||||
### Критерий приемки
|
||||
|
||||
- в проекте-источнике виден список отправленных запросов
|
||||
- у каждой записи отображается актуальный статус целевой задачи
|
||||
|
||||
### Статус
|
||||
|
||||
Реализовано частично в рамках текущего вертикального среза.
|
||||
|
||||
Что уже работает:
|
||||
- source-side список `Открытые / Завершенные`
|
||||
- status pill по фактическому state целевой задачи
|
||||
- отображение целевого проекта
|
||||
- отображение исполнителей целевого контура
|
||||
- отображение фактической даты последнего изменения
|
||||
- индикатор новых изменений в source-side списке на базе unread уведомлений
|
||||
- открытие source-side detail экрана
|
||||
|
||||
Что еще остается на следующие этапы:
|
||||
- полноценная зеркальная activity/history
|
||||
- уведомления
|
||||
|
||||
Дополнительно реализовано:
|
||||
- source-side detail показывает блок маршрутизации
|
||||
- в карточке видны источник, цель, отправитель, дата отправки и связанная целевая задача
|
||||
|
||||
## Этап 3. Source-side детальный экран и зеркалирование изменений
|
||||
|
||||
### Цель
|
||||
|
||||
Сделать так, чтобы отправитель видел ход исполнения не только по одной плашке статуса.
|
||||
|
||||
### Что входит
|
||||
|
||||
- детальный экран внешнего контура
|
||||
- блок `Исходный запрос`
|
||||
- блок `Текущий статус`
|
||||
- mirrored activity stream
|
||||
- mirrored comments
|
||||
- mirrored files
|
||||
- mirrored description updates
|
||||
|
||||
### Важное правило
|
||||
|
||||
Исходный запрос не должен теряться.
|
||||
|
||||
Поэтому target-изменения лучше показывать отдельным блоком истории, а не просто затирать исходное описание.
|
||||
|
||||
### Критерий приемки
|
||||
|
||||
- если в target issue добавили файл, инициатор видит его в source-side карточке
|
||||
- если в target issue поменяли статус, это видно в source-side карточке
|
||||
- если в target issue написали комментарий, это видно в source-side карточке
|
||||
|
||||
### Статус
|
||||
|
||||
Реализовано частично.
|
||||
|
||||
Что уже работает:
|
||||
- source-side detail использует отдельный экран `Внешних контуров`
|
||||
- в карточке отображается блок маршрутизации с ключевой source-target связью
|
||||
- у отправителя открытый внешний запрос редактируется прямо из source-side карточки по полям `заголовок` и `описание`, даже без membership в target project
|
||||
- текущий статус берется из фактического state целевой задачи
|
||||
- если у инициатора нет membership в target project, карточка переключается в source-side readonly режим без прямого открытия чужого проекта
|
||||
- блок `Маршрутизация` перестроен в фиксированный формат `3 x 3`
|
||||
- в `Маршрутизацию` перенесены `Назначенный` и `Срок выполнения`
|
||||
- в блоке `Свойства` убраны дубли `Внешний контур`, `Назначенный` и `Срок выполнения`
|
||||
- название исходного внутреннего контура в карточке маршрутизации берется из живого проекта, а не из застывшего metadata snapshot
|
||||
- для закрытого внешнего запроса доступны source-side действия `Принять` и `Отклонить`
|
||||
- `Принять` фиксирует решение источника в bridge metadata и помечает запрос как принятый во внутренний контур
|
||||
- `Отклонить` требует комментарий причины, возвращает target issue в default-state целевого проекта и переносит source-side карточку обратно в список `Открытые`
|
||||
- source-side readonly карточка зеркалит актуальные комментарии, вложения и activity целевой задачи
|
||||
- вложения доступны через proxy download endpoint без прямого membership в target project
|
||||
- detail карточка source-only пользователя обновляется polling-ом и подтягивает новые комментарии без ручной перезагрузки
|
||||
- инициатор может отправить комментарий обратно во внешний контур прямо из source-side карточки
|
||||
|
||||
Что остается:
|
||||
- зеркалирование inline-файлов из комментариев и описания, а не только issue attachments
|
||||
- realtime вместо polling
|
||||
- отдельная сущность или шаг для переноса принятого результата во `Внутренний контур`
|
||||
|
||||
## Этап 4. Уведомления
|
||||
|
||||
### Цель
|
||||
|
||||
Не заставлять инициатора вручную проверять изменения.
|
||||
|
||||
### Что входит
|
||||
|
||||
- in-app notification на:
|
||||
- принятие
|
||||
- перевод статуса
|
||||
- добавление файла
|
||||
- новый комментарий
|
||||
- завершение
|
||||
- отмену
|
||||
|
||||
### Критерий приемки
|
||||
|
||||
- инициатор получает уведомления по ключевым событиям жизненного цикла внешнего запроса
|
||||
|
||||
### Статус
|
||||
|
||||
Реализовано частично.
|
||||
|
||||
Что уже работает:
|
||||
- создаются in-app уведомления по изменениям целевой задачи внешнего контура
|
||||
- покрыты события:
|
||||
- смена статуса
|
||||
- новый комментарий
|
||||
- изменение описания
|
||||
- новое вложение
|
||||
- уведомление привязано к source project, а не требует membership в target project
|
||||
- notification payload несет `external contour request id` и `target issue id`
|
||||
- список уведомлений помечает такие записи как `is_external_contour = true`
|
||||
- notification preview может открыть source-side карточку внешнего контура, а не обычный issue preview
|
||||
- открытие source-side карточки помечает связанные unread уведомления как прочитанные и снимает индикатор новых изменений в списке
|
||||
|
||||
Что остается:
|
||||
- in-app уведомления на явные source-side решения `Принять / Отклонить`
|
||||
- отдельный индикатор новых изменений в списке `Открытые / Завершенные`
|
||||
- push/realtime канал вместо обычного цикла обновления UI
|
||||
|
||||
## Этап 5. Полировка и правила эксплуатации
|
||||
|
||||
### Что входит
|
||||
|
||||
- edge cases
|
||||
- повторная отправка
|
||||
- отмена
|
||||
- защита от удаления target issue
|
||||
- аудит прав
|
||||
- тест-кейсы
|
||||
- регламент эксплуатации
|
||||
|
||||
## Этап 6. Единый shell карточки внешнего контура
|
||||
|
||||
### Цель
|
||||
|
||||
Привести карточку деталей `Внешних контуров` к тому же UX-паттерну, что и во `Внутреннем контуре`, не ломая при этом внешний data-flow.
|
||||
|
||||
### Что входит
|
||||
|
||||
- общий shell открытия карточки
|
||||
- тот же класс верхнего action-bar:
|
||||
- закрытие просмотра
|
||||
- полноэкранный режим
|
||||
- переключение макета
|
||||
- подписка или отписка
|
||||
- копирование ссылки
|
||||
- меню дополнительных действий
|
||||
- переиспользование общего представления shell без подмены доменной модели внешнего контура
|
||||
- сохранение внешнеконтурного body:
|
||||
- `Маршрутизация`
|
||||
- зеркальные комментарии
|
||||
- зеркальные вложения
|
||||
- external lifecycle
|
||||
|
||||
### Что не входит
|
||||
|
||||
- две системные зоны `Исходящие / Входящие`
|
||||
- пользовательские колонки
|
||||
- drag-and-drop
|
||||
- насильственный перевод внешнего запроса в обычный issue detail
|
||||
|
||||
### Критерий приемки
|
||||
|
||||
- карточка `Внешних контуров` открывается по тому же UX-паттерну, что и внутренний peek
|
||||
- source-only сценарий не ломается
|
||||
- body карточки остается внешнеконтурным
|
||||
|
||||
### Статус
|
||||
|
||||
Запланировано.
|
||||
|
||||
Подробно описано в:
|
||||
- [11_STEP_external-contours-detail-shell.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/11_STEP_external-contours-detail-shell.md)
|
||||
|
||||
## Этап 7. Двусторонняя доска `Исходящие / Входящие`
|
||||
|
||||
### Цель
|
||||
|
||||
Дать проекту единый рабочий экран межконтурной работы, где видны и отправленные, и полученные запросы.
|
||||
|
||||
### Что входит
|
||||
|
||||
- две фиксированные системные зоны:
|
||||
- `Исходящие`
|
||||
- `Входящие`
|
||||
- единый board-level data contract
|
||||
- фильтрация обеих зон по аналогии с `Внутренним контуром`
|
||||
- счетчики
|
||||
- открытие карточки в shell этапа 6
|
||||
|
||||
### Важное правило
|
||||
|
||||
Это не kanban статусов.
|
||||
|
||||
Во `Внешних контурах`:
|
||||
- нет drag-and-drop между блоками
|
||||
- блоки означают представления по направлению и фильтрам
|
||||
- смена состояния не должна кодироваться визуальным переносом карточки
|
||||
|
||||
### Что не входит
|
||||
|
||||
- пользовательские кастомные зоны
|
||||
- свободный конструктор колонок
|
||||
- превращение доски во второй workflow движок
|
||||
|
||||
### Критерий приемки
|
||||
|
||||
- пользователь видит и `Исходящие`, и `Входящие`
|
||||
- отправленные запросы не теряются после отправки
|
||||
- обе системные зоны фильтруются через единый механизм
|
||||
- карточка из любой зоны открывается единообразно
|
||||
|
||||
### Статус
|
||||
|
||||
Запланировано.
|
||||
|
||||
Подробно описано в:
|
||||
- [12_STEP_external-contours-bidirectional-board.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/12_STEP_external-contours-bidirectional-board.md)
|
||||
|
||||
## Этап 8. Пользовательские представления поверх двусторонней доски
|
||||
|
||||
### Цель
|
||||
|
||||
Разрешить пользователю собирать собственные рабочие выборки поверх уже стабилизированной двусторонней доски.
|
||||
|
||||
### Что входит
|
||||
|
||||
- пользовательские блоки или представления
|
||||
- пользовательское имя блока
|
||||
- сохранение набора фильтров
|
||||
- персональные рабочие выборки по контурам, статусам, пользователям и другим признакам
|
||||
|
||||
### Важное правило
|
||||
|
||||
Пользовательские блоки не меняют базовый принцип:
|
||||
- это не стадии workflow
|
||||
- это не drag-and-drop
|
||||
- это не замена `Внутреннего контура`
|
||||
|
||||
### Зависимость
|
||||
|
||||
Этап начинается только после стабилизации этапов 6 и 7.
|
||||
|
||||
### Статус
|
||||
|
||||
Запланировано как следующий слой развития, но не входит в ближайший обязательный срез.
|
||||
|
||||
## Технические решения, которые желательно держать с самого начала
|
||||
|
||||
### 1. Не ломать штатный intake
|
||||
|
||||
Он остается отдельным продуктовым модулем.
|
||||
|
||||
### 2. Явно хранить source/target связь
|
||||
|
||||
Даже если первая версия идет через `IntakeIssue.extra`, связь не должна быть неявной.
|
||||
|
||||
### 3. Использовать фактический статус target issue
|
||||
|
||||
В source-side плашке лучше показывать не abstract intake status, а реальный текущий статус исполнения.
|
||||
|
||||
### 4. Не пытаться делать полную двустороннюю редакцию сразу
|
||||
|
||||
На старте безопаснее сделать:
|
||||
- создание из источника
|
||||
- исполнение в цели
|
||||
- синхронизацию результата обратно в источник
|
||||
|
||||
## Открытые вопросы
|
||||
|
||||
### 1. Что именно делает `Принять`
|
||||
|
||||
Нужно зафиксировать конечную бизнес-логику:
|
||||
- `Принять` только ставит source-side решение `accepted`
|
||||
- `Принять` создает отдельную сущность во `Внутреннем контуре`
|
||||
- `Принять` переводит карточку в отдельный внутренний статус без создания дубликата
|
||||
|
||||
Это главный блокирующий вопрос перед следующим этапом.
|
||||
|
||||
### 2. Где дальше живет принятый запрос
|
||||
|
||||
Нужно решить:
|
||||
- карточка остается во `Внешних контурах` как историческая запись
|
||||
- карточка уходит во `Внутренний контур`
|
||||
- карточка одновременно видна в обоих местах, но с разной ролью
|
||||
|
||||
### 3. Нужна ли отдельная сущность source-side
|
||||
|
||||
Нужно принять решение:
|
||||
- достаточно ли текущей source-side проекции поверх bridge metadata
|
||||
- или уже пора вводить отдельную таблицу/модель для внешних контуров
|
||||
|
||||
### 4. Файлы
|
||||
|
||||
Нужно решить:
|
||||
- достаточно ли proxy-доступа к файлам целевой задачи
|
||||
- или файлы надо физически копировать в source-side representation
|
||||
- нужно ли зеркалировать inline-файлы из описания и комментариев
|
||||
|
||||
### 5. Комментарии
|
||||
|
||||
Нужно решить:
|
||||
- source-side reply остается облегченной обратной связью
|
||||
- или нужен полноценный двусторонний поток комментариев как единый discussion-thread
|
||||
|
||||
### 6. Уровень realtime
|
||||
|
||||
Нужно решить:
|
||||
- хватает ли polling для PoC
|
||||
- или следующий этап уже должен включать push/realtime события
|
||||
|
||||
### 7. Счетчики и вкладки
|
||||
|
||||
Нужно решить:
|
||||
- нужен ли отдельный unread-counter по вкладкам `Открытые / Завершенные`
|
||||
- нужен ли отдельный сегмент для запросов, принятых во `Внутренний контур`
|
||||
|
||||
### 8. Право редактирования после отправки
|
||||
|
||||
Нужно решить:
|
||||
- отправитель редактирует только `заголовок` и `описание`
|
||||
- или после отправки он может менять еще `срок`, `назначенного`, `приоритет`, `метки`
|
||||
|
||||
### 9. Доступ к target issue
|
||||
|
||||
Нужно решить:
|
||||
- должен ли инициатор иметь прямую ссылку на target issue
|
||||
- или source-side карточка должна оставаться единственной точкой просмотра для пользователей без membership
|
||||
|
||||
Текущее решение:
|
||||
- при отсутствии membership в target project прямой переход в target issue скрывается
|
||||
- карточка остается доступной из source project
|
||||
|
||||
## Рекомендуемый порядок фактической разработки
|
||||
|
||||
1. Этап 0
|
||||
2. Этап 1
|
||||
3. Этап 2
|
||||
4. Этап 3
|
||||
5. Этап 4
|
||||
6. Этап 5
|
||||
|
||||
Это даст быстрый полезный результат и не загонит проект в ранний тяжелый refactor.
|
||||
Reference in New Issue
Block a user