mirror of https://github.com/statping/statping
commit
7437cbc901
|
@ -36,7 +36,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
DbModels = []interface{}{&types.Service{}, &types.User{}, &types.Hit{}, &types.Failure{}, &types.Message{}, &types.Checkin{}, &types.CheckinHit{}, ¬ifier.Notification{}}
|
DbModels = []interface{}{&types.Service{}, &types.User{}, &types.Hit{}, &types.Failure{}, &types.Message{}, &types.Group{}, &types.Checkin{}, &types.CheckinHit{}, ¬ifier.Notification{}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DbConfig stores the config.yml file for the statup configuration
|
// DbConfig stores the config.yml file for the statup configuration
|
||||||
|
@ -82,6 +82,11 @@ func messagesDb() *gorm.DB {
|
||||||
return DbSession.Model(&types.Message{})
|
return DbSession.Model(&types.Message{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// messagesDb returns the Checkin records for a service
|
||||||
|
func groupsDb() *gorm.DB {
|
||||||
|
return DbSession.Model(&types.Group{})
|
||||||
|
}
|
||||||
|
|
||||||
// HitsBetween returns the gorm database query for a collection of service hits between a time range
|
// HitsBetween returns the gorm database query for a collection of service hits between a time range
|
||||||
func (s *Service) HitsBetween(t1, t2 time.Time, group string, column string) *gorm.DB {
|
func (s *Service) HitsBetween(t1, t2 time.Time, group string, column string) *gorm.DB {
|
||||||
selector := Dbtimestamp(group, column)
|
selector := Dbtimestamp(group, column)
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hunterlong/statping/types"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Group struct {
|
||||||
|
*types.Group
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete will remove a group
|
||||||
|
func (g *Group) Delete() error {
|
||||||
|
for _, s := range g.Services() {
|
||||||
|
s.GroupId = 0
|
||||||
|
s.Update(false)
|
||||||
|
}
|
||||||
|
err := messagesDb().Delete(g)
|
||||||
|
if err.Error != nil {
|
||||||
|
return err.Error
|
||||||
|
}
|
||||||
|
return err.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create will create a group and insert it into the database
|
||||||
|
func (g *Group) Create() (int64, error) {
|
||||||
|
g.CreatedAt = time.Now()
|
||||||
|
db := groupsDb().Create(g)
|
||||||
|
return g.Id, db.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Services returns all services belonging to a group
|
||||||
|
func (g *Group) Services() []*Service {
|
||||||
|
var services []*Service
|
||||||
|
for _, s := range Services() {
|
||||||
|
if s.Select().GroupId == int(g.Id) {
|
||||||
|
services = append(services, s.(*Service))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return services
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectGroups returns all groups
|
||||||
|
func SelectGroups(includeAll bool, auth bool) []*Group {
|
||||||
|
var groups []*Group
|
||||||
|
var validGroups []*Group
|
||||||
|
groupsDb().Find(&groups).Order("id desc")
|
||||||
|
if includeAll {
|
||||||
|
emptyGroup := &Group{&types.Group{Id: 0, Public: types.NewNullBool(true)}}
|
||||||
|
groups = append(groups, emptyGroup)
|
||||||
|
}
|
||||||
|
for _, g := range groups {
|
||||||
|
if !g.Public.Bool {
|
||||||
|
if auth {
|
||||||
|
validGroups = append(validGroups, g)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
validGroups = append(validGroups, g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return validGroups
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectGroup returns a *core.Group
|
||||||
|
func SelectGroup(id int64) *Group {
|
||||||
|
for _, g := range SelectGroups(false, false) {
|
||||||
|
if g.Id == id {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -26,6 +26,9 @@ import (
|
||||||
// InsertSampleData will create the example/dummy services for a brand new Statping installation
|
// InsertSampleData will create the example/dummy services for a brand new Statping installation
|
||||||
func InsertSampleData() error {
|
func InsertSampleData() error {
|
||||||
utils.Log(1, "Inserting Sample Data...")
|
utils.Log(1, "Inserting Sample Data...")
|
||||||
|
|
||||||
|
insertSampleGroups()
|
||||||
|
|
||||||
s1 := ReturnService(&types.Service{
|
s1 := ReturnService(&types.Service{
|
||||||
Name: "Google",
|
Name: "Google",
|
||||||
Domain: "https://google.com",
|
Domain: "https://google.com",
|
||||||
|
@ -35,6 +38,7 @@ func InsertSampleData() error {
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
Timeout: 10,
|
Timeout: 10,
|
||||||
Order: 1,
|
Order: 1,
|
||||||
|
GroupId: 1,
|
||||||
})
|
})
|
||||||
s2 := ReturnService(&types.Service{
|
s2 := ReturnService(&types.Service{
|
||||||
Name: "Statping Github",
|
Name: "Statping Github",
|
||||||
|
@ -55,6 +59,8 @@ func InsertSampleData() error {
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
Timeout: 30,
|
Timeout: 30,
|
||||||
Order: 3,
|
Order: 3,
|
||||||
|
Public: types.NewNullBool(true),
|
||||||
|
GroupId: 2,
|
||||||
})
|
})
|
||||||
s4 := ReturnService(&types.Service{
|
s4 := ReturnService(&types.Service{
|
||||||
Name: "JSON API Tester",
|
Name: "JSON API Tester",
|
||||||
|
@ -67,6 +73,8 @@ func InsertSampleData() error {
|
||||||
PostData: types.NewNullString(`{ "title": "statup", "body": "bar", "userId": 19999 }`),
|
PostData: types.NewNullString(`{ "title": "statup", "body": "bar", "userId": 19999 }`),
|
||||||
Timeout: 30,
|
Timeout: 30,
|
||||||
Order: 4,
|
Order: 4,
|
||||||
|
Public: types.NewNullBool(true),
|
||||||
|
GroupId: 2,
|
||||||
})
|
})
|
||||||
s5 := ReturnService(&types.Service{
|
s5 := ReturnService(&types.Service{
|
||||||
Name: "Google DNS",
|
Name: "Google DNS",
|
||||||
|
@ -76,6 +84,8 @@ func InsertSampleData() error {
|
||||||
Port: 53,
|
Port: 53,
|
||||||
Timeout: 120,
|
Timeout: 120,
|
||||||
Order: 5,
|
Order: 5,
|
||||||
|
Public: types.NewNullBool(true),
|
||||||
|
GroupId: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
s1.Create(false)
|
s1.Create(false)
|
||||||
|
@ -91,6 +101,20 @@ func InsertSampleData() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func insertSampleGroups() error {
|
||||||
|
group1 := &Group{&types.Group{
|
||||||
|
Name: "Main Services",
|
||||||
|
Public: types.NewNullBool(true),
|
||||||
|
}}
|
||||||
|
_, err := group1.Create()
|
||||||
|
group2 := &Group{&types.Group{
|
||||||
|
Name: "Linked Services",
|
||||||
|
Public: types.NewNullBool(false),
|
||||||
|
}}
|
||||||
|
_, err = group2.Create()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// insertSampleCheckins will create 2 checkins with 60 successful hits per Checkin
|
// insertSampleCheckins will create 2 checkins with 60 successful hits per Checkin
|
||||||
func insertSampleCheckins() error {
|
func insertSampleCheckins() error {
|
||||||
s1 := SelectService(1)
|
s1 := SelectService(1)
|
||||||
|
|
|
@ -189,6 +189,7 @@ func TestCreateService(t *testing.T) {
|
||||||
Type: "http",
|
Type: "http",
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
Timeout: 20,
|
Timeout: 20,
|
||||||
|
GroupId: 1,
|
||||||
})
|
})
|
||||||
var err error
|
var err error
|
||||||
newServiceId, err = s.Create(false)
|
newServiceId, err = s.Create(false)
|
||||||
|
@ -212,6 +213,7 @@ func TestCreateFailingHTTPService(t *testing.T) {
|
||||||
Type: "http",
|
Type: "http",
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
Timeout: 5,
|
Timeout: 5,
|
||||||
|
GroupId: 1,
|
||||||
})
|
})
|
||||||
var err error
|
var err error
|
||||||
newServiceId, err = s.Create(false)
|
newServiceId, err = s.Create(false)
|
||||||
|
@ -238,6 +240,7 @@ func TestCreateFailingTCPService(t *testing.T) {
|
||||||
Interval: 30,
|
Interval: 30,
|
||||||
Type: "tcp",
|
Type: "tcp",
|
||||||
Timeout: 5,
|
Timeout: 5,
|
||||||
|
GroupId: 1,
|
||||||
})
|
})
|
||||||
var err error
|
var err error
|
||||||
newServiceId, err = s.Create(false)
|
newServiceId, err = s.Create(false)
|
||||||
|
|
|
@ -88,6 +88,12 @@ func sendJsonAction(obj interface{}, method string, w http.ResponseWriter, r *ht
|
||||||
case *core.User:
|
case *core.User:
|
||||||
objName = "user"
|
objName = "user"
|
||||||
objId = v.Id
|
objId = v.Id
|
||||||
|
case *types.Group:
|
||||||
|
objName = "group"
|
||||||
|
objId = v.Id
|
||||||
|
case *core.Group:
|
||||||
|
objName = "group"
|
||||||
|
objId = v.Id
|
||||||
case *core.Checkin:
|
case *core.Checkin:
|
||||||
objName = "checkin"
|
objName = "checkin"
|
||||||
objId = v.Id
|
objId = v.Id
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
// Statup
|
||||||
|
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||||
|
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||||
|
//
|
||||||
|
// https://github.com/hunterlong/statup
|
||||||
|
//
|
||||||
|
// The licenses for most software and other practical works are designed
|
||||||
|
// to take away your freedom to share and change the works. By contrast,
|
||||||
|
// the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
// share and change all versions of a program--to make sure it remains free
|
||||||
|
// software for all its users.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/hunterlong/statping/core"
|
||||||
|
"github.com/hunterlong/statping/utils"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// apiAllGroupHandler will show all the groups
|
||||||
|
func apiAllGroupHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !IsReadAuthenticated(r) {
|
||||||
|
sendUnauthorizedJson(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
auth := IsUser(r)
|
||||||
|
groups := core.SelectGroups(false, auth)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(groups)
|
||||||
|
}
|
||||||
|
|
||||||
|
// apiGroupHandler will show a single group
|
||||||
|
func apiGroupHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !IsReadAuthenticated(r) {
|
||||||
|
sendUnauthorizedJson(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
group := core.SelectGroup(utils.ToInt(vars["id"]))
|
||||||
|
if group == nil {
|
||||||
|
sendErrorJson(errors.New("group not found"), w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(group)
|
||||||
|
}
|
||||||
|
|
||||||
|
// apiCreateGroupHandler accepts a POST method to create new groups
|
||||||
|
func apiCreateGroupHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !IsFullAuthenticated(r) {
|
||||||
|
sendUnauthorizedJson(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var group *core.Group
|
||||||
|
decoder := json.NewDecoder(r.Body)
|
||||||
|
err := decoder.Decode(&group)
|
||||||
|
if err != nil {
|
||||||
|
sendErrorJson(err, w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = group.Create()
|
||||||
|
if err != nil {
|
||||||
|
sendErrorJson(err, w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendJsonAction(group, "create", w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// apiGroupDeleteHandler accepts a DELETE method to delete groups
|
||||||
|
func apiGroupDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !IsFullAuthenticated(r) {
|
||||||
|
sendUnauthorizedJson(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
group := core.SelectGroup(utils.ToInt(vars["id"]))
|
||||||
|
if group == nil {
|
||||||
|
sendErrorJson(errors.New("group not found"), w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := group.Delete()
|
||||||
|
if err != nil {
|
||||||
|
sendErrorJson(err, w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendJsonAction(group, "delete", w, r)
|
||||||
|
}
|
|
@ -192,8 +192,13 @@ var handlerFuncs = func(w http.ResponseWriter, r *http.Request) template.FuncMap
|
||||||
"Services": func() []types.ServiceInterface {
|
"Services": func() []types.ServiceInterface {
|
||||||
return core.CoreApp.Services
|
return core.CoreApp.Services
|
||||||
},
|
},
|
||||||
"len": func(g []types.ServiceInterface) int {
|
"Groups": func(includeAll bool) []*core.Group {
|
||||||
return len(g)
|
auth := IsUser(r)
|
||||||
|
return core.SelectGroups(includeAll, auth)
|
||||||
|
},
|
||||||
|
"len": func(g interface{}) int {
|
||||||
|
val := reflect.ValueOf(g)
|
||||||
|
return val.Len()
|
||||||
},
|
},
|
||||||
"IsNil": func(g interface{}) bool {
|
"IsNil": func(g interface{}) bool {
|
||||||
return g == nil
|
return g == nil
|
||||||
|
@ -259,6 +264,9 @@ var handlerFuncs = func(w http.ResponseWriter, r *http.Request) template.FuncMap
|
||||||
"NewMessage": func() *types.Message {
|
"NewMessage": func() *types.Message {
|
||||||
return new(types.Message)
|
return new(types.Message)
|
||||||
},
|
},
|
||||||
|
"NewGroup": func() *types.Group {
|
||||||
|
return new(types.Group)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,7 +284,7 @@ func ExecuteResponse(w http.ResponseWriter, r *http.Request, file string, data i
|
||||||
w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
|
w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
|
||||||
}
|
}
|
||||||
|
|
||||||
templates := []string{"base.gohtml", "head.gohtml", "nav.gohtml", "footer.gohtml", "scripts.gohtml", "form_service.gohtml", "form_notifier.gohtml", "form_user.gohtml", "form_checkin.gohtml", "form_message.gohtml"}
|
templates := []string{"base.gohtml", "head.gohtml", "nav.gohtml", "footer.gohtml", "scripts.gohtml", "form_service.gohtml", "form_notifier.gohtml", "form_group.gohtml", "form_user.gohtml", "form_checkin.gohtml", "form_message.gohtml"}
|
||||||
javascripts := []string{"charts.js", "chart_index.js"}
|
javascripts := []string{"charts.js", "chart_index.js"}
|
||||||
|
|
||||||
render, err := source.TmplBox.String(file)
|
render, err := source.TmplBox.String(file)
|
||||||
|
|
|
@ -31,8 +31,8 @@ import (
|
||||||
|
|
||||||
func TestResetHandlerDatabase(t *testing.T) {
|
func TestResetHandlerDatabase(t *testing.T) {
|
||||||
Clean()
|
Clean()
|
||||||
loadDatabase()
|
//loadDatabase()
|
||||||
createDatabase()
|
//createDatabase()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFailedHTTPServer(t *testing.T) {
|
func TestFailedHTTPServer(t *testing.T) {
|
||||||
|
|
|
@ -85,6 +85,12 @@ func Router() *mux.Router {
|
||||||
r.Handle("/service/{id}/edit", http.HandlerFunc(servicesViewHandler))
|
r.Handle("/service/{id}/edit", http.HandlerFunc(servicesViewHandler))
|
||||||
r.Handle("/service/{id}/delete_failures", http.HandlerFunc(servicesDeleteFailuresHandler)).Methods("GET")
|
r.Handle("/service/{id}/delete_failures", http.HandlerFunc(servicesDeleteFailuresHandler)).Methods("GET")
|
||||||
|
|
||||||
|
// API GROUPS Routes
|
||||||
|
r.Handle("/api/groups", http.HandlerFunc(apiAllGroupHandler)).Methods("GET")
|
||||||
|
r.Handle("/api/groups", http.HandlerFunc(apiCreateGroupHandler)).Methods("POST")
|
||||||
|
r.Handle("/api/groups/{id}", http.HandlerFunc(apiGroupHandler)).Methods("GET")
|
||||||
|
r.Handle("/api/groups/{id}", http.HandlerFunc(apiGroupDeleteHandler)).Methods("DELETE")
|
||||||
|
|
||||||
// API Routes
|
// API Routes
|
||||||
r.Handle("/api", http.HandlerFunc(apiIndexHandler))
|
r.Handle("/api", http.HandlerFunc(apiIndexHandler))
|
||||||
r.Handle("/api/renew", http.HandlerFunc(apiRenewHandler))
|
r.Handle("/api/renew", http.HandlerFunc(apiRenewHandler))
|
||||||
|
|
|
@ -51,7 +51,10 @@ func servicesHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ExecuteResponse(w, r, "services.gohtml", core.CoreApp.Services, nil)
|
data := map[string]interface{}{
|
||||||
|
"Services": core.CoreApp.Services,
|
||||||
|
}
|
||||||
|
ExecuteResponse(w, r, "services.gohtml", data, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
type serviceOrder struct {
|
type serviceOrder struct {
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
{{define "form_group"}}
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
{{$message := .}}
|
||||||
|
{{if ne .Id 0}}
|
||||||
|
<form class="ajax_form" action="/api/groups/{{.Id}}" data-redirect="/services" method="POST">
|
||||||
|
{{else}}
|
||||||
|
<form class="ajax_form" action="/api/groups" data-redirect="/services" method="POST">
|
||||||
|
{{end}}
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="username" class="col-sm-4 col-form-label">Group Name</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="text" name="name" class="form-control" value="{{.Name}}" id="title" placeholder="Group Name" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="order" class="col-sm-4 col-form-label">Public Group</label>
|
||||||
|
<div class="col-8 mt-1">
|
||||||
|
<span class="switch float-left">
|
||||||
|
<input type="checkbox" name="public" class="switch" id="switch-group-public" checked>
|
||||||
|
<label for="switch-group-public">Show group services to the public</label>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<button type="submit" class="btn btn-primary btn-block">{{if ne .Id 0}}Update Group{{else}}Create Group{{end}}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="alert alert-danger d-none" id="alerter" role="alert"></div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
|
@ -1,6 +1,7 @@
|
||||||
{{define "form_service"}}
|
{{define "form_service"}}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
{{$s := .}}
|
||||||
{{if ne .Id 0}}
|
{{if ne .Id 0}}
|
||||||
<form class="ajax_form" action="/api/services/{{.Id}}" data-redirect="/services" method="POST">
|
<form class="ajax_form" action="/api/services/{{.Id}}" data-redirect="/services" method="POST">
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -101,6 +102,27 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="service_type" class="col-sm-4 col-form-label">Group</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<select name="group_id" class="form-control" id="group_id">
|
||||||
|
<option value="0" {{if eq $s.GroupId 0}}selected{{end}}>None</option>
|
||||||
|
{{range Groups false}}
|
||||||
|
<option value="{{.Id}}" {{if eq $s.GroupId .Id}}selected{{end}}>{{.Name}}</option>
|
||||||
|
{{end}}
|
||||||
|
</select>
|
||||||
|
<small class="form-text text-muted">Attach this service to a group</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="order" class="col-sm-4 col-form-label">Visible</label>
|
||||||
|
<div class="col-8 mt-1">
|
||||||
|
<span class="switch float-left">
|
||||||
|
<input type="checkbox" name="public" class="switch" id="switch-public" {{if .Public.Bool}}checked{{end}}>
|
||||||
|
<label for="switch-public">Show service details to the public</label>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<div class="{{if ne .Id 0}}col-6{{else}}col-12{{end}}">
|
<div class="{{if ne .Id 0}}col-6{{else}}col-12{{end}}">
|
||||||
<button type="submit" class="btn btn-success btn-block">{{if ne .Id 0}}Update Service{{else}}Create Service{{end}}</button>
|
<button type="submit" class="btn btn-success btn-block">{{if ne .Id 0}}Update Service{{else}}Create Service{{end}}</button>
|
||||||
|
|
|
@ -8,10 +8,11 @@
|
||||||
<h5 class="col-12 text-center mb-5 header-desc">{{ .Description }}</h5>
|
<h5 class="col-12 text-center mb-5 header-desc">{{ .Description }}</h5>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
{{ range Groups true }}
|
||||||
<div class="col-12 full-col-12">
|
<div class="col-12 full-col-12">
|
||||||
|
<h4>{{.Name}}</h4>
|
||||||
<div class="list-group online_list mb-3">
|
<div class="list-group online_list mb-3">
|
||||||
{{ range Services }}
|
{{ range .Services }}
|
||||||
<a href="#" class="service_li list-group-item list-group-item-action {{if not .Online}}bg-danger text-white{{ end }}" data-id="{{.Id}}">
|
<a href="#" class="service_li list-group-item list-group-item-action {{if not .Online}}bg-danger text-white{{ end }}" data-id="{{.Id}}">
|
||||||
{{ .Name }}
|
{{ .Name }}
|
||||||
{{if .Online}}
|
{{if .Online}}
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
{{ if .Messages }}
|
{{ if .Messages }}
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">Title</th>
|
<th scope="col">Title</th>
|
||||||
<th scope="col">Service</th>
|
<th scope="col" class="d-none d-md-table-cell">Service</th>
|
||||||
<th scope="col">Begins</th>
|
<th scope="col" class="d-none d-md-table-cell">Begins</th>
|
||||||
<th scope="col"></th>
|
<th scope="col"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -18,8 +18,8 @@
|
||||||
{{range .}}
|
{{range .}}
|
||||||
<tr id="message_{{.Id}}">
|
<tr id="message_{{.Id}}">
|
||||||
<td>{{.Title}}</td>
|
<td>{{.Title}}</td>
|
||||||
<td>{{if .Service}}<a href="/service/{{.Service.Id}}">{{.Service.Name}}</a>{{end}}</td>
|
<td class="d-none d-md-table-cell">{{if .Service}}<a href="/service/{{.Service.Id}}">{{.Service.Name}}</a>{{end}}</td>
|
||||||
<td>{{.StartOn}}</td>
|
<td class="d-none d-md-table-cell">{{.StartOn}}</td>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
{{if Auth}}<div class="btn-group">
|
{{if Auth}}<div class="btn-group">
|
||||||
<a href="/message/{{.Id}}" class="btn btn-outline-secondary"><i class="fas fa-exclamation-triangle"></i> Edit</a>
|
<a href="/message/{{.Id}}" class="btn btn-outline-secondary"><i class="fas fa-exclamation-triangle"></i> Edit</a>
|
||||||
|
|
|
@ -769,6 +769,430 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Groups",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "All Groups",
|
||||||
|
"event": [
|
||||||
|
{
|
||||||
|
"listen": "test",
|
||||||
|
"script": {
|
||||||
|
"id": "d87f8a4e-7640-45b8-9d45-4f6e6f2463ee",
|
||||||
|
"exec": [
|
||||||
|
"pm.test(\"View All Groups\", function () {",
|
||||||
|
" var jsonData = pm.response.json();",
|
||||||
|
" pm.expect(jsonData.length).to.eql(2);",
|
||||||
|
"});"
|
||||||
|
],
|
||||||
|
"type": "text/javascript"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"request": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "{{api_key}}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": ""
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{endpoint}}/api/groups",
|
||||||
|
"host": [
|
||||||
|
"{{endpoint}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"groups"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "View an array of all Groups added to your Statping instance."
|
||||||
|
},
|
||||||
|
"response": [
|
||||||
|
{
|
||||||
|
"name": "All Groups",
|
||||||
|
"originalRequest": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": ""
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{endpoint}}/api/groups",
|
||||||
|
"host": [
|
||||||
|
"{{endpoint}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"groups"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": "OK",
|
||||||
|
"code": 200,
|
||||||
|
"_postman_previewlanguage": "json",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Date",
|
||||||
|
"value": "Thu, 03 Jan 2019 21:48:40 GMT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Length",
|
||||||
|
"value": "301"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cookie": [],
|
||||||
|
"body": "[\n {\n \"id\": 1,\n \"name\": \"Main Services\",\n \"public\": true,\n \"created_at\": \"2019-01-03T13:48:23.488553261-08:00\",\n \"updated_at\": \"2019-01-03T13:48:23.488614502-08:00\"\n },\n {\n \"id\": 2,\n \"name\": \"Linked Services\",\n \"public\": false,\n \"created_at\": \"2019-01-03T13:48:23.489693923-08:00\",\n \"updated_at\": \"2019-01-03T13:48:23.489719447-08:00\"\n }\n]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "View Group",
|
||||||
|
"event": [
|
||||||
|
{
|
||||||
|
"listen": "test",
|
||||||
|
"script": {
|
||||||
|
"id": "023c5643-6cb1-4cd0-b775-566f232d68f8",
|
||||||
|
"exec": [
|
||||||
|
"pm.test(\"View Group\", function () {",
|
||||||
|
" var jsonData = pm.response.json();",
|
||||||
|
" pm.expect(jsonData.name).to.eql(\"Main Services\");",
|
||||||
|
"});"
|
||||||
|
],
|
||||||
|
"type": "text/javascript"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"request": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "{{api_key}}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"name": "Content-Type",
|
||||||
|
"type": "text",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": ""
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{endpoint}}/api/groups/1",
|
||||||
|
"host": [
|
||||||
|
"{{endpoint}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"groups",
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "View a specific group"
|
||||||
|
},
|
||||||
|
"response": [
|
||||||
|
{
|
||||||
|
"name": "View Group",
|
||||||
|
"originalRequest": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"name": "Content-Type",
|
||||||
|
"type": "text",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": ""
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{endpoint}}/api/groups/1",
|
||||||
|
"host": [
|
||||||
|
"{{endpoint}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"groups",
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": "OK",
|
||||||
|
"code": 200,
|
||||||
|
"_postman_previewlanguage": "json",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Date",
|
||||||
|
"value": "Thu, 03 Jan 2019 21:48:58 GMT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Length",
|
||||||
|
"value": "148"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cookie": [],
|
||||||
|
"body": "{\n \"id\": 1,\n \"name\": \"Main Services\",\n \"public\": true,\n \"created_at\": \"2019-01-03T13:48:23.488553261-08:00\",\n \"updated_at\": \"2019-01-03T13:48:23.488614502-08:00\"\n}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Create Group",
|
||||||
|
"event": [
|
||||||
|
{
|
||||||
|
"listen": "test",
|
||||||
|
"script": {
|
||||||
|
"id": "d4eb16fe-8495-40e5-9ca3-be20951e5133",
|
||||||
|
"exec": [
|
||||||
|
"pm.test(\"Create Group\", function () {",
|
||||||
|
" var jsonData = pm.response.json();",
|
||||||
|
" pm.expect(jsonData.output.name).to.eql(\"New Group\");",
|
||||||
|
" pm.globals.set(\"group_id\", jsonData.output.id);",
|
||||||
|
"});"
|
||||||
|
],
|
||||||
|
"type": "text/javascript"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"request": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "{{api_key}}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"name\": \"New Group\",\n \"public\": true\n}"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{endpoint}}/api/groups",
|
||||||
|
"host": [
|
||||||
|
"{{endpoint}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"groups"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Create a new Group to organize services."
|
||||||
|
},
|
||||||
|
"response": [
|
||||||
|
{
|
||||||
|
"name": "Create Group",
|
||||||
|
"originalRequest": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"name\": \"New Group\",\n \"public\": true\n}"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{endpoint}}/api/groups",
|
||||||
|
"host": [
|
||||||
|
"{{endpoint}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"groups"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": "OK",
|
||||||
|
"code": 200,
|
||||||
|
"_postman_previewlanguage": "json",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Date",
|
||||||
|
"value": "Thu, 03 Jan 2019 21:49:25 GMT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Length",
|
||||||
|
"value": "214"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cookie": [],
|
||||||
|
"body": "{\n \"status\": \"success\",\n \"type\": \"group\",\n \"method\": \"create\",\n \"id\": 3,\n \"output\": {\n \"id\": 3,\n \"name\": \"New Group\",\n \"public\": true,\n \"created_at\": \"2019-01-03T13:49:25.947069211-08:00\",\n \"updated_at\": \"2019-01-03T13:49:25.947120276-08:00\"\n }\n}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete Group",
|
||||||
|
"event": [
|
||||||
|
{
|
||||||
|
"listen": "test",
|
||||||
|
"script": {
|
||||||
|
"id": "dd4d721d-d874-448b-abc9-59c1afceb58e",
|
||||||
|
"exec": [
|
||||||
|
"pm.test(\"Delete Service\", function () {",
|
||||||
|
" var jsonData = pm.response.json();",
|
||||||
|
" pm.expect(jsonData.status).to.eql(\"success\");",
|
||||||
|
" pm.expect(jsonData.type).to.eql(\"group\");",
|
||||||
|
" pm.expect(jsonData.method).to.eql(\"delete\");",
|
||||||
|
"});"
|
||||||
|
],
|
||||||
|
"type": "text/javascript"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"request": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "{{api_key}}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "DELETE",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": ""
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{endpoint}}/api/groups/{{group_id}}",
|
||||||
|
"host": [
|
||||||
|
"{{endpoint}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"groups",
|
||||||
|
"{{group_id}}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Delete a group"
|
||||||
|
},
|
||||||
|
"response": [
|
||||||
|
{
|
||||||
|
"name": "Delete Group",
|
||||||
|
"originalRequest": {
|
||||||
|
"method": "DELETE",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": ""
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{endpoint}}/api/groups/{{group_id}}",
|
||||||
|
"host": [
|
||||||
|
"{{endpoint}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"groups",
|
||||||
|
"{{group_id}}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": "OK",
|
||||||
|
"code": 200,
|
||||||
|
"_postman_previewlanguage": "json",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Date",
|
||||||
|
"value": "Thu, 03 Jan 2019 21:49:49 GMT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Length",
|
||||||
|
"value": "214"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cookie": [],
|
||||||
|
"body": "{\n \"status\": \"success\",\n \"type\": \"group\",\n \"method\": \"delete\",\n \"id\": 3,\n \"output\": {\n \"id\": 3,\n \"name\": \"New Group\",\n \"public\": true,\n \"created_at\": \"2019-01-03T13:49:25.947069211-08:00\",\n \"updated_at\": \"2019-01-03T13:49:25.947120276-08:00\"\n }\n}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "{{api_key}}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"event": [
|
||||||
|
{
|
||||||
|
"listen": "prerequest",
|
||||||
|
"script": {
|
||||||
|
"id": "4cd2ab82-e60d-45cd-9b74-cb4b5d893f4d",
|
||||||
|
"type": "text/javascript",
|
||||||
|
"exec": [
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"listen": "test",
|
||||||
|
"script": {
|
||||||
|
"id": "c7cb2b6d-289a-4073-b291-202bbec8cb44",
|
||||||
|
"type": "text/javascript",
|
||||||
|
"exec": [
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Users",
|
"name": "Users",
|
||||||
"item": [
|
"item": [
|
||||||
|
|
|
@ -4,21 +4,23 @@
|
||||||
{{template "nav"}}
|
{{template "nav"}}
|
||||||
|
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
{{if ne (len .) 0}}
|
{{if ne (len .Services) 0}}
|
||||||
<h3>Services</h3>
|
<h3>Services</h3>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">Name</th>
|
<th scope="col">Name</th>
|
||||||
<th scope="col" class="d-none d-md-table-cell">Status</th>
|
<th scope="col" class="d-none d-md-table-cell">Status</th>
|
||||||
|
<th scope="col">Visibility</th>
|
||||||
<th scope="col"></th>
|
<th scope="col"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="sortable" id="services_table">
|
<tbody class="sortable" id="services_table">
|
||||||
{{range .}}
|
{{range .Services}}
|
||||||
<tr id="service_{{.Id}}" data-id="{{.Id}}">
|
<tr id="service_{{.Id}}" data-id="{{.Id}}">
|
||||||
<td><span class="drag_icon d-none d-md-inline"><i class="fas fa-bars"></i></span> {{.Name}}</td>
|
<td><span class="drag_icon d-none d-md-inline"><i class="fas fa-bars"></i></span> {{.Name}}</td>
|
||||||
<td class="d-none d-md-table-cell">{{if .Online}}<span class="badge badge-success">ONLINE</span>{{else}}<span class="badge badge-danger">OFFLINE</span>{{end}}</td>
|
<td class="d-none d-md-table-cell">{{if .Online}}<span class="badge badge-success">ONLINE</span>{{else}}<span class="badge badge-danger">OFFLINE</span>{{end}}</td>
|
||||||
|
<td class="d-none d-md-table-cell">{{if .Public.Bool}}<span class="badge badge-primary">PUBLIC</span>{{else}}<span class="badge badge-secondary">PRIVATE</span>{{end}}</td>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<a href="/service/{{.Id}}" class="btn btn-outline-secondary"><i class="fas fa-chart-area"></i> View</a>
|
<a href="/service/{{.Id}}" class="btn btn-outline-secondary"><i class="fas fa-chart-area"></i> View</a>
|
||||||
|
@ -35,6 +37,39 @@
|
||||||
{{template "form_service" NewService}}
|
{{template "form_service" NewService}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 mt-3">
|
||||||
|
<h3>Groups</h3>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Services</th>
|
||||||
|
<th scope="col">Visibility</th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="groups_table">
|
||||||
|
{{range Groups false}}
|
||||||
|
<tr id="group_{{.Id}}" data-id="{{.Id}}">
|
||||||
|
<td>{{.Name}}</td>
|
||||||
|
<td>{{len .Services}}</td>
|
||||||
|
<td>{{if .Public.Bool}}<span class="badge badge-primary">PUBLIC</span>{{else}}<span class="badge badge-secondary">PRIVATE</span>{{end}}</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<div class="btn-group">
|
||||||
|
{{if Auth}}<a href="/api/groups/{{.Id}}" class="ajax_delete btn btn-danger" data-method="DELETE" data-obj="group_{{.Id}}" data-id="{{.Id}}"><i class="fas fa-times"></i></a>{{end}}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{if Auth}}
|
||||||
|
<h3>Create Group</h3>
|
||||||
|
{{template "form_group" NewGroup}}
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "extra_scripts"}}
|
{{define "extra_scripts"}}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// This file was generated by robots at
|
// This file was generated by robots at
|
||||||
// 2018-12-19 21:35:31.636341 -0800 PST m=+0.699027992
|
// 2019-01-03 13:55:35.224765 -0800 PST m=+0.695466687
|
||||||
//
|
//
|
||||||
// This contains the most recently Markdown source for the Statping Wiki.
|
// This contains the most recently Markdown source for the Statping Wiki.
|
||||||
package source
|
package source
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Group is the main struct for Groups
|
||||||
|
type Group struct {
|
||||||
|
Id int64 `gorm:"primary_key;column:id" json:"id"`
|
||||||
|
Name string `gorm:"column:name" json:"name"`
|
||||||
|
Public NullBool `gorm:"default:false;column:public" json:"public"`
|
||||||
|
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||||
|
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||||
|
}
|
|
@ -34,6 +34,8 @@ type Service struct {
|
||||||
Timeout int `gorm:"default:30;column:timeout" json:"timeout"`
|
Timeout int `gorm:"default:30;column:timeout" json:"timeout"`
|
||||||
Order int `gorm:"default:0;column:order_id" json:"order_id"`
|
Order int `gorm:"default:0;column:order_id" json:"order_id"`
|
||||||
AllowNotifications NullBool `gorm:"default:false;column:allow_notifications" json:"allow_notifications"`
|
AllowNotifications NullBool `gorm:"default:false;column:allow_notifications" json:"allow_notifications"`
|
||||||
|
Public NullBool `gorm:"default:false;column:public" json:"public"`
|
||||||
|
GroupId int `gorm:"default:0;column:group_id" json:"group_id"`
|
||||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||||
Online bool `gorm:"-" json:"online"`
|
Online bool `gorm:"-" json:"online"`
|
||||||
|
|
|
@ -231,6 +231,7 @@ func SaveFile(filename string, data []byte) error {
|
||||||
// // headers - An array of Headers to be sent (KEY=VALUE) []string{"Authentication=12345", ...}
|
// // headers - An array of Headers to be sent (KEY=VALUE) []string{"Authentication=12345", ...}
|
||||||
// // body - The body or form data to send with HTTP request
|
// // body - The body or form data to send with HTTP request
|
||||||
// // timeout - Specific duration to timeout on. time.Duration(30 * time.Seconds)
|
// // timeout - Specific duration to timeout on. time.Duration(30 * time.Seconds)
|
||||||
|
// // You can use a HTTP Proxy if you HTTP_PROXY environment variable
|
||||||
func HttpRequest(url, method string, content interface{}, headers []string, body io.Reader, timeout time.Duration) ([]byte, *http.Response, error) {
|
func HttpRequest(url, method string, content interface{}, headers []string, body io.Reader, timeout time.Duration) ([]byte, *http.Response, error) {
|
||||||
var err error
|
var err error
|
||||||
transport := &http.Transport{
|
transport := &http.Transport{
|
||||||
|
@ -240,6 +241,7 @@ func HttpRequest(url, method string, content interface{}, headers []string, body
|
||||||
DisableKeepAlives: true,
|
DisableKeepAlives: true,
|
||||||
ResponseHeaderTimeout: timeout,
|
ResponseHeaderTimeout: timeout,
|
||||||
TLSHandshakeTimeout: timeout,
|
TLSHandshakeTimeout: timeout,
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
}
|
}
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
Transport: transport,
|
Transport: transport,
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.80.32
|
0.80.33
|
Loading…
Reference in New Issue