[status page] checkpoint

This commit is contained in:
LouisLam 2021-09-13 19:21:39 +08:00
parent e205adfd7b
commit 35aca46b68
6 changed files with 203 additions and 57 deletions

View file

@ -301,6 +301,20 @@ h2 {
opacity: 0;
}
.slide-fade-right-enter-active {
transition: all 0.2s $easing-in;
}
.slide-fade-right-leave-active {
transition: all 0.2s $easing-in;
}
.slide-fade-right-enter-from,
.slide-fade-right-leave-to {
transform: translateX(50px);
opacity: 0;
}
.monitor-list {
&.scrollbar {
min-height: calc(100vh - 240px);

View file

@ -0,0 +1,96 @@
<template>
<!-- Group List -->
<Draggable
v-model="$root.publicGroupList"
:disabled="!editMode"
item-key="id"
:animation="100"
>
<template #item="{ element }">
<div>
<h2 class="mt-5">{{ element.name }}</h2>
<div class="shadow-box monitor-list mt-4 position-relative">
<div v-if="element.monitorList.length === 0" class="text-center no-monitor-msg">
{{ $t("No Monitors") }}
</div>
<!-- Monitor List -->
<Draggable
v-model="element.monitorList"
class="monitor-list"
group="same-group"
:disabled="!editMode"
:animation="100"
>
<template #item="{ element }">
<div class="item">
<div class="row">
<div class="col-6 col-md-8 small-padding">
<div class="info">
<Uptime :monitor="element" type="24" :pill="true" />
{{ element.name }}
</div>
</div>
<div :key="$root.userHeartbeatBar" class="col-6 col-md-4">
<HeartbeatBar size="small" :monitor-id="element.id" />
</div>
</div>
</div>
</template>
</Draggable>
</div>
</div>
</template>
</Draggable>
</template>
<script>
import Draggable from "vuedraggable";
import HeartbeatBar from "./HeartbeatBar.vue";
import Uptime from "./Uptime.vue";
export default {
name: "GroupList",
components: {
Draggable,
HeartbeatBar,
Uptime,
},
props: {
editMode: {
type: Boolean,
required: true,
},
},
data() {
return {
}
},
created() {
}
}
</script>
<style lang="scss" scoped>
.no-monitor-msg {
position: absolute;
width: 100%;
top: 20px;
left: 0;
}
.monitor-list {
min-height: 46px;
}
.flip-list-move {
transition: transform 0.5s;
}
.no-move {
transition: transform 0s;
}
</style>

View file

@ -1,10 +1,10 @@
import { library } from "@fortawesome/fontawesome-svg-core"
import { faCog, faEdit, faPlus, faPause, faPlay, faTachometerAlt, faTrash, faList, faArrowAltCircleUp, faEye, faEyeSlash, faCheckCircle, faStream } from "@fortawesome/free-solid-svg-icons"
import { faCog, faEdit, faPlus, faPause, faPlay, faTachometerAlt, faTrash, faList, faArrowAltCircleUp, faEye, faEyeSlash, faCheckCircle, faStream, faSave } from "@fortawesome/free-solid-svg-icons"
//import { fa } from '@fortawesome/free-regular-svg-icons'
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"
// Add Free Font Awesome Icons here
// https://fontawesome.com/v5.15/icons?d=gallery&p=2&s=solid&m=free
library.add(faCog, faEdit, faPlus, faPause, faPlay, faTachometerAlt, faTrash, faList, faArrowAltCircleUp, faEye, faEyeSlash, faCheckCircle, faStream);
library.add(faCog, faEdit, faPlus, faPause, faPlay, faTachometerAlt, faTrash, faList, faArrowAltCircleUp, faEye, faEyeSlash, faCheckCircle, faStream, faSave);
export { FontAwesomeIcon }

View file

@ -13,6 +13,8 @@ import socket from "./mixins/socket";
import theme from "./mixins/theme";
import mobile from "./mixins/mobile";
import datetime from "./mixins/datetime";
import publicMixin from "./mixins/public";
import Dashboard from "./pages/Dashboard.vue";
import DashboardHome from "./pages/DashboardHome.vue";
import Details from "./pages/Details.vue";
@ -140,7 +142,8 @@ const app = createApp({
socket,
theme,
mobile,
datetime
datetime,
publicMixin,
],
data() {
return {

7
src/mixins/public.js Normal file
View file

@ -0,0 +1,7 @@
export default {
data() {
return {
publicGroupList: [],
}
}
}

View file

@ -2,58 +2,61 @@
<div class="container mt-3">
<h1><img src="/icon.svg" alt /> Uptime Kuma</h1>
<div v-if="hasToken" class="mt-3">
<button v-if="!enableEditMode" class="btn btn-info me-2" @click="edit">
<div v-if="hasToken" class="mt-3" style="height: 38px;">
<div v-if="!enableEditMode">
<button class="btn btn-info me-2" @click="edit">
<font-awesome-icon icon="edit" />
Edit Status Page
</button>
<button v-if="enableEditMode" class="btn btn-dark me-2" @click="leaveEditMode">
<font-awesome-icon icon="" />
Leave Edit Mode
</button>
<router-link v-if="!enableEditMode" to="/dashboard" class="btn btn-info">
<router-link to="/dashboard" class="btn btn-info">
<font-awesome-icon icon="tachometer-alt" />
Go to Dashboard
</router-link>
</div>
<div v-else>
<button class="btn btn-success me-2" @click="leaveEditMode">
<font-awesome-icon icon="save" />
{{ $t("Save") }}
</button>
<button class="btn btn-danger me-2" @click="">
<font-awesome-icon icon="save" />
{{ $t("Discard") }}
</button>
<!-- Set Default Language -->
<!-- Set theme -->
</div>
</div>
<div class="shadow-box list p-4 overall-status mt-4">
<font-awesome-icon icon="check-circle" class="ok" /> All Systems Operational
</div>
<div v-if="showEditFeature" class="mt-4">
<div v-if="showEditFeature" class="row mt-4" style="height: 43px;">
<div class="col-2">
<button class="btn btn-primary btn-add-group" @click="addGroup">Add Group</button>
</div>
<div class="col-10">
<div>
<VueMultiselect
v-model="selectedMonitor"
:options="allMonitorList"
:custom-label="monitorSelectorLabel"
:searchable="true"
@select="onSelectedMonitor"
placeholder="Add a monitor"
></VueMultiselect>
</div>
<div class="shadow-box monitor-list mt-4">
<div v-if="Object.keys(monitorList).length === 0" class="text-center my-3">
{{ $t("No Monitors") }}
</div>
<div v-for="(item, index) in monitorList" :key="index" class="item">
<div class="row">
<div class="col-6 col-md-8 small-padding">
<div class="info">
<Uptime :monitor="item" type="24" :pill="true" />
{{ item.name }}
</div>
</div>
<div :key="$root.userHeartbeatBar" class="col-6 col-md-4">
<HeartbeatBar size="small" :monitor-id="item.id" />
</div>
</div>
</div>
</div>
<footer class="mt-4">
<div>
<GroupList :edit-mode="enableEditMode" />
</div>
<footer class="my-4">
Powered by <a target="_blank" href="https://github.com/louislam/uptime-kuma">Uptime Kuma</a>
</footer>
</div>
@ -61,12 +64,8 @@
<script>
import VueMultiselect from "vue-multiselect"
import { useToast } from "vue-toastification";
const toast = useToast();
import axios from "axios";
import HeartbeatBar from "../components/HeartbeatBar.vue";
import Uptime from "../components/Uptime.vue";
import GroupList from "../components/GroupList.vue";
const env = process.env.NODE_ENV || "production";
@ -77,8 +76,7 @@ if (env === "development" || localStorage.dev === "dev") {
export default {
components: {
HeartbeatBar,
Uptime,
GroupList,
VueMultiselect,
},
data() {
@ -91,8 +89,18 @@ export default {
}
},
computed: {
allMonitorList() {
return Object.values(this.$root.monitorList);
let result = [];
for (let id in this.$root.monitorList) {
if (this.$root.monitorList[id] && ! (id in this.monitorList)) {
let monitor = this.$root.monitorList[id];
result.push(monitor);
}
}
return result;
},
showEditFeature() {
return this.enableEditMode && this.$root.socket.connected;
@ -100,6 +108,21 @@ export default {
},
watch: {
/**
* Selected a monitor and add to the list.
*/
selectedMonitor(monitor) {
if (monitor) {
if (this.$root.publicGroupList.length === 0) {
this.addGroup();
}
const firstGroup = this.$root.publicGroupList[0];
firstGroup.monitorList.push(monitor);
this.selectedMonitor = null;
}
}
},
async created() {
this.hasToken = ("token" in localStorage);
@ -126,14 +149,12 @@ export default {
return `${monitor.name}`;
},
onSelectedMonitor(selectedOption, id) {
console.log(selectedOption);
console.log(id);
// TODO: emit socket cmd to set it public
// TODO: Reload monitor or add to list
addGroup() {
this.$root.publicGroupList.push({
name: "Untitled Group",
monitorList: [],
})
}
},
}
</script>
@ -164,4 +185,9 @@ footer {
text-align: center;
font-size: 14px;
}
.btn-add-group {
height: 100%;
width: 100%;
}
</style>