mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 06:05:24 +00:00
feat: finish the docker plugin (B15)
This commit is contained in:
1 parent
0a3f05d99d
commit
993a91c899
167 files changed
+26299
-5136
No files matched your search
@@ -798,7 +798,6 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
|
||||
tunnel_connections TEXT,
|
||||
jump_hosts TEXT,
|
||||
enable_file_manager INTEGER NOT NULL DEFAULT 1,
|
||||
enable_docker INTEGER NOT NULL DEFAULT 0,
|
||||
enable_web_ui INTEGER NOT NULL DEFAULT 0,
|
||||
show_terminal_in_sidebar INTEGER NOT NULL DEFAULT 1,
|
||||
show_file_manager_in_sidebar INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -808,7 +807,6 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
|
||||
default_path TEXT,
|
||||
status_check_enabled INTEGER NOT NULL DEFAULT 1,
|
||||
status_check_interval INTEGER,
|
||||
docker_config TEXT,
|
||||
web_ui_config TEXT,
|
||||
terminal_config TEXT,
|
||||
quick_actions TEXT,
|
||||
@@ -929,8 +927,8 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
|
||||
const sshHosts =
|
||||
await createCurrentHostRepository().listDecryptedByUserId(userId);
|
||||
const insertHost = exportDb.prepare(`
|
||||
INSERT INTO ssh_data (id, user_id, connection_type, name, ip, port, username, folder, tags, pin, auth_type, force_keyboard_interactive, password, key, key_password, key_type, sudo_password, autostart_password, autostart_key, autostart_key_password, credential_id, override_credential_username, enable_terminal, enable_tunnel, tunnel_connections, jump_hosts, enable_file_manager, enable_docker, enable_web_ui, show_terminal_in_sidebar, show_file_manager_in_sidebar, show_tunnel_in_sidebar, show_docker_in_sidebar, show_server_stats_in_sidebar, default_path, status_check_enabled, status_check_interval, docker_config, web_ui_config, terminal_config, quick_actions, notes, use_socks5, socks5_host, socks5_port, socks5_username, socks5_password, socks5_proxy_chain, domain, mac_address, port_knock_sequence, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
INSERT INTO ssh_data (id, user_id, connection_type, name, ip, port, username, folder, tags, pin, auth_type, force_keyboard_interactive, password, key, key_password, key_type, sudo_password, autostart_password, autostart_key, autostart_key_password, credential_id, override_credential_username, enable_terminal, enable_tunnel, tunnel_connections, jump_hosts, enable_file_manager, enable_web_ui, show_terminal_in_sidebar, show_file_manager_in_sidebar, show_tunnel_in_sidebar, show_docker_in_sidebar, show_server_stats_in_sidebar, default_path, status_check_enabled, status_check_interval, web_ui_config, terminal_config, quick_actions, notes, use_socks5, socks5_host, socks5_port, socks5_username, socks5_password, socks5_proxy_chain, domain, mac_address, port_knock_sequence, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
|
||||
for (const decrypted of sshHosts) {
|
||||
@@ -962,7 +960,6 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
|
||||
decrypted.tunnelConnections || null,
|
||||
decrypted.jumpHosts || null,
|
||||
decrypted.enableFileManager ? 1 : 0,
|
||||
decrypted.enableDocker ? 1 : 0,
|
||||
decrypted.enableWebUi ? 1 : 0,
|
||||
decrypted.showTerminalInSidebar ? 1 : 0,
|
||||
decrypted.showFileManagerInSidebar ? 1 : 0,
|
||||
@@ -972,7 +969,6 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
|
||||
decrypted.defaultPath || null,
|
||||
decrypted.statusCheckEnabled === false ? 0 : 1,
|
||||
decrypted.statusCheckInterval ?? null,
|
||||
decrypted.dockerConfig || null,
|
||||
decrypted.webUiConfig || null,
|
||||
decrypted.terminalConfig || null,
|
||||
decrypted.quickActions || null,
|
||||
@@ -1369,7 +1365,6 @@ app.post(
|
||||
tunnelConnections: host.tunnel_connections,
|
||||
jumpHosts: host.jump_hosts,
|
||||
enableFileManager: Boolean(host.enable_file_manager),
|
||||
enableDocker: Boolean(host.enable_docker),
|
||||
showTerminalInSidebar: Boolean(host.show_terminal_in_sidebar),
|
||||
showFileManagerInSidebar: Boolean(
|
||||
host.show_file_manager_in_sidebar,
|
||||
|
||||
@@ -327,7 +327,6 @@ async function initializeCompleteDatabase(): Promise<void> {
|
||||
enable_tunnel INTEGER NOT NULL DEFAULT 1,
|
||||
tunnel_connections TEXT,
|
||||
enable_file_manager INTEGER NOT NULL DEFAULT 1,
|
||||
enable_docker INTEGER NOT NULL DEFAULT 0,
|
||||
enable_web_ui INTEGER NOT NULL DEFAULT 0,
|
||||
default_path TEXT,
|
||||
autostart_password TEXT,
|
||||
@@ -336,7 +335,6 @@ async function initializeCompleteDatabase(): Promise<void> {
|
||||
force_keyboard_interactive TEXT,
|
||||
status_check_enabled INTEGER NOT NULL DEFAULT 1,
|
||||
status_check_interval INTEGER,
|
||||
docker_config TEXT,
|
||||
web_ui_config TEXT,
|
||||
terminal_config TEXT,
|
||||
notes TEXT,
|
||||
@@ -1075,12 +1073,6 @@ const migrateSchema = () => {
|
||||
addColumnIfNotExists("ssh_data", "status_check_interval", "INTEGER");
|
||||
addColumnIfNotExists("ssh_data", "terminal_config", "TEXT");
|
||||
addColumnIfNotExists("ssh_data", "quick_actions", "TEXT");
|
||||
addColumnIfNotExists(
|
||||
"ssh_data",
|
||||
"enable_docker",
|
||||
"INTEGER NOT NULL DEFAULT 0",
|
||||
);
|
||||
addColumnIfNotExists("ssh_data", "docker_config", "TEXT");
|
||||
addColumnIfNotExists(
|
||||
"ssh_data",
|
||||
"enable_web_ui",
|
||||
|
||||
@@ -264,9 +264,6 @@ export const hosts = mysqlTable(
|
||||
.notNull()
|
||||
.default(true),
|
||||
scpLegacy: boolean("scp_legacy").notNull().default(false),
|
||||
enableDocker: boolean("enable_docker")
|
||||
.notNull()
|
||||
.default(false),
|
||||
enableWebUi: boolean("enable_web_ui")
|
||||
.notNull()
|
||||
.default(false),
|
||||
@@ -299,7 +296,6 @@ export const hosts = mysqlTable(
|
||||
.notNull()
|
||||
.default(true),
|
||||
statusCheckInterval: int("status_check_interval"),
|
||||
dockerConfig: text("docker_config"),
|
||||
webUiConfig: text("web_ui_config"),
|
||||
terminalConfig: text("terminal_config"),
|
||||
quickActions: text("quick_actions"),
|
||||
|
||||
@@ -265,9 +265,6 @@ export const hosts = pgTable(
|
||||
.notNull()
|
||||
.default(true),
|
||||
scpLegacy: boolean("scp_legacy").notNull().default(false),
|
||||
enableDocker: boolean("enable_docker")
|
||||
.notNull()
|
||||
.default(false),
|
||||
enableWebUi: boolean("enable_web_ui")
|
||||
.notNull()
|
||||
.default(false),
|
||||
@@ -300,7 +297,6 @@ export const hosts = pgTable(
|
||||
.notNull()
|
||||
.default(true),
|
||||
statusCheckInterval: integer("status_check_interval"),
|
||||
dockerConfig: text("docker_config"),
|
||||
webUiConfig: text("web_ui_config"),
|
||||
terminalConfig: text("terminal_config"),
|
||||
quickActions: text("quick_actions"),
|
||||
|
||||
@@ -257,9 +257,6 @@ export const hosts = sqliteTable(
|
||||
.notNull()
|
||||
.default(true),
|
||||
scpLegacy: integer("scp_legacy", { mode: "boolean" }).notNull().default(false),
|
||||
enableDocker: integer("enable_docker", { mode: "boolean" })
|
||||
.notNull()
|
||||
.default(false),
|
||||
enableWebUi: integer("enable_web_ui", { mode: "boolean" })
|
||||
.notNull()
|
||||
.default(false),
|
||||
@@ -292,7 +289,6 @@ export const hosts = sqliteTable(
|
||||
.notNull()
|
||||
.default(true),
|
||||
statusCheckInterval: integer("status_check_interval"),
|
||||
dockerConfig: text("docker_config"),
|
||||
webUiConfig: text("web_ui_config"),
|
||||
terminalConfig: text("terminal_config"),
|
||||
quickActions: text("quick_actions"),
|
||||
|
||||
@@ -284,8 +284,6 @@ export function registerHostBulkRoutes(
|
||||
simpleUpdates.enableTunnel = updates.enableTunnel;
|
||||
if (typeof updates.enableFileManager === "boolean")
|
||||
simpleUpdates.enableFileManager = updates.enableFileManager;
|
||||
if (typeof updates.enableDocker === "boolean")
|
||||
simpleUpdates.enableDocker = updates.enableDocker;
|
||||
if (typeof updates.enableTmuxMonitor === "boolean")
|
||||
simpleUpdates.enableTmuxMonitor = updates.enableTmuxMonitor;
|
||||
if (typeof updates.enableTerminalToolbar === "boolean")
|
||||
@@ -751,7 +749,6 @@ export function registerHostBulkRoutes(
|
||||
enableTerminal: hostData.enableTerminal !== false,
|
||||
enableTunnel: hostData.enableTunnel !== false,
|
||||
enableFileManager: hostData.enableFileManager !== false,
|
||||
enableDocker: hostData.enableDocker || false,
|
||||
enableTmuxMonitor: hostData.enableTmuxMonitor || false,
|
||||
enableTerminalToolbar: hostData.enableTerminalToolbar !== false,
|
||||
enableAiAssistant: hostData.enableAiAssistant || false,
|
||||
@@ -771,9 +768,6 @@ export function registerHostBulkRoutes(
|
||||
? JSON.stringify(hostData.quickActions)
|
||||
: null,
|
||||
...importedStatusCheck(hostData as Record<string, unknown>),
|
||||
dockerConfig: hostData.dockerConfig
|
||||
? JSON.stringify(hostData.dockerConfig)
|
||||
: null,
|
||||
terminalConfig: hostData.terminalConfig
|
||||
? JSON.stringify(hostData.terminalConfig)
|
||||
: null,
|
||||
@@ -1016,7 +1010,6 @@ export function registerHostBulkRoutes(
|
||||
enableTerminal: true,
|
||||
enableTunnel: true,
|
||||
enableFileManager: true,
|
||||
enableDocker: false,
|
||||
enableTmuxMonitor: false,
|
||||
enableTerminalToolbar: true,
|
||||
enableAiAssistant: false,
|
||||
@@ -1034,7 +1027,6 @@ export function registerHostBulkRoutes(
|
||||
quickActions: null,
|
||||
statusCheckEnabled: true,
|
||||
statusCheckInterval: null,
|
||||
dockerConfig: null,
|
||||
terminalConfig: null,
|
||||
forceKeyboardInteractive: "false",
|
||||
notes: null,
|
||||
|
||||
@@ -174,7 +174,6 @@ export type NormalizedImportedHost = Record<string, unknown> & {
|
||||
enableTerminal?: unknown;
|
||||
enableTunnel?: unknown;
|
||||
enableFileManager?: unknown;
|
||||
enableDocker?: unknown;
|
||||
enableWebUi?: unknown;
|
||||
enableProxmox?: unknown;
|
||||
enableTmuxMonitor?: unknown;
|
||||
@@ -193,7 +192,6 @@ export type NormalizedImportedHost = Record<string, unknown> & {
|
||||
quickActions?: unknown;
|
||||
statusCheckEnabled?: unknown;
|
||||
statusCheckInterval?: unknown;
|
||||
dockerConfig?: unknown;
|
||||
webUiConfig?: unknown;
|
||||
proxmoxConfig?: unknown;
|
||||
enableProxmoxStats?: unknown;
|
||||
@@ -340,7 +338,6 @@ const CONNECT_LEVEL_FIELDS = new Set([
|
||||
"enableTerminal",
|
||||
"enableTunnel",
|
||||
"enableFileManager",
|
||||
"enableDocker",
|
||||
"enableTmuxMonitor",
|
||||
"enableTerminalToolbar",
|
||||
"enableAiAssistant",
|
||||
@@ -437,7 +434,6 @@ export function transformHostResponse(
|
||||
enableTerminal: !!host.enableTerminal,
|
||||
enableTunnel: !!host.enableTunnel,
|
||||
enableFileManager: host.enableFileManager !== false,
|
||||
enableDocker: !!host.enableDocker,
|
||||
enableTmuxMonitor: !!host.enableTmuxMonitor,
|
||||
enableTerminalToolbar: host.enableTerminalToolbar !== false,
|
||||
enableAiAssistant: !!host.enableAiAssistant,
|
||||
@@ -468,9 +464,6 @@ export function transformHostResponse(
|
||||
terminalConfig: host.terminalConfig
|
||||
? JSON.parse(host.terminalConfig as string)
|
||||
: undefined,
|
||||
dockerConfig: host.dockerConfig
|
||||
? JSON.parse(host.dockerConfig as string)
|
||||
: undefined,
|
||||
forceKeyboardInteractive: host.forceKeyboardInteractive === "true",
|
||||
useWarpgate: !!host.useWarpgate,
|
||||
socks5ProxyChain: host.socks5ProxyChain
|
||||
|
||||
@@ -199,7 +199,6 @@ router.post(
|
||||
enableTunnel,
|
||||
enableFileManager,
|
||||
scpLegacy,
|
||||
enableDocker,
|
||||
enableProxmox,
|
||||
enableTmuxMonitor,
|
||||
enableTerminalToolbar,
|
||||
@@ -215,7 +214,6 @@ router.post(
|
||||
quickActions,
|
||||
statusCheckEnabled,
|
||||
statusCheckInterval,
|
||||
dockerConfig,
|
||||
proxmoxConfig,
|
||||
enableProxmoxStats,
|
||||
proxmoxStatsConfig,
|
||||
@@ -332,7 +330,6 @@ router.post(
|
||||
: null,
|
||||
enableFileManager: enableFileManager ? 1 : 0,
|
||||
scpLegacy: scpLegacy ? 1 : 0,
|
||||
enableDocker: enableDocker ? 1 : 0,
|
||||
enableTmuxMonitor: enableTmuxMonitor ? 1 : 0,
|
||||
enableTerminalToolbar: enableTerminalToolbar === false ? 0 : 1,
|
||||
enableAiAssistant: enableAiAssistant ? 1 : 0,
|
||||
@@ -344,11 +341,6 @@ router.post(
|
||||
defaultPath: defaultPath || null,
|
||||
statusCheckEnabled: statusCheckEnabled === false ? 0 : 1,
|
||||
statusCheckInterval: normalizeStatusInterval(statusCheckInterval),
|
||||
dockerConfig: dockerConfig
|
||||
? typeof dockerConfig === "string"
|
||||
? dockerConfig
|
||||
: JSON.stringify(dockerConfig)
|
||||
: null,
|
||||
terminalConfig: terminalConfig
|
||||
? typeof terminalConfig === "string"
|
||||
? terminalConfig
|
||||
@@ -764,7 +756,6 @@ router.post(
|
||||
enableTerminal: true,
|
||||
enableTunnel: false,
|
||||
enableFileManager: true,
|
||||
enableDocker: false,
|
||||
enableWebUi: false,
|
||||
enableTmuxMonitor: false,
|
||||
enableTerminalToolbar: true,
|
||||
@@ -895,7 +886,6 @@ router.put(
|
||||
enableTunnel,
|
||||
enableFileManager,
|
||||
scpLegacy,
|
||||
enableDocker,
|
||||
enableProxmox,
|
||||
enableTmuxMonitor,
|
||||
enableTerminalToolbar,
|
||||
@@ -911,7 +901,6 @@ router.put(
|
||||
quickActions,
|
||||
statusCheckEnabled,
|
||||
statusCheckInterval,
|
||||
dockerConfig,
|
||||
proxmoxConfig,
|
||||
enableProxmoxStats,
|
||||
proxmoxStatsConfig,
|
||||
@@ -1029,7 +1018,6 @@ router.put(
|
||||
: null,
|
||||
enableFileManager: enableFileManager ? 1 : 0,
|
||||
scpLegacy: scpLegacy ? 1 : 0,
|
||||
enableDocker: enableDocker ? 1 : 0,
|
||||
enableTmuxMonitor: enableTmuxMonitor ? 1 : 0,
|
||||
enableTerminalToolbar: enableTerminalToolbar === false ? 0 : 1,
|
||||
enableAiAssistant: enableAiAssistant ? 1 : 0,
|
||||
@@ -1041,11 +1029,6 @@ router.put(
|
||||
defaultPath: defaultPath || null,
|
||||
statusCheckEnabled: statusCheckEnabled === false ? 0 : 1,
|
||||
statusCheckInterval: normalizeStatusInterval(statusCheckInterval),
|
||||
dockerConfig: dockerConfig
|
||||
? typeof dockerConfig === "string"
|
||||
? dockerConfig
|
||||
: JSON.stringify(dockerConfig)
|
||||
: null,
|
||||
terminalConfig: terminalConfig
|
||||
? typeof terminalConfig === "string"
|
||||
? terminalConfig
|
||||
@@ -2099,7 +2082,6 @@ router.get(
|
||||
enableTunnel: !!resolvedHost.enableTunnel,
|
||||
enableFileManager: resolvedHost.enableFileManager !== false,
|
||||
scpLegacy: !!resolvedHost.scpLegacy,
|
||||
enableDocker: !!resolvedHost.enableDocker,
|
||||
enableWebUi: !!webEndpointSettings?.enableWebUi,
|
||||
enableProxmox: !!proxmoxSettings?.enableProxmox,
|
||||
enableProxmoxStats: !!proxmoxSettings?.enableProxmoxStats,
|
||||
@@ -2123,9 +2105,6 @@ router.get(
|
||||
? JSON.parse(resolvedHost.quickActions as string)
|
||||
: null,
|
||||
webUiConfig: webEndpointSettings?.webUiConfig ?? { endpoints: [] },
|
||||
dockerConfig: resolvedHost.dockerConfig
|
||||
? JSON.parse(resolvedHost.dockerConfig as string)
|
||||
: null,
|
||||
proxmoxConfig: proxmoxSettings?.proxmoxConfig ?? null,
|
||||
proxmoxStatsConfig: proxmoxSettings?.proxmoxStatsConfig ?? null,
|
||||
terminalConfig: resolvedHost.terminalConfig
|
||||
@@ -2260,7 +2239,6 @@ router.get(
|
||||
enableCommandHistory: resolvedHost.enableCommandHistory !== false,
|
||||
enableTunnel: !!resolvedHost.enableTunnel,
|
||||
enableFileManager: resolvedHost.enableFileManager !== false,
|
||||
enableDocker: !!resolvedHost.enableDocker,
|
||||
enableWebUi: !!webEndpointSettings?.enableWebUi,
|
||||
enableProxmox: !!proxmoxSettings?.enableProxmox,
|
||||
enableTmuxMonitor: !!resolvedHost.enableTmuxMonitor,
|
||||
@@ -2288,9 +2266,6 @@ router.get(
|
||||
webUiConfig: webEndpointSettings?.webUiConfig ?? {
|
||||
endpoints: [],
|
||||
},
|
||||
dockerConfig: resolvedHost.dockerConfig
|
||||
? JSON.parse(resolvedHost.dockerConfig as string)
|
||||
: null,
|
||||
proxmoxConfig: proxmoxSettings?.proxmoxConfig ?? null,
|
||||
terminalConfig: resolvedHost.terminalConfig
|
||||
? JSON.parse(resolvedHost.terminalConfig as string)
|
||||
|
||||
@@ -85,7 +85,6 @@ function toRecord(host: Record<string, unknown>): PluginHostRecord {
|
||||
enableTerminal: (host.enableTerminal as boolean | null) ?? null,
|
||||
enableFileManager: (host.enableFileManager as boolean | null) ?? null,
|
||||
enableTunnel: (host.enableTunnel as boolean | null) ?? null,
|
||||
enableDocker: (host.enableDocker as boolean | null) ?? null,
|
||||
createdAt: (host.createdAt as string | null) ?? null,
|
||||
updatedAt: (host.updatedAt as string | null) ?? null,
|
||||
...host,
|
||||
|
||||
@@ -393,6 +393,10 @@ async function provisionLocalDesktopUserIfNeeded(): Promise<void> {
|
||||
const { runHostMetricsSettingsMigration } =
|
||||
await import("./utils/crypto-migration/host-metrics-settings-migration.js");
|
||||
await runHostMetricsSettingsMigration();
|
||||
|
||||
const { runDockerSettingsMigration } =
|
||||
await import("./utils/crypto-migration/docker-settings-migration.js");
|
||||
await runDockerSettingsMigration();
|
||||
} catch (error) {
|
||||
systemLogger.warn("Plugin runtime failed to initialize", {
|
||||
operation: "plugin_init",
|
||||
|
||||
@@ -129,7 +129,6 @@ describe("HostRepository Proxmox sync inserts", () => {
|
||||
enableTerminal: true,
|
||||
enableFileManager: true,
|
||||
enableTunnel: true,
|
||||
enableDocker: false,
|
||||
enableSsh: true,
|
||||
enableRdp: false,
|
||||
rdpUser: null,
|
||||
@@ -148,7 +147,6 @@ describe("HostRepository Proxmox sync inserts", () => {
|
||||
tunnelConnections: "[]",
|
||||
jumpHosts: null,
|
||||
quickActions: null,
|
||||
dockerConfig: null,
|
||||
terminalConfig: null,
|
||||
forceKeyboardInteractive: "false",
|
||||
useSocks5: 0,
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* The Docker host settings migration.
|
||||
*
|
||||
* An upgrade must be lossless: every host with Docker on, and every host on
|
||||
* Podman, must come through into the docker plugin's host settings, whatever
|
||||
* shape the engine returned the flag in. Running it twice must not duplicate
|
||||
* or clobber what it moved.
|
||||
*/
|
||||
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const state = vi.hoisted(() => ({
|
||||
pluginRows: [] as Array<{
|
||||
pluginId: string;
|
||||
scope: string;
|
||||
scopeId: string | null;
|
||||
key: string;
|
||||
value: string | null;
|
||||
}>,
|
||||
hostRows: [] as Array<Record<string, unknown>>,
|
||||
pluginInstalled: true,
|
||||
columnsGone: false,
|
||||
}));
|
||||
|
||||
vi.mock("../../database/repositories/factory.js", () => ({
|
||||
createCurrentPluginRepository: () => ({
|
||||
findById: async (id: string) =>
|
||||
state.pluginInstalled && id === "docker" ? { id } : null,
|
||||
}),
|
||||
createCurrentPluginSettingsRepository: () => ({
|
||||
getAll: async (_pluginId: string, scope: string, scopeId: string | null) =>
|
||||
state.pluginRows.filter(
|
||||
(row) => row.scope === scope && row.scopeId === scopeId,
|
||||
),
|
||||
set: async (
|
||||
pluginId: string,
|
||||
scope: string,
|
||||
scopeId: string | null,
|
||||
key: string,
|
||||
value: string | null,
|
||||
) => {
|
||||
const existing = state.pluginRows.find(
|
||||
(row) =>
|
||||
row.scope === scope && row.scopeId === scopeId && row.key === key,
|
||||
);
|
||||
if (existing) {
|
||||
existing.value = value;
|
||||
return;
|
||||
}
|
||||
state.pluginRows.push({ pluginId, scope, scopeId, key, value });
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("../../utils/crypto-migration/raw-rows.js", () => ({
|
||||
selectRows: async () => {
|
||||
if (state.columnsGone) throw new Error("no such column: enable_docker");
|
||||
return state.hostRows;
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("../../utils/logger.js", () => ({
|
||||
databaseLogger: { info: vi.fn(), warn: vi.fn() },
|
||||
}));
|
||||
|
||||
import {
|
||||
dockerSettingsFromRow,
|
||||
runDockerSettingsMigration,
|
||||
} from "../../utils/crypto-migration/docker-settings-migration.js";
|
||||
|
||||
const hostValues = (hostId: number) =>
|
||||
Object.fromEntries(
|
||||
state.pluginRows
|
||||
.filter((row) => row.scope === "host" && row.scopeId === String(hostId))
|
||||
.map((row) => [row.key, JSON.parse(row.value ?? "null")]),
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
state.pluginRows = [];
|
||||
state.hostRows = [];
|
||||
state.pluginInstalled = true;
|
||||
state.columnsGone = false;
|
||||
});
|
||||
|
||||
describe("dockerSettingsFromRow", () => {
|
||||
it("reads SQLite integers, real booleans and strings", () => {
|
||||
expect(
|
||||
dockerSettingsFromRow({ id: 1, enable_docker: 1, docker_config: null }),
|
||||
).toEqual({ enableDocker: true });
|
||||
expect(
|
||||
dockerSettingsFromRow({
|
||||
id: 1,
|
||||
enable_docker: true,
|
||||
docker_config: null,
|
||||
}),
|
||||
).toEqual({ enableDocker: true });
|
||||
expect(
|
||||
dockerSettingsFromRow({ id: 1, enable_docker: 0, docker_config: null }),
|
||||
).toEqual({});
|
||||
expect(
|
||||
dockerSettingsFromRow({
|
||||
id: 1,
|
||||
enable_docker: false,
|
||||
docker_config: null,
|
||||
}),
|
||||
).toEqual({});
|
||||
});
|
||||
|
||||
it("keeps a Podman runtime and ignores the default or broken config", () => {
|
||||
expect(
|
||||
dockerSettingsFromRow({
|
||||
id: 1,
|
||||
enable_docker: 1,
|
||||
docker_config: '{"runtime":"podman"}',
|
||||
}),
|
||||
).toEqual({ enableDocker: true, containerRuntime: "podman" });
|
||||
expect(
|
||||
dockerSettingsFromRow({
|
||||
id: 1,
|
||||
enable_docker: 1,
|
||||
docker_config: '{"runtime":"docker"}',
|
||||
}),
|
||||
).toEqual({ enableDocker: true });
|
||||
expect(
|
||||
dockerSettingsFromRow({
|
||||
id: 1,
|
||||
enable_docker: 1,
|
||||
docker_config: "{oops",
|
||||
}),
|
||||
).toEqual({ enableDocker: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe("runDockerSettingsMigration", () => {
|
||||
it("moves every host's docker options and skips hosts with nothing set", async () => {
|
||||
state.hostRows = [
|
||||
{ id: 1, enable_docker: 1, docker_config: null },
|
||||
{ id: 2, enable_docker: 1, docker_config: '{"runtime":"podman"}' },
|
||||
{ id: 3, enable_docker: 0, docker_config: null },
|
||||
];
|
||||
|
||||
const result = await runDockerSettingsMigration();
|
||||
|
||||
expect(result).toEqual({ hostsMoved: 2, hostsSkipped: 0 });
|
||||
expect(hostValues(1)).toEqual({ enableDocker: true });
|
||||
expect(hostValues(2)).toEqual({
|
||||
enableDocker: true,
|
||||
containerRuntime: "podman",
|
||||
});
|
||||
expect(hostValues(3)).toEqual({});
|
||||
});
|
||||
|
||||
it("changes nothing when run twice", async () => {
|
||||
state.hostRows = [
|
||||
{ id: 1, enable_docker: 1, docker_config: '{"runtime":"podman"}' },
|
||||
];
|
||||
await runDockerSettingsMigration();
|
||||
const before = JSON.stringify(state.pluginRows);
|
||||
|
||||
const second = await runDockerSettingsMigration();
|
||||
|
||||
expect(second).toEqual({ hostsMoved: 0, hostsSkipped: 1 });
|
||||
expect(JSON.stringify(state.pluginRows)).toBe(before);
|
||||
});
|
||||
|
||||
it("keeps a value already saved in the plugin", async () => {
|
||||
state.pluginRows.push({
|
||||
pluginId: "docker",
|
||||
scope: "host",
|
||||
scopeId: "1",
|
||||
key: "enableDocker",
|
||||
value: "false",
|
||||
});
|
||||
state.hostRows = [{ id: 1, enable_docker: 1, docker_config: null }];
|
||||
|
||||
await runDockerSettingsMigration();
|
||||
|
||||
expect(hostValues(1)).toEqual({ enableDocker: false });
|
||||
});
|
||||
|
||||
it("does nothing before the plugin row exists or once the columns are gone", async () => {
|
||||
state.hostRows = [{ id: 1, enable_docker: 1, docker_config: null }];
|
||||
state.pluginInstalled = false;
|
||||
expect(await runDockerSettingsMigration()).toEqual({
|
||||
hostsMoved: 0,
|
||||
hostsSkipped: 0,
|
||||
});
|
||||
|
||||
state.pluginInstalled = true;
|
||||
state.columnsGone = true;
|
||||
expect(await runDockerSettingsMigration()).toEqual({
|
||||
hostsMoved: 0,
|
||||
hostsSkipped: 0,
|
||||
});
|
||||
expect(state.pluginRows).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* Moves each host's Docker options out of ssh_data and into the docker
|
||||
* plugin's host settings: enable_docker becomes enableDocker and the runtime
|
||||
* in docker_config becomes containerRuntime.
|
||||
*
|
||||
* The columns stay in the database, unused: core's drizzle migrations run
|
||||
* before this does, so dropping them there would lose the data first.
|
||||
*
|
||||
* Idempotent: a host that already has any docker row is skipped, so this is
|
||||
* safe on every boot.
|
||||
*/
|
||||
|
||||
import { sql } from "drizzle-orm";
|
||||
import { databaseLogger } from "../logger.js";
|
||||
import {
|
||||
createCurrentPluginRepository,
|
||||
createCurrentPluginSettingsRepository,
|
||||
} from "../../database/repositories/factory.js";
|
||||
import { selectRows } from "./raw-rows.js";
|
||||
|
||||
const PLUGIN_ID = "docker";
|
||||
|
||||
interface LegacyHostRow {
|
||||
id: number;
|
||||
enable_docker: number | boolean | string | null;
|
||||
docker_config: string | null;
|
||||
}
|
||||
|
||||
/** The plugin's host settings for one legacy row, defaults left out. */
|
||||
export function dockerSettingsFromRow(
|
||||
row: LegacyHostRow,
|
||||
): Record<string, unknown> {
|
||||
const values: Record<string, unknown> = {};
|
||||
const flag = row.enable_docker;
|
||||
if (flag === true || flag === 1 || flag === "1" || flag === "true") {
|
||||
values.enableDocker = true;
|
||||
}
|
||||
if (row.docker_config) {
|
||||
try {
|
||||
const config = JSON.parse(row.docker_config) as { runtime?: unknown };
|
||||
if (config?.runtime === "podman") values.containerRuntime = "podman";
|
||||
} catch {
|
||||
// unreadable config means the default runtime
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
export interface DockerSettingsMigrationResult {
|
||||
hostsMoved: number;
|
||||
hostsSkipped: number;
|
||||
}
|
||||
|
||||
export async function runDockerSettingsMigration(): Promise<DockerSettingsMigrationResult> {
|
||||
const result: DockerSettingsMigrationResult = {
|
||||
hostsMoved: 0,
|
||||
hostsSkipped: 0,
|
||||
};
|
||||
|
||||
// plugin_settings has a foreign key to plugins: nothing to migrate into
|
||||
// until the plugin row exists.
|
||||
try {
|
||||
const plugin = await createCurrentPluginRepository().findById(PLUGIN_ID);
|
||||
if (!plugin) return result;
|
||||
} catch {
|
||||
return result;
|
||||
}
|
||||
|
||||
const pluginSettings = createCurrentPluginSettingsRepository();
|
||||
|
||||
let rows: LegacyHostRow[];
|
||||
try {
|
||||
// Raw SQL: schema.ts no longer declares these columns.
|
||||
rows = await selectRows<LegacyHostRow>(
|
||||
sql`SELECT id, enable_docker, docker_config FROM ssh_data`,
|
||||
);
|
||||
} catch {
|
||||
// A fresh install never had the columns.
|
||||
return result;
|
||||
}
|
||||
|
||||
for (const row of rows) {
|
||||
const values = dockerSettingsFromRow(row);
|
||||
if (Object.keys(values).length === 0) continue;
|
||||
const scopeId = String(row.id);
|
||||
try {
|
||||
const existing = await pluginSettings.getAll(PLUGIN_ID, "host", scopeId);
|
||||
if (existing.length > 0) {
|
||||
result.hostsSkipped++;
|
||||
continue;
|
||||
}
|
||||
for (const [key, value] of Object.entries(values)) {
|
||||
await pluginSettings.set(
|
||||
PLUGIN_ID,
|
||||
"host",
|
||||
scopeId,
|
||||
key,
|
||||
JSON.stringify(value),
|
||||
);
|
||||
}
|
||||
result.hostsMoved++;
|
||||
} catch (error) {
|
||||
databaseLogger.warn("Docker host settings migration failed for a host", {
|
||||
operation: "docker_settings_migration",
|
||||
hostId: row.id,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (result.hostsMoved > 0) {
|
||||
databaseLogger.info(
|
||||
`Moved Docker settings for ${result.hostsMoved} host(s) into plugin settings`,
|
||||
{ operation: "docker_settings_migration" },
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -22,7 +22,6 @@ export type WidgetTypeId =
|
||||
| "ssh_terminal"
|
||||
| "quick_connect"
|
||||
| "file_manager_widget"
|
||||
| "docker_widget"
|
||||
| "tunnel_widget"
|
||||
| "calendar"
|
||||
| "countdown"
|
||||
@@ -35,7 +34,6 @@ export type WidgetTypeId =
|
||||
| "dashboard_links"
|
||||
| "search_links"
|
||||
| "link_tree"
|
||||
| "docker_activity"
|
||||
| "ssh_quick_connect"
|
||||
| (string & {});
|
||||
|
||||
@@ -213,10 +211,6 @@ export interface FileManagerWidgetConfig {
|
||||
hostId: number;
|
||||
}
|
||||
|
||||
export interface DockerWidgetConfig {
|
||||
hostId: number;
|
||||
}
|
||||
|
||||
export interface SshTerminalConfig {
|
||||
hostId: number;
|
||||
autoConnect: boolean;
|
||||
|
||||
@@ -157,7 +157,6 @@ export interface HostFeatureFlags {
|
||||
enableTerminal: boolean; // SSH, Telnet only
|
||||
enableTunnel: boolean; // SSH only
|
||||
enableFileManager: boolean; // SSH only
|
||||
enableDocker: boolean; // SSH only
|
||||
enableTmuxMonitor: boolean; // SSH only
|
||||
enableTerminalToolbar: boolean; // SSH, RDP, VNC, and Telnet
|
||||
enableAiAssistant: boolean; // SSH only
|
||||
@@ -216,7 +215,6 @@ export type Host = {
|
||||
enableTunnel: boolean;
|
||||
enableFileManager: boolean;
|
||||
scpLegacy?: boolean;
|
||||
enableDocker: boolean;
|
||||
enableTmuxMonitor: boolean;
|
||||
enableTerminalToolbar: boolean;
|
||||
enableAiAssistant: boolean;
|
||||
@@ -253,7 +251,6 @@ export type Host = {
|
||||
/** "ssh", or the id of the plugin protocol a host without SSH uses. */
|
||||
connectionType?: string;
|
||||
domain?: string;
|
||||
dockerConfig?: Record<string, unknown> | null;
|
||||
enableWebUi?: boolean;
|
||||
webUiConfig?: WebUiConfig | null;
|
||||
|
||||
@@ -368,7 +365,6 @@ export interface HostData {
|
||||
enableTunnel?: boolean;
|
||||
enableFileManager?: boolean;
|
||||
scpLegacy?: boolean;
|
||||
enableDocker?: boolean;
|
||||
enableProxmox?: boolean;
|
||||
enableTmuxMonitor?: boolean;
|
||||
enableTerminalToolbar?: boolean;
|
||||
@@ -410,7 +406,6 @@ export interface HostData {
|
||||
/** "ssh", or the id of the plugin protocol a host without SSH uses. */
|
||||
connectionType?: string;
|
||||
domain?: string;
|
||||
dockerConfig?: Record<string, unknown> | null;
|
||||
enableWebUi?: boolean;
|
||||
webUiConfig?: WebUiConfig | null;
|
||||
|
||||
@@ -1005,52 +1000,3 @@ export interface RestoreRequestBody {
|
||||
// ============================================================================
|
||||
// DOCKER TYPES
|
||||
// ============================================================================
|
||||
|
||||
export interface DockerContainer {
|
||||
id: string;
|
||||
name: string;
|
||||
image: string;
|
||||
status: string;
|
||||
state:
|
||||
| "created"
|
||||
| "running"
|
||||
| "paused"
|
||||
| "restarting"
|
||||
| "removing"
|
||||
| "exited"
|
||||
| "dead";
|
||||
ports: string;
|
||||
created: string;
|
||||
command?: string;
|
||||
labels?: Record<string, string>;
|
||||
networks?: string[];
|
||||
mounts?: string[];
|
||||
}
|
||||
|
||||
export interface DockerStats {
|
||||
cpu: string;
|
||||
memoryUsed: string;
|
||||
memoryLimit: string;
|
||||
memoryPercent: string;
|
||||
netInput: string;
|
||||
netOutput: string;
|
||||
blockRead: string;
|
||||
blockWrite: string;
|
||||
pids?: string;
|
||||
}
|
||||
|
||||
export interface DockerLogOptions {
|
||||
tail?: number;
|
||||
timestamps?: boolean;
|
||||
since?: string;
|
||||
until?: string;
|
||||
follow?: boolean;
|
||||
}
|
||||
|
||||
export interface DockerValidation {
|
||||
available: boolean;
|
||||
version?: string;
|
||||
runtime?: "docker" | "podman";
|
||||
error?: string;
|
||||
code?: string;
|
||||
}
|
||||
@@ -100,10 +100,6 @@ export type Host = {
|
||||
scpLegacy?: boolean;
|
||||
defaultPath?: string;
|
||||
|
||||
enableDocker: boolean;
|
||||
dockerConfig?: {
|
||||
runtime?: "docker" | "podman";
|
||||
} | null;
|
||||
enableWebUi?: boolean;
|
||||
enableProxmox: boolean;
|
||||
enableTmuxMonitor: boolean;
|
||||
|
||||
@@ -2490,7 +2490,6 @@ export function AppShell({
|
||||
enableCommandHistory: false,
|
||||
enableTunnel: false,
|
||||
enableFileManager: false,
|
||||
enableDocker: false,
|
||||
enableProxmox: false,
|
||||
enableProxmoxStats: false,
|
||||
enableTmuxMonitor: false,
|
||||
|
||||
@@ -26,10 +26,8 @@ export function hostToSSHHost(h: Host): SSHHost {
|
||||
enableTerminal: h.enableTerminal ?? false,
|
||||
enableTunnel: h.enableTunnel ?? false,
|
||||
enableFileManager: h.enableFileManager ?? false,
|
||||
enableDocker: h.enableDocker ?? false,
|
||||
enableTerminalToolbar: h.enableTerminalToolbar ?? true,
|
||||
enableAiAssistant: h.enableAiAssistant ?? false,
|
||||
dockerConfig: h.dockerConfig ?? null,
|
||||
enableWebUi: h.enableWebUi ?? false,
|
||||
webUiConfig: (h.pluginSettings?.["web-endpoint"]?.webUiConfig as
|
||||
SSHHost["webUiConfig"] | undefined) ?? { endpoints: [] },
|
||||
|
||||
@@ -1241,8 +1241,6 @@
|
||||
"disableTerminalFeature": "Disable Terminal",
|
||||
"enableFilesFeature": "Enable Files",
|
||||
"disableFilesFeature": "Disable Files",
|
||||
"enableDockerFeature": "Enable Docker",
|
||||
"disableDockerFeature": "Disable Docker",
|
||||
"enableProxmoxFeature": "Enable Proxmox",
|
||||
"disableProxmoxFeature": "Disable Proxmox",
|
||||
"addTagsPlaceholder": "Add tags...",
|
||||
@@ -1364,7 +1362,6 @@
|
||||
"filterFeaturesGroup": "Features",
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "File Manager",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Tags",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Deaktiveer lêers",
|
||||
"enableTunnelsFeature": "Aktiveer tonnels",
|
||||
"disableTunnelsFeature": "Deaktiveer tonnels",
|
||||
"enableDockerFeature": "Aktiveer Docker",
|
||||
"disableDockerFeature": "Deaktiveer Docker",
|
||||
"enableProxmoxFeature": "Aktiveer Proxmox",
|
||||
"disableProxmoxFeature": "Deaktiveer Proxmox",
|
||||
"addTagsPlaceholder": "Voeg etikette by...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminaal",
|
||||
"filterFeatureFileManager": "Lêerbestuurder",
|
||||
"filterFeatureTunnel": "Tonnel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Etikette",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "تعطيل الملفات",
|
||||
"enableTunnelsFeature": "تفعيل الأنفاق",
|
||||
"disableTunnelsFeature": "تعطيل الأنفاق",
|
||||
"enableDockerFeature": "تفعيل Docker",
|
||||
"disableDockerFeature": "تعطيل Docker",
|
||||
"enableProxmoxFeature": "تفعيل Proxmox",
|
||||
"disableProxmoxFeature": "تعطيل Proxmox",
|
||||
"addTagsPlaceholder": "إضافة علامات...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "الطرفية",
|
||||
"filterFeatureFileManager": "مدير الملفات",
|
||||
"filterFeatureTunnel": "نفق",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "الوسوم",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Деактивиране на файлове",
|
||||
"enableTunnelsFeature": "Активиране на тунели",
|
||||
"disableTunnelsFeature": "Деактивиране на тунелите",
|
||||
"enableDockerFeature": "Активиране на Докер",
|
||||
"disableDockerFeature": "Деактивиране на Докер",
|
||||
"enableProxmoxFeature": "Активиране на Proxmox",
|
||||
"disableProxmoxFeature": "Деактивиране на Proxmox",
|
||||
"addTagsPlaceholder": "Добавяне на етикети...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Терминал",
|
||||
"filterFeatureFileManager": "Файлов мениджър",
|
||||
"filterFeatureTunnel": "Тунел",
|
||||
"filterFeatureDocker": "Докер",
|
||||
"filterTagsGroup": "Етикети",
|
||||
"connectRdp": "ПРСР",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "ফাইলগুলি নিষ্ক্রিয় করুন",
|
||||
"enableTunnelsFeature": "টানেলগুলি সক্ষম করুন",
|
||||
"disableTunnelsFeature": "টানেল নিষ্ক্রিয় করুন",
|
||||
"enableDockerFeature": "ডকার সক্রিয় করুন",
|
||||
"disableDockerFeature": "ডকার নিষ্ক্রিয় করুন",
|
||||
"enableProxmoxFeature": "প্রক্সমক্স সক্রিয় করুন",
|
||||
"disableProxmoxFeature": "প্রক্সমক্স নিষ্ক্রিয় করুন",
|
||||
"addTagsPlaceholder": "ট্যাগ যোগ করুন...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "টার্মিনাল",
|
||||
"filterFeatureFileManager": "ফাইল ম্যানেজার",
|
||||
"filterFeatureTunnel": "টানেল",
|
||||
"filterFeatureDocker": "ডকার",
|
||||
"filterTagsGroup": "ট্যাগ",
|
||||
"connectRdp": "আরডিপি",
|
||||
"connectVnc": "ভিএনসি",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Desactiva els fitxers",
|
||||
"enableTunnelsFeature": "Habilita els túnels",
|
||||
"disableTunnelsFeature": "Desactiva els túnels",
|
||||
"enableDockerFeature": "Activa Docker",
|
||||
"disableDockerFeature": "Desactiva Docker",
|
||||
"enableProxmoxFeature": "Activa Proxmox",
|
||||
"disableProxmoxFeature": "Desactiva Proxmox",
|
||||
"addTagsPlaceholder": "Afegeix etiquetes...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Gestor de fitxers",
|
||||
"filterFeatureTunnel": "Túnel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Etiquetes",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Zakázat soubory",
|
||||
"enableTunnelsFeature": "Povolit tunely",
|
||||
"disableTunnelsFeature": "Zakázat tunely",
|
||||
"enableDockerFeature": "Povolit Docker",
|
||||
"disableDockerFeature": "Zakázat Docker",
|
||||
"enableProxmoxFeature": "Povolit Proxmox",
|
||||
"disableProxmoxFeature": "Zakázat Proxmox",
|
||||
"addTagsPlaceholder": "Přidat štítky...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminál",
|
||||
"filterFeatureFileManager": "Správce souborů",
|
||||
"filterFeatureTunnel": "Tunel",
|
||||
"filterFeatureDocker": "Přístavní dělník",
|
||||
"filterTagsGroup": "Štítky",
|
||||
"connectRdp": "PRV",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Deaktiver filer",
|
||||
"enableTunnelsFeature": "Aktivér tunneler",
|
||||
"disableTunnelsFeature": "Deaktiver tunneler",
|
||||
"enableDockerFeature": "Aktivér Docker",
|
||||
"disableDockerFeature": "Deaktiver Docker",
|
||||
"enableProxmoxFeature": "Aktivér Proxmox",
|
||||
"disableProxmoxFeature": "Deaktiver Proxmox",
|
||||
"addTagsPlaceholder": "Tilføj tags...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Filhåndtering",
|
||||
"filterFeatureTunnel": "Tunnel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Tags",
|
||||
"connectRdp": "Landdistriktsudviklingsplan",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Dateien deaktivieren",
|
||||
"enableTunnelsFeature": "Tunnels aktivieren",
|
||||
"disableTunnelsFeature": "Tunnels deaktivieren",
|
||||
"enableDockerFeature": "Docker aktivieren",
|
||||
"disableDockerFeature": "Docker deaktivieren",
|
||||
"enableProxmoxFeature": "Proxmox aktivieren",
|
||||
"disableProxmoxFeature": "Proxmox deaktivieren",
|
||||
"addTagsPlaceholder": "Tags hinzufügen...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Dateimanager",
|
||||
"filterFeatureTunnel": "Tunnel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Tags",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Απενεργοποίηση αρχείων",
|
||||
"enableTunnelsFeature": "Ενεργοποίηση σηράγγων",
|
||||
"disableTunnelsFeature": "Απενεργοποίηση σηράγγων",
|
||||
"enableDockerFeature": "Ενεργοποίηση Docker",
|
||||
"disableDockerFeature": "Απενεργοποίηση Docker",
|
||||
"enableProxmoxFeature": "Ενεργοποίηση Proxmox",
|
||||
"disableProxmoxFeature": "Απενεργοποίηση Proxmox",
|
||||
"addTagsPlaceholder": "Προσθήκη ετικετών...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Τερματικό",
|
||||
"filterFeatureFileManager": "Διαχειριστής αρχείων",
|
||||
"filterFeatureTunnel": "Σήραγγα",
|
||||
"filterFeatureDocker": "Λιμενεργάτης",
|
||||
"filterTagsGroup": "Ετικέτες",
|
||||
"connectRdp": "ΠΑΑ",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Deshabilitar archivos",
|
||||
"enableTunnelsFeature": "Activar túneles",
|
||||
"disableTunnelsFeature": "Desactivar túneles",
|
||||
"enableDockerFeature": "Activar Docker",
|
||||
"disableDockerFeature": "Desactivar Docker",
|
||||
"enableProxmoxFeature": "Activar Proxmox",
|
||||
"disableProxmoxFeature": "Desactivar Proxmox",
|
||||
"addTagsPlaceholder": "Añadir etiquetas...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Gestor de archivos",
|
||||
"filterFeatureTunnel": "Túnel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Etiquetas",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Poista tiedostot käytöstä",
|
||||
"enableTunnelsFeature": "Ota tunnelit käyttöön",
|
||||
"disableTunnelsFeature": "Tunnelien poistaminen käytöstä",
|
||||
"enableDockerFeature": "Ota Docker käyttöön",
|
||||
"disableDockerFeature": "Poista Docker käytöstä",
|
||||
"enableProxmoxFeature": "Ota Proxmox käyttöön",
|
||||
"disableProxmoxFeature": "Poista Proxmox käytöstä",
|
||||
"addTagsPlaceholder": "Lisää tunnisteita...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminaali",
|
||||
"filterFeatureFileManager": "Tiedostonhallinta",
|
||||
"filterFeatureTunnel": "Tunneli",
|
||||
"filterFeatureDocker": "Satamatyöläinen",
|
||||
"filterTagsGroup": "Tunnisteet",
|
||||
"connectRdp": "Maaseudun kehittämisohjelma",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Désactiver les fichiers",
|
||||
"enableTunnelsFeature": "Activer les tunnels",
|
||||
"disableTunnelsFeature": "Désactiver les tunnels",
|
||||
"enableDockerFeature": "Activer Docker",
|
||||
"disableDockerFeature": "Désactiver Docker",
|
||||
"enableProxmoxFeature": "Activer Proxmox",
|
||||
"disableProxmoxFeature": "Désactiver Proxmox",
|
||||
"addTagsPlaceholder": "Ajouter des étiquettes...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Gestionnaire de fichiers",
|
||||
"filterFeatureTunnel": "Tunnel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Étiquettes",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "השבת קבצים",
|
||||
"enableTunnelsFeature": "הפעל מנהרות",
|
||||
"disableTunnelsFeature": "השבת מנהרות",
|
||||
"enableDockerFeature": "הפעל את Docker",
|
||||
"disableDockerFeature": "השבת את Docker",
|
||||
"enableProxmoxFeature": "הפעל את Proxmox",
|
||||
"disableProxmoxFeature": "השבת את פרוקסמוקס",
|
||||
"addTagsPlaceholder": "הוסף תגיות...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "מָסוֹף",
|
||||
"filterFeatureFileManager": "מנהל הקבצים",
|
||||
"filterFeatureTunnel": "מִנהָרָה",
|
||||
"filterFeatureDocker": "דוקר",
|
||||
"filterTagsGroup": "תגיות",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "फ़ाइलें अक्षम करें",
|
||||
"enableTunnelsFeature": "टनल सक्षम करें",
|
||||
"disableTunnelsFeature": "टनल अक्षम करें",
|
||||
"enableDockerFeature": "Docker सक्षम करें",
|
||||
"disableDockerFeature": "Docker अक्षम करें",
|
||||
"enableProxmoxFeature": "Proxmox सक्षम करें",
|
||||
"disableProxmoxFeature": "Proxmox अक्षम करें",
|
||||
"addTagsPlaceholder": "टैग जोड़ें…",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "टर्मिनल",
|
||||
"filterFeatureFileManager": "फ़ाइल प्रबंधक",
|
||||
"filterFeatureTunnel": "टनल",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "टैग्स",
|
||||
"connectRdp": "आरडीपी",
|
||||
"connectVnc": "वीएनसी",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Fájlok letiltása",
|
||||
"enableTunnelsFeature": "Alagutak engedélyezése",
|
||||
"disableTunnelsFeature": "Alagutak letiltása",
|
||||
"enableDockerFeature": "Docker engedélyezése",
|
||||
"disableDockerFeature": "Docker letiltása",
|
||||
"enableProxmoxFeature": "Proxmox engedélyezése",
|
||||
"disableProxmoxFeature": "Proxmox letiltása",
|
||||
"addTagsPlaceholder": "Címkék hozzáadása...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminál",
|
||||
"filterFeatureFileManager": "Fájlkezelő",
|
||||
"filterFeatureTunnel": "Alagút",
|
||||
"filterFeatureDocker": "Dokkmunkás",
|
||||
"filterTagsGroup": "Címkék",
|
||||
"connectRdp": "Vidékfejlesztési Program",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Nonaktifkan File",
|
||||
"enableTunnelsFeature": "Aktifkan Terowongan",
|
||||
"disableTunnelsFeature": "Nonaktifkan Terowongan",
|
||||
"enableDockerFeature": "Aktifkan Docker",
|
||||
"disableDockerFeature": "Nonaktifkan Docker",
|
||||
"enableProxmoxFeature": "Aktifkan Proxmox",
|
||||
"disableProxmoxFeature": "Nonaktifkan Proxmox",
|
||||
"addTagsPlaceholder": "Tambahkan tag...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Pengelola File",
|
||||
"filterFeatureTunnel": "Terowongan",
|
||||
"filterFeatureDocker": "Buruh pelabuhan",
|
||||
"filterTagsGroup": "Tag",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Disabilita File",
|
||||
"enableTunnelsFeature": "Abilita tunnel",
|
||||
"disableTunnelsFeature": "Disabilita tunnel",
|
||||
"enableDockerFeature": "Abilita Docker",
|
||||
"disableDockerFeature": "Disabilita Docker",
|
||||
"enableProxmoxFeature": "Abilita Proxmox",
|
||||
"disableProxmoxFeature": "Disabilita Proxmox",
|
||||
"addTagsPlaceholder": "Aggiungi tag...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminale",
|
||||
"filterFeatureFileManager": "Gestione file",
|
||||
"filterFeatureTunnel": "Tunnel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Tag",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "ファイルを無効化",
|
||||
"enableTunnelsFeature": "トンネルを有効化",
|
||||
"disableTunnelsFeature": "トンネルを無効化",
|
||||
"enableDockerFeature": "Dockerを有効化",
|
||||
"disableDockerFeature": "Dockerを無効化",
|
||||
"enableProxmoxFeature": "Proxmoxを有効化",
|
||||
"disableProxmoxFeature": "Proxmoxを無効化",
|
||||
"addTagsPlaceholder": "タグを追加...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "ターミナル",
|
||||
"filterFeatureFileManager": "ファイルマネージャー",
|
||||
"filterFeatureTunnel": "トンネル",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "タグ",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "파일 비활성화",
|
||||
"enableTunnelsFeature": "터널 활성화",
|
||||
"disableTunnelsFeature": "터널 비활성화",
|
||||
"enableDockerFeature": "Docker 활성화",
|
||||
"disableDockerFeature": "Docker 비활성화",
|
||||
"enableProxmoxFeature": "Proxmox 활성화",
|
||||
"disableProxmoxFeature": "Proxmox 비활성화",
|
||||
"addTagsPlaceholder": "태그 추가...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "터미널",
|
||||
"filterFeatureFileManager": "파일 관리자",
|
||||
"filterFeatureTunnel": "터널",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "태그",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Bestanden uitschakelen",
|
||||
"enableTunnelsFeature": "Tunnels inschakelen",
|
||||
"disableTunnelsFeature": "Tunnels uitschakelen",
|
||||
"enableDockerFeature": "Docker inschakelen",
|
||||
"disableDockerFeature": "Docker uitschakelen",
|
||||
"enableProxmoxFeature": "Proxmox inschakelen",
|
||||
"disableProxmoxFeature": "Proxmox uitschakelen",
|
||||
"addTagsPlaceholder": "Tags toevoegen...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Bestandsbeheerder",
|
||||
"filterFeatureTunnel": "Tunnel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Tags",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Deaktiver filer",
|
||||
"enableTunnelsFeature": "Aktiver tunneler",
|
||||
"disableTunnelsFeature": "Deaktiver tunneler",
|
||||
"enableDockerFeature": "Aktiver Docker",
|
||||
"disableDockerFeature": "Deaktiver Docker",
|
||||
"enableProxmoxFeature": "Aktiver Proxmox",
|
||||
"disableProxmoxFeature": "Deaktiver Proxmox",
|
||||
"addTagsPlaceholder": "Legg til tagger...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Filbehandler",
|
||||
"filterFeatureTunnel": "Tunnel",
|
||||
"filterFeatureDocker": "Dokker",
|
||||
"filterTagsGroup": "Tagger",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Wyłącz pliki",
|
||||
"enableTunnelsFeature": "Włącz tunele",
|
||||
"disableTunnelsFeature": "Wyłącz tunele",
|
||||
"enableDockerFeature": "Włącz Docker",
|
||||
"disableDockerFeature": "Wyłącz Docker",
|
||||
"enableProxmoxFeature": "Włącz Proxmox",
|
||||
"disableProxmoxFeature": "Wyłącz Proxmox",
|
||||
"addTagsPlaceholder": "Dodaj tagi...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Menedżer plików",
|
||||
"filterFeatureTunnel": "Tunel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Tagi",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Desativar arquivos",
|
||||
"enableTunnelsFeature": "Ativar túneis",
|
||||
"disableTunnelsFeature": "Desativar túneis",
|
||||
"enableDockerFeature": "Habilitar Docker",
|
||||
"disableDockerFeature": "Desativar o Docker",
|
||||
"enableProxmoxFeature": "Ativar Proxmox",
|
||||
"disableProxmoxFeature": "Desativar Proxmox",
|
||||
"addTagsPlaceholder": "Adicionar etiquetas...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "terminal",
|
||||
"filterFeatureFileManager": "Gerenciador de arquivos",
|
||||
"filterFeatureTunnel": "Túnel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Etiquetas",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Desativar Ficheiros",
|
||||
"enableTunnelsFeature": "Ativar Tunnels",
|
||||
"disableTunnelsFeature": "Desativar Tunnels",
|
||||
"enableDockerFeature": "Ativar Docker",
|
||||
"disableDockerFeature": "Desativar Docker",
|
||||
"enableProxmoxFeature": "Ativar Proxmox",
|
||||
"disableProxmoxFeature": "Desativar Proxmox",
|
||||
"addTagsPlaceholder": "Adicionar tags...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Gestor de Ficheiros",
|
||||
"filterFeatureTunnel": "Túnel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Etiquetas",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Dezactivați fișierele",
|
||||
"enableTunnelsFeature": "Activează tunelurile",
|
||||
"disableTunnelsFeature": "Dezactivați tunelurile",
|
||||
"enableDockerFeature": "Activează Docker",
|
||||
"disableDockerFeature": "Dezactivați Docker",
|
||||
"enableProxmoxFeature": "Activează Proxmox",
|
||||
"disableProxmoxFeature": "Dezactivați Proxmox",
|
||||
"addTagsPlaceholder": "Adăugați etichete...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Manager de fișiere",
|
||||
"filterFeatureTunnel": "Tunel",
|
||||
"filterFeatureDocker": "Docher",
|
||||
"filterTagsGroup": "Etichete",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Отключить файлы",
|
||||
"enableTunnelsFeature": "Включить туннели",
|
||||
"disableTunnelsFeature": "Отключить туннели",
|
||||
"enableDockerFeature": "Включить Docker",
|
||||
"disableDockerFeature": "Отключить Docker",
|
||||
"enableProxmoxFeature": "Включить Proxmox",
|
||||
"disableProxmoxFeature": "Отключить Proxmox",
|
||||
"addTagsPlaceholder": "Добавить теги...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Терминал",
|
||||
"filterFeatureFileManager": "Файловый менеджер",
|
||||
"filterFeatureTunnel": "Туннель",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Теги",
|
||||
"connectRdp": "РДП",
|
||||
"connectVnc": "ВНК",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Онемогући датотеке",
|
||||
"enableTunnelsFeature": "Омогући тунеле",
|
||||
"disableTunnelsFeature": "Онемогући тунеле",
|
||||
"enableDockerFeature": "Омогући Докер",
|
||||
"disableDockerFeature": "Онемогући Докер",
|
||||
"enableProxmoxFeature": "Омогући Proxmox",
|
||||
"disableProxmoxFeature": "Онемогући Проксмокс",
|
||||
"addTagsPlaceholder": "Додај ознаке...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Терминал",
|
||||
"filterFeatureFileManager": "Менаџер датотека",
|
||||
"filterFeatureTunnel": "Тунел",
|
||||
"filterFeatureDocker": "Докер",
|
||||
"filterTagsGroup": "Ознаке",
|
||||
"connectRdp": "РДП",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Inaktivera filer",
|
||||
"enableTunnelsFeature": "Aktivera tunnlar",
|
||||
"disableTunnelsFeature": "Inaktivera tunnlar",
|
||||
"enableDockerFeature": "Aktivera Docker",
|
||||
"disableDockerFeature": "Inaktivera Docker",
|
||||
"enableProxmoxFeature": "Aktivera Proxmox",
|
||||
"disableProxmoxFeature": "Inaktivera Proxmox",
|
||||
"addTagsPlaceholder": "Lägg till taggar...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Filhanteraren",
|
||||
"filterFeatureTunnel": "Tunnel",
|
||||
"filterFeatureDocker": "Hamnarbetare",
|
||||
"filterTagsGroup": "Taggar",
|
||||
"connectRdp": "Landsbygdsutveckling",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "ปิดใช้งานไฟล์",
|
||||
"enableTunnelsFeature": "เปิดใช้งานอุโมงค์",
|
||||
"disableTunnelsFeature": "ปิดใช้งานอุโมงค์",
|
||||
"enableDockerFeature": "เปิดใช้งาน Docker",
|
||||
"disableDockerFeature": "ปิดใช้งาน Docker",
|
||||
"enableProxmoxFeature": "เปิดใช้งาน Proxmox",
|
||||
"disableProxmoxFeature": "ปิดใช้งาน Proxmox",
|
||||
"addTagsPlaceholder": "เพิ่มแท็ก...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "เทอร์มินัล",
|
||||
"filterFeatureFileManager": "ตัวจัดการไฟล์",
|
||||
"filterFeatureTunnel": "อุโมงค์",
|
||||
"filterFeatureDocker": "ด็อกเกอร์",
|
||||
"filterTagsGroup": "แท็ก",
|
||||
"connectRdp": "อาร์ดีพี",
|
||||
"connectVnc": "วีเอ็นซี",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Dosyaları Devre Dışı Bırak",
|
||||
"enableTunnelsFeature": "Tünelleri Etkinleştir",
|
||||
"disableTunnelsFeature": "Tünelleri Devre Dışı Bırak",
|
||||
"enableDockerFeature": "Docker'ı Etkinleştir",
|
||||
"disableDockerFeature": "Docker'ı Devre Dışı Bırak",
|
||||
"enableProxmoxFeature": "Proxmox'u Etkinleştir",
|
||||
"disableProxmoxFeature": "Proxmox'u Devre Dışı Bırak",
|
||||
"addTagsPlaceholder": "Etiket ekle...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Dosya Yöneticisi",
|
||||
"filterFeatureTunnel": "Tünel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Etiketler",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Вимкнути файли",
|
||||
"enableTunnelsFeature": "Увімкнути тунелі",
|
||||
"disableTunnelsFeature": "Вимкнути тунелі",
|
||||
"enableDockerFeature": "Увімкнути Докер",
|
||||
"disableDockerFeature": "Вимкнути Докер",
|
||||
"enableProxmoxFeature": "Увімкнути Proxmox",
|
||||
"disableProxmoxFeature": "Вимкнути Proxmox",
|
||||
"addTagsPlaceholder": "Додати теги...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Термінал",
|
||||
"filterFeatureFileManager": "Файловий менеджер",
|
||||
"filterFeatureTunnel": "Тунель",
|
||||
"filterFeatureDocker": "Докер",
|
||||
"filterTagsGroup": "Теги",
|
||||
"connectRdp": "ПРП",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "Tắt Files",
|
||||
"enableTunnelsFeature": "Bật Tunnels",
|
||||
"disableTunnelsFeature": "Tắt Tunnels",
|
||||
"enableDockerFeature": "Bật Docker",
|
||||
"disableDockerFeature": "Tắt Docker",
|
||||
"enableProxmoxFeature": "Bật Proxmox",
|
||||
"disableProxmoxFeature": "Tắt Proxmox",
|
||||
"addTagsPlaceholder": "Thêm thẻ...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "Terminal",
|
||||
"filterFeatureFileManager": "Trình quản lý file",
|
||||
"filterFeatureTunnel": "Tunnel",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "Thẻ",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "禁用文件",
|
||||
"enableTunnelsFeature": "启用隧道",
|
||||
"disableTunnelsFeature": "禁用隧道",
|
||||
"enableDockerFeature": "启用 Docker",
|
||||
"disableDockerFeature": "禁用 Docker",
|
||||
"enableProxmoxFeature": "启用 Proxmox",
|
||||
"disableProxmoxFeature": "禁用 Proxmox",
|
||||
"addTagsPlaceholder": "添加标签...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "终端",
|
||||
"filterFeatureFileManager": "文件管理器",
|
||||
"filterFeatureTunnel": "隧道",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "标签",
|
||||
"connectRdp": "RDP",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -1245,8 +1245,6 @@
|
||||
"disableFilesFeature": "停用檔案",
|
||||
"enableTunnelsFeature": "啟用通道",
|
||||
"disableTunnelsFeature": "停用通道",
|
||||
"enableDockerFeature": "啟用 Docker",
|
||||
"disableDockerFeature": "停用 Docker",
|
||||
"enableProxmoxFeature": "啟用 Proxmox",
|
||||
"disableProxmoxFeature": "停用 Proxmox",
|
||||
"addTagsPlaceholder": "新增標籤...",
|
||||
@@ -1369,7 +1367,6 @@
|
||||
"filterFeatureTerminal": "終端機",
|
||||
"filterFeatureFileManager": "檔案管理員",
|
||||
"filterFeatureTunnel": "通道",
|
||||
"filterFeatureDocker": "Docker",
|
||||
"filterTagsGroup": "標籤",
|
||||
"connectRdp": "遠端桌面協定",
|
||||
"connectVnc": "VNC",
|
||||
|
||||
@@ -770,12 +770,6 @@ function initializeApiInstances() {
|
||||
// RBAC API (port 30001)
|
||||
rbacApi = createApiInstance(getApiUrl("", 30001), "RBAC");
|
||||
|
||||
// Docker Management API - the docker plugin, mounted on the main backend.
|
||||
dockerApi = createApiInstance(
|
||||
getApiUrl("/plugin-api/docker/docker", 30001),
|
||||
"DOCKER",
|
||||
);
|
||||
|
||||
// Tmux Monitor API (port 30010) --- tmux-monitor ---
|
||||
tmuxMonitorApi = createApiInstance(
|
||||
getApiUrl("/tmux_monitor", 30010),
|
||||
@@ -803,9 +797,6 @@ export let dashboardApi: AxiosInstance;
|
||||
// RBAC API (port 30001)
|
||||
export let rbacApi: AxiosInstance;
|
||||
|
||||
// Docker Management API (docker plugin)
|
||||
export let dockerApi: AxiosInstance;
|
||||
|
||||
// Tmux Monitor API (port 30010) --- tmux-monitor ---
|
||||
export let tmuxMonitorApi: AxiosInstance;
|
||||
|
||||
|
||||
@@ -85,7 +85,10 @@ export * from "@/components/sheet";
|
||||
export { useConfirmation } from "@/hooks/use-confirmation";
|
||||
export { useAdaptivePolling } from "@/hooks/use-adaptive-polling";
|
||||
// Per-area display density and chart options the user picked in Appearance.
|
||||
export { useAreaPreferences } from "@/contexts/UiPreferencesContext";
|
||||
export {
|
||||
useAreaPreferences,
|
||||
useUiPreferencesContext,
|
||||
} from "@/contexts/UiPreferencesContext";
|
||||
// Homepage widget pieces, for plugins that register a widget.
|
||||
export { WidgetTitle } from "@/features/homepage/widgets/WidgetTitle";
|
||||
export { runVisibleInterval } from "@/features/homepage/use-visible-interval";
|
||||
|
||||
@@ -163,23 +163,13 @@ export function createHostEditorForm(
|
||||
host?.enableCommandHistory ?? d?.enableCommandHistory ?? true,
|
||||
enableFileManager: host?.enableFileManager ?? false,
|
||||
scpLegacy: host?.scpLegacy ?? false,
|
||||
enableDocker: host?.enableDocker ?? false,
|
||||
dockerConfig: host?.dockerConfig ?? { runtime: "docker" as const },
|
||||
enableTmuxMonitor: host?.enableTmuxMonitor ?? false,
|
||||
enableTerminalToolbar: host?.enableTerminalToolbar ?? true,
|
||||
enableAiAssistant: host?.enableAiAssistant ?? false,
|
||||
enableProxmox: (proxmoxSettings.enableProxmox as boolean) ?? false,
|
||||
// The proxmox tab fills in its own defaults when this is unset.
|
||||
proxmoxConfig:
|
||||
((proxmoxSettings.proxmoxConfig as Host["proxmoxConfig"]) ?? {
|
||||
defaultCredentialId: null,
|
||||
defaultAuthType: "password",
|
||||
windowsPatterns: "win, windows",
|
||||
dockerPatterns: "docker",
|
||||
preferredPrefixes: "10., 192.168.",
|
||||
autoSyncEnabled: false,
|
||||
syncIntervalMinutes: 15,
|
||||
markMissingGuests: true,
|
||||
}) as Host["proxmoxConfig"],
|
||||
(proxmoxSettings.proxmoxConfig as Host["proxmoxConfig"]) ?? null,
|
||||
enableProxmoxStats:
|
||||
(proxmoxSettings.enableProxmoxStats as boolean) ?? false,
|
||||
proxmoxStatsConfig:
|
||||
@@ -436,8 +426,6 @@ export function buildHostEditorPayload(
|
||||
enableCommandHistory: form.enableCommandHistory,
|
||||
enableFileManager: form.enableFileManager,
|
||||
scpLegacy: form.scpLegacy,
|
||||
enableDocker: form.enableDocker,
|
||||
dockerConfig: form.enableDocker ? form.dockerConfig : null,
|
||||
enableTmuxMonitor: form.enableTmuxMonitor,
|
||||
enableTerminalToolbar: form.enableTerminalToolbar,
|
||||
enableAiAssistant: form.enableAiAssistant,
|
||||
|
||||
@@ -95,8 +95,6 @@ export function sshHostToHost(h: SSHHostWithStatus): Host {
|
||||
enableCommandHistory: h.enableCommandHistory ?? true,
|
||||
enableTunnel: h.enableTunnel ?? false,
|
||||
enableFileManager: h.enableFileManager ?? true,
|
||||
enableDocker: h.enableDocker ?? false,
|
||||
dockerConfig: h.dockerConfig ?? null,
|
||||
enableWebUi: h.enableWebUi ?? false,
|
||||
enableProxmox: (proxmoxSettings.enableProxmox as boolean) ?? false,
|
||||
enableProxmoxStats:
|
||||
|
||||
@@ -152,8 +152,7 @@ function hostPassesFilters(host: Host, filters: FilterState): boolean {
|
||||
}
|
||||
if (filters.features.length > 0) {
|
||||
const ok =
|
||||
(filters.features.includes("fileManager") && host.enableFileManager) ||
|
||||
(filters.features.includes("docker") && host.enableDocker);
|
||||
filters.features.includes("fileManager") && host.enableFileManager;
|
||||
if (!ok) return false;
|
||||
}
|
||||
if (filters.tags.length > 0) {
|
||||
@@ -355,7 +354,6 @@ export function HostsPanel({
|
||||
enableTerminal: true,
|
||||
enableTunnel: false,
|
||||
enableFileManager: true,
|
||||
enableDocker: false,
|
||||
defaultPath: "/var/www",
|
||||
},
|
||||
{
|
||||
@@ -373,7 +371,6 @@ export function HostsPanel({
|
||||
enableTerminal: true,
|
||||
enableTunnel: true,
|
||||
enableFileManager: false,
|
||||
enableDocker: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -780,23 +777,20 @@ export function HostsPanel({
|
||||
<DropdownMenuLabel>
|
||||
{t("hosts.filterFeaturesGroup")}
|
||||
</DropdownMenuLabel>
|
||||
{(
|
||||
[
|
||||
["fileManager", "FileManager"],
|
||||
["docker", "Docker"],
|
||||
] as const
|
||||
).map(([val, key]) => (
|
||||
<DropdownMenuCheckboxItem
|
||||
key={val}
|
||||
checked={filterState.features.includes(val)}
|
||||
onCheckedChange={() =>
|
||||
handleFilterToggle("features", val)
|
||||
}
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
>
|
||||
{t(`hosts.filterFeature${key}`)}
|
||||
</DropdownMenuCheckboxItem>
|
||||
))}
|
||||
{([["fileManager", "FileManager"]] as const).map(
|
||||
([val, key]) => (
|
||||
<DropdownMenuCheckboxItem
|
||||
key={val}
|
||||
checked={filterState.features.includes(val)}
|
||||
onCheckedChange={() =>
|
||||
handleFilterToggle("features", val)
|
||||
}
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
>
|
||||
{t(`hosts.filterFeature${key}`)}
|
||||
</DropdownMenuCheckboxItem>
|
||||
),
|
||||
)}
|
||||
{allTags.length > 0 && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
@@ -44,7 +44,6 @@ export const FIELD_GROUP_KEYS: Record<FieldGroup, string[]> = {
|
||||
"enableTerminalToolbar",
|
||||
"enableAiAssistant",
|
||||
"enableFileManager",
|
||||
"enableDocker",
|
||||
"enableWebUi",
|
||||
"enableProxmox",
|
||||
"enableTmuxMonitor",
|
||||
@@ -59,7 +58,6 @@ export const FIELD_GROUP_KEYS: Record<FieldGroup, string[]> = {
|
||||
advanced: [
|
||||
"statusCheckEnabled",
|
||||
"statusCheckInterval",
|
||||
"dockerConfig",
|
||||
"webUiConfig",
|
||||
"proxmoxConfig",
|
||||
"terminalConfig",
|
||||
|
||||
@@ -34,7 +34,6 @@ export function createQuickConnectHost(input: QuickConnectInput): Host {
|
||||
enableCommandHistory: false,
|
||||
enableFileManager: false,
|
||||
enableTunnel: false,
|
||||
enableDocker: false,
|
||||
enableTerminalToolbar: false,
|
||||
enableAiAssistant: false,
|
||||
enableSsh: false,
|
||||
@@ -71,7 +70,6 @@ export function createQuickConnectHost(input: QuickConnectInput): Host {
|
||||
enableCommandHistory: true,
|
||||
enableFileManager: true,
|
||||
enableTunnel: true,
|
||||
enableDocker: true,
|
||||
enableProxmox: false,
|
||||
enableProxmoxStats: false,
|
||||
enableTmuxMonitor: false,
|
||||
@@ -102,7 +100,6 @@ export function quickConnectHostToPayload(host: Host): SSHHostData {
|
||||
enableCommandHistory: host.enableCommandHistory,
|
||||
enableFileManager: host.enableFileManager,
|
||||
enableTunnel: host.enableTunnel,
|
||||
enableDocker: host.enableDocker,
|
||||
enableProxmox: host.enableProxmox,
|
||||
enableTmuxMonitor: host.enableTmuxMonitor,
|
||||
enableTerminalToolbar: host.enableTerminalToolbar,
|
||||
|
||||
@@ -11,7 +11,6 @@ import { useTranslation } from "react-i18next";
|
||||
import { useVirtualizer } from "@tanstack/react-virtual";
|
||||
import { useAreaPreferences } from "@/contexts/UiPreferencesContext";
|
||||
import {
|
||||
Box,
|
||||
Boxes,
|
||||
ChevronDown,
|
||||
Download,
|
||||
@@ -612,7 +611,6 @@ export function SidebarTree({
|
||||
enableTerminal: host.enableTerminal,
|
||||
enableTunnel: host.enableTunnel,
|
||||
enableFileManager: host.enableFileManager,
|
||||
enableDocker: host.enableDocker,
|
||||
sshPort: host.sshPort,
|
||||
rdpUser: host.rdpUser ?? null,
|
||||
rdpPassword: host.rdpPassword ?? null,
|
||||
@@ -1173,18 +1171,6 @@ export function SidebarTree({
|
||||
value: false,
|
||||
icon: FolderSearch,
|
||||
},
|
||||
{
|
||||
labelKey: "hosts.enableDockerFeature",
|
||||
field: "enableDocker",
|
||||
value: true,
|
||||
icon: Box,
|
||||
},
|
||||
{
|
||||
labelKey: "hosts.disableDockerFeature",
|
||||
field: "enableDocker",
|
||||
value: false,
|
||||
icon: Box,
|
||||
},
|
||||
{
|
||||
labelKey: "hosts.enableProxmoxFeature",
|
||||
field: "enableProxmox",
|
||||
|
||||
@@ -49,7 +49,6 @@ function makeHost(overrides: Partial<Host>): Host {
|
||||
enableTunnel: false,
|
||||
serverTunnels: [],
|
||||
enableFileManager: true,
|
||||
enableDocker: false,
|
||||
enableProxmox: false,
|
||||
enableProxmoxStats: false,
|
||||
enableTmuxMonitor: false,
|
||||
|
||||
@@ -50,7 +50,6 @@ function sshHost(
|
||||
enableCommandHistory: false,
|
||||
enableTunnel: false,
|
||||
enableFileManager: false,
|
||||
enableDocker: false,
|
||||
enableTmuxMonitor: false,
|
||||
enableTerminalToolbar: true,
|
||||
enableAiAssistant: false,
|
||||
|
||||
@@ -28,7 +28,6 @@ function host(id: string, name: string): Host {
|
||||
enableTerminal: true,
|
||||
enableTunnel: false,
|
||||
enableFileManager: true,
|
||||
enableDocker: false,
|
||||
quickActions: [],
|
||||
} as Host;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,6 @@ const baseHost: Host = {
|
||||
enableCommandHistory: true,
|
||||
enableTunnel: true,
|
||||
enableFileManager: true,
|
||||
enableDocker: true,
|
||||
enableRdp: true,
|
||||
enableVnc: true,
|
||||
enableTelnet: true,
|
||||
|
||||
Reference in new issue
Block a user