module Ecoportal module API class V2 class Page class Component class SelectionField < Page::Component passboolean :multiple, :flat, :other passthrough :other_desc passthrough :data_type embeds_many :options, klass: "Ecoportal::API::V2::Page::Component::SelectionOption", order_key: :weight def numeric!(&block) ordered_options.each {|opt| opt.numeric!(&block)} self.data_type = "num" end def text!(&block) ordered_options.each {|opt| opt.text!(&block)} self.data_type = "str" end def select(value) opt = options.find {|opt| opt.value == value} sel = selected return true if !multiple && opt == sel sel.selected = false if !multiple && sel opt.selected = true unless !opt end def selected if multiple options.select {|opt| opt.selected} else options.find {|opt| opt.selected} end end def value if multiple selected.map {|opt| opt.value} else selected&.value end end def add_option(value:, name: nil, pos: NOT_USED, before: NOT_USED, after: NOT_USED) opt_doc = options.items_class.new_doc options.upsert!(opt_doc, pos: pos, before: before, after: after) do |option| option.name = name option.value = value if prev = previous_option(option) option.weight = prev.weight end yield(option) if block_given? fix_option_weights! end end def ordered_options options.sort_by.with_index do |option, index| [option.weight, index] end end # Quick config helper # @param conf [Symbol, Array] # - `:flat` to display in flat mode # - `:multiple` to allow multiple selection # - `:single` to set to singular selection # - `:other` to enable `other` button # - `:options` to add options (`Hash`) # - `:type` to define the type # - `:num` # - `:str` def configure(*conf) conf.each_with_object([]) do |cnf, unused| case cnf when :flat self.flat = true when :multiple self.multiple = true when :single self.multiple = false when :other self.other = true when Hash supported = [:flat, :options, :type] unless (rest = hash_except(cnf.dup, *supported)).empty? unused.push(rest) end if cnf.key?(:flat) then self.flat = cnf[:flat] end if cnf.key?(:options) if opts = cnf[:options] configure_options opts end end if cnf.key?(:type) if cnf[:type] == :str self.text! elsif cnf[:type] == :num self.numeric! else # Unknown type end end else unused.push(cnf) end end.yield_self do |unused| super(*unused) end end private def configure_options(opts) opts.each do |val, nm| add_option(value: val, name: nm) end end def fix_option_weights! ordered_options.each_with_index do |option, index| option.weight = index end end def previous_option(value) opts = ordered_options pos = opts.index(value) - 1 return if pos < 0 opts[pos] end end end end end end end require 'ecoportal/api/v2/page/component/selection_option'