heart 0.0.1.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. data/MIT-LICENSE +21 -0
  2. data/README.rdoc +3 -0
  3. data/Rakefile +40 -0
  4. data/app/assets/images/heart/add.png +0 -0
  5. data/app/assets/images/heart/bluestar.png +0 -0
  6. data/app/assets/images/heart/bricks.png +0 -0
  7. data/app/assets/images/heart/bricks_off.png +0 -0
  8. data/app/assets/images/heart/chart_bar.png +0 -0
  9. data/app/assets/images/heart/chart_bar_off.png +0 -0
  10. data/app/assets/images/heart/chart_curve.png +0 -0
  11. data/app/assets/images/heart/chart_curve_off.png +0 -0
  12. data/app/assets/images/heart/chart_line.png +0 -0
  13. data/app/assets/images/heart/chart_line_off.png +0 -0
  14. data/app/assets/images/heart/chart_pie.png +0 -0
  15. data/app/assets/images/heart/chart_pie_off.png +0 -0
  16. data/app/assets/images/heart/collapse.png +0 -0
  17. data/app/assets/images/heart/dashboard.png +0 -0
  18. data/app/assets/images/heart/delete.png +0 -0
  19. data/app/assets/images/heart/disk.png +0 -0
  20. data/app/assets/images/heart/expand.png +0 -0
  21. data/app/assets/images/heart/jp.png +0 -0
  22. data/app/assets/images/heart/page_white_excel.png +0 -0
  23. data/app/assets/images/heart/paintcan.png +0 -0
  24. data/app/assets/images/heart/paintcan_off.png +0 -0
  25. data/app/assets/images/heart/pencil.png +0 -0
  26. data/app/assets/images/heart/picture.png +0 -0
  27. data/app/assets/images/heart/table.png +0 -0
  28. data/app/assets/images/heart/tag.png +0 -0
  29. data/app/assets/images/heart/tooltip/columnBg.png +0 -0
  30. data/app/assets/images/heart/tooltip/columnTop.gif +0 -0
  31. data/app/assets/images/heart/tooltip/tipBtm.png +0 -0
  32. data/app/assets/images/heart/tooltip/tipBtm280.png +0 -0
  33. data/app/assets/images/heart/tooltip/tipBtm280b.png +0 -0
  34. data/app/assets/images/heart/tooltip/tipMid.png +0 -0
  35. data/app/assets/images/heart/tooltip/tipMid280.png +0 -0
  36. data/app/assets/images/heart/tooltip/tipMid280b.png +0 -0
  37. data/app/assets/images/heart/tooltip/tipMid280g.png +0 -0
  38. data/app/assets/images/heart/tooltip/tipMid280w.png +0 -0
  39. data/app/assets/images/heart/tooltip/tipTop.png +0 -0
  40. data/app/assets/images/heart/tooltip/tipTop280.png +0 -0
  41. data/app/assets/images/heart/tooltip/tipTop280b.png +0 -0
  42. data/app/assets/images/heart/us.png +0 -0
  43. data/app/assets/images/heart/zoom.png +0 -0
  44. data/app/assets/images/heart/zoom_off.png +0 -0
  45. data/app/assets/javascripts/heart/application.js +201 -0
  46. data/app/assets/javascripts/heart/flot/jquery.colorhelpers.min.js +1 -0
  47. data/app/assets/javascripts/heart/flot/jquery.flot.annotate.js +136 -0
  48. data/app/assets/javascripts/heart/flot/jquery.flot.crosshair.min.js +1 -0
  49. data/app/assets/javascripts/heart/flot/jquery.flot.fillbetween.js +183 -0
  50. data/app/assets/javascripts/heart/flot/jquery.flot.growing.js +140 -0
  51. data/app/assets/javascripts/heart/flot/jquery.flot.js +2651 -0
  52. data/app/assets/javascripts/heart/flot/jquery.flot.navigate.js +336 -0
  53. data/app/assets/javascripts/heart/flot/jquery.flot.pie.js +751 -0
  54. data/app/assets/javascripts/heart/flot/jquery.flot.resize.js +60 -0
  55. data/app/assets/javascripts/heart/flot/jquery.flot.selection.min.js +1 -0
  56. data/app/assets/javascripts/heart/flot/jquery.flot.stack.min.js +1 -0
  57. data/app/assets/javascripts/heart/flot/jquery.flot.symbols.js +85 -0
  58. data/app/assets/javascripts/heart/flot/jquery.flot.threshold.min.js +1 -0
  59. data/app/assets/javascripts/heart/heart.js +664 -0
  60. data/app/assets/javascripts/heart/jquery-1-5-2.js +16 -0
  61. data/app/assets/javascripts/heart/jquery-ui-1.8.7.custom.min.js +781 -0
  62. data/app/assets/javascripts/heart/jquery.betterTooltip.js +108 -0
  63. data/app/assets/javascripts/heart/json2.js +480 -0
  64. data/app/assets/stylesheets/heart/application.css +13 -0
  65. data/app/assets/stylesheets/heart/bluetrip/css/ie.css +29 -0
  66. data/app/assets/stylesheets/heart/bluetrip/css/print.css +46 -0
  67. data/app/assets/stylesheets/heart/bluetrip/css/screen.css +321 -0
  68. data/app/assets/stylesheets/heart/bluetrip/images/grid.png +0 -0
  69. data/app/assets/stylesheets/heart/bluetrip/images/grid.psd +0 -0
  70. data/app/assets/stylesheets/heart/bluetrip/images/icons/cross.png +0 -0
  71. data/app/assets/stylesheets/heart/bluetrip/images/icons/doc.png +0 -0
  72. data/app/assets/stylesheets/heart/bluetrip/images/icons/email.png +0 -0
  73. data/app/assets/stylesheets/heart/bluetrip/images/icons/external.png +0 -0
  74. data/app/assets/stylesheets/heart/bluetrip/images/icons/feed.png +0 -0
  75. data/app/assets/stylesheets/heart/bluetrip/images/icons/im.png +0 -0
  76. data/app/assets/stylesheets/heart/bluetrip/images/icons/information.png +0 -0
  77. data/app/assets/stylesheets/heart/bluetrip/images/icons/key.png +0 -0
  78. data/app/assets/stylesheets/heart/bluetrip/images/icons/pdf.png +0 -0
  79. data/app/assets/stylesheets/heart/bluetrip/images/icons/tick.png +0 -0
  80. data/app/assets/stylesheets/heart/bluetrip/images/icons/visited.png +0 -0
  81. data/app/assets/stylesheets/heart/bluetrip/images/icons/xls.png +0 -0
  82. data/app/assets/stylesheets/heart/bluetrip/images/test-small.jpg +0 -0
  83. data/app/assets/stylesheets/heart/buttons.css +821 -0
  84. data/app/assets/stylesheets/heart/heart.css.erb +480 -0
  85. data/app/assets/stylesheets/heart/start/images/ui-bg_flat_55_999999_40x100.png +0 -0
  86. data/app/assets/stylesheets/heart/start/images/ui-bg_flat_75_aaaaaa_40x100.png +0 -0
  87. data/app/assets/stylesheets/heart/start/images/ui-bg_glass_45_0078ae_1x400.png +0 -0
  88. data/app/assets/stylesheets/heart/start/images/ui-bg_glass_55_f8da4e_1x400.png +0 -0
  89. data/app/assets/stylesheets/heart/start/images/ui-bg_glass_75_79c9ec_1x400.png +0 -0
  90. data/app/assets/stylesheets/heart/start/images/ui-bg_gloss-wave_45_e14f1c_500x100.png +0 -0
  91. data/app/assets/stylesheets/heart/start/images/ui-bg_gloss-wave_50_6eac2c_500x100.png +0 -0
  92. data/app/assets/stylesheets/heart/start/images/ui-bg_gloss-wave_75_2191c0_500x100.png +0 -0
  93. data/app/assets/stylesheets/heart/start/images/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  94. data/app/assets/stylesheets/heart/start/images/ui-icons_0078ae_256x240.png +0 -0
  95. data/app/assets/stylesheets/heart/start/images/ui-icons_056b93_256x240.png +0 -0
  96. data/app/assets/stylesheets/heart/start/images/ui-icons_d8e7f3_256x240.png +0 -0
  97. data/app/assets/stylesheets/heart/start/images/ui-icons_e0fdff_256x240.png +0 -0
  98. data/app/assets/stylesheets/heart/start/images/ui-icons_f5e175_256x240.png +0 -0
  99. data/app/assets/stylesheets/heart/start/images/ui-icons_f7a50d_256x240.png +0 -0
  100. data/app/assets/stylesheets/heart/start/images/ui-icons_fcd113_256x240.png +0 -0
  101. data/app/assets/stylesheets/heart/start/jquery-ui-1.8.7.custom.css +572 -0
  102. data/app/controllers/heart/annotations_controller.rb +22 -0
  103. data/app/controllers/heart/application_controller.rb +21 -0
  104. data/app/controllers/heart/dashboards_controller.rb +85 -0
  105. data/app/controllers/heart/images_controller.rb +19 -0
  106. data/app/controllers/heart/metrics_controller.rb +35 -0
  107. data/app/helpers/heart/application_helper.rb +13 -0
  108. data/app/helpers/heart/dashboards_helper.rb +106 -0
  109. data/app/models/heart/annotation.rb +19 -0
  110. data/app/models/heart/application.rb +5 -0
  111. data/app/models/heart/dashboard.rb +6 -0
  112. data/app/models/heart/image.rb +5 -0
  113. data/app/models/heart/isometric.rb +8 -0
  114. data/app/models/heart/metric.rb +138 -0
  115. data/app/views/heart/annotations/create.js.haml +1 -0
  116. data/app/views/heart/annotations/description.js.haml +2 -0
  117. data/app/views/heart/dashboards/_annotation.haml +13 -0
  118. data/app/views/heart/dashboards/_dashblock.haml +17 -0
  119. data/app/views/heart/dashboards/_dashboard_form.html.haml +89 -0
  120. data/app/views/heart/dashboards/_graph_options.html.haml +24 -0
  121. data/app/views/heart/dashboards/_heart_form.html.haml +100 -0
  122. data/app/views/heart/dashboards/default.html.haml +32 -0
  123. data/app/views/heart/dashboards/edit.html.haml +14 -0
  124. data/app/views/heart/dashboards/flotit.js.haml +6 -0
  125. data/app/views/heart/dashboards/index.html.haml +19 -0
  126. data/app/views/heart/dashboards/new.html.haml +3 -0
  127. data/app/views/heart/dashboards/show.html.haml +65 -0
  128. data/app/views/heart/metrics/cache.html.haml +3 -0
  129. data/app/views/heart/metrics/fetch.html.haml +2 -0
  130. data/app/views/heart/metrics/index.html.haml +12 -0
  131. data/app/views/heart/metrics/show.html.haml +25 -0
  132. data/app/views/layouts/heart_engine.html.haml +88 -0
  133. data/config/cucumber.yml +8 -0
  134. data/config/locales/en.yml +63 -0
  135. data/config/locales/ja.yml +63 -0
  136. data/config/routes.rb +25 -0
  137. data/db/migrate/20130902050854_create_heart_metrics.rb +16 -0
  138. data/db/migrate/20130902051427_create_heart_isometrics.rb +9 -0
  139. data/db/migrate/20130902080256_create_heart_dashboards.rb +13 -0
  140. data/db/migrate/20130902080823_create_heart_annotations.rb +10 -0
  141. data/db/migrate/20130902081206_create_heart_images.rb +11 -0
  142. data/lib/heart/engine.rb +22 -0
  143. data/lib/heart/version.rb +3 -0
  144. data/lib/heart.rb +4 -0
  145. data/lib/tasks/cucumber.rake +65 -0
  146. data/lib/tasks/heart_tasks.rake +85 -0
  147. data/test/dummy/README.rdoc +261 -0
  148. data/test/dummy/Rakefile +7 -0
  149. data/test/dummy/app/assets/javascripts/application.js +15 -0
  150. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  151. data/test/dummy/app/controllers/application_controller.rb +3 -0
  152. data/test/dummy/app/helpers/application_helper.rb +2 -0
  153. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  154. data/test/dummy/config/application.rb +59 -0
  155. data/test/dummy/config/boot.rb +10 -0
  156. data/test/dummy/config/database.yml +21 -0
  157. data/test/dummy/config/environment.rb +5 -0
  158. data/test/dummy/config/environments/development.rb +37 -0
  159. data/test/dummy/config/environments/production.rb +67 -0
  160. data/test/dummy/config/environments/test.rb +37 -0
  161. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  162. data/test/dummy/config/initializers/inflections.rb +15 -0
  163. data/test/dummy/config/initializers/mime_types.rb +5 -0
  164. data/test/dummy/config/initializers/secret_token.rb +7 -0
  165. data/test/dummy/config/initializers/session_store.rb +8 -0
  166. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  167. data/test/dummy/config/locales/en.yml +5 -0
  168. data/test/dummy/config/routes.rb +4 -0
  169. data/test/dummy/config.ru +4 -0
  170. data/test/dummy/db/development.sqlite3 +0 -0
  171. data/test/dummy/db/migrate/20130902083555_create_heart_metrics.heart.rb +17 -0
  172. data/test/dummy/db/migrate/20130902083556_create_heart_isometrics.heart.rb +10 -0
  173. data/test/dummy/db/migrate/20130902083557_create_heart_dashboards.heart.rb +14 -0
  174. data/test/dummy/db/migrate/20130902083558_create_heart_annotations.heart.rb +11 -0
  175. data/test/dummy/db/migrate/20130902083559_create_heart_images.heart.rb +12 -0
  176. data/test/dummy/db/migrate/20130902083560_create_heart_configurations.heart.rb +12 -0
  177. data/test/dummy/db/migrate/20130902084029_add_posts_new_to_metrics.rb +10 -0
  178. data/test/dummy/db/schema.rb +76 -0
  179. data/test/dummy/db/test.sqlite3 +0 -0
  180. data/test/dummy/features/dashboards/overview.feature +39 -0
  181. data/test/dummy/features/language_switching.feature +12 -0
  182. data/test/dummy/features/link_to_this.feature +6 -0
  183. data/test/dummy/features/metrics/exporting.feature +13 -0
  184. data/test/dummy/features/metrics/fetching.feature +0 -0
  185. data/test/dummy/features/metrics/graphing.feature +13 -0
  186. data/test/dummy/features/metrics/summing.feature +0 -0
  187. data/test/dummy/features/step_definitions/dashboard_steps.rb +76 -0
  188. data/test/dummy/features/step_definitions/exporting_steps.rb +24 -0
  189. data/test/dummy/features/step_definitions/generic_steps.rb.example +101 -0
  190. data/test/dummy/features/step_definitions/graphing_steps.rb +37 -0
  191. data/test/dummy/features/step_definitions/language_switching_steps.rb +26 -0
  192. data/test/dummy/features/step_definitions/link_to_steps.rb +12 -0
  193. data/test/dummy/features/support/env.rb +64 -0
  194. data/test/dummy/features/support/factories.rb +16 -0
  195. data/test/dummy/features/support/hooks.rb +3 -0
  196. data/test/dummy/features/support/world_extensions.rb +1 -0
  197. data/test/dummy/log/development.log +549 -0
  198. data/test/dummy/log/test.log +19866 -0
  199. data/test/dummy/public/404.html +26 -0
  200. data/test/dummy/public/422.html +26 -0
  201. data/test/dummy/public/500.html +25 -0
  202. data/test/dummy/public/favicon.ico +0 -0
  203. data/test/dummy/script/rails +6 -0
  204. data/test/dummy/tmp/cache/assets/B7A/D60/sprockets%2F12305388866122331aea456101382236 +0 -0
  205. data/test/dummy/tmp/cache/assets/BE3/050/sprockets%2F0421426926cdd29806245aa078142462 +0 -0
  206. data/test/dummy/tmp/cache/assets/C3E/2A0/sprockets%2Fe37f35746618667d995a3587734e1f14 +0 -0
  207. data/test/dummy/tmp/cache/assets/C4F/0C0/sprockets%2Fb0695bc459d01217161ae9028368b856 +0 -0
  208. data/test/dummy/tmp/cache/assets/C57/200/sprockets%2F2e442476c863f14144881e259b1b597a +0 -0
  209. data/test/dummy/tmp/cache/assets/C61/A80/sprockets%2F7f20dd76170d803754a3085694f669e6 +0 -0
  210. data/test/dummy/tmp/cache/assets/C6B/710/sprockets%2F61a084f53ca308b115c54491f5b38120 +0 -0
  211. data/test/dummy/tmp/cache/assets/C76/680/sprockets%2Fb72c325230e403c89a229efd94013438 +0 -0
  212. data/test/dummy/tmp/cache/assets/C7D/AD0/sprockets%2Fa702e8b86f4697101583ea24307b7a53 +0 -0
  213. data/test/dummy/tmp/cache/assets/C81/4B0/sprockets%2F115a9d464b8720982880ad4926aaf505 +0 -0
  214. data/test/dummy/tmp/cache/assets/C83/670/sprockets%2F125f9496da25b06ace8951e752253273 +0 -0
  215. data/test/dummy/tmp/cache/assets/C86/DC0/sprockets%2F26269d2349fba3c41619fe3e88363044 +0 -0
  216. data/test/dummy/tmp/cache/assets/CA6/170/sprockets%2F6e0bb6a54c8f40c3419b183772c73331 +0 -0
  217. data/test/dummy/tmp/cache/assets/CAF/B10/sprockets%2F68ee8201881a1c1d3d987490e5015ed0 +0 -0
  218. data/test/dummy/tmp/cache/assets/CB6/080/sprockets%2F735f5d59ce0703357780bf4a574490ca +0 -0
  219. data/test/dummy/tmp/cache/assets/CB6/490/sprockets%2Fc4b6a866f5d3627d2a186e2095e60717 +0 -0
  220. data/test/dummy/tmp/cache/assets/CB9/9E0/sprockets%2F7a20a269f11f7331c8a56908c68f18d9 +0 -0
  221. data/test/dummy/tmp/cache/assets/CBB/950/sprockets%2F575827e14ba8d9920284eae267874ca1 +0 -0
  222. data/test/dummy/tmp/cache/assets/CBE/3A0/sprockets%2F73bdae55823e56e6f3796265941b36d1 +0 -0
  223. data/test/dummy/tmp/cache/assets/CC2/A70/sprockets%2F99163775fcea80cf5530f8808188e40b +0 -0
  224. data/test/dummy/tmp/cache/assets/CCB/970/sprockets%2F472690f680dd7d91690ebf603f7685e8 +0 -0
  225. data/test/dummy/tmp/cache/assets/CCB/CA0/sprockets%2F9b705933be3255cfd4938a9c99146e69 +0 -0
  226. data/test/dummy/tmp/cache/assets/CCF/FE0/sprockets%2Fea0015147c89d0181ba9460464bbf08c +0 -0
  227. data/test/dummy/tmp/cache/assets/CD1/1C0/sprockets%2F675a331d19ae21eaa532b27aa7606955 +0 -0
  228. data/test/dummy/tmp/cache/assets/CD1/320/sprockets%2Fb09e869800e3e0a0d7805d4c1c7113d1 +0 -0
  229. data/test/dummy/tmp/cache/assets/CD5/1C0/sprockets%2F9a8012934e9d2f70a66c43310e3e44ab +0 -0
  230. data/test/dummy/tmp/cache/assets/CD7/270/sprockets%2F3bc51cb676bca1416770598d28109fa0 +0 -0
  231. data/test/dummy/tmp/cache/assets/CE0/E50/sprockets%2F9814922a41a67b828e462b31accb38f8 +0 -0
  232. data/test/dummy/tmp/cache/assets/CE3/A70/sprockets%2F87a37405e84d5a30dd672cf6148ec119 +0 -0
  233. data/test/dummy/tmp/cache/assets/CE4/050/sprockets%2F21d0ae6e0a782753af4ed2492e959671 +0 -0
  234. data/test/dummy/tmp/cache/assets/CE4/D80/sprockets%2Fa98448b0f9e10bf393a552d26664d7a3 +0 -0
  235. data/test/dummy/tmp/cache/assets/CE7/F80/sprockets%2F7715072387d4d8e6193c2ffda13a375f +0 -0
  236. data/test/dummy/tmp/cache/assets/CE8/890/sprockets%2F394187006c387afef0429558db43bf4e +0 -0
  237. data/test/dummy/tmp/cache/assets/CE8/CE0/sprockets%2F5c698abb053124d9a5421666bf75c8f8 +0 -0
  238. data/test/dummy/tmp/cache/assets/CF1/7B0/sprockets%2Fa447299b5fa19244e6a281825f9e77dc +0 -0
  239. data/test/dummy/tmp/cache/assets/CF1/CD0/sprockets%2Fd06db0e7d91462ed5ea64694583797e2 +0 -0
  240. data/test/dummy/tmp/cache/assets/CF2/070/sprockets%2Fca7b20d93194b5827d9d57837578b6db +0 -0
  241. data/test/dummy/tmp/cache/assets/CF2/C20/sprockets%2F7b5779909f4f5440c9d0874af23d63db +0 -0
  242. data/test/dummy/tmp/cache/assets/CF4/B20/sprockets%2F604291e761acf24ffb2998f369b176e8 +0 -0
  243. data/test/dummy/tmp/cache/assets/CF6/220/sprockets%2F06bd95eb7a76f96eb2d8c54782607745 +0 -0
  244. data/test/dummy/tmp/cache/assets/CFD/E70/sprockets%2F6cb7d8f69c8c4e1f246868d46f017639 +0 -0
  245. data/test/dummy/tmp/cache/assets/D00/5C0/sprockets%2F9abbd043d031592a556306748dbaeb26 +0 -0
  246. data/test/dummy/tmp/cache/assets/D02/000/sprockets%2F842565584accd26c5572aa1d15b3bb35 +0 -0
  247. data/test/dummy/tmp/cache/assets/D02/7C0/sprockets%2Fa4900a35834e0ab16a2ae17b6887a66d +0 -0
  248. data/test/dummy/tmp/cache/assets/D04/920/sprockets%2F5830c0ccdb2a54d7848283d21f44e2a4 +0 -0
  249. data/test/dummy/tmp/cache/assets/D05/FC0/sprockets%2Fd06631201fe7c8760eea1e3ffd351191 +0 -0
  250. data/test/dummy/tmp/cache/assets/D06/8C0/sprockets%2Faae533655b6c51d0b999ce29015c4c03 +0 -0
  251. data/test/dummy/tmp/cache/assets/D0B/350/sprockets%2F58255cc783163fa49e6caa32e01af293 +0 -0
  252. data/test/dummy/tmp/cache/assets/D0E/560/sprockets%2Ffb853b302b8b8338911fd212f3e9d65a +0 -0
  253. data/test/dummy/tmp/cache/assets/D0F/340/sprockets%2F81d96cf056d0ab1856c588f181b21fe0 +0 -0
  254. data/test/dummy/tmp/cache/assets/D18/460/sprockets%2Fb0145de92306b4c1bedc53aa0030e522 +0 -0
  255. data/test/dummy/tmp/cache/assets/D19/710/sprockets%2F90db64737e5b2ef37757b1cc2e52909d +0 -0
  256. data/test/dummy/tmp/cache/assets/D1C/270/sprockets%2F1475adbe1d4ec03f947d379865d477b3 +0 -0
  257. data/test/dummy/tmp/cache/assets/D27/770/sprockets%2Fa10a1cef30d33ecec13933b36280c548 +0 -0
  258. data/test/dummy/tmp/cache/assets/D27/7B0/sprockets%2F6401357b67027ace91aae0cbcf5e4021 +0 -0
  259. data/test/dummy/tmp/cache/assets/D2B/700/sprockets%2Fe90d34a411e79a9d1b510ae04c80e04e +0 -0
  260. data/test/dummy/tmp/cache/assets/D34/100/sprockets%2F504aeb3e34faa21a7c9fa726264934d3 +0 -0
  261. data/test/dummy/tmp/cache/assets/D35/560/sprockets%2Fa79fc4b2a2293acaa002547e93d9704e +0 -0
  262. data/test/dummy/tmp/cache/assets/D35/F80/sprockets%2Ffb91b5a46525f11e9f6658a0daa005d4 +0 -0
  263. data/test/dummy/tmp/cache/assets/D38/A70/sprockets%2F56d65a0db0739f5f1a215bde93528f0a +0 -0
  264. data/test/dummy/tmp/cache/assets/D3A/A50/sprockets%2F1edbcb279564b5c4a85c13aa6940b279 +0 -0
  265. data/test/dummy/tmp/cache/assets/D3B/A10/sprockets%2F2cecd599ad2374ea47112715ae70ea49 +0 -0
  266. data/test/dummy/tmp/cache/assets/D3B/CF0/sprockets%2F4cac58b5d3abf581ca5857583017d3e1 +0 -0
  267. data/test/dummy/tmp/cache/assets/D3B/EF0/sprockets%2F996d2466d00c1bacc4351f87e2d5e62a +0 -0
  268. data/test/dummy/tmp/cache/assets/D3E/410/sprockets%2F4d2270e9821b7d9658df04c4adbdf214 +0 -0
  269. data/test/dummy/tmp/cache/assets/D43/FC0/sprockets%2F7f972ba9de00917d116bfc1c7126e8d6 +0 -0
  270. data/test/dummy/tmp/cache/assets/D4A/E50/sprockets%2Fa876a03aed98118f76cac6e916ff5423 +0 -0
  271. data/test/dummy/tmp/cache/assets/D4B/310/sprockets%2F3402fd809cbee959fdb8db9950a37342 +0 -0
  272. data/test/dummy/tmp/cache/assets/D4C/E60/sprockets%2Fcd389726cc723176e5547ac75cc3fbc8 +0 -0
  273. data/test/dummy/tmp/cache/assets/D52/590/sprockets%2Fae4195e4fc883e26b828d9c7b525ff42 +0 -0
  274. data/test/dummy/tmp/cache/assets/D52/730/sprockets%2Fd92d03a100128cafe40eb231c3c77ba9 +0 -0
  275. data/test/dummy/tmp/cache/assets/D53/4E0/sprockets%2F6b5c3667b962d3740c9de6a5b9bfc948 +0 -0
  276. data/test/dummy/tmp/cache/assets/D59/B40/sprockets%2F29c73ae2b2a2dcf81b5210703eeed252 +0 -0
  277. data/test/dummy/tmp/cache/assets/D5A/5F0/sprockets%2Fa03a93be0c8545371de91a5cab10fe52 +0 -0
  278. data/test/dummy/tmp/cache/assets/D5D/820/sprockets%2F60c2f35af5ce8dc4ab2a724043fd0373 +0 -0
  279. data/test/dummy/tmp/cache/assets/D5D/C10/sprockets%2Fa56376015a3d663ddeb1c90e3faa901b +0 -0
  280. data/test/dummy/tmp/cache/assets/D5E/030/sprockets%2Fb709d4ed36a3b17b21a42a66ae0098fb +0 -0
  281. data/test/dummy/tmp/cache/assets/D5F/6D0/sprockets%2Ff1f0426663c9048eceaa032dc3f05b5c +0 -0
  282. data/test/dummy/tmp/cache/assets/D64/540/sprockets%2F8b24e4230a33d44ed39d3d4ca015f7ff +0 -0
  283. data/test/dummy/tmp/cache/assets/D66/7D0/sprockets%2F6d2be390800b01686b6aeb7bba686c7b +0 -0
  284. data/test/dummy/tmp/cache/assets/D68/7F0/sprockets%2F35b0c94f2372250feee3c76a8bad07d4 +0 -0
  285. data/test/dummy/tmp/cache/assets/D69/F50/sprockets%2F0fe620b4cef107c5b770d70c5bbe6839 +0 -0
  286. data/test/dummy/tmp/cache/assets/D6A/630/sprockets%2F0e159a9bce743e35c180d0eceac52487 +0 -0
  287. data/test/dummy/tmp/cache/assets/D6F/120/sprockets%2F09730b5eed71a1971eb1ed85f0cd8c28 +0 -0
  288. data/test/dummy/tmp/cache/assets/D73/5A0/sprockets%2F726af59d1d3774cebabf5011f2a9955f +0 -0
  289. data/test/dummy/tmp/cache/assets/D76/410/sprockets%2F3ba75e6fe03df5d227c7e7a54be98720 +0 -0
  290. data/test/dummy/tmp/cache/assets/D76/750/sprockets%2F4422ff4ebec16419ef79a9a9d3f530f0 +0 -0
  291. data/test/dummy/tmp/cache/assets/D78/460/sprockets%2Ff8b234b2bfb694b85d927c693aba7d54 +0 -0
  292. data/test/dummy/tmp/cache/assets/D79/4F0/sprockets%2F0323ebeae0a56602aa023c9bb268b3ab +0 -0
  293. data/test/dummy/tmp/cache/assets/D7B/AF0/sprockets%2Fe1e0818c824997cffe5e04f2bff31e26 +0 -0
  294. data/test/dummy/tmp/cache/assets/D94/590/sprockets%2F95f6b48a4415cb3ab8acc4e0da36750d +0 -0
  295. data/test/dummy/tmp/cache/assets/D99/890/sprockets%2F783e81abd4c0cf96b0642acde9b7202f +0 -0
  296. data/test/dummy/tmp/cache/assets/D9A/FB0/sprockets%2F4bd1e3c2f82a72a0d6f8935ed92aeb60 +0 -0
  297. data/test/dummy/tmp/cache/assets/D9E/A00/sprockets%2Fdb6bd6ed1be390eb760409309a6d79ad +0 -0
  298. data/test/dummy/tmp/cache/assets/D9F/6D0/sprockets%2F6da6b2d77e0c546c69a3bb1720f9b9cd +0 -0
  299. data/test/dummy/tmp/cache/assets/DA1/050/sprockets%2F082944b24f4e6533ce0ce9fa64fadf5b +0 -0
  300. data/test/dummy/tmp/cache/assets/DA5/3B0/sprockets%2Fc5e9c4c0d3563ae2b49bf7cd67f458b1 +0 -0
  301. data/test/dummy/tmp/cache/assets/DAA/300/sprockets%2Ff4ebcefbb66ce3f58d70987c6123523e +0 -0
  302. data/test/dummy/tmp/cache/assets/DB1/C10/sprockets%2Fddabb257ba3637433fc7729f79fe6c9e +0 -0
  303. data/test/dummy/tmp/cache/assets/DB1/C90/sprockets%2Fdf909d50d7a568a1bc9dd9e47baf4973 +0 -0
  304. data/test/dummy/tmp/cache/assets/DB9/800/sprockets%2Fbd0a2a66976fd5ef12be3ac3e22d100e +0 -0
  305. data/test/dummy/tmp/cache/assets/DC2/1D0/sprockets%2F548c5a2d07c2b3db2eea9a24e2e25c9c +0 -0
  306. data/test/dummy/tmp/cache/assets/DC3/C30/sprockets%2F45d3db961ffaa14a7acb04d139f3ae93 +0 -0
  307. data/test/dummy/tmp/cache/assets/DC8/180/sprockets%2F44add687b1c02f2afd55b3dc9d58a04f +0 -0
  308. data/test/dummy/tmp/cache/assets/DCB/0A0/sprockets%2Ffec15e165ae6e45fe4d36b903fccf103 +0 -0
  309. data/test/dummy/tmp/cache/assets/DCC/6C0/sprockets%2F1dd6adb3594e3cf84ce35ea45114ead9 +0 -0
  310. data/test/dummy/tmp/cache/assets/DCD/350/sprockets%2F0a1ad87bab5ab47f377d5f87736acdd2 +0 -0
  311. data/test/dummy/tmp/cache/assets/DCD/ED0/sprockets%2Fe3e1abc488563aa8c2d44c9b8b5b2f6c +0 -0
  312. data/test/dummy/tmp/cache/assets/DD1/620/sprockets%2F3c34c92afb93cab6ab8f1640683ee8fd +0 -0
  313. data/test/dummy/tmp/cache/assets/DD2/2B0/sprockets%2Fcb959dcb42fe971fef3b07705a4de60b +0 -0
  314. data/test/dummy/tmp/cache/assets/DD4/DB0/sprockets%2Fd16e7fa5788cebf2c0335cfb5a94d5b5 +0 -0
  315. data/test/dummy/tmp/cache/assets/DDA/140/sprockets%2F9dab37c1f47e99ba86bf306fbed67c23 +0 -0
  316. data/test/dummy/tmp/cache/assets/DF0/C50/sprockets%2Fc3dee69afa21d4462d0fda717c2f5a1b +0 -0
  317. data/test/dummy/tmp/cache/assets/DF3/CE0/sprockets%2Fd413b4fcbf2a3afe3a2f96fb3b22349f +0 -0
  318. data/test/dummy/tmp/cache/assets/DF5/020/sprockets%2Ffdbfbdaa7be9bc2fa2824455b9f36200 +0 -0
  319. data/test/dummy/tmp/cache/assets/DFB/120/sprockets%2F56abeace37f20e8ed908bb19c26c73ca +0 -0
  320. data/test/dummy/tmp/cache/assets/DFE/9D0/sprockets%2Fdfd5d12ea923dd88dd2fb5c56c2a6a73 +0 -0
  321. data/test/dummy/tmp/cache/assets/E04/670/sprockets%2Fe9e9c736dab1268ea76aed2ba1cf51f9 +0 -0
  322. data/test/dummy/tmp/cache/assets/E11/620/sprockets%2Fb79efcee1bf9f7559d26cc36bcbd6481 +0 -0
  323. data/test/dummy/tmp/cache/assets/E15/B10/sprockets%2F8fded28e5dfea96f7f42212ee4de8d82 +0 -0
  324. data/test/dummy/tmp/cache/assets/E1E/A70/sprockets%2F4a6f52c1cf40efaf040aabe5eca74c86 +0 -0
  325. data/test/dummy/tmp/cache/assets/E2F/B60/sprockets%2F9e9f03eab43fa8aeeb4aa97f1dff2171 +0 -0
  326. data/test/dummy/tmp/cache/assets/E3E/D60/sprockets%2F51bfcacbab0f9acbbcd331e31e095c40 +0 -0
  327. data/test/dummy/tmp/cache/assets/E4E/FE0/sprockets%2Fee2cecebeb842cdbbcfc530d13d50546 +0 -0
  328. data/test/dummy/tmp/cache/assets/E50/170/sprockets%2Faa1cd6441f82b0f9bfa1baffe5ce3c81 +0 -0
  329. data/test/dummy/tmp/cache/assets/E54/7B0/sprockets%2F7eba769afbacdcd2b019e3ae52fdb093 +0 -0
  330. data/test/dummy/tmp/cache/assets/E6C/5E0/sprockets%2F48dce5eee43c4ec8f9daa25a7fb847be +0 -0
  331. data/test/dummy/tmp/cache/assets/E86/5D0/sprockets%2Fec1c00efc9e5ebfa6c0576eb1ddfd60d +0 -0
  332. data/test/dummy/tmp/cache/assets/E8A/510/sprockets%2F4dcf2d4f6fbfe6af61adafbed37240a8 +0 -0
  333. data/test/dummy/tmp/cache/assets/E91/E50/sprockets%2F6caf6f973c4dfd0a94ca97da0cbfb8da +0 -0
  334. data/test/dummy/tmp/cache/assets/F0C/2E0/sprockets%2Fbcad47aa7a1eda0cc0fdc3eac6cb99fd +0 -0
  335. data/test/fixtures/heart/annotations.yml +11 -0
  336. data/test/fixtures/heart/configurations.yml +11 -0
  337. data/test/fixtures/heart/dashboards.yml +11 -0
  338. data/test/fixtures/heart/images.yml +11 -0
  339. data/test/fixtures/heart/isometrics.yml +11 -0
  340. data/test/fixtures/heart/metrics.yml +11 -0
  341. data/test/functional/heart/annotations_controller_test.rb +9 -0
  342. data/test/functional/heart/dashboards_controller_test.rb +9 -0
  343. data/test/functional/heart/images_controller_test.rb +9 -0
  344. data/test/functional/heart/metrics_controller_test.rb +9 -0
  345. data/test/heart_test.rb +7 -0
  346. data/test/integration/navigation_test.rb +10 -0
  347. data/test/test_helper.rb +15 -0
  348. data/test/unit/heart/annotation_test.rb +9 -0
  349. data/test/unit/heart/configuration_test.rb +9 -0
  350. data/test/unit/heart/dashboard_test.rb +9 -0
  351. data/test/unit/heart/image_test.rb +9 -0
  352. data/test/unit/heart/isometric_test.rb +9 -0
  353. data/test/unit/heart/metric_test.rb +9 -0
  354. data/test/unit/helpers/heart/annotations_helper_test.rb +6 -0
  355. data/test/unit/helpers/heart/dashboards_helper_test.rb +6 -0
  356. data/test/unit/helpers/heart/images_helper_test.rb +6 -0
  357. data/test/unit/helpers/heart/metrics_helper_test.rb +6 -0
  358. metadata +791 -0
@@ -0,0 +1,85 @@
1
+ require_dependency "heart/application_controller"
2
+
3
+ module Heart
4
+ class DashboardsController < ApplicationController
5
+
6
+ def default
7
+ end
8
+
9
+ def index
10
+ @dashboards = Heart::Dashboard.active.all
11
+ end
12
+
13
+ def show
14
+ @dashboard = Heart::Dashboard.find(params[:id])
15
+ @charts = ActiveSupport::JSON.decode(@dashboard.dashboard)
16
+ end
17
+
18
+ def new
19
+ end
20
+
21
+ def create
22
+ dashboard = Heart::Dashboard.new()
23
+ dashboard.title = params[:title]
24
+ dashboard.dashboard = params[:charts_serialized]
25
+ dashboard.save
26
+ redirect_to dashboards_path
27
+ end
28
+
29
+ def edit
30
+ @dashboard = Heart::Dashboard.find(params[:id])
31
+ end
32
+
33
+ def update
34
+ dashboard = Heart::Dashboard.find(params[:id])
35
+ dashboard.title = params[:title]
36
+ dashboard.description = params[:description]
37
+ dashboard.dashboard = params[:charts_serialized]
38
+ dashboard.date_from = params[:date_from]
39
+ dashboard.save
40
+ redirect_to dashboards_path
41
+ end
42
+
43
+ def archive
44
+ dashboard = Heart::Dashboard.where(id: params[:dashboard_id]).first
45
+ dashboard.status = Heart::Dashboard::INACTIVE
46
+ dashboard.save
47
+ redirect_to dashboards_path
48
+ end
49
+
50
+ def flotit
51
+ params[:date_from] ||= 30.days.ago.to_s
52
+ params[:date_to] ||= 1.days.ago.to_s
53
+ @annotations = Heart::Annotation.visible(:from => params[:date_from], :to => params[:date_to])
54
+ @description = Heart::Annotation.where(id: params[:description]).first.note if params[:description].to_i > 0
55
+
56
+ # THE WHERE
57
+ where = "WHERE fulldate >= '"+params[:date_from]+"' AND fulldate <= '"+params[:date_to]+"'"
58
+ # THE GROUPBY
59
+ groupby = ""
60
+ if !params[:group_by].empty?
61
+ counter = 0
62
+ params[:group_by].each do |value|
63
+ groupby += "," if counter >= 1
64
+ groupby += " " + value
65
+ counter += 1
66
+ end
67
+ end
68
+ groupby = nil if groupby.empty?
69
+ # THE MEASUREMENTS
70
+ measurements = params[:measurements].empty? ? false : params[:measurements]
71
+
72
+ @metrics = Hash.new
73
+ if params[:moving_averages].kind_of?(Array)
74
+ params[:moving_averages].each do |y|
75
+ if(params[:method_sum] == "true")
76
+ @metrics[y.to_s] = Heart::Metric.aggregate_daily_sums(y, where, groupby, measurements)
77
+ else
78
+ @metrics[y.to_s] = Heart::Metric.aggregate_daily_moving_averages(y, where, groupby, measurements)
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,19 @@
1
+ require_dependency "heart/application_controller"
2
+
3
+ module Heart
4
+ class ImagesController < ApplicationController
5
+ def create
6
+ image = Heart::Image.new
7
+ image.dashboard_id = params[:dashboard_id]
8
+ image.purpose = params[:purpose]
9
+ image.dataurl = params[:dataurl]
10
+ image.save
11
+ render :json => { :result => 'success', :id => image.id }
12
+ end
13
+
14
+ def show
15
+ image = Heart::Image.find(params[:id])
16
+ send_data Base64.decode64(image.dataurl.split(",")[1]), :type => 'image/png', :disposition => 'inline'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ require_dependency "heart/application_controller"
2
+
3
+ module Heart
4
+ class MetricsController < ApplicationController
5
+
6
+ def index
7
+ @metrics = Heart::Metric.recently_added
8
+ end
9
+
10
+ def show
11
+ #restrict the range of dates to prevent a lot useless metric records
12
+ params[:fulldate] = Date.yesterday unless params[:fulldate] <= Date.yesterday.to_s
13
+ @metric = Heart::Metric.find_or_create(params[:fulldate],0)
14
+ @isometric = Heart::Isometric.find_or_create(params[:fulldate],0)
15
+ end
16
+
17
+ def fetch
18
+ method = "fetch_" + params[:attribute].to_s
19
+ params[:enddate] = (params[:enddate].nil?) ? params[:fulldate] : params[:enddate]
20
+ startdate = Date.parse(params[:fulldate].to_s)
21
+ enddate = Date.parse(params[:enddate].to_s)
22
+ startdate.upto(enddate) do |date|
23
+ @metric = Heart::Metric.find_or_create(date,0)
24
+ isometric = Heart::Isometric.find_or_create(date,0)
25
+
26
+ @metric.send(method)
27
+
28
+ @metric.save
29
+ isometric.send(params[:attribute.to_s]+"=", Time.now) unless method == "fetch_all"
30
+ isometric.save unless method == "fetch_all"
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,13 @@
1
+ module Heart
2
+ module ApplicationHelper
3
+
4
+ def current_route?(controller_action)
5
+ if /#/.match(controller_action)
6
+ "current" if "#{controller_name}##{action_name}" == controller_action
7
+ else
8
+ "current" if controller_name == controller_action
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,106 @@
1
+ module Heart
2
+ module DashboardsHelper
3
+
4
+ def check_box_helper(name, value, options, checked=false)
5
+ value = value.to_s
6
+ name = name.to_s
7
+ if params[:review].nil?
8
+ if ["movingaverage[]","annotate[]"].include?(name) && ["0","1","note"].include?(value)
9
+ checked = true
10
+ end
11
+ else
12
+ params.each do |x,y|
13
+ if "#{x}[]" == name && y.include?(value) || x == name
14
+ checked = true
15
+ end
16
+ end
17
+ end
18
+ options['id'] = (options['id'].nil?) ? "#{name.gsub("[]","")}_#{value}" : options['id']
19
+ check_box_tag name, value, checked, options
20
+ end
21
+
22
+ def tool_tip(options)
23
+ "<div class='tipTitle'>#{options[:title]}</div>#{options[:content]}<br /><br /><hr /><div class='center caps'>#{options[:subtitle]}</div>#{options[:footer]}"
24
+ end
25
+
26
+ def to_flot_time(date)
27
+ date.to_time.to_i * 1000
28
+ end
29
+
30
+ # Creates javascript objects to use as hashes for flot graph data series + labels
31
+ def flot_array(metrics)
32
+ replace = false
33
+ hash = Hash.new
34
+ if metrics.nil? || metrics.first.nil? || metrics.first.movingaverage.nil?
35
+ replace = true
36
+ metrics = Metric.aggregate_daily_moving_averages(0, "WHERE fulldate > SUBDATE((SELECT fulldate FROM heart_metrics WHERE movingaverage = 0 ORDER BY fulldate desc LIMIT 1), 3)")
37
+ end
38
+ if metrics.first.nil?
39
+ return ''
40
+ end
41
+ movingaverage = metrics.first.movingaverage
42
+
43
+ #TODO need to move all these options into the HEART js object, set these at runtime, make them easily customizable in the UI
44
+ extraMeasurements = ''
45
+ label_suffix = ''
46
+ if replace == true
47
+ extraMeasurements = "lines : { show : false, fill : false },"
48
+ label_suffix = ''
49
+ else
50
+ if movingaverage.to_i > 0
51
+ extraMeasurements = 'points : { show : false, symbol : "circle" }, lines : { show : true, fill : false },'
52
+ label_suffix = " [MA:#{movingaverage}] "
53
+ end
54
+ end#if replace = true
55
+ #loop through for all the standard measurements
56
+ metrics.first.attributes.sort.each do |att, value|
57
+ next unless value.respond_to? :to_f
58
+ next if value.is_a? Time
59
+ extraSettings = extraMeasurements
60
+ label = t(att) + label_suffix
61
+ hash[att] = "#{att} : {#{extraSettings} label : '#{label}', data : ["
62
+ end
63
+ #
64
+ # Now start creating the data arrays for flot. [date_converted_to_integer, value_of_metric_for_date]
65
+ #
66
+ metrics.each do |metric|
67
+ metric.attributes.sort.each do |att, value|
68
+ next unless value.respond_to? :to_f
69
+ next if value.is_a? Time
70
+ hash[att] = "#{hash[att]} [#{to_flot_time(metric.fulldate)}, #{value}],"
71
+ end
72
+ end
73
+ #
74
+ # Finished creating data arrays
75
+ #
76
+ metrics.first.attributes.sort.each do |att, value|
77
+ next unless value.respond_to? :to_f
78
+ next if value.is_a? Time
79
+ hash[att] = "#{hash[att]} ], att_name : \"#{att}\",},"
80
+ end
81
+
82
+ flotdata = "flotData_#{movingaverage} : {"
83
+ hash.each { |key, value| flotdata += value + "\n" }
84
+ flotdata += "},"
85
+ flotdata
86
+ end
87
+
88
+ def flot_annotations_array(annotation_groups)
89
+ flotdata = ""
90
+ markings = ""
91
+ y_axis = 0
92
+ colors = ["000", "0066ff"]
93
+ annotation_groups.each do |annotations|
94
+ flotdata += "flotDataAnnotationsHash#{y_axis} : { att_name : 'flotDataAnnotationsHash#{y_axis}', note : { lines : { show : false }, points : { show : true, symbol : 'square' }, color: '##{colors[y_axis]}', label : '', data : ["
95
+ annotations.each do |annotation|
96
+ flotdata = flotdata.to_s + ("["+ to_flot_time(annotation.fulldate).to_s + ", #{y_axis},'" + annotation.note.to_s + "'],").to_s
97
+ markings += "{ color: '#000', lineWidth: 1, xaxis: { from: " + to_flot_time(annotation.fulldate).to_s + ", to: " + to_flot_time(annotation.fulldate).to_s + " } },"
98
+ end
99
+ flotdata += "]}},\n "
100
+ y_axis += 1
101
+ end
102
+ flotdata + "markings : [ #{markings}],"
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,19 @@
1
+ module Heart
2
+ class Annotation < Heart::Application
3
+ attr_accessible :fulldate, :note, :dashboard_id
4
+ validate :validate_note
5
+
6
+ def validate_note
7
+ self.note = self.note.to_s.gsub("\n\r","<br />").gsub("\r", "").gsub("\n", "<br />")
8
+ end
9
+
10
+ def self.visible(args)
11
+ from = args[:from].to_date
12
+ to = args[:to].to_date
13
+ dashboard_id = args[:dashboard_id]
14
+ annotations = []
15
+ annotations.push(Annotation.where(:fulldate => from..to).where(:dashboard_id => [nil, dashboard_id]).order("fulldate ASC").all)
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ module Heart
2
+ class Application < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ module Heart
2
+ class Dashboard < Heart::Application
3
+ INACTIVE = 2
4
+ scope :active, lambda { where(:status => nil).where('dashboard != ""') }
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Heart
2
+ class Image < Heart::Application
3
+ # attr_accessible :title, :body
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ module Heart
2
+ class Isometric < Heart::Application
3
+ def self.find_or_create(date,average)
4
+ Heart::Isometric.where(fulldate: date).where(movingaverage: average).first ||
5
+ Heart::Isometric.where(fulldate: date, movingaverage: average)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,138 @@
1
+ module Heart
2
+ class Metric < Heart::Application
3
+ #include metric fetching modules
4
+ Dir["#{Rails.root}/lib/fetch/**/*.rb"].each { |file|
5
+ next if /[0-9]*_*.rb/.match(file.to_s)
6
+ require file
7
+ include ("Fetch::" + File.basename(file).gsub('.rb','').split("_").map{ |ea| ea.capitalize }.join).constantize
8
+ }
9
+
10
+ validates_presence_of :fulldate
11
+ validate :validate_dayofweek, :validate_dayofyear, :validate_weekofyear, :validate_monthofyear, :validate_year, :on => :create
12
+ attr_accessible :fulldate, :movingaverage
13
+
14
+ def validate_dayofweek
15
+ self.dayofweek = self.fulldate.wday
16
+ end
17
+
18
+ def validate_dayofyear
19
+ self.dayofyear = self.fulldate.yday
20
+ end
21
+
22
+ def dayofmonth
23
+ self.fulldate.to_s.slice(8,10)
24
+ end
25
+
26
+ def validate_weekofyear
27
+ self.weekofyear = self.fulldate.cweek
28
+ end
29
+
30
+ def validate_monthofyear
31
+ self.monthofyear = self.fulldate.mon
32
+ end
33
+
34
+ def validate_year
35
+ self.year = self.fulldate.year
36
+ end
37
+
38
+ # returns an array of properties that contain meta data
39
+ def self.metadata
40
+ ["id","fulldate","d","year","monthofyear","month","dayofyear","day","dayofweek","weekofyear","completed_at","movingaverage","created_at","updated_at","deleted_at"]
41
+ end
42
+
43
+ # returns an array of possible GROUP BY fields
44
+ def self.groupbydata
45
+ ["fulldate","dayofyear","dayofweek","weekofyear","monthofyear","year"]
46
+ end
47
+
48
+ def self.recently_added(average=0)
49
+ Metric.where("movingaverage = ?", average).order("fulldate DESC").limit(3)
50
+ end
51
+
52
+ def self.find_or_create(date,average)
53
+ Heart::Metric.where(fulldate: date).where(movingaverage: average).first ||
54
+ Heart::Metric.create(fulldate: date, movingaverage: average)
55
+ end
56
+
57
+ def fetch_all
58
+ isometric = Isometric.find_or_create(self.fulldate,0)
59
+ self.methods.each do |x|
60
+ begin
61
+ if /^fetch_/.match(x.to_s)
62
+ dont_fetch = ["fetch_all"]
63
+ next if dont_fetch.include?(x)
64
+ puts "fetching #{x}"
65
+ self.send(x)
66
+ attribute = x.split(/_/)
67
+ isometric.send(attribute[1]+"=", Time.now)
68
+ end
69
+ self.save
70
+ isometric.save
71
+ rescue e
72
+ puts e.message
73
+ puts e.backtrace.inspect
74
+ end
75
+ end
76
+ end
77
+
78
+ def self.aggregate_daily_moving_averages(days=30, where="WHERE fulldate > SUBDATE(NOW(), 90)", groupby=nil, measurements=true, sum_avg="AVG")
79
+ if groupby.nil?
80
+ #if groupby is nil, then we want the data for each date - not aggregated.
81
+ #Group on fulldate to get non-aggregated results for each date (so the aggregating functions like AVG() don't run across all dates.)
82
+ groupby = "GROUP BY fulldate"
83
+ else
84
+ groupby = "GROUP BY #{groupby}"
85
+ end
86
+ measurements_with_avg = Array.new
87
+ case measurements
88
+ when false
89
+ when Array
90
+ measurements.each do |name|
91
+ measurements_with_avg.push(" #{sum_avg}(#{name}) AS #{name}")
92
+ end
93
+ else
94
+ metric = Metric.new
95
+ metric.attributes.each do |name, value|
96
+ next if Metric.metadata.include?(name)
97
+ next if Metric.groupbydata.include?(name)
98
+ measurements_with_avg.push(" #{sum_avg}(#{name}) AS #{name}")
99
+ end
100
+ end
101
+ m_with_a = (measurements_with_avg.empty?) ? "" : "," + measurements_with_avg.join(",")
102
+ self.find_by_sql("
103
+ SELECT fulldate, fulldate AS d, year, monthofyear AS month, dayofyear AS day, '#{days}' AS movingaverage #{m_with_a}
104
+ FROM heart_metrics
105
+ #{where} AND movingaverage = #{days} #{groupby}
106
+ ORDER BY d ASC"
107
+ )
108
+ end
109
+
110
+ def self.aggregate_daily_sums(days=nil, where=nil, groupby=nil, measurements=true)
111
+ self.aggregate_daily_moving_averages(days, where, groupby, measurements, "SUM")
112
+ end
113
+
114
+ # TODO remove the following methods
115
+ #This method is used in the /metrics/:/:/cache route
116
+ def moving_averages!(days)
117
+ subselects = Metric.subselects_with_day(days).join(",")
118
+ metric_with_calculated_averages = Metric.find_by_sql("SELECT fulldate, fulldate AS d, year, monthofyear AS month, dayofyear AS day, '#{days}' AS movingaverage, #{subselects} FROM heart_metrics WHERE fulldate = '#{fulldate}' AND movingaverage = 0")
119
+ metric_with_calculated_averages.first.attributes.each do |name, value|
120
+ next if Metric.metadata.include?(name)
121
+ next if Metric.groupbydata.include?(name)
122
+ self.send(name+"=",value)
123
+ end
124
+ end
125
+ #was used to create moving averages on the fly... became too slow when data sets were large and is now only used in the daily cache cron job
126
+ def self.subselects_with_day(days=30)
127
+ subqueries = []
128
+ metric = Metric.new
129
+ metric.attributes.each do |name, value|
130
+ next if Metric.metadata.include?(name)
131
+ next if Metric.groupbydata.include?(name)
132
+ subqueries.push("(SELECT AVG(#{name}) AS #{name} FROM heart_metrics WHERE movingaverage = 0 AND fulldate BETWEEN SUBDATE(d,#{days}) AND d) AS #{name}")
133
+ end
134
+ subqueries
135
+ end
136
+
137
+ end #end of class
138
+ end #end of module
@@ -0,0 +1 @@
1
+ != flot_annotations_array(@annotations)
@@ -0,0 +1,2 @@
1
+ $("#description").val(#{@annotation.id});
2
+ var chart_description = "#{@annotation.note}";
@@ -0,0 +1,13 @@
1
+ #clickdata
2
+ %fieldset.notice
3
+ %legend#annotation_legend
4
+ Add an Annotation
5
+ = form_tag(annotations_path) do
6
+ = hidden_field "annotation", "fulldate"
7
+ = hidden_field_tag "dashboard_id", @dashboard ? @dashboard.id : 0
8
+ = text_area "annotation", "note", :cols => 32, :rows => 3
9
+ %br
10
+ = button_to_function "Annotate", "HEART.annotate()"
11
+ %a.whisper{ :onclick => "$('#clickdata').hide();" }
12
+ cancel
13
+ %label#clickdatalabel
@@ -0,0 +1,17 @@
1
+ .span-4.dashboards
2
+ .dashboards-buttons-left
3
+ = link_to image_tag("heart/delete.png", :align => "left", :alt => "Archive", :title => "Archive Dashboard", :onclick => "return confirm('Are you sure you want to archive this dashboard?');"), dashboard_archive_path(dashboard)
4
+ .dashboards-buttons-right
5
+ = link_to image_tag("heart/pencil.png", :align => "right", :alt => "Edit", :title => "Edit"), edit_dashboard_path(dashboard)
6
+ .dashboards-top
7
+ .dashboard_title
8
+ = link_to dashboard.title, dashboard, :class => "button download-itunes"
9
+ .dashboards-bottom{:id => "miniflot#{dashboard.id}"}
10
+ - if Heart::Image.where(:dashboard_id => dashboard.id).exists?
11
+ <img src="#{Heart::Image.where(dashboard_id: dashboard.id).where(purpose: 'index').last.dataurl}"/>
12
+ - else
13
+ - charts = ActiveSupport::JSON.decode(dashboard.dashboard) rescue nil
14
+ - if charts.kind_of?(Array)
15
+ = hidden_field_tag "dashboard[]", charts[1][1], {:id => "miniflot#{dashboard.id}_form"}
16
+ - @reflots += "HEART.miniGraph({ target : '#miniflot#{dashboard.id}'}).draw({ serialized : $('#miniflot#{dashboard.id}_form').val(), image : true, dashboard_id : #{dashboard.id}});"
17
+ #{dashboard.description}
@@ -0,0 +1,89 @@
1
+ .span-22.prefix-1.clear.last
2
+ %fieldset
3
+ = hidden_field_tag "dashboard_id", @dashboard ? @dashboard.id : 0, {:id => "dashboard_id"}
4
+ = hidden_field_tag "dashboards", '', {:id => "dashboards"}
5
+ %legend
6
+ %span{:id => "legend"}
7
+ .span-22.last
8
+ #overlay.black_overlay
9
+ #loadingGif.overlay_content.fancy
10
+ Loading...
11
+ #description_div.span-20.suffix-1.prefix-1.fancy
12
+ #flot.flot.span-22.yspan-10
13
+ #flotlegend.span-21.light-contrast
14
+ .span-21.prefix-1.last
15
+ = render "heart_form"
16
+ .span-16.last
17
+ .panel
18
+ %h3
19
+ %br
20
+ #charts.scrollable{:style => "height:70%"}
21
+ .span-4
22
+ = image_tag "heart/disk.png", :id => "dash_graph1", :onclick => "add_chart(1);"
23
+ <input type="text" name="chart_title" id="chart_title1" maxlength="20" style="width:110px;" value="Chart Title" />
24
+ #flot1.flot.flotmini.span-4.yspan-3{:style => "border:1px dashed #444;", :onclick => "HEART.flotGraph().draw({ serialized : charts.ordered[1][1]});$('#legend').html(charts.ordered[1][0]);"}
25
+ .hidden
26
+ <textarea name="charts_serialized" id="charts_serialized" cols="0" rows="0"></textarea>
27
+ %p
28
+ <button class="thoughtbot" onclick="return check_dashboards();" id="check_save_dashboard">Save &amp; Exit</button>
29
+ #trigger
30
+ #trigger_title.span-1
31
+ <input type="text" name="title" id="dashboard_title" maxlength="18" placeholder="#{@dashboard.try(:title)}" value="#{@dashboard.try(:title)}" />
32
+ #trigger_button.span-1.last
33
+ :javascript
34
+ $('#overlay, #loadingGif').hide();
35
+ var charts = new Object({
36
+ ordered : #{((@dashboard.try(:dashboard)).to_s == '') ? "[]" : @dashboard.dashboard.to_s}
37
+ });
38
+
39
+ var charts_added = 1;
40
+ function add_chart(order, page_loading){
41
+ var next_in_order = 0;
42
+ next_in_order = order + 1;
43
+ var serialized_options = (page_loading) ? { serialized : charts.ordered[order][1]} : null;
44
+ HEART.miniGraph({ target : '#flot' + order }).draw(serialized_options);
45
+ var chart = [$('#chart_title' + order).val(), $('#heartform input:checkbox').serialize().toString()]
46
+ charts.ordered[order] = chart;
47
+ if(next_in_order > charts_added){
48
+ charts_added++;
49
+ $('#charts').append("<div class='span-4' id='minichart_"+ next_in_order + "'>" +
50
+ "<img onclick=\"add_chart("+ next_in_order + ")\" src='/assets/heart/disk.png' class='cursor'> " +
51
+ "<img onclick=\"del_chart("+ next_in_order + ")\" src='/assets/heart/delete.png' class='cursor'> " +
52
+ "<input type=\"text\" name=\"chart_title\" id=\"chart_title" + next_in_order + "\" maxlength=\"20\" style=\"width:110px;\" placeholder=\"Chart Title\" />" +
53
+ "<div class='flot flotmini span-4 yspan-3' id='flot"+ next_in_order + "' style='border:1px dashed #444;' onclick=\"HEART.flotGraph().draw({ serialized : charts.ordered["+ next_in_order + "][1]}); $('#legend').html(charts.ordered["+ next_in_order + "][0]);\"></div>" +
54
+ " </div>");
55
+ }
56
+ }
57
+
58
+ function del_chart(order){
59
+ charts.ordered[order] = false;
60
+ $('#minichart_'+order).remove();
61
+ }
62
+ function check_dashboards(){
63
+ while(charts.ordered.findIndex(false) !== false){
64
+ charts.ordered.splice(charts.ordered.findIndex(false), 1);
65
+ }
66
+ $('#charts_serialized').val(JSON.stringify(charts.ordered));
67
+ if($('#dashboard_title').val() == "Dashboard Name" || $('#dashboard_title').val() == ""){
68
+ alert('Please change the name of the dashboard');
69
+ $('#dashboard_title').addClass('error');
70
+ return false;
71
+ }
72
+ if(charts.ordered.length > 0){
73
+ return true;
74
+ }else{
75
+ alert('You must add a graph before saving!');
76
+ return false;
77
+ }
78
+ }
79
+
80
+ for(x=0;x<charts.ordered.length;x++){
81
+ if(x>0){
82
+ $("#chart_title"+x).val(charts.ordered[x][0]);
83
+ add_chart(x, true);
84
+ }
85
+ if(x == 1){
86
+ $("#chart_title"+x).val(charts.ordered[x][0]);
87
+ HEART.flotGraph().draw({ serialized : charts.ordered[x][1]});
88
+ }
89
+ }
@@ -0,0 +1,24 @@
1
+ #flot_extra.span-20.suffix-1.prefix-1
2
+ .prefix-14.last
3
+ %span.tTip{:title => tool_tip(:title => t('option.tsv'), :content => t('option.tsv_desc')) }
4
+ = link_to image_tag('heart/page_white_excel.png'), nil, :class => 'heart_export_tsv'
5
+ %span.tTip{:title => tool_tip(:title => t('option.image'), :content => t('option.image_desc')) }
6
+ = link_to image_tag('heart/picture.png'), nil, :class => 'heart_export_image', :id => 'heart_export_image'
7
+ %span.tTip{:title => tool_tip(:title => t('option.table'), :content => t('option.table_desc')) }
8
+ = link_to image_tag('heart/table.png'), nil, :class => 'heart_export_table'
9
+ |
10
+ %span.tTip{:title => tool_tip(:title => t('option.pie'), :content => t('option.pie_desc')) }
11
+ = link_to image_tag('heart/chart_pie.png', :class => 'heart_pie heart_off') + image_tag('heart/chart_pie_off.png', :class => 'heart_pie'), nil, :class => 'heart_set_pie'
12
+ %span.tTip{:title => tool_tip(:title => t('option.bars'), :content => t('option.bars_desc')) }
13
+ = link_to image_tag('heart/chart_bar.png', :class => 'heart_bars heart_off') + image_tag('heart/chart_bar_off.png', :class => 'heart_bars'), nil, :class => 'heart_set_bars'
14
+ %span.tTip{:title => tool_tip(:title => t('option.lines'), :content => t('option.lines_desc')) }
15
+ = link_to image_tag('heart/chart_curve.png', :class => 'heart_lines') + image_tag('heart/chart_curve_off.png', :class => 'heart_lines heart_off'), nil, :class => 'heart_set_lines'
16
+ |
17
+ %span.tTip{:title => tool_tip(:title => t('option.stack'), :content => t('option.stack_desc')) }
18
+ = link_to image_tag('heart/bricks.png', :class => 'heart_stack heart_off') + image_tag('heart/bricks_off.png', :class => 'heart_stack'), nil, :class => 'heart_set_stack'
19
+ %span.tTip{:title => tool_tip(:title => t('option.points'), :content => t('option.points_desc')) }
20
+ = link_to image_tag('heart/chart_line.png', :class => 'heart_points heart_off') + image_tag('heart/chart_line_off.png', :class => 'heart_points'), nil, :class => 'heart_set_points'
21
+ %span.tTip{:title => tool_tip(:title => t('option.fill'), :content => t('option.fill_desc')) }
22
+ = link_to image_tag('heart/paintcan.png', :class => 'heart_fill') + image_tag('heart/paintcan_off.png', :class => 'heart_fill heart_off'), nil, :class => 'heart_set_fill'
23
+ %span.tTip{:title => tool_tip(:title => t('option.zoom'), :content => t('option.zoom_desc')) }
24
+ = link_to image_tag('heart/zoom.png', :class => 'heart_zoom heart_off') + image_tag('heart/zoom_off.png', :class => 'heart_zoom'), nil, :class => 'heart_set_zoom'