beyond_canvas 0.22.0.pre → 0.23.0.pre

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/icons/adblocker.svg +5 -0
  3. data/app/assets/images/icons/checkbox_checked.svg +1 -1
  4. data/app/assets/images/icons/checkbox_unchecked.svg +1 -1
  5. data/app/assets/images/icons/external_link.svg +1 -0
  6. data/app/assets/images/icons/toggle.svg +1 -0
  7. data/app/assets/images/icons/toggle_checked.svg +3 -0
  8. data/app/assets/images/icons/toggle_unchecked.svg +3 -0
  9. data/app/assets/javascripts/beyond_canvas/base.js +77 -31
  10. data/app/assets/stylesheets/beyond_canvas/base.scss +19 -18
  11. data/app/assets/stylesheets/beyond_canvas/components/_action_bar.scss +11 -6
  12. data/app/assets/stylesheets/beyond_canvas/components/_breadcrumbs.scss +5 -5
  13. data/app/assets/stylesheets/beyond_canvas/components/_buttons.scss +45 -95
  14. data/app/assets/stylesheets/beyond_canvas/components/_cards.scss +20 -12
  15. data/app/assets/stylesheets/beyond_canvas/components/_collapse.scss +6 -3
  16. data/app/assets/stylesheets/beyond_canvas/components/_flash.scss +11 -11
  17. data/app/assets/stylesheets/beyond_canvas/components/_forms.scss +2 -2
  18. data/app/assets/stylesheets/beyond_canvas/components/_inputs.scss +182 -40
  19. data/app/assets/stylesheets/beyond_canvas/components/_links.scss +51 -3
  20. data/app/assets/stylesheets/beyond_canvas/components/_main.scss +3 -3
  21. data/app/assets/stylesheets/beyond_canvas/components/_menu.scss +13 -0
  22. data/app/assets/stylesheets/beyond_canvas/components/_modals.scss +48 -18
  23. data/app/assets/stylesheets/beyond_canvas/components/_notices.scss +11 -11
  24. data/app/assets/stylesheets/beyond_canvas/components/_scrollbox.scss +5 -4
  25. data/app/assets/stylesheets/beyond_canvas/components/_select2.scss +13 -13
  26. data/app/assets/stylesheets/beyond_canvas/components/_statuses.scss +9 -8
  27. data/app/assets/stylesheets/beyond_canvas/components/_step_list.scss +67 -0
  28. data/app/assets/stylesheets/beyond_canvas/components/_tables.scss +10 -5
  29. data/app/assets/stylesheets/beyond_canvas/components/_titles.scss +1 -1
  30. data/app/assets/stylesheets/beyond_canvas/mailer.scss +2 -1
  31. data/app/assets/stylesheets/beyond_canvas/settings/_base_variables.scss +241 -0
  32. data/app/assets/stylesheets/beyond_canvas/settings/{_variables.scss → _constant_variables.scss} +30 -64
  33. data/app/assets/stylesheets/beyond_canvas/settings/_custom_variables.scss +233 -0
  34. data/app/assets/stylesheets/beyond_canvas/settings/_typography.scss +7 -3
  35. data/app/assets/stylesheets/beyond_canvas/utilities/_mixins.scss +30 -3
  36. data/app/controllers/beyond_canvas/authentications_controller.rb +18 -2
  37. data/app/controllers/beyond_canvas/system_controller.rb +3 -1
  38. data/app/controllers/beyond_canvas/webhooks_controller.rb +49 -0
  39. data/app/controllers/concerns/beyond_canvas/add_blocker_check.rb +17 -0
  40. data/app/controllers/concerns/beyond_canvas/custom_styles.rb +54 -0
  41. data/app/controllers/concerns/beyond_canvas/locale_management.rb +31 -8
  42. data/app/controllers/concerns/beyond_canvas/request_validation.rb +6 -0
  43. data/app/form_builders/beyond_canvas/form_builder.rb +62 -49
  44. data/app/helpers/beyond_canvas/application_helper.rb +27 -4
  45. data/app/helpers/beyond_canvas/form_tag_helper.rb +130 -0
  46. data/app/javascript/beyond_canvas/base.js +0 -1
  47. data/app/javascript/beyond_canvas/initializers/buttons.js +10 -2
  48. data/app/javascript/beyond_canvas/initializers/flash.js +32 -10
  49. data/app/javascript/beyond_canvas/initializers/inputs.js +9 -4
  50. data/app/javascript/beyond_canvas/initializers/modals.js +46 -10
  51. data/app/views/beyond_canvas/mailer/_header.html.erb +2 -2
  52. data/app/views/beyond_canvas/shared/_flash.html.erb +14 -10
  53. data/app/views/beyond_canvas/shared/_head.html.erb +4 -0
  54. data/app/views/beyond_canvas/shared/_locales.html.erb +1 -1
  55. data/app/views/layouts/beyond_canvas/application.html.erb +0 -1
  56. data/app/views/layouts/beyond_canvas/public.html.erb +1 -1
  57. data/config/initializers/beyond_canvas/constants.rb +13 -0
  58. data/config/initializers/beyond_canvas/session_store.rb +8 -0
  59. data/lib/beyond_canvas/configuration.rb +9 -1
  60. data/lib/beyond_canvas/engine.rb +7 -0
  61. data/lib/beyond_canvas/rails/routes.rb +27 -7
  62. data/lib/beyond_canvas/version.rb +1 -1
  63. data/lib/beyond_canvas/webhook_event_registration.rb +19 -0
  64. data/lib/beyond_canvas.rb +6 -4
  65. data/lib/generators/beyond_canvas/install/install_generator.rb +6 -0
  66. data/lib/generators/beyond_canvas/install/templates/beyond_canvas.rb.erb +38 -1
  67. data/lib/generators/beyond_canvas/model/model_generator.rb +3 -0
  68. data/lib/generators/beyond_canvas/webhook/templates/webhooks_controller.rb +22 -0
  69. data/lib/generators/beyond_canvas/webhook/webhook_generator.rb +15 -0
  70. data/lib/models/concerns/authentication.rb +10 -3
  71. data/lib/models/concerns/utils.rb +1 -1
  72. data/lib/models/concerns/webhook.rb +123 -0
  73. data/lib/models/shop.rb +1 -0
  74. metadata +68 -39
  75. data/app/assets/stylesheets/beyond_canvas/components/_comments.scss +0 -6
  76. data/app/views/beyond_canvas/shared/_modal.html.erb +0 -6
  77. data/config/routes.rb +0 -12
@@ -1,5 +1,4 @@
1
1
  import 'jquery';
2
-
3
2
  import './initializers/buttons';
4
3
  import './initializers/collapse';
5
4
  import './initializers/flash';
@@ -23,13 +23,15 @@ const BUTTON_SELECTORS = '[class^="button"]';
23
23
  });
24
24
  };
25
25
 
26
- $(document).on('confirm:complete', function () {
26
+ $(document).on('confirm:complete', function () {
27
27
  $.restoreActionElements();
28
28
  });
29
29
 
30
- $(document).on('click', BUTTON_SELECTORS, function () {
30
+ $(document).on('click', BUTTON_SELECTORS, function (e) {
31
31
  var button = $(this);
32
32
 
33
+ if(e.target.attributes.getNamedItem('target')?.value === '_blank') return;
34
+
33
35
  $.disableActionElements();
34
36
 
35
37
  if (!button.hasClass('button--no-spinner')) {
@@ -38,10 +40,15 @@ const BUTTON_SELECTORS = '[class^="button"]';
38
40
  });
39
41
 
40
42
  $(document).on('ready page:load turbolinks:load', onDOMReady);
43
+
44
+ $(document).on('beforeunload turbolinks:before-visit', function () {
45
+ $.restoreActionElements();
46
+ });
41
47
  })(jQuery);
42
48
 
43
49
  $.extend({
44
50
  restoreActionElements: function () {
51
+ setTimeout(function () {
45
52
  // Hide spinners
46
53
  $(BUTTON_SELECTORS).each(function (_, button) {
47
54
  setTimeout(function () {
@@ -56,6 +63,7 @@ $.extend({
56
63
  $('a, input[type="submit"], input[type="button"], input[type="reset"], button').each(function () {
57
64
  $(this).removeClass('actions--disabled');
58
65
  });
66
+ }, 100);
59
67
  },
60
68
  disableActionElements: function () {
61
69
  $('a, input[type="submit"], input[type="button"], input[type="reset"], button').each(function () {
@@ -10,17 +10,39 @@
10
10
  };
11
11
 
12
12
  $(document).on('click', '.flash__close', function () {
13
- closeAlert();
13
+ $.closeAlert();
14
14
  });
15
15
 
16
- $(document).on('ready page:load turbolinks:load', onDOMReady);
16
+ $(document).on('ready page:load turbolinks:load bc.flash.shown', onDOMReady);
17
17
  })(jQuery);
18
18
 
19
- function closeAlert() {
20
- $('.flash')
21
- .removeClass('flash--shown')
22
- .delay(700)
23
- .queue(function () {
24
- $(this).remove();
25
- });
26
- }
19
+ $.extend({
20
+ showFlash: function(status, message) {
21
+ const flash = `
22
+ <div class="flash">
23
+ <div class="flash__icon flash__icon--${status}">
24
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm6 16.538l-4.592-4.548 4.546-4.587-1.416-1.403-4.545 4.589-4.588-4.543-1.405 1.405 4.593 4.552-4.547 4.592 1.405 1.405 4.555-4.596 4.591 4.55 1.403-1.416z"></path></svg>
25
+ </div>
26
+ <div class="flash__message">
27
+ ${message}
28
+ </div>
29
+ <div class="flash__close">
30
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M24 20.188l-8.315-8.209 8.2-8.282-3.697-3.697-8.212 8.318-8.31-8.203-3.666 3.666 8.321 8.24-8.206 8.313 3.666 3.666 8.237-8.318 8.285 8.203z"></path></svg>
31
+ </div>
32
+ </div>`;
33
+
34
+ $(document).trigger('bc.flash.show');
35
+ $('#flash').html(flash);
36
+ $(document).trigger('bc.flash.shown');
37
+ },
38
+ closeAlert: function() {
39
+ $(document).trigger('bc.flash.hide');
40
+ $('.flash')
41
+ .removeClass('flash--shown')
42
+ .delay(700)
43
+ .queue(function () {
44
+ $(this).remove();
45
+ });
46
+ $(document).trigger('bc.flash.hidden');
47
+ }
48
+ });
@@ -1,15 +1,15 @@
1
1
  (function ($) {
2
2
  const onDOMReady = function () {
3
3
  $('input[type="file"]').each(function () {
4
- var $input = $(this),
4
+ const $input = $(this),
5
5
  $label = $(`.input__file__text.${$input.attr('id')}`),
6
6
  labelVal = $label.html();
7
7
 
8
8
  $input.on('change', function (e) {
9
- var fileName = '';
9
+ let fileName = '';
10
10
 
11
11
  if (this.files && this.files.length > 1)
12
- fileName = (this.getAttribute('data-multiple-caption') || '').replace(
12
+ fileName = (this.getAttribute('data-multiple-caption') || '{count} files selected').replace(
13
13
  '{count}',
14
14
  this.files.length
15
15
  );
@@ -33,5 +33,10 @@
33
33
  });
34
34
  };
35
35
 
36
- $(document).on('ready page:load turbolinks:load', onDOMReady);
36
+ $(document).on('ready page:load turbolinks:load', () => {
37
+ const observer = new MutationObserver(() => onDOMReady());
38
+
39
+ onDOMReady();
40
+ observer.observe(document.body, { childList: true, subtree: true });
41
+ });
37
42
  })(jQuery);
@@ -1,14 +1,50 @@
1
- $.extend({
2
- displayModal: function (content, options = {}) {
3
- $('#modal').find('#modal__content').html(content);
4
- $('#modal').css('display', 'flex');
1
+ (function ($) {
2
+ const onDOMReady = function () {
3
+ $('.modal').each(function () {
4
+ $(this).hide().css('visibility', 'visible');
5
+ });
6
+ };
7
+
8
+ $(document).on('click', '[data-toggle="modal"]', function (e) {
9
+ e.preventDefault();
10
+
11
+ const dataTarget = $(this).attr('data-target');
12
+
5
13
  $.restoreActionElements();
6
- $(document).trigger('modal:opened', options['extraEventParameters']);
14
+ $(dataTarget).showModal();
15
+ });
16
+
17
+ $(document).on('click', '[data-dismiss="modal"]', function (e) {
18
+ e.preventDefault();
19
+
20
+ const dataTarget = $(this).closest('.modal');
21
+
22
+ $.restoreActionElements();
23
+ $(dataTarget).hideModal();
24
+ });
25
+
26
+ $(document).on('ready page:load turbolinks:load', onDOMReady);
27
+ })(jQuery);
28
+
29
+ $.fn.extend({
30
+ showModal: function () {
31
+ const modal = $(this);
32
+
33
+ modal.trigger('bc.modal.show');
34
+
35
+ $.restoreActionElements();
36
+ modal.css('display', 'flex');
37
+
38
+ modal.trigger('bc.modal.shown');
7
39
  },
8
- closeModal: function () {
9
- $('#modal').find('#modal__content').empty();
10
- $('#modal').css('display', 'none');
40
+ hideModal: function () {
41
+ const modal = $(this);
42
+
43
+ modal.trigger('bc.modal.hide');
44
+
11
45
  $.restoreActionElements();
12
- $(document).trigger('modal:closed');
13
- }
46
+ modal.hide();
47
+
48
+ modal.trigger('bc.modal.hidden');
49
+ },
14
50
  });
@@ -1,8 +1,8 @@
1
1
  <!-- Email Header : BEGIN -->
2
2
  <tr>
3
3
  <td style="padding: 20px 0; text-align: center">
4
- <% if BeyondCanvas.configuration.site_logo.present? %>
5
- <%= image_tag BeyondCanvas.configuration.site_logo, width: "200", height: "50", alt: "alt_text", border: "0", style: "height: auto; font-family: sans-serif; font-size: 15px; line-height: 15px; color: #555555;" %>
4
+ <% if BeyondCanvas.configuration.email_logo.present? %>
5
+ <%= image_tag BeyondCanvas.configuration.email_logo, width: "200", height: "50", border: "0", style: "height: auto; font-family: sans-serif; font-size: 15px; line-height: 15px; color: #555555;" %>
6
6
  <% end %>
7
7
  </td>
8
8
  </tr>
@@ -2,21 +2,25 @@
2
2
 
3
3
  <% flash.each do |key, value| %>
4
4
 
5
- <div class="flash">
5
+ <% unless value.blank? %>
6
6
 
7
- <div class="flash__icon flash__icon--<%= key %>">
8
- <%= get_flash_icon(key) %>
9
- </div>
7
+ <div class="flash">
10
8
 
11
- <div class="flash__message">
12
- <%= value %>
13
- </div>
9
+ <div class="flash__icon flash__icon--<%= key %>">
10
+ <%= get_flash_icon(key) %>
11
+ </div>
12
+
13
+ <div class="flash__message">
14
+ <%= value %>
15
+ </div>
16
+
17
+ <div class="flash__close">
18
+ <%= inline_svg_tag 'icons/flash_close.svg' %>
19
+ </div>
14
20
 
15
- <div class="flash__close">
16
- <%= inline_svg_tag 'icons/flash_close.svg' %>
17
21
  </div>
18
22
 
19
- </div>
23
+ <% end %>
20
24
 
21
25
  <% end %>
22
26
 
@@ -16,6 +16,10 @@
16
16
  <% end %>
17
17
  <% end %>
18
18
 
19
+ <% if BeyondCanvas.configuration.cockpit_app %>
20
+ <%= stylesheet_link_tag cookies[:custom_styles_url] %>
21
+ <% end %>
22
+
19
23
  <% BeyondCanvas.configuration.javascripts.each do |path| %>
20
24
  <% if BeyondCanvas.configuration.skip_webpacker %>
21
25
  <%= javascript_include_tag path %>
@@ -1,5 +1,5 @@
1
1
  <% if show_locale_switch? && !is_cockpit_app? %>
2
- <%= form_for :system, url: beyond_canvas.update_locale_path, method: :put do |f| %>
2
+ <%= form_for :system, url: update_locale_path, method: :put do |f| %>
3
3
  <%= f.select :locale, I18n.available_locales.collect { |l| [translate_locale(l), l] },
4
4
  { selected: cookies[:locale] },
5
5
  class: 'select--locale',
@@ -11,7 +11,6 @@
11
11
 
12
12
  <%= render 'beyond_canvas/shared/flash' %>
13
13
  <%= render 'beyond_canvas/shared/locales' %>
14
- <%= render 'beyond_canvas/shared/modal' %>
15
14
  <%= render 'beyond_canvas/shared/menu' %>
16
15
  <%= render 'beyond_canvas/shared/action_bar' %>
17
16
 
@@ -3,7 +3,7 @@
3
3
  <html>
4
4
  <%= render 'beyond_canvas/shared/head' %>
5
5
 
6
- <body class="body--public">
6
+ <body class="beyond-canvas body--public">
7
7
 
8
8
  <main class="main <%= params[:controller].gsub(/[\/_]/, "-") %>--<%= params[:action] %>">
9
9
 
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ if BeyondCanvas.configuration.cockpit_app == true && !Rails.env.development?
4
+ COOKIES_ATTRIBUTES = {
5
+ expires: 1.year.from_now,
6
+ same_site: :none,
7
+ secure: true
8
+ }.freeze
9
+ else
10
+ COOKIES_ATTRIBUTES = {
11
+ expires: 1.year.from_now
12
+ }.freeze
13
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ if BeyondCanvas.configuration.cockpit_app == true && !Rails.env.development?
4
+ Rails.application.config.session_store :cookie_store, {
5
+ secure: true,
6
+ same_site: :none
7
+ }
8
+ end
@@ -3,26 +3,30 @@
3
3
  module BeyondCanvas
4
4
  class Configuration # :nodoc:
5
5
  attr_accessor :site_title, :site_logo, :favicon, :skip_webpacker, :encryption_key, :namespace, :cockpit_app,
6
- :open_app_url, :preinstalled, :debug_mode
6
+ :open_app_url, :preinstalled, :debug_mode, :webhook_site_url, :email_logo, :client_credentials
7
7
 
8
8
  include AssetRegistration
9
9
  include MenuItemRegistration
10
+ include WebhookEventRegistration
10
11
 
11
12
  def initialize
12
13
  @cockpit_app = false
13
14
  @debug_mode = false
15
+ @client_credentials = false
14
16
  @encryption_key = nil
15
17
  @favicon = nil
16
18
  @namespace = '/'
17
19
  @open_app_url = nil
18
20
  @preinstalled = false
19
21
  @site_logo = nil
22
+ @email_logo = nil
20
23
  @site_title = ::Rails.application.class.name.split('::').first.humanize
21
24
  @skip_webpacker = false
22
25
  end
23
26
 
24
27
  def setup!
25
28
  register_default_assets
29
+ register_default_webhook_events
26
30
  end
27
31
 
28
32
  private
@@ -31,5 +35,9 @@ module BeyondCanvas
31
35
  register_stylesheet 'beyond_canvas.css', media: 'screen'
32
36
  register_javascript 'beyond_canvas.js'
33
37
  end
38
+
39
+ def register_default_webhook_events
40
+ register_webhook_event('app.uninstalled')
41
+ end
34
42
  end
35
43
  end
@@ -21,6 +21,7 @@ module BeyondCanvas
21
21
  ActiveSupport.on_load :action_controller do
22
22
  include ::BeyondCanvas::LocaleManagement
23
23
  include ::BeyondCanvas::RequestValidation
24
+ include ::BeyondCanvas::CustomStyles
24
25
  include ::BeyondCanvas::StatusCodes
25
26
  include ::BeyondCanvas::AuthenticationsHelper
26
27
  include ::BeyondCanvas::DebugHelper
@@ -29,5 +30,11 @@ module BeyondCanvas
29
30
  ::ActionController::Base.helper BeyondCanvas::Engine.helpers
30
31
  end
31
32
  end
33
+
34
+ config.after_initialize do
35
+ ActiveSupport.on_load :action_controller do
36
+ include ::BeyondCanvas::AddBlockerCheck
37
+ end
38
+ end
32
39
  end
33
40
  end
@@ -3,18 +3,38 @@
3
3
  module ActionDispatch
4
4
  module Routing
5
5
  class Mapper # :nodoc:
6
- def beyond_canvas_routes(options = nil)
7
- mount BeyondCanvas::Engine => BeyondCanvas.configuration.namespace
6
+ def beyond_canvas_routes(*resources)
7
+ scope BeyondCanvas.configuration.namespace do
8
+ put 'locale', to: 'beyond_canvas/system#update_locale', as: :update_locale
9
+ end
10
+
11
+ resources = resources.extract_options!
12
+
13
+ beyond_canvas_for_controllers(resources[:controllers] || {})
14
+ end
8
15
 
9
- BeyondCanvas.use_rails_app_controller = options.present? && options[:custom_controller].present?
16
+ protected
10
17
 
11
- set_routes if BeyondCanvas.use_rails_app_controller
18
+ def beyond_canvas_for_controllers(controllers)
19
+ [:authentications, :webhooks].each do |method|
20
+ controllers.key?(method) ? send("set_#{method}_routes", controllers[method]) : send("set_#{method}_routes")
21
+ end
22
+ end
23
+
24
+ def set_webhooks_routes(controller = 'beyond_canvas/webhooks')
25
+ scope BeyondCanvas.configuration.namespace do
26
+ resources :shops, only: [] do
27
+ member do
28
+ post :beyond_webhook, controller: controller, action: :webhook
29
+ end
30
+ end
31
+ end
12
32
  end
13
33
 
14
- def set_routes
34
+ def set_authentications_routes(controller = 'beyond_canvas/authentications')
15
35
  scope BeyondCanvas.configuration.namespace do
16
- get 'callback', controller: :authentications, action: :new
17
- post 'callback', controller: :authentications, action: :install
36
+ get 'callback', controller: controller, action: :new
37
+ post 'callback', controller: controller, action: :install
18
38
  end
19
39
  end
20
40
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BeyondCanvas
4
- VERSION = '0.22.0.pre'
4
+ VERSION = '0.23.0.pre'
5
5
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BeyondCanvas
4
+ module WebhookEventRegistration # :nodoc:
5
+ def register_webhook_event(event)
6
+ event.is_a?(Array) ? webhook_events.merge(event) : webhook_events.add(event)
7
+ end
8
+
9
+ def webhook_events
10
+ @webhook_events ||= Set.new
11
+ end
12
+
13
+ def clear_webhook_events!
14
+ webhook_events.clear
15
+ end
16
+
17
+ alias register_webhook_events register_webhook_event
18
+ end
19
+ end
data/lib/beyond_canvas.rb CHANGED
@@ -16,10 +16,11 @@ require 'beyond_api'
16
16
  require 'attr_encrypted'
17
17
 
18
18
  module BeyondCanvas # :nodoc:
19
- autoload :AssetRegistration, 'beyond_canvas/asset_registration'
20
- autoload :Configuration, 'beyond_canvas/configuration'
21
- autoload :MenuItemRegistration, 'beyond_canvas/menu_item_registration'
22
- autoload :ParameterSanitizer, 'beyond_canvas/parameter_sanitizer'
19
+ autoload :AssetRegistration, 'beyond_canvas/asset_registration'
20
+ autoload :Configuration, 'beyond_canvas/configuration'
21
+ autoload :MenuItemRegistration, 'beyond_canvas/menu_item_registration'
22
+ autoload :ParameterSanitizer, 'beyond_canvas/parameter_sanitizer'
23
+ autoload :WebhookEventRegistration, 'beyond_canvas/webhook_event_registration'
23
24
 
24
25
  module Models # :nodoc:
25
26
  autoload :Shop, 'models/shop'
@@ -27,6 +28,7 @@ module BeyondCanvas # :nodoc:
27
28
  module Concerns
28
29
  autoload :Authentication, 'models/concerns/authentication'
29
30
  autoload :Utils, 'models/concerns/utils'
31
+ autoload :Webhook, 'models/concerns/webhook'
30
32
  end
31
33
  end
32
34