diff --git a/openspec/changes/web-modules/design.md b/openspec/changes/web-modules/design.md index 772ee03..9f0ebd1 100644 --- a/openspec/changes/web-modules/design.md +++ b/openspec/changes/web-modules/design.md @@ -146,3 +146,8 @@ type HubModule = { | 42 | 24.10.2026 | Task 5: поле поиска вики на «Обзоре» не ведёт на пустой запрос (Enter при пустой строке ничего не делает); `q` в «Вики» — только начальное значение поля, выбор страницы убирает `q` из адреса | пустой поиск = страница «Вики» без `q`, для неё есть ссылка «Вики»; `hrefOf` страницы по контракту Task 4 не несёт поиск | пользователь, вставший на `?q=` и открывший страницу, теряет в адресе строку поиска (в поле она остаётся) | | 43 | 24.10.2026 | Task 6: номер доски проверяется в окне сам (`/^\d+$/`, ≥ 1, текст «нужно целое число»), поле — `type="text"` с `inputMode="numeric"`, форма `noValidate` | `type="number"` даёт браузерную подсказку вместо нашего текста и пропускает `51.5`/`1e3` по-разному в браузерах; T4.1 | поле без стрелок счётчика; невалидное значение ловится только по «Создать» | | 44 | 24.10.2026 | Task 6: в ядре `useTrackModuleBatch()` (activity.ts) — отслеживание пакета по имени модуля; окно создания вынесено в `shell/NewProject.tsx`; `useTrackBatch` остаётся для пакетов без известного модуля | пакеты нового проекта привязываются каждому своему модулю по `batches[].module` (M-14, T5.3 #68); Layout не обязан знать модули | пакет неизвестного модуля молча не отслеживается | +| 45 | 24.10.2026 | Task 7: узкий экран «Вики» (страница выше дерева) — через `matchMedia("(max-width: 759.98px)")` и порядок в разметке (`WikiPage`), а не CSS `order`; дерево при поиске скрыто (`hidden`), а не размонтировано | порядок Tab совпадает с видимым; раскрытые вручную узлы переживают поиск (T10.2, T10.6); порог окна — приближение порога контейнера страницы | CSS `order` и размонтирование дерева | +| 46 | 24.10.2026 | Task 7: заголовки текста страницы вики сдвинуты ниже заголовка страницы: `#`/`##` → h3, `###` → h4 … не глубже h6 | порядок h1 → h2 → h3 без скачков и без второго h1 (T10.3) | оставить h1–h4 как есть | +| 47 | 24.10.2026 | Task 7: `.issue-table-wrap{overflow-x:auto}` на любой ширине (раньше — только `@container page < 1052px`) | на 1440 px девять столбцов шире панели; цена — липкая шапка таблицы липнет к панели, а не к окну | вернуть условие и сжать столбцы | +| 48 | 24.10.2026 | Task 7: проверка T5.2 «ядро не грузит /board и /wiki/status» идёт на странице вне модулей (`/app/nowhere`), а не на `/wiki?project=…` | страница «Вики» сама запрашивает `/wiki/status` (это модуль, не ядро) | проверять на странице вики с исключением статуса | +| 49 | 24.10.2026 | Task 7: `scrollbar-gutter: stable` — на `html` (прокручивается окно, отдельной области страницы нет); «Обновить из Jira» в шапках — общий `modules/jira/RefreshButton.tsx` | страницы разной высоты не двигаются по ширине; одна реализация кнопки на три страницы | прокручиваемый контейнер страницы; кнопка в каждой странице | diff --git a/web/src/modules/jira/RefreshButton.tsx b/web/src/modules/jira/RefreshButton.tsx new file mode 100644 index 0000000..be9bf6a --- /dev/null +++ b/web/src/modules/jira/RefreshButton.tsx @@ -0,0 +1,9 @@ +import { Button, IconRefresh } from "../../ui/index.ts"; +import { useModuleActivity } from "../../shell/activity/activity.ts"; +import { jiraStatus } from "./status.ts"; + +// «Обновить из Jira» в шапке страницы модуля: вторичная кнопка; ход пакета показывает блок состояния боковой панели +export function RefreshButton() { + const act = useModuleActivity("jira"); + return } loading={act.busy} onClick={() => void act.start()}>{jiraStatus.refresh!.label}; +} diff --git a/web/src/modules/jira/board/BoardPage.test.tsx b/web/src/modules/jira/board/BoardPage.test.tsx index 79826e5..41ed29a 100644 --- a/web/src/modules/jira/board/BoardPage.test.tsx +++ b/web/src/modules/jira/board/BoardPage.test.tsx @@ -36,6 +36,15 @@ const NO_SPRINT_TEXT = "колонки «Спринт» нет — показа describe("страница доски", () => { beforeEach(() => setToken("tok")); + it("шапка: вторичная кнопка «Обновить из Jira», primary нет; пустого блока .board-src под шапкой нет", async () => { + hub(); + const { container } = page(); + await screen.findByText(/задач из/); + expect(screen.getByRole("button", { name: "Обновить из Jira" })).toHaveClass("ui-btn--secondary"); + expect(container.querySelector(".ui-btn--primary")).toBeNull(); + expect(container.querySelector(".board-src")).toBeNull(); + }); + it("строит доску из хаба: источник, статистика, выбор самого наполненного спринта", async () => { hub(); page(); @@ -156,11 +165,11 @@ describe("страница доски", () => { expect(screen.getByText("скрыто: 1")).toBeInTheDocument(); }); - it("доска не рисует «Обновить из Jira» и ход пакета: они в верхней панели", async () => { + it("кнопка «Обновить из Jira» в шапке есть, хода пакета и «Тема» на доске нет", async () => { hub(); page(); await screen.findByText(/задач из 9/); - expect(screen.queryByRole("button", { name: "Обновить из Jira" })).not.toBeInTheDocument(); + expect(screen.getByRole("button", { name: "Обновить из Jira" })).toBeInTheDocument(); await userEvent.click(screen.getByRole("button", { name: "Ещё" })); expect(screen.getByRole("button", { name: "Ещё" })).toHaveAttribute("aria-expanded", "true"); expect(screen.getByRole("button", { name: "Перечитать" })).toBeInTheDocument(); // меню действительно открыто diff --git a/web/src/modules/jira/board/BoardPage.tsx b/web/src/modules/jira/board/BoardPage.tsx index 803e000..c6c8d46 100644 --- a/web/src/modules/jira/board/BoardPage.tsx +++ b/web/src/modules/jira/board/BoardPage.tsx @@ -70,7 +70,7 @@ export function BoardPage({ project }: { project: string }) { return (
команд по задаче не было
команд по задаче не было
| Команда | Пакет | Тип | Статус | Завершена | Ошибка | + {due ? fmtDate(due) : ""}{late && просрочено} + | + ); +} + export function IssueTable({ rows, epicNames, closed, onOpen }: { rows: IssueRow[]; epicNames: Record{i.summary} | {i.status && |
{i.assignee} | -{due ? fmtDate(due) : ""} | +{i.sprint} | {i.epic_key ? epicNames[i.epic_key] ?? i.epic_key : ""} | {i.work_kind} | diff --git a/web/src/modules/jira/issues/IssuesPage.test.tsx b/web/src/modules/jira/issues/IssuesPage.test.tsx index 989c9f9..743e407 100644 --- a/web/src/modules/jira/issues/IssuesPage.test.tsx +++ b/web/src/modules/jira/issues/IssuesPage.test.tsx @@ -351,4 +351,26 @@ describe("список задач", () => { expect(dueCell(2)).not.toHaveClass("overdue"); expect(dueCell(3)).not.toHaveClass("overdue"); }); + it("шапка: вторичная кнопка «Обновить из Jira», primary нет", async () => { + hub(() => [row(1)]); + renderWithProviders(
|---|