swarm ui: one review page
The two review tabs, runs and try-out, are one: /review. It is a column of three sections: try a classification and the classifier settings, each a folded bar (the settings' bar says what they are now), then the recent runs, always open. The settings had been pinned under the try-out form; they are now a section of their own. A new Disclosure primitive is the folding bar, a native details wearing the Panel's classes, so the folded and open sections read as the same surface. /review-runs and /review-tryout are gone, with no redirect.
This commit is contained in:
parent
7b1435eaea
commit
a68d73fa74
2 changed files with 223 additions and 45 deletions
|
|
@ -10,7 +10,7 @@ import { useEffect, useState } from "preact/hooks";
|
|||
import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";
|
||||
import { readApiError, type ProblemDetails } from "@hive/shared/api-error.js";
|
||||
import { Button } from "../../ui/button/Button.js";
|
||||
import { Panel } from "../../ui/panel/Panel.js";
|
||||
import { Disclosure } from "../../ui/disclosure/Disclosure.js";
|
||||
import { SelectField } from "../../ui/select-field/SelectField.js";
|
||||
import { TextField } from "../../ui/text-field/TextField.js";
|
||||
import {
|
||||
|
|
@ -20,6 +20,7 @@ import {
|
|||
changed,
|
||||
draftOf,
|
||||
settingsProblem,
|
||||
settingsSummary,
|
||||
toSettings,
|
||||
type ClassifierSettingsBody,
|
||||
type Runtime,
|
||||
|
|
@ -54,6 +55,9 @@ export function ClassifierSettings() {
|
|||
const [saveError, setSaveError] = useState<ProblemDetails | null>(null);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [justSaved, setJustSaved] = useState(false);
|
||||
// Folded until wanted: the settings are changed now and then, and the
|
||||
// folded header says what they are.
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
|
@ -114,7 +118,13 @@ export function ClassifierSettings() {
|
|||
const problem = draft === null ? null : settingsProblem(draft);
|
||||
|
||||
return (
|
||||
<Panel title="classifier settings" icon="⚙️">
|
||||
<Disclosure
|
||||
title="classifier settings"
|
||||
icon="⚙️"
|
||||
hint={saved ? settingsSummary(saved) : undefined}
|
||||
open={open}
|
||||
onToggle={setOpen}
|
||||
>
|
||||
<p>
|
||||
The runtime, model and effort the review classifier runs with, and how
|
||||
many requested reviews run at once. The API key runtime runs claude on
|
||||
|
|
@ -234,6 +244,6 @@ export function ClassifierSettings() {
|
|||
) : null}
|
||||
</form>
|
||||
) : null}
|
||||
</Panel>
|
||||
</Disclosure>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,3 +182,15 @@ export function changed(
|
|||
d.priceCacheWrite.trim() !== now.priceCacheWrite)
|
||||
);
|
||||
}
|
||||
|
||||
/** The settings in force as one short line, for a folded view of them: the
|
||||
* runtime and the model it runs, the effort when one is set, and how many
|
||||
* reviews run at once. The model is the provider's under ACP. */
|
||||
export function settingsSummary(s: ClassifierSettingsBody): string {
|
||||
const model = s.runtime === "acp" ? (s.acp?.model ?? "") : s.model;
|
||||
const parts = [s.runtime, model, s.effort ? `${s.effort} effort` : ""].filter(
|
||||
(p) => p !== "",
|
||||
);
|
||||
parts.push(`${s.max_concurrent_reviews} at once`);
|
||||
return parts.join(" · ");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue