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",
|
"name": "kvm-ui",
|
||||||
"version": "2025.10.13.2055",
|
"version": "2025.10.14.2130",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "kvm-ui",
|
"name": "kvm-ui",
|
||||||
"version": "2025.10.13.2055",
|
"version": "2025.10.14.2130",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^2.2.9",
|
"@headlessui/react": "^2.2.9",
|
||||||
"@headlessui/tailwindcss": "^0.2.2",
|
"@headlessui/tailwindcss": "^0.2.2",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "kvm-ui",
|
"name": "kvm-ui",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2025.10.13.2055",
|
"version": "2025.10.14.2130",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^22.15.0"
|
"node": "^22.15.0"
|
||||||
|
|
|
||||||
|
|
@ -263,8 +263,8 @@ export default function Actionbar({
|
||||||
text={m.action_bar_settings()}
|
text={m.action_bar_settings()}
|
||||||
LeadingIcon={LuSettings}
|
LeadingIcon={LuSettings}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDisableVideoFocusTrap(true);
|
setDisableVideoFocusTrap(true);
|
||||||
navigateTo("/settings")
|
navigateTo("/settings")
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ export function Combobox({
|
||||||
|
|
||||||
// Disabled
|
// Disabled
|
||||||
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}
|
placeholder={disabled ? disabledMessage : placeholder}
|
||||||
displayValue={displayValue}
|
displayValue={displayValue}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ export function FeatureFlag({
|
||||||
if (!appVersion) return;
|
if (!appVersion) return;
|
||||||
console.log(
|
console.log(
|
||||||
`Feature '${name}' ${isEnabled ? "ENABLED" : "DISABLED"}: ` +
|
`Feature '${name}' ${isEnabled ? "ENABLED" : "DISABLED"}: ` +
|
||||||
`Current version: ${appVersion}, ` +
|
`Current version: ${appVersion}, ` +
|
||||||
`Required min version: ${minAppVersion || "N/A"}`,
|
`Required min version: ${minAppVersion || "N/A"}`,
|
||||||
);
|
);
|
||||||
}, [isEnabled, name, minAppVersion, appVersion]);
|
}, [isEnabled, name, minAppVersion, appVersion]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import type { Ref } from "react";
|
import React, { forwardRef, JSX, type Ref } from "react";
|
||||||
import React, { forwardRef, JSX } from "react";
|
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
import FieldLabel from "@/components/FieldLabel";
|
import FieldLabel from "@components/FieldLabel";
|
||||||
import Card from "@/components/Card";
|
import Card from "@components/Card";
|
||||||
import { cva } from "@/cva.config";
|
import { cva } from "@/cva.config";
|
||||||
|
|
||||||
const sizes = {
|
const sizes = {
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ export function JigglerSetting({
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="space-y-2">
|
<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">
|
<div className="flex flex-wrap gap-2">
|
||||||
{exampleConfigs.map((example, index) => (
|
{exampleConfigs.map((example, index) => (
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export default function MacroBar() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSendFn(send);
|
setSendFn(send);
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
loadMacros();
|
loadMacros();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ export function MacroForm({
|
||||||
? newSteps[stepIndex].keys
|
? newSteps[stepIndex].keys
|
||||||
: [];
|
: [];
|
||||||
if (keysArray.length >= MAX_KEYS_PER_STEP) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
newSteps[stepIndex].keys = [...keysArray, option.value];
|
newSteps[stepIndex].keys = [...keysArray, option.value];
|
||||||
|
|
@ -201,7 +201,7 @@ export function MacroForm({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-slate-500 dark:text-slate-400">
|
<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>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{errors.steps && errors.steps[0]?.keys && (
|
{errors.steps && errors.steps[0]?.keys && (
|
||||||
|
|
@ -247,10 +247,10 @@ export function MacroForm({
|
||||||
theme="light"
|
theme="light"
|
||||||
fullWidth
|
fullWidth
|
||||||
LeadingIcon={LuPlus}
|
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={() => {
|
onClick={() => {
|
||||||
if (isMaxStepsReached) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,11 +96,11 @@ export function MacroStepCard({
|
||||||
})),
|
})),
|
||||||
[keyDisplayMap]
|
[keyDisplayMap]
|
||||||
);
|
);
|
||||||
|
|
||||||
const filteredKeys = useMemo(() => {
|
const filteredKeys = useMemo(() => {
|
||||||
const selectedKeys = ensureArray(step.keys);
|
const selectedKeys = ensureArray(step.keys);
|
||||||
const availableKeys = keyOptions.filter(option => !selectedKeys.includes(option.value));
|
const availableKeys = keyOptions.filter(option => !selectedKeys.includes(option.value));
|
||||||
|
|
||||||
if (keyQuery === '') {
|
if (keyQuery === '') {
|
||||||
return availableKeys;
|
return availableKeys;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -134,7 +134,7 @@ export function MacroStepCard({
|
||||||
LeadingIcon={LuArrowDown}
|
LeadingIcon={LuArrowDown}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{onDelete && (
|
{onDelete && (
|
||||||
<Button
|
<Button
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
|
|
@ -149,7 +149,7 @@ export function MacroStepCard({
|
||||||
|
|
||||||
<div className="space-y-4 mt-2">
|
<div className="space-y-4 mt-2">
|
||||||
<div className="w-full flex flex-col gap-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">
|
<div className="inline-flex flex-wrap gap-3">
|
||||||
{Object.entries(groupedModifiers).map(([group, mods]) => (
|
{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">
|
<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>
|
</div>
|
||||||
|
|
||||||
<div className="w-full flex flex-col gap-1">
|
<div className="w-full flex flex-col gap-1">
|
||||||
<div className="flex items-center 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>
|
</div>
|
||||||
{ensureArray(step.keys) && step.keys.length > 0 && (
|
{ensureArray(step.keys) && step.keys.length > 0 && (
|
||||||
<div className="flex flex-wrap gap-1 pb-2">
|
<div className="flex flex-wrap gap-1 pb-2">
|
||||||
|
|
@ -216,7 +216,7 @@ export function MacroStepCard({
|
||||||
displayValue={() => keyQuery}
|
displayValue={() => keyQuery}
|
||||||
onInputChange={onKeyQueryChange}
|
onInputChange={onKeyQueryChange}
|
||||||
options={() => filteredKeys}
|
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"
|
size="SM"
|
||||||
immediate
|
immediate
|
||||||
disabled={ensureArray(step.keys).length >= MAX_KEYS_PER_STEP}
|
disabled={ensureArray(step.keys).length >= MAX_KEYS_PER_STEP}
|
||||||
|
|
@ -225,7 +225,7 @@ export function MacroStepCard({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full flex flex-col gap-1">
|
<div className="w-full flex flex-col gap-1">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<FieldLabel label={m.macro_step_duration_label()} description={m.macro_step_duration_description()} />
|
<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 { UsbConfigState } from "@hooks/stores";
|
||||||
import { JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc";
|
import { JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc";
|
||||||
|
|
@ -94,7 +94,7 @@ export function UsbInfoSetting() {
|
||||||
|
|
||||||
const syncUsbConfigProduct = useCallback(() => {
|
const syncUsbConfigProduct = useCallback(() => {
|
||||||
send("getUsbConfig", {}, (resp: JsonRpcResponse) => {
|
send("getUsbConfig", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to load USB Config:", resp.error);
|
console.error("Failed to load USB Config:", resp.error);
|
||||||
notifications.error(
|
notifications.error(
|
||||||
m.usb_config_failed_load({ error: String(resp.error.data || "Unknown 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()}
|
description={m.mount_virtual_media_description()}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="animate-fadeIn opacity-0 space-y-2"
|
className="animate-fadeIn opacity-0 space-y-2"
|
||||||
style={{
|
style={{
|
||||||
animationDuration: "0.7s",
|
animationDuration: "0.7s",
|
||||||
|
|
@ -157,7 +157,7 @@ const MountPopopover = forwardRef<HTMLDivElement, object>((_props, ref) => {
|
||||||
</div>
|
</div>
|
||||||
{remoteVirtualMediaState ? (
|
{remoteVirtualMediaState ? (
|
||||||
<div className="flex select-none items-center justify-between text-xs">
|
<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>{m.mount_mounted_as()}</span>{" "}
|
||||||
<span className="font-semibold">
|
<span className="font-semibold">
|
||||||
{remoteVirtualMediaState.mode === "Disk" ? m.mount_mode_disk() : m.mount_mode_cdrom()}
|
{remoteVirtualMediaState.mode === "Disk" ? m.mount_mode_disk() : m.mount_mode_cdrom()}
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,8 @@ const ToastContent = ({
|
||||||
t: Toast;
|
t: Toast;
|
||||||
}) => (
|
}) => (
|
||||||
<Card
|
<Card
|
||||||
className={`${
|
className={`${t.visible ? "animate-enter" : "animate-leave"
|
||||||
t.visible ? "animate-enter" : "animate-leave"
|
} pointer-events-auto z-30 w-full max-w-sm shadow-xl!`}
|
||||||
} 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">
|
<div className="flex items-center gap-x-2 p-2.5 px-2">
|
||||||
{icon}
|
{icon}
|
||||||
|
|
|
||||||
|
|
@ -1159,7 +1159,7 @@ function UploadFileView({
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between text-xs text-slate-600 dark:text-slate-400">
|
<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>
|
<span>
|
||||||
{uploadSpeed !== null
|
{uploadSpeed !== null
|
||||||
? `${formatters.bytes(uploadSpeed)}/s`
|
? `${formatters.bytes(uploadSpeed)}/s`
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ export default function OtherSessionRoute() {
|
||||||
{m.other_session_detected()}
|
{m.other_session_detected()}
|
||||||
</p>
|
</p>
|
||||||
<p className="mb-4 text-sm text-slate-600 dark:text-slate-400">
|
<p className="mb-4 text-sm text-slate-600 dark:text-slate-400">
|
||||||
{m.other_session_take_over()}
|
{m.other_session_take_over()}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex items-center justify-start space-x-4">
|
<div className="flex items-center justify-start space-x-4">
|
||||||
<Button size="SM" theme="primary" text={m.other_session_use_here_button()} onClick={handleClose} />
|
<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) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
enabled
|
enabled
|
||||||
? m.advanced_error_usb_emulation_enable({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()})
|
: m.advanced_error_usb_emulation_disable({ error: resp.error.data || m.unknown_error() })
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +82,7 @@ export default function SettingsAdvancedRoute() {
|
||||||
send("resetConfig", {}, (resp: JsonRpcResponse) => {
|
send("resetConfig", {}, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +94,7 @@ export default function SettingsAdvancedRoute() {
|
||||||
send("setSSHKeyState", { sshKey }, (resp: JsonRpcResponse) => {
|
send("setSSHKeyState", { sshKey }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +107,7 @@ export default function SettingsAdvancedRoute() {
|
||||||
send("setDevModeState", { enabled: developerMode }, (resp: JsonRpcResponse) => {
|
send("setDevModeState", { enabled: developerMode }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +122,7 @@ export default function SettingsAdvancedRoute() {
|
||||||
send("setDevChannelState", { enabled }, (resp: JsonRpcResponse) => {
|
send("setDevChannelState", { enabled }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -138,8 +138,8 @@ export default function SettingsAdvancedRoute() {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
notifications.error(
|
||||||
enabled
|
enabled
|
||||||
? m.advanced_error_loopback_enable({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()})
|
: m.advanced_error_loopback_disable({ error: resp.error.data || m.unknown_error() })
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -308,7 +308,7 @@ function UpdatingDeviceState({
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between text-sm text-slate-600 dark:text-slate-300">
|
<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 ? (
|
{calculateOverallProgress("system") < 100 ? (
|
||||||
<span>{formatProgress(calculateOverallProgress("system"))}</span>
|
<span>{formatProgress(calculateOverallProgress("system"))}</span>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
@ -340,7 +340,7 @@ function UpdatingDeviceState({
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between text-sm text-slate-600 dark:text-slate-300">
|
<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 ? (
|
{calculateOverallProgress("system") < 100 ? (
|
||||||
<span>{formatProgress(calculateOverallProgress("app"))}</span>
|
<span>{formatProgress(calculateOverallProgress("app"))}</span>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ export default function SettingsKeyboardRoute() {
|
||||||
send("setKeyboardLayout", { layout: isoCode }, resp => {
|
send("setKeyboardLayout", { layout: isoCode }, resp => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
notifications.error(
|
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 }));
|
notifications.success(m.keyboard_layout_success({ layout: isoCode }));
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,11 @@ export default function SettingsMacrosAddRoute() {
|
||||||
};
|
};
|
||||||
|
|
||||||
await saveMacros(normalizeSortOrders([...macros, newMacro]));
|
await saveMacros(normalizeSortOrders([...macros, newMacro]));
|
||||||
notifications.success(m.macros_created_success({name: newMacro.name}));
|
notifications.success(m.macros_created_success({ name: newMacro.name }));
|
||||||
navigate("../");
|
navigate("../");
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
if (error instanceof Error) {
|
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 {
|
} else {
|
||||||
notifications.error(m.macros_failed_create());
|
notifications.error(m.macros_failed_create());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ export default function SettingsMacrosEditRoute() {
|
||||||
|
|
||||||
setIsUpdating(true);
|
setIsUpdating(true);
|
||||||
try {
|
try {
|
||||||
const newMacros = macros.map(m =>
|
const newMacros = macros.map(m =>
|
||||||
m.id === macro.id ? {
|
m.id === macro.id ? {
|
||||||
...macro,
|
...macro,
|
||||||
name: updatedMacro.name!.trim(),
|
name: updatedMacro.name!.trim(),
|
||||||
|
|
@ -96,7 +96,6 @@ export default function SettingsMacrosEditRoute() {
|
||||||
<Button
|
<Button
|
||||||
size="SM"
|
size="SM"
|
||||||
theme="light"
|
theme="light"
|
||||||
|
|
||||||
className="text-red-500 dark:text-red-400"
|
className="text-red-500 dark:text-red-400"
|
||||||
LeadingIcon={LuTrash2}
|
LeadingIcon={LuTrash2}
|
||||||
onClick={() => setShowDeleteConfirm(true)}
|
onClick={() => setShowDeleteConfirm(true)}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ const loader: LoaderFunction = async ({ params }: LoaderFunctionArgs) => {
|
||||||
const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
|
const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
|
||||||
// Handle form submission
|
// Handle form submission
|
||||||
const { name, id, returnTo } = Object.fromEntries(await request.formData());
|
const { name, id, returnTo } = Object.fromEntries(await request.formData());
|
||||||
|
|
||||||
if (!name || name === "") {
|
if (!name || name === "") {
|
||||||
return { message: m.register_device_no_name() };
|
return { message: m.register_device_no_name() };
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +42,7 @@ const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
return redirect(returnTo?.toString() ?? `/devices/${id}`);
|
return redirect(returnTo?.toString() ?? `/devices/${id}`);
|
||||||
} else {
|
} else {
|
||||||
return { error: m.register_device_error({ error:res.statusText }) };
|
return { error: m.register_device_error({ error: res.statusText }) };
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
|
||||||
|
|
@ -686,7 +686,7 @@ export default function KvmIdRoute() {
|
||||||
});
|
});
|
||||||
}, [rpcDataChannel?.readyState, send, setHdmiState]);
|
}, [rpcDataChannel?.readyState, send, setHdmiState]);
|
||||||
|
|
||||||
const [ needLedState, setNeedLedState ] = useState(true);
|
const [needLedState, setNeedLedState] = useState(true);
|
||||||
|
|
||||||
// request keyboard led state from the device
|
// request keyboard led state from the device
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -742,8 +742,8 @@ export default function KvmIdRoute() {
|
||||||
}, [navigate, navigateTo, queryParams, setModalView, setQueryParams]);
|
}, [navigate, navigateTo, queryParams, setModalView, setQueryParams]);
|
||||||
|
|
||||||
// System update
|
// System update
|
||||||
const [ kvmTerminal, setKvmTerminal ] = useState<RTCDataChannel | null>(null);
|
const [kvmTerminal, setKvmTerminal] = useState<RTCDataChannel | null>(null);
|
||||||
const [ serialConsole, setSerialConsole ] = useState<RTCDataChannel | null>(null);
|
const [serialConsole, setSerialConsole] = useState<RTCDataChannel | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!peerConnection) return;
|
if (!peerConnection) return;
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error setting password:", 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