From e08d9350fcdda2ff798a3a79e6ccfe9369c25fa2 Mon Sep 17 00:00:00 2001 From: psjakubowska Date: Wed, 2 Oct 2024 15:44:40 +0200 Subject: [PATCH 01/17] Imtroduce a feature flag to secure the rollout --- .../common_repository_blob_header_app.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 config/feature_flags/gitlab_com_derisk/common_repository_blob_header_app.yml diff --git a/config/feature_flags/gitlab_com_derisk/common_repository_blob_header_app.yml b/config/feature_flags/gitlab_com_derisk/common_repository_blob_header_app.yml new file mode 100644 index 00000000000000..2863e0ce0ed6de --- /dev/null +++ b/config/feature_flags/gitlab_com_derisk/common_repository_blob_header_app.yml @@ -0,0 +1,9 @@ +--- +name: common_repository_blob_header_app +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/497051 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/167906 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/497345 +milestone: '17.5' +group: group::source code +type: gitlab_com_derisk +default_enabled: false -- GitLab From 9905d98235a50ac7ccb936a57fa4ab0f71d3a208 Mon Sep 17 00:00:00 2001 From: psjakubowska Date: Wed, 2 Oct 2024 16:18:18 +0200 Subject: [PATCH 02/17] Organize header area components --- .../components/{ => header_area}/blob_controls.vue | 4 ++-- .../components/{ => header_area}/breadcrumbs.vue | 10 +++++----- app/assets/javascripts/repository/index.js | 4 ++-- .../components/{ => header_area}/blob_controls_spec.js | 4 ++-- .../components/{ => header_area}/breadcrumbs_spec.js | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) rename app/assets/javascripts/repository/components/{ => header_area}/blob_controls.vue (97%) rename app/assets/javascripts/repository/components/{ => header_area}/breadcrumbs.vue (95%) rename spec/frontend/repository/components/{ => header_area}/blob_controls_spec.js (96%) rename spec/frontend/repository/components/{ => header_area}/breadcrumbs_spec.js (98%) diff --git a/app/assets/javascripts/repository/components/blob_controls.vue b/app/assets/javascripts/repository/components/header_area/blob_controls.vue similarity index 97% rename from app/assets/javascripts/repository/components/blob_controls.vue rename to app/assets/javascripts/repository/components/header_area/blob_controls.vue index 4611afa270a6de..5f9ce8b7dc61f1 100644 --- a/app/assets/javascripts/repository/components/blob_controls.vue +++ b/app/assets/javascripts/repository/components/header_area/blob_controls.vue @@ -18,8 +18,8 @@ import { import { sanitize } from '~/lib/dompurify'; import { InternalEvents } from '~/tracking'; import { FIND_FILE_BUTTON_CLICK } from '~/tracking/constants'; -import { updateElementsVisibility } from '../utils/dom'; -import blobControlsQuery from '../queries/blob_controls.query.graphql'; +import { updateElementsVisibility } from '~/repository/utils/dom'; +import blobControlsQuery from '~/repository/queries/blob_controls.query.graphql'; import { getRefType } from '../utils/ref_type'; export default { diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/header_area/breadcrumbs.vue similarity index 95% rename from app/assets/javascripts/repository/components/breadcrumbs.vue rename to app/assets/javascripts/repository/components/header_area/breadcrumbs.vue index 3dea54d5995b13..dc5813dff823d6 100644 --- a/app/assets/javascripts/repository/components/breadcrumbs.vue +++ b/app/assets/javascripts/repository/components/header_area/breadcrumbs.vue @@ -5,11 +5,11 @@ import permissionsQuery from 'shared_queries/repository/permissions.query.graphq import { joinPaths, escapeFileUrl, buildURLwithRefType } from '~/lib/utils/url_utility'; import { BV_SHOW_MODAL } from '~/lib/utils/constants'; import { __ } from '~/locale'; -import getRefMixin from '../mixins/get_ref'; -import projectPathQuery from '../queries/project_path.query.graphql'; -import projectShortPathQuery from '../queries/project_short_path.query.graphql'; -import UploadBlobModal from './upload_blob_modal.vue'; -import NewDirectoryModal from './new_directory_modal.vue'; +import getRefMixin from '~/repository/mixins/get_ref'; +import projectPathQuery from '~/repository/queries/project_path.query.graphql'; +import projectShortPathQuery from '~/repository/queries/project_short_path.query.graphql'; +import UploadBlobModal from '~/repository/components/upload_blob_modal.vue'; +import NewDirectoryModal from '~/repository/components/new_directory_modal.vue'; const UPLOAD_BLOB_MODAL_ID = 'modal-upload-blob'; const NEW_DIRECTORY_MODAL_ID = 'modal-new-directory'; diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js index 00c52f6a7607fd..b11f0d0dc3f86b 100644 --- a/app/assets/javascripts/repository/index.js +++ b/app/assets/javascripts/repository/index.js @@ -12,10 +12,10 @@ import RefSelector from '~/ref/components/ref_selector.vue'; import HighlightWorker from '~/vue_shared/components/source_viewer/workers/highlight_worker?worker'; import CodeDropdown from '~/vue_shared/components/code_dropdown/code_dropdown.vue'; import App from './components/app.vue'; -import Breadcrumbs from './components/breadcrumbs.vue'; +import Breadcrumbs from './components/header_area/breadcrumbs.vue'; import ForkInfo from './components/fork_info.vue'; import LastCommit from './components/last_commit.vue'; -import BlobControls from './components/blob_controls.vue'; +import BlobControls from './components/header_area/blob_controls.vue'; import apolloProvider from './graphql'; import commitsQuery from './queries/commits.query.graphql'; import projectPathQuery from './queries/project_path.query.graphql'; diff --git a/spec/frontend/repository/components/blob_controls_spec.js b/spec/frontend/repository/components/header_area/blob_controls_spec.js similarity index 96% rename from spec/frontend/repository/components/blob_controls_spec.js rename to spec/frontend/repository/components/header_area/blob_controls_spec.js index d36b0b8e7c965a..7e3a55223a9b0f 100644 --- a/spec/frontend/repository/components/blob_controls_spec.js +++ b/spec/frontend/repository/components/header_area/blob_controls_spec.js @@ -3,7 +3,7 @@ import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; -import BlobControls from '~/repository/components/blob_controls.vue'; +import BlobControls from '~/repository/components/header_area/blob_controls.vue'; import blobControlsQuery from '~/repository/queries/blob_controls.query.graphql'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { useMockInternalEventsTracking } from 'helpers/tracking_internal_events_helper'; @@ -13,7 +13,7 @@ import { resetShortcutsForTests } from '~/behaviors/shortcuts'; import ShortcutsBlob from '~/behaviors/shortcuts/shortcuts_blob'; import Shortcuts from '~/behaviors/shortcuts/shortcuts'; import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater'; -import { blobControlsDataMock, refMock } from '../mock_data'; +import { blobControlsDataMock, refMock } from '../../mock_data'; jest.mock('~/repository/utils/dom'); jest.mock('~/behaviors/shortcuts/shortcuts_blob'); diff --git a/spec/frontend/repository/components/breadcrumbs_spec.js b/spec/frontend/repository/components/header_area/breadcrumbs_spec.js similarity index 98% rename from spec/frontend/repository/components/breadcrumbs_spec.js rename to spec/frontend/repository/components/header_area/breadcrumbs_spec.js index 57ee0502986936..5f4f6e19b4ecdc 100644 --- a/spec/frontend/repository/components/breadcrumbs_spec.js +++ b/spec/frontend/repository/components/header_area/breadcrumbs_spec.js @@ -2,7 +2,7 @@ import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import { GlDisclosureDropdown, GlDisclosureDropdownGroup } from '@gitlab/ui'; import { shallowMount, RouterLinkStub } from '@vue/test-utils'; -import Breadcrumbs from '~/repository/components/breadcrumbs.vue'; +import Breadcrumbs from '~/repository/components/header_area/breadcrumbs.vue'; import UploadBlobModal from '~/repository/components/upload_blob_modal.vue'; import NewDirectoryModal from '~/repository/components/new_directory_modal.vue'; import waitForPromises from 'helpers/wait_for_promises'; -- GitLab From b12a3e3770351376bb7b1d7c26601a9b713e5f8c Mon Sep 17 00:00:00 2001 From: psjakubowska Date: Wed, 2 Oct 2024 16:24:42 +0200 Subject: [PATCH 03/17] Surfuce the feature flag --- lib/gitlab/gon_helper.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb index 5d6963307b14fe..938deeaf9e4070 100644 --- a/lib/gitlab/gon_helper.rb +++ b/lib/gitlab/gon_helper.rb @@ -80,6 +80,7 @@ def add_gon_variables # Initialize gon.features with any flags that should be # made globally available to the frontend + push_frontend_feature_flag(:common_repository_blob_header_app, current_user) push_frontend_feature_flag(:source_editor_toolbar) push_frontend_feature_flag(:vscode_web_ide, current_user) push_frontend_feature_flag(:ui_for_organizations, current_user) -- GitLab From 9e1e22e5a91e1c0e6e26d64378b0277ad57512e9 Mon Sep 17 00:00:00 2001 From: psjakubowska Date: Wed, 2 Oct 2024 18:29:13 +0200 Subject: [PATCH 04/17] Add history button to header area app Create the base for header area app to be used on tree and blob view. Move tree History control. Add a check to initiate old History control only when its element is present. --- .../repository/components/header_area.vue | 50 +++++++++++++ app/assets/javascripts/repository/index.js | 71 ++++++++++++------- .../projects/tree/_tree_header.html.haml | 38 +++++----- .../repository/components/header_area_spec.js | 66 +++++++++++++++++ 4 files changed, 184 insertions(+), 41 deletions(-) create mode 100644 app/assets/javascripts/repository/components/header_area.vue create mode 100644 spec/frontend/repository/components/header_area_spec.js diff --git a/app/assets/javascripts/repository/components/header_area.vue b/app/assets/javascripts/repository/components/header_area.vue new file mode 100644 index 00000000000000..a4e17414eb62f6 --- /dev/null +++ b/app/assets/javascripts/repository/components/header_area.vue @@ -0,0 +1,50 @@ + + + diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js index b11f0d0dc3f86b..7791c25c4e947a 100644 --- a/app/assets/javascripts/repository/index.js +++ b/app/assets/javascripts/repository/index.js @@ -16,6 +16,7 @@ import Breadcrumbs from './components/header_area/breadcrumbs.vue'; import ForkInfo from './components/fork_info.vue'; import LastCommit from './components/last_commit.vue'; import BlobControls from './components/header_area/blob_controls.vue'; +import HeaderArea from './components/header_area.vue'; import apolloProvider from './graphql'; import commitsQuery from './queries/commits.query.graphql'; import projectPathQuery from './queries/project_path.query.graphql'; @@ -202,6 +203,26 @@ export default function setupVueRepositoryList() { initRefSwitcher(); initForkInfo(); + const headerEl = document.getElementById('js-repository-blob-header-app'); + if (headerEl) { + const { historyLink } = headerEl.dataset; + + // eslint-disable-next-line no-new + new Vue({ + el: headerEl, + router, + render(h) { + return h(HeaderArea, { + props: { + projectPath, + refType: this.$route.meta.refType || this.$route.query.ref_type, + historyLink, + }, + }); + }, + }); + } + router.afterEach(({ params: { path } }) => { setTitle(path, ref, fullName); }); @@ -258,31 +279,33 @@ export default function setupVueRepositoryList() { } const treeHistoryLinkEl = document.getElementById('js-tree-history-link'); - const { historyLink } = treeHistoryLinkEl.dataset; - // eslint-disable-next-line no-new - new Vue({ - el: treeHistoryLinkEl, - router, - render(h) { - const url = new URL(window.location.href); - url.pathname = `${historyLink}/${ - this.$route.params.path ? escapeFileUrl(this.$route.params.path) : '' - }`; - url.searchParams.set('ref_type', this.$route.meta.refType || this.$route.query.ref_type); - return h( - GlButton, - { - attrs: { - href: url.href, - // Ideally passing this class to `props` should work - // But it doesn't work here. :( - class: 'btn btn-default btn-md gl-button', + if (treeHistoryLinkEl) { + const { historyLink } = treeHistoryLinkEl.dataset; + // eslint-disable-next-line no-new + new Vue({ + el: treeHistoryLinkEl, + router, + render(h) { + const url = new URL(window.location.href); + url.pathname = `${historyLink}/${ + this.$route.params.path ? escapeFileUrl(this.$route.params.path) : '' + }`; + url.searchParams.set('ref_type', this.$route.meta.refType || this.$route.query.ref_type); + return h( + GlButton, + { + attrs: { + href: url.href, + // Ideally passing this class to `props` should work + // But it doesn't work here. :( + class: 'btn btn-default btn-md gl-button', + }, }, - }, - [__('History')], - ); - }, - }); + [__('History')], + ); + }, + }); + } initWebIdeLink({ el: document.getElementById('js-tree-web-ide-link'), router }); diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml index da84dc9cffea4a..9678dba1ba964b 100644 --- a/app/views/projects/tree/_tree_header.html.haml +++ b/app/views/projects/tree/_tree_header.html.haml @@ -1,25 +1,29 @@ - add_page_specific_style 'page_bundles/projects' -.tree-ref-container.gl-flex.gl-flex-wrap.gl-gap-2.mb-2.mb-md-0 - .tree-ref-holder.gl-max-w-26{ data: { testid: 'ref-dropdown-container' } } - #js-tree-ref-switcher{ data: { project_id: @project.id, ref_type: @ref_type.to_s, project_root_path: project_path(@project) } } +- if Feature.enabled?(:common_repository_blob_header_app, current_user) + #js-repository-blob-header-app{ data: { project_id: @project.id, ref_type: @ref_type.to_s, history_link: project_commits_path(@project, @ref) } } - #js-repo-breadcrumb{ data: breadcrumb_data_attributes } +- else + .tree-ref-container.gl-flex.gl-flex-wrap.gl-gap-2.mb-2.mb-md-0 + .tree-ref-holder.gl-max-w-26{ data: { testid: 'ref-dropdown-container' } } + #js-tree-ref-switcher{ data: { project_id: @project.id, ref_type: @ref_type.to_s, project_root_path: project_path(@project) } } -#js-blob-controls -.tree-controls - .gl-flex.gl-flex-wrap.gl-gap-3.gl-mb-3.sm:gl-mb-0 - = render_if_exists 'projects/tree/lock_link' - = render 'projects/buttons/compare', project: @project, ref: @ref, root_ref: @repository&.root_ref + #js-repo-breadcrumb{ data: breadcrumb_data_attributes } - #js-tree-history-link{ data: { history_link: project_commits_path(@project, @ref) } } + #js-blob-controls + .tree-controls + .gl-flex.gl-flex-wrap.gl-gap-3.gl-mb-3.sm:gl-mb-0 + = render_if_exists 'projects/tree/lock_link' + = render 'projects/buttons/compare', project: @project, ref: @ref, root_ref: @repository&.root_ref - = render 'projects/find_file_link' - = render 'shared/web_ide_button', blob: nil, css_classes: 'gl-w-full sm:gl-w-auto' + #js-tree-history-link{ data: { history_link: project_commits_path(@project, @ref) } } - .project-code-holder.gl-hidden.sm:gl-inline-block - = render "projects/buttons/code", dropdown_class: 'dropdown-menu-right', ref: @ref + = render 'projects/find_file_link' + = render 'shared/web_ide_button', blob: nil, css_classes: 'gl-w-full sm:gl-w-auto' - .project-code-holder.gl-flex.gl-gap-3{ class: 'sm:!gl-hidden' } - = render 'projects/buttons/download', project: @project, ref: @ref - = render "shared/mobile_clone_panel", ref: @ref + .project-code-holder.gl-hidden.sm:gl-inline-block + = render "projects/buttons/code", dropdown_class: 'dropdown-menu-right', ref: @ref + + .project-code-holder.gl-flex.gl-gap-3{ class: 'sm:!gl-hidden' } + = render 'projects/buttons/download', project: @project, ref: @ref + = render "shared/mobile_clone_panel", ref: @ref diff --git a/spec/frontend/repository/components/header_area_spec.js b/spec/frontend/repository/components/header_area_spec.js new file mode 100644 index 00000000000000..b439fc5a3abf88 --- /dev/null +++ b/spec/frontend/repository/components/header_area_spec.js @@ -0,0 +1,66 @@ +import { shallowMount, RouterLinkStub } from '@vue/test-utils'; +import { GlButton } from '@gitlab/ui'; +import HeaderArea from '~/repository/components/header_area.vue'; +import Breadcrumbs from '~/repository/components/header_area/breadcrumbs.vue'; +import BlobControls from '~/repository/components/header_area/blob_controls.vue'; + +const defaultMockRoute = { + name: 'blobPath', +}; + +describe('HeaderArea', () => { + let wrapper; + + const createComponent = (props = {}) => { + return shallowMount(HeaderArea, { + propsData: { + projectPath: 'test/project', + historyLink: '/history', + refType: 'branch', + ...props, + }, + stubs: { + RouterLink: RouterLinkStub, + }, + mocks: { + $route: { + defaultMockRoute, + params: { + path: '', + }, + meta: { + refType: '', + }, + query: { + ref_type: '', + }, + }, + }, + }); + }; + + it('renders the component', () => { + wrapper = createComponent(); + expect(wrapper.exists()).toBe(true); + }); + + it('renders Breadcrumbs component', () => { + wrapper = createComponent(); + expect(wrapper.findComponent(Breadcrumbs).exists()).toBe(true); + }); + + it('renders BlobControls component with correct props', () => { + wrapper = createComponent({ refType: 'branch' }); + const blobControls = wrapper.findComponent(BlobControls); + expect(blobControls.exists()).toBe(true); + expect(blobControls.props('projectPath')).toBe('test/project'); + expect(blobControls.props('refType')).toBe('branch'); + }); + + it('renders History button with correct href', () => { + wrapper = createComponent(); + const historyButton = wrapper.findComponent(GlButton); + expect(historyButton.exists()).toBe(true); + expect(historyButton.attributes('href')).toContain('/history'); + }); +}); -- GitLab From ece1becc059965da75fc76d2b075f13ccd5d0e3b Mon Sep 17 00:00:00 2001 From: psjakubowska Date: Fri, 4 Oct 2024 10:38:36 +0200 Subject: [PATCH 05/17] Add blob controls to header area --- .../repository/components/header_area/blob_controls.vue | 2 +- app/assets/javascripts/repository/index.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/repository/components/header_area/blob_controls.vue b/app/assets/javascripts/repository/components/header_area/blob_controls.vue index 5f9ce8b7dc61f1..2c5c163f7a8ed6 100644 --- a/app/assets/javascripts/repository/components/header_area/blob_controls.vue +++ b/app/assets/javascripts/repository/components/header_area/blob_controls.vue @@ -20,7 +20,7 @@ import { InternalEvents } from '~/tracking'; import { FIND_FILE_BUTTON_CLICK } from '~/tracking/constants'; import { updateElementsVisibility } from '~/repository/utils/dom'; import blobControlsQuery from '~/repository/queries/blob_controls.query.graphql'; -import { getRefType } from '../utils/ref_type'; +import { getRefType } from '~/repository/utils/ref_type'; export default { i18n: { diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js index 7791c25c4e947a..25cbe7669ce6d0 100644 --- a/app/assets/javascripts/repository/index.js +++ b/app/assets/javascripts/repository/index.js @@ -205,7 +205,7 @@ export default function setupVueRepositoryList() { const headerEl = document.getElementById('js-repository-blob-header-app'); if (headerEl) { - const { historyLink } = headerEl.dataset; + const { historyLink, refType } = headerEl.dataset; // eslint-disable-next-line no-new new Vue({ @@ -215,7 +215,7 @@ export default function setupVueRepositoryList() { return h(HeaderArea, { props: { projectPath, - refType: this.$route.meta.refType || this.$route.query.ref_type, + refType: refType || this.$route.meta.refType || this.$route.query.ref_type, historyLink, }, }); -- GitLab From 70a4033ca1cce3916021f9e2e5231b6454a9c7cc Mon Sep 17 00:00:00 2001 From: psjakubowska Date: Tue, 8 Oct 2024 12:51:39 +0200 Subject: [PATCH 06/17] Add breadcrumbs to header area Provides breadcrumb_data_attributes for Breadcrumbs within new header app. --- .../repository/components/header_area.vue | 41 +++++++++++++++++- app/assets/javascripts/repository/index.js | 43 ++++++++++++++++--- .../projects/tree/_tree_header.html.haml | 2 +- .../repository/components/header_area_spec.js | 21 ++++++++- 4 files changed, 97 insertions(+), 10 deletions(-) diff --git a/app/assets/javascripts/repository/components/header_area.vue b/app/assets/javascripts/repository/components/header_area.vue index a4e17414eb62f6..41a395a97e2130 100644 --- a/app/assets/javascripts/repository/components/header_area.vue +++ b/app/assets/javascripts/repository/components/header_area.vue @@ -11,6 +11,21 @@ export default { Breadcrumbs, BlobControls, }, + inject: [ + 'canCollaborate', + 'canEditTree', + 'canPushCode', + 'originalBranch', + 'selectedBranch', + 'newBranchPath', + 'newTagPath', + 'newBlobPath', + 'forkNewBlobPath', + 'forkNewDirectoryPath', + 'forkUploadBlobPath', + 'uploadPath', + 'newDirPath', + ], props: { // for blob controls projectPath: { @@ -37,14 +52,36 @@ export default { return url.href; }, + getRefType() { + return this.$route.query.ref_type; + }, + currentPath() { + return this.$route.params.path; + }, }, }; diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js index 25cbe7669ce6d0..fca8782091fca9 100644 --- a/app/assets/javascripts/repository/index.js +++ b/app/assets/javascripts/repository/index.js @@ -203,19 +203,54 @@ export default function setupVueRepositoryList() { initRefSwitcher(); initForkInfo(); + router.afterEach(({ params: { path } }) => { + setTitle(path, ref, fullName); + }); + const headerEl = document.getElementById('js-repository-blob-header-app'); if (headerEl) { - const { historyLink, refType } = headerEl.dataset; + const { + historyLink, + refType, + breadcrumbsCanCollaborate, + breadcrumbsCanEditTree, + breadcrumbsCanPushCode, + breadcrumbsSelectedBranch, + breadcrumbsNewBranchPath, + breadcrumbsNewTagPath, + breadcrumbsNewBlobPath, + breadcrumbsForkNewBlobPath, + breadcrumbsForkNewDirectoryPath, + breadcrumbsForkUploadBlobPath, + breadcrumbsUploadPath, + breadcrumbsNewDirPath, + } = headerEl.dataset; // eslint-disable-next-line no-new new Vue({ el: headerEl, + provide: { + canCollaborate: parseBoolean(breadcrumbsCanCollaborate), + canEditTree: parseBoolean(breadcrumbsCanEditTree), + canPushCode: parseBoolean(breadcrumbsCanPushCode), + originalBranch: ref, + selectedBranch: breadcrumbsSelectedBranch, + newBranchPath: breadcrumbsNewBranchPath, + newTagPath: breadcrumbsNewTagPath, + newBlobPath: breadcrumbsNewBlobPath, + forkNewBlobPath: breadcrumbsForkNewBlobPath, + forkNewDirectoryPath: breadcrumbsForkNewDirectoryPath, + forkUploadBlobPath: breadcrumbsForkUploadBlobPath, + uploadPath: breadcrumbsUploadPath, + newDirPath: breadcrumbsNewDirPath, + }, + apolloProvider, router, render(h) { return h(HeaderArea, { props: { projectPath, - refType: refType || this.$route.meta.refType || this.$route.query.ref_type, + refType, historyLink, }, }); @@ -223,10 +258,6 @@ export default function setupVueRepositoryList() { }); } - router.afterEach(({ params: { path } }) => { - setTitle(path, ref, fullName); - }); - const breadcrumbEl = document.getElementById('js-repo-breadcrumb'); if (breadcrumbEl) { diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml index 9678dba1ba964b..de025432671d30 100644 --- a/app/views/projects/tree/_tree_header.html.haml +++ b/app/views/projects/tree/_tree_header.html.haml @@ -1,7 +1,7 @@ - add_page_specific_style 'page_bundles/projects' - if Feature.enabled?(:common_repository_blob_header_app, current_user) - #js-repository-blob-header-app{ data: { project_id: @project.id, ref_type: @ref_type.to_s, history_link: project_commits_path(@project, @ref) } } + #js-repository-blob-header-app{ data: { project_id: @project.id, ref_type: @ref_type.to_s, history_link: project_commits_path(@project, @ref), breadcrumbs: breadcrumb_data_attributes } } - else .tree-ref-container.gl-flex.gl-flex-wrap.gl-gap-2.mb-2.mb-md-0 diff --git a/spec/frontend/repository/components/header_area_spec.js b/spec/frontend/repository/components/header_area_spec.js index b439fc5a3abf88..de30873770a9ac 100644 --- a/spec/frontend/repository/components/header_area_spec.js +++ b/spec/frontend/repository/components/header_area_spec.js @@ -8,11 +8,30 @@ const defaultMockRoute = { name: 'blobPath', }; +const defaultProvided = { + canCollaborate: true, + canEditTree: true, + canPushCode: true, + originalBranch: 'main', + selectedBranch: 'feature/new-ui', + newBranchPath: '/project/new-branch', + newTagPath: '/project/new-tag', + newBlobPath: '/project/new-file', + forkNewBlobPath: '/project/fork/new-file', + forkNewDirectoryPath: '/project/fork/new-directory', + forkUploadBlobPath: '/project/fork/upload', + uploadPath: '/project/upload', + newDirPath: '/project/new-directory', +}; + describe('HeaderArea', () => { let wrapper; const createComponent = (props = {}) => { return shallowMount(HeaderArea, { + provide: { + ...defaultProvided, + }, propsData: { projectPath: 'test/project', historyLink: '/history', @@ -54,7 +73,7 @@ describe('HeaderArea', () => { const blobControls = wrapper.findComponent(BlobControls); expect(blobControls.exists()).toBe(true); expect(blobControls.props('projectPath')).toBe('test/project'); - expect(blobControls.props('refType')).toBe('branch'); + expect(blobControls.props('refType')).toBe(''); }); it('renders History button with correct href', () => { -- GitLab From 11528aa463da2c400842c5129e2164c70a73757f Mon Sep 17 00:00:00 2001 From: psjakubowska Date: Wed, 9 Oct 2024 15:29:03 +0200 Subject: [PATCH 07/17] Add RefSelector component Recreates RefSelector for repository within the new header app. --- .../repository/components/header_area.vue | 32 ++++++++++++++++++- app/assets/javascripts/repository/index.js | 9 +++++- .../projects/tree/_tree_header.html.haml | 2 +- .../repository/components/header_area_spec.js | 15 +++++++-- 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/repository/components/header_area.vue b/app/assets/javascripts/repository/components/header_area.vue index 41a395a97e2130..89f306bd613b43 100644 --- a/app/assets/javascripts/repository/components/header_area.vue +++ b/app/assets/javascripts/repository/components/header_area.vue @@ -1,6 +1,8 @@