cubesystems/releaf

View on GitHub
releaf-core/app/builders/releaf/builders/page/menu_builder.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Releaf::Builders::Page
  class MenuBuilder
    include Releaf::InstanceCache
    include Releaf::Builders::Base
    include Releaf::Builders::Template

    def output
      compacter << tag(:nav, menu_level(Releaf.application.config.menu))
    end

    def active?(item)
      instance_cache("active_#{item.class.name}_#{item.name}") do
        if item.group?
          item.controllers.find{|subitem| active?(subitem) }.present?
        else
          item.controller_name == controller.short_name
        end
      end
    end

    def menu_level(items)
      level_content = items.map{|item| menu_item(item) }.compact
      tag(:ul){ level_content } if level_content.present?
    end

    def menu_item(item)
      tag(:li, item_attributes(item)) do
        if item.group?
          menu_item_group(item)
        else
          menu_item_single(item)
        end
      end
    end

    def menu_item_single(item)
      tag(:a, class: "trigger", href: item.path) do
        item_name_content(item)
      end
    end

    def menu_item_group(item)
      tag(:span, class: "trigger") do
        item_name_content(item) << item_collapser(item)
      end << menu_level(item.controllers)
    end

    def collapsed_item?(item)
      item.group? && !active?(item) && layout_settings("releaf.menu.collapsed.#{item.name}") == true
    end

    def item_attributes(item)
      attributes = {
        class: item_classes(item),
        data: {
          name: item.name
        }
      }

      attributes.delete(:class) if attributes[:class].empty?
      attributes
    end

    def item_classes(item)
      list = []
      list << "collapsed" if collapsed_item?(item)
      list << "active" if active?(item)
      list
    end

    def item_name_content(item)
      item_full_name    = item.localized_name
      item_abbreviation = item_name_abbreviation( item_full_name )

      tag(:abbr, item_abbreviation, title: item_full_name) + tag(:span, item_full_name, class: "name")
    end

    def item_name_abbreviation( item_full_name )
      return "" if item_full_name.blank?
      # use the first two letters after the last slash that is not preceded by a space
      # to avoid identical abbreviations for namespaced items in case of missing translations
      # but still use the first word in cases of user-entered slashes, e.g. "Inputs / Outputs"
      item_full_name.split(/(?<!\s)\//).last.to_s[0..1].mb_chars.capitalize
    end

    def item_collapser(item)
      tag(:span, class: "collapser") do
        tag(:button, type: "button") do
          item_collapser_icon(item)
        end
      end
    end

    def compact_side?
      layout_settings('releaf.side.compact')
    end

    def item_collapser_icon(item)
      if compact_side?
        icon("chevron-right")
      else
        icon(collapsed_item?(item) ? "chevron-down" : "chevron-up")
      end
    end

    def compacter
      tag(:div, class: "compacter") do
        if compact_side?
          icon_name = "angle-double-right"
          title_attribute = 'title-expand'
        else
          icon_name = "angle-double-left"
          title_attribute = 'title-collapse'
        end
        button(nil, icon_name, title: compacter_data[title_attribute], data: compacter_data )
      end
    end

    def compacter_data
      {
        'title-expand'   => t("Expand", scope: :admin),
        'title-collapse' => t("Collapse", scope: :admin)
      }
    end
  end
end