Repository navigation
feat: direct-submit UI, chat flag, licence lane on community writes - #45
Merged
Merged
Conversation
… /topics proxy, chat flag Adds the PHP-side plumbing for the v1 direct-submit flow (chat-free question/bug/feature-request submissions moderated in the hub dashboard): - Consumer::email(): ?string — feeds hub-side subject identity, never public. - Config::$enableChat (default false) — the boot payload's chat-availability flag; when false, Roundtable::mount() no longer registers the chat/message REST routes (message, history, stream, session reset, case draft-from-chat). Cases/comments/votes/publish/topics routes always stay registered. - HubClient::submitTopic() — POSTs /cases/direct with subject_id/type/title/ body plus the Consumer's email/metadata/client_version/licence; hub's 402 maps to the existing licence-invalid exception kind via the shared guard. - TopicController — new POST <ns>/topics REST proxy mirroring PublishController's gating/error-mapping conventions. - Admin\Page now localizes chatEnabled alongside the existing chatDisabled (hub-paused) flag for Task 4's UI to consume. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…dialog Chat panel, launch button, and backdrop now only render when RoundtableConfig.chatEnabled is true (Task 3's boot flag); with it false (the v1 default) the topics feed takes the full width and the "+ New topic" button opens the existing PublishDialog in a new empty "direct" variant (empty type selector, title, free-text body) instead of the chat panel. Direct mode shows the moderation notice above the submit button and POSTs to the new /topics proxy; on success it closes the dialog, refreshes the lists, and switches to the Started tab, matching the existing chat-drafted publish flow. Licence/quota errors render inline via the same notice styling. Chat code stays in the bundle — this is a render switch, not a deletion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… off The empty-state copy in StartedList always said "Use <agent> on the right to draft one", but with chatEnabled=false (the v1 default) there's no chat panel on the right — and this tab is exactly where the new direct-submit flow lands after a successful submission. Extract the message into emptyStateMessage(chatOn, agentName) and switch copy based on config.js's chatEnabled(): chat on keeps the existing sentence, chat off points at the "+ New topic" button instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ed composer avatar Two approved fixes from Robbert's live test round: 1. A pending (unapproved) case's votes and comments are refused hub-side (403), but the detail view and list rows still rendered VoteControl (fetches the vote tally on mount) and, on the detail view, fetched comments and rendered the comment composer — posting showed "Could not post. Try again." and the console filled with 403s. VoteControl is now replaced by a new non-interactive StaticVote (no fetch) for any topic.isPending row/detail, shared by TopicRow (covers all list contexts: all/participating/roadmap/ started) and TopicDetail. TopicDetail also skips the loadComments fetch entirely for a pending topic and shows one quiet line, "Comments open once this topic is approved.", in place of the comments list/composer. Draft rows are untouched (they never rendered VoteControl). 2. The comment composer rendered a hardcoded PersonAvatar initials="Y", while every other rendered identity in the app uses handle initials — read as two different people. Removed the composer's avatar (and its now-orphaned rt-addwrap/rt-you-ava CSS); the editor now spans the full width of the card like the rest of its layout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, composer back Robbert's browser review of the previous fix: a bare vote number next to rows that still show the full arrow stack read as broken, and hiding the comment composer entirely felt like more was missing than intended. Rework per his direction: - vote-control.jsx: StaticVote is now DisabledVote — same up-arrow / count / down-arrow markup as VoteControl, but the buttons carry disabled + aria-disabled and no click handlers, so pending rows and the pending detail header look structurally identical to a published one, just inert. Still no fetchVoteTally() call. - topic-detail.jsx: the comment composer is back for a pending topic (textarea usable as normal) with only its submit button disabled; the "Comments open once this topic is approved." notice now sits directly above the composer instead of replacing the whole comments section. The comments list/header stay hidden (no fetchComments call — still no 403s) since there's nothing fetched to show. - comment-editor.jsx: added a submitDisabled prop that forces the submit button off and blocks the Cmd/Ctrl+Enter submit shortcut, independent of the existing posting/text-empty checks. Draft rows and the no-fetch behavior for pending votes/comments are unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pre-release trust hardening (hub side, parallel task): comment create and
vote cast now enforce the licence gate like the chat message and direct-
submit paths, with 402 denial. Mirrors HubClient::submitTopic's approach:
- HubClient::createComment() / castVote() now send the licence payload
(licenceField()) and the Consumer's email (emailField(), omit-when-null),
reusing the same helpers submitTopic already uses. retractVote() and
getVoteTally() are untouched (no body, no licence needed).
- CommentsController / VotesController map hub 402 to the existing
licence-invalid exception kind at the same status/shape the topics proxy
uses (added the missing LICENCE_INVALID => 402 arm to each statusFor()).
Scope note: the coordinator's brief also named "comment UPDATE" for licence
hardening. Verified against the codebase: no comment-update (or delete)
client method, REST route, or UI caller exists anywhere in this SDK today
(only create + list). The hub already has PATCH /cases/{id}/comments/{id}
(pre-existing, unrelated to this hardening task), but wiring it up would
mean adding a new Transport HTTP verb plus a new REST proxy route — new
feature surface, not "send an existing request one more field" — so it's
left out of this change pending explicit confirmation that's wanted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Approved pre-release cut: drop the banner entirely, no replacement copy. .rt-banner CSS stays — still used by the pending-topic detail banner (rt-banner-pending). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Simplified Community v1, SDK side. Built and reviewed via the SDD run of 2026-09-19/20 (task reviews, scoped re-reviews, opus whole-branch review, plus Robbert's live browser round).
Consumer::email()(breaking interface addition),Config::enableChat(default false): with chat off, no chat UI renders and the chat-only REST proxy routes are not registered; feed goes full-width.POST <ns>/topicsproxy → hub/cases/direct; 402 maps to the licence-invalid kind.Tests: PHP 166/166, JS 145/145, phpcs + phpstan clean; bundle rebuilt and committed.
🤖 Generated with Claude Code