Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit89339f6

Browse files
feat: redesign tasks page to match AI tools (#19962)
**Demo:**<img width="3228" height="1940" alt="image"src="https://github.com/user-attachments/assets/d29555ae-8122-4043-9ee2-2603506e5f3c"/>
1 parentfc58996 commit89339f6

File tree

13 files changed

+114
-782
lines changed

13 files changed

+114
-782
lines changed

‎offlinedocs/pages/[[...slug]].tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
DrawerOverlay,
1010
Flex,
1111
Grid,
12-
GridProps,
12+
typeGridProps,
1313
Heading,
1414
Icon,
1515
Img,
@@ -28,12 +28,12 @@ import {
2828
importfmfrom"front-matter";
2929
import{readFileSync}from"fs";
3030
import_from"lodash";
31-
import{GetStaticPaths,GetStaticProps,NextPage}from"next";
31+
importtype{GetStaticPaths,GetStaticProps,NextPage}from"next";
3232
importHeadfrom"next/head";
3333
importNextLinkfrom"next/link";
3434
import{useRouter}from"next/router";
3535
importpathfrom"path";
36-
import{ReactNode}from"react";
36+
importtype{ReactNode}from"react";
3737
import{MdMenu}from"react-icons/md";
3838
importReactMarkdownfrom"react-markdown";
3939
importrehypeRawfrom"rehype-raw";

‎site/src/api/api.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ export type GetProvisionerDaemonsParams = {
426426
offline?:boolean;
427427
};
428428

429-
exporttypeTasksFilter={
429+
typeTasksFilter={
430430
username?:string;
431431
};
432432

‎site/src/components/Select/Select.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const SelectTrigger = React.forwardRef<
2323
ref={ref}
2424
id={id}
2525
className={cn(
26-
`flex h-10 w-full font-medium items-center justify-between whitespace-nowrap rounded-md
26+
`gap-2flex h-10 w-full font-medium items-center justify-between whitespace-nowrap rounded-md
2727
border border-border border-solid bg-transparent px-3 py-2 text-sm shadow-sm
2828
ring-offset-background text-content-secondary placeholder:text-content-secondary focus:outline-none,
2929
focus:ring-2 focus:ring-content-link disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
importtype{FC,PropsWithChildren}from"react";
2+
import{Outlet}from"react-router";
3+
import{TasksSidebar}from"../TasksSidebar/TasksSidebar";
4+
5+
constTasksLayout:FC<PropsWithChildren>=()=>{
6+
return(
7+
<divclassName="flex items-stretch h-full">
8+
<TasksSidebar/>
9+
<divclassName="flex flex-col h-full flex-1 overflow-y-auto">
10+
<Outlet/>
11+
</div>
12+
</div>
13+
);
14+
};
15+
16+
exportdefaultTasksLayout;

‎site/src/modules/tasks/TasksSidebar/TasksSidebar.tsx‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,14 @@ export const TasksSidebar: FC = () => {
4141
<divclassName="flex items-center place-content-between">
4242
{!isCollapsed&&(
4343
<Button
44+
asChild
4445
size="icon"
4546
variant="subtle"
4647
className={cn(["size-8 p-0 transition-[margin,opacity]"])}
4748
>
48-
<CoderIconclassName="fill-content-primary !size-6 !p-0"/>
49+
<RouterLinkto="/">
50+
<CoderIconclassName="fill-content-primary !size-6 !p-0"/>
51+
</RouterLink>
4952
</Button>
5053
)}
5154

‎site/src/pages/TaskPage/TaskPage.tsx‎

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,14 @@ import { useWorkspaceBuildLogs } from "hooks/useWorkspaceBuildLogs";
1717
import{ArrowLeftIcon,RotateCcwIcon}from"lucide-react";
1818
import{AgentLogs}from"modules/resources/AgentLogs/AgentLogs";
1919
import{useAgentLogs}from"modules/resources/useAgentLogs";
20-
import{TasksSidebar}from"modules/tasks/TasksSidebar/TasksSidebar";
2120
import{
2221
AI_PROMPT_PARAMETER_NAME,
2322
getTaskApps,
2423
typeTask,
2524
}from"modules/tasks/tasks";
2625
import{WorkspaceErrorDialog}from"modules/workspaces/ErrorDialog/WorkspaceErrorDialog";
2726
import{WorkspaceBuildLogs}from"modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs";
28-
import{
29-
typeFC,
30-
typePropsWithChildren,
31-
typeReactNode,
32-
useLayoutEffect,
33-
useRef,
34-
}from"react";
27+
import{typeFC,typeReactNode,useLayoutEffect,useRef}from"react";
3528
import{useMutation,useQuery,useQueryClient}from"react-query";
3629
import{Panel,PanelGroup,PanelResizeHandle}from"react-resizable-panels";
3730
import{LinkasRouterLink,useParams}from"react-router";
@@ -45,15 +38,6 @@ import { TaskAppIFrame } from "./TaskAppIframe";
4538
import{TaskApps}from"./TaskApps";
4639
import{TaskTopbar}from"./TaskTopbar";
4740

48-
constTaskPageLayout:FC<PropsWithChildren>=({ children})=>{
49-
return(
50-
<divclassName="flex items-stretch h-full">
51-
<TasksSidebar/>
52-
<divclassName="flex flex-col h-full flex-1">{children}</div>
53-
</div>
54-
);
55-
};
56-
5741
constTaskPage=()=>{
5842
const{workspace:workspaceName, username}=useParams()as{
5943
workspace:string;
@@ -73,7 +57,7 @@ const TaskPage = () => {
7357

7458
if(error){
7559
return(
76-
<TaskPageLayout>
60+
<>
7761
<title>{pageTitle("Error loading task")}</title>
7862

7963
<divclassName="w-full min-h-80 flex items-center justify-center">
@@ -98,16 +82,16 @@ const TaskPage = () => {
9882
</div>
9983
</div>
10084
</div>
101-
</TaskPageLayout>
85+
</>
10286
);
10387
}
10488

10589
if(!task){
10690
return(
107-
<TaskPageLayout>
91+
<>
10892
<title>{pageTitle("Loading task")}</title>
10993
<LoaderclassName="w-full h-full"/>
110-
</TaskPageLayout>
94+
</>
11195
);
11296
}
11397

@@ -174,12 +158,11 @@ const TaskPage = () => {
174158
}
175159

176160
return(
177-
<TaskPageLayout>
161+
<>
178162
<title>{pageTitle(task.workspace.name)}</title>
179-
180163
<TaskTopbartask={task}/>
181164
{content}
182-
</TaskPageLayout>
165+
</>
183166
);
184167
};
185168

‎site/src/pages/TasksPage/TaskPrompt.tsx‎

Lines changed: 51 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
}from"components/Tooltip/Tooltip";
3030
import{useAuthenticated}from"hooks/useAuthenticated";
3131
import{useExternalAuth}from"hooks/useExternalAuth";
32-
import{RedoIcon,RotateCcwIcon,SendIcon}from"lucide-react";
32+
import{ArrowUpIcon,RedoIcon,RotateCcwIcon}from"lucide-react";
3333
import{AI_PROMPT_PARAMETER_NAME}from"modules/tasks/tasks";
3434
import{typeFC,useEffect,useState}from"react";
3535
import{useMutation,useQuery,useQueryClient}from"react-query";
@@ -106,8 +106,8 @@ const TaskPromptSkeleton: FC = () => {
106106

107107
{/* Bottom controls skeleton */}
108108
<divclassName="flex items-center justify-between pt-2">
109-
<SkeletonclassName="w-[208px] h-8"/>
110-
<SkeletonclassName="w-[96px] h-8"/>
109+
<SkeletonclassName="w-[160px] h-8 rounded-full"/>
110+
<SkeletonclassName="size-8 rounded-full"/>
111111
</div>
112112
</div>
113113
</div>
@@ -160,15 +160,17 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
160160
}=useExternalAuth(selectedTemplate.active_version_id);
161161

162162
// Fetch presets when template changes
163-
const{data:presets,isLoading:isLoadingPresets}=useQuery(
163+
const{data:presets}=useQuery(
164164
templateVersionPresets(selectedTemplate.active_version_id),
165165
);
166-
constdefaultPreset=presets?.find((p)=>p.Default);
167166

168167
// Handle preset selection when data changes
169168
useEffect(()=>{
170-
setSelectedPresetId(defaultPreset?.ID);
171-
},[defaultPreset?.ID]);
169+
if(presets&&presets.length>0){
170+
constdefaultPreset=presets.find((p)=>p.Default)||presets[0];
171+
setSelectedPresetId(defaultPreset.ID);
172+
}
173+
},[presets]);
172174

173175
// Extract AI prompt from selected preset
174176
constselectedPreset=presets?.find((p)=>p.ID===selectedPresetId);
@@ -225,7 +227,7 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
225227
{externalAuthError&&<ErrorAlerterror={externalAuthError}/>}
226228

227229
<fieldset
228-
className="border border-border border-solid rounded-lg p-4"
230+
className="border border-border border-solid rounded-3xl p-4"
229231
disabled={createTaskMutation.isPending}
230232
>
231233
<label
@@ -251,23 +253,22 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
251253
}`}
252254
/>
253255
<divclassName="flex items-center justify-between pt-2">
254-
<divclassName="flex items-center gap-4">
255-
<divclassName="flex flex-col gap-1">
256-
<label
257-
htmlFor="templateID"
258-
className="text-xs font-medium text-content-primary"
259-
>
256+
<divclassName="flex items-center gap-2">
257+
<div>
258+
<labelhtmlFor="templateID"className="sr-only">
260259
Template
261260
</label>
262261
<Select
263262
name="templateID"
264-
onValueChange={(value)=>setSelectedTemplateId(value)}
263+
onValueChange={(value)=>{
264+
setSelectedTemplateId(value);
265+
}}
265266
defaultValue={templates[0].id}
266267
required
267268
>
268269
<SelectTrigger
269270
id="templateID"
270-
className="w-80 text-xs [&_svg]:size-icon-xs border-0 bg-surface-secondary h-8 px-3"
271+
className="w-fit text-xs [&_svg]:size-icon-xs border-0 bg-surface-secondary h-8 px-3 rounded-full"
271272
>
272273
<SelectValueplaceholder="Select a template"/>
273274
</SelectTrigger>
@@ -285,50 +286,34 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
285286
</Select>
286287
</div>
287288

288-
{isLoadingPresets ?(
289-
<divclassName="flex flex-col gap-1">
290-
<label
291-
htmlFor="presetID"
292-
className="text-xs font-medium text-content-primary"
293-
>
289+
{selectedPresetId&&(
290+
<div>
291+
<labelhtmlFor="presetID"className="sr-only">
294292
Preset
295293
</label>
296-
<SkeletonclassName="w-[320px] h-8"/>
297-
</div>
298-
) :(
299-
presets&&
300-
presets.length>0&&(
301-
<divclassName="flex flex-col gap-1">
302-
<label
303-
htmlFor="presetID"
304-
className="text-xs font-medium text-content-primary"
305-
>
306-
Preset
307-
</label>
308-
<Select
309-
key={`preset-select-${selectedTemplate.active_version_id}`}
310-
name="presetID"
311-
value={selectedPresetId||undefined}
312-
onValueChange={setSelectedPresetId}
294+
<Select
295+
key={`preset-select-${selectedTemplate.active_version_id}`}
296+
name="presetID"
297+
value={selectedPresetId}
298+
onValueChange={setSelectedPresetId}
299+
>
300+
<SelectTrigger
301+
id="presetID"
302+
className="w-fit text-xs [&_svg]:size-icon-xs border-0 bg-surface-secondary h-8 px-3 rounded-full"
313303
>
314-
<SelectTrigger
315-
id="presetID"
316-
className="w-80 text-xs [&_svg]:size-icon-xs border-0 bg-surface-secondary h-8 px-3"
317-
>
318-
<SelectValueplaceholder="Select a preset"/>
319-
</SelectTrigger>
320-
<SelectContent>
321-
{presets.toSorted(sortByDefault).map((preset)=>(
322-
<SelectItemvalue={preset.ID}key={preset.ID}>
323-
<spanclassName="overflow-hidden text-ellipsis block">
324-
{preset.Name}{preset.Default&&"(Default)"}
325-
</span>
326-
</SelectItem>
327-
))}
328-
</SelectContent>
329-
</Select>
330-
</div>
331-
)
304+
<SelectValueplaceholder="Select a preset"/>
305+
</SelectTrigger>
306+
<SelectContent>
307+
{presets?.toSorted(sortByDefault).map((preset)=>(
308+
<SelectItemvalue={preset.ID}key={preset.ID}>
309+
<spanclassName="overflow-hidden text-ellipsis block">
310+
{preset.Name}{preset.Default&&"(Default)"}
311+
</span>
312+
</SelectItem>
313+
))}
314+
</SelectContent>
315+
</Select>
316+
</div>
332317
)}
333318
</div>
334319

@@ -340,17 +325,22 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
340325
/>
341326
)}
342327

343-
<Buttonsize="sm"type="submit"disabled={isMissingExternalAuth}>
328+
<Button
329+
size="icon"
330+
className="rounded-full"
331+
type="submit"
332+
disabled={isMissingExternalAuth}
333+
>
344334
<Spinner
345335
loading={
346336
isLoadingExternalAuth||
347337
isPollingExternalAuth||
348338
createTaskMutation.isPending
349339
}
350340
>
351-
<SendIcon/>
341+
<ArrowUpIcon/>
352342
</Spinner>
353-
Run task
343+
<spanclassName="sr-only">Run task</span>
354344
</Button>
355345
</div>
356346
</div>
@@ -380,6 +370,7 @@ const ExternalAuthButtons: FC<ExternalAuthButtonProps> = ({
380370
<divclassName="flex items-center gap-2"key={auth.id}>
381371
<Button
382372
variant="outline"
373+
className="rounded-full"
383374
size="sm"
384375
disabled={isPollingExternalAuth||auth.authenticated}
385376
onClick={()=>{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp