cloudrider 0.3.0 → 0.3.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (227) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -1
  3. data/cloudrider.gemspec +1 -0
  4. data/generica/.gitignore +18 -0
  5. data/generica/Gemfile +8 -1
  6. data/generica/Gemfile.lock +3 -0
  7. data/generica/app/assets/javascripts/apiv1.js.ls +6 -1
  8. data/generica/app/assets/javascripts/components/offers-summary.js.em +2 -0
  9. data/generica/app/assets/javascripts/components/picture-chunk.js.em +17 -0
  10. data/generica/app/assets/javascripts/components/pictures-group.js.em +21 -0
  11. data/generica/app/assets/javascripts/components/search-and-filter.js.em +4 -0
  12. data/generica/app/assets/javascripts/components/site-nav.js.em +5 -1
  13. data/generica/app/assets/javascripts/components/taggable-field.js.em +28 -0
  14. data/generica/app/assets/javascripts/components/tree/taxon-li.js.em +6 -2
  15. data/generica/app/assets/javascripts/controllers/index_controller.js.em +19 -2
  16. data/generica/app/assets/javascripts/controllers/modals/login_controller.js.em +23 -9
  17. data/generica/app/assets/javascripts/controllers/modals/register_controller.js.em +24 -0
  18. data/generica/app/assets/javascripts/controllers/products/index_controller.js.em +23 -13
  19. data/generica/app/assets/javascripts/controllers/products/product/offers/new_controller.js.em +17 -0
  20. data/generica/app/assets/javascripts/controllers/users/offers/index_controller.js.em +10 -0
  21. data/generica/app/assets/javascripts/controllers/users/product/edit_controller.js.em +31 -0
  22. data/generica/app/assets/javascripts/controllers/users/products/index_controller.js.em +8 -0
  23. data/generica/app/assets/javascripts/controllers/users/products/new_controller.js.em +22 -0
  24. data/generica/app/assets/javascripts/controllers/users/products/slice_controller.js.em +4 -0
  25. data/generica/app/assets/javascripts/helpers/filte_previewer.js.ls +21 -0
  26. data/generica/app/assets/javascripts/helpers/listing_picture.js.em +17 -0
  27. data/generica/app/assets/javascripts/models/offer.js.em +9 -8
  28. data/generica/app/assets/javascripts/models/user.js.em +12 -0
  29. data/generica/app/assets/javascripts/models/users/product.js.em +12 -0
  30. data/generica/app/assets/javascripts/routes/application_route.js.em +10 -2
  31. data/generica/app/assets/javascripts/routes/products/index_route.js.em +23 -2
  32. data/generica/app/assets/javascripts/routes/products/product/offers/new_route.js.em +18 -0
  33. data/generica/app/assets/javascripts/routes/users/offers/index_route.js.em +1 -0
  34. data/generica/app/assets/javascripts/routes/users/product_route.js.em +3 -0
  35. data/generica/app/assets/javascripts/routes/users/products/index_route.js.em +3 -0
  36. data/generica/app/assets/javascripts/routes/users/products/new_route.js.em +3 -0
  37. data/generica/app/assets/javascripts/templates/admin/product/edit.emblem +2 -0
  38. data/generica/app/assets/javascripts/templates/admin/products/_form-core.emblem +44 -0
  39. data/generica/app/assets/javascripts/templates/admin/products/new.emblem +4 -42
  40. data/generica/app/assets/javascripts/templates/components/offers-summary.emblem +9 -0
  41. data/generica/app/assets/javascripts/templates/components/picture-chunk.emblem +9 -0
  42. data/generica/app/assets/javascripts/templates/components/pictures-group.emblem +6 -0
  43. data/generica/app/assets/javascripts/templates/components/search-and-filter.emblem +5 -1
  44. data/generica/app/assets/javascripts/templates/components/taggable-field.emblem +1 -0
  45. data/generica/app/assets/javascripts/templates/modals/register.emblem +57 -0
  46. data/generica/app/assets/javascripts/templates/products/product/offers/_anonymous-form.emblem +11 -0
  47. data/generica/app/assets/javascripts/templates/products/product/offers/_offer-form.emblem +55 -0
  48. data/generica/app/assets/javascripts/templates/products/product/offers/new.emblem +37 -0
  49. data/generica/app/assets/javascripts/templates/products/product/show.emblem +26 -1
  50. data/generica/app/assets/javascripts/templates/users.emblem +24 -0
  51. data/generica/app/assets/javascripts/templates/users/index.emblem +3 -0
  52. data/generica/app/assets/javascripts/templates/users/offers/index.emblem +25 -0
  53. data/generica/app/assets/javascripts/templates/users/offers/slice.emblem +31 -0
  54. data/generica/app/assets/javascripts/templates/users/product/edit.emblem +82 -0
  55. data/generica/app/assets/javascripts/templates/users/products/index.emblem +22 -0
  56. data/generica/app/assets/javascripts/templates/users/products/new.emblem +28 -0
  57. data/generica/app/assets/javascripts/templates/users/products/slice.emblem +27 -0
  58. data/generica/app/assets/stylesheets/apiv1/_application.css.scss +4 -0
  59. data/generica/app/assets/stylesheets/apiv1/components/_offers-summary.css.scss +20 -0
  60. data/generica/app/assets/stylesheets/apiv1/components/_pictures-group.css.scss +32 -0
  61. data/generica/app/assets/stylesheets/apiv1/components/_taggable-field.css.scss +32 -0
  62. data/generica/app/assets/stylesheets/apiv1/products/product/offers/_new.css.scss +8 -0
  63. data/generica/app/controllers/admin/base_controller.rb +1 -1
  64. data/generica/app/controllers/admin/sessions/destroy_controller.rb +16 -0
  65. data/generica/app/controllers/apiv1/offers/create_controller.rb +30 -0
  66. data/generica/app/controllers/apiv1/offers/index_controller.rb +22 -0
  67. data/generica/app/controllers/apiv1/offers/show_controller.rb +12 -0
  68. data/generica/app/controllers/apiv1/products/destroy_controller.rb +6 -0
  69. data/generica/app/controllers/apiv1/products/index_controller.rb +8 -2
  70. data/generica/app/controllers/apiv1/products/show_controller.rb +7 -3
  71. data/generica/app/controllers/apiv1/taxons/index_controller.rb +5 -1
  72. data/generica/app/controllers/apiv1/users/create_controller.rb +17 -0
  73. data/generica/app/controllers/apiv1/users/show_controller.rb +12 -0
  74. data/generica/app/controllers/apiv1/users_controller.rb +9 -0
  75. data/generica/app/controllers/application_controller.rb +3 -0
  76. data/generica/app/controllers/users/offers/create_controller.rb +26 -0
  77. data/generica/app/controllers/users/products/create_controller.rb +26 -0
  78. data/generica/app/controllers/users/products/update_controller.rb +35 -0
  79. data/generica/app/mailers/apiv1/aggregate_mailer.rb +13 -0
  80. data/generica/app/mailers/apiv1/aggregate_mailer/summary_context.rb +121 -0
  81. data/generica/app/mailers/apiv1/notifications_mailer.rb +19 -0
  82. data/generica/app/mailers/apiv1/notifications_mailer/new_offer_context.rb +53 -0
  83. data/generica/app/models/admin/user.rb +43 -2
  84. data/generica/app/models/apiv1/attachment.rb +2 -0
  85. data/generica/app/models/apiv1/email_object.rb +35 -0
  86. data/generica/app/models/apiv1/email_request.rb +107 -0
  87. data/generica/app/models/apiv1/offer_message.rb +53 -0
  88. data/generica/app/models/apiv1/offer_postboy.rb +33 -0
  89. data/generica/app/models/apiv1/picture.rb +2 -0
  90. data/generica/app/models/apiv1/product.rb +28 -6
  91. data/generica/app/models/apiv1/products/offer_message_factory.rb +13 -0
  92. data/generica/app/models/apiv1/products_machine.rb +8 -2
  93. data/generica/app/models/apiv1/taxon.rb +1 -1
  94. data/generica/app/models/apiv1/users/product_factory.rb +22 -0
  95. data/generica/app/models/apiv1/users/product_relationship.rb +19 -0
  96. data/generica/app/models/users/products/offer_factory.rb +40 -0
  97. data/generica/app/varissets/javascripts/templates/application.emblem.erb +2 -2
  98. data/generica/app/varissets/javascripts/templates/components/offers-overview.emblem.erb +1 -0
  99. data/generica/app/varissets/javascripts/templates/components/search-and-filter.emblem.erb +33 -0
  100. data/generica/app/varissets/javascripts/templates/components/site-nav.emblem.erb +8 -0
  101. data/generica/app/varissets/javascripts/templates/components/taggable-field.emblem.erb +11 -0
  102. data/generica/app/varissets/javascripts/templates/modals/login.emblem.erb +36 -0
  103. data/generica/app/varissets/javascripts/templates/products.emblem.erb +4 -0
  104. data/generica/app/varissets/javascripts/templates/products/index.emblem.erb +17 -0
  105. data/generica/app/varissets/javascripts/templates/products/product/offers/_anonymous-form.emblem.erb +11 -0
  106. data/generica/app/varissets/javascripts/templates/products/product/offers/_offer-form.emblem.erb +55 -0
  107. data/generica/app/varissets/javascripts/templates/products/product/offers/new.emblem.erb +37 -0
  108. data/generica/app/varissets/javascripts/templates/products/product/show.emblem.erb +108 -0
  109. data/generica/app/varissets/stylesheets/apiv1/components/_offers-overview.css.scss.erb +3 -0
  110. data/generica/app/varissets/stylesheets/apiv1/components/_offers_overview.css.scss.erb +3 -0
  111. data/generica/app/varissets/stylesheets/apiv1/components/_search-and-filter.css.scss.erb +15 -0
  112. data/generica/app/varissets/stylesheets/apiv1/components/_site-footer.css.scss.erb +23 -0
  113. data/generica/app/varissets/stylesheets/apiv1/components/_taggable-field.css.scss.erb +32 -0
  114. data/generica/app/views/apiv1/home/index.html.haml +3 -1
  115. data/generica/app/views/apiv1/layouts/application.html.haml +37 -2
  116. data/generica/config/{database.yml.erb → database.yml.str} +3 -3
  117. data/generica/config/email.yml +11 -0
  118. data/generica/config/email_slave.god +9 -0
  119. data/generica/config/initializers/premailer.rb +1 -0
  120. data/generica/config/initializers/squash.rb.erb +3 -0
  121. data/generica/config/nginx.conf.erb +4 -4
  122. data/generica/config/routes.rb +14 -0
  123. data/generica/db/migrate/20141114213427_add_user_rank_to_admin_users.rb +9 -0
  124. data/generica/db/migrate/20141114225019_create_apiv1_users_products.rb +9 -0
  125. data/generica/db/migrate/20141116053522_create_apiv1_offer_messages.rb +16 -0
  126. data/generica/db/migrate/20141116235011_add_deleted_at_to_apiv1_products.rb +5 -0
  127. data/generica/db/migrate/20141116235209_add_deleted_at_to_apiv1_offer_messages.rb +5 -0
  128. data/generica/db/migrate/20141116235651_add_deleted_at_to_apiv1_pictures.rb +5 -0
  129. data/generica/db/migrate/20141116235808_add_deleted_at_to_apiv1_attachments.rb +5 -0
  130. data/generica/db/migrate/20141127230304_create_apiv1_email_requests.rb +16 -0
  131. data/generica/db/migrate/20141127230455_create_apiv1_email_objects.rb +11 -0
  132. data/generica/lib/generica/assets_unretardifier.rb +32 -0
  133. data/generica/lib/generica/email_slave.rb +92 -0
  134. data/generica/lib/tasks/email_slave.rake +11 -0
  135. data/generica/lib/tasks/production.rake +1 -1
  136. data/generica/public/tests/bermese.jpg +0 -0
  137. data/generica/public/tests/chow.jpg +0 -0
  138. data/generica/public/tests/malamute.jpg +0 -0
  139. data/generica/public/tests/malamute2.JPG +0 -0
  140. data/generica/spec/controllers/apiv1/users/create_controller_spec.rb +17 -0
  141. data/generica/spec/controllers/users/products/create_controller_spec.rb +31 -0
  142. data/generica/spec/mailers/apiv1/aggregate_mailer_spec.rb +29 -0
  143. data/generica/spec/models/apiv1/email_request_spec.rb +4 -0
  144. data/generica/spec/models/apiv1/offer_postboy_spec.rb +22 -0
  145. data/generica/spec/models/apiv1/product_spec.rb +1 -0
  146. data/generica/spec/models/apiv1/products/offer_message_factory_spec.rb +37 -0
  147. data/generica/spec/models/apiv1/products_machine_spec.rb +77 -0
  148. data/generica/spec/models/apiv1/users/product_factory_spec.rb +47 -0
  149. data/generica/spec/models/users/products/offer_factory_spec.rb +38 -0
  150. data/generica/test/mailers/.keep +0 -0
  151. data/generica/test/mailers/previews/apiv1/aggregate_preview.rb +6 -0
  152. data/generica/test/mailers/previews/apiv1/notifications_preview.rb +5 -0
  153. data/lib/cloudrider.rb +1 -1
  154. data/lib/cloudrider/apiv1/base.rb +2 -2
  155. data/lib/cloudrider/apiv1/login_modal_emblem.rb +25 -0
  156. data/lib/cloudrider/apiv1/offers_anonymous_form_partial_emblem.rb +12 -0
  157. data/lib/cloudrider/apiv1/offers_new_emblem.rb +15 -0
  158. data/lib/cloudrider/apiv1/offers_overview_component.rb +8 -0
  159. data/lib/cloudrider/apiv1/offers_overview_sass.rb +8 -0
  160. data/lib/cloudrider/apiv1/product_show_emblem.rb +31 -0
  161. data/lib/cloudrider/apiv1/products_emblem.rb +11 -0
  162. data/lib/cloudrider/apiv1/products_index_emblem.rb +14 -0
  163. data/lib/cloudrider/apiv1/search_and_filter_component.rb +11 -0
  164. data/lib/cloudrider/apiv1/search_and_filter_sass.rb +11 -0
  165. data/lib/cloudrider/apiv1/site_footer_component.rb +7 -7
  166. data/lib/cloudrider/apiv1/site_footer_sass.rb +9 -0
  167. data/lib/cloudrider/application_commander.rb +46 -34
  168. data/lib/cloudrider/backend_commander.rb +15 -9
  169. data/lib/cloudrider/protofile.rb +18 -2
  170. data/lib/cloudrider/protosite.example.json +26 -0
  171. data/lib/cloudrider/protosite.rb +66 -0
  172. data/lib/cloudrider/serverside/base.rb +2 -2
  173. data/lib/cloudrider/serverside/database_yaml.rb +9 -4
  174. data/lib/cloudrider/serverside/nginx_conf.rb +7 -2
  175. data/lib/cloudrider/serverside/squash_ruby.rb +14 -0
  176. data/lib/cloudrider/serverside/unicorn_conf_ruby.rb +2 -1
  177. data/lib/cloudrider/version.rb +1 -1
  178. data/lib/cloudrider/web_firm.rb +16 -0
  179. data/lib/cloudrider/web_firm/component_architect.rb +23 -0
  180. data/lib/cloudrider/web_firm/page_designer.rb +13 -0
  181. data/lib/cloudrider/web_firm/project_lead.rb +30 -0
  182. data/lib/cloudrider/web_firm/scumbag_engineer.rb +40 -0
  183. data/lib/cloudrider/web_firm/support_intern.rb +113 -0
  184. data/lib/generators/cloudrider/server/server_generator.rb +4 -8
  185. data/lib/generators/cloudrider/website/website_generator.rb +25 -0
  186. data/spec/cloudrider/protosite_spec.rb +63 -0
  187. data/vanilla/.bowerrc +4 -0
  188. data/vanilla/.editorconfig +33 -0
  189. data/vanilla/.ember-cli +9 -0
  190. data/vanilla/.gitignore +17 -0
  191. data/vanilla/.jshintrc +32 -0
  192. data/vanilla/.travis.yml +16 -0
  193. data/vanilla/Brocfile.js +20 -0
  194. data/vanilla/README.md +51 -0
  195. data/vanilla/app/app.js +16 -0
  196. data/vanilla/app/components/.gitkeep +0 -0
  197. data/vanilla/app/controllers/.gitkeep +0 -0
  198. data/vanilla/app/controllers/admin.coffee +5 -0
  199. data/vanilla/app/helpers/.gitkeep +0 -0
  200. data/vanilla/app/index.html +21 -0
  201. data/vanilla/app/models/.gitkeep +0 -0
  202. data/vanilla/app/router.js +11 -0
  203. data/vanilla/app/routes/.gitkeep +0 -0
  204. data/vanilla/app/styles/.gitkeep +0 -0
  205. data/vanilla/app/styles/app.css +3 -0
  206. data/vanilla/app/templates/.gitkeep +0 -0
  207. data/vanilla/app/templates/application.hbs +3 -0
  208. data/vanilla/app/templates/components/.gitkeep +0 -0
  209. data/vanilla/app/views/.gitkeep +0 -0
  210. data/vanilla/bower.json +17 -0
  211. data/vanilla/config/environment.js +47 -0
  212. data/vanilla/package.json +39 -0
  213. data/vanilla/public/.gitkeep +0 -0
  214. data/vanilla/public/crossdomain.xml +15 -0
  215. data/vanilla/public/robots.txt +3 -0
  216. data/vanilla/testem.json +11 -0
  217. data/vanilla/tests/.jshintrc +74 -0
  218. data/vanilla/tests/helpers/resolver.js +11 -0
  219. data/vanilla/tests/helpers/start-app.js +25 -0
  220. data/vanilla/tests/index.html +45 -0
  221. data/vanilla/tests/test-helper.js +12 -0
  222. data/vanilla/tests/unit/.gitkeep +0 -0
  223. data/vanilla/tests/unit/controllers/admin-test.coffee +12 -0
  224. data/vanilla/vendor/.gitkeep +0 -0
  225. metadata +189 -5
  226. data/generica/app/views/layouts/application.html.erb +0 -14
  227. data/lib/cloudrider/master_context.rb +0 -105
@@ -0,0 +1,32 @@
1
+ .taggable-field {
2
+ @include display-flex;
3
+ @include flex-direction(row);
4
+ @include flex-wrap(nowrap);
5
+ @include justify-content(flex-start);
6
+ overflow-x: hidden;
7
+ .taggable-textfield {
8
+ margin-bottom: 0px;
9
+ width: 100%;
10
+ height: 40px;
11
+ }
12
+ .taggable-field-tag {
13
+ @include display-flex;
14
+ @include flex-direction(row);
15
+ @include justify-content(center);
16
+ @include align-items(center);
17
+ border: 1px solid #ddd;
18
+ padding-left: 10px;
19
+ padding-right: 15px;
20
+ min-width: 50px;
21
+ height: 40px;
22
+ background: {
23
+ color: #f2f2f2;
24
+ }
25
+ color: #358753;
26
+ }
27
+ .centered-fully {
28
+ @include display-flex;
29
+ @include flex-wrap(nowrap);
30
+ @include flex-direction(row);
31
+ }
32
+ }
@@ -0,0 +1,8 @@
1
+ .products-product-offers-new {
2
+ .form-legend {
3
+ text-transform: capitalize;
4
+ font-size: 1.2rem;
5
+ padding-bottom: 1rem;
6
+ padding-top: 1rem;
7
+ }
8
+ }
@@ -2,7 +2,7 @@ class Admin::BaseController < ApplicationController
2
2
  before_filter :_respond_with_unauthorized_json
3
3
  private
4
4
  def _respond_with_unauthorized_json
5
- unless logged_in?
5
+ unless logged_in? && current_user.admin?
6
6
  render json: { message: "login required" }, status: 401
7
7
  end
8
8
  end
@@ -0,0 +1,16 @@
1
+ class Admin::Sessions::DestroyController < Apiv1::UsersController
2
+ before_filter :_ensure_correct_sessionism
3
+ def destroy
4
+ logout
5
+ render json: nil
6
+ end
7
+ private
8
+ def _ensure_correct_sessionism
9
+ unless current_user == _user
10
+ render json: { message: "you can't log someone else out" }, status: 401
11
+ end
12
+ end
13
+ def _user
14
+ @user ||= Admin::User.find params[:id]
15
+ end
16
+ end
@@ -0,0 +1,30 @@
1
+ class Apiv1::Offers::CreateController < Apiv1::HomeController
2
+ def create
3
+ if _offer_creation_success?
4
+ _offer_factory.save!
5
+ _offer_postboy.request_work!
6
+ render json: _offer_hash
7
+ else
8
+ render json: _error_hash, status: :expectation_failed
9
+ end
10
+ end
11
+ private
12
+ def _offer_postboy
13
+ @offer_postboy ||= Apiv1::OfferPostboy.new _offer_factory.offer
14
+ end
15
+ def _offer_creation_success?
16
+ _offer_factory.satisfy_specifications?
17
+ end
18
+ def _offer_hash
19
+ _offer_factory.offer_hash
20
+ end
21
+ def _error_hash
22
+ _offer_factory.error_hash
23
+ end
24
+ def _offer_factory
25
+ @offer_factory ||= Apiv1::Products::OfferMessageFactory.new(_offer_params)
26
+ end
27
+ def _offer_params
28
+ params.require(:offer)
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ class Apiv1::Offers::IndexController < Apiv1::UsersController
2
+ def index
3
+ render json: { offers: _offers.map(&:to_ember_hash), meta: _meta_hash }
4
+ end
5
+ private
6
+ def _meta_hash
7
+ {
8
+ page: _page,
9
+ per: _per,
10
+ count: current_user.offers.count
11
+ }
12
+ end
13
+ def _offers
14
+ @offers ||= current_user.offers.page(_page).per(_per)
15
+ end
16
+ def _page
17
+ params[:page] || 1
18
+ end
19
+ def _per
20
+ params[:per] || 15
21
+ end
22
+ end
@@ -0,0 +1,12 @@
1
+ class Apiv1::Offers::ShowController < Apiv1::HomeController
2
+ def show
3
+ render json: { offer: _offer_hash }
4
+ end
5
+ private
6
+ def _offer_hash
7
+ _offer.to_ember_hash
8
+ end
9
+ def _offer
10
+ @offer ||= Apiv1::OfferMessage.find params[:id]
11
+ end
12
+ end
@@ -1,8 +1,14 @@
1
1
  class Apiv1::Products::DestroyController < Admin::BaseController
2
+ before_filter :_ensure_product_ownership
2
3
  def destroy
3
4
  render json: { product: _product.destroy }
4
5
  end
5
6
  private
7
+ def _ensure_product_ownership
8
+ unless current_user.admin? || current_user.owns?(_product)
9
+ render json: { message: "This isn't your listing" }, status: 401
10
+ end
11
+ end
6
12
  def _product
7
13
  @product ||= Apiv1::Product.find params[:id]
8
14
  end
@@ -1,8 +1,14 @@
1
1
  class Apiv1::Products::IndexController < Apiv1::HomeController
2
2
  def index
3
- render json: { products: _products_hash, meta: _meta_hash }
3
+ render json: { products: _products_hash, meta: _meta_hash, pictures: _pictures_hash, taxons: _taxons_hash }
4
4
  end
5
5
  private
6
+ def _pictures_hash
7
+ _products.map(&:pictures).flatten.map(&:to_ember_hash)
8
+ end
9
+ def _taxons_hash
10
+ _products.map(&:taxons).flatten.map(&:to_ember_hash)
11
+ end
6
12
  def _products_hash
7
13
  _products.map &:to_ember_hash
8
14
  end
@@ -16,6 +22,6 @@ class Apiv1::Products::IndexController < Apiv1::HomeController
16
22
  @products_machine ||= Apiv1::ProductsMachine.new _query_params
17
23
  end
18
24
  def _query_params
19
- params.permit(:page, :per, :query, :order).merge taxons: params[:taxons]
25
+ params.permit(:page, :per, :query, :order, :user_id, :taxons, taxons: [])
20
26
  end
21
27
  end
@@ -1,10 +1,14 @@
1
1
  class Apiv1::Products::ShowController < Apiv1::HomeController
2
2
  def show
3
- render json: { product: _product_hash, pictures: _product.pictures.map(&:to_ember_hash) }
3
+ render json: _output_hash
4
4
  end
5
5
  private
6
- def _product_hash
7
- _product.to_ember_hash
6
+ def _output_hash
7
+ {
8
+ product: _product.to_ember_hash,
9
+ pictures: _product.pictures.map(&:to_ember_hash),
10
+ offers: _product.offers.map(&:to_ember_hash)
11
+ }
8
12
  end
9
13
  def _product
10
14
  @product ||= Apiv1::Product.find_by_permalink_or_id! params[:id]
@@ -1,12 +1,16 @@
1
1
  class Apiv1::Taxons::IndexController < Apiv1::HomeController
2
2
  def index
3
- render json: { taxons: _taxons }
3
+ render json: { taxons: _taxons_hash }
4
4
  end
5
5
  private
6
+ def _taxons_hash
7
+ _taxons.map(&:to_ember_hash)
8
+ end
6
9
  def _taxons
7
10
  Apiv1::Taxon.pipeline -> (t) { t.by_root_genus(params[:root_genus]) if params[:root_genus].present? },
8
11
  -> (t) { t.children_of_parent(params[:parent_id]) if params[:parent_id].present? },
9
12
  -> (t) { t.root_generation if params.has_key?(:parent_id) && params[:parent_id].blank? },
13
+ -> (t) { t.where id: params[:ids].to_a if params[:ids].present? },
10
14
  -> (t) { t.all }
11
15
  end
12
16
  end
@@ -0,0 +1,17 @@
1
+ class Apiv1::Users::CreateController < Apiv1::HomeController
2
+ def create
3
+ if _user.valid?
4
+ _user.save! && auto_login(_user)
5
+ render json: { user: _user.to_ember_hash }
6
+ else
7
+ render json: _user.errors.to_h, status: :expectation_failed
8
+ end
9
+ end
10
+ private
11
+ def _user
12
+ @user ||= Admin::User.new _user_params
13
+ end
14
+ def _user_params
15
+ params.require(:user).permit :email, :company_name, :phone_number, :password, :password_confirmation, :address
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ class Apiv1::Users::ShowController < Apiv1::HomeController
2
+ def show
3
+ render json: { user: _user_hash }
4
+ end
5
+ private
6
+ def _user_hash
7
+ _user.to_ember_hash
8
+ end
9
+ def _user
10
+ @user ||= Admin::User.find params[:id]
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ class Apiv1::UsersController < ApplicationController
2
+ before_filter :_respond_with_unauthorized_json
3
+ private
4
+ def _respond_with_unauthorized_json
5
+ unless logged_in?
6
+ render json: { message: "login required" }, status: 401
7
+ end
8
+ end
9
+ end
@@ -2,4 +2,7 @@ class ApplicationController < ActionController::Base
2
2
  # Prevent CSRF attacks by raising an exception.
3
3
  # For APIs, you may want to use :null_session instead.
4
4
  protect_from_forgery with: :exception
5
+
6
+ include Squash::Ruby::ControllerMethods
7
+ enable_squash_client
5
8
  end
@@ -0,0 +1,26 @@
1
+ class Users::Offers::CreateController < Apiv1::UsersController
2
+ def create
3
+ if _offer_creation_success?
4
+ _offer_factory.save!
5
+ render json: _offer_hash
6
+ else
7
+ render json: _error_hash, status: :expectation_failed
8
+ end
9
+ end
10
+ private
11
+ def _offer_creation_success?
12
+ _offer_factory.satisfy_specifications?
13
+ end
14
+ def _offer_hash
15
+ _offer_factory.offer_hash
16
+ end
17
+ def _error_hash
18
+ _offer_factory.error_hash
19
+ end
20
+ def _offer_factory
21
+ @offer_factory ||= Users::Products::OfferFactory.new(current_user, _offer_params)
22
+ end
23
+ def _offer_params
24
+ params.require(:users_offer)
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ class Users::Products::CreateController < Apiv1::UsersController
2
+ def create
3
+ if _product_creation_success?
4
+ _product_factory.save!
5
+ render json: _product_hash
6
+ else
7
+ render json: _error_hash, status: :expectation_failed
8
+ end
9
+ end
10
+ private
11
+ def _product_creation_success?
12
+ _product_factory.satisfy_specifications?
13
+ end
14
+ def _product_hash
15
+ _product_factory.product_hash
16
+ end
17
+ def _error_hash
18
+ _product_factory.error_hash
19
+ end
20
+ def _product_factory
21
+ @product_factory ||= Apiv1::Users::ProductFactory.new(current_user, _product_params)
22
+ end
23
+ def _product_params
24
+ params.require(:users_product)
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ class Users::Products::UpdateController < Apiv1::UsersController
2
+ before_filter :_ensure_product_ownership
3
+ def update
4
+ if _product_modification_success?
5
+ _product_modifier.update!
6
+ render json: { product: _product_hash }
7
+ else
8
+ render json: _error_hash, status: :expectation_failed
9
+ end
10
+ end
11
+ private
12
+ def _ensure_product_ownership
13
+ unless current_user.owns? _product
14
+ render json: { message: "This isn't your listing" }, status: 401
15
+ end
16
+ end
17
+ def _product_modification_success?
18
+ _product_modifier.satisfy_specifications?
19
+ end
20
+ def _product_hash
21
+ _product_modifier.product_hash
22
+ end
23
+ def _error_hash
24
+ _product_modifier.error_hash
25
+ end
26
+ def _product_modifier
27
+ @product_modifier ||= Admin::ProductModifier.new _product, _product_params
28
+ end
29
+ def _product
30
+ @product ||= Apiv1::Product.find params[:id]
31
+ end
32
+ def _product_params
33
+ params.require(:users_product)
34
+ end
35
+ end
@@ -0,0 +1,13 @@
1
+ class Apiv1::AggregateMailer < ActionMailer::Base
2
+ default from: "from@example.com"
3
+ layout "apiv1/layouts/email"
4
+ def summary(emails)
5
+ @ctx = Apiv1::AggregateMailer::SummaryContext.new emails
6
+
7
+ mail to: @ctx.to,
8
+ from: @ctx.from,
9
+ cc: @ctx.cc,
10
+ bcc: @ctx.bcc,
11
+ subject: @ctx.subject
12
+ end
13
+ end
@@ -0,0 +1,121 @@
1
+ class Apiv1::AggregateMailer::SummaryContext
2
+ class NoEmailsToAggregate < StandardError; end
3
+ delegate :to,
4
+ :from,
5
+ :cc,
6
+ :bcc,
7
+ to: :_first_email
8
+ def initialize(emails)
9
+ @emails = emails
10
+ raise NoEmailsToAggregate, "no emails to aggregate" if @emails.blank?
11
+ end
12
+ def subject
13
+ [_preamble, _email_type_and_counts.join(", ")].join(" ").strip
14
+ end
15
+ def html_bodies
16
+ @emails.map do |email|
17
+ CoreHtmlFinder.html_body_gist email
18
+ end
19
+ end
20
+ def plain_bodies
21
+ @emails.map do |email|
22
+ CorePlainFinder.plain_body_gist email
23
+ end
24
+ end
25
+ def whoever_this_is_sent_to
26
+ FormalTitleFinder.formal_title _first_email
27
+ end
28
+ private
29
+ def _preamble
30
+ "Update:"
31
+ end
32
+ def _email_type_and_counts
33
+ _email_groups.map do |type_name, emails|
34
+ _that_pluralize_thing noun: type_name, count: emails.count
35
+ end
36
+ end
37
+ def _that_pluralize_thing(noun: noun, count: count)
38
+ if count > 1 || count == 0
39
+ "#{count} #{noun.pluralize}"
40
+ else
41
+ "#{count} #{noun.singularize}"
42
+ end
43
+ end
44
+ def _first_email
45
+ @emails.first
46
+ end
47
+ def _email_groups
48
+ @emails.reduce({}) do |hash, email|
49
+ s = _simplify_subject email.subject
50
+ hash[s] ||= []
51
+ hash[s].push email
52
+ hash
53
+ end
54
+ end
55
+ def _simplify_subject(subject)
56
+ subject.split("-").first.to_s.strip
57
+ end
58
+ end
59
+
60
+ class Apiv1::AggregateMailer::SummaryContext::CoreHtmlFinder
61
+ class << self
62
+ def html_body_gist(mail)
63
+ _process.call mail
64
+ end
65
+ private
66
+ def _process
67
+ _get_html_part >> _parse_by_nokogiri >> _find_via_css >> _return_html
68
+ end
69
+ def _get_html_part
70
+ -> (mail) { mail.html_part.to_s }
71
+ end
72
+ def _parse_by_nokogiri
73
+ -> (string) { Nokogiri::HTML(string) }
74
+ end
75
+ def _find_via_css
76
+ -> (nokodoc) { nokodoc.css "table.the-gist" }
77
+ end
78
+ def _return_html
79
+ -> (nokoel) { nokoel.map(&:to_s).join("\n") }
80
+ end
81
+ end
82
+ end
83
+
84
+ class Apiv1::AggregateMailer::SummaryContext::FormalTitleFinder
85
+ class << self
86
+ def formal_title(mail)
87
+ _process.call mail
88
+ end
89
+ private
90
+ def _process
91
+ _get_html_part >> _parse_by_nokogiri >> _find_via_css >> _return_html
92
+ end
93
+ def _get_html_part
94
+ -> (mail) { mail.html_part.to_s }
95
+ end
96
+ def _parse_by_nokogiri
97
+ -> (string) { Nokogiri::HTML(string) }
98
+ end
99
+ def _find_via_css
100
+ -> (nokodoc) { nokodoc.css "span.product-owner" }
101
+ end
102
+ def _return_html
103
+ -> (nokoel) { nokoel.first.text }
104
+ end
105
+ end
106
+ end
107
+
108
+ class Apiv1::AggregateMailer::SummaryContext::CorePlainFinder
109
+ class << self
110
+ def plain_body_gist(mail)
111
+ _process.call mail
112
+ end
113
+ private
114
+ def _process
115
+ _get_plain_part
116
+ end
117
+ def _get_plain_part
118
+ -> (mail) { mail.text_part.to_s }
119
+ end
120
+ end
121
+ end