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
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-04-13 00:18:30 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-04-13 00:18:30 +0300
commitac48f7c24110a7a1e0a0aa49fc7838ab03c28374 (patch)
tree0d323ff3b3317315241fd1c784d82bfa0577711e /app
parent6ce6d20cf0b81275bad7bf8e95cf49bd475c5c4f (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/header_search/components/app.vue1
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/utils.js9
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js3
-rw-r--r--app/assets/javascripts/repository/components/fork_info.vue6
-rw-r--r--app/assets/javascripts/repository/index.js2
-rw-r--r--app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/dropdown_keyboard_navigation.vue31
-rw-r--r--app/assets/stylesheets/framework/header.scss18
-rw-r--r--app/assets/stylesheets/framework/system_messages.scss2
-rw-r--r--app/assets/stylesheets/framework/variables.scss4
-rw-r--r--app/assets/stylesheets/pages/registry.scss2
-rw-r--r--app/controllers/projects/tree_controller.rb2
-rw-r--r--app/controllers/projects_controller.rb2
-rw-r--r--app/graphql/mutations/projects/sync_fork.rb15
-rw-r--r--app/helpers/application_settings_helper.rb1
-rw-r--r--app/helpers/projects_helper.rb1
-rw-r--r--app/models/application_setting.rb3
-rw-r--r--app/validators/json_schemas/build_report_result_data.json5
-rw-r--r--app/validators/json_schemas/build_report_result_data_tests.json12
-rw-r--r--app/views/groups/new.html.haml2
-rw-r--r--app/views/layouts/_page.html.haml4
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml28
-rw-r--r--app/views/layouts/nav/_top_bar.html.haml10
-rw-r--r--app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml20
-rw-r--r--app/views/layouts/terms.html.haml2
-rw-r--r--app/views/projects/new.html.haml2
-rw-r--r--app/views/shared/_auto_devops_callout.html.haml2
-rw-r--r--app/views/shared/boards/_show.html.haml2
28 files changed, 116 insertions, 77 deletions
diff --git a/app/assets/javascripts/header_search/components/app.vue b/app/assets/javascripts/header_search/components/app.vue
index 306183ebcca..aa349186014 100644
--- a/app/assets/javascripts/header_search/components/app.vue
+++ b/app/assets/javascripts/header_search/components/app.vue
@@ -286,6 +286,7 @@ export default {
:max="searchOptions.length - 1"
:min="$options.FIRST_DROPDOWN_INDEX"
:default-index="defaultIndex"
+ :enable-cycle="true"
/>
<header-search-default-items
v-if="showDefaultItems"
diff --git a/app/assets/javascripts/packages_and_registries/shared/utils.js b/app/assets/javascripts/packages_and_registries/shared/utils.js
index 76623377d90..adffab277cc 100644
--- a/app/assets/javascripts/packages_and_registries/shared/utils.js
+++ b/app/assets/javascripts/packages_and_registries/shared/utils.js
@@ -55,15 +55,6 @@ export const renderBreadcrumb = (router, apolloProvider, RegistryBreadcrumb) =>
RegistryBreadcrumb,
},
render(createElement) {
- // FIXME(@tnir): this is a workaround until the MR gets merged:
- // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48115
- const parentEl = breadCrumbEl.parentElement.parentElement;
- if (parentEl) {
- parentEl.classList.remove('breadcrumbs-container');
- parentEl.classList.add('gl-display-flex');
- parentEl.classList.add('w-100');
- }
- // End of FIXME(@tnir)
return createElement('registry-breadcrumb', {
class: breadCrumbEl.className,
props: {
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js
index 2f8c2a8e86f..6d5460da2e5 100644
--- a/app/assets/javascripts/pages/projects/blob/show/index.js
+++ b/app/assets/javascripts/pages/projects/blob/show/index.js
@@ -17,6 +17,7 @@ import createStore from '~/code_navigation/store';
import { generateRefDestinationPath } from '~/repository/utils/ref_switcher_utils';
import RefSelector from '~/ref/components/ref_selector.vue';
import { joinPaths, visitUrl } from '~/lib/utils/url_utility';
+import { parseBoolean } from '~/lib/utils/common_utils';
Vue.use(Vuex);
Vue.use(VueApollo);
@@ -100,6 +101,7 @@ const initForkInfo = () => {
sourceName,
sourcePath,
sourceDefaultBranch,
+ canSyncBranch,
aheadComparePath,
behindComparePath,
canUserCreateMrInFork,
@@ -110,6 +112,7 @@ const initForkInfo = () => {
render(h) {
return h(ForkInfo, {
props: {
+ canSyncBranch: parseBoolean(canSyncBranch),
projectPath,
selectedBranch,
sourceName,
diff --git a/app/assets/javascripts/repository/components/fork_info.vue b/app/assets/javascripts/repository/components/fork_info.vue
index a7795c8da0a..07a29bd3b96 100644
--- a/app/assets/javascripts/repository/components/fork_info.vue
+++ b/app/assets/javascripts/repository/components/fork_info.vue
@@ -94,6 +94,11 @@ export default {
required: false,
default: '',
},
+ canSyncBranch: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
aheadComparePath: {
type: String,
required: false,
@@ -187,6 +192,7 @@ export default {
hasUpdateButton() {
return (
this.glFeatures.synchronizeFork &&
+ this.canSyncBranch &&
((this.sourceName && this.forkDetails && this.behind) || this.isUnknownDivergence)
);
},
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js
index b1217881bc3..b5568393313 100644
--- a/app/assets/javascripts/repository/index.js
+++ b/app/assets/javascripts/repository/index.js
@@ -75,6 +75,7 @@ export default function setupVueRepositoryList() {
sourcePath,
sourceDefaultBranch,
createMrPath,
+ canSyncBranch,
aheadComparePath,
behindComparePath,
canUserCreateMrInFork,
@@ -85,6 +86,7 @@ export default function setupVueRepositoryList() {
render(h) {
return h(ForkInfo, {
props: {
+ canSyncBranch: parseBoolean(canSyncBranch),
projectPath,
selectedBranch,
sourceName,
diff --git a/app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js b/app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js
index 3d798d278bf..ba5495ba014 100644
--- a/app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js
+++ b/app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js
@@ -32,7 +32,7 @@ const hide = (sidebar, toggle, isUserAction) => {
setTimeout(() => {
sidebar.classList.add(SIDEBAR_VISIBILITY_CLASS);
if (isUserAction) {
- toggle.focus();
+ toggle?.focus();
}
}, SIDEBAR_TRANSITION_DURATION);
};
diff --git a/app/assets/javascripts/vue_shared/components/dropdown_keyboard_navigation.vue b/app/assets/javascripts/vue_shared/components/dropdown_keyboard_navigation.vue
index 1da84df022f..b920af593df 100644
--- a/app/assets/javascripts/vue_shared/components/dropdown_keyboard_navigation.vue
+++ b/app/assets/javascripts/vue_shared/components/dropdown_keyboard_navigation.vue
@@ -27,6 +27,12 @@ export default {
type: Number,
required: true,
},
+ /* enable possibility to cycle around */
+ enableCycle: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
watch: {
max() {
@@ -64,15 +70,34 @@ export default {
return;
}
- const nextIndex = Math.max(this.min, Math.min(this.index + val, this.max));
+ let nextIndex = Math.max(this.min, Math.min(this.index + val, this.max));
- // Return if the index didn't change
if (nextIndex === this.index) {
- return;
+ // Return if the index didn't change and cycle is not enabled
+ if (!this.enableCycle) {
+ return;
+ }
+ // Update nextIndex if the cycle is enabled
+ nextIndex = this.cycle(nextIndex, val);
}
this.$emit('change', nextIndex);
},
+ cycle(nextIndex, val) {
+ if (val === 1 && nextIndex === this.max) {
+ // if we are moving down +1 and we reached bottom (max)
+ // return top most index (min)
+ return this.min;
+ }
+
+ if (val === -1 && nextIndex === this.min) {
+ // if we are moving up -1 and we reached top (min)
+ // return bottom most index (max)
+ return this.max;
+ }
+
+ return nextIndex;
+ },
},
render() {
return this.$scopedSlots.default?.();
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 4eb5a686d43..0d18835ac0f 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -312,22 +312,12 @@ $search-input-field-x-min-width: 200px;
margin-top: $dropdown-vertical-offset;
}
-.breadcrumbs {
- display: flex;
- min-height: $breadcrumb-min-height;
- color: $gl-text-color;
-}
-
-.breadcrumbs-container {
- display: flex;
- width: 100%;
- padding-top: $gl-padding / 2;
- padding-bottom: $gl-padding / 2;
- align-items: center;
+.top-bar-container {
+ min-height: $top-bar-height;
border-bottom: 1px solid $border-color;
}
-.breadcrumbs-links {
+.breadcrumbs {
flex: 1;
min-width: 0;
align-self: center;
@@ -549,7 +539,7 @@ $search-input-field-x-min-width: 200px;
@include media-breakpoint-down(sm) {
@include gl-display-block;
- + .breadcrumbs-links {
+ + .breadcrumbs {
@include gl-pl-4;
@include gl-border-l-1;
@include gl-border-l-solid;
diff --git a/app/assets/stylesheets/framework/system_messages.scss b/app/assets/stylesheets/framework/system_messages.scss
index 06532d6e1f5..db59a482c64 100644
--- a/app/assets/stylesheets/framework/system_messages.scss
+++ b/app/assets/stylesheets/framework/system_messages.scss
@@ -68,7 +68,7 @@
.boards-list,
.board-swimlanes {
- height: calc(100vh - (#{$header-height} + #{$breadcrumb-min-height} + #{$performance-bar-height} + #{$system-footer-height} + #{$gl-padding-32}));
+ height: calc(100vh - (#{$header-height} + #{$top-bar-height} + #{$performance-bar-height} + #{$system-footer-height} + #{$gl-padding-32}));
}
}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index a4d9bcccb38..d9e36735f2c 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -484,7 +484,7 @@ $mr-review-bar-height: calc(2rem + 13px);
$flash-height: 52px;
$flash-container-top: 48px;
$context-header-height: 60px;
-$breadcrumb-min-height: 48px;
+$top-bar-height: 48px;
$home-panel-title-row-height: 64px;
$home-panel-avatar-mobile-size: 24px;
$issuable-title-max-width: 350px;
@@ -694,7 +694,7 @@ $issue-boards-filter-height: 68px;
The following heights are used in environment_logs.scss and are used for calculation of the log viewer height.
*/
$environment-logs-breadcrumbs-height: 63px;
-$environment-logs-breadcrumbs-height-md: $breadcrumb-min-height;
+$environment-logs-breadcrumbs-height-md: $top-bar-height;
$environment-logs-difference-xs-up: calc(#{$header-height} + #{$environment-logs-breadcrumbs-height});
$environment-logs-difference-md-up: calc(#{$header-height} + #{$environment-logs-breadcrumbs-height-md});
diff --git a/app/assets/stylesheets/pages/registry.scss b/app/assets/stylesheets/pages/registry.scss
index 31c6dbd2970..36b86771295 100644
--- a/app/assets/stylesheets/pages/registry.scss
+++ b/app/assets/stylesheets/pages/registry.scss
@@ -2,7 +2,7 @@
// until this gitlab-ui issue is resolved: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1079
//
// See app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue when this is changed.
-.breadcrumbs-container .gl-breadcrumbs {
+.breadcrumbs .gl-breadcrumbs {
padding: 0;
box-shadow: none;
}
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index c8e98e6aa1c..0631c02355e 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -18,7 +18,7 @@ class Projects::TreeController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:highlight_js, @project)
- push_frontend_feature_flag(:synchronize_fork, @project)
+ push_frontend_feature_flag(:synchronize_fork, @project.fork_source)
push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 04b51a2cba1..a6bc754d09e 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -38,7 +38,7 @@ class ProjectsController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:highlight_js, @project)
- push_frontend_feature_flag(:synchronize_fork, @project)
+ push_frontend_feature_flag(:synchronize_fork, @project&.fork_source)
push_licensed_feature(:file_locks) if @project.present? && @project.licensed_feature_available?(:file_locks)
push_licensed_feature(:security_orchestration_policies) if @project.present? && @project.licensed_feature_available?(:security_orchestration_policies)
push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?)
diff --git a/app/graphql/mutations/projects/sync_fork.rb b/app/graphql/mutations/projects/sync_fork.rb
index 121c16df87b..05332457e8c 100644
--- a/app/graphql/mutations/projects/sync_fork.rb
+++ b/app/graphql/mutations/projects/sync_fork.rb
@@ -7,8 +7,6 @@ module Mutations
include FindsProject
- authorize :push_code
-
argument :project_path, GraphQL::Types::ID,
required: true,
description: 'Full path of the project to initialize.'
@@ -22,9 +20,10 @@ module Mutations
description: 'Updated fork details.'
def resolve(project_path:, target_branch:)
- project = authorized_find!(project_path)
+ project = authorized_find!(project_path, target_branch)
- return respond(nil, ['Feature flag is disabled']) unless Feature.enabled?(:synchronize_fork, project)
+ return respond(nil, ['Feature flag is disabled']) unless Feature.enabled?(:synchronize_fork,
+ project.fork_source)
details_resolver = Resolvers::Projects::ForkDetailsResolver.new(object: project, context: context, field: nil)
details = details_resolver.resolve(ref: target_branch)
@@ -56,6 +55,14 @@ module Mutations
def respond(details, errors)
{ details: details, errors: errors }
end
+
+ def authorized_find!(project_path, target_branch)
+ project = find_object(project_path)
+
+ return project if ::Gitlab::UserAccess.new(current_user, container: project).can_update_branch?(target_branch)
+
+ raise_resource_not_available_error!
+ end
end
end
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index fd684ee5ecb..42c9481828c 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -356,6 +356,7 @@ module ApplicationSettingsHelper
:shared_runners_text,
:sign_in_text,
:signup_enabled,
+ :silent_mode_enabled,
:sourcegraph_enabled,
:sourcegraph_url,
:sourcegraph_public_only,
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 21a736bf68a..567cca7cab1 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -137,6 +137,7 @@ module ProjectsHelper
source_name: source_project.full_name,
source_path: project_path(source_project),
source_default_branch: source_default_branch,
+ can_sync_branch: ::Gitlab::UserAccess.new(current_user, container: project).can_update_branch?(ref).to_s,
ahead_compare_path: project_compare_path(
project, from: source_default_branch, to: ref, from_project_id: source_project.id
),
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 9aab1d96083..c11cd0191df 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -439,6 +439,9 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord
allow_nil: false,
inclusion: { in: [true, false], message: N_('must be a boolean value') }
+ validates :silent_mode_enabled,
+ inclusion: { in: [true, false], message: N_('must be a boolean value') }
+
Gitlab::SSHPublicKey.supported_types.each do |type|
validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type }
end
diff --git a/app/validators/json_schemas/build_report_result_data.json b/app/validators/json_schemas/build_report_result_data.json
index d109389a046..d9ef7633acd 100644
--- a/app/validators/json_schemas/build_report_result_data.json
+++ b/app/validators/json_schemas/build_report_result_data.json
@@ -8,10 +8,7 @@
"format": "float"
},
"tests": {
- "type": "object",
- "items": {
- "$ref": "./build_report_result_data_tests.json"
- }
+ "$ref": "./build_report_result_data_tests.json"
}
},
"additionalProperties": false
diff --git a/app/validators/json_schemas/build_report_result_data_tests.json b/app/validators/json_schemas/build_report_result_data_tests.json
index 3b6a2688313..456b651dd6c 100644
--- a/app/validators/json_schemas/build_report_result_data_tests.json
+++ b/app/validators/json_schemas/build_report_result_data_tests.json
@@ -7,7 +7,7 @@
"type": "string"
},
"duration": {
- "type": "string"
+ "type": "number"
},
"failed": {
"type": "integer"
@@ -20,6 +20,16 @@
},
"success": {
"type": "integer"
+ },
+ "suite_error": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ]
}
},
"additionalProperties": false
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index 0677a91f385..4c3ea0f292e 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -1,4 +1,4 @@
-- @hide_breadcrumbs = true
+- @hide_top_bar = true
- @hide_top_links = true
- page_title _('New Group')
- header_title _("Groups"), dashboard_groups_path
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 7e7f8a6a871..1a647249eb7 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -35,8 +35,8 @@
= dispensable_render_if_exists "shared/new_user_signups_cap_reached_alert"
= yield :page_level_alert
= yield :group_invite_members_banner
- - unless @hide_breadcrumbs
- = render "layouts/nav/breadcrumbs"
+ - unless @hide_top_bar
+ = render "layouts/nav/top_bar"
%div{ class: "#{container_class unless @no_container} #{@content_class}" }
%main.content{ id: "content-body", **page_itemtype }
= render "layouts/flash", extra_flash_class: 'limit-container-width'
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
deleted file mode 100644
index 60c5cb1af68..00000000000
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ /dev/null
@@ -1,28 +0,0 @@
-- container = @no_breadcrumb_container ? 'container-fluid' : container_class
-- hide_top_links = @hide_top_links || false
-- unless @skip_current_level_breadcrumb
- - push_to_schema_breadcrumb(@breadcrumb_title, breadcrumb_title_link)
-
-.gl-relative
- .breadcrumbs{ class: [container, @content_class] }
- .breadcrumbs-container
- - if show_super_sidebar?
- = render Pajamas::ButtonComponent.new(icon: 'sidebar', category: :tertiary, button_options: { class: 'js-super-sidebar-toggle super-sidebar-toggle gl-ml-n3 gl-mr-2', title: _('Expand sidebar'), aria: { controls: 'super-sidebar', expanded: 'false', label: _('Navigation sidebar') }, data: {toggle: 'tooltip', placement: 'right' } })
- - elsif defined?(@left_sidebar)
- = render Pajamas::ButtonComponent.new(icon: 'sidebar', category: :tertiary, button_options: { class: 'toggle-mobile-nav gl-ml-n3 gl-mr-2', data: { qa_selector: 'toggle_mobile_nav_button' }, aria: { label: _('Open sidebar') } })
- %nav.breadcrumbs-links{ 'aria-label': _('Breadcrumbs'), data: { testid: 'breadcrumb-links', qa_selector: 'breadcrumb_links_content' } }
- %ul.list-unstyled.breadcrumbs-list.js-breadcrumbs-list
- - unless hide_top_links
- = header_title
- - if @breadcrumbs_extra_links
- - @breadcrumbs_extra_links.each do |extra|
- = breadcrumb_list_item link_to(extra[:text], extra[:link])
- = render "layouts/nav/breadcrumbs/collapsed_inline_list", location: :after
- - unless @skip_current_level_breadcrumb
- %li{ data: { testid: 'breadcrumb-current-link', qa_selector: 'breadcrumb_current_link' } }
- = link_to @breadcrumb_title, breadcrumb_title_link
- -# haml-lint:disable InlineJavaScript
- %script{ type: 'application/ld+json' }
- :plain
- #{schema_breadcrumb_json}
- = yield :header_content
diff --git a/app/views/layouts/nav/_top_bar.html.haml b/app/views/layouts/nav/_top_bar.html.haml
new file mode 100644
index 00000000000..e7a6566a7ff
--- /dev/null
+++ b/app/views/layouts/nav/_top_bar.html.haml
@@ -0,0 +1,10 @@
+- container = @no_top_bar_container ? 'container-fluid' : container_class
+
+.gl-relative
+ %div{ class: [container, @content_class] }
+ .top-bar-container.gl-display-flex.gl-align-items-center
+ - if show_super_sidebar?
+ = render Pajamas::ButtonComponent.new(icon: 'sidebar', category: :tertiary, button_options: { class: 'js-super-sidebar-toggle super-sidebar-toggle gl-ml-n3 gl-mr-2', title: _('Expand sidebar'), aria: { controls: 'super-sidebar', expanded: 'false', label: _('Navigation sidebar') }, data: {toggle: 'tooltip', placement: 'right' } })
+ - elsif defined?(@left_sidebar)
+ = render Pajamas::ButtonComponent.new(icon: 'sidebar', category: :tertiary, button_options: { class: 'toggle-mobile-nav gl-ml-n3 gl-mr-2', data: { qa_selector: 'toggle_mobile_nav_button' }, aria: { label: _('Open sidebar') } })
+ = render "layouts/nav/breadcrumbs/breadcrumbs"
diff --git a/app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml b/app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml
new file mode 100644
index 00000000000..b5f067cf42f
--- /dev/null
+++ b/app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml
@@ -0,0 +1,20 @@
+- hide_top_links = @hide_top_links || false
+- unless @skip_current_level_breadcrumb
+ - push_to_schema_breadcrumb(@breadcrumb_title, breadcrumb_title_link)
+
+%nav.breadcrumbs{ 'aria-label': _('Breadcrumbs'), data: { testid: 'breadcrumb-links', qa_selector: 'breadcrumb_links_content' } }
+ %ul.list-unstyled.breadcrumbs-list.js-breadcrumbs-list
+ - unless hide_top_links
+ = header_title
+ - if @breadcrumbs_extra_links
+ - @breadcrumbs_extra_links.each do |extra|
+ = breadcrumb_list_item link_to(extra[:text], extra[:link])
+ = render "layouts/nav/breadcrumbs/collapsed_inline_list", location: :after
+ - unless @skip_current_level_breadcrumb
+ %li{ data: { testid: 'breadcrumb-current-link', qa_selector: 'breadcrumb_current_link' } }
+ = link_to @breadcrumb_title, breadcrumb_title_link
+ -# haml-lint:disable InlineJavaScript
+ %script{ type: 'application/ld+json' }
+ :plain
+ #{schema_breadcrumb_json}
+= yield :header_content
diff --git a/app/views/layouts/terms.html.haml b/app/views/layouts/terms.html.haml
index 032be73f70c..71c622d7a62 100644
--- a/app/views/layouts/terms.html.haml
+++ b/app/views/layouts/terms.html.haml
@@ -1,6 +1,6 @@
!!! 5
- add_page_specific_style 'page_bundles/terms'
-- @hide_breadcrumbs = true
+- @hide_top_bar = true
- body_classes = [user_application_theme]
%html{ lang: I18n.locale, class: page_class }
= render "layouts/head"
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 004b9b824d9..e64ed2c7b8f 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -1,4 +1,4 @@
-- @hide_breadcrumbs = true
+- @hide_top_bar = true
- @hide_top_links = true
- page_title _('New Project')
- header_title _("Projects"), dashboard_projects_path
diff --git a/app/views/shared/_auto_devops_callout.html.haml b/app/views/shared/_auto_devops_callout.html.haml
index 93f919f01d9..c468b3a2001 100644
--- a/app/views/shared/_auto_devops_callout.html.haml
+++ b/app/views/shared/_auto_devops_callout.html.haml
@@ -1,4 +1,4 @@
-- container = @no_breadcrumb_container ? 'container-fluid' : container_class
+- container = @no_top_bar_container ? 'container-fluid' : container_class
%div{ class: [container, @content_class, 'gl-pt-5!'] }
= render Pajamas::BannerComponent.new(button_text: s_('AutoDevOps|Enable in settings'),
diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml
index c3835386d5a..e5aa4c58da1 100644
--- a/app/views/shared/boards/_show.html.haml
+++ b/app/views/shared/boards/_show.html.haml
@@ -1,5 +1,5 @@
- board = local_assigns.fetch(:board, nil)
-- @no_breadcrumb_container = true
+- @no_top_bar_container = true
- @no_container = true
- @content_wrapper_class = "#{@content_wrapper_class} gl-relative gl-pb-0"
- @content_class = "issue-boards-content js-focus-mode-board"