slack notifier fix, i18n updates, yayness

pull/679/head
hunterlong 2020-06-18 00:58:54 -07:00
parent 641f2d18b2
commit 6fceb832d4
21 changed files with 579 additions and 223 deletions

View File

@ -1,3 +1,7 @@
# 0.90.54 (06-17-2020)
- Fixed Slack Notifier's failure/success data saving issue
- Added additional i18n Languages (help needed!)
# 0.90.53 (06-16-2020) # 0.90.53 (06-16-2020)
- Modified most of the key's for prometheus metrics - Modified most of the key's for prometheus metrics
- Added Database Stats in prometheus metrics - Added Database Stats in prometheus metrics

View File

@ -1,5 +1,7 @@
<template> <template>
<div> <div class="card text-black-50 bg-white mb-5">
<div class="card-header">Cache</div>
<div class="card-body">
<span v-if="!cache" class="text-muted">There are no cached pages yet!</span> <span v-if="!cache" class="text-muted">There are no cached pages yet!</span>
<table v-if="cache" class="table"> <table v-if="cache" class="table">
<thead> <thead>
@ -21,6 +23,7 @@
</table> </table>
<button v-if="cache" @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>
</div>
</template> </template>
<script> <script>

View File

@ -1,5 +1,7 @@
<template> <template>
<div> <div class="card text-black-50 bg-white mb-5">
<div class="card-header">Theme Editor</div>
<div class="card-body">
<div v-if="error" class="alert alert-danger mt-3" style="white-space: pre-line;"> <div v-if="error" class="alert alert-danger mt-3" style="white-space: pre-line;">
{{error}} {{error}}
</div> </div>
@ -33,6 +35,7 @@
</h6> </h6>
</form> </form>
</div> </div>
</div>
</template> </template>
<script> <script>

View File

@ -0,0 +1,138 @@
<template>
<div>
<h2>Notifier Variables</h2>
You can insert dynamic fields within the notifier payloads for some notifiers.
<p class="mt-2">
Checkout the <a href="https://github.com/statping/statping/blob/master/types/services/struct.go">Service struct</a> and the <a href="https://github.com/statping/statping/blob/master/types/failures/struct.go">Failures struct</a> and create variables in golang template format.
</p>
<p class="mt-2">
For example, if you have <b>{{"\{\{.Service.Name\}\}"}}</b> it will return the service name.
</p>
<h2 class="mt-3">Service Variables</h2>
<table class="table">
<thead>
<tr>
<th scope="col">Variable</th>
<th scope="col">True Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><kbd>{{"\{\{.Service.Id\}\}"}}</kbd></td>
<td>1</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Service.Name\}\}"}}</kbd></td>
<td>Example Service</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Service.Domain\}\}"}}</kbd></td>
<td>https://statping.com</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Service.Port\}\}"}}</kbd></td>
<td>8080</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Service.DowntimeAgo\}\}"}}</kbd></td>
<td>35 minutes ago</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Service.LastStatusCode\}\}"}}</kbd></td>
<td>404</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Service.FailuresLast24Hours\}\}"}}</kbd></td>
<td>38</td>
</tr>
</tbody>
<small>Additional variables within the Service struct</small>
</table>
<h2 class="mt-3">Failure Variables</h2>
<table class="table">
<thead>
<tr>
<th scope="col">Variable</th>
<th scope="col">True Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><kbd>{{"\{\{.Failure.Issue\}\}"}}</kbd></td>
<td>Received 404 status code</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Failure.ErrorCode\}\}"}}</kbd></td>
<td>404</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Failure.Service\}\}"}}</kbd></td>
<td>1</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Failure.PingTime\}\}"}}</kbd></td>
<td>12482 (microseconds)</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Failure.DowntimeAgo\}\}"}}</kbd></td>
<td>35 minutes ago</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Failure.CreatedAt\}\}"}}</kbd></td>
<td>2020-05-02 09:14:43.66381 +0000 UTC</td>
</tr>
</tbody>
<small>Additional variables within the Failures struct</small>
</table>
<h2 class="mt-3">Core Variables</h2>
<table class="table">
<thead>
<tr>
<th scope="col">Variable</th>
<th scope="col">True Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><kbd>{{"\{\{.Core.Domain\}\}"}}</kbd></td>
<td>http://localhost:8080</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Core.Name\}\}"}}</kbd></td>
<td>Statping Demo</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Core.Description\}\}"}}</kbd></td>
<td>Statping will monitor your stuff!</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Core.Version\}\}"}}</kbd></td>
<td>v0.90.34</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Core.Started\}\}"}}</kbd></td>
<td>2020-05-02 09:14:43.66381 +0000 UTC</td>
</tr>
</tbody>
<small>Additional variables within the Core struct</small>
</table>
</div>
</template>
<script>
export default {
name: 'Variables',
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

View File

@ -2,9 +2,9 @@
<footer> <footer>
<div v-if="!core.footer" class="footer text-center mb-4 p-2"> <div v-if="!core.footer" class="footer text-center mb-4 p-2">
<a href="https://github.com/statping/statping" target="_blank"> <a href="https://github.com/statping/statping" target="_blank">
Statping {{core.version}} made with <font-awesome-icon icon="heart"/> Statping {{core.version}} made with <font-awesome-icon icon="heart" class="text-danger"/>
</a> | </a> |
<router-link :to="$store.state.admin ? '/dashboard' : '/login'">Dashboard</router-link> <router-link :to="$store.state.admin ? '/dashboard' : '/login'">{{$t('top_nav.dashboard')}}</router-link>
</div> </div>
<div v-else class="footer text-center mb-4 p-2" v-html="core.footer"></div> <div v-else class="footer text-center mb-4 p-2" v-html="core.footer"></div>
</footer> </footer>

View File

@ -62,7 +62,7 @@
<div class="col-md-2 col-6 float-right"> <div class="col-md-2 col-6 float-right">
<button v-if="!expanded" @click="setService" class="btn btn-sm float-right dyn-dark text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}"> <button v-if="!expanded" @click="setService" class="btn btn-sm float-right dyn-dark text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}">
View Service {{$t('service.view')}}
</button> </button>
</div> </div>
</div> </div>

View File

@ -17,7 +17,7 @@
<div v-if="false" class="row mb-4 align-content-center"> <div v-if="false" class="row mb-4 align-content-center">
<div v-if="!service.online" class="col-3 text-left"> <div v-if="!service.online" class="col-3 text-left">
<span class="text-danger font-5 font-weight-bold">okko</span> <span class="text-danger font-5 font-weight-bold"></span>
<span class="font-2 d-block">Current Downtime</span> <span class="font-2 d-block">Current Downtime</span>
</div> </div>

View File

@ -2,15 +2,15 @@
<div class="row stats_area mt-5 mb-4"> <div class="row stats_area mt-5 mb-4">
<div class="col-4"> <div class="col-4">
<span class="font-5 d-block font-weight-bold">{{humanTime(service.avg_response)}}</span> <span class="font-5 d-block font-weight-bold">{{humanTime(service.avg_response)}}</span>
<span class="font-1 subtitle">Average Response</span> <span class="font-1 subtitle">{{$t('service.average')}}</span>
</div> </div>
<div class="col-4"> <div class="col-4">
<span class="font-5 d-block font-weight-bold">{{service.online_24_hours}} %</span> <span class="font-5 d-block font-weight-bold">{{service.online_24_hours}} %</span>
<span class="font-1 subtitle">Uptime last 24 Hours</span> <span class="font-1 subtitle">{{$t('service.last_uptime', [24, $tc('hour', 24)])}}</span>
</div> </div>
<div class="col-4"> <div class="col-4">
<span class="font-5 d-block font-weight-bold">{{service.online_7_days}} %</span> <span class="font-5 d-block font-weight-bold">{{service.online_7_days}} %</span>
<span class="font-1 subtitle">Uptime last 7 Days</span> <span class="font-1 subtitle">{{$t('service.last_uptime', [7, $tc('day', 7)])}}</span>
</div> </div>
</div> </div>
</template> </template>

View File

@ -33,7 +33,7 @@
<div class="form-group"> <div class="form-group">
<label>{{ $t('setup.language') }}</label> <label>{{ $t('setup.language') }}</label>
<select v-model="core.language" v-bind:value="core.language" class="form-control"> <select v-model="core.language" class="form-control">
<option value="en">English</option> <option value="en">English</option>
<option value="es">Spanish</option> <option value="es">Spanish</option>
<option value="fr">French</option> <option value="fr">French</option>
@ -84,7 +84,7 @@
await Api.core_save(c) await Api.core_save(c)
const core = await Api.core() const core = await Api.core()
this.$store.commit('setCore', core) this.$store.commit('setCore', core)
setInterval(() => { this.loading = false }, 1500) this.loading = false
}, },
selectAll() { selectAll() {
this.$refs.input.select(); this.$refs.input.select();

View File

@ -2,13 +2,13 @@
<div> <div>
<form @submit.prevent="login" autocomplete="on"> <form @submit.prevent="login" autocomplete="on">
<div class="form-group row"> <div class="form-group row">
<label for="username" class="col-sm-2 col-form-label">Username</label> <label for="username" class="col-sm-2 col-form-label">{{$t('username')}}</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input @keyup="checkForm" type="text" v-model="username" name="username" class="form-control" id="username" placeholder="Username" autocorrect="off" autocapitalize="none"> <input @keyup="checkForm" type="text" v-model="username" name="username" class="form-control" id="username" placeholder="Username" autocorrect="off" autocapitalize="none">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="password" class="col-sm-2 col-form-label">Password</label> <label for="password" class="col-sm-2 col-form-label">{{$t('password')}}</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input @keyup="checkForm" type="password" v-model="password" name="password" class="form-control" id="password" placeholder="Password"> <input @keyup="checkForm" type="password" v-model="password" name="password" class="form-control" id="password" placeholder="Password">
</div> </div>
@ -16,10 +16,10 @@
<div class="form-group row"> <div class="form-group row">
<div class="col-sm-12"> <div class="col-sm-12">
<div v-if="error" class="alert alert-danger" role="alert"> <div v-if="error" class="alert alert-danger" role="alert">
Incorrect username or password {{$t('dashboard.wrong_login')}}
</div> </div>
<button @click.prevent="login" type="submit" class="btn btn-block mb-3 btn-primary" :disabled="disabled || loading"> <button @click.prevent="login" type="submit" class="btn btn-block mb-3 btn-primary" :disabled="disabled || loading">
{{loading ? "Loading" : "Sign in"}} {{loading ? $t('dashboard.loading') : $t('dashboard.sign_in')}}
</button> </button>
</div> </div>
</div> </div>

View File

@ -33,7 +33,11 @@ const english = {
title: 'Title', title: 'Title',
begins: 'Begins', begins: 'Begins',
name: 'Name', name: 'Name',
visibility: 'Visibility' loading: 'Loading',
login: 'Login',
sign_in: "Sign In",
visibility: 'Visibility',
wrong_login: 'Incorrect username or password'
}, },
settings: { settings: {
name: "Project Name", name: "Project Name",
@ -42,12 +46,23 @@ const english = {
footer_notes: "HTML is allowed inside the footer", footer_notes: "HTML is allowed inside the footer",
error_reporting: "Enable Error Reporting", error_reporting: "Enable Error Reporting",
error_reporting_notes: "Help the Statping project out by sending anonymous error logs back to our server.", error_reporting_notes: "Help the Statping project out by sending anonymous error logs back to our server.",
save: "Save Settings" save: "Save Settings",
main: "Main Settings",
theme: "Theme Editor",
cache: "Cache",
oauth: "OAuth",
beta: "BETA",
changelog: "Changelog",
repo: "Statping Github Repo",
docs: "Documentation",
}, },
service: { service: {
name: "Service Name", name: "Service Name",
type: "Service Type", type: "Service Type",
info: "Service Information" info: "Service Information",
view: "View Service",
average: "Average Response",
last_uptime: "Uptime last {0} {1}",
}, },
email: "Email Address", email: "Email Address",
port: "Database Port", port: "Database Port",

View File

@ -1,19 +1,100 @@
const french = { const french = {
setup: { top_nav: {
language: "Langue", dashboard: "Dashboard",
database_connection: "Database Connection" services: "Services",
users: "Users",
groups: "Groups",
announcements: "Announcements",
settings: "Settings",
logs: "Logs",
logout: 'Logout',
}, },
service: 'service', setup: {
language: "Language",
connection: "Database Connection",
host: "Host",
database: "Database",
project_name: "Project Name",
project_description: "Project Description",
domain: "Domain URL",
username: "Admin Username",
password: "Admin Password",
password_confirm: "Confirm Admin Password",
newsletter: "Newsletter",
newsletter_note: "We will not share your email, emails are only for major updates.",
send_reports: "Send Error Reports to Statping"
},
dashboard: {
total_services: "Total Services",
failures_24_hours: "Failures last 24 Hours",
online_services: "Online Services",
service: 'Service | Services',
group: 'Group',
title: 'Title',
begins: 'Begins',
name: 'Name',
loading: 'Loading',
login: 'Login',
sign_in: "Sign In",
visibility: 'Visibility',
wrong_login: 'Incorrect username or password'
},
settings: {
name: "Project Name",
description: "Project Name",
footer: "Custom Footer",
footer_notes: "HTML is allowed inside the footer",
error_reporting: "Enable Error Reporting",
error_reporting_notes: "Help the Statping project out by sending anonymous error logs back to our server.",
save: "Save Settings",
main: "Main Settings",
theme: "Theme Editor",
cache: "Cache",
oauth: "OAuth",
beta: "BETA",
changelog: "Changelog",
repo: "Statping Github Repo",
docs: "Documentation",
},
service: {
name: "Service Name",
type: "Service Type",
info: "Service Information",
view: "View Service",
average: "Average Response",
last_uptime: "Uptime last {0} {1}",
},
email: "Email Address",
port: "Database Port",
setting: "Settings",
username: "Username",
password: 'Password',
services: 'Services',
domain: 'Domain',
online: 'online', online: 'online',
public: 'Public',
private: 'Private',
admin: 'Admin',
offline: 'offline', offline: 'offline',
incident: 'incident', failure: 'failure | failures',
group: 'group', incident: 'incident | incidents',
checkin: 'checkin | checkins',
user: 'User | Users',
group: 'Group',
message: 'message', message: 'message',
logout: 'logout', edit: 'Edit',
type: 'Type',
sample_data: 'Sample Data', sample_data: 'Sample Data',
today: 'Today', today: 'Today',
day: 'day', last_login: 'Last Login',
hour: 'hour', uptime: '{0}% Uptime',
close: 'Close',
second: 'second | seconds',
minute: 'minute | minutes',
hour: 'hour | hours',
day: 'day | days',
week: 'week | weeks',
month: 'month | months',
} }
export default french export default french

View File

@ -1,19 +1,100 @@
const german = { const german = {
setup: { top_nav: {
language: "Sprache", dashboard: "Dashboard",
database_connection: "Database Connection" services: "Services",
users: "Users",
groups: "Groups",
announcements: "Announcements",
settings: "Settings",
logs: "Logs",
logout: 'Logout',
}, },
service: 'service', setup: {
language: "Language",
connection: "Database Connection",
host: "Host",
database: "Database",
project_name: "Project Name",
project_description: "Project Description",
domain: "Domain URL",
username: "Admin Username",
password: "Admin Password",
password_confirm: "Confirm Admin Password",
newsletter: "Newsletter",
newsletter_note: "We will not share your email, emails are only for major updates.",
send_reports: "Send Error Reports to Statping"
},
dashboard: {
total_services: "Total Services",
failures_24_hours: "Failures last 24 Hours",
online_services: "Online Services",
service: 'Service | Services',
group: 'Group',
title: 'Title',
begins: 'Begins',
name: 'Name',
loading: 'Loading',
login: 'Login',
sign_in: "Sign In",
visibility: 'Visibility',
wrong_login: 'Incorrect username or password'
},
settings: {
name: "Project Name",
description: "Project Name",
footer: "Custom Footer",
footer_notes: "HTML is allowed inside the footer",
error_reporting: "Enable Error Reporting",
error_reporting_notes: "Help the Statping project out by sending anonymous error logs back to our server.",
save: "Save Settings",
main: "Main Settings",
theme: "Theme Editor",
cache: "Cache",
oauth: "OAuth",
beta: "BETA",
changelog: "Changelog",
repo: "Statping Github Repo",
docs: "Documentation",
},
service: {
name: "Service Name",
type: "Service Type",
info: "Service Information",
view: "View Service",
average: "Average Response",
last_uptime: "Uptime last {0} {1}",
},
email: "Email Address",
port: "Database Port",
setting: "Settings",
username: "Username",
password: 'Password',
services: 'Services',
domain: 'Domain',
online: 'online', online: 'online',
public: 'Public',
private: 'Private',
admin: 'Admin',
offline: 'offline', offline: 'offline',
incident: 'incident', failure: 'failure | failures',
group: 'group', incident: 'incident | incidents',
checkin: 'checkin | checkins',
user: 'User | Users',
group: 'Group',
message: 'message', message: 'message',
logout: 'logout', edit: 'Edit',
type: 'Type',
sample_data: 'Sample Data', sample_data: 'Sample Data',
today: 'Today', today: 'Today',
day: 'day', last_login: 'Last Login',
hour: 'hour', uptime: '{0}% Uptime',
close: 'Close',
second: 'second | seconds',
minute: 'minute | minutes',
hour: 'hour | hours',
day: 'day | days',
week: 'week | weeks',
month: 'month | months',
} }
export default german export default german

View File

@ -1,19 +1,100 @@
const russian = { const russian = {
setup: { top_nav: {
language: "язык", dashboard: "Dashboard",
database_connection: "Database Connection" services: "Services",
users: "Users",
groups: "Groups",
announcements: "Announcements",
settings: "Settings",
logs: "Logs",
logout: 'Logout',
}, },
service: 'service', setup: {
online: 'online', language: "Language",
offline: 'offline', connection: "Database Connection",
incident: 'incident', host: "Host",
group: 'group', database: "Database",
project_name: "Project Name",
project_description: "Project Description",
domain: "Domain URL",
username: "Admin Username",
password: "Admin Password",
password_confirm: "Confirm Admin Password",
newsletter: "Newsletter",
newsletter_note: "We will not share your email, emails are only for major updates.",
send_reports: "Send Error Reports to Statping"
},
dashboard: {
total_services: "Total Services",
failures_24_hours: "Failures last 24 Hours",
online_services: "Online Services",
service: 'Service | Services',
group: 'Group',
title: 'Title',
begins: 'Begins',
name: 'Name',
loading: 'Loading',
login: 'Login',
sign_in: "Sign In",
visibility: 'Visibility',
wrong_login: 'Incorrect username or password'
},
settings: {
name: "Project Name",
description: "Project Name",
footer: "Custom Footer",
footer_notes: "HTML is allowed inside the footer",
error_reporting: "Enable Error Reporting",
error_reporting_notes: "Help the Statping project out by sending anonymous error logs back to our server.",
save: "Save Settings",
main: "Main Settings",
theme: "Theme Editor",
cache: "Cache",
oauth: "OAuth",
beta: "BETA",
changelog: "Changelog",
repo: "Statping Github Repo",
docs: "Documentation",
},
service: {
name: "Service Name",
type: "Service Type",
info: "Service Information",
view: "View Service",
average: "Average Response",
last_uptime: "Uptime last {0} {1}",
},
email: "Email Address",
port: "Database Port",
setting: "Settings",
username: "Username",
password: 'Password',
services: 'Services',
domain: 'Domain',
online: 'онлайн',
public: 'Public',
private: 'Private',
admin: 'Admin',
offline: 'не в сети',
failure: 'failure | failures',
incident: 'incident | incidents',
checkin: 'checkin | checkins',
user: 'User | Users',
group: 'Group',
message: 'message', message: 'message',
logout: 'logout', edit: 'Edit',
type: 'Type',
sample_data: 'Sample Data', sample_data: 'Sample Data',
today: 'Today', today: 'Today',
day: 'day', last_login: 'Last Login',
hour: 'hour', uptime: '{0}% Uptime',
close: 'близко',
second: 'второй | секунд',
minute: 'минут | минут',
hour: 'час | часов',
day: 'день | дней',
week: 'неделя | недель',
month: 'месяц | месяцы',
} }
export default russian export default russian

View File

@ -1,19 +1,100 @@
const spanish = { const spanish = {
setup: { top_nav: {
language: "Idioma", dashboard: "Dashboard",
database_connection: "Database Connection" services: "Services",
users: "Users",
groups: "Groups",
announcements: "Announcements",
settings: "Settings",
logs: "Logs",
logout: 'Logout',
}, },
service: 'service', setup: {
language: "Language",
connection: "Database Connection",
host: "Host",
database: "Database",
project_name: "Project Name",
project_description: "Project Description",
domain: "Domain URL",
username: "Admin Username",
password: "Admin Password",
password_confirm: "Confirm Admin Password",
newsletter: "Newsletter",
newsletter_note: "We will not share your email, emails are only for major updates.",
send_reports: "Send Error Reports to Statping"
},
dashboard: {
total_services: "Total Services",
failures_24_hours: "Failures last 24 Hours",
online_services: "Online Services",
service: 'Service | Services',
group: 'Group',
title: 'Title',
begins: 'Begins',
name: 'Name',
loading: 'Loading',
login: 'Login',
sign_in: "Sign In",
visibility: 'Visibility',
wrong_login: 'Incorrect username or password'
},
settings: {
name: "Project Name",
description: "Project Name",
footer: "Custom Footer",
footer_notes: "HTML is allowed inside the footer",
error_reporting: "Enable Error Reporting",
error_reporting_notes: "Help the Statping project out by sending anonymous error logs back to our server.",
save: "Save Settings",
main: "Main Settings",
theme: "Theme Editor",
cache: "Cache",
oauth: "OAuth",
beta: "BETA",
changelog: "Changelog",
repo: "Statping Github Repo",
docs: "Documentation",
},
service: {
name: "Service Name",
type: "Service Type",
info: "Service Information",
view: "View Service",
average: "Average Response",
last_uptime: "Uptime last {0} {1}",
},
email: "Email Address",
port: "Database Port",
setting: "Settings",
username: "Username",
password: 'Password',
services: 'Services',
domain: 'Domain',
online: 'online', online: 'online',
public: 'Public',
private: 'Private',
admin: 'Admin',
offline: 'offline', offline: 'offline',
incident: 'incident', failure: 'failure | failures',
group: 'group', incident: 'incident | incidents',
checkin: 'checkin | checkins',
user: 'User | Users',
group: 'Group',
message: 'message', message: 'message',
logout: 'logout', edit: 'Edit',
type: 'Type',
sample_data: 'Sample Data', sample_data: 'Sample Data',
today: 'Today', today: 'Today',
day: 'day', last_login: 'Last Login',
hour: 'hour', uptime: '{0}% Uptime',
close: 'Close',
second: 'second | seconds',
minute: 'minute | minutes',
hour: 'hour | hours',
day: 'day | days',
week: 'week | weeks',
month: 'month | months',
} }
export default spanish export default spanish

View File

@ -20,7 +20,7 @@ export default Vue.mixin({
return startOfToday() return startOfToday()
}, },
secondsHumanize (val) { secondsHumanize (val) {
return `${val} seconds` return `${val} ${this.$t('second', val)}`
}, },
utc(val) { utc(val) {
return new Date.UTC(val) return new Date.UTC(val)
@ -175,7 +175,7 @@ export default Vue.mixin({
return startOfMonth(date) return startOfMonth(date)
}, },
lastDayOfMonth(month) { lastDayOfMonth(month) {
return lastDayOfMonth(date) return lastDayOfMonth(month)
}, },
addMonths(date, amount) { addMonths(date, amount) {
return addMonths(date, amount) return addMonths(date, amount)

View File

@ -3,19 +3,19 @@
<div class="row"> <div class="row">
<div class="col-md-3 col-sm-12 mb-4 mb-md-0"> <div class="col-md-3 col-sm-12 mb-4 mb-md-0">
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical"> <div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
<h6 class="text-muted">Main Settings</h6> <h6 class="text-muted">{{ $t('settings.main') }}</h6>
<a @click.prevent="changeTab" class="nav-link" v-bind:class="{active: liClass('v-pills-home-tab')}" id="v-pills-home-tab" data-toggle="pill" href="#v-pills-home" role="tab" aria-controls="v-pills-home" aria-selected="true"> <a @click.prevent="changeTab" class="nav-link" v-bind:class="{active: liClass('v-pills-home-tab')}" id="v-pills-home-tab" data-toggle="pill" href="#v-pills-home" role="tab" aria-controls="v-pills-home" aria-selected="true">
<font-awesome-icon icon="cog" class="mr-2"/> Settings <font-awesome-icon icon="cog" class="mr-2"/> {{ $t('setting') }}
</a> </a>
<a @click.prevent="changeTab" class="nav-link" v-bind:class="{active: liClass('v-pills-style-tab')}" id="v-pills-style-tab" data-toggle="pill" href="#v-pills-style" role="tab" aria-controls="v-pills-style" aria-selected="false"> <a @click.prevent="changeTab" class="nav-link" v-bind:class="{active: liClass('v-pills-style-tab')}" id="v-pills-style-tab" data-toggle="pill" href="#v-pills-style" role="tab" aria-controls="v-pills-style" aria-selected="false">
<font-awesome-icon icon="image" class="mr-2"/> Theme Editor <font-awesome-icon icon="image" class="mr-2"/> {{ $t('settings.theme') }}
</a> </a>
<a @click.prevent="changeTab" class="nav-link" v-bind:class="{active: liClass('v-pills-cache-tab')}" id="v-pills-cache-tab" data-toggle="pill" href="#v-pills-cache" role="tab" aria-controls="v-pills-cache" aria-selected="false"> <a @click.prevent="changeTab" class="nav-link" v-bind:class="{active: liClass('v-pills-cache-tab')}" id="v-pills-cache-tab" data-toggle="pill" href="#v-pills-cache" role="tab" aria-controls="v-pills-cache" aria-selected="false">
<font-awesome-icon icon="paperclip" class="mr-2"/> Cache <font-awesome-icon icon="paperclip" class="mr-2"/> {{ $t('settings.cache') }}
</a> </a>
<a @click.prevent="changeTab" class="nav-link" v-bind:class="{active: liClass('v-pills-oauth-tab')}" id="v-pills-oauth-tab" data-toggle="pill" href="#v-pills-oauth" role="tab" aria-controls="v-pills-oauth" aria-selected="false"> <a @click.prevent="changeTab" class="nav-link" v-bind:class="{active: liClass('v-pills-oauth-tab')}" id="v-pills-oauth-tab" data-toggle="pill" href="#v-pills-oauth" role="tab" aria-controls="v-pills-oauth" aria-selected="false">
<font-awesome-icon icon="key" class="mr-2"/> OAuth <span class="mt-1 float-right badge badge-light text-dark font-1">BETA</span> <font-awesome-icon icon="key" class="mr-2"/> {{ $t('settings.oauth') }} <span class="mt-1 float-right badge badge-light text-dark font-1">{{ $t('settings.beta') }}</span>
</a> </a>
<h6 class="mt-4 text-muted">Notifiers</h6> <h6 class="mt-4 text-muted">Notifiers</h6>
@ -33,19 +33,19 @@
<h6 class="mt-4 mb-3 text-muted">Statping Links</h6> <h6 class="mt-4 mb-3 text-muted">Statping Links</h6>
<a href="https://github.com/statping/statping/wiki" class="mb-2 font-2 text-decoration-none text-muted"> <a href="https://github.com/statping/statping/wiki" class="mb-2 font-2 text-decoration-none text-muted">
<font-awesome-icon icon="question" class="mr-3"/> Documentation <font-awesome-icon icon="question" class="mr-3"/> {{$t('settings.docs')}}
</a> </a>
<a href="https://github.com/statping/statping/wiki/API" class="mb-2 font-2 text-decoration-none text-muted"> <a href="https://github.com/statping/statping/wiki/API" class="mb-2 font-2 text-decoration-none text-muted">
<font-awesome-icon icon="laptop" class="mr-2"/> API Documentation <font-awesome-icon icon="laptop" class="mr-2"/> API {{$t('settings.docs')}}
</a> </a>
<a href="https://raw.githubusercontent.com/statping/statping/master/CHANGELOG.md" class="mb-2 font-2 text-decoration-none text-muted"> <a href="https://raw.githubusercontent.com/statping/statping/master/CHANGELOG.md" class="mb-2 font-2 text-decoration-none text-muted">
<font-awesome-icon icon="book" class="mr-3"/> Changelog <font-awesome-icon icon="book" class="mr-3"/> {{$t('settings.changelog')}}
</a> </a>
<a href="https://github.com/statping/statping" class="mb-2 font-2 text-decoration-none text-muted"> <a href="https://github.com/statping/statping" class="mb-2 font-2 text-decoration-none text-muted">
<font-awesome-icon icon="code-branch" class="mr-3"/> Statping Github Repo <font-awesome-icon icon="code-branch" class="mr-3"/> {{$t('settings.repo')}}
</a> </a>
<div class="row justify-content-center mt-2"> <div class="row justify-content-center mt-2">
@ -89,30 +89,18 @@
<div class="card text-black-50 bg-white mt-3"> <div class="card text-black-50 bg-white mt-3">
<div class="card-header">QR Code for Mobile App</div> <div class="card-header">QR Code for Mobile App</div>
<div class="card-body"> <div class="card-body">
<img class="rounded" width="300" height="300" :src="qrcode"> <img class="rounded" width="300" height="300" :src="qrcode">
</div> </div>
</div> </div>
</div> </div>
<div class="tab-pane fade" v-bind:class="{active: liClass('v-pills-style-tab'), show: liClass('v-pills-style-tab')}" id="v-pills-style" role="tabpanel" aria-labelledby="v-pills-style-tab"> <div class="tab-pane fade" v-bind:class="{active: liClass('v-pills-style-tab'), show: liClass('v-pills-style-tab')}" id="v-pills-style" role="tabpanel" aria-labelledby="v-pills-style-tab">
<div class="card text-black-50 bg-white mb-5"> <ThemeEditor/>
<div class="card-header">Theme Editor</div>
<div class="card-body">
<ThemeEditor/>
</div>
</div>
</div> </div>
<div class="tab-pane fade" v-bind:class="{active: liClass('v-pills-cache-tab'), show: liClass('v-pills-cache-tab')}" id="v-pills-cache" role="tabpanel" aria-labelledby="v-pills-cache-tab"> <div class="tab-pane fade" v-bind:class="{active: liClass('v-pills-cache-tab'), show: liClass('v-pills-cache-tab')}" id="v-pills-cache" role="tabpanel" aria-labelledby="v-pills-cache-tab">
<div class="card text-black-50 bg-white mb-5"> <Cache/>
<div class="card-header">Cache</div>
<div class="card-body">
<Cache/>
</div>
</div>
</div> </div>
<div class="tab-pane fade" v-bind:class="{active: liClass('v-pills-oauth-tab'), show: liClass('v-pills-oauth-tab')}" id="v-pills-oauth" role="tabpanel" aria-labelledby="v-pills-oauth-tab"> <div class="tab-pane fade" v-bind:class="{active: liClass('v-pills-oauth-tab'), show: liClass('v-pills-oauth-tab')}" id="v-pills-oauth" role="tabpanel" aria-labelledby="v-pills-oauth-tab">
@ -120,132 +108,7 @@
</div> </div>
<div class="tab-pane fade" v-bind:class="{active: liClass(`v-pills-notifier-docs-tab`), show: liClass(`v-pills-notifier-docs-tab`)}" v-bind:id="`v-pills-notifier-docs-tab`" role="tabpanel" v-bind:aria-labelledby="`v-pills-notifier-docs-tab`"> <div class="tab-pane fade" v-bind:class="{active: liClass(`v-pills-notifier-docs-tab`), show: liClass(`v-pills-notifier-docs-tab`)}" v-bind:id="`v-pills-notifier-docs-tab`" role="tabpanel" v-bind:aria-labelledby="`v-pills-notifier-docs-tab`">
<h2>Notifier Variables</h2> <Variables/>
You can insert dynamic fields within the notifier payloads for some notifiers.
<p class="mt-2">
Checkout the <a href="https://github.com/statping/statping/blob/master/types/services/struct.go">Service struct</a> and the <a href="https://github.com/statping/statping/blob/master/types/failures/struct.go">Failures struct</a> and create variables in golang template format.
</p>
<p class="mt-2">
For example, if you have <b>{{"\{\{.Service.Name\}\}"}}</b> it will return the service name.
</p>
<h2 class="mt-3">Service Variables</h2>
<table class="table">
<thead>
<tr>
<th scope="col">Variable</th>
<th scope="col">True Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><kbd>{{"\{\{.Service.Id\}\}"}}</kbd></td>
<td>1</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Service.Name\}\}"}}</kbd></td>
<td>Example Service</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Service.Domain\}\}"}}</kbd></td>
<td>https://statping.com</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Service.Port\}\}"}}</kbd></td>
<td>8080</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Service.DowntimeAgo\}\}"}}</kbd></td>
<td>35 minutes ago</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Service.LastStatusCode\}\}"}}</kbd></td>
<td>404</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Service.FailuresLast24Hours\}\}"}}</kbd></td>
<td>38</td>
</tr>
</tbody>
<small>Additional variables within the Service struct</small>
</table>
<h2 class="mt-3">Failure Variables</h2>
<table class="table">
<thead>
<tr>
<th scope="col">Variable</th>
<th scope="col">True Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><kbd>{{"\{\{.Failure.Issue\}\}"}}</kbd></td>
<td>Received 404 status code</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Failure.ErrorCode\}\}"}}</kbd></td>
<td>404</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Failure.Service\}\}"}}</kbd></td>
<td>1</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Failure.PingTime\}\}"}}</kbd></td>
<td>12482 (microseconds)</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Failure.DowntimeAgo\}\}"}}</kbd></td>
<td>35 minutes ago</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Failure.CreatedAt\}\}"}}</kbd></td>
<td>2020-05-02 09:14:43.66381 +0000 UTC</td>
</tr>
</tbody>
<small>Additional variables within the Failures struct</small>
</table>
<h2 class="mt-3">Core Variables</h2>
<table class="table">
<thead>
<tr>
<th scope="col">Variable</th>
<th scope="col">True Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><kbd>{{"\{\{.Core.Domain\}\}"}}</kbd></td>
<td>http://localhost:8080</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Core.Name\}\}"}}</kbd></td>
<td>Statping Demo</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Core.Description\}\}"}}</kbd></td>
<td>Statping will monitor your stuff!</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Core.Version\}\}"}}</kbd></td>
<td>v0.90.34</td>
</tr>
<tr>
<td><kbd>{{"\{\{.Core.Started\}\}"}}</kbd></td>
<td>2020-05-02 09:14:43.66381 +0000 UTC</td>
</tr>
</tbody>
<small>Additional variables within the Core struct</small>
</table>
</div> </div>
<div v-for="(notifier, index) in notifiers" v-bind:key="`${notifier.method}_${index}`" class="tab-pane fade" v-bind:class="{active: liClass(`v-pills-${notifier.method.toLowerCase()}-tab`), show: liClass(`v-pills-${notifier.method.toLowerCase()}-tab`)}" v-bind:id="`v-pills-${notifier.method.toLowerCase()}-tab`" role="tabpanel" v-bind:aria-labelledby="`v-pills-${notifier.method.toLowerCase()}-tab`"> <div v-for="(notifier, index) in notifiers" v-bind:key="`${notifier.method}_${index}`" class="tab-pane fade" v-bind:class="{active: liClass(`v-pills-${notifier.method.toLowerCase()}-tab`), show: liClass(`v-pills-${notifier.method.toLowerCase()}-tab`)}" v-bind:id="`v-pills-${notifier.method.toLowerCase()}-tab`" role="tabpanel" v-bind:aria-labelledby="`v-pills-${notifier.method.toLowerCase()}-tab`">
@ -262,6 +125,7 @@
<script> <script>
import Api from '../API'; import Api from '../API';
import GithubButton from 'vue-github-button' import GithubButton from 'vue-github-button'
import Variables from "@/components/Dashboard/Variables";
const CoreSettings = () => import('@/forms/CoreSettings') const CoreSettings = () => import('@/forms/CoreSettings')
const FormIntegration = () => import('@/forms/Integration') const FormIntegration = () => import('@/forms/Integration')
@ -273,6 +137,7 @@
export default { export default {
name: 'Settings', name: 'Settings',
components: { components: {
Variables,
GithubButton, GithubButton,
OAuth, OAuth,
Cache, Cache,

View File

@ -167,11 +167,17 @@ export default new Vuex.Store({
context.commit("setGroups", groups); context.commit("setGroups", groups);
const services = await Api.services() const services = await Api.services()
context.commit("setServices", services); context.commit("setServices", services);
const checkins = await Api.checkins() const messages = await Api.messages()
context.commit("setCheckins", checkins); context.commit("setMessages", messages)
const messages = await Api.messages() context.commit("setHasPublicData", true)
context.commit("setMessages", messages) try {
context.commit("setHasPublicData", true) const checkins = await Api.checkins()
context.commit("setCheckins", checkins);
} catch(e) {
window.console.error(e)
await Api.logout()
return
}
const notifiers = await Api.notifiers() const notifiers = await Api.notifiers()
context.commit("setNotifiers", notifiers); context.commit("setNotifiers", notifiers);
const users = await Api.users() const users = await Api.users()

View File

@ -18,11 +18,6 @@ const (
slackMethod = "slack" slackMethod = "slack"
) )
var (
failingTemplate = `{ "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": ":warning: The service {{.Service.Name}} is currently offline! :warning:" } }, { "type": "divider" }, { "type": "section", "fields": [ { "type": "mrkdwn", "text": "*Service:*\n{{.Service.Name}}" }, { "type": "mrkdwn", "text": "*URL:*\n{{.Service.Domain}}" }, { "type": "mrkdwn", "text": "*Status Code:*\n{{.Service.LastStatusCode}}" }, { "type": "mrkdwn", "text": "*When:*\n{{.Failure.CreatedAt}}" }, { "type": "mrkdwn", "text": "*Downtime:*\n{{.Service.DowntimeAgo}}" }, { "type": "plain_text", "text": "*Error:*\n{{.Failure.Issue}}" } ] }, { "type": "divider" }, { "type": "actions", "elements": [ { "type": "button", "text": { "type": "plain_text", "text": "View Offline Service", "emoji": true }, "style": "danger", "url": "{{.Core.Domain}}/service/{{.Service.Id}}" }, { "type": "button", "text": { "type": "plain_text", "text": "Go to Statping", "emoji": true }, "url": "{{.Core.Domain}}" } ] } ] }`
successTemplate = `{ "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": "The service {{.Service.Name}} is back online." } }, { "type": "actions", "elements": [ { "type": "button", "text": { "type": "plain_text", "text": "View Service", "emoji": true }, "style": "primary", "url": "{{.Core.Domain}}/service/{{.Service.Id}}" }, { "type": "button", "text": { "type": "plain_text", "text": "Go to Statping", "emoji": true }, "url": "{{.Core.Domain}}" } ] } ] }`
)
type slack struct { type slack struct {
*notifications.Notification *notifications.Notification
} }
@ -40,8 +35,8 @@ var slacker = &slack{&notifications.Notification{
Delay: time.Duration(10 * time.Second), Delay: time.Duration(10 * time.Second),
Host: "https://webhooksurl.slack.com/***", Host: "https://webhooksurl.slack.com/***",
Icon: "fab fa-slack", Icon: "fab fa-slack",
SuccessData: successTemplate, SuccessData: `{ "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": "The service {{.Service.Name}} is back online." } }, { "type": "actions", "elements": [ { "type": "button", "text": { "type": "plain_text", "text": "View Service", "emoji": true }, "style": "primary", "url": "{{.Core.Domain}}/service/{{.Service.Id}}" }, { "type": "button", "text": { "type": "plain_text", "text": "Go to Statping", "emoji": true }, "url": "{{.Core.Domain}}" } ] } ] }`,
FailureData: failingTemplate, FailureData: `{ "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": ":warning: The service {{.Service.Name}} is currently offline! :warning:" } }, { "type": "divider" }, { "type": "section", "fields": [ { "type": "mrkdwn", "text": "*Service:*\n{{.Service.Name}}" }, { "type": "mrkdwn", "text": "*URL:*\n{{.Service.Domain}}" }, { "type": "mrkdwn", "text": "*Status Code:*\n{{.Service.LastStatusCode}}" }, { "type": "mrkdwn", "text": "*When:*\n{{.Failure.CreatedAt}}" }, { "type": "mrkdwn", "text": "*Downtime:*\n{{.Service.DowntimeAgo}}" }, { "type": "plain_text", "text": "*Error:*\n{{.Failure.Issue}}" } ] }, { "type": "divider" }, { "type": "actions", "elements": [ { "type": "button", "text": { "type": "plain_text", "text": "View Offline Service", "emoji": true }, "style": "danger", "url": "{{.Core.Domain}}/service/{{.Service.Id}}" }, { "type": "button", "text": { "type": "plain_text", "text": "Go to Statping", "emoji": true }, "url": "{{.Core.Domain}}" } ] } ] }`,
DataType: "json", DataType: "json",
RequestInfo: "Slack allows you to customize your own messages with many complex components. Checkout the <a target=\"_blank\" href=\"https://api.slack.com/reference/surfaces/formatting\">Slack Message API</a> to learn how you can create your own.", RequestInfo: "Slack allows you to customize your own messages with many complex components. Checkout the <a target=\"_blank\" href=\"https://api.slack.com/reference/surfaces/formatting\">Slack Message API</a> to learn how you can create your own.",
Limits: 60, Limits: 60,
@ -66,7 +61,7 @@ func (s *slack) sendSlack(msg string) (string, error) {
func (s *slack) OnTest() (string, error) { func (s *slack) OnTest() (string, error) {
example := services.Example(true) example := services.Example(true)
testMsg := ReplaceVars(failingTemplate, example, nil) testMsg := ReplaceVars(s.SuccessData, example, nil)
contents, resp, err := utils.HttpRequest(s.Host, "POST", "application/json", nil, bytes.NewBuffer([]byte(testMsg)), time.Duration(10*time.Second), true, nil) contents, resp, err := utils.HttpRequest(s.Host, "POST", "application/json", nil, bytes.NewBuffer([]byte(testMsg)), time.Duration(10*time.Second), true, nil)
if err != nil { if err != nil {
return "", err return "", err
@ -80,14 +75,14 @@ func (s *slack) OnTest() (string, error) {
// OnFailure will trigger failing service // OnFailure will trigger failing service
func (s *slack) OnFailure(srv *services.Service, f *failures.Failure) (string, error) { func (s *slack) OnFailure(srv *services.Service, f *failures.Failure) (string, error) {
msg := ReplaceVars(failingTemplate, srv, f) msg := ReplaceVars(s.FailureData, srv, f)
out, err := s.sendSlack(msg) out, err := s.sendSlack(msg)
return out, err return out, err
} }
// OnSuccess will trigger successful service // OnSuccess will trigger successful service
func (s *slack) OnSuccess(srv *services.Service) (string, error) { func (s *slack) OnSuccess(srv *services.Service) (string, error) {
msg := ReplaceVars(successTemplate, srv, nil) msg := ReplaceVars(s.SuccessData, srv, nil)
out, err := s.sendSlack(msg) out, err := s.sendSlack(msg)
return out, err return out, err
} }

View File

@ -40,6 +40,9 @@ func Select() (*Core, error) {
if utils.Params.GetBool("ALLOW_REPORTS") { if utils.Params.GetBool("ALLOW_REPORTS") {
App.AllowReports = null.NewNullBool(true) App.AllowReports = null.NewNullBool(true)
} }
if utils.Params.GetString("LANGUAGE") != "" {
App.Language = utils.Params.GetString("LANGUAGE")
}
return App, q.Error() return App, q.Error()
} }

View File

@ -1 +1 @@
0.90.53 0.90.54