Merge branch 'master' into feature/add-support-for-method-body-and-headers

This commit is contained in:
Bert Verhelst
2021-10-05 18:19:07 +02:00
13 changed files with 915 additions and 142 deletions

View File

@@ -0,0 +1,52 @@
<template>
<div>
<h4>{{ $t("Certificate Info") }}</h4>
{{ $t("Certificate Chain") }}:
<div
v-if="valid"
class="rounded d-inline-flex ms-2 text-white tag-valid"
>
{{ $t("Valid") }}
</div>
<div
v-if="!valid"
class="rounded d-inline-flex ms-2 text-white tag-invalid"
>
{{ $t("Invalid") }}
</div>
<certificate-info-row :cert="certInfo" />
</div>
</template>
<script>
import CertificateInfoRow from "./CertificateInfoRow.vue";
export default {
components: {
CertificateInfoRow,
},
props: {
certInfo: {
type: Object,
required: true,
},
valid: {
type: Boolean,
required: true,
},
},
};
</script>
<style lang="scss" scoped>
@import "../assets/vars.scss";
.tag-valid {
padding: 2px 25px;
background-color: $primary;
}
.tag-invalid {
padding: 2px 25px;
background-color: $danger;
}
</style>

View File

@@ -0,0 +1,122 @@
<template>
<div>
<div class="d-flex flex-row align-items-center p-1 overflow-hidden">
<div class="m-3 ps-3">
<div class="cert-icon">
<font-awesome-icon icon="file" />
<font-awesome-icon class="award-icon" icon="award" />
</div>
</div>
<div class="m-3">
<table class="text-start">
<tbody>
<tr class="my-3">
<td class="px-3">Subject:</td>
<td>{{ formatSubject(cert.subject) }}</td>
</tr>
<tr class="my-3">
<td class="px-3">Valid To:</td>
<td><Datetime :value="cert.validTo" /></td>
</tr>
<tr class="my-3">
<td class="px-3">Days Remaining:</td>
<td>{{ cert.daysRemaining }}</td>
</tr>
<tr class="my-3">
<td class="px-3">Issuer:</td>
<td>{{ formatSubject(cert.issuer) }}</td>
</tr>
<tr class="my-3">
<td class="px-3">Fingerprint:</td>
<td>{{ cert.fingerprint }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="d-flex">
<font-awesome-icon
v-if="cert.issuerCertificate"
class="m-2 ps-6 link-icon"
icon="link"
/>
</div>
<certificate-info-row
v-if="cert.issuerCertificate"
:cert="cert.issuerCertificate"
/>
</div>
</template>
<script>
import Datetime from "../components/Datetime.vue";
export default {
name: "CertificateInfoRow",
components: {
Datetime,
},
props: {
cert: {
type: Object,
required: true,
},
},
methods: {
formatSubject(subject) {
if (subject.O && subject.CN && subject.C) {
return `${subject.CN} - ${subject.O} (${subject.C})`;
} else if (subject.O && subject.CN) {
return `${subject.CN} - ${subject.O}`;
} else if (subject.CN) {
return subject.CN;
} else {
return "no info";
}
},
},
};
</script>
<style lang="scss" scoped>
@import "../assets/vars.scss";
table {
overflow: hidden;
}
.cert-icon {
position: relative;
font-size: 70px;
color: $link-color;
opacity: 0.5;
.dark & {
color: $dark-font-color;
opacity: 0.3;
}
}
.award-icon {
position: absolute;
font-size: 0.5em;
bottom: 20%;
left: 12%;
color: white;
.dark & {
color: $dark-bg;
}
}
.link-icon {
font-size: 20px;
margin-left: 50px !important;
color: $link-color;
opacity: 0.5;
.dark & {
color: $dark-font-color;
opacity: 0.3;
}
}
</style>

View File

@@ -38,7 +38,7 @@ export default {
beatMargin: 4,
move: false,
maxBeat: -1,
}
};
},
computed: {
@@ -69,12 +69,12 @@ export default {
if (start < 0) {
// Add empty placeholder
for (let i = start; i < 0; i++) {
placeholders.push(0)
placeholders.push(0);
}
start = 0;
}
return placeholders.concat(this.beatList.slice(start))
return placeholders.concat(this.beatList.slice(start));
},
wrapStyle() {
@@ -84,7 +84,7 @@ export default {
return {
padding: `${topBottom}px ${leftRight}px`,
width: "100%",
}
};
},
barStyle() {
@@ -94,12 +94,12 @@ export default {
return {
transition: "all ease-in-out 0.25s",
transform: `translateX(${width}px)`,
}
};
}
return {
transform: "translateX(0)",
}
};
},
@@ -109,7 +109,7 @@ export default {
height: this.beatHeight + "px",
margin: this.beatMargin + "px",
"--hover-scale": this.hoverScale,
}
};
},
},
@@ -120,7 +120,7 @@ export default {
setTimeout(() => {
this.move = false;
}, 300)
}, 300);
},
deep: true,
},
@@ -162,7 +162,7 @@ export default {
methods: {
resize() {
if (this.$refs.wrap) {
this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2))
this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2));
}
},
@@ -170,7 +170,7 @@ export default {
return `${this.$root.datetime(beat.time)} - ${beat.msg}`;
}
},
}
};
</script>
<style lang="scss" scoped>
@@ -183,6 +183,9 @@ export default {
}
.hp-bar-big {
display: flex;
justify-content: flex-end;
.beat {
display: inline-block;
background-color: $primary;

View File

@@ -3,10 +3,10 @@
<div class="list-header">
<div class="placeholder"></div>
<div class="search-wrapper">
<a v-if="searchText == ''" class="search-icon">
<a v-if="!searchText" class="search-icon">
<font-awesome-icon icon="search" />
</a>
<a v-if="searchText != ''" class="search-icon" @click="clearSearchText">
<a v-if="searchText" class="search-icon" @click="clearSearchText">
<font-awesome-icon icon="times" />
</a>
<input v-model="searchText" class="form-control search-input" :placeholder="$t('Search...')" />
@@ -19,21 +19,21 @@
<router-link v-for="(item, index) in sortedMonitorList" :key="index" :to="monitorURL(item.id)" class="item" :class="{ 'disabled': ! item.active }">
<div class="row">
<div class="col-6 col-md-8 small-padding" :class="{ 'monitorItem': $root.userHeartbeatBar == 'bottom' || $root.userHeartbeatBar == 'none' }">
<div class="col-6 col-md-8 small-padding" :class="{ 'monitorItem': $root.userHeartbeatBar === 'bottom' || $root.userHeartbeatBar === 'none' }">
<div class="info">
<Uptime :monitor="item" type="24" :pill="true" />
{{ item.name }}
<span class="ms-1">{{ item.name }}</span>
</div>
<div class="tags">
<Tag v-for="tag in item.tags" :key="tag" :item="tag" :size="'sm'" />
</div>
</div>
<div v-show="$root.userHeartbeatBar == 'normal'" :key="$root.userHeartbeatBar" class="col-6 col-md-4">
<div v-show="$root.userHeartbeatBar === 'normal'" :key="$root.userHeartbeatBar" class="col-6 col-md-4 small-padding">
<HeartbeatBar size="small" :monitor-id="item.id" />
</div>
</div>
<div v-if="$root.userHeartbeatBar == 'bottom'" class="row">
<div v-if="$root.userHeartbeatBar === 'bottom'" class="row">
<div class="col-12">
<HeartbeatBar size="small" :monitor-id="item.id" />
</div>
@@ -62,7 +62,7 @@ export default {
data() {
return {
searchText: "",
}
};
},
computed: {
sortedMonitorList() {
@@ -91,17 +91,17 @@ export default {
}
return m1.name.localeCompare(m2.name);
})
});
// Simple filter by search text
// finds monitor name, tag name or tag value
if (this.searchText != "") {
if (this.searchText) {
const loweredSearchText = this.searchText.toLowerCase();
result = result.filter(monitor => {
return monitor.name.toLowerCase().includes(loweredSearchText)
|| monitor.tags.find(tag => tag.name.toLowerCase().includes(loweredSearchText)
|| tag.value?.toLowerCase().includes(loweredSearchText))
})
|| tag.value?.toLowerCase().includes(loweredSearchText));
});
}
return result;
@@ -115,7 +115,7 @@ export default {
this.searchText = "";
}
},
}
};
</script>
<style lang="scss" scoped>

View File

@@ -22,33 +22,33 @@ export default {
return Math.round(this.$root.uptimeList[key] * 10000) / 100 + "%";
}
return this.$t("notAvailableShort")
return this.$t("notAvailableShort");
},
color() {
if (this.lastHeartBeat.status === 0) {
return "danger"
return "danger";
}
if (this.lastHeartBeat.status === 1) {
return "primary"
return "primary";
}
if (this.lastHeartBeat.status === 2) {
return "warning"
return "warning";
}
return "secondary"
return "secondary";
},
lastHeartBeat() {
if (this.monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[this.monitor.id]) {
return this.$root.lastHeartbeatList[this.monitor.id]
return this.$root.lastHeartbeatList[this.monitor.id];
}
return {
status: -1,
}
};
},
className() {
@@ -59,7 +59,7 @@ export default {
return "";
},
},
}
};
</script>
<style>

View File

@@ -45,17 +45,17 @@
<div class="mb-3">
<label for="to-email" class="form-label">To Email</label>
<input id="to-email" v-model="$parent.notification.smtpTo" type="text" class="form-control" required autocomplete="false" placeholder="example2@kuma.pet, example3@kuma.pet">
<input id="to-email" v-model="$parent.notification.smtpTo" type="text" class="form-control" autocomplete="false" placeholder="example2@kuma.pet, example3@kuma.pet" :required="!hasRecipient">
</div>
<div class="mb-3">
<label for="to-cc" class="form-label">CC</label>
<input id="to-cc" v-model="$parent.notification.smtpCC" type="text" class="form-control" autocomplete="false">
<input id="to-cc" v-model="$parent.notification.smtpCC" type="text" class="form-control" autocomplete="false" :required="!hasRecipient">
</div>
<div class="mb-3">
<label for="to-bcc" class="form-label">BCC</label>
<input id="to-bcc" v-model="$parent.notification.smtpBCC" type="text" class="form-control" autocomplete="false">
<input id="to-bcc" v-model="$parent.notification.smtpBCC" type="text" class="form-control" autocomplete="false" :required="!hasRecipient">
</div>
</template>
@@ -66,10 +66,19 @@ export default {
components: {
HiddenInput,
},
computed: {
hasRecipient() {
if (this.$parent.notification.smtpTo || this.$parent.notification.smtpCC || this.$parent.notification.smtpBCC) {
return true;
} else {
return false;
}
}
},
mounted() {
if (typeof this.$parent.notification.smtpSecure === "undefined") {
this.$parent.notification.smtpSecure = false;
}
},
}
}
};
</script>