dockge/frontend/src/pages/DashboardHome.vue

232 lines
6.3 KiB
Vue

<template>
<transition ref="tableContainer" name="slide-fade" appear>
<div v-if="$route.name === 'DashboardHome'">
<h1 class="mb-3">
{{ $t("home") }}
</h1>
<div class="shadow-box big-padding text-center mb-4">
<div class="row">
<div class="col">
<h3>{{ $t("active") }}</h3>
<span class="num active">{{ activeNum }}</span>
</div>
<div class="col">
<h3>{{ $t("exited") }}</h3>
<span class="num exited">{{ exitedNum }}</span>
</div>
<div class="col">
<h3>{{ $t("inactive") }}</h3>
<span class="num inactive">{{ inactiveNum }}</span>
</div>
</div>
</div>
<h2 class="mb-3">Docker Run</h2>
<div class="mb-3">
<textarea id="name" v-model="dockerRunCommand" type="text" class="form-control docker-run" required placeholder="docker run ..."></textarea>
</div>
<button class="btn-normal btn" @click="convertDockerRun">Convert to Compose</button>
</div>
</transition>
<router-view ref="child" />
</template>
<script>
import { statusNameShort } from "../../../backend/util-common";
export default {
components: {
},
props: {
calculatedHeight: {
type: Number,
default: 0
}
},
data() {
return {
page: 1,
perPage: 25,
initialPerPage: 25,
paginationConfig: {
hideCount: true,
chunksNavigation: "scroll",
},
importantHeartBeatListLength: 0,
displayedRecords: [],
dockerRunCommand: "",
};
},
computed: {
activeNum() {
return this.getStatusNum("active");
},
inactiveNum() {
return this.getStatusNum("inactive");
},
exitedNum() {
return this.getStatusNum("exited");
},
},
watch: {
perPage() {
this.$nextTick(() => {
this.getImportantHeartbeatListPaged();
});
},
page() {
this.getImportantHeartbeatListPaged();
},
},
mounted() {
this.initialPerPage = this.perPage;
window.addEventListener("resize", this.updatePerPage);
this.updatePerPage();
},
beforeUnmount() {
window.removeEventListener("resize", this.updatePerPage);
},
methods: {
getStatusNum(statusName) {
let num = 0;
for (let stackName in this.$root.stackList) {
const stack = this.$root.stackList[stackName];
if (statusNameShort(stack.status) === statusName) {
num += 1;
}
}
return num;
},
convertDockerRun() {
if (this.dockerRunCommand.trim() === "docker run") {
throw new Error("Please enter a docker run command");
}
// composerize is working in dev, but after "vite build", it is not working
// So pass to backend to do the conversion
this.$root.getSocket().emit("composerize", this.dockerRunCommand, (res) => {
if (res.ok) {
this.$root.composeTemplate = res.composeTemplate;
this.$router.push("/compose");
} else {
this.$root.toastRes(res);
}
});
},
/**
* Updates the displayed records when a new important heartbeat arrives.
* @param {object} heartbeat - The heartbeat object received.
* @returns {void}
*/
onNewImportantHeartbeat(heartbeat) {
if (this.page === 1) {
this.displayedRecords.unshift(heartbeat);
if (this.displayedRecords.length > this.perPage) {
this.displayedRecords.pop();
}
this.importantHeartBeatListLength += 1;
}
},
/**
* Retrieves the length of the important heartbeat list for all monitors.
* @returns {void}
*/
getImportantHeartbeatListLength() {
this.$root.getSocket().emit("monitorImportantHeartbeatListCount", null, (res) => {
if (res.ok) {
this.importantHeartBeatListLength = res.count;
this.getImportantHeartbeatListPaged();
}
});
},
/**
* Retrieves the important heartbeat list for the current page.
* @returns {void}
*/
getImportantHeartbeatListPaged() {
const offset = (this.page - 1) * this.perPage;
this.$root.getSocket().emit("monitorImportantHeartbeatListPaged", null, offset, this.perPage, (res) => {
if (res.ok) {
this.displayedRecords = res.data;
}
});
},
/**
* Updates the number of items shown per page based on the available height.
* @returns {void}
*/
updatePerPage() {
const tableContainer = this.$refs.tableContainer;
const tableContainerHeight = tableContainer.offsetHeight;
const availableHeight = window.innerHeight - tableContainerHeight;
const additionalPerPage = Math.floor(availableHeight / 58);
if (additionalPerPage > 0) {
this.perPage = Math.max(this.initialPerPage, this.perPage + additionalPerPage);
} else {
this.perPage = this.initialPerPage;
}
},
},
};
</script>
<style lang="scss" scoped>
@import "../styles/vars";
.num {
font-size: 30px;
font-weight: bold;
display: block;
&.active {
color: $primary;
}
&.exited {
color: $danger;
}
}
.shadow-box {
padding: 20px;
}
table {
font-size: 14px;
tr {
transition: all ease-in-out 0.2ms;
}
@media (max-width: 550px) {
table-layout: fixed;
overflow-wrap: break-word;
}
}
.docker-run {
background-color: $dark-bg !important;
border: none;
}
</style>