Louis/hooks (#599)
* Update useDevServer to use tanstack (vibe-kanban a5e7cb20) We are migrating the frontend to use Tanstack query. We should make radical changes in order to improve readability and performance. See an example in frontend/src/hooks/useRebase.ts Please plan how to modernise the frontend/src/hooks/useDevServer.ts hook * Deprecate useExecutionProcesses → Replace with useAttemptExecution (vibe-kanban 5123ff1e)
This commit is contained in:
committed by
GitHub
parent
13fceaf77e
commit
a10d3f0854
@@ -104,7 +104,9 @@ export function AttemptHeaderCard({
|
||||
Open in IDE
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={runningDevServer ? stopDevServer : startDevServer}
|
||||
onClick={() =>
|
||||
runningDevServer ? stopDevServer() : startDevServer()
|
||||
}
|
||||
disabled={!selectedAttempt}
|
||||
className={runningDevServer ? 'text-destructive' : ''}
|
||||
>
|
||||
|
||||
@@ -512,7 +512,9 @@ function CurrentAttempt({
|
||||
<Button
|
||||
variant={runningDevServer ? 'destructive' : 'outline'}
|
||||
size="xs"
|
||||
onClick={runningDevServer ? stopDevServer : startDevServer}
|
||||
onClick={() =>
|
||||
runningDevServer ? stopDevServer() : startDevServer()
|
||||
}
|
||||
disabled={isStartingDevServer || !projectHasDevScript}
|
||||
className="gap-1 flex-1"
|
||||
>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
export { useExecutionProcesses } from './useExecutionProcesses';
|
||||
export { useBranchStatus } from './useBranchStatus';
|
||||
export { useAttemptExecution } from './useAttemptExecution';
|
||||
export { useOpenInEditor } from './useOpenInEditor';
|
||||
|
||||
@@ -1,30 +1,39 @@
|
||||
import { useCallback } from 'react';
|
||||
import { attemptsApi } from '@/lib/api';
|
||||
import type { CreateGitHubPrRequest } from 'shared/types';
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { attemptsApi, type Result } from '@/lib/api';
|
||||
import type { CreateGitHubPrRequest, GitHubServiceError } from 'shared/types';
|
||||
|
||||
export function useCreatePR(
|
||||
attemptId: string | undefined,
|
||||
onSuccess?: (prUrl?: string) => void,
|
||||
onError?: (err: unknown) => void
|
||||
) {
|
||||
return useCallback(
|
||||
async (prData: CreateGitHubPrRequest) => {
|
||||
if (!attemptId) return;
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
try {
|
||||
const result = await attemptsApi.createPR(attemptId, prData);
|
||||
|
||||
if (result.success) {
|
||||
onSuccess?.(result.data);
|
||||
return result.data;
|
||||
} else {
|
||||
throw result.error || new Error(result.message);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to create PR:', err);
|
||||
onError?.(err);
|
||||
return useMutation<
|
||||
Result<string, GitHubServiceError>,
|
||||
Error,
|
||||
CreateGitHubPrRequest
|
||||
>({
|
||||
mutationFn: async (prData: CreateGitHubPrRequest) => {
|
||||
if (!attemptId)
|
||||
return { success: false, error: undefined, message: 'No attempt ID' };
|
||||
return attemptsApi.createPR(attemptId, prData);
|
||||
},
|
||||
onSuccess: (result) => {
|
||||
if (result.success) {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ['branchStatus', attemptId],
|
||||
});
|
||||
onSuccess?.(result.data);
|
||||
} else {
|
||||
throw (
|
||||
result.error || new Error(result.message || 'Failed to create PR')
|
||||
);
|
||||
}
|
||||
},
|
||||
[attemptId, onSuccess, onError]
|
||||
);
|
||||
onError: (err) => {
|
||||
console.error('Failed to create PR:', err);
|
||||
onError?.(err);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { attemptsApi, executionProcessesApi } from '@/lib/api';
|
||||
import { useAttemptExecution } from '@/hooks/useAttemptExecution';
|
||||
import type { ExecutionProcess } from 'shared/types';
|
||||
@@ -14,12 +15,11 @@ export function useDevServer(
|
||||
attemptId: string | undefined,
|
||||
options?: UseDevServerOptions
|
||||
) {
|
||||
const queryClient = useQueryClient();
|
||||
const { attemptData } = useAttemptExecution(attemptId);
|
||||
const [isStarting, setIsStarting] = useState(false);
|
||||
const [isStopping, setIsStopping] = useState(false);
|
||||
|
||||
// Find running dev server process
|
||||
const runningDevServer = useMemo((): ExecutionProcess | undefined => {
|
||||
const runningDevServer = useMemo<ExecutionProcess | undefined>(() => {
|
||||
return attemptData.processes.find(
|
||||
(process) =>
|
||||
process.run_reason === 'devserver' && process.status === 'running'
|
||||
@@ -27,7 +27,7 @@ export function useDevServer(
|
||||
}, [attemptData.processes]);
|
||||
|
||||
// Find latest dev server process (for logs viewing)
|
||||
const latestDevServerProcess = useMemo((): ExecutionProcess | undefined => {
|
||||
const latestDevServerProcess = useMemo<ExecutionProcess | undefined>(() => {
|
||||
return [...attemptData.processes]
|
||||
.filter((process) => process.run_reason === 'devserver')
|
||||
.sort(
|
||||
@@ -36,41 +36,56 @@ export function useDevServer(
|
||||
)[0];
|
||||
}, [attemptData.processes]);
|
||||
|
||||
const start = useCallback(async () => {
|
||||
if (!attemptId) return;
|
||||
|
||||
setIsStarting(true);
|
||||
try {
|
||||
// Start mutation
|
||||
const startMutation = useMutation({
|
||||
mutationKey: ['startDevServer', attemptId],
|
||||
mutationFn: async () => {
|
||||
if (!attemptId) return;
|
||||
await attemptsApi.startDevServer(attemptId);
|
||||
},
|
||||
onSuccess: async () => {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ['executionProcesses', attemptId],
|
||||
});
|
||||
options?.onStartSuccess?.();
|
||||
} catch (err) {
|
||||
},
|
||||
onError: (err) => {
|
||||
console.error('Failed to start dev server:', err);
|
||||
options?.onStartError?.(err);
|
||||
} finally {
|
||||
setIsStarting(false);
|
||||
}
|
||||
}, [attemptId, options?.onStartSuccess, options?.onStartError]);
|
||||
},
|
||||
});
|
||||
|
||||
const stop = useCallback(async () => {
|
||||
if (!runningDevServer) return;
|
||||
|
||||
setIsStopping(true);
|
||||
try {
|
||||
// Stop mutation
|
||||
const stopMutation = useMutation({
|
||||
mutationKey: ['stopDevServer', runningDevServer?.id],
|
||||
mutationFn: async () => {
|
||||
if (!runningDevServer) return;
|
||||
await executionProcessesApi.stopExecutionProcess(runningDevServer.id);
|
||||
},
|
||||
onSuccess: async () => {
|
||||
await Promise.all([
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ['executionProcesses', attemptId],
|
||||
}),
|
||||
runningDevServer
|
||||
? queryClient.invalidateQueries({
|
||||
queryKey: ['processDetails', runningDevServer.id],
|
||||
})
|
||||
: Promise.resolve(),
|
||||
]);
|
||||
options?.onStopSuccess?.();
|
||||
} catch (err) {
|
||||
},
|
||||
onError: (err) => {
|
||||
console.error('Failed to stop dev server:', err);
|
||||
options?.onStopError?.(err);
|
||||
} finally {
|
||||
setIsStopping(false);
|
||||
}
|
||||
}, [runningDevServer, options?.onStopSuccess, options?.onStopError]);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
start,
|
||||
stop,
|
||||
isStarting,
|
||||
isStopping,
|
||||
start: startMutation.mutate,
|
||||
stop: stopMutation.mutate,
|
||||
isStarting: startMutation.isPending,
|
||||
isStopping: stopMutation.isPending,
|
||||
runningDevServer,
|
||||
latestDevServerProcess,
|
||||
};
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { executionProcessesApi } from '@/lib/api';
|
||||
import type { ExecutionProcess } from 'shared/types';
|
||||
|
||||
export function useExecutionProcesses(attemptId?: string) {
|
||||
const query = useQuery({
|
||||
queryKey: ['executionProcesses', attemptId],
|
||||
queryFn: () => executionProcessesApi.getExecutionProcesses(attemptId!),
|
||||
enabled: !!attemptId,
|
||||
refetchInterval: () => {
|
||||
// Always poll every 5 seconds when enabled - we'll control this via enabled
|
||||
return 5000;
|
||||
},
|
||||
select: (data) => ({
|
||||
processes: data,
|
||||
isAttemptRunning: data.some(
|
||||
(process: ExecutionProcess) =>
|
||||
(process.run_reason === 'codingagent' ||
|
||||
process.run_reason === 'setupscript' ||
|
||||
process.run_reason === 'cleanupscript') &&
|
||||
process.status === 'running'
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
return query;
|
||||
}
|
||||
Reference in New Issue
Block a user