feat(task-trackers): автокомплит карточки в модале «Приложить карточку»#245
Merged
Conversation
Решения:
- Новый эндпоинт GET /task-trackers/{tracker}/boards/{board}/cards/search
(провайдер-нейтральный порт SearchCardsAsync на ITaskTrackerConnectionProvider).
Пустой query → топ по updated_at desc, ввод текста → live-proxy в трекер.
Лимит клампится на бэке (default 10, max 25).
- Kaiten-адаптер прокидывает order_by=updated + order_direction=desc и condition=Live,
плюс страхующая in-memory сортировка на случай, если трекер отдаст не в том
порядке. Ошибки маппятся через тот же health-классификатор, что и list.
- Фронт: CardSearchCombobox с ARIA-паттерном (combobox+listbox), debounce 250ms,
fallback на чисто числовой ввод (клавиатурный short-path без запросов).
- Тесты эндпоинта вынесены в отдельный класс BoardCardSearchEndpointTests,
чтобы вписаться в бюджет публичных членов на тип (12).
Отброшено:
- TTL-кэш поиска на бэке — MVP live-proxy, ускорим при явной нагрузке.
- Клиентская фильтрация «мои активные» — требует /users/current и меняет UX,
вне scope этого прохода.
- Мульти-бордовый поиск и фильтры по колонке/статусу — отложено в бэклог.
Ограничения:
- Kaiten `query`-фильтр без явного контракта по сортировке при непустом query —
полагаемся на серверный ранжир, доп. клиентский sort включаем только для
пустого запроса.
- Combobox без клавиатурной навигации по списку (arrow-up/down) — MVP ставит
фокус мыши/touch, добавим при UX-доработке.
Решения: - boxClassName: max-w-md → w-full max-w-xl overflow-visible, чтобы список подсказок не резался краем modal-box и вмещал длинные заголовки карточек. - Дропдаун combobox поднят до z-[60] и max-h-80, чтобы стабильно всплывал над панелью и оставался прокручиваемым при полном топ-10. Отброшено: - Портал списка в document.body — оверлей модалки уже z-50, а modal-box с overflow-visible пускает absolute-элемент наружу; лишний портал добавил бы синхронизацию позиции при ресайзе. Ограничения: - max-h-80 (20rem) — визуально комфортно на десктопе; на мобильном модал уже прижат к низу экрана, доп. адаптация не в скоупе прохода.
gently-whitesnow
force-pushed
the
feat/attach-card-autocomplete
branch
from
July 10, 2026 11:26
d21b60e to
1dd9e0c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Цель
Ушли от ввода
card_idчислом на глаз: теперь оператор вводит имя карточки — combobox с server-side автокомплитом (scope = выбранная доска) отдаёт релевантные подсказки, пустой фокус показывает недавно обновлённые карточки. Чистый числовой ввод остаётся коротким путём для «уже скопировал id».Существенные изменения
ITaskTrackerConnectionProvider.SearchCardsAsync(connection, boardId, query, limit, ct).GET /cardsсcondition=Live,board_id=<id>; при пустом query —order_by=updated,order_direction=desc+ страхующая in-memory сортировка. Ошибки через ту же health-таксономию (Auth→409, Blocked→402, Offline→502).BoardCardBrowserService.SearchBoardCardsAsyncсимметричноListBoardCardsAsync(resolve → провайдер → health-tracking).GET /api/v1/task-trackers/{tracker}/boards/{board}/cards/search?query=&limit=(default 10, max 25). Ответ — тот жеTaskTrackerBoardCardsResponse.useBoardCardSearchQuery(tracker, boardId, query, {limit, enabled})— React Query поверх нового эндпоинта сstaleTime: 30s, ретраи только на транзиентах.CardSearchCombobox— ARIA combobox+listbox,useDebouncedValue(250ms), numeric fallback (/^\d+$/) без запросов, строка#{card_id} · {title}+column_title.AttachCardModalподключает combobox под лейблом «ID карточки» черезaria-labelledby(существующие e2e/RTL тесты продолжают ловить поле поgetByLabelText).Принятые решения
queryранжирует по релевантности сам.BoardCardSearchEndpointTests, чтобы уложиться в бюджет публичных членов на тип (12).Ограничения
Как проверить
/settings→ подключить Kaiten и выбрать доску.updated_at.777) → сетевого запроса нет, вместо списка — хинт «Приложить карточку по id #777», submit кладётcard_id=777.pnpm --filter web test,dotnet test,python3 scripts/quality/verify.py --fast— зелёные (проверено локально).