Initial commit: StackPilot Phase 1 (Core)
Self-hosted Docker Compose manager. - Backend: FastAPI + docker-py + SQLite (JWT auth, file-first stacks, lifecycle, live status, WebSocket logs, docker-run converter, audit log) - Frontend: React + Vite + Tailwind (login/setup, dashboard, stacks, stack detail, Monaco editor, dark/light theme) - Deployment: docker-compose.yml, Dockerfiles, nginx reverse proxy Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import { useState } from "react";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import { stacksApi } from "@/api/stacks";
|
||||
import { apiErrorMessage } from "@/api/client";
|
||||
|
||||
export function useStackActions() {
|
||||
const qc = useQueryClient();
|
||||
const [busyId, setBusyId] = useState<string | null>(null);
|
||||
|
||||
const run = async (
|
||||
id: string,
|
||||
label: string,
|
||||
fn: (id: string) => Promise<unknown>
|
||||
) => {
|
||||
setBusyId(id);
|
||||
const t = toast.loading(`${label} ${id}…`);
|
||||
try {
|
||||
await fn(id);
|
||||
toast.success(`${label} ${id} ✓`, { id: t });
|
||||
qc.invalidateQueries({ queryKey: ["stacks"] });
|
||||
qc.invalidateQueries({ queryKey: ["stack", id] });
|
||||
} catch (err) {
|
||||
toast.error(apiErrorMessage(err), { id: t });
|
||||
} finally {
|
||||
setBusyId(null);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
busyId,
|
||||
start: (id: string) => run(id, "Starting", stacksApi.start),
|
||||
stop: (id: string) => run(id, "Stopping", stacksApi.stop),
|
||||
restart: (id: string) => run(id, "Restarting", stacksApi.restart),
|
||||
pull: (id: string) => run(id, "Pulling", stacksApi.pull),
|
||||
updateImages: (id: string) => run(id, "Updating", stacksApi.update_images),
|
||||
down: (id: string) => run(id, "Tearing down", stacksApi.down),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user