UI fixes, i18n updates, notifier example usage

pull/679/head
hunterlong 2020-06-17 15:35:13 -07:00
parent 7432d9cf00
commit 641f2d18b2
26 changed files with 160 additions and 133 deletions

View File

@ -1,6 +1,7 @@
<template> <template>
<div> <div>
<table class="table"> <span v-if="!cache" class="text-muted">There are no cached pages yet!</span>
<table v-if="cache" class="table">
<thead> <thead>
<tr> <tr>
<th scope="col">URL</th> <th scope="col">URL</th>
@ -18,7 +19,7 @@
</tbody> </tbody>
</table> </table>
<button @click.prevent="clearCache" class="btn btn-danger btn-block">Clear Cache</button> <button v-if="cache" @click.prevent="clearCache" class="btn btn-danger btn-block">Clear Cache</button>
</div> </div>
</template> </template>

View File

@ -1,14 +1,14 @@
<template> <template>
<div class="col-12"> <div class="col-12">
<div class="card contain-card text-black-50 bg-white mb-4"> <div class="card contain-card text-black-50 bg-white mb-4">
<div class="card-header">Announcements</div> <div class="card-header">{{ $t('top_nav.announcements') }}</div>
<div class="card-body pt-0"> <div class="card-body pt-0">
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
<tr> <tr>
<th scope="col">Title</th> <th scope="col">{{ $t('dashboard.title') }}</th>
<th scope="col" class="d-none d-md-table-cell">Service</th> <th scope="col" class="d-none d-md-table-cell">{{ $tc('dashboard.service', 1) }}</th>
<th scope="col" class="d-none d-md-table-cell">Begins</th> <th scope="col" class="d-none d-md-table-cell">{{ $t('dashboard.begins') }}</th>
<th scope="col"></th> <th scope="col"></th>
</tr> </tr>
</thead> </thead>
@ -21,8 +21,12 @@
<td class="d-none d-md-table-cell">{{niceDate(message.start_on)}}</td> <td class="d-none d-md-table-cell">{{niceDate(message.start_on)}}</td>
<td class="text-right"> <td class="text-right">
<div v-if="$store.state.admin" class="btn-group"> <div v-if="$store.state.admin" class="btn-group">
<a @click.prevent="editMessage(message, edit)" href="#" class="btn btn-outline-secondary"><i class="fas fa-exclamation-triangle"></i> Edit</a> <button @click.prevent="editMessage(message, edit)" href="#" class="btn btn-sm btn-outline-secondary">
<a @click.prevent="deleteMessage(message)" href="#" class="btn btn-danger"><font-awesome-icon icon="times" /></a> <font-awesome-icon icon="edit" />
</button>
<button @click.prevent="deleteMessage(message)" href="#" class="btn btn-sm btn-danger">
<font-awesome-icon icon="times" />
</button>
</div> </div>
</td> </td>
</tr> </tr>
@ -48,6 +52,9 @@
} }
}, },
methods: { methods: {
goto(to) {
this.$router.push(to)
},
editChange(v) { editChange(v) {
this.message = {} this.message = {}
this.edit = v this.edit = v

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="col-12"> <div class="col-12">
<div class="card contain-card text-black-50 bg-white mb-4"> <div class="card contain-card text-black-50 bg-white mb-4">
<div class="card-header">Services <div class="card-header">{{ $t('top_nav.services') }}
<router-link v-if="$store.state.admin" to="/dashboard/create_service" class="btn btn-sm btn-outline-success float-right"> <router-link v-if="$store.state.admin" to="/dashboard/create_service" class="btn btn-sm btn-outline-success float-right">
<font-awesome-icon icon="plus"/> Create <font-awesome-icon icon="plus"/> Create
</router-link> </router-link>
@ -12,14 +12,14 @@
</div> </div>
<div class="card contain-card text-black-50 bg-white mb-4"> <div class="card contain-card text-black-50 bg-white mb-4">
<div class="card-header">Groups</div> <div class="card-header">{{ $t('top_nav.groups') }}</div>
<div class="card-body pt-0"> <div class="card-body pt-0">
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th scope="col">Name</th> <th scope="col">{{ $t('dashboard.name') }}</th>
<th scope="col">Services</th> <th scope="col">{{ $tc('dashboard.service', 2) }}</th>
<th scope="col">Visibility</th> <th scope="col">{{ $t('dashboard.visibility') }}</th>
<th scope="col"></th> <th scope="col"></th>
</tr> </tr>
</thead> </thead>
@ -31,8 +31,9 @@
</td> </td>
<td>{{$store.getters.servicesInGroup(group.id).length}}</td> <td>{{$store.getters.servicesInGroup(group.id).length}}</td>
<td> <td>
<span v-if="group.public" class="badge badge-primary text-uppercase">{{ $t('public') }}</span> <span class="badge text-uppercase" :class="{'badge-primary': group.public, 'badge-secondary': !group.public}">
<span v-if="!group.public" class="badge badge-secondary text-uppercase">{{ $t('private') }}</span> {{group.public ? $t('public') : $t('private')}}
</span>
</td> </td>
<td class="text-right"> <td class="text-right">
<div v-if="$store.state.admin" class="btn-group"> <div v-if="$store.state.admin" class="btn-group">

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="col-12"> <div class="col-12">
<div class="card contain-card text-black-50 bg-white mb-4"> <div class="card contain-card text-black-50 bg-white mb-4">
<div class="card-header">Users</div> <div class="card-header">{{ $t('top_nav.users') }}</div>
<div class="card-body pt-0"> <div class="card-body pt-0">
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>

View File

@ -16,7 +16,7 @@
</span> {{service.name}} </span> {{service.name}}
</td> </td>
<td class="d-none d-md-table-cell"> <td class="d-none d-md-table-cell">
<span class="badge" :class="{'badge-primary': service.public, 'badge-secondary': !service.public}"> <span class="badge text-uppercase" :class="{'badge-primary': service.public, 'badge-secondary': !service.public}">
{{service.public ? $t('public') : $t('private')}} {{service.public ? $t('public') : $t('private')}}
</span> </span>
</td> </td>
@ -27,15 +27,16 @@
</td> </td>
<td class="text-right"> <td class="text-right">
<div class="btn-group"> <div class="btn-group">
<router-link v-if="$store.state.admin" :to="{path: `/dashboard/edit_service/${service.id}`, params: {service: service} }" class="btn btn-outline-secondary"> <button v-if="$store.state.admin" @click.prevent="goto({path: `/dashboard/edit_service/${service.id}`, params: {service: service} })" class="btn btn-sm btn-outline-secondary">
<i class="fas fa-chart-area"></i> Edit <font-awesome-icon icon="edit" />
</router-link> </button>
<router-link :to="{path: serviceLink(service), params: {service: service} }" class="btn btn-outline-secondary"> <button @click.prevent="goto({path: serviceLink(service), params: {service: service} })" class="btn btn-sm btn-outline-secondary">
<i class="fas fa-chart-area"></i> View <font-awesome-icon icon="chart-area" />
</router-link> </button>
<a v-if="$store.state.admin" @click.prevent="deleteService(service)" href="#" class="btn btn-danger"> <button v-if="$store.state.admin" @click.prevent="deleteService(service)" href="#" class="btn btn-sm btn-danger">
<font-awesome-icon icon="times" /> <font-awesome-icon v-if="!loading" icon="times" />
</a> <font-awesome-icon v-if="loading" icon="circle-notch" spin/>
</button>
</div> </div>
</td> </td>
</tr> </tr>
@ -54,6 +55,11 @@ export default {
ToggleSwitch, ToggleSwitch,
draggable draggable
}, },
data() {
return {
loading: false,
}
},
computed: { computed: {
servicesList: { servicesList: {
get () { get () {
@ -65,6 +71,9 @@ export default {
} }
}, },
methods: { methods: {
goto(to) {
this.$router.push(to)
},
async updateOrder(value) { async updateOrder(value) {
let data = []; let data = [];
value.forEach((s, k) => { value.forEach((s, k) => {
@ -76,8 +85,10 @@ export default {
async deleteService(s) { async deleteService(s) {
let c = confirm(`Are you sure you want to delete '${s.name}'?`) let c = confirm(`Are you sure you want to delete '${s.name}'?`)
if (c) { if (c) {
this.loading = true
await Api.service_delete(s.id) await Api.service_delete(s.id)
await this.update() await this.update()
this.loading = false
} }
}, },
serviceGroup(s) { serviceGroup(s) {

View File

@ -1,13 +1,20 @@
<template> <template>
<div> <div>
<div v-if="error" class="alert alert-danger mt-3" style="white-space: pre-line;">
{{error}}
</div>
<div v-if="loaded && !directory" class="jumbotron jumbotron-fluid"> <div v-if="loaded && !directory" class="jumbotron jumbotron-fluid">
<div class="text-center col-12"> <div class="text-center col-12">
<h1 class="display-5">Enable Local Assets</h1> <h1 class="display-5">Enable Local Assets</h1>
<span class="lead">Customize your status page design by enabling local assets. This will create a 'assets' directory containing all CSS.<p> <span class="lead">Customize your status page design by enabling local assets. This will create a 'assets' directory containing all CSS.<p>
<button id="enable_assets" @click.prevent="createAssets" :disabled="pending" href="#" class="btn btn-primary mt-3">Enable Local Assets</button> <button id="enable_assets" @click.prevent="createAssets" :disabled="pending" href="#" class="btn btn-primary mt-3">
<font-awesome-icon v-if="pending" icon="circle-notch" class="mr-2" spin/>{{pending ? "Creating Assets" : "Enable Local Assets"}}
</button>
</p></span> </p></span>
</div> </div>
</div> </div>
<form v-observe-visibility="visible" v-if="loaded && directory" @submit.prevent="saveAssets" :disabled="pending"> <form v-observe-visibility="visible" v-if="loaded && directory" @submit.prevent="saveAssets" :disabled="pending">
<h3>Variables</h3> <h3>Variables</h3>
<codemirror v-show="loaded" v-model="vars" ref="vars" :options="cmOptions" class="codemirrorInput"/> <codemirror v-show="loaded" v-model="vars" ref="vars" :options="cmOptions" class="codemirrorInput"/>
@ -18,8 +25,6 @@
<h3 class="mt-3">Mobile Overwrites</h3> <h3 class="mt-3">Mobile Overwrites</h3>
<codemirror v-show="loaded" v-model="mobile" ref="mobile" :options="cmOptions" class="codemirrorInput"/> <codemirror v-show="loaded" v-model="mobile" ref="mobile" :options="cmOptions" class="codemirrorInput"/>
<div v-if="error" class="alert alert-danger mt-3" style="white-space: pre-line;">{{error}}</div>
<button id="save_assets" @submit.prevent="saveAssets" type="submit" class="btn btn-primary btn-block mt-2" :disabled="pending">{{pending ? "Saving..." : "Save Style"}}</button> <button id="save_assets" @submit.prevent="saveAssets" type="submit" class="btn btn-primary btn-block mt-2" :disabled="pending">{{pending ? "Saving..." : "Save Style"}}</button>
<button id="delete_assets" v-if="directory" @click.prevent="deleteAssets" href="#" class="btn btn-danger btn-block confirm-btn" :disabled="pending">Delete Local Assets</button> <button id="delete_assets" v-if="directory" @click.prevent="deleteAssets" href="#" class="btn btn-danger btn-block confirm-btn" :disabled="pending">Delete Local Assets</button>
@ -115,7 +120,12 @@
async saveAssets() { async saveAssets() {
this.pending = true this.pending = true
const data = {base: this.base, variables: this.vars, mobile: this.mobile} const data = {base: this.base, variables: this.vars, mobile: this.mobile}
const resp = await Api.theme_save(data) let resp
try {
resp = await Api.theme_save(data)
} catch(e) {
resp = {status: 'error', error: e.response.data.error}
}
if (resp.error) { if (resp.error) {
this.error = resp.error this.error = resp.error
this.pending = false this.pending = false

View File

@ -5,7 +5,9 @@
<a v-for="(service, index) in $store.getters.servicesInGroup(group.id)" v-bind:key="index" class="service_li list-group-item list-group-item-action"> <a v-for="(service, index) in $store.getters.servicesInGroup(group.id)" 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> <router-link class="no-decoration font-3" :to="serviceLink(service)">{{service.name}}</router-link>
<span class="badge float-right" :class="{'bg-success': service.online, 'bg-danger': !service.online }">{{service.online ? "ONLINE" : "OFFLINE"}}</span> <span class="badge text-uppercase float-right" :class="{'bg-success': service.online, 'bg-danger': !service.online }">
{{service.online ? $t('online') : $t('offline')}}
</span>
<GroupServiceFailures :service="service"/> <GroupServiceFailures :service="service"/>

View File

@ -3,9 +3,9 @@
<div class="card-title px-4 pt-3"> <div class="card-title px-4 pt-3">
<h4 v-observe-visibility="setVisible"> <h4 v-observe-visibility="setVisible">
<router-link :to="serviceLink(service)">{{service.name}}</router-link> <router-link :to="serviceLink(service)">{{service.name}}</router-link>
<span class="badge float-right" :class="{'badge-success': service.online, 'badge-danger': !service.online}"> <span class="badge float-right text-uppercase" :class="{'badge-success': service.online, 'badge-danger': !service.online}">
{{service.online ? "ONLINE" : "OFFLINE"}} {{service.online ? $t('online') : $t('offline')}}
</span> </span>
</h4> </h4>
</div> </div>
@ -68,22 +68,24 @@
<div class="row"> <div class="row">
<div class="col-12 col-md-3 mb-2 mb-md-0"> <div class="col-12 col-md-3 mb-2 mb-md-0">
<router-link :to="{path: `/dashboard/service/${service.id}/incidents`, params: {id: service.id} }" class="btn btn-block btn-white incident"> <router-link :to="{path: `/dashboard/service/${service.id}/incidents`, params: {id: service.id} }" class="btn btn-block btn-white text-capitalize incident">
Incidents {{$tc('incident', 2)}}
</router-link> </router-link>
</div> </div>
<div class="col-12 col-md-3 mb-2 mb-md-0"> <div class="col-12 col-md-3 mb-2 mb-md-0">
<router-link :to="{path: `/dashboard/service/${service.id}/checkins`, params: {id: service.id} }" class="btn btn-block btn-white checkins"> <router-link :to="{path: `/dashboard/service/${service.id}/checkins`, params: {id: service.id} }" class="btn btn-block btn-white text-capitalize checkins">
Checkins {{$tc('checkin', 2)}}
</router-link> </router-link>
</div> </div>
<div class="col-12 col-md-3 mb-2 mb-md-0"> <div class="col-12 col-md-3 mb-2 mb-md-0">
<router-link :to="{path: `/dashboard/service/${service.id}/failures`, params: {id: service.id} }" class="btn btn-block btn-white failures"> <router-link :to="{path: `/dashboard/service/${service.id}/failures`, params: {id: service.id} }" class="btn btn-block btn-white text-capitalize failures">
Failures <span class="badge badge-danger float-right mt-1">{{service.stats.failures}}</span> {{$tc('failure', 2)}} <span class="badge badge-danger float-right mt-1">{{service.stats.failures}}</span>
</router-link> </router-link>
</div> </div>
<div class="col-12 col-md-3 mb-2 mb-md-0 mt-0 mt-md-1"> <div class="col-12 col-md-3 mb-2 mb-md-0 mt-0 mt-md-1">
<span class="text-black-50 float-md-right">{{service.online_7_days}} % Uptime</span> <span class="text-black-50 float-md-right">
{{$t('uptime', [service.online_7_days])}}
</span>
</div> </div>
</div> </div>

View File

@ -2,19 +2,21 @@
<div class="card contain-card text-black-50 bg-white mb-3"> <div class="card contain-card text-black-50 bg-white mb-3">
<div class="card-header">{{group.id ? `Update ${group.name}` : "Create Group"}} <div class="card-header">{{group.id ? `Update ${group.name}` : "Create Group"}}
<transition name="slide-fade"> <transition name="slide-fade">
<button @click="removeEdit" v-if="group.id" class="btn float-right btn-danger btn-sm">Close</button> <button @click="removeEdit" v-if="group.id" class="btn float-right btn-danger btn-sm">
{{ $t('close') }}
</button>
</transition></div> </transition></div>
<div class="card-body"> <div class="card-body">
<form @submit.prevent="saveGroup"> <form @submit.prevent="saveGroup">
<div class="form-group row"> <div class="form-group row">
<label for="title" class="col-sm-4 col-form-label">Group Name</label> <label for="title" class="col-sm-4 col-form-label">{{ $t('dashboard.group') }} {{ $t('dashboard.name') }}</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input v-model="group.name" type="text" class="form-control" id="title" placeholder="Group Name" required> <input v-model="group.name" type="text" class="form-control" id="title" placeholder="Group Name" required>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="switch-group-public" class="col-sm-4 col-form-label">Public Group</label> <label for="switch-group-public" class="col-sm-4 col-form-label text-capitalize">{{ $t('public') }} {{ $t('dashboard.group') }}</label>
<div class="col-md-8 col-xs-12 mt-1"> <div class="col-md-8 col-xs-12 mt-1">
<span @click="group.public = !!group.public" class="switch float-left"> <span @click="group.public = !!group.public" class="switch float-left">
<input v-model="group.public" type="checkbox" class="switch" id="switch-group-public" :checked="group.public"> <input v-model="group.public" type="checkbox" class="switch" id="switch-group-public" :checked="group.public">

View File

@ -3,13 +3,15 @@
<div class="card contain-card text-black-50 bg-white mb-5"> <div class="card contain-card text-black-50 bg-white mb-5">
<div class="card-header">{{message.id ? `Update ${message.title}` : "Create Announcement"}} <div class="card-header">{{message.id ? `Update ${message.title}` : "Create Announcement"}}
<transition name="slide-fade"> <transition name="slide-fade">
<button @click="removeEdit" v-if="message.id" class="btn btn-sm float-right btn-danger btn-sm">Close</button> <button @click="removeEdit" v-if="message.id" class="btn btn-sm float-right btn-danger btn-sm">
{{ $t('close') }}
</button>
</transition> </transition>
</div> </div>
<div class="card-body"> <div class="card-body">
<form @submit="saveMessage"> <form @submit="saveMessage">
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">Title</label> <label class="col-sm-4 col-form-label">{{ $t('dashboard.title') }}</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input v-model="message.title" type="text" name="title" class="form-control" id="title" placeholder="Announcement Title" required> <input v-model="message.title" type="text" name="title" class="form-control" id="title" placeholder="Announcement Title" required>
</div> </div>

View File

@ -49,7 +49,7 @@
<input @keyup="canSubmit" v-model="setup.db_password" id="db_password" type="password" class="form-control" placeholder="password123"> <input @keyup="canSubmit" v-model="setup.db_password" id="db_password" type="password" class="form-control" placeholder="password123">
</div> </div>
<div v-if="setup.db_connection !== 'sqlite'" class="form-group"> <div v-if="setup.db_connection !== 'sqlite'" class="form-group">
<label for="db_database" class="text-capitalize">{{ $t('database') }}</label> <label for="db_database" class="text-capitalize">{{ $t('setup.database') }}</label>
<input @keyup="canSubmit" v-model="setup.db_database" id="db_database" type="text" class="form-control" placeholder="Database name"> <input @keyup="canSubmit" v-model="setup.db_database" id="db_database" type="text" class="form-control" placeholder="Database name">
</div> </div>
@ -125,7 +125,7 @@
</div> </div>
<button @click.prevent="saveSetup" v-bind:disabled="disabled || loading" type="submit" class="btn btn-primary btn-block" :class="{'btn-primary': !loading, 'btn-default': loading}"> <button @click.prevent="saveSetup" v-bind:disabled="disabled || loading" type="submit" class="btn btn-primary btn-block" :class="{'btn-primary': !loading, 'btn-default': loading}">
{{loading ? "Loading..." : "Save Settings"}} <font-awesome-icon v-if="loading" icon="circle-notch" class="mr-2" spin/>{{loading ? "Loading..." : "Save Settings"}}
</button> </button>
</div> </div>
</form> </form>
@ -176,6 +176,7 @@
} }
}, },
mounted() { mounted() {
this.changeLanguages()
this.setup.domain = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":"+window.location.port : "") this.setup.domain = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":"+window.location.port : "")
}, },
methods: { methods: {
@ -203,13 +204,12 @@
}, },
async saveSetup() { async saveSetup() {
this.loading = true this.loading = true
const s = this.setup let resp
if (s.password !== s.confirm_password) { try {
alert('Passwords do not match!') resp = await Api.setup_save(this.setup)
this.loading = false } catch(e) {
return resp = {status: 'error', error: e.response.data.error}
} }
const resp = await Api.setup_save(s)
if (resp.status === 'error') { if (resp.status === 'error') {
this.error = resp.error this.error = resp.error
this.loading = false this.loading = false

View File

@ -32,7 +32,7 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-4 col-form-label">Confirm Password</label> <label class="col-sm-4 col-form-label">{{ $t('close') }}</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input v-model="user.confirm_password" type="password" id="password_confirm" class="form-control" placeholder="Confirm Password" required> <input v-model="user.confirm_password" type="password" id="password_confirm" class="form-control" placeholder="Confirm Password" required>
</div> </div>

View File

@ -3,6 +3,7 @@ const english = {
dashboard: "Dashboard", dashboard: "Dashboard",
services: "Services", services: "Services",
users: "Users", users: "Users",
groups: "Groups",
announcements: "Announcements", announcements: "Announcements",
settings: "Settings", settings: "Settings",
logs: "Logs", logs: "Logs",
@ -27,6 +28,12 @@ const english = {
total_services: "Total Services", total_services: "Total Services",
failures_24_hours: "Failures last 24 Hours", failures_24_hours: "Failures last 24 Hours",
online_services: "Online Services", online_services: "Online Services",
service: 'Service | Services',
group: 'Group',
title: 'Title',
begins: 'Begins',
name: 'Name',
visibility: 'Visibility'
}, },
settings: { settings: {
name: "Project Name", name: "Project Name",
@ -53,9 +60,11 @@ const english = {
public: 'Public', public: 'Public',
private: 'Private', private: 'Private',
admin: 'Admin', admin: 'Admin',
user: 'User',
offline: 'offline', offline: 'offline',
incident: 'incident', failure: 'failure | failures',
incident: 'incident | incidents',
checkin: 'checkin | checkins',
user: 'User | Users',
group: 'Group', group: 'Group',
message: 'message', message: 'message',
edit: 'Edit', edit: 'Edit',
@ -63,9 +72,14 @@ const english = {
sample_data: 'Sample Data', sample_data: 'Sample Data',
today: 'Today', today: 'Today',
last_login: 'Last Login', last_login: 'Last Login',
day: 'day', uptime: '{0}% Uptime',
hour: 'hour', close: 'Close',
uptime: '{0} Uptime', second: 'second | seconds',
minute: 'minute | minutes',
hour: 'hour | hours',
day: 'day | days',
week: 'week | weeks',
month: 'month | months',
} }
export default english export default english

View File

@ -3,22 +3,20 @@
<div class="col-12 mb-4"> <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}"> <span class="mt-3 mb-3 text-white d-md-none btn d-block d-md-none text-uppercase" :class="{'bg-success': service.online, 'bg-danger': !service.online}">
{{service.online ? "ONLINE" : "OFFLINE"}} {{service.online ? $t('online') : $t('offline')}}
</span> </span>
<h4 class="mt-2"> <h4 class="mt-2">
<router-link to="/" class="text-black-50 text-decoration-none">{{core.name}}</router-link> - <span class="text-muted">{{service.name}}</span> <router-link to="/" class="text-black-50 text-decoration-none">{{core.name}}</router-link> - <span class="text-muted">{{service.name}}</span>
<span class="badge float-right d-none d-md-block" :class="{'bg-success': service.online, 'bg-danger': !service.online}"> <span class="badge float-right d-none d-md-block text-uppercase" :class="{'bg-success': service.online, 'bg-danger': !service.online}">
{{service.online ? "ONLINE" : "OFFLINE"}} {{service.online ? $t('online') : $t('offline')}}
</span> </span>
</h4> </h4>
<ServiceTopStats :service="service"/> <ServiceTopStats :service="service"/>
<div> <MessageBlock v-for="message in messagesInRange" v-bind:key="message.id" :message="message"/>
<MessageBlock v-for="message in messagesInRange" v-bind:key="message.id" :message="message"/>
</div>
<div class="row mt-5 mb-4"> <div class="row mt-5 mb-4">
<div class="col-12 col-md-5 font-2 mb-3 mb-md-0"> <div class="col-12 col-md-5 font-2 mb-3 mb-md-0">

View File

@ -64,7 +64,7 @@ func (c *commandLine) OnFailure(s *services.Service, f *failures.Failure) (strin
// OnTest for commandLine triggers when this notifier has been saved // OnTest for commandLine triggers when this notifier has been saved
func (c *commandLine) OnTest() (string, error) { func (c *commandLine) OnTest() (string, error) {
tmpl := ReplaceVars(c.Var1, services.Example(true), exampleFailure) tmpl := ReplaceVars(c.Var1, services.Example(true), failures.Example())
in, out, err := runCommand(c.Host, tmpl) in, out, err := runCommand(c.Host, tmpl)
utils.Log.Infoln(in) utils.Log.Infoln(in)
utils.Log.Infoln(out) utils.Log.Infoln(out)

View File

@ -2,8 +2,10 @@ package notifiers
import ( import (
"github.com/statping/statping/database" "github.com/statping/statping/database"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications" "github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -39,12 +41,12 @@ func TestCommandNotifier(t *testing.T) {
}) })
t.Run("Command OnFailure", func(t *testing.T) { t.Run("Command OnFailure", func(t *testing.T) {
_, err := Command.OnFailure(exampleService, exampleFailure) _, err := Command.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err) assert.Nil(t, err)
}) })
t.Run("Command OnSuccess", func(t *testing.T) { t.Run("Command OnSuccess", func(t *testing.T) {
_, err := Command.OnSuccess(exampleService) _, err := Command.OnSuccess(services.Example(true))
assert.Nil(t, err) assert.Nil(t, err)
}) })

View File

@ -2,8 +2,10 @@ package notifiers
import ( import (
"github.com/statping/statping/database" "github.com/statping/statping/database"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications" "github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -46,12 +48,12 @@ func TestDiscordNotifier(t *testing.T) {
}) })
t.Run("discord OnFailure", func(t *testing.T) { t.Run("discord OnFailure", func(t *testing.T) {
_, err := Discorder.OnFailure(exampleService, exampleFailure) _, err := Discorder.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err) assert.Nil(t, err)
}) })
t.Run("discord OnSuccess", func(t *testing.T) { t.Run("discord OnSuccess", func(t *testing.T) {
_, err := Discorder.OnSuccess(exampleService) _, err := Discorder.OnSuccess(services.Example(true))
assert.Nil(t, err) assert.Nil(t, err)
}) })

View File

@ -2,8 +2,10 @@ package notifiers
import ( import (
"github.com/statping/statping/database" "github.com/statping/statping/database"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications" "github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -62,21 +64,21 @@ func TestEmailNotifier(t *testing.T) {
}) })
t.Run("email OnFailure", func(t *testing.T) { t.Run("email OnFailure", func(t *testing.T) {
_, err := email.OnFailure(exampleService, exampleFailure) _, err := email.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err) assert.Nil(t, err)
}) })
t.Run("email OnSuccess", func(t *testing.T) { t.Run("email OnSuccess", func(t *testing.T) {
_, err := email.OnSuccess(exampleService) _, err := email.OnSuccess(services.Example(false))
assert.Nil(t, err) assert.Nil(t, err)
}) })
t.Run("email Check Back Online", func(t *testing.T) { t.Run("email Check Back Online", func(t *testing.T) {
assert.True(t, exampleService.Online) assert.True(t, services.Example(true).Online)
}) })
t.Run("email OnSuccess Again", func(t *testing.T) { t.Run("email OnSuccess Again", func(t *testing.T) {
_, err := email.OnSuccess(exampleService) _, err := email.OnSuccess(services.Example(true))
assert.Nil(t, err) assert.Nil(t, err)
}) })

View File

@ -2,8 +2,10 @@ package notifiers
import ( import (
"github.com/statping/statping/database" "github.com/statping/statping/database"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications" "github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -51,12 +53,12 @@ func TestMobileNotifier(t *testing.T) {
}) })
t.Run("Mobile OnFailure", func(t *testing.T) { t.Run("Mobile OnFailure", func(t *testing.T) {
_, err := Mobile.OnFailure(exampleService, exampleFailure) _, err := Mobile.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err) assert.Nil(t, err)
}) })
t.Run("Mobile OnSuccess", func(t *testing.T) { t.Run("Mobile OnSuccess", func(t *testing.T) {
_, err := Mobile.OnSuccess(exampleService) _, err := Mobile.OnSuccess(services.Example(true))
assert.Nil(t, err) assert.Nil(t, err)
}) })

View File

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"github.com/statping/statping/types/core" "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/null"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"html/template" "html/template"
@ -12,7 +11,6 @@ import (
) )
var log = utils.Log.WithField("type", "notifier") var log = utils.Log.WithField("type", "notifier")
var exampleService = services.Example(true)
type replacer struct { type replacer struct {
Core *core.Core Core *core.Core
@ -63,46 +61,6 @@ func ReplaceVars(input string, s *services.Service, f *failures.Failure) string
return ReplaceTemplate(input, replacer{Service: s, Failure: f, Core: core.App}) return ReplaceTemplate(input, replacer{Service: s, Failure: f, Core: core.App})
} }
var ExampleService = &services.Service{
Id: 1,
Name: "Statping",
Domain: "https://statping.com",
Expected: null.NewNullString("a better response"),
ExpectedStatus: 200,
Interval: 60,
Type: "http",
Method: "get",
Timeout: 10,
Order: 2,
VerifySSL: null.NewNullBool(true),
Public: null.NewNullBool(true),
GroupId: 0,
Permalink: null.NewNullString("statping"),
Online: true,
Latency: 324399,
PingTime: 18399,
Online24Hours: 99.2,
Online7Days: 99.8,
AvgResponse: 300233,
FailuresLast24Hours: 4,
Checkpoint: utils.Now().Add(-10 * time.Minute),
SleepDuration: 55,
LastResponse: "returning from a response",
AllowNotifications: null.NewNullBool(true),
UserNotified: false,
UpdateNotify: null.NewNullBool(true),
SuccessNotified: false,
LastStatusCode: 200,
LastLookupTime: 5233,
LastLatency: 270233,
LastCheck: utils.Now().Add(-15 * time.Second),
LastOnline: utils.Now().Add(-15 * time.Second),
LastOffline: utils.Now().Add(-10 * time.Minute),
SecondsOnline: 4500,
SecondsOffline: 300,
Redirect: null.NewNullBool(true),
}
var exampleFailure = &failures.Failure{ var exampleFailure = &failures.Failure{
Id: 1, Id: 1,
Issue: "HTTP returned a 500 status code", Issue: "HTTP returned a 500 status code",

View File

@ -2,8 +2,10 @@ package notifiers
import ( import (
"github.com/statping/statping/database" "github.com/statping/statping/database"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications" "github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -49,12 +51,12 @@ func TestPushoverNotifier(t *testing.T) {
}) })
t.Run("Pushover OnFailure", func(t *testing.T) { t.Run("Pushover OnFailure", func(t *testing.T) {
_, err := Pushover.OnFailure(exampleService, exampleFailure) _, err := Pushover.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err) assert.Nil(t, err)
}) })
t.Run("Pushover OnSuccess", func(t *testing.T) { t.Run("Pushover OnSuccess", func(t *testing.T) {
_, err := Pushover.OnSuccess(exampleService) _, err := Pushover.OnSuccess(services.Example(true))
assert.Nil(t, err) assert.Nil(t, err)
}) })

View File

@ -2,8 +2,10 @@ package notifiers
import ( import (
"github.com/statping/statping/database" "github.com/statping/statping/database"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications" "github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -47,12 +49,12 @@ func TestSlackNotifier(t *testing.T) {
}) })
t.Run("slack OnFailure", func(t *testing.T) { t.Run("slack OnFailure", func(t *testing.T) {
_, err := slacker.OnFailure(exampleService, exampleFailure) _, err := slacker.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err) assert.Nil(t, err)
}) })
t.Run("slack OnSuccess", func(t *testing.T) { t.Run("slack OnSuccess", func(t *testing.T) {
_, err := slacker.OnSuccess(exampleService) _, err := slacker.OnSuccess(services.Example(true))
assert.Nil(t, err) assert.Nil(t, err)
}) })

View File

@ -2,8 +2,10 @@ package notifiers
import ( import (
"github.com/statping/statping/database" "github.com/statping/statping/database"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications" "github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -53,12 +55,12 @@ func TestTelegramNotifier(t *testing.T) {
}) })
t.Run("Telegram OnFailure", func(t *testing.T) { t.Run("Telegram OnFailure", func(t *testing.T) {
_, err := Telegram.OnFailure(exampleService, exampleFailure) _, err := Telegram.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err) assert.Nil(t, err)
}) })
t.Run("Telegram OnSuccess", func(t *testing.T) { t.Run("Telegram OnSuccess", func(t *testing.T) {
_, err := Telegram.OnSuccess(exampleService) _, err := Telegram.OnSuccess(services.Example(true))
assert.Nil(t, err) assert.Nil(t, err)
}) })

View File

@ -2,8 +2,10 @@ package notifiers
import ( import (
"github.com/statping/statping/database" "github.com/statping/statping/database"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications" "github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -53,12 +55,12 @@ func TestTwilioNotifier(t *testing.T) {
}) })
t.Run("Twilio OnFailure", func(t *testing.T) { t.Run("Twilio OnFailure", func(t *testing.T) {
_, err := Twilio.OnFailure(exampleService, exampleFailure) _, err := Twilio.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err) assert.Nil(t, err)
}) })
t.Run("Twilio OnSuccess", func(t *testing.T) { t.Run("Twilio OnSuccess", func(t *testing.T) {
_, err := Twilio.OnSuccess(exampleService) _, err := Twilio.OnSuccess(services.Example(true))
assert.Nil(t, err) assert.Nil(t, err)
}) })

View File

@ -2,8 +2,10 @@ package notifiers
import ( import (
"github.com/statping/statping/database" "github.com/statping/statping/database"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications" "github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -45,12 +47,12 @@ func TestWebhookNotifier(t *testing.T) {
}) })
t.Run("webhooker OnFailure", func(t *testing.T) { t.Run("webhooker OnFailure", func(t *testing.T) {
_, err := Webhook.OnFailure(exampleService, exampleFailure) _, err := Webhook.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err) assert.Nil(t, err)
}) })
t.Run("webhooker OnSuccess", func(t *testing.T) { t.Run("webhooker OnSuccess", func(t *testing.T) {
_, err := Webhook.OnSuccess(exampleService) _, err := Webhook.OnSuccess(services.Example(true))
assert.Nil(t, err) assert.Nil(t, err)
}) })

View File

@ -42,9 +42,10 @@ func SentryInit(v *string, allow bool) {
allowReports := Params.GetBool("ALLOW_REPORTS") allowReports := Params.GetBool("ALLOW_REPORTS")
if allowReports || allow || goEnv == "test" { if allowReports || allow || goEnv == "test" {
if err := sentry.Init(sentry.ClientOptions{ if err := sentry.Init(sentry.ClientOptions{
Dsn: errorReporter, Dsn: errorReporter,
Environment: goEnv, Environment: goEnv,
Release: version, Release: version,
AttachStacktrace: true,
}); err != nil { }); err != nil {
Log.Errorln(err) Log.Errorln(err)
} }