beyond_canvas 0.14.0.pre → 0.16.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -6
  3. data/app/assets/images/icons/checkbox_checked.svg +1 -0
  4. data/app/assets/images/icons/checkbox_unchecked.svg +1 -0
  5. data/app/assets/images/icons/radiobutton_checked.svg +1 -0
  6. data/app/assets/images/icons/radiobutton_unchecked.svg +1 -0
  7. data/app/assets/javascripts/beyond_canvas/base.js +248 -87
  8. data/app/assets/stylesheets/beyond_canvas/base.scss +3 -0
  9. data/app/assets/stylesheets/beyond_canvas/components/_containers.scss +37 -0
  10. data/app/assets/stylesheets/beyond_canvas/components/_inputs.scss +47 -1
  11. data/app/assets/stylesheets/beyond_canvas/settings/_breakpoints.scss +6 -0
  12. data/app/assets/stylesheets/beyond_canvas/settings/_variables.scss +24 -0
  13. data/app/assets/stylesheets/beyond_canvas/utilities/_functions.scss +15 -0
  14. data/app/controllers/beyond_canvas/authentications_controller.rb +62 -0
  15. data/app/controllers/concerns/beyond_canvas/authentication.rb +24 -0
  16. data/app/controllers/concerns/beyond_canvas/request_validation.rb +1 -1
  17. data/app/controllers/concerns/beyond_canvas/resource_management.rb +33 -0
  18. data/app/form_builders/beyond_canvas/form_builder.rb +65 -8
  19. data/app/javascript/beyond_canvas/base.js +3 -6
  20. data/app/javascript/beyond_canvas/initializers/buttons.js +21 -39
  21. data/app/javascript/beyond_canvas/initializers/flash.js +5 -14
  22. data/app/javascript/beyond_canvas/initializers/functions.js +41 -0
  23. data/app/javascript/beyond_canvas/initializers/inputs.js +3 -8
  24. data/app/views/beyond_canvas/authentications/new.html.erb +18 -0
  25. data/config/locales/en.yml +4 -0
  26. data/config/routes.rb +6 -0
  27. data/lib/beyond_canvas.rb +22 -2
  28. data/lib/beyond_canvas/configuration.rb +4 -1
  29. data/lib/beyond_canvas/engine.rb +4 -0
  30. data/lib/beyond_canvas/models/authentication.rb +66 -0
  31. data/lib/beyond_canvas/models/shop.rb +28 -0
  32. data/lib/beyond_canvas/models/utils.rb +55 -0
  33. data/lib/beyond_canvas/parameter_sanitizer.rb +43 -0
  34. data/lib/beyond_canvas/rails/routes.rb +21 -0
  35. data/lib/beyond_canvas/version.rb +1 -1
  36. data/lib/generators/beyond_canvas/auth_model/auth_model_generator.rb +50 -0
  37. data/lib/generators/beyond_canvas/auth_model/templates/migration.erb +20 -0
  38. data/lib/generators/beyond_canvas/auth_model/templates/model.erb +5 -0
  39. data/lib/generators/beyond_canvas/controller/controller_generator.rb +20 -0
  40. data/lib/generators/beyond_canvas/controller/templates/controller.erb +37 -0
  41. data/lib/generators/beyond_canvas/install/install_generator.rb +15 -5
  42. data/lib/generators/beyond_canvas/install/templates/beyond_canvas.rb.erb +11 -0
  43. data/lib/generators/beyond_canvas/views/views_generator.rb +19 -0
  44. metadata +58 -6
@@ -0,0 +1,6 @@
1
+ $mobile-s: 321px !global;
2
+ $mobile-m: 376px !global;
3
+ $mobile-l: 426px !global;
4
+ $tablet: 769px !global;
5
+ $laptop: 1025px !global;
6
+ $laptop-l: 1441px !global;
@@ -70,6 +70,12 @@ $card-separator-color: rgb(222, 222, 222) !default;
70
70
  $card-separator-spacing: 50px !global;
71
71
  $card-title-color: rgb(247, 133, 96) !default;
72
72
 
73
+ // ************************************************************
74
+ // Containers
75
+ // ************************************************************
76
+
77
+ $container-spacing: 30px !global;
78
+
73
79
  // ************************************************************
74
80
  // Labels
75
81
  // ************************************************************
@@ -84,6 +90,24 @@ $input-border-color: rgb(217, 216, 195) !default;
84
90
  $input-border-color-focus: $palette-primary !default;
85
91
  $input-errors-color: $palette-danger !default;
86
92
 
93
+ // ************************************************************
94
+ // Checkboxes
95
+ // ************************************************************
96
+
97
+ $checkbox-checked-color: #97C344 !default;
98
+ $checkbox-checked-background: #ffffff !default;
99
+ $checkbox-unchecked-color: #C2BF9D !default;
100
+ $checkbox-unchecked-background: #ffffff !default;
101
+
102
+ // ************************************************************
103
+ // Radiobuttons
104
+ // ************************************************************
105
+
106
+ $radio-checked-color: #97C344 !default;
107
+ $radio-checked-background: #ffffff !default;
108
+ $radio-unchecked-color: #C2BF9D !default;
109
+ $radio-unchecked-background: #ffffff !default;
110
+
87
111
  // ************************************************************
88
112
  // Hints
89
113
  // ************************************************************
@@ -0,0 +1,15 @@
1
+ /// Replace `$search` with `$replace` in `$string`
2
+ /// @author Hugo Giraudel
3
+ /// @param {String} $string - Initial string
4
+ /// @param {String} $search - Substring to replace
5
+ /// @param {String} $replace ('') - New value
6
+ /// @return {String} - Updated string
7
+ @function str-replace($string, $search, $replace: '') {
8
+ $index: str-index($string, $search);
9
+
10
+ @if $index {
11
+ @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
12
+ }
13
+
14
+ @return $string;
15
+ }
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency 'beyond_canvas/application_controller'
4
+
5
+ module BeyondCanvas
6
+ class AuthenticationsController < ApplicationController # :nodoc:
7
+ layout 'beyond_canvas/public'
8
+
9
+ include ::BeyondCanvas::Authentication
10
+ include ::BeyondCanvas::ResourceManagement
11
+
12
+ before_action :validate_app_installation_request!, only: :new
13
+
14
+ def new
15
+ self.resource = resource_class.new
16
+ end
17
+
18
+ def create
19
+ # Search for the api url. If there is no record it creates a new record.
20
+ resource_params = new_resource_params
21
+ self.resource = resource_class.find_or_create_by(beyond_api_url: resource_params[:api_url])
22
+ # Assign the attributes to the record
23
+ raise ActiveRecord::RecordNotSaved unless resource.update(resource_params)
24
+ # Get and save access_token and refresh_token using the authentication code
25
+ raise BeyondApi::Error if resource.authenticate.is_a?(BeyondApi::Error)
26
+
27
+ redirect_to after_create_path
28
+ rescue ActiveRecord::RecordNotSaved, BeyondApi::Error, StandardError => e
29
+ logger.error "[BeyondCanvas] #{e.message}".red
30
+ send "handle_#{e.class.name.split('::').first.underscore}_exception", e
31
+ end
32
+
33
+ def update
34
+ create
35
+ end
36
+
37
+ private
38
+
39
+ def new_resource_params
40
+ send "new_#{resource_name}_params"
41
+ end
42
+
43
+ def after_create_path
44
+ new_resource_params[:return_url]
45
+ end
46
+
47
+ def handle_active_record_exception(_exception)
48
+ flash[:error] = t('beyond_canvas.authentications.failure')
49
+ render :new
50
+ end
51
+
52
+ def handle_beyond_api_exception(_exception)
53
+ flash[:error] = t('beyond_canvas.authentications.failure')
54
+ render :new
55
+ end
56
+
57
+ def handle_standard_error_exception(_exception)
58
+ flash[:error] = t('beyond_canvas.authentications.failure')
59
+ render :new
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BeyondCanvas
4
+ module Authentication # :nodoc:
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
+
18
+ private
19
+
20
+ def beyond_canvas_parameter_sanitizer
21
+ @beyond_canvas_parameter_sanitizer ||= BeyondCanvas::ParameterSanitizer.new(AUTH_RESOURCE, params)
22
+ end
23
+ end
24
+ end
@@ -31,7 +31,7 @@ module BeyondCanvas
31
31
  def valid_signature?(signature, data, secret)
32
32
  digest = OpenSSL::Digest.new('SHA1')
33
33
  hmac = OpenSSL::HMAC.digest(digest, secret, data)
34
- signature == Base64.encode64(hmac).chop
34
+ URI.decode(signature) == Base64.encode64(hmac).chop
35
35
  end
36
36
  end
37
37
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BeyondCanvas
4
+ module ResourceManagement # :nodoc:
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ # Share some methods defined in the controller to make them available for the view
9
+ if respond_to?(:helper_method)
10
+ helpers = %w[resource resource_name resource_class]
11
+ helper_method(*helpers)
12
+ end
13
+ end
14
+
15
+ protected
16
+
17
+ def resource_name
18
+ BeyondCanvas.auth_model
19
+ end
20
+
21
+ def resource
22
+ instance_variable_get(:"@#{resource_name}")
23
+ end
24
+
25
+ def resource=(new_resource)
26
+ instance_variable_set(:"@#{resource_name}", new_resource)
27
+ end
28
+
29
+ def resource_class
30
+ resource_name.classify.constantize
31
+ end
32
+ end
33
+ end
@@ -2,18 +2,39 @@
2
2
 
3
3
  module BeyondCanvas
4
4
  class FormBuilder < ActionView::Helpers::FormBuilder # :nodoc:
5
+ ############################################################################
6
+ # Wrappers
7
+ ############################################################################
8
+
5
9
  def field_wrapper(attribute, args, &block)
6
- label = args[:label].presence || attribute.to_s.humanize
10
+ label = args[:label] == false ? nil : args[:label].presence || attribute.to_s.humanize
7
11
 
8
12
  errors = object.errors[attribute].join(', ') if object.respond_to?(:errors) && object.errors.include?(attribute)
9
13
 
10
14
  @template.content_tag(:div, class: 'form__row') do
11
15
  @template.content_tag(:label, label, class: 'input__label') +
12
- @template.content_tag(:div, class: 'relative') do
13
- block.call +
14
- (@template.content_tag(:label, errors, class: 'input__error') if errors.present?)
15
- end +
16
- (@template.content_tag(:div, args[:hint].html_safe, class: 'input__hint') if args[:hint].present?)
16
+ @template.content_tag(:div, class: 'relative') do
17
+ block.call +
18
+ (@template.content_tag(:label, errors, class: 'input__error') if errors.present?)
19
+ end +
20
+ (@template.content_tag(:div, args[:hint].html_safe, class: 'input__hint') if args[:hint].present?)
21
+ end
22
+ end
23
+
24
+ def inline_wrapper(attribute, args, &block)
25
+ label = args[:label] == false ? nil : args[:label].presence || attribute.to_s.humanize
26
+
27
+ errors = object.errors[attribute].join(', ') if object.respond_to?(:errors) && object.errors.include?(attribute)
28
+
29
+ @template.content_tag(:div, class: 'form__row') do
30
+ @template.content_tag(:div, class: 'relative', style: 'display: flex; align-items: center;') do
31
+ block.call +
32
+ @template.content_tag(:div) do
33
+ @template.content_tag(:label, label, class: 'input__label') +
34
+ (@template.content_tag(:div, args[:hint].html_safe, class: 'input__hint') if args[:hint].present?)
35
+ end +
36
+ (@template.content_tag(:label, errors, class: 'input__error') if errors.present?)
37
+ end
17
38
  end
18
39
  end
19
40
 
@@ -25,9 +46,39 @@ module BeyondCanvas
25
46
  end
26
47
  end
27
48
 
49
+ def check_box(attribute, args = {})
50
+ inline_wrapper(attribute, args) do
51
+ filed_identifyer = filed_identifyer(attribute)
52
+
53
+ args.merge!(id: filed_identifyer)
54
+ .merge!(hidden: true)
55
+
56
+ @template.content_tag(:div, class: 'input__checkbox') do
57
+ super(attribute, args) +
58
+ @template.content_tag(:label, nil, class: 'input__checkbox__control', for: filed_identifyer)
59
+ end
60
+ end
61
+ end
62
+
63
+ def radio_button(attribute, value, args = {})
64
+ args.merge!(label: value) unless args[:label]
65
+
66
+ inline_wrapper(attribute, args) do
67
+ filed_identifyer = filed_identifyer(attribute)
68
+
69
+ args.merge!(id: filed_identifyer)
70
+ .merge!(hidden: true)
71
+
72
+ @template.content_tag(:div, class: 'input__radio') do
73
+ super(attribute, value, args) +
74
+ @template.content_tag(:label, nil, class: 'input__radio__control', for: filed_identifyer)
75
+ end
76
+ end
77
+ end
78
+
28
79
  def file_field(attribute, args = {})
29
80
  field_wrapper(attribute, args) do
30
- filed_identifyer = "#{attribute}_#{(Time.now.to_f * 1000).to_i}"
81
+ filed_identifyer = filed_identifyer(attribute)
31
82
 
32
83
  args.merge!(id: filed_identifyer)
33
84
  .merge!(hidden: true)
@@ -39,7 +90,7 @@ module BeyondCanvas
39
90
  super(attribute, args) +
40
91
  @template.content_tag(:label,
41
92
  for: filed_identifyer,
42
- class: 'input__file__label button__transparent--primary') do
93
+ class: 'input__file__control button__transparent--primary') do
43
94
  args[:data][:button_text] || 'Choose file'
44
95
  end +
45
96
  @template.content_tag(:span,
@@ -48,5 +99,11 @@ module BeyondCanvas
48
99
  end
49
100
  end
50
101
  end
102
+
103
+ private
104
+
105
+ def filed_identifyer(attribute)
106
+ "#{attribute}_#{DateTime.now.strftime('%Q') + rand(10_000).to_s}"
107
+ end
51
108
  end
52
109
  end
@@ -1,6 +1,3 @@
1
- import 'jquery'
2
- import 'jquery-ujs'
3
-
4
- import './initializers/buttons'
5
- import './initializers/flash'
6
- import './initializers/inputs'
1
+ import './initializers/buttons';
2
+ import './initializers/flash';
3
+ import './initializers/inputs';
@@ -1,7 +1,21 @@
1
- const SPINNER_ANIMATION_TIMEOUT = 125;
1
+ import { disableActionElements, enableActionElements, hideSpinner, showSpinner } from './functions';
2
2
 
3
- (function($) {
3
+ (function ($) {
4
4
  const onDOMReady = function () {
5
+ const inputs = $('input, textarea, select').not(':input[type=button], :input[type=submit], :input[type=reset]');
6
+
7
+ inputs.each(function () {
8
+ var input = $(this);
9
+
10
+ input.bind('invalid', function (e) {
11
+ if ($(input).is(':hidden')) {
12
+ e.preventDefault();
13
+ }
14
+ hideSpinner();
15
+ enableActionElements();
16
+ });
17
+ });
18
+
5
19
  $('button[class^="button"]').each(function () {
6
20
  var button = $(this);
7
21
 
@@ -15,58 +29,26 @@ const SPINNER_ANIMATION_TIMEOUT = 125;
15
29
  <div class="bounce1"></div>
16
30
  <div class="bounce2"></div>
17
31
  <div class="bounce3"></div>
18
- </div>`
19
- );
32
+ </div>`);
20
33
 
21
34
  // Bind ajax:success and ajax:error to the form the button belongs to
22
35
  button
23
36
  .closest('form')
24
37
  .on('ajax:success', function () {
25
- hideSpinner(button);
38
+ hideSpinner();
26
39
  enableActionElements();
27
40
  })
28
41
  .on('ajax:error', function () {
29
- hideSpinner(button);
42
+ hideSpinner();
30
43
  enableActionElements();
31
44
  });
32
45
  });
33
46
  };
34
47
 
35
- $(document).on('click', '[class^="button"]', function() {
48
+ $(document).on('click', '[class^="button"]', function () {
36
49
  disableActionElements();
37
50
  showSpinner($(this));
38
51
  });
39
52
 
40
- $(document)
41
- .ready(onDOMReady)
42
- .on('ready page:load turbolinks:load', onDOMReady);
53
+ $(document).on('ready page:load turbolinks:load', onDOMReady);
43
54
  })(jQuery);
44
-
45
- function showSpinner(button) {
46
- // Adjust the width of the button
47
- button.width(button.width() + $('.spinner').outerWidth(true));
48
- // Show the spinner
49
- setTimeout(function() {
50
- button.find('.spinner').css('display', 'flex');
51
- }, SPINNER_ANIMATION_TIMEOUT);
52
- }
53
-
54
- function hideSpinner(button) {
55
- setTimeout(function () {
56
- // Hide the spinner
57
- button.find('.spinner').hide();
58
- // Adjust the width of the button
59
- button.width(button.data('oldWidth'));
60
- }, SPINNER_ANIMATION_TIMEOUT);
61
- }
62
-
63
- function disableActionElements() {
64
- $('a, input[type="submit"], input[type="button"], input[type="reset"], button').each(function() {
65
- $(this).addClass('actions--disabled');
66
- });
67
- }
68
- function enableActionElements() {
69
- $('a, input[type="submit"], input[type="button"], input[type="reset"], button').each(function() {
70
- $(this).removeClass("actions--disabled");
71
- });
72
- }
@@ -1,4 +1,6 @@
1
- (function($) {
1
+ import { closeAlert } from './functions';
2
+
3
+ (function ($) {
2
4
  const onDOMReady = function () {
3
5
  $('.flash').each(function () {
4
6
  $(this).css('right', -$(this).width() + 'px');
@@ -9,20 +11,9 @@
9
11
  }, 100);
10
12
  };
11
13
 
12
- $(document).on('click', '.flash', function() {
14
+ $(document).on('click', '.flash', function () {
13
15
  closeAlert();
14
16
  });
15
17
 
16
- $(document)
17
- .ready(onDOMReady)
18
- .on('ready page:load turbolinks:load', onDOMReady);
18
+ $(document).on('ready page:load turbolinks:load', onDOMReady);
19
19
  })(jQuery);
20
-
21
- function closeAlert() {
22
- $('.flash')
23
- .removeClass('flash--shown')
24
- .delay(700)
25
- .queue(function() {
26
- $(this).remove();
27
- });
28
- }
@@ -0,0 +1,41 @@
1
+ const SPINNER_ANIMATION_TIMEOUT = 125;
2
+
3
+ export function showSpinner(button) {
4
+ // Adjust the width of the button
5
+ button.width(button.width() + $('.spinner').outerWidth(true));
6
+ // Show the spinner
7
+ setTimeout(function () {
8
+ button.find('.spinner').css('display', 'flex');
9
+ }, SPINNER_ANIMATION_TIMEOUT);
10
+ }
11
+
12
+ export function hideSpinner() {
13
+ $('button[class^="button"]').each(function (_, button) {
14
+ setTimeout(function () {
15
+ // Hide the spinner
16
+ $(button).find('.spinner').hide();
17
+ // Adjust the width of the button
18
+ $(button).width($(button).data('oldWidth'));
19
+ }, SPINNER_ANIMATION_TIMEOUT);
20
+ });
21
+ }
22
+
23
+ export function disableActionElements() {
24
+ $('a, input[type="submit"], input[type="button"], input[type="reset"], button').each(function (_, button) {
25
+ $(button).addClass('actions--disabled');
26
+ });
27
+ }
28
+ export function enableActionElements() {
29
+ $('a, input[type="submit"], input[type="button"], input[type="reset"], button').each(function (_, button) {
30
+ $(button).removeClass('actions--disabled');
31
+ });
32
+ }
33
+
34
+ export function closeAlert() {
35
+ $('.flash')
36
+ .removeClass('flash--shown')
37
+ .delay(700)
38
+ .queue(function () {
39
+ $(this).remove();
40
+ });
41
+ }