web47core 3.2.36 → 3.2.50

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51addb55203d5e9bca94ca014394dc522b41ef51c1dabb32e2b1fa294f1aa1b8
4
- data.tar.gz: 341d01b151ce0c08ee6409c434a37f292dd424c8bcea2647f0434bf7e52cdb3f
3
+ metadata.gz: 5c3675d2ab5fbd549deab9374e349736b27f3f648bd12d3a29566c5b0af3bbea
4
+ data.tar.gz: fd2209c37ae9f88094037c1b28af3e5d4ee4420e98aff389ac86f724b2a4a4e3
5
5
  SHA512:
6
- metadata.gz: f3278e6e57ed98a3e54910cb10676844554e8e418397a991193342b09c5500a6bc6915cae2f11a5d616f4699ceeb18f35c0bbfba0400342a577cbb23d5dbd035
7
- data.tar.gz: 73694c5acd82fbd7879289fe536be74cef0024073ae3f182333ec97323907dc0c040f44b1df16eea53c5908473cae84ada2cc10af6fc97b6a12ef76d2bfc1e49
6
+ metadata.gz: c7a42d5c97ee0b629eee606061c871e75c67e2499ec18158fc8a52c5e2bef28d73a29b32dd08fae4a982206e7b0409c089401defcdf90a2c16dad3309cd874ba
7
+ data.tar.gz: 4bf04e44e0cb319e79c92aaaa65abd328a00f12c6e9667906991d2139e80416cfcf7ba12acf335aeff7f0b5028a04cf8f43da29c2b9219ae4e7307cbb620bd4c
@@ -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,11 +4,11 @@
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
13
  #
14
14
  # Text area
@@ -37,18 +37,18 @@ module CoreFormHelper
37
37
  #
38
38
  # Text field
39
39
  #
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
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
52
52
 
53
53
  def form_date_field(model, field, options = {})
54
54
  classes = options[:classes] || %w[s12 m6 l4 xl3]
@@ -84,17 +84,17 @@ module CoreFormHelper
84
84
  #
85
85
  # Password field
86
86
  #
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
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
98
98
 
99
99
  #
100
100
  # Select field
@@ -170,47 +170,47 @@ module CoreFormHelper
170
170
  #
171
171
  # Checkbox field
172
172
  #
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
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
192
192
 
193
193
  #
194
194
  # get the label for checkbox
195
195
  #
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
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
214
214
 
215
215
  #
216
216
  # File field
@@ -230,24 +230,28 @@ module CoreFormHelper
230
230
  # get the label for field
231
231
  #
232
232
  def form_label_tag(model, field, value, options = {})
233
- # dont do a label if we are in default browser mode
233
+ # don't do a label if we are in default browser mode
234
234
  return if options[:no_label]
235
235
  return if options[:input_classes].present? && options[:input_classes].include?('browser-default')
236
236
 
237
+ help_text = form_helper_text(model, field)
238
+
237
239
  # or if we have a prompt with now value
238
- place_holder = options[:place_holder] || field_place_holder(model, field)
240
+ place_holder = options[:place_holder] || form_place_holder_text(model, field)
239
241
  return if place_holder.blank? && value.blank? && options[:prompt].present?
240
242
 
241
243
  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
244
+ classes = %w[form-label mb-2]
245
+ classes << 'text-red' if error.present?
246
+ options[:class] = classes.compact.uniq.join(' ')
246
247
  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?
248
+ # options['data-error'] = error.join(', ') if error.present?
249
+ options[:required] = form_required_field?(model, field) ? 'required' : nil
250
+ tag.label(**options) do
251
+ concat(input_label(model, field, field.to_s.humanize))
252
+ concat(content_tag(:span, class: 'form-help ms-2', data: { bs_toggle: :popover, bs_content: help_text }) { '?' }) if help_text.present?
253
+ # @todo CMS add handling specific errors later
254
+ # concat(" #{error.join(', ')}") if error.present?
251
255
  end
252
256
  end
253
257
 
@@ -266,35 +270,37 @@ module CoreFormHelper
266
270
  #
267
271
  # Add the placeholder option if found in the translations
268
272
  #
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
273
+ # def text_field_options(model, field, options)
274
+ # hint_key = "ui_form.#{model.class.to_s.underscore}.hints.#{field}"
275
+ # if I18n.exists?(hint_key)
276
+ # classes = %w[validate tooltipped]
277
+ # options[:data] = { tooltip: I18n.t(hint_key), position: :top }
278
+ # else
279
+ # classes = %w[validate]
280
+ # end
281
+ # classes += options[:input_classes] if options[:input_classes].present?
282
+ # options[:name] = form_field_name(model, field, options)
283
+ # options[:id] = form_field_id(model, field, options)
284
+ # place_holder = options[:place_holder] || field_place_holder(model, field)
285
+ # if place_holder.present?
286
+ # classes << 'active'
287
+ # options[:placeholder] = place_holder
288
+ # end
289
+ # classes << 'active' if options[:value].present?
290
+ # options[:class] = classes.uniq
291
+ # options
292
+ # end
289
293
 
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
294
+ # def field_place_holder(model, field)
295
+ # place_holder_key = "ui_form.#{model.class.to_s.underscore}.placeholders.#{field}"
296
+ # I18n.exists?(place_holder_key) ? I18n.t(place_holder_key) : nil
297
+ # end
294
298
 
295
- #
296
- # Return a consistent form field name
297
- #
299
+ # @abstract Return a consistent form field name
300
+ # @param [Mongoid::Document] model
301
+ # @param [Symbol] field
302
+ # @param [Hash] options
303
+ # @return [HTML]
298
304
  def form_field_name(model, field, options = {})
299
305
  return options[:form_name] if options[:form_name].present?
300
306
 
@@ -316,28 +322,26 @@ module CoreFormHelper
316
322
  end
317
323
  end
318
324
 
319
- #
320
- # Return a consistent form field id
321
- #
325
+ # @abstract Return a consistent form field id
326
+ # @param [Mongoid::Document] model
327
+ # @param [Symbol] field
328
+ # @param [Hash] options
329
+ # @return [HTML]
322
330
  def form_field_id(model, field, options = {})
323
331
  return options[:form_id] if options[:form_id].present?
324
332
 
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
333
  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
334
+ [options[:form_id_prefix], options[:base_name], options[:array_name] || model.class.to_s.underscore, options[:index], field].compact.join('_')
335
+ end
336
+
337
+ # @abstract Determine if the field is required or not
338
+ # @param [Mongoid::Document] model
339
+ # @param [Symbol] field
340
+ # @return [Boolean]
341
+ def form_required_field?(model, field)
342
+ model.class.validators_on(field).any? { |v| v.is_a?(Mongoid::Validatable::PresenceValidator) }
343
+ rescue StandardError
344
+ false
341
345
  end
342
346
 
343
347
  def form_radio_button(model, field, options = {})
@@ -348,4 +352,57 @@ module CoreFormHelper
348
352
  concat(form_label_tag(model, field, value))
349
353
  end
350
354
  end
355
+
356
+ # @abstract Get the placeholder for this input element
357
+ # @param [Mongoid::Document] model
358
+ # @param [Symbol] field
359
+ # @param [String, nil] default
360
+ # @return [String, nil]
361
+ def form_place_holder_text(model, field, default = nil)
362
+ form_localized_text(model, field, :placeholders, default)
363
+ end
364
+
365
+ # @abstract Get the helper text for this input element
366
+ # @param [Mongoid::Document] model
367
+ # @param [Symbol] field
368
+ # @param [String, nil] default
369
+ # @return [String, nil]
370
+ def form_helper_text(model, field, default = nil)
371
+ form_localized_text(model, field, :helpers, default)
372
+ end
373
+
374
+ # @abstract Get the hint text for this input element
375
+ # @param [Mongoid::Document] model
376
+ # @param [Symbol] field
377
+ # @param [String, nil] default
378
+ # @return [String,nil]
379
+ def form_hint_text(model, field, default = nil)
380
+ form_localized_text(model, field, :hints, default)
381
+ end
382
+
383
+ # @abstract Get the label for this input element
384
+ # @param [Mongoid::Document] model
385
+ # @param [Symbol] field
386
+ # @param [String, nil] default
387
+ # @return [String,nil]
388
+ def input_label(model, field, default = model.class.human_attribute_name(field))
389
+ form_localized_text(model, field, :labels, default)
390
+ end
391
+
392
+ def required_field?(model, field)
393
+ form_required_field?(model, field)
394
+ end
395
+
396
+ # @abstract Get the localized value for the given key
397
+ # @param [Mongoid::Document] model
398
+ # @param [Symbol] field
399
+ # @param [Symbol] type
400
+ # @param [String] default
401
+ # @return [String,nil]
402
+ def form_localized_text(model, field, type, default = nil)
403
+ key = ['ui_form', model.class.to_s.underscore, type, field].join('.')
404
+ I18n.exists?(key) ? I18n.t(key) : default
405
+ rescue StandardError
406
+ default
407
+ end
351
408
  end
@@ -0,0 +1,74 @@
1
+ module CoreFormInputHelper
2
+
3
+ # @abstract Render a email text field
4
+ # @param [Mongoid::Document] model - The model to render the field for
5
+ # @param [Symbol] field - The field to render
6
+ # @param [Hash] options - Options to pass to the field
7
+ def form_number_field(model, field, options = {})
8
+ options[:type] ||= :number
9
+ options[:step] ||= 1
10
+ options[:min] ||= 0
11
+ form_text_field(model, field, options)
12
+ end
13
+
14
+ # @abstract Render a email text field
15
+ # @param [Mongoid::Document] model - The model to render the field for
16
+ # @param [Symbol] field - The field to render
17
+ # @param [Hash] options - Options to pass to the field
18
+ def form_email_field(model, field, options = {})
19
+ options[:type] ||= :email
20
+ form_text_field(model, field, options)
21
+ end
22
+
23
+ # @abstract Render a text field
24
+ # @param [Mongoid::Document] model - The model to render the field for
25
+ # @param [Symbol] field - The field to render
26
+ # @param [Hash] options - Options to pass to the field
27
+ def form_url_field(model, field, options = {})
28
+ options[:type] ||= :url
29
+ form_text_field(model, field, options)
30
+ end
31
+
32
+ # @abstract Render a text field
33
+ # @param [Mongoid::Document] model - The model to render the field for
34
+ # @param [Symbol] field - The field to render
35
+ # @param [Hash] options - Options to pass to the field
36
+ def form_password(model, field, options = {})
37
+ options[:type] = :password
38
+ form_text_field(model, field, options)
39
+ end
40
+
41
+ # @abstract Render a text field
42
+ # @param [Mongoid::Document] model - The model to render the field for
43
+ # @param [Symbol] field - The field to render
44
+ # @param [Hash] options - Options to pass to the field
45
+ def form_text_field(model, field, options = {})
46
+ label_options = options.clone
47
+ classes = options[:classes] || []
48
+ classes << 'mb-3'
49
+ value = model.send(field)
50
+ options[:type] ||= :text
51
+ options[:value] = value
52
+ options[:disabled] ||= false
53
+ tag_options = text_field_options(model, field, options)
54
+ content_tag(:div, class: classes.join(' ')) do
55
+ concat(form_label_tag(model, field, value, label_options))
56
+ concat(tag(:input, tag_options))
57
+ end
58
+ end
59
+
60
+ # @abstract Build the options for a text field, place holder, hint, etc.
61
+ # @param [Mongoid::Document] model - The model to render the field for
62
+ # @param [Symbol] field - The field to render
63
+ # @param [Hash] options - Options to pass to the field
64
+ def text_field_options(model, field, options = {})
65
+ classes = %w[form-control]
66
+ classes += options[:input_classes] if options[:input_classes].present?
67
+ options[:name] = form_field_name(model, field, options)
68
+ options[:id] = form_field_id(model, field, options)
69
+ place_holder = options[:place_holder] || form_place_holder_text(model, field)
70
+ options[:placeholder] = place_holder if place_holder.present?
71
+ options[:class] = classes.uniq
72
+ options
73
+ end
74
+ end
@@ -0,0 +1,65 @@
1
+ module CoreFormSelectHelper
2
+ def form_select(model, field, options = {})
3
+ value = model.send(field)
4
+ raise 'Prompt needed' if value.blank? && options[:prompt].blank? && !options[:no_label]
5
+
6
+ label_options = options.clone
7
+ hint = input_hint(model, field)
8
+ if hint.present?
9
+ base_classes = %w[tooltipped]
10
+ data = { tooltip: I18n.t(hint_key), position: :top }
11
+ else
12
+ base_classes = []
13
+ data = {}
14
+ end
15
+ classes = (base_classes + (options[:classes] || %w[s12 m6 l4 xl3])).join(' ')
16
+ content_tag(:div, class: classes, data: data) do
17
+ concat(input_label_tag(model, field, value, options))
18
+ concat(form_input_select_tag(model, field, label_options))
19
+ end
20
+ end
21
+
22
+ def form_select_tag(model, field, options = {})
23
+ select_content = {
24
+ id: form_field_id(model, field, options),
25
+ name: form_field_name(model, field, options),
26
+ class: [options[:input_classes], 'form-select'].compact.join(' '),
27
+ disabled: options[:disabled]
28
+ }
29
+ content_tag(:select, select_content) do
30
+ form_select_option_key_values(model.send(field), options).each do |value|
31
+ concat(content_tag(:option, value: value[:key], selected: value[:selected]) do
32
+ concat(value[:value])
33
+ end)
34
+ end
35
+ end
36
+ end
37
+
38
+ def form_select_option_key_values(value, options)
39
+ select_options = []
40
+ select_options << { key: '', value: options[:prompt], selected: false } if options[:prompt].present?
41
+ options[:options].each do |option_value|
42
+ option_value[:display_name] = option_value.display_name if option_value.respond_to?(:display_name)
43
+ option_value[:display_name] = option_value.user_display_name if option_value.respond_to?(:user_display_name)
44
+ select_options << case option_value
45
+ when String, Integer
46
+ { key: option_value,
47
+ value: option_value,
48
+ selected: value.eql?(option_value) }
49
+ when Array
50
+ { key: option_value.last,
51
+ value: option_value.first,
52
+ selected: value.to_s.eql?(option_value.last.to_s) }
53
+ when Hash
54
+ { key: option_value[:key],
55
+ value: option_value[:value],
56
+ selected: value.eql?(option_value[:key]) }
57
+ else
58
+ { key: option_value[:_id].to_s,
59
+ value: option_value[:display_name] || option_value[:name],
60
+ selected: value.eql?(option_value) }
61
+ end
62
+ end
63
+ select_options
64
+ end
65
+ end
@@ -0,0 +1,22 @@
1
+ module CoreFormTextareaHelper
2
+ def form_textarea(model, field, options = {})
3
+ classes = options[:classes] || []
4
+ value = model.send(field)
5
+ # options[:value] = value
6
+ # options[:disabled] ||= false
7
+ # tag_options = {class: []} # text_field_options(model, field, options)
8
+ # tag_options[:class] += ['materialize-textarea']
9
+ content_tag(:div, class: (%w[mb-3] + classes).flatten.join(' ')) do
10
+ concat(input_label_tag(model, field, value, options))
11
+ concat(textarea_tag(model, field, value, options))
12
+ end
13
+ end
14
+
15
+ def form_textarea_tag(model, field, value, options = {})
16
+ tag_options = text_input_options(model, field, options)
17
+ tag_options[:class] << 'form-control'
18
+ content_tag(:textarea, tag_options) do
19
+ concat(value)
20
+ end
21
+ end
22
+ end
@@ -115,14 +115,6 @@ module CoreLinkHelper
115
115
  end
116
116
  end
117
117
 
118
- def edit_modal_tag(obj, path, _options = {})
119
- return unless can? :edit, obj
120
-
121
- content_tag(:a, href: path, class: 'modal-action') do
122
- concat(I18n.t('ui_form.actions.edit'))
123
- end
124
- end
125
-
126
118
  #
127
119
  # Restart a thingy
128
120
  #
@@ -4,6 +4,16 @@
4
4
  # Methods useful for building out tables
5
5
  #
6
6
  module CoreTableHelper
7
+ def card_table_header_actions_tag(clazz, path, classes: [], icon_name: :add, title: 'Add')
8
+ return unless can?(:create, clazz)
9
+
10
+ classes << 'btn'
11
+ content_tag(:a, class: classes.join(' '), href: path) do
12
+ concat(svg_icon(icon_name))
13
+ concat(content_tag(:span, title))
14
+ end
15
+ end
16
+
7
17
  #
8
18
  # Format the table header
9
19
  # @param name - Name of the header, either the text or a localized value
@@ -77,4 +87,17 @@ module CoreTableHelper
77
87
  end)
78
88
  end
79
89
  end
90
+
91
+ # @abstract Return a table data cell with a boolean value
92
+ # @param value [Boolean] - The value to display
93
+ # @return [String] - The HTML for the cell
94
+ def table_data_boolean(value, show_false: true)
95
+ content_tag(:td, class: 'text-center', data: { order: value ? 0 : 1 }) do
96
+ if value
97
+ svg_icon(:check, color: :green)
98
+ else
99
+ svg_icon(:x, color: :red) if show_false
100
+ end
101
+ end
102
+ end
80
103
  end
@@ -69,15 +69,20 @@ module ModelModalHelper
69
69
  end
70
70
 
71
71
  def model_modal_action(model, _options = {})
72
- content_tag(:a, class: 'modal-trigger', href: "#modal-#{model.id}") do
72
+ content_tag(:a, href: '#', data: { bs_toggle: :modal, bs_target: "#modal-#{model.id}" }) do
73
73
  concat(model.name)
74
74
  end
75
75
  end
76
76
 
77
77
  def model_modal(model, edit_path, options = {})
78
- content_tag(:div, class: 'modal', id: "modal-#{model.id}") do
79
- concat(model_modal_content(model, options))
80
- concat(model_modal_footer(model, edit_path))
78
+ content_tag(:div, class: 'modal', id: "modal-#{model.id}", tabindex: -1) do
79
+ concat(model_modal_dialog(model, edit_path, options))
80
+ end
81
+ end
82
+
83
+ def model_modal_dialog(model, edit_path, options = {})
84
+ content_tag(:div, class: 'modal-dialog', role: :document) do
85
+ concat(model_modal_content(model, edit_path, options))
81
86
  end
82
87
  end
83
88
 
@@ -85,40 +90,60 @@ module ModelModalHelper
85
90
  model_modal_content(model, options) + model_modal_footer(model, "#{request.url}/edit")
86
91
  end
87
92
 
88
- def model_modal_content(model, options = {})
93
+ def model_modal_content(model, edit_path, options = {})
89
94
  content_tag(:div, class: 'modal-content') do
90
- concat(content_tag(:h2) { model.name })
91
- concat(content_tag(:div, class: 'row') do
92
- concat(model_modal_tabs(model, options))
93
- concat(model_modal_fields_tab(model, options))
94
- concat(model_modal_standard_tab(model, options))
95
- concat(model_modal_logs_tab(model, options)) if model.respond_to?(:logs) && options[:show_audit_logs]
96
- end)
95
+ concat(model_modal_header(model, edit_path, options))
96
+ model_modal_body(model, edit_path, options)
97
+ concat(model_modal_footer(model, edit_path))
98
+ end
99
+ end
100
+
101
+ def model_modal_header(model, edit_path, options = {})
102
+ content_tag(:div, class: 'modal-header') do
103
+ concat(content_tag(:h2) { model.name.titleize })
104
+ concat(tag(:button, class: 'btn-close', data: { bs_dismiss: :modal }, aria_label: :close))
97
105
  end
98
106
  end
99
107
 
108
+ def model_modal_body(model, edit_path, options = {})
109
+ concat(content_tag(:div, class: 'model-body') do
110
+ concat(model_modal_tabs(model, options))
111
+ concat(model_modal_tab_content(model, options))
112
+ end)
113
+ end
114
+
100
115
  def model_modal_tabs(model, _options = {})
101
- content_tag(:div, class: 'col s12') do
102
- concat(content_tag(:ul, class: 'tabs tabs-fixed-width') do
103
- concat(content_tag(:li, class: 'tab') do
104
- content_tag(:a, href: "#field-tab-#{model.id}") { model.class.to_s.titleize }
105
- end)
106
- concat(content_tag(:li, class: 'tab') { content_tag(:a, href: "#standard-tab-#{model.id}") { 'Details' } })
107
- if model.respond_to?(:logs)
108
- concat(content_tag(:li, class: 'tab') { content_tag(:a, href: "#logs-tab-#{model.id}") { 'Logs' } })
109
- end
116
+ content_tag(:ul, class: 'nav nav-tabs', data: { bs_toggle: :tabs }) do
117
+ concat(content_tag(:li, class: 'nav-item') do
118
+ content_tag(:a, class: 'nav-link active', href: "#field-tab-#{model.id}", data: { bs_toggle: :tab }) { model.class.to_s.titleize }
110
119
  end)
120
+ concat(content_tag(:li, class: 'nav-item') do
121
+ content_tag(:a, class: 'nav-link', href: "#standard-tab-#{model.id}", data: { bs_toggle: :tab }) { 'Details' }
122
+ end)
123
+ if model.respond_to?(:logs)
124
+ concat(content_tag(:li, class: 'nav-item') do
125
+ content_tag(:a, class: 'nav-item', href: "#logs-tab-#{model.id}", data: { bs_toggler: :tab }) { 'Logs' }
126
+ end)
127
+ end
128
+ end
129
+ end
130
+
131
+ def model_modal_tab_content(model, options = {})
132
+ content_tag(:div, class: 'tab-content') do
133
+ concat(model_modal_fields_tab(model, options))
134
+ concat(model_modal_standard_tab(model, options))
135
+ # concat(model_modal_logs_tab(model, options)) if model.respond_to?(:logs) && options[:show_audit_logs]
111
136
  end
112
137
  end
113
138
 
114
139
  def model_modal_standard_tab(model, options = {})
115
- content_tag(:div, id: "standard-tab-#{model.id}", class: 'col s12') do
116
- concat(model_modal_standard(model, options))
140
+ content_tag(:div, id: "standard-tab-#{model.id}", class: 'tab-pane', role: :tabpanel) do
141
+ concat(model_modal_standard_fields(model, options))
117
142
  end
118
143
  end
119
144
 
120
145
  def model_modal_fields_tab(model, options = {})
121
- content_tag(:div, id: "field-tab-#{model.id}", class: 'col s12') do
146
+ content_tag(:div, id: "field-tab-#{model.id}", class: 'tab-pane active', role: :tabpanel) do
122
147
  concat(model_modal_fields(model, options))
123
148
  end
124
149
  end
@@ -150,33 +175,28 @@ module ModelModalHelper
150
175
  end
151
176
 
152
177
  def model_modal_fields(model, _options = {})
153
- content_tag(:table, class: 'center-align') do
154
- concat(content_tag(:tbody) do
155
- model.class.allowed_param_names.sort.each do |field_name|
156
- concat(model_modal_field(model, field_name))
157
- end
158
- end)
178
+ content_tag(:div, class: 'datagrid m-2') do
179
+ field_names = ((model.class.allowed_param_names) + %w(description name)).uniq.sort
180
+ field_names.each do |field_name|
181
+ next if model.respond_to?(field_name) && model.send(field_name).blank?
182
+
183
+ concat(model_modal_field(model, field_name))
184
+ end
159
185
  end
160
186
  end
161
187
 
162
- def model_modal_standard(model, _options = {})
163
- content_tag(:table, class: 'center-align highlight') do
164
- concat(content_tag(:tbody) do
165
- %w[_id _type created_at updated_at search_text sort_text].each do |field_name|
166
- concat(model_modal_field(model, field_name))
167
- end
168
- end)
188
+ def model_modal_standard_fields(model, _options = {})
189
+ content_tag(:div, class: 'datagrid m-2') do
190
+ model.class::STANDARD_FIELDS.each do |field_name|
191
+ concat(model_modal_field(model, field_name))
192
+ end
169
193
  end
170
194
  end
171
195
 
172
196
  def model_modal_field(model, field_name)
173
- content_tag(:tr) do
174
- concat(content_tag(:th, class: 'right-align') do
175
- field_name
176
- end)
177
- concat(content_tag(:td) do
178
- model_modal_field_value(model, field_name)
179
- end)
197
+ content_tag(:div, class: 'datagrid-item') do
198
+ concat(content_tag(:div, class: 'datagrid-title') { field_name })
199
+ concat(content_tag(:div, class: 'datagrid-content') { model_modal_field_value(model, field_name) })
180
200
  end
181
201
  end
182
202
 
@@ -191,11 +211,11 @@ module ModelModalHelper
191
211
  related_model.present? ? related_model.name : 'N/A'
192
212
  end
193
213
  when FalseClass
194
- 'No'
214
+ svg_icon(:x, color: :red)
195
215
  when TrueClass
196
- 'Yes'
216
+ svg_icon(:check, color: :green)
197
217
  when Mongoid::Boolean
198
- value ? 'Yes' : 'No'
218
+ value ? svg_icon(:check, color: :green) : svg_icon(:x, color: :red)
199
219
  when Date, DateTime, Time
200
220
  current_user.local_time(value, :long)
201
221
  when Integer, Array, Hash, Float
@@ -207,7 +227,20 @@ module ModelModalHelper
207
227
 
208
228
  def model_modal_footer(model, edit_path)
209
229
  content_tag(:div, class: 'modal-footer') do
230
+ concat(content_tag(:button, class: 'btn me-auto', data: { bs_dismiss: :modal }) do
231
+ concat(I18n.t('ui_form.actions.close'))
232
+ concat(svg_icon(:close))
233
+ end)
210
234
  concat(edit_modal_tag(model, edit_path))
211
235
  end
212
236
  end
237
+
238
+ def edit_modal_tag(obj, path, _options = {})
239
+ return unless can? :edit, obj
240
+
241
+ content_tag(:a, href: path, class: 'modal-action') do
242
+ concat(I18n.t('ui_form.actions.edit'))
243
+ concat(svg_icon(:edit))
244
+ end
245
+ end
213
246
  end
@@ -2,9 +2,13 @@
2
2
  module SvgIconHelper
3
3
  # @abstract Render the appropriate icon based on the name and type
4
4
  # @return [View]
5
- def svg_icon(name, size: 24, type: :outline, classes: [], color: 'currentColor')
6
- classes = ['icon', classes].compact.flatten.join(' ')
7
- key = "icon_partial_path:#{name}:#{type}"
5
+ def svg_icon(name, size: 24, type: :outline, classes: [], color: 'currentColor', stroke_width: 2)
6
+ classes = if size <= 24
7
+ ['icon', classes].compact.flatten.join(' ')
8
+ else
9
+ classes.compact.flatten.join(' ')
10
+ end
11
+ puts "key: #{key}"
8
12
  (partial, stroke) = Rails.cache.fetch(key, expires_in: 1.hour) do
9
13
  path_with_type = "icons/#{name}-#{type}"
10
14
  path_without_type = "icons/#{name}"
@@ -27,12 +31,12 @@ module SvgIconHelper
27
31
  class: classes,
28
32
  fill: 'none',
29
33
  stroke: stroke,
30
- stroke_width: 1,
34
+ stroke_width: stroke_width,
31
35
  stroke_linecap: 'round',
32
36
  stroke_linejoin: 'round') do
33
37
  render partial
34
38
  end
35
- rescue StandardError
39
+ rescue StandardError
36
40
  tag.svg(xmlns: "http://www.w3.org/2000/svg",
37
41
  viewBox: "0 0 24 24",
38
42
  width: size,
@@ -40,7 +44,7 @@ module SvgIconHelper
40
44
  class: classes,
41
45
  fill: 'none',
42
46
  stroke: 'red',
43
- stroke_width: 1,
47
+ stroke_width: stroke_width,
44
48
  stroke_linecap: 'round',
45
49
  stroke_linejoin: 'round',
46
50
  data: { bs_toggle: :tooltip },
@@ -22,6 +22,7 @@ en:
22
22
  axlsx: '%Y-%m-%d'
23
23
  ui_form:
24
24
  actions:
25
+ close: Close
25
26
  reset: Reset
26
27
  cancel: Cancel
27
28
  update: Update
@@ -10,24 +10,25 @@ module StandardModel
10
10
  include Mongoid::Timestamps
11
11
  include App47Logger
12
12
 
13
+ unless defined? FILER_NAMES
14
+ STANDARD_FIELDS = %w[created_at updated_at _type _id search_text sort_text last_modified_by_email
15
+ last_modified_by_name created_by_email created_by_name last_modified_by_id created_by_id
16
+ last_modified_by_type created_by_type].sort
17
+ end
18
+
13
19
  def self.included(base)
14
20
  base.class_eval do
15
- #
21
+ # Constants
16
22
  # Fields
17
- #
18
23
  field :last_modified_by_email, type: String
19
24
  field :last_modified_by_name, type: String
20
25
  field :created_by_email, type: String
21
26
  field :created_by_name, type: String
22
- #
23
27
  # Relationships
24
- #
25
28
  belongs_to :last_modified_by, polymorphic: true, optional: true
26
29
  belongs_to :created_by, polymorphic: true, optional: true
27
30
  has_many Web47core::Config.audit_model_log_symbol, dependent: :nullify, inverse_of: :model
28
- #
29
31
  # Callbacks
30
- #
31
32
  after_save :clear_cache
32
33
  before_destroy :clear_cache
33
34
  before_save :capture_user_info
@@ -62,7 +63,7 @@ module StandardModel
62
63
  #
63
64
  def allowed_param_names(filter_names = [], include_relationships = true)
64
65
  # Always filter out the mongoid reserved items
65
- filter_names += %w[created_at updated_at _type _id search_text sort_text]
66
+ filter_names += STANDARD_FIELDS
66
67
  associations = many_to_many_associations
67
68
  # filter out the relationship names so we don't have dups
68
69
  associations.each { |association| filter_names << association.keys.first }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Web47core
4
- VERSION = '3.2.36'
4
+ VERSION = '3.2.50'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: web47core
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.36
4
+ version: 3.2.50
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Schroeder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-08-06 00:00:00.000000000 Z
11
+ date: 2025-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -529,7 +529,11 @@ files:
529
529
  - app/helpers/core_dropdown_helper.rb
530
530
  - app/helpers/core_flash_toast_helper.rb
531
531
  - app/helpers/core_floating_action_button_helper.rb
532
+ - app/helpers/core_form_checkbox_helper.rb
532
533
  - app/helpers/core_form_helper.rb
534
+ - app/helpers/core_form_input_helper.rb
535
+ - app/helpers/core_form_select_helper.rb
536
+ - app/helpers/core_form_textarea_helper.rb
533
537
  - app/helpers/core_helper.rb
534
538
  - app/helpers/core_html5_form_helper.rb
535
539
  - app/helpers/core_job_state_helper.rb