feat: show the way to publish, and what is blocking it, in the editor

Publishing was reachable only by walking the whole chain blind. The editor
offered one link — "저장본 검증" — and the word "게시" appeared nowhere until
three screens later, so an author with a finished draft could not tell how to
publish it. The working-copy list already named the next step, but the name was
plain text with nowhere to go.

The editor now shows the whole path: 검증 → 미리보기 → 게시, each a link. The
list's next step is a link to that step. Neither weakens the gates — an
unvalidated document is still refused at preview, an unpreviewed one at
publish. What changes is that the order stops being a secret.

What is blocking publication now appears where it gets fixed. The validation
report lived on its own screen, so an author read the list, navigated back, and
had to remember which field each item meant. The editor shows the same issues
above the fields, in red, and says plainly when they describe an older saved
version rather than the current one.

The clock is read during render, not captured as an effect dependency. It is a
new function on every render of the provider, so depending on it refetched the
document endlessly — the editor never settled, and a tab click did not even
register. A value you are asking about now does not belong in a dependency
array.
This commit is contained in:
DongHyeonka
2026-08-21 18:43:10 +09:00
parent fb478f951b
commit 7345500ef3
7 changed files with 153 additions and 7 deletions
@@ -104,10 +104,18 @@ describe("TechLog Studio document editor", () => {
expect(screen.getByRole("complementary", { name: "작업 상태" })).toHaveTextContent(
"저장 버전4종류CASE",
);
expect(screen.getByRole("link", { name: "저장본 검증" })).toHaveAttribute(
"href",
`/studio/documents/${FIXTURE_IDS.redisAdapterCase}/validation`,
);
// 편집기는 다음 한 칸이 아니라 게시까지의 길을 보여 준다. 예전에는 "저장본 검증" 하나뿐이라,
// 작성자가 그 단계를 밟아 본 뒤에야 뒤에 미리보기와 게시가 있다는 것을 알 수 있었다.
const flow = screen.getByRole("navigation", { name: "게시까지의 단계" });
expect(
within(flow)
.getAllByRole("link")
.map((link) => [link.textContent, link.getAttribute("href")]),
).toEqual([
["검증", `/studio/documents/${FIXTURE_IDS.redisAdapterCase}/validation`],
["미리보기", `/studio/documents/${FIXTURE_IDS.redisAdapterCase}/preview`],
["게시", `/studio/documents/${FIXTURE_IDS.redisAdapterCase}/publish`],
]);
const editTab = screen.getByRole("tab", { name: "편집" });
const previewTab = screen.getByRole("tab", { name: "즉시 미리보기" });