mirror of https://github.com/statping/statping
updates
parent
d2331fe14b
commit
b8dbad85fe
|
@ -29,7 +29,6 @@ const webpackConfig = merge(commonConfig, {
|
|||
new FriendlyErrorsPlugin(),
|
||||
new HtmlPlugin({
|
||||
template: 'public/index.html',
|
||||
chunksSortMode: 'dependency'
|
||||
})
|
||||
],
|
||||
devServer: {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free-solid": "^5.1.0-3",
|
||||
"@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/vue-fontawesome": "^0.1.9",
|
||||
"apexcharts": "^3.15.0",
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{{Name}}</title>
|
||||
<title>{{CoreApp.Name}}</title>
|
||||
<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="description" content="{{Description}}">
|
||||
<meta name="description" content="{{CoreApp.Description}}">
|
||||
<base href="{{BasePath}}">
|
||||
{{if USE_CDN}}
|
||||
<link rel="shortcut icon" type="image/x-icon" href="https://assets.statping.com/favicon.ico">
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Api from './components/API';
|
||||
import Footer from "./components/Footer";
|
||||
import Footer from "./components/Index/Footer";
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
|
@ -22,7 +22,11 @@
|
|||
}
|
||||
},
|
||||
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
|
||||
if (!this.$store.getters.core.setup) {
|
||||
this.$router.push('/setup')
|
||||
|
@ -32,8 +36,9 @@
|
|||
async mounted() {
|
||||
if (this.$route.path !== '/setup') {
|
||||
const tk = localStorage.getItem("statping_user")
|
||||
if (tk) {
|
||||
// await this.$store.dispatch('loadAdmin')
|
||||
if (this.$store.getters.core.logged_in) {
|
||||
this.logged_in = true
|
||||
await this.$store.dispatch('loadAdmin')
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -147,9 +147,14 @@ HTML,BODY {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
.card-title A {
|
||||
color: $service-title;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
position: relative;
|
||||
height: 200px;
|
||||
height: 24.1vh;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
@ -284,6 +289,33 @@ input.inputTags-field:focus {
|
|||
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 {
|
||||
/* Bootstrap Settings */
|
||||
box-sizing: border-box;
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
}
|
||||
|
||||
.lg_number {
|
||||
font-size: 7.8vw;
|
||||
font-size: 7vw;
|
||||
}
|
||||
|
||||
.stats_area {
|
||||
|
@ -66,6 +66,10 @@
|
|||
font-size: 0.6rem;
|
||||
}
|
||||
|
||||
.navbar-item {
|
||||
border-bottom: 1px solid #eaeaea;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
border-top: 1px solid #e4e4e4;
|
||||
border: 0px;
|
||||
|
|
|
@ -25,8 +25,10 @@
|
|||
</span> {{service.name}}
|
||||
</td>
|
||||
<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>
|
||||
<ToggleSwitch :service="service"/>
|
||||
<span class="badge" :class="{'animate-fader': !service.online, 'badge-success': service.online, 'badge-danger': !service.online}">
|
||||
{{service.online ? "ONLINE" : "OFFLINE"}}
|
||||
</span>
|
||||
<ToggleSwitch v-if="service.online" :service="service"/>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<span class="badge" :class="{'badge-primary': service.public, 'badge-secondary': !service.public}">
|
||||
|
@ -117,7 +119,7 @@
|
|||
computed: {
|
||||
servicesList: {
|
||||
get() {
|
||||
return this.$store.getters.servicesInOrder
|
||||
return this.$store.state.servicesInOrder
|
||||
},
|
||||
async set(value) {
|
||||
let data = [];
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
</span>
|
||||
</h5>
|
||||
<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"/>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="col-md-6 col-sm-12">
|
||||
<ServiceSparkLine :title="set2_name" subtitle="Last 7 Days Latency" :series="set2"/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,33 +1,34 @@
|
|||
<template>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<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">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
<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">
|
||||
<font-awesome-icon v-if="!navopen" icon="bars"/>
|
||||
<font-awesome-icon v-if="navopen" icon="times"/>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarText">
|
||||
<div class="navbar-collapse" :class="{collapse: !navopen}" id="navbarText">
|
||||
<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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -44,9 +45,11 @@
|
|||
|
||||
export default {
|
||||
name: 'TopNav',
|
||||
props: {
|
||||
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
navopen: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async logout () {
|
||||
await Api.logout()
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
<template>
|
||||
<footer>
|
||||
<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="/dashboard">Dashboard</a>
|
||||
</div>
|
||||
<div v-else class="footer text-center mb-4 p-2" v-html="$store.getters.core.footer">
|
||||
<a href="https://github.com/hunterlong/statping" target="_blank">
|
||||
Statping {{$store.getters.core.version}} made with <font-awesome-icon style="color: #d40d0d" icon="heart"/>
|
||||
</a> |
|
||||
<router-link :to="$store.getters.core.logged_in ? '/dashboard' : '/login'">Dashboard</router-link>
|
||||
</div>
|
||||
<div v-else class="footer text-center mb-4 p-2" v-html="$store.getters.core.footer"></div>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Dashboard from "../pages/Dashboard";
|
||||
import Dashboard from "../../pages/Dashboard";
|
||||
|
||||
export default {
|
||||
name: 'Footer',
|
||||
|
@ -18,8 +19,14 @@
|
|||
Dashboard
|
||||
},
|
||||
props: {
|
||||
version: String
|
||||
}
|
||||
version: String,
|
||||
logged_in: Boolean
|
||||
},
|
||||
watch: {
|
||||
logged_in() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<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>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<small class="form-text text-muted" v-html="form.small_text"></small>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="row mt-4">
|
||||
<div class="col-9 col-sm-6">
|
||||
<div class="input-group mb-2">
|
||||
<div class="input-group-prepend">
|
||||
|
@ -43,14 +43,14 @@
|
|||
</button>
|
||||
</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>
|
||||
{{loading ? "Loading..." : "Test Notifier"}}</button>
|
||||
</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>
|
||||
</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 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 "./mixin"
|
||||
|
||||
library.add(fas)
|
||||
import "./icons"
|
||||
|
||||
Vue.component('apexchart', VueApexCharts)
|
||||
Vue.component('font-awesome-icon', FontAwesomeIcon)
|
||||
|
||||
Vue.use(VueRouter);
|
||||
Vue.use(require('vue-moment'));
|
||||
|
|
|
@ -56,6 +56,36 @@ export default Vue.mixin({
|
|||
loggedIn() {
|
||||
const core = this.$store.getters.core
|
||||
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: {
|
||||
TopNav,
|
||||
},
|
||||
async mounted() {
|
||||
if (this.$route.path !== "/login") {
|
||||
try {
|
||||
const u = await Api.users()
|
||||
} catch (e) {
|
||||
this.$router.push('/logout')
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
authenticated: false
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<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-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>
|
||||
|
||||
<FormLogin/>
|
||||
|
|
|
@ -5,20 +5,26 @@
|
|||
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
|
||||
<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-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>
|
||||
<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 @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
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
<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">
|
||||
<i class="fas fa-file-csv"></i> {{integration.full_name}}
|
||||
<font-awesome-icon :icon="iconName(integration.name)" class="mr-2"/> {{integration.full_name}}
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -126,7 +126,15 @@ export default new Vuex.Store({
|
|||
window.console.log('finished loading required data')
|
||||
},
|
||||
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()
|
||||
context.commit("setNotifiers", notifiers);
|
||||
const users = await Api.users()
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,15 +1,9 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/core"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -18,137 +12,19 @@ var (
|
|||
|
||||
var handlerFuncs = func(w http.ResponseWriter, r *http.Request) 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 {
|
||||
return core.VERSION
|
||||
},
|
||||
"CoreApp": func() *core.Core {
|
||||
return core.CoreApp
|
||||
},
|
||||
"Services": func() []types.ServiceInterface {
|
||||
return core.CoreApp.Services
|
||||
},
|
||||
"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
|
||||
"CoreApp": func() core.Core {
|
||||
c := *core.CoreApp
|
||||
if c.Name == "" {
|
||||
c.Name = "Statping"
|
||||
}
|
||||
return c
|
||||
},
|
||||
"USE_CDN": func() 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 {
|
||||
return basePath
|
||||
},
|
||||
|
|
|
@ -44,7 +44,7 @@ var (
|
|||
httpServer *http.Server
|
||||
usingSSL bool
|
||||
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
|
||||
|
|
|
@ -25,7 +25,7 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.Redirect(w, r, "/setup", http.StatusSeeOther)
|
||||
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) {
|
||||
|
|
|
@ -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