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,4 +1,8 @@
1
1
  module Binda
2
+ # This class depends on `Binda::Text` and it's use mainly to differentiate the type of text
3
+ # this class is responsible for.
4
+ #
5
+ # Binda uses this class to store plain text. The field responsible to store `Binda::String` instances is `type="string"`.
2
6
  class String < Text
3
7
  end
4
8
  end
@@ -12,7 +12,11 @@ module Binda
12
12
  # Validations
13
13
  validates :name, presence: true
14
14
  validates :slug, uniqueness: true
15
- validates :instance_type, presence: true, inclusion: { in: %w(component board), message: "%{value} is not a valid instance" }
15
+ validates_associated :field_groups
16
+ validates :instance_type, presence: true, inclusion: {
17
+ in: %w(component board),
18
+ message: I18n.t('binda.structure.validation_message.instance_type', { arg1: "%{value}" })
19
+ }
16
20
  accepts_nested_attributes_for :field_groups, allow_destroy: true, reject_if: :is_rejected
17
21
 
18
22
  # Slug
@@ -20,7 +24,7 @@ module Binda
20
24
  friendly_id :default_slug, use: [:slugged, :finders]
21
25
 
22
26
  after_create :add_default_field_group
23
- after_create :add_instance_details
27
+ after_save :add_instance_details
24
28
  after_create :set_default_position
25
29
 
26
30
  # Friendly id preference on slug generation
@@ -28,12 +32,12 @@ module Binda
28
32
  # Method inherited from friendly id
29
33
  # @see https://github.com/norman/friendly_id/issues/436
30
34
  def should_generate_new_friendly_id?
31
- slug.blank? || name_changed?
35
+ slug.blank?
32
36
  end
33
37
 
34
38
  #
35
39
  # Sets the validation rules to accept and save an attribute
36
- def is_rejected( attributes )
40
+ def is_rejected(attributes)
37
41
  attributes['name'].blank?
38
42
  end
39
43
 
@@ -41,10 +45,10 @@ module Binda
41
45
  #
42
46
  # It generates 4 possible slugs before falling back to FriendlyId default behaviour
43
47
  def default_slug
44
- [ "#{ self.name }",
45
- "#{ self.name }-1",
46
- "#{ self.name }-2",
47
- "#{ self.name }-3" ]
48
+ [ "#{ self.name.parameterize }",
49
+ "#{ self.name.parameterize }-1",
50
+ "#{ self.name.parameterize }-2",
51
+ "#{ self.name.parameterize }-3" ]
48
52
  end
49
53
 
50
54
  # Add a field group as a default
@@ -54,10 +58,10 @@ module Binda
54
58
  # @return [redirect]
55
59
  def add_default_field_group
56
60
  # Creates a default empty field group
57
- field_group = self.field_groups.build( name: 'General Details', position: 1 )
61
+ field_group = self.field_groups.build(name: I18n.t('binda.default_field_group.name'), position: 1)
58
62
  # Unless there is a problem...
59
63
  unless field_group.save
60
- return redirect_to structure_path( self.slug ), flash: { error: 'General Details group hasn\'t been created' }
64
+ return redirect_to structure_path(self.slug), flash: { error: I18n.t('binda.default_field_group.error_on_create') }
61
65
  end
62
66
  end
63
67
 
@@ -68,10 +72,17 @@ module Binda
68
72
  # It also disable categories (this could be a different method, or method could be more explicit)
69
73
  def add_instance_details
70
74
  if self.instance_type == 'board'
71
- self.update_attribute 'has_categories', false
75
+ self.update_attribute('has_categories', false)
76
+ add_default_board
77
+ end
78
+ end
79
+
80
+ # Add default board to a structure if needed
81
+ def add_default_board
82
+ if Board.where(structure_id: self.id).empty?
72
83
  board = self.build_board( name: self.name )
73
84
  unless board.save
74
- return redirect_to structure_path( self.slug ), flash: { error: 'The board instance hasn\'t been created' }
85
+ return redirect_to structure_path(self.slug), flash: { error: I18n.t('binda.default_field_group.error_on_create') }
75
86
  end
76
87
  end
77
88
  end
@@ -83,8 +94,8 @@ module Binda
83
94
  #
84
95
  # @return [object] Repeater instance
85
96
  def set_default_position
86
- position = Structure.all.length
87
- self.update_attribute 'position', position
97
+ position = Structure.all.length
98
+ self.update_attribute('position', position)
88
99
  end
89
100
 
90
101
  end
@@ -1,9 +1,18 @@
1
1
  module Binda
2
+ # This class provides support for storing text. It can be called directly to get texts,
3
+ # or referenced to call other classes depending on it that deal differently with text.
4
+ #
5
+ # Binda uses this class to store complex texts usually with rich HTML features. On the admin panel infact
6
+ # this field is represented by a WYSIWYG. But this is just a admin panel convention: the class can infact store
7
+ # a simple string of text as well.
2
8
  class Text < ApplicationRecord
3
9
 
4
10
  # Associations
5
11
  belongs_to :fieldable, polymorphic: true
6
12
  belongs_to :field_setting
7
13
 
14
+ validates :fieldable_id, presence: true
15
+ validates :fieldable_type, presence: true
16
+
8
17
  end
9
18
  end
@@ -1,4 +1,5 @@
1
1
  module Binda
2
+ # This class provides support for uploading videos.
2
3
  class Video < Asset
3
4
 
4
5
  mount_uploader :video, VideoUploader
@@ -3,9 +3,6 @@ module Binda
3
3
  module DefaultHelpers
4
4
  extend ActiveSupport::Concern
5
5
 
6
- included do
7
- end
8
-
9
6
  class_methods do
10
7
 
11
8
  # Get components
@@ -35,14 +32,14 @@ module Binda
35
32
  # @param slug [string] The slug of the structure to which the components belong
36
33
  # @param slug [array] The slugs of the structures to which the components belongs
37
34
  #
38
- # @return [ActiveRelation Object] if slug is nil or is an array
35
+ # @return [ActiveRecord::Relation Object] if slug is nil or is an array
39
36
  #
40
- def get_components slug = nil
37
+ def get_components(slug = nil)
41
38
  if slug.nil?
42
39
  Component.all
43
40
  else
44
41
  # Generate query
45
- Component.where( structure_id: Structure.where( slug: slug ) )
42
+ Component.where(structure_id: Structure.where(slug: slug))
46
43
  end
47
44
  end
48
45
 
@@ -64,13 +61,13 @@ module Binda
64
61
  # @param slug [string] The slug of the structure on which the board is based
65
62
  # @param slug [array] The slugs of the structures to which the board belongs
66
63
  #
67
- # @return [ActiveRelation Object] if slug is nil or is an array
64
+ # @return [ActiveRecord::Relation Object] if slug is nil or is an array
68
65
  #
69
- def get_boards slug = nil
66
+ def get_boards(slug = nil)
70
67
  if slug.nil?
71
68
  Board.all
72
69
  else
73
- Board.where( structure_id: Structure.where( slug: slug ) )
70
+ Board.where(structure_id: Structure.where(slug: slug))
74
71
  end
75
72
  end
76
73
 
@@ -92,13 +89,13 @@ module Binda
92
89
  # @param slug [string] The slug of the structure to which categories belong
93
90
  # @param slug [array] The slugs of the structures to which categories belong
94
91
  #
95
- # @return [ActiveRelation Object]
92
+ # @return [ActiveRecord::Relation Object]
96
93
  #
97
- def get_categories slug = nil
94
+ def get_categories(slug = nil)
98
95
  if slug.nil?
99
96
  Category.all
100
97
  else
101
- Category.where( structure_id: Structure.where( slug: slug ) )
98
+ Category.where(structure_id: Structure.where(slug: slug))
102
99
  end
103
100
  end
104
101
 
@@ -112,14 +109,14 @@ module Binda
112
109
  # # returns all field settings
113
110
  #
114
111
  # B.get_field_settings('subtitle')
115
- # # returns an ActiveRelation (a sort of Array) containing the 'subtitle' field setting
112
+ # # returns an ActiveRecord::Relation (a sort of Array) containing the 'subtitle' field setting
116
113
  #
117
114
  # @param slug [string] The slug of a specific field setting
118
115
  # @param slug [array] The slugs of the selected field settings
119
116
  #
120
- # @return [ActiveRelation Object]
117
+ # @return [ActiveRecord::Relation]
121
118
  #
122
- def get_field_settings slug = nil
119
+ def get_field_settings(slug = nil)
123
120
  if slug.nil?
124
121
  FieldSetting.all
125
122
  else
@@ -134,14 +131,14 @@ module Binda
134
131
  #
135
132
  # @return [Array]
136
133
  #
137
- def get_relation_owners field_slug
134
+ def get_relation_owners(field_slug)
138
135
  owner_class = Structure.includes(field_groups: :field_settings)
139
- .where(binda_field_settings: {id: FieldSetting.where(slug: field_slug)})
136
+ .where(binda_field_settings: { id: FieldSetting.where(slug: field_slug) })
140
137
  .first
141
138
  obj = "Binda::#{owner_class.instance_type.classify}".constantize
142
139
  .distinct
143
140
  .includes(relations: :dependent_components)
144
- .where(binda_relations: {field_setting_id: FieldSetting.where(slug: field_slug)})
141
+ .where(binda_relations: { field_setting_id: FieldSetting.where(slug: field_slug) })
145
142
  raise ArgumentError, "There isn't any instance with a relation associated to the current slug (#{field_slug}).", caller if obj.nil?
146
143
  return obj
147
144
  end
@@ -162,25 +159,37 @@ module Binda
162
159
  #
163
160
  # @return [Array]
164
161
  #
165
- def get_relation_dependents field_slug, instance_type = nil
162
+ def get_relation_dependents(field_slug, instance_type = nil)
166
163
  raise ArgumentError, "There isn't any instance named: #{instance_type}. Make sure is either 'component' or 'board'", caller if !instance_type.nil? && ['board','component'].include?(instance_type)
167
164
 
168
- dependents = []
169
- if instance_type != 'board'
170
- dependent_components = Component.distinct
171
- .includes(:owner_components)
172
- .where(binda_relations: {field_setting_id: FieldSetting.where(slug: field_slug)})
173
- dependents = [ *dependents, *dependent_components ]
174
- elsif instance_type != 'component'
175
- dependent_boards = Board.distinct
176
- .includes(:owner_components)
177
- .where(binda_relations: {field_setting_id: FieldSetting.where(slug: field_slug)})
178
- dependents = [ *dependents, *dependent_boards ]
179
- end
165
+ dependents = get_dependents(instance_type, field_slug)
180
166
 
181
167
  raise ArgumentError, "There isn't any instance with a relation associated to the current slug (#{field_slug}).", caller unless dependents.any?
182
168
  return dependents
183
169
  end
170
+
171
+ private
172
+
173
+ # Get dependents based on slug and instance type
174
+ #
175
+ # @param instance_type [string] The instance type of the record (either board or component)
176
+ # @param field_slug [string] The record slug
177
+ # @return [array] Array of ActiveRecord dependents
178
+ def get_dependents(instance_type, field_slug)
179
+ dependents = []
180
+ if instance_type != 'board'
181
+ dependent_components = Component.distinct
182
+ .includes(:owner_components)
183
+ .where(binda_relations: { field_setting_id: FieldSetting.where(slug: field_slug) })
184
+ dependents = [ *dependents, *dependent_components ]
185
+ elsif instance_type != 'component'
186
+ dependent_boards = Board.distinct
187
+ .includes(:owner_components)
188
+ .where(binda_relations: { field_setting_id: FieldSetting.where(slug: field_slug) })
189
+ dependents = [ *dependents, *dependent_boards ]
190
+ end
191
+ return dependents
192
+ end
184
193
  end
185
194
  end
186
195
  end
@@ -0,0 +1,6 @@
1
+ Binda::Deprecation
2
+ .new
3
+ .deprecate_methods(
4
+ Binda::FieldableAssociations,
5
+ get_selection_choice: :get_selection_choices
6
+ )
@@ -0,0 +1,366 @@
1
+ module Binda
2
+ module FieldableAssociationHelpers
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ # Get the object related to that field setting
7
+ # If the object doesn't exists yet it will return nil
8
+ #
9
+ # @param field_slug [string] The slug of the field setting
10
+ # @return [string] Returns the content of the text
11
+ # @return [error] Raise an error if no record is found
12
+ def get_text(field_slug)
13
+ obj = self.texts.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) && t.type != 'Binda::String' }
14
+ unless obj.nil?
15
+ obj.content
16
+ else
17
+ check_text_error field_slug
18
+ end
19
+ end
20
+
21
+ # Check why get_text doesn't return a value
22
+ # This method isn't supposed to be used by anything other than get_text method
23
+ def check_text_error(field_slug)
24
+ you_mean_string = !self.strings.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) && t.type = 'Binda::String' }.nil?
25
+ if you_mean_string
26
+ raise ArgumentError, "This slug (#{field_slug}) is associated to a string not a text. Use get_string() instead on instance (#{self.class.name} ##{self.id}).", caller
27
+ else
28
+ raise ArgumentError, "There isn't any text associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller
29
+ end
30
+ end
31
+
32
+ # Get the object related to that field setting
33
+ #
34
+ # @param field_slug [string] The slug of the field setting
35
+ # @return [boolean]
36
+ def has_text(field_slug)
37
+ obj = self.texts.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) && t.type != 'Binda::String' }
38
+ raise ArgumentError, "There isn't any text associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
39
+ if obj.present?
40
+ return !obj.content.nil?
41
+ else
42
+ return false
43
+ end
44
+ end
45
+
46
+ # Get the object related to that field setting
47
+ # If the object doesn't exists yet it will return nil
48
+ #
49
+ # @param field_slug [string] The slug of the field setting
50
+ # @return [string] Returns the content of the string
51
+ # @return [error] Raise an error if no record is found
52
+ def get_string(field_slug)
53
+ obj = self.strings.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) && t.type == 'Binda::String' }
54
+ unless obj.nil?
55
+ obj.content
56
+ else
57
+ check_string_error field_slug
58
+ end
59
+ end
60
+
61
+ # Check why get_string doesn't return a value
62
+ # This method isn't supposed to be used by anything other than get_string method
63
+ def check_string_error(field_slug)
64
+ you_mean_text = !self.strings.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) && t.type = 'Binda::Text' }.nil?
65
+ if you_mean_text
66
+ raise ArgumentError, "This slug (#{field_slug}) is associated to a text not a string. Use get_text() instead on instance (#{self.class.name} ##{self.id}).", caller
67
+ else
68
+ raise ArgumentError, "There isn't any string associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller
69
+ end
70
+ end
71
+
72
+ # Get the object related to that field setting
73
+ #
74
+ # @param field_slug [string] The slug of the field setting
75
+ # @return [boolean]
76
+ def has_string(field_slug)
77
+ obj = self.strings.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) && t.type == 'Binda::String' }
78
+ raise ArgumentError, "There isn't any string associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
79
+ if obj.present?
80
+ return !obj.content.nil?
81
+ else
82
+ return false
83
+ end
84
+ end
85
+
86
+ # Check if the field has an attached image
87
+ #
88
+ # @param field_slug [string] The slug of the field setting
89
+ # @return [boolean]
90
+ def has_image(field_slug)
91
+ obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
92
+ # Alternative query
93
+ # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first
94
+ raise ArgumentError, "There isn't any image associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
95
+ return obj.image.present?
96
+ end
97
+
98
+ # Get the image url based on the size provided,
99
+ # default is Carrierwave default (usually the real size)
100
+ #
101
+ # @param field_slug [string] The slug of the field setting
102
+ # @param size [string] The size. It can be 'thumb' 200x200 cropped,
103
+ # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank
104
+ # @return [string] The url of the image
105
+ def get_image_url(field_slug, size = '')
106
+ get_image_info( field_slug, size, 'url' )
107
+ end
108
+
109
+ # Get the image path based on the size provided,
110
+ # default is Carrierwave default (usually the real size)
111
+ #
112
+ # @param field_slug [string] The slug of the field setting
113
+ # @param size [string] The size. It can be 'thumb' 200x200 cropped,
114
+ # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank
115
+ # @return [string] The url of the image
116
+ def get_image_path(field_slug, size = '')
117
+ get_image_info( field_slug, size, 'path' )
118
+ end
119
+
120
+ # Get the object related to that field setting
121
+ #
122
+ # @param field_slug [string] The slug of the field setting
123
+ # @param size [string] The size. It can be 'thumb' 200x200 cropped,
124
+ # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank
125
+ # @param info [string] String of the info to be retrieved
126
+ # @return [string] The info requested if present
127
+ # @return [boolean] Returns false if no info is found or if image isn't found
128
+ def get_image_info(field_slug, size, info)
129
+ obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
130
+ # Alternative query
131
+ # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first
132
+ raise ArgumentError, "There isn't any image associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
133
+ if obj.image.present? && obj.image.respond_to?(size) && %w[thumb medium large].include?(size)
134
+ obj.image.send(size).send(info)
135
+ elsif obj.image.present?
136
+ obj.image.send(info)
137
+ else
138
+ raise "Looks like the image you are looking for isn't present. See field setting with slug=\"#{field_slug}\" on component with id=\"self.id\""
139
+ end
140
+ end
141
+
142
+ def get_image_dimension(field_slug)
143
+ obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
144
+
145
+ raise ArgumentError, "There isn't any image associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
146
+ if obj.image.present? && obj.image.respond_to?(size) && %w[thumb medium large].include?(size)
147
+ obj.image.send(size).send(info)
148
+ elsif obj.image.present?
149
+ obj.image.send(info)
150
+ else
151
+ raise "Looks like the image you are looking for isn't present. See field setting with slug=\"#{field_slug}\" on component with id=\"self.id\""
152
+ end
153
+ end
154
+
155
+ # Check if the field has an attached video
156
+ #
157
+ # @param field_slug [string] The slug of the field setting
158
+ # @return [boolean]
159
+ def has_video(field_slug)
160
+ obj = self.videos.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
161
+ # Alternative query
162
+ # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first
163
+ raise ArgumentError, "There isn't any video associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
164
+ return obj.video.present?
165
+ end
166
+
167
+ # Get the video url based on the size provided,
168
+ # default is Carrierwave default (usually the real size)
169
+ #
170
+ # @param field_slug [string] The slug of the field setting
171
+ # @param size [string] The size. It can be 'thumb' 200x200 cropped,
172
+ # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank
173
+ # @return [string] The url of the video
174
+ def get_video_url(field_slug)
175
+ get_video_info( field_slug, 'url' )
176
+ end
177
+
178
+ # Get the video path based on the size provided,
179
+ # default is Carrierwave default (usually the real size)
180
+ #
181
+ # @param field_slug [string] The slug of the field setting
182
+ # @param size [string] The size. It can be 'thumb' 200x200 cropped,
183
+ # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank
184
+ # @return [string] The url of the video
185
+ def get_video_path(field_slug)
186
+ get_video_info( field_slug, 'path' )
187
+ end
188
+
189
+ # Get the object related to that field setting
190
+ #
191
+ # @param field_slug [string] The slug of the field setting
192
+ # @param info [string] String of the info to be retrieved
193
+ # @return [string] The info requested if present
194
+ # @return [boolean] Returns false if no info is found or if image isn't found
195
+ def get_video_info(field_slug, info)
196
+ obj = self.videos.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
197
+ # Alternative query
198
+ # obj = video.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first
199
+ raise ArgumentError, "There isn't any video associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
200
+ if obj.video.present?
201
+ obj.video.send(info)
202
+ end
203
+ end
204
+
205
+ # Check if the field has an attached date
206
+ #
207
+ # @param field_slug [string] The slug of the field setting
208
+ # @return [datetime] The date
209
+ # @return [boolean] Reutrn false if nothing is found
210
+ def has_date(field_slug)
211
+ obj = self.dates.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
212
+ raise ArgumentError, "There isn't any date associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
213
+ if obj.present?
214
+ return !obj.date.nil?
215
+ else
216
+ return false
217
+ end
218
+ end
219
+
220
+ # Get the object related to that field setting
221
+ #
222
+ # @param field_slug [string] The slug of the field setting
223
+ # @return [boolean]
224
+ def get_date(field_slug)
225
+ obj = self.dates.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
226
+ raise ArgumentError, "There isn't any date associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
227
+ obj.date
228
+ end
229
+
230
+ # Check if exists any repeater with that slug
231
+ #
232
+ # @param field_slug [string] The slug of the field setting
233
+ # @return [boolean]
234
+ def has_repeater(field_slug)
235
+ obj = self.repeaters.find_all{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
236
+ raise ArgumentError, "There isn't any repeater associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
237
+ return obj.present?
238
+ end
239
+
240
+ # Get the all repeater instances sorted by position
241
+ #
242
+ # @param field_slug [string] The slug of the field setting
243
+ # @return [array] An array of repeater items which have all sorts of fields attached
244
+ def get_repeater(field_slug)
245
+ obj = self.repeaters.find_all{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
246
+ raise ArgumentError, "There isn't any repeater associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
247
+ obj.sort_by(&:position)
248
+ end
249
+
250
+ # Get the radio choice
251
+ #
252
+ # If by mistake the Radio instance has many choices associated,
253
+ # only the first one will be retrieved.
254
+ #
255
+ # @param field_slug [string] The slug of the field setting
256
+ # @return [hash] A hash of containing the label and value of the selected choice. `{ label: 'the label', value: 'the value'}`
257
+ def get_radio_choice(field_slug)
258
+ field_setting = FieldSetting.find_by(slug:field_slug)
259
+ obj = self.radios.find{ |t| t.field_setting_id == field_setting.id }
260
+ raise ArgumentError, "There isn't any radio associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
261
+ raise "There isn't any choice available for the current radio (#{field_slug}) on instance (#{self.class.name} ##{self.id})." unless obj.choices.any?
262
+ return { label: obj.choices.first.label, value: obj.choices.first.value }
263
+ end
264
+
265
+ # Get the select choices
266
+ #
267
+ # @param field_slug [string] The slug of the field setting
268
+ # @return [hash] A hash of containing the label and value of the selected choice. `{ label: 'the label', 'value': 'the value'}`
269
+ def get_selection_choice(field_slug)
270
+ field_setting = FieldSetting.find_by(slug:field_slug)
271
+ obj = self.selections.find{ |t| t.field_setting_id == field_setting.id }
272
+ raise ArgumentError, "There isn't any selection associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
273
+ raise "There isn't any choice available for the current selection (#{field_slug}) on instance (#{self.class.name} ##{self.id})." unless field_setting.choices.any?
274
+ return { label: obj.choices.first.label, value: obj.choices.first.value }
275
+ end
276
+
277
+ # Get the select choices
278
+ #
279
+ # @param field_slug [string] The slug of the field setting
280
+ # @return [array] An array of hashes of containing label and value of the selected choices. `{ label: 'the label', 'value': 'the value'}`
281
+ def get_selection_choices(field_slug)
282
+ field_setting = FieldSetting.find_by(slug:field_slug)
283
+ obj = self.selections.find{ |t| t.field_setting_id == field_setting.id }
284
+ raise ArgumentError, "There isn't any selection associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
285
+ raise "There isn't any choice available for the current selection (#{field_slug}) on instance (#{self.class.name} ##{self.id})." unless field_setting.choices.any?
286
+ return obj.choices.map{|choice| { label: choice.label, value: choice.value }}
287
+ end
288
+
289
+ # Get the checkbox choice
290
+ #
291
+ # @param field_slug [string] The slug of the field setting
292
+ # @return [array] An array of labels and values of the selected choices. `[{ label: '1st label', value: '1st-value'}, { label: '2nd label', value: '2nd-value'}]`
293
+ def get_checkbox_choices(field_slug)
294
+ field_setting = FieldSetting.find_by(slug:field_slug)
295
+ obj = self.checkboxes.find{ |t| t.field_setting_id == field_setting.id }
296
+ raise ArgumentError, "There isn't any checkbox associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
297
+ raise "There isn't any choice available for the current checkbox (#{field_slug}) on instance (#{self.class.name} ##{self.id})." unless field_setting.choices.any?
298
+ obj_array = []
299
+ obj.choices.order('label').each do |o|
300
+ obj_array << { label: o.label, value: o.value }
301
+ end
302
+ return obj_array
303
+ end
304
+
305
+ # Check if has related components
306
+ #
307
+ # @param field_slug [string] The slug of the field setting
308
+ # @return [boolean]
309
+ def has_related_components(field_slug)
310
+ obj = self.relations.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
311
+ raise ArgumentError, "There isn't any related field associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
312
+ return obj.dependent_relations.any?
313
+ end
314
+
315
+ # Alias for has_related_components
316
+ def has_dependent_components(field_slug)
317
+ has_related_components(field_slug)
318
+ end
319
+
320
+ # Get related components
321
+ #
322
+ # @param field_slug [string] The slug of the field setting
323
+ # @return [array] An array of components
324
+ def get_related_components(field_slug)
325
+ obj = self.relations.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
326
+ raise ArgumentError, "There isn't any related field associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
327
+ return obj.dependent_relations.map{|relation| relation.dependent}
328
+ end
329
+
330
+ # Alias for get_related_components
331
+ def get_dependent_components(field_slug)
332
+ get_related_components(field_slug)
333
+ end
334
+
335
+ # Get all components which owns a relation where the current instance is a dependent
336
+ #
337
+ # @param field_slug [string] The slug of the field setting of the relation
338
+ # @return [array] An array of components and/or boards
339
+ def get_owner_components(field_slug)
340
+ # obj = self.owner_relations.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
341
+ obj = Relation.where(field_setting_id: B.get_field_settings(field_slug)).includes(dependent_relations: :dependent).where(binda_relation_links: {dependent_type: self.class.name})
342
+ raise ArgumentError, "There isn't any relation associated to the current slug (#{field_slug}) where the current instance (#{self.class.name} ##{self.id}) is a dependent.", caller if obj.nil?
343
+ return obj
344
+ end
345
+
346
+ # Check if has related boards
347
+ #
348
+ # @param field_slug [string] The slug of the field setting
349
+ # @return [boolean]
350
+ def has_related_boards(field_slug)
351
+ obj = self.relations.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) }
352
+ raise ArgumentError, "There isn't any related field associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
353
+ return obj.dependent_relations.any?
354
+ end
355
+
356
+ # Get related boards
357
+ #
358
+ # @param field_slug [string] The slug of the field setting
359
+ # @return [array] An array of boards
360
+ def get_related_boards(field_slug)
361
+ obj = self.relations.find{ |t| t.field_setting_idid == FieldSetting.get_id( field_slug ) }
362
+ raise ArgumentError, "There isn't any related field associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil?
363
+ return obj.dependent_relations.map{|relation| relation.dependent}
364
+ end
365
+ end
366
+ end