diff --git a/config/widgets.yaml b/config/widgets.yaml index 8aa127a8..4ea53eec 100644 --- a/config/widgets.yaml +++ b/config/widgets.yaml @@ -12,3 +12,27 @@ timeStyle: short dateStyle: short hourCycle: h23 + +- deploy: + service: ppt-tool + label: DeckForge + +- deploy: + service: semblance + label: Semblance + +- deploy: + service: olivas + label: OliVAS + +- deploy: + service: gmal-scope-builder + label: Scope Builder + +- deploy: + service: cc-dashboard + label: CC Dashboard + +- deploy: + service: homepage + label: Homepage diff --git a/src/components/widgets/deploy/deploy.jsx b/src/components/widgets/deploy/deploy.jsx new file mode 100644 index 00000000..a9243aca --- /dev/null +++ b/src/components/widgets/deploy/deploy.jsx @@ -0,0 +1,87 @@ +import { useState } from "react"; +import useSWR from "swr"; + +const STATUS_COLORS = { + idle: "text-theme-500 dark:text-theme-400", + running: "text-blue-500 dark:text-blue-400", + success: "text-emerald-500 dark:text-emerald-400", + failed: "text-red-500 dark:text-red-400", +}; + +const STATUS_LABELS = { + idle: "Never deployed", + running: "Deploying...", + success: "Deployed", + failed: "Failed", +}; + +function formatTime(iso) { + if (!iso) return null; + const d = new Date(iso); + return d.toLocaleString("en-GB", { dateStyle: "short", timeStyle: "short", hourCycle: "h23" }); +} + +export default function Deploy({ options }) { + const { service, label, apiBase = "/deploy-api" } = options ?? {}; + const bp = process.env.NEXT_PUBLIC_BASE_PATH ?? ""; + const statusUrl = service ? `${bp}${apiBase}/status/${service}` : null; + + const { data, mutate } = useSWR(statusUrl, { + refreshInterval: (d) => (d?.status === "running" ? 2000 : 10000), + }); + + const [triggering, setTriggering] = useState(false); + + const status = data?.status ?? "idle"; + const lastRun = data?.last_run ? formatTime(data.last_run) : null; + const isRunning = status === "running"; + + const handleDeploy = async () => { + if (isRunning || triggering) return; + setTriggering(true); + try { + await fetch(`${bp}${apiBase}/deploy/${service}`, { method: "POST" }); + await mutate(); + } finally { + setTriggering(false); + } + }; + + if (!service) { + return ( +