Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-06-16 21:25:58 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-16 21:25:58 +0300
commita5f4bba440d7f9ea47046a0a561d49adf0a1e6d4 (patch)
treefb69158581673816a8cd895f9d352dcb3c678b1e /app/views/layouts
parentd16b2e8639e99961de6ddc93909f3bb5c1445ba1 (diff)
Add latest changes from gitlab-org/gitlab@14-0-stable-eev14.0.0-rc42
Diffstat (limited to 'app/views/layouts')
-rw-r--r--app/views/layouts/_head.html.haml6
-rw-r--r--app/views/layouts/_page.html.haml6
-rw-r--r--app/views/layouts/_search.html.haml2
-rw-r--r--app/views/layouts/_startup_css.haml3
-rw-r--r--app/views/layouts/application.html.haml4
-rw-r--r--app/views/layouts/devise.html.haml2
-rw-r--r--app/views/layouts/fullscreen.html.haml5
-rw-r--r--app/views/layouts/header/_default.html.haml30
-rw-r--r--app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml3
-rw-r--r--app/views/layouts/header/_help_dropdown.html.haml2
-rw-r--r--app/views/layouts/header/_new_dropdown.html.haml62
-rw-r--r--app/views/layouts/header/_new_repo_experiment.html.haml6
-rw-r--r--app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml3
-rw-r--r--app/views/layouts/header/_registration_enabled_callout.html.haml25
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml18
-rw-r--r--app/views/layouts/nav/_top_nav.html.haml8
-rw-r--r--app/views/layouts/nav/_top_nav_responsive.html.haml7
-rw-r--r--app/views/layouts/nav/groups_dropdown/_show.html.haml17
-rw-r--r--app/views/layouts/nav/projects_dropdown/_show.html.haml8
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml41
-rw-r--r--app/views/layouts/nav/sidebar/_analytics_links.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_context_menu_body.html.haml9
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml39
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml7
-rw-r--r--app/views/layouts/terms.html.haml2
25 files changed, 161 insertions, 156 deletions
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index b28cd47efcc..683d3a6ad1b 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -36,7 +36,7 @@
= favicon_link_tag favicon, id: 'favicon', data: { original_href: favicon }, type: 'image/png'
- = render 'layouts/startup_css'
+ = render 'layouts/startup_css', { startup_filename: local_assigns.fetch(:startup_filename, nil) }
- if user_application_theme == 'gl-dark'
= stylesheet_link_tag_defer "application_dark"
= yield :page_specific_styles
@@ -54,8 +54,6 @@
= stylesheet_link_tag 'performance_bar' if performance_bar_enabled?
- -# Rendering this above Gon, to use in JS later
- = render 'layouts/header/new_repo_experiment'
= Gon::Base.render_data(nonce: content_security_policy_nonce)
= javascript_include_tag locale_path unless I18n.locale == :en
@@ -73,7 +71,7 @@
= action_cable_meta_tag
%meta{ name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1' }
- %meta{ name: 'theme-color', content: '#474D57' }
+ %meta{ name: 'theme-color', content: user_theme_primary_color }
-# Apple Safari/iOS home screen icons
= favicon_link_tag 'touch-icon-iphone.png', rel: 'apple-touch-icon'
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index c91d27e3ed1..2b63e2c647c 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -1,7 +1,7 @@
-.layout-page{ class: page_with_sidebar_class }
+.layout-page.hide-when-top-nav-responsive-open{ class: page_with_sidebar_class }
- if defined?(nav) && nav
= render "layouts/nav/sidebar/#{nav}"
- .content-wrapper{ class: "#{@content_wrapper_class}" }
+ .content-wrapper.content-wrapper-margin{ class: "#{@content_wrapper_class}" }
.mobile-overlay
= yield :group_invite_members_banner
.alert-wrapper.gl-force-block-formatting-context
@@ -27,3 +27,5 @@
= render "layouts/flash", extra_flash_class: 'limit-container-width'
= yield :before_content
= yield
+
+= render "layouts/nav/top_nav_responsive", class: 'layout-page content-wrapper-margin'
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
index 2032d1e95a6..e617b4358e3 100644
--- a/app/views/layouts/_search.html.haml
+++ b/app/views/layouts/_search.html.haml
@@ -1,5 +1,5 @@
.search.search-form{ data: { track_label: "navbar_search", track_event: "activate_form_input", track_value: "" } }
- = form_tag search_path, method: :get, class: 'form-inline' do |_f|
+ = form_tag search_path, method: :get, class: 'form-inline form-control' do |_f|
.search-input-container
.search-input-wrap
.dropdown{ data: { url: search_autocomplete_path } }
diff --git a/app/views/layouts/_startup_css.haml b/app/views/layouts/_startup_css.haml
index 7d3cfe28007..67c871b95f5 100644
--- a/app/views/layouts/_startup_css.haml
+++ b/app/views/layouts/_startup_css.haml
@@ -1,4 +1,5 @@
-- startup_filename = current_path?("sessions#new") ? 'signin' : user_application_theme == 'gl-dark' ? 'dark' : 'general'
+- startup_filename_default = user_application_theme == 'gl-dark' ? 'dark' : 'general'
+- startup_filename = local_assigns.fetch(:startup_filename, nil) || startup_filename_default
%style
= Rails.application.assets_manifest.find_sources("themes/#{user_application_theme_css_filename}.css").first.to_s.html_safe if user_application_theme_css_filename
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 58408ec822c..47c092e199a 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -1,10 +1,12 @@
- page_classes = page_class << @html_class
- page_classes = page_classes.flatten.compact
+- body_classes = [user_application_theme, user_tab_width, @body_class, client_class_list]
+- body_classes << 'sidebar-refactoring' if sidebar_refactor_enabled?
!!! 5
%html{ lang: I18n.locale, class: page_classes }
= render "layouts/head"
- %body{ class: "#{user_application_theme} #{user_tab_width} #{@body_class} #{client_class_list}", data: body_data }
+ %body{ class: body_classes, data: body_data }
= render "layouts/init_auto_complete" if @gfm_form
= render "layouts/init_client_detection_flags"
= render 'peek/bar'
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index ef61a04c288..ae7c160c060 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -1,6 +1,6 @@
!!! 5
%html.devise-layout-html{ class: system_message_class }
- = render "layouts/head"
+ = render "layouts/head", { startup_filename: 'signin' }
%body.ui-indigo.login-page.application.navless{ class: "#{client_class_list}", data: { page: body_data_page, qa_selector: 'login_page' } }
= header_message
= render "layouts/init_client_detection_flags"
diff --git a/app/views/layouts/fullscreen.html.haml b/app/views/layouts/fullscreen.html.haml
index 63bb9f8fff5..2a865aeda40 100644
--- a/app/views/layouts/fullscreen.html.haml
+++ b/app/views/layouts/fullscreen.html.haml
@@ -6,11 +6,12 @@
= header_message
= render partial: "layouts/header/default", locals: { project: @project, group: @group }
.mobile-overlay
- .alert-wrapper
+ .alert-wrapper.hide-when-top-nav-responsive-open
= render 'shared/outdated_browser'
= render "layouts/broadcast"
= yield :flash_message
= render "layouts/flash"
- .content-wrapper{ id: "content-body", class: "d-flex flex-column align-items-stretch mt-0" }
+ .content-wrapper.hide-when-top-nav-responsive-open{ id: "content-body", class: "d-flex flex-column align-items-stretch" }
= yield
+ = render "layouts/nav/top_nav_responsive", class: "gl-flex-grow-1 gl-overflow-y-auto"
= footer_message
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index ae333cffb84..87580e57e75 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -1,11 +1,12 @@
- has_impersonation_link = header_link?(:admin_impersonation)
- user_status_data = user_status_properties(current_user)
+- use_top_nav_redesign = Feature.enabled?(:combined_menu, current_user, default_enabled: :yaml)
%header.navbar.navbar-gitlab.navbar-expand-sm.js-navbar{ data: { qa_selector: 'navbar' } }
%a.gl-sr-only.gl-accessibility{ href: "#content-body" } Skip to content
.container-fluid
.header-content
- .title-container
+ .title-container.hide-when-menu-expanded
%h1.title
%span.gl-sr-only GitLab
= link_to root_path, title: _('Dashboard'), id: 'logo', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation') do
@@ -19,8 +20,9 @@
%span.gl-badge.gl-bg-green-500.gl-text-white.gl-rounded-pill.gl-font-weight-bold.gl-py-1
= _('Next')
- - if Feature.enabled?(:combined_menu, current_user, default_enabled: :yaml)
- = render "layouts/nav/top_nav"
+ - if use_top_nav_redesign
+ .gl-display-none.gl-sm-display-block
+ = render "layouts/nav/top_nav"
- else
- if current_user
= render "layouts/nav/dashboard"
@@ -30,13 +32,14 @@
.navbar-collapse.collapse
%ul.nav.navbar-nav
- if current_user
- = render 'layouts/header/new_dropdown'
- - if header_link?(:search)
+ = render 'layouts/header/new_dropdown', class: ('gl-display-none gl-sm-display-block' if use_top_nav_redesign)
+ - if top_nav_show_search
+ - search_menu_item = top_nav_search_menu_item_attrs
%li.nav-item.d-none.d-lg-block.m-auto
= render 'layouts/search' unless current_controller?(:search)
- %li.nav-item.d-inline-block.d-lg-none
- = link_to search_context.search_url, title: _('Search'), aria: { label: _('Search') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
- = sprite_icon('search')
+ %li.nav-item{ class: use_top_nav_redesign ? 'd-none d-sm-inline-block d-lg-none' : 'd-inline-block d-lg-none' }
+ = link_to search_menu_item.fetch(:href), title: search_menu_item.fetch(:title), aria: { label: search_menu_item.fetch(:title) }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = sprite_icon(search_menu_item.fetch(:icon))
- if header_link?(:issues)
= nav_link(path: 'dashboard#issues', html_options: { class: "user-counter" }) do
= link_to assigned_issues_dashboard_path, title: _('Issues'), class: 'dashboard-shortcuts-issues', aria: { label: _('Issues') },
@@ -115,10 +118,15 @@
- sign_in_text = allow_signup? ? _('Sign in / Register') : _('Sign in')
= link_to sign_in_text, new_session_path(:user, redirect_to_referer: 'yes'), class: 'gl-button btn btn-default btn-sign-in'
- %button.navbar-toggler.d-block.d-sm-none{ type: 'button' }
+ %button.navbar-toggler.d-block.d-sm-none{ type: 'button', class: ('gl-border-none!' if use_top_nav_redesign) }
%span.sr-only= _('Toggle navigation')
- = sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon js-navbar-toggle-right')
- = sprite_icon('close', size: 12, css_class: 'close-icon js-navbar-toggle-left')
+ - if use_top_nav_redesign
+ %span.more-icon.gl-px-3.gl-font-sm.gl-font-weight-bold
+ %span.gl-pr-2= _('Menu')
+ = sprite_icon('hamburger', size: 16)
+ - else
+ = sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon')
+ = sprite_icon('close', size: 12, css_class: 'close-icon')
- if display_whats_new?
#whats-new-app{ data: { version_digest: whats_new_version_digest } }
diff --git a/app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml b/app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml
deleted file mode 100644
index cb74c77dff8..00000000000
--- a/app/views/layouts/header/_group_invite_members_new_dropdown_item.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-- return unless Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can?(current_user, :admin_group_member, @group)
-
-%li= dropdown_invite_members_link(@group)
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
index c3769dd2993..01e59b8e2ef 100644
--- a/app/views/layouts/header/_help_dropdown.html.haml
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -10,7 +10,7 @@
%li
%button.js-shortcuts-modal-trigger{ type: "button" }
= _("Keyboard shortcuts")
- %span.text-secondary.float-right{ "aria-hidden": true }= '?'.html_safe
+ %span.text-secondary.float-right{ "aria-hidden": "true" }= '?'.html_safe
%li.divider
%li
= link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback"
diff --git a/app/views/layouts/header/_new_dropdown.html.haml b/app/views/layouts/header/_new_dropdown.html.haml
index ca90d2e02fa..c5f43fb2c16 100644
--- a/app/views/layouts/header/_new_dropdown.html.haml
+++ b/app/views/layouts/header/_new_dropdown.html.haml
@@ -1,47 +1,27 @@
-- new_repo_experiment_text = content_for(:new_repo_experiment)
-%li.header-new.dropdown{ data: { track_label: "new_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }
- = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", id: "js-onboarding-new-project-link", title: _("New..."), ref: 'tooltip', aria: { label: _("New...") }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static' } do
+- view_model = new_dropdown_view_model(project: @project, group: @group)
+- menu_sections = view_model.fetch(:menu_sections)
+- title = view_model.fetch(:title)
+- show_headers = menu_sections.length > 1
+- top_class = local_assigns.fetch(:class, nil)
+
+- return if menu_sections.empty?
+
+%li.header-new.dropdown{ class: top_class, data: { track_label: "new_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }
+ = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip", id: "js-onboarding-new-project-link", title: title, ref: 'tooltip', aria: { label: title }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static', qa_selector: 'new_menu_toggle' } do
= sprite_icon('plus-square')
= sprite_icon('chevron-down', css_class: 'caret-down')
.dropdown-menu.dropdown-menu-right.dropdown-extended-height
%ul
- - if @group&.persisted?
- - create_group_project = can?(current_user, :create_projects, @group)
- - create_group_subgroup = can?(current_user, :create_subgroup, @group)
-
- - if create_group_project || create_group_subgroup
- %li.dropdown-bold-header
- = _('This group')
- - if create_group_project
- %li= link_to new_repo_experiment_text, new_project_path(namespace_id: @group.id), data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
- - if create_group_subgroup
- %li= link_to _('New subgroup'), new_group_path(parent_id: @group.id), data: { track_event: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' }
- = render_if_exists 'layouts/header/create_epic_new_dropdown_item'
- = render 'layouts/header/group_invite_members_new_dropdown_item'
+ - menu_sections.each_with_index do |section, index|
+ - if index > 0
%li.divider
- %li.dropdown-bold-header GitLab
-
- - if @project&.persisted?
- - create_project_issue = show_new_issue_link?(@project)
- - merge_project = merge_request_source_project_for_project(@project)
- - create_project_snippet = can?(current_user, :create_snippet, @project)
-
- - if create_project_issue || merge_project || create_project_snippet
+ - if show_headers
%li.dropdown-bold-header
- = _('This project')
- - if create_project_issue
- %li= link_to _('New issue'), new_project_issue_path(@project), data: { track_event: 'click_link_new_issue', track_label: 'plus_menu_dropdown' }
- - if merge_project
- %li= link_to _('New merge request'), project_new_merge_request_path(merge_project), data: { track_event: 'click_link_new_mr', track_label: 'plus_menu_dropdown' }
-
- - if create_project_snippet
- %li= link_to _('New snippet'), new_project_snippet_path(@project), data: { track_event: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown' }
- = render 'layouts/header/project_invite_members_new_dropdown_item'
- %li.divider
- %li.dropdown-bold-header GitLab
- - if current_user.can_create_project?
- %li= link_to new_repo_experiment_text, new_project_path, class: 'qa-global-new-project-link', data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown' }
- - if current_user.can_create_group?
- %li= link_to _('New group'), new_group_path, data: { track_event: 'click_link_new_group', track_label: 'plus_menu_dropdown' }
- - if current_user.can?(:create_snippet)
- %li= link_to _('New snippet'), new_snippet_path, data: { track_event: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown' }, class: 'qa-global-new-snippet-link'
+ = section.fetch(:title)
+ - section.fetch(:menu_items).each do |menu_item|
+ %li<
+ = link_to menu_item.fetch(:href), class: menu_item.fetch(:css_class), data: menu_item.fetch(:data) do
+ = menu_item.fetch(:title)
+ - if menu_item.fetch(:emoji)
+ -# We need to insert a space between the title and emoji
+ = " #{emoji_icon(menu_item.fetch(:emoji), 'aria-hidden': true, class: "gl-font-base gl-vertical-align-baseline")}".html_safe
diff --git a/app/views/layouts/header/_new_repo_experiment.html.haml b/app/views/layouts/header/_new_repo_experiment.html.haml
deleted file mode 100644
index aaa13d593cd..00000000000
--- a/app/views/layouts/header/_new_repo_experiment.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-- content_for :new_repo_experiment do
- - experiment(:new_repo, user: current_user) do |e|
- - e.use do
- = _('New project')
- - e.try do
- = _('New project/repository')
diff --git a/app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml b/app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml
deleted file mode 100644
index 2cb67e857e3..00000000000
--- a/app/views/layouts/header/_project_invite_members_new_dropdown_item.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-- return unless Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can_import_members?
-
-%li= dropdown_invite_members_link(@project)
diff --git a/app/views/layouts/header/_registration_enabled_callout.html.haml b/app/views/layouts/header/_registration_enabled_callout.html.haml
index 1b1804edcc7..9266702e44e 100644
--- a/app/views/layouts/header/_registration_enabled_callout.html.haml
+++ b/app/views/layouts/header/_registration_enabled_callout.html.haml
@@ -1,15 +1,14 @@
- return unless show_registration_enabled_user_callout?
-%div{ class: [container_class, @content_class, 'gl-pt-5!'] }
- .gl-alert.gl-alert-warning.js-registration-enabled-callout{ role: 'alert', data: { feature_id: UserCalloutsHelper::REGISTRATION_ENABLED_CALLOUT, dismiss_endpoint: user_callouts_path } }
- = sprite_icon('warning', size: 16, css_class: 'gl-alert-icon')
- %button.gl-alert-dismiss.js-close{ type: 'button', aria: { label: _('Close') }, data: { testid: 'close-registration-enabled-callout' } }
- = sprite_icon('close', size: 16)
- .gl-alert-title
- = _('Open registration is enabled on your instance.')
- .gl-alert-body
- = html_escape(_('%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance.')) % { anchorOpen: "<a href=\"#{help_page_path('user/admin_area/settings/sign_up_restrictions')}\">".html_safe, anchorClose: '</a>'.html_safe }
- .gl-alert-actions
- = link_to general_admin_application_settings_path(anchor: 'js-signup-settings'), class: 'btn gl-alert-action btn-info btn-md gl-button' do
- %span.gl-button-text
- = _('View setting')
+= render 'shared/global_alert',
+ title: _('Open registration is enabled on your instance.'),
+ variant: :warning,
+ alert_class: 'js-registration-enabled-callout',
+ alert_data: { feature_id: UserCalloutsHelper::REGISTRATION_ENABLED_CALLOUT, dismiss_endpoint: user_callouts_path },
+ close_button_data: { testid: 'close-registration-enabled-callout' } do
+ .gl-alert-body
+ = html_escape(_('%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance.')) % { anchorOpen: "<a href=\"#{help_page_path('user/admin_area/settings/sign_up_restrictions')}\">".html_safe, anchorClose: '</a>'.html_safe }
+ .gl-alert-actions
+ = link_to general_admin_application_settings_path(anchor: 'js-signup-settings'), class: 'btn gl-alert-action btn-info btn-md gl-button' do
+ %span.gl-button-text
+ = _('View setting')
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index 718b2002422..117382d87b5 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -4,7 +4,7 @@
-# [1]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587
%ul.list-unstyled.navbar-sub-nav
- if dashboard_nav_link?(:projects)
- = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects qa-projects-dropdown", data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }) do
+ = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects", data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Projects')
= sprite_icon('chevron-down', css_class: 'caret-down')
@@ -12,7 +12,7 @@
= render "layouts/nav/projects_dropdown/show"
- if dashboard_nav_link?(:groups)
- = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "d-none d-md-block home dropdown header-groups qa-groups-dropdown", data: { track_label: "groups_dropdown", track_event: "click_dropdown" } }) do
+ = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "d-none d-md-block home dropdown header-groups", data: { track_label: "groups_dropdown", track_event: "click_dropdown" } }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Groups')
= sprite_icon('chevron-down', css_class: 'caret-down')
@@ -21,28 +21,28 @@
- if any_dashboard_nav_link?([:groups, :milestones, :activity, :snippets])
= nav_link(html_options: { id: 'nav-more-dropdown', class: "header-more dropdown", data: { track_label: "more_dropdown", track_event: "click_more_link" } }) do
- %a{ href: "#", data: { toggle: "dropdown", qa_selector: 'more_dropdown' } }
+ %a{ href: "#", data: { toggle: "dropdown" } }
= _('More')
= sprite_icon('chevron-down', css_class: 'caret-down')
.dropdown-menu
%ul
- if dashboard_nav_link?(:groups)
%li.d-md-none
- = link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', data: { qa_selector: 'groups_link' } do
+ = link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups' do
= _('Groups')
- if dashboard_nav_link?(:activity)
= nav_link(path: 'dashboard#activity') do
- = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', data: { qa_selector: 'activity_link' } do
+ = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity' do
= _('Activity')
- if dashboard_nav_link?(:milestones)
= nav_link(controller: 'dashboard/milestones') do
- = link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', data: { qa_selector: 'milestones_link' } do
+ = link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones' do
= _('Milestones')
- if dashboard_nav_link?(:snippets)
= nav_link(controller: 'dashboard/snippets') do
- = link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', data: { qa_selector: 'snippets_link' } do
+ = link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets' do
= _('Snippets')
%li.dropdown
@@ -50,7 +50,7 @@
- if current_user.admin?
= nav_link(controller: 'admin/dashboard') do
- = link_to admin_root_path, class: 'admin-icon qa-admin-area-link d-xl-none' do
+ = link_to admin_root_path, class: 'admin-icon d-xl-none' do
= _('Admin Area')
- if Gitlab::CurrentSettings.admin_mode
- if header_link?(:admin_mode)
@@ -68,7 +68,7 @@
- if current_user.admin?
= nav_link(controller: 'admin/dashboard', html_options: { class: "d-none d-xl-block"}) do
- = link_to admin_root_path, class: 'admin-icon qa-admin-area-link', title: _('Admin Area'), aria: { label: _('Admin Area') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = link_to admin_root_path, class: 'admin-icon', title: _('Admin Area'), aria: { label: _('Admin Area') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('admin', size: 18)
- if Gitlab::CurrentSettings.admin_mode
diff --git a/app/views/layouts/nav/_top_nav.html.haml b/app/views/layouts/nav/_top_nav.html.haml
index 50c003f8e13..42119ddb291 100644
--- a/app/views/layouts/nav/_top_nav.html.haml
+++ b/app/views/layouts/nav/_top_nav.html.haml
@@ -2,6 +2,10 @@
%ul.list-unstyled.navbar-sub-nav#js-top-nav{ data: { view_model: view_model.to_json } }
%li
%a.top-nav-toggle{ href: '#', type: 'button', data: { toggle: "dropdown" } }
- = sprite_icon('dot-grid', css_class: "dropdown-icon")
+ = sprite_icon('hamburger', css_class: "dropdown-icon")
= view_model[:activeTitle]
- = sprite_icon('chevron-down')
+
+.hidden
+ - view_model[:shortcuts].each do |shortcut|
+ = link_to shortcut[:href], class: shortcut[:css_class] do
+ = shortcut[:title]
diff --git a/app/views/layouts/nav/_top_nav_responsive.html.haml b/app/views/layouts/nav/_top_nav_responsive.html.haml
new file mode 100644
index 00000000000..0d122f1adff
--- /dev/null
+++ b/app/views/layouts/nav/_top_nav_responsive.html.haml
@@ -0,0 +1,7 @@
+- return unless Feature.enabled?(:combined_menu, current_user, default_enabled: :yaml)
+
+- top_class = local_assigns.fetch(:class, nil)
+- view_model = top_nav_responsive_view_model(project: @project, group: @group)
+
+.top-nav-responsive{ class: top_class }
+ #js-top-nav-responsive{ data: { view_model: view_model.to_json } }
diff --git a/app/views/layouts/nav/groups_dropdown/_show.html.haml b/app/views/layouts/nav/groups_dropdown/_show.html.haml
index 036647e2be1..d7b0c7150d4 100644
--- a/app/views/layouts/nav/groups_dropdown/_show.html.haml
+++ b/app/views/layouts/nav/groups_dropdown/_show.html.haml
@@ -4,19 +4,20 @@
-# [1]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587
- group_meta = { id: @group.id, name: @group.name, namespace: @group.full_name, web_url: group_path(@group), avatar_url: @group.avatar_url } if @group&.persisted?
.frequent-items-dropdown-container.with-deprecated-styles
- .frequent-items-dropdown-sidebar.qa-groups-dropdown-sidebar
+ .frequent-items-dropdown-sidebar
%ul
= nav_link(path: 'dashboard/groups#index') do
- = link_to dashboard_groups_path, class: 'qa-your-groups-link', data: { track_label: "groups_dropdown_your_groups", track_event: "click_link" } do
+ = link_to dashboard_groups_path, data: { track_label: "groups_dropdown_your_groups", track_event: "click_link" } do
= _('Your groups')
= nav_link(path: 'groups#explore') do
= link_to explore_groups_path, data: { track_label: "groups_dropdown_explore_groups", track_event: "click_link" } do
= _('Explore groups')
- = nav_link(path: 'groups/new#create-group-pane', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
- = link_to new_group_path(anchor: 'create-group-pane'), data: { track_label: "groups_dropdown_create_group", track_event: "click_link", qa_selector: 'create_group_link' } do
- = _('Create group')
- = nav_link(path: 'groups/new#import-group-pane') do
- = link_to new_group_path(anchor: 'import-group-pane'), data: { track_label: "groups_dropdown_import_group", track_event: "click_link", qa_selector: 'import_group_link' } do
- = _('Import group')
+ - if current_user.can_create_group?
+ = nav_link(path: 'groups/new#create-group-pane', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
+ = link_to new_group_path(anchor: 'create-group-pane'), data: { track_label: "groups_dropdown_create_group", track_event: "click_link" } do
+ = _('Create group')
+ = nav_link(path: 'groups/new#import-group-pane') do
+ = link_to new_group_path(anchor: 'import-group-pane'), data: { track_label: "groups_dropdown_import_group", track_event: "click_link" } do
+ = _('Import group')
.frequent-items-dropdown-content
#js-groups-dropdown{ data: { user_name: current_user.username, group: group_meta } }
diff --git a/app/views/layouts/nav/projects_dropdown/_show.html.haml b/app/views/layouts/nav/projects_dropdown/_show.html.haml
index 2517508ba6c..46070975566 100644
--- a/app/views/layouts/nav/projects_dropdown/_show.html.haml
+++ b/app/views/layouts/nav/projects_dropdown/_show.html.haml
@@ -4,10 +4,10 @@
-# [1]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587
- project_meta = { id: @project.id, name: @project.name, namespace: @project.full_name, web_url: project_path(@project), avatar_url: @project.avatar_url } if @project&.persisted?
.frequent-items-dropdown-container.with-deprecated-styles
- .frequent-items-dropdown-sidebar.qa-projects-dropdown-sidebar
+ .frequent-items-dropdown-sidebar
%ul
= nav_link(path: 'dashboard/projects#index') do
- = link_to dashboard_projects_path, class: 'qa-your-projects-link', data: { track_label: "projects_dropdown_your_projects", track_event: "click_link" } do
+ = link_to dashboard_projects_path, data: { track_label: "projects_dropdown_your_projects", track_event: "click_link" } do
= _('Your projects')
= nav_link(path: 'projects#starred') do
= link_to starred_dashboard_projects_path, data: { track_label: "projects_dropdown_starred_projects", track_event: "click_link" } do
@@ -18,10 +18,10 @@
- experiment(:new_repo, user: current_user) do |e|
- e.use do
= nav_link(path: 'projects/new#blank_project', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
- = link_to new_project_path(anchor: 'blank_project'), data: { track_label: "projects_dropdown_blank_project", track_event: "click_link", track_experiment: "new_repo" } do
+ = link_to new_project_path(anchor: 'blank_project'), data: { track_label: "projects_dropdown_blank_project", track_event: "click_link", track_experiment: "new_repo", qa_selector: "create_project_link" } do
= _('Create blank project')
= nav_link(path: 'projects/new#import_project') do
- = link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link", track_experiment: "new_repo" } do
+ = link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link", track_experiment: "new_repo", qa_selector: "import_project_link" } do
= _('Import project')
- e.try do
= nav_link(path: 'projects/new#blank_project', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index b71866c9138..7a80c4e0ba9 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -1,14 +1,17 @@
+- avatar_size = sidebar_refactor_disabled? ? 24 : 18
+- avatar_size_class = sidebar_refactor_disabled? ? 's40' : 's32'
+
%aside.nav-sidebar.qa-admin-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), 'aria-label': _('Admin navigation') }
.nav-sidebar-inner-scroll
.context-header
= link_to admin_root_path, title: _('Admin Overview') do
- %span.avatar-container.s40.settings-avatar
- = sprite_icon('admin', size: 24)
+ %span{ class: ['avatar-container', 'settings-avatar', 'rect-avatar', avatar_size_class] }
+ = sprite_icon('admin', size: avatar_size)
%span.sidebar-context-title
= _('Admin Area')
%ul.sidebar-top-level-items{ data: { qa_selector: 'admin_sidebar_overview_submenu_content' } }
= nav_link(controller: %w(dashboard admin admin/projects users groups jobs runners gitaly_servers), html_options: {class: 'home'}) do
- = link_to admin_root_path do
+ = link_to admin_root_path, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('overview')
%span.nav-item-name
@@ -49,7 +52,7 @@
= _('Gitaly Servers')
= nav_link(controller: admin_analytics_nav_links) do
- = link_to admin_dev_ops_report_path, data: { qa_selector: 'admin_analytics_link' } do
+ = link_to admin_dev_ops_report_path, data: { qa_selector: 'admin_analytics_link' }, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('chart')
%span.nav-item-name
@@ -71,14 +74,14 @@
= _('Usage Trends')
= nav_link(controller: admin_monitoring_nav_links) do
- = link_to admin_system_info_path, data: { qa_selector: 'admin_monitoring_link' } do
+ = link_to admin_system_info_path, data: { qa_selector: 'admin_monitoring_link' }, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('monitor')
%span.nav-item-name
= _('Monitoring')
%ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_sidebar_monitoring_submenu_content' } }
- = nav_link(controller: %w(system_info background_jobs health_check requests_profiles), html_options: { class: "fly-out-top-item" } ) do
+ = nav_link(controller: admin_monitoring_nav_links, html_options: { class: "fly-out-top-item" } ) do
= link_to admin_system_info_path do
%strong.fly-out-top-item-name
= _('Monitoring')
@@ -87,6 +90,10 @@
= link_to admin_system_info_path, title: _('System Info') do
%span
= _('System Info')
+ = nav_link(controller: :background_migrations) do
+ = link_to admin_background_migrations_path, title: _('Background Migrations') do
+ %span
+ = _('Background Migrations')
= nav_link(controller: :background_jobs) do
= link_to admin_background_jobs_path, title: _('Background Jobs') do
%span
@@ -227,20 +234,8 @@
%strong.fly-out-top-item-name
= _('Labels')
- = nav_link(controller: :appearances) do
- = link_to admin_appearances_path do
- .nav-icon-container
- = sprite_icon('appearance')
- %span.nav-item-name
- = _('Appearance')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :appearances, html_options: { class: "fly-out-top-item" } ) do
- = link_to admin_appearances_path do
- %strong.fly-out-top-item-name
- = _('Appearance')
-
- = nav_link(controller: [:application_settings, :integrations]) do
- = link_to general_admin_application_settings_path do
+ = nav_link(controller: [:application_settings, :integrations, :appearances]) do
+ = link_to general_admin_application_settings_path, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('settings')
%span.nav-item-name.qa-admin-settings-item
@@ -248,7 +243,7 @@
%ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_sidebar_settings_submenu_content' } }
-# This active_nav_link check is also used in `app/views/layouts/admin.html.haml`
- = nav_link(controller: [:application_settings, :integrations], html_options: { class: "fly-out-top-item" } ) do
+ = nav_link(controller: [:application_settings, :integrations, :appearances], html_options: { class: "fly-out-top-item" } ) do
= link_to general_admin_application_settings_path do
%strong.fly-out-top-item-name
= _('Settings')
@@ -295,6 +290,10 @@
= link_to network_admin_application_settings_path, title: _('Network'), data: { qa_selector: 'admin_settings_network_item' } do
%span
= _('Network')
+ = nav_link(controller: :appearances ) do
+ = link_to admin_application_settings_appearances_path do
+ %span
+ = _('Appearance')
= nav_link(path: 'application_settings#preferences') do
= link_to preferences_admin_application_settings_path, title: _('Preferences'), data: { qa_selector: 'admin_settings_preferences_link' } do
%span
diff --git a/app/views/layouts/nav/sidebar/_analytics_links.html.haml b/app/views/layouts/nav/sidebar/_analytics_links.html.haml
index 970a1d5f2c7..58989d6afc4 100644
--- a/app/views/layouts/nav/sidebar/_analytics_links.html.haml
+++ b/app/views/layouts/nav/sidebar/_analytics_links.html.haml
@@ -4,7 +4,7 @@
- if navbar_links.any?
= nav_link(path: all_paths) do
- = link_to analytics_link.link, {class: 'shortcuts-analytics', data: { qa_selector: 'analytics_anchor' } } do
+ = link_to analytics_link.link, {class: 'shortcuts-analytics has-sub-items', data: { qa_selector: 'analytics_anchor' } } do
.nav-icon-container
= sprite_icon('chart')
%span.nav-item-name{ data: { qa_selector: 'analytics_link' } }
diff --git a/app/views/layouts/nav/sidebar/_context_menu_body.html.haml b/app/views/layouts/nav/sidebar/_context_menu_body.html.haml
new file mode 100644
index 00000000000..321bcda5702
--- /dev/null
+++ b/app/views/layouts/nav/sidebar/_context_menu_body.html.haml
@@ -0,0 +1,9 @@
+- avatar_size_class = sidebar_refactor_disabled? ? 's40' : 's32'
+- avatar_classes = ['avatar-container', 'rect-avatar', 'group-avatar']
+- avatar_classes << avatar_size_class
+
+= link_to group_path(@group), title: @group.name, data: { qa_selector: 'group_scope_link' } do
+ %span{ class: avatar_classes }
+ = group_icon(@group, class: ['avatar', 'avatar-tile', avatar_size_class])
+ %span.sidebar-context-title
+ = @group.name
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index 757f95f864a..0ce1d48a2de 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -1,36 +1,39 @@
- issues_count = cached_issuables_count(@group, type: :issues)
-- merge_requests_count = group_open_merge_requests_count(@group)
+- merge_requests_count = cached_issuables_count(@group, type: :merge_requests)
- aside_title = @group.subgroup? ? _('Subgroup navigation') : _('Group navigation')
%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **sidebar_tracking_attributes_by_object(@group), 'aria-label': aside_title }
.nav-sidebar-inner-scroll
- .context-header
- = link_to group_path(@group), title: @group.name do
- %span.avatar-container.rect-avatar.s40.group-avatar
- = group_icon(@group, class: "avatar s40 avatar-tile")
- %span.sidebar-context-title
- = @group.name
+ - if sidebar_refactor_disabled?
+ .context-header
+ = render 'layouts/nav/sidebar/context_menu_body'
+
%ul.sidebar-top-level-items.qa-group-sidebar
+ - if sidebar_refactor_enabled?
+ = nav_link(path: ['groups#show', 'groups#details'], html_options: { class: 'context-header' }) do
+ = render 'layouts/nav/sidebar/context_menu_body'
+
= render_if_exists 'layouts/nav/sidebar/group_trial_status_widget', group: @group
- if group_sidebar_link?(:overview)
- paths = group_overview_nav_link_paths
= nav_link(path: paths, unless: -> { current_path?('groups/contribution_analytics#show') }, html_options: { class: 'home' }) do
- = link_to group_path(@group) do
+ - information_link = sidebar_refactor_enabled? ? activity_group_path(@group) : group_path(@group)
+ = link_to information_link, class: 'has-sub-items', data: { qa_selector: 'group_information_link' } do
.nav-icon-container
- - sprite = Feature.enabled?(:sidebar_refactor, current_user) ? 'group' : 'home'
+ - sprite = sidebar_refactor_enabled? ? 'group' : 'home'
= sprite_icon(sprite)
%span.nav-item-name
= group_information_title(@group)
- %ul.sidebar-sub-level-items
+ %ul.sidebar-sub-level-items{ data: { qa_selector: 'group_information_submenu'} }
= nav_link(path: paths, html_options: { class: "fly-out-top-item" } ) do
- = link_to group_path(@group) do
+ = link_to information_link do
%strong.fly-out-top-item-name
= group_information_title(@group)
%li.divider.fly-out-top-item
- - if Feature.disabled?(:sidebar_refactor, current_user)
+ - if sidebar_refactor_disabled?
= nav_link(path: ['groups#show', 'groups#details', 'groups#subgroups'], html_options: { class: 'home' }) do
= link_to details_group_path(@group), title: _('Group details') do
%span
@@ -42,13 +45,13 @@
%span
= _('Activity')
- - if group_sidebar_link?(:labels) && Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+ - if group_sidebar_link?(:labels) && sidebar_refactor_enabled?
= nav_link(path: 'labels#index') do
= link_to group_labels_path(@group), title: _('Labels') do
%span
= _('Labels')
- - if Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+ - if sidebar_refactor_enabled?
- if group_sidebar_link?(:group_members)
= nav_link(path: 'group_members#index') do
= link_to group_group_members_path(@group), title: _('Members'), data: { qa_selector: 'group_members_item' } do
@@ -59,7 +62,7 @@
- if group_sidebar_link?(:issues)
= nav_link(path: group_issues_sub_menu_items, unless: -> { current_path?('issues_analytics#show') }) do
- = link_to issues_group_path(@group), data: { qa_selector: 'group_issues_item' } do
+ = link_to issues_group_path(@group), data: { qa_selector: 'group_issues_item' }, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('issues')
%span.nav-item-name
@@ -85,7 +88,7 @@
%span
= boards_link_text
- - if group_sidebar_link?(:labels) && Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+ - if group_sidebar_link?(:labels) && sidebar_refactor_disabled?
= nav_link(path: 'labels#index') do
= link_to group_labels_path(@group), title: _('Labels') do
%span
@@ -138,7 +141,7 @@
- if group_sidebar_link?(:wiki)
= render 'layouts/nav/sidebar/wiki_link', wiki_url: @group.wiki.web_url
- - if Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+ - if sidebar_refactor_disabled?
- if group_sidebar_link?(:group_members)
= nav_link(path: 'group_members#index') do
= link_to group_group_members_path(@group) do
@@ -154,7 +157,7 @@
- if group_sidebar_link?(:settings)
= nav_link(path: group_settings_nav_link_paths) do
- = link_to edit_group_path(@group) do
+ = link_to edit_group_path(@group), class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('settings')
%span.nav-item-name{ data: { qa_selector: 'group_settings' } }
diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml
index 63b97e3133c..daafabdb799 100644
--- a/app/views/layouts/nav/sidebar/_profile.html.haml
+++ b/app/views/layouts/nav/sidebar/_profile.html.haml
@@ -1,9 +1,12 @@
+- avatar_size = sidebar_refactor_disabled? ? 40 : 32
+- avatar_size_class = sidebar_refactor_disabled? ? 's40' : 's32'
+
%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **sidebar_tracking_attributes_by_object(current_user), 'aria-label': _('User settings') }
.nav-sidebar-inner-scroll
.context-header
= link_to profile_path, title: _('Profile Settings') do
- %span.avatar-container.s40.settings-avatar
- = image_tag avatar_icon_for_user(current_user, 40), class: "avatar s40 avatar-tile js-sidebar-user-avatar", alt: current_user.name, data: { testid: 'sidebar-user-avatar' }
+ %span{ class: ['avatar-container', 'settings-avatar', avatar_size_class] }
+ = image_tag avatar_icon_for_user(current_user, avatar_size), class: ['avatar', 'avatar-tile', 'js-sidebar-user-avatar', avatar_size_class], alt: current_user.name, data: { testid: 'sidebar-user-avatar' }
%span.sidebar-context-title= _('User Settings')
%ul.sidebar-top-level-items
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
diff --git a/app/views/layouts/terms.html.haml b/app/views/layouts/terms.html.haml
index e39cb5ee0a2..4d5c354388f 100644
--- a/app/views/layouts/terms.html.haml
+++ b/app/views/layouts/terms.html.haml
@@ -5,7 +5,7 @@
%body{ data: { page: body_data_page } }
.layout-page.terms{ class: page_class }
- .content-wrapper.gl-mt-0
+ .content-wrapper
.mobile-overlay
.alert-wrapper
= render "layouts/broadcast"