diff options
Diffstat (limited to 'app/models/sidebars')
20 files changed, 723 insertions, 0 deletions
diff --git a/app/models/sidebars/context.rb b/app/models/sidebars/context.rb new file mode 100644 index 00000000000..d9ac2705aaf --- /dev/null +++ b/app/models/sidebars/context.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +# This class stores all the information needed to display and +# render the sidebar and menus. +# It usually stores information regarding the context and calculated +# values where the logic is in helpers. +module Sidebars + class Context + attr_reader :current_user, :container + + def initialize(current_user:, container:, **args) + @current_user = current_user + @container = container + + args.each do |key, value| + singleton_class.public_send(:attr_reader, key) # rubocop:disable GitlabSecurity/PublicSend + instance_variable_set("@#{key}", value) + end + end + end +end diff --git a/app/models/sidebars/menu.rb b/app/models/sidebars/menu.rb new file mode 100644 index 00000000000..a5c8be2bb31 --- /dev/null +++ b/app/models/sidebars/menu.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +module Sidebars + class Menu + extend ::Gitlab::Utils::Override + include ::Gitlab::Routing + include GitlabRoutingHelper + include Gitlab::Allowable + include ::Sidebars::HasPill + include ::Sidebars::HasIcon + include ::Sidebars::PositionableList + include ::Sidebars::Renderable + include ::Sidebars::ContainerWithHtmlOptions + include ::Sidebars::HasActiveRoutes + + attr_reader :context + delegate :current_user, :container, to: :@context + + def initialize(context) + @context = context + @items = [] + + configure_menu_items + end + + def configure_menu_items + # No-op + end + + override :render? + def render? + @items.empty? || renderable_items.any? + end + + # Menus might have or not a link + override :link + def link + nil + 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 + @all_active_routes ||= begin + ([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 + end + + def has_items? + @items.any? + end + + 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 + + def has_renderable_items? + renderable_items.any? + end + + def renderable_items + @renderable_items ||= @items.select(&:render?) + end + end +end diff --git a/app/models/sidebars/menu_item.rb b/app/models/sidebars/menu_item.rb new file mode 100644 index 00000000000..7466b31898e --- /dev/null +++ b/app/models/sidebars/menu_item.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Sidebars + class MenuItem + extend ::Gitlab::Utils::Override + include ::Gitlab::Routing + include GitlabRoutingHelper + include Gitlab::Allowable + include ::Sidebars::HasIcon + include ::Sidebars::HasHint + include ::Sidebars::Renderable + include ::Sidebars::ContainerWithHtmlOptions + include ::Sidebars::HasActiveRoutes + + attr_reader :context + + def initialize(context) + @context = context + end + end +end diff --git a/app/models/sidebars/panel.rb b/app/models/sidebars/panel.rb new file mode 100644 index 00000000000..5c8191ebda3 --- /dev/null +++ b/app/models/sidebars/panel.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +module Sidebars + class Panel + extend ::Gitlab::Utils::Override + include ::Sidebars::PositionableList + + attr_reader :context, :scope_menu, :hidden_menu + + def initialize(context) + @context = context + @scope_menu = nil + @hidden_menu = nil + @menus = [] + + configure_menus + end + + def configure_menus + # No-op + end + + def add_menu(menu) + add_element(@menus, menu) + end + + def insert_menu_before(before_menu, new_menu) + insert_element_before(@menus, before_menu, new_menu) + end + + def insert_menu_after(after_menu, new_menu) + insert_element_after(@menus, after_menu, new_menu) + end + + def set_scope_menu(scope_menu) + @scope_menu = scope_menu + end + + def set_hidden_menu(hidden_menu) + @hidden_menu = hidden_menu + end + + def aria_label + raise NotImplementedError + end + + def has_renderable_menus? + renderable_menus.any? + end + + def renderable_menus + @renderable_menus ||= @menus.select(&:render?) + end + + def container + context.container + end + + # Auxiliar method that helps with the migration from + # regular views to the new logic + def render_raw_scope_menu_partial + # No-op + end + + # Auxiliar method that helps with the migration from + # regular views to the new logic. + # + # Any menu inside this partial will be added after + # all the menus added in the `configure_menus` + # method. + def render_raw_menus_partial + # No-op + end + end +end diff --git a/app/models/sidebars/projects/context.rb b/app/models/sidebars/projects/context.rb new file mode 100644 index 00000000000..4c82309035d --- /dev/null +++ b/app/models/sidebars/projects/context.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + class Context < ::Sidebars::Context + def initialize(current_user:, container:, **args) + super(current_user: current_user, container: container, project: container, **args) + end + end + end +end diff --git a/app/models/sidebars/projects/menus/learn_gitlab/menu.rb b/app/models/sidebars/projects/menus/learn_gitlab/menu.rb new file mode 100644 index 00000000000..4b572846d1a --- /dev/null +++ b/app/models/sidebars/projects/menus/learn_gitlab/menu.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module LearnGitlab + class Menu < ::Sidebars::Menu + override :link + def link + project_learn_gitlab_path(context.project) + end + + override :active_routes + def active_routes + { controller: :learn_gitlab } + end + + override :title + def title + _('Learn GitLab') + end + + override :extra_container_html_options + def nav_link_html_options + { class: 'home' } + end + + override :sprite_icon + def sprite_icon + 'home' + end + + override :render? + def render? + context.learn_gitlab_experiment_enabled + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/menus/project_overview/menu.rb b/app/models/sidebars/projects/menus/project_overview/menu.rb new file mode 100644 index 00000000000..e6aa8ed159f --- /dev/null +++ b/app/models/sidebars/projects/menus/project_overview/menu.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module ProjectOverview + class Menu < ::Sidebars::Menu + override :configure_menu_items + def configure_menu_items + add_item(MenuItems::Details.new(context)) + add_item(MenuItems::Activity.new(context)) + add_item(MenuItems::Releases.new(context)) + end + + override :link + def link + project_path(context.project) + end + + override :extra_container_html_options + def extra_container_html_options + { + class: 'shortcuts-project rspec-project-link' + } + end + + override :extra_container_html_options + def nav_link_html_options + { class: 'home' } + end + + override :title + def title + _('Project overview') + end + + override :sprite_icon + def sprite_icon + 'home' + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/menus/project_overview/menu_items/activity.rb b/app/models/sidebars/projects/menus/project_overview/menu_items/activity.rb new file mode 100644 index 00000000000..46d0f0bc43b --- /dev/null +++ b/app/models/sidebars/projects/menus/project_overview/menu_items/activity.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module ProjectOverview + module MenuItems + class Activity < ::Sidebars::MenuItem + override :link + def link + activity_project_path(context.project) + end + + override :extra_container_html_options + def extra_container_html_options + { + class: 'shortcuts-project-activity' + } + end + + override :active_routes + def active_routes + { path: 'projects#activity' } + end + + override :title + def title + _('Activity') + end + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/menus/project_overview/menu_items/details.rb b/app/models/sidebars/projects/menus/project_overview/menu_items/details.rb new file mode 100644 index 00000000000..c40c2ed8fa2 --- /dev/null +++ b/app/models/sidebars/projects/menus/project_overview/menu_items/details.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module ProjectOverview + module MenuItems + class Details < ::Sidebars::MenuItem + override :link + def link + project_path(context.project) + end + + override :extra_container_html_options + def extra_container_html_options + { + aria: { label: _('Project details') }, + class: 'shortcuts-project' + } + end + + override :active_routes + def active_routes + { path: 'projects#show' } + end + + override :title + def title + _('Details') + end + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/menus/project_overview/menu_items/releases.rb b/app/models/sidebars/projects/menus/project_overview/menu_items/releases.rb new file mode 100644 index 00000000000..5e8348f4398 --- /dev/null +++ b/app/models/sidebars/projects/menus/project_overview/menu_items/releases.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module ProjectOverview + module MenuItems + class Releases < ::Sidebars::MenuItem + override :link + def link + project_releases_path(context.project) + end + + override :extra_container_html_options + def extra_container_html_options + { + class: 'shortcuts-project-releases' + } + end + + override :render? + def render? + can?(context.current_user, :read_release, context.project) && !context.project.empty_repo? + end + + override :active_routes + def active_routes + { controller: :releases } + end + + override :title + def title + _('Releases') + end + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/menus/repository/menu.rb b/app/models/sidebars/projects/menus/repository/menu.rb new file mode 100644 index 00000000000..f49a0479521 --- /dev/null +++ b/app/models/sidebars/projects/menus/repository/menu.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module Repository + class Menu < ::Sidebars::Menu + override :configure_menu_items + def configure_menu_items + add_item(MenuItems::Files.new(context)) + add_item(MenuItems::Commits.new(context)) + add_item(MenuItems::Branches.new(context)) + add_item(MenuItems::Tags.new(context)) + add_item(MenuItems::Contributors.new(context)) + add_item(MenuItems::Graphs.new(context)) + add_item(MenuItems::Compare.new(context)) + end + + override :link + def link + project_tree_path(context.project) + end + + override :extra_container_html_options + def extra_container_html_options + { + class: 'shortcuts-tree' + } + end + + override :title + def title + _('Repository') + end + + override :title_html_options + def title_html_options + { + id: 'js-onboarding-repo-link' + } + end + + override :sprite_icon + def sprite_icon + 'doc-text' + end + + override :render? + def render? + can?(context.current_user, :download_code, context.project) && + !context.project.empty_repo? + end + end + end + end + end +end + +Sidebars::Projects::Menus::Repository::Menu.prepend_if_ee('EE::Sidebars::Projects::Menus::Repository::Menu') diff --git a/app/models/sidebars/projects/menus/repository/menu_items/branches.rb b/app/models/sidebars/projects/menus/repository/menu_items/branches.rb new file mode 100644 index 00000000000..4a62803dd2b --- /dev/null +++ b/app/models/sidebars/projects/menus/repository/menu_items/branches.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module Repository + module MenuItems + class Branches < ::Sidebars::MenuItem + override :link + def link + project_branches_path(context.project) + end + + override :extra_container_html_options + def extra_container_html_options + { + id: 'js-onboarding-branches-link' + } + end + + override :active_routes + def active_routes + { controller: :branches } + end + + override :title + def title + _('Branches') + end + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/menus/repository/menu_items/commits.rb b/app/models/sidebars/projects/menus/repository/menu_items/commits.rb new file mode 100644 index 00000000000..647cf89133e --- /dev/null +++ b/app/models/sidebars/projects/menus/repository/menu_items/commits.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module Repository + module MenuItems + class Commits < ::Sidebars::MenuItem + override :link + def link + project_commits_path(context.project, context.current_ref) + end + + override :extra_container_html_options + def extra_container_html_options + { + id: 'js-onboarding-commits-link' + } + end + + override :active_routes + def active_routes + { controller: %w(commit commits) } + end + + override :title + def title + _('Commits') + end + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/menus/repository/menu_items/compare.rb b/app/models/sidebars/projects/menus/repository/menu_items/compare.rb new file mode 100644 index 00000000000..4812636b63f --- /dev/null +++ b/app/models/sidebars/projects/menus/repository/menu_items/compare.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module Repository + module MenuItems + class Compare < ::Sidebars::MenuItem + override :link + def link + project_compare_index_path(context.project, from: context.project.repository.root_ref, to: context.current_ref) + end + + override :active_routes + def active_routes + { controller: :compare } + end + + override :title + def title + _('Compare') + end + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/menus/repository/menu_items/contributors.rb b/app/models/sidebars/projects/menus/repository/menu_items/contributors.rb new file mode 100644 index 00000000000..d60fd05bb64 --- /dev/null +++ b/app/models/sidebars/projects/menus/repository/menu_items/contributors.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module Repository + module MenuItems + class Contributors < ::Sidebars::MenuItem + override :link + def link + project_graph_path(context.project, context.current_ref) + end + + override :active_routes + def active_routes + { path: 'graphs#show' } + end + + override :title + def title + _('Contributors') + end + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/menus/repository/menu_items/files.rb b/app/models/sidebars/projects/menus/repository/menu_items/files.rb new file mode 100644 index 00000000000..4989efe9fa5 --- /dev/null +++ b/app/models/sidebars/projects/menus/repository/menu_items/files.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module Repository + module MenuItems + class Files < ::Sidebars::MenuItem + override :link + def link + project_tree_path(context.project, context.current_ref) + end + + override :active_routes + def active_routes + { controller: %w[tree blob blame edit_tree new_tree find_file] } + end + + override :title + def title + _('Files') + end + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/menus/repository/menu_items/graphs.rb b/app/models/sidebars/projects/menus/repository/menu_items/graphs.rb new file mode 100644 index 00000000000..a57021be4d0 --- /dev/null +++ b/app/models/sidebars/projects/menus/repository/menu_items/graphs.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module Repository + module MenuItems + class Graphs < ::Sidebars::MenuItem + override :link + def link + project_network_path(context.project, context.current_ref) + end + + override :active_routes + def active_routes + { controller: :network } + end + + override :title + def title + _('Graph') + end + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/menus/repository/menu_items/tags.rb b/app/models/sidebars/projects/menus/repository/menu_items/tags.rb new file mode 100644 index 00000000000..d84bc89b93c --- /dev/null +++ b/app/models/sidebars/projects/menus/repository/menu_items/tags.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module Repository + module MenuItems + class Tags < ::Sidebars::MenuItem + override :link + def link + project_tags_path(context.project) + end + + override :active_routes + def active_routes + { controller: :tags } + end + + override :title + def title + _('Tags') + end + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/menus/scope/menu.rb b/app/models/sidebars/projects/menus/scope/menu.rb new file mode 100644 index 00000000000..3b699083f75 --- /dev/null +++ b/app/models/sidebars/projects/menus/scope/menu.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + module Scope + class Menu < ::Sidebars::Menu + override :link + def link + project_path(context.project) + end + + override :title + def title + context.project.name + end + end + end + end + end +end diff --git a/app/models/sidebars/projects/panel.rb b/app/models/sidebars/projects/panel.rb new file mode 100644 index 00000000000..ec4fac53a40 --- /dev/null +++ b/app/models/sidebars/projects/panel.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + class Panel < ::Sidebars::Panel + override :configure_menus + def configure_menus + set_scope_menu(Sidebars::Projects::Menus::Scope::Menu.new(context)) + + add_menu(Sidebars::Projects::Menus::ProjectOverview::Menu.new(context)) + add_menu(Sidebars::Projects::Menus::LearnGitlab::Menu.new(context)) + add_menu(Sidebars::Projects::Menus::Repository::Menu.new(context)) + end + + override :render_raw_menus_partial + def render_raw_menus_partial + 'layouts/nav/sidebar/project_menus' + end + + override :aria_label + def aria_label + _('Project navigation') + end + end + end +end |