disco_app 0.9.3

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 (291) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +37 -0
  3. data/app/assets/images/disco_app/icon.svg +1 -0
  4. data/app/assets/images/disco_app/icons.svg +0 -0
  5. data/app/assets/javascripts/disco_app/components/custom/filterable_shop_list.js.jsx +61 -0
  6. data/app/assets/javascripts/disco_app/components/custom/inline-radio-options.es6.jsx +59 -0
  7. data/app/assets/javascripts/disco_app/components/custom/rules-editor.es6.jsx +417 -0
  8. data/app/assets/javascripts/disco_app/components/custom/shop_filter_query.js.jsx +13 -0
  9. data/app/assets/javascripts/disco_app/components/custom/shop_filter_tab.js.jsx +34 -0
  10. data/app/assets/javascripts/disco_app/components/custom/shop_filter_tabs.js.jsx +21 -0
  11. data/app/assets/javascripts/disco_app/components/custom/shop_list.js.jsx +142 -0
  12. data/app/assets/javascripts/disco_app/components/custom/shop_row.js.jsx +43 -0
  13. data/app/assets/javascripts/disco_app/components/custom/shopify_admin_link.js.jsx +29 -0
  14. data/app/assets/javascripts/disco_app/components/ui-kit/cards/card-section.es6.jsx +30 -0
  15. data/app/assets/javascripts/disco_app/components/ui-kit/cards/card.es6.jsx +9 -0
  16. data/app/assets/javascripts/disco_app/components/ui-kit/cards/cart-section-title.es6.jsx +7 -0
  17. data/app/assets/javascripts/disco_app/components/ui-kit/forms/base_form.es6.jsx +72 -0
  18. data/app/assets/javascripts/disco_app/components/ui-kit/forms/base_input.es6.jsx +20 -0
  19. data/app/assets/javascripts/disco_app/components/ui-kit/forms/button.es6.jsx +13 -0
  20. data/app/assets/javascripts/disco_app/components/ui-kit/forms/input-radio.es6.jsx +30 -0
  21. data/app/assets/javascripts/disco_app/components/ui-kit/forms/input-select.es6.jsx +39 -0
  22. data/app/assets/javascripts/disco_app/components/ui-kit/forms/input-text.es6.jsx +59 -0
  23. data/app/assets/javascripts/disco_app/components/ui-kit/forms/input-textarea.es6.jsx +48 -0
  24. data/app/assets/javascripts/disco_app/components/ui-kit/icons/icon-chevron.es6.jsx +33 -0
  25. data/app/assets/javascripts/disco_app/components/ui-kit/icons/next-icon.es6.jsx +18 -0
  26. data/app/assets/javascripts/disco_app/components/ui-kit/input_select.es6.jsx +21 -0
  27. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-annotated-section.es6.jsx +29 -0
  28. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-empty-state.es6.jsx +35 -0
  29. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-footer-help.es6.jsx +13 -0
  30. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-page-actions.es6.jsx +39 -0
  31. data/app/assets/javascripts/disco_app/components.js +2 -0
  32. data/app/assets/javascripts/disco_app/disco_app.js +9 -0
  33. data/app/assets/javascripts/disco_app/frame.js +152 -0
  34. data/app/assets/javascripts/disco_app/shopify-turbolinks.js +7 -0
  35. data/app/assets/javascripts/disco_app/ui-kit.js +1 -0
  36. data/app/assets/stylesheets/disco_app/admin/_header.scss +75 -0
  37. data/app/assets/stylesheets/disco_app/admin/_layout.scss +32 -0
  38. data/app/assets/stylesheets/disco_app/admin/_nav.scss +184 -0
  39. data/app/assets/stylesheets/disco_app/admin.scss +11 -0
  40. data/app/assets/stylesheets/disco_app/disco_app.scss +19 -0
  41. data/app/assets/stylesheets/disco_app/frame/_buttons.scss +54 -0
  42. data/app/assets/stylesheets/disco_app/frame/_forms.scss +26 -0
  43. data/app/assets/stylesheets/disco_app/frame/_layout.scss +77 -0
  44. data/app/assets/stylesheets/disco_app/frame/_type.scss +25 -0
  45. data/app/assets/stylesheets/disco_app/frame.scss +10 -0
  46. data/app/assets/stylesheets/disco_app/mixins/_flexbox.scss +400 -0
  47. data/app/assets/stylesheets/disco_app/ui-kit/_ui-empty-state.scss +121 -0
  48. data/app/assets/stylesheets/disco_app/ui-kit/_ui-footer-help.scss +28 -0
  49. data/app/assets/stylesheets/disco_app/ui-kit/_ui-icons.scss +28 -0
  50. data/app/assets/stylesheets/disco_app/ui-kit/_ui-kit.scss +5113 -0
  51. data/app/assets/stylesheets/disco_app/ui-kit/_ui-layout.scss +10 -0
  52. data/app/assets/stylesheets/disco_app/ui-kit/_ui-page-actions.scss +21 -0
  53. data/app/assets/stylesheets/disco_app/ui-kit/_ui-tabs.scss +75 -0
  54. data/app/assets/stylesheets/disco_app/ui-kit/_ui-type.scss +13 -0
  55. data/app/controllers/disco_app/admin/app_settings_controller.rb +3 -0
  56. data/app/controllers/disco_app/admin/application_controller.rb +3 -0
  57. data/app/controllers/disco_app/admin/concerns/app_settings_controller.rb +24 -0
  58. data/app/controllers/disco_app/admin/concerns/authenticated_controller.rb +20 -0
  59. data/app/controllers/disco_app/admin/concerns/plans_controller.rb +54 -0
  60. data/app/controllers/disco_app/admin/concerns/shops_controller.rb +7 -0
  61. data/app/controllers/disco_app/admin/concerns/subscriptions_controller.rb +29 -0
  62. data/app/controllers/disco_app/admin/plans_controller.rb +3 -0
  63. data/app/controllers/disco_app/admin/resources/shops_controller.rb +3 -0
  64. data/app/controllers/disco_app/admin/shops_controller.rb +3 -0
  65. data/app/controllers/disco_app/admin/subscriptions_controller.rb +3 -0
  66. data/app/controllers/disco_app/charges_controller.rb +47 -0
  67. data/app/controllers/disco_app/concerns/app_proxy_controller.rb +40 -0
  68. data/app/controllers/disco_app/concerns/authenticated_controller.rb +56 -0
  69. data/app/controllers/disco_app/concerns/carrier_request_controller.rb +21 -0
  70. data/app/controllers/disco_app/frame_controller.rb +9 -0
  71. data/app/controllers/disco_app/install_controller.rb +27 -0
  72. data/app/controllers/disco_app/subscriptions_controller.rb +32 -0
  73. data/app/controllers/disco_app/webhooks_controller.rb +46 -0
  74. data/app/controllers/sessions_controller.rb +28 -0
  75. data/app/helpers/disco_app/application_helper.rb +50 -0
  76. data/app/jobs/disco_app/app_installed_job.rb +3 -0
  77. data/app/jobs/disco_app/app_uninstalled_job.rb +3 -0
  78. data/app/jobs/disco_app/concerns/app_installed_job.rb +39 -0
  79. data/app/jobs/disco_app/concerns/app_uninstalled_job.rb +20 -0
  80. data/app/jobs/disco_app/concerns/shop_update_job.rb +13 -0
  81. data/app/jobs/disco_app/concerns/subscription_changed_job.rb +7 -0
  82. data/app/jobs/disco_app/concerns/synchronise_carrier_service_job.rb +52 -0
  83. data/app/jobs/disco_app/concerns/synchronise_webhooks_job.rb +61 -0
  84. data/app/jobs/disco_app/shop_job.rb +27 -0
  85. data/app/jobs/disco_app/shop_update_job.rb +3 -0
  86. data/app/jobs/disco_app/subscription_changed_job.rb +3 -0
  87. data/app/jobs/disco_app/synchronise_carrier_service_job.rb +3 -0
  88. data/app/jobs/disco_app/synchronise_webhooks_job.rb +3 -0
  89. data/app/models/disco_app/app_settings.rb +3 -0
  90. data/app/models/disco_app/application_charge.rb +18 -0
  91. data/app/models/disco_app/concerns/app_settings.rb +7 -0
  92. data/app/models/disco_app/concerns/plan.rb +26 -0
  93. data/app/models/disco_app/concerns/plan_code.rb +15 -0
  94. data/app/models/disco_app/concerns/shop.rb +63 -0
  95. data/app/models/disco_app/concerns/subscription.rb +60 -0
  96. data/app/models/disco_app/concerns/synchronises.rb +39 -0
  97. data/app/models/disco_app/plan.rb +3 -0
  98. data/app/models/disco_app/plan_code.rb +3 -0
  99. data/app/models/disco_app/recurring_application_charge.rb +18 -0
  100. data/app/models/disco_app/session_storage.rb +18 -0
  101. data/app/models/disco_app/shop.rb +3 -0
  102. data/app/models/disco_app/subscription.rb +3 -0
  103. data/app/resources/disco_app/admin/resources/concerns/shop_resource.rb +100 -0
  104. data/app/resources/disco_app/admin/resources/shop_resource.rb +4 -0
  105. data/app/services/disco_app/carrier_request_service.rb +15 -0
  106. data/app/services/disco_app/charges_service.rb +81 -0
  107. data/app/services/disco_app/proxy_service.rb +17 -0
  108. data/app/services/disco_app/subscription_service.rb +46 -0
  109. data/app/services/disco_app/webhook_service.rb +30 -0
  110. data/app/views/disco_app/admin/app_settings/edit.html.erb +5 -0
  111. data/app/views/disco_app/admin/plans/_form.html.erb +72 -0
  112. data/app/views/disco_app/admin/plans/_plan_code_fields.html.erb +15 -0
  113. data/app/views/disco_app/admin/plans/edit.html.erb +7 -0
  114. data/app/views/disco_app/admin/plans/index.html.erb +43 -0
  115. data/app/views/disco_app/admin/plans/new.html.erb +7 -0
  116. data/app/views/disco_app/admin/shops/index.html.erb +13 -0
  117. data/app/views/disco_app/admin/subscriptions/edit.html.erb +33 -0
  118. data/app/views/disco_app/charges/activate.html.erb +1 -0
  119. data/app/views/disco_app/charges/create.html.erb +1 -0
  120. data/app/views/disco_app/charges/new.html.erb +12 -0
  121. data/app/views/disco_app/frame/frame.html.erb +36 -0
  122. data/app/views/disco_app/install/installing.html.erb +7 -0
  123. data/app/views/disco_app/install/uninstalling.html.erb +1 -0
  124. data/app/views/disco_app/proxy_errors/404.html.erb +1 -0
  125. data/app/views/disco_app/shared/_card.html.erb +14 -0
  126. data/app/views/disco_app/shared/_icons.html.erb +3 -0
  127. data/app/views/disco_app/shared/_section.html.erb +17 -0
  128. data/app/views/disco_app/subscriptions/new.html.erb +25 -0
  129. data/app/views/layouts/admin/_nav_items.erb +20 -0
  130. data/app/views/layouts/admin.html.erb +67 -0
  131. data/app/views/layouts/application.html.erb +18 -0
  132. data/app/views/layouts/embedded_app.html.erb +43 -0
  133. data/app/views/layouts/embedded_app_modal.html.erb +28 -0
  134. data/app/views/sessions/new.html.erb +26 -0
  135. data/config/routes.rb +48 -0
  136. data/db/migrate/20150525000000_create_shops_if_not_existent.rb +15 -0
  137. data/db/migrate/20150525162112_add_status_to_shops.rb +5 -0
  138. data/db/migrate/20150525171422_add_meta_to_shops.rb +11 -0
  139. data/db/migrate/20150629210346_add_charge_status_to_shop.rb +5 -0
  140. data/db/migrate/20150814214025_add_more_meta_to_shops.rb +15 -0
  141. data/db/migrate/20151017231302_create_disco_app_plans.rb +13 -0
  142. data/db/migrate/20151017232027_create_disco_app_subscriptions.rb +15 -0
  143. data/db/migrate/20151017234409_move_shop_to_disco_app_engine.rb +5 -0
  144. data/db/migrate/20160112233706_create_disco_app_sessions.rb +12 -0
  145. data/db/migrate/20160113194418_add_shop_id_to_disco_app_sessions.rb +6 -0
  146. data/db/migrate/20160223111044_create_disco_app_settings.rb +8 -0
  147. data/db/migrate/20160301223215_update_plans.rb +22 -0
  148. data/db/migrate/20160301224558_update_subscriptions.rb +13 -0
  149. data/db/migrate/20160302104816_create_disco_app_recurring_application_charges.rb +14 -0
  150. data/db/migrate/20160302105259_create_disco_app_application_charges.rb +14 -0
  151. data/db/migrate/20160302134728_drop_charge_status_from_shops.rb +5 -0
  152. data/db/migrate/20160302142941_add_shopify_attributes_to_charges.rb +8 -0
  153. data/db/migrate/20160331093148_create_disco_app_plan_codes.rb +14 -0
  154. data/db/migrate/20160401044420_add_status_to_plan_codes.rb +5 -0
  155. data/db/migrate/20160401045551_add_amount_and_plan_code_to_disco_app_subscriptions.rb +7 -0
  156. data/db/migrate/20160425205211_add_source_to_disco_app_subscriptions.rb +5 -0
  157. data/db/migrate/20160426033520_add_trial_period_days_to_disco_app_subscriptions.rb +5 -0
  158. data/db/migrate/20160513140727_add_name_to_disco_app_shops.rb +5 -0
  159. data/db/migrate/20160521135510_move_shop_to_synchronises.rb +61 -0
  160. data/lib/disco_app/configuration.rb +39 -0
  161. data/lib/disco_app/constants.rb +4 -0
  162. data/lib/disco_app/engine.rb +26 -0
  163. data/lib/disco_app/session.rb +14 -0
  164. data/lib/disco_app/support/file_fixtures.rb +23 -0
  165. data/lib/disco_app/test_help.rb +11 -0
  166. data/lib/disco_app/version.rb +3 -0
  167. data/lib/disco_app.rb +7 -0
  168. data/lib/generators/disco_app/USAGE +5 -0
  169. data/lib/generators/disco_app/disco_app_generator.rb +236 -0
  170. data/lib/generators/disco_app/templates/assets/javascripts/application.js +17 -0
  171. data/lib/generators/disco_app/templates/assets/javascripts/components.js +3 -0
  172. data/lib/generators/disco_app/templates/assets/stylesheets/application.scss +5 -0
  173. data/lib/generators/disco_app/templates/config/database.yml.tt +20 -0
  174. data/lib/generators/disco_app/templates/config/newrelic.yml +26 -0
  175. data/lib/generators/disco_app/templates/config/puma.rb +15 -0
  176. data/lib/generators/disco_app/templates/controllers/home_controller.rb +7 -0
  177. data/lib/generators/disco_app/templates/initializers/disco_app.rb +19 -0
  178. data/lib/generators/disco_app/templates/initializers/rollbar.rb +12 -0
  179. data/lib/generators/disco_app/templates/initializers/session_store.rb +2 -0
  180. data/lib/generators/disco_app/templates/initializers/shopify_app.rb +7 -0
  181. data/lib/generators/disco_app/templates/initializers/shopify_session_repository.rb +7 -0
  182. data/lib/generators/disco_app/templates/root/CHECKS +4 -0
  183. data/lib/generators/disco_app/templates/root/Procfile +2 -0
  184. data/lib/generators/disco_app/templates/views/home/index.html.erb +2 -0
  185. data/lib/tasks/carrier_service.rake +10 -0
  186. data/lib/tasks/database.rake +8 -0
  187. data/lib/tasks/sessions.rake +9 -0
  188. data/lib/tasks/shops.rake +10 -0
  189. data/lib/tasks/start.rake +3 -0
  190. data/lib/tasks/webhooks.rake +10 -0
  191. data/test/controllers/disco_app/admin/shops_controller_test.rb +54 -0
  192. data/test/controllers/disco_app/charges_controller_test.rb +99 -0
  193. data/test/controllers/disco_app/install_controller_test.rb +50 -0
  194. data/test/controllers/disco_app/subscriptions_controller_test.rb +68 -0
  195. data/test/controllers/disco_app/webhooks_controller_test.rb +58 -0
  196. data/test/controllers/home_controller_test.rb +92 -0
  197. data/test/controllers/proxy_controller_test.rb +42 -0
  198. data/test/disco_app_test.rb +7 -0
  199. data/test/dummy/Rakefile +6 -0
  200. data/test/dummy/app/assets/javascripts/application.js +17 -0
  201. data/test/dummy/app/assets/stylesheets/application.scss +5 -0
  202. data/test/dummy/app/controllers/application_controller.rb +6 -0
  203. data/test/dummy/app/controllers/disco_app/admin/shops_controller.rb +8 -0
  204. data/test/dummy/app/controllers/home_controller.rb +7 -0
  205. data/test/dummy/app/controllers/proxy_controller.rb +8 -0
  206. data/test/dummy/app/helpers/application_helper.rb +2 -0
  207. data/test/dummy/app/jobs/disco_app/app_installed_job.rb +16 -0
  208. data/test/dummy/app/jobs/disco_app/app_uninstalled_job.rb +11 -0
  209. data/test/dummy/app/jobs/products_create_job.rb +7 -0
  210. data/test/dummy/app/jobs/products_delete_job.rb +7 -0
  211. data/test/dummy/app/jobs/products_update_job.rb +7 -0
  212. data/test/dummy/app/models/disco_app/shop.rb +15 -0
  213. data/test/dummy/app/models/product.rb +6 -0
  214. data/test/dummy/app/views/home/index.html.erb +2 -0
  215. data/test/dummy/bin/bundle +3 -0
  216. data/test/dummy/bin/rails +4 -0
  217. data/test/dummy/bin/rake +4 -0
  218. data/test/dummy/bin/setup +29 -0
  219. data/test/dummy/config/application.rb +38 -0
  220. data/test/dummy/config/boot.rb +5 -0
  221. data/test/dummy/config/database.codeship.yml +23 -0
  222. data/test/dummy/config/database.gitlab-ci.yml +24 -0
  223. data/test/dummy/config/database.yml +20 -0
  224. data/test/dummy/config/environment.rb +5 -0
  225. data/test/dummy/config/environments/development.rb +41 -0
  226. data/test/dummy/config/environments/production.rb +85 -0
  227. data/test/dummy/config/environments/test.rb +42 -0
  228. data/test/dummy/config/initializers/assets.rb +11 -0
  229. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  230. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  231. data/test/dummy/config/initializers/disco_app.rb +19 -0
  232. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  233. data/test/dummy/config/initializers/inflections.rb +16 -0
  234. data/test/dummy/config/initializers/mime_types.rb +4 -0
  235. data/test/dummy/config/initializers/omniauth.rb +9 -0
  236. data/test/dummy/config/initializers/session_store.rb +2 -0
  237. data/test/dummy/config/initializers/shopify_app.rb +7 -0
  238. data/test/dummy/config/initializers/shopify_session_repository.rb +7 -0
  239. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  240. data/test/dummy/config/locales/en.yml +23 -0
  241. data/test/dummy/config/routes.rb +10 -0
  242. data/test/dummy/config/secrets.yml +22 -0
  243. data/test/dummy/config.ru +4 -0
  244. data/test/dummy/db/migrate/20160307182229_create_products.rb +11 -0
  245. data/test/dummy/db/schema.rb +126 -0
  246. data/test/dummy/public/404.html +67 -0
  247. data/test/dummy/public/422.html +67 -0
  248. data/test/dummy/public/500.html +66 -0
  249. data/test/dummy/public/favicon.ico +0 -0
  250. data/test/fixtures/api/widget_store/charges/activate_application_charge_request.json +16 -0
  251. data/test/fixtures/api/widget_store/charges/activate_application_charge_response.json +1 -0
  252. data/test/fixtures/api/widget_store/charges/activate_recurring_application_charge_request.json +20 -0
  253. data/test/fixtures/api/widget_store/charges/activate_recurring_application_charge_response.json +1 -0
  254. data/test/fixtures/api/widget_store/charges/create_application_charge_request.json +9 -0
  255. data/test/fixtures/api/widget_store/charges/create_application_charge_response.json +16 -0
  256. data/test/fixtures/api/widget_store/charges/create_recurring_application_charge_request.json +9 -0
  257. data/test/fixtures/api/widget_store/charges/create_recurring_application_charge_response.json +20 -0
  258. data/test/fixtures/api/widget_store/charges/create_second_recurring_application_charge_request.json +9 -0
  259. data/test/fixtures/api/widget_store/charges/create_second_recurring_application_charge_response.json +20 -0
  260. data/test/fixtures/api/widget_store/charges/get_accepted_application_charge_response.json +16 -0
  261. data/test/fixtures/api/widget_store/charges/get_accepted_recurring_application_charge_response.json +20 -0
  262. data/test/fixtures/api/widget_store/charges/get_declined_application_charge_response.json +16 -0
  263. data/test/fixtures/api/widget_store/charges/get_declined_recurring_application_charge_response.json +20 -0
  264. data/test/fixtures/api/widget_store/charges/get_pending_application_charge_response.json +16 -0
  265. data/test/fixtures/api/widget_store/charges/get_pending_recurring_application_charge_response.json +20 -0
  266. data/test/fixtures/api/widget_store/shop.json +46 -0
  267. data/test/fixtures/api/widget_store/webhooks.json +1 -0
  268. data/test/fixtures/disco_app/application_charges.yml +11 -0
  269. data/test/fixtures/disco_app/plan_codes.yml +13 -0
  270. data/test/fixtures/disco_app/plans.yml +37 -0
  271. data/test/fixtures/disco_app/recurring_application_charges.yml +11 -0
  272. data/test/fixtures/disco_app/shops.yml +10 -0
  273. data/test/fixtures/disco_app/subscriptions.yml +22 -0
  274. data/test/fixtures/products.yml +4 -0
  275. data/test/fixtures/webhooks/app_uninstalled.json +46 -0
  276. data/test/fixtures/webhooks/product_created.json +167 -0
  277. data/test/fixtures/webhooks/product_deleted.json +3 -0
  278. data/test/fixtures/webhooks/product_updated.json +167 -0
  279. data/test/integration/synchronises_test.rb +55 -0
  280. data/test/jobs/disco_app/app_installed_job_test.rb +55 -0
  281. data/test/jobs/disco_app/app_uninstalled_job_test.rb +30 -0
  282. data/test/models/disco_app/plan_test.rb +5 -0
  283. data/test/models/disco_app/session_test.rb +31 -0
  284. data/test/models/disco_app/shop_test.rb +27 -0
  285. data/test/models/disco_app/subscription_test.rb +19 -0
  286. data/test/services/disco_app/charges_service_test.rb +112 -0
  287. data/test/services/disco_app/subscription_service_test.rb +60 -0
  288. data/test/support/test_file_fixtures.rb +29 -0
  289. data/test/support/test_shopify_api.rb +16 -0
  290. data/test/test_helper.rb +55 -0
  291. metadata +727 -0
@@ -0,0 +1,81 @@
1
+ class DiscoApp::ChargesService
2
+
3
+ # Create the appropriate type of Shopify charge for the given subscription
4
+ # (either one-time or recurring) and return.
5
+ def self.create(shop, subscription)
6
+ # Create the charge object locally first.
7
+ charge = subscription.charge_class.create!(
8
+ shop: shop,
9
+ subscription: subscription,
10
+ )
11
+
12
+ # Create the charge object on Shopify.
13
+ shopify_charge = shop.temp {
14
+ subscription.shopify_charge_class.create(
15
+ name: subscription.plan.name,
16
+ price: '%.2f' % (subscription.amount.to_f / 100.0),
17
+ trial_days: subscription.plan.has_trial? ? subscription.trial_period_days : nil,
18
+ return_url: charge.activate_url,
19
+ test: !DiscoApp.configuration.real_charges?
20
+ )
21
+ }
22
+
23
+ # If we couldn't create the charge on Shopify, return nil.
24
+ if shopify_charge.nil?
25
+ return nil
26
+ end
27
+
28
+ # Update the local record of the charge from Shopify's created charge, then
29
+ # return it.
30
+ charge.update(
31
+ shopify_id: shopify_charge.id,
32
+ confirmation_url: shopify_charge.confirmation_url
33
+ )
34
+ charge
35
+ end
36
+
37
+ # Attempt to activate the given Shopify charge for the given Shop using the
38
+ # Shopify API. Returns true on successful activation, false otherwise.
39
+ def self.activate(shop, charge)
40
+ begin
41
+ # Start by fetching the Shopify charge to check that it was accepted.
42
+ shopify_charge = shop.temp {
43
+ charge.subscription.shopify_charge_class.find(charge.shopify_id)
44
+ }
45
+
46
+ # Update the status of the local charge based on the Shopify charge.
47
+ charge.send("#{shopify_charge.status}!") if charge.respond_to? "#{shopify_charge.status}!"
48
+
49
+ # If the charge wasn't accepted, fail and return.
50
+ return false unless charge.accepted?
51
+
52
+ # If the charge was indeed accepted, activate it via Shopify.
53
+ charge.shop.temp {
54
+ shopify_charge.activate
55
+ }
56
+
57
+ # If the charge was recurring, make sure that all other local recurring
58
+ # charges are marked inactive.
59
+ if charge.recurring?
60
+ self.cancel_recurring_charges(shop, charge)
61
+ end
62
+
63
+ charge.active!
64
+
65
+ true
66
+ rescue
67
+ false
68
+ end
69
+ end
70
+
71
+ # Cancel all recurring charges for the given shop. If the optional charge
72
+ # parameter is given, it will be excluded from the cancellation.
73
+ def self.cancel_recurring_charges(shop, charge = nil)
74
+ charges = DiscoApp::RecurringApplicationCharge.where(shop: shop)
75
+ if charge.present?
76
+ charges = charges.where.not(id: charge)
77
+ end
78
+ charges.update_all(status: DiscoApp::RecurringApplicationCharge.statuses[:cancelled])
79
+ end
80
+
81
+ end
@@ -0,0 +1,17 @@
1
+ class DiscoApp::ProxyService
2
+
3
+ # Return true iff the signature provided in the given query string matches
4
+ # that calculated from the remaining query parameters and the given secret.
5
+ def self.proxy_signature_is_valid?(query_string, secret)
6
+ query_hash = Rack::Utils.parse_query(query_string)
7
+ signature = query_hash.delete('signature').to_s
8
+ ActiveSupport::SecurityUtils.variable_size_secure_compare(self.calculated_signature(query_hash, secret), signature)
9
+ end
10
+
11
+ # Return the calculated signature for the given query hash and secret.
12
+ def self.calculated_signature(query_hash, secret)
13
+ sorted_params = query_hash.collect{ |k, v| "#{k}=#{Array(v).join(',')}" }.sort.join
14
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), secret, sorted_params)
15
+ end
16
+
17
+ end
@@ -0,0 +1,46 @@
1
+ class DiscoApp::SubscriptionService
2
+
3
+ # Subscribe the given shop to the given plan, optionally using the given plan
4
+ # code and optionally tracking the subscription source.
5
+ def self.subscribe(shop, plan, plan_code = nil, source = nil)
6
+
7
+ # If a plan code was provided, fetch it for the given plan.
8
+ plan_code_instance = nil
9
+ if plan_code.present?
10
+ plan_code_instance = DiscoApp::PlanCode.available.find_by(plan: plan, code: plan_code)
11
+ end
12
+
13
+ # Cancel any existing current subscriptions.
14
+ shop.subscriptions.current.update_all(
15
+ status: DiscoApp::Subscription.statuses[:cancelled],
16
+ cancelled_at: Time.now
17
+ )
18
+
19
+ # Get the amount that should be charged for the subscription.
20
+ subscription_amount = plan_code_instance.present? ? plan_code_instance.amount : plan.amount
21
+
22
+ # Get the date the subscription trial should end.
23
+ subscription_trial_period_days = plan_code_instance.present? ? plan_code_instance.trial_period_days : plan.trial_period_days
24
+
25
+ # Create the new subscription.
26
+ new_subscription = DiscoApp::Subscription.create!(
27
+ shop: shop,
28
+ plan: plan,
29
+ plan_code: plan_code_instance,
30
+ status: DiscoApp::Subscription.statuses[plan.has_trial? ? :trial : :active],
31
+ subscription_type: plan.plan_type,
32
+ amount: subscription_amount,
33
+ trial_period_days: plan.has_trial? ? subscription_trial_period_days : nil,
34
+ trial_start_at: plan.has_trial? ? Time.now : nil,
35
+ trial_end_at: plan.has_trial? ? subscription_trial_period_days.days.from_now : nil,
36
+ source: source
37
+ )
38
+
39
+ # Enqueue the subscription changed background job.
40
+ DiscoApp::SubscriptionChangedJob.perform_later(shop.shopify_domain, new_subscription)
41
+
42
+ # Return the new subscription.
43
+ new_subscription
44
+ end
45
+
46
+ end
@@ -0,0 +1,30 @@
1
+ class DiscoApp::WebhookService
2
+
3
+ # Return true iff the provided hmac_to_verify matches that calculated from the
4
+ # given data and secret.
5
+ def self.is_valid_hmac?(body, secret, hmac_to_verify)
6
+ ActiveSupport::SecurityUtils.secure_compare(self.calculated_hmac(body, secret), hmac_to_verify.to_s)
7
+ end
8
+
9
+ # Calculate the HMAC for the given data and secret.
10
+ def self.calculated_hmac(body, secret)
11
+ digest = OpenSSL::Digest.new('sha256')
12
+ Base64.encode64(OpenSSL::HMAC.digest(digest, secret, body)).strip
13
+ end
14
+
15
+ # Try to find a job class for the given webhook topic.
16
+ def self.find_job_class(topic)
17
+ begin
18
+ # First try to find a top-level matching job class.
19
+ "#{topic}_job".gsub('/', '_').classify.constantize
20
+ rescue NameError
21
+ # If that fails, try to find a DiscoApp:: prefixed job class.
22
+ begin
23
+ %Q{DiscoApp::#{"#{topic}_job".gsub('/', '_').classify}}.constantize
24
+ rescue NameError
25
+ nil
26
+ end
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,5 @@
1
+ <% provide(:title, 'App Settings') %>
2
+
3
+ <p>Update 'app/views/disco_app/admin/app_settings/edit.html.erb' on your own rails app.</p>
4
+
5
+
@@ -0,0 +1,72 @@
1
+ <section class="section">
2
+ <div class="layout-content">
3
+ <section class="layout-content__main">
4
+ <div class="next-grid">
5
+ <div class="next-grid__cell">
6
+ <div class="next-card">
7
+
8
+ <header class="next-card__header">
9
+ <h1>Plan</h1>
10
+ </header>
11
+
12
+ <section class="next-card__section">
13
+ <div class="form-group">
14
+ <%= f.label(:name, 'Name') %>
15
+ <%= f.text_field(:name) %>
16
+ </div>
17
+
18
+ <div class="form-group">
19
+ <%= f.label(:status, 'Status') %>
20
+ <%= f.select(:status, DiscoApp::Plan.statuses.map { |s| [s.first.humanize, s.first] }) %>
21
+ </div>
22
+
23
+ <div class="form-group">
24
+ <%= f.label(:plan_type, 'Plan Type') %>
25
+ <%= f.select(:plan_type, DiscoApp::Plan.plan_types.map { |s| [s.first.humanize, s.first] }) %>
26
+ </div>
27
+
28
+ <div class="form-group">
29
+ <%= f.label(:trial_period_days, 'Trial Period Days') %>
30
+ <%= f.number_field(:trial_period_days) %>
31
+ </div>
32
+
33
+ <div class="form-group">
34
+ <%= f.label(:amount, 'Amount') %>
35
+ <%= f.number_field(:amount) %>
36
+ </div>
37
+ </section>
38
+ </div>
39
+ </div>
40
+ <div class="next-grid__cell">
41
+ <div class="next-card next-card--aside">
42
+ <header class="next-card__header">
43
+ <h1>Plan Codes</h1>
44
+ </header>
45
+
46
+ <%= f.fields_for :plan_codes do |plan_code| %>
47
+ <%= render 'plan_code_fields', f: plan_code %>
48
+ <% end %>
49
+
50
+ <br>
51
+
52
+ <%= link_to_add_fields('Add New Plan Code', f, :plan_codes) %>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ <hr />
57
+ <div class="row">
58
+ <div class="col-md-12">
59
+ <%= f.submit 'Save', { class: 'btn btn-primary' } %>
60
+ </div>
61
+ </div>
62
+ </section>
63
+ </div>
64
+ </section>
65
+ <script type="text/javascript">
66
+ $('form').on('click', '.add_fields', function(event) {
67
+ var time = new Date().getTime();
68
+ var regexp = new RegExp($(this).data('id'), 'g');
69
+ $(this).before($(this).data('fields').replace(regexp, time));
70
+ event.preventDefault();
71
+ });
72
+ </script>
@@ -0,0 +1,15 @@
1
+ <section class="next-card__section">
2
+ <div class="app-container">
3
+ <%= f.label(:code, 'Code') %>
4
+ <%= f.text_field(:code) %>
5
+
6
+ <%= f.label(:trial_period_days, 'Trial Period Days') %>
7
+ <%= f.number_field(:trial_period_days) %>
8
+
9
+ <%= f.label(:amount, 'Amount') %>
10
+ <%= f.number_field(:amount) %>
11
+
12
+ <%= f.label :_destroy, 'Remove Plan' %>
13
+ <%= f.check_box :_destroy %>
14
+ </div>
15
+ </section>
@@ -0,0 +1,7 @@
1
+ <% provide(:title, 'Edit Plan') %>
2
+
3
+ <%= form_for(@plan, url: admin_plan_path(@plan)) do |f| %>
4
+ <%= render 'form', f: f %>
5
+ <% end %>
6
+
7
+ <%= link_to 'Back', admin_plans_path, { class: 'btn btn-default' } %>
@@ -0,0 +1,43 @@
1
+ <% provide(:title, 'Plans') %>
2
+
3
+ <div class="next-grid">
4
+ <div class="next-grid__cell">
5
+ <div class="next-card">
6
+ <% unless @plans.empty? %>
7
+ <table class="table">
8
+ <thead>
9
+ <tr>
10
+ <th>Name</th>
11
+ <th>Status</th>
12
+ <th>Plan Type</th>
13
+ <th>Trial Period</th>
14
+ <th>Amount</th>
15
+ <th>Currency</th>
16
+ <th>Interval</th>
17
+ <th>Interval Count</th>
18
+ <th></th>
19
+ </tr>
20
+ </thead>
21
+ <tbody>
22
+ <% @plans.each do |plan| %>
23
+ <tr>
24
+ <td><%= link_to(plan.name, edit_admin_plan_path(plan)) %></td>
25
+ <td><%= plan.status %></td>
26
+ <td><%= plan.plan_type %></td>
27
+ <td><%= plan.trial_period_days %></td>
28
+ <td><%= plan.amount %></td>
29
+ <td><%= plan.currency %></td>
30
+ <td><%= plan.interval %></td>
31
+ <td><%= plan.interval_count %></td>
32
+ <td><%= link_to 'Delete', admin_plan_path(plan), action: 'destroy', method: :delete, data: {confirm: "About to delete plan: #{plan.name}. Are you sure?"} %></td>
33
+ </tr>
34
+ <% end %>
35
+ </tbody>
36
+ </table>
37
+ <% end %>
38
+ </div>
39
+ <hr/>
40
+ <%= link_to 'Create new plan', new_admin_plan_path, { class: 'btn btn-primary' } %>
41
+ </div>
42
+ </div>
43
+
@@ -0,0 +1,7 @@
1
+ <% provide(:title, 'New Plan') %>
2
+
3
+ <%= form_for(@plan, url: admin_plans_path) do |f| %>
4
+ <%= render 'form', f: f %>
5
+ <% end %>
6
+
7
+ <%= link_to 'Back', admin_plans_path, { class: 'btn btn-default' } %>
@@ -0,0 +1,13 @@
1
+ <% provide(:title, 'Shops') %>
2
+
3
+ <div class="next-grid">
4
+ <div class="next-grid__cell">
5
+
6
+ <%= react_component('FilterableShopList', {
7
+ shopsUrl: admin_resources_shops_path(format: :json),
8
+ editShopUrl: edit_admin_shop_path(':id'),
9
+ editSubscriptionUrl: edit_admin_shop_subscription_path(':shop_id', ':id')
10
+ }) %>
11
+
12
+ </div>
13
+ </div>
@@ -0,0 +1,33 @@
1
+ <% provide(:breadcrumb, 'Shops') %>
2
+ <% provide(:breadcrumb_url, admin_shops_path) %>
3
+ <% provide(:title, 'Edit subscription') %>
4
+
5
+ <div class="next-grid">
6
+ <div class="next-grid__cell">
7
+
8
+ <%= form_for(@subscription, url: admin_shop_subscription_path(@subscription.shop, @subscription)) do |f| %>
9
+
10
+ <%= f.label(:amount) %>
11
+ <%= f.number_field(:amount) %>
12
+
13
+ <%= f.label(:trial_period_days) %>
14
+ <%= f.number_field(:trial_period_days) %>
15
+
16
+ <p>
17
+ Note that adjusting the amount or trial days of the subscription will
18
+ clear any charge previously authorized by the user, and they'll be asked
19
+ to re-authorize the next time they open the application.
20
+ </p>
21
+
22
+ <p>
23
+ If you're changing the amount of a subscription for an existing user and
24
+ don't want them to get another trial period, make sure to set "Trial
25
+ period days" to zero.
26
+ </p>
27
+
28
+ <%= f.submit 'Save', { class: 'btn btn-primary' } %>
29
+
30
+ <% end %>
31
+
32
+ </div>
33
+ </div>
@@ -0,0 +1 @@
1
+ activate_charge
@@ -0,0 +1 @@
1
+ create_charge
@@ -0,0 +1,12 @@
1
+ <% provide(:title, 'Thankyou') %>
2
+
3
+ <p>
4
+ Thanks for installing <%= DiscoApp.configuration.app_name %>!
5
+ </p>
6
+ <p>
7
+ Before we start setting things up, we need you to authorize a charge for the application.
8
+ </p>
9
+
10
+ <%= form_tag disco_app.subscription_charges_path(@subscription), method: 'POST', target: '_parent' do %>
11
+ <%= submit_tag 'Okay', class: 'form-input' %>
12
+ <% end %>
@@ -0,0 +1,36 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dev Frame</title>
5
+ <%= stylesheet_link_tag 'disco_app/frame', media: 'all' %>
6
+ <%= javascript_include_tag 'disco_app/frame' %>
7
+ </head>
8
+ <body>
9
+ <!-- Left Sidebar -->
10
+ <aside id="sidebar"></aside>
11
+
12
+ <!-- Header Bar -->
13
+ <header id="header">
14
+ <h1 id="header-title">
15
+ <img id="header-title-icon" src="<%= image_path('disco_app/icon.svg') %>" width="20" height="20" />
16
+ Shopify Dev Frame
17
+ </h1>
18
+ <div id="header-actions">
19
+ <!-- No action. -->
20
+ </div>
21
+ </header>
22
+
23
+ <!-- Content iFrame -->
24
+ <section id="content-wrapper">
25
+ <iframe id="content" src="/"></iframe>
26
+ </section>
27
+
28
+ <!-- Setup FrameApp. -->
29
+ <script type="text/javascript">
30
+ FrameApp.init({
31
+ debug: true,
32
+ iframe: document.getElementById('content')
33
+ });
34
+ </script>
35
+ </body>
36
+ </html>
@@ -0,0 +1,7 @@
1
+ <% content_for :extra_head do %>
2
+ <meta http-equiv="refresh" content="5">
3
+ <% end %>
4
+
5
+ <p>
6
+ Installing, please wait...
7
+ </p>
@@ -0,0 +1 @@
1
+ uninstalling
@@ -0,0 +1 @@
1
+ 404 Not Found
@@ -0,0 +1,14 @@
1
+ <% disabled ||= false %>
2
+ <div class="next-card <% if disabled %>next-card--disabled<% end %>">
3
+ <% if content_for?(:card_header) %>
4
+ <header class="next-card__header">
5
+ <%= content_for :card_header %>
6
+ </header>
7
+ <% end %>
8
+ <%= content_for :card_content %>
9
+ <% if content_for?(:card_footer) %>
10
+ <footer class="next-card__footer">
11
+ <%= content_for :card_footer %>
12
+ </footer>
13
+ <% end %>
14
+ </div>
@@ -0,0 +1,3 @@
1
+ <div style="display: none;">
2
+ <svg xmlns="http://www.w3.org/2000/svg"><symbol id="next-products"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" enable-background="new 0 0 24 24"><path d="M21.8 1h-7c-.8 0-1.5.3-2 .8L1.4 13.2c-.5.5-.5 1.3 0 1.8L9 22.7c.5.5 1.3.5 1.8 0l11.3-11.4c.5-.5.8-1.3.8-2v-7c.1-.7-.4-1.3-1.1-1.3zm-4 7.6c-1.3 0-2.3-1.1-2.3-2.3C15.5 5 16.6 4 17.8 4c1.3 0 2.3 1.1 2.3 2.3 0 1.3-1 2.3-2.3 2.3z"/></svg></symbol><symbol id="rte-html"><svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="12" height="12" viewBox="0 0 12 12"><title>rte-html</title><desc>Created with Sketch.</desc><path d="M5 4.406l-3.761 1.603 3.761 1.591v1.4l-5-2.334v-1.327l5-2.339v1.406zm2 0v-1.406l5 2.339v1.327l-5 2.334v-1.4l3.761-1.591-3.761-1.603z" sketch:type="MSShapeGroup" fill="#000"/></svg></symbol><symbol id="rte-formatting"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 3 12 12" enable-background="new -1 3 12 12"><title>rte-formatting</title><desc>Created with Sketch.</desc><path d="M10.9 13.2c-.1 0-.3 0-.5-.1-.2 0-.3-.1-.4-.2-.2-.1-.3-.2-.4-.3-.1-.1-.2-.3-.2-.4l-3.9-9.1v-.1h-.8v.1c-.6 1.3-1.2 2.8-1.9 4.4-.7 1.7-1.4 3.2-1.9 4.5l-.3.6c-.1.1-.3.3-.5.4-.1 0-.3.1-.5.1s-.4.1-.5.1h-.1v.8h4.6v-.8h-.1c-.4 0-.8-.1-1.1-.2-.3-.1-.4-.2-.4-.3v-.3c0-.1.1-.3.1-.5l.3-.7c.1-.2.3-.8.5-1.2h3.5l1 2.6v.2s0 .1-.3.1c-.3.1-.6.1-1 .1h-.1v1h5v-.8h-.1zm-5-4.2h-2.7l1.3-3.2 1.4 3.2z"/></svg></symbol><symbol id="next-disclosure"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" enable-background="new 0 0 24 24"><path d="M4.8 8h14.4c.6 0 .9.7.6 1.2l-7.2 8.9c-.3.4-.8.4-1.1 0L4.2 9.2c-.4-.5 0-1.2.6-1.2z"/></svg></symbol><symbol id="rte-bold"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 3 12 12" enable-background="new -1 3 12 12"><title>rte-bold</title><desc>Created with Sketch.</desc><path d="M9.7 9.8c-.3-.5-.4-.6-.7-.8-.3-.3-.7-.4-1.1-.6-.4-.1-.8-.2-1.1-.2v-.2l1-.3c.3-.2.6-.3.8-.5.3-.2.5-.5.6-.8.2-.3.2-.6.2-1 0-.8-.3-1.4-.9-1.8-.6-.4-1.6-.6-3-.6h-5.5v.7c.2.1.4.1.5.2.2.1.4.2.4.3.1.1.1.3.1.5v7.7c0 .2 0 .4-.1.5-.1.1-.2.2-.4.3-.1.1-.2.1-.4.1h-.1v.7h5.3c.7 0 1.4 0 2-.1.5-.1 1-.3 1.4-.6.4-.2.8-.5 1-.9.2-.3.3-.8.3-1.4 0-.4 0-.7-.3-1.2zm-6.2-6.1h1.3c.6 0 1.1.2 1.4.5.3.4.5.8.5 1.4 0 .7-.2 1.2-.6 1.6-.4.4-.9.6-1.7.6h-.9v-4.1zm3.1 9c-.3.4-.8.6-1.4.6-.3 0-1-.1-1.3-.2-.2-.1-.3-.3-.4-.5v-4h.7c.8 0 1.9.2 2.3.6.5.4.7 1 .7 1.7 0 .8-.2 1.4-.6 1.8z"/></svg></symbol><symbol id="rte-italic"><svg xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" xmlns="http://www.w3.org/2000/svg" viewBox="-1 3 12 12" enable-background="new -1 3 12 12"><title>rte-italic</title><desc>Created with Sketch.</desc><path sketch:type="MSShapeGroup" d="M9 3l-.3 1c-.1 0-.4 0-.6.1-.3 0-.5.1-.6.1-.3.1-.5.2-.6.3l-.2.5-1.7 7v.2c0 .1 0 .2.1.3.1.1.2.2.3.2.1 0 .3.1.5.1.3.2.5.2.6.2l-.2 1h-5.3l.2-1h.7s.5-.1.6-.1c.2-.1.4-.2.5-.3.1-.1.2-.3.2-.5l1.8-7v-.30000000000000004c0-.1 0-.2-.1-.3 0-.1-.1-.1-.3-.2-.1-.1-.3-.1-.6-.2-.2 0-.4-.1-.5-.1l.2-1h5.3z"/></svg></symbol><symbol id="rte-list"><svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="12" height="12" viewBox="0 0 12 12"><title>rte-list</title><desc>Created with Sketch.</desc><g sketch:type="MSArtboardGroup" fill="#000"><rect sketch:type="MSShapeGroup" width="9" height="2" rx="1" transform="translate(3 5)"/><rect sketch:type="MSShapeGroup" x="3" y="1" width="9" height="2" rx="1"/><rect sketch:type="MSShapeGroup" x="3" y="9" width="9" height="2" rx="1"/><circle sketch:type="MSShapeGroup" cx="1" cy="2" r="1"/><circle sketch:type="MSShapeGroup" cx="1" cy="6" r="1"/><circle sketch:type="MSShapeGroup" cx="1" cy="10" r="1"/></g></svg></symbol><symbol id="rte-list-ordered"><svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="12" height="12" viewBox="0 0 12 12"><title>rte-list-ordered</title><desc>Created with Sketch.</desc><g sketch:type="MSArtboardGroup" fill="#000"><rect sketch:type="MSShapeGroup" width="9" height="2" rx="1" transform="translate(3 5)"/><path d="M0 2.479h.697v-1.943l-.648.152v-.533l.653-.148h.602v2.472h.697v.521h-2v-.521z" sketch:type="MSShapeGroup"/><rect sketch:type="MSShapeGroup" x="3" y="1" width="9" height="2" rx="1"/><path d="M.685 6.481h1.35v.512h-2.035v-.496l.343-.335.743-.734c.107-.113.185-.213.232-.3.047-.087.071-.174.071-.259 0-.131-.043-.233-.13-.304-.087-.072-.209-.107-.368-.107-.113 0-.24.021-.381.062-.141.041-.288.101-.441.18v-.541c.153-.051.303-.09.45-.117.147-.027.287-.04.422-.04.339 0 .606.073.8.218.194.145.291.343.291.594 0 .116-.021.224-.063.325-.042.101-.115.213-.218.337-.076.089-.284.29-.625.603l-.44.406z" sketch:type="MSShapeGroup"/><rect sketch:type="MSShapeGroup" x="3" y="9" width="9" height="2" rx="1"/><path d="M.88 9.646h-.328v-.502h.328c.152 0 .27-.028.354-.084.084-.056.126-.135.126-.237 0-.107-.042-.19-.126-.25-.084-.06-.202-.09-.354-.09-.116 0-.241.014-.374.041-.133.027-.271.066-.413.118v-.518c.143-.04.283-.071.421-.092.138-.021.271-.032.399-.032.327 0 .581.066.764.199.183.133.274.316.274.549 0 .171-.053.311-.158.42-.105.109-.255.18-.45.214.221.036.39.118.506.246.116.128.174.297.174.505 0 .28-.096.493-.289.64-.192.147-.472.22-.839.22-.156 0-.31-.012-.462-.037-.152-.024-.296-.06-.435-.106v-.529c.13.061.271.107.421.138.151.032.309.047.475.047.166 0 .298-.036.394-.107.097-.071.145-.168.145-.289 0-.148-.048-.262-.145-.343-.097-.081-.234-.121-.411-.121z" sketch:type="MSShapeGroup"/></g></svg></symbol><symbol id="rte-outdent"><svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="12" height="12" viewBox="0 0 12 12"><title>rte-outdent</title><desc>Created with Sketch.</desc><g sketch:type="MSArtboardGroup" fill="#000"><g sketch:type="MSLayerGroup"><rect sketch:type="MSShapeGroup" width="12" height="2" rx="1"/><path d="M6 4c0-.552.439-1 .996-1h4.538-.542c.557 0 1.008.444 1.008 1 0 .552-.451 1-.991 1h-4.018c-.547 0-.991-.444-.991-1z" sketch:type="MSShapeGroup"/><rect sketch:type="MSShapeGroup" x="6" y="6" width="6" height="2" rx="1"/><rect sketch:type="MSShapeGroup" y="9" width="12" height="2" rx="1"/></g><path sketch:type="MSShapeGroup" d="M0 5.48l4-2.48v5z"/></g></svg></symbol><symbol id="rte-indent"><svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="12" height="12" viewBox="0 0 12 12"><title>rte-indent</title><desc>Created with Sketch.</desc><g sketch:type="MSArtboardGroup" fill="#000"><g sketch:type="MSLayerGroup"><rect sketch:type="MSShapeGroup" width="12" height="2" rx="1"/><path d="M6 4c0-.552.439-1 .996-1h4.538-.542c.557 0 1.008.444 1.008 1 0 .552-.451 1-.991 1h-4.018c-.547 0-.991-.444-.991-1z" sketch:type="MSShapeGroup"/><rect sketch:type="MSShapeGroup" x="6" y="6" width="6" height="2" rx="1"/><rect sketch:type="MSShapeGroup" y="9" width="12" height="2" rx="1"/></g><path sketch:type="MSShapeGroup" d="M4 5.48l-4-2.48v5z"/></g></svg></symbol><symbol id="rte-justify"><svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="12" height="12" viewBox="0 0 12 12"><title>rte-justify</title><desc>Created with Sketch.</desc><g sketch:type="MSLayerGroup" transform="translate(-1)" fill="#000"><rect sketch:type="MSShapeGroup" x=".994" width="6.003" height="2" rx="1"/><path d="M.994 4c0-.552.454-1 1.009-1h7.992c.554 0 1.004.444 1.004 1 0 .552-.456 1-.996 1h-8.013c-.55 0-.996-.444-.996-1z" sketch:type="MSShapeGroup"/><rect sketch:type="MSShapeGroup" x=".994" y="6" width="8.006" height="2" rx="1"/><rect sketch:type="MSShapeGroup" x=".994" y="9" width="12.006" height="2" rx="1"/></g></svg></symbol><symbol id="rte-color"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 3 12 12" enable-background="new -1 3 12 12"><title>rte-color</title><desc>Created with Sketch.</desc><path d="M8.9 10.3c-.1 0-.2 0-.3-.1l-.3-.1-.3-.1-.1-.3-2.5-6.7h-.7v.2c-.4.9-.8 1.9-1.2 3.1-.5 1.2-.9 2.2-1.3 3.2 0 .2-.1.3-.2.4 0 .1-.1.2-.3.3l-.3.1-.3.1h-.1v.6h3.1v-.7h-.1c-.3 0-.5-.1-.7-.1-.2-.1-.3-.1-.3-.2v-.2c0-.1 0-.2.1-.4 0-.2.1-.3.2-.5.1-.1.3-.7.3-.9h2.2l.7 2v.2s-.1 0-.2.1c-.2 0-.4.1-.7.1h-.1v.6h3.5v-.7h-.1zm-3.4-3h-1.6l.8-2.1.8 2.1zM8 12h-6c-.6 0-1 .4-1 1 0 .5.4 1 1 1h6c.6 0 1-.4 1-1 0-.5-.4-1-1-1z"/></svg></symbol><symbol id="rte-link"><svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="12" height="12" viewBox="0 0 12 12"><title>rte-link</title><desc>Created with Sketch.</desc><path d="M7.606 4.394c1.044 1.066 1.057 2.798 0 3.855l-.643.643-.643.643-.643.643c-1.062 1.062-2.791 1.064-3.855 0-1.068-1.068-1.066-2.789 0-3.855l.871-.871c-.045.714.121 1.439.496 2.075l-.081.081c-.357.357-.358.927 0 1.285.354.354.932.353 1.285 0l.643-.643.643-.643.643-.643c.354-.354.354-.931 0-1.285l.643-.643.643-.643zm-3.213 3.213c-1.044-1.066-1.057-2.798 0-3.855l.643-.643.643-.643.643-.643c1.062-1.062 2.791-1.064 3.855 0 1.068 1.068 1.066 2.789 0 3.855l-.871.871c.045-.714-.121-1.439-.496-2.075l.081-.081c.357-.357.358-.927 0-1.285-.354-.354-.932-.353-1.285 0l-.643.643-.643.643-.643.643c-.354.354-.354.931 0 1.285l-.643.643-.643.643z" sketch:type="MSShapeGroup" fill="#000"/></svg></symbol><symbol id="rte-table"><svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="12" height="12" viewBox="0 0 12 12"><title>rte-table</title><desc>Created with Sketch.</desc><g sketch:type="MSArtboardGroup" fill="#000"><rect sketch:type="MSShapeGroup" width="12" height="2" rx="1"/><path d="M12 10c0 .552-.456 1-1.002 1h-9.995c-.554 0-1.002-.444-1.002-1h12z" sketch:type="MSShapeGroup"/><path d="M12 1.002v8.995c0 .554-.444 1.002-1 1.002v-11c.552 0 1 .456 1 1.002z" sketch:type="MSShapeGroup"/><path d="M0 1.002v8.995c0 .554.444 1.002 1 1.002v-11c-.552 0-1 .456-1 1.002z" sketch:type="MSShapeGroup"/><path d="M10.5 5h.5v-1h-10v1h9.5z" id="Line" sketch:type="MSShapeGroup"/><path d="M10.5 8h.5v-1h-10v1h9.5z" sketch:type="MSShapeGroup"/><path d="M4 9.5v.5h1v-8h-1v7.5zM7 9.5v.5h1v-8h-1v7.5z" sketch:type="MSShapeGroup"/></g></svg></symbol><symbol id="rte-image"><svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="12" height="12" viewBox="0 0 12 12"><title>rte-image</title><desc>Created with Sketch.</desc><g sketch:type="MSArtboardGroup" fill="#000"><path d="M12 10c0 .552-.456 1-1.002 1h-9.995c-.554 0-1.002-.444-1.002-1h12z" sketch:type="MSShapeGroup"/><path d="M12 1c0-.552-.456-1-1.002-1h-9.995c-.554 0-1.002.444-1.002 1h12z" sketch:type="MSShapeGroup"/><path d="M12 1.002v8.995c0 .554-.444 1.002-1 1.002v-11c.552 0 1 .456 1 1.002z" sketch:type="MSShapeGroup"/><path d="M0 1.002v8.995c0 .554.444 1.002 1 1.002v-11c-.552 0-1 .456-1 1.002z" sketch:type="MSShapeGroup"/><circle sketch:type="MSShapeGroup" cx="3.5" cy="3.5" r="1.5"/><path d="M5.463 7.951l-1.463-1.951-3 4h10v-4.2l-2-2.8-3.537 4.951z" sketch:type="MSShapeGroup"/></g></svg></symbol><symbol id="rte-camera"><svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="12" height="12" viewBox="0 0 12 12"><title>rte-camera</title><desc>Created with Sketch.</desc><g sketch:type="MSArtboardGroup" fill="#000"><rect sketch:type="MSShapeGroup" y="2" width="9" height="8" rx="1"/><path d="M12 3v6l-5-3 5-3z" sketch:type="MSShapeGroup"/></g></svg></symbol><symbol id="rte-clear"><svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="12" height="12" viewBox="0 0 12 12"><title>rte-clear</title><desc>Created with Sketch.</desc><g sketch:type="MSArtboardGroup" fill="#000"><path d="M8.293 9.707l.707.707 1.414-1.414-.707-.707-6-6-.707-.707-1.414 1.414.707.707 6 6z" sketch:type="MSShapeGroup"/><path d="M12 6c0-3.314-2.686-6-6-6s-6 2.686-6 6 2.686 6 6 6 6-2.686 6-6zm-10 0c0-2.209 1.791-4 4-4s4 1.791 4 4-1.791 4-4 4-4-1.791-4-4z" sketch:type="MSShapeGroup"/></g></svg></symbol><symbol id="next-remove"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" enable-background="new 0 0 24 24"><path d="M19.5 22c-.2 0-.5-.1-.7-.3L12 14.9l-6.8 6.8c-.2.2-.4.3-.7.3-.2 0-.5-.1-.7-.3l-1.6-1.6c-.1-.2-.2-.4-.2-.6 0-.2.1-.5.3-.7L9.1 12 2.3 5.2C2.1 5 2 4.8 2 4.5c0-.2.1-.5.3-.7l1.6-1.6c.2-.1.4-.2.6-.2.3 0 .5.1.7.3L12 9.1l6.8-6.8c.2-.2.4-.3.7-.3.2 0 .5.1.7.3l1.6 1.6c.1.2.2.4.2.6 0 .2-.1.5-.3.7L14.9 12l6.8 6.8c.2.2.3.4.3.7 0 .2-.1.5-.3.7l-1.6 1.6c-.2.1-.4.2-.6.2z"/></svg></symbol><symbol id="next-photos-80"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><path d="M80 57.6l-4-18.7v-23.9c0-1.1-.9-2-2-2h-3.5l-1.1-5.4c-.3-1.1-1.4-1.8-2.4-1.6l-32.6 7h-27.4c-1.1 0-2 .9-2 2v4.3l-3.4.7c-1.1.2-1.8 1.3-1.5 2.4l5 23.4v20.2c0 1.1.9 2 2 2h2.7l.9 4.4c.2.9 1 1.6 2 1.6h.4l27.9-6h33c1.1 0 2-.9 2-2v-5.5l2.4-.5c1.1-.2 1.8-1.3 1.6-2.4zm-75-21.5l-3-14.1 3-.6v14.7zm62.4-28.1l1.1 5h-24.5l23.4-5zm-54.8 64l-.8-4h19.6l-18.8 4zm37.7-6h-43.3v-51h67v51h-23.7zm25.7-7.5v-9.9l2 9.4-2 .5zm-52-21.5c-2.8 0-5-2.2-5-5s2.2-5 5-5 5 2.2 5 5-2.2 5-5 5zm0-8c-1.7 0-3 1.3-3 3s1.3 3 3 3 3-1.3 3-3-1.3-3-3-3zm-13-10v43h59v-43h-59zm57 2v24.1l-12.8-12.8c-3-3-7.9-3-11 0l-13.3 13.2-.1-.1c-1.1-1.1-2.5-1.7-4.1-1.7-1.5 0-3 .6-4.1 1.7l-9.6 9.8v-34.2h55zm-55 39v-2l11.1-11.2c1.4-1.4 3.9-1.4 5.3 0l9.7 9.7c-5.2 1.3-9 2.4-9.4 2.5l-3.7 1h-13zm55 0h-34.2c7.1-2 23.2-5.9 33-5.9l1.2-.1v6zm-1.3-7.9c-7.2 0-17.4 2-25.3 3.9l-9.1-9.1 13.3-13.3c2.2-2.2 5.9-2.2 8.1 0l14.3 14.3v4.1l-1.3.1z"/></svg></symbol><symbol id="next-checkmark"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" enable-background="new 0 0 24 24"><path d="M23.6 5L22 3.4c-.5-.4-1.2-.4-1.7 0L8.5 15l-4.8-4.7c-.5-.4-1.2-.4-1.7 0L.3 11.9c-.5.4-.5 1.2 0 1.6l7.3 7.1c.5.4 1.2.4 1.7 0l14.3-14c.5-.4.5-1.1 0-1.6z"/></svg></symbol><symbol id="next-chevron-down"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" enable-background="new 0 0 24 24"><path d="M21 5.176l-9.086 9.353-8.914-9.353-2.314 2.471 11.314 11.735 11.314-11.735-2.314-2.471z"/></svg></symbol><symbol id="next-calendar"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" enable-background="new 0 0 24 24"><path d="M21 3h-1V2c0-1.1-.9-2-2-2s-2 .9-2 2v1H8V2c0-1.1-.9-2-2-2S4 .9 4 2v1H3C1.3 3 0 4.3 0 6v15c0 1.7 1.3 3 3 3h18c1.7 0 3-1.3 3-3V6c0-1.7-1.3-3-3-3zM3 21V10h18v11H3z"/></svg></symbol><symbol id="next-arrow-double-16"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M11.5 6.5l-3.5-3.4-3.5 3.4-1-1 4.5-4.6 4.5 4.5-1 1.1zm1 4l-1.1-1.1-3.4 3.5-3.5-3.4-1.1 1.1 4.6 4.5 4.5-4.6z"/></svg></symbol><symbol id="next-add-circle"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12"><path d="M6 0c-3.3 0-6 2.7-6 6s2.7 6 6 6 6-2.7 6-6-2.7-6-6-6zm3 7h-2v2c0 .5-.5 1-1 1s-1-.5-1-1v-2h-2c-.5 0-1-.5-1-1s.5-1 1-1h2v-2c0-.5.5-1 1-1s1 .5 1 1v2h2c.5 0 1 .5 1 1s-.5 1-1 1z"/></svg></symbol><symbol id="next-website"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M9.4 2c-.2 0-.3.3-.2.4l1.4 1.4-3.8 3.9c-.2.2-.2.6 0 .8l.8.8c.2.2.6.2.8 0l3.8-3.8 1.4 1.4c.2.2.4 0 .4-.2v-4.2c0-.3-.2-.5-.5-.5h-4.1zm.6 0h-6c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2v-6 2h-2v3c0 .6-.5 1-1 1h-6c-.6 0-1-.5-1-1v-6c0-.6.5-1 1-1h3v-2h2z"/></svg></symbol><symbol id="next-search-16"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><path d="M0 5.667c0 3.125 2.542 5.667 5.667 5.667 1.202 0 2.315-.38 3.233-1.02l.455.456c-.07.5.082 1.025.466 1.41l3.334 3.332c.326.325.753.488 1.18.488.425 0 .852-.163 1.177-.488.652-.65.652-1.706 0-2.357L12.18 9.822c-.384-.384-.91-.536-1.41-.466l-.454-.456c.64-.918 1.02-2.03 1.02-3.233C11.333 2.542 8.79 0 5.666 0S0 2.542 0 5.667zm2 0C2 3.645 3.645 2 5.667 2s3.667 1.645 3.667 3.667-1.646 3.666-3.667 3.666S2 7.688 2 5.667z"/></svg></symbol><symbol id="next-info"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" enable-background="new 0 0 24 24"><g><path d="M13.5 7h-2c-.8 0-1.5.7-1.5 1.5v14c0 .8.7 1.5 1.5 1.5h2c.8 0 1.5-.7 1.5-1.5v-14c0-.8-.7-1.5-1.5-1.5z"/><circle cx="12.5" cy="2.5" r="2.5"/></g></svg></symbol><symbol id="next-dashboard-16"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><g><path d="M8.43 3.445c-.248-.21-.612-.21-.86 0L2.353 7.86C2.13 8.05 2 8.33 2 8.624v6.71c0 .366.3.666.667.666h2.667C5.7 16 6 15.7 6 15.333v-3c0-.183.15-.333.333-.333h3.333c.184 0 .334.15.334.333v3c0 .367.3.667.667.667h2.667c.366 0 .666-.3.666-.667v-6.71c0-.294-.13-.573-.354-.763L8.43 3.445zM15.764 6.158L8.944.39C8.692.14 8.357 0 8 0c-.357 0-.692.14-.902.354L.236 6.158c-.28.238-.316.66-.078.94.132.156.32.236.51.236.15 0 .304-.052.43-.158L7.6 1.638c.238-.178.56-.18.797-.003 1.468 1.1 6.505 5.54 6.505 5.54.28.237.702.203.94-.078.238-.28.203-.7-.078-.94z"/></g></svg></symbol><symbol id="next-orders-16"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><g><path d="M13.992 0H2.1C.94 0 0 .94 0 2.1v12.244C0 15.305.785 16 1.75 16H14.34c.964 0 1.658-.694 1.658-1.658V2.1C16 .94 15.15 0 13.992 0zM14 2v8h-1.757C11.28 10 10 11.28 10 12.243v.7c0 .193.337.057.144.057H5.247c-.193 0-.247.136-.247-.057v-.7C5 11.28 4.113 10 3.148 10H2V2h12zM7.117 9.963c.167.16.437.16.603.002l5.17-5.042c.165-.16.165-.422 0-.583l-.604-.583c-.166-.16-.437-.16-.603 0L7.42 7.924 5.694 6.24c-.166-.16-.437-.16-.603 0l-.604.582c-.166.162-.166.423 0 .584l2.63 2.557z"/></g></svg></symbol><symbol id="next-chevron"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10.6,6 L8.2,8 L12,12 L8.2,16 L10.6,18 L15.3,13 C15.8,12.4 15.8,11.6 15.3,11 L10.6,6 L10.6,6 Z"/></svg></symbol><symbol id="next-products-16"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><path d="M15.087 0H10.01c-.554 0-1.085.235-1.476.627L.3 8.87c-.37.368-.37.965 0 1.327l5.553 5.556c.362.368.955.37 1.323 0L15.4 7.52c.39-.392.6-.922.6-1.476V.967C16 .45 15.604 0 15.087 0zm-2.89 5.56c-.94 0-1.702-.764-1.702-1.703 0-.94.763-1.702 1.702-1.702.94 0 1.702.763 1.702 1.702 0 .94-.764 1.702-1.703 1.702z"/></svg></symbol><symbol id="next-customers-16"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><g><path d="M13.08 8.26c-.68-.275-.674-.732-.674-1.007 0-.274.29-.657.566-.903.48-.423.777-1.04.777-1.737 0-1.206-1.018-2.21-2.224-2.257-.896-.03-1.658.41-2.062 1.1-.088.15-.03.337.127.415 1.12.555 1.873 1.69 1.873 3.03 0 .87-.32 1.698-.894 2.332-.128.14-.077.362.094.442.663.31 2.044.745 2.598 1.462.055.07.134-.136.224-.136h1.657c.473 0 .857.116.857-.358v-.12c0-1.308-1.93-1.85-2.92-2.263zM5.398 9.232c-.542-.603-.827-1.39-.827-2.304 0-1.348.74-2.53 1.863-3.08.16-.077.22-.267.128-.418-.5-.816-1.523-1.265-2.634-.993-1.006.24-1.64 1.17-1.64 2.21 0 .698.223 1.28.71 1.704.273.247.6.63.6.904s-.035.73-.715 1.006C1.89 8.67 0 9.214 0 10.522v.12c0 .474.384.358.857.358h1.656c.09 0 .17.206.226.133.544-.716 1.905-1.277 2.56-1.59.167-.078.222-.173.098-.31zM9.867 10.546c-.68-.278-.78-.735-.78-1.006 0-.274.234-.656.508-.9.483-.426.754-1.046.754-1.74 0-1.492-1.39-2.55-2.957-2.184-1.018.237-1.672 1.168-1.672 2.212 0 .695.223 1.286.706 1.71.274.246.596.628.596.902 0 .27-.248.728-.927 1.006C5.11 10.954 3 11.5 3 12.806v.122C3 13.4 3.812 14 4.286 14h7.43c.472 0 1.284-.6 1.284-1.072v-.122c0-1.307-2.147-1.852-3.133-2.26z"/></g></svg></symbol><symbol id="next-reports-16"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><g><path d="M4 9.667C4 9.297 3.702 9 3.333 9H1.667C1.297 9 1 9.298 1 9.667v5.667c0 .368.298.666.667.666h1.667c.368 0 .666-.298.666-.667V9.667zM8 3.667C8 3.297 7.702 3 7.333 3H5.667C5.297 3 5 3.298 5 3.667v11.667c0 .368.298.666.667.666h1.667c.368 0 .666-.298.666-.667V3.667zM12 .667c0-.37-.298-.667-.667-.667H9.667C9.297 0 9 .298 9 .667v14.667c0 .368.298.666.667.666h1.667c.368 0 .666-.298.666-.667V.667zM16 6.667c0-.37-.298-.667-.667-.667h-1.667c-.368 0-.666.298-.666.667v8.667c0 .368.298.666.667.666h1.667c.368 0 .666-.298.666-.667V6.667z"/></g></svg></symbol><symbol id="next-discounts-16"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><g><path d="M9 13.333C9 13.15 8.85 13 8.667 13H6.333c-.184 0-.333.15-.333.333v.333c0 .185.15.334.333.334h2.333c.185 0 .334-.15.334-.333v-.334zM13 13.333c0-.184-.15-.333-.333-.333h-2.333c-.185 0-.334.15-.334.333v.333c0 .185.15.334.333.334h2.333c.185 0 .334-.15.334-.333v-.334zM16 8.333C16 8.15 15.85 8 15.667 8h-.333c-.185 0-.334.15-.334.333v2.333c0 .185.15.334.333.334h.333c.185 0 .334-.15.334-.333V8.333zM11.3 9.2L7.272 5.902 11.3 2.607l-.013-.016c-.692-.845-1.94-.97-2.786-.278l-2.808 2.3-1.18-.966c.096-.254.155-.526.155-.813C4.667 1.547 3.62.5 2.333.5S0 1.547 0 2.833s1.047 2.333 2.333 2.333c.255 0 .495-.05.725-.127l1.055.862-.93.763c-.265-.103-.55-.165-.85-.165C1.047 6.5 0 7.547 0 8.833s1.047 2.333 2.333 2.333 2.333-1.047 2.333-2.333c0-.246-.05-.478-.12-.7l1.145-.938L8.5 9.493c.846.692 2.094.568 2.786-.28L11.3 9.2zM1.333 2.832c0-.55.45-1 1-1s1 .45 1 1-.45 1-1 1-1-.448-1-1zm1 7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1c0 .552-.448 1-1 1zM13 5.333C13 5.15 12.85 5 12.667 5h-2.333c-.185 0-.334.15-.334.333v.333c0 .185.15.334.333.334h2.333c.185 0 .334-.15.334-.333v-.334zM15.5 5h-1c-.276 0-.5 0-.5.5s.224.5.5.5h.5v.48c0 .275 0 .5.5.5s.5-.225.5-.5V5.5c0-.276-.063-.5-.5-.5zM3.5 14h1c.276 0 .5 0 .5-.5s-.224-.5-.5-.5H4v-.5c0-.276 0-.5-.5-.5s-.5.224-.5.5v.98c0 .275.062.52.5.52zM16 13.49v-1c0-.276 0-.5-.5-.5s-.5.224-.5.5V13h-.49c-.276 0-.5 0-.5.5s.224.5.5.5h.98c.276 0 .51-.073.51-.51z"/></g></svg></symbol><symbol id="next-online-store-16"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 14.1c-3.4 0-6.1-2.7-6.1-6.1 0-.9.2-1.8.6-2.6v.3c0 .2.3.5.3.7 0 .3.2.5.4.7.3.1.6.2.8.4.2.2.4.3.7.2.2.2.1.4 0 .6-.2.2-.3.4-.3.5-.1.3-.1.6.2.8.2.1.3.3.3.5s.2.4.3.5c.4.2.4.6.5 1 .1.8.7 2 .9 1.6.2-.3.6-.9.8-1.1.1-.1.2-.2.2-.3.1-.2.2-.4.4-.5.1-.1.2-.2.2-.3 0-.4.2-.8.4-1.1.4-.5.2-.8-.4-1-.3-.1-.7-.3-1.1-.1v-.2c.1-.5 0-.6-.5-.8-.2-.2-.4-.3-.6-.4-.2-.1-.5 0-.8-.1-.3.1-.2-.4-.5-.5-.6-.6.3-.8.7-.6.1.1.5-.5 1.3-1 .2 0 .1-1 .3-1-1.7-1-2-1.4-2-1.4h-.2c.9-.6 2-.9 3.2-.9h.6l-.1.1s-.5.3.1 1c.2.2.7.8.6.9 0 .2 1.4-.1 1.6-.1.4 0 .3.6 0 .7 0 .1-1.8.3-1.9.3-.3.4-.3.3-.2.7 0 .2-.1.3-.1.6.2.2.4.5.6.8.3.3.5.8.8.7.1 0 .2-.1.4-.2.1.1.3.4.5.5-.1.3 0 .5.2.8.1.1 0 .8-.1.9-.1.2 0 .6.2 1s.7.4.9 0l.7-1.9c.2-.4.5-.7.9-.9l.3-.1V8c.1 3.4-2.6 6.1-6 6.1z"/></svg></symbol><symbol id="next-apps-16"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><path d="M12.383 9.734c.59.41.882 1.044.87 1.675-.004.29.357.43.563.226l1.894-1.894c.387-.387.387-1.015 0-1.402l-2.498-2.498c-.167-.167-.115-.463.11-.54.397-.133.76-.396 1.02-.798.432-.662.416-1.56-.04-2.204-.734-1.033-2.175-1.123-3.03-.268-.216.216-.37.47-.463.74-.08.23-.387.28-.56.108L7.767.397C7.38.01 6.75.01 6.364.397L4.472 2.29c-.215.214-.05.565.257.565.504 0 1.013.192 1.4.58.87.87.765 2.34-.316 3.06-.663.443-1.568.435-2.216-.028-.576-.412-.86-1.04-.855-1.664.01-.29-.355-.43-.56-.224L.29 6.47c-.387.388-.387 1.016 0 1.403l2.498 2.498c.167.168.115.464-.11.54-.397.134-.76.397-1.02.8-.432.66-.416 1.56.04 2.203.734 1.033 2.175 1.123 3.03.268.216-.215.37-.47.463-.74.08-.23.387-.28.56-.107l2.483 2.484c.387.387 1.015.387 1.402 0l1.892-1.892c.215-.215.05-.564-.254-.563-.508 0-1.016-.193-1.404-.582-.86-.86-.768-2.304.278-3.037.658-.462 1.574-.466 2.235-.01z"/></svg></symbol><symbol id="next-settings-16"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><path d="M15.733 6.767l-1.77-.36c-.117-.025-.21-.112-.245-.227-.102-.323-.232-.636-.39-.935-.056-.107-.053-.234.013-.335l1-1.51c.086-.13.07-.304-.042-.415L13.02 1.707c-.114-.114-.292-.132-.426-.043l-1.504.995c-.1.066-.228.07-.335.013-.3-.158-.61-.288-.935-.39-.114-.037-.202-.13-.226-.247l-.36-1.77C9.2.113 9.063 0 8.906 0H7.093c-.158 0-.295.11-.326.267l-.36 1.77c-.025.117-.113.21-.227.245-.323.102-.636.232-.935.39-.107.056-.234.053-.335-.013l-1.504-.996c-.134-.09-.312-.07-.426.043L1.702 2.985c-.11.11-.128.284-.042.415l1 1.51c.066.1.07.228.012.335-.158.3-.288.612-.39.935-.036.114-.128.202-.246.226l-1.77.36C.113 6.8 0 6.937 0 7.094v1.813c0 .158.11.295.267.327l1.77.36c.117.025.21.112.245.227.102.323.232.636.39.935.056.107.053.234-.013.335l-.996 1.504c-.09.134-.07.312.043.426l1.273 1.273c.114.114.292.132.426.043l1.504-.995c.1-.066.228-.07.335-.012.3.158.61.288.935.39.115.036.202.128.226.246l.36 1.77c.032.155.17.266.327.266h1.813c.158 0 .295-.11.327-.267l.36-1.77c.025-.117.112-.21.227-.245.323-.102.636-.232.935-.39.107-.056.234-.053.335.013l1.504.996c.134.09.312.07.426-.043l1.273-1.273c.114-.114.132-.292.043-.426l-.995-1.504c-.066-.1-.07-.228-.012-.335.158-.3.288-.61.39-.935.036-.115.128-.202.246-.226l1.77-.36c.155-.032.266-.17.266-.327V7.093c0-.158-.112-.295-.267-.326zM10.667 8c0 1.473-1.193 2.667-2.667 2.667S5.333 9.473 5.333 8c0-1.473 1.193-2.667 2.667-2.667S10.667 6.527 10.667 8z"/></svg></symbol><symbol id="next-menu-16"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><path d="M7 9H1c-.552 0-1-.114-1-.667v-.666C0 7.114.448 7 1 7h14c.552 0 1 .114 1 .667v.667c0 .552-.448.666-1 .666H7zM7 4H1c-.552 0-1-.114-1-.667v-.666C0 2.114.448 2 1 2h14c.552 0 1 .114 1 .667v.667c0 .552-.448.666-1 .666H7zM7 14H1c-.552 0-1-.114-1-.667v-.667C0 12.114.448 12 1 12h14c.552 0 1 .114 1 .667v.667c0 .552-.448.666-1 .666H7z"/></svg></symbol></svg>
3
+ </div>
@@ -0,0 +1,17 @@
1
+ <section class="section">
2
+ <div class="layout-content">
3
+
4
+ <aside class="layout-content__sidebar layout-content__first">
5
+ <% if content_for?(:section_summary) %>
6
+ <div class="section-summary">
7
+ <%= content_for :section_summary %>
8
+ </div>
9
+ <% end %>
10
+ </aside>
11
+
12
+ <section class="layout-content__main">
13
+ <%= content_for :section_content %>
14
+ </section>
15
+
16
+ </div>
17
+ </section>
@@ -0,0 +1,25 @@
1
+ <% if @shop.current_subscription? %>
2
+ <p>
3
+ You are currently on the <%= @shop.current_subscription.plan.name %> plan.
4
+ </p>
5
+ <p>
6
+ Choose a new plan:
7
+ </p>
8
+ <% else %>
9
+ <p>
10
+ Welcome!
11
+ </p>
12
+ <p>
13
+ Choose a plan below to get started:
14
+ </p>
15
+ <% end %>
16
+
17
+ <% for plan in DiscoApp::Plan.available %>
18
+
19
+ <h2><%= plan.name %></h2>
20
+ <%= form_for(@subscription) do |f| %>
21
+ <%= f.hidden_field :plan, value: plan.id %>
22
+ <%= f.submit %>
23
+ <% end %>
24
+
25
+ <% end %>
@@ -0,0 +1,20 @@
1
+ <li class="next-nav__item">
2
+ <a href="<%= admin_shops_path %>" class="next-nav__link <%= active_link_to_class(admin_shops_path, class_active: 'next-nav__link--is-selected', active: :inclusive) %>">
3
+ <svg class="next-icon next-icon--size-16 next-icon--no-nudge" role="img" aria-labelledby="next-dashboard-16-17dbedf316126bf9bd81f6c6b7626199-title"><title id="next-dashboard-16-17dbedf316126bf9bd81f6c6b7626199-title">Home</title><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#next-dashboard-16"></use></svg>
4
+ <span class="next-nav__text">Shops</span>
5
+ </a>
6
+ </li>
7
+
8
+ <li class="next-nav__item">
9
+ <a href="<%= admin_plans_path %>" class="next-nav__link <%= active_link_to_class(admin_plans_path, class_active: 'next-nav__link--is-selected', active: :inclusive) %>">
10
+ <svg class="next-icon next-icon--size-16 next-icon--no-nudge" role="img" aria-labelledby="next-dashboard-16-17dbedf316126bf9bd81f6c6b7626199-title"><title id="next-dashboard-16-17dbedf316126bf9bd81f6c6b7626199-title">Home</title><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#next-dashboard-16"></use></svg>
11
+ <span class="next-nav__text">Plans</span>
12
+ </a>
13
+ </li>
14
+
15
+ <li class="next-nav__item">
16
+ <a href="<%= edit_admin_app_settings_path %>" class="next-nav__link <%= active_link_to_class(edit_admin_app_settings_path, class_active: 'next-nav__link--is-selected', active: :inclusive) %>">
17
+ <svg class="next-icon next-icon--size-16 next-icon--no-nudge" role="img" aria-labelledby="next-dashboard-16-17dbedf316126bf9bd81f6c6b7626199-title"><title id="next-dashboard-16-17dbedf316126bf9bd81f6c6b7626199-title">Home</title><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#next-dashboard-16"></use></svg>
18
+ <span class="next-nav__text">Settings</span>
19
+ </a>
20
+ </li>