binda 0.1.3 → 0.1.4

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 (132) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +83 -25
  3. data/app/assets/javascripts/binda/application.js +3 -3
  4. data/app/assets/javascripts/binda/components/bootstrap.js +3 -4
  5. data/app/assets/javascripts/binda/components/field_group_editor.js +10 -10
  6. data/app/assets/javascripts/binda/components/field_setting_choices.js +61 -49
  7. data/app/assets/javascripts/binda/components/fileupload.js +135 -118
  8. data/app/assets/javascripts/binda/components/form_item.js +65 -65
  9. data/app/assets/javascripts/binda/components/form_item_editor.js +19 -19
  10. data/app/assets/javascripts/binda/components/form_item_image.js +11 -13
  11. data/app/assets/javascripts/binda/components/form_item_repeater.js +77 -71
  12. data/app/assets/javascripts/binda/components/login-shader.js +171 -164
  13. data/app/assets/javascripts/binda/components/login_form.js +65 -73
  14. data/app/assets/javascripts/binda/components/radio-toggle.js +8 -12
  15. data/app/assets/javascripts/binda/components/select2.js +19 -14
  16. data/app/assets/javascripts/binda/components/sortable.js +76 -71
  17. data/app/assets/javascripts/binda/dist/binda.bundle.js +735 -727
  18. data/app/assets/javascripts/binda/index.js +49 -35
  19. data/app/assets/stylesheets/binda/components/assets_manager.scss +13 -22
  20. data/app/assets/stylesheets/binda/components/b-alert.scss +18 -14
  21. data/app/assets/stylesheets/binda/components/b-btn.scss +24 -43
  22. data/app/assets/stylesheets/binda/components/field_setting_choices.scss +16 -31
  23. data/app/assets/stylesheets/binda/components/fileupload.scss +25 -42
  24. data/app/assets/stylesheets/binda/components/form_item.scss +51 -93
  25. data/app/assets/stylesheets/binda/components/form_item_choices.scss +7 -10
  26. data/app/assets/stylesheets/binda/components/login.scss +2 -2
  27. data/app/assets/stylesheets/binda/components/main_header.scss +5 -10
  28. data/app/assets/stylesheets/binda/components/main_sidebar.scss +42 -46
  29. data/app/assets/stylesheets/binda/components/main_sortable_table.scss +12 -21
  30. data/app/assets/stylesheets/binda/components/main_table.scss +18 -35
  31. data/app/assets/stylesheets/binda/components/popup_warning.scss +14 -27
  32. data/app/assets/stylesheets/binda/components/select2.scss +46 -48
  33. data/app/assets/stylesheets/binda/components/sortable.scss +25 -45
  34. data/app/assets/stylesheets/binda/components/standard-form.scss +43 -73
  35. data/app/assets/stylesheets/binda/controllers/users_sessions_new.scss +52 -89
  36. data/app/assets/stylesheets/binda/index.scss +0 -1
  37. data/app/assets/stylesheets/binda/settings/buttons.scss +9 -10
  38. data/app/assets/stylesheets/binda/settings/common.scss +17 -22
  39. data/app/assets/stylesheets/binda/settings/fonts.scss +112 -67
  40. data/app/assets/stylesheets/binda/settings/tiny_mce_overrides.scss +20 -36
  41. data/app/assets/stylesheets/binda/settings/variables.scss +38 -43
  42. data/app/controllers/binda/choices_controller.rb +14 -11
  43. data/app/controllers/binda/components_controller.rb +6 -4
  44. data/app/controllers/binda/structures_controller.rb +7 -3
  45. data/app/helpers/binda/components_helper.rb +69 -3
  46. data/app/helpers/binda/field_groups_helper.rb +16 -6
  47. data/app/helpers/binda/structures_helper.rb +1 -4
  48. data/app/models/binda/application_record.rb +4 -1
  49. data/app/models/binda/asset.rb +3 -1
  50. data/app/models/binda/b.rb +1 -0
  51. data/app/models/binda/category.rb +1 -0
  52. data/app/models/binda/checkbox.rb +2 -0
  53. data/app/models/binda/choice.rb +74 -41
  54. data/app/models/binda/component.rb +1 -1
  55. data/app/models/binda/date.rb +4 -0
  56. data/app/models/binda/deprecation.rb +7 -0
  57. data/app/models/binda/field_group.rb +16 -3
  58. data/app/models/binda/field_setting.rb +168 -41
  59. data/app/models/binda/image.rb +1 -0
  60. data/app/models/binda/radio.rb +2 -0
  61. data/app/models/binda/relation.rb +3 -0
  62. data/app/models/binda/repeater.rb +3 -0
  63. data/app/models/binda/selection.rb +237 -0
  64. data/app/models/binda/string.rb +4 -0
  65. data/app/models/binda/structure.rb +25 -14
  66. data/app/models/binda/text.rb +9 -0
  67. data/app/models/binda/video.rb +1 -0
  68. data/app/models/concerns/binda/default_helpers.rb +40 -31
  69. data/app/models/concerns/binda/deprecations.rb +6 -0
  70. data/app/models/concerns/binda/fieldable_association_helpers.rb +366 -0
  71. data/app/models/concerns/binda/fieldable_associations.rb +32 -369
  72. data/app/views/binda/boards/edit.html.erb +15 -2
  73. data/app/views/binda/categories/_form.html.erb +24 -51
  74. data/app/views/binda/categories/edit.html.erb +23 -3
  75. data/app/views/binda/categories/index.html.erb +49 -25
  76. data/app/views/binda/categories/new.html.erb +21 -2
  77. data/app/views/binda/components/edit.html.erb +27 -4
  78. data/app/views/binda/components/index.html.erb +47 -50
  79. data/app/views/binda/components/new.html.erb +12 -2
  80. data/app/views/binda/components/sort_index.html.erb +28 -13
  81. data/app/views/binda/field_groups/_form_body.html.erb +43 -82
  82. data/app/views/binda/field_groups/_form_item.html.erb +3 -120
  83. data/app/views/binda/field_groups/_form_section.html.erb +11 -16
  84. data/app/views/binda/field_groups/_form_section_repeater.html.erb +7 -15
  85. data/app/views/binda/field_groups/edit.html.erb +14 -2
  86. data/app/views/binda/field_groups/form_item/_form_item_choice_editor.html.erb +11 -0
  87. data/app/views/binda/field_groups/form_item/_form_item_editor.html.erb +14 -0
  88. data/app/views/binda/field_groups/form_item/_form_item_header.html.erb +25 -0
  89. data/app/views/binda/field_groups/form_item/_form_item_new_editor.html.erb +8 -0
  90. data/app/views/binda/field_groups/form_item/_form_item_persisted_editor.html.erb +27 -0
  91. data/app/views/binda/field_groups/form_item/form_item_choice/_form_item_allow_null_choice.html.erb +11 -0
  92. data/app/views/binda/field_groups/form_item/form_item_choice/_form_item_choice_header.html.erb +11 -0
  93. data/app/views/binda/field_groups/form_item/form_item_choice/_form_item_default_choice.html.erb +11 -0
  94. data/app/views/binda/field_groups/form_item/form_item_choice/_form_item_new_choice.html.erb +16 -0
  95. data/app/views/binda/field_groups/form_item/form_item_choice/_form_item_persisted_choices.html.erb +16 -0
  96. data/app/views/binda/field_groups/new.html.erb +14 -2
  97. data/app/views/binda/field_settings/_form_body.html.erb +1 -3
  98. data/app/views/binda/field_settings/edit.html.erb +1 -1
  99. data/app/views/binda/field_settings/new.html.erb +1 -1
  100. data/app/views/binda/fieldable/_form_body.html.erb +24 -72
  101. data/app/views/binda/fieldable/_form_item_date.html.erb +1 -4
  102. data/app/views/binda/fieldable/_form_item_image.html.erb +3 -7
  103. data/app/views/binda/fieldable/_form_item_new_repeater.html.erb +0 -13
  104. data/app/views/binda/fieldable/_form_item_selections.html.erb +20 -112
  105. data/app/views/binda/fieldable/form_item_selections/_form_item_checkbox.html.erb +34 -0
  106. data/app/views/binda/fieldable/form_item_selections/_form_item_radio.html.erb +28 -0
  107. data/app/views/binda/fieldable/form_item_selections/_form_item_selection.html.erb +30 -0
  108. data/app/views/binda/manage/users/_form_body.html.erb +1 -31
  109. data/app/views/binda/manage/users/edit.html.erb +12 -2
  110. data/app/views/binda/manage/users/index.html.erb +36 -19
  111. data/app/views/binda/manage/users/new.html.erb +14 -3
  112. data/app/views/binda/structures/_form_body.html.erb +2 -25
  113. data/app/views/binda/structures/_form_section.html.erb +43 -65
  114. data/app/views/binda/structures/_form_sidebar.html.erb +19 -12
  115. data/app/views/binda/structures/edit.html.erb +20 -3
  116. data/app/views/binda/structures/index.html.erb +46 -26
  117. data/app/views/binda/structures/new.html.erb +13 -2
  118. data/app/views/binda/structures/sort_index.html.erb +37 -17
  119. data/app/views/binda/users/sessions/new.html.erb +25 -20
  120. data/app/views/layouts/binda/_form_errors.html.erb +10 -0
  121. data/app/views/layouts/binda/_sidebar.html.erb +6 -6
  122. data/app/views/layouts/binda/application.html.erb +1 -1
  123. data/config/initializers/carrierwave.rb +3 -2
  124. data/config/locales/en.yml +56 -12
  125. data/config/tinymce.yml +2 -2
  126. data/db/migrate/1_create_binda_tables.rb +1 -1
  127. data/lib/binda/version.rb +1 -1
  128. data/lib/generators/binda/setup/setup_generator.rb +2 -2
  129. data/lib/tasks/add_default_choice_to_all_selections_with_no_choices_task.rake +6 -0
  130. metadata +58 -8
  131. data/app/assets/stylesheets/binda/components/form_item_image.scss +0 -0
  132. data/app/views/binda/field_groups/_form_item_choice.erb +0 -104
@@ -1,88 +1,83 @@
1
- // - - - - - - - - - - - - - - - - - -
1
+ // - - - - - - - - - - - - - - - - - -
2
2
  // GLOBAL PARAMETERS
3
- // - - - - - - - - - - - - - - - - - -
4
-
3
+ // - - - - - - - - - - - - - - - - - -
5
4
 
6
5
  // MEDIA QUERIES
7
6
  // -------------
8
7
  $tablet: 480px;
9
8
  $desktop: 960px;
10
9
 
11
-
12
10
  // FROM BOOTSTRAP
13
11
  // --------------
14
12
 
15
- $color-black: #000;
16
- $color-white: #FFF;
13
+ $color-black: #000;
14
+ $color-white: #fff;
17
15
 
18
16
  //== Colors
19
17
  //
20
18
  //## Gray and colors for use across Bootstrap.
21
19
 
22
- $color-gray-darkest: rgb( 17, 17, 17 );
23
- $color-gray-darker: rgb( 51, 51, 51 );
24
- $color-gray-dark: rgb( 102, 102, 102 );
25
- $color-gray: rgb( 128, 128, 128 );
26
- $color-gray-light: rgb( 153, 153, 153 );
27
- $color-gray-lighter: rgb( 193, 193, 193 );
28
- $color-gray-lightest: rgb( 238, 238, 238 );
29
-
30
- $color-primary: #337ab7;
31
- $color-success: #67CD9B;
32
- $color-info: #5bc0de;
33
- $color-warning: #f0ad4e;
34
- $color-danger: #fc4242;
35
- $color-danger-hover: darken( $color-danger, 20%);
36
-
20
+ $color-gray-darkest: rgb(17, 17, 17);
21
+ $color-gray-darker: rgb(51, 51, 51);
22
+ $color-gray-dark: rgb(102, 102, 102);
23
+ $color-gray: rgb(128, 128, 128);
24
+ $color-gray-light: rgb(153, 153, 153);
25
+ $color-gray-lighter: rgb(193, 193, 193);
26
+ $color-gray-lightest: rgb(238, 238, 238);
27
+
28
+ $color-primary: #337ab7;
29
+ $color-success: #67cd9b;
30
+ $color-info: #5bc0de;
31
+ $color-warning: #f0ad4e;
32
+ $color-danger: #fc4242;
33
+ $color-danger-hover: darken($color-danger, 20%);
37
34
 
38
35
  //== Scaffolding
39
36
  //
40
37
  //## Settings for some of the most global styles.
41
38
 
42
39
  //** Background color for `<body>`.
43
- $body-bg: $color-gray-lightest;
40
+ $body-bg: $color-gray-lightest;
44
41
  //** Global text color on `<body>`.
45
- $text-color: $color-gray-darker;
42
+ $text-color: $color-gray-darker;
46
43
 
47
44
  //** Global textual link color.
48
- $link-color: $color-primary;
45
+ $link-color: $color-primary;
49
46
  //** Link hover color set via `darken()` function.
50
- $link-hover-color: darken($link-color, 15%);
47
+ $link-hover-color: darken($link-color, 15%);
51
48
  //** Link hover decoration.
52
49
  $link-hover-decoration: underline;
53
50
 
54
-
55
51
  //== Typography
56
52
  //
57
53
  //## Font, line-height, and color for body text, headings, and more.
58
54
 
59
- $font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
60
- $font-family-serif: Georgia, "Times New Roman", Times, serif;
55
+ $font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
56
+ $font-family-serif: Georgia, "Times New Roman", Times, serif;
61
57
  //** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
62
- $font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
63
- $font-family-base: $font-family-sans-serif;
64
-
65
- $font-size-base: 14px;
66
- $font-size-large: ceil(($font-size-base * 1.25)); // ~18px
67
- $font-size-small: ceil(($font-size-base * 0.85)); // ~12px
58
+ $font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
59
+ $font-family-base: $font-family-sans-serif;
68
60
 
69
- $font-size-h1: floor(($font-size-base * 2.6)); // ~36px
70
- $font-size-h2: floor(($font-size-base * 2.15)); // ~30px
71
- $font-size-h3: ceil(($font-size-base * 1.7)); // ~24px
72
- $font-size-h4: ceil(($font-size-base * 1.25)); // ~18px
73
- $font-size-h5: $font-size-base;
74
- $font-size-h6: ceil(($font-size-base * 0.85)); // ~12px
61
+ $font-size-base: 14px;
62
+ $font-size-large: ceil(($font-size-base * 1.25)); // ~18px
63
+ $font-size-small: ceil(($font-size-base * 0.85)); // ~12px
75
64
 
65
+ $font-size-h1: floor(($font-size-base * 2.6)); // ~36px
66
+ $font-size-h2: floor(($font-size-base * 2.15)); // ~30px
67
+ $font-size-h3: ceil(($font-size-base * 1.7)); // ~24px
68
+ $font-size-h4: ceil(($font-size-base * 1.25)); // ~18px
69
+ $font-size-h5: $font-size-base;
70
+ $font-size-h6: ceil(($font-size-base * 0.85)); // ~12px
76
71
 
77
72
  // MIXINS
78
73
  // ------
79
74
  @mixin font-size( $pixels, $lineheight: $pixels, $default: $font-size-base ) {
80
- // NOTE this function works only if you put
75
+ // NOTE this function works only if you put
81
76
  // 'font-size: $font-size-base' in 'body' styles
82
- font-size: #{$pixels/$default}em;
77
+ font-size: #{$pixels/$default}em;
83
78
  line-height: #{$lineheight/$pixels}em;
84
79
  }
85
80
 
86
81
  @function kerning( $kerning ) {
87
82
  @return #{ $kerning / 1000 }em;
88
- }
83
+ }
@@ -1,19 +1,22 @@
1
1
  require_dependency "binda/application_controller"
2
2
 
3
3
  module Binda
4
- class ChoicesController < ApplicationController
4
+ class ChoicesController < ApplicationController
5
5
 
6
- before_action :set_choice
6
+ before_action :set_choice
7
7
 
8
- def destroy
9
- @choice.destroy
10
- head :ok
11
- end
8
+ def destroy
9
+ if @choice.destroy
10
+ head :ok
11
+ else
12
+ render json: { errors: @choice.errors.full_messages }, status: 500
13
+ end
14
+ end
12
15
 
13
- private
16
+ private
14
17
 
15
- def set_choice
16
- @choice = Choice.find( params[:id] )
17
- end
18
- end
18
+ def set_choice
19
+ @choice = Choice.find( params[:id] )
20
+ end
21
+ end
19
22
  end
@@ -9,10 +9,12 @@ module Binda
9
9
  include FieldableHelpers
10
10
 
11
11
  def index
12
- # if a specific order is requested otherwise order by position
13
- avilable_orders = ['LOWER(name) ASC', 'LOWER(name) DESC', 'publish_state ASC, LOWER(name) ASC', 'publish_state DESC, LOWER(name) ASC']
14
- params[:order] = avilable_orders[0] if params[:order].nil? || !avilable_orders.include?(params[:order])
15
- order = params[:order]
12
+ # set default value
13
+ order = 'LOWER(name) ASC'
14
+ unless params[:order].nil?
15
+ order_hash = params[:order].permit(:name, :publish_state).to_h
16
+ order = order_hash.map{|k,v| "LOWER(#{k}) #{v}"}.join(', ') if order_hash.any?
17
+ end
16
18
  @components = @structure.components.order(order).all.page params[:page]
17
19
  end
18
20
 
@@ -79,9 +79,13 @@ module Binda
79
79
  def add_new_field_groups
80
80
  new_params[:new_field_groups].each do |field_group|
81
81
  next if field_group[:name].blank?
82
- new_field_group = @structure.field_groups.create( name: field_group[:name], slug: field_group[:slug] )
83
- next if new_field_group
84
- return redirect_to structure_path( @structure.slug ), flash: { error: new_field_group.errors }
82
+ new_field_group = @structure.field_groups.create(name: field_group[:name], slug: field_group[:slug])
83
+ unless new_field_group
84
+ return redirect_to(
85
+ structure_path(@structure.slug),
86
+ flash: { error: new_field_group.errors }
87
+ )
88
+ end
85
89
  end
86
90
  end
87
91
  end
@@ -5,6 +5,7 @@ module Binda
5
5
  #
6
6
  # This helper generate the a link to the page where to sort components, or
7
7
  # a broken link that tells you that you have too many components to go to that page.
8
+ #
8
9
  def get_sort_index_link
9
10
  if @structure.components.length < Component.sort_limit
10
11
  link_to "<i class=\"fa fa-random\" aria-hidden=\"true\"></i>Sort #{ @structure.name.humanize.split.map(&:capitalize).join(' ').pluralize }".html_safe, structure_components_sort_index_path, class: 'main-header--link b-btn b-btn-primary'
@@ -13,17 +14,82 @@ module Binda
13
14
  end
14
15
  end
15
16
 
16
- # Prepare description for form hint
17
+ # Prepare description for form hint.
17
18
  #
18
19
  # This helper return the field description (as `string`) or false (as `boolean`)
19
20
  # in order to tell Simple Form whether to generate or not the hint html tag.
20
- def prepare_description_for_form_hint field_setting
21
+ #
22
+ # @param field_setting [Binda::FieldSetting] The field setting object
23
+ def prepare_description_for_form_hint(field_setting)
21
24
  if field_setting.description.blank?
22
25
  return false
23
- else
26
+ else
24
27
  return field_setting.description
25
28
  end
26
29
  end
27
30
 
31
+
32
+ # Prepare description for form hint belonging to select, radio and checkbox fields.
33
+ #
34
+ # This helper return the field description (as `string`) or false (as `boolean`)
35
+ # in order to tell Simple Form whether to generate or not the hint html tag.
36
+ #
37
+ # @param field_setting [Binda::FieldSetting] The field setting object
38
+ def prepare_description_for_selections_form_hint(field_setting)
39
+ description = []
40
+ unless field_setting.description.blank? && field_setting.allow_null?
41
+ description << field_setting.description unless field_setting.description.blank?
42
+ description << I18n.t("binda.null_is_not_allowed") if !field_setting.allow_null?
43
+ return description.join('. ')
44
+ else
45
+ return false
46
+ end
47
+ end
48
+
49
+ # Get sort link by argument
50
+ #
51
+ # This method returns a URL which contains the current sort options
52
+ # and update just the title one. The URL then is used to change the
53
+ # sorting of the index in which is used.
54
+ #
55
+ # Rails guide reference --> http://guides.rubyonrails.org/action_controller_overview.html#hash-and-array-parameters
56
+ #
57
+ # @param arg [string] This should be the database column on which sort will be based
58
+ # @return [string] The URL with the encoded parameters
59
+ #
60
+ def get_sort_link_by argument
61
+ arg = "#{argument}".to_sym
62
+ if params[:order].nil?
63
+ structure_components_path( [@structure], { order: {arg => "DESC"} } )
64
+ else
65
+ order_hash = params[:order].permit(:name, :publish_state).to_h
66
+ if order_hash[arg] == "ASC"
67
+ order_hash[arg] = "DESC"
68
+ structure_components_path( [@structure], { order: order_hash } )
69
+ else
70
+ order_hash[arg] = "ASC"
71
+ structure_components_path( [@structure], { order: order_hash } )
72
+ end
73
+ end
74
+ end
75
+
76
+ # Get sort link icon by argument
77
+ #
78
+ # This method returns a Font Awesome icon
79
+ #
80
+ # @param arg [string] This should be the database column on which sort will be based
81
+ # @return [string] The icon which needs to be escaped with the `html_safe` method
82
+ #
83
+ def get_sort_link_icon_by arg
84
+ case
85
+ when params[:order].nil?
86
+ '<i class="fas fa-sort-alpha-down"></i>'
87
+ when params[:order][arg] == "DESC"
88
+ '<i class="fas fa-sort-alpha-up"></i>'
89
+ else
90
+ '<i class="fas fa-sort-alpha-down"></i>'
91
+ end
92
+ end
93
+
28
94
  end
29
95
  end
@@ -1,26 +1,36 @@
1
1
  module Binda
2
2
  module FieldGroupsHelper
3
3
 
4
+
4
5
  def get_form_field_group_url
5
6
  return structure_field_groups_path if action_name == 'new'
6
7
  return structure_field_group_path if action_name == 'edit'
7
8
  end
8
9
 
9
- def get_relationable_components field_setting
10
+ def get_relationable_components(field_setting)
10
11
  if @instance.class.to_s == 'Binda::Component'
11
- Binda::Component.where( structure_id: Binda::Structure.where( id: field_setting.accepted_structure_ids )).where.not(id: @instance.id)
12
+ Binda::Component.where(structure_id: Binda::Structure.where(id: field_setting.accepted_structure_ids)).where.not(id: @instance.id)
12
13
  elsif @instance.class.to_s == 'Binda::Board'
13
- Binda::Component.where( structure_id: Binda::Structure.where( id: field_setting.accepted_structure_ids ))
14
+ Binda::Component.where(structure_id: Binda::Structure.where(id: field_setting.accepted_structure_ids))
14
15
  end
15
16
  end
16
17
 
17
- def get_relationable_boards field_setting
18
+ def get_relationable_boards(field_setting)
18
19
  if @instance.class.to_s == 'Binda::Component'
19
- Binda::Board.where( structure_id: Binda::Structure.where( id: field_setting.accepted_structure_ids ))
20
+ Binda::Board.where(structure_id: Binda::Structure.where(id: field_setting.accepted_structure_ids))
20
21
  elsif @instance.class.to_s == 'Binda::Board'
21
- Binda::Board.where( structure_id: Binda::Structure.where( id: field_setting.accepted_structure_ids )).where.not(id: @instance.id)
22
+ Binda::Board.where(structure_id: Binda::Structure.where(id: field_setting.accepted_structure_ids)).where.not(id: @instance.id)
22
23
  end
23
24
  end
24
25
 
26
+ def get_entries_number
27
+ instance_type = @structure.instance_type
28
+ if ['board', 'component'].include? instance_type
29
+ "Binda::#{instance_type.classify}".constantize.where(structure_id:@structure.id).count
30
+ else
31
+ 0
32
+ end
33
+ end
34
+
25
35
  end
26
36
  end
@@ -1,10 +1,7 @@
1
1
  module Binda
2
2
  module StructuresHelper
3
-
4
3
  def get_structures_sort_index_link
5
-
6
- link_to "<i class=\"fa fa-random\" aria-hidden=\"true\"></i>Sort Structures".html_safe, structures_sort_index_path, class: 'main-header--link b-btn b-btn-primary'
4
+ link_to "<i class=\"fa fa-random\" aria-hidden=\"true\"></i>Sort Structures".html_safe, structures_sort_index_path, class: 'main-header--link b-btn b-btn-primary'
7
5
  end
8
-
9
6
  end
10
7
  end
@@ -1,5 +1,8 @@
1
+ # require deprecations list which can be found in app/models/concerns/binda/deprecations.rb
2
+ require 'binda/deprecations'
3
+
1
4
  module Binda
2
5
  class ApplicationRecord < ActiveRecord::Base
3
6
  self.abstract_class = true
4
7
  end
5
- end
8
+ end
@@ -1,4 +1,6 @@
1
1
  module Binda
2
+ # Assets is a parent class which isn't directly used but can be referenced to gather
3
+ # all the classes that deal with files.
2
4
  class Asset < ApplicationRecord
3
5
 
4
6
  # Associations
@@ -6,4 +8,4 @@ module Binda
6
8
  belongs_to :field_setting
7
9
 
8
10
  end
9
- end
11
+ end
@@ -1,4 +1,5 @@
1
1
  module Binda
2
+ # This provides a convenient way to access Binda [default helpers](http://www.rubydoc.info/gems/binda/Binda/DefaultHelpers).
2
3
  class B < ApplicationRecord
3
4
  include DefaultHelpers
4
5
  end
@@ -7,6 +7,7 @@ module Binda
7
7
 
8
8
  # Validations
9
9
  validates :name, presence: true
10
+ validates :structure_id, presence: true
10
11
 
11
12
  # Slug
12
13
  extend FriendlyId
@@ -1,4 +1,6 @@
1
1
  module Binda
2
+ # This class provides support for checkboxes and depends on `Binda::Selection`.
3
+ # You can find more info at the _selection_ [documentation](http://www.rubydoc.info/gems/binda/Binda/Selection)
2
4
  class Checkbox < Selection
3
5
 
4
6
  end
@@ -1,31 +1,73 @@
1
1
  module Binda
2
+ # Choices are used in **select**, **radio** and **checkboxes** and defined by a **field setting**.
3
+ #
4
+ # The architecture of this class is a bit complex and deserves some attention:
5
+ # Here the rules that defines the class behaviour:
6
+ #
7
+ # 1. **Choices** must be associated to a **field setting**
8
+ # 2. Every **choice** can be associated to several **select/radio/checkbox**
9
+ # 3. (This is tricky) Assuming you are going to delete a choice and 1) **field setting** requires at least one choice
10
+ # 2) some **select/checkbox/radio** are associated just to that **choice**. To be able to do it you must first replace
11
+ # that **choice** on those **select/checkbox/radio**. Only then you can delete that **choice**.
12
+ #
13
+ # The **default choice** is applied only to field that requires at least a **choice**.
2
14
  class Choice < ApplicationRecord
3
15
 
4
16
  belongs_to :field_setting
5
17
  has_and_belongs_to_many :selections
6
18
 
7
- validates :label, presence: true
8
- validates :value, presence: true
9
- validates :field_setting_id, presence: true
10
-
19
+ validates :label, presence: {
20
+ message: I18n.t('binda.choice.label_validation_message')
21
+ }
22
+ validates :value, presence: {
23
+ message: I18n.t('binda.choice.value_validation_message')
24
+ }
25
+ validates :field_setting_id, presence: {
26
+ message: I18n.t('binda.choice.field_setting_id_validation_message')
27
+ }
28
+
29
+ before_destroy :check_last_choice
11
30
  after_create :set_default_choice
12
31
  after_destroy :reset_default_choice
13
32
 
33
+ # Some field setting requires at least one choice. To avoid leaving this kind of field setting without
34
+ # any choice, a validation checks that there is at least an alternative choice that will become the default one.
35
+ # This validation is skipped when deleting the field setting from which the choice depends because choice are
36
+ # deleted directly from database (see `dependent: :delete_all`).
37
+ def check_last_choice
38
+ if !self.field_setting.allow_null? && Choice.where(field_setting_id: self.field_setting.id).length == 1
39
+ errors.add(:base, I18n.t('binda.choice.validation_message.destroy'))
40
+ throw(:abort)
41
+ end
42
+ end
43
+
14
44
  # In order to make sure that a default choice is set, this method is executed after
15
45
  # the first choice is associated to the field setting. What does it do?
16
46
  # If there isn't a default it sets the current choice as the default one.
17
47
  # The method is executed as well if new choices are added.
18
48
  def set_default_choice
19
-
20
49
  # Make sure you are referring to the updated ActiveRecord object where the choice has already been deleted
21
50
  # Infact: self.field_setting != FieldSetting.find( self.field_setting.id )
22
51
  field_setting = FieldSetting.find(self.field_setting.id)
23
-
24
- # unless Choice.find(field_setting.default_choice_id).present?
25
- return unless field_setting.default_choice_id.nil?
26
- field_setting.default_choice_id = self.id
27
- unless field_setting.save
28
- raise "It hasn't been possible to set the default choice for the current setting (#{field_setting.slug})."
52
+
53
+ if field_setting.default_choice_id.nil? && !field_setting.allow_null?
54
+ field_setting.default_choice_id = self.id
55
+ unless field_setting.save
56
+ raise "It hasn't been possible to set the default choice for the current setting (#{field_setting.slug})."
57
+ end
58
+ assign_choice_to_selections(field_setting, self)
59
+ end
60
+ end
61
+
62
+ # Assign a choice to `Binda::Selection` items belonging to a specific field setting.
63
+ # @param field_setting [Binda::FieldSetting]
64
+ # @param new_default_choice [Binda::Choice]
65
+ def assign_choice_to_selections(field_setting, new_default_choice)
66
+ Selection.where(field_setting_id: field_setting.id).each do |selection|
67
+ selection.choices << new_default_choice
68
+ unless selection.save
69
+ raise "It hasn't been possible to set the default choice for #{selection.class.name} with id=#{selection.id}."
70
+ end
29
71
  end
30
72
  end
31
73
 
@@ -33,54 +75,45 @@ module Binda
33
75
  # default choice is removed. What does it do? If the removed choice is the default one it sets
34
76
  # another defautl picking the first of the choices associated by id.
35
77
  # Once done, update all associated records that now don't have the any associated choice.
78
+ #
79
+ # This method doesn't run when a field setting is destroyed as the association is
80
+ # `Binda::FieldSetting has_many :choices, dependent: :delete_all` not `dependent: :destory`.
81
+ # That means the `after_destroy` callback for Binda::Choice (and this method as well) won't run.
36
82
  def reset_default_choice
37
-
38
83
  # Make sure you are referring to the updated ActiveRecord object where the choice has already been deleted
39
- # Infact: self.field_setting != FieldSetting.find( self.field_setting.id )
84
+ # Infact: self.field_setting != FieldSetting.find(self.field_setting.id)
40
85
  field_setting = FieldSetting.find(self.field_setting.id)
41
86
 
42
87
  # Don't do anything if the default choice isn't the one we just destroyed
43
- return if field_setting.choice_ids.include? field_setting.default_choice_id
88
+ return if field_setting.choice_ids.include?(field_setting.default_choice_id)
44
89
 
45
90
  # Make sure the default choice is needed
46
91
  return if field_setting.allow_null? && field_setting.field_type != 'radio'
47
92
 
48
-
49
93
  if field_setting.choices.any?
50
94
  # Mark as default choice the first choice available
51
- field_setting.default_choice_id = field_setting.choices.first.id
95
+ update_default_choice(field_setting, field_setting.choices.first.id)
52
96
  else
97
+ warn("WARNING: Binda::FieldSetting \"#{field_setting.slug}\" doesn't have any default choice! Please set a new default choice and then run the following command from Rails Console to update all related Binda::Selection records: \nrails binda:add_default_choice_to_all_selections_with_no_choices")
53
98
  # Remove default choice setting (which at this point is the current choice (self))
54
- field_setting.default_choice_id = nil
99
+ update_default_choice(field_setting, nil)
55
100
  end
56
101
 
57
- # Update field setting with the new default choice
58
- update_default_choice_of field_setting
59
- end
60
-
61
- # Update field setting with a default choice
62
- #
63
- # This method is used by reset_default_choice method.
64
- #
65
- # @param field_setting [ActiveRecord Object]
66
- def update_default_choice_of field_setting
67
-
68
- # Save and check if it's alright
69
- raise "It hasn't been possible to set the default choice for the current setting (#{field_setting.slug})." unless field_setting.save
70
-
71
- # Create an empty array in order to avoid generating an error on the following each loop
72
- selections = Selection.joins(:field_setting).where(binda_field_settings: {id: field_setting.id })
73
-
74
- # Make sure none of the Binda::Selection instances (radios/checkboxes/selects) are left without a choice
75
- update_selection selections
102
+ # Update all selection records which depend on the deleted choice
103
+ Selection.check_all_selections_depending_on(field_setting)
76
104
  end
77
105
 
78
106
  private
79
- def update_selection selections
80
- selections.each do |selection|
81
- next if selection.choices.any?
82
- selection.choices << Choice.find(self.field_setting.default_choice_id)
83
- raise "It hasn't been possible to set the default choice for Binda::Selection with id=#{selection.id}" unless selection.save
107
+
108
+ # Update field setting with a default choice
109
+ #
110
+ # This is private method for reset_default_choice method.
111
+ #
112
+ # @param field_setting [ActiveRecord Object]
113
+ def update_default_choice(field_setting, id)
114
+ # Update and check if it's alright
115
+ unless field_setting.update(default_choice_id: id)
116
+ raise "It hasn't been possible to set the default choice for the current setting (#{field_setting.slug})."
84
117
  end
85
118
  end
86
119