shell-spinner 1.0.1 → 1.0.2

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 (476) hide show
  1. data/.gitignore +22 -4
  2. data/.rspec +1 -0
  3. data/.rvmrc +53 -0
  4. data/Gemfile +90 -3
  5. data/Gemfile.lock +479 -0
  6. data/README.md +56 -0
  7. data/Rakefile +7 -1
  8. data/app/admin/carriers.rb +17 -0
  9. data/app/admin/dashboards.rb +31 -0
  10. data/app/admin/interviews.rb +77 -0
  11. data/app/admin/users.rb +40 -0
  12. data/app/assets/images/icons/ajax-loader.gif +0 -0
  13. data/app/assets/images/icons/clear-results.png +0 -0
  14. data/app/assets/images/icons/clipboard.png +0 -0
  15. data/app/assets/images/icons/magnify.png +0 -0
  16. data/app/assets/images/icons/social/facebook.png +0 -0
  17. data/app/assets/images/icons/social/google.png +0 -0
  18. data/app/assets/images/icons/social/linkedin.png +0 -0
  19. data/app/assets/images/icons/social/small/facebook.png +0 -0
  20. data/app/assets/images/icons/social/small/google.png +0 -0
  21. data/app/assets/images/icons/social/small/linkedin.png +0 -0
  22. data/app/assets/images/icons/social/small/twitter.png +0 -0
  23. data/app/assets/images/icons/social/small/windowslive.png +0 -0
  24. data/app/assets/images/icons/social/small/yahoo.png +0 -0
  25. data/app/assets/images/icons/social/twitter.png +0 -0
  26. data/app/assets/images/icons/social/windowslive.png +0 -0
  27. data/app/assets/images/icons/social/yahoo.png +0 -0
  28. data/app/assets/images/logo.png +0 -0
  29. data/app/assets/javascripts/active_admin.js.coffee +18 -0
  30. data/app/assets/javascripts/admin/base.coffee +0 -0
  31. data/app/assets/javascripts/admin/interview_form.coffee +95 -0
  32. data/app/assets/javascripts/app/controllers/questions.js.coffee +12 -0
  33. data/app/assets/javascripts/app/index.js.coffee +25 -0
  34. data/app/assets/javascripts/app/lib/view.js.coffee +3 -0
  35. data/app/assets/javascripts/app/models/interview_template.js.coffee +6 -0
  36. data/app/assets/javascripts/app/models/question.js.coffee +6 -0
  37. data/app/assets/javascripts/app/views/questions/show.jst.hamljs +2 -0
  38. data/app/assets/javascripts/application.coffee +48 -0
  39. data/app/assets/javascripts/attachment_form.coffee +31 -0
  40. data/app/assets/javascripts/clipboard_control.coffee +30 -0
  41. data/app/assets/javascripts/invitation_form.coffee +72 -0
  42. data/app/assets/javascripts/recommendation_form.coffee +19 -0
  43. data/app/assets/javascripts/recommendations_list.coffee +11 -0
  44. data/app/assets/javascripts/search_contacts_form.coffee +36 -0
  45. data/app/assets/javascripts/templates/empty_recipients_list.tmpl +1 -0
  46. data/app/assets/javascripts/templates/recipient.tmpl +5 -0
  47. data/app/assets/stylesheets/active_admin.css.scss +28 -0
  48. data/app/assets/stylesheets/application.sass +24 -0
  49. data/app/assets/stylesheets/includes/_authorisation.sass +29 -0
  50. data/app/assets/stylesheets/includes/_bootstrap_tweaks.sass +2 -0
  51. data/app/assets/stylesheets/includes/_campaigns.sass +44 -0
  52. data/app/assets/stylesheets/includes/_controls.sass +41 -0
  53. data/app/assets/stylesheets/includes/_form.sass +23 -0
  54. data/app/assets/stylesheets/includes/_formatting.sass +8 -0
  55. data/app/assets/stylesheets/includes/_icons.sass +31 -0
  56. data/app/assets/stylesheets/includes/_interview.sass +16 -0
  57. data/app/assets/stylesheets/includes/_interview_form.sass +170 -0
  58. data/app/assets/stylesheets/includes/_interview_management.sass +3 -0
  59. data/app/assets/stylesheets/includes/_invitation_form.sass +190 -0
  60. data/app/assets/stylesheets/includes/_layout.sass +69 -0
  61. data/app/assets/stylesheets/includes/_mixins.sass +42 -0
  62. data/app/assets/stylesheets/includes/_navigation.sass +16 -0
  63. data/app/assets/stylesheets/includes/_recommendations.sass +34 -0
  64. data/app/concerns/authenticate_users.rb +72 -0
  65. data/app/concerns/conditional_redirect_after_signing_in.rb +24 -0
  66. data/app/concerns/eventable.rb +16 -0
  67. data/app/controllers/application_controller.rb +31 -0
  68. data/app/controllers/attachments_controller.rb +36 -0
  69. data/app/controllers/campaigns_controller.rb +23 -0
  70. data/app/controllers/contacts_controller.rb +37 -0
  71. data/app/controllers/interview_result_invitations_controller.rb +21 -0
  72. data/app/controllers/interview_results_controller.rb +39 -0
  73. data/app/controllers/interview_templates_controller.rb +3 -0
  74. data/app/controllers/pages_controller.rb +6 -0
  75. data/app/controllers/questions_controller.rb +5 -0
  76. data/app/controllers/recommendations_controller.rb +64 -0
  77. data/app/controllers/resources_controller.rb +1 -0
  78. data/app/controllers/users/omniauth_callbacks_controller.rb +52 -0
  79. data/app/helpers/admin/interview_helper.rb +14 -0
  80. data/app/helpers/answers_helper.rb +8 -0
  81. data/app/helpers/application_helper.rb +1 -0
  82. data/app/helpers/attachments_helper.rb +5 -0
  83. data/app/helpers/campaigns_helper.rb +5 -0
  84. data/app/helpers/layout_helper.rb +5 -0
  85. data/app/helpers/recommendation_helper.rb +14 -0
  86. data/app/mailers/invitation_mailer.rb +13 -0
  87. data/app/models/ability.rb +23 -0
  88. data/app/models/answer.rb +36 -0
  89. data/app/models/answer_choice.rb +28 -0
  90. data/app/models/attachment.rb +34 -0
  91. data/app/models/buying_attempt.rb +31 -0
  92. data/app/models/campaign.rb +37 -0
  93. data/app/models/carrier.rb +30 -0
  94. data/app/models/cell_phone_insurance_interview.rb +17 -0
  95. data/app/models/contact.rb +31 -0
  96. data/app/models/default_interview.rb +17 -0
  97. data/app/models/interesting_fact.rb +30 -0
  98. data/app/models/interview_result.rb +65 -0
  99. data/app/models/interview_template.rb +52 -0
  100. data/app/models/invitation.rb +45 -0
  101. data/app/models/invitation_identifier.rb +29 -0
  102. data/app/models/numeric_question.rb +19 -0
  103. data/app/models/one_correct_question.rb +27 -0
  104. data/app/models/possible_answer.rb +54 -0
  105. data/app/models/question.rb +96 -0
  106. data/app/models/recommendation.rb +27 -0
  107. data/app/models/scale_question.rb +42 -0
  108. data/app/models/user.rb +102 -0
  109. data/app/models/yes_no_question.rb +18 -0
  110. data/app/renderers/nav_links_renderer.rb +10 -0
  111. data/app/uploaders/attachement_uploader.rb +55 -0
  112. data/app/uploaders/file_uploader.rb +20 -0
  113. data/app/views/admin/interviews/_form.html.haml +36 -0
  114. data/app/views/admin/interviews/_possible_answer_fields.html.haml +6 -0
  115. data/app/views/admin/interviews/_question_fields.html.haml +28 -0
  116. data/app/views/admin/interviews/_wrapper_question_fields.html.haml +2 -0
  117. data/app/views/admin/interviews/numeric_question/_fields.html.haml +7 -0
  118. data/app/views/admin/interviews/one_correct_question/_answer_fields.html.haml +6 -0
  119. data/app/views/admin/interviews/one_correct_question/_fields.html.haml +18 -0
  120. data/app/views/admin/interviews/scale_question/_fields.html.haml +7 -0
  121. data/app/views/admin/interviews/scale_question/_start_end_values.html.haml +6 -0
  122. data/app/views/admin/interviews/yes_no_question/_fields.html.haml +3 -0
  123. data/app/views/attachments/_form.html.haml +5 -0
  124. data/app/views/attachments/_interesting_facts.html.haml +11 -0
  125. data/app/views/attachments/_resource.html.haml +13 -0
  126. data/app/views/attachments/buttons/_delete.html.haml +3 -0
  127. data/app/views/attachments/index.html.haml +28 -0
  128. data/app/views/attachments/new.html.haml +1 -0
  129. data/app/views/attachments/show.html.haml +1 -0
  130. data/app/views/campaigns/_form.html.haml +7 -0
  131. data/app/views/campaigns/_form_actions.html.haml +4 -0
  132. data/app/views/campaigns/edit.html.haml +7 -0
  133. data/app/views/campaigns/index.html.haml +14 -0
  134. data/app/views/campaigns/new.html.haml +7 -0
  135. data/app/views/campaigns/show.html.haml +15 -0
  136. data/app/views/contacts/_list.html.haml +17 -0
  137. data/app/views/contacts/_table.html.haml +8 -0
  138. data/app/views/contacts/search.html.haml +1 -0
  139. data/app/views/interesting_facts/_fact.html.haml +4 -0
  140. data/app/views/interview_result_invitations/new.html.haml +29 -0
  141. data/app/views/interview_results/_answer_choice.html.haml +11 -0
  142. data/app/views/interview_results/_form.html.haml +16 -0
  143. data/app/views/interview_results/_list.html.haml +3 -0
  144. data/app/views/interview_results/_numeric_question.html.haml +3 -0
  145. data/app/views/interview_results/_one_correct_question.html.haml +3 -0
  146. data/app/views/interview_results/_scale_question.html.haml +6 -0
  147. data/app/views/interview_results/_yes_no_question.html.haml +6 -0
  148. data/app/views/interview_results/index.html.haml +2 -0
  149. data/app/views/interview_results/new.html.haml +4 -0
  150. data/app/views/interview_results/numeric/_price.html.haml +2 -0
  151. data/app/views/interview_results/numeric/_simple_number.html.haml +2 -0
  152. data/app/views/interview_results/one_correct/_dropdown.html.haml +1 -0
  153. data/app/views/interview_results/one_correct/_radio.html.haml +2 -0
  154. data/app/views/interview_results/one_correct/_slider.html.haml +2 -0
  155. data/app/views/interview_results/show.html.haml +24 -0
  156. data/app/views/interview_templates/index.json.rabl +6 -0
  157. data/app/views/interview_templates/show.html.haml +1 -0
  158. data/app/views/layouts/_footer.haml +9 -0
  159. data/app/views/layouts/_header.haml +21 -0
  160. data/app/views/layouts/application.html.haml +29 -0
  161. data/app/views/pages/home.html.haml +10 -0
  162. data/app/views/questions/show.json.rabl +2 -0
  163. data/app/views/recommendations/new.html.haml +19 -0
  164. data/app/views/shared/_ask_facebook_friends.html.haml +11 -0
  165. data/app/views/shared/_ask_twitter_followers.html.haml +13 -0
  166. data/app/views/shared/_conditional_html_tags.html.haml +8 -0
  167. data/app/views/shared/_errors.html.haml +2 -0
  168. data/app/views/shared/_friends_recommendations.html.haml +12 -0
  169. data/app/views/shared/_import_contacts_links.html.haml +10 -0
  170. data/app/views/shared/_interview_widget.html.haml +1 -0
  171. data/app/views/shared/_login_social_buttons.html.haml +19 -0
  172. data/app/views/shared/_sign_in_modal.html.haml +22 -0
  173. data/app/views/shared/buttons/_create.html.haml +3 -0
  174. data/app/views/shared/buttons/_delete.html.haml +3 -0
  175. data/app/views/shared/buttons/_edit.html.haml +3 -0
  176. data/app/views/users/confirmations/new.html.haml +11 -0
  177. data/app/views/users/mailer/confirmation_instructions.html.haml +4 -0
  178. data/app/views/users/mailer/reset_password_instructions.html.haml +6 -0
  179. data/app/views/users/mailer/unlock_instructions.html.haml +5 -0
  180. data/app/views/users/passwords/edit.html.haml +16 -0
  181. data/app/views/users/passwords/new.html.haml +9 -0
  182. data/app/views/users/registrations/edit.html.haml +27 -0
  183. data/app/views/users/registrations/new.html.haml +17 -0
  184. data/app/views/users/sessions/new.html.haml +14 -0
  185. data/app/views/users/shared/_links.haml +14 -0
  186. data/app/views/users/unlocks/new.html.haml +11 -0
  187. data/config.ru +4 -0
  188. data/config/application.rb +86 -0
  189. data/config/boot.rb +6 -0
  190. data/config/bottom_navigation.rb +13 -0
  191. data/config/cucumber.yml +8 -0
  192. data/config/database.yml +20 -0
  193. data/config/environment.rb +5 -0
  194. data/config/environments/development.rb +38 -0
  195. data/config/environments/production.rb +71 -0
  196. data/config/environments/test.rb +39 -0
  197. data/config/exceptional.yml +7 -0
  198. data/config/initializers/active_admin.rb +129 -0
  199. data/config/initializers/backtrace_silencers.rb +7 -0
  200. data/config/initializers/contacts_monkey_patch.rb +8 -0
  201. data/config/initializers/core_extensions.rb +1 -0
  202. data/config/initializers/delayed_job_config.rb +6 -0
  203. data/config/initializers/devise.rb +236 -0
  204. data/config/initializers/formtastic.rb +1 -0
  205. data/config/initializers/generators.rb +2 -0
  206. data/config/initializers/inflections.rb +15 -0
  207. data/config/initializers/mime_types.rb +5 -0
  208. data/config/initializers/net_ssl_monkey_patch.rb +22 -0
  209. data/config/initializers/secret_token.rb +7 -0
  210. data/config/initializers/session_store.rb +8 -0
  211. data/config/initializers/settings.rb +20 -0
  212. data/config/initializers/setup_mailer.rb +1 -0
  213. data/config/initializers/wrap_parameters.rb +14 -0
  214. data/config/locales/devise.en.yml +57 -0
  215. data/config/locales/en.yml +131 -0
  216. data/config/navigation.rb +25 -0
  217. data/config/omniauth.yml +54 -0
  218. data/config/routes.rb +41 -0
  219. data/config/sendgrid.yml +18 -0
  220. data/config/sendgrid.yml.example +18 -0
  221. data/config/top_navigation.rb +28 -0
  222. data/data/.gitkeep +0 -0
  223. data/db/migrate/20120615102902_create_users.rb +10 -0
  224. data/db/migrate/20120615103611_add_devise_to_users.rb +53 -0
  225. data/db/migrate/20120615104044_add_facebook_id_to_users.rb +5 -0
  226. data/db/migrate/20120618051144_add_twitter_id_to_users.rb +5 -0
  227. data/db/migrate/20120618051522_add_google_id_to_users.rb +5 -0
  228. data/db/migrate/20120618083140_add_linkedin_id_to_users.rb +5 -0
  229. data/db/migrate/20120618094240_add_yahoo_id_to_users.rb +5 -0
  230. data/db/migrate/20120618102303_add_windowslive_id_to_users.rb +5 -0
  231. data/db/migrate/20120618121959_create_survey_templates.rb +9 -0
  232. data/db/migrate/20120618122120_create_survey_results.rb +10 -0
  233. data/db/migrate/20120618122346_create_questions.rb +12 -0
  234. data/db/migrate/20120618122442_create_answers.rb +11 -0
  235. data/db/migrate/20120618122551_create_question_results.rb +10 -0
  236. data/db/migrate/20120618123137_create_question_choices.rb +10 -0
  237. data/db/migrate/20120619142239_create_admin_notes.rb +17 -0
  238. data/db/migrate/20120619142255_move_admin_notes_to_comments.rb +25 -0
  239. data/db/migrate/20120619142315_add_fields_to_survey_template.rb +6 -0
  240. data/db/migrate/20120621124117_add_role_to_users.rb +5 -0
  241. data/db/migrate/20120625115344_rename_surveys_to_interviews.rb +5 -0
  242. data/db/migrate/20120625120613_rename_survey_relation_field.rb +7 -0
  243. data/db/migrate/20120625121230_rename_survey_results_to_interview_results.rb +5 -0
  244. data/db/migrate/20120625134119_add_type_field_to_interview_templates.rb +5 -0
  245. data/db/migrate/20120627104823_add_display_as_field_to_question.rb +5 -0
  246. data/db/migrate/20120628115724_rename_question_choices_to_answer_choices.rb +5 -0
  247. data/db/migrate/20120628124041_rename_answers_to_possible_answers.rb +5 -0
  248. data/db/migrate/20120628125515_rename_question_results_to_answers.rb +5 -0
  249. data/db/migrate/20120628125728_rename_questions_body_to_text.rb +5 -0
  250. data/db/migrate/20120628125839_rename_possible_answers_body_to_text.rb +5 -0
  251. data/db/migrate/20120628131944_fix_answer_choice_fields.rb +6 -0
  252. data/db/migrate/20120704144442_add_text_to_answer_choices.rb +5 -0
  253. data/db/migrate/20120706065743_add_body_from3rd_point_view_to_possible_answers.rb +5 -0
  254. data/db/migrate/20120706125136_change_facebook_id_and_twitter_id_type.rb +11 -0
  255. data/db/migrate/20120710070940_create_invitations.rb +10 -0
  256. data/db/migrate/20120710105054_create_delayed_jobs.rb +22 -0
  257. data/db/migrate/20120711084512_create_recommendations.rb +14 -0
  258. data/db/migrate/20120712092224_create_invitation_identifiers.rb +8 -0
  259. data/db/migrate/20120712130638_remove_user_id_from_recommendations.rb +9 -0
  260. data/db/migrate/20120712130711_remove_interview_template_id_from_recommendations.rb +9 -0
  261. data/db/migrate/20120712130744_add_invitation_id_to_recommendations.rb +5 -0
  262. data/db/migrate/20120716113646_create_contacts.rb +12 -0
  263. data/db/migrate/20120718135613_add_secret_to_interview_results.rb +5 -0
  264. data/db/migrate/20120718162312_fix_recommendation_relation.rb +5 -0
  265. data/db/migrate/20120724095308_add_state_to_interview_results.rb +5 -0
  266. data/db/migrate/20120724142439_create_carriers.rb +11 -0
  267. data/db/migrate/20120725071947_create_campaigns.rb +11 -0
  268. data/db/migrate/20120725083605_add_last_visited_path_to_users.rb +5 -0
  269. data/db/migrate/20120725085526_create_interesting_facts.rb +13 -0
  270. data/db/migrate/20120725131809_add_attachment_to_campaigns.rb +5 -0
  271. data/db/migrate/20120726115141_create_attachments.rb +10 -0
  272. data/db/migrate/20120726115644_extract_attachment_from_campaign.rb +11 -0
  273. data/db/migrate/20120726135706_create_buying_attempts.rb +11 -0
  274. data/db/migrate/20120727104402_add_campaign_id_to_interview_result.rb +5 -0
  275. data/db/migrate/20120730064404_change_interesting_facts.rb +6 -0
  276. data/db/migrate/20120730114402_add_attachment_id_to_interesting_facts.rb +5 -0
  277. data/db/migrate/20120730115758_remove_campaign_id_from_interesting_facts.rb +9 -0
  278. data/db/schema.rb +201 -0
  279. data/db/seeds.rb +86 -0
  280. data/doc/Ability.html +221 -0
  281. data/doc/Admin/InterviewHelper.html +292 -0
  282. data/doc/Answer.html +241 -0
  283. data/doc/AnswerChoice.html +296 -0
  284. data/doc/AnswersHelper.html +194 -0
  285. data/doc/ApplicationController.html +318 -0
  286. data/doc/ApplicationHelper.html +119 -0
  287. data/doc/CellPhoneInsuranceInterview.html +192 -0
  288. data/doc/Contact.html +186 -0
  289. data/doc/ContactsController.html +283 -0
  290. data/doc/CoreExtensions.html +129 -0
  291. data/doc/CoreExtensions/Object.html +210 -0
  292. data/doc/DefaultInterview.html +192 -0
  293. data/doc/DevelopmentMailInterceptor.html +203 -0
  294. data/doc/EmailValidator.html +210 -0
  295. data/doc/InterviewResult.html +251 -0
  296. data/doc/InterviewResultInvitationsController.html +218 -0
  297. data/doc/InterviewResultsController.html +280 -0
  298. data/doc/InterviewTemplate.html +330 -0
  299. data/doc/InterviewTemplatesController.html +145 -0
  300. data/doc/Invitation.html +362 -0
  301. data/doc/InvitationIdentifier.html +287 -0
  302. data/doc/InvitationMailer.html +218 -0
  303. data/doc/LayoutHelper.html +188 -0
  304. data/doc/NavLinksRenderer.html +214 -0
  305. data/doc/NumericQuestion.html +196 -0
  306. data/doc/OneCorrectQuestion.html +269 -0
  307. data/doc/PagesController.html +206 -0
  308. data/doc/PossibleAnswer.html +627 -0
  309. data/doc/Question.html +620 -0
  310. data/doc/Recommendation.html +186 -0
  311. data/doc/RecommendationHelper.html +292 -0
  312. data/doc/RecommendationsController.html +230 -0
  313. data/doc/ResourcesController.html +141 -0
  314. data/doc/ScaleQuestion.html +525 -0
  315. data/doc/SocialProvidersConfig.html +240 -0
  316. data/doc/User.html +677 -0
  317. data/doc/Users/OmniauthCallbacksController.html +542 -0
  318. data/doc/Wisemuv/Contacts.html +188 -0
  319. data/doc/Wisemuv/Contacts/Google/ControllerConcerns.html +204 -0
  320. data/doc/Wisemuv/Contacts/Google/ModelConcerns.html +128 -0
  321. data/doc/Wisemuv/Contacts/WindowsLive/ControllerConcerns.html +204 -0
  322. data/doc/Wisemuv/Contacts/WindowsLive/Grabber.html +307 -0
  323. data/doc/Wisemuv/Contacts/WindowsLive/ModelConcerns.html +128 -0
  324. data/doc/Wisemuv/Contacts/Yahoo/ControllerConcerns.html +206 -0
  325. data/doc/Wisemuv/Contacts/Yahoo/Grabber.html +526 -0
  326. data/doc/Wisemuv/Contacts/Yahoo/ModelConcerns.html +128 -0
  327. data/doc/YesNoQuestion.html +209 -0
  328. data/doc/_index.html +509 -0
  329. data/doc/carriers-campaigns-interviews-relationships.png +0 -0
  330. data/doc/class_list.html +61 -0
  331. data/doc/css/common.css +1 -0
  332. data/doc/css/cucumber.css +222 -0
  333. data/doc/css/full_list.css +57 -0
  334. data/doc/css/style.css +328 -0
  335. data/doc/feature_list.html +513 -0
  336. data/doc/file.README.html +152 -0
  337. data/doc/file_list.html +63 -0
  338. data/doc/frames.html +28 -0
  339. data/doc/index.html +152 -0
  340. data/doc/js/app.js +214 -0
  341. data/doc/js/cucumber.js +305 -0
  342. data/doc/js/full_list.js +173 -0
  343. data/doc/js/jquery.js +4 -0
  344. data/doc/method_list.html +740 -0
  345. data/doc/requirements.html +196 -0
  346. data/doc/requirements/features.html +180 -0
  347. data/doc/requirements/features/admin_manages_users.html +1260 -0
  348. data/doc/requirements/features/ask_friends_and_family.html +918 -0
  349. data/doc/requirements/features/create_interview.html +1734 -0
  350. data/doc/requirements/features/edit_interview.html +832 -0
  351. data/doc/requirements/features/pass_interview.html +757 -0
  352. data/doc/requirements/features/pulling_contacts.html +718 -0
  353. data/doc/requirements/features/questions_order_during_creating_interview.html +126 -0
  354. data/doc/requirements/features/sign_in.html +1035 -0
  355. data/doc/requirements/features/sign_up.html +1948 -0
  356. data/doc/requirements/step_transformers.html +10401 -0
  357. data/doc/requirements/tags.html +670 -0
  358. data/doc/requirements/tags/javascript.html +245 -0
  359. data/doc/requirements/tags/omniauth.html +165 -0
  360. data/doc/requirements/tags/users.html +227 -0
  361. data/doc/tag_list.html +82 -0
  362. data/doc/top-level-namespace.html +128 -0
  363. data/features/admin_manages_users.feature +57 -0
  364. data/features/ask_friends_and_family.feature +39 -0
  365. data/features/buying_tracking_code.feature +11 -0
  366. data/features/campaign_management.feature +42 -0
  367. data/features/create_interview.feature +74 -0
  368. data/features/edit_interview.feature +40 -0
  369. data/features/interesting_facts_parser.feature +11 -0
  370. data/features/interview_completion.feature +6 -0
  371. data/features/pass_interview.feature +31 -0
  372. data/features/pulling_contacts.feature +21 -0
  373. data/features/questions_order_during_creating_interview.feature +2 -0
  374. data/features/redirecting_after_signing_in.feature +19 -0
  375. data/features/sign_in.feature +51 -0
  376. data/features/sign_up.feature +43 -0
  377. data/features/step_definitions/admin_manages_users_steps.rb +91 -0
  378. data/features/step_definitions/ask_friends_and_family_steps.rb +41 -0
  379. data/features/step_definitions/buying_tracking_code_steps.rb +15 -0
  380. data/features/step_definitions/campaign_management_steps.rb +50 -0
  381. data/features/step_definitions/create_interview_steps.rb +130 -0
  382. data/features/step_definitions/edit_interview_steps.rb +35 -0
  383. data/features/step_definitions/interesting_facts_parser_steps.rb +34 -0
  384. data/features/step_definitions/interview_completion_steps.rb +8 -0
  385. data/features/step_definitions/interview_results_steps.rb +7 -0
  386. data/features/step_definitions/interview_steps.rb +11 -0
  387. data/features/step_definitions/pass_interview_steps.rb +52 -0
  388. data/features/step_definitions/pulling_contacts_steps.rb +24 -0
  389. data/features/step_definitions/redirecting_after_sign_in_steps.rb +19 -0
  390. data/features/step_definitions/sign_in_steps.rb +110 -0
  391. data/features/step_definitions/sign_up_steps.rb +56 -0
  392. data/features/support/env.rb +23 -0
  393. data/features/support/omniauth.rb +69 -0
  394. data/features/support/pickle.rb +26 -0
  395. data/features/support/uploading.rb +6 -0
  396. data/features/support/users.rb +18 -0
  397. data/features/upload-files/Life Insurance Facts-Final.xls +0 -0
  398. data/lib/assets/.gitkeep +0 -0
  399. data/lib/core_extensions/object.rb +9 -0
  400. data/lib/interceptors/development_mail_interceptor.rb +5 -0
  401. data/lib/social_providers_config.rb +10 -0
  402. data/lib/tasks/auto_annotate_models.rake +22 -0
  403. data/lib/tasks/cucumber.rake +65 -0
  404. data/lib/tasks/db/reseed.rake +12 -0
  405. data/lib/tasks/db/seed/interviews.rake +14 -0
  406. data/lib/tasks/db/truncate.rake +19 -0
  407. data/lib/tasks/yardoc.rake +19 -0
  408. data/lib/validators/email_validator.rb +7 -0
  409. data/lib/wisemuv/contacts.rb +5 -0
  410. data/lib/wisemuv/contacts/google/controller_concerns.rb +19 -0
  411. data/lib/wisemuv/contacts/google/model_concerns.rb +17 -0
  412. data/lib/wisemuv/contacts/windows_live/controller_concerns.rb +23 -0
  413. data/lib/wisemuv/contacts/windows_live/grabber.rb +22 -0
  414. data/lib/wisemuv/contacts/windows_live/model_concerns.rb +17 -0
  415. data/lib/wisemuv/contacts/yahoo/controller_concerns.rb +29 -0
  416. data/lib/wisemuv/contacts/yahoo/grabber.rb +55 -0
  417. data/lib/wisemuv/contacts/yahoo/model_concerns.rb +17 -0
  418. data/lib/wisemuv/interesting_facts_parser.rb +65 -0
  419. data/log/.gitkeep +0 -0
  420. data/public/403.html +26 -0
  421. data/public/404.html +26 -0
  422. data/public/422.html +26 -0
  423. data/public/500.html +25 -0
  424. data/public/ZeroClipboard10.swf +0 -0
  425. data/public/favicon.ico +0 -0
  426. data/public/robots.txt +5 -0
  427. data/script/cucumber +10 -0
  428. data/script/delayed_job +5 -0
  429. data/script/rails +6 -0
  430. data/spec/factories/answer.rb +6 -0
  431. data/spec/factories/answer_choice.rb +6 -0
  432. data/spec/factories/attachment.rb +11 -0
  433. data/spec/factories/buying_attempts.rb +8 -0
  434. data/spec/factories/campaign.rb +8 -0
  435. data/spec/factories/carrier.rb +6 -0
  436. data/spec/factories/contact.rb +8 -0
  437. data/spec/factories/interesting_facts.rb +10 -0
  438. data/spec/factories/interview_result.rb +27 -0
  439. data/spec/factories/interview_template.rb +46 -0
  440. data/spec/factories/invitation_identifier.rb +8 -0
  441. data/spec/factories/possible_answer.rb +23 -0
  442. data/spec/factories/question.rb +55 -0
  443. data/spec/factories/recommendation.rb +10 -0
  444. data/spec/factories/user.rb +21 -0
  445. data/spec/mailers/invitation_mailer_spec.rb +5 -0
  446. data/spec/models/answer_spec.rb +5 -0
  447. data/spec/models/attachment_spec.rb +5 -0
  448. data/spec/models/buying_attempt_spec.rb +5 -0
  449. data/spec/models/campaign_spec.rb +5 -0
  450. data/spec/models/carrier_spec.rb +5 -0
  451. data/spec/models/contact_spec.rb +5 -0
  452. data/spec/models/interesting_fact_spec.rb +5 -0
  453. data/spec/models/invitation_identifier_spec.rb +5 -0
  454. data/spec/models/question_choice_spec.rb +5 -0
  455. data/spec/models/question_result_spec.rb +5 -0
  456. data/spec/models/question_spec.rb +5 -0
  457. data/spec/models/recommendation_spec.rb +5 -0
  458. data/spec/models/survey_result_spec.rb +5 -0
  459. data/spec/models/survey_template_spec.rb +5 -0
  460. data/spec/spec_helper.rb +32 -0
  461. data/vendor/.rvmrc +53 -0
  462. data/vendor/Gemfile +60 -0
  463. data/vendor/Gemfile.lock +166 -0
  464. data/vendor/README.rdoc +261 -0
  465. data/vendor/Rakefile +7 -0
  466. data/vendor/assets/javascripts/ZeroClipboard.js +316 -0
  467. data/vendor/assets/javascripts/selectToUISlider.js +240 -0
  468. data/vendor/assets/javascripts/underscore.string.js +566 -0
  469. data/vendor/assets/stylesheets/.gitkeep +0 -0
  470. data/vendor/config.ru +4 -0
  471. data/vendor/plugins/.gitkeep +0 -0
  472. metadata +504 -55
  473. data/README.markdown +0 -44
  474. data/lib/shell-spinner.rb +0 -52
  475. data/lib/shell-spinner/version.rb +0 -3
  476. data/shell-spinner.gemspec +0 -18
@@ -0,0 +1,17 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: interview_templates
4
+ #
5
+ # *id*:: <tt>integer, not null, primary key</tt>
6
+ # *author_id*:: <tt>integer</tt>
7
+ # *created_at*:: <tt>datetime, not null</tt>
8
+ # *updated_at*:: <tt>datetime, not null</tt>
9
+ # *title*:: <tt>string(255)</tt>
10
+ # *description*:: <tt>text</tt>
11
+ # *type*:: <tt>string(255)</tt>
12
+ #--
13
+ # == Schema Information End
14
+ #++
15
+
16
+ class CellPhoneInsuranceInterview < InterviewTemplate
17
+ end
@@ -0,0 +1,31 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: contacts
4
+ #
5
+ # *id*:: <tt>integer, not null, primary key</tt>
6
+ # *user_id*:: <tt>integer</tt>
7
+ # *provider*:: <tt>string(255)</tt>
8
+ # *name*:: <tt>string(255)</tt>
9
+ # *email*:: <tt>string(255)</tt>
10
+ # *created_at*:: <tt>datetime, not null</tt>
11
+ # *updated_at*:: <tt>datetime, not null</tt>
12
+ #--
13
+ # == Schema Information End
14
+ #++
15
+
16
+ class Contact < ActiveRecord::Base
17
+ include Enumerize
18
+ include Wisemuv::Contacts::WindowsLive::ModelConcerns
19
+ include Wisemuv::Contacts::Yahoo::ModelConcerns
20
+ include Wisemuv::Contacts::Google::ModelConcerns
21
+
22
+ enumerize :provider, :in => Wisemuv::Contacts.providers
23
+
24
+ belongs_to :user
25
+
26
+ validates :provider, :presence => true
27
+ validates :user, :presence => true
28
+ validates :email, :email => true, :presence => true
29
+
30
+ scope :occurrences, proc { |text| where("name ILIKE :occurrence OR email ILIKE :occurrence", :occurrence => "%#{text}%") }
31
+ end
@@ -0,0 +1,17 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: interview_templates
4
+ #
5
+ # *id*:: <tt>integer, not null, primary key</tt>
6
+ # *author_id*:: <tt>integer</tt>
7
+ # *created_at*:: <tt>datetime, not null</tt>
8
+ # *updated_at*:: <tt>datetime, not null</tt>
9
+ # *title*:: <tt>string(255)</tt>
10
+ # *description*:: <tt>text</tt>
11
+ # *type*:: <tt>string(255)</tt>
12
+ #--
13
+ # == Schema Information End
14
+ #++
15
+
16
+ class DefaultInterview < InterviewTemplate
17
+ end
@@ -0,0 +1,30 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: interesting_facts
4
+ #
5
+ # *id*:: <tt>integer, not null, primary key</tt>
6
+ # *text*:: <tt>text</tt>
7
+ # *condition*:: <tt>string(255)</tt>
8
+ # *source_name*:: <tt>string(255)</tt>
9
+ # *source_url*:: <tt>string(255)</tt>
10
+ # *created_at*:: <tt>datetime, not null</tt>
11
+ # *updated_at*:: <tt>datetime, not null</tt>
12
+ # *attachment_id*:: <tt>integer</tt>
13
+ #--
14
+ # == Schema Information End
15
+ #++
16
+
17
+ class InterestingFact < ActiveRecord::Base
18
+ belongs_to :attachment
19
+
20
+ validate :text, :presence => true
21
+ delegate :to_s, :to => :text
22
+
23
+ def self.random
24
+ order('RANDOM()').first
25
+ end
26
+
27
+ def source?
28
+ source_name? && source_url?
29
+ end
30
+ end
@@ -0,0 +1,65 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: interview_results
4
+ #
5
+ # *id*:: <tt>integer, not null, primary key</tt>
6
+ # *user_id*:: <tt>integer</tt>
7
+ # *interview_template_id*:: <tt>integer</tt>
8
+ # *created_at*:: <tt>datetime, not null</tt>
9
+ # *updated_at*:: <tt>datetime, not null</tt>
10
+ # *secret*:: <tt>string(255)</tt>
11
+ # *state*:: <tt>string(255)</tt>
12
+ # *campaign_id*:: <tt>integer</tt>
13
+ #--
14
+ # == Schema Information End
15
+ #++
16
+
17
+ class InterviewResult < ActiveRecord::Base
18
+ belongs_to :interview_template
19
+ belongs_to :user
20
+ belongs_to :campaign
21
+
22
+ has_many :answers
23
+ has_many :answered_questions, :through => :answers, :source => :question
24
+ has_many :questions, :through => :interview_template
25
+ has_many :invitations
26
+ has_many :recommendations
27
+ has_many :buying_attempts
28
+
29
+ state_machine :state, :initial => :draft do
30
+ state :draft
31
+ state :completed
32
+
33
+ event :complete do
34
+ transition :draft => :completed
35
+ end
36
+ end
37
+
38
+ accepts_nested_attributes_for :answers
39
+ validates :answers, :user, :interview_template, :presence => true
40
+
41
+ after_create :create_secret
42
+
43
+ def create_secret
44
+ require 'digest/sha1'
45
+ update_column :secret, Digest::SHA1.hexdigest("#{user_id}-#{id}")
46
+ end
47
+
48
+ def verify_completion!
49
+ complete! unless pending_questions?
50
+ end
51
+
52
+ def pending_questions
53
+ questions - answered_questions
54
+ end
55
+
56
+ def pending_questions?
57
+ not pending_questions.empty?
58
+ end
59
+
60
+ def carrier_url attempt
61
+ uri = URI(campaign.carrier.site_url)
62
+ uri.query = "key=#{attempt.tracking_code}"
63
+ uri.to_s
64
+ end
65
+ end
@@ -0,0 +1,52 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: interview_templates
4
+ #
5
+ # *id*:: <tt>integer, not null, primary key</tt>
6
+ # *author_id*:: <tt>integer</tt>
7
+ # *created_at*:: <tt>datetime, not null</tt>
8
+ # *updated_at*:: <tt>datetime, not null</tt>
9
+ # *title*:: <tt>string(255)</tt>
10
+ # *description*:: <tt>text</tt>
11
+ # *type*:: <tt>string(255)</tt>
12
+ #--
13
+ # == Schema Information End
14
+ #++
15
+
16
+ class InterviewTemplate < ActiveRecord::Base
17
+ include Enumerize
18
+
19
+ has_many :questions, :dependent => :destroy
20
+ belongs_to :author, :class_name => 'User'
21
+ has_many :recommendations
22
+ has_many :campaigns
23
+
24
+ has_many :campaigns
25
+ has_many :interview_results
26
+
27
+ has_many :campaigns
28
+ has_many :interview_results
29
+
30
+ enumerize :type, :in => %w(DefaultInterview CellPhoneInsuranceInterview), :default => 'DefaultInterview'
31
+
32
+ accepts_nested_attributes_for :questions, :allow_destroy => true, :reject_if => :hidden_question_form?
33
+ attr_accessible :type, :title, :description, :questions_attributes
34
+
35
+ validates :title, :questions, :presence => true
36
+ validates_associated :questions
37
+
38
+ scope :recent, limit(5)
39
+
40
+ def to_s
41
+ title
42
+ end
43
+
44
+ def results
45
+ interview_results
46
+ end
47
+
48
+ def hidden_question_form? attributes
49
+ attributes["_destroy"] == 1 && attributes["id"].blank?
50
+ end
51
+
52
+ end
@@ -0,0 +1,45 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: invitations
4
+ #
5
+ # *id*:: <tt>integer, not null, primary key</tt>
6
+ # *interview_result_id*:: <tt>integer</tt>
7
+ # *recipients*:: <tt>text</tt>
8
+ # *created_at*:: <tt>datetime, not null</tt>
9
+ # *updated_at*:: <tt>datetime, not null</tt>
10
+ #--
11
+ # == Schema Information End
12
+ #++
13
+
14
+ class Invitation < ActiveRecord::Base
15
+ belongs_to :interview_result
16
+ has_one :author, :through => :interview_result
17
+ has_one :identifier, :class_name => 'InvitationIdentifier'
18
+ has_many :recommendations
19
+
20
+ attr_accessible :interview_result, :recipients_attributes, :recipients
21
+ validates :recipients, :presence => true
22
+
23
+ delegate :secret, :to => :identifier, :allow_nil => true
24
+ delegate :user, :interview_template, :to => :interview_result
25
+
26
+ after_create do |invitation|
27
+ invitation.create_identifier && invitation.ship
28
+ end
29
+
30
+ # кораблег :)
31
+ def ship
32
+ recipients_emails.all? do |email|
33
+ InvitationMailer.ask_friends_and_family(email, self).deliver
34
+ end
35
+ end
36
+
37
+ def recipients_emails
38
+ recipients.split ','
39
+ end
40
+
41
+ def recipients_attributes= attributes
42
+ self.recipients = attributes.join ','
43
+ end
44
+
45
+ end
@@ -0,0 +1,29 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: invitation_identifiers
4
+ #
5
+ # *id*:: <tt>integer, not null, primary key</tt>
6
+ # *invitation_id*:: <tt>integer</tt>
7
+ # *secret*:: <tt>string(255)</tt>
8
+ #--
9
+ # == Schema Information End
10
+ #++
11
+
12
+ class InvitationIdentifier < ActiveRecord::Base
13
+ belongs_to :invitation
14
+
15
+ validates :secret, :uniqueness => true
16
+
17
+ after_initialize do |invitation_identifier|
18
+ require 'digest/sha1'
19
+ invitation_identifier.secret = Digest::SHA1.hexdigest("#{invitation_identifier.user_id}-#{invitation_identifier.invitation_id}-trollface")
20
+ end
21
+
22
+ def user_id
23
+ invitation.interview_result.user_id
24
+ end
25
+
26
+ def invitation_id
27
+ invitation.id
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: questions
4
+ #
5
+ # *id*:: <tt>integer, not null, primary key</tt>
6
+ # *text*:: <tt>text</tt>
7
+ # *interview_template_id*:: <tt>integer</tt>
8
+ # *position*:: <tt>integer</tt>
9
+ # *type*:: <tt>string(255)</tt>
10
+ # *created_at*:: <tt>datetime, not null</tt>
11
+ # *updated_at*:: <tt>datetime, not null</tt>
12
+ # *display_as*:: <tt>string(255)</tt>
13
+ #--
14
+ # == Schema Information End
15
+ #++
16
+
17
+ class NumericQuestion < Question
18
+ enumerize :display_as, :in => %w(simple_number price)
19
+ end
@@ -0,0 +1,27 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: questions
4
+ #
5
+ # *id*:: <tt>integer, not null, primary key</tt>
6
+ # *text*:: <tt>text</tt>
7
+ # *interview_template_id*:: <tt>integer</tt>
8
+ # *position*:: <tt>integer</tt>
9
+ # *type*:: <tt>string(255)</tt>
10
+ # *created_at*:: <tt>datetime, not null</tt>
11
+ # *updated_at*:: <tt>datetime, not null</tt>
12
+ # *display_as*:: <tt>string(255)</tt>
13
+ #--
14
+ # == Schema Information End
15
+ #++
16
+
17
+ class OneCorrectQuestion < Question
18
+ has_many :possible_answers, :foreign_key => :question_id
19
+
20
+ enumerize :display_as, :in => %w(radio dropdown slider), :default => 'radio'
21
+
22
+ validates :possible_answers, :presence => true
23
+
24
+ def after_becomes
25
+ 2.times { possible_answers.build } if possible_answers.empty?
26
+ end
27
+ end
@@ -0,0 +1,54 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: possible_answers
4
+ #
5
+ # *id*:: <tt>integer, not null, primary key</tt>
6
+ # *question_id*:: <tt>integer</tt>
7
+ # *text*:: <tt>text</tt>
8
+ # *position*:: <tt>integer</tt>
9
+ # *created_at*:: <tt>datetime, not null</tt>
10
+ # *updated_at*:: <tt>datetime, not null</tt>
11
+ # *body_from_3rd_point_view*:: <tt>text</tt>
12
+ #--
13
+ # == Schema Information End
14
+ #++
15
+
16
+ class PossibleAnswer < ActiveRecord::Base
17
+ belongs_to :question
18
+
19
+ attr_accessible :text, :position, :question_id, :body_from_3rd_point_view
20
+
21
+ validates :text, :presence => true
22
+ validate :validate_minimum, :if => :scale_minimum_answer?
23
+ validate :validate_greater, :if => :scale_maximum_answer?
24
+ validate :validate_range, :if => :scale_answer?
25
+
26
+ def scale_minimum_answer?
27
+ scale_answer? && self == question.possible_answers.first
28
+ end
29
+
30
+ def scale_maximum_answer?
31
+ scale_answer? && self == question.possible_answers.last
32
+ end
33
+
34
+ def scale_answer?
35
+ question.present? && question.scale?
36
+ end
37
+
38
+ def validate_range
39
+ errors.add(:text, 'Please enter numeric value') unless text.numeric?
40
+ errors.add(:body_from_3rd_point_view, 'Please enter label to the value') if body_from_3rd_point_view.blank?
41
+ end
42
+
43
+ def validate_greater
44
+ errors.add(:text, 'Max value must be greater than min value') if (question.max_value - question.min_value) <= 0
45
+ end
46
+
47
+ def validate_minimum
48
+ errors.add(:text, 'Min value must be lower than max value') if (question.max_value - question.min_value) <= 0
49
+ end
50
+
51
+ def to_s
52
+ text
53
+ end
54
+ end
@@ -0,0 +1,96 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: questions
4
+ #
5
+ # *id*:: <tt>integer, not null, primary key</tt>
6
+ # *text*:: <tt>text</tt>
7
+ # *interview_template_id*:: <tt>integer</tt>
8
+ # *position*:: <tt>integer</tt>
9
+ # *type*:: <tt>string(255)</tt>
10
+ # *created_at*:: <tt>datetime, not null</tt>
11
+ # *updated_at*:: <tt>datetime, not null</tt>
12
+ # *display_as*:: <tt>string(255)</tt>
13
+ #--
14
+ # == Schema Information End
15
+ #++
16
+
17
+ class Question < ActiveRecord::Base
18
+ include Enumerize
19
+ include RankedModel
20
+
21
+ ranks :position
22
+
23
+ belongs_to :interview_template
24
+ has_one :answer
25
+ has_many :possible_answers, :dependent => :destroy, :inverse_of => :question
26
+
27
+ %w(OneCorrectQuestion YesNoQuestion NumericQuestion ScaleQuestion).tap do |question_klasses|
28
+ enumerize :type, :in => question_klasses, :default => 'OneCorrectQuestion'
29
+
30
+ question_klasses.each do |klass|
31
+
32
+ # question.scale?, question.numeric?, etc.
33
+ define_method :"#{klass.sub('Question', '').underscore}?" do
34
+ type == klass
35
+ end
36
+
37
+ # Question.scale, Question.numeric, etc.
38
+ scope klass.sub('Question', '').underscore, where(:type => klass)
39
+ end
40
+ end
41
+
42
+ accepts_nested_attributes_for :possible_answers, :allow_destroy => true
43
+ attr_accessible :text, :position, :interview_template_id, :possible_answers_attributes, :display_as, :type
44
+ validates :text, :presence => true
45
+
46
+ # TODO move this validations to the related STI classes
47
+ validates :display_as, :inclusion => { :in => proc { OneCorrectQuestion.display_as.values }, :message => 'Please select one of the options' },
48
+ :if => :one_correct?
49
+
50
+ validates_associated :possible_answers, :unless => :numeric?
51
+
52
+ before_validation :build_yes_no_possible_answers, :if => :yes_no?
53
+ before_validation :build_min_max_values, :if => :scale?
54
+
55
+ default_scope order('position ASC')
56
+
57
+ def to_s
58
+ text
59
+ end
60
+
61
+ def build_subclass klass
62
+ if self.class == klass
63
+ new_question = self
64
+ else
65
+ new_question = dup.becomes(klass)
66
+ end
67
+
68
+ new_question.tap do |q|
69
+ q.possible_answers = possible_answers
70
+ q.after_becomes if q.respond_to?(:after_becomes)
71
+ end
72
+ end
73
+
74
+ def given_answer interview_result
75
+ Answer.where(:interview_result_id => interview_result, :question_id => id).first
76
+ end
77
+
78
+ # TODO you shouldn't use factory girl in production environment in most of cases
79
+ def build_yes_no_possible_answers
80
+ self.possible_answers = [ FactoryGirl.build(:possible_answer, :yes), FactoryGirl.build(:possible_answer, :no) ]
81
+ end
82
+
83
+ # TODO you shouldn't use factory girl in production environment in most of cases
84
+ def build_min_max_values
85
+ self.possible_answers = FactoryGirl.build_list(:possible_answer, 2, :empty) if possible_answers.empty?
86
+ end
87
+
88
+ def max_value
89
+ possible_answers.last.text.to_i
90
+ end
91
+
92
+ def min_value
93
+ possible_answers.first.text.to_i
94
+ end
95
+
96
+ end