beyond_canvas 0.16.2.pre → 0.17.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/beyond_canvas_manifest.js +1 -0
  3. data/app/assets/images/icons/arrow_right.svg +1 -0
  4. data/app/assets/images/icons/close.svg +1 -0
  5. data/app/assets/images/icons/home.svg +1 -0
  6. data/app/assets/javascripts/beyond_canvas/base.js +120 -246
  7. data/app/assets/stylesheets/beyond_canvas/base.scss +8 -1
  8. data/app/assets/stylesheets/beyond_canvas/components/_action_bar.scss +28 -0
  9. data/app/assets/stylesheets/beyond_canvas/components/_breadcrumbs.scss +29 -0
  10. data/app/assets/stylesheets/beyond_canvas/components/_buttons.scss +1 -1
  11. data/app/assets/stylesheets/beyond_canvas/components/_debug.scss +10 -0
  12. data/app/assets/stylesheets/beyond_canvas/components/_forms.scss +11 -14
  13. data/app/assets/stylesheets/beyond_canvas/components/_main.scss +12 -13
  14. data/app/assets/stylesheets/beyond_canvas/components/_margins.scss +8 -0
  15. data/app/assets/stylesheets/beyond_canvas/components/_menu.scss +40 -0
  16. data/app/assets/stylesheets/beyond_canvas/components/_modals.scss +27 -0
  17. data/app/assets/stylesheets/beyond_canvas/components/_sidebar.scss +53 -0
  18. data/app/assets/stylesheets/beyond_canvas/components/_titles.scss +7 -0
  19. data/app/assets/stylesheets/beyond_canvas/settings/_variables.scss +64 -9
  20. data/app/controllers/beyond_canvas/application_controller.rb +2 -0
  21. data/app/controllers/beyond_canvas/authentications_controller.rb +37 -30
  22. data/app/controllers/concerns/beyond_canvas/authentication.rb +1 -12
  23. data/app/controllers/concerns/beyond_canvas/locale_management.rb +5 -4
  24. data/app/helpers/beyond_canvas/authentications_helper.rb +28 -0
  25. data/app/helpers/beyond_canvas/cockpit_app_helper.rb +17 -0
  26. data/app/helpers/beyond_canvas/debug_helper.rb +9 -0
  27. data/app/helpers/beyond_canvas/locale_switch_helper.rb +5 -1
  28. data/app/javascript/beyond_canvas/base.js +3 -0
  29. data/app/javascript/beyond_canvas/initializers/buttons.js +65 -19
  30. data/app/javascript/beyond_canvas/initializers/flash.js +9 -2
  31. data/app/javascript/beyond_canvas/initializers/inputs.js +4 -1
  32. data/app/javascript/beyond_canvas/initializers/modals.js +14 -0
  33. data/app/views/beyond_canvas/authentications/new.html.erb +19 -10
  34. data/app/views/beyond_canvas/shared/_action_bar.html.erb +15 -0
  35. data/app/views/beyond_canvas/shared/_breadcrumbs.html.erb +14 -0
  36. data/app/views/beyond_canvas/shared/_flash.html.erb +22 -12
  37. data/app/views/beyond_canvas/shared/_locales.html.erb +8 -0
  38. data/app/views/beyond_canvas/shared/_menu.html.erb +31 -0
  39. data/app/views/beyond_canvas/shared/_modal.html.erb +6 -0
  40. data/app/views/beyond_canvas/shared/_sidebar.html.erb +16 -0
  41. data/app/views/layouts/beyond_canvas/application.html.erb +31 -0
  42. data/app/views/layouts/beyond_canvas/public.html.erb +11 -4
  43. data/config/locales/en.yml +5 -0
  44. data/config/routes.rb +5 -4
  45. data/lib/beyond_canvas.rb +12 -12
  46. data/lib/beyond_canvas/configuration.rb +11 -6
  47. data/lib/beyond_canvas/engine.rb +4 -2
  48. data/lib/beyond_canvas/menu_item_registration.rb +19 -0
  49. data/lib/beyond_canvas/parameter_sanitizer.rb +1 -1
  50. data/lib/beyond_canvas/rails/routes.rb +8 -7
  51. data/lib/beyond_canvas/version.rb +1 -1
  52. data/lib/generators/beyond_canvas/controller/controller_generator.rb +1 -2
  53. data/lib/generators/beyond_canvas/controller/templates/controller.erb +2 -19
  54. data/lib/generators/beyond_canvas/custom_menu/custom_menu_generator.rb +13 -0
  55. data/lib/generators/beyond_canvas/custom_menu/templates/beyond_canvas_custom_menu.html.erb +32 -0
  56. data/lib/generators/beyond_canvas/custom_styles/custom_styles_generator.rb +1 -1
  57. data/lib/generators/beyond_canvas/custom_styles/templates/beyond_canvas_custom_styles.scss +55 -9
  58. data/lib/generators/beyond_canvas/install/install_generator.rb +3 -5
  59. data/lib/generators/beyond_canvas/install/templates/beyond_canvas.rb.erb +51 -13
  60. data/lib/generators/beyond_canvas/{auth_model/auth_model_generator.rb → model/model_generator.rb} +4 -5
  61. data/lib/generators/beyond_canvas/{auth_model → model}/templates/migration.erb +2 -4
  62. data/lib/generators/beyond_canvas/{auth_model → model}/templates/model.erb +0 -0
  63. data/lib/generators/beyond_canvas/views/views_generator.rb +4 -6
  64. data/lib/models/concerns/authentication.rb +57 -0
  65. data/lib/models/concerns/utils.rb +79 -0
  66. data/lib/models/shop.rb +12 -0
  67. metadata +69 -30
  68. data/app/controllers/concerns/beyond_canvas/resource_management.rb +0 -33
  69. data/app/javascript/beyond_canvas/initializers/functions.js +0 -41
  70. data/app/views/beyond_canvas/locales/_edit.html.erb +0 -8
  71. data/lib/beyond_canvas/models/authentication.rb +0 -66
  72. data/lib/beyond_canvas/models/shop.rb +0 -28
  73. data/lib/beyond_canvas/models/utils.rb +0 -55
@@ -3,22 +3,11 @@
3
3
  module BeyondCanvas
4
4
  module Authentication # :nodoc:
5
5
  extend ActiveSupport::Concern
6
- AUTH_RESOURCE = BeyondCanvas.auth_model
7
-
8
- class_eval <<-METHODS, __FILE__, __LINE__ + 1
9
- def current_#{AUTH_RESOURCE}
10
- instance_variable_get("@#{AUTH_RESOURCE}")
11
- end
12
-
13
- def new_#{AUTH_RESOURCE}_params
14
- beyond_canvas_parameter_sanitizer.sanitize
15
- end
16
- METHODS
17
6
 
18
7
  private
19
8
 
20
9
  def beyond_canvas_parameter_sanitizer
21
- @beyond_canvas_parameter_sanitizer ||= BeyondCanvas::ParameterSanitizer.new(AUTH_RESOURCE, params)
10
+ @beyond_canvas_parameter_sanitizer ||= BeyondCanvas::ParameterSanitizer.new(:shop, params)
22
11
  end
23
12
  end
24
13
  end
@@ -15,16 +15,13 @@ module BeyondCanvas
15
15
  # browser compatible locale, sets the value to the cookie and set that locale as default locale.
16
16
  #
17
17
  def switch_locale(&action)
18
- # NOTE: Check the HTTP_ACCEPT_LANGUAGE header to identify if the request comes from a browser or a server
19
- return I18n.with_locale(I18n.default_locale, &action) if request.headers['HTTP_ACCEPT_LANGUAGE'].blank?
20
-
21
18
  unless valid_locale?(cookies[:locale])
22
19
  cookies[:locale] = { value: browser_compatible_locale, expires: 1.day.from_now }
23
20
  end
24
21
 
25
22
  I18n.with_locale(cookies[:locale], &action)
26
23
 
27
- logger.debug "[BeyondCanvas] Locale set to: #{cookies[:locale]}".yellow
24
+ logger.debug "[BeyondCanvas] Locale set to: #{cookies[:locale]}".yellow if debug_mode?
28
25
  end
29
26
 
30
27
  #
@@ -36,12 +33,16 @@ module BeyondCanvas
36
33
  # +I18n.default_locale+. (e.g. +'en-GB'+)
37
34
  #
38
35
  def browser_compatible_locale
36
+ return I18n.default_locale if request.headers['HTTP_ACCEPT_LANGUAGE'].blank?
37
+
39
38
  browser_locales = HTTP::Accept::Languages.parse(request.headers['HTTP_ACCEPT_LANGUAGE'])
40
39
  available_locales = HTTP::Accept::Languages::Locales.new(I18n.available_locales.map(&:to_s))
41
40
 
42
41
  locales = available_locales & browser_locales
43
42
 
44
43
  locales.empty? ? I18n.default_locale : locales.first
44
+ rescue
45
+ I18n.default_locale
45
46
  end
46
47
 
47
48
  #
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BeyondCanvas
4
+ module AuthenticationsHelper # :nodoc:
5
+ #
6
+ # Logs in the given shop
7
+ #
8
+ def log_in(shop)
9
+ session[:shop_id] = shop.id
10
+ end
11
+
12
+ #
13
+ # Returns the current logged-in shop (if any)
14
+ #
15
+ def current_shop
16
+ if session[:shop_id]
17
+ @current_shop ||= Shop.find_by(id: session[:shop_id])
18
+ end
19
+ end
20
+
21
+ #
22
+ # Returns true if the shop is logged in, false otherwise
23
+ #
24
+ def logged_in?
25
+ !current_shop.nil?
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BeyondCanvas
4
+ module CockpitAppHelper # :nodoc:
5
+ def is_cockpit_app?
6
+ BeyondCanvas.configuration.cockpit_app == true
7
+ end
8
+
9
+ def action_bar_content?
10
+ content_for?(:action_bar_left) || content_for?(:action_bar_right)
11
+ end
12
+
13
+ def menu_content?
14
+ BeyondCanvas.configuration.menu_items.any?
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BeyondCanvas
4
+ module DebugHelper # :nodoc:
5
+ def debug_mode?
6
+ Rails.env.development? && BeyondCanvas.configuration.debug_mode
7
+ end
8
+ end
9
+ end
@@ -2,11 +2,15 @@
2
2
 
3
3
  module BeyondCanvas
4
4
  module LocaleSwitchHelper # :nodoc:
5
+ def show_locale_switch?
6
+ defined?(I18n) && I18n.available_locales.count > 1
7
+ end
8
+
5
9
  def translate_locale(locale)
6
10
  if I18n.exists?("locales.#{locale}")
7
11
  I18n.t("locales.#{locale}")
8
12
  else
9
- logger.debug "[BeyondCanvas] Missing translation: #{I18n.locale}.locales.#{locale}".yellow
13
+ logger.debug "[BeyondCanvas] Missing translation: #{I18n.locale}.locales.#{locale}".yellow if debug_mode?
10
14
  locale
11
15
  end
12
16
  end
@@ -1,3 +1,6 @@
1
+ import 'jquery';
2
+
1
3
  import './initializers/buttons';
2
4
  import './initializers/flash';
3
5
  import './initializers/inputs';
6
+ import './initializers/modals';
@@ -1,8 +1,11 @@
1
- import { disableActionElements, enableActionElements, hideSpinner, showSpinner } from './functions';
1
+ const SPINNER_ANIMATION_TIMEOUT = 125;
2
+ const BUTTON_SELECTORS = '[class^="button"]';
2
3
 
3
4
  (function ($) {
4
- const onDOMReady = function () {
5
- const inputs = $('input, textarea, select').not(':input[type=button], :input[type=submit], :input[type=reset]');
5
+ const onDOMReady = function (e) {
6
+ const inputs = $('input, textarea, select').not(
7
+ ':input[type=button], :input[type=submit], :input[type=reset]'
8
+ );
6
9
 
7
10
  inputs.each(function () {
8
11
  var input = $(this);
@@ -11,12 +14,11 @@ import { disableActionElements, enableActionElements, hideSpinner, showSpinner }
11
14
  if ($(input).is(':hidden')) {
12
15
  e.preventDefault();
13
16
  }
14
- hideSpinner();
15
- enableActionElements();
17
+ $.restoreActionElements();
16
18
  });
17
19
  });
18
20
 
19
- $('button[class^="button"]').each(function () {
21
+ $(BUTTON_SELECTORS).each(function () {
20
22
  var button = $(this);
21
23
 
22
24
  // Add width attribute and save old width
@@ -24,31 +26,75 @@ import { disableActionElements, enableActionElements, hideSpinner, showSpinner }
24
26
  button.data('oldWidth', button.width());
25
27
 
26
28
  // Add the spinner
27
- button.prepend(`
28
- <div class="spinner">
29
- <div class="bounce1"></div>
30
- <div class="bounce2"></div>
31
- <div class="bounce3"></div>
32
- </div>`);
29
+ if (button.find('.spinner').length == 0) {
30
+ button.prepend(`
31
+ <div class="spinner">
32
+ <div class="bounce1"></div>
33
+ <div class="bounce2"></div>
34
+ <div class="bounce3"></div>
35
+ </div>`);
36
+ }
33
37
 
34
38
  // Bind ajax:success and ajax:error to the form the button belongs to
35
39
  button
36
40
  .closest('form')
37
41
  .on('ajax:success', function () {
38
- hideSpinner();
39
- enableActionElements();
42
+ $.restoreActionElements();
40
43
  })
41
44
  .on('ajax:error', function () {
42
- hideSpinner();
43
- enableActionElements();
45
+ $.restoreActionElements();
44
46
  });
45
47
  });
46
48
  };
47
49
 
48
- $(document).on('click', '[class^="button"]', function () {
49
- disableActionElements();
50
- showSpinner($(this));
50
+ $(document).on('confirm:complete', function () {
51
+ $.restoreActionElements();
52
+ });
53
+
54
+ $(document).on('click', BUTTON_SELECTORS, function () {
55
+ $.disableActionElements();
56
+ $(this).showSpinner();
51
57
  });
52
58
 
53
59
  $(document).on('ready page:load turbolinks:load', onDOMReady);
54
60
  })(jQuery);
61
+
62
+ $.extend({
63
+ restoreActionElements: function () {
64
+ // Hide spinners
65
+ $(BUTTON_SELECTORS).each(function (_, button) {
66
+ setTimeout(function () {
67
+ // Hide the spinner
68
+ $(button).find('.spinner').hide();
69
+ // Adjust the width of the button
70
+ $(button).width($(button).data('oldWidth'));
71
+ }, SPINNER_ANIMATION_TIMEOUT);
72
+ });
73
+
74
+ // Enable action elements
75
+ $('a, input[type="submit"], input[type="button"], input[type="reset"], button').each(function () {
76
+ $(this).removeClass('actions--disabled');
77
+ });
78
+ },
79
+ disableActionElements: function () {
80
+ $('a, input[type="submit"], input[type="button"], input[type="reset"], button').each(function () {
81
+ $(this).addClass('actions--disabled');
82
+ });
83
+ }
84
+ });
85
+
86
+ $.fn.extend({
87
+ showSpinner: function () {
88
+ var button = $(this);
89
+
90
+ // Adjust the width of the button
91
+ button.width(
92
+ button.width() + $('.spinner').outerWidth(true)
93
+ );
94
+
95
+ // Show the spinner
96
+ setTimeout(function () {
97
+ button.find('.spinner').css('display', 'inline-flex');
98
+ }, SPINNER_ANIMATION_TIMEOUT);
99
+ }
100
+ });
@@ -1,5 +1,3 @@
1
- import { closeAlert } from './functions';
2
-
3
1
  (function ($) {
4
2
  const onDOMReady = function () {
5
3
  $('.flash').each(function () {
@@ -17,3 +15,12 @@ import { closeAlert } from './functions';
17
15
 
18
16
  $(document).on('ready page:load turbolinks:load', onDOMReady);
19
17
  })(jQuery);
18
+
19
+ function closeAlert() {
20
+ $('.flash')
21
+ .removeClass('flash--shown')
22
+ .delay(700)
23
+ .queue(function () {
24
+ $(this).remove();
25
+ });
26
+ }
@@ -9,7 +9,10 @@
9
9
  var fileName = '';
10
10
 
11
11
  if (this.files && this.files.length > 1)
12
- fileName = (this.getAttribute('data-multiple-caption') || '').replace('{count}', this.files.length);
12
+ fileName = (this.getAttribute('data-multiple-caption') || '').replace(
13
+ '{count}',
14
+ this.files.length
15
+ );
13
16
  else if (e.target.value) fileName = e.target.value.split('\\').pop();
14
17
 
15
18
  if (fileName)
@@ -0,0 +1,14 @@
1
+ $.extend({
2
+ displayModal: function (content, options = {}) {
3
+ $('#modal').find('#modal__content').html(content);
4
+ $('#modal').css('display', 'flex');
5
+ $.restoreActionElements();
6
+ $(document).trigger('modal:opened', options['extraEventParameters']);
7
+ },
8
+ closeModal: function () {
9
+ $('#modal').find('#modal__content').empty();
10
+ $('#modal').css('display', 'none');
11
+ $.restoreActionElements();
12
+ $(document).trigger('modal:closed');
13
+ }
14
+ });
@@ -1,17 +1,26 @@
1
- <div class='card card--padding'>
1
+ <% app_name = BeyondCanvas.configuration.site_title %>
2
+ <% i18n_scope = 'beyond_canvas.authentications.new' %>
2
3
 
3
- <%= form_for(resource, as: resource_name) do |f| %>
4
+ <div class="card card--padding">
4
5
 
5
- <h2 class='card__headline'>Install <%= BeyondCanvas.configuration.site_title %> in your shop</h2>
6
+ <%= form_with(url: callback_path, method: :post, scope: :shop, model: @shop, local: true, builder: BeyondCanvas::FormBuilder) do |f| %>
6
7
 
7
- <%= f.hidden_field :code, value: params[:code] || resource.code %>
8
- <%= f.hidden_field :signature, value: params[:signature] || resource.signature %>
9
- <%= f.hidden_field :return_url, value: params[:return_url] || resource.return_url %>
10
- <%= f.hidden_field :api_url, value: params[:api_url] || resource.api_url %>
11
- <%= f.hidden_field :access_token_url, value: params[:access_token_url] || resource.access_token_url %>
8
+ <h2 class="card__headline"><%= I18n.t('headline', app_name: app_name, scope: i18n_scope) %></h2>
12
9
 
13
- <div class='form__actions--spaced'>
14
- <%= f.button 'Save', type: :submit, class: 'button__solid--primary' %>
10
+ <p class="margin--bottom"><%= I18n.t('body', app_name: app_name, scope: i18n_scope) %></p>
11
+
12
+ <%# Don't delete or modify any ot these hidden fields. They are used on shop identification and authentication %>
13
+
14
+ <%= f.hidden_field :code, value: params[:code] || @shop.code %>
15
+ <%= f.hidden_field :signature, value: params[:signature] || @shop.signature %>
16
+ <%= f.hidden_field :return_url, value: params[:return_url] || @shop.return_url %>
17
+ <%= f.hidden_field :api_url, value: params[:api_url] || @shop.api_url %>
18
+ <%= f.hidden_field :access_token_url, value: params[:access_token_url] || @shop.access_token_url %>
19
+
20
+ <%# Add HERE your custom shop fields %>
21
+
22
+ <div class="form__actions--spaced">
23
+ <%= f.button I18n.t('actions.install', scope: i18n_scope), type: :submit, class: 'button__solid--primary' %>
15
24
  </div>
16
25
 
17
26
  <% end %>
@@ -0,0 +1,15 @@
1
+ <% if action_bar_content? %>
2
+
3
+ <div class="action_bar<% if menu_content? %> action_bar--menu<% end %>">
4
+
5
+ <div class="action_bar--left">
6
+ <%= yield :action_bar_left %>
7
+ </div>
8
+
9
+ <div class="action_bar--right">
10
+ <%= yield :action_bar_right %>
11
+ </div>
12
+
13
+ </div>
14
+
15
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <% if is_cockpit_app? %>
2
+
3
+ <div class='breadcrumbs'>
4
+
5
+ <%= inline_svg_tag 'icons/home.svg' %>
6
+
7
+ <% breadcrumb_trail do |crumb| %>
8
+ <%= link_to crumb.name, crumb.url, class: "breadcrumb__item#{ '--current' if crumb.current? }" %>
9
+ <% unless crumb.current? %><%= inline_svg_tag 'icons/arrow_right.svg' %><% end %>
10
+ <% end %>
11
+
12
+ </div>
13
+
14
+ <% end %>
@@ -1,13 +1,23 @@
1
- <% flash.each do |key, value| %>
2
- <div class="flash">
3
- <div class="flash__icon flash__icon--<%= key %>">
4
- <%= get_flash_icon(key) %>
1
+ <div id="flash">
2
+
3
+ <% flash.each do |key, value| %>
4
+
5
+ <div class="flash">
6
+
7
+ <div class="flash__icon flash__icon--<%= key %>">
8
+ <%= get_flash_icon(key) %>
9
+ </div>
10
+
11
+ <div class="flash__message">
12
+ <%= value %>
13
+ </div>
14
+
15
+ <div class="flash__close">
16
+ <%= inline_svg_tag 'icons/flash_close.svg' %>
17
+ </div>
18
+
5
19
  </div>
6
- <div class="flash__message">
7
- <%= value %>
8
- </div>
9
- <div class="flash__close">
10
- <%= inline_svg_tag 'icons/flash_close.svg' %>
11
- </div>
12
- </div>
13
- <% end %>
20
+
21
+ <% end %>
22
+
23
+ </div>
@@ -0,0 +1,8 @@
1
+ <% if show_locale_switch? && !is_cockpit_app? %>
2
+ <%= form_for :system, url: beyond_canvas.update_locale_path, method: :put do |f| %>
3
+ <%= f.select :locale, I18n.available_locales.collect { |l| [translate_locale(l), l] },
4
+ { selected: cookies[:locale] },
5
+ class: 'select--locale',
6
+ onchange: 'this.form.submit()' %>
7
+ <% end %>
8
+ <% end %>
@@ -0,0 +1,31 @@
1
+ <% if menu_content? %>
2
+
3
+ <div class="menu">
4
+
5
+ <div class="menu--left">
6
+ <%= render 'beyond_canvas/shared/logo' %>
7
+ </div>
8
+
9
+ <div class="menu--center">
10
+
11
+ <% BeyondCanvas.configuration.menu_items.each do |menu_item| %>
12
+ <% name, url, options = menu_item.name.to_s, menu_item.url.to_s, menu_item.options %>
13
+
14
+ <% url, external_url = respond_to?(url) ? [send(url), false] : [url, true] %>
15
+ <% name = defined?(I18n) && I18n.exists?(name) ? I18n.t(name) : name %>
16
+
17
+ <% path = Rails.application.routes.recognize_path(url) %>
18
+
19
+ <% options = options.merge(class: 'menu__item--active') { |_key, old_val, new_val| [new_val, old_val].join(' ') if !external_url && path[:controller] == params[:controller] } %>
20
+ <% options = options.merge(class: 'menu__item') { |_key, old_val, new_val| [new_val, old_val].join(' ') } %>
21
+
22
+ <%= link_to name, url, options %>
23
+ <% end %>
24
+
25
+ </div>
26
+
27
+ <div class="menu--right"></div>
28
+
29
+ </div>
30
+
31
+ <% end %>