web47core 3.2.38 → 3.2.51

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/app/helpers/core_card_nav_items_helper.rb +6 -6
  3. data/app/helpers/core_dropdown_helper.rb +8 -8
  4. data/app/helpers/core_floating_action_button_helper.rb +8 -8
  5. data/app/helpers/core_form_checkbox_helper.rb +43 -0
  6. data/app/helpers/core_form_helper.rb +195 -160
  7. data/app/helpers/core_form_input_helper.rb +74 -0
  8. data/app/helpers/core_form_select_helper.rb +65 -0
  9. data/app/helpers/core_form_textarea_helper.rb +26 -0
  10. data/app/helpers/core_table_helper.rb +23 -0
  11. data/app/helpers/model_modal_helper.rb +19 -19
  12. data/app/helpers/svg_icon_helper.rb +6 -3
  13. data/app/views/cron_servers/index.html.haml +3 -3
  14. data/app/views/cron_tabs/index.html.haml +1 -1
  15. data/app/views/delayed_job_workers/index.html.haml +3 -3
  16. data/app/views/delayed_jobs/index.html.haml +4 -0
  17. data/app/views/icons/_bed-filled.html.erb +1 -0
  18. data/app/views/icons/_bed-outline.html.erb +1 -0
  19. data/app/views/icons/_binary-tree-2.html.erb +1 -0
  20. data/app/views/icons/_cancel.html.erb +1 -0
  21. data/app/views/icons/_circle-plus-filled.html.erb +1 -0
  22. data/app/views/icons/_circle-plus-outline.html.erb +1 -0
  23. data/app/views/icons/_dots-vertical.html.erb +1 -0
  24. data/app/views/icons/_edit.html.erb +1 -0
  25. data/app/views/icons/_heartbeat.html.erb +1 -0
  26. data/app/views/icons/_hourglass.html.erb +1 -0
  27. data/app/views/icons/_player-play-filled.html.erb +1 -0
  28. data/app/views/icons/_player-play-outline.html.erb +1 -0
  29. data/app/views/icons/_repeat.html.erb +1 -0
  30. data/app/views/icons/_rotate.html.erb +1 -0
  31. data/app/views/icons/_run.html.erb +1 -0
  32. data/app/views/icons/_skull.html.erb +1 -0
  33. data/app/views/icons/_thumb-down-filled.html.erb +1 -0
  34. data/app/views/icons/_thumb-down-outline.html.erb +1 -0
  35. data/app/views/icons/_thumb-up-filled.html.erb +1 -0
  36. data/app/views/icons/_thumb-up-outline.html.erb +1 -0
  37. data/app/views/icons/_trash-filled.html.erb +1 -0
  38. data/app/views/icons/_trash-outline.html.erb +1 -0
  39. data/app/views/icons/_treadmill.html.erb +1 -0
  40. data/config/locales/en.yml +14 -0
  41. data/lib/app/models/concerns/standard_model.rb +8 -7
  42. data/lib/web47core/version.rb +1 -1
  43. metadata +28 -2
  44. data/app/helpers/core_remix_icon_helper.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36566c9389b2ee92272fe7432399a3d55029ed0bdaa52ffcd14c2db78aa2a031
4
- data.tar.gz: 883b36a38dd85e4fa04b6204ee8d3da95a16ccdd4ee66faa34f6b93780786916
3
+ metadata.gz: 493bd66d0238d2d87765fcdb27511dc4bc15a0cf0546e5c7b42087663c8ec2ab
4
+ data.tar.gz: 704e2c9b02814618551ba57f7e69d0c51037ae79f4066642ef9a96ab0e5a1d67
5
5
  SHA512:
6
- metadata.gz: 8c6cb73735a771a00c40a7d305f7c8bfc6aa065bafa3ca92683e14c6decea87c7dbdf79a869d14c2e651737323661a323d2b0dd131b2434bebf6e886653a8abc
7
- data.tar.gz: 3c022b643ec889afc646d67974825ccda35656e8a0ac5b5d929bf3845239a993cbe9832f51cf2c0bd259f6eb680cff6926c834ca680a756d1fd88da98c8f75cf
6
+ metadata.gz: 122f415c2d598ef1591cc5e2bdc5615229f407a565b0ea016ec2aef4bf97e58c6b11de84ef5e01f968629dd3a224a40b3f02d1d066e5b12bdd5b032dfe38bda6
7
+ data.tar.gz: bd0573247e1d3fa8898b60ddb5824e5aaf90f3118e72218625e5fcdec302f20cae8ae99b5b4f2ba4448bbce39ab1271c88b552d1981a5255aa713def36c2e87d
@@ -32,8 +32,8 @@ module CoreCardNavItemsHelper
32
32
  def start_job_nav_link(obj, path, title: 'Start', confirm: nil)
33
33
  return unless can?(:view, obj)
34
34
 
35
- confirm ||= "Are you sure you want to restart this #{obj.class_title} job?"
36
- card_nav_item_link(path, title, 'play', btn_class: 'btn-success', confirm: confirm, method: :post)
35
+ confirm ||= "Are you sure you want to start this #{obj.class_title} job?"
36
+ card_nav_item_link(path, title, :play, btn_class: 'btn-success', confirm: confirm, method: :post)
37
37
  end
38
38
 
39
39
  # @abstract Link to restart, replay a given object
@@ -46,7 +46,7 @@ module CoreCardNavItemsHelper
46
46
  return unless can?(:edit, obj)
47
47
 
48
48
  confirm ||= "Are you sure you want to restart this #{obj.class_title}?"
49
- card_nav_item_link(path, title, 'delete-bin', confirm: confirm)
49
+ card_nav_item_link(path, title, :replay, confirm: confirm)
50
50
  end
51
51
 
52
52
  def edit_nav_link(obj, path, title: 'Edit')
@@ -61,13 +61,13 @@ module CoreCardNavItemsHelper
61
61
  return unless can?(:manage, obj)
62
62
 
63
63
  confirm ||= "Are you sure you want to delete this #{obj.class_title}?"
64
- card_nav_item_link(path, title, 'delete-bin', confirm: confirm, method: :delete, btn_class: 'btn-danger')
64
+ card_nav_item_link(path, title, :delete, confirm: confirm, method: :delete, btn_class: 'btn-danger')
65
65
  end
66
66
 
67
67
  # @abstract The work horse for the card nav item
68
68
  # @param [String] path - The path/URL for the action
69
69
  # @param [String] title - The title of the action
70
- # @param [String] icon_name - Name of the icon to render
70
+ # @param [String, Symbol] icon_name - Name of the icon to render
71
71
  # @param [String] confirm - If the action requires confirmation before completing
72
72
  # @param [String|Symbol] method - The HTTP method to use for the link, default is :get
73
73
  # @param [String] btn_class - The class of button that should be used, btn-primary is the default
@@ -80,7 +80,7 @@ module CoreCardNavItemsHelper
80
80
  end
81
81
  content_tag(:li, class: 'nav-item me-2') do
82
82
  link_to path, class: "#{btn_class} btn nav-link active", data: data do
83
- concat(remix_icon(icon_name, classes: ['me-2'], tooltip_text: title))
83
+ concat(svg_icon(icon_name, classes: ['me-2']))
84
84
  concat(content_tag(:span, class: 'd-none d-md-inline') { title })
85
85
  end
86
86
  end
@@ -11,7 +11,7 @@ module CoreDropdownHelper
11
11
  class: 'btn p-0 dropdown-toggle hide-arrow',
12
12
  type: :button,
13
13
  data: { 'bs-toggle': :dropdown }) do
14
- concat(remix_icon('more-2', size: icon_size))
14
+ concat(svg_icon(:more_menu, size: icon_size))
15
15
  end)
16
16
  concat(content_tag(:div, class: 'dropdown-menu') { yield block })
17
17
  end
@@ -26,7 +26,7 @@ module CoreDropdownHelper
26
26
  classes << 'dropdown-item'
27
27
  content_tag(:li) do
28
28
  concat(content_tag(:a, class: classes.join(' '), href: path, data: data) do
29
- concat(menu_remix_icon(icon_name))
29
+ concat(svg_icon(icon_name))
30
30
  concat(action_name)
31
31
  end)
32
32
  end
@@ -35,7 +35,7 @@ module CoreDropdownHelper
35
35
  def demote_dropdown_item(obj, path)
36
36
  return unless can? :edit, obj
37
37
 
38
- dropdown_item(path, 'thumb-down', 'Demote')
38
+ dropdown_item(path, :demote, 'Demote')
39
39
  end
40
40
 
41
41
  def info_dropdown_item(obj, path, name: 'Info')
@@ -59,19 +59,19 @@ module CoreDropdownHelper
59
59
  def current_job_dropdown_item(obj, path)
60
60
  return unless can? :view, obj
61
61
 
62
- dropdown_item(path, 'hourglass-2', 'Current Job')
62
+ dropdown_item(path, :hourglass, 'Current Job')
63
63
  end
64
64
 
65
65
  def edit_dropdown_item(obj, path)
66
66
  return unless can? :edit, obj
67
67
 
68
- dropdown_item(path, 'pencil', 'Edit')
68
+ dropdown_item(path, :edit, 'Edit')
69
69
  end
70
70
 
71
71
  def delete_dropdown_item(obj, path)
72
72
  return unless can? :delete, obj
73
73
 
74
- dropdown_item(path, 'delete-bin', 'Delete', method: :delete, confirm: 'are you sure?')
74
+ dropdown_item(path, :delete, 'Delete', method: :delete, confirm: 'are you sure?')
75
75
  end
76
76
 
77
77
  def cancel_dropdown_item(obj, path, confirm: 'Are you sure?', method: :delete)
@@ -88,12 +88,12 @@ module CoreDropdownHelper
88
88
  def run_dropdown_item(obj, path, method: :get, title: 'Run')
89
89
  return unless can? :read, obj
90
90
 
91
- dropdown_item(path, 'run', title, method: method)
91
+ dropdown_item(path, :run, title, method: method)
92
92
  end
93
93
 
94
94
  def replay_dropdown_item(obj, path, confirm: nil, title: 'Replay')
95
95
  return unless can? :read, obj
96
96
 
97
- dropdown_item(path, 'reset-left', title, confirm: confirm)
97
+ dropdown_item(path, :repeat, title, confirm: confirm)
98
98
  end
99
99
  end
@@ -9,7 +9,7 @@ module CoreFloatingActionButtonHelper
9
9
  def add_fab_button(clazz, path)
10
10
  return unless can?(:create, clazz)
11
11
 
12
- floating_action_button(path, title: "Add #{clazz.to_s.humanize}", icon_name: 'add-circle')
12
+ floating_action_button(path, title: "Add #{clazz.to_s.humanize}", icon_name: :add)
13
13
  end
14
14
 
15
15
  # @abstract Render a creation FAB
@@ -20,7 +20,7 @@ module CoreFloatingActionButtonHelper
20
20
  end
21
21
 
22
22
  # @abstract Render a floating action button
23
- def floating_action_button(path, title: 'Add', icon_name: 'add-circle')
23
+ def floating_action_button(path, title: 'Add', icon_name: :add)
24
24
  content_tag(:div, class: 'btn-fab') do
25
25
  concat(content_tag(:a, class: 'btn btn-primary btn-large rounded-circle', href: path, title: title) do
26
26
  concat(content_tag(:i, class: "ri-#{icon_name}-line ri-36px") {})
@@ -37,13 +37,13 @@ module CoreFloatingActionButtonHelper
37
37
  'data-bs-toggle': :dropdown,
38
38
  haspopup: true,
39
39
  'aria-expanded': false) do
40
- remix_icon('more-2', classes: %w[ri-24px])
40
+ svg_icon(:more_menu, classes: %w[ri-24px])
41
41
  end)
42
42
  concat(content_tag(:ul, class: 'dropdown-menu') { yield block })
43
43
  end
44
44
  end
45
45
 
46
- def delete_floating_action_button(clazz, path, title: 'Delete', icon_name: 'delete-bin', confirm: 'Are you sure you want to delete this item?')
46
+ def delete_floating_action_button(clazz, path, title: 'Delete', icon_name: :delete, confirm: 'Are you sure you want to delete this item?')
47
47
  return unless can?(:destroy, clazz)
48
48
 
49
49
  floating_action_link(path, title, icon_name, confirm: confirm, method: :delete)
@@ -53,18 +53,18 @@ module CoreFloatingActionButtonHelper
53
53
  def add_floating_action_link(clazz, path)
54
54
  return unless can?(:create, clazz)
55
55
 
56
- floating_action_link(path, "New #{clazz.to_s.humanize}", 'add-circle')
56
+ floating_action_link(path, "New #{clazz.to_s.humanize}", :add)
57
57
  end
58
58
 
59
59
  # @abstract Edit floating action, if the user is allowed to edit the object
60
60
  def edit_floating_action_link(clazz, path)
61
61
  return unless can?(:edit, clazz)
62
62
 
63
- floating_action_link(path, 'Edit', 'edit')
63
+ floating_action_link(path, 'Edit', :edit)
64
64
  end
65
65
 
66
66
  # @abstract Edit floating action, if the user is allowed to edit the object
67
- def refresh_floating_action_link(clazz, path, title: 'Refresh', icon_name: 'refresh', confirm: 'Are you sure you want to refresh this item?')
67
+ def refresh_floating_action_link(clazz, path, title: 'Refresh', icon_name: :replay, confirm: 'Are you sure you want to refresh this item?')
68
68
  return unless can?(:edit, clazz)
69
69
 
70
70
  floating_action_link(path, title, icon_name, confirm: confirm)
@@ -74,7 +74,7 @@ module CoreFloatingActionButtonHelper
74
74
  data = { confirm: confirm, turbo_confirm: confirm, title: title, method: method, turbo_method: method }
75
75
  content_tag(:li) do
76
76
  concat(content_tag(:a, class: 'dropdown-item', href: path, data: data) do
77
- concat(menu_remix_icon(icon_name))
77
+ concat(svg_icon(icon_name))
78
78
  concat(content_tag(:span) { title })
79
79
  end)
80
80
  end
@@ -0,0 +1,43 @@
1
+ module CoreFormCheckboxHelper
2
+ # @abstract Render a text field
3
+ # @param [Mongoid::Document] model - The model to render the field for
4
+ # @param [Symbol] field - The field to render
5
+ # @param [Hash] options - Options to pass to the field
6
+ def form_checkbox(model, field, options = {})
7
+ classes = options[:classes] || []
8
+ value = model.send(field)
9
+ options[:disabled] ||= false
10
+ properties = {
11
+ class: 'form-check-input',
12
+ id: form_field_id(model, field, options),
13
+ name: form_field_name(model, field, options),
14
+ type: :checkbox,
15
+ disabled: options[:disabled]
16
+ }
17
+ properties[:checked] = true if model.send(field)
18
+ checkbox_tag = tag(:input, properties)
19
+ content_tag(:div, class: (%w[mb-3 align-items-center d-flex] + classes).join(' ')) do
20
+ concat(content_tag(:label, class: 'form-check form-switch align-middle') do
21
+ concat(checkbox_tag)
22
+ concat(form_checkbox_label_tag(model, field, value, input_classes: classes))
23
+ end)
24
+ end
25
+ end
26
+
27
+ def form_checkbox_label_tag(model, field, value, options = {})
28
+ # dont do a label if we are in default browser mode
29
+ return if options[:input_classes].present? && options[:input_classes].include?('browser-default')
30
+
31
+ # or if we have a prompt with now value
32
+ place_holder = form_place_holder_text(model, field)
33
+ return if place_holder.blank? && value.blank? && options[:prompt].present?
34
+
35
+ error = model.errors[field]
36
+ label = input_label(model, field)
37
+ classes = value.nil? && place_holder.blank? ? '' : 'active'
38
+ classes += error.present? ? ' invalid red-text' : ' valid'
39
+ options[:class] = classes
40
+ options['data-error'] = error.join(', ') if error.present?
41
+ content_tag(:span, options) { label}
42
+ end
43
+ end
@@ -4,51 +4,29 @@
4
4
  # helpers for creating forms
5
5
  #
6
6
  module CoreFormHelper
7
- def materialize_form_for(options = {}, &block)
8
- options[:form_authenticity_token] = form_authenticity_token
9
- form = Materialize::Form.new(options)
10
- form.render_form(&block)
11
- end
7
+ # def materialize_form_for(options = {}, &block)
8
+ # options[:form_authenticity_token] = form_authenticity_token
9
+ # form = Materialize::Form.new(options)
10
+ # form.render_form(&block)
11
+ # end
12
12
 
13
- #
14
- # Text area
15
- #
16
- def form_text_area(model, field, options = {})
17
- classes = options[:classes] || %w[s12]
18
- value = model.send(field)
19
- # options[:value] = value
20
- # options[:disabled] ||= false
21
- # tag_options = {class: []} # text_field_options(model, field, options)
22
- # tag_options[:class] += ['materialize-textarea']
23
- content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
24
- concat(text_area_tag(model, field, value, options))
25
- concat(form_label_tag(model, field, value, options))
26
- end
27
- end
28
13
 
29
- def text_area_tag(model, field, value, options = {})
30
- tag_options = text_field_options(model, field, options)
31
- tag_options[:class] += ['materialize-textarea']
32
- content_tag(:textarea, tag_options) do
33
- concat(value)
34
- end
35
- end
36
14
 
37
15
  #
38
16
  # Text field
39
17
  #
40
- def form_text_field(model, field, options = {})
41
- classes = options[:classes] || %w[s12 m6 l4 xl3]
42
- value = model.send(field)
43
- options[:type] ||= :text
44
- options[:value] = value
45
- options[:disabled] ||= false
46
- tag_options = text_field_options(model, field, options)
47
- content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
48
- concat(tag(:input, tag_options))
49
- concat(form_label_tag(model, field, value, options))
50
- end
51
- end
18
+ # def form_text_field(model, field, options = {})
19
+ # classes = options[:classes] || %w[s12 m6 l4 xl3]
20
+ # value = model.send(field)
21
+ # options[:type] ||= :text
22
+ # options[:value] = value
23
+ # options[:disabled] ||= false
24
+ # tag_options = text_field_options(model, field, options)
25
+ # content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
26
+ # concat(tag(:input, tag_options))
27
+ # concat(form_label_tag(model, field, value, options))
28
+ # end
29
+ # end
52
30
 
53
31
  def form_date_field(model, field, options = {})
54
32
  classes = options[:classes] || %w[s12 m6 l4 xl3]
@@ -84,39 +62,39 @@ module CoreFormHelper
84
62
  #
85
63
  # Password field
86
64
  #
87
- def form_password(model, field, options = {})
88
- classes = options[:classes] || %w[s12 m6 l4 xl3]
89
- value = model.send(field)
90
- options[:type] = :password
91
- options[:place_holder] ||= mask_value(value)
92
- tag_options = text_field_options(model, field, options)
93
- content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
94
- concat(tag(:input, tag_options))
95
- concat(form_label_tag(model, field, value, options))
96
- end
97
- end
65
+ # def form_password(model, field, options = {})
66
+ # classes = options[:classes] || %w[s12 m6 l4 xl3]
67
+ # value = model.send(field)
68
+ # options[:type] = :password
69
+ # options[:place_holder] ||= mask_value(value)
70
+ # tag_options = text_field_options(model, field, options)
71
+ # content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
72
+ # concat(tag(:input, tag_options))
73
+ # concat(form_label_tag(model, field, value, options))
74
+ # end
75
+ # end
98
76
 
99
77
  #
100
78
  # Select field
101
79
  #
102
- def form_select(model, field, options = {})
103
- value = model.send(field)
104
- raise 'Prompt needed' if value.blank? && options[:prompt].blank? && !options[:no_label]
105
-
106
- hint_key = "ui_form.#{model.class.to_s.underscore}.hints.#{field}"
107
- if I18n.exists?(hint_key)
108
- base_classes = %w[input-field col tooltipped]
109
- data = { tooltip: I18n.t(hint_key), position: :top }
110
- else
111
- base_classes = %w[input-field col]
112
- data = {}
113
- end
114
- classes = (base_classes + (options[:classes] || %w[s12 m6 l4 xl3])).join(' ')
115
- content_tag(:div, class: classes, data: data) do
116
- concat(form_select_tag(model, field, options))
117
- concat(form_label_tag(model, field, value, options))
118
- end
119
- end
80
+ # def form_select(model, field, options = {})
81
+ # value = model.send(field)
82
+ # raise 'Prompt needed' if value.blank? && options[:prompt].blank? && !options[:no_label]
83
+ #
84
+ # hint_key = "ui_form.#{model.class.to_s.underscore}.hints.#{field}"
85
+ # if I18n.exists?(hint_key)
86
+ # base_classes = %w[input-field col tooltipped]
87
+ # data = { tooltip: I18n.t(hint_key), position: :top }
88
+ # else
89
+ # base_classes = %w[input-field col]
90
+ # data = {}
91
+ # end
92
+ # classes = (base_classes + (options[:classes] || %w[s12 m6 l4 xl3])).join(' ')
93
+ # content_tag(:div, class: classes, data: data) do
94
+ # concat(form_select_tag(model, field, options))
95
+ # concat(form_label_tag(model, field, value, options))
96
+ # end
97
+ # end
120
98
 
121
99
  #
122
100
  # Create the select tag
@@ -170,47 +148,47 @@ module CoreFormHelper
170
148
  #
171
149
  # Checkbox field
172
150
  #
173
- def form_checkbox(model, field, classes = %w[s12 m6 l4 xl3], options = {})
174
- value = model.send(field)
175
- options[:disabled] ||= false
176
- properties = {
177
- class: 'validate',
178
- id: form_field_id(model, field, options),
179
- name: form_field_name(model, field, options),
180
- type: :checkbox,
181
- disabled: options[:disabled]
182
- }
183
- properties[:checked] = true if model.send(field)
184
- checkbox_tag = tag(:input, properties)
185
- content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
186
- concat(content_tag(:label) do
187
- concat(checkbox_tag)
188
- concat(form_checkbox_label_tag(model, field, value, input_classes: classes))
189
- end)
190
- end
191
- end
151
+ # def form_checkbox(model, field, classes = %w[s12 m6 l4 xl3], options = {})
152
+ # value = model.send(field)
153
+ # options[:disabled] ||= false
154
+ # properties = {
155
+ # class: 'validate',
156
+ # id: form_field_id(model, field, options),
157
+ # name: form_field_name(model, field, options),
158
+ # type: :checkbox,
159
+ # disabled: options[:disabled]
160
+ # }
161
+ # properties[:checked] = true if model.send(field)
162
+ # checkbox_tag = tag(:input, properties)
163
+ # content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
164
+ # concat(content_tag(:label) do
165
+ # concat(checkbox_tag)
166
+ # concat(form_checkbox_label_tag(model, field, value, input_classes: classes))
167
+ # end)
168
+ # end
169
+ # end
192
170
 
193
171
  #
194
172
  # get the label for checkbox
195
173
  #
196
- def form_checkbox_label_tag(model, field, value, options = {})
197
- # dont do a label if we are in default browser mode
198
- return if options[:input_classes].present? && options[:input_classes].include?('browser-default')
199
-
200
- # or if we have a prompt with now value
201
- place_holder = field_place_holder(model, field)
202
- return if place_holder.blank? && value.blank? && options[:prompt].present?
203
-
204
- error = model.errors[field]
205
- key = "ui_form.#{model.class.to_s.underscore}.labels.#{field}"
206
- classes = value.nil? && place_holder.blank? ? '' : 'active'
207
- classes += error.present? ? ' invalid red-text' : ' valid'
208
- options[:class] = classes
209
- options['data-error'] = error.join(', ') if error.present?
210
- content_tag(:span, options) do
211
- concat(I18n.exists?(key) ? I18n.t(key) : field.to_s.humanize)
212
- end
213
- end
174
+ # def form_checkbox_label_tag(model, field, value, options = {})
175
+ # # dont do a label if we are in default browser mode
176
+ # return if options[:input_classes].present? && options[:input_classes].include?('browser-default')
177
+ #
178
+ # # or if we have a prompt with now value
179
+ # place_holder = field_place_holder(model, field)
180
+ # return if place_holder.blank? && value.blank? && options[:prompt].present?
181
+ #
182
+ # error = model.errors[field]
183
+ # key = "ui_form.#{model.class.to_s.underscore}.labels.#{field}"
184
+ # classes = value.nil? && place_holder.blank? ? '' : 'active'
185
+ # classes += error.present? ? ' invalid red-text' : ' valid'
186
+ # options[:class] = classes
187
+ # options['data-error'] = error.join(', ') if error.present?
188
+ # content_tag(:span, options) do
189
+ # concat(I18n.exists?(key) ? I18n.t(key) : field.to_s.humanize)
190
+ # end
191
+ # end
214
192
 
215
193
  #
216
194
  # File field
@@ -230,24 +208,28 @@ module CoreFormHelper
230
208
  # get the label for field
231
209
  #
232
210
  def form_label_tag(model, field, value, options = {})
233
- # dont do a label if we are in default browser mode
211
+ # don't do a label if we are in default browser mode
234
212
  return if options[:no_label]
235
213
  return if options[:input_classes].present? && options[:input_classes].include?('browser-default')
236
214
 
215
+ help_text = form_helper_text(model, field)
216
+
237
217
  # or if we have a prompt with now value
238
- place_holder = options[:place_holder] || field_place_holder(model, field)
218
+ place_holder = options[:place_holder] || form_place_holder_text(model, field)
239
219
  return if place_holder.blank? && value.blank? && options[:prompt].present?
240
220
 
241
221
  error = model.errors[field]
242
- key = "ui_form.#{model.class.to_s.underscore}.labels.#{field}"
243
- classes = value.nil? && place_holder.blank? ? '' : 'active'
244
- classes += error.present? ? ' invalid red-text' : ' valid'
245
- options[:class] = classes
222
+ classes = %w[form-label mb-2]
223
+ classes << 'text-red' if error.present?
224
+ options[:class] = classes.compact.uniq.join(' ')
246
225
  options[:for] = form_field_id(model, field, options)
247
- options['data-error'] = error.join(', ') if error.present?
248
- content_tag(:label, options) do
249
- concat(I18n.exists?(key) ? I18n.t(key) : field.to_s.humanize)
250
- concat(" #{error.join(', ')}") if error.present?
226
+ # options['data-error'] = error.join(', ') if error.present?
227
+ options[:required] = form_required_field?(model, field) ? 'required' : nil
228
+ tag.label(**options) do
229
+ concat(input_label(model, field, field.to_s.humanize))
230
+ concat(content_tag(:span, class: 'form-help ms-2', data: { bs_toggle: :popover, bs_content: help_text }) { '?' }) if help_text.present?
231
+ # @todo CMS add handling specific errors later
232
+ # concat(" #{error.join(', ')}") if error.present?
251
233
  end
252
234
  end
253
235
 
@@ -266,35 +248,37 @@ module CoreFormHelper
266
248
  #
267
249
  # Add the placeholder option if found in the translations
268
250
  #
269
- def text_field_options(model, field, options)
270
- hint_key = "ui_form.#{model.class.to_s.underscore}.hints.#{field}"
271
- if I18n.exists?(hint_key)
272
- classes = %w[validate tooltipped]
273
- options[:data] = { tooltip: I18n.t(hint_key), position: :top }
274
- else
275
- classes = %w[validate]
276
- end
277
- classes += options[:input_classes] if options[:input_classes].present?
278
- options[:name] = form_field_name(model, field, options)
279
- options[:id] = form_field_id(model, field, options)
280
- place_holder = options[:place_holder] || field_place_holder(model, field)
281
- if place_holder.present?
282
- classes << 'active'
283
- options[:placeholder] = place_holder
284
- end
285
- classes << 'active' if options[:value].present?
286
- options[:class] = classes.uniq
287
- options
288
- end
251
+ # def text_field_options(model, field, options)
252
+ # hint_key = "ui_form.#{model.class.to_s.underscore}.hints.#{field}"
253
+ # if I18n.exists?(hint_key)
254
+ # classes = %w[validate tooltipped]
255
+ # options[:data] = { tooltip: I18n.t(hint_key), position: :top }
256
+ # else
257
+ # classes = %w[validate]
258
+ # end
259
+ # classes += options[:input_classes] if options[:input_classes].present?
260
+ # options[:name] = form_field_name(model, field, options)
261
+ # options[:id] = form_field_id(model, field, options)
262
+ # place_holder = options[:place_holder] || field_place_holder(model, field)
263
+ # if place_holder.present?
264
+ # classes << 'active'
265
+ # options[:placeholder] = place_holder
266
+ # end
267
+ # classes << 'active' if options[:value].present?
268
+ # options[:class] = classes.uniq
269
+ # options
270
+ # end
289
271
 
290
- def field_place_holder(model, field)
291
- place_holder_key = "ui_form.#{model.class.to_s.underscore}.placeholders.#{field}"
292
- I18n.exists?(place_holder_key) ? I18n.t(place_holder_key) : nil
293
- end
272
+ # def field_place_holder(model, field)
273
+ # place_holder_key = "ui_form.#{model.class.to_s.underscore}.placeholders.#{field}"
274
+ # I18n.exists?(place_holder_key) ? I18n.t(place_holder_key) : nil
275
+ # end
294
276
 
295
- #
296
- # Return a consistent form field name
297
- #
277
+ # @abstract Return a consistent form field name
278
+ # @param [Mongoid::Document] model
279
+ # @param [Symbol] field
280
+ # @param [Hash] options
281
+ # @return [HTML]
298
282
  def form_field_name(model, field, options = {})
299
283
  return options[:form_name] if options[:form_name].present?
300
284
 
@@ -316,28 +300,26 @@ module CoreFormHelper
316
300
  end
317
301
  end
318
302
 
319
- #
320
- # Return a consistent form field id
321
- #
303
+ # @abstract Return a consistent form field id
304
+ # @param [Mongoid::Document] model
305
+ # @param [Symbol] field
306
+ # @param [Hash] options
307
+ # @return [HTML]
322
308
  def form_field_id(model, field, options = {})
323
309
  return options[:form_id] if options[:form_id].present?
324
310
 
325
- # TODO: Need to handle the other side of the 1:M use case where
326
- # the field name needs to end in _ids, not _id.
327
311
  field = "#{field}_id" if model.class.reflect_on_association(field).present?
328
- if options[:index].present?
329
- if options[:array_name].present?
330
- if options[:base_name].present?
331
- "#{options[:form_id_prefix]}#{options[:base_name]}[#{options[:array_name]}[#{options[:index]}][#{field}]]"
332
- else
333
- "#{options[:form_id_prefix]}#{options[:array_name]}[#{options[:index]}][#{field}]"
334
- end
335
- else
336
- "#{options[:form_id_prefix]}#{model.class.to_s.underscore}[#{options[:index]}][#{field}]"
337
- end
338
- else
339
- "#{options[:form_id_prefix]}#{model.class.to_s.underscore}[#{field}]"
340
- end
312
+ [options[:form_id_prefix], options[:base_name], options[:array_name] || model.class.to_s.underscore, options[:index], field].compact.join('_')
313
+ end
314
+
315
+ # @abstract Determine if the field is required or not
316
+ # @param [Mongoid::Document] model
317
+ # @param [Symbol] field
318
+ # @return [Boolean]
319
+ def form_required_field?(model, field)
320
+ model.class.validators_on(field).any? { |v| v.is_a?(Mongoid::Validatable::PresenceValidator) }
321
+ rescue StandardError
322
+ false
341
323
  end
342
324
 
343
325
  def form_radio_button(model, field, options = {})
@@ -348,4 +330,57 @@ module CoreFormHelper
348
330
  concat(form_label_tag(model, field, value))
349
331
  end
350
332
  end
333
+
334
+ # @abstract Get the placeholder for this input element
335
+ # @param [Mongoid::Document] model
336
+ # @param [Symbol] field
337
+ # @param [String, nil] default
338
+ # @return [String, nil]
339
+ def form_place_holder_text(model, field, default = nil)
340
+ form_localized_text(model, field, :placeholders, default)
341
+ end
342
+
343
+ # @abstract Get the helper text for this input element
344
+ # @param [Mongoid::Document] model
345
+ # @param [Symbol] field
346
+ # @param [String, nil] default
347
+ # @return [String, nil]
348
+ def form_helper_text(model, field, default = nil)
349
+ form_localized_text(model, field, :helpers, default)
350
+ end
351
+
352
+ # @abstract Get the hint text for this input element
353
+ # @param [Mongoid::Document] model
354
+ # @param [Symbol] field
355
+ # @param [String, nil] default
356
+ # @return [String,nil]
357
+ def form_hint_text(model, field, default = nil)
358
+ form_localized_text(model, field, :hints, default)
359
+ end
360
+
361
+ # @abstract Get the label for this input element
362
+ # @param [Mongoid::Document] model
363
+ # @param [Symbol] field
364
+ # @param [String, nil] default
365
+ # @return [String,nil]
366
+ def input_label(model, field, default = model.class.human_attribute_name(field))
367
+ form_localized_text(model, field, :labels, default)
368
+ end
369
+
370
+ def required_field?(model, field)
371
+ form_required_field?(model, field)
372
+ end
373
+
374
+ # @abstract Get the localized value for the given key
375
+ # @param [Mongoid::Document] model
376
+ # @param [Symbol] field
377
+ # @param [Symbol] type
378
+ # @param [String] default
379
+ # @return [String,nil]
380
+ def form_localized_text(model, field, type, default = nil)
381
+ key = ['ui_form', model.class.to_s.underscore, type, field].join('.')
382
+ I18n.exists?(key) ? I18n.t(key) : default
383
+ rescue StandardError
384
+ default
385
+ end
351
386
  end