xrono 1.0.0

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 (520) hide show
  1. data/.gitignore +19 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +20 -0
  4. data/Gemfile +30 -0
  5. data/Gemfile.lock +336 -0
  6. data/LICENSE +21 -0
  7. data/README.md +64 -0
  8. data/RELEASE_NOTES.md +83 -0
  9. data/Rakefile +15 -0
  10. data/XRONO.md +64 -0
  11. data/app/assets/images/chosen-sprite.png +0 -0
  12. data/app/assets/images/grid.png +0 -0
  13. data/app/assets/images/isotope_logo.png +0 -0
  14. data/app/assets/images/logo.png +0 -0
  15. data/app/assets/images/logo_122x40.png +0 -0
  16. data/app/assets/images/logo_97x40.png +0 -0
  17. data/app/assets/images/main_bg.jpg +0 -0
  18. data/app/assets/images/nav_bg.jpg +0 -0
  19. data/app/assets/images/rails.png +0 -0
  20. data/app/assets/images/top_bg.jpg +0 -0
  21. data/app/assets/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  22. data/app/assets/images/ui-bg_flat_0_fbf9ee_40x100.png +0 -0
  23. data/app/assets/images/ui-bg_flat_55_fbec88_40x100.png +0 -0
  24. data/app/assets/images/ui-bg_flat_65_ffffff_40x100.png +0 -0
  25. data/app/assets/images/ui-bg_flat_75_cccccc_40x100.png +0 -0
  26. data/app/assets/images/ui-bg_flat_75_dadada_40x100.png +0 -0
  27. data/app/assets/images/ui-bg_flat_75_e6e6e6_40x100.png +0 -0
  28. data/app/assets/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  29. data/app/assets/images/ui-bg_flat_95_fef1ec_40x100.png +0 -0
  30. data/app/assets/images/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  31. data/app/assets/images/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  32. data/app/assets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  33. data/app/assets/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  34. data/app/assets/images/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  35. data/app/assets/images/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  36. data/app/assets/images/ui-icons_217bc0_256x240.png +0 -0
  37. data/app/assets/images/ui-icons_222222_256x240.png +0 -0
  38. data/app/assets/images/ui-icons_2e83ff_256x240.png +0 -0
  39. data/app/assets/images/ui-icons_454545_256x240.png +0 -0
  40. data/app/assets/images/ui-icons_469bdd_256x240.png +0 -0
  41. data/app/assets/images/ui-icons_6da8d5_256x240.png +0 -0
  42. data/app/assets/images/ui-icons_888888_256x240.png +0 -0
  43. data/app/assets/images/ui-icons_cd0a0a_256x240.png +0 -0
  44. data/app/assets/images/ui-icons_d8e7f3_256x240.png +0 -0
  45. data/app/assets/images/ui-icons_f9bd01_256x240.png +0 -0
  46. data/app/assets/javascripts/add_taxonomy.js.erb +307 -0
  47. data/app/assets/javascripts/admin_invoices.js +15 -0
  48. data/app/assets/javascripts/api/v1/clients.js.coffee +3 -0
  49. data/app/assets/javascripts/api/v1/tokens.js.coffee +3 -0
  50. data/app/assets/javascripts/application.js.erb +25 -0
  51. data/app/assets/javascripts/bootstrap-dropdown.js +92 -0
  52. data/app/assets/javascripts/bootstrap-tabs.js +80 -0
  53. data/app/assets/javascripts/bootstrap.js.coffee +4 -0
  54. data/app/assets/javascripts/calendar.js +25 -0
  55. data/app/assets/javascripts/chosen.jquery.js +898 -0
  56. data/app/assets/javascripts/client_login/clients.js.coffee +3 -0
  57. data/app/assets/javascripts/client_login/reports.js.coffee +3 -0
  58. data/app/assets/javascripts/comments.js +16 -0
  59. data/app/assets/javascripts/css_browser_selector.js +8 -0
  60. data/app/assets/javascripts/dashboard.js +3 -0
  61. data/app/assets/javascripts/data_vaults.js.coffee +3 -0
  62. data/app/assets/javascripts/file_attachments.js +9 -0
  63. data/app/assets/javascripts/jquery-tagselector.js +50 -0
  64. data/app/assets/javascripts/jquery-ui-1.8.16.custom.min.js +791 -0
  65. data/app/assets/javascripts/jquery.jeditable.js +543 -0
  66. data/app/assets/javascripts/jquery_ujs.js +336 -0
  67. data/app/assets/javascripts/schedule_modal.js +25 -0
  68. data/app/assets/javascripts/specify_project.js +21 -0
  69. data/app/assets/javascripts/ticket_board.js +104 -0
  70. data/app/assets/stylesheets/_jquery-ui-1.8.16.custom.css +568 -0
  71. data/app/assets/stylesheets/application.css +7 -0
  72. data/app/assets/stylesheets/bootstrap_and_overrides.css.scss +41 -0
  73. data/app/assets/stylesheets/chosen.css +367 -0
  74. data/app/assets/stylesheets/client_login/clients.css.scss +3 -0
  75. data/app/assets/stylesheets/client_login/reports.css.scss +3 -0
  76. data/app/assets/stylesheets/data_vaults.css.scss +3 -0
  77. data/app/assets/stylesheets/jquery-tagselector.css +49 -0
  78. data/app/assets/stylesheets/responsive.scss +650 -0
  79. data/app/assets/stylesheets/screen.scss +303 -0
  80. data/app/controllers/admin/base_controller.rb +18 -0
  81. data/app/controllers/admin/invoices_controller.rb +42 -0
  82. data/app/controllers/admin/payroll_controller.rb +29 -0
  83. data/app/controllers/admin/site_settings_controller.rb +19 -0
  84. data/app/controllers/admin/unentered_time_report_controller.rb +26 -0
  85. data/app/controllers/admin/users_controller.rb +86 -0
  86. data/app/controllers/admin/weekly_time_report_controller.rb +11 -0
  87. data/app/controllers/api/base_controller.rb +14 -0
  88. data/app/controllers/api/v1/base_controller.rb +2 -0
  89. data/app/controllers/api/v1/clients_controller.rb +10 -0
  90. data/app/controllers/api/v1/credentials_controller.rb +10 -0
  91. data/app/controllers/api/v1/projects_controller.rb +27 -0
  92. data/app/controllers/api/v1/tickets_controller.rb +46 -0
  93. data/app/controllers/api/v1/tokens_controller.rb +30 -0
  94. data/app/controllers/api/v1/work_units_controller.rb +23 -0
  95. data/app/controllers/client_login/base_controller.rb +3 -0
  96. data/app/controllers/client_login/clients_controller.rb +35 -0
  97. data/app/controllers/client_login/contacts_controller.rb +53 -0
  98. data/app/controllers/client_login/projects_controller.rb +24 -0
  99. data/app/controllers/client_login/reports_controller.rb +23 -0
  100. data/app/controllers/client_login/tickets_controller.rb +41 -0
  101. data/app/controllers/client_login/work_units_controller.rb +11 -0
  102. data/app/controllers/clients_controller.rb +103 -0
  103. data/app/controllers/comments_controller.rb +75 -0
  104. data/app/controllers/contacts_controller.rb +54 -0
  105. data/app/controllers/dashboard/base_controller.rb +79 -0
  106. data/app/controllers/data_vaults_controller.rb +12 -0
  107. data/app/controllers/doorkeeper/application_controller.rb +33 -0
  108. data/app/controllers/file_attachments_controller.rb +60 -0
  109. data/app/controllers/projects_controller.rb +62 -0
  110. data/app/controllers/tickets_controller.rb +48 -0
  111. data/app/controllers/users_controller.rb +57 -0
  112. data/app/controllers/work_units_controller.rb +114 -0
  113. data/app/controllers/xrono/application_controller.rb +65 -0
  114. data/app/helpers/admin/unentered_time_report_helper.rb +9 -0
  115. data/app/helpers/admin_base_helper.rb +14 -0
  116. data/app/helpers/clients_helper.rb +5 -0
  117. data/app/helpers/dashboard_helper.rb +9 -0
  118. data/app/helpers/gravatar_helper.rb +5 -0
  119. data/app/helpers/refurl_helper.rb +9 -0
  120. data/app/helpers/xrono/application_helper.rb +54 -0
  121. data/app/mailers/notifier.rb +18 -0
  122. data/app/models/chart_data.rb +20 -0
  123. data/app/models/client.rb +98 -0
  124. data/app/models/comment.rb +8 -0
  125. data/app/models/contact.rb +10 -0
  126. data/app/models/data_vault.rb +6 -0
  127. data/app/models/file_attachment.rb +8 -0
  128. data/app/models/project.rb +76 -0
  129. data/app/models/role.rb +3 -0
  130. data/app/models/roles_user.rb +4 -0
  131. data/app/models/site_settings.rb +4 -0
  132. data/app/models/ticket.rb +85 -0
  133. data/app/models/user.rb +147 -0
  134. data/app/models/weekly_time_report.rb +26 -0
  135. data/app/models/work_unit.rb +99 -0
  136. data/app/models/work_unit/finders.rb +67 -0
  137. data/app/views/admin/_nav.html.haml +1 -0
  138. data/app/views/admin/base/index.html.haml +3 -0
  139. data/app/views/admin/base/reports.html.haml +3 -0
  140. data/app/views/admin/invoices/index.html.haml +19 -0
  141. data/app/views/admin/invoices/show.html.haml +57 -0
  142. data/app/views/admin/payroll/index.html.haml +18 -0
  143. data/app/views/admin/payroll/show.html.haml +56 -0
  144. data/app/views/admin/site_settings/edit.html.haml +32 -0
  145. data/app/views/admin/unentered_time_report/_week_navigation.html.haml +6 -0
  146. data/app/views/admin/unentered_time_report/show.html.haml +16 -0
  147. data/app/views/admin/users/_form.html.haml +48 -0
  148. data/app/views/admin/users/_locked_users.html.haml +31 -0
  149. data/app/views/admin/users/_users_table.html.haml +25 -0
  150. data/app/views/admin/users/edit.html.haml +1 -0
  151. data/app/views/admin/users/index.html.haml +14 -0
  152. data/app/views/admin/users/locked_clients.html.haml +13 -0
  153. data/app/views/admin/users/locked_users.html.haml +13 -0
  154. data/app/views/admin/users/new.html.haml +1 -0
  155. data/app/views/admin/users/projects.html.haml +25 -0
  156. data/app/views/admin/users/unlocked_clients.html.haml +13 -0
  157. data/app/views/admin/weekly_time_report/_week_pagination.html.haml +11 -0
  158. data/app/views/admin/weekly_time_report/show.html.haml +41 -0
  159. data/app/views/client_login/_work_unit_index.haml +16 -0
  160. data/app/views/client_login/base/index.html.haml +18 -0
  161. data/app/views/client_login/clients/show.html.haml +32 -0
  162. data/app/views/client_login/contacts/_form.html.haml +34 -0
  163. data/app/views/client_login/contacts/edit.html.haml +4 -0
  164. data/app/views/client_login/contacts/index.html.haml +30 -0
  165. data/app/views/client_login/contacts/new.html.haml +5 -0
  166. data/app/views/client_login/contacts/show.html.haml +26 -0
  167. data/app/views/client_login/projects/_tickets.html.haml +31 -0
  168. data/app/views/client_login/projects/show.html.haml +8 -0
  169. data/app/views/client_login/reports/index.html.haml +4 -0
  170. data/app/views/client_login/reports/work_units.html.haml +96 -0
  171. data/app/views/client_login/tickets/_form.html.haml +33 -0
  172. data/app/views/client_login/tickets/new.html.haml +1 -0
  173. data/app/views/client_login/tickets/show.html.haml +23 -0
  174. data/app/views/client_login/work_units/show.html.haml +18 -0
  175. data/app/views/clients/_breadcrumbs.html.haml +2 -0
  176. data/app/views/clients/_clients_table.html.haml +24 -0
  177. data/app/views/clients/_form.html.haml +34 -0
  178. data/app/views/clients/_projects.html.haml +31 -0
  179. data/app/views/clients/edit.html.haml +1 -0
  180. data/app/views/clients/inactive_clients.html.haml +9 -0
  181. data/app/views/clients/index.html.haml +8 -0
  182. data/app/views/clients/new.html.haml +1 -0
  183. data/app/views/clients/show.html.haml +34 -0
  184. data/app/views/clients/suspended_clients.html.haml +8 -0
  185. data/app/views/comments/_comment.html.haml +46 -0
  186. data/app/views/comments/_comment_form.haml +29 -0
  187. data/app/views/comments/_comments.html.haml +3 -0
  188. data/app/views/contacts/_form.html.haml +34 -0
  189. data/app/views/contacts/edit.html.haml +1 -0
  190. data/app/views/contacts/index.html.haml +23 -0
  191. data/app/views/contacts/new.html.haml +1 -0
  192. data/app/views/contacts/show.html.haml +26 -0
  193. data/app/views/dashboard/base/_two_week_time_report.html.haml +13 -0
  194. data/app/views/dashboard/base/_week_pagination.html.haml +10 -0
  195. data/app/views/dashboard/base/calendar.html.haml +1 -0
  196. data/app/views/dashboard/base/calendar.js.erb +3 -0
  197. data/app/views/dashboard/base/index.html.haml +18 -0
  198. data/app/views/devise/confirmations/new.html.haml +9 -0
  199. data/app/views/devise/mailer/confirmation_instructions.html.haml +4 -0
  200. data/app/views/devise/mailer/reset_password_instructions.html.haml +6 -0
  201. data/app/views/devise/mailer/unlock_instructions.html.haml +5 -0
  202. data/app/views/devise/passwords/edit.html.haml +17 -0
  203. data/app/views/devise/passwords/new.html.haml +12 -0
  204. data/app/views/devise/registrations/edit.html.haml +36 -0
  205. data/app/views/devise/registrations/new.html.haml +32 -0
  206. data/app/views/devise/sessions/new.html.haml +22 -0
  207. data/app/views/devise/shared/_links.haml +15 -0
  208. data/app/views/devise/unlocks/new.html.haml +9 -0
  209. data/app/views/file_attachments/_file_attachment.html.haml +10 -0
  210. data/app/views/file_attachments/_file_attachment_combined.html.haml +30 -0
  211. data/app/views/file_attachments/_file_attachments.html.haml +5 -0
  212. data/app/views/file_attachments/new.html.haml +17 -0
  213. data/app/views/layouts/application.html.haml +32 -0
  214. data/app/views/layouts/doorkeeper.html.haml +31 -0
  215. data/app/views/notifier/daily.text.erb +8 -0
  216. data/app/views/notifier/work_unit_notification.text.erb +17 -0
  217. data/app/views/projects/_breadcrumbs.html.haml +5 -0
  218. data/app/views/projects/_form.html.haml +94 -0
  219. data/app/views/projects/_pie_chart_metrics.html.haml +4 -0
  220. data/app/views/projects/_specify.html.haml +11 -0
  221. data/app/views/projects/_ticket_table.html.haml +36 -0
  222. data/app/views/projects/edit.html.haml +2 -0
  223. data/app/views/projects/new.html.haml +2 -0
  224. data/app/views/projects/show.html.haml +57 -0
  225. data/app/views/shared/_calendar.html.haml +86 -0
  226. data/app/views/shared/_data_vault.html.haml +16 -0
  227. data/app/views/shared/_files_and_comments.html.haml +21 -0
  228. data/app/views/shared/_flashes.html.haml +10 -0
  229. data/app/views/shared/_javascripts.html.haml +8 -0
  230. data/app/views/shared/_menu.html.haml +14 -0
  231. data/app/views/shared/_user_roles.html.haml +7 -0
  232. data/app/views/shared/_work_unit_index.html.haml +24 -0
  233. data/app/views/tickets/_add_ticket.html.haml +27 -0
  234. data/app/views/tickets/_breadcrumbs.html.haml +8 -0
  235. data/app/views/tickets/_form.html.haml +40 -0
  236. data/app/views/tickets/_ticket_detail.html.haml +18 -0
  237. data/app/views/tickets/edit.html.haml +2 -0
  238. data/app/views/tickets/modal_new.html.haml +28 -0
  239. data/app/views/tickets/new.html.haml +1 -0
  240. data/app/views/tickets/show.html.haml +28 -0
  241. data/app/views/tickets/ticket_detail.html.haml +18 -0
  242. data/app/views/users/_change_password_form.haml +13 -0
  243. data/app/views/users/_user_head.html.haml +7 -0
  244. data/app/views/users/edit.haml +34 -0
  245. data/app/views/users/historical_time.html.haml +5 -0
  246. data/app/views/users/index.html.haml +18 -0
  247. data/app/views/users/show.html.haml +13 -0
  248. data/app/views/work_units/_add_work_unit.html.haml +81 -0
  249. data/app/views/work_units/_breadcrumbs.html.haml +11 -0
  250. data/app/views/work_units/_dashboard_line.html.haml +6 -0
  251. data/app/views/work_units/_edit_work_unit.haml +44 -0
  252. data/app/views/work_units/_shared_form.haml +40 -0
  253. data/app/views/work_units/edit.html.haml +2 -0
  254. data/app/views/work_units/index.html.haml +7 -0
  255. data/app/views/work_units/new.html.haml +6 -0
  256. data/app/views/work_units/show.html.haml +25 -0
  257. data/app/workers/daily_notifier_worker.rb +7 -0
  258. data/app/workers/work_unit_notifier_worker.rb +7 -0
  259. data/config.ru +7 -0
  260. data/config/admin_navigation.rb +71 -0
  261. data/config/admin_reports_navigation.rb +6 -0
  262. data/config/boot.rb +6 -0
  263. data/config/client_navigation.rb +64 -0
  264. data/config/cucumber.yml +8 -0
  265. data/config/initializers/00_requirements.rb +2 -0
  266. data/config/initializers/backtrace_silencers.rb +7 -0
  267. data/config/initializers/devise.rb +144 -0
  268. data/config/initializers/doorkeeper.rb +32 -0
  269. data/config/initializers/doorkeeper_monkeypatch.rb +66 -0
  270. data/config/initializers/github_concern.rb +4 -0
  271. data/config/initializers/haml.rb +13 -0
  272. data/config/initializers/inflections.rb +10 -0
  273. data/config/initializers/load_controller_mixins.rb +1 -0
  274. data/config/initializers/mime_types.rb +5 -0
  275. data/config/initializers/paper_clip.rb +1 -0
  276. data/config/initializers/simple_navigation.rb +1 -0
  277. data/config/initializers/wrap_parameters.rb +14 -0
  278. data/config/locales/devise.en.yml +39 -0
  279. data/config/locales/doorkeeper.en.yml +23 -0
  280. data/config/locales/en.yml +201 -0
  281. data/config/locales/faker.en.yml +48 -0
  282. data/config/navigation.rb +78 -0
  283. data/config/rackspace_cloudfiles.yml +14 -0
  284. data/config/routes.rb +113 -0
  285. data/config/secondary_navigation.rb +65 -0
  286. data/config/trinidad.yml +4 -0
  287. data/config/warble.rb +144 -0
  288. data/db/migrate/20100825165612_create_clients.rb +14 -0
  289. data/db/migrate/20100825185313_create_projects.rb +14 -0
  290. data/db/migrate/20100825223943_create_tickets.rb +16 -0
  291. data/db/migrate/20100902174920_create_work_units.rb +14 -0
  292. data/db/migrate/20100902190129_add_missing_fields_to_work_units.rb +13 -0
  293. data/db/migrate/20100904173839_add_guid_to_clients_projects_tickets_and_work_orders.rb +13 -0
  294. data/db/migrate/20100922181642_create_comments.rb +19 -0
  295. data/db/migrate/20100927180254_devise_create_users.rb +32 -0
  296. data/db/migrate/20100927184505_add_details_to_users.rb +13 -0
  297. data/db/migrate/20100927191329_add_user_to_work_units.rb +9 -0
  298. data/db/migrate/20100928163356_create_roles.rb +22 -0
  299. data/db/migrate/20100928203745_create_addresses.rb +19 -0
  300. data/db/migrate/20100928204544_create_contacts.rb +17 -0
  301. data/db/migrate/20101007175626_add_lockable_to_users.rb +11 -0
  302. data/db/migrate/20101020162216_add_paid_at_to_work_units_table.rb +9 -0
  303. data/db/migrate/20101020162516_add_check_number_to_work_units_table.rb +9 -0
  304. data/db/migrate/20101020215135_add_paid_field_to_work_units_table.rb +9 -0
  305. data/db/migrate/20101020215226_add_invoiced_field_to_work_units_table.rb +9 -0
  306. data/db/migrate/20101020215457_remove_paid_at_from_work_units_table.rb +9 -0
  307. data/db/migrate/20101020215624_remove_check_number_from_work_units_table.rb +9 -0
  308. data/db/migrate/20101025161443_add_invoiced_at_to_work_units_table.rb +9 -0
  309. data/db/migrate/20101026151900_add_initials_to_clients.rb +9 -0
  310. data/db/migrate/20101029145059_create_file_attachments.rb +18 -0
  311. data/db/migrate/20101030142615_add_guid_to_users.rb +9 -0
  312. data/db/migrate/20101102145137_add_paid_at_to_work_units.rb +9 -0
  313. data/db/migrate/20101112151337_add_active_to_comments.rb +9 -0
  314. data/db/migrate/20101119172727_add_recieves_email_to_contact.rb +10 -0
  315. data/db/migrate/20101122225423_projects_users.rb +11 -0
  316. data/db/migrate/20101129214537_remove_projects_users_table.rb +11 -0
  317. data/db/migrate/20101130225328_contact_receives_email.rb +9 -0
  318. data/db/migrate/20101202203051_add_address_to_contacts.rb +19 -0
  319. data/db/migrate/20101202214746_remove_address_table.rb +17 -0
  320. data/db/migrate/20101216214304_add_hours_type_to_work_unit.rb +9 -0
  321. data/db/migrate/20101217152455_add_effective_hours_to_work_units.rb +9 -0
  322. data/db/migrate/20101228154820_add_overtime_multiplier_to_clients_table.rb +9 -0
  323. data/db/migrate/20101228154951_add_overtime_multiplier_to_projects_table.rb +9 -0
  324. data/db/migrate/20101228155122_create_site_settings_table.rb +11 -0
  325. data/db/migrate/20110107190927_add_site_logo_columns_to_site_settings.rb +15 -0
  326. data/db/migrate/20110111155513_add_total_yearly_pto_per_user_to_site_settings.rb +9 -0
  327. data/db/migrate/20110111220015_add_not_valid_to_file_attachment.rb +9 -0
  328. data/db/migrate/20110125153818_add_fullwidth_to_users.rb +9 -0
  329. data/db/migrate/20110222162404_add_daily_target_hours_to_users.rb +9 -0
  330. data/db/migrate/20110310021732_add_client_to_site_settings.rb +9 -0
  331. data/db/migrate/20110630194044_add_expanded_calendar_to_user.rb +9 -0
  332. data/db/migrate/20110922175742_add_state_to_tickets.rb +9 -0
  333. data/db/migrate/20111212193345_add_estimated_hours_to_tickets.rb +5 -0
  334. data/db/migrate/20111216152557_add_client_boolean_to_user.rb +5 -0
  335. data/db/migrate/20111220193307_add_repo_and_branch_to_projects_and_ticket.rb +6 -0
  336. data/db/migrate/20111220193619_create_git_pushes.rb +9 -0
  337. data/db/migrate/20111220193620_create_git_commits.rb +10 -0
  338. data/db/migrate/20111220193621_add_user_id_to_git_push.rb +5 -0
  339. data/db/migrate/20111220193622_create_github_concernable_git_pushes.rb +11 -0
  340. data/db/migrate/20111227140859_add_token_to_user.rb +7 -0
  341. data/db/migrate/20120102185406_add_completed_boolean_to_ticket.rb +5 -0
  342. data/db/migrate/20120104132121_add_completed_to_project.rb +5 -0
  343. data/db/migrate/20120124184915_modify_project_for_new_git_integration.rb +11 -0
  344. data/db/migrate/20120125145833_add_rates_to_project.rb +6 -0
  345. data/db/migrate/20120126151009_create_data_vaults.rb +11 -0
  346. data/db/migrate/20120126151341_create_versions.rb +18 -0
  347. data/db/migrate/20120126154403_rename_column_data_to_encrypted_data.rb +8 -0
  348. data/db/migrate/20120221193022_add_index_to_user_id_on_work_units.rb +5 -0
  349. data/db/migrate/20120221195345_acts_as_taggable_on_migration.rb +30 -0
  350. data/db/migrate/20120320212313_remove_timestamps_from_roles_users_table.rb +11 -0
  351. data/db/migrate/20120710034831_create_doorkeeper_tables.rb +42 -0
  352. data/db/migrate/20121021122002_add_missing_indices.rb +21 -0
  353. data/doc/website/favicon.ico +0 -0
  354. data/doc/website/images/clock_box.png +0 -0
  355. data/doc/website/images/demo.png +0 -0
  356. data/doc/website/images/download.png +0 -0
  357. data/doc/website/images/fork_me.png +0 -0
  358. data/doc/website/images/lightbox-blank.gif +0 -0
  359. data/doc/website/images/lightbox-btn-close.gif +0 -0
  360. data/doc/website/images/lightbox-btn-next.gif +0 -0
  361. data/doc/website/images/lightbox-btn-prev.gif +0 -0
  362. data/doc/website/images/lightbox-ico-loading.gif +0 -0
  363. data/doc/website/images/main_bg.png +0 -0
  364. data/doc/website/images/nav_bg.png +0 -0
  365. data/doc/website/images/screen_1.png +0 -0
  366. data/doc/website/images/screen_2.png +0 -0
  367. data/doc/website/images/screen_3.png +0 -0
  368. data/doc/website/images/screen_4.png +0 -0
  369. data/doc/website/images/screen_5.png +0 -0
  370. data/doc/website/images/screen_6.png +0 -0
  371. data/doc/website/images/support.png +0 -0
  372. data/doc/website/images/thumb_1.png +0 -0
  373. data/doc/website/images/thumb_2.png +0 -0
  374. data/doc/website/images/thumb_3.png +0 -0
  375. data/doc/website/images/thumb_4.png +0 -0
  376. data/doc/website/images/thumb_5.png +0 -0
  377. data/doc/website/images/thumb_6.png +0 -0
  378. data/doc/website/images/xrono_logo.png +0 -0
  379. data/doc/website/index.html +274 -0
  380. data/doc/website/javascripts/application.js +18 -0
  381. data/doc/website/javascripts/greyscalebasic_regular.typeface.js +1 -0
  382. data/doc/website/javascripts/jquery.lightbox-0.5.min.js +42 -0
  383. data/doc/website/javascripts/jquery.min.js +32 -0
  384. data/doc/website/javascripts/jquery.tweet.js +181 -0
  385. data/doc/website/javascripts/typeface.js +873 -0
  386. data/doc/website/javascripts/verdana_regular.typeface.js +1 -0
  387. data/doc/website/stylesheets/jquery.lightbox.css +104 -0
  388. data/doc/website/stylesheets/jquery.tweet.css +38 -0
  389. data/doc/website/stylesheets/reset-fonts-grids.css +32 -0
  390. data/doc/website/stylesheets/screen.css +228 -0
  391. data/doc/xrono_dash.png +0 -0
  392. data/doc/xrono_ticket.png +0 -0
  393. data/features/admin/invoices.feature +37 -0
  394. data/features/admin/manage_users.feature +17 -0
  395. data/features/admin/payroll.feature +64 -0
  396. data/features/admin/roles.feature +9 -0
  397. data/features/admin/site_settings.feature +19 -0
  398. data/features/admin/unentered_time_report.feature +38 -0
  399. data/features/admin/weekly_time_report.feature +14 -0
  400. data/features/api/v1/clients_controller.feature +58 -0
  401. data/features/authorization-admin.feature +34 -0
  402. data/features/authorization-non-admin.feature +38 -0
  403. data/features/client_login.feature +15 -0
  404. data/features/collaborative_work_units.feature +112 -0
  405. data/features/daily_emails.feature +11 -0
  406. data/features/dashboard.feature +74 -0
  407. data/features/manage_clients.feature +116 -0
  408. data/features/manage_comments.feature +30 -0
  409. data/features/manage_contacts.feature +56 -0
  410. data/features/manage_file_attachments.feature +51 -0
  411. data/features/manage_projects.feature +92 -0
  412. data/features/manage_self.feature +48 -0
  413. data/features/manage_tickets.feature +74 -0
  414. data/features/manage_users.feature +76 -0
  415. data/features/manage_work_units.feature +115 -0
  416. data/features/mockups/images/asset-tracker-client-show.png +0 -0
  417. data/features/mockups/images/asset-tracker.png +0 -0
  418. data/features/mockups/images/ixi - asset tracker v3 homepage - no time entered modal.png +0 -0
  419. data/features/mockups/images/ixi - asset tracker v3 homepage - schedule on modal.png +0 -0
  420. data/features/mockups/images/ixi - asset tracker v3 homepage.png +0 -0
  421. data/features/mockups/ixi - asset tracker v3 homepage - no time entered modal.bmml +194 -0
  422. data/features/mockups/ixi - asset tracker v3 homepage - schedule on modal.bmml +208 -0
  423. data/features/mockups/ixi - asset tracker v3 homepage.bmml +172 -0
  424. data/features/project_assignment.feature +69 -0
  425. data/features/search_work_units.feature +38 -0
  426. data/features/step_definitions/calendar_expansion_steps.rb +7 -0
  427. data/features/step_definitions/client_login_steps.rb +8 -0
  428. data/features/step_definitions/client_steps.rb +29 -0
  429. data/features/step_definitions/comment_steps.rb +4 -0
  430. data/features/step_definitions/contact_steps.rb +22 -0
  431. data/features/step_definitions/debug_steps.rb +5 -0
  432. data/features/step_definitions/devise_steps.rb +26 -0
  433. data/features/step_definitions/email_steps.rb +74 -0
  434. data/features/step_definitions/file_attachment_steps.rb +8 -0
  435. data/features/step_definitions/modified_web_steps.rb +25 -0
  436. data/features/step_definitions/pickle_steps.rb +101 -0
  437. data/features/step_definitions/project_steps.rb +32 -0
  438. data/features/step_definitions/search_steps.rb +3 -0
  439. data/features/step_definitions/ticket_board_steps.rb +39 -0
  440. data/features/step_definitions/ticket_detail_steps.rb +9 -0
  441. data/features/step_definitions/ticket_steps.rb +12 -0
  442. data/features/step_definitions/unentered_time_report_steps.rb +3 -0
  443. data/features/step_definitions/user_steps.rb +43 -0
  444. data/features/step_definitions/web_steps.rb +274 -0
  445. data/features/step_definitions/weekly_time_report_steps.rb +7 -0
  446. data/features/step_definitions/work_unit_index_steps.rb +8 -0
  447. data/features/step_definitions/work_unit_steps.rb +39 -0
  448. data/features/support/email.rb +21 -0
  449. data/features/support/env.rb +80 -0
  450. data/features/support/paths.rb +96 -0
  451. data/features/support/pickle.rb +26 -0
  452. data/features/support/selectors.rb +51 -0
  453. data/features/support/xrono.rb +19 -0
  454. data/features/work_unit_notifier.feature +11 -0
  455. data/lib/controller_mixins.rb +5 -0
  456. data/lib/controller_mixins/authorization.rb +15 -0
  457. data/lib/controller_mixins/contacts.rb +37 -0
  458. data/lib/controller_mixins/generic.rb +15 -0
  459. data/lib/controller_mixins/tickets.rb +35 -0
  460. data/lib/controller_mixins/work_units.rb +13 -0
  461. data/lib/date_ext.rb +16 -0
  462. data/lib/guid_referenced.rb +19 -0
  463. data/lib/tasks/.gitkeep +0 -0
  464. data/lib/tasks/acts_as_commentable_tasks.rake +4 -0
  465. data/lib/tasks/cucumber.rake +65 -0
  466. data/lib/tasks/git_repo_tasks.rake +47 -0
  467. data/lib/tasks/notifications.rake +8 -0
  468. data/lib/tasks/paperclip_tasks.rake +79 -0
  469. data/lib/xrono.rb +1 -0
  470. data/lib/xrono/engine.rb +45 -0
  471. data/public/404.html +26 -0
  472. data/public/422.html +26 -0
  473. data/public/500.html +26 -0
  474. data/public/favicon.ico +0 -0
  475. data/public/favicon.psd +0 -0
  476. data/public/robots.txt +5 -0
  477. data/public/stylesheets/.gitkeep +0 -0
  478. data/public/stylesheets/ie.css +53 -0
  479. data/public/stylesheets/print.css +57 -0
  480. data/public/stylesheets/screen.css +182 -0
  481. data/script/cucumber +10 -0
  482. data/script/rails +6 -0
  483. data/spec/blueprints.rb +86 -0
  484. data/spec/controllers/api/v1/clients_controller_spec.rb +41 -0
  485. data/spec/controllers/api/v1/projects_controller_spec.rb +54 -0
  486. data/spec/controllers/api/v1/tickets_controller_spec.rb +122 -0
  487. data/spec/controllers/api/v1/tokens_controller_spec.rb +52 -0
  488. data/spec/controllers/client_login/clients_controller_spec.rb +5 -0
  489. data/spec/controllers/client_login/reports_controller_spec.rb +5 -0
  490. data/spec/controllers/data_vaults_controller_spec.rb +5 -0
  491. data/spec/internal/app/controllers/application_controller.rb +5 -0
  492. data/spec/internal/config/admin_navigation.rb +71 -0
  493. data/spec/internal/config/database.yml +14 -0
  494. data/spec/internal/config/database.yml.example +20 -0
  495. data/spec/internal/config/database.yml.mysql +20 -0
  496. data/spec/internal/config/database.yml.mysql.jruby +20 -0
  497. data/spec/internal/config/database.yml.postgres +20 -0
  498. data/spec/internal/config/database.yml.postgres.jruby +20 -0
  499. data/spec/internal/config/navigation.rb +80 -0
  500. data/spec/internal/config/routes.rb +3 -0
  501. data/spec/internal/config/secondary_navigation.rb +65 -0
  502. data/spec/internal/db/schema.rb +296 -0
  503. data/spec/internal/log/.gitignore +1 -0
  504. data/spec/internal/public/favicon.ico +0 -0
  505. data/spec/internal/public/system/attachment_files/2/original/tmp.txt +1 -0
  506. data/spec/internal/public/system/attachment_files/3/original/tmp.txt +1 -0
  507. data/spec/lib/date_ext_spec.rb +40 -0
  508. data/spec/mailers/notifier_spec.rb +9 -0
  509. data/spec/models/client_spec.rb +167 -0
  510. data/spec/models/contact_spec.rb +29 -0
  511. data/spec/models/data_vault_spec.rb +5 -0
  512. data/spec/models/project_spec.rb +115 -0
  513. data/spec/models/ticket_spec.rb +223 -0
  514. data/spec/models/user_spec.rb +258 -0
  515. data/spec/models/work_unit_spec.rb +467 -0
  516. data/spec/spec_helper.rb +44 -0
  517. data/spec/support/xrono/macros.rb +15 -0
  518. data/vendor/plugins/.gitkeep +0 -0
  519. data/xrono.gemspec +50 -0
  520. metadata +1209 -0
@@ -0,0 +1,172 @@
1
+ <mockup version="1.0" skin="sketch" measuredW="1034" measuredH="778" mockupW="1024" mockupH="768">
2
+ <controls>
3
+ <control controlID="0" controlTypeID="com.balsamiq.mockups::BrowserWindow" x="0" y="0" w="1024" h="768" measuredW="450" measuredH="400" zOrder="0" locked="true" isInGroup="-1">
4
+ <controlProperties>
5
+ <text>Isotope11%20Asset%20Tracking%0Ahttp%3A//assets.isotope11.com</text>
6
+ </controlProperties>
7
+ </control>
8
+ <control controlID="1" controlTypeID="com.balsamiq.mockups::Title" x="105" y="78" w="-1" h="-1" measuredW="168" measuredH="56" zOrder="1" locked="true" isInGroup="-1">
9
+ <controlProperties>
10
+ <text>Isotope11</text>
11
+ </controlProperties>
12
+ </control>
13
+ <control controlID="6" controlTypeID="com.balsamiq.mockups::ButtonBar" x="858" y="78" w="-1" h="-1" measuredW="151" measuredH="29" zOrder="2" locked="true" isInGroup="-1">
14
+ <controlProperties>
15
+ <text>username%2C%20logout</text>
16
+ </controlProperties>
17
+ </control>
18
+ <control controlID="64" controlTypeID="__group__" x="15" y="171" w="-1" h="-1" measuredW="775" measuredH="527" zOrder="6" locked="false" isInGroup="-1">
19
+ <groupChildrenDescriptors>
20
+ <control controlID="11" controlTypeID="com.balsamiq.mockups::Canvas" x="0" y="0" w="775" h="527" measuredW="100" measuredH="70" zOrder="0" locked="false" isInGroup="64"/>
21
+ <control controlID="10" controlTypeID="com.balsamiq.mockups::DataGrid" x="7" y="7" w="759" h="112" measuredW="648" measuredH="112" zOrder="1" locked="false" isInGroup="64">
22
+ <controlProperties>
23
+ <selectedIndex>-1</selectedIndex>
24
+ <text>M-19%2C%20T-20%2C%20W-21%2C%20R-22%2C%20F-23%2C%20S-24%2C%20S-25%2C%20TOTAL%3A%0AIXI%3A%201%5CrICS%3A%207%2CICS%3A%208%2C%20ICS%3A%206%5CrIXI%3A%201%5CrBUY%3A1%2C%20ICS%3A%2011%5CrIXI%3A%201%2C%20ICS%3A%207%2C%20%2C%20%2CTotal%20Outstanding%20Hours%3A%2087%0ATotal%3A%208%2C%20Total%3A%208%2C%20Total%3A%208%2C%20Total%3A%2012%2C%20Total%3A%207%2C%20Total%3A%200%2C%20Total%3A%200%2C%20Week%20Total%3A%2043</text>
25
+ </controlProperties>
26
+ </control>
27
+ <control controlID="37" controlTypeID="__group__" x="7" y="119" w="369" h="399" measuredW="369" measuredH="399" zOrder="2" locked="false" isInGroup="64">
28
+ <groupChildrenDescriptors>
29
+ <control controlID="36" controlTypeID="com.balsamiq.mockups::FieldSet" x="0" y="0" w="369" h="399" measuredW="200" measuredH="170" zOrder="0" locked="false" isInGroup="37">
30
+ <controlProperties>
31
+ <text>New%20Work%20Unit%20Entry</text>
32
+ </controlProperties>
33
+ </control>
34
+ <control controlID="29" controlTypeID="com.balsamiq.mockups::Tree" x="0" y="45" w="367" h="288" measuredW="300" measuredH="291" zOrder="1" locked="false" isInGroup="37">
35
+ <controlProperties>
36
+ <text>v%20Friday%2C%20Septaugust%2024%2C%202010%0A%20%5B%20%5D%20%5C%5BICS%5C%5D%20-%202%20hours%20-%20Did%20something%20to%20something%20else...%0A%20%5B%20%5D%20%5C%5BICS%5C%5D%20-%203%20hours%20-%20The%20quick%20brown%20fox%20jumped%20over...%0A%20%5B%20%5D%20%5C%5BICS%5C%5D%20-%202%20hours%20-%20Lorem%20Ipsum%20dolar%20sit%20amini%20dos...%0A%3E%20Thursday%2C%20Septaugust%2023%2C%202010%0A%3E%20Wednesday%2C%20Septaugust%2022%2C%202010%0A%3E%20Tuesday%2C%20Septaugust%2021%2C%202010%0A%3E%20Monday%2C%20Septaugust%2020%2C%202010%0A%3E%20Sunday%2C%20Septaugust%2019%2C%202010%0A%3E%20Sunday%2C%20Septaugust%2017%2C%202010%0A%3E%20Saturday%2C%20Septaugust%2016%2C%202010</text>
37
+ </controlProperties>
38
+ </control>
39
+ <control controlID="30" controlTypeID="com.balsamiq.mockups::Link" x="6" y="367" w="-1" h="-1" measuredW="118" measuredH="23" zOrder="2" locked="false" isInGroup="37">
40
+ <controlProperties>
41
+ <text>%3C%3C%20Previous%20Entries</text>
42
+ </controlProperties>
43
+ </control>
44
+ <control controlID="31" controlTypeID="com.balsamiq.mockups::Link" x="258" y="366" w="-1" h="-1" measuredW="102" measuredH="23" zOrder="3" locked="false" isInGroup="37">
45
+ <controlProperties>
46
+ <text>Later%20Entries%20%3E%3E</text>
47
+ </controlProperties>
48
+ </control>
49
+ <control controlID="33" controlTypeID="com.balsamiq.mockups::SubTitle" x="0" y="8" w="157" h="-1" measuredW="157" measuredH="37" zOrder="4" locked="false" isInGroup="37">
50
+ <controlProperties>
51
+ <text>Recent%20Work%3A</text>
52
+ </controlProperties>
53
+ </control>
54
+ </groupChildrenDescriptors>
55
+ </control>
56
+ <control controlID="63" controlTypeID="__group__" x="391" y="118" w="369" h="399" measuredW="369" measuredH="399" zOrder="3" locked="false" isInGroup="64">
57
+ <groupChildrenDescriptors>
58
+ <control controlID="28" controlTypeID="com.balsamiq.mockups::FieldSet" x="0" y="0" w="369" h="399" measuredW="200" measuredH="170" zOrder="0" locked="false" isInGroup="63">
59
+ <controlProperties>
60
+ <text>New%20Work%20Unit%20Entry</text>
61
+ </controlProperties>
62
+ </control>
63
+ <control controlID="35" controlTypeID="com.balsamiq.mockups::SubTitle" x="7" y="12" w="176" h="-1" measuredW="176" measuredH="37" zOrder="1" locked="false" isInGroup="63">
64
+ <controlProperties>
65
+ <text>Add%20Work%20Unit%3A</text>
66
+ </controlProperties>
67
+ </control>
68
+ <control controlID="38" controlTypeID="com.balsamiq.mockups::CheckBox" x="107" y="310" w="79" h="22" measuredW="79" measuredH="22" zOrder="2" locked="false" isInGroup="63">
69
+ <controlProperties>
70
+ <text>Overtime</text>
71
+ </controlProperties>
72
+ </control>
73
+ <control controlID="39" controlTypeID="com.balsamiq.mockups::CheckBox" x="234" y="310" w="73" h="22" measuredW="73" measuredH="22" zOrder="3" locked="false" isInGroup="63">
74
+ <controlProperties>
75
+ <text>Unbilled</text>
76
+ </controlProperties>
77
+ </control>
78
+ <control controlID="40" controlTypeID="com.balsamiq.mockups::ComboBox" x="107" y="71" w="112" h="-1" measuredW="112" measuredH="23" zOrder="4" locked="false" isInGroup="63">
79
+ <controlProperties>
80
+ <text>Choose%20Client</text>
81
+ </controlProperties>
82
+ </control>
83
+ <control controlID="41" controlTypeID="com.balsamiq.mockups::ComboBox" x="107" y="99" w="113" h="-1" measuredW="113" measuredH="23" zOrder="5" locked="false" isInGroup="63">
84
+ <controlProperties>
85
+ <text>Choose%20Ticket</text>
86
+ </controlProperties>
87
+ </control>
88
+ <control controlID="42" controlTypeID="com.balsamiq.mockups::Button" x="234" y="356" w="76" h="28" measuredW="76" measuredH="28" zOrder="6" locked="false" isInGroup="63">
89
+ <controlProperties>
90
+ <text>Add%20Unit</text>
91
+ </controlProperties>
92
+ </control>
93
+ <control controlID="43" controlTypeID="com.balsamiq.mockups::TextArea" x="107" y="163" w="200" h="140" measuredW="200" measuredH="140" zOrder="7" locked="false" isInGroup="63">
94
+ <controlProperties>
95
+ <text>Some%20text%0AA%20second%20line%20of%20text</text>
96
+ </controlProperties>
97
+ </control>
98
+ <control controlID="44" controlTypeID="com.balsamiq.mockups::TextInput" x="107" y="128" w="79" h="-1" measuredW="79" measuredH="29" zOrder="8" locked="false" isInGroup="63">
99
+ <controlProperties>
100
+ <text/>
101
+ </controlProperties>
102
+ </control>
103
+ <control controlID="45" controlTypeID="com.balsamiq.mockups::Label" x="7" y="132" w="42" h="23" measuredW="42" measuredH="23" zOrder="9" locked="false" isInGroup="63">
104
+ <controlProperties>
105
+ <text>Hours%3A</text>
106
+ </controlProperties>
107
+ </control>
108
+ <control controlID="46" controlTypeID="com.balsamiq.mockups::Label" x="7" y="171" w="75" h="23" measuredW="75" measuredH="23" zOrder="10" locked="false" isInGroup="63">
109
+ <controlProperties>
110
+ <text>Description%3A</text>
111
+ </controlProperties>
112
+ </control>
113
+ <control controlID="59" controlTypeID="__group__" x="7" y="49" w="156" h="24" measuredW="156" measuredH="24" zOrder="11" locked="false" isInGroup="63">
114
+ <groupChildrenDescriptors>
115
+ <control controlID="56" controlTypeID="com.balsamiq.mockups::Label" x="0" y="1" w="90" h="23" measuredW="90" measuredH="23" zOrder="0" locked="false" isInGroup="59">
116
+ <controlProperties>
117
+ <text>Scheduled%20On%3A</text>
118
+ </controlProperties>
119
+ </control>
120
+ <control controlID="57" controlTypeID="com.balsamiq.mockups::Icon" x="140" y="4" w="-1" h="-1" measuredW="16" measuredH="16" zOrder="1" locked="false" isInGroup="59">
121
+ <controlProperties>
122
+ <icon>CalendarIcon%7Cxsmall</icon>
123
+ </controlProperties>
124
+ </control>
125
+ <control controlID="58" controlTypeID="com.balsamiq.mockups::Link" x="101" y="0" w="-1" h="-1" measuredW="39" measuredH="23" zOrder="2" locked="false" isInGroup="59">
126
+ <controlProperties>
127
+ <text>Today</text>
128
+ </controlProperties>
129
+ </control>
130
+ </groupChildrenDescriptors>
131
+ </control>
132
+ <control controlID="61" controlTypeID="com.balsamiq.mockups::Label" x="7" y="71" w="44" h="23" measuredW="44" measuredH="23" zOrder="12" locked="false" isInGroup="63">
133
+ <controlProperties>
134
+ <text>Client%3A</text>
135
+ </controlProperties>
136
+ </control>
137
+ <control controlID="62" controlTypeID="com.balsamiq.mockups::Label" x="7" y="98" w="45" h="23" measuredW="45" measuredH="23" zOrder="13" locked="false" isInGroup="63">
138
+ <controlProperties>
139
+ <text>Ticket%3A</text>
140
+ </controlProperties>
141
+ </control>
142
+ </groupChildrenDescriptors>
143
+ </control>
144
+ </groupChildrenDescriptors>
145
+ </control>
146
+ <control controlID="65" controlTypeID="com.balsamiq.mockups::StickyNote" x="818" y="189" w="175" h="216" measuredW="109" measuredH="123" zOrder="7" locked="false" isInGroup="-1">
147
+ <controlProperties>
148
+ <text>This%20area%20will%20be%20used%20as%20a%20place%20for%20pligns%20to%20report%20too%2C%20such%20as%20the%20ability%20to%20watch%20a%20project%2C%20client%2C%20or%20ticket%2C%20or%20other%20future%20plugins</text>
149
+ </controlProperties>
150
+ </control>
151
+ <control controlID="12" controlTypeID="com.balsamiq.mockups::Canvas" x="809" y="171" w="200" h="527" measuredW="100" measuredH="70" zOrder="3" locked="false" isInGroup="-1"/>
152
+ <control controlID="18" controlTypeID="__group__" x="15" y="134" w="-1" h="-1" measuredW="994" measuredH="29" zOrder="4" locked="true" isInGroup="-1">
153
+ <groupChildrenDescriptors>
154
+ <control controlID="15" controlTypeID="com.balsamiq.mockups::ButtonBar" x="0" y="0" w="878" h="29" measuredW="327" measuredH="29" zOrder="0" locked="false" isInGroup="18">
155
+ <controlProperties>
156
+ <text>Home%2C%20Clients%2C%20%3F%2C%20%3F%2C%20Users%2C%20Admin</text>
157
+ </controlProperties>
158
+ </control>
159
+ <control controlID="17" controlTypeID="com.balsamiq.mockups::SearchBox" x="884" y="1" w="110" h="-1" measuredW="93" measuredH="25" zOrder="1" locked="false" isInGroup="18">
160
+ <controlProperties>
161
+ <text>search</text>
162
+ </controlProperties>
163
+ </control>
164
+ </groupChildrenDescriptors>
165
+ </control>
166
+ <control controlID="23" controlTypeID="com.balsamiq.mockups::Paragraph" x="432" y="698" w="159" h="21" measuredW="200" measuredH="140" zOrder="5" locked="false" isInGroup="-1">
167
+ <controlProperties>
168
+ <text>Footer%20Text%20Here.%20%5BA%20Link.%5D</text>
169
+ </controlProperties>
170
+ </control>
171
+ </controls>
172
+ </mockup>
@@ -0,0 +1,69 @@
1
+ Feature: Project Assignment
2
+ In order to manage projects properly
3
+ Administrators should be able to assign projects to developers
4
+
5
+ @wip
6
+ Scenario: Assign a project to a developer
7
+ Given I am an authenticated user with an admin role
8
+ And a user exists with a "developer" role
9
+ And a client "Acme" exists
10
+ And a project exists with name: "Testproject", client: client "Acme"
11
+ When I assign the project to the user
12
+ Then the user should have access to the project
13
+
14
+ Scenario: User tries to access a project they are not assigned to
15
+ Given I am an authenticated user
16
+ And a client "Acme" exists
17
+ And a project exists with name: "Testproject", client: client "Acme"
18
+ When I go to the project's page
19
+ Then I should see "Access denied." within ".alert-message"
20
+
21
+ Scenario: User tries to access a project they are assigned to
22
+ Given I am an authenticated user
23
+ And a client "Acme" exists
24
+ And a project exists with name: "Testproject", client: client "Acme"
25
+ And I am assigned to the project
26
+ When I go to the project's page
27
+ Then I should see "Testproject" within the breadcrumbs
28
+
29
+ Scenario: User tries to access the client of a project they are not assigned to
30
+ Given I am an authenticated user
31
+ And a client "Acme" exists
32
+ And a project exists with name: "Testproject", client: client "Acme"
33
+ When I go to the client's page
34
+ Then I should see "Access denied." within ".alert-message"
35
+
36
+ Scenario: User tries to access a ticket of a project they are not assigned to
37
+ Given I am an authenticated user
38
+ And a client "Acme" exists
39
+ And a project "Testproject" exists with name: "Testproject", client: client "Acme"
40
+ And a ticket exists with project: project "Testproject", name: "test ticket"
41
+ When I go to the ticket's page
42
+ Then I should see "Access denied." within ".alert-message"
43
+
44
+ Scenario: User tries to access a work unit of a project they are not assigned to
45
+ Given I am an authenticated user
46
+ And a client "Acme" exists
47
+ And a project "Testproject" exists with name: "Testproject", client: client "Acme"
48
+ And a ticket "test ticket" exists with project: project "Testproject", name: "test ticket"
49
+ And a work_unit exists with ticket: ticket "test ticket", hours: "1", scheduled_at: "2010-10-01"
50
+ When I go to the work_unit's page
51
+ Then I should see "Access denied." within ".alert-message"
52
+
53
+ Scenario: User tries to select a client they don't have access to on the dashboard
54
+ Given I am an authenticated user
55
+ And a client "test client" exists with name: "test client", initials: "TTC"
56
+ And a project "test project" exists with name: "test project", client: client "test client"
57
+ And a ticket "test ticket" exists with project: project "test project", name: "test ticket"
58
+ When I visit /
59
+ Then I should not see "test client"
60
+
61
+ Scenario: User shouldn't see projects they aren't assigned to on the client show page
62
+ Given I am an authenticated user
63
+ And a client "test client" exists with name: "test client", initials: "TTC"
64
+ And a project "test project" exists with name: "test project", client: client "test client"
65
+ And a project "assigned project" exists with name: "assigned project", client: client "test client"
66
+ And I am assigned to the project
67
+ When I go to the client's page
68
+ Then I should not see "test project"
69
+ And I should see "assigned project"
@@ -0,0 +1,38 @@
1
+ @wip
2
+ Feature: Search Work Units
3
+ In order to search work units
4
+ User
5
+ wants a nice search interface
6
+
7
+ @wip
8
+ Scenario: Search for all work units containing a particular invoiced string
9
+ Given I am an authenticated user with an admin role
10
+ And a client "test client" exists with name: "test client", initials: "TTC"
11
+ And a project "test project" exists with name: "test project", client: client "test client"
12
+ And a ticket "test ticket" exists with project: project "test project", name: "test ticket"
13
+ And a work_unit "test work unit" exists with ticket: ticket "test ticket", scheduled_at: "2010-01-01", hours: "1", invoiced: "123"
14
+ And a work unit "test work unit2" exists with ticket: ticket "test ticket", scheduled_at: "2010-02-01", hours: "1", invoiced: "123"
15
+ And I go to the work unit's page
16
+ And I follow "123"
17
+ Then I should see "2010-01-01" within "td"
18
+ And I should see "2010-02-01" within "td"
19
+
20
+ @wip
21
+ Scenario: Search for all work units containing a particular paid string
22
+ Given I am an authenticated user with an admin role
23
+ And a client "test client" exists with name: "test client", initials: "TTC"
24
+ And a project "test project" exists with name: "test project", client: client "test client"
25
+ And a ticket "test ticket" exists with project: project "test project", name: "test ticket"
26
+ And a work_unit "test work unit" exists with ticket: ticket "test ticket", scheduled_at: "2010-03-01", hours: "1", paid: "12"
27
+ And a work unit "test work unit2" exists with ticket: ticket "test ticket", scheduled_at: "2010-04-01", hours: "1", paid: "12"
28
+ And a work unit "test work unit3" exists with ticket: ticket "test ticket", scheduled_at: "2010-01-01", hours: "1", paid: "34"
29
+ And I go to the first work unit's page
30
+ And I follow "12"
31
+ Then I should see "2010-03-01" within "td"
32
+ And I should see "2010-04-01" within "td"
33
+
34
+ @wip
35
+ Scenario: Cannot search if I am not an admin
36
+ Given I am an authenticated user with an developer role
37
+ And I visit /work_units
38
+ Then I should see "You must be an admin to do that"
@@ -0,0 +1,7 @@
1
+ Then /^I should see description$/ do
2
+ page.should have_css('.description')
3
+ end
4
+
5
+ Then /^I should see description\.expand$/ do
6
+ page.should have_css('.description.expand')
7
+ end
@@ -0,0 +1,8 @@
1
+ Given /^I only have (\d+) client$/ do |num_clients|
2
+ num_projects = num_clients.to_i - Client.for_user(@current_user).all.count #for some reason count without the all was returning {1=>1}
3
+ num_projects.times do |i|
4
+ p = Project.make
5
+ @current_user.has_role!(:client, p)
6
+ end
7
+ Client.for_user(@current_user).all.count.should == num_clients.to_i
8
+ end
@@ -0,0 +1,29 @@
1
+ Given /^the following clients:$/ do |clients|
2
+ Client.create!(clients.hashes)
3
+ end
4
+
5
+ When /^I visit the clients index page$/ do
6
+ visit clients_path
7
+ end
8
+
9
+ When /^I delete the (\d+)(?:st|nd|rd|th) client$/ do |pos|
10
+ visit clients_path
11
+ within("table tbody tr:nth-child(#{pos.to_i})") do
12
+ click_link "Destroy"
13
+ end
14
+ end
15
+
16
+ Then /^I should see the following clients:$/ do |expected_clients_table|
17
+ expected_clients_table.diff!(find('table').all('tr').map { |row| row.all('th, td').map { |cell| cell.text.strip } })
18
+ end
19
+
20
+ Given /^the following clients, projects and tickets exist$/ do |table|
21
+ table.hashes.each do |row|
22
+ client = Client.make :name => row["client name"]
23
+ project = Project.make :name => row["project name"], :client => client
24
+ ticket = Ticket.make :name => row["ticket name"], :project => project
25
+ Client.find_by_name(client.name).should_not == nil
26
+ client.projects.find_by_name(project.name).should_not == nil
27
+ project.tickets.find_by_name(ticket.name).should_not == nil
28
+ end
29
+ end
@@ -0,0 +1,4 @@
1
+ Given /^the following comments:$/ do |comments|
2
+ ::Comment.create!(comments.hashes)
3
+ end
4
+
@@ -0,0 +1,22 @@
1
+ Given /^the following contacts:$/ do |contacts|
2
+ Contact.create!(contacts.hashes)
3
+ end
4
+
5
+ When /^I visit the contacts index page$/ do
6
+ visit client_contacts_path
7
+ end
8
+
9
+
10
+
11
+ When /^I delete the (\d+)(?:st|nd|rd|th) contact$/ do |pos|
12
+ visit client_contacts_path
13
+ within("table tbody tr:nth-child(#{pos.to_i})") do
14
+ click_link "Destroy"
15
+ end
16
+ end
17
+
18
+ Then /^I should see the following contacts:$/ do |expected_contacts_table|
19
+ expected_contacts_table.diff!(find('table').all('tr').map { |row| row.all('th, td').map { |cell| cell.text.strip } })
20
+ end
21
+
22
+
@@ -0,0 +1,5 @@
1
+ Given /^I debug$/ do
2
+ de="de"
3
+ debugger
4
+ de="de"
5
+ end
@@ -0,0 +1,26 @@
1
+ Given /^I am an authenticated user with an? (\w+) role$/ do |role|
2
+ visit destroy_user_session_path
3
+ @current_user = User.make(:email => "current_user@example.com", :password => "password", :password_confirmation => "password")
4
+ @current_user.has_role!(role.to_sym) if role
5
+ if role == 'client'
6
+ p = Project.make
7
+ @current_user.has_role!(:client, p)
8
+ end
9
+ visit new_user_session_path
10
+ step %{I fill in "user_email" with "current_user@example.com"}
11
+ step %{I fill in "user_password" with "password"}
12
+ step %{I press "Sign in"}
13
+ end
14
+
15
+ Given /^I am an authenticated user$/ do
16
+ visit destroy_user_session_path
17
+ @current_user = User.make(:email => "current_user@example.com", :password => "password", :password_confirmation => "password")
18
+ visit new_user_session_path
19
+ step %{I fill in "user_email" with "current_user@example.com"}
20
+ step %{I fill in "user_password" with "password"}
21
+ step %{I press "Sign in"}
22
+ end
23
+
24
+ Then /^I should see the following users:$/ do |expected_users_table|
25
+ expected_users_table.diff!(find('table').all('tr').map { |row| row.all('th, td').map { |cell| cell.text.strip } })
26
+ end
@@ -0,0 +1,74 @@
1
+ # this file generated by script/generate pickle email
2
+ #
3
+ # add email mappings in features/support/email.rb
4
+
5
+ ActionMailer::Base.delivery_method = :test
6
+ ActionMailer::Base.perform_deliveries = true
7
+
8
+ Before do
9
+ ActionMailer::Base.deliveries.clear
10
+ end
11
+
12
+ # Clear the deliveries array, useful if your background sends email that you want to ignore
13
+ Given(/^all emails? (?:have|has) been delivered$/) do
14
+ ActionMailer::Base.deliveries.clear
15
+ end
16
+
17
+ Given(/^(\d)+ emails? should be delivered$/) do |count|
18
+ emails.size.should == count.to_i
19
+ end
20
+
21
+ # not auto-generated
22
+
23
+ When(/^the daily email goes out to #{capture_model}$/) do |name|
24
+ client = find_model!(name)
25
+ DailyNotifierWorker.perform_async(client.id)
26
+ end
27
+
28
+ When(/^(?:I|they) follow "([^"]*?)" in #{capture_email}$/) do |link, email_ref|
29
+ visit_in_email(email(email_ref), link)
30
+ end
31
+
32
+ When(/^(?:I|they) click the first link in #{capture_email}$/) do |email_ref|
33
+ click_first_link_in_email(email(email_ref))
34
+ end
35
+
36
+ Then(/^(\d)+ emails? should be delivered bcc to (.*)$/) do |count, to|
37
+ emails("bcc: \"#{email_for(to)}\"").size.should == count.to_i
38
+ end
39
+
40
+ Then(/^(\d)+ emails? should be delivered to (.*)$/) do |count, to|
41
+ emails("to: \"#{email_for(to)}\"").size.should == count.to_i
42
+ end
43
+
44
+ Then(/^(\d)+ emails? should be delivered with #{capture_fields}$/) do |count, fields|
45
+ emails(fields).size.should == count.to_i
46
+ end
47
+
48
+ Then(/^#{capture_email} should be delivered to (.+)$/) do |email_ref, to|
49
+ email(email_ref, "to: \"#{email_for(to)}\"").should_not be_nil
50
+ end
51
+
52
+ Then(/^#{capture_email} should not be delivered to (.+)$/) do |email_ref, to|
53
+ email(email_ref, "to: \"#{email_for(to)}\"").should be_nil
54
+ end
55
+
56
+ Then(/^#{capture_email} should have #{capture_fields}$/) do |email_ref, fields|
57
+ email(email_ref, fields).should_not be_nil
58
+ end
59
+
60
+ Then(/^#{capture_email} should contain "(.*)"$/) do |email_ref, text|
61
+ email(email_ref).body.should =~ /#{text}/
62
+ end
63
+
64
+ Then(/^#{capture_email} should not contain "(.*)"$/) do |email_ref, text|
65
+ email(email_ref).body.should_not =~ /#{text}/
66
+ end
67
+
68
+ Then(/^#{capture_email} should link to (.+)$/) do |email_ref, page|
69
+ email(email_ref).body.should =~ /#{path_to(page)}/
70
+ end
71
+
72
+ Then(/^show me the emails?$/) do
73
+ save_and_open_emails
74
+ end