Slice 2: the §8 active-RFC view in full
Per the §19.1 brief: the three-column shape (§8.1) opens on main
in discuss mode (§8.2), supports the §8.3 discuss-vs-contribute
flip on non-main branches, hosts §8.4's per-branch chat with AI
participation (§18's <change> protocol → §8.14 changes rows), the
§8.8 change-card panel with §8.9 accept/decline/edit-before-accept,
the §8.10 tracked-change markup + DiffView toggle, the §8.11
manual-edit flushes with the stale-change mechanic, the §8.12
range and paragraph sub-threads, the §8.13 flag affordance, and
the §8.14 discuss-mode buffer.
Backend: bot.py grew per-RFC-repo write ops (cut_branch_from_main,
commit_accepted_change with the structured original/proposed/reason
body and Change-Id + Source-Message-Id + On-behalf-of trailers,
commit_manual_flush, ensure_rfc_repo_seed). cache.py grew
refresh_rfc_repo and the webhook dispatches on repository.full_name.
providers.py and chat.py port the §18 carryovers — multi-provider
LLM abstraction and SSE-streaming chat against the §5 threads /
thread_messages / changes schema. api_branches.py mounts the §17
branches/<branch>/* and threads/<thread_id>/* routes with the §6
/ §11 permission checks inline.
Frontend: RFCView.jsx rebuilt as the §8 surface; Editor.jsx,
ChatPanel.jsx, ChangePanel.jsx, PromptBar.jsx, SelectionTooltip.jsx,
DiffView.jsx, ModelPicker.jsx, modelStyles.js lifted from the
prototype and adapted to the canonical schema.
Covered by `backend/tests/test_rfc_view_vertical.py` — eleven new
integration tests against an extended FakeGitea (PUT contents,
POST orgs/{org}/repos, seed_rfc_repo): main-view read,
promote-to-branch, accept (with and without edit-before-accept),
decline, manual flush + system message, flag creation, visibility
flip, anonymous read-but-no-contribute, stale-change refusal, and
the chat-streaming path with a fake provider injected. The 5
Slice 1 tests continue to pass alongside.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
// PromptBar.jsx — the §8.1 prompt-bar at the bottom of the center column.
|
||||
//
|
||||
// Carryover from the prototype. In discuss mode the contributor types
|
||||
// to talk; in contribute mode the model is told to lean toward concrete
|
||||
// edits. The selection-quote machinery is preserved — a passage
|
||||
// highlighted in the editor surfaces here as a "scoped to selection"
|
||||
// badge and travels to the backend with the message.
|
||||
|
||||
import { useState } from 'react'
|
||||
import ModelPicker from './ModelPicker.jsx'
|
||||
|
||||
export default function PromptBar({
|
||||
selection,
|
||||
onSubmit,
|
||||
disabled,
|
||||
models,
|
||||
selectedModel,
|
||||
onModelChange,
|
||||
discussMode = false,
|
||||
placeholder,
|
||||
}) {
|
||||
const [prompt, setPrompt] = useState('')
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!prompt.trim() || disabled) return
|
||||
onSubmit(prompt.trim(), selection)
|
||||
setPrompt('')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="prompt-bar">
|
||||
{selection && (
|
||||
<div className="selection-badge">
|
||||
<span className="selection-icon">✦</span>
|
||||
Scoped to selection — "{selection.slice(0, 80)}{selection.length > 80 ? '…' : ''}"
|
||||
</div>
|
||||
)}
|
||||
<div className="prompt-row">
|
||||
{models?.length > 1 && (
|
||||
<ModelPicker models={models} selected={selectedModel} onChange={onModelChange} />
|
||||
)}
|
||||
<textarea
|
||||
className="prompt-input"
|
||||
value={prompt}
|
||||
onChange={e => setPrompt(e.target.value)}
|
||||
onKeyDown={e => {
|
||||
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSubmit() }
|
||||
}}
|
||||
placeholder={
|
||||
placeholder ?? (
|
||||
selection ? 'Ask anything about the selected text…'
|
||||
: discussMode ? 'Ask anything about this RFC…'
|
||||
: 'Ask anything or propose changes…'
|
||||
)
|
||||
}
|
||||
disabled={disabled}
|
||||
rows={1}
|
||||
/>
|
||||
<button className="prompt-submit" onClick={handleSubmit} disabled={!prompt.trim() || disabled}>
|
||||
Ask
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user