Merge branch 'louislam:master' into master

This commit is contained in:
AICHIGUA 2023-11-25 09:23:45 +08:00 committed by GitHub
commit 66d569a4f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 1826 additions and 81 deletions

View file

@ -0,0 +1,72 @@
title: "❓ Ask for help"
labels: [help]
body:
- type: checkboxes
id: no-duplicate-issues
attributes:
label: "⚠️ Please verify that this bug has NOT been raised before."
description: "Search in the issues sections by clicking [HERE](https://github.com/louislam/dockge/discussions/categories/ask-for-help)"
options:
- label: "I checked and didn't find similar issue"
required: true
- type: checkboxes
attributes:
label: "🛡️ Security Policy"
description: Please review the security policy before reporting security related issues/bugs.
options:
- label: I agree to have read this project [Security Policy](https://github.com/louislam/dockge/security/policy)
required: true
- type: textarea
id: steps-to-reproduce
validations:
required: true
attributes:
label: "📝 Describe your problem"
description: "Please walk us through it step by step."
placeholder: "Describe what are you asking for..."
- type: textarea
id: error-msg
validations:
required: false
attributes:
label: "📝 Error Message(s) or Log"
- type: input
id: dockge-version
attributes:
label: "🐻 Dockge Version"
description: "Which version of Dockge are you running? Please do NOT provide the docker tag such as latest or 1"
placeholder: "Ex. 1.10.0"
validations:
required: true
- type: input
id: operating-system
attributes:
label: "💻 Operating System and Arch"
description: "Which OS is your server/device running on? (For Replit, please do not report this bug)"
placeholder: "Ex. Ubuntu 20.04 x86"
validations:
required: true
- type: input
id: browser-vendor
attributes:
label: "🌐 Browser"
description: "Which browser are you running on? (For Replit, please do not report this bug)"
placeholder: "Ex. Google Chrome 95.0.4638.69"
validations:
required: true
- type: input
id: docker-version
attributes:
label: "🐋 Docker Version"
description: "If running with Docker, which version are you running?"
placeholder: "Ex. Docker 20.10.9 / K8S / Podman"
validations:
required: false
- type: input
id: nodejs-version
attributes:
label: "🟩 NodeJS Version"
description: "If running with Node.js? which version are you running?"
placeholder: "Ex. 14.18.0"
validations:
required: false

View file

@ -0,0 +1,55 @@
title: 🚀 Feature Request
labels: [feature-request]
body:
- type: checkboxes
id: no-duplicate-issues
attributes:
label: "⚠️ Please verify that this feature request has NOT been suggested before."
description: "Search in the issues sections by clicking [HERE](https://github.com/louislam/dockge/discussions/categories/feature-request)"
options:
- label: "I checked and didn't find similar feature request"
required: true
- type: dropdown
id: feature-area
attributes:
label: "🏷️ Feature Request Type"
description: "What kind of feature request is this?"
multiple: true
options:
- API
- UI Feature
- Other
validations:
required: true
- type: textarea
id: feature-description
validations:
required: true
attributes:
label: "🔖 Feature description"
description: "A clear and concise description of what the feature request is."
placeholder: "You should add ..."
- type: textarea
id: solution
validations:
required: true
attributes:
label: "✔️ Solution"
description: "A clear and concise description of what you want to happen."
placeholder: "In my use-case, ..."
- type: textarea
id: alternatives
validations:
required: false
attributes:
label: "❓ Alternatives"
description: "A clear and concise description of any alternative solutions or features you've considered."
placeholder: "I have considered ..."
- type: textarea
id: additional-context
validations:
required: false
attributes:
label: "📝 Additional Context"
description: "Add any other context or screenshots about the feature request here."
placeholder: "..."

View file

@ -0,0 +1,14 @@
name: "❓ Ask for help"
description: "Please go to the Discussions tab to submit a Help Request"
body:
- type: markdown
attributes:
value: |
Please go to https://github.com/louislam/dockge/discussions/new?category=ask-for-help
- type: checkboxes
id: no-duplicate-issues
attributes:
label: "Issues are for bug reports only"
options:
- label: "I understand"
required: true

99
.github/ISSUE_TEMPLATE/bug_report.yaml vendored Normal file
View file

@ -0,0 +1,99 @@
name: "🐛 Bug Report"
description: "Submit a bug report to help us improve"
#title: "[Bug] "
labels: [bug]
body:
- type: checkboxes
id: no-duplicate-issues
attributes:
label: "⚠️ Please verify that this bug has NOT been reported before."
description: "Search in the issues sections by clicking [HERE](https://github.com/louislam/dockge/issues?q=)"
options:
- label: "I checked and didn't find similar issue"
required: true
- type: checkboxes
attributes:
label: "🛡️ Security Policy"
description: Please review the security policy before reporting security related issues/bugs.
options:
- label: I agree to have read this project [Security Policy](https://github.com/louislam/dockge/security/policy)
required: true
- type: textarea
id: description
validations:
required: false
attributes:
label: "Description"
description: "You could also upload screenshots"
- type: textarea
id: steps-to-reproduce
validations:
required: true
attributes:
label: "👟 Reproduction steps"
description: "How do you trigger this bug? Please walk us through it step by step."
placeholder: "..."
- type: textarea
id: expected-behavior
validations:
required: true
attributes:
label: "👀 Expected behavior"
description: "What did you think would happen?"
placeholder: "..."
- type: textarea
id: actual-behavior
validations:
required: true
attributes:
label: "😓 Actual Behavior"
description: "What actually happen?"
placeholder: "..."
- type: input
id: dockge-version
attributes:
label: "Dockge Version"
description: "Which version of Dockge are you running? Please do NOT provide the docker tag such as latest or 1"
placeholder: "Ex. 1.1.1"
validations:
required: true
- type: input
id: operating-system
attributes:
label: "💻 Operating System and Arch"
description: "Which OS is your server/device running on?"
placeholder: "Ex. Ubuntu 20.04 x64 "
validations:
required: true
- type: input
id: browser-vendor
attributes:
label: "🌐 Browser"
description: "Which browser are you running on?"
placeholder: "Ex. Google Chrome 95.0.4638.69"
validations:
required: true
- type: input
id: docker-version
attributes:
label: "🐋 Docker Version"
description: "If running with Docker, which version are you running?"
placeholder: "Ex. Docker 20.10.9 / K8S / Podman"
validations:
required: false
- type: input
id: nodejs-version
attributes:
label: "🟩 NodeJS Version"
description: "If running with Node.js? which version are you running?"
placeholder: "Ex. 14.18.0"
validations:
required: false
- type: textarea
id: logs
attributes:
label: "📝 Relevant log output"
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
validations:
required: false

View file

@ -0,0 +1,14 @@
name: 🚀 Feature Request
description: "Please go to the Discussions tab to submit a Feature Request"
body:
- type: markdown
attributes:
value: |
Please go to https://github.com/louislam/dockge/discussions/new?category=feature-request
- type: checkboxes
id: no-duplicate-issues
attributes:
label: "Issues are for bug reports only"
options:
- label: "I understand"
required: true

19
.github/ISSUE_TEMPLATE/security.md vendored Normal file
View file

@ -0,0 +1,19 @@
---
name: "Security Issue"
about: "Just for alerting @louislam, do not provide any details here"
title: "Security Issue"
ref: "main"
labels:
- security
---
DO NOT PROVIDE ANY DETAILS HERE. Please privately report to https://github.com/louislam/dockge/security/advisories/new.
Why need this issue? It is because GitHub Advisory do not send a notification to @louislam, it is a workaround to do so.
Your GitHub Advisory URL:

34
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,34 @@
⚠️⚠️⚠️ Since we do not accept all types of pull requests and do not want to waste your time. Please be sure that you have read pull request rules:
https://github.com/louislam/dockge/blob/master/CONTRIBUTING.md
Tick the checkbox if you understand [x]:
- [ ] I have read and understand the pull request rules.
# Description
Fixes #(issue)
## Type of change
Please delete any options that are not relevant.
- Bug fix (non-breaking change which fixes an issue)
- User interface (UI)
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing functionality to not work as expected)
- Other
- This change requires a documentation update
## Checklist
- [ ] My code follows the style guidelines of this project
- [ ] I ran ESLint and other linters for modified files
- [ ] I have performed a self-review of my own code and tested it
- [ ] I have commented my code, particularly in hard-to-understand areas
(including JSDoc for methods)
- [ ] My changes generate no new warnings
- [ ] My code needed automated testing. I have added them (this is optional task)
## Screenshots (if any)
Please do not use any external image service. Instead, just paste in or drag and drop the image here, and it will be uploaded automatically.

1
.github/config/exclude.txt vendored Normal file
View file

@ -0,0 +1 @@
# This is a .gitignore style file for 'GrantBirki/json-yaml-validate' Action workflow

View file

@ -56,5 +56,8 @@ jobs:
- name: Check Typescript
run: pnpm run check-ts
- name: Build
run: pnpm run build:frontend
# more things can be add later like tests etc..

View file

@ -0,0 +1,42 @@
name: Close Incorrect Issue
on:
issues:
types: [opened]
jobs:
close-incorrect-issue:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
node-version: [16]
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
name: Install pnpm
with:
version: 8
run_install: false
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install
- name: Close Incorrect Issue
run: node extra/close-incorrect-issue.js ${{ secrets.GITHUB_TOKEN }} ${{ github.event.issue.number }} ${{ github.event.issue.user.login }}

View file

@ -0,0 +1,27 @@
name: json-yaml-validate
on:
push:
branches:
- master
pull_request:
branches:
- master
- 2.0.X
workflow_dispatch:
permissions:
contents: read
pull-requests: write # enable write permissions for pull request comments
jobs:
json-yaml-validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: json-yaml-validate
id: json-yaml-validate
uses: GrantBirki/json-yaml-validate@v1.3.0
with:
comment: "false" # enable comment mode
exclude_file: ".github/config/exclude.txt" # gitignore style file for exclusions

139
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,139 @@
## Can I create a pull request for Dockge?
Yes or no, it depends on what you will try to do. Since I don't want to waste your time, be sure to **create open a discussion, so we can have a discussion first**. Especially for a large pull request or you don't know if it will be merged or not.
Here are some references:
### ✅ Usually accepted:
- Bug fix
- Security fix
- Translation
### ⚠️ Discussion required:
- Large pull requests
- New features
### ❌ Won't be merged:
- Do not pass the auto-test
- Any breaking changes
- Duplicated pull requests
- Buggy
- UI/UX is not close to Dockge
- Modifications or deletions of existing logic without a valid reason.
- Adding functions that is completely out of scope
- Converting existing code into other programming languages
- Unnecessarily large code changes that are hard to review and cause conflicts with other PRs.
The above cases may not cover all possible situations.
I (@louislam) have the final say. If your pull request does not meet my expectations, I will reject it, no matter how much time you spend on it. Therefore, it is essential to have a discussion beforehand.
I will assign your pull request to a [milestone](https://github.com/louislam/dockge/milestones), if I plan to review and merge it.
Also, please don't rush or ask for an ETA, because I have to understand the pull request, make sure it is no breaking changes and stick to my vision of this project, especially for large pull requests.
## Project Styles
I personally do not like something that requires so many configurations before you can finally start the app.
- Settings should be configurable in the frontend. Environment variables are discouraged, unless it is related to startup such as `DOCKGE_STACKS_DIR`
- Easy to use
- The web UI styling should be consistent and nice
- No native build dependency
## Coding Styles
- 4 spaces indentation
- Follow `.editorconfig`
- Follow ESLint
- Methods and functions should be documented with JSDoc
## Name Conventions
- Javascript/Typescript: camelCaseType
- SQLite: snake_case (Underscore)
- CSS/SCSS: kebab-case (Dash)
## Tools
- [`Node.js`](https://nodejs.org/) >= 20
- [`pnpm`](https://pnpm.io/)
- [`git`](https://git-scm.com/)
- IDE that supports [`ESLint`](https://eslint.org/) and EditorConfig (I am using [`IntelliJ IDEA`](https://www.jetbrains.com/idea/))
- A SQLite GUI tool (f.ex. [`SQLite Expert Personal`](https://www.sqliteexpert.com/download.html) or [`DBeaver Community`](https://dbeaver.io/download/))
## Install Dependencies for Development
```bash
pnpm install
```
## Dev Server
```
pnpm run dev:frontend
pnpm run dev:backend
```
## Backend Dev Server
It binds to `0.0.0.0:5001` by default.
It is mainly a socket.io app + express.js.
## Frontend Dev Server
It binds to `0.0.0.0:5000` by default. The frontend dev server is used for development only.
For production, it is not used. It will be compiled to `frontend-dist` directory instead.
You can use Vue.js devtools Chrome extension for debugging.
### Build the frontend
```bash
pnpm run build
```
## Database Migration
TODO
## Dependencies
Both frontend and backend share the same package.json. However, the frontend dependencies are eventually not used in the production environment, because it is usually also baked into dist files. So:
- Frontend dependencies = "devDependencies"
- Examples: vue, chart.js
- Backend dependencies = "dependencies"
- Examples: socket.io, sqlite3
- Development dependencies = "devDependencies"
- Examples: eslint, sass
### Update Dependencies
Should only be done by the maintainer.
```bash
pnpm update
````
It should update the patch release version only.
Patch release = the third digit ([Semantic Versioning](https://semver.org/))
If for security / bug / other reasons, a library must be updated, breaking changes need to be checked by the person proposing the change.
## Translations
Please add **all** the strings which are translatable to `src/lang/en.json` (If translation keys are omitted, they can not be translated).
**Don't include any other languages in your initial Pull-Request** (even if this is your mother tongue), to avoid merge-conflicts between weblate and `master`.
The translations can then (after merging a PR into `master`) be translated by awesome people donating their language skills.
If you want to help by translating Uptime Kuma into your language, please visit the [instructions on how to translate using weblate](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md).
## Spelling & Grammar
Feel free to correct the grammar in the documentation or code.
My mother language is not English and my grammar is not that great.

View file

@ -6,7 +6,7 @@
A fancy, easy-to-use and reactive self-hosted docker compose.yaml stack-oriented manager.
![GitHub Repo stars](https://img.shields.io/github/stars/louislam/dockge?logo=github) ![GitHub issues](https://img.shields.io/github/issues/louislam/dockge?logo=github) ![GitHub pull requests](https://img.shields.io/github/issues-pr/louislam/dockge?logo=github) ![Docker Pulls](https://img.shields.io/docker/pulls/louislam/dockge?logo=docker) ![Docker Image Version (latest semver)](https://img.shields.io/docker/v/louislam/dockge?logo=docker) ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/louislam/dockge/master?logo=github) ![GitHub](https://img.shields.io/github/license/louislam/dockge?logo=github)
![GitHub Repo stars](https://img.shields.io/github/stars/louislam/dockge?logo=github) ![GitHub issues](https://img.shields.io/github/issues/louislam/dockge?logo=github) ![GitHub pull requests](https://img.shields.io/github/issues-pr/louislam/dockge?logo=github) ![Docker Pulls](https://img.shields.io/docker/pulls/louislam/dockge?logo=docker) ![Docker Image Version (latest semver)](https://img.shields.io/docker/v/louislam/dockge/latest?label=docker%20image%20ver.) ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/louislam/dockge/master?logo=github) ![GitHub](https://img.shields.io/github/license/louislam/dockge?logo=github)
<img src="https://github.com/louislam/dockge/assets/1336778/26a583e1-ecb1-4a8d-aedf-76157d714ad7" width="900" alt="" />
@ -25,7 +25,7 @@ View Video: https://youtu.be/AWAlOQeNpgU?t=48
- If you love Uptime Kuma's UI/UX, you will love this one too
- Convert `docker run ...` commands into `compose.yaml`
- File based structure
- Dockge won't kidnap your compose files, they are stored on your drive as usual. You can interact with them using normal `docker compose` commands
- Dockge won't kidnap your compose files, they are stored on your drive as usual. You can interact with them using normal `docker compose` commands
<img src="https://github.com/louislam/dockge/assets/1336778/cc071864-592e-4909-b73a-343a57494002" width=300 />
@ -37,7 +37,7 @@ Requirements:
- [Docker CE](https://docs.docker.com/engine/install/) 20+ is recommended / Podman
- (Docker only) [Docker Compose Plugin](https://docs.docker.com/compose/install/linux/)
- (Podman only) podman-docker (Debian: `apt install podman-docker`)
- OS:
- OS:
- As long as you can run Docker CE / Podman, it should be fine, but:
- Debian/Raspbian Buster or lower is not supported, please upgrade to Bullseye or higher
- Arch: armv7, arm64, amd64 (a.k.a x86_64)
@ -59,7 +59,7 @@ curl https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml --out
docker compose up -d
# If you are using docker-compose V1 or Podman
# docker-compose up -d
# docker-compose up -d
```
Dockge is now running on http://localhost:5001
@ -75,7 +75,7 @@ services:
image: louislam/dockge:1
restart: unless-stopped
ports:
# Host Port:Container Port
# Host Port : Container Port
- 5001:5001
volumes:
- /var/run/docker.sock:/var/run/docker.sock
@ -86,8 +86,8 @@ services:
# Your stacks directory in the host (The paths inside container must be the same as the host)
# ⚠️⚠️ If you did it wrong, your data could end up be written into a wrong path.
# ✔️✔️✔️✔️ CORRECT EXAMPLE: - /my-stacks:/my-stacks (Both paths match)
# ❌❌❌❌ WRONG EXAMPLE: - /docker:/my-stacks (Both paths do not match)
# ✔️✔️✔️✔️ CORRECT: - /my-stacks:/my-stacks (Both paths match)
# ❌❌❌❌ WRONG: - /docker:/my-stacks (Both paths do not match)
- /opt/stacks:/opt/stacks
environment:
# Tell Dockge where is your stacks directory
@ -130,6 +130,10 @@ https://github.com/louislam/dockge/issues
### Ask for Help / Discussions
https://github.com/louislam/dockge/discussions
## Translation
If you want to translate Dockge into your language, please read [Translation Guide](https://github.com/louislam/dockge/blob/master/frontend/src/lang/README.md)
## FAQ
#### "Dockge"?

12
SECURITY.md Normal file
View file

@ -0,0 +1,12 @@
# Security Policy
## Reporting a Vulnerability
1. Please report security issues to https://github.com/louislam/dockge/security/advisories/new.
1. Please also create an empty security issue to alert me, as GitHub Advisories do not send a notification, I probably will miss it without this. https://github.com/louislam/dockge/issues/new?assignees=&labels=help&template=security.md
Do not use the public issue tracker or discuss it in public as it will cause more damage.
## Do you accept other 3rd-party bug bounty platforms?
At this moment, I DO NOT accept other bug bounty platforms, because I am not familiar with these platforms and someone has tried to send a phishing link to me by doing this already. To minimize my own risk, please report through GitHub Advisories only. I will ignore all 3rd-party bug bounty platforms emails.

View file

@ -30,6 +30,7 @@ import { Cron } from "croner";
import gracefulShutdown from "http-graceful-shutdown";
import User from "./models/user";
import childProcess from "child_process";
import { Terminal } from "./terminal";
export class DockgeServer {
app : Express;
@ -230,6 +231,11 @@ export class DockgeServer {
});
if (isDev) {
setInterval(() => {
log.debug("terminal", "Terminal count: " + Terminal.getTerminalCount());
}, 5000);
}
}
async afterLogin(socket : DockgeSocket, user : User) {
@ -285,18 +291,18 @@ export class DockgeServer {
}
// Listen
this.httpServer.listen(5001, this.config.hostname, () => {
this.httpServer.listen(this.config.port, this.config.hostname, () => {
if (this.config.hostname) {
log.info( "server", `Listening on ${this.config.hostname}:${this.config.port}`);
} else {
log.info("server", `Listening on ${this.config.port}`);
}
// Run every 5 seconds
Cron("*/2 * * * * *", {
// Run every 10 seconds
Cron("*/10 * * * * *", {
protect: true, // Enabled over-run protection.
}, () => {
log.debug("server", "Cron job running");
//log.debug("server", "Cron job running");
this.sendStackList(true);
});

View file

@ -103,6 +103,10 @@ class Logger {
* @param level Log level. One of INFO, WARN, ERROR, DEBUG or can be customized.
*/
log(module: string, msg: unknown, level: string) {
if (level === "DEBUG" && !isDev) {
return;
}
if (this.hideLog[level] && this.hideLog[level].includes(module.toLowerCase())) {
return;
}

View file

@ -75,7 +75,9 @@ export class DockerSocketHandler extends SocketHandler {
const stack = Stack.getStack(server, stackName);
stack.joinCombinedTerminal(socket);
if (stack.isManagedByDockge) {
stack.joinCombinedTerminal(socket);
}
callback({
ok: true,
@ -187,6 +189,27 @@ export class DockerSocketHandler extends SocketHandler {
}
});
// down stack
socket.on("downStack", async (stackName : unknown, callback) => {
try {
checkLogin(socket);
if (typeof(stackName) !== "string") {
throw new ValidationError("Stack name must be a string");
}
const stack = Stack.getStack(server, stackName);
await stack.down(socket);
callback({
ok: true,
msg: "Downed"
});
server.sendStackList();
} catch (e) {
callbackError(e, callback);
}
});
// Services status
socket.on("serviceStatusList", async (stackName : unknown, callback) => {
try {
@ -196,7 +219,7 @@ export class DockerSocketHandler extends SocketHandler {
throw new ValidationError("Stack name must be a string");
}
const stack = Stack.getStack(server, stackName);
const stack = Stack.getStack(server, stackName, true);
const serviceStatusList = Object.fromEntries(await stack.getServiceStatusList());
callback({
ok: true,

View file

@ -140,9 +140,26 @@ export class TerminalSocketHandler extends SocketHandler {
}
});
// Close Terminal
socket.on("terminalClose", async (terminalName : unknown, callback : unknown) => {
// Leave Combined Terminal
socket.on("leaveCombinedTerminal", async (stackName : unknown, callback) => {
try {
checkLogin(socket);
log.debug("leaveCombinedTerminal", "Stack name: " + stackName);
if (typeof(stackName) !== "string") {
throw new ValidationError("Stack name must be a string.");
}
const stack = Stack.getStack(server, stackName);
await stack.leaveCombinedTerminal(socket);
callback({
ok: true,
});
} catch (e) {
callbackError(e, callback);
}
});
// TODO: Resize Terminal

View file

@ -31,17 +31,19 @@ export class Stack {
protected static managedStackList: Map<string, Stack> = new Map();
constructor(server : DockgeServer, name : string, composeYAML? : string) {
constructor(server : DockgeServer, name : string, composeYAML? : string, skipFSOperations = false) {
this.name = name;
this.server = server;
this._composeYAML = composeYAML;
// Check if compose file name is different from compose.yaml
const supportedFileNames = [ "compose.yaml", "compose.yml", "docker-compose.yml", "docker-compose.yaml" ];
for (const filename of supportedFileNames) {
if (fs.existsSync(path.join(this.path, filename))) {
this._composeFileName = filename;
break;
if (!skipFSOperations) {
// Check if compose file name is different from compose.yaml
const supportedFileNames = [ "compose.yaml", "compose.yml", "docker-compose.yml", "docker-compose.yaml" ];
for (const filename of supportedFileNames) {
if (fs.existsSync(path.join(this.path, filename))) {
this._composeFileName = filename;
break;
}
}
}
}
@ -189,6 +191,7 @@ export class Stack {
let stacksDir = server.stacksDir;
let stackList : Map<string, Stack>;
// Use cached stack list?
if (useCacheForManaged && this.managedStackList.size > 0) {
stackList = this.managedStackList;
} else {
@ -218,22 +221,19 @@ export class Stack {
this.managedStackList = new Map(stackList);
}
// Also get the list from `docker compose ls --all --format json`
// Get status from docker compose ls
let res = childProcess.execSync("docker compose ls --all --format json");
let composeList = JSON.parse(res.toString());
for (let composeStack of composeList) {
// Skip the dockge stack
// TODO: Could be self managed?
if (composeStack.Name === "dockge") {
continue;
}
let stack = stackList.get(composeStack.Name);
// This stack probably is not managed by Dockge, but we still want to show it
if (!stack) {
// Skip the dockge stack if it is not managed by Dockge
if (composeStack.Name === "dockge") {
continue;
}
stack = new Stack(server, composeStack.Name);
stackList.set(composeStack.Name, stack);
}
@ -281,23 +281,34 @@ export class Stack {
}
}
static getStack(server: DockgeServer, stackName: string) : Stack {
static getStack(server: DockgeServer, stackName: string, skipFSOperations = false) : Stack {
let dir = path.join(server.stacksDir, stackName);
if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {
// Maybe it is a stack managed by docker compose directly
let stackList = this.getStackList(server);
let stack = stackList.get(stackName);
if (!skipFSOperations) {
if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {
// Maybe it is a stack managed by docker compose directly
let stackList = this.getStackList(server, true);
let stack = stackList.get(stackName);
if (stack) {
return stack;
} else {
// Really not found
throw new ValidationError("Stack not found");
if (stack) {
return stack;
} else {
// Really not found
throw new ValidationError("Stack not found");
}
}
} else {
//log.debug("getStack", "Skip FS operations");
}
let stack : Stack;
if (!skipFSOperations) {
stack = new Stack(server, stackName);
} else {
stack = new Stack(server, stackName, undefined, true);
}
let stack = new Stack(server, stackName);
stack._status = UNKNOWN;
stack._configFilePath = path.resolve(dir);
return stack;
@ -330,6 +341,15 @@ export class Stack {
return exitCode;
}
async down(socket: DockgeSocket) : Promise<number> {
const terminalName = getComposeTerminalName(this.name);
let exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", [ "compose", "down" ], this.path);
if (exitCode !== 0) {
throw new Error("Failed to down, please check the terminal output for more information.");
}
return exitCode;
}
async update(socket: DockgeSocket) {
const terminalName = getComposeTerminalName(this.name);
let exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", [ "compose", "pull" ], this.path);
@ -354,12 +374,21 @@ export class Stack {
async joinCombinedTerminal(socket: DockgeSocket) {
const terminalName = getCombinedTerminalName(this.name);
const terminal = Terminal.getOrCreateTerminal(this.server, terminalName, "docker", [ "compose", "logs", "-f", "--tail", "100" ], this.path);
terminal.enableKeepAlive = true;
terminal.rows = COMBINED_TERMINAL_ROWS;
terminal.cols = COMBINED_TERMINAL_COLS;
terminal.join(socket);
terminal.start();
}
async leaveCombinedTerminal(socket: DockgeSocket) {
const terminalName = getCombinedTerminalName(this.name);
const terminal = Terminal.getTerminal(terminalName);
if (terminal) {
terminal.leave(socket);
}
}
async joinContainerTerminal(socket: DockgeSocket, serviceName: string, shell : string = "sh", index: number = 0) {
const terminalName = getContainerExecTerminalName(this.name, serviceName, index);
let terminal = Terminal.getTerminal(terminalName);
@ -377,11 +406,11 @@ export class Stack {
async getServiceStatusList() {
let statusList = new Map<string, number>();
let res = childProcess.execSync("docker compose ps --format json", {
let res = childProcess.spawnSync("docker", [ "compose", "ps", "--format", "json" ], {
cwd: this.path,
});
let lines = res.toString().split("\n");
let lines = res.stdout.toString().split("\n");
for (let line of lines) {
try {

View file

@ -34,6 +34,9 @@ export class Terminal {
protected _rows : number = TERMINAL_ROWS;
protected _cols : number = TERMINAL_COLS;
public enableKeepAlive : boolean = false;
protected keepAliveInterval? : NodeJS.Timeout;
constructor(server : DockgeServer, name : string, file : string, args : string | string[], cwd : string) {
this.server = server;
this._name = name;
@ -80,37 +83,76 @@ export class Terminal {
return;
}
this._ptyProcess = pty.spawn(this.file, this.args, {
name: this.name,
cwd: this.cwd,
cols: TERMINAL_COLS,
rows: this.rows,
});
if (this.enableKeepAlive) {
log.debug("Terminal", "Keep alive enabled for terminal " + this.name);
// On Data
this._ptyProcess.onData((data) => {
this.buffer.pushItem(data);
if (this.server.io) {
this.server.io.to(this.name).emit("terminalWrite", this.name, data);
// Close if there is no clients
this.keepAliveInterval = setInterval(() => {
const clients = this.server.io.sockets.adapter.rooms.get(this.name);
const numClients = clients ? clients.size : 0;
if (numClients === 0) {
log.debug("Terminal", "Terminal " + this.name + " has no client, closing...");
this.close();
} else {
log.debug("Terminal", "Terminal " + this.name + " has " + numClients + " client(s)");
}
}, 60 * 1000);
} else {
log.debug("Terminal", "Keep alive disabled for terminal " + this.name);
}
try {
this._ptyProcess = pty.spawn(this.file, this.args, {
name: this.name,
cwd: this.cwd,
cols: TERMINAL_COLS,
rows: this.rows,
});
// On Data
this._ptyProcess.onData((data) => {
this.buffer.pushItem(data);
if (this.server.io) {
this.server.io.to(this.name).emit("terminalWrite", this.name, data);
}
});
// On Exit
this._ptyProcess.onExit(this.exit);
} catch (error) {
if (error instanceof Error) {
clearInterval(this.keepAliveInterval);
log.error("Terminal", "Failed to start terminal: " + error.message);
const exitCode = Number(error.message.split(" ").pop());
this.exit({
exitCode,
});
}
});
// On Exit
this._ptyProcess.onExit((res) => {
this.server.io.to(this.name).emit("terminalExit", this.name, res.exitCode);
// Remove room
this.server.io.in(this.name).socketsLeave(this.name);
Terminal.terminalMap.delete(this.name);
log.debug("Terminal", "Terminal " + this.name + " exited with code " + res.exitCode);
if (this.callback) {
this.callback(res.exitCode);
}
});
}
}
/**
* Exit event handler
* @param res
*/
protected exit = (res : {exitCode: number, signal?: number | undefined}) => {
this.server.io.to(this.name).emit("terminalExit", this.name, res.exitCode);
// Remove room
this.server.io.in(this.name).socketsLeave(this.name);
Terminal.terminalMap.delete(this.name);
log.debug("Terminal", "Terminal " + this.name + " exited with code " + res.exitCode);
clearInterval(this.keepAliveInterval);
if (this.callback) {
this.callback(res.exitCode);
}
};
public onExit(callback : (exitCode : number) => void) {
this.callback = callback;
}
@ -142,7 +184,9 @@ export class Terminal {
}
close() {
this._ptyProcess?.kill();
clearInterval(this.keepAliveInterval);
// Send Ctrl+C to the terminal
this.ptyProcess?.write("\x03");
}
/**
@ -177,6 +221,10 @@ export class Terminal {
terminal.start();
});
}
public static getTerminalCount() {
return Terminal.terminalMap.size;
}
}
/**

View file

@ -0,0 +1,57 @@
import github from "@actions/github";
(async () => {
try {
const token = process.argv[2];
const issueNumber = process.argv[3];
const username = process.argv[4];
const client = github.getOctokit(token).rest;
const issue = {
owner: "louislam",
repo: "dockge",
number: issueNumber,
};
const labels = (
await client.issues.listLabelsOnIssue({
owner: issue.owner,
repo: issue.repo,
issue_number: issue.number
})
).data.map(({ name }) => name);
if (labels.length === 0) {
console.log("Bad format here");
await client.issues.addLabels({
owner: issue.owner,
repo: issue.repo,
issue_number: issue.number,
labels: [ "invalid-format" ]
});
// Add the issue closing comment
await client.issues.createComment({
owner: issue.owner,
repo: issue.repo,
issue_number: issue.number,
body: `@${username}: Hello! :wave:\n\nThis issue is being automatically closed because it does not follow the issue template. Please DO NOT open a blank issue.`
});
// Close the issue
await client.issues.update({
owner: issue.owner,
repo: issue.repo,
issue_number: issue.number,
state: "closed"
});
} else {
console.log("Pass!");
}
} catch (e) {
console.log(e);
}
})();

View file

@ -0,0 +1,42 @@
// Generate on GitHub
const input = `
* Add Korean translation by @Alanimdeo in https://github.com/louislam/dockge/pull/86
`;
const template = `
### 🆕 New Features
### Improvements
### 🐞 Bug Fixes
### 🦎 Translation Contributions
### Others
- Other small changes, code refactoring and comment/doc updates in this repo:
`;
const lines = input.split("\n").filter((line) => line.trim() !== "");
for (const line of lines) {
// Split the last " by "
const usernamePullRequesURL = line.split(" by ").pop();
if (!usernamePullRequesURL) {
console.log("Unable to parse", line);
continue;
}
const [ username, pullRequestURL ] = usernamePullRequesURL.split(" in ");
const pullRequestID = "#" + pullRequestURL.split("/").pop();
let message = line.split(" by ").shift();
if (!message) {
console.log("Unable to parse", line);
continue;
}
message = message.split("* ").pop();
console.log("-", pullRequestID, message, `(Thanks ${username})`);
}
console.log(template);

View file

@ -11,6 +11,8 @@ declare module 'vue' {
Appearance: typeof import('./src/components/settings/Appearance.vue')['default']
ArrayInput: typeof import('./src/components/ArrayInput.vue')['default']
ArraySelect: typeof import('./src/components/ArraySelect.vue')['default']
BDropdown: typeof import('bootstrap-vue-next')['BDropdown']
BDropdownItem: typeof import('bootstrap-vue-next')['BDropdownItem']
BModal: typeof import('bootstrap-vue-next')['BModal']
Confirm: typeof import('./src/components/Confirm.vue')['default']
Container: typeof import('./src/components/Container.vue')['default']

View file

@ -45,6 +45,8 @@ export default {
<style scoped>
.badge {
min-width: 62px;
overflow: hidden;
text-overflow: ellipsis;
}
.fixed-width {

View file

@ -7,13 +7,21 @@ const languageList = {
"es": "Español",
"de": "Deutsch",
"fr": "Français",
"pl-PL": "Polski",
"pt": "Português",
"pt-BR": "Português-Brasil",
"sl": "Slovenščina",
"tr": "Türkçe",
"zh-CN": "简体中文",
"zh-TW": "繁體中文(台灣)",
"ur": "Urdu",
"ko-KR": "한국어",
"ru": "Русский",
"cs-CZ": "Čeština",
"ar": "العربية",
"th":"ไทย",
"it-IT":"Italiano",
"sv-SE":"Svenska"
};
let messages = {

View file

@ -0,0 +1,14 @@
# Translations
A simple guide on how to translate `Dockge` in your native language.
## How to add a new language in the dropdown
(11-21-2023) Updated
1. Add your Language at `frontend/src/lang/` by creating a new file with your language Code, format: `zh-TW.json` .
2. Copy the content from `en.json` and make translations from that.
3. Add your language at the end of `languageList` in `frontend/src/i18n.ts`, format: `"zh-TW": "繁體中文 (台灣)"`,
4. Commit to new branch and make a new Pull Request for me to approve.
*Note:* Currently we are only accepting one Pull Request per Language Translate.

95
frontend/src/lang/ar.json Normal file
View file

@ -0,0 +1,95 @@
{
"languageName": "العربية",
"Create your admin account": "إنشاء حساب المشرف",
"authIncorrectCreds": "اسم المستخدم أو كلمة المرور غير صحيحة.",
"PasswordsDoNotMatch": "كلمة المرور غير مطابقة.",
"Repeat Password": "أعد كتابة كلمة السر",
"Create": "إنشاء",
"signedInDisp": "تم تسجيل الدخول باسم {0}",
"signedInDispDisabled": "تم تعطيل المصادقة.",
"home": "الرئيسية",
"console": "سطر الأوامر",
"registry": "السجل",
"compose": "أنشاء كمبوز",
"addFirstStackMsg": "أنشيء أول كمبوز!",
"stackName" : "اسم المكدسة",
"deployStack": "شنر",
"deleteStack": "حذف",
"stopStack": "إيقاف",
"restartStack": "إعادة تشغيل",
"updateStack": "تحديث",
"startStack": "تشغيل",
"downStack": "أيقاف",
"editStack": "تعديل",
"discardStack": "إهمال",
"saveStackDraft": "حفظ",
"notAvailableShort" : "غير متوفر",
"deleteStackMsg": "هل أنت متأكد أنك تريد حذف هذه المكدسة؟",
"stackNotManagedByDockgeMsg": "لا يتم إدارة هذه المكدس بواسطة Dockge.",
"primaryHostname": "اسم المضيف الرئيسي",
"general": "عام",
"container": "حاوية | حاويات",
"scanFolder": "مسح مجلد المكدسات",
"dockerImage": "صورة",
"restartPolicyUnlessStopped": "ما لم يوقف",
"restartPolicyAlways": "دائماً",
"restartPolicyOnFailure": "عند الفشل",
"restartPolicyNo": "لا",
"environmentVariable": "متغير البيئة | متغيرات البيئة",
"restartPolicy": "سياسة إعادة التشغيل",
"containerName": "اسم الحاوية",
"port": "منفذ | منافذ",
"volume": "مجلد | مجلدات",
"network": "شبكة | شبكات",
"dependsOn": "تبعية الحاوية | تبعية الحاويات",
"addListItem": "إضافة {0}",
"deleteContainer": "حذف",
"addContainer": "أضافة حاوية",
"addNetwork": "أضافة شبكة",
"disableauth.message1": "هل أنت متأكد أنك تريد <strong>تعطيل المصادقة</strong>?",
"disableauth.message2": "إنه مصمم للحالات <strong>التي تنوي فيها مصادقة الطرف الثالث</strong> أمام Dockge مثل Cloudflare Access, Authelia أو أي من آليات المصادقة الأخرى.",
"passwordNotMatchMsg": "كلمة المرور المكررة غير متطابقة.",
"autoGet": "الجلب التلقائي",
"add": "إضافة",
"Edit": "تعديل",
"applyToYAML": "تطبيق على YAML",
"createExternalNetwork": "إنشاء",
"addInternalNetwork": "إضافة",
"Save": "حفظ",
"Language": "اللغة",
"Current User": "المستخدم الحالي",
"Change Password": "تعديل كلمة المرور",
"Current Password": "كلمة المرور الحالية",
"New Password": "كلمة مرور جديدة",
"Repeat New Password": "أعد تكرار كلمة المرور",
"Update Password": "تحديث كلمة المرور",
"Advanced": "متقدم",
"Please use this option carefully!": "من فضلك استخدم هذا الخيار بعناية!",
"Enable Auth": "تفعيل المصادقة",
"Disable Auth": "تعطيل المصادقة",
"I understand, please disable": "أتفهم, أرجو التعطيل",
"Leave": "مغادرة",
"Frontend Version": "لإصدار الواجهة الأمامية",
"Check Update On GitHub": "تحق من التحديث على GitHub",
"Show update if available": "اعرض التحديث إذا كان متاحًا",
"Also check beta release": "تحقق أيضًا من إصدار النسخة التجريبية",
"Remember me": "تذكرني",
"Login": "تسجيل الدخول",
"Username": "اسم المستخدم",
"Password": "كلمة المرور",
"Settings": "الاعدادات",
"Logout": "تسجيل الخروج",
"Lowercase only": "أحرف صغيرة فقط",
"Convert to Compose": "تحويل إلى كومبوز",
"Docker Run": "تشغيل Docker",
"active": "نشيط",
"exited": "تم الخروج",
"inactive": "غير نشيط",
"Appearance": "المظهر",
"Security": "الأمان",
"About": "حول",
"Allowed commands:": "الأوامر المسموح بها:",
"Internal Networks": "الشبكات الداخلية",
"External Networks": "الشبكات الخارجية",
"No External Networks": "لا توجد شبكات خارجية"
}

View file

@ -0,0 +1,95 @@
{
"languageName": "Čeština",
"Create your admin account": "Vytvořit účet administrátora",
"authIncorrectCreds": "Nesprávné uživatelské jméno nebo heslo.",
"PasswordsDoNotMatch": "Hesla se neshodují.",
"Repeat Password": "Opakujte heslo",
"Create": "Vytvořit",
"signedInDisp": "Přihlášen jako {0}",
"signedInDispDisabled": "Ověření zakázáno.",
"home": "Domů",
"console": "Konzole",
"registry": "Registry",
"compose": "Compose",
"addFirstStackMsg": "Vytvořte svůj první stack!",
"stackName": "Název stacku",
"deployStack": "Nainstalovat",
"deleteStack": "Smazat",
"stopStack": "Zastavit",
"restartStack": "Restartovat",
"updateStack": "Aktualizovat",
"startStack": "Spustit",
"downStack": "Zastavit a vypnout",
"editStack": "Upravit",
"discardStack": "Zahodit",
"saveStackDraft": "Uložit",
"notAvailableShort": "N/A",
"deleteStackMsg": "Opravdu chcete smazat tento stack?",
"stackNotManagedByDockgeMsg": "Tento stack není spravován systémem Dockge.",
"primaryHostname": "Primární název hostitele",
"general": "Obecné",
"container": "Kontejner | Kontejnery",
"scanFolder": "Prohledat složku se stacky",
"dockerImage": "Obrázek",
"restartPolicyUnlessStopped": "Pokud není zastaveno",
"restartPolicyAlways": "Vždy",
"restartPolicyOnFailure": "Při selhání",
"restartPolicyNo": "Ne",
"environmentVariable": "Proměnná prostředí | Proměnné prostředí",
"restartPolicy": "Politika restartu",
"containerName": "Název kontejneru",
"port": "Port | Porty",
"volume": "Svazek | Svazky",
"network": "Síť | Sítě",
"dependsOn": "Závisí na kontejneru | Závislosti na kontejneru",
"addListItem": "Přidat {0}",
"deleteContainer": "Smazat",
"addContainer": "Přidat kontejner",
"addNetwork": "Přidat síť",
"disableauth.message1": "Opravdu chcete <strong>zakázat ověřování</strong>?",
"disableauth.message2": "Je navrženo pro scénáře, kde <strong>plánujete implementovat ověřování třetí strany</strong> před Dockge, například Cloudflare Access, Authelia nebo jiné ověřovací mechanismy.",
"passwordNotMatchMsg": "Hesla se neshodují.",
"autoGet": "Automaticky získat",
"add": "Přidat",
"Edit": "Upravit",
"applyToYAML": "Použít na YAML",
"createExternalNetwork": "Vytvořit",
"addInternalNetwork": "Přidat",
"Save": "Uložit",
"Language": "Jazyk",
"Current User": "Aktuální uživatel",
"Change Password": "Změnit heslo",
"Current Password": "Aktuální heslo",
"New Password": "Nové heslo",
"Repeat New Password": "Opakujte nové heslo",
"Update Password": "Aktualizovat heslo",
"Advanced": "Pokročilé",
"Please use this option carefully!": "Používejte tuto možnost opatrně!",
"Enable Auth": "Povolit ověřování",
"Disable Auth": "Zakázat ověřování",
"I understand, please disable": "Rozumím, prosím zakážte",
"Leave": "Opustit",
"Frontend Version": "Verze rozhraní",
"Check Update On GitHub": "Zkontrolovat aktualizaci na GitHubu",
"Show update if available": "Zobrazit aktualizaci, pokud je k dispozici",
"Also check beta release": "Zkontrolovat také beta verzi",
"Remember me": "Zapamatovat údaje",
"Login": "Přihlásit se",
"Username": "Uživatelské jméno",
"Password": "Heslo",
"Settings": "Nastavení",
"Logout": "Odhlásit se",
"Lowercase only": "Pouze malá písmena",
"Convert to Compose": "Převést na Compose",
"Docker Run": "Docker Run",
"active": "Aktivní",
"exited": "Ukončený",
"inactive": "Neaktivní",
"Appearance": "Vzhled",
"Security": "Zabezpečení",
"About": "O aplikaci",
"Allowed commands:": "Povolené příkazy:",
"Internal Networks": "Interní sítě",
"External Networks": "Externí sítě",
"No External Networks": "Žádné externí sítě"
}

View file

@ -19,6 +19,7 @@
"restartStack": "Restart",
"updateStack": "Update",
"startStack": "Start",
"downStack": "Stop & Down",
"editStack": "Edit",
"discardStack": "Discard",
"saveStackDraft": "Save",

View file

@ -0,0 +1,95 @@
{
"languageName": "Italiano",
"Create your admin account": "Crea il tuo account amministratore",
"authIncorrectCreds": "Username e/o password errati.",
"PasswordsDoNotMatch": "Le password non corrispondono.",
"Repeat Password": "Ripetere la password",
"Create": "Crea",
"signedInDisp": "Autenticato come {0}",
"signedInDispDisabled": "Autenticazione disabilitata.",
"home": "Home",
"console": "Console",
"registry": "Registro",
"compose": "Compose",
"addFirstStackMsg": "Componi il tuo primo stack!",
"stackName" : "Nome dello stack",
"deployStack": "Deploy",
"deleteStack": "Cancella",
"stopStack": "Stop",
"restartStack": "Riavvia",
"updateStack": "Aggiorna",
"startStack": "Avvia",
"downStack": "Stop & Down",
"editStack": "Modifica",
"discardStack": "Annulla",
"saveStackDraft": "Salva",
"notAvailableShort" : "N/D",
"deleteStackMsg": "Sei sicuro di voler eliminare questo stack?",
"stackNotManagedByDockgeMsg": "Questo stack non è gestito da Dockge.",
"primaryHostname": "Hostname primario",
"general": "Generale",
"container": "Container | Container",
"scanFolder": "Scansiona la cartella degli stack",
"dockerImage": "Immagine",
"restartPolicyUnlessStopped": "A meno che non venga fermato",
"restartPolicyAlways": "Sempre",
"restartPolicyOnFailure": "Quando fallisce",
"restartPolicyNo": "No",
"environmentVariable": "Variabile d'ambiente | Variabili d'ambiente",
"restartPolicy": "Politica di riavvio",
"containerName": "Nome del container",
"port": "Porta | Porte",
"volume": "Volume | Volumi",
"network": "Rete | Reti",
"dependsOn": "Dipendenza del container | Dipendenze del container",
"addListItem": "Aggiungi {0}",
"deleteContainer": "Elimina",
"addContainer": "Aggiungi container",
"addNetwork": "Aggiungi rete",
"disableauth.message1": "Sei sicuro di voler <strong>disabilitare l'autenticazione</strong>?",
"disableauth.message2": "È stato progettato per scenari <strong>in cui intendi implementare un'autenticazione di terze parti</strong> davanti a Dockge come ad esempio Cloudflare Access, Authelia o altri meccanismi di autenticazione.",
"passwordNotMatchMsg": "La password ripetuta non corrisponde.",
"autoGet": "Ottieni automaticamente",
"add": "Aggiungi",
"Edit": "Modifica",
"applyToYAML": "Applica al file YAML",
"createExternalNetwork": "Crea",
"addInternalNetwork": "Aggiungi",
"Save": "Salva",
"Language": "Lingua",
"Current User": "Utente corrente",
"Change Password": "Cambia la password",
"Current Password": "Password corrente",
"New Password": "Nuova password",
"Repeat New Password": "Ripeti la nuova password",
"Update Password": "Aggiornamento password",
"Advanced": "Avanzato",
"Please use this option carefully!": "Per favore usa questa opzione con cautela!",
"Enable Auth": "Abilita l'autenticazione",
"Disable Auth": "Disabilita l'autenticazione",
"I understand, please disable": "Lo capisco, disabilita",
"Leave": "Lascia",
"Frontend Version": "Versione del frontend",
"Check Update On GitHub": "Controlla la presenza di aggiornamenti su GitHub",
"Show update if available": "Mostra l'aggiornamento se è disponibile",
"Also check beta release": "Controlla anche le release in beta",
"Remember me": "Ricordami",
"Login": "Login",
"Username": "Username",
"Password": "Password",
"Settings": "Impostazioni",
"Logout": "Logout",
"Lowercase only": "Solo lettere minuscole",
"Convert to Compose": "Converti a Compose",
"Docker Run": "Docker Run",
"active": "attivo",
"exited": "uscito",
"inactive": "inattivo",
"Appearance": "Aspetto",
"Security": "Sicurezza",
"About": "Informazioni su",
"Allowed commands:": "Comandi permessi:",
"Internal Networks": "Reti interne",
"External Networks": "Reti esterne",
"No External Networks": "Nessuna rete esterna"
}

View file

@ -0,0 +1,94 @@
{
"languageName": "Polski",
"Create your admin account": "Utwórz konto administratora",
"authIncorrectCreds": "Nieprawidłowa nazwa użytkownika lub hasło.",
"PasswordsDoNotMatch": "Hasła nie pasują do siebie.",
"Repeat Password": "Powtórz hasło",
"Create": "Utwórz",
"signedInDisp": "Zalogowany jako {0}",
"signedInDispDisabled": "Autoryzacja wyłączona.",
"home": "Strona główna",
"console": "Konsola",
"registry": "Rejestr",
"compose": "Stwórz",
"addFirstStackMsg": "Stwórz swój pierwszy stos!",
"stackName" : "Nazwa stosu",
"deployStack": "Wdroż",
"deleteStack": "Usuń",
"stopStack": "Zatrzymaj",
"restartStack": "Uruchom ponownie",
"updateStack": "Aktualizuj",
"startStack": "Uruchom",
"editStack": "Edytuj",
"discardStack": "Odrzuć",
"saveStackDraft": "Zapisz",
"notAvailableShort" : "N/A",
"deleteStackMsg": "Czy na pewno chcesz usunąć ten stos?",
"stackNotManagedByDockgeMsg": "Ten stos nie jest zarządzany przez Dockge.",
"primaryHostname": "Podstawowa nazwa hosta",
"general": "Ogólne",
"container": "Kontener | Kontenery",
"scanFolder": "Skanuj folder ze stosami",
"dockerImage": "Obraz",
"restartPolicyUnlessStopped": "Jeśli nie zatrzymano",
"restartPolicyAlways": "Zawsze",
"restartPolicyOnFailure": "Po awarii",
"restartPolicyNo": "Nie restartuj",
"environmentVariable": "Zmienna środowiskowa | Zmienne środowiskowe",
"restartPolicy": "Polityka restartu",
"containerName": "Nazwa kontenera",
"port": "Port | Porty",
"volume": "Wolumin | Woluminy",
"network": "Sieć | Sieci",
"dependsOn": "Zależność kontenera | Zależności kontenera",
"addListItem": "Dodaj {0}",
"deleteContainer": "Usuń kontener",
"addContainer": "Dodaj kontener",
"addNetwork": "Dodaj sieć",
"disableauth.message1": "Czy na pewno chcesz <strong>wyłączyć uwierzytelnianie</strong>?",
"disableauth.message2": "Przeznaczone dla sytuacji, <strong>w których zamierzasz zaimplementować zewnętrzne mechanizmy uwierzytelniania</strong> przed Dockge, takie jak Cloudflare Access, Authelia lub inne.",
"passwordNotMatchMsg": "Hasła się nie zgadzają.",
"autoGet": "Automatyczne pobieranie",
"add": "Dodaj",
"Edit": "Edytuj",
"applyToYAML": "Zastosuj do YAML",
"createExternalNetwork": "Utwórz",
"addInternalNetwork": "Dodaj",
"Save": "Zapisz",
"Language": "Język",
"Current User": "Aktualny użytkownik",
"Change Password": "Zmień hasło",
"Current Password": "Aktualne hasło",
"New Password": "Nowe hasło",
"Repeat New Password": "Powtórz nowe hasło",
"Update Password": "Aktualizuj hasło",
"Advanced": "Zaawansowane",
"Please use this option carefully!": "Proszę używać tej opcji ostrożnie!",
"Enable Auth": "Włącz autoryzację",
"Disable Auth": "Wyłącz autoryzację",
"I understand, please disable": "Rozumiem, proszę wyłączyć",
"Leave": "Wyjdź",
"Frontend Version": "Wersja interfejsu graficznego",
"Check Update On GitHub": "Sprawdź dostępność aktualizacji na GitHub",
"Show update if available": "Pokaż aktualizacje, jeśli są dostępne",
"Also check beta release": "Sprawdź także wersje beta",
"Remember me": "Zapamiętaj mnie",
"Login": "Zaloguj się",
"Username": "Nazwa użytkownika",
"Password": "Hasło",
"Settings": "Ustawienia",
"Logout": "Wyloguj się",
"Lowercase only": "Tylko małe litery",
"Convert to Compose": "Przekształć na składnię Compose",
"Docker Run": "Uruchom za pomocą Dockera",
"active": "aktywny",
"exited": "wyłączony",
"inactive": "nieaktywny",
"Appearance": "Wygląd",
"Security": "Bezpieczeństwo",
"About": "O programie",
"Allowed commands:": "Dozwolone polecenia:",
"Internal Networks": "Sieci wewnętrzne",
"External Networks": "Sieci zewnętrzne",
"No External Networks": "Brak sieci zewnętrznych"
}

View file

@ -0,0 +1,94 @@
{
"languageName": "Português-Brasil",
"Create your admin account": "Crie sua conta de administrador",
"authIncorrectCreds": "Nome de usuário ou senha incorretos.",
"PasswordsDoNotMatch": "As senhas não correspondem.",
"Repeat Password": "Repetir a senha",
"Create": "Criar",
"signedInDisp": "Logado como {0}",
"signedInDispDisabled": "Autenticação desativada.",
"home": "Início",
"console": "Console",
"registry": "Registro",
"compose": "Compose",
"addFirstStackMsg": "Crie sua primeira stack!",
"stackName" : "Nome da stack",
"deployStack": "Deploy",
"deleteStack": "Excluir",
"stopStack": "Parar",
"restartStack": "Reiniciar",
"updateStack": "Atualizar",
"startStack": "Iniciar",
"editStack": "Editar",
"discardStack": "Descartar",
"saveStackDraft": "Salvar",
"notAvailableShort" : "N/D",
"deleteStackMsg": "Tem certeza que deseja excluir esta stack?",
"stackNotManagedByDockgeMsg": "Esta stack não é gerenciada pelo Dockge.",
"primaryHostname": "Nome do Host Primário",
"general": "Geral",
"container": "Contêiner | Contêineres",
"scanFolder": "Pesquisar na pasta de stacks",
"dockerImage": "Imagem",
"restartPolicyUnlessStopped": "A menos que seja parado",
"restartPolicyAlways": "Sempre",
"restartPolicyOnFailure": "Em caso de falha",
"restartPolicyNo": "Não",
"environmentVariable": "Variável de ambiente | Variáveis de ambiente",
"restartPolicy": "Política de reinicialização",
"containerName": "Nome do contêiner",
"port": "Porta | Portas",
"volume": "Volume | Volumes",
"network": "Rede | Redes",
"dependsOn": "Dependência do contêiner | Dependências do contêiner",
"addListItem": "Adicionar {0}",
"deleteContainer": "Excluir",
"addContainer": "Adicionar contêiner",
"addNetwork": "Adicionar rede",
"disableauth.message1": "Tem certeza que deseja <strong>desativar a autenticação</strong>?",
"disableauth.message2": "Isso foi projetado para ambientes <strong>onde você pretende implementar autenticação de terceiros</strong> no Dockge, como Cloudflare Access, Authelia entre outros mecanismos de autenticação.",
"passwordNotMatchMsg": "A senha repetida não corresponde.",
"autoGet": "Obter automaticamente",
"add": "Adicionar",
"Edit": "Editar",
"applyToYAML": "Aplicar ao YAML",
"createExternalNetwork": "Criar",
"addInternalNetwork": "Adicionar",
"Save": "Salvar",
"Language": "Idioma",
"Current User": "Usuário atual",
"Change Password": "Alterar senha",
"Current Password": "Senha atual",
"New Password": "Nova senha",
"Repeat New Password": "Repetir nova senha",
"Update Password": "Atualizar senha",
"Advanced": "Avançado",
"Please use this option carefully!": "Por favor, use esta opção com atenção!",
"Enable Auth": "Habilitar autenticação",
"Disable Auth": "Desabilitar autenticação",
"I understand, please disable": "Entendido, por favor desabilitar",
"Leave": "Sair",
"Frontend Version": "Versão da interface",
"Check Update On GitHub": "Verificar atualização no GitHub",
"Show update if available": "Mostrar atualização se disponível",
"Also check beta release": "Também verificar versão beta",
"Remember me": "Lembrar-me",
"Login": "Entrar",
"Username": "Nome de usuário",
"Password": "Senha",
"Settings": "Configurações",
"Logout": "Sair",
"Lowercase only": "Somente minúsculas",
"Convert to Compose": "Converter para compose",
"Docker Run": "Executar Docker",
"active": "ativo",
"exited": "encerrado",
"inactive": "inativo",
"Appearance": "Aparência",
"Security": "Segurança",
"About": "Sobre",
"Allowed commands:": "Comandos permitidos:",
"Internal Networks": "Redes internas",
"External Networks": "Redes externas",
"No External Networks": "Sem redes externas"
}

94
frontend/src/lang/sl.json Normal file
View file

@ -0,0 +1,94 @@
{
"languageName": "Slovenščina",
"Create your admin account": "Ustvarite svoj skrbniški račun",
"authIncorrectCreds": "Napačno uporabniško ime ali geslo.",
"PasswordsDoNotMatch": "Gesli se ne ujemata.",
"Repeat Password": "Ponovi geslo",
"Create": "Ustvari",
"signedInDisp": "Prijavljeni kot {0}",
"signedInDispDisabled": "Preverjanje pristnosti onemogočeno.",
"home": "Domov",
"console": "Konzola",
"registry": "Register",
"compose": "Compose",
"addFirstStackMsg": "Ustvarite svoj prvi Stack!",
"stackName": "Ime Stack-a",
"deployStack": "Razporedi",
"deleteStack": "Izbriši",
"stopStack": "Ustavi",
"restartStack": "Ponovni zagon",
"updateStack": "Posodobi",
"startStack": "Zaženi",
"editStack": "Uredi",
"discardStack": "Zavrzi",
"saveStackDraft": "Shrani",
"notAvailableShort": "Ni na voljo",
"deleteStackMsg": "Ste prepričani, da želite izbrisati ta Stack?",
"stackNotManagedByDockgeMsg": "Ta Stack ni upravljan s strani Dockge.",
"primaryHostname": "Osnovno gostiteljsko ime",
"general": "Splošno",
"container": "Kontejner | Kontejnerji",
"scanFolder": "Preglej Stack mapo",
"dockerImage": "Slika",
"restartPolicyUnlessStopped": "Razen ko je zaustavljeno",
"restartPolicyAlways": "Vedno",
"restartPolicyOnFailure": "Ob napaki",
"restartPolicyNo": "Ne",
"environmentVariable": "Okoljska spremenljivka | Okoljske spremenljivke",
"restartPolicy": "Politika ponovnega zagona",
"containerName": "Ime kontejnerja",
"port": "Vrata | Vrata",
"volume": "Zvezek | Zvezki",
"network": "Omrežje | Omrežja",
"dependsOn": "Odvisnost kontejnerja | Odvisnosti kontejnerjev",
"addListItem": "Dodaj {0}",
"deleteContainer": "Izbriši",
"addContainer": "Dodaj kontejner",
"addNetwork": "Dodaj omrežje",
"disableauth.message1": "Ste prepričani, da želite <strong>onemogočiti overjanje</strong>?",
"disableauth.message2": "Namerno je zasnovano za scenarije, <strong>kjer nameravate izvajati avtentikacijo tretjih oseb</strong> pred Dockge, kot so Cloudflare Access, Authelia ali druge avtentikacijske mehanizme.",
"passwordNotMatchMsg": "Ponovljeno geslo se ne ujema.",
"autoGet": "Samodejno pridobi",
"add": "Dodaj",
"Edit": "Uredi",
"applyToYAML": "Uporabi za YAML",
"createExternalNetwork": "Ustvari",
"addInternalNetwork": "Dodaj",
"Save": "Shrani",
"Language": "Jezik",
"Current User": "Trenutni uporabnik",
"Change Password": "Spremeni geslo",
"Current Password": "Trenutno geslo",
"New Password": "Novo geslo",
"Repeat New Password": "Ponovi novo geslo",
"Update Password": "Posodobi geslo",
"Advanced": "Napredno",
"Please use this option carefully!": "Prosimo, uporabite to možnost previdno!",
"Enable Auth": "Omogoči overjanje",
"Disable Auth": "Onemogoči overjanje",
"I understand, please disable": "Razumem, prosim onemogočite",
"Leave": "Zapusti",
"Frontend Version": "Različica vmesnika",
"Check Update On GitHub": "Preveri posodobitve na GitHubu",
"Show update if available": "Prikaži posodobitve, če so na voljo",
"Also check beta release": "Preveri tudi beta izdaje",
"Remember me": "Zapomni si me",
"Login": "Prijava",
"Username": "Uporabniško ime",
"Password": "Geslo",
"Settings": "Nastavitve",
"Logout": "Odjava",
"Lowercase only": "Samo male črke",
"Convert to Compose": "Pretvori v Compose",
"Docker Run": "Zagon Dockerja",
"active": "aktivno",
"exited": "izklopljeno",
"inactive": "neaktivno",
"Appearance": "Videz",
"Security": "Varnost",
"About": "O nas",
"Allowed commands:": "Dovoljeni ukazi:",
"Internal Networks": "Notranja omrežja",
"External Networks": "Zunanja omrežja",
"No External Networks": "Ni zunanjih omrežij"
}

View file

@ -0,0 +1,95 @@
{
"languageName": "Svenska",
"Create your admin account": "Skapa ditt Admin-konto.",
"authIncorrectCreds": "Fel användarnamn eller lösenord.",
"PasswordsDoNotMatch": "Lösenorden matchar inte.",
"Repeat Password": "Repetera lösenord",
"Create": "Skapa",
"signedInDisp": "Inloggad som {0}",
"signedInDispDisabled": "Auth inaktiverad.",
"home": "Hem",
"console": "Konsol",
"registry": "Register",
"compose": "Komponera",
"addFirstStackMsg": "Komponera din första stack!",
"stackName" : "Stacknamn",
"deployStack": "Distribuera",
"deleteStack": "Radera",
"stopStack": "Stop",
"restartStack": "Starta om",
"updateStack": "Uppdatera",
"startStack": "Starta",
"downStack": "Stop & Ner",
"editStack": "Redigera",
"discardStack": "Kasta",
"saveStackDraft": "Spara",
"notAvailableShort" : "N/A",
"deleteStackMsg": "Är du säker på att du vill radera stacken?",
"stackNotManagedByDockgeMsg": "Denna stacken hanteras inte av Dockge.",
"primaryHostname": "Primärt värdnamn",
"general": "Allmän",
"container": "Container | Containrar",
"scanFolder": "Scanna Stackfolder",
"dockerImage": "Bild",
"restartPolicyUnlessStopped": "Om inte stoppas",
"restartPolicyAlways": "Alltid",
"restartPolicyOnFailure": "Vid Misslyckande",
"restartPolicyNo": "Nej",
"environmentVariable": "Miljövariabel | Miljövariabler",
"restartPolicy": "Omstartspolicy",
"containerName": "Containernamn",
"port": "Port | Portar",
"volume": "Volym | Volymer",
"network": "Nätverk | Nätverk",
"dependsOn": "Containerberoende | Containerberoenden",
"addListItem": "Lägg till {0}",
"deleteContainer": "Radera",
"addContainer": "Lägg till Container",
"addNetwork": "Lägg till Nätverk",
"disableauth.message1": "Är du säker på att du vill <strong>inaktivera autentisering</strong>?",
"disableauth.message2": "Det är designat för senarion <stong>när du ska implementera tredjeparts autentisering</strong> framör Dockge som Cloudflare Access, Authelia eller andra autentiseringsmekanismer.",
"passwordNotMatchMsg": "Det upprepade lösenordet matchar inte",
"autoGet": "Auto Hämta",
"add": "Lägg till",
"Edit": "Redigera",
"applyToYAML": "Lägg till i YAML",
"createExternalNetwork": "Skapa",
"addInternalNetwork": "Lägg till",
"Save": "Spara",
"Language": "Språk",
"Current User": "Nuvarande användaren",
"Change Password": "Byt lösenord",
"Current Password": "Nuvarande lösenord",
"New Password": "Nytt lösenord",
"Repeat New Password": "Upprepa nytt lösenord",
"Update Password": "Uppdatera lösenord",
"Advanced": "Avancerat",
"Please use this option carefully!": "Använd detta alternativ försiktigt!",
"Enable Auth": "Aktivera Auth",
"Disable Auth": "Avaktivera Auth",
"I understand, please disable": "Jag förstår, vänligen inaktivera",
"Leave": "Lämna",
"Frontend Version": "Frontendversion",
"Check Update On GitHub": "Kontrollera Uppdatering på GitHub",
"Show update if available": "Visa uppdatering om tillgänglig",
"Also check beta release": "Kontrollera även betaversionen",
"Remember me": "Kom ihåg mig",
"Login": "Logga in",
"Username": "Användarnamn",
"Password": "Lösenord",
"Settings": "Inställningar",
"Logout": "Logga ut",
"Lowercase only": "Endast små tecken",
"Convert to Compose": "Omvandla till Compose",
"Docker Run": "Docker Run",
"active": "aktiv",
"exited": "avslutad",
"inactive": "inaktiv",
"Appearance": "Utseende",
"Security": "Säkerhet",
"About": "Om",
"Allowed commands:": "Tillåtna kommandon:",
"Internal Networks": "Interna Nätverk",
"External Networks": "Externa Nätverk",
"No External Networks": "Inga Externa Nätverk"
}

95
frontend/src/lang/th.json Normal file
View file

@ -0,0 +1,95 @@
{
"languageName": "ไทย",
"Create your admin account": "สร้างบัญชีผู้ดูแลระบบของคุณ",
"authIncorrectCreds": "ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง",
"PasswordsDoNotMatch": "รหัสผ่านไม่ตรงกัน",
"Repeat Password": "ยืนยันรหัสผ่าน",
"Create": "สร้าง",
"signedInDisp": "ลงชื่อเข้าใช้ในชื่อ {0}",
"signedInDispDisabled": "ปิดใช้งาน Auth",
"home": "หน้าหลักe",
"console": "คอนโซล",
"registry": "Registry",
"compose": "Compose",
"addFirstStackMsg": "Compose stack แรกของคุณ",
"stackName": "ชื่อ Stack",
"deployStack": "ปรับใช้",
"deleteStack": "ลบ",
"stopStack": "หยุด",
"restartStack": "เริ่มใหม่",
"updateStack": "อัปเดต",
"startStack": "เริ่มต้น",
"downStack": "หยุดและปิด",
"editStack": "แก้ไข",
"discardStack": "ยกเลิก",
"saveStackDraft": "บันทึก",
"notAvailableShort": "N/A",
"deleteStackMsg": "คุณแน่ใจหรือไม่ว่าต้องการลบ stack นี้",
"stackNotManagedByDockgeMsg": "stack นี้ไม่ได้รับการจัดการโดย Dockge",
"primaryHostname": "ชื่อโฮสต์หลัก",
"general": "ทั่วไป",
"container": "Container | Containers",
"scanFolder": "สแกนโฟลเดอร์ Stacks",
"dockerImage": "Image",
"restartPolicyUnlessStopped": "Unless Stopped",
"restartPolicyAlways": "Always",
"restartPolicyOnFailure": "On Failure",
"restartPolicyNo": "No",
"environmentVariable": "Environment Variable | Environment Variables",
"restartPolicy": "เริ่มต้น Policy ใหม่",
"containerName": "ชื่อ Container",
"port": "พอร์ต | พอร์ต",
"volume": "ปริมาณ | ปริมาณ",
"network": "เครือข่าย | เครือข่าย",
"dependsOn": "Container Dependency | Container Dependencies",
"addListItem": "เพิ่ม {0}",
"deleteContainer": "ลบ",
"addContainer": "เพิ่ม Container",
"addNetwork": "เพิ่ม เครือข่าย",
"disableauth.message1": "คุณแน่ใจหรือไม่ว่าต้องการ <strong>ปิดใช้งานการตรวจสอบสิทธิ์</strong>?",
"disableauth.message2": "ได้รับการออกแบบมาสำหรับสถานการณ์ <strong>ที่คุณตั้งใจจะใช้การตรวจสอบสิทธิ์ของบุคคลที่สาม</strong> หน้า Dockge เช่น Cloudflare Access, Authelia หรือกลไกการตรวจสอบสิทธิ์อื่นๆ",
"passwordNotMatchMsg": "รหัสผ่านซ้ำไม่ตรงกัน",
"autoGet": "รับอัตโนมัติ",
"add": "เพิ่ม",
"Edit": "แก้ไข",
"applyToYAML": "นำไปใช้เป็น YAML",
"createExternalNetwork": "สร้าง",
"addInternalNetwork": "เพิ่ม",
"Save": "บันทึก",
"Language": "ภาษา",
"Current User": "ผู้ใช้งานปัจจุบัน",
"Change Password": "เปลี่ยนรหัสผ่าน",
"Current Password": "รหัสผ่านปัจจุบัน",
"New Password": "รหัสผ่านใหม่",
"Repeat New Password": "รหัสผ่านใหม่ซ้ำ",
"Update Password": "อัปเดตรหัสผ่าน",
"Advanced": "ขั้นสูง",
"Please use this option carefully!": "โปรดใช้ตัวเลือกนี้อย่างระมัดระวัง!",
"Enable Auth": "เปิดใช้งาน Auth",
"Disable Auth": "ปิดใช้งาน Auth",
"I understand, please disable": "ฉันเข้าใจ กรุณาปิดการใช้งาน",
"Leave": "ออก",
"Frontend Version": "เวอร์ชัน Frontend",
"Check Update On GitHub": "ตรวจสอบการอัปเดตบน GitHub",
"Show update if available": "แสดงการอัปเดตหากมี",
"Also check beta release": "สามารถตรวจสอบรุ่นเบต้าได้",
"Remember me": "จดจำฉัน",
"Login": "เข้าสู่ระบบ",
"Username": "ชื่อผู้ใช้",
"Password": "รหัสผ่าน",
"Settings": "การตั้งค่า",
"Logout": "ออกจากระบบ",
"Lowercase only": "ตัวเล็กทั้งหมด",
"Convert to Compose": "แปลงเป็น Compose",
"Docker Run": "เรียกใช้ Docker",
"active": "ใช้งานอยู่",
"exited": "ปิดลงแล้ว",
"inactive": "ไม่ได้ใช้งาน",
"Appearance": "รูปลักษณ์",
"Security": "ความปลอดภัย",
"About": "เกี่ยวกับ",
"Allowed commands:": "คำสั่งที่อนุญาต:",
"Internal Networks": "เครือข่ายภายใน",
"External Networks": "เครือข่ายภายนอก",
"No External Networks": "ไม่มีเครือข่ายภายนอก"
}

View file

@ -1,7 +1,10 @@
{
"languageName": "Türkçe",
"Create your admin account": "Yönetici hesabınızı oluşturun",
"authIncorrectCreds": "Yanlış kullanıcı adı veya parola.",
"PasswordsDoNotMatch": "Parolalar eşleşmiyor.",
"Repeat Password": "Parolayı Tekrarla",
"Create": "Oluştur",
"signedInDisp": "{0} olarak oturum açıldı",
"signedInDispDisabled": "Yetkilendirme Devre Dışı.",
"home": "Anasayfa",
@ -47,7 +50,45 @@
"passwordNotMatchMsg": "Tekrarlanan parola eşleşmiyor.",
"autoGet": "Otomatik Al",
"add": "Ekle",
"Edit": "Düzenle",
"applyToYAML": "YAML'ye uygulayın",
"createExternalNetwork": "Oluştur",
"addInternalNetwork": "Ekle"
"addInternalNetwork": "Ekle",
"Save": "Kaydet",
"Language": "Dil",
"Current User": "Mevcut Kullanıcı",
"Change Password": "Mevcut Parola",
"Current Password": "Mevcut Parola",
"New Password": "Yeni Parola",
"Repeat New Password": "Yeni Parolayı Tekrarla",
"Update Password": "Parolayı Güncelle",
"Advanced": "Gelişmiş",
"Please use this option carefully!": "Lütfen bu seçeneği dikkatli kullanın!",
"Enable Auth": "Kimlik Doğrulamayı Etkinleştir",
"Disable Auth": "Kimlik Doğrulamayı Devre Dışı Bırak",
"I understand, please disable": "Anlıyorum, lütfen devre dışı bırakın",
"Leave": "Ayrıl",
"Frontend Version": "Frontend Versiyon",
"Check Update On GitHub": "GitHub'da Güncellemeyi Kontrol Edin",
"Show update if available": "Varsa güncellemeyi göster",
"Also check beta release": "Ayrıca beta sürümünü kontrol edin",
"Remember me": "Beni Hatırla",
"Login": "Oturum Aç",
"Username": "Kullanıcı Adı",
"Password": "Parola",
"Settings": "Ayarlar",
"Logout": "Oturumu Kapat",
"Lowercase only": "Yalnızca küçük harf",
"Convert to Compose": "Compose'a Dönüştür",
"Docker Run": "Docker Run",
"active": "aktif",
"exited": ıkış yaptı",
"inactive": "aktif değil",
"Appearance": "Görünüm",
"Security": "Güvenlik",
"About": "Hakkında",
"Allowed commands:": "İzin verilen komutlar:",
"Internal Networks": "İç Ağlar",
"External Networks": "Dış Ağlar",
"No External Networks": "Dış Ağ Yok"
}

View file

@ -40,6 +40,13 @@
<font-awesome-icon icon="stop" class="me-1" />
{{ $t("stopStack") }}
</button>
<BDropdown v-if="!isEditMode && active" right text="" variant="normal">
<BDropdownItem @click="downStack">
<font-awesome-icon icon="stop" class="me-1" />
{{ $t("downStack") }}
</BDropdownItem>
</BDropdown>
</div>
<button v-if="isEditMode && !isAdd" class="btn btn-normal" :disabled="processing" @click="discardStack">{{ $t("discardStack") }}</button>
@ -312,6 +319,12 @@ export default {
},
deep: true,
},
$route(to, from) {
// Leave Combined Terminal
console.debug("leaveCombinedTerminal", from.params.stackName);
this.$root.getSocket().emit("leaveCombinedTerminal", this.stack.name, () => {});
}
},
mounted() {
if (this.isAdd) {
@ -354,7 +367,7 @@ export default {
clearTimeout(serviceStatusTimeout);
serviceStatusTimeout = setTimeout(async () => {
this.requestServiceStatus();
}, 2000);
}, 5000);
},
requestServiceStatus() {
@ -473,6 +486,15 @@ export default {
});
},
downStack() {
this.processing = true;
this.$root.getSocket().emit("downStack", this.stack.name, (res) => {
this.processing = false;
this.$root.toastRes(res);
});
},
restartStack() {
this.processing = true;
@ -528,10 +550,6 @@ export default {
throw new Error("Services must be an object");
}
if (!config.version) {
config.version = "3.8";
}
this.yamlDoc = doc;
this.jsonConfig = config;

View file

@ -1,13 +1,13 @@
{
"name": "dockge",
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"scripts": {
"fmt": "eslint \"**/*.{ts,vue}\" --fix",
"lint": "eslint \"**/*.{ts,vue}\"",
"check-ts": "tsc --noEmit",
"start": "tsx ./backend/index.ts",
"dev:backend": "cross-env NODE_ENV=development tsx watch ./backend/index.ts",
"dev:backend": "cross-env NODE_ENV=development tsx watch --inspect ./backend/index.ts",
"dev:frontend": "cross-env NODE_ENV=development vite --host --config ./frontend/vite.config.ts",
"release-final": "tsx ./extra/test-docker.ts && tsx extra/update-version.ts && pnpm run build:frontend && npm run build:docker",
"build:frontend": "vite build --config ./frontend/vite.config.ts",
@ -15,7 +15,8 @@
"build:docker": "node ./extra/env2arg.js docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/dockge:latest -t louislam/dockge:1 -t louislam/dockge:$VERSION --target release -f ./docker/Dockerfile . --push",
"build:docker-nightly": "pnpm run build:frontend && docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/dockge:nightly --target nightly -f ./docker/Dockerfile . --push",
"start-docker": "docker run --rm -p 5001:5001 --name dockge louislam/dockge:latest",
"mark-as-nightly": "tsx ./extra/mark-as-nightly.ts"
"mark-as-nightly": "tsx ./extra/mark-as-nightly.ts",
"reformat-changelog": "tsx ./extra/reformat-changelog.ts"
},
"dependencies": {
"@homebridge/node-pty-prebuilt-multiarch": "~0.11.11",
@ -45,6 +46,7 @@
"yaml": "~2.3.4"
},
"devDependencies": {
"@actions/github": "^6.0.0",
"@fontsource/jetbrains-mono": "^5.0.17",
"@fortawesome/fontawesome-svg-core": "6.4.2",
"@fortawesome/free-regular-svg-icons": "6.4.2",

139
pnpm-lock.yaml generated
View file

@ -82,6 +82,9 @@ dependencies:
version: 2.3.4
devDependencies:
'@actions/github':
specifier: ^6.0.0
version: 6.0.0
'@fontsource/jetbrains-mono':
specifier: ^5.0.17
version: 5.0.17
@ -192,6 +195,22 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/@actions/github@6.0.0:
resolution: {integrity: sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==}
dependencies:
'@actions/http-client': 2.2.0
'@octokit/core': 5.0.1
'@octokit/plugin-paginate-rest': 9.1.4(@octokit/core@5.0.1)
'@octokit/plugin-rest-endpoint-methods': 10.1.5(@octokit/core@5.0.1)
dev: true
/@actions/http-client@2.2.0:
resolution: {integrity: sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==}
dependencies:
tunnel: 0.0.6
undici: 5.27.2
dev: true
/@antfu/utils@0.7.6:
resolution: {integrity: sha512-pvFiLP2BeOKA/ZOS6jxx4XhKzdVLHDhGlFEaZ2flWWYf2xOqVniqpk38I04DFRyz+L0ASggl7SkItTc+ZLju4w==}
dev: true
@ -665,6 +684,11 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@fastify/busboy@2.1.0:
resolution: {integrity: sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==}
engines: {node: '>=14'}
dev: true
/@floating-ui/core@1.5.0:
resolution: {integrity: sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==}
dependencies:
@ -884,6 +908,92 @@ packages:
dev: false
optional: true
/@octokit/auth-token@4.0.0:
resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==}
engines: {node: '>= 18'}
dev: true
/@octokit/core@5.0.1:
resolution: {integrity: sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==}
engines: {node: '>= 18'}
dependencies:
'@octokit/auth-token': 4.0.0
'@octokit/graphql': 7.0.2
'@octokit/request': 8.1.5
'@octokit/request-error': 5.0.1
'@octokit/types': 12.3.0
before-after-hook: 2.2.3
universal-user-agent: 6.0.1
dev: true
/@octokit/endpoint@9.0.2:
resolution: {integrity: sha512-qhKW8YLIi+Kmc92FQUFGr++DYtkx/1fBv+Thua6baqnjnOsgBYJDCvWZR1YcINuHGOEQt416WOfE+A/oG60NBQ==}
engines: {node: '>= 18'}
dependencies:
'@octokit/types': 12.3.0
is-plain-object: 5.0.0
universal-user-agent: 6.0.1
dev: true
/@octokit/graphql@7.0.2:
resolution: {integrity: sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==}
engines: {node: '>= 18'}
dependencies:
'@octokit/request': 8.1.5
'@octokit/types': 12.3.0
universal-user-agent: 6.0.1
dev: true
/@octokit/openapi-types@19.0.2:
resolution: {integrity: sha512-8li32fUDUeml/ACRp/njCWTsk5t17cfTM1jp9n08pBrqs5cDFJubtjsSnuz56r5Tad6jdEPJld7LxNp9dNcyjQ==}
dev: true
/@octokit/plugin-paginate-rest@9.1.4(@octokit/core@5.0.1):
resolution: {integrity: sha512-MvZx4WvfhBnt7PtH5XE7HORsO7bBk4er1FgRIUr1qJ89NR2I6bWjGyKsxk8z42FPQ34hFQm0Baanh4gzdZR4gQ==}
engines: {node: '>= 18'}
peerDependencies:
'@octokit/core': '>=5'
dependencies:
'@octokit/core': 5.0.1
'@octokit/types': 12.3.0
dev: true
/@octokit/plugin-rest-endpoint-methods@10.1.5(@octokit/core@5.0.1):
resolution: {integrity: sha512-LMEdsMV8TTMjMTqVoqMzV95XTbv0ZsWxCxQtjAunQOCdwoDH4BVF/Ke5JMSZEVCWGI2kzxnUNbFnK/MxwV7NjA==}
engines: {node: '>= 18'}
peerDependencies:
'@octokit/core': '>=5'
dependencies:
'@octokit/core': 5.0.1
'@octokit/types': 12.3.0
dev: true
/@octokit/request-error@5.0.1:
resolution: {integrity: sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==}
engines: {node: '>= 18'}
dependencies:
'@octokit/types': 12.3.0
deprecation: 2.3.1
once: 1.4.0
dev: true
/@octokit/request@8.1.5:
resolution: {integrity: sha512-zVKbNbX1xUluD9ZR4/tPs1yuYrK9xeh5fGZUXA6u04XGsTvomg0YO8/ZUC0FqAd49hAOEMFPAVUTh+2lBhOhLA==}
engines: {node: '>= 18'}
dependencies:
'@octokit/endpoint': 9.0.2
'@octokit/request-error': 5.0.1
'@octokit/types': 12.3.0
is-plain-object: 5.0.0
universal-user-agent: 6.0.1
dev: true
/@octokit/types@12.3.0:
resolution: {integrity: sha512-nJ8X2HRr234q3w/FcovDlA+ttUU4m1eJAourvfUUtwAWeqL8AsyRqfnLvVnYn3NFbUnsmzQCzLNdFerPwdmcDQ==}
dependencies:
'@octokit/openapi-types': 19.0.2
dev: true
/@pkgjs/parseargs@0.11.0:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
@ -1567,6 +1677,10 @@ packages:
resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==}
dev: false
/before-after-hook@2.2.3:
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
dev: true
/binary-extensions@2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'}
@ -2005,6 +2119,10 @@ packages:
engines: {node: '>= 0.8'}
dev: false
/deprecation@2.3.1:
resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==}
dev: true
/destroy@1.2.0:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
@ -2924,6 +3042,11 @@ packages:
engines: {node: '>=8'}
dev: true
/is-plain-object@5.0.0:
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
engines: {node: '>=0.10.0'}
dev: true
/is-property@1.0.2:
resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==}
dev: false
@ -4408,6 +4531,11 @@ packages:
safe-buffer: 5.2.1
dev: false
/tunnel@0.0.6:
resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==}
engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'}
dev: true
/type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
@ -4452,6 +4580,13 @@ packages:
/undici-types@5.26.5:
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
/undici@5.27.2:
resolution: {integrity: sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==}
engines: {node: '>=14.0'}
dependencies:
'@fastify/busboy': 2.1.0
dev: true
/unique-filename@1.1.1:
resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==}
requiresBuild: true
@ -4468,6 +4603,10 @@ packages:
dev: false
optional: true
/universal-user-agent@6.0.1:
resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==}
dev: true
/universalify@2.0.1:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}

View file

@ -8,5 +8,5 @@
},
"include": [
"backend/**/*"
],
]
}