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 {