├── .gitignore ├── CHANGELOG.md ├── Gemfile ├── MIT-LICENSE.txt ├── README.md ├── Rakefile ├── bin └── sensu-dashboard ├── lib ├── sensu-dashboard.rb └── sensu-dashboard │ ├── assets │ ├── javascripts │ │ ├── app.js │ │ ├── application.coffee │ │ ├── bootstrapper.coffee │ │ ├── collections │ │ │ ├── base.coffee │ │ │ ├── checks.coffee │ │ │ ├── clients.coffee │ │ │ ├── events.coffee │ │ │ └── stashes.coffee │ │ ├── config │ │ │ └── states.coffee │ │ ├── handlebars_helpers.coffee │ │ ├── libs │ │ │ ├── backbone-min.js │ │ │ ├── bootstrap.min.js │ │ │ ├── jquery-1.9.1.min.js │ │ │ ├── liquid.metal.js │ │ │ ├── lodash.underscore.min.js │ │ │ ├── retina.js │ │ │ ├── scroll.into.view.js │ │ │ ├── toastr.min.js │ │ │ └── token.field.coffee │ │ ├── matcher.coffee │ │ ├── models │ │ │ ├── check.coffee │ │ │ ├── client.coffee │ │ │ ├── event.coffee │ │ │ ├── info.coffee │ │ │ ├── metadata │ │ │ │ └── events.coffee │ │ │ └── stash.coffee │ │ ├── namespace.coffee │ │ ├── state.coffee │ │ ├── state_manager.coffee │ │ ├── states │ │ │ └── main_state.coffee │ │ ├── templates │ │ │ ├── autocomplete │ │ │ │ ├── results_check_item.hbs │ │ │ │ ├── results_check_token.hbs │ │ │ │ ├── results_client_item.hbs │ │ │ │ ├── results_client_token.hbs │ │ │ │ ├── results_query_item.hbs │ │ │ │ └── results_query_token.hbs │ │ │ ├── checks │ │ │ │ ├── index.hbs │ │ │ │ ├── list.hbs │ │ │ │ └── list_item.hbs │ │ │ ├── clients │ │ │ │ ├── counts.hbs │ │ │ │ ├── index.hbs │ │ │ │ ├── list.hbs │ │ │ │ ├── list_item.hbs │ │ │ │ └── modal.hbs │ │ │ ├── empty_list.hbs │ │ │ ├── error.hbs │ │ │ ├── events │ │ │ │ ├── counts.hbs │ │ │ │ ├── index.hbs │ │ │ │ ├── list.hbs │ │ │ │ ├── list_item.hbs │ │ │ │ └── modal.hbs │ │ │ ├── info │ │ │ │ └── index.hbs │ │ │ ├── modal.hbs │ │ │ └── stashes │ │ │ │ ├── counts.hbs │ │ │ │ ├── index.hbs │ │ │ │ ├── list.hbs │ │ │ │ ├── list_item.hbs │ │ │ │ └── modal.hbs │ │ └── views │ │ │ ├── auto_complete │ │ │ ├── auto_complete_field.coffee │ │ │ ├── auto_complete_results.coffee │ │ │ └── auto_complete_token.coffee │ │ │ ├── base.coffee │ │ │ ├── checks │ │ │ ├── index.coffee │ │ │ ├── list.coffee │ │ │ └── list_item.coffee │ │ │ ├── clients │ │ │ ├── counts.coffee │ │ │ ├── index.coffee │ │ │ ├── list.coffee │ │ │ ├── list_item.coffee │ │ │ └── modal.coffee │ │ │ ├── error.coffee │ │ │ ├── events │ │ │ ├── counts.coffee │ │ │ ├── index.coffee │ │ │ ├── list.coffee │ │ │ ├── list_item.coffee │ │ │ └── modal.coffee │ │ │ ├── info │ │ │ └── index.coffee │ │ │ ├── list.coffee │ │ │ ├── list_item.coffee │ │ │ ├── modal.coffee │ │ │ └── stashes │ │ │ ├── counts.coffee │ │ │ ├── index.coffee │ │ │ ├── list.coffee │ │ │ ├── list_item.coffee │ │ │ └── modal.coffee │ └── stylesheets │ │ ├── app.css │ │ ├── libs │ │ ├── bootstrap.min.css │ │ ├── font-awesome.less │ │ └── toastr.min.css │ │ └── main.sass │ ├── constants.rb │ ├── public │ ├── favicon.ico │ ├── font │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ └── fontawesome-webfont.woff │ └── img │ │ ├── favicon_114.png │ │ ├── favicon_144.png │ │ ├── favicon_57.png │ │ ├── favicon_64.png │ │ ├── favicon_72.png │ │ ├── glyphicons-halflings-white.png │ │ ├── glyphicons-halflings.png │ │ ├── loading.gif │ │ ├── logo.png │ │ └── logo@2x.png │ ├── server.rb │ └── views │ ├── layout.slim │ └── main.slim └── sensu-dashboard.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .sass-cache/ 3 | .gem 4 | .bundle 5 | Gemfile.lock 6 | pkg/* 7 | vendor 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sensu/sensu-dashboard/7634eed1cddf652219cf84fdefdaa4013e7c682f/CHANGELOG.md -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Specify your gem's dependencies in sensu-dashboard.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Sonian Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![sensu](https://raw.github.com/sensu/sensu/master/sensu-logo.png) 2 | 3 | A front-end dashboard for the Sensu monitoring framework. 4 | 5 | [![Join the chat at https://slack.sensu.io/](https://slack.sensu.io/badge.svg)](https://slack.sensu.io/) 6 | 7 | :warning: **ANNOUNCEMENT - Sensu 1.x has reached End-Of-Life (December 31st, 2019)** 8 | 9 | The Sensu 1.x project reached end-of-life on December 31st, 2019. The 10 | existing package repositories became unreachable on January 6th, 2020. 11 | Please see our blog post for more details: 12 | https://blog.sensu.io/announcing-the-sensu-archives 13 | 14 | Sensu 1.x has been superseded by [Sensu Go](https://github.com/sensu/sensu-go). 15 | 16 | As always, we want to hear from the Community and please reach out on 17 | Slack or Discourse if you have any questions or concerns. 18 | 19 | ## Documentation 20 | Please refer to the Sensu documentation on [sensuapp.org/docs](http://sensuapp.org/docs) for more information. 21 | 22 | ## License 23 | Sensu is released under the [MIT license](https://raw.github.com/sensu/sensu-dashboard/master/MIT-LICENSE.txt). 24 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | -------------------------------------------------------------------------------- /bin/sensu-dashboard: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | unless $:.include?(File.dirname(__FILE__) + '/../lib/') 4 | $: << File.dirname(__FILE__) + '/../lib' 5 | end 6 | 7 | require 'sensu-dashboard/server' 8 | 9 | options = Sensu::CLI.read 10 | Sensu::Dashboard::Server.run(options) 11 | -------------------------------------------------------------------------------- /lib/sensu-dashboard.rb: -------------------------------------------------------------------------------- 1 | module Sensu 2 | # A front-end dashboard for the Sensu monitoring framework. 3 | end 4 | -------------------------------------------------------------------------------- /lib/sensu-dashboard/assets/javascripts/app.js: -------------------------------------------------------------------------------- 1 | //= require ./libs/jquery-1.9.1.min.js 2 | //= require ./libs/lodash.underscore.min.js 3 | //= require ./libs/backbone-min.js 4 | //= require ./libs/bootstrap.min.js 5 | //= require ./libs/retina.js 6 | //= require ./libs/toastr.min.js 7 | //= require ./libs/liquid.metal.js 8 | //= require ./libs/scroll.into.view.js 9 | //= require ./libs/token.field 10 | 11 | //= require handlebars.runtime 12 | //= require handlebars_helpers 13 | //= require_tree ./templates 14 | 15 | //= require namespace 16 | 17 | //= require_directory ./models 18 | 19 | //= require_tree ./collections 20 | 21 | //= require_directory ./models/metadata 22 | 23 | //= require_directory ./views 24 | //= require_tree ./views/auto_complete 25 | //= require_tree ./views/clients 26 | //= require_tree ./views/events 27 | //= require_tree ./views/stashes 28 | //= require_tree ./views/info 29 | //= require_tree ./views/checks 30 | 31 | //= require state_manager 32 | //= require state 33 | //= require_tree ./states 34 | //= require_tree ./config 35 | 36 | //= require matcher 37 | //= require bootstrapper 38 | //= require application 39 | -------------------------------------------------------------------------------- /lib/sensu-dashboard/assets/javascripts/application.coffee: -------------------------------------------------------------------------------- 1 | namespace "SensuDashboard", (exports) -> 2 | 3 | class Application 4 | 5 | constructor: -> 6 | $.ajaxSetup(cache: false) 7 | 8 | bootstrapper = new SensuDashboard.Bootstrapper 9 | success: => 10 | @boot() 11 | 12 | error: => 13 | new SensuDashboard.Views.Error 14 | toastr.error("Error during bootstrap. Is Sensu API running?" 15 | , "Bootstrap Error" 16 | , { positionClass: "toast-bottom-right" }) 17 | 18 | boot: -> 19 | Backbone.history.start() 20 | 21 | exports.App = new Application() # Initialize app 22 | -------------------------------------------------------------------------------- /lib/sensu-dashboard/assets/javascripts/bootstrapper.coffee: -------------------------------------------------------------------------------- 1 | namespace "SensuDashboard", (exports) -> 2 | 3 | class exports.Bootstrapper 4 | 5 | constructor: (options = {}) -> 6 | @successCallback = options.success 7 | @errorCallback = options.error 8 | 9 | try 10 | $.ajax 11 | type: "GET" 12 | url: "/all" 13 | context: this 14 | dataType: "json" 15 | success: (data, textStatus, jqXHR) -> 16 | SensuDashboard.PollFrequency = data.info.sensu_dashboard.poll_frequency 17 | SensuDashboard.Stashes = new SensuDashboard.Collections.Stashes(data.stashes) 18 | SensuDashboard.Events = new SensuDashboard.Collections.Events(data.events) 19 | SensuDashboard.Clients = new SensuDashboard.Collections.Clients(data.clients) 20 | SensuDashboard.Checks = new SensuDashboard.Collections.Checks(data.checks) 21 | SensuDashboard.EventsMetadata = new SensuDashboard.Models.Metadata.Events 22 | SensuDashboard.Info = new SensuDashboard.Models.Info(data.info) 23 | 24 | SensuDashboard.Stashes.startLongPolling(SensuDashboard.PollFrequency) 25 | SensuDashboard.Events.startLongPolling(SensuDashboard.PollFrequency) 26 | SensuDashboard.Clients.startLongPolling(SensuDashboard.PollFrequency) 27 | SensuDashboard.Checks.startLongPolling(SensuDashboard.PollFrequency) 28 | SensuDashboard.Info.startLongPolling(SensuDashboard.PollFrequency) 29 | 30 | @successCallback.call(this) 31 | error: (jqXHR, textStatus, errorThrown) -> 32 | @error() 33 | 34 | catch error 35 | @error() 36 | 37 | error: -> 38 | @errorCallback.call(this) 39 | return 40 | -------------------------------------------------------------------------------- /lib/sensu-dashboard/assets/javascripts/collections/base.coffee: -------------------------------------------------------------------------------- 1 | namespace "SensuDashboard.Collections", (exports) -> 2 | 3 | class exports.Base extends Backbone.Collection 4 | longPolling: false 5 | 6 | intervalSeconds: 10 7 | 8 | startLongPolling: (intervalSeconds) => 9 | @longPolling = true 10 | @intervalSeconds = intervalSeconds if intervalSeconds 11 | @executeLongPolling() 12 | 13 | stopLongPolling: => 14 | @longPolling = false 15 | 16 | executeLongPolling: => 17 | @fetch 18 | success: => 19 | @onFetch() 20 | 21 | onFetch: => 22 | setTimeout(@executeLongPolling, 1000 * @intervalSeconds) if @longPolling 23 | -------------------------------------------------------------------------------- /lib/sensu-dashboard/assets/javascripts/collections/checks.coffee: -------------------------------------------------------------------------------- 1 | namespace "SensuDashboard.Collections", (exports) -> 2 | 3 | class exports.Checks extends SensuDashboard.Collections.Base 4 | model: SensuDashboard.Models.Check, 5 | url: "/checks" 6 | 7 | comparator: (event) -> 8 | event.get "name" 9 | -------------------------------------------------------------------------------- /lib/sensu-dashboard/assets/javascripts/collections/clients.coffee: -------------------------------------------------------------------------------- 1 | namespace "SensuDashboard.Collections", (exports) -> 2 | 3 | class exports.Clients extends SensuDashboard.Collections.Base 4 | model: SensuDashboard.Models.Client, 5 | url: "/clients" 6 | 7 | comparator: (event) -> 8 | event.get("name") 9 | 10 | getSelected: -> 11 | @where(selected: true) 12 | 13 | toggleSelected: -> 14 | selected = true 15 | selected = false if @getSelected().length == @length 16 | @each (client) -> 17 | client.set(selected: selected) 18 | 19 | getSilenced: -> 20 | @where(silenced: true) 21 | 22 | getUnsilenced: -> 23 | @where(silenced: false) 24 | 25 | getSelectedSilenced: -> 26 | @where(silenced: true, selected: true) 27 | 28 | getSelectedUnsilenced: -> 29 | @where(silenced: false, selected: true) 30 | 31 | selectAll: -> 32 | @each (client) -> 33 | client.set(selected: true) 34 | 35 | selectNone: -> 36 | @each (client) -> 37 | client.set(selected: false) 38 | 39 | selectSilenced: -> 40 | clients = @getSilenced() 41 | clients_selected = @getSelectedSilenced() 42 | for client in clients 43 | selected = true 44 | selected = false if clients_selected.length == clients.length 45 | client.set(selected: selected) 46 | 47 | selectUnsilenced: -> 48 | clients = @getUnsilenced() 49 | clients_selected = @getSelectedUnsilenced() 50 | for client in clients 51 | selected = true 52 | selected = false if clients_selected.length == clients.length 53 | client.set(selected: selected) 54 | 55 | silenceSelected: (options = {}) -> 56 | @successCallback = options.success 57 | @errorCallback = options.error 58 | for client in @getSelected() 59 | client.silence 60 | success: (model, response, opts) => 61 | @successCallback.call(this, model) if @successCallback 62 | error: (model, xhr, opts) => 63 | @errorCallback.call(this, model) if @errorCallback 64 | 65 | unsilenceSelected: (options = {}) -> 66 | @successCallback = options.success 67 | @errorCallback = options.error 68 | for client in @getSelected() 69 | client.unsilence 70 | success: (model, xhr, opts) => 71 | @successCallback.call(this, model) if @successCallback 72 | error: (model, xhr, opts) => 73 | @errorCallback.call(this, model) if @errorCallback 74 | 75 | removeSelected: (options = {}) -> 76 | @successCallback = options.success 77 | @errorCallback = options.error 78 | for client in @getSelected() 79 | client.remove 80 | success: (model, response, opts) => 81 | @successCallback.call(this, model) if @successCallback 82 | error: (model, xhr, opts) => 83 | @errorCallback.call(this, model) if @errorCallback 84 | -------------------------------------------------------------------------------- /lib/sensu-dashboard/assets/javascripts/collections/events.coffee: -------------------------------------------------------------------------------- 1 | namespace "SensuDashboard.Collections", (exports) -> 2 | 3 | class exports.Events extends SensuDashboard.Collections.Base 4 | model: SensuDashboard.Models.Event, 5 | url: "/events" 6 | 7 | comparator: (event) -> 8 | event.get("status_name") 9 | 10 | getSelected: -> 11 | @where(selected: true) 12 | 13 | getSelectedClients: -> 14 | _.map(@getSelected(), (event) -> event.get("client")) 15 | 16 | getUniqueSelectedClients: -> 17 | clients = _.uniq(@getSelectedClients()) 18 | 19 | getCriticals: -> 20 | @where(status: 2) 21 | 22 | getUnknowns: -> 23 | @filter (event) -> 24 | status = event.get("status") 25 | return status != 1 && status != 2 26 | 27 | getWarnings: -> 28 | @where(status: 1) 29 | 30 | getSilenced: -> 31 | @where(silenced: true) 32 | 33 | getSilencedClients: -> 34 | @where(client_silenced: true) 35 | 36 | getUnsilenced: -> 37 | @where(silenced: false) 38 | 39 | getUnsilencedClients: -> 40 | @where(client_silenced: false) 41 | 42 | getSelectedCriticals: -> 43 | @where(status: 2, selected: true) 44 | 45 | getSelectedUnknowns: -> 46 | @filter (event) -> 47 | status = event.get("status") 48 | selected = event.get("selected") 49 | return status != 1 && status != 2 && selected == true 50 | 51 | getSelectedWarnings: -> 52 | @where(status: 1, selected: true) 53 | 54 | getSelectedSilenced: -> 55 | @where(silenced: true, selected: true) 56 | 57 | getSelectedSilencedClients: -> 58 | @where(client_silenced: true, selected: true) 59 | 60 | getSelectedUnsilenced: -> 61 | @where(silenced: false, selected: true) 62 | 63 | getSelectedUnsilencedClients: -> 64 | @where(client_silenced: false, selected: true) 65 | 66 | toggleSelected: -> 67 | selected = true 68 | selected = false if @getSelected().length == @length 69 | @each (event) -> 70 | event.set(selected: selected) 71 | 72 | selectAll: -> 73 | @each (event) -> 74 | event.set(selected: true) 75 | 76 | selectNone: -> 77 | @each (event) -> 78 | event.set(selected: false) 79 | 80 | selectCritical: -> 81 | events = @getCriticals() 82 | events_selected = @getSelectedCriticals() 83 | for event in events 84 | selected = true 85 | selected = false if events_selected.length == events.length 86 | event.set(selected: selected) 87 | 88 | selectUnknown: -> 89 | events = @getUnknowns() 90 | events_selected = @getSelectedUnknowns() 91 | for event in events 92 | selected = true 93 | selected = false if events_selected.length == events.length 94 | event.set(selected: selected) 95 | 96 | selectWarning: -> 97 | events = @getWarnings() 98 | events_selected = @getSelectedWarnings() 99 | for event in events 100 | selected = true 101 | selected = false if events_selected.length == events.length 102 | event.set(selected: selected) 103 | 104 | selectSilenced: -> 105 | events = @getSilenced() 106 | events_selected = @getSelectedSilenced() 107 | for event in events 108 | selected = true 109 | selected = false if events_selected.length == events.length 110 | event.set(selected: selected) 111 | 112 | selectSilencedClients: -> 113 | events = @getSilencedClients() 114 | events_selected = @getSelectedSilencedClients() 115 | for event in events 116 | selected = true 117 | selected = false if events_selected.length == events.length 118 | event.set(selected: selected) 119 | 120 | selectUnsilenced: -> 121 | events = @getUnsilenced() 122 | events_selected = @getSelectedUnsilenced() 123 | for event in events 124 | selected = true 125 | selected = false if events_selected.length == events.length 126 | event.set(selected: selected) 127 | 128 | selectUnsilencedClients: -> 129 | events = @getUnsilencedClients() 130 | events_selected = @getSelectedUnsilencedClients() 131 | for event in events 132 | selected = true 133 | selected = false if events_selected.length == events.length 134 | event.set(selected: selected) 135 | 136 | resolveSelected: (options = {}) -> 137 | @successCallback = options.success 138 | @errorCallback = options.error 139 | for event in @getSelected() 140 | event.resolve 141 | success: (model, response, opts) => 142 | @successCallback.call(this, model) if @successCallback 143 | error: (model, xhr, opts) => 144 | @errorCallback.call(this, model) if @errorCallback 145 | 146 | silenceSelectedChecks: (options = {}) -> 147 | @successCallback = options.success 148 | @errorCallback = options.error 149 | for event in @getSelected() 150 | event.silence 151 | success: (model, response, opts) => 152 | @successCallback.call(this, model) if @successCallback 153 | error: (model, xhr, opts) => 154 | @errorCallback.call(this, model) if @errorCallback 155 | 156 | unsilenceSelectedChecks: (options = {}) -> 157 | @successCallback = options.success 158 | @errorCallback = options.error 159 | for event in @getSelected() 160 | event.unsilence 161 | success: (model, response, opts) => 162 | @successCallback.call(this, model) if @successCallback 163 | error: (model, xhr, opts) => 164 | @errorCallback.call(this, model) if @errorCallback 165 | 166 | silenceSelectedClients: (options = {}) -> 167 | @successCallback = options.success 168 | @errorCallback = options.error 169 | for client in @getUniqueSelectedClients() 170 | SensuDashboard.Clients.get(client).silence 171 | success: (model, response, opts) => 172 | @successCallback.call(this, model) if @successCallback 173 | error: (model, xhr, opts) => 174 | @errorCallback.call(this, model) if @errorCallback 175 | 176 | unsilenceSelectedClients: (options = {}) -> 177 | @successCallback = options.success 178 | @errorCallback = options.error 179 | for client in @getUniqueSelectedClients() 180 | SensuDashboard.Clients.get(client).unsilence 181 | success: (model, response, opts) => 182 | @successCallback.call(this, model) if @successCallback 183 | error: (model, xhr, opts) => 184 | @errorCallback.call(this, model) if @errorCallback 185 | -------------------------------------------------------------------------------- /lib/sensu-dashboard/assets/javascripts/collections/stashes.coffee: -------------------------------------------------------------------------------- 1 | namespace "SensuDashboard.Collections", (exports) -> 2 | 3 | class exports.Stashes extends SensuDashboard.Collections.Base 4 | model: SensuDashboard.Models.Stash, 5 | url: "/stashes" 6 | 7 | getSelected: -> 8 | @where(selected: true) 9 | 10 | toggleSelected: -> 11 | selected = true 12 | selected = false if @getSelected().length == @length 13 | @each (stash) -> 14 | stash.set(selected: selected) 15 | 16 | selectAll: -> 17 | @each (stash) -> 18 | stash.set(selected: true) 19 | 20 | selectNone: -> 21 | @each (stash) -> 22 | stash.set(selected: false) 23 | 24 | removeSelected: (options = {}) -> 25 | @successCallback = options.success 26 | @errorCallback = options.error 27 | for stash in @getSelected() 28 | stash.remove 29 | success: (model, xhr, opts) => 30 | @successCallback.call(this, model) if @successCallback 31 | error: (model, xhr, opts) => 32 | @errorCallback.call(this, model) if @errorCallback 33 | 34 | create: (attributes, options) -> 35 | options ||= {} 36 | options.wait = true 37 | Backbone.Collection.prototype.create.call(this, attributes, options) 38 | -------------------------------------------------------------------------------- /lib/sensu-dashboard/assets/javascripts/config/states.coffee: -------------------------------------------------------------------------------- 1 | namespace "SensuDashboard", (exports) -> 2 | 3 | exports.States = new exports.StateManager { 4 | 5 | events: class extends exports.MainState 6 | route: "events" 7 | view: (opts) -> 8 | new SensuDashboard.Views.Events.Index(model: SensuDashboard.EventsMetadata) 9 | 10 | clients: class extends exports.MainState 11 | route: "clients" 12 | view: (opts) -> 13 | new SensuDashboard.Views.Clients.Index(collection: SensuDashboard.Clients) 14 | 15 | stashes: class extends exports.MainState 16 | route: "stashes" 17 | view: (opts) -> 18 | new SensuDashboard.Views.Stashes.Index(collection: SensuDashboard.Stashes) 19 | 20 | checks: class extends exports.MainState 21 | route: "checks" 22 | view: (opts) -> 23 | new SensuDashboard.Views.Checks.Index(collection: SensuDashboard.Checks) 24 | 25 | info: class extends exports.MainState 26 | route: "info" 27 | view: (opts) -> 28 | new SensuDashboard.Views.Info.Index(model: SensuDashboard.Info) 29 | 30 | }, "events" 31 | -------------------------------------------------------------------------------- /lib/sensu-dashboard/assets/javascripts/handlebars_helpers.coffee: -------------------------------------------------------------------------------- 1 | Handlebars.registerHelper "selected", (selected) -> 2 | return if selected then "checked" else "" 3 | 4 | Handlebars.registerHelper "truncate", (text, length) -> 5 | truncated = text.substring(0, length) 6 | if text.length > length 7 | truncated = truncated + "..." 8 | return truncated 9 | 10 | Handlebars.registerHelper "strip", (text) -> 11 | return text.toString().replace(/^\s\s*/, '').replace(/\s\s*$/, '') 12 | 13 | Handlebars.registerHelper "linkify", (text) -> 14 | exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig 15 | return text.toString().replace(exp,"$1") 16 | 17 | Handlebars.registerHelper "modalValue", (key, text) -> 18 | text = Handlebars.helpers.formatTimestamp(text) if key in ["issued", "timestamp"] 19 | linkified = Handlebars.helpers.linkify(text) 20 | return Handlebars.helpers.strip(linkified) 21 | 22 | Handlebars.registerHelper "formatTimestamp", (text) -> 23 | date = new Date(text*1000) 24 | return date.toISOString() 25 | -------------------------------------------------------------------------------- /lib/sensu-dashboard/assets/javascripts/libs/backbone-min.js: -------------------------------------------------------------------------------- 1 | (function(){var t=this;var e=t.Backbone;var i=[];var r=i.push;var s=i.slice;var n=i.splice;var a;if(typeof exports!=="undefined"){a=exports}else{a=t.Backbone={}}a.VERSION="1.0.0";var h=t._;if(!h&&typeof require!=="undefined")h=require("underscore");a.$=t.jQuery||t.Zepto||t.ender||t.$;a.noConflict=function(){t.Backbone=e;return this};a.emulateHTTP=false;a.emulateJSON=false;var o=a.Events={on:function(t,e,i){if(!l(this,"on",t,[e,i])||!e)return this;this._events||(this._events={});var r=this._events[t]||(this._events[t]=[]);r.push({callback:e,context:i,ctx:i||this});return this},once:function(t,e,i){if(!l(this,"once",t,[e,i])||!e)return this;var r=this;var s=h.once(function(){r.off(t,s);e.apply(this,arguments)});s._callback=e;return this.on(t,s,i)},off:function(t,e,i){var r,s,n,a,o,u,c,f;if(!this._events||!l(this,"off",t,[e,i]))return this;if(!t&&!e&&!i){this._events={};return this}a=t?[t]:h.keys(this._events);for(o=0,u=a.length;o").attr(t);this.setElement(e,false)}else{this.setElement(h.result(this,"el"),false)}}});a.sync=function(t,e,i){var r=k[t];h.defaults(i||(i={}),{emulateHTTP:a.emulateHTTP,emulateJSON:a.emulateJSON});var s={type:r,dataType:"json"};if(!i.url){s.url=h.result(e,"url")||U()}if(i.data==null&&e&&(t==="create"||t==="update"||t==="patch")){s.contentType="application/json";s.data=JSON.stringify(i.attrs||e.toJSON(i))}if(i.emulateJSON){s.contentType="application/x-www-form-urlencoded";s.data=s.data?{model:s.data}:{}}if(i.emulateHTTP&&(r==="PUT"||r==="DELETE"||r==="PATCH")){s.type="POST";if(i.emulateJSON)s.data._method=r;var n=i.beforeSend;i.beforeSend=function(t){t.setRequestHeader("X-HTTP-Method-Override",r);if(n)return n.apply(this,arguments)}}if(s.type!=="GET"&&!i.emulateJSON){s.processData=false}if(s.type==="PATCH"&&window.ActiveXObject&&!(window.external&&window.external.msActiveXFilteringEnabled)){s.xhr=function(){return new ActiveXObject("Microsoft.XMLHTTP")}}var o=i.xhr=a.ajax(h.extend(s,i));e.trigger("request",e,o,i);return o};var k={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};a.ajax=function(){return a.$.ajax.apply(a.$,arguments)};var S=a.Router=function(t){t||(t={});if(t.routes)this.routes=t.routes;this._bindRoutes();this.initialize.apply(this,arguments)};var $=/\((.*?)\)/g;var T=/(\(\?)?:\w+/g;var H=/\*\w+/g;var A=/[\-{}\[\]+?.,\\\^$|#\s]/g;h.extend(S.prototype,o,{initialize:function(){},route:function(t,e,i){if(!h.isRegExp(t))t=this._routeToRegExp(t);if(h.isFunction(e)){i=e;e=""}if(!i)i=this[e];var r=this;a.history.route(t,function(s){var n=r._extractParameters(t,s);i&&i.apply(r,n);r.trigger.apply(r,["route:"+e].concat(n));r.trigger("route",e,n);a.history.trigger("route",r,e,n)});return this},navigate:function(t,e){a.history.navigate(t,e);return this},_bindRoutes:function(){if(!this.routes)return;this.routes=h.result(this,"routes");var t,e=h.keys(this.routes);while((t=e.pop())!=null){this.route(t,this.routes[t])}},_routeToRegExp:function(t){t=t.replace(A,"\\$&").replace($,"(?:$1)?").replace(T,function(t,e){return e?t:"([^/]+)"}).replace(H,"(.*?)");return new RegExp("^"+t+"$")},_extractParameters:function(t,e){var i=t.exec(e).slice(1);return h.map(i,function(t){return t?decodeURIComponent(t):null})}});var I=a.History=function(){this.handlers=[];h.bindAll(this,"checkUrl");if(typeof window!=="undefined"){this.location=window.location;this.history=window.history}};var N=/^[#\/]|\s+$/g;var P=/^\/+|\/+$/g;var O=/msie [\w.]+/;var C=/\/$/;I.started=false;h.extend(I.prototype,o,{interval:50,getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:""},getFragment:function(t,e){if(t==null){if(this._hasPushState||!this._wantsHashChange||e){t=this.location.pathname;var i=this.root.replace(C,"");if(!t.indexOf(i))t=t.substr(i.length)}else{t=this.getHash()}}return t.replace(N,"")},start:function(t){if(I.started)throw new Error("Backbone.history has already been started");I.started=true;this.options=h.extend({},{root:"/"},this.options,t);this.root=this.options.root;this._wantsHashChange=this.options.hashChange!==false;this._wantsPushState=!!this.options.pushState;this._hasPushState=!!(this.options.pushState&&this.history&&this.history.pushState);var e=this.getFragment();var i=document.documentMode;var r=O.exec(navigator.userAgent.toLowerCase())&&(!i||i<=7);this.root=("/"+this.root+"/").replace(P,"/");if(r&&this._wantsHashChange){this.iframe=a.$('