Implement approved specification #32 and tickets #33-#37. Keep host authentication server-verified and pin session interaction language. Compile scoped base selectors for browser compatibility and retain full gutters during CSS pruning.
43 lines
3.8 KiB
TypeScript
43 lines
3.8 KiB
TypeScript
import { useI18n } from "../i18n";
|
|
import { useState } from "react";
|
|
import { ChevronDown, Cpu, Layers, LockKeyhole, SlidersHorizontal } from "lucide-react";
|
|
import { Button } from "../components/ui/button";
|
|
import type { useWorkingContext } from "../workspaces/WorkingContext";
|
|
import "./WorkingContextShelf.css";
|
|
|
|
export function WorkingContextShelf({ context, locked, onWorkspace, onModel }: {
|
|
context: ReturnType<typeof useWorkingContext>; locked: boolean;
|
|
onWorkspace: (id: string) => void; onModel: (id: string) => void;
|
|
}) {
|
|
const { t: translate } = useI18n();
|
|
const [expanded, setExpanded] = useState(false);
|
|
const open = expanded || !context.ready;
|
|
return <section className="thot-context-shelf" aria-label={translate("Global working context")}>
|
|
<button className="thot-context-trigger" aria-expanded={open} aria-controls="thoth-working-context"
|
|
onClick={() => setExpanded(!open)}>
|
|
<SlidersHorizontal size={18} aria-hidden />
|
|
<span className="thot-context-summary"><small>{translate("WORKING CONTEXT")}</small><strong>{context.workspace?.displayName ?? translate("Choose workspace")}<span aria-hidden> / </span>{context.model?.name ?? translate("Choose model")}</strong></span>
|
|
<span className="thot-context-action">{locked && <LockKeyhole size={15} aria-hidden />}<span>{locked ? translate("Locked") : open ? translate("Close") : translate("Change context")}</span><ChevronDown size={16} aria-hidden /></span>
|
|
</button>
|
|
<div id="thoth-working-context" hidden={!open} className="thot-context-body">
|
|
<p className="thot-context-explanation">{translate("Your last choices take precedence over installation defaults. Workspace and model are remembered independently.")}</p>
|
|
<div className="thot-context-fields">
|
|
<label><span><Layers size={15} aria-hidden />{translate("Workspace")}</span>
|
|
<select aria-label={translate("Workspace")} value={context.workspace ? context.workspaceId : ""} disabled={locked || context.loading} onChange={event => onWorkspace(event.target.value)}>
|
|
<option value="" disabled>{translate("Choose a workspace")}</option>{context.workspaces.map(workspace => <option key={workspace.id} value={workspace.id}>{workspace.displayName}</option>)}
|
|
</select><small>{translate(context.origins.workspace)}</small>
|
|
</label>
|
|
<label><span><Cpu size={15} aria-hidden />{translate("AI interaction model")}</span>
|
|
<select aria-label={translate("Model")} value={context.model ? context.modelId : ""} disabled={locked || context.loading} onChange={event => onModel(event.target.value)}>
|
|
<option value="" disabled>{translate("Choose a model")}</option>{context.models.map(model => <option key={`${model.provider}/${model.id}`} value={`${model.provider}/${model.id}`}>{model.name}</option>)}
|
|
</select><small>{translate(context.origins.model)}</small>
|
|
</label>
|
|
</div>
|
|
{locked && <p role="status">{translate("Workspace and model are locked until the current operation finishes.")}</p>}
|
|
{context.ready && context.error && <p role="status">{translate("Context refresh failed. Your current choices and unsaved work have been retained.")}</p>}
|
|
{!context.ready && <p role="status">{context.loading ? translate("Loading working context…") : context.error ? translate("Working context is unavailable. Retry or ask the installation operator to check configuration.") : translate("Select an available workspace and model to enable Core and Administration. Unavailable saved choices are not replaced automatically.")}</p>}
|
|
<div className="thot-context-footer">{context.error && <Button variant="outline" onClick={context.retry}>{translate("Retry context")}</Button>}{context.ready && <Button variant="outline" onClick={() => setExpanded(false)}>{translate("Done")}</Button>}</div>
|
|
</div>
|
|
</section>;
|
|
}
|