Restore some missing blanks

This commit is contained in:
Marc Brooks 2025-10-14 16:38:37 -05:00
parent 75716405d5
commit c6a12588f5
No known key found for this signature in database
GPG Key ID: 583A6AF2D6AE1DC6
23 changed files with 53 additions and 56 deletions

4
ui/package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "kvm-ui",
"version": "2025.10.13.2055",
"version": "2025.10.14.2130",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "kvm-ui",
"version": "2025.10.13.2055",
"version": "2025.10.14.2130",
"dependencies": {
"@headlessui/react": "^2.2.9",
"@headlessui/tailwindcss": "^0.2.2",

View File

@ -1,7 +1,7 @@
{
"name": "kvm-ui",
"private": true,
"version": "2025.10.13.2055",
"version": "2025.10.14.2130",
"type": "module",
"engines": {
"node": "^22.15.0"

View File

@ -263,8 +263,8 @@ export default function Actionbar({
text={m.action_bar_settings()}
LeadingIcon={LuSettings}
onClick={() => {
setDisableVideoFocusTrap(true);
navigateTo("/settings")
setDisableVideoFocusTrap(true);
navigateTo("/settings")
}}
/>
</div>

View File

@ -78,7 +78,7 @@ export function Combobox({
// Disabled
disabled &&
"pointer-events-none select-none bg-slate-50 text-slate-500/80 disabled:hover:bg-white dark:bg-slate-800 dark:text-slate-400/80 dark:disabled:hover:bg-slate-800",
"pointer-events-none select-none bg-slate-50 text-slate-500/80 disabled:hover:bg-white dark:bg-slate-800 dark:text-slate-400/80 dark:disabled:hover:bg-slate-800",
)}
placeholder={disabled ? disabledMessage : placeholder}
displayValue={displayValue}

View File

@ -19,8 +19,8 @@ export function FeatureFlag({
if (!appVersion) return;
console.log(
`Feature '${name}' ${isEnabled ? "ENABLED" : "DISABLED"}: ` +
`Current version: ${appVersion}, ` +
`Required min version: ${minAppVersion || "N/A"}`,
`Current version: ${appVersion}, ` +
`Required min version: ${minAppVersion || "N/A"}`,
);
}, [isEnabled, name, minAppVersion, appVersion]);

View File

@ -1,9 +1,8 @@
import type { Ref } from "react";
import React, { forwardRef, JSX } from "react";
import React, { forwardRef, JSX, type Ref } from "react";
import clsx from "clsx";
import FieldLabel from "@/components/FieldLabel";
import Card from "@/components/Card";
import FieldLabel from "@components/FieldLabel";
import Card from "@components/Card";
import { cva } from "@/cva.config";
const sizes = {

View File

@ -72,7 +72,7 @@ export function JigglerSetting({
return (
<div className="space-y-4">
<div className="space-y-2">
<h4 className="text-sm font-semibold text-gray-900 dark:text-gray-100">{m.jiggler_examples_label()}</h4>
<h4 className="text-sm font-semibold text-gray-900 dark:text-gray-100">{m.jiggler_examples_label()}</h4>
<div className="flex flex-wrap gap-2">
{exampleConfigs.map((example, index) => (
<Button

View File

@ -14,7 +14,7 @@ export default function MacroBar() {
useEffect(() => {
setSendFn(send);
if (!initialized) {
loadMacros();
}

View File

@ -113,7 +113,7 @@ export function MacroForm({
? newSteps[stepIndex].keys
: [];
if (keysArray.length >= MAX_KEYS_PER_STEP) {
showTemporaryError(m.macro_max_steps_error({max: MAX_KEYS_PER_STEP}));
showTemporaryError(m.macro_max_steps_error({ max: MAX_KEYS_PER_STEP }));
return;
}
newSteps[stepIndex].keys = [...keysArray, option.value];
@ -201,7 +201,7 @@ export function MacroForm({
/>
</div>
<span className="text-slate-500 dark:text-slate-400">
{m.macro_step_count({steps: macro.steps?.length || 0, max: MAX_STEPS_PER_MACRO})}
{m.macro_step_count({ steps: macro.steps?.length || 0, max: MAX_STEPS_PER_MACRO })}
</span>
</div>
{errors.steps && errors.steps[0]?.keys && (
@ -247,10 +247,10 @@ export function MacroForm({
theme="light"
fullWidth
LeadingIcon={LuPlus}
text={m.macro_add_step({ maxed_out: isMaxStepsReached ? m.macro_max_steps_reached({ max: MAX_STEPS_PER_MACRO} ) : ""})}
text={m.macro_add_step({ maxed_out: isMaxStepsReached ? m.macro_max_steps_reached({ max: MAX_STEPS_PER_MACRO }) : "" })}
onClick={() => {
if (isMaxStepsReached) {
showTemporaryError(m.macro_max_steps_error({max: MAX_STEPS_PER_MACRO}));
showTemporaryError(m.macro_max_steps_error({ max: MAX_STEPS_PER_MACRO }));
return;
}

View File

@ -96,11 +96,11 @@ export function MacroStepCard({
})),
[keyDisplayMap]
);
const filteredKeys = useMemo(() => {
const selectedKeys = ensureArray(step.keys);
const availableKeys = keyOptions.filter(option => !selectedKeys.includes(option.value));
if (keyQuery === '') {
return availableKeys;
} else {
@ -134,7 +134,7 @@ export function MacroStepCard({
LeadingIcon={LuArrowDown}
/>
</div>
{onDelete && (
{onDelete && (
<Button
size="XS"
theme="light"
@ -149,7 +149,7 @@ export function MacroStepCard({
<div className="space-y-4 mt-2">
<div className="w-full flex flex-col gap-2">
<FieldLabel label={m.macro_step_modifiers_label()} description={m.macro_step_modifiers_description()}/>
<FieldLabel label={m.macro_step_modifiers_label()} description={m.macro_step_modifiers_description()} />
<div className="inline-flex flex-wrap gap-3">
{Object.entries(groupedModifiers).map(([group, mods]) => (
<div key={group} className="relative min-w-[120px] rounded-md border border-slate-200 dark:border-slate-700 p-2">
@ -178,10 +178,10 @@ export function MacroStepCard({
))}
</div>
</div>
<div className="w-full flex flex-col gap-1">
<div className="flex items-center gap-1">
<FieldLabel label={m.macro_step_keys_label()} description={m.macro_step_keys_description({max: MAX_KEYS_PER_STEP})} />
<FieldLabel label={m.macro_step_keys_label()} description={m.macro_step_keys_description({ max: MAX_KEYS_PER_STEP })} />
</div>
{ensureArray(step.keys) && step.keys.length > 0 && (
<div className="flex flex-wrap gap-1 pb-2">
@ -216,7 +216,7 @@ export function MacroStepCard({
displayValue={() => keyQuery}
onInputChange={onKeyQueryChange}
options={() => filteredKeys}
disabledMessage={m.macro_step_max_keys_reached({max: MAX_KEYS_PER_STEP})}
disabledMessage={m.macro_step_max_keys_reached({ max: MAX_KEYS_PER_STEP })}
size="SM"
immediate
disabled={ensureArray(step.keys).length >= MAX_KEYS_PER_STEP}
@ -225,7 +225,7 @@ export function MacroStepCard({
/>
</div>
</div>
<div className="w-full flex flex-col gap-1">
<div className="flex items-center gap-1">
<FieldLabel label={m.macro_step_duration_label()} description={m.macro_step_duration_description()} />

View File

@ -1,4 +1,4 @@
import { useMemo , useCallback , useEffect, useState } from "react";
import { useMemo, useCallback, useEffect, useState } from "react";
import { UsbConfigState } from "@hooks/stores";
import { JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc";
@ -94,7 +94,7 @@ export function UsbInfoSetting() {
const syncUsbConfigProduct = useCallback(() => {
send("getUsbConfig", {}, (resp: JsonRpcResponse) => {
if ("error" in resp) {
if ("error" in resp) {
console.error("Failed to load USB Config:", resp.error);
notifications.error(
m.usb_config_failed_load({ error: String(resp.error.data || "Unknown error") }),

View File

@ -137,7 +137,7 @@ const MountPopopover = forwardRef<HTMLDivElement, object>((_props, ref) => {
description={m.mount_virtual_media_description()}
/>
<div
<div
className="animate-fadeIn opacity-0 space-y-2"
style={{
animationDuration: "0.7s",
@ -157,7 +157,7 @@ const MountPopopover = forwardRef<HTMLDivElement, object>((_props, ref) => {
</div>
{remoteVirtualMediaState ? (
<div className="flex select-none items-center justify-between text-xs">
<div className="select-none text-white dark:text-slate-300">
<div className="select-none text-white dark:text-slate-300">
<span>{m.mount_mounted_as()}</span>{" "}
<span className="font-semibold">
{remoteVirtualMediaState.mode === "Disk" ? m.mount_mode_disk() : m.mount_mode_cdrom()}

View File

@ -19,9 +19,8 @@ const ToastContent = ({
t: Toast;
}) => (
<Card
className={`${
t.visible ? "animate-enter" : "animate-leave"
} pointer-events-auto z-30 w-full max-w-sm shadow-xl!`}
className={`${t.visible ? "animate-enter" : "animate-leave"
} pointer-events-auto z-30 w-full max-w-sm shadow-xl!`}
>
<div className="flex items-center gap-x-2 p-2.5 px-2">
{icon}

View File

@ -1159,7 +1159,7 @@ function UploadFileView({
></div>
</div>
<div className="flex justify-between text-xs text-slate-600 dark:text-slate-400">
<span>{m.mount_uploading()}</span>
<span>{m.mount_uploading()}</span>{" "}
<span>
{uploadSpeed !== null
? `${formatters.bytes(uploadSpeed)}/s`

View File

@ -34,7 +34,7 @@ export default function OtherSessionRoute() {
{m.other_session_detected()}
</p>
<p className="mb-4 text-sm text-slate-600 dark:text-slate-400">
{m.other_session_take_over()}
{m.other_session_take_over()}
</p>
<div className="flex items-center justify-start space-x-4">
<Button size="SM" theme="primary" text={m.other_session_use_here_button()} onClick={handleClose} />

View File

@ -66,8 +66,8 @@ export default function SettingsAdvancedRoute() {
if ("error" in resp) {
notifications.error(
enabled
? m.advanced_error_usb_emulation_enable({error: resp.error.data || m.unknown_error()})
: m.advanced_error_usb_emulation_disable({error: resp.error.data || m.unknown_error()})
? m.advanced_error_usb_emulation_enable({ error: resp.error.data || m.unknown_error() })
: m.advanced_error_usb_emulation_disable({ error: resp.error.data || m.unknown_error() })
);
return;
}
@ -82,7 +82,7 @@ export default function SettingsAdvancedRoute() {
send("resetConfig", {}, (resp: JsonRpcResponse) => {
if ("error" in resp) {
notifications.error(
m.advanced_error_reset_config({error: resp.error.data || m.unknown_error()})
m.advanced_error_reset_config({ error: resp.error.data || m.unknown_error() })
);
return;
}
@ -94,7 +94,7 @@ export default function SettingsAdvancedRoute() {
send("setSSHKeyState", { sshKey }, (resp: JsonRpcResponse) => {
if ("error" in resp) {
notifications.error(
m.advanced_error_update_ssh_key({error: resp.error.data || m.unknown_error()})
m.advanced_error_update_ssh_key({ error: resp.error.data || m.unknown_error() })
);
return;
}
@ -107,7 +107,7 @@ export default function SettingsAdvancedRoute() {
send("setDevModeState", { enabled: developerMode }, (resp: JsonRpcResponse) => {
if ("error" in resp) {
notifications.error(
m.advanced_error_set_dev_mode({error: resp.error.data || m.unknown_error()})
m.advanced_error_set_dev_mode({ error: resp.error.data || m.unknown_error() })
);
return;
}
@ -122,7 +122,7 @@ export default function SettingsAdvancedRoute() {
send("setDevChannelState", { enabled }, (resp: JsonRpcResponse) => {
if ("error" in resp) {
notifications.error(
m.advanced_error_set_dev_channel({error: resp.error.data || m.unknown_error()})
m.advanced_error_set_dev_channel({ error: resp.error.data || m.unknown_error() })
);
return;
}
@ -138,8 +138,8 @@ export default function SettingsAdvancedRoute() {
if ("error" in resp) {
notifications.error(
enabled
? m.advanced_error_loopback_enable({error: resp.error.data || m.unknown_error()})
: m.advanced_error_loopback_disable({error: resp.error.data || m.unknown_error()})
? m.advanced_error_loopback_enable({ error: resp.error.data || m.unknown_error() })
: m.advanced_error_loopback_disable({ error: resp.error.data || m.unknown_error() })
);
return;
}

View File

@ -308,7 +308,7 @@ function UpdatingDeviceState({
></div>
</div>
<div className="flex justify-between text-sm text-slate-600 dark:text-slate-300">
<span>{getUpdateStatus("system")}</span>
<span>{getUpdateStatus("system")}</span>{" "}
{calculateOverallProgress("system") < 100 ? (
<span>{formatProgress(calculateOverallProgress("system"))}</span>
) : null}
@ -340,7 +340,7 @@ function UpdatingDeviceState({
></div>
</div>
<div className="flex justify-between text-sm text-slate-600 dark:text-slate-300">
<span>{getUpdateStatus("app")}</span>
<span>{getUpdateStatus("app")}</span>{" "}
{calculateOverallProgress("system") < 100 ? (
<span>{formatProgress(calculateOverallProgress("app"))}</span>
) : null}

View File

@ -34,7 +34,7 @@ export default function SettingsKeyboardRoute() {
send("setKeyboardLayout", { layout: isoCode }, resp => {
if ("error" in resp) {
notifications.error(
m.keyboard_layout_error({ error: resp.error.data || m.unknown_error() }),
m.keyboard_layout_error({ error: resp.error.data || m.unknown_error() }),
);
}
notifications.success(m.keyboard_layout_success({ layout: isoCode }));

View File

@ -25,11 +25,11 @@ export default function SettingsMacrosAddRoute() {
};
await saveMacros(normalizeSortOrders([...macros, newMacro]));
notifications.success(m.macros_created_success({name: newMacro.name}));
notifications.success(m.macros_created_success({ name: newMacro.name }));
navigate("../");
} catch (error: unknown) {
if (error instanceof Error) {
notifications.error(m.macros_failed_create_error({error: error.message || m.unknown_error() }));
notifications.error(m.macros_failed_create_error({ error: error.message || m.unknown_error() }));
} else {
notifications.error(m.macros_failed_create());
}

View File

@ -42,7 +42,7 @@ export default function SettingsMacrosEditRoute() {
setIsUpdating(true);
try {
const newMacros = macros.map(m =>
const newMacros = macros.map(m =>
m.id === macro.id ? {
...macro,
name: updatedMacro.name!.trim(),
@ -96,7 +96,6 @@ export default function SettingsMacrosEditRoute() {
<Button
size="SM"
theme="light"
className="text-red-500 dark:text-red-400"
LeadingIcon={LuTrash2}
onClick={() => setShowDeleteConfirm(true)}

View File

@ -31,7 +31,7 @@ const loader: LoaderFunction = async ({ params }: LoaderFunctionArgs) => {
const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
// Handle form submission
const { name, id, returnTo } = Object.fromEntries(await request.formData());
if (!name || name === "") {
return { message: m.register_device_no_name() };
}
@ -42,7 +42,7 @@ const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
if (res.ok) {
return redirect(returnTo?.toString() ?? `/devices/${id}`);
} else {
return { error: m.register_device_error({ error:res.statusText }) };
return { error: m.register_device_error({ error: res.statusText }) };
}
} catch (e) {
console.error(e);

View File

@ -686,7 +686,7 @@ export default function KvmIdRoute() {
});
}, [rpcDataChannel?.readyState, send, setHdmiState]);
const [ needLedState, setNeedLedState ] = useState(true);
const [needLedState, setNeedLedState] = useState(true);
// request keyboard led state from the device
useEffect(() => {
@ -742,8 +742,8 @@ export default function KvmIdRoute() {
}, [navigate, navigateTo, queryParams, setModalView, setQueryParams]);
// System update
const [ kvmTerminal, setKvmTerminal ] = useState<RTCDataChannel | null>(null);
const [ serialConsole, setSerialConsole ] = useState<RTCDataChannel | null>(null);
const [kvmTerminal, setKvmTerminal] = useState<RTCDataChannel | null>(null);
const [serialConsole, setSerialConsole] = useState<RTCDataChannel | null>(null);
useEffect(() => {
if (!peerConnection) return;

View File

@ -47,7 +47,7 @@ const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
}
} catch (error) {
console.error("Error setting password:", error);
return { error: m.auth_mode_local_password_failed_set({ error: String(error) })};
return { error: m.auth_mode_local_password_failed_set({ error: String(error) }) };
}
};