Settings General pages

This commit is contained in:
Marc Brooks 2025-10-14 00:03:18 -05:00
parent f2e665126a
commit 340a04f23a
No known key found for this signature in database
GPG Key ID: 583A6AF2D6AE1DC6
4 changed files with 118 additions and 82 deletions

View File

@ -337,6 +337,7 @@
"rename_device_new_name_placeholder": "Plex Media Server",
"rename_device_no_name": "Please specify a name",
"rename": "Rename",
"retry": "Retry",
"saving": "Saving…",
"search_placeholder": "Search…",
"serial_console_baud_rate": "Baud Rate",
@ -599,5 +600,50 @@
"appearance_theme_light": "Light",
"appearance_theme_system": "System",
"appearance_theme": "Theme",
"appearance_title": "Appearance"
"appearance_title": "Appearance",
"general_app_version": "App: {version}",
"general_auto_update_description": "Automatically update the device to the latest version",
"general_auto_update_error": "Failed to set auto-update: {error}",
"general_auto_update_title": "Auto Update",
"general_check_for_updates": "Check for Updates",
"general_page_description": "Configure device settings and update preferences",
"general_reboot_device": "Reboot Device",
"general_reboot_device_description": "Power cycle the JetKVM",
"general_system_version": "System: {version}",
"general_title": "General",
"general_update_app_update_title": "App Update",
"general_update_application_type": "App",
"general_update_available_description": "A new update is available to enhance system performance and improve compatibility. We recommend updating to ensure everything runs smoothly.",
"general_update_available_title": "Update available",
"general_update_background_button": "Update in Background",
"general_update_check_again_button": "Check Again",
"general_update_checking_description": "We're ensuring your device has the latest features and improvements.",
"general_update_checking_title": "Checking for updates...",
"general_update_completed_description": "Your device has been successfully updated to the latest version. Enjoy the new features and improvements!",
"general_update_completed_title": "Update Completed Successfully",
"general_update_error_description": "An error occurred while updating your device. Please try again later.",
"general_update_error_details": "Error details: {errorMessage}",
"general_update_error_title": "Update Error",
"general_update_later_button": "Do it later",
"general_update_now_button": "Update Now",
"general_update_rebooting": "Rebooting to complete the update...",
"general_update_system_type": "System",
"general_update_status_awaiting_reboot": "Awaiting reboot",
"general_update_status_downloading": "Downloading {update_type} update...",
"general_update_status_fetching": "Fetching update information...",
"general_update_status_installing": "Installing {update_type} update...",
"general_update_status_verifying": "Verifying {update_type} update...",
"general_update_system_update_title": "Linux System Update",
"general_update_up_to_date_description": "Your system is running the latest version. No updates are currently available.",
"general_update_up_to_date_title": "System is up to date",
"general_update_updating_description": "Please don't turn off your device. This process may take a few minutes.",
"general_update_updating_title": "Updating your device",
"general_reboot_description": "Do you want to proceed with rebooting the system?",
"general_reboot_no_button": "No",
"general_reboot_title": "Reboot JetKVM",
"general_reboot_yes_button": "Yes"
}

View File

@ -1,16 +1,14 @@
import { useState, useEffect } from "react";
import { useState , useEffect } from "react";
import { JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc";
import { useDeviceUiNavigation } from "@hooks/useAppNavigation";
import { useDeviceStore } from "@hooks/stores";
import { Button } from "@components/Button";
import Checkbox from "@components/Checkbox";
import { SettingsItem } from "@components/SettingsItem";
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
import { SettingsPageHeader } from "../components/SettingsPageheader";
import { Button } from "../components/Button";
import notifications from "../notifications";
import Checkbox from "../components/Checkbox";
import { useDeviceUiNavigation } from "../hooks/useAppNavigation";
import { useDeviceStore } from "../hooks/stores";
import { SettingsPageHeader } from "@components/SettingsPageheader";
import notifications from "@/notifications";
import { m } from "@localizations/messages.js";
export default function SettingsGeneralRoute() {
const { send } = useJsonRpc();
@ -34,7 +32,7 @@ export default function SettingsGeneralRoute() {
send("setAutoUpdateState", { enabled }, (resp: JsonRpcResponse) => {
if ("error" in resp) {
notifications.error(
`Failed to set auto-update: ${resp.error.data || "Unknown error"}`,
m.general_auto_update_error({ error: resp.error.data || m.unknown_error() }),
);
return;
}
@ -45,44 +43,36 @@ export default function SettingsGeneralRoute() {
return (
<div className="space-y-4">
<SettingsPageHeader
title="General"
description="Configure device settings and update preferences"
title={m.general_title()}
description={m.general_page_description()}
/>
<div className="space-y-4">
<div className="space-y-4 pb-2">
<div className="mt-2 flex items-center justify-between gap-x-2">
<SettingsItem
title="Check for Updates"
title={m.general_check_for_updates()}
description={
currentVersions ? (
<>
App: {currentVersions.appVersion}
<br />
System: {currentVersions.systemVersion}
</>
) : (
<>
App: Loading...
<br />
System: Loading...
</>
)
<>
{m.general_app_version({ version: currentVersions ? currentVersions.appVersion : m.loading() })}
<br />
{m.general_system_version({ version: currentVersions ? currentVersions.systemVersion : m.loading() })}
</>
}
/>
<div>
<Button
size="SM"
theme="light"
text="Check for Updates"
text={m.general_check_for_updates()}
onClick={() => navigateTo("./update")}
/>
</div>
</div>
<div className="space-y-4">
<SettingsItem
title="Auto Update"
description="Automatically update the device to the latest version"
title={m.general_auto_update_title()}
description={m.general_auto_update_description()}
>
<Checkbox
checked={autoUpdate}
@ -95,14 +85,14 @@ export default function SettingsGeneralRoute() {
<div className="mt-2 flex items-center justify-between gap-x-2">
<SettingsItem
title="Reboot Device"
description="Power cycle the JetKVM"
title={m.general_reboot_device()}
description={m.general_reboot_device_description()}
/>
<div>
<Button
size="SM"
theme="light"
text="Reboot Device"
text={m.general_reboot_device()}
onClick={() => navigateTo("./reboot")}
/>
</div>

View File

@ -3,6 +3,7 @@ import { useNavigate } from "react-router";
import { useJsonRpc } from "@hooks/useJsonRpc";
import { Button } from "@components/Button";
import { m } from "@localizations/messages.js";
export default function SettingsGeneralRebootRoute() {
const navigate = useNavigate();
@ -50,15 +51,15 @@ function ConfirmationBox({
<div className="flex flex-col items-start justify-start space-y-4 text-left">
<div className="text-left">
<p className="text-base font-semibold text-black dark:text-white">
Reboot JetKVM
{m.general_reboot_title()}
</p>
<p className="text-sm text-slate-600 dark:text-slate-300">
Do you want to proceed with rebooting the system?
{m.general_reboot_description()}
</p>
<div className="mt-4 flex gap-x-2">
<Button size="SM" theme="light" text="Yes" onClick={onYes} />
<Button size="SM" theme="blank" text="No" onClick={onNo} />
<Button size="SM" theme="light" text={m.general_reboot_yes_button()} onClick={onYes} />
<Button size="SM" theme="blank" text={m.general_reboot_no_button()} onClick={onNo} />
</div>
</div>
</div>

View File

@ -1,14 +1,15 @@
import { useLocation, useNavigate } from "react-router";
import { useCallback, useEffect, useRef, useState } from "react";
import { useLocation, useNavigate } from "react-router";
import { CheckCircleIcon } from "@heroicons/react/20/solid";
import Card from "@/components/Card";
import { useJsonRpc } from "@/hooks/useJsonRpc";
import { useJsonRpc } from "@hooks/useJsonRpc";
import { UpdateState, useUpdateStore } from "@hooks/stores";
import { useDeviceUiNavigation } from "@hooks/useAppNavigation";
import { SystemVersionInfo, useVersion } from "@hooks/useVersion";
import { Button } from "@components/Button";
import { UpdateState, useUpdateStore } from "@/hooks/stores";
import LoadingSpinner from "@/components/LoadingSpinner";
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
import { SystemVersionInfo, useVersion } from "@/hooks/useVersion";
import Card from "@components/Card";
import LoadingSpinner from "@components/LoadingSpinner";
import { m } from "@localizations/messages.js";
export default function SettingsGeneralUpdateRoute() {
const navigate = useNavigate();
@ -160,10 +161,10 @@ function LoadingState({
<div className="space-y-4">
<div className="space-y-0">
<p className="text-base font-semibold text-black dark:text-white">
Checking for updates...
{m.general_update_checking_title()}
</p>
<p className="text-sm text-slate-600 dark:text-slate-300">
We{"'"}re ensuring your device has the latest features and improvements.
{m.general_update_checking_description()}
</p>
</div>
<div className="h-2.5 w-full overflow-hidden rounded-full bg-slate-300">
@ -174,7 +175,7 @@ function LoadingState({
></div>
</div>
<div className="mt-4">
<Button size="SM" theme="light" text="Cancel" onClick={onCancelCheck} />
<Button size="SM" theme="light" text={m.cancel()} onClick={onCancelCheck} />
</div>
</div>
</div>
@ -228,16 +229,18 @@ function UpdatingDeviceState({
const verfiedAt = otaState[`${type}VerifiedAt`];
const updatedAt = otaState[`${type}UpdatedAt`];
const update_type = () => (type === "system" ? m.general_update_system_type() : m.general_update_app_type());
if (!otaState.metadataFetchedAt) {
return "Fetching update information...";
return m.general_update_status_fetching();
} else if (!downloadFinishedAt) {
return `Downloading ${type} update...`;
return m.general_update_status_downloading({ update_type });
} else if (!verfiedAt) {
return `Verifying ${type} update...`;
return m.general_update_status_verifying({ update_type });
} else if (!updatedAt) {
return `Installing ${type} update...`;
return m.general_update_status_installing({ update_type });
} else {
return `Awaiting reboot`;
return m.general_update_status_awaiting_reboot();
}
};
@ -260,10 +263,10 @@ function UpdatingDeviceState({
<div className="w-full max-w-sm space-y-4">
<div className="space-y-0">
<p className="text-base font-semibold text-black dark:text-white">
Updating your device
{m.general_update_updating_title()}
</p>
<p className="text-sm text-slate-600 dark:text-slate-300">
Please don{"'"}t turn off your device. This process may take a few minutes.
{m.general_update_updating_description()}
</p>
</div>
<Card className="space-y-4 p-4">
@ -272,7 +275,7 @@ function UpdatingDeviceState({
<LoadingSpinner className="h-6 w-6 text-blue-700 dark:text-blue-500" />
<div className="flex justify-between text-sm text-slate-600 dark:text-slate-300">
<span className="font-medium text-black dark:text-white">
Rebooting to complete the update...
{m.general_update_rebooting()}
</span>
</div>
</div>
@ -288,7 +291,7 @@ function UpdatingDeviceState({
<div className="space-y-2">
<div className="flex items-center justify-between">
<p className="text-sm font-semibold text-black dark:text-white">
Linux System Update
{m.general_update_system_update_title()}
</p>
{calculateOverallProgress("system") < 100 ? (
<LoadingSpinner className="h-4 w-4 text-blue-700 dark:text-blue-500" />
@ -320,7 +323,7 @@ function UpdatingDeviceState({
<div className="space-y-2">
<div className="flex items-center justify-between">
<p className="text-sm font-semibold text-black dark:text-white">
App Update
{m.general_update_app_update_title()}
</p>
{calculateOverallProgress("app") < 100 ? (
<LoadingSpinner className="h-4 w-4 text-blue-700 dark:text-blue-500" />
@ -352,7 +355,7 @@ function UpdatingDeviceState({
<Button
size="XS"
theme="light"
text="Update in Background"
text={m.general_update_background_button()}
onClick={onMinimizeUpgradeDialog}
/>
</div>
@ -372,15 +375,15 @@ function SystemUpToDateState({
<div className="flex flex-col items-start justify-start space-y-4 text-left">
<div className="text-left">
<p className="text-base font-semibold text-black dark:text-white">
System is up to date
{m.general_update_up_to_date_title()}
</p>
<p className="text-sm text-slate-600 dark:text-slate-300">
Your system is running the latest version. No updates are currently available.
{m.general_update_up_to_date_description()}
</p>
<div className="mt-4 flex gap-x-2">
<Button size="SM" theme="light" text="Check Again" onClick={checkUpdate} />
<Button size="SM" theme="blank" text="Back" onClick={onClose} />
<Button size="SM" theme="light" text={m.general_update_check_again_button()} onClick={checkUpdate} />
<Button size="SM" theme="blank" text={m.general_update_back_button()} onClick={onClose} />
</div>
</div>
</div>
@ -400,30 +403,27 @@ function UpdateAvailableState({
<div className="flex flex-col items-start justify-start space-y-4 text-left">
<div className="text-left">
<p className="text-base font-semibold text-black dark:text-white">
Update available
{m.general_update_available_title()}
</p>
<p className="mb-2 text-sm text-slate-600 dark:text-slate-300">
A new update is available to enhance system performance and improve
compatibility. We recommend updating to ensure everything runs smoothly.
{m.general_update_available_description()}
</p>
<p className="mb-4 text-sm text-slate-600 dark:text-slate-300">
{versionInfo?.systemUpdateAvailable ? (
<>
<span className="font-semibold">System:</span>{" "}
{versionInfo?.remote?.systemVersion}
<span className="font-semibold">{m.general_update_system_type()}</span>:&nbsp;{versionInfo?.remote?.systemVersion}
<br />
</>
) : null}
{versionInfo?.appUpdateAvailable ? (
<>
<span className="font-semibold">App:</span>{" "}
{versionInfo?.remote?.appVersion}
<span className="font-semibold">{m.general_update_application_type()}</span>:&nbsp;{versionInfo?.remote?.appVersion}
</>
) : null}
</p>
<div className="flex items-center justify-start gap-x-2">
<Button size="SM" theme="primary" text="Update Now" onClick={onConfirmUpdate} />
<Button size="SM" theme="light" text="Do it later" onClick={onClose} />
<Button size="SM" theme="primary" text={m.general_update_now_button()} onClick={onConfirmUpdate} />
<Button size="SM" theme="light" text={m.general_update_later_button()} onClick={onClose} />
</div>
</div>
</div>
@ -435,14 +435,13 @@ function UpdateCompletedState({ onClose }: { onClose: () => void }) {
<div className="flex flex-col items-start justify-start space-y-4 text-left">
<div className="text-left">
<p className="text-base font-semibold dark:text-white">
Update Completed Successfully
{m.general_update_completed_title()}
</p>
<p className="mb-4 text-sm text-slate-600 dark:text-slate-400">
Your device has been successfully updated to the latest version. Enjoy the new
features and improvements!
{m.general_update_completed_description()}
</p>
<div className="flex items-center justify-start">
<Button size="SM" theme="primary" text="Back" onClick={onClose} />
<Button size="SM" theme="primary" text={m.back()} onClick={onClose} />
</div>
</div>
</div>
@ -461,18 +460,18 @@ function UpdateErrorState({
return (
<div className="flex flex-col items-start justify-start space-y-4 text-left">
<div className="text-left">
<p className="text-base font-semibold dark:text-white">Update Error</p>
<p className="text-base font-semibold dark:text-white">{m.general_update_error_title()}</p>
<p className="mb-4 text-sm text-slate-600 dark:text-slate-400">
An error occurred while updating your device. Please try again later.
{m.general_update_error_description()}
</p>
{errorMessage && (
<p className="mb-4 text-sm font-medium text-red-600 dark:text-red-400">
Error details: {errorMessage}
{m.general_update_error_details({ errorMessage })}
</p>
)}
<div className="flex items-center justify-start gap-x-2">
<Button size="SM" theme="light" text="Back" onClick={onClose} />
<Button size="SM" theme="blank" text="Retry" onClick={onRetryUpdate} />
<Button size="SM" theme="light" text={m.back()} onClick={onClose} />
<Button size="SM" theme="blank" text={m.retry()} onClick={onRetryUpdate} />
</div>
</div>
</div>