mirror of
https://github.com/louislam/dockge.git
synced 2025-08-14 14:39:09 +02:00
Compare commits
8 Commits
fix-consol
...
master
Author | SHA1 | Date | |
---|---|---|---|
e31f766516 | |||
27bfe723d7 | |||
69818d665d | |||
bac498f97f | |||
3e37f38fc7 | |||
6dff52cc73 | |||
7fcc4c510c | |||
0ceb6336dd |
@ -106,7 +106,7 @@ docker compose pull && docker compose up -d
|
|||||||
## Motivations
|
## Motivations
|
||||||
|
|
||||||
- I have been using Portainer for some time, but for the stack management, I am sometimes not satisfied with it. For example, sometimes when I try to deploy a stack, the loading icon keeps spinning for a few minutes without progress. And sometimes error messages are not clear.
|
- I have been using Portainer for some time, but for the stack management, I am sometimes not satisfied with it. For example, sometimes when I try to deploy a stack, the loading icon keeps spinning for a few minutes without progress. And sometimes error messages are not clear.
|
||||||
- Try to develop with ES Module + TypeScript (Originally, I planned to use Deno or Bun.js, but they don't have support for arm64, so I stepped back to Node.js)
|
- Try to develop with ES Module + TypeScript
|
||||||
|
|
||||||
If you love this project, please consider giving it a ⭐.
|
If you love this project, please consider giving it a ⭐.
|
||||||
|
|
||||||
|
@ -38,6 +38,11 @@ export class TerminalSocketHandler extends AgentSocketHandler {
|
|||||||
try {
|
try {
|
||||||
checkLogin(socket);
|
checkLogin(socket);
|
||||||
|
|
||||||
|
// Throw an error if console is not enabled
|
||||||
|
if (!server.config.enableConsole) {
|
||||||
|
throw new ValidationError("Console is not enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Reset the name here, force one main terminal for now
|
// TODO: Reset the name here, force one main terminal for now
|
||||||
terminalName = "console";
|
terminalName = "console";
|
||||||
|
|
||||||
@ -66,6 +71,18 @@ export class TerminalSocketHandler extends AgentSocketHandler {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Check if MainTerminal is enabled
|
||||||
|
agentSocket.on("checkMainTerminal", async (callback) => {
|
||||||
|
try {
|
||||||
|
checkLogin(socket);
|
||||||
|
callbackResult({
|
||||||
|
ok: server.config.enableConsole,
|
||||||
|
}, callback);
|
||||||
|
} catch (e) {
|
||||||
|
callbackError(e, callback);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Interactive Terminal for containers
|
// Interactive Terminal for containers
|
||||||
agentSocket.on("interactiveTerminal", async (stackName : unknown, serviceName : unknown, shell : unknown, callback) => {
|
agentSocket.on("interactiveTerminal", async (stackName : unknown, serviceName : unknown, shell : unknown, callback) => {
|
||||||
try {
|
try {
|
||||||
|
@ -136,6 +136,11 @@ export class DockgeServer {
|
|||||||
stacksDir: {
|
stacksDir: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true,
|
optional: true,
|
||||||
|
},
|
||||||
|
enableConsole: {
|
||||||
|
type: Boolean,
|
||||||
|
optional: true,
|
||||||
|
defaultValue: false,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -149,6 +154,7 @@ export class DockgeServer {
|
|||||||
this.config.hostname = args.hostname || process.env.DOCKGE_HOSTNAME || undefined;
|
this.config.hostname = args.hostname || process.env.DOCKGE_HOSTNAME || undefined;
|
||||||
this.config.dataDir = args.dataDir || process.env.DOCKGE_DATA_DIR || "./data/";
|
this.config.dataDir = args.dataDir || process.env.DOCKGE_DATA_DIR || "./data/";
|
||||||
this.config.stacksDir = args.stacksDir || process.env.DOCKGE_STACKS_DIR || defaultStacksDir;
|
this.config.stacksDir = args.stacksDir || process.env.DOCKGE_STACKS_DIR || defaultStacksDir;
|
||||||
|
this.config.enableConsole = args.enableConsole || process.env.DOCKGE_ENABLE_CONSOLE === "true" || false;
|
||||||
this.stacksDir = this.config.stacksDir;
|
this.stacksDir = this.config.stacksDir;
|
||||||
|
|
||||||
log.debug("server", this.config);
|
log.debug("server", this.config);
|
||||||
|
@ -311,7 +311,12 @@ export class MainSocketHandler extends SocketHandler {
|
|||||||
throw new ValidationError("dockerRunCommand must be a string");
|
throw new ValidationError("dockerRunCommand must be a string");
|
||||||
}
|
}
|
||||||
|
|
||||||
const composeTemplate = composerize(dockerRunCommand);
|
// Option: 'latest' | 'v2x' | 'v3x'
|
||||||
|
let composeTemplate = composerize(dockerRunCommand, "", "latest");
|
||||||
|
|
||||||
|
// Remove the first line "name: <your project name>"
|
||||||
|
composeTemplate = composeTemplate.split("\n").slice(1).join("\n");
|
||||||
|
|
||||||
callback({
|
callback({
|
||||||
ok: true,
|
ok: true,
|
||||||
composeTemplate,
|
composeTemplate,
|
||||||
|
@ -4,7 +4,6 @@ import * as pty from "@homebridge/node-pty-prebuilt-multiarch";
|
|||||||
import { LimitQueue } from "./utils/limit-queue";
|
import { LimitQueue } from "./utils/limit-queue";
|
||||||
import { DockgeSocket } from "./util-server";
|
import { DockgeSocket } from "./util-server";
|
||||||
import {
|
import {
|
||||||
allowedCommandList, allowedRawKeys,
|
|
||||||
PROGRESS_TERMINAL_ROWS,
|
PROGRESS_TERMINAL_ROWS,
|
||||||
TERMINAL_COLS,
|
TERMINAL_COLS,
|
||||||
TERMINAL_ROWS
|
TERMINAL_ROWS
|
||||||
@ -16,7 +15,6 @@ import { log } from "./log";
|
|||||||
* Terminal for running commands, no user interaction
|
* Terminal for running commands, no user interaction
|
||||||
*/
|
*/
|
||||||
export class Terminal {
|
export class Terminal {
|
||||||
|
|
||||||
protected static terminalMap : Map<string, Terminal> = new Map();
|
protected static terminalMap : Map<string, Terminal> = new Map();
|
||||||
|
|
||||||
protected _ptyProcess? : pty.IPty;
|
protected _ptyProcess? : pty.IPty;
|
||||||
@ -272,6 +270,11 @@ export class MainTerminal extends InteractiveTerminal {
|
|||||||
constructor(server : DockgeServer, name : string) {
|
constructor(server : DockgeServer, name : string) {
|
||||||
let shell;
|
let shell;
|
||||||
|
|
||||||
|
// Throw an error if console is not enabled
|
||||||
|
if (!server.config.enableConsole) {
|
||||||
|
throw new Error("Console is not enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
if (os.platform() === "win32") {
|
if (os.platform() === "win32") {
|
||||||
if (commandExistsSync("pwsh.exe")) {
|
if (commandExistsSync("pwsh.exe")) {
|
||||||
shell = "pwsh.exe";
|
shell = "pwsh.exe";
|
||||||
@ -285,21 +288,6 @@ export class MainTerminal extends InteractiveTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public write(input : string) {
|
public write(input : string) {
|
||||||
// For like Ctrl + C
|
|
||||||
if (allowedRawKeys.includes(input)) {
|
|
||||||
super.write(input);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the command is allowed
|
|
||||||
const cmdParts = input.split(" ");
|
|
||||||
const executable = cmdParts[0].trim();
|
|
||||||
log.debug("console", "Executable: " + executable);
|
|
||||||
log.debug("console", "Executable length: " + executable.length);
|
|
||||||
|
|
||||||
if (!allowedCommandList.includes(executable)) {
|
|
||||||
throw new Error("Command not allowed.");
|
|
||||||
}
|
|
||||||
super.write(input);
|
super.write(input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ export interface Arguments {
|
|||||||
hostname? : string;
|
hostname? : string;
|
||||||
dataDir? : string;
|
dataDir? : string;
|
||||||
stacksDir? : string;
|
stacksDir? : string;
|
||||||
|
enableConsole? : boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some config values are required
|
// Some config values are required
|
||||||
|
@ -107,17 +107,6 @@ export const COMBINED_TERMINAL_ROWS = 20;
|
|||||||
|
|
||||||
export const ERROR_TYPE_VALIDATION = 1;
|
export const ERROR_TYPE_VALIDATION = 1;
|
||||||
|
|
||||||
export const allowedCommandList : string[] = [
|
|
||||||
"docker",
|
|
||||||
"ls",
|
|
||||||
"cd",
|
|
||||||
"dir",
|
|
||||||
];
|
|
||||||
|
|
||||||
export const allowedRawKeys = [
|
|
||||||
"\u0003", // Ctrl + C
|
|
||||||
];
|
|
||||||
|
|
||||||
export const acceptedComposeFileNames = [
|
export const acceptedComposeFileNames = [
|
||||||
"compose.yaml",
|
"compose.yaml",
|
||||||
"docker-compose.yaml",
|
"docker-compose.yaml",
|
||||||
|
@ -10,7 +10,7 @@ FROM louislam/dockge:base AS build
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --chown=node:node ./package.json ./package.json
|
COPY --chown=node:node ./package.json ./package.json
|
||||||
COPY --chown=node:node ./package-lock.json ./package-lock.json
|
COPY --chown=node:node ./package-lock.json ./package-lock.json
|
||||||
RUN npm ci
|
RUN npm ci --omit=dev
|
||||||
|
|
||||||
############################################
|
############################################
|
||||||
# ⭐ Main Image
|
# ⭐ Main Image
|
||||||
|
@ -201,7 +201,6 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.cursorPosition++;
|
this.cursorPosition++;
|
||||||
this.terminalInputBuffer += e.key;
|
this.terminalInputBuffer += e.key;
|
||||||
console.log(this.terminalInputBuffer);
|
|
||||||
this.terminal.write(e.key);
|
this.terminal.write(e.key);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -32,6 +32,7 @@ const languageList = {
|
|||||||
"hu": "Magyar",
|
"hu": "Magyar",
|
||||||
"ca": "Català",
|
"ca": "Català",
|
||||||
"ga": "Gaeilge",
|
"ga": "Gaeilge",
|
||||||
|
"de-CH": "Schwiizerdütsch",
|
||||||
};
|
};
|
||||||
|
|
||||||
let messages = {
|
let messages = {
|
||||||
|
132
frontend/src/lang/de-CH.json
Normal file
132
frontend/src/lang/de-CH.json
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"languageName": "Schwiizerdütsch",
|
||||||
|
"Create your admin account": "Erstell dis Admin-Konto",
|
||||||
|
"authIncorrectCreds": "Falsche Benutzername oder falsches Passwort.",
|
||||||
|
"PasswordsDoNotMatch": "Passwörter stimmed nöd überein.",
|
||||||
|
"Repeat Password": "Passwort wiederhole",
|
||||||
|
"Create": "Erstelle",
|
||||||
|
"signedInDisp": "Agmeldet als {0}",
|
||||||
|
"signedInDispDisabled": "Ameldig deaktiviert.",
|
||||||
|
"home": "Startsiite",
|
||||||
|
"console": "Konsole",
|
||||||
|
"registry": "Container Registry",
|
||||||
|
"compose": "Compose",
|
||||||
|
"addFirstStackMsg": "Stell din erste Stack zämme!",
|
||||||
|
"stackName": "Stack-Name",
|
||||||
|
"deployStack": "Deploye",
|
||||||
|
"deleteStack": "Lösche",
|
||||||
|
"stopStack": "Ahalte",
|
||||||
|
"restartStack": "Neustarte",
|
||||||
|
"updateStack": "Aktualisiere",
|
||||||
|
"startStack": "Starte",
|
||||||
|
"editStack": "Bearbeite",
|
||||||
|
"discardStack": "Verwerfe",
|
||||||
|
"saveStackDraft": "Speicher",
|
||||||
|
"notAvailableShort": "N/V",
|
||||||
|
"deleteStackMsg": "Wotsch de Stack würklich lösche?",
|
||||||
|
"stackNotManagedByDockgeMsg": "De Stack wird nöd vo Dockge verwaltet.",
|
||||||
|
"primaryHostname": "Primäre Hostname",
|
||||||
|
"general": "Allgemein",
|
||||||
|
"container": "Container",
|
||||||
|
"scanFolder": "Stacks-Ordner durchsueche",
|
||||||
|
"dockerImage": "Image",
|
||||||
|
"restartPolicyUnlessStopped": "Falls nöd gstoppt",
|
||||||
|
"restartPolicyAlways": "Immer",
|
||||||
|
"restartPolicyOnFailure": "Bimene Fehler",
|
||||||
|
"restartPolicyNo": "Kein Neustart",
|
||||||
|
"environmentVariable": "Umgebigsvariable",
|
||||||
|
"restartPolicy": "Neustart Richtlinie",
|
||||||
|
"containerName": "Container-Name",
|
||||||
|
"port": "Port / Ports",
|
||||||
|
"volume": "Volume / Volumes",
|
||||||
|
"network": "Netzwerk | Netzwerke",
|
||||||
|
"dependsOn": "Container-Abhängigkeit/e",
|
||||||
|
"addListItem": "{0} hinzuefüege",
|
||||||
|
"deleteContainer": "Lösche",
|
||||||
|
"addContainer": "Container hinzuefüege",
|
||||||
|
"addNetwork": "Netzwerk hinzuefüege",
|
||||||
|
"disableauth.message1": "Bisch der sicher, dass du d'<strong>Ameldung deaktiviere</strong> wotsch?",
|
||||||
|
"disableauth.message2": "Es isch für Szenarien vorgseh, <strong>in dene du beabsichtigsch, e Drittabüter-Authentifizierig</strong> vor Dockge z'implementiere, wie zum Bispiel Cloudflare Access, Authelia oder anderi Authentifizierigsmechanisme.",
|
||||||
|
"passwordNotMatchMsg": "s'wiederholte Passwort stimmt nöd überein.",
|
||||||
|
"autoGet": "Automatisch lade",
|
||||||
|
"add": "Hinzuefüege",
|
||||||
|
"Edit": "Bearbeite",
|
||||||
|
"applyToYAML": "Uf s'YAML awende",
|
||||||
|
"createExternalNetwork": "Erstelle",
|
||||||
|
"addInternalNetwork": "Hinzuefüege",
|
||||||
|
"Save": "Speichere",
|
||||||
|
"Language": "Sprach",
|
||||||
|
"Current User": "Aktuelle Benutzer",
|
||||||
|
"Change Password": "Passwort ändere",
|
||||||
|
"Current Password": "Aktuells Passwort",
|
||||||
|
"New Password": "Neus Passwort",
|
||||||
|
"Repeat New Password": "Neus Passwort wiederhole",
|
||||||
|
"Update Password": "Passwort aktualisiere",
|
||||||
|
"Advanced": "Erwiitert",
|
||||||
|
"Please use this option carefully!": "Bitte verwend die Option sorgfältig!",
|
||||||
|
"Enable Auth": "Ameldig aktiviere",
|
||||||
|
"Disable Auth": "Ameldig deaktiviere",
|
||||||
|
"I understand, please disable": "Ich verstah, bitte deaktiviere",
|
||||||
|
"Leave": "Verlah",
|
||||||
|
"Frontend Version": "Frontend Version",
|
||||||
|
"Check Update On GitHub": "Update uf GitHub überprüefe",
|
||||||
|
"Show update if available": "Update azeige, wenn verfüegbar",
|
||||||
|
"Also check beta release": "Au Beta-Version überprüefe",
|
||||||
|
"Remember me": "Agmeldet blibe",
|
||||||
|
"Login": "Amelde",
|
||||||
|
"Username": "Benutzername",
|
||||||
|
"Password": "Passwort",
|
||||||
|
"Settings": "Istellige",
|
||||||
|
"Logout": "Abmelde",
|
||||||
|
"Lowercase only": "Nur Chliibuechstabe",
|
||||||
|
"Convert to Compose": "In Compose-Syntax umwandle",
|
||||||
|
"Docker Run": "Docker Run",
|
||||||
|
"active": "aktiv",
|
||||||
|
"exited": "beendet",
|
||||||
|
"inactive": "inaktiv",
|
||||||
|
"Appearance": "Erschiinigsbild",
|
||||||
|
"Security": "Sicherheit",
|
||||||
|
"About": "Über",
|
||||||
|
"Allowed commands:": "Zueglasseni Befehl:",
|
||||||
|
"Internal Networks": "Interni Netzwerk",
|
||||||
|
"External Networks": "Externi Netzwerk",
|
||||||
|
"No External Networks": "Kei externi Netzwerk",
|
||||||
|
"Cannot connect to the socket server.": "Kei Verbindig zum Socket Server.",
|
||||||
|
"reverseProxyMsg1": "Wird en Reverse Proxy benutzt?",
|
||||||
|
"reconnecting...": "Erneute Verbindigsufbau…",
|
||||||
|
"downStack": "Stoppe & Deaktiviere",
|
||||||
|
"extra": "Extra",
|
||||||
|
"url": "URL / URLs",
|
||||||
|
"reverseProxyMsg2": "Lern wie er für WebSockets z'konfiguriere isch.",
|
||||||
|
"connecting...": "Verbindigsufbau zum Socket Server…",
|
||||||
|
"newUpdate": "Neues Update",
|
||||||
|
"dockgeAgent": "Dockge Agent | Dockge Agente",
|
||||||
|
"currentEndpoint": "Aktuell",
|
||||||
|
"dockgeURL": "Dockge URL (z. B. http://127.0.0.1:5001)",
|
||||||
|
"agentOnline": "Online",
|
||||||
|
"agentOffline": "Offline",
|
||||||
|
"connecting": "Verbinde",
|
||||||
|
"connect": "Verbinde",
|
||||||
|
"addAgent": "Agent Hinzuefüege",
|
||||||
|
"agentAddedSuccessfully": "Agent erfolgriich hinzuegfüegt.",
|
||||||
|
"agentRemovedSuccessfully": "Agent erfolgriich entfernt.",
|
||||||
|
"removeAgent": "Agent Entferne",
|
||||||
|
"removeAgentMsg": "Bisch der sicher, dass du de Agent entferne wotsch?",
|
||||||
|
"LongSyntaxNotSupported": "Lange Syntax wird nöd unterstützt. Bitte verwend de YAML-Editor.",
|
||||||
|
"Lost connection to the socket server. Reconnecting...": "Verbindig zum Socket Server verlore. Verbinde...",
|
||||||
|
"Saved": "Gspeicheret",
|
||||||
|
"Deleted": "Glöscht",
|
||||||
|
"Started": "Gstartet",
|
||||||
|
"Stopped": "Gstoppt",
|
||||||
|
"Restarted": "Neugstartet",
|
||||||
|
"New Container Name...": "Neue Container Name...",
|
||||||
|
"Network name...": "Netzwerkname...",
|
||||||
|
"Select a network...": "Netzwerk uswähle...",
|
||||||
|
"Updated": "Aktualisiert",
|
||||||
|
"Deployed": "Deployed",
|
||||||
|
"Switch to sh": "Zu sh wechsle",
|
||||||
|
"terminal": "Terminal",
|
||||||
|
"CurrentHostname": "(nöd gsetzt: verwendet aktuelli Hostname)",
|
||||||
|
"Downed": "Abegfahre",
|
||||||
|
"NoNetworksAvailable": "Kei Netzwerk verfüegbar. Du muesch zersch interni Netzwerk hinzuefüege oder externi Netzwerk uf de rechte Siite aktiviere."
|
||||||
|
}
|
@ -25,6 +25,7 @@
|
|||||||
"saveStackDraft": "Save",
|
"saveStackDraft": "Save",
|
||||||
"notAvailableShort": "N/A",
|
"notAvailableShort": "N/A",
|
||||||
"deleteStackMsg": "Are you sure you want to delete this stack?",
|
"deleteStackMsg": "Are you sure you want to delete this stack?",
|
||||||
|
"cancel": "Cancel",
|
||||||
"stackNotManagedByDockgeMsg": "This stack is not managed by Dockge.",
|
"stackNotManagedByDockgeMsg": "This stack is not managed by Dockge.",
|
||||||
"primaryHostname": "Primary Hostname",
|
"primaryHostname": "Primary Hostname",
|
||||||
"general": "General",
|
"general": "General",
|
||||||
@ -128,5 +129,10 @@
|
|||||||
"New Container Name...": "New Container Name...",
|
"New Container Name...": "New Container Name...",
|
||||||
"Network name...": "Network name...",
|
"Network name...": "Network name...",
|
||||||
"Select a network...": "Select a network...",
|
"Select a network...": "Select a network...",
|
||||||
"NoNetworksAvailable": "No networks available. You need to add internal networks or enable external networks in the right side first."
|
"NoNetworksAvailable": "No networks available. You need to add internal networks or enable external networks in the right side first.",
|
||||||
|
"Console is not enabled": "Console is not enabled",
|
||||||
|
"ConsoleNotEnabledMSG1": "Console is a powerful tool that allows you to execute any commands such as <code>docker</code>, <code>rm</code> within the Dockge's container in this Web UI.",
|
||||||
|
"ConsoleNotEnabledMSG2": "It might be dangerous since this Dockge container is connecting to the host's Docker daemon. Also Dockge could be possibly taken down by commands like <code>rm -rf</code>" ,
|
||||||
|
"ConsoleNotEnabledMSG3": "If you understand the risk, you can enable it by setting <code>DOCKGE_ENABLE_CONSOLE=true</code> in the environment variables.",
|
||||||
|
"confirmLeaveStack": "You are currently editing a stack. Are you sure you want to leave?"
|
||||||
}
|
}
|
||||||
|
@ -279,7 +279,6 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.on("agentList", (res) => {
|
socket.on("agentList", (res) => {
|
||||||
console.log(res);
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
this.agentList = res.agentList;
|
this.agentList = res.agentList;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="slide-fade" appear>
|
<transition name="slide-fade" appear>
|
||||||
<div>
|
<div>
|
||||||
<h1 v-if="isAdd" class="mb-3">{{$t("compose")}}</h1>
|
<h1 v-if="isAdd" class="mb-3">{{ $t("compose") }}</h1>
|
||||||
<h1 v-else class="mb-3">
|
<h1 v-else class="mb-3">
|
||||||
<Uptime :stack="globalStack" :pill="true" /> {{ stack.name }}
|
<Uptime :stack="globalStack" :pill="true" /> {{ stack.name }}
|
||||||
<span v-if="$root.agentCount > 1" class="agent-name">
|
<span v-if="$root.agentCount > 1" class="agent-name">
|
||||||
@ -150,7 +150,7 @@
|
|||||||
|
|
||||||
<!-- Combined Terminal Output -->
|
<!-- Combined Terminal Output -->
|
||||||
<div v-show="!isEditMode">
|
<div v-show="!isEditMode">
|
||||||
<h4 class="mb-3">{{$t("terminal")}}</h4>
|
<h4 class="mb-3">{{ $t("terminal") }}</h4>
|
||||||
<Terminal
|
<Terminal
|
||||||
ref="combinedTerminal"
|
ref="combinedTerminal"
|
||||||
class="mb-3 terminal"
|
class="mb-3 terminal"
|
||||||
@ -229,7 +229,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Delete Dialog -->
|
<!-- Delete Dialog -->
|
||||||
<BModal v-model="showDeleteDialog" :okTitle="$t('deleteStack')" okVariant="danger" @ok="deleteDialog">
|
<BModal v-model="showDeleteDialog" :cancelTitle="$t('cancel')" :okTitle="$t('deleteStack')" okVariant="danger" @ok="deleteDialog">
|
||||||
{{ $t("deleteStackMsg") }}
|
{{ $t("deleteStackMsg") }}
|
||||||
</BModal>
|
</BModal>
|
||||||
</div>
|
</div>
|
||||||
@ -491,6 +491,11 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
requestServiceStatus() {
|
requestServiceStatus() {
|
||||||
|
// Do not request if it is add mode
|
||||||
|
if (this.isAdd) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.$root.emitAgent(this.endpoint, "serviceStatusList", this.stack.name, (res) => {
|
this.$root.emitAgent(this.endpoint, "serviceStatusList", this.stack.name, (res) => {
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
this.serviceStatusList = res.serviceStatusList;
|
this.serviceStatusList = res.serviceStatusList;
|
||||||
@ -503,7 +508,7 @@ export default {
|
|||||||
|
|
||||||
exitConfirm(next) {
|
exitConfirm(next) {
|
||||||
if (this.isEditMode) {
|
if (this.isEditMode) {
|
||||||
if (confirm("You are currently editing a stack. Are you sure you want to leave?")) {
|
if (confirm(this.$t("confirmLeaveStack"))) {
|
||||||
this.exitAction();
|
this.exitAction();
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,35 +1,28 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="slide-fade" appear>
|
<transition name="slide-fade" appear>
|
||||||
<div>
|
<div v-if="!processing">
|
||||||
<h1 class="mb-3">Console</h1>
|
<h1 class="mb-3">{{ $t("console") }}</h1>
|
||||||
|
|
||||||
<div>
|
<Terminal v-if="enableConsole" class="terminal" :rows="20" mode="mainTerminal" name="console" :endpoint="endpoint"></Terminal>
|
||||||
<p>
|
|
||||||
{{ $t("Allowed commands:") }}
|
|
||||||
<template v-for="(command, index) in allowedCommandList" :key="command">
|
|
||||||
<code>{{ command }}</code>
|
|
||||||
|
|
||||||
<!-- No comma at the end -->
|
<div v-else class="alert alert-warning shadow-box" role="alert">
|
||||||
<span v-if="index !== allowedCommandList.length - 1">, </span>
|
<h4 class="alert-heading">{{ $t("Console is not enabled") }}</h4>
|
||||||
</template>
|
<p v-html="$t('ConsoleNotEnabledMSG1')"></p>
|
||||||
</p>
|
<p v-html="$t('ConsoleNotEnabledMSG2')"></p>
|
||||||
|
<p v-html="$t('ConsoleNotEnabledMSG3')"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Terminal class="terminal" :rows="20" mode="mainTerminal" name="console" :endpoint="endpoint"></Terminal>
|
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import { allowedCommandList } from "../../../common/util-common";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
allowedCommandList,
|
processing: true,
|
||||||
|
enableConsole: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -38,10 +31,13 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.$root.emitAgent(this.endpoint, "checkMainTerminal", (res) => {
|
||||||
|
this.enableConsole = res.ok;
|
||||||
|
this.processing = false;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
12
package-lock.json
generated
12
package-lock.json
generated
@ -53,7 +53,7 @@
|
|||||||
"@types/semver": "^7.7.0",
|
"@types/semver": "^7.7.0",
|
||||||
"@typescript-eslint/eslint-plugin": "~6.8.0",
|
"@typescript-eslint/eslint-plugin": "~6.8.0",
|
||||||
"@typescript-eslint/parser": "~6.8.0",
|
"@typescript-eslint/parser": "~6.8.0",
|
||||||
"@vitejs/plugin-vue": "~4.5.2",
|
"@vitejs/plugin-vue": "~5.2.3",
|
||||||
"@xterm/addon-fit": "beta",
|
"@xterm/addon-fit": "beta",
|
||||||
"@xterm/xterm": "beta",
|
"@xterm/xterm": "beta",
|
||||||
"bootstrap": "5.3.2",
|
"bootstrap": "5.3.2",
|
||||||
@ -2153,16 +2153,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitejs/plugin-vue": {
|
"node_modules/@vitejs/plugin-vue": {
|
||||||
"version": "4.5.2",
|
"version": "5.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.3.tgz",
|
||||||
"integrity": "sha512-UGR3DlzLi/SaVBPX0cnSyE37vqxU3O6chn8l0HJNzQzDia6/Au2A4xKv+iIJW8w2daf80G7TYHhi1pAUjdZ0bQ==",
|
"integrity": "sha512-IYSLEQj4LgZZuoVpdSUCw3dIynTWQgPlaRP6iAvMle4My0HdYwr5g5wQAfwOeHQBmYwEkqF70nRpSilr6PoUDg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.18.0 || >=16.0.0"
|
"node": "^18.0.0 || >=20.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"vite": "^4.0.0 || ^5.0.0",
|
"vite": "^5.0.0 || ^6.0.0",
|
||||||
"vue": "^3.2.25"
|
"vue": "^3.2.25"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dockge",
|
"name": "dockge",
|
||||||
"version": "1.4.2",
|
"version": "1.5.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 22.14.0"
|
"node": ">= 22.14.0"
|
||||||
@ -72,7 +72,7 @@
|
|||||||
"@types/semver": "^7.7.0",
|
"@types/semver": "^7.7.0",
|
||||||
"@typescript-eslint/eslint-plugin": "~6.8.0",
|
"@typescript-eslint/eslint-plugin": "~6.8.0",
|
||||||
"@typescript-eslint/parser": "~6.8.0",
|
"@typescript-eslint/parser": "~6.8.0",
|
||||||
"@vitejs/plugin-vue": "~4.5.2",
|
"@vitejs/plugin-vue": "~5.2.3",
|
||||||
"@xterm/addon-fit": "beta",
|
"@xterm/addon-fit": "beta",
|
||||||
"@xterm/xterm": "beta",
|
"@xterm/xterm": "beta",
|
||||||
"bootstrap": "5.3.2",
|
"bootstrap": "5.3.2",
|
||||||
|
Reference in New Issue
Block a user