mirror of https://github.com/statping/statping
updates
parent
d2331fe14b
commit
b8dbad85fe
|
@ -29,7 +29,6 @@ const webpackConfig = merge(commonConfig, {
|
||||||
new FriendlyErrorsPlugin(),
|
new FriendlyErrorsPlugin(),
|
||||||
new HtmlPlugin({
|
new HtmlPlugin({
|
||||||
template: 'public/index.html',
|
template: 'public/index.html',
|
||||||
chunksSortMode: 'dependency'
|
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
devServer: {
|
devServer: {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free-solid": "^5.1.0-3",
|
"@fortawesome/fontawesome-free-solid": "^5.1.0-3",
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.26",
|
"@fortawesome/fontawesome-svg-core": "^1.2.26",
|
||||||
"@fortawesome/free-brands-svg-icons": "^5.12.0",
|
"@fortawesome/free-brands-svg-icons": "^5.12.1",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.12.0",
|
"@fortawesome/free-solid-svg-icons": "^5.12.0",
|
||||||
"@fortawesome/vue-fontawesome": "^0.1.9",
|
"@fortawesome/vue-fontawesome": "^0.1.9",
|
||||||
"apexcharts": "^3.15.0",
|
"apexcharts": "^3.15.0",
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>{{Name}}</title>
|
<title>{{CoreApp.Name}}</title>
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, maximum-scale=1.0, user-scalable=0">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, maximum-scale=1.0, user-scalable=0">
|
||||||
<meta name="description" content="{{Description}}">
|
<meta name="description" content="{{CoreApp.Description}}">
|
||||||
<base href="{{BasePath}}">
|
<base href="{{BasePath}}">
|
||||||
{{if USE_CDN}}
|
{{if USE_CDN}}
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="https://assets.statping.com/favicon.ico">
|
<link rel="shortcut icon" type="image/x-icon" href="https://assets.statping.com/favicon.ico">
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<router-view :loaded="loaded"/>
|
<router-view :loaded="loaded"/>
|
||||||
<Footer :version="version" v-if="$route.path !== '/setup'"/>
|
<Footer :logged_in="logged_in" :version="version" v-if="$route.path !== '/setup'"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Api from './components/API';
|
import Api from './components/API';
|
||||||
import Footer from "./components/Footer";
|
import Footer from "./components/Index/Footer";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'app',
|
name: 'app',
|
||||||
|
@ -23,6 +23,10 @@
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
await this.$store.dispatch('loadRequired')
|
await this.$store.dispatch('loadRequired')
|
||||||
|
|
||||||
|
if (this.$store.getters.core.logged_in) {
|
||||||
|
await this.$store.dispatch('loadAdmin')
|
||||||
|
}
|
||||||
this.loaded = true
|
this.loaded = true
|
||||||
if (!this.$store.getters.core.setup) {
|
if (!this.$store.getters.core.setup) {
|
||||||
this.$router.push('/setup')
|
this.$router.push('/setup')
|
||||||
|
@ -32,8 +36,9 @@
|
||||||
async mounted() {
|
async mounted() {
|
||||||
if (this.$route.path !== '/setup') {
|
if (this.$route.path !== '/setup') {
|
||||||
const tk = localStorage.getItem("statping_user")
|
const tk = localStorage.getItem("statping_user")
|
||||||
if (tk) {
|
if (this.$store.getters.core.logged_in) {
|
||||||
// await this.$store.dispatch('loadAdmin')
|
this.logged_in = true
|
||||||
|
await this.$store.dispatch('loadAdmin')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -147,9 +147,14 @@ HTML,BODY {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-title A {
|
||||||
|
color: $service-title;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
.chart-container {
|
.chart-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 200px;
|
height: 24.1vh;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
@ -284,6 +289,33 @@ input.inputTags-field:focus {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInOut {
|
||||||
|
0% { opacity:1; }
|
||||||
|
50% { opacity:0.3; }
|
||||||
|
100% { opacity:1; }
|
||||||
|
}
|
||||||
|
@-o-keyframes fadeInOut {
|
||||||
|
0% { opacity:1; }
|
||||||
|
50% { opacity:0.3; }
|
||||||
|
100% { opacity:1; }
|
||||||
|
}
|
||||||
|
@-moz-keyframes fadeInOut {
|
||||||
|
0% { opacity:1; }
|
||||||
|
50% { opacity:0.3; }
|
||||||
|
100% { opacity:1; }
|
||||||
|
}
|
||||||
|
@-webkit-keyframes fadeInOut {
|
||||||
|
0% { opacity:1; }
|
||||||
|
50% { opacity:0.3; }
|
||||||
|
100% { opacity:1; }
|
||||||
|
}
|
||||||
|
.animate-fader {
|
||||||
|
-webkit-animation: fadeInOut 1s infinite;
|
||||||
|
-moz-animation: fadeInOut 1s infinite;
|
||||||
|
-o-animation: fadeInOut 1s infinite;
|
||||||
|
animation: fadeInOut 21 infinite;
|
||||||
|
}
|
||||||
|
|
||||||
.CodeMirror {
|
.CodeMirror {
|
||||||
/* Bootstrap Settings */
|
/* Bootstrap Settings */
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.lg_number {
|
.lg_number {
|
||||||
font-size: 7.8vw;
|
font-size: 7vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats_area {
|
.stats_area {
|
||||||
|
@ -66,6 +66,10 @@
|
||||||
font-size: 0.6rem;
|
font-size: 0.6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navbar-item {
|
||||||
|
border-bottom: 1px solid #eaeaea;
|
||||||
|
}
|
||||||
|
|
||||||
.list-group-item {
|
.list-group-item {
|
||||||
border-top: 1px solid #e4e4e4;
|
border-top: 1px solid #e4e4e4;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
|
|
|
@ -25,8 +25,10 @@
|
||||||
</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-success': service.online, 'badge-danger': !service.online}">{{service.online ? "ONLINE" : "OFFLINE"}}</span>
|
<span class="badge" :class="{'animate-fader': !service.online, 'badge-success': service.online, 'badge-danger': !service.online}">
|
||||||
<ToggleSwitch :service="service"/>
|
{{service.online ? "ONLINE" : "OFFLINE"}}
|
||||||
|
</span>
|
||||||
|
<ToggleSwitch v-if="service.online" :service="service"/>
|
||||||
</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" :class="{'badge-primary': service.public, 'badge-secondary': !service.public}">
|
||||||
|
@ -117,7 +119,7 @@
|
||||||
computed: {
|
computed: {
|
||||||
servicesList: {
|
servicesList: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.getters.servicesInOrder
|
return this.$store.state.servicesInOrder
|
||||||
},
|
},
|
||||||
async set(value) {
|
async set(value) {
|
||||||
let data = [];
|
let data = [];
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
</span>
|
</span>
|
||||||
</h5>
|
</h5>
|
||||||
<div v-if="loaded && service.online" class="row">
|
<div v-if="loaded && service.online" class="row">
|
||||||
<div class="col-6">
|
<div class="col-md-6 col-sm-12">
|
||||||
<ServiceSparkLine :title="set1_name" subtitle="Last Day Latency" :series="set1"/>
|
<ServiceSparkLine :title="set1_name" subtitle="Last Day Latency" :series="set1"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="col-md-6 col-sm-12">
|
||||||
<ServiceSparkLine :title="set2_name" subtitle="Last 7 Days Latency" :series="set2"/>
|
<ServiceSparkLine :title="set2_name" subtitle="Last 7 Days Latency" :series="set2"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,33 +1,34 @@
|
||||||
<template>
|
<template>
|
||||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
<router-link to="/" class="navbar-brand">Statping</router-link>
|
<router-link to="/" class="navbar-brand">Statping</router-link>
|
||||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
|
<button @click="navopen = !navopen" class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<font-awesome-icon v-if="!navopen" icon="bars"/>
|
||||||
|
<font-awesome-icon v-if="navopen" icon="times"/>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="collapse navbar-collapse" id="navbarText">
|
<div class="navbar-collapse" :class="{collapse: !navopen}" id="navbarText">
|
||||||
<ul class="navbar-nav mr-auto">
|
<ul class="navbar-nav mr-auto">
|
||||||
<li class="nav-item">
|
<li @click="navopen = !navopen" class="nav-item navbar-item">
|
||||||
<router-link to="/dashboard" class="nav-link">Dashboard</router-link>
|
<router-link to="/dashboard" class="nav-link">Dashboard</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li @click="navopen = !navopen" class="nav-item navbar-item">
|
||||||
<router-link to="/dashboard/services" class="nav-link">Services</router-link>
|
<router-link to="/dashboard/services" class="nav-link">Services</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li @click="navopen = !navopen" class="nav-item navbar-item">
|
||||||
<router-link to="/dashboard/users" class="nav-link">Users</router-link>
|
<router-link to="/dashboard/users" class="nav-link">Users</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li @click="navopen = !navopen" class="nav-item navbar-item">
|
||||||
<router-link to="/dashboard/messages" class="nav-link">Messages</router-link>
|
<router-link to="/dashboard/messages" class="nav-link">Messages</router-link>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li @click="navopen = !navopen" class="nav-item navbar-item">
|
||||||
<router-link to="/dashboard/settings" class="nav-link">Settings</router-link>
|
<router-link to="/dashboard/settings" class="nav-link">Settings</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li @click="navopen = !navopen" class="nav-item navbar-item">
|
||||||
<router-link to="/dashboard/logs" class="nav-link">Logs</router-link>
|
<router-link to="/dashboard/logs" class="nav-link">Logs</router-link>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li @click="navopen = !navopen" class="nav-item navbar-item">
|
||||||
<router-link to="/dashboard/help" class="nav-link">Help</router-link>
|
<router-link to="/dashboard/help" class="nav-link">Help</router-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -44,8 +45,10 @@
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TopNav',
|
name: 'TopNav',
|
||||||
props: {
|
data () {
|
||||||
|
return {
|
||||||
|
navopen: false,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async logout () {
|
async logout () {
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<footer>
|
<footer>
|
||||||
<div v-if="!$store.getters.core.footer" class="footer text-center mb-4 p-2">
|
<div v-if="!$store.getters.core.footer" 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> |
|
<a href="https://github.com/hunterlong/statping" target="_blank">
|
||||||
<a href="/dashboard">Dashboard</a>
|
Statping {{$store.getters.core.version}} made with <font-awesome-icon style="color: #d40d0d" icon="heart"/>
|
||||||
</div>
|
</a> |
|
||||||
<div v-else class="footer text-center mb-4 p-2" v-html="$store.getters.core.footer">
|
<router-link :to="$store.getters.core.logged_in ? '/dashboard' : '/login'">Dashboard</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else class="footer text-center mb-4 p-2" v-html="$store.getters.core.footer"></div>
|
||||||
</footer>
|
</footer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Dashboard from "../pages/Dashboard";
|
import Dashboard from "../../pages/Dashboard";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Footer',
|
name: 'Footer',
|
||||||
|
@ -18,7 +19,13 @@
|
||||||
Dashboard
|
Dashboard
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
version: String
|
version: String,
|
||||||
|
logged_in: Boolean
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
logged_in() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<apexchart v-if="ready" width="100%" height="215" type="area" :options="chartOptions" :series="series"></apexchart>
|
<apexchart v-if="ready" width="100%" height="225" type="area" :options="chartOptions" :series="series"></apexchart>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<small class="form-text text-muted" v-html="form.small_text"></small>
|
<small class="form-text text-muted" v-html="form.small_text"></small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row mt-4">
|
||||||
<div class="col-9 col-sm-6">
|
<div class="col-9 col-sm-6">
|
||||||
<div class="input-group mb-2">
|
<div class="input-group mb-2">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
|
@ -43,14 +43,14 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12 col-sm-12">
|
<div class="col-12 col-sm-12 mt-3">
|
||||||
<button @click="testNotifier" class="btn btn-secondary btn-block text-capitalize col-12 float-right"><i class="fa fa-vial"></i>
|
<button @click="testNotifier" class="btn btn-secondary btn-block text-capitalize col-12 float-right"><i class="fa fa-vial"></i>
|
||||||
{{loading ? "Loading..." : "Test Notifier"}}</button>
|
{{loading ? "Loading..." : "Test Notifier"}}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="d-block small text-center mt-3 mb-5">
|
<span class="d-block small text-center mt-5 mb-5">
|
||||||
<span class="text-capitalize">{{notifier.title}}</span> Notifier created by <a :href="notifier.author_url" target="_blank">{{notifier.author}}</a>
|
<span class="text-capitalize">{{notifier.title}}</span> Notifier created by <a :href="notifier.author_url" target="_blank">{{notifier.author}}</a>
|
||||||
</span>
|
</span>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import {library} from '@fortawesome/fontawesome-svg-core'
|
||||||
|
import {fas} from '@fortawesome/fontawesome-free-solid';
|
||||||
|
import {fab} from '@fortawesome/free-brands-svg-icons';
|
||||||
|
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome'
|
||||||
|
import Vue from "vue";
|
||||||
|
|
||||||
|
library.add(fas, fab)
|
||||||
|
|
||||||
|
Vue.component('font-awesome-icon', FontAwesomeIcon)
|
|
@ -5,16 +5,11 @@ import VueApexCharts from 'vue-apexcharts'
|
||||||
import App from '@/App.vue'
|
import App from '@/App.vue'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
|
|
||||||
import {library} from '@fortawesome/fontawesome-svg-core'
|
|
||||||
import {fas} from '@fortawesome/fontawesome-free-solid';
|
|
||||||
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome'
|
|
||||||
import router from './routes'
|
import router from './routes'
|
||||||
import "./mixin"
|
import "./mixin"
|
||||||
|
import "./icons"
|
||||||
library.add(fas)
|
|
||||||
|
|
||||||
Vue.component('apexchart', VueApexCharts)
|
Vue.component('apexchart', VueApexCharts)
|
||||||
Vue.component('font-awesome-icon', FontAwesomeIcon)
|
|
||||||
|
|
||||||
Vue.use(VueRouter);
|
Vue.use(VueRouter);
|
||||||
Vue.use(require('vue-moment'));
|
Vue.use(require('vue-moment'));
|
||||||
|
|
|
@ -56,6 +56,36 @@ export default Vue.mixin({
|
||||||
loggedIn() {
|
loggedIn() {
|
||||||
const core = this.$store.getters.core
|
const core = this.$store.getters.core
|
||||||
return core.logged_in === true
|
return core.logged_in === true
|
||||||
|
},
|
||||||
|
iconName(name) {
|
||||||
|
switch (name) {
|
||||||
|
case "fas fa-terminal":
|
||||||
|
return "terminal"
|
||||||
|
case "fab fa-discord":
|
||||||
|
return ["fab", "discord"]
|
||||||
|
case "far fa-envelope":
|
||||||
|
return "envelope"
|
||||||
|
case "far fa-bell":
|
||||||
|
return "bell"
|
||||||
|
case "fas fa-mobile-alt":
|
||||||
|
return "mobile"
|
||||||
|
case "fab fa-slack":
|
||||||
|
return ["fab", "slack-hash"]
|
||||||
|
case "fab fa-telegram-plane":
|
||||||
|
return ["fab", "telegram-plane"]
|
||||||
|
case "far fa-comment-alt":
|
||||||
|
return "comment"
|
||||||
|
case "fas fa-code-branch":
|
||||||
|
return "code-branch"
|
||||||
|
case "csv":
|
||||||
|
return "file"
|
||||||
|
case "docker":
|
||||||
|
return ["fab", "docker"]
|
||||||
|
case "traefik":
|
||||||
|
return "server"
|
||||||
|
default:
|
||||||
|
return "bars"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,6 +14,15 @@
|
||||||
components: {
|
components: {
|
||||||
TopNav,
|
TopNav,
|
||||||
},
|
},
|
||||||
|
async mounted() {
|
||||||
|
if (this.$route.path !== "/login") {
|
||||||
|
try {
|
||||||
|
const u = await Api.users()
|
||||||
|
} catch (e) {
|
||||||
|
this.$router.push('/logout')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
authenticated: false
|
authenticated: false
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="container col-md-7 col-sm-12 mt-md-5 bg-light">
|
<div class="container col-md-7 col-sm-12 mt-md-5 bg-light">
|
||||||
<div class="col-10 offset-1 col-md-8 offset-md-2 mt-md-2">
|
<div class="col-10 offset-1 col-md-8 offset-md-2 mt-md-2">
|
||||||
<div class="col-12 col-md-8 offset-md-2 mb-4">
|
<div class="col-12 col-md-8 offset-md-2 mb-4">
|
||||||
<img class="col-12 mt-5 mt-md-0" src="/public/banner.png">
|
<img class="col-12 mt-5 mt-md-0" src="/banner.png">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FormLogin/>
|
<FormLogin/>
|
||||||
|
|
|
@ -5,20 +5,26 @@
|
||||||
<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">Main Settings</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"><i class="fa fa-cogs"></i> Settings</a>
|
<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-style-tab')}" id="v-pills-style-tab" data-toggle="pill" href="#v-pills-style" role="tab" aria-controls="v-pills-style" aria-selected="false"><i class="fa fa-image"></i> Theme Editor</a>
|
<font-awesome-icon icon="cog" class="mr-2"/> Settings
|
||||||
<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"><i class="fa fa-paperclip"></i> Cache</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">
|
||||||
|
<font-awesome-icon icon="image" class="mr-2"/> Theme Editor
|
||||||
|
</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">
|
||||||
|
<font-awesome-icon icon="paperclip" class="mr-2"/> Cache
|
||||||
|
</a>
|
||||||
|
|
||||||
<h6 class="mt-4 text-muted">Notifiers</h6>
|
<h6 class="mt-4 text-muted">Notifiers</h6>
|
||||||
|
|
||||||
<a v-for="(notifier, index) in $store.getters.notifiers" v-bind:key="`${notifier.method}_${index}`" @click.prevent="changeTab" class="nav-link text-capitalize" v-bind:class="{active: liClass(`v-pills-${notifier.method.toLowerCase()}-tab`)}" v-bind:id="`v-pills-${notifier.method.toLowerCase()}-tab`" data-toggle="pill" v-bind:href="`#v-pills-${notifier.method.toLowerCase()}`" role="tab" v-bind:aria-controls="`v-pills-${notifier.method.toLowerCase()}`" aria-selected="false">
|
<a v-for="(notifier, index) in $store.getters.notifiers" v-bind:key="`${notifier.method}_${index}`" @click.prevent="changeTab" class="nav-link text-capitalize" v-bind:class="{active: liClass(`v-pills-${notifier.method.toLowerCase()}-tab`)}" v-bind:id="`v-pills-${notifier.method.toLowerCase()}-tab`" data-toggle="pill" v-bind:href="`#v-pills-${notifier.method.toLowerCase()}`" role="tab" v-bind:aria-controls="`v-pills-${notifier.method.toLowerCase()}`" aria-selected="false">
|
||||||
<i class="fas fa-terminal"></i> {{notifier.method}}
|
<font-awesome-icon :icon="iconName(notifier.icon)" class="mr-2"/> {{notifier.method}}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<h6 class="mt-4 text-muted">Integrations (beta)</h6>
|
<h6 class="mt-4 text-muted">Integrations (beta)</h6>
|
||||||
|
|
||||||
<a v-for="(integration, index) in $store.getters.integrations" v-bind:key="`${integration.name}_${index}`" @click.prevent="changeTab" class="nav-link text-capitalize" v-bind:class="{active: liClass(`v-pills-integration-${integration.name}`)}" v-bind:id="`v-pills-integration-${integration.name}`" data-toggle="pill" v-bind:href="`#v-pills-integration-${integration.name}`" role="tab" :aria-controls="`v-pills-integration-${integration.name}`" aria-selected="false">
|
<a v-for="(integration, index) in $store.getters.integrations" v-bind:key="`${integration.name}_${index}`" @click.prevent="changeTab" class="nav-link text-capitalize" v-bind:class="{active: liClass(`v-pills-integration-${integration.name}`)}" v-bind:id="`v-pills-integration-${integration.name}`" data-toggle="pill" v-bind:href="`#v-pills-integration-${integration.name}`" role="tab" :aria-controls="`v-pills-integration-${integration.name}`" aria-selected="false">
|
||||||
<i class="fas fa-file-csv"></i> {{integration.full_name}}
|
<font-awesome-icon :icon="iconName(integration.name)" class="mr-2"/> {{integration.full_name}}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -126,7 +126,15 @@ export default new Vuex.Store({
|
||||||
window.console.log('finished loading required data')
|
window.console.log('finished loading required data')
|
||||||
},
|
},
|
||||||
async loadAdmin (context) {
|
async loadAdmin (context) {
|
||||||
await context.dispatch('loadRequired')
|
const core = await Api.core()
|
||||||
|
context.commit("setCore", core);
|
||||||
|
const groups = await Api.groups()
|
||||||
|
context.commit("setGroups", groups);
|
||||||
|
const services = await Api.services()
|
||||||
|
context.commit("setServices", services);
|
||||||
|
const messages = await Api.messages()
|
||||||
|
context.commit("setMessages", messages)
|
||||||
|
context.commit("setHasPublicData", true)
|
||||||
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()
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,15 +1,9 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"github.com/hunterlong/statping/core"
|
"github.com/hunterlong/statping/core"
|
||||||
"github.com/hunterlong/statping/types"
|
|
||||||
"github.com/hunterlong/statping/utils"
|
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -18,137 +12,19 @@ var (
|
||||||
|
|
||||||
var handlerFuncs = func(w http.ResponseWriter, r *http.Request) template.FuncMap {
|
var handlerFuncs = func(w http.ResponseWriter, r *http.Request) template.FuncMap {
|
||||||
return template.FuncMap{
|
return template.FuncMap{
|
||||||
"js": func(html interface{}) template.JS {
|
|
||||||
return template.JS(utils.ToString(html))
|
|
||||||
},
|
|
||||||
"safe": func(html string) template.HTML {
|
|
||||||
return template.HTML(html)
|
|
||||||
},
|
|
||||||
"safeURL": func(u string) template.URL {
|
|
||||||
return template.URL(u)
|
|
||||||
},
|
|
||||||
"Auth": func() bool {
|
|
||||||
return IsFullAuthenticated(r)
|
|
||||||
},
|
|
||||||
"IsUser": func() bool {
|
|
||||||
return IsUser(r)
|
|
||||||
},
|
|
||||||
"VERSION": func() string {
|
"VERSION": func() string {
|
||||||
return core.VERSION
|
return core.VERSION
|
||||||
},
|
},
|
||||||
"CoreApp": func() *core.Core {
|
"CoreApp": func() core.Core {
|
||||||
return core.CoreApp
|
c := *core.CoreApp
|
||||||
},
|
if c.Name == "" {
|
||||||
"Services": func() []types.ServiceInterface {
|
c.Name = "Statping"
|
||||||
return core.CoreApp.Services
|
}
|
||||||
},
|
return c
|
||||||
"VisibleServices": func() []*core.Service {
|
|
||||||
auth := IsUser(r)
|
|
||||||
return core.SelectServices(auth)
|
|
||||||
},
|
|
||||||
"VisibleGroupServices": func(group *core.Group) []*core.Service {
|
|
||||||
auth := IsUser(r)
|
|
||||||
return group.VisibleServices(auth)
|
|
||||||
},
|
|
||||||
"Groups": func(includeAll bool) []*core.Group {
|
|
||||||
auth := IsUser(r)
|
|
||||||
return core.SelectGroups(includeAll, auth)
|
|
||||||
},
|
|
||||||
"Group": func(id int) *core.Group {
|
|
||||||
return core.SelectGroup(int64(id))
|
|
||||||
},
|
|
||||||
"len": func(g interface{}) int {
|
|
||||||
val := reflect.ValueOf(g)
|
|
||||||
return val.Len()
|
|
||||||
},
|
|
||||||
"IsNil": func(g interface{}) bool {
|
|
||||||
return g == nil
|
|
||||||
},
|
},
|
||||||
"USE_CDN": func() bool {
|
"USE_CDN": func() bool {
|
||||||
return core.CoreApp.UseCdn.Bool
|
return core.CoreApp.UseCdn.Bool
|
||||||
},
|
},
|
||||||
"UPDATENOTIFY": func() bool {
|
|
||||||
return core.CoreApp.UpdateNotify.Bool
|
|
||||||
},
|
|
||||||
"QrAuth": func() string {
|
|
||||||
return fmt.Sprintf("statping://setup?domain=%v&api=%v", core.CoreApp.Domain, core.CoreApp.ApiSecret)
|
|
||||||
},
|
|
||||||
"Type": func(g interface{}) []string {
|
|
||||||
fooType := reflect.TypeOf(g)
|
|
||||||
var methods []string
|
|
||||||
methods = append(methods, fooType.String())
|
|
||||||
for i := 0; i < fooType.NumMethod(); i++ {
|
|
||||||
method := fooType.Method(i)
|
|
||||||
fmt.Println(method.Name)
|
|
||||||
methods = append(methods, method.Name)
|
|
||||||
}
|
|
||||||
return methods
|
|
||||||
},
|
|
||||||
"ToJSON": func(g interface{}) template.HTML {
|
|
||||||
data, _ := json.Marshal(g)
|
|
||||||
return template.HTML(string(data))
|
|
||||||
},
|
|
||||||
"underscore": func(html string) string {
|
|
||||||
return utils.UnderScoreString(html)
|
|
||||||
},
|
|
||||||
"URL": func() string {
|
|
||||||
return basePath + r.URL.String()
|
|
||||||
},
|
|
||||||
"CHART_DATA": func() string {
|
|
||||||
return ""
|
|
||||||
},
|
|
||||||
"Error": func() string {
|
|
||||||
return ""
|
|
||||||
},
|
|
||||||
"Cache": func() Cacher {
|
|
||||||
return CacheStorage
|
|
||||||
},
|
|
||||||
"ToString": func(v interface{}) string {
|
|
||||||
return utils.ToString(v)
|
|
||||||
},
|
|
||||||
"Ago": func(t time.Time) string {
|
|
||||||
return utils.Timestamp(t).Ago()
|
|
||||||
},
|
|
||||||
"Duration": func(t time.Duration) string {
|
|
||||||
duration, _ := time.ParseDuration(fmt.Sprintf("%vs", t.Seconds()))
|
|
||||||
return utils.FormatDuration(duration)
|
|
||||||
},
|
|
||||||
"ToUnix": func(t time.Time) int64 {
|
|
||||||
return t.UTC().Unix()
|
|
||||||
},
|
|
||||||
"ParseTime": func(t time.Time, format string) string {
|
|
||||||
return t.Format(format)
|
|
||||||
},
|
|
||||||
"FromUnix": func(t int64) string {
|
|
||||||
return utils.Timezoner(time.Unix(t, 0), core.CoreApp.Timezone).Format("Monday, January 02")
|
|
||||||
},
|
|
||||||
"UnixTime": func(t int64, nano bool) string {
|
|
||||||
if nano {
|
|
||||||
t = t / 1e9
|
|
||||||
}
|
|
||||||
return utils.Timezoner(time.Unix(t, 0), core.CoreApp.Timezone).String()
|
|
||||||
},
|
|
||||||
"ServiceLink": func(s *core.Service) string {
|
|
||||||
if s.Permalink.Valid {
|
|
||||||
return s.Permalink.String
|
|
||||||
}
|
|
||||||
return utils.ToString(s.Id)
|
|
||||||
},
|
|
||||||
"NewService": func() *types.Service {
|
|
||||||
return new(types.Service)
|
|
||||||
},
|
|
||||||
"NewUser": func() *types.User {
|
|
||||||
return new(types.User)
|
|
||||||
},
|
|
||||||
"NewCheckin": func() *types.Checkin {
|
|
||||||
return new(types.Checkin)
|
|
||||||
},
|
|
||||||
"NewMessage": func() *types.Message {
|
|
||||||
return new(types.Message)
|
|
||||||
},
|
|
||||||
"NewGroup": func() *types.Group {
|
|
||||||
return new(types.Group)
|
|
||||||
},
|
|
||||||
"BasePath": func() string {
|
"BasePath": func() string {
|
||||||
return basePath
|
return basePath
|
||||||
},
|
},
|
||||||
|
|
|
@ -44,7 +44,7 @@ var (
|
||||||
httpServer *http.Server
|
httpServer *http.Server
|
||||||
usingSSL bool
|
usingSSL bool
|
||||||
mainTmpl = `{{define "main" }} {{ template "base" . }} {{ end }}`
|
mainTmpl = `{{define "main" }} {{ template "base" . }} {{ end }}`
|
||||||
templates = []string{"base.gohtml", "head.gohtml", "nav.gohtml", "footer.gohtml", "scripts.gohtml", "form_service.gohtml", "form_notifier.gohtml", "form_integration.gohtml", "form_group.gohtml", "form_user.gohtml", "form_checkin.gohtml", "form_message.gohtml"}
|
templates = []string{"base.gohtml"}
|
||||||
)
|
)
|
||||||
|
|
||||||
// RunHTTPServer will start a HTTP server on a specific IP and port
|
// RunHTTPServer will start a HTTP server on a specific IP and port
|
||||||
|
|
|
@ -25,7 +25,7 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Redirect(w, r, "/setup", http.StatusSeeOther)
|
http.Redirect(w, r, "/setup", http.StatusSeeOther)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ExecuteResponse(w, r, "index.html", core.CoreApp, nil)
|
ExecuteResponse(w, r, "base.gohtml", core.CoreApp, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
|
func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
{{ define "base" }}
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
{{block "head" .}} {{end}}
|
|
||||||
<body>
|
|
||||||
{{template "content" .}}
|
|
||||||
</body>
|
|
||||||
<footer>{{template "footer" .}}</footer>
|
|
||||||
{{template "scripts" .}}
|
|
||||||
</html>
|
|
||||||
{{end}}
|
|
Loading…
Reference in New Issue