diff --git a/.gitlab/lint/unused_helper_methods/potential_methods_to_remove.yml b/.gitlab/lint/unused_helper_methods/potential_methods_to_remove.yml index 5ce9a44108f..01eb364bbd9 100644 --- a/.gitlab/lint/unused_helper_methods/potential_methods_to_remove.yml +++ b/.gitlab/lint/unused_helper_methods/potential_methods_to_remove.yml @@ -51,8 +51,6 @@ text_color_for_bg: file: app/helpers/labels_helper.rb manage_labels_title: file: app/helpers/labels_helper.rb -show_projects?: - file: app/helpers/projects_helper.rb request_access_group_members_path: file: app/helpers/routing/groups/members_helper.rb approve_access_request_group_member_path: diff --git a/app/assets/javascripts/ci/ci_environments_dropdown/ci_environments_dropdown.vue b/app/assets/javascripts/ci/ci_environments_dropdown/ci_environments_dropdown.vue index dc6cefb537f..11fa8793ad2 100644 --- a/app/assets/javascripts/ci/ci_environments_dropdown/ci_environments_dropdown.vue +++ b/app/assets/javascripts/ci/ci_environments_dropdown/ci_environments_dropdown.vue @@ -73,8 +73,12 @@ export default { }; }, computed: { - composedCreateButtonLabel() { - return sprintf(__('Create wildcard: %{searchTerm}'), { searchTerm: this.searchTerm }); + composedCreateScopeButtonLabel() { + const label = this.searchTerm?.includes('*') + ? __('Create wildcard: %{searchTerm}') + : s__('CiVariable|Create environment scope: %{searchTerm}'); + + return sprintf(label, { searchTerm: this.searchTerm }); }, environmentScopeLabel() { return convertEnvironmentScope(this.selectedEnvironmentScope); @@ -108,15 +112,12 @@ export default { text: environment, })); }, - shouldRenderCreateButton() { - if (!this.canCreateWildcard) { + shouldRenderCreateScopeButton() { + if (!this.canCreateWildcard || !this.searchTerm) { return false; } - return ( - this.searchTerm?.includes('*') && - ![...this.environments, this.customEnvScope].includes(this.searchTerm) - ); + return ![...this.environments, this.customEnvScope].includes(this.searchTerm); }, shouldRenderDivider() { return !this.areEnvironmentsLoading; @@ -174,14 +175,14 @@ export default { {{ $options.i18n.searchQueryNote }} -
+
- {{ composedCreateButtonLabel }} + {{ composedCreateScopeButtonLabel }}
diff --git a/app/assets/javascripts/environments/environment_details/environment_breadcrumbs.vue b/app/assets/javascripts/environments/environment_details/environment_breadcrumbs.vue index 766cce3be05..f817f7faac3 100644 --- a/app/assets/javascripts/environments/environment_details/environment_breadcrumbs.vue +++ b/app/assets/javascripts/environments/environment_details/environment_breadcrumbs.vue @@ -7,9 +7,8 @@ export default { }, props: { staticBreadcrumbs: { - type: Object, - required: false, - default: () => ({ items: [] }), + type: Array, + required: true, }, }, computed: { @@ -37,7 +36,7 @@ export default { if (!this.isLoaded) { return []; } - const breadCrumbs = [...this.staticBreadcrumbs.items, this.rootRoute]; + const breadCrumbs = [...this.staticBreadcrumbs, this.rootRoute]; if (!this.isRootRoute) { breadCrumbs.push(this.logsRoute); diff --git a/app/assets/javascripts/environments/mount_show.js b/app/assets/javascripts/environments/mount_show.js index d08f4c1771f..6be199bce13 100644 --- a/app/assets/javascripts/environments/mount_show.js +++ b/app/assets/javascripts/environments/mount_show.js @@ -109,7 +109,7 @@ export const initPage = async () => { }, }); - injectVueAppBreadcrumbs(router, EnvironmentBreadcrumbs, null, {}, { singleNavOptIn: true }); + injectVueAppBreadcrumbs(router, EnvironmentBreadcrumbs); return new Vue({ el, diff --git a/app/assets/javascripts/lib/utils/breadcrumbs.js b/app/assets/javascripts/lib/utils/breadcrumbs.js index 70a03b27b91..fd01582280e 100644 --- a/app/assets/javascripts/lib/utils/breadcrumbs.js +++ b/app/assets/javascripts/lib/utils/breadcrumbs.js @@ -7,11 +7,6 @@ export const injectVueAppBreadcrumbs = ( BreadcrumbsComponent, apolloProvider = null, provide = {}, - // this is intended to be a temporary option. Once all uses of - // injectVueAppBreadcrumbs use it, the option should be removed and its - // behavior should be the default. - // Cf. https://gitlab.com/gitlab-org/gitlab/-/merge_requests/186906 - { singleNavOptIn = false } = {}, // eslint-disable-next-line max-params ) => { const injectBreadcrumbEl = document.querySelector('#js-injected-page-breadcrumbs'); @@ -20,22 +15,9 @@ export const injectVueAppBreadcrumbs = ( return false; } - if (singleNavOptIn) { - destroySuperSidebarBreadcrumbs(); - // After singleNavOptIn is turned on for all Vue apps, we can stop - // changing the content of staticBreadcrumbs and instead pass a mutated - // copy of it to the CustomBreadcrumbsRoot component. For now, we need - // to conditionally mutate the staticBreadcrumbs object so that the last - // breadcrumb is hidden for Vue apps that have not opted in to the - // singleNavOptIn. - // Cf. https://gitlab.com/gitlab-org/gitlab/-/merge_requests/186906 - staticBreadcrumbs.items = staticBreadcrumbs.items.slice(0, -1); - } else { - // Hide the last of the static breadcrumbs by nulling its values. - // This way, the separator "/" stays visible and also the new "last" static item isn't displayed in bold font. - staticBreadcrumbs.items[staticBreadcrumbs.items.length - 1].text = ''; - staticBreadcrumbs.items[staticBreadcrumbs.items.length - 1].href = ''; - } + destroySuperSidebarBreadcrumbs(); + + const { items } = staticBreadcrumbs; return new Vue({ el: injectBreadcrumbEl, @@ -47,7 +29,9 @@ export const injectVueAppBreadcrumbs = ( return createElement(BreadcrumbsComponent, { class: injectBreadcrumbEl.className, props: { - staticBreadcrumbs, + // The last item from the static breadcrumb set is replaced by the + // root of the vue app, so the last item should be removed + staticBreadcrumbs: items.slice(0, -1), }, }); }, diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js index 2edef1c6a94..ca5327c864b 100644 --- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js +++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js @@ -92,14 +92,7 @@ export default () => { }); return { - attachBreadcrumb: () => - injectVueAppBreadcrumbs( - router, - RegistryBreadcrumb, - apolloProvider, - {}, - { singleNavOptIn: true }, - ), + attachBreadcrumb: () => injectVueAppBreadcrumbs(router, RegistryBreadcrumb, apolloProvider), attachMainComponent, }; }; diff --git a/app/assets/javascripts/packages_and_registries/harbor_registry/components/harbor_registry_breadcrumb.vue b/app/assets/javascripts/packages_and_registries/harbor_registry/components/harbor_registry_breadcrumb.vue index fae705a16e9..df11054a67b 100644 --- a/app/assets/javascripts/packages_and_registries/harbor_registry/components/harbor_registry_breadcrumb.vue +++ b/app/assets/javascripts/packages_and_registries/harbor_registry/components/harbor_registry_breadcrumb.vue @@ -11,9 +11,8 @@ export default { }, props: { staticBreadcrumbs: { - type: Object, - default: () => ({ items: [] }), - required: false, + type: Array, + required: true, }, }, computed: { @@ -42,9 +41,7 @@ export default { }); } - const staticCrumbs = this.staticBreadcrumbs.items; - - return [...staticCrumbs, ...routeInfoList]; + return [...this.staticBreadcrumbs, ...routeInfoList]; }, isLoaded() { return this.isRootRoute || last(this.currentRoute).text; @@ -59,9 +56,8 @@ export default { if (!this.isRootRoute) { crumbs = crumbs.concat(this.currentRoute); } - const staticCrumbs = this.staticBreadcrumbs.items; - return [...staticCrumbs, ...crumbs]; + return [...this.staticBreadcrumbs, ...crumbs]; }, }, }; diff --git a/app/assets/javascripts/packages_and_registries/harbor_registry/index.js b/app/assets/javascripts/packages_and_registries/harbor_registry/index.js index d3815da2e00..18187a5c5ff 100644 --- a/app/assets/javascripts/packages_and_registries/harbor_registry/index.js +++ b/app/assets/javascripts/packages_and_registries/harbor_registry/index.js @@ -77,17 +77,7 @@ export default (id) => { }; return { - attachBreadcrumb: () => - injectVueAppBreadcrumbs( - router, - RegistryBreadcrumb, - null, - {}, - { - // cf. https://gitlab.com/gitlab-org/gitlab/-/merge_requests/186906 - singleNavOptIn: true, - }, - ), + attachBreadcrumb: () => injectVueAppBreadcrumbs(router, RegistryBreadcrumb), attachMainComponent, }; }; diff --git a/app/assets/javascripts/packages_and_registries/package_registry/index.js b/app/assets/javascripts/packages_and_registries/package_registry/index.js index 2c8e93924b7..cbd781532f8 100644 --- a/app/assets/javascripts/packages_and_registries/package_registry/index.js +++ b/app/assets/javascripts/packages_and_registries/package_registry/index.js @@ -51,14 +51,7 @@ export default () => { }); return { - attachBreadcrumb: () => - injectVueAppBreadcrumbs( - router, - RegistryBreadcrumb, - apolloProvider, - {}, - { singleNavOptIn: true }, - ), + attachBreadcrumb: () => injectVueAppBreadcrumbs(router, RegistryBreadcrumb, apolloProvider), attachMainComponent, }; }; diff --git a/app/assets/javascripts/packages_and_registries/shared/components/registry_breadcrumb.vue b/app/assets/javascripts/packages_and_registries/shared/components/registry_breadcrumb.vue index b2955ba515e..56c626f5a81 100644 --- a/app/assets/javascripts/packages_and_registries/shared/components/registry_breadcrumb.vue +++ b/app/assets/javascripts/packages_and_registries/shared/components/registry_breadcrumb.vue @@ -11,9 +11,8 @@ export default { }, props: { staticBreadcrumbs: { - type: Object, - required: false, - default: () => ({ items: [] }), + type: Array, + required: true, }, }, computed: { @@ -34,7 +33,7 @@ export default { }, allCrumbs() { const crumbs = [ - ...this.staticBreadcrumbs.items, + ...this.staticBreadcrumbs, { text: this.rootRoute.meta.nameGenerator(), to: this.rootRoute.path, diff --git a/app/assets/javascripts/token_access/components/inbound_token_access.vue b/app/assets/javascripts/token_access/components/inbound_token_access.vue index c0cf55e93b8..12426c063d7 100644 --- a/app/assets/javascripts/token_access/components/inbound_token_access.vue +++ b/app/assets/javascripts/token_access/components/inbound_token_access.vue @@ -142,8 +142,10 @@ export default { groups = this.mapAllowlistNodes(allowlist?.groupsAllowlist); projects = this.mapAllowlistNodes(allowlist?.projectsAllowlist); // Add a dummy entry for the current project. The new ciJobTokenScopeAllowlist endpoint doesn't have an entry - // for the current project like the old ciJobTokenScope endpoint did, so we have to add it in manually. - projects.push({ ...project, defaultPermissions: true, jobTokenPolicies: [] }); + // for the current project like the old ciJobTokenScope endpoint did, so we have to add it in manually, if it + // doesn't exist yet. + if (!projects.some(({ id }) => id === project.id)) + projects.push({ ...project, defaultPermissions: true, jobTokenPolicies: [] }); } else { projects = project?.ciJobTokenScope?.inboundAllowlist?.nodes ?? []; groups = project?.ciJobTokenScope?.groupsAllowlist?.nodes ?? []; @@ -211,7 +213,7 @@ export default { }, allowlist() { const { groups, projects } = this.groupsAndProjectsWithAccess; - return [...groups, ...projects]; + return [...groups, ...projects].sort((a, b) => a.fullPath.localeCompare(b.fullPath)); }, disclosureDropdownOptions() { return [ diff --git a/app/assets/javascripts/token_access/components/token_access_table.vue b/app/assets/javascripts/token_access/components/token_access_table.vue index c29da091aa5..5e761a408dc 100644 --- a/app/assets/javascripts/token_access/components/token_access_table.vue +++ b/app/assets/javascripts/token_access/components/token_access_table.vue @@ -1,5 +1,6 @@ @@ -136,6 +135,9 @@ export default { class="gl-ml-3 gl-shrink-0" data-testid="autopopulated-icon" /> + {{ + __('Current project') + }}
@@ -159,7 +161,7 @@ export default {