diff --git a/apps/arc-web/app/components/collapsible-file.tsx b/apps/arc-web/app/components/collapsible-file.tsx new file mode 100644 index 000000000..d3b293591 --- /dev/null +++ b/apps/arc-web/app/components/collapsible-file.tsx @@ -0,0 +1,44 @@ +import { useState } from "react"; +import { ChevronRightIcon } from "@heroicons/react/20/solid"; +import type { FileContents } from "@pierre/diffs"; +import { File } from "@pierre/diffs/react"; + +export function CollapsibleFile({ + file, + defaultOpen = true, +}: { + file: FileContents; + defaultOpen?: boolean; +}) { + const [open, setOpen] = useState(defaultOpen); + + const lines = file.contents.split("\n"); + const lineCount = lines.length; + const loc = lines.filter((l) => l.trim().length > 0).length; + + return ( +
+ + +
+
+ +
+
+ ); +} diff --git a/apps/arc-web/app/routes.ts b/apps/arc-web/app/routes.ts index 31e463c39..dc0bad8ef 100644 --- a/apps/arc-web/app/routes.ts +++ b/apps/arc-web/app/routes.ts @@ -19,6 +19,8 @@ export default [ route("runs/:id", "routes/run-detail.tsx", [ index("routes/run-overview.tsx"), route("stages/:stageId", "routes/run-stages.tsx"), + route("configuration", "routes/run-configuration.tsx"), + route("graph", "routes/run-graph.tsx"), route("files", "routes/run-files-changed.tsx"), route("usage", "routes/run-usage.tsx"), ]), diff --git a/apps/arc-web/app/routes/run-configuration.tsx b/apps/arc-web/app/routes/run-configuration.tsx new file mode 100644 index 000000000..b26cc6c32 --- /dev/null +++ b/apps/arc-web/app/routes/run-configuration.tsx @@ -0,0 +1,101 @@ +import { Link, useParams } from "react-router"; +import { CheckCircleIcon, ArrowPathIcon, PauseCircleIcon, XCircleIcon } from "@heroicons/react/24/solid"; +import { DocumentTextIcon, MapIcon } from "@heroicons/react/24/outline"; +import { findRun } from "../data/runs"; +import { workflowData } from "./workflow-detail"; +import { CollapsibleFile } from "../components/collapsible-file"; + +export const handle = { wide: true }; + +type StageStatus = "completed" | "running" | "pending" | "failed"; + +interface Stage { + id: string; + name: string; + status: StageStatus; + duration: string; +} + +const stages: Stage[] = [ + { id: "detect-drift", name: "Detect Drift", status: "completed", duration: "1m 12s" }, + { id: "propose-changes", name: "Propose Changes", status: "completed", duration: "2m 34s" }, + { id: "review-changes", name: "Review Changes", status: "completed", duration: "0m 45s" }, + { id: "apply-changes", name: "Apply Changes", status: "running", duration: "1m 58s" }, +]; + +const statusConfig: Record = { + completed: { icon: CheckCircleIcon, color: "text-mint" }, + running: { icon: ArrowPathIcon, color: "text-teal-500" }, + pending: { icon: PauseCircleIcon, color: "text-navy-600" }, + failed: { icon: XCircleIcon, color: "text-coral" }, +}; + +export default function RunConfiguration() { + const { id } = useParams(); + const run = findRun(id ?? ""); + const workflow = run ? workflowData[run.workflow] : undefined; + + return ( +
+ + +
+ {workflow ? ( + + ) : ( +

No configuration found.

+ )} +
+
+ ); +} diff --git a/apps/arc-web/app/routes/run-graph.tsx b/apps/arc-web/app/routes/run-graph.tsx new file mode 100644 index 000000000..c5552cb48 --- /dev/null +++ b/apps/arc-web/app/routes/run-graph.tsx @@ -0,0 +1,119 @@ +import { useEffect, useState } from "react"; +import { Link, useParams } from "react-router"; +import type { BundledLanguage } from "@pierre/diffs"; +import { CheckCircleIcon, ArrowPathIcon, PauseCircleIcon, XCircleIcon } from "@heroicons/react/24/solid"; +import { DocumentTextIcon, MapIcon } from "@heroicons/react/24/outline"; +import { findRun } from "../data/runs"; +import { workflowData } from "./workflow-detail"; +import { registerDotLanguage } from "../data/register-dot-language"; +import { CollapsibleFile } from "../components/collapsible-file"; + +export const handle = { wide: true }; + +type StageStatus = "completed" | "running" | "pending" | "failed"; + +interface Stage { + id: string; + name: string; + status: StageStatus; + duration: string; +} + +const stages: Stage[] = [ + { id: "detect-drift", name: "Detect Drift", status: "completed", duration: "1m 12s" }, + { id: "propose-changes", name: "Propose Changes", status: "completed", duration: "2m 34s" }, + { id: "review-changes", name: "Review Changes", status: "completed", duration: "0m 45s" }, + { id: "apply-changes", name: "Apply Changes", status: "running", duration: "1m 58s" }, +]; + +const statusConfig: Record = { + completed: { icon: CheckCircleIcon, color: "text-mint" }, + running: { icon: ArrowPathIcon, color: "text-teal-500" }, + pending: { icon: PauseCircleIcon, color: "text-navy-600" }, + failed: { icon: XCircleIcon, color: "text-coral" }, +}; + +export default function RunGraph() { + const { id } = useParams(); + const run = findRun(id ?? ""); + const workflow = run ? workflowData[run.workflow] : undefined; + const [dotReady, setDotReady] = useState(false); + + useEffect(() => { + let cancelled = false; + registerDotLanguage().then(() => { + if (!cancelled) setDotReady(true); + }); + return () => { + cancelled = true; + }; + }, []); + + return ( +
+ + +
+ {workflow && dotReady ? ( + + ) : ( +

No workflow graph available.

+ )} +
+
+ ); +} diff --git a/apps/arc-web/app/routes/run-overview.tsx b/apps/arc-web/app/routes/run-overview.tsx index 9ae41d59b..1dfba072f 100644 --- a/apps/arc-web/app/routes/run-overview.tsx +++ b/apps/arc-web/app/routes/run-overview.tsx @@ -295,7 +295,7 @@ export default function RunOverview() {
  • @@ -304,7 +304,7 @@ export default function RunOverview() {
  • diff --git a/apps/arc-web/app/routes/run-stages.tsx b/apps/arc-web/app/routes/run-stages.tsx index 3eae0b4e1..6a4d0435a 100644 --- a/apps/arc-web/app/routes/run-stages.tsx +++ b/apps/arc-web/app/routes/run-stages.tsx @@ -192,7 +192,7 @@ export default function RunStages() {
    • @@ -201,7 +201,7 @@ export default function RunStages() {
    • diff --git a/apps/arc-web/app/routes/workflow-definition.tsx b/apps/arc-web/app/routes/workflow-definition.tsx index 928fc60de..29a54f602 100644 --- a/apps/arc-web/app/routes/workflow-definition.tsx +++ b/apps/arc-web/app/routes/workflow-definition.tsx @@ -1,50 +1,9 @@ -import { ChevronRightIcon } from "@heroicons/react/20/solid"; import { useEffect, useState } from "react"; import { useParams } from "react-router"; -import type { BundledLanguage, FileContents } from "@pierre/diffs"; -import { File } from "@pierre/diffs/react"; +import type { BundledLanguage } from "@pierre/diffs"; import { registerDotLanguage } from "../data/register-dot-language"; import { workflowData } from "./workflow-detail"; - -function CollapsibleFile({ - file, - defaultOpen = true, -}: { - file: FileContents; - defaultOpen?: boolean; -}) { - const [open, setOpen] = useState(defaultOpen); - - const lines = file.contents.split("\n"); - const lineCount = lines.length; - const loc = lines.filter((l) => l.trim().length > 0).length; - - return ( -
      - - -
      -
      - -
      -
      - ); -} +import { CollapsibleFile } from "../components/collapsible-file"; export default function WorkflowDefinition() { const { name } = useParams();