feat: editor language menu, title field, header actions, publish dialogs, read-only rendering and draft recovery
This commit is contained in:
1 parent
a671b81f80
commit
339e646eb8
85 files changed
+6369
-624
No files matched your search
@@ -15,8 +15,10 @@ Feature: Editor screen — load, edit and save an article's body
|
||||
/article (mobile top bar title "Edit article" instead), an ArticleStatusBadge size "md"
|
||||
reflecting article.is_online ("Draft" or "Online"), a SaveStatus span, a Save button,
|
||||
and a PublishControl button, per docs/design/components.md
|
||||
And the article's title is never editable after creation, per
|
||||
features/article_title_rules.feature; only the body is edited here
|
||||
And the title is an editable field labelled "Title" ("Title (French)" when the site has more
|
||||
than one enabled language), per features/localization_editor_navigation.feature, which
|
||||
supersedes features/article_title_rules.feature's "never editable"; the body is edited in
|
||||
ArticleEditor
|
||||
And the body is edited in ArticleEditor (modelValue bound to the fetched HTML body); any
|
||||
change moves useArticleDraft's state from "clean" to "dirty", and PublishControl's label
|
||||
switches from "Publish" (or "Unpublish", if online) to "Save and publish" while dirty and
|
||||
@@ -32,17 +34,21 @@ Feature: Editor screen — load, edit and save an article's body
|
||||
And a successful save (200) sets useArticleDraft's state to "saved" and records the save
|
||||
time; SaveStatus shows "Saved at {HH:MM}" for the first hour and "Saved {n} min ago" after
|
||||
an hour has passed, per docs/design/components.md
|
||||
And the Save button reads "Save" for every caller allowed to edit; the "Save draft" label of
|
||||
callers who cannot publish no longer exists
|
||||
And a 500 response or a request that never reaches the server sets useArticleDraft's state
|
||||
to "error"; SaveStatus shows "Save failed" with an inline Retry button (UButton size="xs"
|
||||
variant="outline"); the edited body is kept exactly as typed, both in the editor and for
|
||||
the next Retry
|
||||
to "error"; SaveStatus shows "Save failed" and the header's primary button reads "Try saving
|
||||
again", per features/localization_editor_navigation.feature (the inline Retry button of
|
||||
SaveStatus is no longer rendered in the editor); the edited body is kept exactly as typed,
|
||||
both in the editor and for the next retry
|
||||
And a 404 response to a save (the article was deleted elsewhere) does not use the "error"
|
||||
SaveStatus; it shows a toast "That article no longer exists.", per docs/design/states.md's
|
||||
HTTP-status-to-copy table
|
||||
And a 401 response to a save is handled by useApi's global handling
|
||||
(features/api_client_global_error_handling.feature): before the redirect, useArticleDraft
|
||||
mirrors the current dirty body to sessionStorage keyed by the article's id, so it survives
|
||||
the redirect to /login?redirect=/article/{id}/edit&reason=expired
|
||||
mirrors the current dirty title, body and search fields to sessionStorage keyed by the user
|
||||
id and the article id, with the time of the mirror, so it survives the redirect to
|
||||
/login?redirect=/article/{id}/edit&reason=expired
|
||||
And EditorStatusBar shows a neutral "{words} words · {characters} characters" count with
|
||||
en-US thousands separators (e.g. "1,204 words · 7,318 characters", "0 words · 0 characters"
|
||||
for an empty body); characters is the body's HTML string length, words are the
|
||||
@@ -65,10 +71,11 @@ Feature: Editor screen — load, edit and save an article's body
|
||||
proceeds with the navigation, discarding the edit; "Keep editing" closes the dialog and
|
||||
keeps the user on the editor with the edit intact; navigating away while "clean" or
|
||||
"saved" never opens this dialog
|
||||
And an id absent from the repository (GET resolves 404) replaces the entire editor with an
|
||||
error state: title "This article doesn't exist.", and a single action "All articles"
|
||||
navigating to /article; no breadcrumb-title, SaveStatus, Save, PublishControl or
|
||||
ArticleEditor renders in this state
|
||||
And an id absent from the repository (GET resolves 404) replaces the entire editor with the
|
||||
Version unavailable state: title "This version isn't available", text "It may have been
|
||||
deleted, or you may not have access.", and a single action "Back to Articles" navigating
|
||||
to /article; no header, SaveStatus, Save, PublishControl or ArticleEditor renders in this
|
||||
state
|
||||
And skeleton placeholders (for the title, content and details) replace the editor's content
|
||||
only after 150 ms of GET /v1/article/{id} being unresolved, so a fast response never
|
||||
flashes a skeleton, per the Skeleton component spec
|
||||
@@ -132,12 +139,12 @@ Feature: Editor screen — load, edit and save an article's body
|
||||
When more than an hour has passed with no further edit or save
|
||||
Then SaveStatus reads "Saved {n} min ago" instead of "Saved at 11:02"
|
||||
|
||||
Scenario Outline: Save failed — a 500 or a network failure keeps the changes and offers Retry
|
||||
Scenario Outline: Save failed — a 500 or a network failure keeps the changes and offers Try saving again
|
||||
Given the user is on /article/12/edit with unsaved changes to the body "Revised opening
|
||||
paragraph."
|
||||
When the user activates Save
|
||||
And PATCH /v1/article/12 <failure>
|
||||
Then SaveStatus reads "Save failed" with a Retry button
|
||||
Then SaveStatus reads "Save failed" and the primary button reads "Try saving again"
|
||||
And the editor still shows the body "Revised opening paragraph."
|
||||
And no navigation occurs
|
||||
|
||||
@@ -149,7 +156,7 @@ Feature: Editor screen — load, edit and save an article's body
|
||||
Scenario: Retry resends the same body and can recover
|
||||
Given the user is on /article/12/edit in the Save failed state, with unsaved body "Revised
|
||||
opening paragraph." and PATCH /v1/article/12 having failed with a 500
|
||||
When the user activates Retry
|
||||
When the user activates "Try saving again"
|
||||
Then PATCH /v1/article/12 is sent again with JSON {"body": "Revised opening paragraph."}
|
||||
When it resolves 200 with the updated article
|
||||
Then SaveStatus reads "Saved at {current time}"
|
||||
@@ -214,7 +221,7 @@ Feature: Editor screen — load, edit and save an article's body
|
||||
When the user activates Save
|
||||
And PATCH /v1/article/12 resolves 401
|
||||
Then the body "Paragraph added just before the session expired." is mirrored to
|
||||
sessionStorage keyed by article id 12
|
||||
sessionStorage keyed by user id and article id 12
|
||||
And the app navigates to /login?redirect=/article/12/edit&reason=expired
|
||||
When the user logs in again and is returned to /article/12/edit
|
||||
And GET /v1/article/12 resolves 200 with the last-saved body (without that paragraph)
|
||||
@@ -225,8 +232,8 @@ Feature: Editor screen — load, edit and save an article's body
|
||||
Scenario: An unknown or deleted article id replaces the editor with an error state
|
||||
Given GET /v1/article/9999 resolves 404
|
||||
When the user navigates to /article/9999/edit
|
||||
Then the editor shows a single error state: title "This article doesn't exist." and one
|
||||
action "All articles"
|
||||
And no breadcrumb-title, SaveStatus, Save, PublishControl or ArticleEditor renders
|
||||
When the user activates "All articles"
|
||||
Then the editor shows a single Version unavailable state: title "This version isn't
|
||||
available" and one action "Back to Articles"
|
||||
And no header, SaveStatus, Save, PublishControl or ArticleEditor renders
|
||||
When the user activates "Back to Articles"
|
||||
Then the app navigates to /article
|
||||
Reference in new issue
Block a user