Skip to content

Commit d5be5e3

Browse files
committed
Ui fixes
1 parent a76299f commit d5be5e3

File tree

2 files changed

+64
-42
lines changed

2 files changed

+64
-42
lines changed

ui/src/routes/devices.$id.settings.access._index.tsx

Lines changed: 53 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ import notifications from "@/notifications";
1414
import { DEVICE_API } from "@/ui.config";
1515
import { useJsonRpc } from "@/hooks/useJsonRpc";
1616
import { isOnDevice } from "@/main";
17+
import { TextAreaWithLabel } from "@components/TextArea";
1718

1819
import { LocalDevice } from "./devices.$id";
1920
import { SettingsItem } from "./devices.$id.settings";
2021
import { CloudState } from "./adopt";
21-
import { TextAreaWithLabel } from "@components/TextArea";
2222

2323
export interface TLSState {
2424
mode: "self-signed" | "custom" | "disabled";
2525
certificate?: string;
2626
privateKey?: string;
27-
};
27+
}
2828

2929
export const loader = async () => {
3030
if (isOnDevice) {
@@ -147,9 +147,37 @@ export default function SettingsAccessIndexRoute() {
147147
}
148148
};
149149

150+
// Function to update TLS state - accepts a mode parameter
151+
const updateTlsState = useCallback(
152+
(mode: string, cert?: string, key?: string) => {
153+
const state = { mode } as TLSState;
154+
if (cert && key) {
155+
state.certificate = cert;
156+
state.privateKey = key;
157+
}
158+
159+
send("setTLSState", { state }, resp => {
160+
if ("error" in resp) {
161+
notifications.error(
162+
`Failed to update TLS settings: ${resp.error.data || "Unknown error"}`,
163+
);
164+
return;
165+
}
166+
167+
notifications.success("TLS settings updated successfully");
168+
});
169+
},
170+
[send],
171+
);
172+
150173
// Handle TLS mode change
151174
const handleTlsModeChange = (value: string) => {
152175
setTlsMode(value);
176+
177+
// For "disabled" and "self-signed" modes, immediately apply the settings
178+
if (value !== "custom") {
179+
updateTlsState(value);
180+
}
153181
};
154182

155183
const handleTlsCertChange = (value: string) => {
@@ -160,21 +188,10 @@ export default function SettingsAccessIndexRoute() {
160188
setTlsKey(value);
161189
};
162190

163-
const handleTlsUpdate = useCallback(() => {
164-
const state = { mode: tlsMode } as TLSState;
165-
if (tlsMode !== "disabled") {
166-
state.certificate = tlsCert;
167-
state.privateKey = tlsKey;
168-
}
169-
send("setTLSState", { state }, resp => {
170-
if ("error" in resp) {
171-
notifications.error(`Failed to update TLS settings: ${resp.error.data || "Unknown error"}`);
172-
return;
173-
}
174-
175-
notifications.success("TLS settings updated successfully");
176-
});
177-
}, [send, tlsMode, tlsCert, tlsKey]);
191+
// Update the custom TLS settings button click handler
192+
const handleCustomTlsUpdate = () => {
193+
updateTlsState(tlsMode, tlsCert, tlsKey);
194+
};
178195

179196
// Fetch device ID and cloud state on component mount
180197
useEffect(() => {
@@ -203,11 +220,9 @@ export default function SettingsAccessIndexRoute() {
203220
/>
204221
<>
205222
<SettingsItem
206-
title="HTTPS/TLS Mode"
207-
description={<>
208-
Select the TLS mode for your device <sup>experimental</sup><br />
209-
<small>The feature might not work as expected, please report any issues if you encounter any.</small>
210-
</>}
223+
title="HTTPS Mode"
224+
badge="Experimental"
225+
description="Configure secure HTTPS access to your device"
211226
>
212227
<SelectMenuBasic
213228
size="SM"
@@ -227,13 +242,15 @@ export default function SettingsAccessIndexRoute() {
227242
<div className="space-y-4">
228243
<SettingsItem
229244
title="TLS Certificate"
230-
description="Enter your TLS certificate here, if intermediate or root CA is used, you can paste the entire chain here too"
245+
description="Paste your TLS certificate below. For certificate chains, include the entire chain (leaf, intermediate, and root certificates)."
231246
/>
232247
<div className="space-y-4">
233248
<TextAreaWithLabel
234249
label="Certificate"
235250
rows={3}
236-
placeholder={"-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"}
251+
placeholder={
252+
"-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
253+
}
237254
value={tlsCert}
238255
onChange={e => handleTlsCertChange(e.target.value)}
239256
/>
@@ -243,32 +260,28 @@ export default function SettingsAccessIndexRoute() {
243260
<div className="space-y-4">
244261
<TextAreaWithLabel
245262
label="Private Key"
263+
description="For security reasons, it will not be displayed after saving."
246264
rows={3}
247-
placeholder={"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"}
265+
placeholder={
266+
"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
267+
}
248268
value={tlsKey}
249269
onChange={e => handleTlsKeyChange(e.target.value)}
250270
/>
251-
<p className="text-xs text-slate-600 dark:text-slate-400">
252-
Private key won't be shown again after saving.
253-
</p>
254271
</div>
255272
</div>
256273
</div>
274+
<div className="flex items-center gap-x-2">
275+
<Button
276+
size="SM"
277+
theme="primary"
278+
text="Update TLS Settings"
279+
onClick={handleCustomTlsUpdate}
280+
/>
281+
</div>
257282
</div>
258283
)}
259284

260-
261-
<div className="space-y-4">
262-
<div className="flex items-center gap-x-2">
263-
<Button
264-
size="SM"
265-
theme="light"
266-
text="Update TLS Settings"
267-
onClick={handleTlsUpdate}
268-
/>
269-
</div>
270-
</div>
271-
272285
<SettingsItem
273286
title="Authentication Mode"
274287
description={`Current mode: ${loaderData.authMode === "password" ? "Password protected" : "No password"}`}

ui/src/routes/devices.$id.settings.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,15 @@ export function SettingsItem({
234234
children,
235235
className,
236236
loading,
237+
badge,
237238
}: {
238239
title: string;
239240
description: string | React.ReactNode;
240241
children?: React.ReactNode;
241242
className?: string;
242243
name?: string;
243244
loading?: boolean;
245+
badge?: string;
244246
}) {
245247
return (
246248
<label
@@ -251,10 +253,17 @@ export function SettingsItem({
251253
>
252254
<div className="space-y-0.5">
253255
<div className="flex items-center gap-x-2">
254-
<h3 className="text-base font-semibold text-black dark:text-white">{title}</h3>
256+
<div className="flex items-center text-base font-semibold text-black dark:text-white">
257+
{title}
258+
{badge && (
259+
<span className="ml-2 rounded-full bg-red-500 px-2 py-1 text-[10px] font-medium leading-none text-white dark:border dark:border-red-700 dark:bg-red-800 dark:text-red-50">
260+
{badge}
261+
</span>
262+
)}
263+
</div>
255264
{loading && <LoadingSpinner className="h-4 w-4 text-blue-500" />}
256265
</div>
257-
<p className="text-sm text-slate-700 dark:text-slate-300">{description}</p>
266+
<div className="text-sm text-slate-700 dark:text-slate-300">{description}</div>
258267
</div>
259268
{children ? <div>{children}</div> : null}
260269
</label>

0 commit comments

Comments
 (0)