diff --git a/web/src/modules/wiki/versions/VersionModal.test.tsx b/web/src/modules/wiki/versions/VersionModal.test.tsx
index 44f6c9c..fa6a1db 100644
--- a/web/src/modules/wiki/versions/VersionModal.test.tsx
+++ b/web/src/modules/wiki/versions/VersionModal.test.tsx
@@ -152,6 +152,18 @@ describe("окно правки вики", () => {
expect(within(d).queryByRole("button", { name: "Показать дальше" })).toBeNull();
});
+ it("I-2: строки диффа — дети одного контейнера строк, «Показать дальше» вне него", async () => {
+ hub(() => ({ diff: "--- a\n+++ b\n+первая\n+вторая\n", next_offset: 20000 }));
+ await openFromFeed();
+ const d = dialog();
+ const l1 = await within(d).findByText("+первая");
+ const l2 = within(d).getByText("+вторая");
+ const box = l1.parentElement!;
+ expect(box).toHaveClass("wiki-version__lines");
+ expect(l2.parentElement).toBe(box);
+ expect(box.contains(within(d).getByRole("button", { name: "Показать дальше" }))).toBe(false);
+ });
+
it("«Показать дальше»: часть рвёт строку — строка целая и одна", async () => {
hub((_v, offset) => offset === 0
? { diff: "--- a\n+++ b\n+строка дл", next_offset: 20000 }
diff --git a/web/src/modules/wiki/versions/VersionModal.tsx b/web/src/modules/wiki/versions/VersionModal.tsx
index ada6e91..9613a7c 100644
--- a/web/src/modules/wiki/versions/VersionModal.tsx
+++ b/web/src/modules/wiki/versions/VersionModal.tsx
@@ -81,6 +81,7 @@ function VersionBody({ project, code, version, onClose, onNavigate }: Props) {
{first && (
{lines.length === 0 &&
В правке нет изменений текста.
}
+
{lines.map((l, i) => (
{l.kind === "add" && добавлено: }
@@ -88,6 +89,7 @@ function VersionBody({ project, code, version, onClose, onNavigate }: Props) {
{l.text}
))}
+
{diff.hasNextPage && (
)}
diff --git a/web/src/modules/wiki/versions/versions.css b/web/src/modules/wiki/versions/versions.css
index 2614a3c..406a1b1 100644
--- a/web/src/modules/wiki/versions/versions.css
+++ b/web/src/modules/wiki/versions/versions.css
@@ -12,6 +12,7 @@
.wiki-version__page{color:var(--color-action-primary)}
.wiki-version__hint{margin:0;color:var(--color-text-secondary)}
.wiki-version__diff{display:flex;flex-direction:column;gap:var(--space-3);align-items:flex-start;min-width:0}
+.wiki-version__lines{display:flex;flex-direction:column;align-self:stretch;min-width:0}
.wiki-version-line{font-family:var(--font-mono);font-size:13px;line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere;min-width:0;max-width:100%;align-self:stretch}
.wiki-version-line--add{color:var(--color-status-success);background:var(--color-status-success-bg)}
.wiki-version-line--del{color:var(--color-status-error);background:var(--color-status-error-bg)}
diff --git a/web/src/shell/feed/FeedPage.test.tsx b/web/src/shell/feed/FeedPage.test.tsx
index 26b9bbe..b3d6e46 100644
--- a/web/src/shell/feed/FeedPage.test.tsx
+++ b/web/src/shell/feed/FeedPage.test.tsx
@@ -159,6 +159,13 @@ describe("лента изменений", () => {
expect(await screen.findAllByTestId("feed-group")).toHaveLength(1);
});
+ it("I-1 (П-11): у вики сообщение, у Jira за период пусто — и сообщение вики, и «за период изменений нет»", async () => {
+ hub(() => ({ changes: [] }), () => ({ history_at: null }));
+ open("/app/feed?project=AWPCA");
+ expect(await screen.findByText("история вики ещё не загружена — нужен eva-agent v2")).toBeInTheDocument();
+ expect(await screen.findByText("за период изменений нет")).toBeInTheDocument();
+ });
+
it("«Ошибка одного источника»: /wiki/changes 500 — события Jira показаны, «Вики: …» и «Повторить» перезапрашивает только вики", async () => {
let fail = true;
const calls = hub(() => ({ changes: [ev({})] }), () => fail ? json(500, { error: "boom", detail: "сбой" }) : { changes: [wc()] });
diff --git a/web/src/shell/feed/FeedPage.tsx b/web/src/shell/feed/FeedPage.tsx
index 69e525a..17d0c38 100644
--- a/web/src/shell/feed/FeedPage.tsx
+++ b/web/src/shell/feed/FeedPage.tsx
@@ -52,7 +52,7 @@ export function FeedPage({ project }: { project: Project }) {
// группы всех выбранных источников одним списком по времени, новые сверху; при равенстве — порядок модулей (сортировка устойчива)
const groups = shown.flatMap(({ m, r }) => r.groups.map((g) => ({ ...g, key: `${m.name}:${g.key}` })))
.sort((a, b) => time(b.at) - time(a.at));
- const settled = shown.length > 0 && shown.every(({ r }) => !r.pending && !r.error && !r.notice);
+ const settled = shown.length > 0 && shown.every(({ r }) => !r.pending && !r.error) && shown.some(({ r }) => !r.notice); // П-11
return (