mirror of https://github.com/jetkvm/kvm.git
Add inlang/paraglide-js
This commit is contained in:
parent
d91b95783a
commit
d81a497926
|
@ -31,7 +31,10 @@
|
||||||
// Frontend
|
// Frontend
|
||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
"dbaeumer.vscode-eslint",
|
"dbaeumer.vscode-eslint",
|
||||||
"bradlc.vscode-tailwindcss"
|
"bradlc.vscode-tailwindcss",
|
||||||
|
"codeandstuff.package-json-upgrade",
|
||||||
|
// Localization
|
||||||
|
"inlang.vs-code-extension"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
// coding styles
|
||||||
|
"chrislajoie.vscode-modelines",
|
||||||
|
"editorconfig.editorconfig",
|
||||||
|
// GitHub
|
||||||
|
"GitHub.vscode-pull-request-github",
|
||||||
|
"github.vscode-github-actions",
|
||||||
|
// Golang
|
||||||
|
"golang.go",
|
||||||
|
// C / C++
|
||||||
|
"ms-vscode.cpptools",
|
||||||
|
"ms-vscode.cpptools-extension-pack",
|
||||||
|
// CMake / Makefile
|
||||||
|
"ms-vscode.makefile-tools",
|
||||||
|
"ms-vscode.cmake-tools",
|
||||||
|
// Frontend
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"bradlc.vscode-tailwindcss",
|
||||||
|
"codeandstuff.package-json-upgrade",
|
||||||
|
// Localization
|
||||||
|
"inlang.vs-code-extension"
|
||||||
|
]
|
||||||
|
}
|
|
@ -81,6 +81,8 @@ module.exports = defineConfig([{
|
||||||
map: [
|
map: [
|
||||||
["@components", "./src/components"],
|
["@components", "./src/components"],
|
||||||
["@routes", "./src/routes"],
|
["@routes", "./src/routes"],
|
||||||
|
["@hooks", "./src/hooks"],
|
||||||
|
["@providers", "./src/providers"],
|
||||||
["@assets", "./src/assets"],
|
["@assets", "./src/assets"],
|
||||||
["@", "./src"],
|
["@", "./src"],
|
||||||
],
|
],
|
||||||
|
|
|
@ -45,31 +45,39 @@
|
||||||
<link rel="shortcut icon" href="/favicon.ico" />
|
<link rel="shortcut icon" href="/favicon.ico" />
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||||
<meta name="apple-mobile-web-app-title" content="JetKVM" />
|
<meta name="apple-mobile-web-app-title" content="JetKVM" />
|
||||||
<link rel="manifest" href="/site.webmanifest" />
|
<link rel="manifest" href="/public/site.webmanifest" />
|
||||||
<meta name="theme-color" content="#051946" />
|
<meta name="theme-color" content="#051946" />
|
||||||
<meta name="description" content="A web-based KVM console for managing remote servers." />
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="A web-based KVM console for managing remote servers."
|
||||||
|
/>
|
||||||
<script>
|
<script>
|
||||||
function applyThemeFromPreference() {
|
function applyThemeFromPreference() {
|
||||||
// dark theme setup
|
// dark theme setup
|
||||||
var darkDesired = localStorage.theme === "dark" ||
|
var darkDesired =
|
||||||
|
localStorage.theme === "dark" ||
|
||||||
(!("theme" in localStorage) &&
|
(!("theme" in localStorage) &&
|
||||||
window.matchMedia("(prefers-color-scheme: dark)").matches)
|
window.matchMedia("(prefers-color-scheme: dark)").matches);
|
||||||
|
|
||||||
document.documentElement.classList.toggle("dark", darkDesired)
|
document.documentElement.classList.toggle("dark", darkDesired);
|
||||||
}
|
}
|
||||||
|
|
||||||
// initial theme application
|
// initial theme application
|
||||||
applyThemeFromPreference();
|
applyThemeFromPreference();
|
||||||
|
|
||||||
// Listen for system theme changes
|
// Listen for system theme changes
|
||||||
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", applyThemeFromPreference);
|
window
|
||||||
window.matchMedia("(prefers-color-scheme: light)").addEventListener("change", applyThemeFromPreference);
|
.matchMedia("(prefers-color-scheme: dark)")
|
||||||
|
.addEventListener("change", applyThemeFromPreference);
|
||||||
|
window
|
||||||
|
.matchMedia("(prefers-color-scheme: light)")
|
||||||
|
.addEventListener("change", applyThemeFromPreference);
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body
|
<body
|
||||||
class="h-full w-full bg-[#f3f9ff] font-sans text-sm antialiased dark:bg-slate-900 md:text-base"
|
class="h-full w-full bg-[#f3f9ff] font-sans text-sm antialiased md:text-base dark:bg-slate-900"
|
||||||
>
|
>
|
||||||
<div id="root" class="w-full h-full"></div>
|
<div id="root" class="h-full w-full"></div>
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
||||||
|
"jetkvm": "JetKVM",
|
||||||
|
"oh_no": "Åh nej!",
|
||||||
|
"something_went_wrong": "Noget gik galt. Prøv igen senere, eller kontakt support.",
|
||||||
|
"jetkvm_logo": "JetKVM-logo",
|
||||||
|
"action_bar_virtual_media": "Virtuelle medier",
|
||||||
|
"action_bar_paste_text": "Indsæt tekst",
|
||||||
|
"action_bar_web_terminal": "Webterminal",
|
||||||
|
"action_bar_wake_on_lan": "Vågn på LAN",
|
||||||
|
"action_bar_virtual_keyboard": "Virtuelt tastatur",
|
||||||
|
"action_bar_extension": "Udvidelse",
|
||||||
|
"action_bar_connection_stats": "Forbindelsesstatistik",
|
||||||
|
"action_bar_settings": "Indstillinger",
|
||||||
|
"action_bar_fullscreen": "Fuldskærm",
|
||||||
|
"action_bar_exit_fullscreen": "Afslut fuldskærm"
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
||||||
|
"jetkvm": "JetKVM",
|
||||||
|
"oh_no": "Oh nein!",
|
||||||
|
"something_went_wrong": "Ein Fehler ist aufgetreten. Bitte versuchen Sie es später noch einmal oder wenden Sie sich an den Support.",
|
||||||
|
"jetkvm_logo": "JetKVM Logo",
|
||||||
|
"action_bar_virtual_media": "Virtuelle Medien",
|
||||||
|
"action_bar_paste_text": "Text einfügen",
|
||||||
|
"action_bar_web_terminal": "Web-Terminal",
|
||||||
|
"action_bar_wake_on_lan": "Wake-on-LAN",
|
||||||
|
"action_bar_virtual_keyboard": "Virtuelle Tastatur",
|
||||||
|
"action_bar_extension": "Verlängerung",
|
||||||
|
"action_bar_connection_stats": "Verbindungsstatistiken",
|
||||||
|
"action_bar_settings": "Einstellungen",
|
||||||
|
"action_bar_fullscreen": "Vollbild",
|
||||||
|
"action_bar_exit_fullscreen": "Vollbildmodus beenden"
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
||||||
|
"jetkvm": "JetKVM",
|
||||||
|
"oh_no": "Oh no!",
|
||||||
|
"something_went_wrong": "Something went wrong. Please try again later or contact support",
|
||||||
|
"jetkvm_logo": "JetKVM Logo",
|
||||||
|
"action_bar_virtual_media": "Virtual Media",
|
||||||
|
"action_bar_paste_text": "Paste text",
|
||||||
|
"action_bar_web_terminal": "Web Terminal",
|
||||||
|
"action_bar_wake_on_lan": "Wake on LAN",
|
||||||
|
"action_bar_virtual_keyboard": "Virtual Keyboard",
|
||||||
|
"action_bar_extension": "Extension",
|
||||||
|
"action_bar_connection_stats": "Connection Stats",
|
||||||
|
"action_bar_settings": "Settings",
|
||||||
|
"action_bar_fullscreen": "Fullscreen",
|
||||||
|
"action_bar_exit_fullscreen": "Exit Fullscreen"
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
||||||
|
"jetkvm": "JetKVM",
|
||||||
|
"oh_no": "¡Oh, no!",
|
||||||
|
"something_went_wrong": "Algo salió mal. Inténtalo de nuevo más tarde o contacta con el servicio de asistencia.",
|
||||||
|
"jetkvm_logo": "Logotipo de JetKVM",
|
||||||
|
"action_bar_virtual_media": "Medios virtuales",
|
||||||
|
"action_bar_paste_text": "Pegar texto",
|
||||||
|
"action_bar_web_terminal": "Terminal web",
|
||||||
|
"action_bar_wake_on_lan": "Activación en LAN",
|
||||||
|
"action_bar_virtual_keyboard": "Teclado virtual",
|
||||||
|
"action_bar_extension": "Extensión",
|
||||||
|
"action_bar_connection_stats": "Estadísticas de conexión",
|
||||||
|
"action_bar_settings": "Ajustes",
|
||||||
|
"action_bar_fullscreen": "Pantalla completa",
|
||||||
|
"action_bar_exit_fullscreen": "Salir de pantalla completa"
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
||||||
|
"jetkvm": "JetKVM",
|
||||||
|
"oh_no": "Oh non!",
|
||||||
|
"something_went_wrong": "Une erreur s'est produite. Veuillez réessayer ultérieurement ou contacter le support.",
|
||||||
|
"jetkvm_logo": "Logo JetKVM",
|
||||||
|
"action_bar_virtual_media": "Médias virtuels",
|
||||||
|
"action_bar_paste_text": "Coller du texte",
|
||||||
|
"action_bar_web_terminal": "Terminal Web",
|
||||||
|
"action_bar_wake_on_lan": "Réveil sur LAN",
|
||||||
|
"action_bar_virtual_keyboard": "Clavier virtuel",
|
||||||
|
"action_bar_extension": "Extension",
|
||||||
|
"action_bar_connection_stats": "Statistiques de connexion",
|
||||||
|
"action_bar_settings": "Paramètres",
|
||||||
|
"action_bar_fullscreen": "Plein écran",
|
||||||
|
"action_bar_exit_fullscreen": "Quitter le plein écran"
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
||||||
|
"jetkvm": "JetKVM",
|
||||||
|
"oh_no": "Oh no!",
|
||||||
|
"something_went_wrong": "Qualcosa è andato storto. Riprova più tardi o contatta l'assistenza.",
|
||||||
|
"jetkvm_logo": "Logo JetKVM",
|
||||||
|
"action_bar_virtual_media": "Media virtuali",
|
||||||
|
"action_bar_paste_text": "Incolla il testo",
|
||||||
|
"action_bar_web_terminal": "Terminale Web",
|
||||||
|
"action_bar_wake_on_lan": "Wake on LAN",
|
||||||
|
"action_bar_virtual_keyboard": "Tastiera virtuale",
|
||||||
|
"action_bar_extension": "Estensione",
|
||||||
|
"action_bar_connection_stats": "Statistiche di connessione",
|
||||||
|
"action_bar_settings": "Impostazioni",
|
||||||
|
"action_bar_fullscreen": "A schermo intero",
|
||||||
|
"action_bar_exit_fullscreen": "Esci dalla modalità a schermo intero"
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
||||||
|
"jetkvm": "JetKVM",
|
||||||
|
"oh_no": "Å nei!",
|
||||||
|
"something_went_wrong": "Noe gikk galt. Prøv igjen senere, eller kontakt kundestøtte.",
|
||||||
|
"jetkvm_logo": "JetKVM-logo",
|
||||||
|
"action_bar_virtual_media": "Virtuelle medier",
|
||||||
|
"action_bar_paste_text": "Lim inn tekst",
|
||||||
|
"action_bar_web_terminal": "Nettterminal",
|
||||||
|
"action_bar_wake_on_lan": "Vekk på LAN",
|
||||||
|
"action_bar_virtual_keyboard": "Virtuelt tastatur",
|
||||||
|
"action_bar_extension": "Forlengelse",
|
||||||
|
"action_bar_connection_stats": "Tilkoblingsstatistikk",
|
||||||
|
"action_bar_settings": "Innstillinger",
|
||||||
|
"action_bar_fullscreen": "Fullskjerm",
|
||||||
|
"action_bar_exit_fullscreen": "Avslutt fullskjerm"
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
||||||
|
"jetkvm": "JetKVM",
|
||||||
|
"oh_no": "nej då!",
|
||||||
|
"something_went_wrong": "Något gick fel. Försök igen senare eller kontakta supporten.",
|
||||||
|
"jetkvm_logo": "JetKVM-logotyp",
|
||||||
|
"action_bar_virtual_media": "Virtuella medier",
|
||||||
|
"action_bar_paste_text": "Klistra in text",
|
||||||
|
"action_bar_web_terminal": "Webbterminal",
|
||||||
|
"action_bar_wake_on_lan": "Vakna på LAN",
|
||||||
|
"action_bar_virtual_keyboard": "Virtuellt tangentbord",
|
||||||
|
"action_bar_extension": "Förlängning",
|
||||||
|
"action_bar_connection_stats": "Anslutningsstatistik",
|
||||||
|
"action_bar_settings": "Inställningar",
|
||||||
|
"action_bar_fullscreen": "Helskärm",
|
||||||
|
"action_bar_exit_fullscreen": "Avsluta helskärm"
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
||||||
|
"jetkvm": "JetKVM",
|
||||||
|
"oh_no": "噢不!",
|
||||||
|
"something_went_wrong": "出了点问题。请稍后重试或联系客服",
|
||||||
|
"jetkvm_logo": "JetKVM 徽标",
|
||||||
|
"action_bar_virtual_media": "虚拟媒体",
|
||||||
|
"action_bar_paste_text": "粘贴文本",
|
||||||
|
"action_bar_web_terminal": "网页终端",
|
||||||
|
"action_bar_wake_on_lan": "局域网唤醒",
|
||||||
|
"action_bar_virtual_keyboard": "虚拟键盘",
|
||||||
|
"action_bar_extension": "扩大",
|
||||||
|
"action_bar_connection_stats": "连接统计",
|
||||||
|
"action_bar_settings": "设置",
|
||||||
|
"action_bar_fullscreen": "全屏",
|
||||||
|
"action_bar_exit_fullscreen": "退出全屏"
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -11,12 +11,13 @@
|
||||||
"dev:ssl": "USE_SSL=true ./dev_device.sh",
|
"dev:ssl": "USE_SSL=true ./dev_device.sh",
|
||||||
"dev:cloud": "vite dev --mode=cloud-development",
|
"dev:cloud": "vite dev --mode=cloud-development",
|
||||||
"build": "npm run build:prod",
|
"build": "npm run build:prod",
|
||||||
"build:device": "tsc && vite build --mode=device --emptyOutDir",
|
"build:device": "paraglide-js compile --project ./project.inlang && tsc && vite build --mode=device --emptyOutDir",
|
||||||
"build:staging": "tsc && vite build --mode=cloud-staging",
|
"build:staging": "paraglide-js compile --project ./project.inlang && tsc && vite build --mode=cloud-staging",
|
||||||
"build:prod": "tsc && vite build --mode=cloud-production",
|
"build:prod": "paraglide-js compile --project ./project.inlang && tsc && vite build --mode=cloud-production",
|
||||||
"lint": "eslint './src/**/*.{ts,tsx}'",
|
"lint": "paraglide-js compile --project ./project.inlang && eslint './src/**/*.{ts,tsx}'",
|
||||||
"lint:fix": "eslint './src/**/*.{ts,tsx}' --fix",
|
"lint:fix": "paraglide-js compile --project ./project.inlang && eslint './src/**/*.{ts,tsx}' --fix",
|
||||||
"preview": "vite preview"
|
"paraglide": "paraglide-js compile --project ./project.inlang",
|
||||||
|
"machine-translate": "inlang machine translate --project project.inlang"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^2.2.9",
|
"@headlessui/react": "^2.2.9",
|
||||||
|
@ -36,9 +37,9 @@
|
||||||
"framer-motion": "^12.23.22",
|
"framer-motion": "^12.23.22",
|
||||||
"lodash.throttle": "^4.1.1",
|
"lodash.throttle": "^4.1.1",
|
||||||
"mini-svg-data-uri": "^1.4.4",
|
"mini-svg-data-uri": "^1.4.4",
|
||||||
"react": "^19.1.1",
|
"react": "^19.2.0",
|
||||||
"react-animate-height": "^3.2.3",
|
"react-animate-height": "^3.2.3",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.2.0",
|
||||||
"react-hot-toast": "^2.6.0",
|
"react-hot-toast": "^2.6.0",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-router": "^7.9.3",
|
"react-router": "^7.9.3",
|
||||||
|
@ -55,12 +56,17 @@
|
||||||
"@eslint/compat": "^1.4.0",
|
"@eslint/compat": "^1.4.0",
|
||||||
"@eslint/eslintrc": "^3.3.1",
|
"@eslint/eslintrc": "^3.3.1",
|
||||||
"@eslint/js": "^9.36.0",
|
"@eslint/js": "^9.36.0",
|
||||||
|
"@inlang/cli": "^3.0.12",
|
||||||
|
"@inlang/paraglide-js": "^2.4.0",
|
||||||
|
"@inlang/plugin-m-function-matcher": "^2.1.0",
|
||||||
|
"@inlang/plugin-message-format": "^4.0.0",
|
||||||
|
"@inlang/sdk": "^2.4.9",
|
||||||
"@tailwindcss/forms": "^0.5.10",
|
"@tailwindcss/forms": "^0.5.10",
|
||||||
"@tailwindcss/postcss": "^4.1.14",
|
"@tailwindcss/postcss": "^4.1.14",
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@tailwindcss/vite": "^4.1.14",
|
"@tailwindcss/vite": "^4.1.14",
|
||||||
"@types/react": "^19.1.17",
|
"@types/react": "^19.2.0",
|
||||||
"@types/react-dom": "^19.1.10",
|
"@types/react-dom": "^19.2.0",
|
||||||
"@types/semver": "^7.7.1",
|
"@types/semver": "^7.7.1",
|
||||||
"@types/validator": "^13.15.3",
|
"@types/validator": "^13.15.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.45.0",
|
"@typescript-eslint/eslint-plugin": "^8.45.0",
|
||||||
|
@ -71,8 +77,8 @@
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-import": "^2.32.0",
|
"eslint-plugin-import": "^2.32.0",
|
||||||
"eslint-plugin-react": "^7.37.5",
|
"eslint-plugin-react": "^7.37.5",
|
||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^6.1.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.22",
|
"eslint-plugin-react-refresh": "^0.4.23",
|
||||||
"globals": "^16.4.0",
|
"globals": "^16.4.0",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
cache
|
|
@ -0,0 +1 @@
|
||||||
|
TI1a2RjjH4qkImNj0w
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://inlang.com/schema/project-settings",
|
||||||
|
"baseLocale": "en",
|
||||||
|
"sourceLanguageTag": "en",
|
||||||
|
"languageTags": [
|
||||||
|
"en",
|
||||||
|
"da",
|
||||||
|
"de",
|
||||||
|
"es",
|
||||||
|
"fr",
|
||||||
|
"it",
|
||||||
|
"nb",
|
||||||
|
"sv",
|
||||||
|
"zh"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
"https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@latest/dist/index.js",
|
||||||
|
"https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@latest/dist/index.js"
|
||||||
|
],
|
||||||
|
"plugin.inlang.messageFormat": {
|
||||||
|
"pathPattern": "./messages/{locale}.json"
|
||||||
|
},
|
||||||
|
"strategy": [
|
||||||
|
"localStorage",
|
||||||
|
"preferredLanguage",
|
||||||
|
"baseLocale"
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,24 +1,25 @@
|
||||||
|
import { Fragment, useCallback, useRef } from "react";
|
||||||
import { MdOutlineContentPasteGo } from "react-icons/md";
|
import { MdOutlineContentPasteGo } from "react-icons/md";
|
||||||
import { LuCable, LuHardDrive, LuMaximize, LuSettings, LuSignal } from "react-icons/lu";
|
import { LuCable, LuHardDrive, LuMaximize, LuSettings, LuSignal } from "react-icons/lu";
|
||||||
import { FaKeyboard } from "react-icons/fa6";
|
import { FaKeyboard } from "react-icons/fa6";
|
||||||
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
|
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
|
||||||
import { Fragment, useCallback, useRef } from "react";
|
|
||||||
import { CommandLineIcon } from "@heroicons/react/20/solid";
|
import { CommandLineIcon } from "@heroicons/react/20/solid";
|
||||||
|
|
||||||
import { Button } from "@components/Button";
|
|
||||||
import {
|
import {
|
||||||
useHidStore,
|
useHidStore,
|
||||||
useMountMediaStore,
|
useMountMediaStore,
|
||||||
useSettingsStore,
|
useSettingsStore,
|
||||||
useUiStore,
|
useUiStore,
|
||||||
} from "@/hooks/stores";
|
} from "@hooks/stores";
|
||||||
import Container from "@components/Container";
|
|
||||||
import { cx } from "@/cva.config";
|
import { cx } from "@/cva.config";
|
||||||
import PasteModal from "@/components/popovers/PasteModal";
|
import { Button } from "@components/Button";
|
||||||
import WakeOnLanModal from "@/components/popovers/WakeOnLan/Index";
|
import Container from "@components/Container";
|
||||||
import MountPopopover from "@/components/popovers/MountPopover";
|
import PasteModal from "@components/popovers/PasteModal";
|
||||||
import ExtensionPopover from "@/components/popovers/ExtensionPopover";
|
import WakeOnLanModal from "@components/popovers/WakeOnLan/Index";
|
||||||
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
|
import MountPopopover from "@components/popovers/MountPopover";
|
||||||
|
import ExtensionPopover from "@components/popovers/ExtensionPopover";
|
||||||
|
import { useDeviceUiNavigation } from "@hooks/useAppNavigation";
|
||||||
|
import { m } from "@/paraglide/messages.js";
|
||||||
|
|
||||||
export default function Actionbar({
|
export default function Actionbar({
|
||||||
requestFullscreen,
|
requestFullscreen,
|
||||||
|
@ -28,10 +29,7 @@ export default function Actionbar({
|
||||||
const { navigateTo } = useDeviceUiNavigation();
|
const { navigateTo } = useDeviceUiNavigation();
|
||||||
const { isVirtualKeyboardEnabled, setVirtualKeyboardEnabled } = useHidStore();
|
const { isVirtualKeyboardEnabled, setVirtualKeyboardEnabled } = useHidStore();
|
||||||
const { setDisableVideoFocusTrap, terminalType, setTerminalType, toggleSidebarView } = useUiStore();
|
const { setDisableVideoFocusTrap, terminalType, setTerminalType, toggleSidebarView } = useUiStore();
|
||||||
|
const { remoteVirtualMediaState } = useMountMediaStore();
|
||||||
const remoteVirtualMediaState = useMountMediaStore(
|
|
||||||
state => state.remoteVirtualMediaState,
|
|
||||||
);
|
|
||||||
const { developerMode } = useSettingsStore();
|
const { developerMode } = useSettingsStore();
|
||||||
|
|
||||||
// This is the only way to get a reliable state change for the popover
|
// This is the only way to get a reliable state change for the popover
|
||||||
|
@ -64,7 +62,7 @@ export default function Actionbar({
|
||||||
<Button
|
<Button
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
text="Web Terminal"
|
text={m.action_bar_web_terminal()}
|
||||||
LeadingIcon={({ className }) => <CommandLineIcon className={className} />}
|
LeadingIcon={({ className }) => <CommandLineIcon className={className} />}
|
||||||
onClick={() => setTerminalType(terminalType === "kvm" ? "none" : "kvm")}
|
onClick={() => setTerminalType(terminalType === "kvm" ? "none" : "kvm")}
|
||||||
/>
|
/>
|
||||||
|
@ -74,7 +72,7 @@ export default function Actionbar({
|
||||||
<Button
|
<Button
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
text="Paste text"
|
text={m.action_bar_paste_text()}
|
||||||
LeadingIcon={MdOutlineContentPasteGo}
|
LeadingIcon={MdOutlineContentPasteGo}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDisableVideoFocusTrap(true);
|
setDisableVideoFocusTrap(true);
|
||||||
|
@ -105,7 +103,7 @@ export default function Actionbar({
|
||||||
<Button
|
<Button
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
text="Virtual Media"
|
text={m.action_bar_virtual_media()}
|
||||||
LeadingIcon={({ className }) => {
|
LeadingIcon={({ className }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -148,7 +146,7 @@ export default function Actionbar({
|
||||||
<Button
|
<Button
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
text="Wake on LAN"
|
text={m.action_bar_wake_on_lan()}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDisableVideoFocusTrap(true);
|
setDisableVideoFocusTrap(true);
|
||||||
}}
|
}}
|
||||||
|
@ -198,7 +196,7 @@ export default function Actionbar({
|
||||||
<Button
|
<Button
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
text="Virtual Keyboard"
|
text={m.action_bar_virtual_keyboard()}
|
||||||
LeadingIcon={FaKeyboard}
|
LeadingIcon={FaKeyboard}
|
||||||
onClick={() => setVirtualKeyboardEnabled(!isVirtualKeyboardEnabled)}
|
onClick={() => setVirtualKeyboardEnabled(!isVirtualKeyboardEnabled)}
|
||||||
/>
|
/>
|
||||||
|
@ -211,7 +209,7 @@ export default function Actionbar({
|
||||||
<Button
|
<Button
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
text="Extension"
|
text={m.action_bar_extension()}
|
||||||
LeadingIcon={LuCable}
|
LeadingIcon={LuCable}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDisableVideoFocusTrap(true);
|
setDisableVideoFocusTrap(true);
|
||||||
|
@ -237,7 +235,7 @@ export default function Actionbar({
|
||||||
<Button
|
<Button
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
text="Virtual Keyboard"
|
text={m.action_bar_virtual_keyboard()}
|
||||||
LeadingIcon={FaKeyboard}
|
LeadingIcon={FaKeyboard}
|
||||||
onClick={() => setVirtualKeyboardEnabled(!isVirtualKeyboardEnabled)}
|
onClick={() => setVirtualKeyboardEnabled(!isVirtualKeyboardEnabled)}
|
||||||
/>
|
/>
|
||||||
|
@ -246,7 +244,7 @@ export default function Actionbar({
|
||||||
<Button
|
<Button
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
text="Connection Stats"
|
text={m.action_bar_connection_stats()}
|
||||||
LeadingIcon={({ className }) => (
|
LeadingIcon={({ className }) => (
|
||||||
<LuSignal
|
<LuSignal
|
||||||
className={cx(className, "mb-0.5 text-green-500")}
|
className={cx(className, "mb-0.5 text-green-500")}
|
||||||
|
@ -262,7 +260,7 @@ export default function Actionbar({
|
||||||
<Button
|
<Button
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
text="Settings"
|
text={m.action_bar_settings()}
|
||||||
LeadingIcon={LuSettings}
|
LeadingIcon={LuSettings}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDisableVideoFocusTrap(true);
|
setDisableVideoFocusTrap(true);
|
||||||
|
@ -276,7 +274,7 @@ export default function Actionbar({
|
||||||
<Button
|
<Button
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
text="Fullscreen"
|
text={m.action_bar_fullscreen()}
|
||||||
LeadingIcon={LuMaximize}
|
LeadingIcon={LuMaximize}
|
||||||
onClick={() => requestFullscreen()}
|
onClick={() => requestFullscreen()}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { lazy } from "react";
|
import { lazy } from "react";
|
||||||
import ReactDOM from "react-dom/client";
|
import ReactDOM from "react-dom/client";
|
||||||
import "./index.css";
|
|
||||||
import {
|
import {
|
||||||
createBrowserRouter,
|
createBrowserRouter,
|
||||||
isRouteErrorResponse,
|
isRouteErrorResponse,
|
||||||
|
@ -8,11 +7,13 @@ import {
|
||||||
RouterProvider,
|
RouterProvider,
|
||||||
useRouteError,
|
useRouteError,
|
||||||
} from "react-router";
|
} from "react-router";
|
||||||
|
import "./index.css";
|
||||||
import { ExclamationTriangleIcon } from "@heroicons/react/16/solid";
|
import { ExclamationTriangleIcon } from "@heroicons/react/16/solid";
|
||||||
|
|
||||||
import { CLOUD_API, DEVICE_API } from "@/ui.config";
|
import { CLOUD_API, DEVICE_API } from "@/ui.config";
|
||||||
import api from "@/api";
|
import api from "@/api";
|
||||||
import Root from "@/root";
|
import Root from "@/root";
|
||||||
|
import { m } from "@/paraglide/messages.js";
|
||||||
import Card from "@components/Card";
|
import Card from "@components/Card";
|
||||||
import EmptyCard from "@components/EmptyCard";
|
import EmptyCard from "@components/EmptyCard";
|
||||||
import NotFoundPage from "@components/NotFoundPage";
|
import NotFoundPage from "@components/NotFoundPage";
|
||||||
|
@ -28,12 +29,12 @@ import DeviceIdRename from "@routes/devices.$id.rename";
|
||||||
import DevicesRoute from "@routes/devices";
|
import DevicesRoute from "@routes/devices";
|
||||||
import SettingsIndexRoute from "@routes/devices.$id.settings._index";
|
import SettingsIndexRoute from "@routes/devices.$id.settings._index";
|
||||||
import SettingsAccessIndexRoute from "@routes/devices.$id.settings.access._index";
|
import SettingsAccessIndexRoute from "@routes/devices.$id.settings.access._index";
|
||||||
import Notifications from "@/notifications";
|
import Notifications from "@/notifications";
|
||||||
const SignupRoute = lazy(() => import("@routes/signup"));
|
const SignupRoute = lazy(() => import("@routes/signup"));
|
||||||
const LoginRoute = lazy(() => import("@routes/login"));
|
const LoginRoute = lazy(() => import("@routes/login"));
|
||||||
const DevicesAlreadyAdopted = lazy(() => import("@routes/devices.already-adopted"));
|
const DevicesAlreadyAdopted = lazy(() => import("@routes/devices.already-adopted"));
|
||||||
const OtherSessionRoute = lazy(() => import("@routes/devices.$id.other-session"));
|
const OtherSessionRoute = lazy(() => import("@routes/devices.$id.other-session"));
|
||||||
const MountRoute = lazy(() => import("./routes/devices.$id.mount"));
|
const MountRoute = lazy(() => import("@routes/devices.$id.mount"));
|
||||||
const SettingsRoute = lazy(() => import("@routes/devices.$id.settings"));
|
const SettingsRoute = lazy(() => import("@routes/devices.$id.settings"));
|
||||||
const SettingsMouseRoute = lazy(() => import("@routes/devices.$id.settings.mouse"));
|
const SettingsMouseRoute = lazy(() => import("@routes/devices.$id.settings.mouse"));
|
||||||
const SettingsKeyboardRoute = lazy(() => import("@routes/devices.$id.settings.keyboard"));
|
const SettingsKeyboardRoute = lazy(() => import("@routes/devices.$id.settings.keyboard"));
|
||||||
|
@ -404,8 +405,8 @@ function ErrorBoundary() {
|
||||||
<div className="w-full max-w-2xl">
|
<div className="w-full max-w-2xl">
|
||||||
<EmptyCard
|
<EmptyCard
|
||||||
IconElm={ExclamationTriangleIcon}
|
IconElm={ExclamationTriangleIcon}
|
||||||
headline="Oh no!"
|
headline={m.oh_no()}
|
||||||
description="Something went wrong. Please try again later or contact support"
|
description={m.something_went_wrong()}
|
||||||
BtnElm={
|
BtnElm={
|
||||||
errorMessage && (
|
errorMessage && (
|
||||||
<Card>
|
<Card>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useNavigate } from "react-router";
|
|
||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
|
import { useNavigate } from "react-router";
|
||||||
|
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { useJsonRpc } from "@hooks/useJsonRpc";
|
||||||
import { Button } from "@components/Button";
|
import { Button } from "@components/Button";
|
||||||
|
|
||||||
export default function SettingsGeneralRebootRoute() {
|
export default function SettingsGeneralRebootRoute() {
|
||||||
|
@ -10,7 +10,7 @@ export default function SettingsGeneralRebootRoute() {
|
||||||
|
|
||||||
const onConfirmUpdate = useCallback(() => {
|
const onConfirmUpdate = useCallback(() => {
|
||||||
// This is where we send the RPC to the golang binary
|
// This is where we send the RPC to the golang binary
|
||||||
send("reboot", {force: true});
|
send("reboot", { force: true });
|
||||||
}, [send]);
|
}, [send]);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -30,10 +30,10 @@ export function Dialog({
|
||||||
return (
|
return (
|
||||||
<div className="pointer-events-auto relative mx-auto text-left">
|
<div className="pointer-events-auto relative mx-auto text-left">
|
||||||
<div>
|
<div>
|
||||||
<ConfirmationBox
|
<ConfirmationBox
|
||||||
onYes={onConfirmUpdate}
|
onYes={onConfirmUpdate}
|
||||||
onNo={onClose}
|
onNo={onClose}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { cx } from "cva";
|
|
||||||
import { redirect } from "react-router";
|
import { redirect } from "react-router";
|
||||||
import type { LoaderFunction } from "react-router";
|
import type { LoaderFunction } from "react-router";
|
||||||
|
import { cx } from "cva";
|
||||||
|
|
||||||
|
import api from "@/api";
|
||||||
|
import { DEVICE_API } from "@/ui.config";
|
||||||
import GridBackground from "@components/GridBackground";
|
import GridBackground from "@components/GridBackground";
|
||||||
import Container from "@components/Container";
|
import Container from "@components/Container";
|
||||||
import { LinkButton } from "@components/Button";
|
import { LinkButton } from "@components/Button";
|
||||||
import LogoBlueIcon from "@/assets/logo-blue.png";
|
import LogoBlueIcon from "@assets/logo-blue.png";
|
||||||
import LogoWhiteIcon from "@/assets/logo-white.svg";
|
import LogoWhiteIcon from "@assets/logo-white.svg";
|
||||||
import DeviceImage from "@/assets/jetkvm-device-still.png";
|
import DeviceImage from "@assets/jetkvm-device-still.png";
|
||||||
import LogoMark from "@/assets/logo-mark.png";
|
import LogoMark from "@assets/logo-mark.png";
|
||||||
import { DEVICE_API } from "@/ui.config";
|
import { m } from "@/paraglide/messages.js";
|
||||||
|
|
||||||
import api from "../api";
|
|
||||||
|
|
||||||
export interface DeviceStatus {
|
export interface DeviceStatus {
|
||||||
isSetup: boolean;
|
isSetup: boolean;
|
||||||
|
@ -49,7 +49,7 @@ export default function WelcomeRoute() {
|
||||||
<div className="animate-fadeIn animation-delay-1000 flex items-center justify-center opacity-0">
|
<div className="animate-fadeIn animation-delay-1000 flex items-center justify-center opacity-0">
|
||||||
<img
|
<img
|
||||||
src={LogoWhiteIcon}
|
src={LogoWhiteIcon}
|
||||||
alt="JetKVM Logo"
|
alt={m.jetkvm_logo()}
|
||||||
className="hidden h-[32px] dark:block"
|
className="hidden h-[32px] dark:block"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
|
|
|
@ -3,9 +3,14 @@
|
||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"lib": ["ES2021", "DOM", "DOM.Iterable"],
|
"lib": [
|
||||||
|
"ES2021",
|
||||||
|
"DOM",
|
||||||
|
"DOM.Iterable"
|
||||||
|
],
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
"allowJs": true,
|
||||||
/* Bundler mode */
|
/* Bundler mode */
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"allowImportingTsExtensions": false,
|
"allowImportingTsExtensions": false,
|
||||||
|
@ -18,16 +23,36 @@
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"types": ["vite/client"],
|
"erasableSyntaxOnly": true,
|
||||||
|
"noUncheckedSideEffectImports": true,
|
||||||
|
"types": [
|
||||||
|
"vite/client"
|
||||||
|
],
|
||||||
/* Import Aliases */
|
/* Import Aliases */
|
||||||
"paths": {
|
"paths": {
|
||||||
"@components/*": ["./src/components/*"],
|
"@components/*": [
|
||||||
"@routes/*": ["./src/routes/*"],
|
"./src/components/*"
|
||||||
"@assets/*": ["./src/assets/*"],
|
],
|
||||||
"@/*": ["./src/*"]
|
"@routes/*": [
|
||||||
|
"./src/routes/*"
|
||||||
|
],
|
||||||
|
"@hooks/*": [
|
||||||
|
"./src/hooks/*"
|
||||||
|
],
|
||||||
|
"@providers/*": [
|
||||||
|
"./src/providers/*"
|
||||||
|
],
|
||||||
|
"@assets/*": [
|
||||||
|
"./src/assets/*"
|
||||||
|
],
|
||||||
|
"@/*": [
|
||||||
|
"./src/*"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": [
|
||||||
|
"src"
|
||||||
|
],
|
||||||
"references": [
|
"references": [
|
||||||
{
|
{
|
||||||
"path": "./tsconfig.node.json"
|
"path": "./tsconfig.node.json"
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"composite": true,
|
"composite": true,
|
||||||
"skipLibCheck": true,
|
/* Bundler mode */
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"strict": true
|
|
||||||
},
|
},
|
||||||
"include": ["vite.config.ts"]
|
"include": [
|
||||||
|
"vite.config.ts"
|
||||||
|
]
|
||||||
}
|
}
|
|
@ -3,6 +3,7 @@ import react from "@vitejs/plugin-react-swc";
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import tsconfigPaths from "vite-tsconfig-paths";
|
import tsconfigPaths from "vite-tsconfig-paths";
|
||||||
import basicSsl from "@vitejs/plugin-basic-ssl";
|
import basicSsl from "@vitejs/plugin-basic-ssl";
|
||||||
|
import { paraglideVitePlugin } from "@inlang/paraglide-js";
|
||||||
|
|
||||||
declare const process: {
|
declare const process: {
|
||||||
env: {
|
env: {
|
||||||
|
@ -22,10 +23,20 @@ export default defineConfig(({ mode, command }) => {
|
||||||
tsconfigPaths(),
|
tsconfigPaths(),
|
||||||
react()
|
react()
|
||||||
];
|
];
|
||||||
|
|
||||||
if (useSSL) {
|
if (useSSL) {
|
||||||
plugins.push(basicSsl());
|
plugins.push(basicSsl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugins.push(paraglideVitePlugin({
|
||||||
|
project: "./project.inlang",
|
||||||
|
outdir: "./src/paraglide",
|
||||||
|
outputStructure: 'message-modules',
|
||||||
|
cookieName: 'JETKVM_LOCALE',
|
||||||
|
localStorageKey: 'JETKVM_LOCALE',
|
||||||
|
strategy: ['cookie', 'localStorage', 'preferredLanguage', 'baseLocale'],
|
||||||
|
}))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
plugins,
|
plugins,
|
||||||
esbuild: {
|
esbuild: {
|
||||||
|
|
Loading…
Reference in New Issue