Skip to content

Commit c2ff997

Browse files
committed
feat: automatically run tasks
- we now automatically start tasks on creation. we also remember the previous run mode and use that. The task execution behaviour can be configured in settings - fixed a bug where CliTaskPanel would autofocus, and where TaskListFilter would accidentally pick up a keypress meant for task mode
1 parent 89811c9 commit c2ff997

File tree

7 files changed

+244
-144
lines changed

7 files changed

+244
-144
lines changed
Lines changed: 169 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
import { AsciiArt } from "@components/AsciiArt";
21
import { useAuthStore } from "@features/auth/stores/authStore";
2+
import {
3+
type DefaultRunMode,
4+
useSettingsStore,
5+
} from "@features/settings/stores/settingsStore";
36
import {
47
Box,
58
Button,
69
Card,
710
Flex,
811
Heading,
12+
Select,
913
Switch,
1014
Text,
1115
TextField,
@@ -24,6 +28,8 @@ export function SettingsView() {
2428
} = useAuthStore();
2529
const isDarkMode = useThemeStore((state) => state.isDarkMode);
2630
const toggleDarkMode = useThemeStore((state) => state.toggleDarkMode);
31+
const { autoRunTasks, defaultRunMode, setAutoRunTasks, setDefaultRunMode } =
32+
useSettingsStore();
2733
const [apiKey, setApiKey] = useState("");
2834
const [host, setHost] = useState(apiHost);
2935
const [initialHost] = useState(apiHost);
@@ -64,158 +70,190 @@ export function SettingsView() {
6470
};
6571

6672
return (
67-
<Box height="100%">
68-
<Flex height="100%">
69-
{/* Left pane - Settings */}
70-
<Box
71-
width="50%"
72-
p="6"
73-
className="border-gray-6 border-r"
74-
overflowY="auto"
75-
>
76-
<Flex direction="column" gap="6">
77-
<Flex direction="column" gap="2">
78-
<Heading size="6">Settings</Heading>
79-
<Text size="2" color="gray">
80-
Manage your PostHog connection and preferences
81-
</Text>
82-
</Flex>
73+
<Box height="100%" overflowY="auto">
74+
<Box p="6" style={{ maxWidth: "600px", margin: "0 auto" }}>
75+
<Flex direction="column" gap="6">
76+
<Flex direction="column" gap="2">
77+
<Heading size="4">Settings</Heading>
78+
<Text size="1" color="gray">
79+
Manage your PostHog connection and preferences
80+
</Text>
81+
</Flex>
8382

84-
{/* Appearance Section */}
85-
<Flex direction="column" gap="3">
86-
<Heading size="4">Appearance</Heading>
87-
<Card>
83+
{/* Appearance Section */}
84+
<Flex direction="column" gap="3">
85+
<Heading size="3">Appearance</Heading>
86+
<Card>
87+
<Flex align="center" justify="between">
88+
<Text size="1" weight="medium">
89+
Dark mode
90+
</Text>
91+
<Switch
92+
checked={isDarkMode}
93+
onCheckedChange={toggleDarkMode}
94+
size="1"
95+
/>
96+
</Flex>
97+
</Card>
98+
</Flex>
99+
100+
<Box className="border-gray-6 border-t" />
101+
102+
{/* Task Execution Section */}
103+
<Flex direction="column" gap="3">
104+
<Heading size="3">Task execution</Heading>
105+
<Card>
106+
<Flex direction="column" gap="4">
88107
<Flex align="center" justify="between">
89-
<Text size="2" weight="medium">
90-
Dark Mode
91-
</Text>
108+
<Flex direction="column" gap="1">
109+
<Text size="1" weight="medium">
110+
Auto-run new tasks
111+
</Text>
112+
<Text size="1" color="gray">
113+
Automatically start tasks after creation
114+
</Text>
115+
</Flex>
92116
<Switch
93-
checked={isDarkMode}
94-
onCheckedChange={toggleDarkMode}
95-
size="2"
117+
checked={autoRunTasks}
118+
onCheckedChange={setAutoRunTasks}
119+
size="1"
96120
/>
97121
</Flex>
98-
</Card>
99-
</Flex>
100-
101-
<Box className="border-gray-6 border-t" />
102122

103-
{/* Authentication Section */}
104-
<Flex direction="column" gap="3">
105-
<Flex align="center" gap="3">
106-
<Heading size="4">Authentication</Heading>
107-
<Flex align="center" gap="2">
108-
<Box
109-
width="8px"
110-
height="8px"
111-
className={`rounded-full ${isAuthenticated ? "bg-green-9" : "bg-red-9"}`}
112-
/>
113-
<Text size="2" color="gray">
114-
{isAuthenticated ? "Connected" : "Not connected"}
123+
<Flex direction="column" gap="2">
124+
<Text size="1" weight="medium">
125+
Default run environment
126+
</Text>
127+
<Select.Root
128+
value={defaultRunMode}
129+
onValueChange={(value) =>
130+
setDefaultRunMode(value as DefaultRunMode)
131+
}
132+
size="1"
133+
>
134+
<Select.Trigger />
135+
<Select.Content>
136+
<Select.Item value="local">Local</Select.Item>
137+
<Select.Item value="cloud">Cloud</Select.Item>
138+
<Select.Item value="last_used">Last used</Select.Item>
139+
</Select.Content>
140+
</Select.Root>
141+
<Text size="1" color="gray">
142+
Choose which environment to use when running tasks
115143
</Text>
116144
</Flex>
117145
</Flex>
146+
</Card>
147+
</Flex>
118148

119-
<Card>
120-
<Flex direction="column" gap="3">
121-
<Flex direction="column" gap="2">
122-
<Text size="2" weight="medium">
123-
API Key
124-
</Text>
125-
<TextField.Root
126-
type="password"
127-
placeholder="Enter your PostHog API key"
128-
value={apiKey}
129-
onChange={(e) => setApiKey(e.target.value)}
130-
onBlur={handleApiKeyBlur}
131-
disabled={updateCredentialsMutation.isPending}
132-
/>
133-
</Flex>
149+
<Box className="border-gray-6 border-t" />
134150

135-
<Flex direction="column" gap="2">
136-
<Text size="2" weight="medium">
137-
API Host
138-
</Text>
139-
<TextField.Root
140-
type="text"
141-
placeholder="https://us.posthog.com"
142-
value={host}
143-
onChange={(e) => setHost(e.target.value)}
144-
onBlur={handleHostBlur}
145-
disabled={updateCredentialsMutation.isPending}
146-
/>
147-
</Flex>
151+
{/* Authentication Section */}
152+
<Flex direction="column" gap="3">
153+
<Flex align="center" gap="3">
154+
<Heading size="3">Authentication</Heading>
155+
<Flex align="center" gap="2">
156+
<Box
157+
width="8px"
158+
height="8px"
159+
className={`rounded-full ${isAuthenticated ? "bg-green-9" : "bg-red-9"}`}
160+
/>
161+
<Text size="1" color="gray">
162+
{isAuthenticated ? "Connected" : "Not connected"}
163+
</Text>
164+
</Flex>
165+
</Flex>
148166

149-
{updateCredentialsMutation.isError && (
150-
<Text size="2" color="red">
151-
{updateCredentialsMutation.error instanceof Error
152-
? updateCredentialsMutation.error.message
153-
: "Failed to update credentials"}
154-
</Text>
155-
)}
167+
<Card>
168+
<Flex direction="column" gap="3">
169+
<Flex direction="column" gap="2">
170+
<Text size="1" weight="medium">
171+
API Key
172+
</Text>
173+
<TextField.Root
174+
size="1"
175+
type="password"
176+
placeholder="Enter your PostHog API key"
177+
value={apiKey}
178+
onChange={(e) => setApiKey(e.target.value)}
179+
onBlur={handleApiKeyBlur}
180+
disabled={updateCredentialsMutation.isPending}
181+
/>
182+
</Flex>
156183

157-
{updateCredentialsMutation.isSuccess && (
158-
<Text size="2" color="green">
159-
Credentials updated successfully
160-
</Text>
161-
)}
162-
163-
<Box>
164-
<Button
165-
variant="classic"
166-
size="2"
167-
onClick={() => {
168-
const keyToUse = apiKey.trim() || currentApiKey;
169-
if (keyToUse && host.trim()) {
170-
updateCredentialsMutation.mutate({
171-
apiKey: keyToUse,
172-
host,
173-
});
174-
}
175-
}}
176-
disabled={updateCredentialsMutation.isPending}
177-
loading={updateCredentialsMutation.isPending}
178-
>
179-
Save credentials
180-
</Button>
181-
</Box>
184+
<Flex direction="column" gap="2">
185+
<Text size="1" weight="medium">
186+
API Host
187+
</Text>
188+
<TextField.Root
189+
size="1"
190+
type="text"
191+
placeholder="https://us.posthog.com"
192+
value={host}
193+
onChange={(e) => setHost(e.target.value)}
194+
onBlur={handleHostBlur}
195+
disabled={updateCredentialsMutation.isPending}
196+
/>
182197
</Flex>
183-
</Card>
184-
</Flex>
185198

186-
{isAuthenticated && <Box className="border-gray-6 border-t" />}
199+
{updateCredentialsMutation.isError && (
200+
<Text size="1" color="red">
201+
{updateCredentialsMutation.error instanceof Error
202+
? updateCredentialsMutation.error.message
203+
: "Failed to update credentials"}
204+
</Text>
205+
)}
206+
207+
{updateCredentialsMutation.isSuccess && (
208+
<Text size="1" color="green">
209+
Credentials updated successfully
210+
</Text>
211+
)}
187212

188-
{/* Account Section */}
189-
{isAuthenticated && (
190-
<Flex direction="column" gap="3">
191-
<Heading size="4">Account</Heading>
192-
<Card>
213+
<Box>
193214
<Button
194-
variant="soft"
195-
color="red"
196-
onClick={handleLogout}
215+
variant="classic"
216+
size="1"
217+
onClick={() => {
218+
const keyToUse = apiKey.trim() || currentApiKey;
219+
if (keyToUse && host.trim()) {
220+
updateCredentialsMutation.mutate({
221+
apiKey: keyToUse,
222+
host,
223+
});
224+
}
225+
}}
197226
disabled={updateCredentialsMutation.isPending}
227+
loading={updateCredentialsMutation.isPending}
198228
>
199-
Logout
229+
Save credentials
200230
</Button>
201-
</Card>
231+
</Box>
202232
</Flex>
203-
)}
233+
</Card>
204234
</Flex>
205-
</Box>
206-
207-
{/* Right pane - ASCII Art */}
208-
<Box
209-
width="50%"
210-
height="100%"
211-
className="bg-panel-solid"
212-
style={{ position: "relative" }}
213-
>
214-
<Box style={{ position: "absolute", inset: 0, zIndex: 0 }}>
215-
<AsciiArt scale={1} opacity={0.1} />
216-
</Box>
217-
</Box>
218-
</Flex>
235+
236+
{isAuthenticated && <Box className="border-gray-6 border-t" />}
237+
238+
{/* Account Section */}
239+
{isAuthenticated && (
240+
<Flex direction="column" gap="3">
241+
<Heading size="3">Account</Heading>
242+
<Card>
243+
<Button
244+
variant="soft"
245+
color="red"
246+
size="1"
247+
onClick={handleLogout}
248+
disabled={updateCredentialsMutation.isPending}
249+
>
250+
Logout
251+
</Button>
252+
</Card>
253+
</Flex>
254+
)}
255+
</Flex>
256+
</Box>
219257
</Box>
220258
);
221259
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { create } from "zustand";
2+
import { persist } from "zustand/middleware";
3+
4+
export type DefaultRunMode = "local" | "cloud" | "last_used";
5+
6+
interface SettingsStore {
7+
autoRunTasks: boolean;
8+
defaultRunMode: DefaultRunMode;
9+
lastUsedRunMode: "local" | "cloud";
10+
11+
setAutoRunTasks: (autoRun: boolean) => void;
12+
setDefaultRunMode: (mode: DefaultRunMode) => void;
13+
setLastUsedRunMode: (mode: "local" | "cloud") => void;
14+
}
15+
16+
export const useSettingsStore = create<SettingsStore>()(
17+
persist(
18+
(set) => ({
19+
autoRunTasks: true,
20+
defaultRunMode: "last_used",
21+
lastUsedRunMode: "local",
22+
23+
setAutoRunTasks: (autoRun) => set({ autoRunTasks: autoRun }),
24+
setDefaultRunMode: (mode) => set({ defaultRunMode: mode }),
25+
setLastUsedRunMode: (mode) => set({ lastUsedRunMode: mode }),
26+
}),
27+
{
28+
name: "settings-storage",
29+
},
30+
),
31+
);

0 commit comments

Comments
 (0)