debian-mirror-gitlab/lib/sidebars/menu.rb

164 lines
4.4 KiB
Ruby
Raw Normal View History

2021-04-29 21:17:54 +05:30
# frozen_string_literal: true
module Sidebars
class Menu
extend ::Gitlab::Utils::Override
include ::Gitlab::Routing
include GitlabRoutingHelper
include Gitlab::Allowable
2021-06-08 01:23:25 +05:30
include ::Sidebars::Concerns::HasPill
include ::Sidebars::Concerns::HasIcon
include ::Sidebars::Concerns::PositionableList
include ::Sidebars::Concerns::Renderable
include ::Sidebars::Concerns::ContainerWithHtmlOptions
include ::Sidebars::Concerns::HasActiveRoutes
2021-10-27 15:23:28 +05:30
include ::Sidebars::Concerns::HasPartial
2021-04-29 21:17:54 +05:30
attr_reader :context
2022-05-07 20:08:51 +05:30
2021-04-29 21:17:54 +05:30
delegate :current_user, :container, to: :@context
def initialize(context)
@context = context
@items = []
configure_menu_items
end
def configure_menu_items
2021-06-08 01:23:25 +05:30
true
2021-04-29 21:17:54 +05:30
end
override :render?
def render?
2021-10-27 15:23:28 +05:30
has_renderable_items? || menu_with_partial?
2021-04-29 21:17:54 +05:30
end
override :link
def link
2021-11-11 11:23:49 +05:30
renderable_items.first&.link
2021-04-29 21:17:54 +05:30
end
# This method normalizes the information retrieved from the submenus and this menu
# Value from menus is something like: [{ path: 'foo', path: 'bar', controller: :foo }]
# This method filters the information and returns: { path: ['foo', 'bar'], controller: :foo }
def all_active_routes
2023-03-04 22:38:38 +05:30
@all_active_routes ||=
2021-04-29 21:17:54 +05:30
([active_routes] + renderable_items.map(&:active_routes)).flatten.each_with_object({}) do |pairs, hash|
pairs.each do |k, v|
hash[k] ||= []
hash[k] += Array(v)
hash[k].uniq!
end
hash
end
end
2021-06-08 01:23:25 +05:30
# Returns whether the menu has any menu item, no
# matter whether it is renderable or not
2021-04-29 21:17:54 +05:30
def has_items?
@items.any?
end
2021-06-08 01:23:25 +05:30
# Returns all renderable menu items
def renderable_items
@renderable_items ||= @items.select(&:render?)
end
2023-07-09 08:55:56 +05:30
# Defines whether menu is separated from others with a top separator
def separated?
false
end
2023-05-27 22:25:52 +05:30
# Returns a tree-like representation of itself and all
# renderable menu entries, with additional information
# on whether the item(s) have an active route
def serialize_for_super_sidebar
items = serialize_items_for_super_sidebar
is_active = @context.route_is_active.call(active_routes) || items.any? { |item| item[:is_active] }
{
title: title,
icon: sprite_icon,
link: link,
is_active: is_active,
pill_count: has_pill? ? pill_count : nil,
2023-07-09 08:55:56 +05:30
items: items,
separated: separated?
2023-05-27 22:25:52 +05:30
}
end
# Returns an array of renderable menu entries,
# with additional information on whether the item
# has an active route
def serialize_items_for_super_sidebar
# All renderable menu entries
renderable_items.map do |entry|
entry.serialize_for_super_sidebar.tap do |item|
active_routes = item.delete(:active_routes)
item[:is_active] = active_routes ? @context.route_is_active.call(active_routes) : false
end
end
end
def pick_into_super_sidebar?
false
end
2021-06-08 01:23:25 +05:30
# Returns whether the menu has any renderable menu item
def has_renderable_items?
renderable_items.any?
end
2021-04-29 21:17:54 +05:30
def add_item(item)
add_element(@items, item)
end
def insert_item_before(before_item, new_item)
insert_element_before(@items, before_item, new_item)
end
def insert_item_after(after_item, new_item)
insert_element_after(@items, after_item, new_item)
end
2023-06-20 00:43:36 +05:30
def replace_placeholder(item)
idx = @items.index { |e| e.item_id == item.item_id && e.is_a?(::Sidebars::NilMenuItem) }
if idx.nil?
add_item(item)
else
replace_element(@items, item.item_id, item)
end
end
2021-09-04 01:27:46 +05:30
override :container_html_options
def container_html_options
super.tap do |html_options|
# Flagging menus that can be rendered and with renderable menu items
if render? && has_renderable_items?
html_options[:class] = [*html_options[:class], 'has-sub-items'].join(' ')
end
end
end
2023-05-27 22:25:52 +05:30
# Sometimes we want to convert a top-level Menu (e.g. Wiki/Snippets)
# to a MenuItem. This serializer is used in order to enable that conversion
def serialize_as_menu_item_args
{
title: title,
link: link,
active_routes: active_routes,
container_html_options: container_html_options
}
end
2021-06-08 01:23:25 +05:30
private
2021-04-29 21:17:54 +05:30
2021-06-08 01:23:25 +05:30
override :index_of
def index_of(list, element)
list.index { |e| e.item_id == element }
2021-04-29 21:17:54 +05:30
end
end
end