Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions apps/web/src/pages/collaborators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/
import { wording } from "../config.ts";
import { useCallback, useEffect, useState } from "react";
import { toast } from "sonner";
import { Banner, Button, QuietSelect, StateLabel } from "../components.jsx";
import { productClient } from "../api/transport.ts";
import { workspaceTenantId, type HubUser } from "../api/auth.ts";
Expand Down Expand Up @@ -108,7 +109,7 @@ export function Collaborators({ user }: { user: HubUser | null }) {
setEmail("");
await read();
} catch (cause) {
setError(await refusal(cause));
toast.error(await refusal(cause));
} finally {
setBusy(false);
}
Expand All @@ -122,7 +123,7 @@ export function Collaborators({ user }: { user: HubUser | null }) {
await client.revokeInvitation(await workspaceTenantId(), invitationId);
await read();
} catch (cause) {
setError(await refusal(cause));
toast.error(await refusal(cause));
} finally {
setBusy(false);
}
Expand Down
26 changes: 6 additions & 20 deletions apps/web/src/pages/custom-providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import type {
ModelCatalog,
ModelProvider,
} from "@corbits-builder/schemas/models";
import { Banner, Button, QuietState } from "../components.jsx";
import { Button, QuietState } from "../components.jsx";
import { keys } from "../queries/keys.ts";
import { productClient } from "../api/transport.ts";
import { workspaceTenantId } from "../api/auth.ts";
Expand Down Expand Up @@ -128,13 +128,12 @@ export function message(cause: unknown): string {
return cause instanceof Error ? cause.message : String(cause);
}

/** Title, lead, the fields, the last error, and Cancel or Back beside the dialog's action. */
/** Title, lead, the fields, and Cancel or Back beside the dialog's action. */
export function ProviderDialog(props: {
open: boolean;
onOpenChange: (open: boolean) => void;
title: string;
description: string;
error: string | null;
busy: boolean;
ready: boolean;
/** Whether submitting tests a connection first. */
Expand All @@ -148,7 +147,7 @@ export function ProviderDialog(props: {
focusDialog?: boolean;
children: ReactNode;
}) {
const { busy, error, onBack, onOpenChange } = props;
const { busy, onBack, onOpenChange } = props;
return (
<Dialog open={props.open} onOpenChange={onOpenChange}>
<DialogContent
Expand Down Expand Up @@ -178,7 +177,6 @@ export function ProviderDialog(props: {
}
>
{props.children}
{error ? <Banner tone="error" title={error} /> : null}
</DialogBody>
<DialogFooter>
<Button
Expand Down Expand Up @@ -724,12 +722,10 @@ export function CustomProviderRow({
provider,
apis,
onChanged,
onError,
}: {
provider: ModelProvider;
apis: Apis;
onChanged: () => void;
onError: (message: string | null) => void;
}) {
const [open, setOpen] = useState(false);
const listId = `custom-models-${provider.id}`;
Expand All @@ -755,7 +751,6 @@ export function CustomProviderRow({
provider={provider}
apis={apis}
onChanged={onChanged}
onError={onError}
/>
</span>
</div>
Expand All @@ -780,7 +775,6 @@ function CustomProviderModels({
provider.models.map((model) => ({ ...modelDraftOf(model), fixed: true })),
);
const [saveState, setSaveState] = useState<SaveState | null>(null);
const [error, setError] = useState<string | null>(null);
const saved = useRef(JSON.stringify(parsedModels(models)));

// Saves once the list is complete and differs from what the hub holds; a half-typed model waits.
Expand All @@ -789,7 +783,6 @@ function CustomProviderModels({
const snapshot = JSON.stringify(parsed);
if (!parsed || snapshot === saved.current) return;
setSaveState("saving");
setError(null);
try {
await productClient().updateCustomProvider(
await workspaceTenantId(),
Expand All @@ -808,7 +801,7 @@ function CustomProviderModels({
onChanged();
} catch (cause) {
setSaveState("failed");
setError(message(cause));
toast.error(message(cause));
}
};

Expand Down Expand Up @@ -861,7 +854,6 @@ function CustomProviderModels({
{copy.custom.addModel}
</Button>
</div>
{error ? <Banner tone="error" title={error} /> : null}
</>
);
}
Expand All @@ -871,12 +863,10 @@ function CustomProviderActions({
provider,
apis,
onChanged,
onError,
}: {
provider: ModelProvider;
apis: Apis;
onChanged: () => void;
onError: (message: string | null) => void;
}) {
const queryClient = useQueryClient();
const [editing, setEditing] = useState(false);
Expand All @@ -886,7 +876,6 @@ function CustomProviderActions({

const remove = async () => {
setRemoving(true);
onError(null);
try {
await productClient().removeCustomProvider(
await workspaceTenantId(),
Expand All @@ -896,7 +885,7 @@ function CustomProviderActions({
await queryClient.invalidateQueries({ queryKey: keys.modelCatalog });
onChanged();
} catch (cause) {
onError(message(cause));
toast.error(message(cause));
} finally {
setRemoving(false);
}
Expand Down Expand Up @@ -971,20 +960,18 @@ function EditCustomProviderDialog({
const queryClient = useQueryClient();
const form = useCustomProviderForm(apis, provider);
const [busy, setBusy] = useState(false);
const [error, setError] = useState<string | null>(null);

const save = async () => {
if (!form.ready || busy) return;
setBusy(true);
setError(null);
try {
await form.save();
toast.success(copy.custom.saved(form.name));
await queryClient.invalidateQueries({ queryKey: keys.modelCatalog });
onSaved();
onClose();
} catch (cause) {
setError(message(cause));
toast.error(message(cause));
} finally {
setBusy(false);
}
Expand All @@ -996,7 +983,6 @@ function EditCustomProviderDialog({
onOpenChange={(open) => (open || busy ? undefined : onClose())}
title={copy.custom.editTitle(provider.label)}
description={copy.custom.editLead}
error={error}
busy={busy}
ready={form.ready}
tests={form.tests}
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/pages/invite-accept.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/
import { wording } from "../config.ts";
import { useEffect, useState } from "react";
import { toast } from "sonner";
import { Banner, Button, Mark, StateLabel } from "../components.jsx";
import { productClient } from "../api/transport.ts";
import { getHubSession, type HubUser } from "../api/auth.ts";
Expand Down Expand Up @@ -58,12 +59,11 @@ export function InvitationAccept({ invitationId }: { invitationId: string }) {

const accept = async () => {
setBusy(true);
setFailed(null);
try {
const result = await productClient().acceptInvitation(invitationId);
setAccepted(result);
} catch (cause) {
setFailed(cause instanceof Error ? cause.message : String(cause));
toast.error(cause instanceof Error ? cause.message : String(cause));
} finally {
setBusy(false);
}
Expand Down
3 changes: 1 addition & 2 deletions apps/web/src/pages/model-setup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function ModelSetup({
onConnected();
};
const catalog = useModelCatalog();
const { logins, signingIn, error, signIn } = useSubscriptionLogins(connected);
const { logins, signingIn, signIn } = useSubscriptionLogins(connected);
const apiKeyProviders = (catalog.data?.providers ?? []).filter(
(provider) => provider.kind === "api_key",
);
Expand All @@ -85,7 +85,6 @@ export function ModelSetup({
{catalog.error ? (
<Banner tone="error" title={catalog.error.message} />
) : null}
{error ? <Banner tone="error" title={error} /> : null}
<KindCardGrid
label={copy.loginGroup}
className="provider-tiles"
Expand Down
4 changes: 1 addition & 3 deletions apps/web/src/pages/project-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
restoreProject,
shipProject,
} from "../api/projects.ts";
import { Banner, Button, type NoticeAction } from "../components.jsx";
import { Button, type NoticeAction } from "../components.jsx";
import { Dictated } from "../dictation.jsx";

/** What the menu needs of a project: the summaries (rail, top bar) both have it. */
Expand Down Expand Up @@ -324,7 +324,6 @@ export function ProjectInfoDialog({
const [title, setTitle] = useState(project.title);
const [saving, setSaving] = useState(false);
const [archiving, setArchiving] = useState(false);
const [error] = useState<string | null>(null);

const act = async (work: () => Promise<unknown>) => {
try {
Expand Down Expand Up @@ -366,7 +365,6 @@ export function ProjectInfoDialog({
<DialogTitle>{project.title}</DialogTitle>
</DialogHeader>
<DialogBody>
{error ? <Banner tone="error" title={error} /> : null}
<div className="field">
<label htmlFor={`project-name-${project.id}`}>Name</label>
<Dictated value={title} onValueChange={setTitle} align="center">
Expand Down
7 changes: 2 additions & 5 deletions apps/web/src/pages/projects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,17 @@ export function Projects({
const [problem, setProblem] = useState("");
const [profile, setProfile] = useState<string>();
const [busy, setBusy] = useState<"start" | "import" | null>(null);
const [error, setError] = useState<string | null>(null);
const starting = busy === "start";
const shell = useShellReply(useRef<HTMLElement>(null));

const start = async () => {
if (busy !== null) return;
if (shell.answers(problem)) return setProblem("");
if (!canStartProject(problem)) {
setError(wording.message.projectTooShort);
toast.error(wording.message.projectTooShort);
return;
}
setBusy("start");
setError(null);
try {
const created = await createProject({
problemStatement: problem.trim(),
Expand All @@ -69,7 +67,7 @@ export function Projects({
// shows it until the conversation records it.
onOpen(created.projectId, opening);
} catch (cause) {
setError(
toast.error(
cause instanceof ApiFailure ? cause.detail.message : String(cause),
);
} finally {
Expand Down Expand Up @@ -143,7 +141,6 @@ export function Projects({
<h1 id="new-project-title">{wording.newProject.title}</h1>
<p>{wording.newProject.lead}</p>
</hgroup>
{error ? <Banner tone="error" title={error} /> : null}
{needsProvider ? (
<Banner tone="warning" title={wording.providers.none}>
<p>{wording.providers.noneHint}</p>
Expand Down
Loading