summaryrefslogtreecommitdiffstats
path: root/src/components/PublicGroupList.vue
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/PublicGroupList.vue')
-rw-r--r--src/components/PublicGroupList.vue273
1 files changed, 273 insertions, 0 deletions
diff --git a/src/components/PublicGroupList.vue b/src/components/PublicGroupList.vue
new file mode 100644
index 0000000..bacddbf
--- /dev/null
+++ b/src/components/PublicGroupList.vue
@@ -0,0 +1,273 @@
+<template>
+ <!-- Group List -->
+ <Draggable
+ v-model="$root.publicGroupList"
+ :disabled="!editMode"
+ item-key="id"
+ :animation="100"
+ >
+ <template #item="group">
+ <div class="mb-5" data-testid="group">
+ <!-- Group Title -->
+ <h2 class="group-title">
+ <font-awesome-icon v-if="editMode && showGroupDrag" icon="arrows-alt-v" class="action drag me-3" />
+ <font-awesome-icon v-if="editMode" icon="times" class="action remove me-3" @click="removeGroup(group.index)" />
+ <Editable v-model="group.element.name" :contenteditable="editMode" tag="span" data-testid="group-name" />
+ </h2>
+
+ <div class="shadow-box monitor-list mt-4 position-relative">
+ <div v-if="group.element.monitorList.length === 0" class="text-center no-monitor-msg">
+ {{ $t("No Monitors") }}
+ </div>
+
+ <!-- Monitor List -->
+ <!-- animation is not working, no idea why -->
+ <Draggable
+ v-model="group.element.monitorList"
+ class="monitor-list"
+ group="same-group"
+ :disabled="!editMode"
+ :animation="100"
+ item-key="id"
+ >
+ <template #item="monitor">
+ <div class="item" data-testid="monitor">
+ <div class="row">
+ <div class="col-9 col-md-8 small-padding">
+ <div class="info">
+ <font-awesome-icon v-if="editMode" icon="arrows-alt-v" class="action drag me-3" />
+ <font-awesome-icon v-if="editMode" icon="times" class="action remove me-3" @click="removeMonitor(group.index, monitor.index)" />
+
+ <Uptime :monitor="monitor.element" type="24" :pill="true" />
+ <a
+ v-if="showLink(monitor)"
+ :href="monitor.element.url"
+ class="item-name"
+ target="_blank"
+ rel="noopener noreferrer"
+ data-testid="monitor-name"
+ >
+ {{ monitor.element.name }}
+ </a>
+ <p v-else class="item-name" data-testid="monitor-name"> {{ monitor.element.name }} </p>
+
+ <span
+ title="Setting"
+ >
+ <font-awesome-icon
+ v-if="editMode"
+ :class="{'link-active': true, 'btn-link': true}"
+ icon="cog" class="action me-3"
+ @click="$refs.monitorSettingDialog.show(group, monitor)"
+ />
+ </span>
+ </div>
+ <div class="extra-info">
+ <div v-if="showCertificateExpiry && monitor.element.certExpiryDaysRemaining">
+ <Tag :item="{name: $t('Cert Exp.'), value: formattedCertExpiryMessage(monitor), color: certExpiryColor(monitor)}" :size="'sm'" />
+ </div>
+ <div v-if="showTags">
+ <Tag v-for="tag in monitor.element.tags" :key="tag" :item="tag" :size="'sm'" data-testid="monitor-tag" />
+ </div>
+ </div>
+ </div>
+ <div :key="$root.userHeartbeatBar" class="col-3 col-md-4">
+ <HeartbeatBar size="mid" :monitor-id="monitor.element.id" />
+ </div>
+ </div>
+ </div>
+ </template>
+ </Draggable>
+ </div>
+ </div>
+ </template>
+ </Draggable>
+ <MonitorSettingDialog ref="monitorSettingDialog" />
+</template>
+
+<script>
+import MonitorSettingDialog from "./MonitorSettingDialog.vue";
+import Draggable from "vuedraggable";
+import HeartbeatBar from "./HeartbeatBar.vue";
+import Uptime from "./Uptime.vue";
+import Tag from "./Tag.vue";
+
+export default {
+ components: {
+ MonitorSettingDialog,
+ Draggable,
+ HeartbeatBar,
+ Uptime,
+ Tag,
+ },
+ props: {
+ /** Are we in edit mode? */
+ editMode: {
+ type: Boolean,
+ required: true,
+ },
+ /** Should tags be shown? */
+ showTags: {
+ type: Boolean,
+ },
+ /** Should expiry be shown? */
+ showCertificateExpiry: {
+ type: Boolean,
+ }
+ },
+ data() {
+ return {
+
+ };
+ },
+ computed: {
+ showGroupDrag() {
+ return (this.$root.publicGroupList.length >= 2);
+ }
+ },
+ created() {
+
+ },
+ methods: {
+ /**
+ * Remove the specified group
+ * @param {number} index Index of group to remove
+ * @returns {void}
+ */
+ removeGroup(index) {
+ this.$root.publicGroupList.splice(index, 1);
+ },
+
+ /**
+ * Remove a monitor from a group
+ * @param {number} groupIndex Index of group to remove monitor
+ * from
+ * @param {number} index Index of monitor to remove
+ * @returns {void}
+ */
+ removeMonitor(groupIndex, index) {
+ this.$root.publicGroupList[groupIndex].monitorList.splice(index, 1);
+ },
+
+ /**
+ * Should a link to the monitor be shown?
+ * Attempts to guess if a link should be shown based upon if
+ * sendUrl is set and if the URL is default or not.
+ * @param {object} monitor Monitor to check
+ * @param {boolean} ignoreSendUrl Should the presence of the sendUrl
+ * property be ignored. This will only work in edit mode.
+ * @returns {boolean} Should the link be shown
+ */
+ showLink(monitor, ignoreSendUrl = false) {
+ // We must check if there are any elements in monitorList to
+ // prevent undefined errors if it hasn't been loaded yet
+ if (this.$parent.editMode && ignoreSendUrl && Object.keys(this.$root.monitorList).length) {
+ return this.$root.monitorList[monitor.element.id].type === "http" || this.$root.monitorList[monitor.element.id].type === "keyword" || this.$root.monitorList[monitor.element.id].type === "json-query";
+ }
+ return monitor.element.sendUrl && monitor.element.url && monitor.element.url !== "https://";
+ },
+
+ /**
+ * Returns formatted certificate expiry or Bad cert message
+ * @param {object} monitor Monitor to show expiry for
+ * @returns {string} Certificate expiry message
+ */
+ formattedCertExpiryMessage(monitor) {
+ if (monitor?.element?.validCert && monitor?.element?.certExpiryDaysRemaining) {
+ return monitor.element.certExpiryDaysRemaining + " " + this.$tc("day", monitor.element.certExpiryDaysRemaining);
+ } else if (monitor?.element?.validCert === false) {
+ return this.$t("noOrBadCertificate");
+ } else {
+ return this.$t("Unknown") + " " + this.$tc("day", 2);
+ }
+ },
+
+ /**
+ * Returns certificate expiry color based on days remaining
+ * @param {object} monitor Monitor to show expiry for
+ * @returns {string} Color for certificate expiry
+ */
+ certExpiryColor(monitor) {
+ if (monitor?.element?.validCert && monitor.element.certExpiryDaysRemaining > 7) {
+ return "#059669";
+ }
+ return "#DC2626";
+ },
+ }
+};
+</script>
+
+<style lang="scss" scoped>
+@import "../assets/vars";
+
+.extra-info {
+ display: flex;
+ margin-bottom: 0.5rem;
+}
+
+.extra-info > div > div:first-child {
+ margin-left: 0 !important;
+}
+
+.no-monitor-msg {
+ position: absolute;
+ width: 100%;
+ top: 20px;
+ left: 0;
+}
+
+.monitor-list {
+ min-height: 46px;
+}
+
+.item-name {
+ padding-left: 5px;
+ padding-right: 5px;
+ margin: 0;
+ display: inline-block;
+}
+
+.btn-link {
+ color: #bbbbbb;
+ margin-left: 5px;
+}
+
+.link-active {
+ color: $primary;
+}
+
+.flip-list-move {
+ transition: transform 0.5s;
+}
+
+.no-move {
+ transition: transform 0s;
+}
+
+.drag {
+ color: #bbb;
+ cursor: grab;
+}
+
+.remove {
+ color: $danger;
+}
+
+.group-title {
+ span {
+ display: inline-block;
+ min-width: 15px;
+ }
+}
+
+.mobile {
+ .item {
+ padding: 13px 0 10px;
+ }
+}
+
+.bg-maintenance {
+ background-color: $maintenance;
+}
+
+</style>