Skip to content

Commit 0a11e8e

Browse files
committed
feat: add preset selector in TasksPage
1 parent bb83071 commit 0a11e8e

File tree

1 file changed

+92
-28
lines changed

1 file changed

+92
-28
lines changed

site/src/pages/TasksPage/TasksPage.tsx

Lines changed: 92 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import Skeleton from "@mui/material/Skeleton";
22
import { API } from "api/api";
33
import { getErrorDetail, getErrorMessage } from "api/errors";
44
import { disabledRefetchOptions } from "api/queries/util";
5-
import type { Template, TemplateVersionExternalAuth } from "api/typesGenerated";
5+
import type {
6+
Preset,
7+
Template,
8+
TemplateVersionExternalAuth,
9+
} from "api/typesGenerated";
610
import { ErrorAlert } from "components/Alert/ErrorAlert";
711
import { Avatar } from "components/Avatar/Avatar";
812
import { AvatarData } from "components/Avatar/AvatarData";
@@ -50,7 +54,7 @@ import { RedoIcon, RotateCcwIcon, SendIcon } from "lucide-react";
5054
import { AI_PROMPT_PARAMETER_NAME, type Task } from "modules/tasks/tasks";
5155
import { WorkspaceAppStatus } from "modules/workspaces/WorkspaceAppStatus/WorkspaceAppStatus";
5256
import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName";
53-
import { type FC, type ReactNode, useState } from "react";
57+
import { type FC, type ReactNode, useEffect, useState } from "react";
5458
import { Helmet } from "react-helmet-async";
5559
import { useMutation, useQuery, useQueryClient } from "react-query";
5660
import { Link as RouterLink, useNavigate } from "react-router-dom";
@@ -210,7 +214,11 @@ const TaskFormSection: FC<{
210214
);
211215
};
212216

213-
type CreateTaskMutationFnProps = { prompt: string; templateVersionId: string };
217+
type CreateTaskMutationFnProps = {
218+
prompt: string;
219+
templateVersionId: string;
220+
presetId: string | null;
221+
};
214222

215223
type TaskFormProps = {
216224
templates: Template[];
@@ -223,6 +231,8 @@ const TaskForm: FC<TaskFormProps> = ({ templates, onSuccess }) => {
223231
const [selectedTemplateId, setSelectedTemplateId] = useState<string>(
224232
templates[0].id,
225233
);
234+
const [presets, setPresets] = useState<Preset[] | null>(null);
235+
const [selectedPresetId, setSelectedPresetId] = useState<string | null>(null);
226236
const selectedTemplate = templates.find(
227237
(t) => t.id === selectedTemplateId,
228238
) as Template;
@@ -232,6 +242,28 @@ const TaskForm: FC<TaskFormProps> = ({ templates, onSuccess }) => {
232242
isPollingExternalAuth,
233243
isLoadingExternalAuth,
234244
} = useExternalAuth(selectedTemplate.active_version_id);
245+
246+
// Fetch presets when template changes
247+
const { data: presetsData } = useQuery<Preset[] | null, Error>({
248+
queryKey: ["template-version-presets", selectedTemplate.active_version_id],
249+
queryFn: () =>
250+
API.getTemplateVersionPresets(selectedTemplate.active_version_id),
251+
...disabledRefetchOptions,
252+
});
253+
254+
// Handle preset data changes
255+
useEffect(() => {
256+
if (presetsData) {
257+
setPresets(presetsData);
258+
// Set default preset if available
259+
const defaultPreset = presetsData.find((p: Preset) => p.Default);
260+
if (defaultPreset) {
261+
setSelectedPresetId(defaultPreset.ID);
262+
} else {
263+
setSelectedPresetId(null);
264+
}
265+
}
266+
}, [presetsData]);
235267
const missedExternalAuth = externalAuth?.filter(
236268
(auth) => !auth.optional && !auth.authenticated,
237269
);
@@ -243,8 +275,9 @@ const TaskForm: FC<TaskFormProps> = ({ templates, onSuccess }) => {
243275
mutationFn: async ({
244276
prompt,
245277
templateVersionId,
278+
presetId,
246279
}: CreateTaskMutationFnProps) =>
247-
data.createTask(prompt, user.id, templateVersionId),
280+
data.createTask(prompt, user.id, templateVersionId, presetId),
248281
onSuccess: async (task) => {
249282
await queryClient.invalidateQueries({
250283
queryKey: ["tasks"],
@@ -265,6 +298,7 @@ const TaskForm: FC<TaskFormProps> = ({ templates, onSuccess }) => {
265298
await createTaskMutation.mutateAsync({
266299
prompt,
267300
templateVersionId: selectedTemplate.active_version_id,
301+
presetId: selectedPresetId,
268302
});
269303
} catch (error) {
270304
const message = getErrorMessage(error, "Error creating task");
@@ -297,27 +331,50 @@ const TaskForm: FC<TaskFormProps> = ({ templates, onSuccess }) => {
297331
text-sm shadow-sm text-content-primary placeholder:text-content-secondary md:text-sm`}
298332
/>
299333
<div className="flex items-center justify-between pt-2">
300-
<Select
301-
name="templateID"
302-
onValueChange={(value) => setSelectedTemplateId(value)}
303-
defaultValue={templates[0].id}
304-
required
305-
>
306-
<SelectTrigger className="w-52 text-xs [&_svg]:size-icon-xs border-0 bg-surface-secondary h-8 px-3">
307-
<SelectValue placeholder="Select a template" />
308-
</SelectTrigger>
309-
<SelectContent>
310-
{templates.map((template) => {
311-
return (
312-
<SelectItem value={template.id} key={template.id}>
313-
<span className="overflow-hidden text-ellipsis block">
314-
{template.display_name || template.name}
315-
</span>
316-
</SelectItem>
317-
);
318-
})}
319-
</SelectContent>
320-
</Select>
334+
<div className="flex items-center gap-2">
335+
<Select
336+
name="templateID"
337+
onValueChange={(value) => setSelectedTemplateId(value)}
338+
defaultValue={templates[0].id}
339+
required
340+
>
341+
<SelectTrigger className="w-40 text-xs [&_svg]:size-icon-xs border-0 bg-surface-secondary h-8 px-3">
342+
<SelectValue placeholder="Select a template" />
343+
</SelectTrigger>
344+
<SelectContent>
345+
{templates.map((template) => {
346+
return (
347+
<SelectItem value={template.id} key={template.id}>
348+
<span className="overflow-hidden text-ellipsis block">
349+
{template.display_name || template.name}
350+
</span>
351+
</SelectItem>
352+
);
353+
})}
354+
</SelectContent>
355+
</Select>
356+
357+
{presets && presets.length > 0 && (
358+
<Select
359+
name="presetID"
360+
value={selectedPresetId === null ? undefined : selectedPresetId}
361+
onValueChange={(value) => setSelectedPresetId(value)}
362+
>
363+
<SelectTrigger className="w-40 text-xs [&_svg]:size-icon-xs border-0 bg-surface-secondary h-8 px-3">
364+
<SelectValue placeholder="Select a preset" />
365+
</SelectTrigger>
366+
<SelectContent>
367+
{presets.map((preset) => (
368+
<SelectItem value={preset.ID} key={preset.ID}>
369+
<span className="overflow-hidden text-ellipsis block">
370+
{preset.Name} {preset.Default && "(Default)"}
371+
</span>
372+
</SelectItem>
373+
))}
374+
</SelectContent>
375+
</Select>
376+
)}
377+
</div>
321378

322379
<div className="flex items-center gap-2">
323380
{missedExternalAuth && (
@@ -608,13 +665,20 @@ export const data = {
608665
prompt: string,
609666
userId: string,
610667
templateVersionId: string,
668+
presetId: string | null = null,
611669
): Promise<Task> {
612-
const presets = await API.getTemplateVersionPresets(templateVersionId);
613-
const defaultPreset = presets?.find((p) => p.Default);
670+
// If no preset is selected, get the default preset
671+
let preset_id: string | undefined = presetId || undefined;
672+
if (!preset_id) {
673+
const presets = await API.getTemplateVersionPresets(templateVersionId);
674+
const defaultPreset = presets?.find((p) => p.Default);
675+
preset_id = defaultPreset?.ID;
676+
}
677+
614678
const workspace = await API.createWorkspace(userId, {
615679
name: `task-${generateWorkspaceName()}`,
616680
template_version_id: templateVersionId,
617-
template_version_preset_id: defaultPreset?.ID,
681+
template_version_preset_id: preset_id || undefined,
618682
rich_parameter_values: [
619683
{ name: AI_PROMPT_PARAMETER_NAME, value: prompt },
620684
],

0 commit comments

Comments
 (0)