瀏覽代碼

Add "docker compose down" (#122)

Louis Lam 1 年之前
父節點
當前提交
e95ef66ca1

+ 21 - 0
backend/socket-handlers/docker-socket-handler.ts

@@ -187,6 +187,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
         // Services status
         socket.on("serviceStatusList", async (stackName : unknown, callback) => {
         socket.on("serviceStatusList", async (stackName : unknown, callback) => {
             try {
             try {

+ 9 - 0
backend/stack.ts

@@ -330,6 +330,15 @@ export class Stack {
         return exitCode;
         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) {
     async update(socket: DockgeSocket) {
         const terminalName = getComposeTerminalName(this.name);
         const terminalName = getComposeTerminalName(this.name);
         let exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", [ "compose", "pull" ], this.path);
         let exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", [ "compose", "pull" ], this.path);

+ 3 - 0
frontend/components.d.ts

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

+ 1 - 0
frontend/src/lang/en.json

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

+ 16 - 0
frontend/src/pages/Compose.vue

@@ -40,6 +40,13 @@
                         <font-awesome-icon icon="stop" class="me-1" />
                         <font-awesome-icon icon="stop" class="me-1" />
                         {{ $t("stopStack") }}
                         {{ $t("stopStack") }}
                     </button>
                     </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>
                 </div>
 
 
                 <button v-if="isEditMode && !isAdd" class="btn btn-normal" :disabled="processing" @click="discardStack">{{ $t("discardStack") }}</button>
                 <button v-if="isEditMode && !isAdd" class="btn btn-normal" :disabled="processing" @click="discardStack">{{ $t("discardStack") }}</button>
@@ -473,6 +480,15 @@ export default {
             });
             });
         },
         },
 
 
+        downStack() {
+            this.processing = true;
+
+            this.$root.getSocket().emit("downStack", this.stack.name, (res) => {
+                this.processing = false;
+                this.$root.toastRes(res);
+            });
+        },
+
         restartStack() {
         restartStack() {
             this.processing = true;
             this.processing = true;