Skip to content

Commit cf8d45d

Browse files
authored
fix(ui): correctly route to the admin console (#3060)
* fix(ui): correctly route to the admin console * chore: help text dropped by mistake
1 parent 91de724 commit cf8d45d

15 files changed

+516
-457
lines changed

web/src/App.tsx

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
2-
import { LinuxConfigProvider } from "./providers/LinuxConfigProvider";
3-
import { KubernetesConfigProvider } from "./providers/KubernetesConfigProvider";
42
import { SettingsProvider } from "./providers/SettingsProvider";
53
import { WizardProvider } from "./providers/WizardProvider";
64
import { InitialStateProvider } from "./providers/InitialStateProvider";
@@ -19,25 +17,21 @@ function App() {
1917
<AuthProvider>
2018
<SettingsProvider>
2119
<InstallationProgressProvider>
22-
<LinuxConfigProvider>
23-
<KubernetesConfigProvider>
24-
<div className="min-h-screen bg-gray-50 text-gray-900 font-sans">
25-
<BrowserRouter>
26-
<Routes>
27-
<Route
28-
path="/"
29-
element={
30-
<WizardProvider>
31-
<InstallWizard />
32-
</WizardProvider>
33-
}
34-
/>
35-
<Route path="*" element={<Navigate to="/" replace />} />
36-
</Routes>
37-
</BrowserRouter>
38-
</div>
39-
</KubernetesConfigProvider>
40-
</LinuxConfigProvider>
20+
<div className="min-h-screen bg-gray-50 text-gray-900 font-sans">
21+
<BrowserRouter>
22+
<Routes>
23+
<Route
24+
path="/"
25+
element={
26+
<WizardProvider>
27+
<InstallWizard />
28+
</WizardProvider>
29+
}
30+
/>
31+
<Route path="*" element={<Navigate to="/" replace />} />
32+
</Routes>
33+
</BrowserRouter>
34+
</div>
4135
</InstallationProgressProvider>
4236
</SettingsProvider>
4337
</AuthProvider>

web/src/components/wizard/completion/KubernetesCompletionStep.tsx

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,82 @@
11
import React, { useState } from "react";
22
import Card from "../../common/Card";
33
import Button from "../../common/Button";
4-
import { useKubernetesConfig } from "../../../contexts/KubernetesConfigContext";
4+
import { useQuery } from "@tanstack/react-query";
55
import { useInitialState } from "../../../contexts/InitialStateContext";
66
import { useSettings } from "../../../contexts/SettingsContext";
7-
import { CheckCircle, ClipboardCheck, Copy, Terminal } from "lucide-react";
7+
import { useAuth } from "../../../contexts/AuthContext";
8+
import { CheckCircle, ClipboardCheck, Copy, Terminal, Loader2, XCircle } from "lucide-react";
9+
import { KubernetesConfigResponse } from "../../../types";
10+
import { getApiBase } from '../../../utils/api-base';
11+
import { ApiError } from '../../../utils/api-error';
812

913
const KubernetesCompletionStep: React.FC = () => {
1014
const [copied, setCopied] = useState(false);
11-
const { config } = useKubernetesConfig();
12-
const { title } = useInitialState();
13-
const { settings } = useSettings();
14-
const themeColor = settings.themeColor;
15+
const { title, installTarget, mode } = useInitialState();
16+
const { settings: { themeColor } } = useSettings();
17+
const { token } = useAuth();
18+
19+
const apiBase = getApiBase(installTarget, mode);
20+
// Query for fetching install configuration
21+
const { isLoading, error, data: config } = useQuery<KubernetesConfigResponse, Error>({
22+
queryKey: ["installConfig"],
23+
queryFn: async () => {
24+
const response = await fetch(`${apiBase}/installation/config`, {
25+
headers: {
26+
Authorization: `Bearer ${token}`,
27+
},
28+
});
29+
if (!response.ok) {
30+
throw await ApiError.fromResponse(response, "Failed to fetch install configuration")
31+
}
32+
const configResponse = await response.json() as KubernetesConfigResponse;
33+
return configResponse;
34+
},
35+
});
1536

1637
const copyInstallCommand = () => {
17-
if (config.installCommand) {
18-
navigator.clipboard.writeText(config.installCommand).then(() => {
38+
if (config?.resolved.installCommand) {
39+
navigator.clipboard.writeText(config?.resolved.installCommand).then(() => {
1940
setCopied(true);
2041
setTimeout(() => setCopied(false), 2000);
2142
});
2243
}
2344
};
2445

46+
// Loading state
47+
if (isLoading) {
48+
return (
49+
<div className="space-y-6" data-testid="kubernetes-completion-loading">
50+
<Card>
51+
<div className="flex flex-col items-center justify-center py-12">
52+
<Loader2 className="w-8 h-8 animate-spin mb-4" style={{ color: themeColor }} />
53+
<p className="text-gray-600">Loading installation configuration...</p>
54+
</div>
55+
</Card>
56+
</div>
57+
);
58+
}
59+
60+
// Error state
61+
if (error) {
62+
return (
63+
<div className="space-y-6" data-testid="kubernetes-completion-error">
64+
<Card>
65+
<div className="flex flex-col items-center justify-center py-12">
66+
<div className="w-12 h-12 rounded-full bg-red-100 flex items-center justify-center mb-4">
67+
<XCircle className="w-6 h-6 text-red-600" />
68+
</div>
69+
<p className="text-lg font-medium text-gray-900">Failed to load installation configuration</p>
70+
<p className="text-sm text-red-600 mt-2">
71+
{error instanceof ApiError ? error.details || error.message : error.message}
72+
</p>
73+
</div>
74+
</Card>
75+
</div>
76+
);
77+
}
78+
79+
// Success state
2580
return (
2681
<div className="space-y-6">
2782
<Card>
@@ -50,7 +105,7 @@ const KubernetesCompletionStep: React.FC = () => {
50105
<div className="flex items-start space-x-2 p-2 bg-white rounded border border-gray-300">
51106
<Terminal className="w-4 h-4 text-gray-400 mt-0.5 shrink-0" />
52107
<code className="font-mono text-sm text-left">
53-
{config.installCommand}
108+
{config?.resolved.installCommand}
54109
</code>
55110
</div>
56111
</div>

web/src/components/wizard/completion/LinuxCompletionStep.tsx

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,73 @@
11
import React from "react";
22
import Card from "../../common/Card";
33
import Button from "../../common/Button";
4-
import { useLinuxConfig } from "../../../contexts/LinuxConfigContext";
54
import { useInitialState } from "../../../contexts/InitialStateContext";
65
import { useSettings } from "../../../contexts/SettingsContext";
7-
import { CheckCircle, ExternalLink } from "lucide-react";
6+
import { useQuery } from "@tanstack/react-query";
7+
import { useAuth } from "../../../contexts/AuthContext";
8+
import { CheckCircle, ExternalLink, Loader2, XCircle } from "lucide-react";
9+
import { getApiBase } from '../../../utils/api-base';
10+
import { LinuxConfigResponse } from "../../../types";
11+
import { ApiError } from '../../../utils/api-error';
812

913
const LinuxCompletionStep: React.FC = () => {
10-
const { config } = useLinuxConfig();
11-
const { title } = useInitialState();
14+
const { title, installTarget, mode } = useInitialState();
1215
const { settings } = useSettings();
1316
const themeColor = settings.themeColor;
1417

18+
const { token } = useAuth();
19+
const apiBase = getApiBase(installTarget, mode);
20+
// Query for fetching install configuration
21+
const { isLoading, error, data: config } = useQuery<LinuxConfigResponse, Error>({
22+
queryKey: ["installConfig"],
23+
queryFn: async () => {
24+
const response = await fetch(`${apiBase}/installation/config`, {
25+
headers: {
26+
Authorization: `Bearer ${token}`,
27+
},
28+
});
29+
if (!response.ok) {
30+
throw await ApiError.fromResponse(response, "Failed to fetch install configuration")
31+
}
32+
const configResponse = await response.json() as LinuxConfigResponse;
33+
return configResponse;
34+
},
35+
});
36+
37+
// Loading state
38+
if (isLoading) {
39+
return (
40+
<div className="space-y-6" data-testid="linux-completion-loading">
41+
<Card>
42+
<div className="flex flex-col items-center justify-center py-12">
43+
<Loader2 className="w-8 h-8 animate-spin mb-4" style={{ color: themeColor }} />
44+
<p className="text-gray-600">Loading installation configuration...</p>
45+
</div>
46+
</Card>
47+
</div>
48+
);
49+
}
50+
51+
// Error state
52+
if (error) {
53+
return (
54+
<div className="space-y-6" data-testid="linux-completion-error">
55+
<Card>
56+
<div className="flex flex-col items-center justify-center py-12">
57+
<div className="w-12 h-12 rounded-full bg-red-100 flex items-center justify-center mb-4">
58+
<XCircle className="w-6 h-6 text-red-600" />
59+
</div>
60+
<p className="text-lg font-medium text-gray-900">Failed to load installation configuration</p>
61+
<p className="text-sm text-red-600 mt-2">
62+
{error instanceof ApiError ? error.details || error.message : error.message}
63+
</p>
64+
</div>
65+
</Card>
66+
</div>
67+
);
68+
}
69+
70+
// Success state
1571
return (
1672
<div className="space-y-6">
1773
<Card>
@@ -26,7 +82,7 @@ const LinuxCompletionStep: React.FC = () => {
2682
<Button
2783
className="mt-4"
2884
dataTestId="admin-console-button"
29-
onClick={() => window.open(`http://${window.location.hostname}:${config.adminConsolePort}`, "_blank")}
85+
onClick={() => window.open(`http://${window.location.hostname}:${config?.resolved.adminConsolePort}`, "_blank")}
3086
icon={<ExternalLink className="ml-2 mr-1 h-5 w-5" />}
3187
>
3288
Visit Admin Console

web/src/components/wizard/setup/KubernetesSetupStep.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ import React, { useState } from "react";
22
import Input from "../../common/Input";
33
import Button from "../../common/Button";
44
import Card from "../../common/Card";
5-
import { useKubernetesConfig } from "../../../contexts/KubernetesConfigContext";
65
import { useWizard } from "../../../contexts/WizardModeContext";
76
import { useQuery, useMutation } from "@tanstack/react-query";
87
import { useAuth } from "../../../contexts/AuthContext";
98
import { formatErrorMessage } from "../../../utils/errorMessage";
109
import { ChevronRight, ChevronLeft } from "lucide-react";
11-
import { KubernetesConfig } from "../../../types";
10+
import { KubernetesConfig, KubernetesConfigResponse } from "../../../types";
1211
import { getApiBase } from '../../../utils/api-base';
1312
import { ApiError } from '../../../utils/api-error';
1413

@@ -36,14 +35,7 @@ interface Status {
3635
description?: string;
3736
}
3837

39-
interface KubernetesConfigResponse {
40-
values: KubernetesConfig;
41-
defaults: KubernetesConfig;
42-
resolved: KubernetesConfig;
43-
}
44-
4538
const KubernetesSetupStep: React.FC<KubernetesSetupStepProps> = ({ onNext, onBack }) => {
46-
const { updateConfig } = useKubernetesConfig(); // We need to make sure to update the global config
4739
const { text, target, mode } = useWizard();
4840
const [error, setError] = useState<string | null>(null);
4941
const [defaults, setDefaults] = useState<KubernetesConfig>({});
@@ -64,8 +56,6 @@ const KubernetesSetupStep: React.FC<KubernetesSetupStepProps> = ({ onNext, onBac
6456
throw await ApiError.fromResponse(response, "Failed to fetch install configuration")
6557
}
6658
const configResponse = await response.json();
67-
// Update the global config with resolved config which includes user values and defaults.
68-
updateConfig(configResponse.resolved);
6959
// Store defaults for display in help text
7060
setDefaults(configResponse.defaults);
7161
// Store the config values for display in the form inputs
@@ -92,8 +82,6 @@ const KubernetesSetupStep: React.FC<KubernetesSetupStepProps> = ({ onNext, onBac
9282
return response.json();
9383
},
9484
onSuccess: () => {
95-
// Update the global (context) config we use accross the project
96-
updateConfig(configValues);
9785
// Clear any previous errors
9886
setError(null);
9987
startInstallation();

web/src/components/wizard/setup/LinuxSetupStep.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@ import Select from "../../common/Select";
44
import Button from "../../common/Button";
55
import Card from "../../common/Card";
66
import { useInitialState } from "../../../contexts/InitialStateContext";
7-
import { useLinuxConfig } from "../../../contexts/LinuxConfigContext";
87
import { useWizard } from "../../../contexts/WizardModeContext";
98
import { useQuery, useMutation } from "@tanstack/react-query";
109
import { useAuth } from "../../../contexts/AuthContext";
1110
import { formatErrorMessage } from "../../../utils/errorMessage";
1211
import { ChevronDown, ChevronLeft, ChevronRight } from "lucide-react";
13-
import { LinuxConfig, State } from "../../../types";
12+
import { LinuxConfigResponse, LinuxConfig, State } from "../../../types";
1413
import { getApiBase } from '../../../utils/api-base';
1514
import { ApiError } from '../../../utils/api-error';
1615

@@ -45,12 +44,6 @@ interface Status {
4544
description?: string;
4645
}
4746

48-
interface LinuxConfigResponse {
49-
values: LinuxConfig;
50-
defaults: LinuxConfig;
51-
resolved: LinuxConfig;
52-
}
53-
5447
interface InstallationStatusResponse {
5548
description: string;
5649
lastUpdated: string;
@@ -62,7 +55,6 @@ interface NetworkInterfacesResponse {
6255
}
6356

6457
const LinuxSetupStep: React.FC<LinuxSetupStepProps> = ({ onNext, onBack }) => {
65-
const { updateConfig } = useLinuxConfig(); // We need to make sure to update the global config
6658
const { text, target, mode } = useWizard();
6759
const { title } = useInitialState();
6860
const [isInstallationStatusPolling, setIsInstallationStatusPolling] = useState(false);
@@ -86,8 +78,6 @@ const LinuxSetupStep: React.FC<LinuxSetupStepProps> = ({ onNext, onBack }) => {
8678
throw await ApiError.fromResponse(response, "Failed to fetch install configuration")
8779
}
8880
const configResponse = await response.json();
89-
// Update the global config with resolved config which includes user values and defaults.
90-
updateConfig(configResponse.resolved);
9181
// Store defaults for display in help text
9282
setDefaults(configResponse.defaults);
9383
// Store the config values for display in the form inputs
@@ -150,8 +140,6 @@ const LinuxSetupStep: React.FC<LinuxSetupStepProps> = ({ onNext, onBack }) => {
150140
return response.json();
151141
},
152142
onSuccess: () => {
153-
// Update the global (context) config we use accross the project
154-
updateConfig(configValues);
155143
// Clear any previous errors
156144
setError(null);
157145
// Start polling installation status

0 commit comments

Comments
 (0)