Class: HakumiComponents::Transfer::Component

Inherits:
BaseComponent
  • Object
show all
Extended by:
T::Sig
Includes:
Concerns::FormField
Defined in:
app/components/hakumi_components/transfer/component.rb

Constant Summary collapse

ItemInput =
T.type_alias { HakumiComponents::Transfer::Coercion::ItemInput }
PaginationHash =
T.type_alias do
  T::Hash[Types::HtmlKey, Types::HtmlPrimitive]
end
OperationsHash =
T.type_alias do
  T::Hash[Types::HtmlKey, T.nilable(Types::HtmlKey)]
end
ControllerScalar =
T.type_alias { T.nilable(Types::ValidationPrimitive) }
StringArrayValue =
T.type_alias { T::Array[String] }
ItemArrayValue =
T.type_alias { T::Array[ItemInput] }
PaginationScalar =
T.type_alias { T.any(String, T::Boolean) }
PaginationInput =
T.type_alias { T.nilable(T.any(PaginationScalar, PaginationHash)) }
PaginationValue =
T.type_alias { T.nilable(T.any(T::Boolean, PaginationHash)) }
ControllerCollection =
T.type_alias { T.any(StringArrayValue, ItemArrayValue, PaginationHash) }
ControllerParam =
T.type_alias { T.nilable(T.any(ControllerScalar, ControllerCollection)) }
ControllerLocalValue =
T.type_alias { T.nilable(T.any(ControllerScalar, ControllerCollection)) }
ControllerLocals =
T.type_alias { T::Hash[Symbol, ControllerLocalValue] }
PaginationDataValue =
T.type_alias { Types::HtmlPrimitive }
StringOrItemsInput =
T.type_alias { T.nilable(T.any(String, ItemArrayValue)) }
StringOrStringsInput =
T.type_alias { T.nilable(T.any(String, StringArrayValue)) }
RenderItem =
T.type_alias do
  T.nilable(T.any(
    T.proc.params(item: HakumiComponents::Transfer::Item).returns(Types::Renderable),
    Types::ComponentRenderable
  ))
end

Constants inherited from BaseComponent

BaseComponent::ControllerOptions, BaseComponent::DateInput, BaseComponent::DateLikeValue, BaseComponent::DimensionInput, BaseComponent::HtmlPayloadInput, BaseComponent::I18nOptionValue, BaseComponent::PresenceArray, BaseComponent::PresenceScalar, BaseComponent::PresenceValue, BaseComponent::RawHtmlInput, BaseComponent::SIZES, BaseComponent::SizeValue, BaseComponent::SymbolInput

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Concerns::FormField

#describedby_ids, #error?, #error_message, #form_field_caption, #form_field_contract, #form_field_errors, #form_field_html_options, #form_field_label, #form_field_name, #form_field_required, #form_field_rules, #form_field_standalone, #form_item_attributes, #form_item_classes, #input_id, #render_caption, #render_error, #render_explain, #render_label, #standalone?

Methods included from Concerns::FormFieldInterface

#form_field_contract

Methods inherited from BaseComponent

#append_data_token, boolean_html_param, #build_inline_style, cast_boolean, #cast_boolean, #class_names, #component_classes, #data_attributes_from, #dimension_to_css, #ensure_dom_id!, float_html_param, #generate_id, #html_classes, html_param, html_primitive_param, #html_style, #i18n_scope, integer_html_param, #merge_attributes, #render_value, #size_to_pixels, #stimulus_attrs, string_html_param, string_or_symbol_array_html_param, symbol_html_param, #t_default, #translate_with_default, #validate_inclusion!, #validate_required!, #value_present?

Constructor Details

#initialize(data_source:, target_keys: nil, name: nil, label: nil, caption: nil, value: nil, titles: nil, disabled: false, required: false, show_search: false, show_select_all: true, one_way: false, pagination: false, standalone: true, rules: nil, errors: [], render_item: nil, operations: nil, search_placeholder: nil, **html_options) ⇒ Component

Returns a new instance of Component.



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'app/components/hakumi_components/transfer/component.rb', line 76

def initialize(
  data_source:,
  target_keys: nil,
  name: nil,
  label: nil,
  caption: nil,
  value: nil,
  titles: nil,
  disabled: false,
  required: false,
  show_search: false,
  show_select_all: true,
  one_way: false,
  pagination: false,
  standalone: true,
  rules: nil,
  errors: [],
  render_item: nil,
  operations: nil,
  search_placeholder: nil,
  **html_options
)
  @name = T.let(normalize_string(name) || generate_id("transfer"), Types::FormFieldName)
  @label = label
  @caption = caption
  @value = T.let(value, Types::FormFieldValue)
  @disabled = T.let(cast_boolean(disabled) == true, T::Boolean)
  @required = T.let(cast_boolean(required) == true, T::Boolean)
  @standalone = T.let(cast_boolean(standalone) != false, T::Boolean)
  @rules = T.let(rules, T.nilable(T::Array[Types::ValidationRule]))
  @errors = T.let(errors, Types::FormFieldErrors)
  @html_options = T.let(html_options, Types::HtmlAttributes)
  @data_source = T.let(HakumiComponents::Transfer::Coercion.items(data_source, disabled: @disabled), T::Array[HakumiComponents::Transfer::Item])
  @target_keys = T.let(normalize_target_keys(target_keys, value), T::Array[String])
  @titles = T.let(normalize_titles(titles), [ String, String ])
  @show_search = T.let(cast_boolean(show_search) == true, T::Boolean)
  @show_select_all = T.let(cast_boolean(show_select_all) != false, T::Boolean)
  @one_way = T.let(cast_boolean(one_way) == true, T::Boolean)
  @pagination = T.let(pagination, PaginationValue)
  @render_item = T.let(render_item, RenderItem)
  @operations = T.let(normalize_operations(operations), HakumiComponents::Transfer::Operations)
  @search_placeholder = search_placeholder
  @source_items = T.let(nil, T.nilable(T::Array[HakumiComponents::Transfer::Item]))
  @target_items = T.let(nil, T.nilable(T::Array[HakumiComponents::Transfer::Item]))
  initialize_form_field_contract!(
    name: @name,
    label: @label,
    caption: @caption,
    errors: @errors,
    standalone: @standalone,
    required: @required,
    html_options: @html_options,
    rules: @rules
  )

  validate_props!
end

Instance Attribute Details

#operationsObject (readonly)

Returns the value of attribute operations.



138
139
140
# File 'app/components/hakumi_components/transfer/component.rb', line 138

def operations
  @operations
end

#titlesObject (readonly)

Returns the value of attribute titles.



135
136
137
# File 'app/components/hakumi_components/transfer/component.rb', line 135

def titles
  @titles
end

Class Method Details

.boolean_param(value, default: false) ⇒ Object



354
355
356
357
358
# File 'app/components/hakumi_components/transfer/component.rb', line 354

def self.boolean_param(value, default: false)
  return default if value.nil?

  cast_boolean(value) == true
end

.boolean_param_input(value) ⇒ Object



381
382
383
384
385
# File 'app/components/hakumi_components/transfer/component.rb', line 381

def self.boolean_param_input(value)
  return value if value.is_a?(String) || value.is_a?(Symbol) || value.is_a?(Numeric) || value == true || value == false

  nil
end

.data_source_param(value) ⇒ Object



361
362
363
364
365
366
367
368
369
370
371
# File 'app/components/hakumi_components/transfer/component.rb', line 361

def self.data_source_param(value)
  return value if value.is_a?(String)

  if value.is_a?(Array)
    items = T.let([], T::Array[ItemInput])
    value.each { |item| items << item if item.is_a?(HakumiComponents::Transfer::Item) || item.is_a?(Hash) || item.is_a?(String) || item.is_a?(Symbol) || item.is_a?(Numeric) || item == true || item == false || item.nil? || item.is_a?(Date) || item.is_a?(Time) || item.is_a?(DateTime) || item.is_a?(ActiveSupport::TimeWithZone) }
    return items
  end

  nil
end

.extract_controller_locals(params) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'app/components/hakumi_components/transfer/component.rb', line 38

def self.extract_controller_locals(params)
  {
    data_source: parse_data_source(data_source_param(params[:data_source])),
    target_keys: parse_json_array(string_array_param(params[:target_keys])),
    titles: parse_json_array(string_array_param(params[:titles])),
    disabled: boolean_param(boolean_param_input(params[:disabled])),
    show_search: boolean_param(boolean_param_input(params[:show_search])),
    show_select_all: boolean_param(boolean_param_input(params[:show_select_all]), default: true),
    one_way: boolean_param(boolean_param_input(params[:one_way])),
    pagination: parse_pagination(pagination_param(params[:pagination])),
    name: params[:name]
  }.compact
end

.pagination_param(value) ⇒ Object



388
389
390
391
392
# File 'app/components/hakumi_components/transfer/component.rb', line 388

def self.pagination_param(value)
  return value if value.is_a?(String) || value == true || value == false || value.is_a?(Hash)

  nil
end

.parse_data_source(value) ⇒ Object



314
315
316
317
318
319
320
321
322
# File 'app/components/hakumi_components/transfer/component.rb', line 314

def self.parse_data_source(value)
  return [] if value.nil? || value == ""
  return value if value.is_a?(Array)

  parsed = JSON.parse(value)
  parsed.is_a?(Array) ? parsed : []
rescue JSON::ParserError
  []
end

.parse_json_array(value) ⇒ Object



325
326
327
328
329
330
331
332
333
334
335
# File 'app/components/hakumi_components/transfer/component.rb', line 325

def self.parse_json_array(value)
  return [] if value.nil? || value == ""
  return value if value.is_a?(Array)

  parsed = JSON.parse(value)
  return [] unless parsed.is_a?(Array)

  parsed.map(&:to_s)
rescue JSON::ParserError
  []
end

.parse_pagination(value) ⇒ Object



338
339
340
341
342
343
344
345
346
347
348
349
350
351
# File 'app/components/hakumi_components/transfer/component.rb', line 338

def self.parse_pagination(value)
  return false if value.nil?
  return value if value.is_a?(Hash)
  return value if value == true || value == false
  return false unless value.is_a?(String)

  string_value = value
  parsed = JSON.parse(string_value)
  return parsed if parsed.is_a?(Hash) || parsed == true || parsed == false

  false
rescue JSON::ParserError
  cast_boolean(string_value)
end

.string_array_param(value) ⇒ Object



374
375
376
377
378
# File 'app/components/hakumi_components/transfer/component.rb', line 374

def self.string_array_param(value)
  return value if value.is_a?(String)

  value.is_a?(Array) ? value.map(&:to_s) : nil
end

Instance Method Details

#disabled?Boolean

Returns:

  • (Boolean)


181
182
183
# File 'app/components/hakumi_components/transfer/component.rb', line 181

def disabled?
  @disabled
end

#item_checkbox_id(item, panel, index) ⇒ Object



201
202
203
# File 'app/components/hakumi_components/transfer/component.rb', line 201

def item_checkbox_id(item, panel, index)
  "#{@name}_#{panel}_#{index}_#{item.key}"
end

#item_classes(item) ⇒ Object



196
197
198
# File 'app/components/hakumi_components/transfer/component.rb', line 196

def item_classes(item)
  class_names("transfer-list-item", { disabled: item.disabled }, [ item.class_name ])
end

#item_content(item) ⇒ Object



206
207
208
209
210
211
212
213
214
# File 'app/components/hakumi_components/transfer/component.rb', line 206

def item_content(item)
  if @render_item.is_a?(Proc)
    render_value(@render_item.call(item))
  elsif @render_item&.respond_to?(:render_in)
    render(@render_item)
  else
    item.title.to_s
  end
end

#item_description(item) ⇒ Object



217
218
219
220
221
# File 'app/components/hakumi_components/transfer/component.rb', line 217

def item_description(item)
  return nil if @render_item

  render_value(item.description)
end

#one_way?Boolean

Returns:

  • (Boolean)


186
187
188
# File 'app/components/hakumi_components/transfer/component.rb', line 186

def one_way?
  @one_way
end

#pagination?Boolean

Returns:

  • (Boolean)


191
192
193
# File 'app/components/hakumi_components/transfer/component.rb', line 191

def pagination?
  !@pagination.nil? && @pagination != false
end

#search_placeholderObject



141
142
143
# File 'app/components/hakumi_components/transfer/component.rb', line 141

def search_placeholder
  @search_placeholder || t_default(:search_placeholder, default: "Search")
end

#show_search?Boolean

Returns:

  • (Boolean)


171
172
173
# File 'app/components/hakumi_components/transfer/component.rb', line 171

def show_search?
  @show_search
end

#show_select_all?Boolean

Returns:

  • (Boolean)


176
177
178
# File 'app/components/hakumi_components/transfer/component.rb', line 176

def show_select_all?
  @show_select_all
end

#source_itemsObject



156
157
158
# File 'app/components/hakumi_components/transfer/component.rb', line 156

def source_items
  @source_items ||= @data_source.reject { |item| @target_keys.include?(item.key) }
end

#target_itemsObject



161
162
163
164
165
166
167
168
# File 'app/components/hakumi_components/transfer/component.rb', line 161

def target_items
  @target_items ||= begin
    item_map = @data_source.each_with_object(T.let({}, T::Hash[String, HakumiComponents::Transfer::Item])) do |item, hash|
      hash[item.key] = item
    end
    @target_keys.filter_map { |key| item_map[key] }
  end
end

#wrapper_attributesObject



146
147
148
149
150
151
152
153
# File 'app/components/hakumi_components/transfer/component.rb', line 146

def wrapper_attributes
  attrs = {
    class: wrapper_classes,
    data: data_attributes
  }

  merge_attributes(attrs, form_field_html_options.except(:class))
end