Return NilMenuItems instead of nil in project menu items

In this commit we change how creating menu items in the
project sidebar works.

Before, when the user couldn't see a menu item, we will
return `nil` and avoid displaying it, but this has a problem.

If we later want to reference it, in order to add another
menu item based on that item position, the menu item
won't exist.

In this commit we return a `NilMenuItem` instead of
a `nil` value, whenever the menu item can't be rendered.
parent ff721e29
......@@ -25,7 +25,9 @@ module EE
private
def insights_menu_item
return unless context.project.insights_available?
unless context.project.insights_available?
return ::Sidebars::NilMenuItem.new(item_id: :insights)
end
::Sidebars::MenuItem.new(
title: _('Insights'),
......@@ -37,7 +39,9 @@ module EE
end
def code_review_analytics_menu_item
return unless can?(context.current_user, :read_code_review_analytics, context.project)
unless can?(context.current_user, :read_code_review_analytics, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :code_review)
end
::Sidebars::MenuItem.new(
title: _('Code Review'),
......@@ -48,9 +52,9 @@ module EE
end
def issues_analytics_menu_item
return unless ::Feature.enabled?(:project_level_issues_analytics, context.project, default_enabled: true)
return unless context.project.licensed_feature_available?(:issues_analytics)
return unless can?(context.current_user, :read_project, context.project)
unless show_issues_analytics?
return ::Sidebars::NilMenuItem.new(item_id: :issues)
end
::Sidebars::MenuItem.new(
title: _('Issue'),
......@@ -60,8 +64,16 @@ module EE
)
end
def show_issues_analytics?
::Feature.enabled?(:project_level_issues_analytics, context.project, default_enabled: true) &&
context.project.licensed_feature_available?(:issues_analytics) &&
can?(context.current_user, :read_project, context.project)
end
def merge_request_analytics_menu_item
return unless can?(context.current_user, :read_project_merge_request_analytics, context.project)
unless can?(context.current_user, :read_project_merge_request_analytics, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :merge_requests)
end
::Sidebars::MenuItem.new(
title: _('Merge Request'),
......
......@@ -19,8 +19,10 @@ module EE
private
def test_cases_menu_item
return unless context.project.licensed_feature_available?(:quality_management)
return unless can?(context.current_user, :read_issue, context.project)
if !context.project.licensed_feature_available?(:quality_management) ||
!can?(context.current_user, :read_issue, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :test_cases)
end
::Sidebars::MenuItem.new(
title: _('Test Cases'),
......
......@@ -19,8 +19,10 @@ module EE
private
def iterations_menu_item
return unless context.project.licensed_feature_available?(:iterations)
return unless can?(context.current_user, :read_iteration, context.project)
if !context.project.licensed_feature_available?(:iterations) ||
!can?(context.current_user, :read_iteration, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :iterations)
end
::Sidebars::MenuItem.new(
title: _('Iterations'),
......
......@@ -20,7 +20,9 @@ module EE
private
def on_call_schedules_menu_item
return unless can?(context.current_user, :read_incident_management_oncall_schedule, context.project)
unless can?(context.current_user, :read_incident_management_oncall_schedule, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :on_call_schedules)
end
::Sidebars::MenuItem.new(
title: _('On-call Schedules'),
......@@ -31,7 +33,9 @@ module EE
end
def escalation_policies_menu_item
return unless can?(context.current_user, :read_incident_management_escalation_policy, context.project)
unless can?(context.current_user, :read_incident_management_escalation_policy, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :escalation_policies)
end
::Sidebars::MenuItem.new(
title: _('Escalation policies'),
......
......@@ -19,7 +19,9 @@ module EE
private
def file_locks_menu_item
return unless context.project.licensed_feature_available?(:file_locks)
unless context.project.licensed_feature_available?(:file_locks)
return ::Sidebars::NilMenuItem.new(item_id: :file_locks)
end
::Sidebars::MenuItem.new(
title: _('Locked Files'),
......
......@@ -27,9 +27,9 @@ module EE
override :link
def link
return project_security_discover_path(context.project) unless has_items?
return security_dashboard_menu_item.link if security_dashboard_menu_item
return audit_events_menu_item.link if audit_events_menu_item
return dependencies_menu_item.link if dependencies_menu_item
return security_dashboard_menu_item.link if security_dashboard_menu_item.render?
return audit_events_menu_item.link if audit_events_menu_item.render?
return dependencies_menu_item.link if dependencies_menu_item.render?
renderable_items.first.link
end
......@@ -62,7 +62,9 @@ module EE
def security_dashboard_menu_item
strong_memoize(:security_dashboard_menu_item) do
next unless can?(context.current_user, :read_project_security_dashboard, context.project)
unless can?(context.current_user, :read_project_security_dashboard, context.project)
next ::Sidebars::NilMenuItem.new(item_id: :dashboard)
end
::Sidebars::MenuItem.new(
title: _('Security Dashboard'),
......@@ -75,7 +77,9 @@ module EE
def vulnerability_report_menu_item
strong_memoize(:vulnerability_report_menu_item) do
next unless can?(context.current_user, :read_project_security_dashboard, context.project)
unless can?(context.current_user, :read_project_security_dashboard, context.project)
next ::Sidebars::NilMenuItem.new(item_id: :vulnerability_report)
end
::Sidebars::MenuItem.new(
title: _('Vulnerability Report'),
......@@ -88,7 +92,9 @@ module EE
def on_demand_scans_menu_item
strong_memoize(:on_demand_scans_menu_item) do
next unless can?(context.current_user, :read_on_demand_scans, context.project)
unless can?(context.current_user, :read_on_demand_scans, context.project)
next ::Sidebars::NilMenuItem.new(item_id: :on_demand_scans)
end
::Sidebars::MenuItem.new(
title: s_('OnDemandScans|On-demand Scans'),
......@@ -105,7 +111,9 @@ module EE
def dependencies_menu_item
strong_memoize(:dependencies_menu_item) do
next unless can?(context.current_user, :read_dependencies, context.project)
unless can?(context.current_user, :read_dependencies, context.project)
next ::Sidebars::NilMenuItem.new(item_id: :dependency_list)
end
::Sidebars::MenuItem.new(
title: _('Dependency List'),
......@@ -118,7 +126,9 @@ module EE
def license_compliance_menu_item
strong_memoize(:license_compliance_menu_item) do
next unless can?(context.current_user, :read_licenses, context.project)
unless can?(context.current_user, :read_licenses, context.project)
next ::Sidebars::NilMenuItem.new(item_id: :license_compliance)
end
::Sidebars::MenuItem.new(
title: _('License Compliance'),
......@@ -131,7 +141,9 @@ module EE
def threat_monitoring_menu_item
strong_memoize(:threat_monitoring_menu_item) do
next unless can?(context.current_user, :read_threat_monitoring, context.project)
unless can?(context.current_user, :read_threat_monitoring, context.project)
next ::Sidebars::NilMenuItem.new(item_id: :threat_monitoring)
end
::Sidebars::MenuItem.new(
title: _('Threat Monitoring'),
......@@ -144,8 +156,10 @@ module EE
def scan_policies_menu_item
strong_memoize(:scan_policies_menu_item) do
next if ::Feature.disabled?(:security_orchestration_policies_configuration, context.project)
next unless can?(context.current_user, :security_orchestration_policies, context.project)
if ::Feature.disabled?(:security_orchestration_policies_configuration, context.project) ||
!can?(context.current_user, :security_orchestration_policies, context.project)
next ::Sidebars::NilMenuItem.new(item_id: :scan_policies)
end
::Sidebars::MenuItem.new(
title: _('Scan Policies'),
......@@ -158,8 +172,9 @@ module EE
def audit_events_menu_item
strong_memoize(:audit_events_menu_item) do
next unless can?(context.current_user, :read_project_audit_events, context.project)
next unless context.project.licensed_feature_available?(:audit_events) || context.show_promotions
unless show_audit_events?
next ::Sidebars::NilMenuItem.new(item_id: :audit_events)
end
::Sidebars::MenuItem.new(
title: _('Audit Events'),
......@@ -169,6 +184,11 @@ module EE
)
end
end
def show_audit_events?
can?(context.current_user, :read_project_audit_events, context.project) &&
(context.project.licensed_feature_available?(:audit_events) || context.show_promotions)
end
end
end
end
......
......@@ -37,7 +37,9 @@ module Sidebars
private
def list_menu_item
return if Feature.enabled?(:sidebar_refactor, context.current_user)
if Feature.enabled?(:sidebar_refactor, context.current_user)
return ::Sidebars::NilMenuItem.new(item_id: :requirements_list)
end
::Sidebars::MenuItem.new(
title: _('List'),
......
......@@ -19,7 +19,7 @@ module Sidebars
override :link
def link
return cycle_analytics_menu_item.link if cycle_analytics_menu_item
return cycle_analytics_menu_item.link if cycle_analytics_menu_item.render?
renderable_items.first.link
end
......@@ -44,9 +44,11 @@ module Sidebars
private
def ci_cd_analytics_menu_item
return if context.project.empty_repo?
return unless context.project.feature_available?(:builds, context.current_user)
return unless can?(context.current_user, :read_build, context.project)
if !context.project.feature_available?(:builds, context.current_user) ||
!can?(context.current_user, :read_build, context.project) ||
context.project.empty_repo?
return ::Sidebars::NilMenuItem.new(item_id: :ci_cd_analytics)
end
::Sidebars::MenuItem.new(
title: _('CI/CD'),
......@@ -57,7 +59,9 @@ module Sidebars
end
def repository_analytics_menu_item
return if context.project.empty_repo?
if context.project.empty_repo?
return ::Sidebars::NilMenuItem.new(item_id: :repository_analytics)
end
::Sidebars::MenuItem.new(
title: _('Repository'),
......@@ -70,7 +74,9 @@ module Sidebars
def cycle_analytics_menu_item
strong_memoize(:cycle_analytics_menu_item) do
next unless can?(context.current_user, :read_cycle_analytics, context.project)
unless can?(context.current_user, :read_cycle_analytics, context.project)
next ::Sidebars::NilMenuItem.new(item_id: :cycle_analytics)
end
::Sidebars::MenuItem.new(
title: _('Value Stream'),
......
......@@ -65,7 +65,9 @@ module Sidebars
end
def pipelines_editor_menu_item
return unless context.can_view_pipeline_editor
unless context.can_view_pipeline_editor
return ::Sidebars::NilMenuItem.new(item_id: :pipelines_editor)
end
::Sidebars::MenuItem.new(
title: s_('Pipelines|Editor'),
......@@ -86,7 +88,9 @@ module Sidebars
end
def artifacts_menu_item
return unless Feature.enabled?(:artifacts_management_page, context.project)
unless Feature.enabled?(:artifacts_management_page, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :artifacts)
end
::Sidebars::MenuItem.new(
title: _('Artifacts'),
......
......@@ -29,8 +29,10 @@ module Sidebars
end
def graph_menu_item
return unless can?(context.current_user, :download_code, context.project)
return if context.project.empty_repo?
if !can?(context.current_user, :download_code, context.project) ||
context.project.empty_repo?
return ::Sidebars::NilMenuItem.new(item_id: :graph)
end
::Sidebars::MenuItem.new(
title: _('Graph'),
......@@ -42,7 +44,9 @@ module Sidebars
end
def new_issue_menu_item
return unless can?(context.current_user, :read_issue, context.project)
unless can?(context.current_user, :read_issue, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :new_issue)
end
::Sidebars::MenuItem.new(
title: _('Create a new issue'),
......@@ -54,7 +58,9 @@ module Sidebars
end
def jobs_menu_item
return unless can?(context.current_user, :read_build, context.project)
unless can?(context.current_user, :read_build, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :jobs)
end
::Sidebars::MenuItem.new(
title: _('Jobs'),
......@@ -66,8 +72,10 @@ module Sidebars
end
def commits_menu_item
return unless can?(context.current_user, :download_code, context.project)
return if context.project.empty_repo?
if !can?(context.current_user, :download_code, context.project) ||
context.project.empty_repo?
return ::Sidebars::NilMenuItem.new(item_id: :commits)
end
::Sidebars::MenuItem.new(
title: _('Commits'),
......@@ -79,7 +87,9 @@ module Sidebars
end
def issue_boards_menu_item
return unless can?(context.current_user, :read_issue, context.project)
unless can?(context.current_user, :read_issue, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :issue_boards)
end
::Sidebars::MenuItem.new(
title: _('Issue Boards'),
......
......@@ -41,7 +41,9 @@ module Sidebars
private
def kubernetes_menu_item
return unless can?(context.current_user, :read_cluster, context.project)
unless can?(context.current_user, :read_cluster, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :kubernetes)
end
::Sidebars::MenuItem.new(
title: _('Kubernetes clusters'),
......@@ -67,7 +69,9 @@ module Sidebars
end
def serverless_menu_item
return unless can?(context.current_user, :read_cluster, context.project)
unless can?(context.current_user, :read_cluster, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :serverless)
end
::Sidebars::MenuItem.new(
title: _('Serverless platform'),
......@@ -78,7 +82,9 @@ module Sidebars
end
def terraform_menu_item
return unless can?(context.current_user, :read_terraform_state, context.project)
unless can?(context.current_user, :read_terraform_state, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :terraform)
end
::Sidebars::MenuItem.new(
title: _('Terraform'),
......
......@@ -58,7 +58,9 @@ module Sidebars
private
def metrics_dashboard_menu_item
return unless can?(context.current_user, :metrics_dashboard, context.project)
unless can?(context.current_user, :metrics_dashboard, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :metrics)
end
::Sidebars::MenuItem.new(
title: _('Metrics'),
......@@ -70,8 +72,10 @@ module Sidebars
end
def logs_menu_item
return unless can?(context.current_user, :read_environment, context.project)
return unless can?(context.current_user, :read_pod_logs, context.project)
if !can?(context.current_user, :read_environment, context.project) ||
!can?(context.current_user, :read_pod_logs, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :logs)
end
::Sidebars::MenuItem.new(
title: _('Logs'),
......@@ -82,8 +86,10 @@ module Sidebars
end
def tracing_menu_item
return unless can?(context.current_user, :read_environment, context.project)
return unless can?(context.current_user, :admin_project, context.project)
if !can?(context.current_user, :read_environment, context.project) ||
!can?(context.current_user, :admin_project, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :tracing)
end
::Sidebars::MenuItem.new(
title: _('Tracing'),
......@@ -94,7 +100,9 @@ module Sidebars
end
def error_tracking_menu_item
return unless can?(context.current_user, :read_sentry_issue, context.project)
unless can?(context.current_user, :read_sentry_issue, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :error_tracking)
end
::Sidebars::MenuItem.new(
title: _('Error Tracking'),
......@@ -105,7 +113,9 @@ module Sidebars
end
def alert_management_menu_item
return unless can?(context.current_user, :read_alert_management_alert, context.project)
unless can?(context.current_user, :read_alert_management_alert, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :alert_management)
end
::Sidebars::MenuItem.new(
title: _('Alerts'),
......@@ -116,7 +126,9 @@ module Sidebars
end
def incidents_menu_item
return unless can?(context.current_user, :read_issue, context.project)
unless can?(context.current_user, :read_issue, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :incidents)
end
::Sidebars::MenuItem.new(
title: _('Incidents'),
......@@ -127,8 +139,10 @@ module Sidebars
end
def serverless_menu_item
return if Feature.enabled?(:sidebar_refactor, context.current_user)
return unless can?(context.current_user, :read_cluster, context.project)
if Feature.enabled?(:sidebar_refactor, context.current_user) ||
!can?(context.current_user, :read_cluster, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :serverless)
end
::Sidebars::MenuItem.new(
title: _('Serverless'),
......@@ -139,8 +153,10 @@ module Sidebars
end
def terraform_menu_item
return if Feature.enabled?(:sidebar_refactor, context.current_user)
return unless can?(context.current_user, :read_terraform_state, context.project)
if Feature.enabled?(:sidebar_refactor, context.current_user) ||
!can?(context.current_user, :read_terraform_state, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :terraform)
end
::Sidebars::MenuItem.new(
title: _('Terraform'),
......@@ -151,8 +167,10 @@ module Sidebars
end
def kubernetes_menu_item
return if Feature.enabled?(:sidebar_refactor, context.current_user)
return unless can?(context.current_user, :read_cluster, context.project)
if Feature.enabled?(:sidebar_refactor, context.current_user) ||
!can?(context.current_user, :read_cluster, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :kubernetes)
end
::Sidebars::MenuItem.new(
title: _('Kubernetes'),
......@@ -178,7 +196,9 @@ module Sidebars
end
def environments_menu_item
return unless can?(context.current_user, :read_environment, context.project)
unless can?(context.current_user, :read_environment, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :environments)
end
::Sidebars::MenuItem.new(
title: _('Environments'),
......@@ -190,7 +210,9 @@ module Sidebars
end
def feature_flags_menu_item
return unless can?(context.current_user, :read_feature_flag, context.project)
unless can?(context.current_user, :read_feature_flag, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :feature_flags)
end
::Sidebars::MenuItem.new(
title: _('Feature Flags'),
......@@ -202,8 +224,10 @@ module Sidebars
end
def product_analytics_menu_item
return if Feature.disabled?(:product_analytics, context.project)
return unless can?(context.current_user, :read_product_analytics, context.project)
if Feature.disabled?(:product_analytics, context.project) ||
!can?(context.current_user, :read_product_analytics, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :product_analytics)
end
::Sidebars::MenuItem.new(
title: _('Product Analytics'),
......
......@@ -31,8 +31,9 @@ module Sidebars
private
def packages_registry_menu_item
return unless ::Gitlab.config.packages.enabled
return unless can?(context.current_user, :read_package, context.project)
if !::Gitlab.config.packages.enabled || !can?(context.current_user, :read_package, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :packages_registry)
end
::Sidebars::MenuItem.new(
title: _('Package Registry'),
......@@ -44,8 +45,9 @@ module Sidebars
end
def container_registry_menu_item
return unless ::Gitlab.config.registry.enabled
return unless can?(context.current_user, :read_container_image, context.project)
if !::Gitlab.config.registry.enabled || !can?(context.current_user, :read_container_image, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :container_registry)
end
::Sidebars::MenuItem.new(
title: _('Container Registry'),
......@@ -56,7 +58,9 @@ module Sidebars
end
def infrastructure_registry_menu_item
return if Feature.disabled?(:infrastructure_registry_page, context.current_user)
if Feature.disabled?(:infrastructure_registry_page, context.current_user)
return ::Sidebars::NilMenuItem.new(item_id: :infrastructure_registry)
end
::Sidebars::MenuItem.new(
title: _('Infrastructure Registry'),
......
......@@ -83,8 +83,9 @@ module Sidebars
end
def releases_menu_item
return unless can?(context.current_user, :read_release, context.project)
return if context.project.empty_repo?
if !can?(context.current_user, :read_release, context.project) || context.project.empty_repo?
return ::Sidebars::NilMenuItem.new(item_id: :releases)
end
::Sidebars::MenuItem.new(
title: _('Releases'),
......
......@@ -34,7 +34,9 @@ module Sidebars
def configuration_menu_item
strong_memoize(:configuration_menu_item) do
next unless render_configuration_menu_item?
unless render_configuration_menu_item?
next ::Sidebars::NilMenuItem.new(item_id: :configuration)
end
::Sidebars::MenuItem.new(
title: _('Configuration'),
......
......@@ -73,7 +73,9 @@ module Sidebars
end
def access_tokens_menu_item
return unless can?(context.current_user, :read_resource_access_tokens, context.project)
unless can?(context.current_user, :read_resource_access_tokens, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :access_tokens)
end
::Sidebars::MenuItem.new(
title: _('Access Tokens'),
......@@ -93,8 +95,9 @@ module Sidebars
end
def ci_cd_menu_item
return if context.project.archived?
return unless context.project.feature_available?(:builds, context.current_user)
if context.project.archived? || !context.project.feature_available?(:builds, context.current_user)
return ::Sidebars::NilMenuItem.new(item_id: :ci_cd)
end
::Sidebars::MenuItem.new(
title: _('CI/CD'),
......@@ -105,8 +108,9 @@ module Sidebars
end
def operations_menu_item
return if context.project.archived?
return unless can?(context.current_user, :admin_operations, context.project)
if context.project.archived? || !can?(context.current_user, :admin_operations, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :operations)
end
::Sidebars::MenuItem.new(
title: _('Operations'),
......@@ -117,7 +121,9 @@ module Sidebars
end
def pages_menu_item
return unless context.project.pages_available?
unless context.project.pages_available?
return ::Sidebars::NilMenuItem.new(item_id: :pages)
end
::Sidebars::MenuItem.new(
title: _('Pages'),
......@@ -128,9 +134,11 @@ module Sidebars
end
def packages_and_registries_menu_item
return unless Gitlab.config.registry.enabled
return if Feature.disabled?(:sidebar_refactor, context.current_user)
return unless can?(context.current_user, :destroy_container_image, context.project)
if !Gitlab.config.registry.enabled ||
Feature.disabled?(:sidebar_refactor, context.current_user) ||
!can?(context.current_user, :destroy_container_image, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :packages_and_registries)
end
::Sidebars::MenuItem.new(
title: _('Packages & Registries'),
......
......@@ -47,7 +47,7 @@ RSpec.describe Sidebars::Projects::Menus::AnalyticsMenu do
context 'when Value Stream is not visible' do
it 'returns link to the the first visible menu item' do
allow(subject).to receive(:cycle_analytics_menu_item).and_return(nil)
allow(subject).to receive(:cycle_analytics_menu_item).and_return(double(render?: false))
expect(subject.link).to eq subject.renderable_items.first.link
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment