statping/frontend/src/pages/Service.vue

267 lines
8.6 KiB
Vue

<template>
<div v-if="ready" class="container col-md-7 col-sm-12 mt-md-5 bg-light">
<div class="col-12 mb-4">
<span class="mt-3 mb-3 text-white d-md-none btn d-block d-md-none" :class="{'bg-success': service.online, 'bg-danger': !service.online}">
{{service.online ? "ONLINE" : "OFFLINE"}}
</span>
<h4 class="mt-2">
<router-link to="/">{{$store.getters.core.name}}</router-link> - {{service.name}}
<span class="badge float-right d-none d-md-block" :class="{'bg-success': service.online, 'bg-danger': !service.online}">
{{service.online ? "ONLINE" : "OFFLINE"}}
</span>
</h4>
<ServiceTopStats :service="service"/>
<div v-for="(message, index) in messages" v-if="messageInRange(message)">
<MessageBlock :message="message"/>
</div>
<div class="row mt-5 mb-4">
<span class="col-6 font-2">
<flatPickr v-model="start_time" type="text" name="start_time" class="form-control form-control-plaintext" id="start_time" value="0001-01-01T00:00:00Z" required />
</span>
<span class="col-6 font-2">
<flatPickr v-model="end_time" type="text" name="end_time" class="form-control form-control-plaintext" id="end_time" value="0001-01-01T00:00:00Z" required />
</span>
</div>
<div v-if="series" class="service-chart-container">
<apexchart width="100%" height="420" type="area" :options="chartOptions" :series="series"></apexchart>
</div>
<div class="service-chart-heatmap mt-3 mb-4">
<ServiceHeatmap :service="service"/>
</div>
<nav v-if="service.failures" class="nav nav-pills flex-column flex-sm-row mt-3" id="service_tabs">
<a @click="tab='failures'" class="flex-sm-fill text-sm-center nav-link active">Failures</a>
<a @click="tab='incidents'" class="flex-sm-fill text-sm-center nav-link">Incidents</a>
<a @click="tab='checkins'" v-if="$store.getters.token" class="flex-sm-fill text-sm-center nav-link">Checkins</a>
<a @click="tab='response'" v-if="$store.getters.token" class="flex-sm-fill text-sm-center nav-link">Response</a>
</nav>
<div v-if="service.failures" class="tab-content">
<div class="tab-pane fade active show">
<ServiceFailures :service="service"/>
</div>
<div class="tab-pane fade" :class="{active: tab === 'incidents'}" id="incidents">
</div>
<div class="tab-pane fade" :class="{show: tab === 'checkins'}" id="checkins">
<div class="card">
<div class="card-body">
<Checkin :service="service"/>
</div>
</div>
</div>
<div class="tab-pane fade" :class="{show: tab === 'response'}" id="response">
<div class="col-12 mt-4">
<h3>Last Response</h3>
<textarea rows="8" class="form-control" readonly>invalid route</textarea>
<div class="form-group row mt-2">
<label for="last_status_code" class="col-sm-3 col-form-label">HTTP Status Code</label>
<div class="col-sm-2">
<input type="text" id="last_status_code" class="form-control" value="200" readonly>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Api from "../API"
import MessageBlock from '../components/Index/MessageBlock';
import ServiceFailures from '../components/Service/ServiceFailures';
import Checkin from "../forms/Checkin";
import ServiceHeatmap from "@/components/Service/ServiceHeatmap";
import ServiceTopStats from "@/components/Service/ServiceTopStats";
import flatPickr from 'vue-flatpickr-component';
import 'flatpickr/dist/flatpickr.css';
const axisOptions = {
labels: {
show: true
},
crosshairs: {
show: false
},
lines: {
show: true
},
tooltip: {
enabled: false
},
axisTicks: {
show: true
},
grid: {
show: true
},
marker: {
show: false
}
};
export default {
name: 'Service',
components: {
ServiceTopStats,
ServiceHeatmap,
ServiceFailures,
MessageBlock,
Checkin,
flatPickr
},
data() {
return {
id: null,
tab: "failures",
service: {},
authenticated: false,
ready: false,
data: null,
messages: [],
failures: [],
start_time: "",
end_time: "",
chartOptions: {
chart: {
height: 500,
width: "100%",
type: "area",
animations: {
enabled: true,
initialAnimation: {
enabled: true
}
},
selection: {
enabled: false
},
zoom: {
enabled: false
},
toolbar: {
show: false
},
},
grid: {
show: true,
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0,
}
},
xaxis: {
type: "datetime",
...axisOptions
},
yaxis: {
...axisOptions
},
tooltip: {
enabled: false,
marker: {
show: false,
},
x: {
show: false,
}
},
legend: {
show: false,
},
dataLabels: {
enabled: false
},
floating: true,
axisTicks: {
show: false
},
axisBorder: {
show: false
},
fill: {
colors: ["#48d338"],
opacity: 1,
type: 'solid'
},
stroke: {
show: true,
curve: 'smooth',
lineCap: 'butt',
colors: ["#3aa82d"],
}
},
series: [{
data: []
}],
heatmap_data: [],
config: {
enableTime: true
},
}
},
async mounted() {
const id = this.$attrs.id
this.id = id
let service;
if (this.isInt(id)) {
service = this.$store.getters.serviceById(id)
} else {
service = this.$store.getters.serviceByPermalink(id)
}
this.service = service
this.getService(service)
this.messages = this.$store.getters.serviceMessages(service.id)
},
methods: {
messageInRange(message) {
const start = this.isBetween(new Date(), message.start_on)
const end = this.isBetween(message.end_on, new Date())
return start && end
},
async getService(s) {
await this.chartHits()
await this.serviceFailures()
},
async serviceFailures() {
this.failures = await Api.service_failures(this.service.id, this.now() - 3600, this.now(), 15)
},
async chartHits() {
const start = this.nowSubtract((3600 * 24) * 3)
this.start_time = start
this.end_time = new Date()
this.data = await Api.service_hits(this.service.id, this.toUnix(start), this.toUnix(new Date()), "30m", false)
this.series = [{
name: this.service.name,
...this.data
}]
this.ready = true
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>