module Ecoportal module API class V2 class Page class Section < Common::Content::DoubleModel class << self def new_doc(split: false) { "id" => new_uuid, "type" => split ? "split" : "content", "weight" => 800 }.tap do |out| component_ids = if split { "left_component_ids" => [], "right_component_ids" => [] } else { "component_ids" => [] } end out.merge!(component_ids) end end end passkey :id passforced :patch_ver, default: 1 passthrough :weight, :type passthrough :heading, :left_heading, :right_heading passarray :component_ids, :left_component_ids, :right_component_ids passboolean :minimized def split? doc && doc["type"] == "split" end def all_component_ids return component_ids.to_a unless split? left_component_ids.to_a | right_component_ids.to_a end def component?(id) all_component_ids.include?(id) end def components(side: nil) case side when :right components_right when :left components_left when NilClass components_by_id(*all_component_ids) else raise "Side should be one of [nil, :right, :left]. Given: #{side}" end end def components_left raise "You are trying to retrieve side components in a Split Section" unless split? components_by_id(*left_component_ids) end def components_right raise "You are trying to retrieve side components in a Split Section" unless split? components_by_id(*right_component_ids) end # Adds `field` to the section # @note # - To the specified `side`, when split section (default `:left`) # - To the end if `after` is not specified # - If `after` is specified, it searches field # - On the specific `side`, if specified (and split section) # - And adds the `field` after it, when found, or at the end if `after` is not found # @param field [Ecoportal::API::V2::Page::Component] the field to be added. def add_component(field, after: nil, side: nil) raise "field should be a Ecoportal::API::V2::Page::Component. Given: #{field.class}" unless field.is_a?(Ecoportal::API::V2::Page::Component) if field.section == self raise "Field with id '#{field.id}' already belongs to this section" elsif sec = field.section # Field belongs to another section raise "Field with id '#{field.id}' belongs to section '#{sec.heading || "Unnamed"}' (id: '#{sec.id}')" end if split? ids_ary = side == :right ? right_component_ids : left_component_ids fields = components(side: side || :left) else ids_ary = component_ids fields = components end if after after_fld = fields.find do |fld| found = nil found ||= !!after if after.is_a?(Ecoportal::API::V2::Page::Component) found ||= fld.id == after found ||= same_string?(fld.label, after) end end ids_ary.insert_one(field.id, after: after_fld&.id) self end private def components_by_id(*ids) root.components.values_at(*ids).select.with_index do |fld, i| puts "Warning: field id #{ids[i]} points to missing field" if !fld fld && (!block_given? || yield(fld)) end end end end end end end