flapjack 0.7.18 → 0.7.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/CHANGELOG.md +7 -0
  2. data/bin/flapjack +3 -0
  3. data/bin/flapjack-nagios-receiver +4 -1
  4. data/bin/flapjack-netsaint-parser +2 -1
  5. data/bin/flapjack-populator +6 -3
  6. data/bin/receive-events +3 -1
  7. data/bin/simulate-failed-check +2 -1
  8. data/etc/flapjack_config.yaml.example +20 -0
  9. data/features/events.feature +1 -1
  10. data/features/events_check_names.feature +1 -1
  11. data/features/notification_rules.feature +1 -1
  12. data/features/notifications.feature +1 -1
  13. data/features/steps/events_steps.rb +18 -17
  14. data/features/steps/flapjack-netsaint-parser_steps.rb +1 -2
  15. data/features/steps/notifications_steps.rb +14 -1
  16. data/features/support/env.rb +27 -10
  17. data/flapjack.gemspec +1 -3
  18. data/lib/flapjack/coordinator.rb +30 -20
  19. data/lib/flapjack/data/contact.rb +3 -2
  20. data/lib/flapjack/data/entity.rb +3 -3
  21. data/lib/flapjack/data/entity_check.rb +116 -43
  22. data/lib/flapjack/data/event.rb +10 -10
  23. data/lib/flapjack/data/message.rb +3 -6
  24. data/lib/flapjack/data/notification.rb +122 -57
  25. data/lib/flapjack/data/notification_rule.rb +11 -11
  26. data/lib/flapjack/filters/acknowledgement.rb +2 -2
  27. data/lib/flapjack/filters/ok.rb +1 -1
  28. data/lib/flapjack/gateways/api/entity_check_presenter.rb +1 -0
  29. data/lib/flapjack/gateways/api/entity_methods.rb +4 -6
  30. data/lib/flapjack/gateways/api/rack/json_params_parser.rb +1 -1
  31. data/lib/flapjack/gateways/email.rb +3 -5
  32. data/lib/flapjack/gateways/email/{alert.html.haml → alert.html.erb} +0 -0
  33. data/lib/flapjack/gateways/jabber.rb +66 -35
  34. data/lib/flapjack/gateways/oobetet.rb +5 -7
  35. data/lib/flapjack/gateways/pagerduty.rb +7 -7
  36. data/lib/flapjack/gateways/web.rb +101 -41
  37. data/lib/flapjack/gateways/web/public/css/flapjack.css +1 -1
  38. data/lib/flapjack/gateways/web/views/{_css.haml → _css.html.erb} +2 -1
  39. data/lib/flapjack/gateways/web/views/_foot.html.erb +3 -0
  40. data/lib/flapjack/gateways/web/views/_head.html.erb +4 -0
  41. data/lib/flapjack/gateways/web/views/_nav.html.erb +9 -0
  42. data/lib/flapjack/gateways/web/views/check.html.erb +204 -0
  43. data/lib/flapjack/gateways/web/views/checks.html.erb +77 -0
  44. data/lib/flapjack/gateways/web/views/contact.html.erb +114 -0
  45. data/lib/flapjack/gateways/web/views/contacts.html.erb +42 -0
  46. data/lib/flapjack/gateways/web/views/entities.html.erb +39 -0
  47. data/lib/flapjack/gateways/web/views/entity.html.erb +67 -0
  48. data/lib/flapjack/gateways/web/views/index.html.erb +27 -0
  49. data/lib/flapjack/gateways/web/views/self_stats.html.erb +97 -0
  50. data/lib/flapjack/logger.rb +71 -23
  51. data/lib/flapjack/notifier.rb +157 -0
  52. data/lib/flapjack/patches.rb +1 -41
  53. data/lib/flapjack/pikelet.rb +4 -2
  54. data/lib/flapjack/{executive.rb → processor.rb} +32 -145
  55. data/lib/flapjack/version.rb +1 -1
  56. data/spec/lib/flapjack/coordinator_spec.rb +134 -71
  57. data/spec/lib/flapjack/data/contact_spec.rb +1 -0
  58. data/spec/lib/flapjack/data/entity_check_spec.rb +146 -30
  59. data/spec/lib/flapjack/data/entity_spec.rb +4 -4
  60. data/spec/lib/flapjack/data/event_spec.rb +4 -4
  61. data/spec/lib/flapjack/data/message_spec.rb +2 -3
  62. data/spec/lib/flapjack/data/notification_spec.rb +13 -19
  63. data/spec/lib/flapjack/gateways/api/entity_methods_spec.rb +2 -2
  64. data/spec/lib/flapjack/gateways/jabber_spec.rb +34 -0
  65. data/spec/lib/flapjack/gateways/pagerduty_spec.rb +0 -2
  66. data/spec/lib/flapjack/gateways/web/views/{check.haml_spec.rb → check.html.erb_spec.rb} +2 -2
  67. data/spec/lib/flapjack/gateways/web/views/{contact.haml_spec.rb → contact.html.erb_spec.rb} +3 -3
  68. data/spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb +14 -0
  69. data/spec/lib/flapjack/gateways/web_spec.rb +20 -8
  70. data/spec/lib/flapjack/logger_spec.rb +30 -28
  71. data/spec/lib/flapjack/notifier_spec.rb +6 -0
  72. data/spec/lib/flapjack/pikelet_spec.rb +8 -8
  73. data/spec/lib/flapjack/{executive_spec.rb → processor_spec.rb} +4 -4
  74. data/spec/spec_helper.rb +1 -13
  75. data/spec/support/erb_view_helper.rb +23 -0
  76. data/tasks/profile.rake +1 -1
  77. data/tmp/acknowledge.rb +3 -1
  78. data/tmp/create_event_ok.rb +3 -1
  79. data/tmp/create_event_unknown.rb +3 -1
  80. data/tmp/create_events_failure.rb +3 -1
  81. data/tmp/create_events_ok.rb +3 -1
  82. data/tmp/create_events_ok_fail_ack_ok.rb +3 -1
  83. data/tmp/create_events_ok_failure.rb +3 -1
  84. data/tmp/create_events_ok_failure_ack.rb +3 -1
  85. data/tmp/test_json_post.rb +5 -3
  86. data/tmp/test_notification_rules_api.rb +5 -3
  87. metadata +32 -61
  88. data/lib/flapjack/gateways/web/views/_foot.haml +0 -8
  89. data/lib/flapjack/gateways/web/views/_head.haml +0 -10
  90. data/lib/flapjack/gateways/web/views/_nav.haml +0 -14
  91. data/lib/flapjack/gateways/web/views/check.haml +0 -191
  92. data/lib/flapjack/gateways/web/views/checks.haml +0 -49
  93. data/lib/flapjack/gateways/web/views/contact.haml +0 -85
  94. data/lib/flapjack/gateways/web/views/contacts.haml +0 -30
  95. data/lib/flapjack/gateways/web/views/entities.haml +0 -28
  96. data/lib/flapjack/gateways/web/views/entity.haml +0 -50
  97. data/lib/flapjack/gateways/web/views/index.haml +0 -32
  98. data/lib/flapjack/gateways/web/views/self_stats.haml +0 -70
  99. data/spec/lib/flapjack/gateways/web/views/index.haml_spec.rb +0 -13
  100. data/spec/support/haml_view_helper.rb +0 -15
@@ -43,7 +43,7 @@
43
43
 
44
44
  .container {
45
45
  width: auto;
46
- max-width: 900px;
46
+ max-width: 1900px;
47
47
  }
48
48
  .container .credit {
49
49
  margin: 10px 0;
@@ -1,4 +1,4 @@
1
- :css
1
+ <style type="text/css">
2
2
  * { margin: 0; padding: 0; }
3
3
  html { font-size: 62.5%; }
4
4
  body { font-size: 16px; }
@@ -39,3 +39,4 @@
39
39
  table td.up {
40
40
  background-color: #B2DF8A;
41
41
  }
42
+ </style>
@@ -0,0 +1,3 @@
1
+ <div class="container">
2
+ <p class="muted credit">Flapjack version <%= ::Flapjack::VERSION %> | <a href="http://flapjack-project.com">Flapjack Project</a> | <a href="https://github.com/flpjck/flapjack">Flapjack on Github</a></p>
3
+ </div>
@@ -0,0 +1,4 @@
1
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
2
+ <link rel="stylesheet" href="/css/bootstrap.min.css" media="screen">
3
+ <link rel="stylesheet" href="/css/flapjack.css" media="screen">
4
+ <link rel="stylesheet" href="/css/bootstrap-responsive.min.css" media="screen">
@@ -0,0 +1,9 @@
1
+ <p>
2
+ <a title="" href="/">Summary</a> |
3
+ <a title="" href="/entities_all">All Entities</a> |
4
+ <a title="" href="/entities_failing">Failing Entities</a> |
5
+ <a title="" href="/checks_all">All Checks</a> |
6
+ <a title="" href="/checks_failing">Failing Checks</a> |
7
+ <a title="" href="/contacts">Contacts</a> |
8
+ <a title="" href="/self_stats">Internal Statistics</a>
9
+ </p>
@@ -0,0 +1,204 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <% nav = render_erb('_nav.html.erb', binding) %>
5
+ <% head = render_erb('_head.html.erb', binding) %>
6
+ <% foot = render_erb('_foot.html.erb', binding) %>
7
+ <% check_path_escaped = u(@entity) << '/' << u(@check) %>
8
+ <% current_time = Time.now %>
9
+ <title>Flapjack - Check: <%= h @entity %>:<%= h @check %></title>
10
+ <%= head %>
11
+ </head>
12
+ <body>
13
+ <div id="wrap">
14
+ <div class="container">
15
+ <div class="page-header">
16
+ <%= nav %>
17
+ <% entity_link = "/entity/" + u(@entity) %>
18
+ <h2><%= h @check %> on <a href="<%= entity_link %>" title="entity summary"><%= h @entity %></a></h2>
19
+ </div>
20
+ <% state_qualifier = @check_enabled ? '' : "DISABLED. Last " %>
21
+ <h3><%= state_qualifier %>State: <%= @check_state ? h(@check_state.upcase) : '' %></h3>
22
+ <% if (['warning', 'critical', 'unknown'].include?(@check_state) and !@current_scheduled_maintenance) %>
23
+ <form action="/acknowledgements/<%= check_path_escaped %>" method="post" class="form-inline">
24
+ <input type="hidden" name="acknowledgement_id" value="<%= @acknowledgement_id %>">
25
+ <input type="submit" value="<%= @current_unscheduled_maintenance ? 'Replace acknowledgment' : 'Acknowledge' %>" class="button">
26
+ with
27
+ <label>summary:</label>
28
+ <input type="text" name="summary" value="">
29
+ <label>duration:</label>
30
+ <input type="text" name="duration" value="">
31
+ e.g. "5 hours"
32
+ </form>
33
+ <% end %>
34
+ <% if @current_unscheduled_maintenance %>
35
+ <h3>(Acknowledged - <%= h @current_unscheduled_maintenance[:summary] %>)</h3>
36
+ <% start = Time.at(@current_unscheduled_maintenance[:start_time]) %>
37
+ <% finish = Time.at(@current_unscheduled_maintenance[:start_time] + @current_unscheduled_maintenance[:duration]) %>
38
+ <% remain = time_period_in_words( (finish - current_time).ceil ) %>
39
+ <p><%= h start.to_s %> -&gt; <%= h finish.to_s %> (<%= h remain %> remaining)</p>
40
+ <form action="/end_unscheduled_maintenance/<%= check_path_escaped %>" method="post">
41
+ <input type="submit" value="End Unscheduled Maintenance (Unacknowledge)" class="button">
42
+ </form>
43
+ <% end %>
44
+ <% if @current_scheduled_maintenance %>
45
+ <h4>(Scheduled Maintenance - <%= h @current_scheduled_maintenance[:summary] %></h4>
46
+ <% start = Time.at(@current_scheduled_maintenance[:start_time]) %>
47
+ <% finish = Time.at(@current_scheduled_maintenance[:start_time] + @current_scheduled_maintenance[:duration]) %>
48
+ <% remain = time_period_in_words( (finish - current_time).ceil ) %>
49
+ <p><%= h start.to_s %> -&gt; <%= h finish.to_s %> (<%= h remain %> remaining)</p>
50
+ <% end %>
51
+ <h3>Output: <%= h @check_summary %></h3>
52
+ <p><%= h @check_details %></p>
53
+ <table class="table table-hover table-condensed">
54
+ <tr>
55
+ <td>Last state change:</td>
56
+ <td><%= h relative_time_ago(Time.at(@check_last_change.to_i)) %> ago</td>
57
+ <td><%= h Time.at(@check_last_change.to_i).to_s %></td>
58
+ <td>&nbsp;</td>
59
+ </tr>
60
+ <tr>
61
+ <td>Last update:</td>
62
+ <td><%= h relative_time_ago(Time.at(@check_last_update.to_i)) %> ago</td>
63
+ <td><%= h Time.at(@check_last_update.to_i).to_s %></td>
64
+ <td>&nbsp;</td>
65
+ </tr>
66
+ <% [:critical, :warning, :unknown, :recovery, :acknowledgement].each do |type| %>
67
+ <tr>
68
+ <td>Last <%= h type.to_s %> notification:</td>
69
+ <td><%= @last_notifications[type] ? h(@last_notifications[type][:relative]) : 'never' %></td>
70
+ <td><%= @last_notifications[type] ? h(@last_notifications[type][:time].to_s) : '&nbsp;' %></td>
71
+ <td><%= @last_notifications[type] ? h(@last_notifications[type][:summary]) : '&nbsp;' %></td>
72
+ </tr>
73
+ <% end %>
74
+ </table>
75
+
76
+ <div id="currency">
77
+ <% if @check_enabled %>
78
+ Enabled ...
79
+ <form action="/checks/<%= check_path_escaped %>" method="post" style="display:inline-block">
80
+ <input type='hidden' name='_method' value='delete'>
81
+ <input type='submit' value="Disable" class='button'>
82
+ </form>
83
+ <% else %>
84
+ Disabled
85
+ <% end %>
86
+
87
+ <h3>Scheduled Maintenance Periods</h3>
88
+ <% if @scheduled_maintenances && !@scheduled_maintenances.empty? %>
89
+ <table class="table table-bordered table-hover table-condensed">
90
+ <tr>
91
+ <th>Start</th>
92
+ <th>End</th>
93
+ <th>Duration</th>
94
+ <th>Summary</th>
95
+ <th>Actions</th>
96
+ </tr>
97
+
98
+ <% @scheduled_maintenances.sort_by {|s| s[:start_time]}.each do |scheduled_maintenance| %>
99
+ <% start_time = scheduled_maintenance[:start_time]
100
+ end_time = scheduled_maintenance[:end_time]
101
+ duration = scheduled_maintenance[:duration]
102
+ summary = scheduled_maintenance[:summary]
103
+ %>
104
+ <tr>
105
+ <td><%= h Time.at(start_time).to_s %></td>
106
+ <td><%= h Time.at(end_time).to_s %></td>
107
+ <td><%= h ChronicDuration.output(duration) %></td>
108
+ <td><%= h summary %></td>
109
+ <td>
110
+ <% if end_time > current_time.to_i %>
111
+ <% label = (start_time > current_time.to_i) ? 'Delete' : 'End Now' %>
112
+ <form action="/scheduled_maintenances/<%= check_path_escaped %>" method="post">
113
+ <input type="hidden" name="_method" value="delete">
114
+ <input type="hidden" name="start_time" value="<%= start_time %>">
115
+ <input type="submit" value="<%= label %>" class="button">
116
+ </form>
117
+ <% else %>
118
+ &nbsp;
119
+ <% end %>
120
+ </td>
121
+ </tr>
122
+ <% end %>
123
+
124
+ </table>
125
+ <% else %>
126
+ <p>No maintenance is scheduled</p>
127
+ <% end %>
128
+ <h4>Add Scheduled Maintenance</h4>
129
+ <form action="/scheduled_maintenances/<%= check_path_escaped %>" method="post" class="form-horizontal">
130
+ <div class="control-group">
131
+ <label class="control-label" for="start_time">Start time:</label>
132
+ <div class="controls">
133
+ <input type="text" name="start_time" class="text" size="20" maxlength="80" value="">
134
+ e.g. "today 4pm", "two hours hence", "friday 2pm", "2012-01-28 13:00"
135
+ </div>
136
+ </div>
137
+ <div class="control-group">
138
+ <label class="control-label" for="duration">Duration:</label>
139
+ <div class="controls">
140
+ <input type="text" name="duration" class="text" size="20" maxlength="80" value="">
141
+ e.g. "1 hour", "2:30:00", "three days", etc
142
+ </div>
143
+ </div>
144
+ <div class="control-group">
145
+ <label class="control-label" for="summary">Summary:</label>
146
+ <div class="controls">
147
+ <input type="text" name="summary" class="text" size="80" maxlength="160" value="">
148
+ </div>
149
+ </div>
150
+ <div class="control-group">
151
+ <div class="controls">
152
+ <input type="submit" value="Save" class="button">
153
+ </div>
154
+ </div>
155
+ </form>
156
+ <p>Times given will be interpreted in the local timezone of <%= h local_timezone %></p>
157
+ <% if @state_changes && !@state_changes.empty? %>
158
+ <h3>Recent state changes</h3>
159
+ <table class="table table-bordered table-hover table-condensed">
160
+ <tr>
161
+ <th>Timestamp</th>
162
+ <th>State</th>
163
+ <th>Summary</th>
164
+ </tr>
165
+ <% @state_changes.each do |state_change| %>
166
+ <tr>
167
+ <td><%= h Time.at(state_change[:timestamp]).to_s %></td>
168
+ <td><%= h state_change[:state] %></td>
169
+ <td><%= h state_change[:summary] %></td>
170
+ </tr>
171
+ <% end %>
172
+ </table>
173
+ <% end %>
174
+ <h3>Contacts</h3>
175
+ <% if @contacts && !@contacts.empty? %>
176
+ <table class="table table-bordered table-hover table-condensed">
177
+ <tr>
178
+ <th>Name</th>
179
+ <th>Media</th>
180
+ </tr>
181
+ <% @contacts.sort_by {|c| [c.first_name, c.last_name] }.each do |contact| %>
182
+ <tr>
183
+ <td><a href="/contacts/<% contact.id %>" title="contact details"><%= h contact.name %></a></td>
184
+ <td>
185
+ <% if contact.media && !contact.media.empty? %>
186
+ <p><%= h contact.media.keys.collect(&:capitalize).join(", ") %></p>
187
+ <% else %>
188
+ <p>No media</p>
189
+ <% end %>
190
+ </td>
191
+ </tr>
192
+ <% end %>
193
+ </table>
194
+ <% else %>
195
+ <p>No contacts</p>
196
+ <% end %>
197
+ </div>
198
+ <div id="push"></div>
199
+ </div>
200
+ <div id="footer">
201
+ <%= foot %>
202
+ </div>
203
+ </body>
204
+ </html>
@@ -0,0 +1,77 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <% nav = render_erb('_nav.html.erb', binding) %>
5
+ <% head = render_erb('_head.html.erb', binding) %>
6
+ <% foot = render_erb('_foot.html.erb', binding) %>
7
+ <title>Flapjack - <%= @adjective.capitalize %> Checks</title>
8
+ <%= head %>
9
+ </head>
10
+ <body>
11
+ <div id="wrap">
12
+ <div class="container">
13
+ <div class="page-header">
14
+ <%= nav %>
15
+ <h2><%= @adjective.capitalize %> Checks</h2>
16
+ </div>
17
+
18
+ <p><%= h @count_failing_checks %> failing out of <%= h @count_all_checks %></p>
19
+
20
+ <table class="table table-bordered table-hover table-condensed">
21
+ <tr>
22
+ <th>Entity</th>
23
+ <th>Check</th>
24
+ <th>State</th>
25
+ <th>Summary</th>
26
+ <th>Last State Change</th>
27
+ <th>Last Update</th>
28
+ <th>Last Notification</th>
29
+ </tr>
30
+ <% @entities_sorted.each do |entity| %>
31
+ <% row_entity = nil %>
32
+ <% entity_link = "/entity/" << u(entity) %>
33
+ <% @states[entity].each do |check, status, summary, changed, updated, in_unscheduled_outage, in_scheduled_outage, notified| %>
34
+ <%
35
+ row_colour = case status
36
+ when 'critical', 'unknown'
37
+ 'error'
38
+ when 'ok', 'up'
39
+ 'success'
40
+ else
41
+ status
42
+ end
43
+
44
+ check_link = "/check?entity=" << u(entity) << "&amp;check=" << u(check)
45
+
46
+ %>
47
+ <tr class="<%= row_colour %>">
48
+ <% unless row_entity && entity == row_entity %>
49
+ <td rowspan=<%= @states[entity].length %>>
50
+ <a href="<%= entity_link %>"><%= h entity %></a>
51
+ </td>
52
+ <% row_entity = entity %>
53
+ <% end %>
54
+ <td><a href="<%= check_link %>" title="check detail"><%= h check %></a></td>
55
+ <td class="<%= status %>">
56
+ <%= h status.upcase %>
57
+ <% if in_unscheduled_outage%> (Ack'd)<% end %>
58
+ <% if in_scheduled_outage %> (Sched)<% end %>
59
+ </td>
60
+ <td><%= h summary %></td>
61
+ <td><%= h changed %></td>
62
+ <td><%= h updated %></td>
63
+ <td><%= h notified %></td>
64
+ </tr>
65
+
66
+ <% end %>
67
+ <% end %>
68
+ </table>
69
+
70
+ </div>
71
+ <div id="push"></div>
72
+ </div>
73
+ <div id="footer">
74
+ <%= foot %>
75
+ </div>
76
+ </body>
77
+ </html>
@@ -0,0 +1,114 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <% nav = render_erb('_nav.html.erb', binding) %>
5
+ <% head = render_erb('_head.html.erb', binding) %>
6
+ <% foot = render_erb('_foot.html.erb', binding) %>
7
+ <title>Flapjack - <%= h @contact.name %> (contact)</title>
8
+ <%= head %>
9
+ </head>
10
+ <body>
11
+ <div id="wrap">
12
+ <div class="container">
13
+ <div class="page-header">
14
+ <%= nav %>
15
+ <h2><%= h @contact.name %></h2>
16
+ </div>
17
+
18
+ <h3>Contact Media</h3>
19
+ <% if !@contact.media || @contact.media.empty? %>
20
+ <p>No media</p>
21
+ <% else %>
22
+ <table class="table table-bordered table-hover table-condensed">
23
+ <tr>
24
+ <th>Media</th>
25
+ <th>Address</th>
26
+ <th>Interval</th>
27
+ </tr>
28
+ <% @contact.media.each_pair do |mk, mv| %>
29
+ <tr>
30
+ <% if 'pagerduty'.eql?(mk) %>
31
+ <td>PagerDuty</td>
32
+ <td>
33
+ <% @pagerduty_credentials.each_pair do |pk, pv| %>
34
+ <p><%= 'password'.eql?(pk) ? h("#{pk}: ...") : h("#{pk}: #{pv}") %></p>
35
+ <% end %>
36
+ </td>
37
+ <td>-</td>
38
+ <% else %>
39
+ <td><%= h mk.capitalize %></td>
40
+ <td><%= h mv %></td>
41
+ <td>
42
+ <% if @contact.media_intervals[mk] %>
43
+ <%= h @contact.media_intervals[mk] %> seconds
44
+ <% else %>
45
+ no custom interval
46
+ <% end %>
47
+ </td>
48
+ <% end %>
49
+ </tr>
50
+ <% end %>
51
+ </table>
52
+ <% end %>
53
+
54
+ <h3>Entities and Checks</h3>
55
+ <% if !@entities_and_checks || @entities_and_checks.empty? %>
56
+ <p>No entities</p>
57
+ <% else %>
58
+ <table class="table table-bordered table-hover table-condensed">
59
+ <tr>
60
+ <th>Entity</th>
61
+ <th>Checks</th>
62
+ </tr>
63
+ <% @entities_and_checks.each do |ec| %>
64
+ <%
65
+ entity = ec[:entity]
66
+ checks = ec[:checks]
67
+ %>
68
+ <tr>
69
+ <td><a href="/entity/<%= u(entity.name) %>" title="entity status"><%= h entity.name %></a></td>
70
+ <td>
71
+ <% checks.each do |check| %>
72
+ <a href="/check?entity=<%= u(entity.name) %>&amp;check=<%= u(check) %>" title="check status"><%= h check %></a>
73
+ <% end %>
74
+ </td>
75
+ </tr>
76
+ <% end %>
77
+ </table>
78
+ <% end %>
79
+
80
+ <h3>Notification Rules</h3>
81
+ <% rules = @contact.notification_rules %>
82
+ <% if !rules || rules.empty? %>
83
+ <p>No notification rules</p>
84
+ <% else %>
85
+ <table class="table table-bordered table-hover table-condensed">
86
+ <tr>
87
+ <th>ID</th>
88
+ <th>Entities</th>
89
+ <th>Entity Tags</th>
90
+ <th>Warning Media</th>
91
+ <th>Critical Media</th>
92
+ <th>Time Restrictions</th>
93
+ </tr>
94
+ <% rules.each do |rule| %>
95
+ <tr>
96
+ <td><%= h rule.id %></td>
97
+ <td><%= h( (rule.entities && !rule.entities.empty?) ? rule.entities.join(', ') : '-') %></td>
98
+ <td><%= h( (rule.entity_tags && !rule.entity_tags.empty?) ? rule.entity_tags.join(', ') : '-') %></td>
99
+ <td><%= h( (rule.warning_media && !rule.warning_media.empty?) ? rule.warning_media.join(', ') : '-')%></td>
100
+ <td><%= h( (rule.critical_media && !rule.critical_media.empty?) ? rule.critical_media.join(', ') : '-') %></td>
101
+ <td><%= h(rule.time_restrictions) %></td>
102
+ </tr>
103
+ <% end %>
104
+ </table>
105
+ <% end %>
106
+
107
+ </div>
108
+ <div id="push"></div>
109
+ </div>
110
+ <div id="footer">
111
+ <%= foot %>
112
+ </div>
113
+ </body>
114
+ </html>
@@ -0,0 +1,42 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <% nav = render_erb('_nav.html.erb', binding) %>
5
+ <% head = render_erb('_head.html.erb', binding) %>
6
+ <% foot = render_erb('_foot.html.erb', binding) %>
7
+ <title>Flapjack - Contacts</title>
8
+ <%= head %>
9
+ </head>
10
+ <body>
11
+ <div id="wrap">
12
+ <div class="container">
13
+ <div class="page-header">
14
+ <%= nav %>
15
+ <h2>Contacts</h2>
16
+ </div>
17
+
18
+ <% if !@contacts || @contacts.empty? %>
19
+ <p>No contacts</p>
20
+ <% else %>
21
+ <table class="table table-bordered table-hover table-condensed">
22
+ <tr>
23
+ <th>Name</th>
24
+ <th>Email</th>
25
+ </tr>
26
+ <% @contacts.sort_by {|c| [c.last_name, c.first_name] }.each do |contact| %>
27
+ <tr>
28
+ <td><a href="/contacts/<%= contact.id %>" title="contact details"><%= h contact.name %></a></td>
29
+ <td><%= h contact.email %></td>
30
+ </tr>
31
+ <% end %>
32
+ </table>
33
+ <% end %>
34
+
35
+ </div>
36
+ <div id="push"></div>
37
+ </div>
38
+ <div id="footer">
39
+ <%= foot %>
40
+ </div>
41
+ </body>
42
+ </html>