mirror of
https://github.com/louislam/dockge.git
synced 2026-05-21 22:12:17 +00:00
wip
This commit is contained in:
@@ -71,6 +71,7 @@
|
||||
<script>
|
||||
import Confirm from "../components/Confirm.vue";
|
||||
import StackListItem from "../components/StackListItem.vue";
|
||||
import { CREATED_FILE, CREATED_STACK, EXITED, RUNNING, UNKNOWN } from "../../../backend/util-common";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -154,8 +155,30 @@ export default {
|
||||
return searchTextMatch && activeMatch && tagsMatch;
|
||||
});
|
||||
|
||||
// Filter result by active state, weight and alphabetical
|
||||
result.sort((m1, m2) => {
|
||||
if (m1.status !== m2.status) {
|
||||
if (m2.status === RUNNING) {
|
||||
return 1;
|
||||
} else if (m1.status === RUNNING) {
|
||||
return -1;
|
||||
} else if (m2.status === EXITED) {
|
||||
return 1;
|
||||
} else if (m1.status === EXITED) {
|
||||
return -1;
|
||||
} else if (m2.status === CREATED_STACK) {
|
||||
return 1;
|
||||
} else if (m1.status === CREATED_STACK) {
|
||||
return -1;
|
||||
} else if (m2.status === CREATED_FILE) {
|
||||
return 1;
|
||||
} else if (m1.status === CREATED_FILE) {
|
||||
return -1;
|
||||
} else if (m2.status === UNKNOWN) {
|
||||
return 1;
|
||||
} else if (m1.status === UNKNOWN) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return m1.name.localeCompare(m2.name);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div :class="{ 'dim' : !stack.isManagedByDockge }">
|
||||
<div :style="depthMargin">
|
||||
<!-- Checkbox -->
|
||||
<div v-if="isSelectMode" class="select-input-wrapper">
|
||||
@@ -16,7 +16,7 @@
|
||||
<div class="row">
|
||||
<div class="col-9 col-md-8 small-padding">
|
||||
<div class="info">
|
||||
<Uptime :stack="stack" type="24" :pill="true" />
|
||||
<Uptime :stack="stack" :fixed-width="true" />
|
||||
{{ stackName }}
|
||||
</div>
|
||||
<div v-if="stack.tags.length > 0" class="tags">
|
||||
@@ -36,7 +36,6 @@ import Uptime from "./Uptime.vue";
|
||||
export default {
|
||||
components: {
|
||||
Uptime
|
||||
|
||||
},
|
||||
props: {
|
||||
/** Stack this represents */
|
||||
@@ -181,4 +180,8 @@ export default {
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
.dim {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -46,7 +46,7 @@ export default {
|
||||
rows: this.rows,
|
||||
});
|
||||
|
||||
this.terminal.loadAddon(new WebLinksAddon());
|
||||
//this.terminal.loadAddon(new WebLinksAddon());
|
||||
|
||||
// Bind to a div
|
||||
this.terminal.open(this.$refs.terminal);
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
<template>
|
||||
<span :class="className" :title="title">{{ uptime }}</span>
|
||||
<span :class="className">{{ statusName }}</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { statusColor, statusNameShort } from "../../../backend/util-common";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
/** Monitor this represents */
|
||||
monitor: {
|
||||
stack: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
/** Type of monitor */
|
||||
type: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
/** Is this a pill? */
|
||||
pill: {
|
||||
fixedWidth: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
@@ -25,28 +19,26 @@ export default {
|
||||
|
||||
computed: {
|
||||
uptime() {
|
||||
return "0.00%";
|
||||
return this.$t("notAvailableShort");
|
||||
},
|
||||
|
||||
color() {
|
||||
return "secondary";
|
||||
return statusColor(this.stack?.status);
|
||||
},
|
||||
|
||||
statusName() {
|
||||
return this.$t(statusNameShort(this.stack?.status));
|
||||
},
|
||||
|
||||
className() {
|
||||
if (this.pill) {
|
||||
return `badge rounded-pill bg-${this.color}`;
|
||||
}
|
||||
let className = `badge rounded-pill bg-${this.color}`;
|
||||
|
||||
return "";
|
||||
if (this.fixedWidth) {
|
||||
className += " fixed-width";
|
||||
}
|
||||
return className;
|
||||
},
|
||||
|
||||
title() {
|
||||
if (this.type === "720") {
|
||||
return `30${this.$t("-day")}`;
|
||||
}
|
||||
|
||||
return `24${this.$t("-hour")}`;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -55,4 +47,8 @@ export default {
|
||||
.badge {
|
||||
min-width: 62px;
|
||||
}
|
||||
|
||||
.fixed-width {
|
||||
width: 62px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -18,5 +18,7 @@
|
||||
"editStack": "Edit",
|
||||
"discardStack": "Discard",
|
||||
"saveStackDraft": "Save",
|
||||
"notAvailableShort" : "N/A"
|
||||
"notAvailableShort" : "N/A",
|
||||
"deleteStackMsg": "Are you sure you want to delete this stack?",
|
||||
"stackNotManagedByDockgeMsg": "This stack is not managed by Dockge."
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import App from "./App.vue";
|
||||
import { router } from "./router";
|
||||
import { FontAwesomeIcon } from "./icon.js";
|
||||
import { i18n } from "./i18n";
|
||||
await import("../../backend/util-common");
|
||||
|
||||
// Dependencies
|
||||
import "bootstrap";
|
||||
@@ -25,10 +26,6 @@ import socket from "./mixins/socket";
|
||||
import lang from "./mixins/lang";
|
||||
import theme from "./mixins/theme";
|
||||
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
const app = createApp(rootApp());
|
||||
|
||||
app.use(Toast, {
|
||||
|
||||
@@ -203,6 +203,20 @@ export default defineComponent({
|
||||
this.stackList = res.stackList;
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("stackStatusList", (res) => {
|
||||
if (res.ok) {
|
||||
|
||||
console.log(res.stackStatusList);
|
||||
|
||||
for (let stackName in res.stackStatusList) {
|
||||
const stackObj = this.stackList[stackName];
|
||||
if (stackObj) {
|
||||
stackObj.status = res.stackStatusList[stackName];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<transition name="slide-fade" appear>
|
||||
<div>
|
||||
<h1 v-if="isAdd" class="mb-3">Compose</h1>
|
||||
<h1 v-else class="mb-3">Stack: {{ stack.name }}</h1>
|
||||
<h1 v-else class="mb-3"><Uptime :stack="globalStack" :pill="true" /> {{ stack.name }}</h1>
|
||||
|
||||
<div class="mb-3">
|
||||
<div v-if="stack.isManagedByDockge" class="mb-3">
|
||||
<div class="btn-group" role="group">
|
||||
<button v-if="isEditMode" class="btn btn-primary" :disabled="processing" @click="deployStack">
|
||||
<font-awesome-icon icon="rocket" class="me-1" />
|
||||
@@ -18,10 +18,11 @@
|
||||
|
||||
<button v-if="!isEditMode" class="btn btn-normal" :disabled="processing" @click="isEditMode = true">{{ $t("editStack") }}</button>
|
||||
<button v-if="isEditMode && !isAdd" class="btn btn-normal" :disabled="processing" @click="discardStack">{{ $t("discardStack") }}</button>
|
||||
<button v-if="!isEditMode" class="btn btn-primary" :disabled="processing">{{ $t("updateStack") }}</button>
|
||||
<button v-if="!isEditMode" class="btn btn-primary" :disabled="processing">{{ $t("startStack") }}</button>
|
||||
<button v-if="!isEditMode" class="btn btn-primary " :disabled="processing">{{ $t("restartStack") }}</button>
|
||||
<button v-if="!isEditMode" class="btn btn-danger" :disabled="processing">{{ $t("stopStack") }}</button>
|
||||
<button v-if="!isEditMode" class="btn btn-danger" :disabled="processing">{{ $t("deleteStack") }}</button>
|
||||
<button v-if="!isEditMode" class="btn btn-danger" :disabled="processing" @click="showDeleteDialog = !showDeleteDialog">{{ $t("deleteStack") }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -33,18 +34,20 @@
|
||||
:allow-input="false"
|
||||
class="mb-3 terminal"
|
||||
:rows="progressTerminalRows"
|
||||
@has-data="showProgressTerminal = true"
|
||||
@has-data="showProgressTerminal = true; submitted = true;"
|
||||
></Terminal>
|
||||
</transition>
|
||||
|
||||
<div class="row">
|
||||
<div v-if="stack.isManagedByDockge" class="row">
|
||||
<div class="col">
|
||||
<h4 class="mb-3">General</h4>
|
||||
<div class="shadow-box big-padding mb-3">
|
||||
<!-- Stack Name -->
|
||||
<div v-if="isAdd" class="mb-3">
|
||||
<label for="name" class="form-label">{{ $t("stackName") }}</label>
|
||||
<input id="name" v-model="stack.name" type="text" class="form-control" required>
|
||||
<div v-if="isAdd">
|
||||
<h4 class="mb-3">General</h4>
|
||||
<div class="shadow-box big-padding mb-3">
|
||||
<!-- Stack Name -->
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">{{ $t("stackName") }}</label>
|
||||
<input id="name" v-model="stack.name" type="text" class="form-control" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -58,8 +61,9 @@
|
||||
<div class="col">
|
||||
<h4 class="mb-3">compose.yaml</h4>
|
||||
|
||||
<div class="shadow-box mb-3">
|
||||
<prism-editor v-model="stack.composeYAML" class="yaml-editor" :highlight="highlighter" line-numbers :readonly="!isEditMode" @input="yamlCodeChange"></prism-editor>
|
||||
<!-- YAML editor -->
|
||||
<div class="shadow-box mb-3 editor-box" :class="{'edit-mode' : isEditMode}">
|
||||
<prism-editor ref="editor" v-model="stack.composeYAML" class="yaml-editor" :highlight="highlighter" line-numbers :readonly="!isEditMode" @input="yamlCodeChange"></prism-editor>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
{{ yamlError }}
|
||||
@@ -75,6 +79,15 @@
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!stack.isManagedByDockge">
|
||||
{{ $t("stackNotManagedByDockgeMsg") }}
|
||||
</div>
|
||||
|
||||
<!-- Delete Dialog -->
|
||||
<BModal v-model="showDeleteDialog" :okTitle="$t('deleteStack')" okVariant="danger" @ok="deleteDialog">
|
||||
{{ $t("deleteStackMsg") }}
|
||||
</BModal>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
@@ -89,6 +102,7 @@ import "prismjs/themes/prism-tomorrow.css";
|
||||
import "vue-prism-editor/dist/prismeditor.min.css";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { getComposeTerminalName, PROGRESS_TERMINAL_ROWS } from "../../../backend/util-common";
|
||||
import { BModal } from "bootstrap-vue-next";
|
||||
|
||||
const template = `version: "3.8"
|
||||
services:
|
||||
@@ -104,6 +118,7 @@ export default {
|
||||
components: {
|
||||
FontAwesomeIcon,
|
||||
PrismEditor,
|
||||
BModal,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -112,15 +127,26 @@ export default {
|
||||
processing: true,
|
||||
showProgressTerminal: false,
|
||||
progressTerminalRows: PROGRESS_TERMINAL_ROWS,
|
||||
stack: {},
|
||||
stack: {
|
||||
|
||||
},
|
||||
isEditMode: false,
|
||||
submitted: false,
|
||||
showDeleteDialog: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isAdd() {
|
||||
return this.$route.path === "/compose" && !this.submitted;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the stack from the global stack list, because it may contain more real-time data like status
|
||||
* @return {*}
|
||||
*/
|
||||
globalStack() {
|
||||
return this.$root.stackList[this.stack.name];
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
"stack.composeYAML": {
|
||||
@@ -139,6 +165,7 @@ export default {
|
||||
this.stack = {
|
||||
name: "",
|
||||
composeYAML: template,
|
||||
isManagedByDockge: true,
|
||||
};
|
||||
|
||||
} else {
|
||||
@@ -147,11 +174,17 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
bindTerminal() {
|
||||
// Bind Terminal output
|
||||
const terminalName = getComposeTerminalName(this.stack.name);
|
||||
this.$refs.progressTerminal.bind(terminalName);
|
||||
},
|
||||
loadStack() {
|
||||
this.$root.getSocket().emit("getStack", this.stack.name, (res) => {
|
||||
if (res.ok) {
|
||||
this.stack = res.stack;
|
||||
this.processing = false;
|
||||
this.bindTerminal();
|
||||
} else {
|
||||
this.$root.toastRes(res);
|
||||
}
|
||||
@@ -160,9 +193,7 @@ export default {
|
||||
deployStack() {
|
||||
this.processing = true;
|
||||
|
||||
// Bind Terminal output
|
||||
const terminalName = getComposeTerminalName(this.stack.name);
|
||||
this.$refs.progressTerminal.bind(terminalName);
|
||||
this.bindTerminal();
|
||||
|
||||
this.$root.getSocket().emit("deployStack", this.stack.name, this.stack.composeYAML, this.isAdd, (res) => {
|
||||
this.processing = false;
|
||||
@@ -170,8 +201,6 @@ export default {
|
||||
|
||||
if (res.ok) {
|
||||
this.$router.push("/compose/" + this.stack.name);
|
||||
} else {
|
||||
this.submitted = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -187,6 +216,14 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
deleteDialog() {
|
||||
this.$root.getSocket().emit("deleteStack", this.stack.name, (res) => {
|
||||
this.$root.toastRes(res);
|
||||
if (res.ok) {
|
||||
this.$router.push("/");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
discardStack() {
|
||||
this.loadStack();
|
||||
@@ -221,4 +258,8 @@ export default {
|
||||
.terminal {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.editor-box.edit-mode {
|
||||
background-color: #2c2f38 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Terminal :allow-input="true" class="terminal"></Terminal>
|
||||
<Terminal ref="terminal" :allow-input="true" class="terminal" :rows="20"></Terminal>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
@@ -20,7 +20,16 @@ export default {
|
||||
components: {
|
||||
},
|
||||
mounted() {
|
||||
this.$root.terminalFit(50);
|
||||
// Bind Terminal Component to Socket.io
|
||||
const terminalName = "console";
|
||||
this.$refs.terminal.bind(terminalName);
|
||||
|
||||
// Create a new Terminal
|
||||
this.$root.getSocket().emit("mainTerminal", terminalName, (res) => {
|
||||
if (!res.ok) {
|
||||
this.$root.toastRes(res);
|
||||
}
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user