mirror of https://github.com/statping/statping
updates
parent
8061d91fd7
commit
6d3e204131
|
@ -44,11 +44,11 @@ func checkServices() {
|
|||
func (s *Service) Check(record bool) {
|
||||
switch s.Type {
|
||||
case "http":
|
||||
s.checkHttp(record)
|
||||
s.CheckHttp(record)
|
||||
case "tcp", "udp":
|
||||
s.checkTcp(record)
|
||||
s.CheckTcp(record)
|
||||
case "icmp":
|
||||
s.checkIcmp(record)
|
||||
s.CheckIcmp(record)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ func isIPv6(address string) bool {
|
|||
}
|
||||
|
||||
// checkIcmp will send a ICMP ping packet to the service
|
||||
func (s *Service) checkIcmp(record bool) *Service {
|
||||
func (s *Service) CheckIcmp(record bool) *Service {
|
||||
p := fastping.NewPinger()
|
||||
resolveIP := "ip4:icmp"
|
||||
if isIPv6(s.Domain) {
|
||||
|
@ -148,7 +148,7 @@ func (s *Service) checkIcmp(record bool) *Service {
|
|||
}
|
||||
|
||||
// checkTcp will check a TCP service
|
||||
func (s *Service) checkTcp(record bool) *Service {
|
||||
func (s *Service) CheckTcp(record bool) *Service {
|
||||
dnsLookup, err := s.dnsCheck()
|
||||
if err != nil {
|
||||
if record {
|
||||
|
@ -188,7 +188,7 @@ func (s *Service) checkTcp(record bool) *Service {
|
|||
}
|
||||
|
||||
// checkHttp will check a HTTP service
|
||||
func (s *Service) checkHttp(record bool) *Service {
|
||||
func (s *Service) CheckHttp(record bool) *Service {
|
||||
dnsLookup, err := s.dnsCheck()
|
||||
if err != nil {
|
||||
if record {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "rm -rf dist && cross-env NODE_ENV=production webpack",
|
||||
"dev": "cross-env NODE_ENV=development webpack-dev-server --progress",
|
||||
"dev": "cross-env NODE_ENV=development webpack-dev-server --host 0.0.0.0 --port 8888 --progress",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -22,6 +22,7 @@
|
|||
"querystring": "^0.2.0",
|
||||
"vue": "^2.6.10",
|
||||
"vue-apexcharts": "^1.5.2",
|
||||
"vue-flatpickr-component": "^8.1.5",
|
||||
"vue-moment": "^4.1.0",
|
||||
"vue-router": "~3.0",
|
||||
"vuedraggable": "^2.23.2",
|
||||
|
|
|
@ -64,6 +64,10 @@ class Api {
|
|||
return axios.post('/api/groups', data).then(response => (response.data))
|
||||
}
|
||||
|
||||
async group_update (data) {
|
||||
return axios.post('/api/groups/'+data.id, data).then(response => (response.data))
|
||||
}
|
||||
|
||||
async users () {
|
||||
return axios.get('/api/users').then(response => (response.data))
|
||||
}
|
||||
|
@ -72,6 +76,10 @@ class Api {
|
|||
return axios.post('/api/users', data).then(response => (response.data))
|
||||
}
|
||||
|
||||
async user_update (data) {
|
||||
return axios.post('/api/users/'+data.id, data).then(response => (response.data))
|
||||
}
|
||||
|
||||
async user_delete (id) {
|
||||
return axios.delete('/api/users/'+id).then(response => (response.data))
|
||||
}
|
||||
|
@ -80,6 +88,14 @@ class Api {
|
|||
return axios.get('/api/messages').then(response => (response.data))
|
||||
}
|
||||
|
||||
async message_create (data) {
|
||||
return axios.post('/api/messages', data).then(response => (response.data))
|
||||
}
|
||||
|
||||
async message_update (data) {
|
||||
return axios.post('/api/messages/'+data.id, data).then(response => (response.data))
|
||||
}
|
||||
|
||||
async message_delete (id) {
|
||||
return axios.delete('/api/messages/'+id).then(response => (response.data))
|
||||
}
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
<tr v-for="(message, index) in $store.getters.messages" v-bind:key="index">
|
||||
<td>{{message.title}}</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<router-link to="/service/${service(message.service).id}">{{service(message.service)}}</router-link>
|
||||
<router-link :to="serviceLink(message.service)">{{service(message.service)}}</router-link>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">{{message.start_on}}</td>
|
||||
<td class="text-right">
|
||||
<div class="btn-group">
|
||||
<a href="message/1" class="btn btn-outline-secondary"><i class="fas fa-exclamation-triangle"></i> Edit</a>
|
||||
<a @click="deleteMessage(message)" href="#" class="btn btn-danger"><font-awesome-icon icon="times" /></a>
|
||||
<a @click.prevent="editMessage(message, edit)" href="#" class="btn btn-outline-secondary"><i class="fas fa-exclamation-triangle"></i> Edit</a>
|
||||
<a @click.prevent="deleteMessage(message)" href="#" class="btn btn-danger"><font-awesome-icon icon="times" /></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -31,15 +31,8 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<FormMessage :edit="editChange" :in_message="message"/>
|
||||
|
||||
<div class="col-12">
|
||||
<h1 class="text-black-50 mt-5">Create Message</h1>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<FormMessage/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -52,12 +45,22 @@
|
|||
components: {FormMessage},
|
||||
data () {
|
||||
return {
|
||||
|
||||
edit: false,
|
||||
message: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
editChange(v) {
|
||||
this.message = {}
|
||||
this.edit = v
|
||||
},
|
||||
editMessage(m, mode) {
|
||||
this.message = m
|
||||
this.edit = !mode
|
||||
},
|
||||
service (id) {
|
||||
return this.$store.getters.serviceById(id).name || ""
|
||||
const s = this.$store.getters.serviceById(id) || {}
|
||||
return s.name || "Global Message"
|
||||
},
|
||||
async deleteMessage(m) {
|
||||
let c = confirm(`Are you sure you want to delete message '${m.title}'?`)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<i class="fas fa-plus"></i> Create
|
||||
</router-link>
|
||||
</h1>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -16,7 +17,7 @@
|
|||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<draggable @update="log" tag="tbody" v-model="servicesList" :list="$store.getters.servicesInOrder" :key="this.$store.getters.servicesInOrder.length" class="sortable" handle=".drag_icon">
|
||||
<draggable tag="tbody" v-model="servicesList" :list="$store.getters.servicesInOrder" :key="this.$store.getters.servicesInOrder.length" class="sortable" handle=".drag_icon">
|
||||
<tr v-for="(service, index) in $store.getters.services" :key="index">
|
||||
<td>
|
||||
<span class="drag_icon d-none d-md-inline">
|
||||
|
@ -40,7 +41,7 @@
|
|||
<router-link :to="{path: `/dashboard/edit_service/${service.id}`, params: {service: service} }" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-chart-area"></i> View
|
||||
</router-link>
|
||||
<a @click="deleteService(service)" href="#" class="btn btn-danger">
|
||||
<a @click.prevent="deleteService(service)" href="#" class="btn btn-danger">
|
||||
<font-awesome-icon icon="times" />
|
||||
</a>
|
||||
</div>
|
||||
|
@ -74,8 +75,8 @@
|
|||
</td>
|
||||
<td class="text-right">
|
||||
<div class="btn-group">
|
||||
<a href="group/2" class="btn btn-outline-secondary"><font-awesome-icon icon="chart-area" /> Edit</a>
|
||||
<a @click="deleteGroup(group)" href="#" class="btn btn-danger">
|
||||
<a @click.prevent="editGroup(group, edit)" href="#" class="btn btn-outline-secondary"><font-awesome-icon icon="chart-area" /> Edit</a>
|
||||
<a @click.prevent="deleteGroup(group)" href="#" class="btn btn-danger">
|
||||
<font-awesome-icon icon="times" />
|
||||
</a>
|
||||
</div>
|
||||
|
@ -85,13 +86,7 @@
|
|||
</draggable>
|
||||
</table>
|
||||
|
||||
<h1 class="text-muted mt-5">Create Group</h1>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<FormGroup/>
|
||||
</div>
|
||||
</div>
|
||||
<FormGroup :edit="editChange" :in_group="group"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -112,7 +107,8 @@
|
|||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
edit: false,
|
||||
group: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -149,6 +145,14 @@
|
|||
|
||||
},
|
||||
methods: {
|
||||
editChange(v) {
|
||||
this.group = {}
|
||||
this.edit = v
|
||||
},
|
||||
editGroup(g, mode) {
|
||||
this.group = g
|
||||
this.edit = !mode
|
||||
},
|
||||
reordered_services() {
|
||||
|
||||
},
|
||||
|
|
|
@ -14,15 +14,15 @@
|
|||
<td>{{user.username}}</td>
|
||||
<td class="text-right">
|
||||
<div class="btn-group">
|
||||
<a @click="editUser(user)" href="#" class="btn btn-outline-secondary"><font-awesome-icon icon="user" /> Edit</a>
|
||||
<a @click="deleteUser(user)" href="#" class="btn btn-danger"><font-awesome-icon icon="times" /></a>
|
||||
<a @click.prevent="editUser(user, edit)" href="" class="btn btn-outline-secondary"><font-awesome-icon icon="user" /> Edit</a>
|
||||
<a v-if="index !== 0" @click.prevent="deleteUser(user)" href="" class="btn btn-danger"><font-awesome-icon icon="times" /></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<FormUser :in_user="user"/>
|
||||
<FormUser :edit="editChange" :in_user="user"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -36,13 +36,17 @@
|
|||
data () {
|
||||
return {
|
||||
edit: false,
|
||||
user: null
|
||||
user: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
editUser(u) {
|
||||
this.edit = true
|
||||
editChange(v) {
|
||||
this.user = {}
|
||||
this.edit = v
|
||||
},
|
||||
editUser(u, mode) {
|
||||
this.user = u
|
||||
this.edit = !mode
|
||||
},
|
||||
async deleteUser(u) {
|
||||
let c = confirm(`Are you sure you want to delete user '${u.username}'?`)
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<template>
|
||||
<div>
|
||||
<FormService v-if="ready" :in_service="service"/>
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<FormService :in_service="service"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -25,15 +29,16 @@
|
|||
data () {
|
||||
return {
|
||||
ready: false,
|
||||
service: null
|
||||
service: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
async beforeCreate() {
|
||||
if (this.$route.params.id) {
|
||||
this.service = await Api.service(this.$route.params.id)
|
||||
const id = this.$route.params.id
|
||||
if (id) {
|
||||
this.service = await Api.service(id)
|
||||
}
|
||||
this.ready = true
|
||||
},
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<template v-if="service">
|
||||
<div class="col-12 card mb-3" style="min-height: 260px">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><a href="service/7">{{service.name}}</a>
|
||||
<span class="badge float-right badge-success">{{service.online ? "ONLINE" : "OFFLINE"}}</span>
|
||||
<h5 class="card-title"><router-link :to="serviceLink(service)">{{service.name}}</router-link>
|
||||
<span class="badge float-right" :class="{'badge-success': service.online, 'badge-danger': !service.online}">
|
||||
{{service.online ? "ONLINE" : "OFFLINE"}}
|
||||
</span>
|
||||
</h5>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-sm-6">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<footer>
|
||||
<div class="footer text-center mb-4 p-2">
|
||||
<a href="https://github.com/hunterlong/statping" target="_blank">Statping {{version}} made with <i class="text-danger fas fa-heart"></i></a> |
|
||||
<router-link to="/dashboard">Dashboard</router-link>
|
||||
<a href="/dashboard">Dashboard</a>
|
||||
</div>
|
||||
</footer>
|
||||
</template>
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<span class="d-none d-md-inline">Online, last Failure was Wednesday 1:16:49PM, Dec 18 2019</span>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-2">
|
||||
<router-link :to="`/service/${service.id}`" class="btn btn-success btn-sm float-right dyn-dark btn-block">View Service</router-link>
|
||||
<router-link :to="serviceLink(service)" class="btn btn-success btn-sm float-right dyn-dark btn-block">View Service</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
<div class="form-group row mt-3">
|
||||
<label class="col-sm-3 col-form-label">API Key</label>
|
||||
<div class="col-sm-9">
|
||||
<input v-model="core.api_key" type="text" class="form-control select-input" readonly>
|
||||
<input v-model="core.api_key" @focus="$event.target.select()" type="text" class="form-control select-input" readonly>
|
||||
<small class="form-text text-muted">API Key can be used for read only routes</small>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -92,7 +92,7 @@
|
|||
<div class="form-group row">
|
||||
<label class="col-sm-3 col-form-label">API Secret</label>
|
||||
<div class="col-sm-9">
|
||||
<input v-model="core.api_secret" type="text" class="form-control select-input" readonly>
|
||||
<input v-model="core.api_secret" @focus="$event.target.select()" type="text" class="form-control select-input" readonly>
|
||||
<small class="form-text text-muted">API Secret is used for read, create, update and delete routes</small>
|
||||
<small class="form-text text-muted">You can <a href="#" @click="renewApiKeys">Regenerate API Keys</a> if you need to.</small>
|
||||
</div>
|
||||
|
@ -102,21 +102,15 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import time from '../components/Time'
|
||||
import Api from '../components/API'
|
||||
import Api from '../components/API'
|
||||
|
||||
export default {
|
||||
export default {
|
||||
name: 'CoreSettings',
|
||||
data () {
|
||||
return {
|
||||
core: null,
|
||||
core: this.$store.getters.core,
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
const core = await Api.core()
|
||||
this.core = core
|
||||
this.$store.commit('setCore', core)
|
||||
},
|
||||
async mounted () {
|
||||
|
||||
},
|
||||
|
@ -126,7 +120,6 @@ export default {
|
|||
const c = this.core
|
||||
const coreForm = {name: c.name, description: c.description, domain: c.domain,
|
||||
timezone: c.timezone, using_cdn: c.using_cdn, footer: c.footer, update_notify: c.update_notify}
|
||||
alert(JSON.stringify(coreForm))
|
||||
await Api.core_save(coreForm)
|
||||
const core = await Api.core()
|
||||
this.$store.commit('setCore', core)
|
||||
|
@ -140,7 +133,10 @@ export default {
|
|||
this.$store.commit('setCore', core)
|
||||
this.core = core
|
||||
}
|
||||
}
|
||||
},
|
||||
selectAll() {
|
||||
this.$refs.input.select();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
<template>
|
||||
<div>
|
||||
<h1 class="text-muted mt-5">
|
||||
{{group.id ? `Update ${group.name}` : "Create Group"}}
|
||||
<button @click="removeEdit" v-if="group.id" class="mt-3 btn float-right btn-danger btn-sm">Close</button>
|
||||
</h1>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form @submit="saveGroup">
|
||||
<div class="form-group row">
|
||||
<label for="title" class="col-sm-4 col-form-label">Group Name</label>
|
||||
<div class="col-sm-8">
|
||||
<input v-model="group.name" type="text" name="name" class="form-control" value="" 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 class="form-group row">
|
||||
|
@ -17,21 +25,29 @@
|
|||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-12">
|
||||
<button @click="saveGroup" type="submit" class="btn btn-primary btn-block">Create Group</button>
|
||||
<button @click="saveGroup" type="submit" class="btn btn-block" :class="{'btn-primary': !group.name, 'btn-secondary': group.name}">
|
||||
{{group.id ? "Update Group" : "Create Group"}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-danger d-none" id="alerter" role="alert"></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Api from "../components/API";
|
||||
import Api from "../components/API";
|
||||
|
||||
export default {
|
||||
export default {
|
||||
name: 'FormGroup',
|
||||
props: {
|
||||
in_group: {
|
||||
type: Object
|
||||
},
|
||||
edit: {
|
||||
type: Function
|
||||
}
|
||||
},
|
||||
data () {
|
||||
|
@ -42,20 +58,41 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.props.in_group) {
|
||||
this.group = this.props.in_group
|
||||
watch: {
|
||||
in_group() {
|
||||
this.group = this.in_group
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeEdit() {
|
||||
this.group = {}
|
||||
this.edit(false)
|
||||
},
|
||||
async saveGroup(e) {
|
||||
e.preventDefault();
|
||||
if (this.in_group) {
|
||||
await this.updateGroup()
|
||||
} else {
|
||||
await this.createGroup()
|
||||
}
|
||||
},
|
||||
|
||||
async createGroup() {
|
||||
const g = this.group
|
||||
const data = {name: g.name, public: g.public}
|
||||
await Api.group_create(data)
|
||||
const groups = await Api.groups()
|
||||
this.$store.commit('setGroups', groups)
|
||||
this.group = {}
|
||||
},
|
||||
async updateGroup() {
|
||||
const g = this.group
|
||||
const data = {id: g.id, name: g.name, public: g.public}
|
||||
await Api.group_update(data)
|
||||
const groups = await Api.groups()
|
||||
this.$store.commit('setGroups', groups)
|
||||
this.edit(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,56 +1,42 @@
|
|||
<template>
|
||||
<form class="ajax_form" action="api/messages" data-redirect="messages" method="POST">
|
||||
<div class="col-12">
|
||||
<h1 class="text-black-50 mt-5">
|
||||
{{message.id ? `Update ${message.title}` : "Create Message"}}
|
||||
<button @click="removeEdit" v-if="message.id" class="mt-3 btn float-right btn-danger btn-sm">Close</button>
|
||||
</h1>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form @submit="saveMessage">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">Title</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" name="title" class="form-control" value="" id="title" placeholder="Message Title" required>
|
||||
<input v-model="message.title" type="text" name="title" class="form-control" id="title" placeholder="Message Title" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">Description</label>
|
||||
<div class="col-sm-8">
|
||||
<textarea rows="5" name="description" class="form-control" id="description" required></textarea>
|
||||
<textarea v-model="message.description" rows="5" name="description" class="form-control" id="description" required></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">Message Date Range</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" name="start_on" class="form-control form-control-plaintext" id="start_on" value="0001-01-01T00:00:00Z" required>
|
||||
<flatPickr v-model="message.start_on" :config="config" type="text" name="start_on" class="form-control form-control-plaintext" id="start_on" value="0001-01-01T00:00:00Z" required />
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" name="end_on" class="form-control form-control-plaintext" id="end_on" value="0001-01-01T00:00:00Z" required>
|
||||
<flatPickr v-model="message.end_on" :config="config" type="text" name="end_on" class="form-control form-control-plaintext" id="end_on" value="0001-01-01T00:00:00Z" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="service_id" class="col-sm-4 col-form-label">Service</label>
|
||||
<div class="col-sm-8">
|
||||
<select class="form-control" name="service" id="service_id">
|
||||
<option value="0" selected>Global Message</option>
|
||||
|
||||
|
||||
<option value="7" >Statping API</option>
|
||||
|
||||
|
||||
<option value="6" >Push Notification Server</option>
|
||||
|
||||
|
||||
<option value="1" >Google</option>
|
||||
|
||||
|
||||
<option value="2" >Statping Github</option>
|
||||
|
||||
|
||||
<option value="3" >JSON Users Test</option>
|
||||
|
||||
|
||||
<option value="4" >JSON API Tester</option>
|
||||
|
||||
|
||||
<option value="5" >Google DNS</option>
|
||||
|
||||
<select v-model="message.service_id" class="form-control" name="service" id="service_id">
|
||||
<option :value="0">Global Message</option>
|
||||
<option v-for="(service, index) in $store.getters.services" :value="service.id" v-bind:key="index" >{{service.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -58,15 +44,15 @@
|
|||
<div class="form-group row">
|
||||
<label for="notify_method" class="col-sm-4 col-form-label">Notification Method</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" name="notify_method" class="form-control" id="notify_method" value="" placeholder="email">
|
||||
<input v-model="message.notify_method" type="text" name="notify_method" class="form-control" id="notify_method" value="" placeholder="email">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="notify_method" class="col-sm-4 col-form-label">Notify Users</label>
|
||||
<div class="col-sm-8">
|
||||
<span class="switch">
|
||||
<input @click="message.notify = !!message.notify" type="checkbox" class="switch" id="switch-normal">
|
||||
<span @click="message.notify = !!message.notify" class="switch">
|
||||
<input v-model="message.notify" type="checkbox" class="switch" id="switch-normal">
|
||||
<label for="switch-normal">Notify Users Before Scheduled Time</label>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -76,8 +62,8 @@
|
|||
<label for="notify_before" class="col-sm-4 col-form-label">Notify Before</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="form-inline">
|
||||
<input type="number" name="notify_before" class="col-4 form-control" id="notify_before" value="0">
|
||||
<select class="ml-2 col-7 form-control" name="notify_before_scale" id="notify_before_scale">
|
||||
<input v-model="message.notify_before" type="number" name="notify_before" class="col-4 form-control" id="notify_before">
|
||||
<select v-model="message.notify_before_scale" class="ml-2 col-7 form-control" name="notify_before_scale" id="notify_before_scale">
|
||||
<option value="minute">Minutes</option>
|
||||
<option value="hour">Hours</option>
|
||||
<option value="day">Days</option>
|
||||
|
@ -88,42 +74,91 @@
|
|||
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-12">
|
||||
<button type="submit" class="btn btn-primary btn-block">Create Message</button>
|
||||
<button @click="saveMessage" type="submit" class="btn btn-block" :class="{'btn-primary': !message.id, 'btn-secondary': message.id}">
|
||||
{{message.id ? "Edit Message" : "Create Message"}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-danger d-none" id="alerter" role="alert"></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{JSON.stringify(temp)}}
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Api from "../components/API";
|
||||
import Api from "../components/API";
|
||||
import flatPickr from 'vue-flatpickr-component';
|
||||
import 'flatpickr/dist/flatpickr.css';
|
||||
|
||||
export default {
|
||||
export default {
|
||||
name: 'FormMessage',
|
||||
components: {
|
||||
flatPickr
|
||||
},
|
||||
props: {
|
||||
|
||||
in_message: {
|
||||
type: Object
|
||||
},
|
||||
edit: {
|
||||
type: Function
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
group: {
|
||||
name: "",
|
||||
public: true
|
||||
}
|
||||
message: {
|
||||
title: "",
|
||||
description: "",
|
||||
start_on: new Date(),
|
||||
end_on: new Date(),
|
||||
service_id: 0,
|
||||
notify_method: "",
|
||||
notify: false,
|
||||
notify_before: 0,
|
||||
notify_before_scale: "minute",
|
||||
},
|
||||
config: {
|
||||
altFormat: "Y-m-d H:iK",
|
||||
altInput: true,
|
||||
enableTime: true,
|
||||
dateFormat: "Z",
|
||||
},
|
||||
temp: {}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.props.group) {
|
||||
this.group = this.props.group
|
||||
watch: {
|
||||
in_message() {
|
||||
this.message = this.in_message
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async saveGroup(e) {
|
||||
e.preventDefault();
|
||||
const data = {name: this.group.name, public: this.group.public}
|
||||
await Api.group_create(data)
|
||||
const groups = await Api.groups()
|
||||
this.$store.commit('setGroups', groups)
|
||||
removeEdit() {
|
||||
this.message = {}
|
||||
this.edit(false)
|
||||
},
|
||||
async saveMessage(e) {
|
||||
e.preventDefault();
|
||||
if (this.message.id) {
|
||||
await this.updateMessage()
|
||||
} else {
|
||||
await this.createMessage()
|
||||
}
|
||||
},
|
||||
async createMessage() {
|
||||
await Api.message_create(this.message)
|
||||
const messages = await Api.messages()
|
||||
this.$store.commit('setMessages', messages)
|
||||
this.message = {}
|
||||
},
|
||||
async updateMessage() {
|
||||
await Api.message_update(this.message)
|
||||
const messages = await Api.messages()
|
||||
this.$store.commit('setMessages', messages)
|
||||
this.edit(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="mt-5 mb-5 text-muted">Request Details</h4>
|
||||
<h4 v-if="service.type !== 'icmp'" class="mt-5 mb-5 text-muted">Request Details</h4>
|
||||
|
||||
<div v-if="service.type.match(/^(http)$/)" class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">Service Check Type</label>
|
||||
|
@ -82,7 +82,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div v-if="service.type.match(/^(tcp|udp)$/)" class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">TCP Port</label>
|
||||
<label class="col-sm-4 col-form-label">{{service.type.toUpperCase()}} Port</label>
|
||||
<div class="col-sm-8">
|
||||
<input v-model="service.port" type="number" name="port" class="form-control" id="service_port" placeholder="8080">
|
||||
</div>
|
||||
|
@ -146,8 +146,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-12">
|
||||
<button @click="saveService" type="submit" class="btn btn-success btn-block">Create Service</button>
|
||||
<div class="col-6">
|
||||
<button @click.prevent="saveService" type="submit" class="btn btn-success btn-block">Create Service</button>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<button @click.prevent="saveService" class="btn btn-secondary btn-block">Test</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -178,7 +182,7 @@
|
|||
check_interval: 60,
|
||||
timeout: 15,
|
||||
permalink: "",
|
||||
order: 0,
|
||||
order: 1,
|
||||
verify_ssl: true,
|
||||
allow_notifications: true,
|
||||
public: true,
|
||||
|
@ -186,16 +190,17 @@
|
|||
groups: [],
|
||||
}
|
||||
},
|
||||
props: {
|
||||
in_service: {
|
||||
type: Object,
|
||||
required: false,
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
if (this.props.in_service) {
|
||||
this.service = this.props.in_service
|
||||
}
|
||||
props: {
|
||||
in_service: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
in_service() {
|
||||
this.service = this.in_service
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
if (!this.$store.getters.groups) {
|
||||
const groups = await Api.groups()
|
||||
this.$store.commit('setGroups', groups)
|
||||
|
@ -211,7 +216,10 @@
|
|||
delete s.last_success
|
||||
delete s.latency
|
||||
delete s.online_24_hours
|
||||
await Api.service_save()
|
||||
await Api.service_create(s)
|
||||
},
|
||||
async testService(e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<div class="col-12">
|
||||
|
||||
<form @submit="">
|
||||
<form @submit="saveSetup">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
|
@ -147,15 +147,13 @@
|
|||
this.loading = false
|
||||
return
|
||||
}
|
||||
await this.completeAuth()
|
||||
this.loading = false
|
||||
this.$router.push('')
|
||||
},
|
||||
async completeAuth() {
|
||||
const auth = await Api.login(this.setup.username, this.setup.password)
|
||||
this.auth = Api.saveToken(this.setup.username, auth.token)
|
||||
|
||||
const auth = await Api.login(s.username, s.password)
|
||||
this.auth = Api.saveToken(s.username, auth.token)
|
||||
await this.$store.dispatch('loadAdmin')
|
||||
|
||||
this.loading = false
|
||||
this.$router.push('/')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
<template>
|
||||
<div>
|
||||
<h1 class="text-black-50 mt-5">{{in_user === null ? "Create User" : "Edit User"}}</h1>
|
||||
<h1 class="text-black-50 mt-5">
|
||||
{{user.id ? `Update ${user.username}` : "Create User"}}
|
||||
|
||||
<button @click="removeEdit" v-if="user.id" class="mt-3 btn float-right btn-danger btn-sm">Close</button></h1>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
|
@ -20,24 +23,26 @@
|
|||
<div class="form-group row">
|
||||
<label for="email" class="col-sm-4 col-form-label">Email Address</label>
|
||||
<div class="col-sm-8">
|
||||
<input v-model="user.email" type="email" name="email" class="form-control" id="email" value="" placeholder="user@domain.com" required autocapitalize="none" spellcheck="false">
|
||||
<input v-model="user.email" type="email" class="form-control" id="email" placeholder="user@domain.com" required autocapitalize="none" spellcheck="false">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="password" class="col-sm-4 col-form-label">Password</label>
|
||||
<label class="col-sm-4 col-form-label">Password</label>
|
||||
<div class="col-sm-8">
|
||||
<input v-model="user.password" type="password" name="password" class="form-control" id="password" placeholder="Password" required>
|
||||
<input v-model="user.password" type="password" class="form-control" placeholder="Password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="password_confirm" class="col-sm-4 col-form-label">Confirm Password</label>
|
||||
<label class="col-sm-4 col-form-label">Confirm Password</label>
|
||||
<div class="col-sm-8">
|
||||
<input v-model="user.confirm_password" type="password" name="password_confirm" class="form-control" id="password_confirm" placeholder="Confirm Password" required>
|
||||
<input v-model="user.confirm_password" type="password" class="form-control" placeholder="Confirm Password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-12">
|
||||
<button @click="saveUser" class="btn btn-primary btn-block">Create User</button>
|
||||
<button @click="saveUser" class="btn btn-block" :class="{'btn-primary': !user.id, 'btn-secondary': user.id}">
|
||||
{{user.id ? "Update User" : "Create User"}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-danger d-none" id="alerter" role="alert"></div>
|
||||
|
@ -55,6 +60,9 @@
|
|||
props: {
|
||||
in_user: {
|
||||
type: Object
|
||||
},
|
||||
edit: {
|
||||
type: Function
|
||||
}
|
||||
},
|
||||
data () {
|
||||
|
@ -68,23 +76,46 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.in_user) {
|
||||
this.user = this.in_user
|
||||
watch: {
|
||||
in_user() {
|
||||
const u = this.in_user
|
||||
delete u.password
|
||||
delete u.confirm_password
|
||||
this.user = u
|
||||
}
|
||||
},
|
||||
computed() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
removeEdit() {
|
||||
this.user = {}
|
||||
this.edit(false)
|
||||
},
|
||||
async saveUser(e) {
|
||||
e.preventDefault();
|
||||
if (this.user.id) {
|
||||
await this.updateUser()
|
||||
} else {
|
||||
await this.createUser()
|
||||
}
|
||||
},
|
||||
async createUser() {
|
||||
let user = this.user
|
||||
delete user.confirm_password
|
||||
await Api.user_create(user)
|
||||
const users = await Api.users()
|
||||
this.$store.commit('setUsers', users)
|
||||
this.user = {}
|
||||
},
|
||||
async updateUser() {
|
||||
let user = this.user
|
||||
if (!user.password) {
|
||||
delete user.password
|
||||
}
|
||||
delete user.confirm_password
|
||||
await Api.user_update(user)
|
||||
const users = await Api.users()
|
||||
this.$store.commit('setUsers', users)
|
||||
this.edit(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -9,6 +9,19 @@ export default Vue.mixin({
|
|||
return this.now() - seconds
|
||||
},
|
||||
hour(){ return 3600 },
|
||||
day() { return 3600 * 24 }
|
||||
day() { return 3600 * 24 },
|
||||
serviceLink(service) {
|
||||
if (!service) {
|
||||
return ""
|
||||
}
|
||||
if (!service.id) {
|
||||
service = this.$store.getters.serviceById(service)
|
||||
}
|
||||
let link = service.permalink ? service.permalink : service.id
|
||||
return `/service/${link}`
|
||||
},
|
||||
isInt(n) {
|
||||
return n % 1 === 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -49,10 +49,11 @@
|
|||
<nav class="nav nav-pills flex-column flex-sm-row mt-3" id="service_tabs">
|
||||
<a @click="tab='failures'" class="flex-sm-fill text-sm-center nav-link active">Failures</a>
|
||||
<a @click="tab='incidents'" class="flex-sm-fill text-sm-center nav-link">Incidents</a>
|
||||
<a @click="tab='checkins'" v-if="$store.getters.token.token" class="flex-sm-fill text-sm-center nav-link">Checkins</a>
|
||||
<a @click="tab='response'" v-if="$store.getters.token.token" class="flex-sm-fill text-sm-center nav-link">Response</a>
|
||||
<a @click="tab='checkins'" v-if="$store.getters.token" class="flex-sm-fill text-sm-center nav-link">Checkins</a>
|
||||
<a @click="tab='response'" v-if="$store.getters.token" class="flex-sm-fill text-sm-center nav-link">Response</a>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade active show">
|
||||
<div class="list-group mt-3 mb-4">
|
||||
|
@ -138,7 +139,7 @@ export default {
|
|||
return {
|
||||
id: null,
|
||||
tab: "failures",
|
||||
service: null,
|
||||
service: {},
|
||||
authenticated: false,
|
||||
ready: false,
|
||||
data: null,
|
||||
|
@ -219,19 +220,22 @@ export default {
|
|||
}]
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.service = this.$route.params.service
|
||||
async created() {
|
||||
this.id = this.$route.params.id
|
||||
if (!this.service) {
|
||||
this.getService(this.id)
|
||||
let service;
|
||||
if (this.isInt(this.id)) {
|
||||
service = this.$store.getters.serviceById(this.id)
|
||||
} else {
|
||||
service = this.$store.getters.serviceByPermalink(this.id)
|
||||
}
|
||||
await this.getService(service)
|
||||
},
|
||||
mounted() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
async getService(id) {
|
||||
this.service = await Api.service(id)
|
||||
async getService(s) {
|
||||
this.service = await Api.service(s.id)
|
||||
await this.chartHits()
|
||||
await this.serviceFailures()
|
||||
},
|
||||
|
|
|
@ -44,8 +44,8 @@ export default new Vuex.Store({
|
|||
serviceById: (state) => (id) => {
|
||||
return state.services.find(s => s.id === id)
|
||||
},
|
||||
serviceByName: (state) => (name) => {
|
||||
return state.services.find(s => s.name === name)
|
||||
serviceByPermalink: (state) => (permalink) => {
|
||||
return state.services.find(s => s.permalink === permalink)
|
||||
},
|
||||
servicesInGroup: (state) => (id) => {
|
||||
return state.services.filter(s => s.group_id === id)
|
||||
|
@ -57,7 +57,7 @@ export default new Vuex.Store({
|
|||
return state.groups.find(g => g.id === id)
|
||||
},
|
||||
cleanGroups: (state) => () => {
|
||||
return state.groups.filter(g => g.name !== '')
|
||||
return state.groups.filter(g => g.name !== 'Empty Group')
|
||||
},
|
||||
userById: (state) => (id) => {
|
||||
return state.users.find(u => u.id === id)
|
||||
|
|
|
@ -3551,6 +3551,11 @@ flat-cache@^2.0.1:
|
|||
rimraf "2.6.3"
|
||||
write "1.0.3"
|
||||
|
||||
flatpickr@^4.6.1:
|
||||
version "4.6.3"
|
||||
resolved "https://registry.yarnpkg.com/flatpickr/-/flatpickr-4.6.3.tgz#15a8b76b6e34e3a072861250503a5995b9d3bc60"
|
||||
integrity sha512-007VucCkqNOMMb9ggRLNuJowwaJcyOh4sKAFcdGfahfGc7JQbf94zSzjdBq/wVyHWUEs5o3+idhFZ0wbZMRmVQ==
|
||||
|
||||
flatted@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08"
|
||||
|
@ -7940,6 +7945,13 @@ vue-eslint-parser@^4.0.2:
|
|||
esquery "^1.0.1"
|
||||
lodash "^4.17.11"
|
||||
|
||||
vue-flatpickr-component@^8.1.5:
|
||||
version "8.1.5"
|
||||
resolved "https://registry.yarnpkg.com/vue-flatpickr-component/-/vue-flatpickr-component-8.1.5.tgz#a7a7978d0034c8e44cf1527442d100c0655882fb"
|
||||
integrity sha512-whrR+WM7fWyHW+1ZxCx7uVSuOlTeZXEMzhsgcILXGxIzQxr5uX5RlS5amLXdGGSSVf+zukrb6MvYit/uIkhk3Q==
|
||||
dependencies:
|
||||
flatpickr "^4.6.1"
|
||||
|
||||
vue-hot-reload-api@^2.3.0:
|
||||
version "2.3.4"
|
||||
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
|
||||
|
|
|
@ -94,6 +94,7 @@ func Router() *mux.Router {
|
|||
// API SERVICE Routes
|
||||
r.Handle("/api/services", scoped(apiAllServicesHandler)).Methods("GET")
|
||||
r.Handle("/api/services", authenticated(apiCreateServiceHandler, false)).Methods("POST")
|
||||
r.Handle("/api/services_test", authenticated(apiTestServiceHandler, false)).Methods("POST")
|
||||
r.Handle("/api/services/{id}", scoped(apiServiceHandler)).Methods("GET")
|
||||
r.Handle("/api/reorder/services", authenticated(reorderServiceHandler, false)).Methods("POST")
|
||||
r.Handle("/api/services/{id}/running", authenticated(apiServiceRunningHandler, false)).Methods("POST")
|
||||
|
|
|
@ -147,6 +147,24 @@ func apiCreateServiceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
sendJsonAction(newService, "create", w, r)
|
||||
}
|
||||
|
||||
func apiTestServiceHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var service *types.Service
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
err := decoder.Decode(&service)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
newService := core.ReturnService(service)
|
||||
_, err = newService.Create(true)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
sendJsonAction(newService, "create", w, r)
|
||||
}
|
||||
|
||||
func apiServiceUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
service := core.SelectService(utils.ToInt(vars["id"]))
|
||||
|
|
Loading…
Reference in New Issue