From 1c3e89d108081e8b6a413e9b8239c6cb1ccc7021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 5 Feb 2026 11:05:49 +0100 Subject: [PATCH] Fix rendering of multiple dialogs in module menu and allow patching --- config/locales/en.yml | 1 + .../menu_manager/top_menu/module_menu.rb | 51 +++++++++++-------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index db350ee1cf2..e4487b5d002 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3150,6 +3150,7 @@ en: label_always_visible: "Always displayed" label_announcement: "Announcement" label_angular: "AngularJS" + label_app_modules: "%{app_title} modules" label_api_access_key: "API access key" label_api_access_key_created_on: "API access key created %{value} ago" label_api_access_key_type: "API" diff --git a/lib/redmine/menu_manager/top_menu/module_menu.rb b/lib/redmine/menu_manager/top_menu/module_menu.rb index fa5b473cad8..6ed9ad6d6b9 100644 --- a/lib/redmine/menu_manager/top_menu/module_menu.rb +++ b/lib/redmine/menu_manager/top_menu/module_menu.rb @@ -29,7 +29,7 @@ #++ module Redmine::MenuManager::TopMenu::ModuleMenu - def render_module_top_menu_node(item_groups = module_top_menu_item_groups) + def render_module_top_menu_node(item_groups = module_top_menu_item_groups) # rubocop:disable Metrics/AbcSize unless item_groups.empty? render Primer::Alpha::Dialog.new(classes: "op-app-menu--item", title: I18n.t("label_global_modules"), @@ -46,8 +46,14 @@ module Redmine::MenuManager::TopMenu::ModuleMenu render_waffle_menu_logo_icon if show_waffle_icon? end - item_groups.each do |item_group| - render_dialog_item_group(dialog, item_group) + dialog.with_body do + concat call_hook(:module_menu_dialog_content_before) + + item_groups.each do |item_group| + concat render_dialog_item_group(item_group) + end + + concat call_hook(:module_menu_dialog_content_after) end end end @@ -55,32 +61,31 @@ module Redmine::MenuManager::TopMenu::ModuleMenu private - def render_dialog_item_group(dialog, item_group) - dialog.with_body do - render Primer::Alpha::ActionList.new( - classes: "op-app-menu--items", - id: "op-app-header--modules-menu-list" - ) do |list| - list.with_heading(title: item_group[:title], align_items: :flex_start) if item_group[:title] + def render_dialog_item_group(item_group) + render Primer::Alpha::ActionList.new( + classes: "op-app-menu--items", + id: "op-app-header--modules-menu-list" + ) do |list| + list.with_heading(title: item_group[:title], align_items: :flex_start) if item_group[:title] - my_items, remaining_items = item_group[:items].partition { |item| item.context == :my } + my_items, remaining_items = item_group[:items].partition { |item| item.context == :my } - render_action_list_items(list, my_items) + render_action_list_items(list, my_items) - list.with_divider if my_items.any? && remaining_items.any? + list.with_divider if my_items.any? && remaining_items.any? - render_action_list_items(list, remaining_items) - end + render_action_list_items(list, remaining_items) end end def render_action_list_items(list, items) items.each do |item| - label = if item.enterprise_feature_missing? - h(item.caption) + upsell_icon - else - item.caption - end + label = + if item.enterprise_feature_missing? + h(item.caption) + upsell_icon + else + item.caption + end list.with_item( href: url_for(item.url), @@ -102,7 +107,7 @@ module Redmine::MenuManager::TopMenu::ModuleMenu # add untitled group, if no heading is present unless items.first.heading? - item_groups = [{ title: nil, items: [] }] + item_groups = [default_module_menu_group] end # create item groups @@ -117,6 +122,10 @@ module Redmine::MenuManager::TopMenu::ModuleMenu end end + def default_module_menu_group + { title: nil, items: [] } + end + # Menu items for the modules top menu def more_top_menu_items split = split_top_menu_into_main_or_more_menus