Skip to content

feat(FR-3223): allow editing the system announcement from the WebUI#8067

Draft
agatha197 wants to merge 18 commits into
mainfrom
feat/FR-3223-edit-announcement
Draft

feat(FR-3223): allow editing the system announcement from the WebUI#8067
agatha197 wants to merge 18 commits into
mainfrom
feat/FR-3223-edit-announcement

Conversation

@agatha197

@agatha197 agatha197 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Resolves #8066 (FR-3223)

Draft: the enabled flag is not persistable on the current manager (see Notes), so the Enabled toggle is replaced by an explicit Delete action for now.

Summary

  • Add a superadmin-only edit flow for the system announcement, surfaced directly on the announcement alert where it is shown.
  • BAICodeEditor: add a markdown language (Monaco) so the message can be authored with markdown highlighting.
  • AnnouncementEditModal (new): markdown code editor + a live preview rendered with the same markdown-to-jsx setup as the alert. Publishes via baiClient.service.update_announcement and invalidates the get_announcement query so the alert refreshes immediately.
  • Footer Delete action: the footer now carries a danger Delete button (left) alongside Cancel/Publish (right), following the ShellScriptEditModal layout but inlined with BAIFlex. Delete clears the announcement and is guarded by a Popconfirm; it is disabled when nothing is stored.
  • AnnouncementAlert: show an Edit button on the alert for superadmins only, opening the modal.
  • i18n: add announcement-edit strings across all locales (incl. AnnouncementDeleted).

Notes

  • Why the Enabled toggle is gone: the manager stores the announcement purely by presence — update_announcement(enabled=true, message) puts the message in etcd, and update_announcement(enabled=false, …) deletes it. There is no way to persist a disabled-but-present announcement, so the Enabled checkbox could not work. The toggle implementation is kept in AnnouncementEditModal (commented out) so it can be restored once the backend can persist the flag.
  • Delete = disable: the Delete button issues update_announcement(false, ''), which is exactly the operation the disable path performed.
  • The edit button is gated to superadmin because the manager POST /manager/announcement endpoint is superadmin_required — a regular admin would receive 403.
  • The button lives on the existing alert, which only renders when an announcement message is present.

Test plan

  • As superadmin, open the start page with an existing announcement → Edit button is visible on the alert.
  • Click Edit → modal opens with the current message prefilled and a live markdown preview.
  • Edit the markdown and Publish → success toast, alert refreshes with the new content.
  • Click Delete → confirm → announcement is cleared and the alert disappears.
  • With no announcement stored, the Delete button is disabled.
  • As a non-superadmin, the Edit button is not shown.

Verification

bash scripts/verify.sh → Relay / Lint / Format PASS. (TypeScript reports a pre-existing, unrelated FluentEmojiIcon.tsx error caused by a worktree patched-dep symlink; not part of this change.)

Screenshot

Enlarged announcement edit modal (markdown editor + live preview, side by side):

image.png

@github-actions github-actions Bot added area:ux UI / UX issue. area:i18n Localization size:L 100~500 LoC labels Jun 29, 2026

agatha197 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • flow:merge-queue - adds this PR to the back of the merge queue
  • flow:hotfix - for urgent changes, fast-track this PR to the front of the merge queue

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has required the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@agatha197 agatha197 marked this pull request as ready for review June 29, 2026 04:59
Copilot AI review requested due to automatic review settings June 29, 2026 04:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a superadmin-only UI flow to edit the system announcement directly from the start-page announcement alert, including a markdown-capable code editor and live preview, and persists changes via the existing manager API.

Changes:

  • Added AnnouncementEditModal with an enabled toggle, markdown editor, preview, and save/invalidate flow.
  • Updated AnnouncementAlert to show an Edit action for superadmins and open the edit modal.
  • Extended BAICodeEditor to support Monaco’s markdown language and added i18n strings (en/ko).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
resources/i18n/ko.json Adds Korean strings for the announcement edit UI.
resources/i18n/en.json Adds English strings for the announcement edit UI.
react/src/components/BAICodeEditor.tsx Adds markdown to supported editor languages and Monaco language mapping.
react/src/components/AnnouncementEditModal.tsx New modal for editing announcement content with markdown preview and saving via update_announcement.
react/src/components/AnnouncementAlert.tsx Adds superadmin-gated Edit button and wires modal opening from the alert.

Comment thread react/src/components/AnnouncementEditModal.tsx Outdated
Comment thread react/src/components/AnnouncementAlert.tsx
Comment thread resources/i18n/en.json
Comment thread resources/i18n/ko.json
@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for react-coverage (./react)

Status Category Percentage Covered / Total
🔵 Lines 7.16% 2115 / 29528
🔵 Statements 5.91% 2418 / 40894
🔵 Functions 6.06% 349 / 5756
🔵 Branches 3.91% 1509 / 38515
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
react/src/components/AnnouncementAlert.tsx 0% 0% 0% 0% 18-28
react/src/components/AnnouncementEditModal.tsx 0% 0% 0% 0% 55-541
react/src/components/BAICodeEditor.tsx 0% 0% 0% 0% 13-82
react/src/hooks/useSuspenseGetAnnouncement.tsx 0% 0% 0% 0% 17-29
Generated in workflow #2734 for commit 39f74fd by the Vitest Coverage Report Action

Comment thread react/src/components/AnnouncementMarkdown.tsx Outdated
Comment thread react/src/hooks/useSuspenseGetAnnouncement.tsx
@agatha197 agatha197 force-pushed the feat/FR-3223-edit-announcement branch from 5d71df8 to fff7f6f Compare June 29, 2026 14:17
@agatha197

Copy link
Copy Markdown
Contributor Author

Also addressed the suggestion from the Teams thread: AnnouncementEditModal now reads the announcement via useSuspenseGetAnnouncement directly (under a Suspense boundary) instead of receiving initialMessage/initialEnabled from the parent. As a result MaintenanceSettingList no longer fetches get_announcement just to prefill the modal.

@agatha197 agatha197 requested a review from nowgnuesLee June 29, 2026 14:17
Comment thread react/src/hooks/useSuspenseGetAnnouncement.tsx
@agatha197 agatha197 force-pushed the feat/FR-3223-edit-announcement branch from fff7f6f to 68b42c8 Compare June 30, 2026 09:08
@agatha197 agatha197 requested a review from nowgnuesLee June 30, 2026 09:09

@nowgnuesLee nowgnuesLee left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@agatha197 agatha197 requested a review from yomybaby July 2, 2026 02:27
@github-actions github-actions Bot added size:XL 500~ LoC and removed size:L 100~500 LoC labels Jul 3, 2026
@agatha197 agatha197 force-pushed the feat/FR-3223-edit-announcement branch from 84fda1a to dfd8144 Compare July 7, 2026 08:35

@ironAiken2 ironAiken2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Markdown formatting for 'quotes, code and lists' is not applied.

@agatha197 agatha197 force-pushed the feat/FR-3223-edit-announcement branch from dfd8144 to 9d1c3fc Compare July 8, 2026 08:13

Copy link
Copy Markdown
Contributor Author

Markdown formatting for 'quotes, code and lists' is not applied.

​I applied it.

@agatha197 agatha197 requested a review from ironAiken2 July 8, 2026 08:29
agatha197 and others added 17 commits July 10, 2026 07:09
Add a superadmin-only edit flow for the system announcement, surfaced
directly on the announcement alert where it is displayed.

- BAICodeEditor: add 'markdown' language so the message can be authored
  with Monaco's markdown support.
- AnnouncementEditModal: new modal with an enabled toggle, a markdown
  code editor, and a live preview rendered with the same markdown-to-jsx
  setup as the alert. Saves via baiClient.service.update_announcement and
  invalidates the announcement query so the alert refreshes immediately.
- AnnouncementAlert: show an Edit button on the alert for superadmins
  only (the manager update endpoint is superadmin-only) that opens the
  modal.
- i18n: add the announcement-edit strings (en, ko).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Address PR review feedback:
- Pass initialEnabled from the announcement query and initialize the
  modal's enabled toggle from it, so the switch reflects the server's
  current state instead of always defaulting to true.
- Wrap the modal in BAIUnmountAfterClose so it remounts on each open;
  this drops the manual useEffect re-sync and removes the stale-state
  class of bugs (the useState initializers are now the single source).
- Add the new summary.* announcement keys to all remaining locales.
…eview

- Block saving (with an inline error) when the announcement is enabled
  but the message is empty, mirroring the backend constraint ("Empty
  message not allowed to enable announcement"); mark the message field
  required while enabled.
- Lay the markdown editor and live preview side by side (editor left,
  preview right) and widen the modal, matching the conventional markdown
  editor UX.
- i18n: add summary.AnnouncementMessageRequired across all locales.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Mark the Enabled and Preview fields as required so the form's
  "(optional)" suffix no longer renders on them.
- Make the preview box padding visually even on all sides by collapsing
  the first/last block margins via a scoped style, instead of the
  negative bottom-margin trick.
- Remove the "Markdown syntax is supported." help text and its now-unused
  summary.AnnouncementMarkdownHelp key across all locales.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…n renderer

- Add useSuspenseGetAnnouncement hook + ANNOUNCEMENT_QUERY_KEY constant so
  the get_announcement query and its key live in one place (also used for
  cache invalidation in the edit modal), removing the duplicated query.
- Add AnnouncementMarkdown component and use it in both the alert and the
  modal preview, replacing two divergent markdown-rendering blocks with a
  single shared, margin-collapsed renderer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the manual message/enabled useState + onOk guard with a
Form.useForm() instance:
- name-bound fields (Switch via valuePropName, BAICodeEditor as a
  controlled field) so the form store is the single source of truth.
- declarative validation: the "message required when enabled" rule lives
  on the field (dependencies on enabled) and shows an inline error
  instead of a toast.
- the live preview and the required marker read from Form.useWatch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… state

Replace the useState open/close flag in AnnouncementAlert with ahooks
useToggle, matching the project idiom (e.g. ConfigurationsSettingList):
the toggle handler drives both the Edit button and onRequestClose.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The preview was a content-box div, so its padding/border made it taller
than the markdown editor. Set box-sizing: border-box and size it to the
editor's outer height (shared EDITOR_HEIGHT constant + the wrapper border)
so both boxes line up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Widen the modal to 90% / max 1900px (matching FolderExplorerModalV2) and
grow the editor/preview to a viewport-relative height so there is ample
room to author and preview markdown side by side.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Address review feedback (seungwon):
- AnnouncementEditModal now reads the announcement via
  useSuspenseGetAnnouncement directly (under a Suspense boundary) instead
  of receiving initialMessage/initialEnabled props from the parent.
- Rename the hook file to useSuspenseGetAnnouncement.tsx to match its
  primary export.
- Drop the shared AnnouncementMarkdown component; render the markdown
  inline in the alert and the modal preview.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per review (seungwon): factor the announcement queryKey + queryFn into a
TanStack queryOptions factory (announcementQueryOptions) and keep
useSuspenseGetAnnouncement as the primary hook built on top of it. Cache
invalidation reads the key from the same factory instead of a separate
constant.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…bar and velog-style preview

- Move the announcement Enabled switch out of the body into the modal header (top-right, next to the close button) as a controlled Switch synced to the form field via a hidden registered Form.Item.
- Add a velog-style formatting toolbar (heading, bold, italic, strikethrough, quote, code, link, image, lists) above the Monaco markdown editor, operating on the editor selection via the Monaco API.
- Replace the markdown-to-jsx preview with react-markdown + remark-gfm / remark-math / rehype-katex and the shared shiki SyntaxHighlighter, with velog-like reading typography.
- Bold the Message / Preview field labels.
- Add en/ko i18n keys for the toolbar tooltips.
…h button

Replace the header Enabled switch with a footer checkbox (left) plus Cancel / Publish buttons (right), matching the DeploymentAddRevisionModal footer pattern. Removes the modal-title full-width workaround. Adds button.Publish (en: Publish, ko: 발행하기).
… all locales

Fill in the 11 new keys (button.Publish + summary.Markdown* toolbar labels) for the 19 remaining languages (de, el, es, fi, fr, id, it, ja, mn, ms, pl, pt-BR, pt, ru, th, tr, vi, zh-CN, zh-TW). en/ko already had them.
The Enabled toggle lives in the modal footer (outside any <Form>), which
previously forced bridging it through the form store via a hidden Switch
field + setFieldValue + Form.useWatch, and split the fields into a separate
suspense child so the footer/title could stay visible during load.

Collapse to a single component: fetch the announcement with a non-suspense
useTanQuery (chrome renders immediately, body shows a Skeleton while loading)
and manage enabled/message as plain useState drafts that fall back to the
server value until edited. Validation (message required when enabled) becomes
a plain derived flag that disables Publish and shows an inline error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@agatha197 agatha197 force-pushed the feat/FR-3223-edit-announcement branch from 9d1c3fc to e9c1de2 Compare July 10, 2026 07:15
@agatha197 agatha197 marked this pull request as draft July 10, 2026 07:37
The manager stores the announcement purely by presence, so the `enabled` flag
cannot be persisted and its footer toggle could not work. Comment out the
toggle (kept for a future backend that can persist it) and give the footer two
explicit actions, following the Edit Bootstrap Script modal:

- Reset: clears the editor content locally (Popconfirm-guarded) so the admin
  can start over without touching the server.
- Delete: removes the published announcement via update_announcement(false, ''),
  routed through a confirm modal (not an inline Popconfirm); disabled when
  nothing is stored.

Publishing always enables (enabled=true) and requires a non-empty message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@agatha197 agatha197 force-pushed the feat/FR-3223-edit-announcement branch from f623bb2 to 39f74fd Compare July 10, 2026 09:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:i18n Localization area:ux UI / UX issue. size:XL 500~ LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow editing the system announcement from the WebUI

4 participants