mirror of https://github.com/statping/statping
better loading, updated service chart
parent
2319cd36d1
commit
8b54ceb16f
|
@ -7,6 +7,7 @@
|
|||
- Added Help page that is generated from Statping's Wiki repo on build
|
||||
- Modified Service Group failures on index page to show 90 days of failures
|
||||
- Modified Service view page, updated Latency and Ping charts, added failures below
|
||||
- Modified Service chart on index page to show ping data along with latency
|
||||
|
||||
# 0.90.63 (08-17-2020)
|
||||
- Modified build process to use xgo for all arch builds
|
||||
|
|
|
@ -87,6 +87,9 @@ func (g *GroupQuery) GraphData(by By) ([]*TimeValue, error) {
|
|||
return caller.ToValues()
|
||||
}
|
||||
|
||||
// ToTimeValue will format the SQL rows into a JSON format for the API.
|
||||
// [{"timestamp": "2006-01-02T15:04:05Z", "amount": 468293}]
|
||||
// TODO redo this entire function, use better SQL query to group by time
|
||||
func (g *GroupQuery) ToTimeValue() (*TimeVar, error) {
|
||||
rows, err := g.db.Rows()
|
||||
if err != nil {
|
||||
|
|
|
@ -19,10 +19,9 @@ func (it *Db) ParseTime(t string) (time.Time, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// FormatTime returns the timestamp in the same format as the DATETIME column in database
|
||||
func (it *Db) FormatTime(t time.Time) string {
|
||||
switch it.Type {
|
||||
case "mysql":
|
||||
return t.Format("2006-01-02 15:04:05")
|
||||
case "postgres":
|
||||
return t.Format("2006-01-02 15:04:05.999999999")
|
||||
default:
|
||||
|
@ -30,6 +29,7 @@ func (it *Db) FormatTime(t time.Time) string {
|
|||
}
|
||||
}
|
||||
|
||||
// SelectByTime returns an SQL query that will group "created_at" column by x seconds and returns as "timeframe"
|
||||
func (it *Db) SelectByTime(increment time.Duration) string {
|
||||
seconds := int64(increment.Seconds())
|
||||
switch it.Type {
|
||||
|
@ -41,33 +41,3 @@ func (it *Db) SelectByTime(increment time.Duration) string {
|
|||
return fmt.Sprintf("datetime((strftime('%%s', created_at) / %d) * %d, 'unixepoch') as timeframe", seconds, seconds)
|
||||
}
|
||||
}
|
||||
|
||||
func (it *Db) correctTimestamp(increment string) string {
|
||||
var timestamper string
|
||||
switch increment {
|
||||
case "second":
|
||||
timestamper = "%Y-%m-%d %H:%M:%S"
|
||||
case "minute":
|
||||
timestamper = "%Y-%m-%d %H:%M:00"
|
||||
case "hour":
|
||||
timestamper = "%Y-%m-%d %H:00:00"
|
||||
case "day":
|
||||
timestamper = "%Y-%m-%d 00:00:00"
|
||||
case "month":
|
||||
timestamper = "%Y-%m-01 00:00:00"
|
||||
case "year":
|
||||
timestamper = "%Y-01-01 00:00:00"
|
||||
default:
|
||||
timestamper = "%Y-%m-%d 00:00:00"
|
||||
}
|
||||
|
||||
switch it.Type {
|
||||
case "mysql":
|
||||
case "second":
|
||||
timestamper = "%Y-%m-%d %H:%i:%S"
|
||||
case "minute":
|
||||
timestamper = "%Y-%m-%d %H:%i:00"
|
||||
}
|
||||
|
||||
return timestamper
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<router-view :loaded="loaded"/>
|
||||
<router-view/>
|
||||
<Footer v-if="$route.path !== '/setup'"/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -65,7 +65,3 @@
|
|||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
</style>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div class="col-12 full-col-12">
|
||||
<div v-if="services.length > 0" class="col-12 full-col-12">
|
||||
<h4 v-if="group.name !== 'Empty Group'" class="group_header mb-3 mt-4">{{group.name}}</h4>
|
||||
<div class="list-group online_list mb-4">
|
||||
|
||||
<div v-for="(service, index) in $store.getters.servicesInGroup(group.id)" v-bind:key="index" class="service_li list-group-item list-group-item-action">
|
||||
<div v-for="(service, index) in services" v-bind:key="index" class="service_li list-group-item list-group-item-action">
|
||||
<router-link class="no-decoration font-3" :to="serviceLink(service)">{{service.name}}</router-link>
|
||||
<span class="badge text-uppercase float-right" :class="{'bg-success': service.online, 'bg-danger': !service.online }">
|
||||
{{service.online ? $t('online') : $t('offline')}}
|
||||
|
@ -30,11 +30,15 @@ export default {
|
|||
GroupServiceFailures
|
||||
},
|
||||
props: {
|
||||
group: Object
|
||||
group: {
|
||||
type: Object,
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
services() {
|
||||
return this.$store.getters.servicesInGroup(this.group.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
</style>
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-observe-visibility="{callback: visibleChart, once: true}" v-if="!loaded" class="row">
|
||||
<div class="col-12 text-center mt-3">
|
||||
<font-awesome-icon icon="circle-notch" class="text-dim" size="1x" spin/>
|
||||
</div>
|
||||
</div>
|
||||
<transition name="fade">
|
||||
<div v-if="loaded">
|
||||
<div class="d-flex mt-3">
|
||||
<div class="flex-fill service_day" v-for="(d, index) in failureData" @mouseover="mouseover(d)" @mouseout="mouseout" :class="{'day-error': d.amount > 0, 'day-success': d.amount === 0}">
|
||||
<span v-if="d.amount !== 0" class="d-none d-md-block text-center small"></span>
|
||||
|
@ -17,6 +24,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="daily-failures small text-right text-dim">{{hover_text}}</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -31,7 +40,9 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
failureData: [],
|
||||
hover_text: ""
|
||||
hover_text: "",
|
||||
loaded: false,
|
||||
visible: false,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
|
@ -45,10 +56,16 @@ export default {
|
|||
return this.smallText(this.service)
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.lastDaysFailures()
|
||||
mounted () {
|
||||
|
||||
},
|
||||
methods: {
|
||||
visibleChart(isVisible, entry) {
|
||||
if (isVisible && !this.visible) {
|
||||
this.visible = true
|
||||
this.lastDaysFailures().then(() => this.loaded = true)
|
||||
}
|
||||
},
|
||||
mouseout() {
|
||||
this.hover_text = ""
|
||||
},
|
||||
|
|
|
@ -15,7 +15,3 @@ export default {
|
|||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
</style>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="!expanded" v-observe-visibility="visibleChart" class="chart-container">
|
||||
<div v-show="!expanded" v-observe-visibility="{callback: visibleChart, throttle: 200}" class="chart-container">
|
||||
<ServiceChart :service="service" :visible="visible" :chart_timeframe="chartTimeframe"/>
|
||||
</div>
|
||||
|
||||
|
@ -67,18 +67,12 @@ export default {
|
|||
name: 'ServiceBlock',
|
||||
components: { Analytics, ServiceTopStats, ServiceChart},
|
||||
props: {
|
||||
in_service: {
|
||||
service: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
|
||||
},
|
||||
computed: {
|
||||
service() {
|
||||
return this.track_service
|
||||
},
|
||||
timeframepick() {
|
||||
return this.timeframes.find(s => s.value === this.timeframe_val)
|
||||
},
|
||||
|
@ -124,7 +118,7 @@ export default {
|
|||
{value: "4320m", text: "3/day", set: 10 },
|
||||
{value: "10080m", text: "7/day", set: 11 },
|
||||
],
|
||||
stats: {
|
||||
stats: {
|
||||
total_failures: {
|
||||
title: "Total Failures",
|
||||
subtitle: "Last 7 Days",
|
||||
|
@ -151,14 +145,13 @@ export default {
|
|||
value: 0,
|
||||
}
|
||||
},
|
||||
track_service: null,
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
// clearInterval(this.timer_func)
|
||||
},
|
||||
async created() {
|
||||
this.track_service = this.in_service
|
||||
created() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
disabled_interval(interval) {
|
||||
|
@ -189,30 +182,8 @@ export default {
|
|||
},
|
||||
async setService() {
|
||||
await this.$store.commit('setService', this.service)
|
||||
this.$router.push('/service/'+this.service.id, {props: {in_service: this.service}})
|
||||
this.$router.push('/service/'+this.service.id, {props: {service: this.service}})
|
||||
},
|
||||
async showMoreStats() {
|
||||
this.expanded = !this.expanded;
|
||||
|
||||
const failData = await Graphing.failures(this.service, 7)
|
||||
this.stats.total_failures.chart = failData.data;
|
||||
this.stats.total_failures.value = failData.total;
|
||||
|
||||
const hitsData = await Graphing.hits(this.service, 7)
|
||||
|
||||
this.stats.high_latency.chart = hitsData.chart;
|
||||
this.stats.high_latency.value = this.humanTime(hitsData.high);
|
||||
|
||||
this.stats.lowest_latency.chart = hitsData.chart;
|
||||
this.stats.lowest_latency.value = this.humanTime(hitsData.low);
|
||||
|
||||
const pingData = await Graphing.pings(this.service, 7)
|
||||
this.stats.high_ping.chart = pingData.chart;
|
||||
this.stats.high_ping.value = this.humanTime(pingData.high);
|
||||
|
||||
this.stats.low_ping.chart = pingData.chart;
|
||||
this.stats.low_ping.value = this.humanTime(pingData.low);
|
||||
},
|
||||
visibleChart(isVisible, entry) {
|
||||
if (isVisible && !this.visible) {
|
||||
this.visible = true
|
||||
|
@ -226,4 +197,4 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -47,122 +47,138 @@
|
|||
return {
|
||||
ready: false,
|
||||
showing: false,
|
||||
data: [],
|
||||
chartOptions: {
|
||||
noData: {
|
||||
text: 'Loading...'
|
||||
},
|
||||
chart: {
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
type: "area",
|
||||
animations: {
|
||||
enabled: true,
|
||||
initialAnimation: {
|
||||
enabled: true
|
||||
}
|
||||
},
|
||||
selection: {
|
||||
enabled: false
|
||||
},
|
||||
zoom: {
|
||||
enabled: false
|
||||
},
|
||||
toolbar: {
|
||||
show: false
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: -10,
|
||||
}
|
||||
},
|
||||
dropShadow: {
|
||||
enabled: false,
|
||||
},
|
||||
xaxis: {
|
||||
type: "datetime",
|
||||
labels: {
|
||||
show: false
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
show: false
|
||||
},
|
||||
},
|
||||
markers: {
|
||||
size: 0,
|
||||
strokeWidth: 0,
|
||||
hover: {
|
||||
size: undefined,
|
||||
sizeOffset: 0
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
theme: false,
|
||||
enabled: true,
|
||||
custom: ({series, seriesIndex, dataPointIndex, w}) => {
|
||||
let ts = w.globals.seriesX[seriesIndex][dataPointIndex];
|
||||
const dt = new Date(ts).toLocaleDateString("en-us", timeoptions)
|
||||
let val = series[seriesIndex][dataPointIndex];
|
||||
if (val >= 10000) {
|
||||
val = Math.round(val / 1000) + " ms"
|
||||
} else {
|
||||
val = val + " μs"
|
||||
}
|
||||
return `<div class="chartmarker"><span>Average Response Time: </span><span class="font-3">${val}</span><span>${dt}</span></div>`
|
||||
},
|
||||
fixed: {
|
||||
enabled: true,
|
||||
position: 'topRight',
|
||||
offsetX: -30,
|
||||
offsetY: 0,
|
||||
},
|
||||
x: {
|
||||
show: false,
|
||||
},
|
||||
y: {
|
||||
formatter: (value) => { return value + " %" },
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
floating: true,
|
||||
axisTicks: {
|
||||
show: false
|
||||
},
|
||||
axisBorder: {
|
||||
show: false
|
||||
},
|
||||
fill: {
|
||||
colors: [this.service.online ? "#48d338" : "#dd3545"],
|
||||
opacity: 1,
|
||||
type: 'solid'
|
||||
},
|
||||
stroke: {
|
||||
show: false,
|
||||
curve: 'smooth',
|
||||
lineCap: 'butt',
|
||||
colors: [this.service.online ? "#3aa82d" : "#dd3545"],
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
data: []
|
||||
}]
|
||||
data: null,
|
||||
ping_data: null,
|
||||
series: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
chartOptions() {
|
||||
return {
|
||||
noData: {
|
||||
text: 'Loading...'
|
||||
},
|
||||
chart: {
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
type: "area",
|
||||
animations: {
|
||||
enabled: true,
|
||||
easing: 'easeinout',
|
||||
speed: 800,
|
||||
animateGradually: {
|
||||
enabled: false,
|
||||
delay: 400,
|
||||
},
|
||||
dynamicAnimation: {
|
||||
enabled: true,
|
||||
speed: 500
|
||||
},
|
||||
hover: {
|
||||
animationDuration: 0, // duration of animations when hovering an item
|
||||
},
|
||||
responsiveAnimationDuration: 0,
|
||||
},
|
||||
selection: {
|
||||
enabled: false
|
||||
},
|
||||
zoom: {
|
||||
enabled: false
|
||||
},
|
||||
toolbar: {
|
||||
show: false
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
show: false,
|
||||
padding: {
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: -10,
|
||||
}
|
||||
},
|
||||
dropShadow: {
|
||||
enabled: false,
|
||||
},
|
||||
xaxis: {
|
||||
type: "datetime",
|
||||
labels: {
|
||||
show: false
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
show: false
|
||||
},
|
||||
},
|
||||
markers: {
|
||||
size: 0,
|
||||
strokeWidth: 0,
|
||||
hover: {
|
||||
size: undefined,
|
||||
sizeOffset: 0
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
theme: false,
|
||||
enabled: true,
|
||||
custom: ({series, seriesIndex, dataPointIndex, w}) => {
|
||||
let ts = w.globals.seriesX[seriesIndex][dataPointIndex];
|
||||
const dt = new Date(ts).toLocaleDateString("en-us", timeoptions)
|
||||
let val = series[0][dataPointIndex];
|
||||
let pingVal = series[1][dataPointIndex];
|
||||
return `<div class="chartmarker">
|
||||
<span>Average Response Time: ${this.humanTime(val)}/${this.chart_timeframe.interval}</span>
|
||||
<span>Average Ping: ${this.humanTime(pingVal)}/${this.chart_timeframe.interval}</span>
|
||||
<span>${dt}</span>
|
||||
</div>`
|
||||
},
|
||||
fixed: {
|
||||
enabled: true,
|
||||
position: 'topRight',
|
||||
offsetX: -30,
|
||||
offsetY: 0,
|
||||
},
|
||||
x: {
|
||||
show: false,
|
||||
},
|
||||
y: {
|
||||
formatter: (value) => {
|
||||
return value + " %"
|
||||
},
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
floating: true,
|
||||
axisTicks: {
|
||||
show: false
|
||||
},
|
||||
axisBorder: {
|
||||
show: false
|
||||
},
|
||||
fill: {
|
||||
colors: this.service.online ? ["#3dc82f", "#48d338"] : ["#c60f20", "#dd3545"],
|
||||
opacity: 1,
|
||||
type: 'solid',
|
||||
},
|
||||
stroke: {
|
||||
show: false,
|
||||
curve: 'smooth',
|
||||
lineCap: 'butt',
|
||||
colors: this.service.online ? ["#38bc2a", "#48d338"] : ["#c60f20", "#dd3545"],
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible: function(newVal, oldVal) {
|
||||
if (newVal && !this.showing) {
|
||||
|
@ -185,11 +201,13 @@
|
|||
if (this.data === null && val.interval !== "5m") {
|
||||
await this.chartHits({start_time: val.start_time, interval: "5m"})
|
||||
}
|
||||
this.series = [{
|
||||
name: this.service.name,
|
||||
...this.convertToChartData(this.data)
|
||||
}]
|
||||
this.ready = true
|
||||
this.ping_data = await Api.service_ping(this.service.id, start, end, val.interval, false)
|
||||
|
||||
this.series = [
|
||||
{name: "Latency", ...this.convertToChartData(this.data)},
|
||||
{name: "Ping", ...this.convertToChartData(this.ping_data)},
|
||||
]
|
||||
this.ready = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,10 @@ Sentry.init({
|
|||
integrations: [new Integrations.Vue({Vue, attachProps: true, logErrors: true})],
|
||||
});
|
||||
|
||||
Vue.config.productionTip = false
|
||||
Vue.config.productionTip = process.env.NODE_ENV !== 'production'
|
||||
Vue.config.devtools = process.env.NODE_ENV !== 'production'
|
||||
Vue.config.performance = process.env.NODE_ENV !== 'production'
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
|
|
|
@ -57,7 +57,6 @@ export default Vue.mixin({
|
|||
return getUnixTime(parseISO(val)) <= 0
|
||||
},
|
||||
smallText(s) {
|
||||
const incidents = s.incidents
|
||||
if (s.online) {
|
||||
return `Online, checked ${this.ago(s.last_success)} ago`
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
<template>
|
||||
<div class="container col-md-7 col-sm-12 sm-container">
|
||||
|
||||
<Header/>
|
||||
<Header/>
|
||||
|
||||
<div v-if="!loaded" class="row mt-5 mb-5">
|
||||
<div class="col-12 mt-5 mb-2 text-center">
|
||||
<font-awesome-icon icon="circle-notch" class="text-dim" size="3x" spin/>
|
||||
</div>
|
||||
<div class="col-12 text-center mt-3 mb-3">
|
||||
<span class="text-dim">{{loading_text}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 full-col-12">
|
||||
<div v-for="service in services_no_group" v-bind:key="service.id" class="list-group online_list mb-4">
|
||||
|
@ -14,9 +23,9 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Group v-for="group in groups" v-bind:key="group.id" :group=group />
|
||||
</div>
|
||||
<div v-if="loaded">
|
||||
<Group v-for="group in groups" v-bind:key="group.id" :group=group />
|
||||
</div>
|
||||
|
||||
<div class="col-12 full-col-12">
|
||||
<MessageBlock v-for="message in messages" v-bind:key="message.id" :message="message" />
|
||||
|
@ -24,7 +33,7 @@
|
|||
|
||||
<div class="col-12 full-col-12">
|
||||
<div v-for="service in services" :ref="service.id" v-bind:key="service.id">
|
||||
<ServiceBlock :in_service=service />
|
||||
<ServiceBlock :service="service" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -52,10 +61,29 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
logged_in: false
|
||||
logged_in: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
loading_text() {
|
||||
if (this.core == null) {
|
||||
return "Loading Core"
|
||||
} else if (this.groups == null) {
|
||||
return "Loading Groups"
|
||||
} else if (this.services == null) {
|
||||
return "Loading Services"
|
||||
} else if (this.messages == null) {
|
||||
return "Loading Announcements"
|
||||
} else {
|
||||
return "Completed"
|
||||
}
|
||||
},
|
||||
loaded() {
|
||||
return this.core !== null && this.groups !== null && this.services !== null
|
||||
},
|
||||
core() {
|
||||
return this.$store.getters.core
|
||||
},
|
||||
messages() {
|
||||
return this.$store.getters.messages.filter(m => this.inRange(m) && m.service === 0)
|
||||
},
|
||||
|
|
|
@ -173,10 +173,6 @@
|
|||
},
|
||||
methods: {
|
||||
async update() {
|
||||
const c = await Api.core()
|
||||
this.$store.commit('setCore', c)
|
||||
const n = await Api.notifiers()
|
||||
this.$store.commit('setNotifiers', n)
|
||||
this.cache = await Api.cache()
|
||||
await this.getGithub()
|
||||
},
|
||||
|
@ -194,19 +190,24 @@
|
|||
return this.tab === id
|
||||
},
|
||||
async renewApiKeys() {
|
||||
let r = confirm("Are you sure you want to reset the API keys?");
|
||||
let r = confirm("Are you sure you want to reset the API keys? You will be logged out.");
|
||||
if (r === true) {
|
||||
await Api.renewApiKeys()
|
||||
const core = await Api.core()
|
||||
this.$store.commit('setCore', core)
|
||||
this.core = core
|
||||
await this.logout()
|
||||
}
|
||||
},
|
||||
async logout () {
|
||||
await Api.logout()
|
||||
this.$store.commit('setHasAllData', false)
|
||||
this.$store.commit('setToken', null)
|
||||
this.$store.commit('setAdmin', false)
|
||||
this.$store.commit('setUser', false)
|
||||
// this.$cookies.remove("statping_auth")
|
||||
await this.$router.push('/logout')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
|
|
@ -2,6 +2,9 @@ module.exports = {
|
|||
baseUrl: '/',
|
||||
assetsDir: 'assets',
|
||||
filenameHashing: false,
|
||||
productionTip: process.env.NODE_ENV !== 'production',
|
||||
devtools: process.env.NODE_ENV !== 'production',
|
||||
performance: process.env.NODE_ENV !== 'production',
|
||||
devServer: {
|
||||
disableHostCheck: true,
|
||||
proxyTable: {
|
||||
|
|
|
@ -79,7 +79,7 @@ func (m *mobilePush) OnFailure(s services.Service, f failures.Failure) (string,
|
|||
func (m *mobilePush) OnSuccess(s services.Service) (string, error) {
|
||||
data := dataJson(s, failures.Failure{})
|
||||
msg := &pushArray{
|
||||
Message: fmt.Sprintf("%s is currently online!", s.Name),
|
||||
Message: fmt.Sprintf("%s is back online and was down for %s", s.Name, s.Downtime().Human()),
|
||||
Title: "Service Online",
|
||||
Data: data,
|
||||
Platform: 2,
|
||||
|
|
|
@ -19,7 +19,6 @@ var (
|
|||
)
|
||||
|
||||
func TestMobileNotifier(t *testing.T) {
|
||||
t.SkipNow()
|
||||
err := utils.InitLogs()
|
||||
require.Nil(t, err)
|
||||
|
||||
|
|
Loading…
Reference in New Issue