diff --git a/web/src/App.tsx b/web/src/App.tsx index 338734f741..a0dde72316 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,6 +1,4 @@ import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom"; -import { LinuxConfigProvider } from "./providers/LinuxConfigProvider"; -import { KubernetesConfigProvider } from "./providers/KubernetesConfigProvider"; import { SettingsProvider } from "./providers/SettingsProvider"; import { WizardProvider } from "./providers/WizardProvider"; import { InitialStateProvider } from "./providers/InitialStateProvider"; @@ -19,25 +17,21 @@ function App() { - - -
- - - - - - } - /> - } /> - - -
-
-
+
+ + + + + + } + /> + } /> + + +
diff --git a/web/src/components/wizard/completion/KubernetesCompletionStep.tsx b/web/src/components/wizard/completion/KubernetesCompletionStep.tsx index 5542ba3cad..a6ef73b62c 100644 --- a/web/src/components/wizard/completion/KubernetesCompletionStep.tsx +++ b/web/src/components/wizard/completion/KubernetesCompletionStep.tsx @@ -1,27 +1,82 @@ import React, { useState } from "react"; import Card from "../../common/Card"; import Button from "../../common/Button"; -import { useKubernetesConfig } from "../../../contexts/KubernetesConfigContext"; +import { useQuery } from "@tanstack/react-query"; import { useInitialState } from "../../../contexts/InitialStateContext"; import { useSettings } from "../../../contexts/SettingsContext"; -import { CheckCircle, ClipboardCheck, Copy, Terminal } from "lucide-react"; +import { useAuth } from "../../../contexts/AuthContext"; +import { CheckCircle, ClipboardCheck, Copy, Terminal, Loader2, XCircle } from "lucide-react"; +import { KubernetesConfigResponse } from "../../../types"; +import { getApiBase } from '../../../utils/api-base'; +import { ApiError } from '../../../utils/api-error'; const KubernetesCompletionStep: React.FC = () => { const [copied, setCopied] = useState(false); - const { config } = useKubernetesConfig(); - const { title } = useInitialState(); - const { settings } = useSettings(); - const themeColor = settings.themeColor; + const { title, installTarget, mode } = useInitialState(); + const { settings: { themeColor } } = useSettings(); + const { token } = useAuth(); + + const apiBase = getApiBase(installTarget, mode); + // Query for fetching install configuration + const { isLoading, error, data: config } = useQuery({ + queryKey: ["installConfig"], + queryFn: async () => { + const response = await fetch(`${apiBase}/installation/config`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + if (!response.ok) { + throw await ApiError.fromResponse(response, "Failed to fetch install configuration") + } + const configResponse = await response.json() as KubernetesConfigResponse; + return configResponse; + }, + }); const copyInstallCommand = () => { - if (config.installCommand) { - navigator.clipboard.writeText(config.installCommand).then(() => { + if (config?.resolved.installCommand) { + navigator.clipboard.writeText(config?.resolved.installCommand).then(() => { setCopied(true); setTimeout(() => setCopied(false), 2000); }); } }; + // Loading state + if (isLoading) { + return ( +
+ +
+ +

Loading installation configuration...

+
+
+
+ ); + } + + // Error state + if (error) { + return ( +
+ +
+
+ +
+

Failed to load installation configuration

+

+ {error instanceof ApiError ? error.details || error.message : error.message} +

+
+
+
+ ); + } + + // Success state return (
@@ -50,7 +105,7 @@ const KubernetesCompletionStep: React.FC = () => {
- {config.installCommand} + {config?.resolved.installCommand}
diff --git a/web/src/components/wizard/completion/LinuxCompletionStep.tsx b/web/src/components/wizard/completion/LinuxCompletionStep.tsx index a097433d3c..27bc517d7e 100644 --- a/web/src/components/wizard/completion/LinuxCompletionStep.tsx +++ b/web/src/components/wizard/completion/LinuxCompletionStep.tsx @@ -1,17 +1,73 @@ import React from "react"; import Card from "../../common/Card"; import Button from "../../common/Button"; -import { useLinuxConfig } from "../../../contexts/LinuxConfigContext"; import { useInitialState } from "../../../contexts/InitialStateContext"; import { useSettings } from "../../../contexts/SettingsContext"; -import { CheckCircle, ExternalLink } from "lucide-react"; +import { useQuery } from "@tanstack/react-query"; +import { useAuth } from "../../../contexts/AuthContext"; +import { CheckCircle, ExternalLink, Loader2, XCircle } from "lucide-react"; +import { getApiBase } from '../../../utils/api-base'; +import { LinuxConfigResponse } from "../../../types"; +import { ApiError } from '../../../utils/api-error'; const LinuxCompletionStep: React.FC = () => { - const { config } = useLinuxConfig(); - const { title } = useInitialState(); + const { title, installTarget, mode } = useInitialState(); const { settings } = useSettings(); const themeColor = settings.themeColor; + const { token } = useAuth(); + const apiBase = getApiBase(installTarget, mode); + // Query for fetching install configuration + const { isLoading, error, data: config } = useQuery({ + queryKey: ["installConfig"], + queryFn: async () => { + const response = await fetch(`${apiBase}/installation/config`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + if (!response.ok) { + throw await ApiError.fromResponse(response, "Failed to fetch install configuration") + } + const configResponse = await response.json() as LinuxConfigResponse; + return configResponse; + }, + }); + + // Loading state + if (isLoading) { + return ( +
+ +
+ +

Loading installation configuration...

+
+
+
+ ); + } + + // Error state + if (error) { + return ( +
+ +
+
+ +
+

Failed to load installation configuration

+

+ {error instanceof ApiError ? error.details || error.message : error.message} +

+
+
+
+ ); + } + + // Success state return (
@@ -26,7 +82,7 @@ const LinuxCompletionStep: React.FC = () => {