mirror of https://github.com/statping/statping
notifier fixers - UI fixes
parent
8c20efd9cc
commit
f096db178f
|
@ -110,6 +110,15 @@ func OnUpdatedCore(c *types.Core) {
|
|||
}
|
||||
}
|
||||
|
||||
// OnUpdatedCore is triggered when the CoreApp settings are saved - CoreEvents interface
|
||||
func OnStart(c *types.Core) {
|
||||
for _, comm := range AllCommunications {
|
||||
if isType(comm, new(CoreEvents)) && isEnabled(comm) && inLimits(comm) {
|
||||
comm.(CoreEvents).OnUpdatedCore(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NotifierEvents interface
|
||||
func OnNewNotifier(n *Notification) {
|
||||
for _, comm := range AllCommunications {
|
||||
|
|
|
@ -122,6 +122,12 @@ func (n *Example) OnFailure(s *types.Service, f *types.Failure) {
|
|||
n.AddQueue(msg)
|
||||
}
|
||||
|
||||
// OPTIONAL Test function before user saves
|
||||
func (n *Example) OnTest(s Notification) (bool, error) {
|
||||
fmt.Printf("received a test trigger with form data: %v\n", s.Host)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// OPTIONAL
|
||||
func (n *Example) OnNewService(s *types.Service) {
|
||||
msg := fmt.Sprintf("received a new service trigger for service: %v\n", s.Name)
|
||||
|
@ -164,6 +170,12 @@ func (n *Example) OnUpdatedCore(s *types.Core) {
|
|||
n.AddQueue(msg)
|
||||
}
|
||||
|
||||
// OPTIONAL
|
||||
func (n *Example) OnStart(s *types.Core) {
|
||||
msg := fmt.Sprintf("received a trigger on Statup boot: %v\n", s.Name)
|
||||
n.AddQueue(msg)
|
||||
}
|
||||
|
||||
// OPTIONAL
|
||||
func (n *Example) OnNewNotifier(s *Notification) {
|
||||
msg := fmt.Sprintf("received a new notifier trigger for notifier: %v\n", s.Method)
|
||||
|
|
|
@ -21,7 +21,6 @@ import "github.com/hunterlong/statup/types"
|
|||
type Notifier interface {
|
||||
OnSave() error // OnSave is triggered when the notifier is saved
|
||||
Send(interface{}) error // OnSave is triggered when the notifier is saved
|
||||
Test() error // Test will run a function inside the notifier to Test if it works
|
||||
Select() *Notification // Select returns the *Notification for a notifier
|
||||
}
|
||||
|
||||
|
@ -31,6 +30,11 @@ type BasicEvents interface {
|
|||
OnFailure(*types.Service, *types.Failure) // OnFailure is triggered when a service is failing
|
||||
}
|
||||
|
||||
// Tester interface will include a function to Test users settings before saving
|
||||
type Tester interface {
|
||||
OnTest(Notification) (bool, error)
|
||||
}
|
||||
|
||||
// ServiceEvents are events for Services
|
||||
type ServiceEvents interface {
|
||||
OnNewService(*types.Service)
|
||||
|
@ -48,6 +52,7 @@ type UserEvents interface {
|
|||
// CoreEvents are events for the main Core app
|
||||
type CoreEvents interface {
|
||||
OnUpdatedCore(*types.Core)
|
||||
OnStart(*types.Core)
|
||||
}
|
||||
|
||||
// NotifierEvents are events for other Notifiers
|
||||
|
|
|
@ -57,6 +57,7 @@ type Notification struct {
|
|||
Delay time.Duration `gorm:"-" json:"-"`
|
||||
Queue []interface{} `gorm:"-" json:"-"`
|
||||
Running chan bool `gorm:"-" json:"-"`
|
||||
CanTest bool `gorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
type NotificationForm struct {
|
||||
|
@ -65,6 +66,7 @@ type NotificationForm struct {
|
|||
Placeholder string
|
||||
DbField string
|
||||
SmallText string
|
||||
Required bool
|
||||
}
|
||||
|
||||
type NotificationLog struct {
|
||||
|
@ -299,13 +301,22 @@ func (f *Notification) LastSent() time.Duration {
|
|||
return since
|
||||
}
|
||||
|
||||
// SentLastHour returns the amount of sent notifications within the last hour
|
||||
func (f *Notification) SentLastHour() int {
|
||||
since := time.Now().Add(-1 * time.Hour)
|
||||
return f.SentLast(since)
|
||||
}
|
||||
|
||||
func (f *Notification) SentLastMinute() int {
|
||||
since := time.Now().Add(-1 * time.Minute)
|
||||
return f.SentLast(since)
|
||||
}
|
||||
|
||||
// SentLastHour returns the amount of sent notifications within the last hour
|
||||
func (f *Notification) SentLast(since time.Time) int {
|
||||
sent := 0
|
||||
hourAgo := time.Now().Add(-1 * time.Minute)
|
||||
for _, v := range f.Logs() {
|
||||
lastTime := time.Time(v.Time)
|
||||
if lastTime.After(hourAgo) {
|
||||
if lastTime.After(since) {
|
||||
sent++
|
||||
}
|
||||
}
|
||||
|
@ -340,6 +351,11 @@ func (n *Notification) GetValue(dbField string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// Testable returns true if it includes the CoreEvents interface
|
||||
func (n *Notification) Testable() bool {
|
||||
return isType(n, new(Tester))
|
||||
}
|
||||
|
||||
// isType will return true if a variable can implement an interface
|
||||
func isType(n interface{}, obj interface{}) bool {
|
||||
one := reflect.TypeOf(n)
|
||||
|
|
|
@ -74,6 +74,7 @@ func TestIsBasicType(t *testing.T) {
|
|||
assert.True(t, isType(example, new(UserEvents)))
|
||||
assert.True(t, isType(example, new(CoreEvents)))
|
||||
assert.True(t, isType(example, new(NotifierEvents)))
|
||||
assert.True(t, isType(example, new(Tester)))
|
||||
}
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
|
|
|
@ -89,6 +89,29 @@ func InsertSampleData() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// InsertSampleHits will create a couple new hits for the sample services
|
||||
func InsertSampleHits() error {
|
||||
since := time.Now().Add(-24 * time.Hour)
|
||||
for i := int64(1); i <= 5; i++ {
|
||||
service := SelectService(i)
|
||||
utils.Log(1, fmt.Sprintf("Adding %v sample hit records to service %v", 360, service.Name))
|
||||
createdAt := since
|
||||
|
||||
for hi := int64(1); hi <= 360; hi++ {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
latency := rand.Float64()
|
||||
createdAt = createdAt.Add(2 * time.Minute)
|
||||
hit := &types.Hit{
|
||||
Service: service.Id,
|
||||
CreatedAt: createdAt,
|
||||
Latency: latency,
|
||||
}
|
||||
service.CreateHit(hit)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func InsertSampleCore() error {
|
||||
core := &types.Core{
|
||||
Name: "Statup Sample Data",
|
||||
|
|
|
@ -141,6 +141,9 @@ func ExecuteResponse(w http.ResponseWriter, r *http.Request, file string, data i
|
|||
"CHART_DATA": func() string {
|
||||
return ""
|
||||
},
|
||||
"Error": func() string {
|
||||
return ""
|
||||
},
|
||||
})
|
||||
t, err = t.Parse(nav)
|
||||
if err != nil {
|
||||
|
|
|
@ -140,6 +140,7 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
if sample == "on" {
|
||||
core.InsertSampleData()
|
||||
core.InsertSampleHits()
|
||||
}
|
||||
|
||||
core.InitApp()
|
||||
|
|
|
@ -70,11 +70,6 @@ func (u *Discord) Send(msg interface{}) error {
|
|||
return resp.Body.Close()
|
||||
}
|
||||
|
||||
func (u *Discord) Test() error {
|
||||
u.AddQueue([]byte(DISCORD_TEST))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *Discord) Select() *notifier.Notification {
|
||||
return u.Notification
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ func (u *Email) Send(msg interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *Email) Test() error {
|
||||
func (u *Email) OnTest(n notifier.Notification) (bool, error) {
|
||||
email := &EmailOutgoing{
|
||||
To: emailer.GetValue("var2"),
|
||||
Subject: "Test Email",
|
||||
|
@ -103,7 +103,7 @@ func (u *Email) Test() error {
|
|||
From: emailer.GetValue("var1"),
|
||||
}
|
||||
u.AddQueue(email)
|
||||
return nil
|
||||
return true, nil
|
||||
}
|
||||
|
||||
type EmailOutgoing struct {
|
||||
|
|
|
@ -75,12 +75,6 @@ func (u *LineNotify) Select() *notifier.Notification {
|
|||
return u.Notification
|
||||
}
|
||||
|
||||
func (u *LineNotify) Test() error {
|
||||
msg := fmt.Sprintf("You're Statup Line Notify Notifier is working correctly!")
|
||||
u.AddQueue(msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ON SERVICE FAILURE, DO YOUR OWN FUNCTIONS
|
||||
func (u *LineNotify) OnFailure(s *types.Service, f *types.Failure) {
|
||||
msg := fmt.Sprintf("Your service '%v' is currently offline!", s.Name)
|
||||
|
|
|
@ -46,6 +46,7 @@ var slacker = &Slack{¬ifier.Notification{
|
|||
AuthorUrl: "https://github.com/hunterlong",
|
||||
Delay: time.Duration(10 * time.Second),
|
||||
Host: "https://webhooksurl.slack.com/***",
|
||||
CanTest: true,
|
||||
Form: []notifier.NotificationForm{{
|
||||
Type: "text",
|
||||
Title: "Incoming Webhook Url",
|
||||
|
@ -94,10 +95,11 @@ func (u *Slack) Select() *notifier.Notification {
|
|||
return u.Notification
|
||||
}
|
||||
|
||||
func (u *Slack) Test() error {
|
||||
func (u *Slack) OnTest(n notifier.Notification) (bool, error) {
|
||||
utils.Log(1, "Slack notifier loaded")
|
||||
msg := fmt.Sprintf("You're Statup Slack Notifier is working correctly!")
|
||||
return sendSlack(TEST_TEMPLATE, msg)
|
||||
err := sendSlack(TEST_TEMPLATE, msg)
|
||||
return true, err
|
||||
}
|
||||
|
||||
// ON SERVICE FAILURE, DO YOUR OWN FUNCTIONS
|
||||
|
|
|
@ -77,13 +77,6 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *Twilio) Test() error {
|
||||
utils.Log(1, "Twilio notifier loaded")
|
||||
msg := fmt.Sprintf("You're Statup Twilio Notifier is working correctly!")
|
||||
u.AddQueue(msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *Twilio) Select() *notifier.Notification {
|
||||
return u.Notification
|
||||
}
|
||||
|
|
|
@ -377,6 +377,11 @@ HTML, BODY {
|
|||
cursor: -moz-grabbing;
|
||||
cursor: -webkit-grabbing; }
|
||||
|
||||
.switch_btn {
|
||||
float: right;
|
||||
margin: -1px 0px 0px 0px;
|
||||
display: block; }
|
||||
|
||||
@media (max-width: 767px) {
|
||||
HTML, BODY {
|
||||
background-color: #fcfcfc; }
|
||||
|
|
|
@ -435,4 +435,10 @@ HTML,BODY {
|
|||
cursor: -webkit-grabbing;
|
||||
}
|
||||
|
||||
@import 'mobile';
|
||||
.switch_btn {
|
||||
float: right;
|
||||
margin: -1px 0px 0px 0px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@import 'mobile';
|
||||
|
|
|
@ -42,6 +42,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-md-8 col-sm-12">
|
||||
{{if Error}}
|
||||
<div class="alert alert-danger" role="alert">{{Error}}</div>
|
||||
{{end}}
|
||||
<div class="tab-content" id="v-pills-tabContent">
|
||||
<div class="tab-pane fade show active" id="v-pills-home" role="tabpanel" aria-labelledby="v-pills-home-tab">
|
||||
<h3>Settings</h3>
|
||||
|
@ -135,43 +138,59 @@
|
|||
{{ range .Notifications }}
|
||||
{{$n := .Select}}
|
||||
<div class="tab-pane" id="v-pills-{{underscore $n.Method}}" role="tabpanel" aria-labelledby="v-pills-{{underscore $n.Method }}-tab">
|
||||
{{if $n.Title}}<h4>{{$n.Title}}</h4>{{end}}
|
||||
{{if $n.Description}}<p class="text-muted">{{safe $n.Description}}</p>{{end}}
|
||||
<form method="POST" action="/settings/notifier/{{ $n.Method }}">
|
||||
{{if $n.Title}}<h4>{{$n.Title}}
|
||||
</h4>{{end}}
|
||||
{{if $n.Description}}<p class="text-muted">{{safe $n.Description}}</p>{{end}}
|
||||
{{range .Form}}
|
||||
<div class="form-group">
|
||||
<label class="text-capitalize" for="{{underscore .Title}}">{{.Title}}</label>
|
||||
<input type="{{.Type}}" name="{{underscore .DbField}}" class="form-control" value="{{ $n.GetValue .DbField }}" id="{{underscore .Title}}" placeholder="{{.Placeholder}}">
|
||||
<input type="{{.Type}}" name="{{underscore .DbField}}" class="form-control" value="{{ $n.GetValue .DbField }}" id="{{underscore .Title}}" placeholder="{{.Placeholder}}" {{if .Required}}required{{end}}>
|
||||
{{if .SmallText}}<small class="form-text text-muted">{{safe .SmallText}}</small>{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="form-group">
|
||||
<label class="text-capitalize" for="limits_per_hour_{{underscore $n.Method }}">Limits per Hour</label>
|
||||
<input type="number" name="limits" class="form-control" value="{{$n.Limits}}" id="limits_per_hour_{{underscore $n.Method }}" min="1" max="60" placeholder="How many messages can send per hour">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group mb-2">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">Limit</div>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="limits" min="1" max="60" id="limits_per_hour_{{underscore $n.Method }}" value="{{$n.Limits}}" placeholder="7">
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">Per Minute</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-6">
|
||||
<span class="switch">
|
||||
<div class="col-sm-2 mt-1">
|
||||
<span class="switch">
|
||||
<input type="checkbox" name="enable" class="switch" id="switch-{{ $n.Method }}" {{if $n.Enabled}}checked{{end}}>
|
||||
<label for="switch-{{ $n.Method }}">Enable {{ $n.Method }}</label>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<button type="submit" class="btn btn-primary btn-block text-capitalize">Save {{ $n.Method }} Settings</button>
|
||||
<label for="switch-{{ $n.Method }}"></label>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-4">
|
||||
<button type="submit" class="btn btn-primary btn-block text-capitalize">Save</button>
|
||||
</div>
|
||||
|
||||
{{if $n.CanTest}}
|
||||
<div class="col-sm-12">
|
||||
<button class="btn btn-secondary btn-block text-capitalize">Test</button>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
</div>
|
||||
|
||||
{{if $n.Author}}
|
||||
<span class="d-block small text-center">
|
||||
<span class="d-block small text-center mt-3 mb-5">
|
||||
{{$n.Title}} Notifier created by <a href="{{$n.AuthorUrl}}" target="_blank">{{$n.Author}}</a>
|
||||
</span>
|
||||
{{ end }}
|
||||
</form>
|
||||
|
||||
{{ if $n.Logs }}
|
||||
Sent {{$n.SentLastHour}} out of {{$n.Limit}} in the last hour<br>
|
||||
Sent {{$n.SentLastHour}} in the last hour<br>
|
||||
{{ range $n.Logs }}
|
||||
<div class="card mt-1">
|
||||
<div class="card-body">
|
||||
|
|
Loading…
Reference in New Issue