mirror of https://github.com/jetkvm/kvm.git
Restore some missing blanks
This commit is contained in:
parent
75716405d5
commit
c6a12588f5
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export default function MacroBar() {
|
|||
|
||||
useEffect(() => {
|
||||
setSendFn(send);
|
||||
|
||||
|
||||
if (!initialized) {
|
||||
loadMacros();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()} />
|
||||
|
|
|
|||
|
|
@ -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") }),
|
||||
|
|
|
|||
|
|
@ -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()}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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} />
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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 }));
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) }) };
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue