sensu-dashboard-sonian 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +4 -0
  3. data/MIT-LICENSE.txt +20 -0
  4. data/README.org +4 -0
  5. data/Rakefile +1 -0
  6. data/bin/sensu-dashboard +9 -0
  7. data/lib/sensu-dashboard/app.rb +449 -0
  8. data/lib/sensu-dashboard/public/css/autoSuggest.css +217 -0
  9. data/lib/sensu-dashboard/public/css/style.css +177 -0
  10. data/lib/sensu-dashboard/public/img/cross.png +0 -0
  11. data/lib/sensu-dashboard/public/img/footer_bg.png +0 -0
  12. data/lib/sensu-dashboard/public/img/header_bg.png +0 -0
  13. data/lib/sensu-dashboard/public/img/loading_circle.gif +0 -0
  14. data/lib/sensu-dashboard/public/img/main_content_bg.png +0 -0
  15. data/lib/sensu-dashboard/public/img/megaphone_icon.png +0 -0
  16. data/lib/sensu-dashboard/public/img/megaphone_icon_off.png +0 -0
  17. data/lib/sensu-dashboard/public/js/FABridge.js +604 -0
  18. data/lib/sensu-dashboard/public/js/functions.js +379 -0
  19. data/lib/sensu-dashboard/public/js/jquery-1.5.1.min.js +16 -0
  20. data/lib/sensu-dashboard/public/js/jquery.autoSuggest.js +375 -0
  21. data/lib/sensu-dashboard/public/js/jquery.leanModal.min.js +1 -0
  22. data/lib/sensu-dashboard/public/js/jquery.sortElements.js +69 -0
  23. data/lib/sensu-dashboard/public/js/jquery.tmpl.min.js +1 -0
  24. data/lib/sensu-dashboard/public/js/jquery.zclip.min.js +12 -0
  25. data/lib/sensu-dashboard/public/js/modernizr-1.7.min.js +2 -0
  26. data/lib/sensu-dashboard/public/js/swfobject.js +4 -0
  27. data/lib/sensu-dashboard/public/js/web_socket.js +312 -0
  28. data/lib/sensu-dashboard/public/js/webtoolkit.sha1.js +174 -0
  29. data/lib/sensu-dashboard/public/swf/WebSocketMain.swf +0 -0
  30. data/lib/sensu-dashboard/public/swf/ZeroClipboard.swf +0 -0
  31. data/lib/sensu-dashboard/version.rb +5 -0
  32. data/lib/sensu-dashboard/views/client_templates.erb +68 -0
  33. data/lib/sensu-dashboard/views/clients.erb +37 -0
  34. data/lib/sensu-dashboard/views/event_templates.erb +190 -0
  35. data/lib/sensu-dashboard/views/index.erb +48 -0
  36. data/lib/sensu-dashboard/views/layout.erb +124 -0
  37. data/lib/sensu-dashboard/views/sonian.sass +213 -0
  38. data/lib/sensu-dashboard/views/stash_templates.erb +44 -0
  39. data/lib/sensu-dashboard/views/stashes.erb +32 -0
  40. data/sensu-dashboard.gemspec +22 -0
  41. metadata +166 -0
@@ -0,0 +1,5 @@
1
+ module Sensu
2
+ module Dashboard
3
+ VERSION = "0.9.3"
4
+ end
5
+ end
@@ -0,0 +1,68 @@
1
+ <!-- Client template -->
2
+ <script id="clientTemplate" type="text/x-jquery-tmpl">
3
+ <tr id="${name}" rel="leanModal" href="#event_details_modal">
4
+ <td id="client_id">${name}</td>
5
+ <td id="environment">${environment}</td>
6
+ <td id="public_ip">${address}</td>
7
+ <td id="timestamp">${timestamp}</td>
8
+ <td id="subscriptions">${subscriptions}</td>
9
+ </tr>
10
+ </script>
11
+
12
+ <!-- Client details row template -->
13
+ <script id="clientDetailsRowTemplate" type="text/x-jquery-tmpl">
14
+ {{each $data}}
15
+ <div class="event_detail_group">
16
+ <div class="event_detail">
17
+ <h1>${capitaliseFirstLetter($index)}</h1>
18
+ <p id="${$index}">${$value}</p>
19
+ </div>
20
+ <!--<div class="copy">Copy</div>-->
21
+ <div style="clear: both;"></div>
22
+ </div>
23
+ {{/each}}
24
+ </script>
25
+
26
+ <script type="text/javascript">
27
+ fetchClients();
28
+
29
+ ws = new WebSocket("ws://" + location.hostname + ":9000");
30
+ ws.onmessage = function(evt) {
31
+ fetchClients();
32
+ }
33
+
34
+ $("#remove_client").click(function() {
35
+ var client = $("#name").html();
36
+ var cross_img = $("#remove_client").children().first();
37
+ cross_img.attr("src", "/img/loading_circle.gif");
38
+ $.ajax({
39
+ type: 'DELETE',
40
+ contentType: 'application/json',
41
+ url: '/client/'+client+'.json',
42
+ success: function(data, textStatus, xhr) {
43
+ alert('Client '+client+' is being removed, resolving events...');
44
+ cross_img.attr("src", "/img/cross.png");
45
+ $("#lean_overlay").fadeOut(200);
46
+ $("#event_details_modal").css({'display':'none'});
47
+ fetchClients();
48
+ },
49
+ error: function(xhr, textStatus, errorThrown) {
50
+ cross_img.attr("src", "/img/cross.png");
51
+ alert('Client was not found in sensu. This may be due to a delay in a previous removal attempt.');
52
+ }
53
+ });
54
+ });
55
+
56
+ $("input[type=text]").autoSuggest("http://" + location.hostname + ":" + location.port + "/clients/autocomplete.json", {
57
+ startText: "Enter keywords to filter by",
58
+ selectedItemProp: "name",
59
+ searchObjProps: "name",
60
+ selectionAdded: function(elem) {
61
+ fetchClients();
62
+ },
63
+ selectionRemoved: function(elem) {
64
+ elem.fadeTo("fast", 0, function() { elem.remove(); });
65
+ fetchClients();
66
+ }
67
+ });
68
+ </script>
@@ -0,0 +1,37 @@
1
+ <h1>Current Clients <span class="clients_count">(<span id="client_count">0</span>)</span></h1>
2
+
3
+ <input type="text" id="autosuggest_filter" style="width: 300px;"/>
4
+
5
+ <table id="clients">
6
+
7
+ <thead>
8
+
9
+ <tr>
10
+ <th class="col_clients">Client</th>
11
+ <th class="col_environment">Environment</th>
12
+ <th class="col_public_ip">Public IP</th>
13
+ <th class="col_timestamp">Timestamp</th>
14
+ <th class="col_output">Subscriptions</th>
15
+ </tr>
16
+
17
+ </thead>
18
+
19
+ <tbody></tbody>
20
+
21
+ </table>
22
+
23
+ <div id="event_details_modal" class="event_details_modal">
24
+ <h1 class="section_title">Actions</h1>
25
+ <div id="event_actions">
26
+ <div class="event_detail_group">
27
+ <div class="event_detail">
28
+ <div id="remove_client" class="action_btn" style="margin-right: 7px;">
29
+ <img src="/img/cross.png" style="vertical-align: middle; padding-right: 7px;"/><strong>Remove</strong>
30
+ </div>
31
+ </div>
32
+ <div style="clear: both;"></div>
33
+ </div>
34
+ </div>
35
+ <h1 class="section_title">Client Data</h1>
36
+ <div id="client_data"></div>
37
+ </div>
@@ -0,0 +1,190 @@
1
+ <!-- Event template -->
2
+ <script id="eventTemplate" type="text/x-jquery-tmpl">
3
+ {{if is_unknown}}
4
+ <tr class="status3" id="${identifier}" rel="leanModal" href="#event_details_modal">
5
+ {{else}}
6
+ <tr class="status${status}" id="${identifier}" rel="leanModal" href="#event_details_modal">
7
+ {{/if}}
8
+ <td id="client">${client}</td>
9
+ <td id="check">${check}</td>
10
+ <td id="environment">${environment}</td>
11
+ <td id="output">${output}</td>
12
+ </tr>
13
+ </script>
14
+
15
+ <!-- Event details row template -->
16
+ <script id="eventDetailsRowTemplate" type="text/x-jquery-tmpl">
17
+ <div class="event_detail_group">
18
+ <div class="event_detail">
19
+ <h1>Client</h1>
20
+ <p id="client_id_value">${client}</p>
21
+ </div>
22
+ <!--<div class="copy">Copy</div>-->
23
+ <div style="clear: both;"></div>
24
+ </div>
25
+ <div class="event_detail_group">
26
+ <div class="event_detail">
27
+ <h1>Check</h1>
28
+ <p id="check_name_value">${check}</p>
29
+ </div>
30
+ <!--<div class="copy">Copy</div>-->
31
+ <div style="clear: both;"></div>
32
+ </div>
33
+ <div class="event_detail_group">
34
+ <div class="event_detail">
35
+ <h1>Status</h1>
36
+ <p>${status}</p>
37
+ </div>
38
+ <!--<div class="copy">Copy</div>-->
39
+ <div style="clear: both;"></div>
40
+ </div>
41
+ <div class="event_detail_group">
42
+ <div class="event_detail">
43
+ <h1>Output</h1>
44
+ <p>${output}</p>
45
+ </div>
46
+ <!--<div class="copy">Copy</div>-->
47
+ <div style="clear: both;"></div>
48
+ </div>
49
+ <div class="event_detail_group">
50
+ <div class="event_detail">
51
+ <h1>Occurrences</h1>
52
+ <p>${occurrences}</p>
53
+ </div>
54
+ <!--<div class="copy">Copy</div>-->
55
+ <div style="clear: both;"></div>
56
+ </div>
57
+ </script>
58
+
59
+ <!-- Client details row template -->
60
+ <script id="clientDetailsRowTemplate" type="text/x-jquery-tmpl">
61
+ {{each $data}}
62
+ <div class="event_detail_group">
63
+ <div class="event_detail">
64
+ <h1>${capitaliseFirstLetter($index)}</h1>
65
+ <p>${$value}</p>
66
+ </div>
67
+ <!--<div class="copy">Copy</div>-->
68
+ <div style="clear: both;"></div>
69
+ </div>
70
+ {{/each}}
71
+ </script>
72
+
73
+ <script type="text/javascript">
74
+ fetchEvents();
75
+
76
+ ws = new WebSocket("ws://" + location.hostname + ":9000");
77
+ ws.onmessage = function(evt) {
78
+ fetchEvents();
79
+ }
80
+
81
+ $("#disable_client_alerts").click(function() {
82
+ var client_id = $("#client_id_value").html();
83
+ var alert_img = $("#disable_client_alerts").children().first();
84
+
85
+ if(alert_img.attr("src") == "/img/megaphone_icon_off.png") {
86
+ alert_img.attr("src", "/img/loading_circle.gif");
87
+ $.ajax({
88
+ type: 'DELETE',
89
+ contentType: 'application/json',
90
+ url: '/stash/silence/'+client_id+'.json',
91
+ success: function(data, textStatus, xhr) {
92
+ alert_img.attr("src", "/img/megaphone_icon.png");
93
+ },
94
+ error: function(xhr, textStatus, errorThrown) {
95
+ if(xhr.status == 404) {
96
+ alert_img.attr("src", "/img/megaphone_icon_off.png");
97
+ }
98
+ },
99
+ dataType: 'json'
100
+ });
101
+ } else if(alert_img.attr("src") == "/img/megaphone_icon.png") {
102
+ alert_img.attr("src", "/img/loading_circle.gif");
103
+ $.ajax({
104
+ type: 'POST',
105
+ contentType: 'application/json',
106
+ url: '/stash/silence/'+client_id+'.json',
107
+ success: function(data, textStatus, xhr) {
108
+ alert_img.attr("src", "/img/megaphone_icon_off.png");
109
+ },
110
+ error: function(xhr, textStatus, errorThrown) {
111
+ },
112
+ dataType: 'json'
113
+ });
114
+ }
115
+ });
116
+
117
+ $("#disable_client_check_alerts").click(function() {
118
+ var client_id = $("#client_id_value").html();
119
+ var check_name = $("#check_name_value").html();
120
+ var alert_img = $("#disable_client_check_alerts").children().first();
121
+
122
+ if(alert_img.attr("src") == "/img/megaphone_icon_off.png") {
123
+ alert_img.attr("src", "/img/loading_circle.gif");
124
+ $.ajax({
125
+ type: 'DELETE',
126
+ contentType: 'application/json',
127
+ url: '/stash/silence/'+client_id+'/'+check_name+'.json',
128
+ success: function(data, textStatus, xhr) {
129
+ alert_img.attr("src", "/img/megaphone_icon.png");
130
+ },
131
+ error: function(xhr, textStatus, errorThrown) {
132
+ if(xhr.status == 404) {
133
+ alert_img.attr("src", "/img/megaphone_icon_off.png");
134
+ }
135
+ },
136
+ dataType: 'json'
137
+ });
138
+ } else if(alert_img.attr("src") == "/img/megaphone_icon.png") {
139
+ alert_img.attr("src", "/img/loading_circle.gif");
140
+ $.ajax({
141
+ type: 'POST',
142
+ contentType: 'application/json',
143
+ url: '/stash/silence/'+client_id+'/'+check_name+'.json',
144
+ success: function(data, textStatus, xhr) {
145
+ alert_img.attr("src", "/img/megaphone_icon_off.png");
146
+ },
147
+ error: function(xhr, textStatus, errorThrown) {
148
+ },
149
+ dataType: 'json'
150
+ });
151
+ }
152
+ });
153
+
154
+ $("#resolve_event").click(function() {
155
+ var client = $("#client_id_value").html();
156
+ var check = $("#check_name_value").html();
157
+ $.ajax({
158
+ type: 'POST',
159
+ contentType: 'application/json',
160
+ url: '/event/resolve.json',
161
+ data: JSON.stringify({"client":client, "check":check}),
162
+ success: function(data, textStatus, xhr) {
163
+ $("#lean_overlay").fadeOut(200);
164
+ $("#event_details_modal").css({'display':'none'});
165
+ fetchEvents();
166
+ },
167
+ error: function(xhr, textStatus, errorThrown) {
168
+ alert('Failed to resolve event');
169
+ }
170
+ });
171
+ });
172
+
173
+ $("input[type=text]").autoSuggest("http://" + location.hostname + ":" + location.port + "/autocomplete.json", {
174
+ startText: "Enter keywords to filter by",
175
+ selectedItemProp: "name",
176
+ searchObjProps: "name",
177
+ selectionAdded: function(elem) {
178
+ fetchEvents();
179
+ },
180
+ selectionRemoved: function(elem) {
181
+ elem.fadeTo("fast", 0, function() { elem.remove(); });
182
+ fetchEvents();
183
+ }
184
+ });
185
+
186
+ $('#filter_unknown_checks').change(function() {
187
+ filter_unknown_checks = !filter_unknown_checks;
188
+ fetchEvents();
189
+ });
190
+ </script>
@@ -0,0 +1,48 @@
1
+ <h1>Current Events <span class="events_count">(<span id="event_count">0</span>)</span></h1>
2
+
3
+ <div style="padding-bottom: 7px;">
4
+ <input type="checkbox" checked="checked" id="filter_unknown_checks" style="margin-right: 7px;"/>Filter Unknown Checks
5
+ </div>
6
+
7
+ <input type="text" id="autosuggest_client_filter" style="width: 300px;"/>
8
+
9
+ <table id="events">
10
+
11
+ <thead>
12
+
13
+ <tr>
14
+ <th class="col_clients">Client</th>
15
+ <th class="col_checks">Check</th>
16
+ <th class="col_environment">Environment</th>
17
+ <th class="col_output">Output</th>
18
+ </tr>
19
+
20
+ </thead>
21
+
22
+ <tbody></tbody>
23
+
24
+ </table>
25
+
26
+ <div id="event_details_modal" class="event_details_modal">
27
+ <h1 class="section_title">Actions</h1>
28
+ <div id="event_actions">
29
+ <div class="event_detail_group">
30
+ <div class="event_detail">
31
+ <div id="disable_client_alerts" class="action_btn" style="margin-right: 7px;">
32
+ <img src="/img/loading_circle.gif" style="vertical-align: middle; padding-right: 7px;"/><strong>Client</strong>
33
+ </div>
34
+ <div id="disable_client_check_alerts" class="action_btn" style="margin-right: 7px;">
35
+ <img src="/img/loading_circle.gif" style="vertical-align: middle; padding-right: 7px;"/><strong>Check</strong>
36
+ </div>
37
+ <div id="resolve_event" class="action_btn" style="margin-right: 7px;">
38
+ <img src="/img/cross.png" style="vertical-align: middle; padding-right: 7px;"/><strong>Resolve</strong>
39
+ </div>
40
+ </div>
41
+ <div style="clear: both;"></div>
42
+ </div>
43
+ </div>
44
+ <h1 class="section_title">Event Data</h1>
45
+ <div id="event_data"></div>
46
+ <h1 class="section_title">Client Data</h1>
47
+ <div id="client_data"></div>
48
+ </div>
@@ -0,0 +1,124 @@
1
+ <!doctype html>
2
+
3
+ <!--[if lt IE 7 ]> <html class="ie ie6 no-js" lang="en"> <![endif]-->
4
+ <!--[if IE 7 ]> <html class="ie ie7 no-js" lang="en"> <![endif]-->
5
+ <!--[if IE 8 ]> <html class="ie ie8 no-js" lang="en"> <![endif]-->
6
+ <!--[if IE 9 ]> <html class="ie ie9 no-js" lang="en"> <![endif]-->
7
+ <!--[if gt IE 9]><!--><html class="no-js" lang="en"><!--<![endif]-->
8
+ <!-- the "no-js" class is for Modernizr. -->
9
+
10
+ <head id="www-sitename-com" data-template-set="html5-reset">
11
+
12
+ <meta charset="utf-8">
13
+
14
+ <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame -->
15
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
16
+
17
+ <title>Sensu Dashboard</title>
18
+
19
+ <meta name="author" content="Justin Kolberg">
20
+ <meta name="Copyright" content="Copyright Sonian, Inc. 2011. MIT License.">
21
+
22
+ <!-- Mobile Viewport Fix
23
+ j.mp/mobileviewport & davidbcalhoun.com/2010/viewport-metatag
24
+ device-width : Occupy full width of the screen in its current orientation
25
+ initial-scale = 1.0 retains dimensions instead of zooming out if page height > device height
26
+ maximum-scale = 1.0 retains dimensions instead of zooming in if page width < device width
27
+ -->
28
+ <!-- Uncomment to use; use thoughtfully!
29
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
30
+ -->
31
+
32
+ <!--<link rel="shortcut icon" href="img/favicon.ico">-->
33
+ <!-- This is the traditional favicon.
34
+ - size: 16x16 or 32x32
35
+ - transparency is OK
36
+ - see wikipedia for info on browser support: http://mky.be/favicon/ -->
37
+
38
+ <!--<link rel="apple-touch-icon" href="img/apple-touch-icon.png">-->
39
+ <!-- The is the icon for iOS's Web Clip.
40
+ - size: 57x57 for older iPhones, 72x72 for iPads, 114x114 for iPhone4's retina display (IMHO, just go ahead and use the biggest one)
41
+ - To prevent iOS from applying its styles to the icon name it thusly: apple-touch-icon-precomposed.png
42
+ - Transparency is not recommended (iOS will put a black BG behind the icon) -->
43
+
44
+ <!-- CSS: screen, mobile & print are all in the same file -->
45
+ <link rel="stylesheet" href="css/style.css">
46
+ <link rel="stylesheet" href="css/sonian.css">
47
+ <link rel="stylesheet" href="css/autoSuggest.css">
48
+
49
+ <!-- all our JS is at the bottom of the page, except for Modernizr. -->
50
+ <script src="js/modernizr-1.7.min.js"></script>
51
+
52
+ </head>
53
+
54
+ <body>
55
+
56
+ <div class="wrapper"><!-- not needed? up to you: http://camendesign.com/code/developpeurs_sans_frontieres -->
57
+
58
+ <header>
59
+
60
+ <h1><a href="/">Sensu Dashboard</a></h1>
61
+
62
+ <nav>
63
+
64
+ <ol>
65
+ <li><a href="/clients">Clients</a></li>
66
+ <li><a href="/stashes">Stashes</a></li>
67
+ <li><a href="/">Current Events</a></li>
68
+ </ol>
69
+
70
+ </nav>
71
+
72
+ <div style="clear: both;"></div>
73
+
74
+ </header>
75
+
76
+ <section id="main_content">
77
+
78
+ <%= yield %>
79
+
80
+ </section>
81
+
82
+ <footer>
83
+
84
+ <p><small>&copy;
85
+ Copyright <a href="http://www.sonian.com">Sonian, Inc.</a> 2011.
86
+ <a href="https://github.com/sonian/sensu-dashboard/blob/master/MIT-LICENSE.txt">License (MIT)</a>
87
+ </small></p>
88
+
89
+ </footer>
90
+
91
+ </div>
92
+
93
+ <!-- here comes the javascript -->
94
+
95
+ <!-- Grab Google CDN's jQuery. fall back to local if necessary -->
96
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
97
+ <script>window.jQuery || document.write("<script src='js/jquery-1.5.1.min.js'>\x3C/script>")</script>
98
+
99
+ <!-- Javascript SHA1 -->
100
+ <script src="js/webtoolkit.sha1.js"></script>
101
+
102
+ <!-- jQuery templates -->
103
+ <script src="js/jquery.tmpl.min.js"></script>
104
+
105
+ <!-- jQuery lean modal -->
106
+ <script src="js/jquery.leanModal.min.js"></script>
107
+
108
+ <!-- jQuery zclip (clipboard support) -->
109
+ <script type="text/javascript" src="js/jquery.zclip.min.js"></script>
110
+
111
+ <!-- this is where we put our custom functions -->
112
+ <script src="js/functions.js"></script>
113
+
114
+ <!-- jQuery sort elements -->
115
+ <script src="js/jquery.sortElements.js"></script>
116
+
117
+ <!-- jQuery auto suggest -->
118
+ <script src="js/jquery.autoSuggest.js"></script>
119
+
120
+ <!-- include other js -->
121
+ <%= @js %>
122
+
123
+ </body>
124
+ </html>