flapjack 1.6.0 → 2.0.0b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (301) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -6
  3. data/.gitmodules +1 -1
  4. data/.rspec +1 -1
  5. data/.ruby-version +1 -1
  6. data/.travis.yml +12 -13
  7. data/CHANGELOG.md +2 -9
  8. data/CONTRIBUTING.md +7 -2
  9. data/Gemfile +4 -13
  10. data/LICENCE +1 -0
  11. data/README.md +8 -2
  12. data/Rakefile +2 -2
  13. data/bin/flapjack +3 -12
  14. data/build.sh +4 -2
  15. data/etc/flapjack_config.toml.example +273 -0
  16. data/features/ack_after_sched_maint.feature +18 -21
  17. data/features/cli.feature +11 -71
  18. data/features/cli_flapjack-feed-events.feature +14 -15
  19. data/features/cli_flapjack-nagios-receiver.feature +12 -41
  20. data/features/cli_flapper.feature +12 -41
  21. data/features/cli_purge.feature +5 -6
  22. data/features/cli_receive-events.feature +6 -7
  23. data/features/cli_simulate-failed-check.feature +5 -6
  24. data/features/events.feature +206 -181
  25. data/features/events_check_names.feature +4 -7
  26. data/features/notification_rules.feature +144 -223
  27. data/features/notifications.feature +65 -57
  28. data/features/rollup.feature +45 -47
  29. data/features/steps/cli_steps.rb +4 -5
  30. data/features/steps/events_steps.rb +163 -373
  31. data/features/steps/notifications_steps.rb +408 -264
  32. data/features/steps/packaging-lintian_steps.rb +0 -4
  33. data/features/steps/time_travel_steps.rb +0 -26
  34. data/features/support/daemons.rb +6 -31
  35. data/features/support/env.rb +65 -74
  36. data/flapjack.gemspec +22 -24
  37. data/lib/flapjack.rb +14 -7
  38. data/lib/flapjack/cli/flapper.rb +74 -173
  39. data/lib/flapjack/cli/maintenance.rb +278 -109
  40. data/lib/flapjack/cli/migrate.rb +950 -0
  41. data/lib/flapjack/cli/purge.rb +19 -22
  42. data/lib/flapjack/cli/receiver.rb +150 -326
  43. data/lib/flapjack/cli/server.rb +8 -235
  44. data/lib/flapjack/cli/simulate.rb +42 -57
  45. data/lib/flapjack/configuration.rb +51 -37
  46. data/lib/flapjack/coordinator.rb +138 -129
  47. data/lib/flapjack/data/acknowledgement.rb +177 -0
  48. data/lib/flapjack/data/alert.rb +97 -158
  49. data/lib/flapjack/data/check.rb +611 -0
  50. data/lib/flapjack/data/condition.rb +70 -0
  51. data/lib/flapjack/data/contact.rb +226 -456
  52. data/lib/flapjack/data/event.rb +96 -184
  53. data/lib/flapjack/data/extensions/associations.rb +59 -0
  54. data/lib/flapjack/data/extensions/short_name.rb +25 -0
  55. data/lib/flapjack/data/medium.rb +428 -0
  56. data/lib/flapjack/data/metrics.rb +194 -0
  57. data/lib/flapjack/data/notification.rb +22 -281
  58. data/lib/flapjack/data/rule.rb +473 -0
  59. data/lib/flapjack/data/scheduled_maintenance.rb +244 -0
  60. data/lib/flapjack/data/state.rb +221 -0
  61. data/lib/flapjack/data/statistic.rb +112 -0
  62. data/lib/flapjack/data/tag.rb +277 -0
  63. data/lib/flapjack/data/test_notification.rb +182 -0
  64. data/lib/flapjack/data/unscheduled_maintenance.rb +159 -0
  65. data/lib/flapjack/data/validators/id_validator.rb +20 -0
  66. data/lib/flapjack/exceptions.rb +6 -0
  67. data/lib/flapjack/filters/acknowledgement.rb +23 -16
  68. data/lib/flapjack/filters/base.rb +0 -5
  69. data/lib/flapjack/filters/delays.rb +53 -43
  70. data/lib/flapjack/filters/ok.rb +23 -14
  71. data/lib/flapjack/filters/scheduled_maintenance.rb +3 -3
  72. data/lib/flapjack/filters/unscheduled_maintenance.rb +12 -3
  73. data/lib/flapjack/gateways/aws_sns.rb +65 -49
  74. data/lib/flapjack/gateways/aws_sns/alert.text.erb +2 -2
  75. data/lib/flapjack/gateways/aws_sns/alert_subject.text.erb +2 -2
  76. data/lib/flapjack/gateways/aws_sns/rollup_subject.text.erb +1 -1
  77. data/lib/flapjack/gateways/email.rb +107 -90
  78. data/lib/flapjack/gateways/email/alert.html.erb +19 -18
  79. data/lib/flapjack/gateways/email/alert.text.erb +20 -14
  80. data/lib/flapjack/gateways/email/alert_subject.text.erb +2 -1
  81. data/lib/flapjack/gateways/email/rollup.html.erb +14 -13
  82. data/lib/flapjack/gateways/email/rollup.text.erb +13 -10
  83. data/lib/flapjack/gateways/jabber.rb +679 -671
  84. data/lib/flapjack/gateways/jabber/alert.text.erb +9 -6
  85. data/lib/flapjack/gateways/jsonapi.rb +164 -350
  86. data/lib/flapjack/gateways/jsonapi/data/join_descriptor.rb +44 -0
  87. data/lib/flapjack/gateways/jsonapi/data/method_descriptor.rb +21 -0
  88. data/lib/flapjack/gateways/jsonapi/helpers/headers.rb +63 -0
  89. data/lib/flapjack/gateways/jsonapi/helpers/miscellaneous.rb +136 -0
  90. data/lib/flapjack/gateways/jsonapi/helpers/resources.rb +227 -0
  91. data/lib/flapjack/gateways/jsonapi/helpers/serialiser.rb +313 -0
  92. data/lib/flapjack/gateways/jsonapi/helpers/swagger_docs.rb +322 -0
  93. data/lib/flapjack/gateways/jsonapi/methods/association_delete.rb +115 -0
  94. data/lib/flapjack/gateways/jsonapi/methods/association_get.rb +288 -0
  95. data/lib/flapjack/gateways/jsonapi/methods/association_patch.rb +178 -0
  96. data/lib/flapjack/gateways/jsonapi/methods/association_post.rb +116 -0
  97. data/lib/flapjack/gateways/jsonapi/methods/metrics.rb +71 -0
  98. data/lib/flapjack/gateways/jsonapi/methods/resource_delete.rb +119 -0
  99. data/lib/flapjack/gateways/jsonapi/methods/resource_get.rb +186 -0
  100. data/lib/flapjack/gateways/jsonapi/methods/resource_patch.rb +239 -0
  101. data/lib/flapjack/gateways/jsonapi/methods/resource_post.rb +197 -0
  102. data/lib/flapjack/gateways/jsonapi/middleware/array_param_fixer.rb +27 -0
  103. data/lib/flapjack/gateways/jsonapi/{rack → middleware}/json_params_parser.rb +7 -6
  104. data/lib/flapjack/gateways/jsonapi/middleware/request_timestamp.rb +18 -0
  105. data/lib/flapjack/gateways/oobetet.rb +222 -170
  106. data/lib/flapjack/gateways/pager_duty.rb +388 -0
  107. data/lib/flapjack/gateways/pager_duty/alert.text.erb +13 -0
  108. data/lib/flapjack/gateways/slack.rb +56 -48
  109. data/lib/flapjack/gateways/slack/alert.text.erb +1 -1
  110. data/lib/flapjack/gateways/slack/rollup.text.erb +1 -1
  111. data/lib/flapjack/gateways/sms_aspsms.rb +155 -0
  112. data/lib/flapjack/gateways/sms_aspsms/alert.text.erb +7 -0
  113. data/lib/flapjack/gateways/sms_aspsms/rollup.text.erb +2 -0
  114. data/lib/flapjack/gateways/sms_messagenet.rb +77 -57
  115. data/lib/flapjack/gateways/sms_messagenet/alert.text.erb +3 -2
  116. data/lib/flapjack/gateways/sms_nexmo.rb +53 -51
  117. data/lib/flapjack/gateways/sms_nexmo/alert.text.erb +2 -2
  118. data/lib/flapjack/gateways/sms_nexmo/rollup.text.erb +1 -1
  119. data/lib/flapjack/gateways/sms_twilio.rb +79 -62
  120. data/lib/flapjack/gateways/sms_twilio/alert.text.erb +3 -2
  121. data/lib/flapjack/gateways/web.rb +437 -345
  122. data/lib/flapjack/gateways/web/middleware/request_timestamp.rb +18 -0
  123. data/lib/flapjack/gateways/web/public/css/bootstrap.css +3793 -4340
  124. data/lib/flapjack/gateways/web/public/css/bootstrap.css.map +1 -0
  125. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.eot +0 -0
  126. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.svg +273 -214
  127. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  128. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.woff +0 -0
  129. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.woff2 +0 -0
  130. data/lib/flapjack/gateways/web/public/js/bootstrap.js +1637 -1607
  131. data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -2
  132. data/lib/flapjack/gateways/web/views/_pagination.html.erb +19 -0
  133. data/lib/flapjack/gateways/web/views/check.html.erb +159 -121
  134. data/lib/flapjack/gateways/web/views/checks.html.erb +82 -41
  135. data/lib/flapjack/gateways/web/views/contact.html.erb +59 -71
  136. data/lib/flapjack/gateways/web/views/contacts.html.erb +32 -8
  137. data/lib/flapjack/gateways/web/views/index.html.erb +2 -2
  138. data/lib/flapjack/gateways/web/views/{layout.erb → layout.html.erb} +7 -23
  139. data/lib/flapjack/gateways/web/views/self_stats.html.erb +32 -33
  140. data/lib/flapjack/gateways/web/views/tag.html.erb +32 -0
  141. data/lib/flapjack/gateways/web/views/tags.html.erb +51 -0
  142. data/lib/flapjack/logger.rb +34 -3
  143. data/lib/flapjack/notifier.rb +180 -112
  144. data/lib/flapjack/patches.rb +8 -63
  145. data/lib/flapjack/pikelet.rb +185 -143
  146. data/lib/flapjack/processor.rb +323 -191
  147. data/lib/flapjack/record_queue.rb +33 -0
  148. data/lib/flapjack/redis_proxy.rb +66 -0
  149. data/lib/flapjack/utility.rb +21 -15
  150. data/lib/flapjack/version.rb +2 -1
  151. data/libexec/httpbroker.go +218 -14
  152. data/libexec/oneoff.go +13 -10
  153. data/spec/lib/flapjack/configuration_spec.rb +286 -0
  154. data/spec/lib/flapjack/coordinator_spec.rb +103 -157
  155. data/spec/lib/flapjack/data/check_spec.rb +175 -0
  156. data/spec/lib/flapjack/data/contact_spec.rb +26 -349
  157. data/spec/lib/flapjack/data/event_spec.rb +76 -291
  158. data/spec/lib/flapjack/data/medium_spec.rb +19 -0
  159. data/spec/lib/flapjack/data/rule_spec.rb +43 -0
  160. data/spec/lib/flapjack/data/scheduled_maintenance_spec.rb +976 -0
  161. data/spec/lib/flapjack/data/unscheduled_maintenance_spec.rb +34 -0
  162. data/spec/lib/flapjack/gateways/aws_sns_spec.rb +111 -60
  163. data/spec/lib/flapjack/gateways/email_spec.rb +194 -161
  164. data/spec/lib/flapjack/gateways/jabber_spec.rb +961 -162
  165. data/spec/lib/flapjack/gateways/jsonapi/methods/check_links_spec.rb +155 -0
  166. data/spec/lib/flapjack/gateways/jsonapi/methods/checks_spec.rb +426 -0
  167. data/spec/lib/flapjack/gateways/jsonapi/methods/contact_links_spec.rb +217 -0
  168. data/spec/lib/flapjack/gateways/jsonapi/methods/contacts_spec.rb +425 -0
  169. data/spec/lib/flapjack/gateways/jsonapi/methods/events_spec.rb +271 -0
  170. data/spec/lib/flapjack/gateways/jsonapi/methods/media_spec.rb +257 -0
  171. data/spec/lib/flapjack/gateways/jsonapi/methods/medium_links_spec.rb +163 -0
  172. data/spec/lib/flapjack/gateways/jsonapi/methods/metrics_spec.rb +8 -0
  173. data/spec/lib/flapjack/gateways/jsonapi/methods/rule_links_spec.rb +212 -0
  174. data/spec/lib/flapjack/gateways/jsonapi/methods/rules_spec.rb +289 -0
  175. data/spec/lib/flapjack/gateways/jsonapi/methods/scheduled_maintenance_links_spec.rb +49 -0
  176. data/spec/lib/flapjack/gateways/jsonapi/methods/scheduled_maintenances_spec.rb +242 -0
  177. data/spec/lib/flapjack/gateways/jsonapi/methods/tag_links_spec.rb +274 -0
  178. data/spec/lib/flapjack/gateways/jsonapi/methods/tags_spec.rb +302 -0
  179. data/spec/lib/flapjack/gateways/jsonapi/methods/unscheduled_maintenance_links_spec.rb +49 -0
  180. data/spec/lib/flapjack/gateways/jsonapi/methods/unscheduled_maintenances_spec.rb +339 -0
  181. data/spec/lib/flapjack/gateways/jsonapi_spec.rb +1 -1
  182. data/spec/lib/flapjack/gateways/oobetet_spec.rb +151 -79
  183. data/spec/lib/flapjack/gateways/pager_duty_spec.rb +353 -0
  184. data/spec/lib/flapjack/gateways/slack_spec.rb +53 -53
  185. data/spec/lib/flapjack/gateways/sms_aspsms_spec.rb +106 -0
  186. data/spec/lib/flapjack/gateways/sms_messagenet_spec.rb +111 -54
  187. data/spec/lib/flapjack/gateways/sms_nexmo_spec.rb +50 -51
  188. data/spec/lib/flapjack/gateways/sms_twilio_spec.rb +108 -48
  189. data/spec/lib/flapjack/gateways/web_spec.rb +144 -216
  190. data/spec/lib/flapjack/notifier_spec.rb +132 -1
  191. data/spec/lib/flapjack/pikelet_spec.rb +111 -50
  192. data/spec/lib/flapjack/processor_spec.rb +210 -40
  193. data/spec/lib/flapjack/redis_proxy_spec.rb +45 -0
  194. data/spec/lib/flapjack/utility_spec.rb +11 -15
  195. data/spec/service_consumers/fixture_data.rb +547 -0
  196. data/spec/service_consumers/pact_helper.rb +21 -32
  197. data/spec/service_consumers/pacts/flapjack-diner_v2.0.json +4652 -0
  198. data/spec/service_consumers/provider_states_for_flapjack-diner.rb +279 -322
  199. data/spec/service_consumers/provider_support.rb +8 -0
  200. data/spec/spec_helper.rb +34 -44
  201. data/spec/support/erb_view_helper.rb +1 -1
  202. data/spec/support/factories.rb +58 -0
  203. data/spec/support/jsonapi_helper.rb +15 -26
  204. data/spec/support/mock_logger.rb +43 -0
  205. data/spec/support/xmpp_comparable.rb +24 -0
  206. data/src/flapjack/transport_test.go +30 -1
  207. data/tasks/dump_keys.rake +82 -0
  208. data/tasks/events.rake +7 -7
  209. data/tasks/support/flapjack_config_benchmark.toml +28 -0
  210. data/tasks/support/flapjack_config_benchmark.yaml +0 -2
  211. metadata +175 -222
  212. data/Guardfile +0 -14
  213. data/etc/flapjack_config.yaml.example +0 -477
  214. data/features/cli_flapjack-populator.feature +0 -90
  215. data/features/support/silent_system.rb +0 -4
  216. data/lib/flapjack/cli/import.rb +0 -108
  217. data/lib/flapjack/data/entity.rb +0 -652
  218. data/lib/flapjack/data/entity_check.rb +0 -1044
  219. data/lib/flapjack/data/message.rb +0 -56
  220. data/lib/flapjack/data/migration.rb +0 -234
  221. data/lib/flapjack/data/notification_rule.rb +0 -425
  222. data/lib/flapjack/data/semaphore.rb +0 -44
  223. data/lib/flapjack/data/tagged.rb +0 -48
  224. data/lib/flapjack/gateways/jsonapi/check_methods.rb +0 -206
  225. data/lib/flapjack/gateways/jsonapi/check_presenter.rb +0 -221
  226. data/lib/flapjack/gateways/jsonapi/contact_methods.rb +0 -186
  227. data/lib/flapjack/gateways/jsonapi/entity_methods.rb +0 -223
  228. data/lib/flapjack/gateways/jsonapi/medium_methods.rb +0 -185
  229. data/lib/flapjack/gateways/jsonapi/metrics_methods.rb +0 -132
  230. data/lib/flapjack/gateways/jsonapi/notification_rule_methods.rb +0 -141
  231. data/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb +0 -139
  232. data/lib/flapjack/gateways/jsonapi/report_methods.rb +0 -146
  233. data/lib/flapjack/gateways/pagerduty.rb +0 -318
  234. data/lib/flapjack/gateways/pagerduty/alert.text.erb +0 -10
  235. data/lib/flapjack/gateways/web/public/css/select2-bootstrap.css +0 -87
  236. data/lib/flapjack/gateways/web/public/css/select2.css +0 -615
  237. data/lib/flapjack/gateways/web/public/css/tablesort.css +0 -67
  238. data/lib/flapjack/gateways/web/public/img/select2-spinner.gif +0 -0
  239. data/lib/flapjack/gateways/web/public/img/select2.png +0 -0
  240. data/lib/flapjack/gateways/web/public/img/select2x2.png +0 -0
  241. data/lib/flapjack/gateways/web/public/js/backbone.js +0 -1581
  242. data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +0 -322
  243. data/lib/flapjack/gateways/web/public/js/flapjack.js +0 -82
  244. data/lib/flapjack/gateways/web/public/js/jquery.tablesorter.js +0 -1640
  245. data/lib/flapjack/gateways/web/public/js/jquery.tablesorter.widgets.js +0 -1390
  246. data/lib/flapjack/gateways/web/public/js/modules/contact.js +0 -520
  247. data/lib/flapjack/gateways/web/public/js/modules/entity.js +0 -28
  248. data/lib/flapjack/gateways/web/public/js/modules/medium.js +0 -40
  249. data/lib/flapjack/gateways/web/public/js/select2.js +0 -3397
  250. data/lib/flapjack/gateways/web/public/js/tablesort.js +0 -44
  251. data/lib/flapjack/gateways/web/public/js/underscore.js +0 -1276
  252. data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +0 -173
  253. data/lib/flapjack/gateways/web/views/entities.html.erb +0 -30
  254. data/lib/flapjack/gateways/web/views/entity.html.erb +0 -51
  255. data/lib/flapjack/rack_logger.rb +0 -47
  256. data/lib/flapjack/redis_pool.rb +0 -42
  257. data/spec/lib/flapjack/data/entity_check_spec.rb +0 -1418
  258. data/spec/lib/flapjack/data/entity_spec.rb +0 -872
  259. data/spec/lib/flapjack/data/message_spec.rb +0 -30
  260. data/spec/lib/flapjack/data/migration_spec.rb +0 -104
  261. data/spec/lib/flapjack/data/notification_rule_spec.rb +0 -232
  262. data/spec/lib/flapjack/data/notification_spec.rb +0 -53
  263. data/spec/lib/flapjack/data/semaphore_spec.rb +0 -24
  264. data/spec/lib/flapjack/filters/acknowledgement_spec.rb +0 -6
  265. data/spec/lib/flapjack/filters/delays_spec.rb +0 -6
  266. data/spec/lib/flapjack/filters/ok_spec.rb +0 -6
  267. data/spec/lib/flapjack/filters/scheduled_maintenance_spec.rb +0 -6
  268. data/spec/lib/flapjack/filters/unscheduled_maintenance_spec.rb +0 -6
  269. data/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb +0 -315
  270. data/spec/lib/flapjack/gateways/jsonapi/check_presenter_spec.rb +0 -223
  271. data/spec/lib/flapjack/gateways/jsonapi/contact_methods_spec.rb +0 -131
  272. data/spec/lib/flapjack/gateways/jsonapi/entity_methods_spec.rb +0 -389
  273. data/spec/lib/flapjack/gateways/jsonapi/medium_methods_spec.rb +0 -231
  274. data/spec/lib/flapjack/gateways/jsonapi/notification_rule_methods_spec.rb +0 -169
  275. data/spec/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods_spec.rb +0 -114
  276. data/spec/lib/flapjack/gateways/jsonapi/report_methods_spec.rb +0 -590
  277. data/spec/lib/flapjack/gateways/pagerduty_spec.rb +0 -249
  278. data/spec/lib/flapjack/gateways/web/views/check.html.erb_spec.rb +0 -21
  279. data/spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb +0 -24
  280. data/spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb +0 -16
  281. data/spec/lib/flapjack/redis_pool_spec.rb +0 -29
  282. data/spec/service_consumers/pacts/flapjack-diner_v1.0.json +0 -4702
  283. data/tasks/entities.rake +0 -151
  284. data/tasks/profile.rake +0 -282
  285. data/tmp/acknowledge.rb +0 -13
  286. data/tmp/create_config_yaml.rb +0 -16
  287. data/tmp/create_event_ok.rb +0 -30
  288. data/tmp/create_event_unknown.rb +0 -30
  289. data/tmp/create_events_failure.rb +0 -34
  290. data/tmp/create_events_ok.rb +0 -32
  291. data/tmp/create_events_ok_fail_ack_ok.rb +0 -53
  292. data/tmp/create_events_ok_failure.rb +0 -41
  293. data/tmp/create_events_ok_failure_ack.rb +0 -53
  294. data/tmp/dummy_contacts.json +0 -43
  295. data/tmp/dummy_entities.json +0 -37
  296. data/tmp/generate_nagios_test_hosts.rb +0 -16
  297. data/tmp/notification_rules.rb +0 -73
  298. data/tmp/parse_config_yaml.rb +0 -7
  299. data/tmp/redis_find_spurious_unknown_states.rb +0 -52
  300. data/tmp/test_json_post.rb +0 -19
  301. data/tmp/test_notification_rules_api.rb +0 -171
@@ -1,520 +0,0 @@
1
- (function(flapjack, Contact) {
2
- // Dependencies
3
- var Entity = flapjack.module("entity");
4
- var Medium = flapjack.module("medium");
5
-
6
- // Shorthands
7
- // The application container
8
- var app = flapjack.app;
9
-
10
- Contact.Model = Backbone.JSONAPIModel.extend({
11
- name: 'contacts',
12
- defaults: {
13
- first_name: '',
14
- last_name: '',
15
- email: '',
16
- id: null,
17
- links: {},
18
- },
19
- initialize: function(){
20
- Backbone.JSONAPIModel.prototype.initialize.apply(this, arguments);
21
- this.on('change', this.setDirty, this);
22
- },
23
- toJSON: function() {
24
- // TODO ensure that attributes has nothing outside the above, except 'links'
25
- return _.pick(this.attributes, 'id', 'first_name', 'last_name', 'email');
26
- },
27
- validate: function() {
28
- // TODO hack media-email-address edit to set contact.email field
29
- var fn = this.get('first_name');
30
- var ln = this.get('last_name');
31
-
32
- var errors = new Array();
33
-
34
- if ( _.isUndefined(fn) || _.isNull(fn) || (fn.length == 0) ) {
35
- errors.push("First name must be provided.");
36
- }
37
-
38
- if ( _.isUndefined(ln) || _.isNull(ln) || (ln.length == 0) ) {
39
- errors.push("Last name must be provided.");
40
- }
41
-
42
- if ( _.isEmpty(errors) ) {
43
- return;
44
- }
45
-
46
- return(errors);
47
- }
48
- });
49
-
50
- Contact.List = Backbone.JSONAPICollection.extend({
51
- model: Contact.Model,
52
- url: function() { return flapjack.api_url + "contacts"; }
53
- });
54
-
55
- Contact.Views.List = Backbone.View.extend({
56
- tagName: 'tbody',
57
- id: 'contactList',
58
- initialize: function() {
59
- this.collection.on('add', this.render, this);
60
- this.collection.on('remove', this.render, this);
61
- },
62
- render: function() {
63
- // TODO just rerender changed rows (insert new row or remove deleted)
64
- var jqel = this.$el;
65
- jqel.empty();
66
-
67
- this.collection.each(function(contact) {
68
- var item = new (Contact.Views.ListItem)({ model: contact });
69
- jqel.append(item.render().$el);
70
- });
71
-
72
- return this;
73
- }
74
- });
75
-
76
- Contact.Views.ListItem = Backbone.View.extend({
77
- tagName: 'tr',
78
- className: 'contact_list_item',
79
- events: {
80
- 'click button.contact-media' : 'editContactMedia',
81
- 'click button.contact-entities' : 'editContactEntities',
82
- 'click button.delete-contact' : 'removeContact',
83
- 'click td' : 'editContactDetails'
84
- },
85
- initialize: function() {
86
- this.template = _.template($('#contact-list-item-template').html());
87
- // causes an unnecessary render on create, but required for update TODO cleanup
88
- this.listenTo(this.model, "sync", this.render);
89
- },
90
-
91
- render: function() {
92
- var template_values = _.clone(this.model.attributes);
93
- this.$el.html(this.template(template_values));
94
- return this;
95
- },
96
-
97
- editContactDetails: function(e) {
98
- e.stopImmediatePropagation();
99
- // skip if modal showing
100
- if ( $('#contactModal').hasClass('in') ) { return; }
101
-
102
- var contactDetailsView = new Contact.Views.ContactDetails({model: this.model});
103
- contactDetailsView.render();
104
-
105
- $('div.modal-dialog').append(contactDetailsView.$el);
106
- $('#contactModal').modal('show');
107
- },
108
-
109
- editContactMedia: function(e) {
110
- e.stopImmediatePropagation();
111
- // skip if modal showing
112
- if ( $('#contactModal').hasClass('in') ) { return; }
113
-
114
- var context = this;
115
-
116
- var deferreds = this.model.resolveLinks({media: Medium.List});
117
-
118
- $.when.apply($, deferreds).done(
119
- function() {
120
- var media = context.model.linked['media'];
121
-
122
- var mediaMain = new Contact.Views.Media({collection: media, contact: context.model});
123
- $('div.modal-dialog').append(mediaMain.render().$el);
124
-
125
- $('#contactModal').on('hidden.bs.modal', function() {
126
- mediaMain.trigger('close');
127
- });
128
-
129
- $('#contactModal').modal('show');
130
- }
131
- );
132
-
133
- },
134
-
135
- editContactEntities: function(e) {
136
- e.stopImmediatePropagation();
137
- // skip if modal showing
138
- if ( $('#contactModal').hasClass('in') ) { return; }
139
-
140
- var deferreds = this.model.resolveLinks({entities: Entity.List});
141
-
142
- var allEntities = new Entity.List();
143
-
144
- deferreds.push(allEntities.fetch());
145
-
146
- var context = this.model;
147
-
148
- $.when.apply($, deferreds).done(
149
- function() {
150
- var entities = context.linked['entities'];
151
-
152
- var entitiesView = new Contact.Views.Entities({contact: context, current: entities, all: allEntities});
153
- $('div.modal-dialog').append(entitiesView.render().$el);
154
-
155
- $('#contactModal').modal('show');
156
- }
157
- );
158
- },
159
-
160
- removeContact: function(e) {
161
- e.stopImmediatePropagation();
162
- this.model.destroy();
163
- }
164
-
165
- });
166
-
167
- Contact.Views.ContactDetails = Backbone.View.extend({
168
- events: {
169
- "input input[name='contact_first_name'],input[name='contact_last_name']" : 'updateAcceptButton',
170
- "change input[name='contact_first_name']" : 'setFirstName',
171
- "change input[name='contact_last_name']" : 'setLastName',
172
- "click button#contactCancel" : 'cancel',
173
- "click button#contactAccept" : 'accept',
174
- },
175
- updateAcceptButton: function(event) {
176
- event.stopImmediatePropagation();
177
-
178
- var firstNameVal = $("input[name='contact_first_name']").val();
179
- var firstNameInvalid = _.isUndefined(firstNameVal) || _.isNull(firstNameVal) || _.isEmpty(firstNameVal);
180
-
181
- var lastNameVal = $("input[name='contact_last_name']").val();
182
- var lastNameInvalid = _.isUndefined(lastNameVal) || _.isNull(lastNameVal) || _.isEmpty(lastNameVal);
183
-
184
- $('button#contactAccept').prop('disabled', firstNameInvalid || lastNameInvalid);
185
- },
186
- setFirstName: function(event) {
187
- event.stopImmediatePropagation();
188
- this.model.set('first_name', $(event.target).val());
189
- },
190
- setLastName: function(event) {
191
- event.stopImmediatePropagation();
192
- this.model.set('last_name', $(event.target).val());
193
- },
194
- cancel: function(event) {
195
- event.stopImmediatePropagation();
196
- $('#contactModal').modal('hide');
197
- if ( this.model.dirty ) {
198
- this.model.revertClean();
199
- }
200
- },
201
- accept: function(event) {
202
- event.stopImmediatePropagation();
203
-
204
- $(event.target).prop('disabled', true);
205
-
206
- if ( this.model.isNew() ) {
207
- var save_success = function(model, response, options) {
208
- model.setPersisted(true);
209
- flapjack.contactList.add(model);
210
- $('#contactModal').modal('hide');
211
- };
212
- var save_error = function(model, response, options) {
213
- };
214
-
215
- this.model.save({}, {success: save_success, error: save_error});
216
- } else {
217
-
218
- if ( _.isUndefined(this.model.clean) ) {
219
- $('#contactModal').modal('hide');
220
- } else {
221
- var changedAttrKeys = _.keys(this.model.clean);
222
- if (changedAttrKeys.length > 0) {
223
- var save_success = function(data, response, options) {
224
- $('#contactModal').modal('hide');
225
- };
226
- var save_error = function(data, response, options) {
227
- };
228
- var attrs = _.pick(this.model.attributes, changedAttrKeys);
229
- this.model.patch('contacts', attrs, {success: save_success, error: save_error});
230
- } else {
231
- $('#contactModal').modal('hide');
232
- }
233
- }
234
- }
235
-
236
- },
237
- initialize: function() {
238
- this.template = _.template($('#contact-details-form-template').html());
239
- },
240
- render: function() {
241
- var template_values = _.clone(this.model.attributes);
242
- template_values['is_new'] = this.model.isNew();
243
- template_values['is_valid'] = this.model.isValid();
244
-
245
- this.$el.html(this.template(template_values));
246
-
247
- return this;
248
- }
249
-
250
- });
251
-
252
- Contact.Views.Media = Backbone.View.extend({
253
- initialize: function(options) {
254
- this.options = options || {};
255
- this.template = _.template($('#contact-media-template').html());
256
- },
257
- events: {
258
- 'close' : 'revert',
259
- },
260
- revert: function() {
261
- if ( !_.isUndefined(this.mediaList) ) {
262
- this.mediaList.trigger('revert');
263
- }
264
- },
265
- render: function() {
266
- var template_values = _.clone(this.options.contact.attributes);
267
- this.$el.html(this.template(template_values));
268
-
269
- this.mediaList = new Contact.Views.MediaList({collection: this.options.collection, contact: this.options.contact});
270
- this.$el.find('tbody#contactMediaList').replaceWith(this.mediaList.render().$el);
271
-
272
- return this;
273
- }
274
- });
275
-
276
- Contact.Views.MediaList = Backbone.View.extend({
277
- tagName: 'tbody',
278
- id: 'contactMediaList',
279
- initialize: function(options) {
280
- var context = this;
281
-
282
- _.each(['email', 'sms', 'slack', 'sms_twilio', 'sms_nexmo', 'sns', 'jabber'], function(type) {
283
- var medium = context.collection.find(function(cm) {
284
- return cm.get('type') == type;
285
- });
286
-
287
- if ( _.isUndefined(medium) ) {
288
- medium = new Medium.Model({
289
- type: type,
290
- address: '',
291
- interval: 15,
292
- rollup_threshold: 3
293
- });
294
- medium.setPersisted(false);
295
- medium.set('id', options.contact.get('id') + '_' + type);
296
- context.collection.add(medium);
297
- }
298
- medium.contact = options.contact;
299
- });
300
- },
301
- events: {
302
- 'revert' : 'revertUnsaved'
303
- },
304
- render: function() {
305
- var jqel = $(this.el);
306
- jqel.empty();
307
-
308
- this.collection.each(function(medium) {
309
- var item = new Contact.Views.MediaListItem({ model: medium });
310
- jqel.append(item.render().el);
311
- });
312
-
313
- return this;
314
- },
315
- revertUnsaved: function() {
316
- this.collection.each(function(medium) {
317
- medium.revertClean();
318
- });
319
- }
320
- });
321
-
322
- Contact.Views.MediaListItem = Backbone.View.extend({
323
- tagName: 'tr',
324
- events: {
325
- "change input[data-attr='address']" : 'setAddress',
326
- "change input[data-attr='interval']" : 'setInterval',
327
- "change input[data-attr='rollup_threshold']" : 'setRollupThreshold'
328
- },
329
- initialize: function() {
330
- this.template = _.template($('#contact-media-list-item-template').html());
331
- },
332
- render: function() {
333
- var template_values = _.clone(this.model.attributes);
334
- template_values['labels'] = {
335
- 'email' : 'Email',
336
- 'sms' : 'SMS (MessageNet)',
337
- 'slack' : 'Slack',
338
- 'sms_twilio' : 'SMS (Twilio)',
339
- 'sms_nexmo' : 'SMS (Nexmo)',
340
- 'sns' : 'SMS (Amazon SNS)',
341
- 'jabber' : 'Jabber'
342
- };
343
- this.$el.html(this.template(template_values));
344
- return this;
345
- },
346
-
347
- setAddress: function(event) {
348
- this.model.set('address', $(event.target).val());
349
- if ( this.model.isValid() ) { this.addOrUpdate(this.model); }
350
- },
351
- setInterval: function(event) {
352
- this.model.set('interval', $(event.target).val());
353
- if ( this.model.isValid() ) { this.addOrUpdate(this.model); }
354
- },
355
- setRollupThreshold: function(event) {
356
- this.model.set('rollup_threshold', $(event.target).val());
357
- if ( this.model.isValid() ) { this.addOrUpdate(this.model); }
358
- },
359
- addOrUpdate: function(model) {
360
- var changedAttrKeys = _.keys(model.clean);
361
- var attrs = _.pick(model.attributes, changedAttrKeys);
362
- if ( model.isNew() ) {
363
- model.save(attrs);
364
- model.setPersisted(true);
365
- model.contact.addLinked('contacts', 'media', model);
366
- } else {
367
- model.patch('media', attrs);
368
- }
369
- }
370
- });
371
-
372
- Contact.Views.Entities = Backbone.View.extend({
373
- initialize: function(options) {
374
- this.options = options || {};
375
- this.template = _.template($('#contact-entities-template').html());
376
- },
377
- render: function() {
378
- var template_values = _.clone(this.options.contact.attributes);
379
- this.$el.html(this.template(template_values));
380
-
381
- var entityChooser = new Contact.Views.EntityChooser({contact: this.options.contact, current: this.options.current, all: this.options.all});
382
- this.$el.find('div#contactEntityChooser').replaceWith(entityChooser.render().$el);
383
-
384
- var entityList = new Contact.Views.EntityList({contact: this.options.contact, collection: this.options.current});
385
- this.$el.find('tbody#contactEntityList').replaceWith(entityList.render().$el);
386
-
387
- return this;
388
- }
389
-
390
- });
391
-
392
- // this.model == current contact
393
- // this.collection == duplicate of entities with
394
- // entities enabled for this contact removed
395
- Contact.Views.EntityChooser = Backbone.View.extend({
396
- id: "contactEntityChooser",
397
- events: {
398
- 'click button#add-contact-entity' : 'addEntities',
399
- 'change input#entityChooser' : 'chooserChanged'
400
- },
401
- initialize: function(options) {
402
- this.options = options || {};
403
- this.template = _.template($('#contact-entities-chooser-template').html());
404
- this.listenTo(options.current, 'add', this.refresh);
405
- this.listenTo(options.current, 'remove', this.refresh);
406
- },
407
- chooserChanged: function(e) {
408
- if ( !_.isArray(e.removed) && _.isObject(e.removed) ) {
409
- this.entityIdsToAdd = _.without(this.entityIdsToAdd, e.removed.id);
410
- }
411
-
412
- if ( !_.isArray(e.added) && _.isObject(e.added) && (this.entityIdsToAdd.indexOf(e.added.id) == -1) ) {
413
- this.entityIdsToAdd.push(e.added.id);
414
- }
415
- },
416
- render: function() {
417
- this.calculate();
418
-
419
- // clear array
420
- this.entityIdsToAdd = new Array();
421
-
422
- this.$el.html(this.template({}));
423
-
424
- var jqel = $(this.el).find('input#entityChooser');
425
-
426
- var format = function(item) { return item.name; }
427
- var context = this;
428
-
429
- jqel.select2({
430
- placeholder: "Select Entities",
431
- data: {results: context.results, text: 'name'},
432
- formatSelection: format,
433
- formatResult: format,
434
- multiple: true,
435
- width: 'off',
436
- });
437
-
438
- return this;
439
- },
440
- calculate: function() {
441
- var contact_entity_ids = this.options.current.pluck('id');
442
-
443
- var some = this.options.all.reject(function(item, context) {
444
- return _.contains(contact_entity_ids, item.get('id'));
445
- });
446
-
447
- this.collection = new Entity.List(some);
448
-
449
- this.results = this.collection.map( function(item) {
450
- return item.attributes;
451
- });
452
- },
453
- refresh: function(model, collection, options) {
454
- this.calculate();
455
- var jqel = $(this.el).find('input#entityChooser');
456
- var context = this;
457
- var format = function(item) { return item.name; }
458
- jqel.select2({
459
- placeholder: "Select Entities",
460
- data: {results: context.results, text: 'name'},
461
- formatSelection: format,
462
- formatResult: format,
463
- multiple: true,
464
- width: 'off',
465
- });
466
- },
467
- addEntities: function() {
468
- var jqel = $(this.el).find('input#entityChooser');
469
- jqel.select2("val", null);
470
- var context = this;
471
- _.each(this.entityIdsToAdd, function(entity_id) {
472
- var newEntity = context.options.all.find(function(entity) { return entity.id == entity_id; });
473
- context.options.contact.addLinked('contacts', 'entities', newEntity);
474
- });
475
- this.entityIdsToAdd.length = 0;
476
- }
477
- });
478
-
479
- Contact.Views.EntityList = Backbone.View.extend({
480
- tagName: 'tbody',
481
- id: 'contactEntityList',
482
- initialize: function(options) {
483
- this.options = options || {};
484
- this.collection.on('add', this.render, this);
485
- this.collection.on('remove', this.render, this);
486
- },
487
- render: function() {
488
- var jqel = $(this.el);
489
- jqel.empty();
490
- var contact = this.options.contact;
491
- this.collection.each(function(entity) {
492
- var item = new Contact.Views.EntityListItem({ model: entity, contact: contact });
493
- jqel.append(item.render().el);
494
- });
495
-
496
- return this;
497
- }
498
- });
499
-
500
- Contact.Views.EntityListItem = Backbone.View.extend({
501
- tagName: 'tr',
502
- events: {
503
- 'click button.delete-entity' : 'removeEntity',
504
- },
505
- initialize: function(options) {
506
- this.options = options || {};
507
- this.template = _.template($('#contact-entities-list-item-template').html());
508
- },
509
- render: function() {
510
- var template_values = _.clone(this.model.attributes);
511
- this.$el.html(this.template(template_values));
512
- return this;
513
- },
514
- removeEntity: function() {
515
- this.options.contact.removeLinked('contacts', 'entities', this.model);
516
- this.$el.remove();
517
- }
518
- });
519
-
520
- })(flapjack, flapjack.module("contact"));