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, enum_class: "Ecoportal::API::V2::Page::Component::SelectionOptions" def empty? values.empty? end def numeric? self.data_type == "num" end def text? self.data_type == "txt" end def numeric!(&block) options.ordered.each {|opt| opt.numeric!(&block)} self.data_type = "num" end def text!(&block) options.ordered.each {|opt| opt.text!(&block)} self.data_type = "str" end def switch_type!(&block) numeric? ? text!(&block) : numeric!(&block) end def select(value_name, by_name: false) opt = options.find_option(value_name, by_name: by_name) sel = selected return true if !multiple && opt == sel sel.selected = false if !multiple && sel opt.selected = true unless !opt end def deselect(value_name, by_name: false) if opt = options.find_option(value_name, by_name: by_name) opt.selected = false end end def selected(by_name: false, by_value: false, value: false, name: false) case when by_value elems = [selected].flatten.compact options.hash(elems) do |option| name ? option.name : option end when by_name elems = [selected].flatten.compact options.hash(elems, by_name: true) do |option| value ? option.value : option end else if multiple options.ordered.select {|opt| opt.selected} else options.find {|opt| opt.selected} end end end def value if multiple selected.map {|opt| opt.value} else selected&.value end end def values [value].flatten.compact end def name if multiple selected.map {|opt| opt.name} else selected&.name end end def names [name].flatten.compact end # @see Ecoportal::API::V2::Component::SelectionOptions#add def add_option(**kargs, &block) options.add(**kargs, &block) end def ordered_options options.ordered end # @see Ecoportal::API::V2::Component::SelectionOptions#by_value def options_by_value(name: false) options.by_value(name: name) end # @see Ecoportal::API::V2::Component::SelectionOptions#by_name def options_by_name(value: false) options.by_name(value: value) end def to_s(value: true, delimiter: "\n") [selected].flatten.compact.map do |opt| value ? opt.value : opt.name end.join(delimiter) 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`) or update option names # - `: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) hopts = self.options_by_value opts.each do |val, nm| if option = hopts[val] option.name = nm else add_option(value: val, name: nm) end end end end end end end end end require 'ecoportal/api/v2/page/component/selection_options' require 'ecoportal/api/v2/page/component/selection_option'