diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml
index 6500140a981..b62dad6633b 100644
--- a/.rubocop_todo/layout/line_length.yml
+++ b/.rubocop_todo/layout/line_length.yml
@@ -526,7 +526,6 @@ Layout/LineLength:
- 'ee/app/helpers/ee/notes_helper.rb'
- 'ee/app/helpers/ee/profiles_helper.rb'
- 'ee/app/helpers/ee/subscribable_banner_helper.rb'
- - 'ee/app/helpers/epics_helper.rb'
- 'ee/app/helpers/gitlab_subscriptions/upcoming_reconciliation_helper.rb'
- 'ee/app/helpers/license_helper.rb'
- 'ee/app/helpers/projects/on_demand_scans_helper.rb'
@@ -1222,7 +1221,6 @@ Layout/LineLength:
- 'ee/spec/lib/gitlab/custom_file_templates_spec.rb'
- 'ee/spec/lib/gitlab/data_builder/vulnerability_spec.rb'
- 'ee/spec/lib/gitlab/elastic/group_search_results_spec.rb'
- - 'ee/spec/lib/gitlab/elastic/snippet_search_results_spec.rb'
- 'ee/spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- 'ee/spec/lib/gitlab/expiring_subscription_message_spec.rb'
- 'ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb'
diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml
index 25e2ab5889c..cfeded17d92 100644
--- a/.rubocop_todo/rspec/context_wording.yml
+++ b/.rubocop_todo/rspec/context_wording.yml
@@ -318,7 +318,6 @@ RSpec/ContextWording:
- 'ee/spec/lib/gitlab/code_owners/users_loader_spec.rb'
- 'ee/spec/lib/gitlab/custom_file_templates_spec.rb'
- 'ee/spec/lib/gitlab/elastic/group_search_results_spec.rb'
- - 'ee/spec/lib/gitlab/elastic/snippet_search_results_spec.rb'
- 'ee/spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- 'ee/spec/lib/gitlab/expiring_subscription_message_spec.rb'
- 'ee/spec/lib/gitlab/geo/cron_manager_spec.rb'
diff --git a/.rubocop_todo/rspec/feature_category.yml b/.rubocop_todo/rspec/feature_category.yml
index c0a332598fe..80fc13c77f5 100644
--- a/.rubocop_todo/rspec/feature_category.yml
+++ b/.rubocop_todo/rspec/feature_category.yml
@@ -553,7 +553,6 @@ RSpec/FeatureCategory:
- 'ee/spec/lib/gitlab/custom_file_templates_spec.rb'
- 'ee/spec/lib/gitlab/customers_dot/jwt_spec.rb'
- 'ee/spec/lib/gitlab/elastic/elasticsearch_enabled_cache_spec.rb'
- - 'ee/spec/lib/gitlab/elastic/snippet_search_results_spec.rb'
- 'ee/spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- 'ee/spec/lib/gitlab/expiring_subscription_message_spec.rb'
- 'ee/spec/lib/gitlab/favicon_spec.rb'
diff --git a/.rubocop_todo/rspec/named_subject.yml b/.rubocop_todo/rspec/named_subject.yml
index 562406de9f5..50707eaa5bd 100644
--- a/.rubocop_todo/rspec/named_subject.yml
+++ b/.rubocop_todo/rspec/named_subject.yml
@@ -273,7 +273,6 @@ RSpec/NamedSubject:
- 'ee/spec/lib/ee/sidebars/projects/menus/security_compliance_menu_spec.rb'
- 'ee/spec/lib/ee/sidebars/projects/menus/settings_menu_spec.rb'
- 'ee/spec/lib/elastic/latest/application_instance_proxy_spec.rb'
- - 'ee/spec/lib/elastic/latest/epic_class_proxy_spec.rb'
- 'ee/spec/lib/elastic/latest/epic_instance_proxy_spec.rb'
- 'ee/spec/lib/elastic/latest/git_instance_proxy_spec.rb'
- 'ee/spec/lib/elastic/latest/routing_spec.rb'
diff --git a/app/assets/javascripts/admin/groups/index/constants.js b/app/assets/javascripts/admin/groups/index/constants.js
index 166d92cd1c9..0806de5174b 100644
--- a/app/assets/javascripts/admin/groups/index/constants.js
+++ b/app/assets/javascripts/admin/groups/index/constants.js
@@ -1,4 +1,5 @@
-import { __ } from '~/locale';
+import groupsEmptyStateIllustration from '@gitlab/svgs/dist/illustrations/empty-state/empty-groups-md.svg?url';
+import { s__, __ } from '~/locale';
import {
SORT_LABEL_NAME,
SORT_LABEL_CREATED,
@@ -7,6 +8,7 @@ import {
} from '~/groups_projects/constants';
import GroupsList from '~/vue_shared/components/groups_list/groups_list.vue';
import { formatGraphQLGroups } from '~/vue_shared/components/groups_list/formatter';
+import ResourceListsEmptyState from '~/vue_shared/components/resource_lists/empty_state.vue';
import adminGroupsQuery from './graphql/queries/groups.query.graphql';
const baseTab = {
@@ -24,6 +26,7 @@ const baseTab = {
listItemClass: 'gl-px-5',
showGroupIcon: true,
},
+ emptyStateComponent: ResourceListsEmptyState,
query: adminGroupsQuery,
queryPath: 'groups',
};
@@ -34,6 +37,14 @@ export const ACTIVE_TAB = {
value: 'active',
variables: { active: true },
countsQueryPath: 'active',
+ emptyStateComponentProps: {
+ svgPath: groupsEmptyStateIllustration,
+ title: s__("Groups|You don't have any active groups yet."),
+ description: s__(
+ 'Organization|A group is a collection of several projects. If you organize your projects under a group, it works like a folder.',
+ ),
+ 'data-testid': 'groups-empty-state',
+ },
};
export const INACTIVE_TAB = {
@@ -42,6 +53,11 @@ export const INACTIVE_TAB = {
value: 'inactive',
variables: { active: false },
countsQueryPath: 'inactive',
+ emptyStateComponentProps: {
+ svgPath: groupsEmptyStateIllustration,
+ title: s__("Groups|You don't have any inactive groups."),
+ description: s__('Groups|Groups that are archived or pending deletion will appear here.'),
+ },
};
export const SORT_OPTION_NAME = {
diff --git a/app/assets/javascripts/ci/runner/components/runner_create_wizard.vue b/app/assets/javascripts/ci/runner/components/runner_create_wizard.vue
index 7ad66f394fa..2eeece2b639 100644
--- a/app/assets/javascripts/ci/runner/components/runner_create_wizard.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_create_wizard.vue
@@ -2,12 +2,14 @@
import { RUNNER_TYPES } from '../constants';
import RequiredFields from './runner_create_wizard_required_fields.vue';
import OptionalFields from './runner_create_wizard_optional_fields.vue';
+import RunnerRegistration from './runner_create_wizard_registration.vue';
export default {
name: 'RunnerCreateWizard',
components: {
RequiredFields,
OptionalFields,
+ RunnerRegistration,
},
props: {
runnerType: {
@@ -58,4 +60,9 @@ export default {
@next="onNext"
@back="onBack"
/>
+
diff --git a/app/assets/javascripts/ci/runner/components/runner_create_wizard_optional_fields.vue b/app/assets/javascripts/ci/runner/components/runner_create_wizard_optional_fields.vue
index dcc19771042..aa797e9e14e 100644
--- a/app/assets/javascripts/ci/runner/components/runner_create_wizard_optional_fields.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_create_wizard_optional_fields.vue
@@ -1,12 +1,19 @@
-
+
@@ -143,12 +213,12 @@ export default {
-
{{ __('Next step') }}
diff --git a/app/assets/javascripts/ci/runner/components/runner_create_wizard_registration.vue b/app/assets/javascripts/ci/runner/components/runner_create_wizard_registration.vue
new file mode 100644
index 00000000000..fea81a4a068
--- /dev/null
+++ b/app/assets/javascripts/ci/runner/components/runner_create_wizard_registration.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+ {{ s__('Runners|View runners') }}
+
+
+
+
diff --git a/app/assets/javascripts/content_editor/components/bubble_menus/link_bubble_menu.vue b/app/assets/javascripts/content_editor/components/bubble_menus/link_bubble_menu.vue
index 7a1567b9249..c4b696a235f 100644
--- a/app/assets/javascripts/content_editor/components/bubble_menus/link_bubble_menu.vue
+++ b/app/assets/javascripts/content_editor/components/bubble_menus/link_bubble_menu.vue
@@ -11,6 +11,7 @@ import {
GlTooltipDirective as GlTooltip,
} from '@gitlab/ui';
import { getMarkType, getMarkRange } from '@tiptap/core';
+import { joinPaths } from '~/lib/utils/url_utility';
import Link from '../../extensions/link';
import EditorStateObserver from '../editor_state_observer.vue';
import BubbleMenu from './bubble_menu.vue';
@@ -167,7 +168,11 @@ export default {
},
copyLinkHref() {
- navigator.clipboard.writeText(this.linkCanonicalSrc);
+ const fullUrl = this.linkCanonicalSrc.startsWith('http')
+ ? this.linkCanonicalSrc
+ : joinPaths(gon.gitlab_url, this.linkHref);
+
+ navigator.clipboard.writeText(fullUrl);
},
removeLink() {
diff --git a/app/assets/javascripts/rapid_diffs/options_menu/adapter.js b/app/assets/javascripts/rapid_diffs/options_menu/adapter.js
index de809a6e594..798fb1156a4 100644
--- a/app/assets/javascripts/rapid_diffs/options_menu/adapter.js
+++ b/app/assets/javascripts/rapid_diffs/options_menu/adapter.js
@@ -10,6 +10,7 @@ export const OptionsMenuAdapter = {
clicks: {
toggleOptionsMenu(event, button) {
const menuContainer = this.diffElement.querySelector('[data-options-menu]');
+ if (!menuContainer) return;
const items = getMenuItems(menuContainer);
// eslint-disable-next-line no-new
new Vue({
diff --git a/app/assets/javascripts/security_configuration/components/pipeline_secret_detection_feature_card.vue b/app/assets/javascripts/security_configuration/components/pipeline_secret_detection_feature_card.vue
index f562d83dff6..e6aea00a19d 100644
--- a/app/assets/javascripts/security_configuration/components/pipeline_secret_detection_feature_card.vue
+++ b/app/assets/javascripts/security_configuration/components/pipeline_secret_detection_feature_card.vue
@@ -1,5 +1,5 @@