From fdc26e021b1e3eea4161bf6891f3a151fb7414b0 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 11 May 2022 21:08:09 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- .eslintrc.yml | 2 + .rubocop_todo/database/multiple_databases.yml | 10 +- .../javascripts/behaviors/markdown/render_kroki.js | 4 +- .../javascripts/behaviors/markdown/render_math.js | 4 +- .../blob/blob_line_permalink_updater.js | 5 +- app/assets/javascripts/blob/viewer/index.js | 17 +-- app/assets/javascripts/breadcrumb.js | 2 +- .../javascripts/code_navigation/utils/index.js | 4 +- .../deprecated_jquery_dropdown/render.js | 8 +- app/assets/javascripts/diff.js | 2 +- .../filtered_search/available_dropdown_mappings.js | 4 +- .../javascripts/filtered_search/dropdown_hint.js | 4 +- .../filtered_search/dropdown_operator.js | 2 +- .../javascripts/filtered_search/dropdown_user.js | 4 +- .../javascripts/filtered_search/dropdown_utils.js | 2 + .../filtered_search/droplab/drop_down.js | 4 +- .../filtered_search/filtered_search_manager.js | 2 +- .../javascripts/image_diff/helpers/dom_helper.js | 2 +- .../issues/create_merge_request_dropdown.js | 5 +- .../issues/show/components/description.vue | 2 +- app/assets/javascripts/lazy_loader.js | 9 +- .../confirm_via_gl_modal/confirm_via_gl_modal.js | 2 +- .../members/components/table/role_dropdown.vue | 2 +- .../javascripts/pages/registrations/new/index.js | 5 + .../pages/shared/nav/sidebar_tracking.js | 10 +- .../javascripts/pages/users/activity_calendar.js | 2 +- .../header/pipeline_editor_mini_graph.vue | 18 ++-- .../pipelines_list/pipeline_mini_graph.vue | 2 +- .../components/pipelines_list/pipeline_stage.vue | 25 ++--- .../components/pipelines_list/pipelines_table.vue | 3 +- .../components/commit_box_pipeline_mini_graph.vue | 8 +- .../projects/commits/components/author_select.vue | 2 +- app/assets/javascripts/sidebar/mount_sidebar.js | 4 +- app/assets/javascripts/terraform/index.js | 2 +- .../components/mr_widget_pipeline.vue | 5 +- .../javascripts/vue_shared/components/ci_icon.vue | 33 ++++-- .../javascripts/whats_new/components/app.vue | 2 +- .../javascripts/whats_new/utils/notification.js | 2 +- .../bootstrap_migration_components.scss | 9 +- app/assets/stylesheets/framework/icons.scss | 72 ++++++++++++- app/assets/stylesheets/framework/wells.scss | 2 +- .../stylesheets/page_bundles/_pipeline_mixins.scss | 99 ------------------ .../stylesheets/page_bundles/merge_requests.scss | 4 - app/assets/stylesheets/page_bundles/pipelines.scss | 65 ++---------- app/assets/stylesheets/pages/commits.scss | 5 - app/finders/error_tracking/errors_finder.rb | 46 -------- app/graphql/types/ci/runner_status_enum.rb | 7 +- app/graphql/types/work_item_type.rb | 3 +- app/helpers/ci/runners_helper.rb | 2 +- app/models/ci/build.rb | 1 + app/models/ci/namespace_settings.rb | 19 ++++ app/models/ci/runner.rb | 6 +- app/models/issue.rb | 14 +-- app/models/namespace.rb | 1 + app/models/namespace_ci_cd_setting.rb | 2 + app/models/project.rb | 1 - app/services/error_tracking/base_service.rb | 10 ++ .../error_tracking/collect_error_service.rb | 26 ++--- .../error_tracking/issue_details_service.rb | 11 +- .../error_tracking/issue_latest_event_service.rb | 13 ++- .../error_tracking/issue_update_service.rb | 6 +- app/services/error_tracking/list_issues_service.rb | 16 +-- .../_merge_request_merge_method_settings.html.haml | 2 +- config/application.rb | 2 + .../development/enhanced_notify_css.yml | 4 +- .../ops/ci_runner_separation_by_plan.yml | 8 ++ config/gitlab.yml.example | 4 + config/initializers/1_settings.rb | 3 + ...5-0-runner-api-status-renames-not_connected.yml | 16 +++ ...220421141342_add_allowed_plans_to_ci_runners.rb | 9 ++ ...er_pruning_index_to_namespace_ci_cd_settings.rb | 18 ++++ ...move_not_null_constraint_from_work_item_type.rb | 16 +++ db/schema_migrations/20220421141342 | 1 + db/schema_migrations/20220505092254 | 1 + db/schema_migrations/20220511152439 | 1 + db/structure.sql | 6 +- doc/.vale/gitlab/spelling-exceptions.txt | 23 ++++ doc/administration/configure.md | 2 +- .../runbooks/planned_failover_single_node.md | 2 +- .../reference_architectures/10k_users.md | 4 +- .../reference_architectures/25k_users.md | 4 +- .../reference_architectures/2k_users.md | 4 +- .../reference_architectures/3k_users.md | 4 +- .../reference_architectures/50k_users.md | 4 +- .../reference_architectures/5k_users.md | 4 +- .../reference_architectures/index.md | 2 +- .../troubleshooting/diagnostics_tools.md | 2 +- .../troubleshooting/gitlab_rails_cheat_sheet.md | 2 +- doc/administration/troubleshooting/log_parsing.md | 2 +- doc/api/graphql/reference/index.md | 3 +- doc/api/members.md | 29 ++++++ doc/api/runners.md | 18 ++-- .../blueprints/database_scaling/size-limits.md | 2 +- doc/ci/yaml/workflow.md | 10 +- doc/development/application_slis/index.md | 2 +- doc/development/audit_event_guide/index.md | 2 +- .../database/batched_background_migrations.md | 2 +- doc/development/database/loose_foreign_keys.md | 6 +- doc/development/documentation/testing.md | 2 +- doc/development/fe_guide/registry_architecture.md | 2 +- doc/development/foreign_keys.md | 4 + doc/development/go_guide/go_upgrade.md | 2 +- doc/development/performance.md | 2 +- doc/development/pipelines.md | 2 +- doc/development/redis/new_redis_instance.md | 4 +- doc/development/ruby_upgrade.md | 2 +- doc/development/snowplow/troubleshooting.md | 2 +- doc/install/aws/gitlab_hybrid_on_aws.md | 12 +-- doc/install/aws/index.md | 2 +- doc/operations/feature_flags.md | 2 +- doc/update/index.md | 2 +- doc/update/removals.md | 14 +++ .../secret_detection/post_processing.md | 2 +- doc/user/clusters/agent/install/index.md | 10 +- doc/user/group/saml_sso/index.md | 2 +- doc/user/packages/container_registry/index.md | 2 +- doc/user/profile/notifications.md | 4 + .../project/merge_requests/approvals/settings.md | 2 +- .../project/merge_requests/fast_forward_merge.md | 77 ++------------ .../merge_requests/img/merge_method_ff_v15_0.png | Bin 0 -> 4744 bytes .../img/merge_method_merge_commit_v15_0.png | Bin 0 -> 14531 bytes ...merge_commit_with_semi_linear_history_v15_0.png | Bin 0 -> 14867 bytes doc/user/project/merge_requests/methods/index.md | 116 +++++++++++++++++++++ doc/user/project/merge_requests/revert_changes.md | 2 +- doc/user/project/merge_requests/reviews/index.md | 17 +-- .../project/merge_requests/squash_and_merge.md | 6 +- doc/user/project/releases/index.md | 2 +- doc/user/project/settings/index.md | 2 +- lib/api/error_tracking/collector.rb | 2 +- .../Security/DAST-On-Demand-Scan.gitlab-ci.yml | 2 +- .../ci/templates/Security/DAST.gitlab-ci.yml | 2 +- .../templates/Security/DAST.latest.gitlab-ci.yml | 2 +- lib/gitlab/error_tracking/error_repository.rb | 113 ++++++++++++++++++++ .../error_repository/active_record_strategy.rb | 98 +++++++++++++++++ .../github_import/importer/issue_importer.rb | 3 +- locale/gitlab.pot | 14 +-- rubocop/cop/database/multiple_databases.rb | 1 + spec/factories/namespace_ci_cd_settings.rb | 7 ++ .../user_sees_mini_pipeline_graph_spec.rb | 43 -------- .../projects/commit/mini_pipeline_graph_spec.rb | 2 +- spec/finders/error_tracking/errors_finder_spec.rb | 53 ---------- .../__helpers__/init_vue_mr_page_helper.js | 18 ++-- .../__helpers__/matchers/to_have_sprite_icon.js | 2 +- spec/frontend/access_tokens/index_spec.js | 2 +- spec/frontend/admin/users/index_spec.js | 8 +- .../authentication/two_factor_auth/index_spec.js | 4 +- .../blob/components/table_contents_spec.js | 4 +- spec/frontend/blob/viewer/index_spec.js | 6 +- .../components/lock_popovers_spec.js | 10 +- .../frontend/code_navigation/store/actions_spec.js | 12 +-- spec/frontend/confirm_modal_spec.js | 6 +- spec/frontend/helpers/startup_css_helper_spec.js | 7 +- .../issues/create_merge_request_dropdown_spec.js | 4 +- spec/frontend/labels/delete_label_modal_spec.js | 6 +- spec/frontend/lazy_loader_spec.js | 4 +- spec/frontend/lib/utils/datetime_utility_spec.js | 4 +- spec/frontend/members/index_spec.js | 2 +- spec/frontend/members/utils_spec.js | 2 +- spec/frontend/notebook/cells/markdown_spec.js | 4 +- spec/frontend/notes/stores/actions_spec.js | 10 +- spec/frontend/performance_bar/index_spec.js | 10 +- .../pipelines_list/pipeline_stage_spec.js | 6 +- spec/frontend/search_autocomplete_spec.js | 2 +- spec/frontend/user_popovers_spec.js | 2 +- spec/frontend/users_select/test_helper.js | 8 +- .../components/states/mr_widget_merged_spec.js | 4 +- .../vue_mr_widget/mr_widget_options_spec.js | 2 +- .../frontend_integration/ide/helpers/ide_helper.js | 4 +- spec/lib/gitlab/database/migration_helpers_spec.rb | 28 +++-- .../github_import/importer/issue_importer_spec.rb | 6 +- .../markdown_cache/active_record/extension_spec.rb | 2 - spec/models/ci/build_spec.rb | 29 ++++-- spec/models/ci/processable_spec.rb | 2 +- spec/models/ci/runner_spec.rb | 4 +- spec/models/concerns/cache_markdown_field_spec.rb | 2 - .../concerns/pg_full_text_searchable_spec.rb | 4 - spec/models/issue_spec.rb | 15 +-- spec/models/project_spec.rb | 1 - spec/requests/api/ci/runners_spec.rb | 2 +- spec/requests/api/error_tracking/collector_spec.rb | 12 ++- spec/requests/api/graphql/ci/runner_spec.rb | 8 +- spec/requests/api/graphql/ci/runners_spec.rb | 4 +- .../error_tracking/collect_error_service_spec.rb | 15 ++- .../error_tracking/issue_details_service_spec.rb | 12 +++ .../issue_latest_event_service_spec.rb | 12 +++ 185 files changed, 1035 insertions(+), 805 deletions(-) delete mode 100644 app/finders/error_tracking/errors_finder.rb create mode 100644 app/models/ci/namespace_settings.rb create mode 100644 config/feature_flags/ops/ci_runner_separation_by_plan.yml create mode 100644 data/removals/15_0/15-0-runner-api-status-renames-not_connected.yml create mode 100644 db/migrate/20220421141342_add_allowed_plans_to_ci_runners.rb create mode 100644 db/migrate/20220505092254_add_allow_stale_runner_pruning_index_to_namespace_ci_cd_settings.rb create mode 100644 db/post_migrate/20220511152439_remove_not_null_constraint_from_work_item_type.rb create mode 100644 db/schema_migrations/20220421141342 create mode 100644 db/schema_migrations/20220505092254 create mode 100644 db/schema_migrations/20220511152439 create mode 100644 doc/user/project/merge_requests/img/merge_method_ff_v15_0.png create mode 100644 doc/user/project/merge_requests/img/merge_method_merge_commit_v15_0.png create mode 100644 doc/user/project/merge_requests/img/merge_method_merge_commit_with_semi_linear_history_v15_0.png create mode 100644 doc/user/project/merge_requests/methods/index.md create mode 100644 lib/gitlab/error_tracking/error_repository.rb create mode 100644 lib/gitlab/error_tracking/error_repository/active_record_strategy.rb create mode 100644 spec/factories/namespace_ci_cd_settings.rb delete mode 100644 spec/finders/error_tracking/errors_finder_spec.rb diff --git a/.eslintrc.yml b/.eslintrc.yml index d29af93319e..e02d2c02d79 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -108,6 +108,8 @@ rules: message: 'Migrate to GlSkeletonLoader, or import GlDeprecatedSkeletonLoading.' # See https://gitlab.com/gitlab-org/gitlab/-/issues/360551 vue/multi-word-component-names: off + unicorn/prefer-dom-node-dataset: + - error overrides: - files: - '{,ee/,jh/}spec/frontend*/**/*' diff --git a/.rubocop_todo/database/multiple_databases.yml b/.rubocop_todo/database/multiple_databases.yml index 1c63431c4d7..7cc54a5b373 100644 --- a/.rubocop_todo/database/multiple_databases.yml +++ b/.rubocop_todo/database/multiple_databases.yml @@ -1,25 +1,19 @@ --- Database/MultipleDatabases: Exclude: - - 'config/application.rb' - 'config/initializers/active_record_data_types.rb' - - 'config/initializers/active_record_force_reconnects.rb' - 'config/initializers/active_record_lifecycle.rb' - 'config/initializers/sidekiq.rb' - - 'config/initializers/validate_database_config.rb' - 'db/post_migrate/20210317104032_set_iteration_cadence_automatic_to_false.rb' - 'db/post_migrate/20210811122206_update_external_project_bots.rb' - 'db/post_migrate/20210812013042_remove_duplicate_project_authorizations.rb' - - 'ee/lib/tasks/geo.rake' - 'ee/spec/services/ee/merge_requests/update_service_spec.rb' - - 'lib/backup/database.rb' - 'lib/backup/manager.rb' - - lib/gitlab/background_migration/backfill_projects_with_coverage.rb - - lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans.rb + - 'lib/gitlab/background_migration/backfill_projects_with_coverage.rb' + - 'lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans.rb' - 'lib/gitlab/database.rb' - 'lib/gitlab/database/load_balancing/load_balancer.rb' - 'lib/gitlab/database/migrations/observers/query_log.rb' - - 'lib/tasks/dev.rake' - 'lib/tasks/gitlab/db/validate_config.rake' - 'spec/db/schema_spec.rb' - 'spec/initializers/database_config_spec.rb' diff --git a/app/assets/javascripts/behaviors/markdown/render_kroki.js b/app/assets/javascripts/behaviors/markdown/render_kroki.js index abe71694d73..241585c30f1 100644 --- a/app/assets/javascripts/behaviors/markdown/render_kroki.js +++ b/app/assets/javascripts/behaviors/markdown/render_kroki.js @@ -55,8 +55,8 @@ export function renderKroki(krokiImages) { // A single Kroki image is processed multiple times for some reason, // so this condition ensures we only create one alert per Kroki image - if (!parent.hasAttribute('data-kroki-processed')) { - parent.setAttribute('data-kroki-processed', 'true'); + if (!Object.hasOwn(parent.dataset, 'krokiProcessed')) { + parent.dataset.krokiProcessed = 'true'; parent.after(createAlert(krokiImage)); } }); diff --git a/app/assets/javascripts/behaviors/markdown/render_math.js b/app/assets/javascripts/behaviors/markdown/render_math.js index 12f47255bdf..7e1bf83f8a1 100644 --- a/app/assets/javascripts/behaviors/markdown/render_math.js +++ b/app/assets/javascripts/behaviors/markdown/render_math.js @@ -110,7 +110,7 @@ class SafeMathRenderer { try { displayContainer.innerHTML = this.katex.renderToString(text, { - displayMode: el.getAttribute('data-math-style') === 'display', + displayMode: el.dataset.mathStyle === 'display', throwOnError: true, maxSize: 20, maxExpand: 20, @@ -143,7 +143,7 @@ class SafeMathRenderer { this.elements.forEach((el) => { const placeholder = document.createElement('span'); placeholder.style.display = 'none'; - placeholder.setAttribute('data-math-style', el.getAttribute('data-math-style')); + placeholder.dataset.mathStyle = el.dataset.mathStyle; placeholder.textContent = el.textContent; el.parentNode.replaceChild(placeholder, el); this.queue.push(placeholder); diff --git a/app/assets/javascripts/blob/blob_line_permalink_updater.js b/app/assets/javascripts/blob/blob_line_permalink_updater.js index a3dd241604d..0a5bcf326a1 100644 --- a/app/assets/javascripts/blob/blob_line_permalink_updater.js +++ b/app/assets/javascripts/blob/blob_line_permalink_updater.js @@ -9,10 +9,11 @@ const updateLineNumbersOnBlobPermalinks = (linksToUpdate) => { [].concat(Array.prototype.slice.call(linksToUpdate)).forEach((permalinkButton) => { const baseHref = - permalinkButton.getAttribute('data-original-href') || + permalinkButton.dataset.originalHref || (() => { const href = permalinkButton.getAttribute('href'); - permalinkButton.setAttribute('data-original-href', href); + // eslint-disable-next-line no-param-reassign + permalinkButton.dataset.originalHref = href; return href; })(); permalinkButton.setAttribute('href', `${baseHref}${hashUrlString}`); diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js index a6eed4ecae3..a0d4f7ef4f2 100644 --- a/app/assets/javascripts/blob/viewer/index.js +++ b/app/assets/javascripts/blob/viewer/index.js @@ -36,19 +36,19 @@ const loadRichBlobViewer = (type) => { const loadViewer = (viewerParam) => { const viewer = viewerParam; - const url = viewer.getAttribute('data-url'); + const { url } = viewer.dataset; - if (!url || viewer.getAttribute('data-loaded') || viewer.getAttribute('data-loading')) { + if (!url || viewer.dataset.loaded || viewer.dataset.loading) { return Promise.resolve(viewer); } - viewer.setAttribute('data-loading', 'true'); + viewer.dataset.loading = 'true'; return axios.get(url).then(({ data }) => { viewer.innerHTML = data.html; window.requestIdleCallback(() => { - viewer.removeAttribute('data-loading'); + delete viewer.dataset.loading; }); return viewer; @@ -108,7 +108,7 @@ export class BlobViewer { switchToInitialViewer() { const initialViewer = this.$fileHolder[0].querySelector('.blob-viewer:not(.hidden)'); - let initialViewerName = initialViewer.getAttribute('data-type'); + let initialViewerName = initialViewer.dataset.type; if (this.switcher && window.location.hash.indexOf('#L') === 0) { initialViewerName = 'simple'; @@ -138,12 +138,12 @@ export class BlobViewer { e.preventDefault(); - this.switchToViewer(target.getAttribute('data-viewer')); + this.switchToViewer(target.dataset.viewer); } toggleCopyButtonState() { if (!this.copySourceBtn) return; - if (this.simpleViewer.getAttribute('data-loaded')) { + if (this.simpleViewer.dataset.loaded) { this.copySourceBtnTooltip.setAttribute('title', __('Copy file contents')); this.copySourceBtn.classList.remove('disabled'); } else if (this.activeViewer === this.simpleViewer) { @@ -199,7 +199,8 @@ export class BlobViewer { this.$fileHolder.trigger('highlight:line'); handleLocationHash(); - viewer.setAttribute('data-loaded', 'true'); + // eslint-disable-next-line no-param-reassign + viewer.dataset.loaded = 'true'; this.toggleCopyButtonState(); eventHub.$emit('showBlobInteractionZones', viewer.dataset.path); }); diff --git a/app/assets/javascripts/breadcrumb.js b/app/assets/javascripts/breadcrumb.js index b9d3742974c..113840dbc52 100644 --- a/app/assets/javascripts/breadcrumb.js +++ b/app/assets/javascripts/breadcrumb.js @@ -5,7 +5,7 @@ export const addTooltipToEl = (el) => { if (textEl && textEl.scrollWidth > textEl.offsetWidth) { el.setAttribute('title', el.textContent); - el.setAttribute('data-container', 'body'); + el.dataset.container = 'body'; el.classList.add('has-tooltip'); } }; diff --git a/app/assets/javascripts/code_navigation/utils/index.js b/app/assets/javascripts/code_navigation/utils/index.js index 0d72153d8fe..46038df2f86 100644 --- a/app/assets/javascripts/code_navigation/utils/index.js +++ b/app/assets/javascripts/code_navigation/utils/index.js @@ -32,8 +32,8 @@ export const addInteractionClass = ({ path, d, wrapTextNodes }) => { }); if (el && !isTextNode(el)) { - el.setAttribute('data-char-index', d.start_char); - el.setAttribute('data-line-index', d.start_line); + el.dataset.charIndex = d.start_char; + el.dataset.lineIndex = d.start_line; el.classList.add('cursor-pointer', 'code-navigation', 'js-code-navigation'); el.closest('.line').classList.add('code-navigation-line'); } diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/render.js b/app/assets/javascripts/deprecated_jquery_dropdown/render.js index 37287b9d981..f10c2d82b61 100644 --- a/app/assets/javascripts/deprecated_jquery_dropdown/render.js +++ b/app/assets/javascripts/deprecated_jquery_dropdown/render.js @@ -107,10 +107,10 @@ function createLink(data, selected, options, index) { } if (options.trackSuggestionClickedLabel) { - link.setAttribute('data-track-action', 'click_text'); - link.setAttribute('data-track-label', options.trackSuggestionClickedLabel); - link.setAttribute('data-track-value', index); - link.setAttribute('data-track-property', slugify(data.category || 'no-category')); + link.dataset.trackAction = 'click_text'; + link.dataset.trackLabel = options.trackSuggestionClickedLabel; + link.dataset.trackValue = index; + link.dataset.trackProperty = slugify(data.category || 'no-category'); } link.classList.toggle('is-active', selected); diff --git a/app/assets/javascripts/diff.js b/app/assets/javascripts/diff.js index a12829f8420..47de7a76899 100644 --- a/app/assets/javascripts/diff.js +++ b/app/assets/javascripts/diff.js @@ -26,7 +26,7 @@ export default class Diff { FilesCommentButton.init($diffFile); const firstFile = $('.files').first().get(0); - const canCreateNote = firstFile && firstFile.hasAttribute('data-can-create-note'); + const canCreateNote = firstFile && Object.hasOwn(firstFile.dataset, 'canCreateNote'); $diffFile.each((index, file) => initImageDiffHelper.initImageDiff(file, canCreateNote)); if (!isBound) { diff --git a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js index b57db73a86e..3913e4e8d81 100644 --- a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js +++ b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js @@ -197,10 +197,10 @@ export default class AvailableDropdownMappings { } getGroupId() { - return this.filteredSearchInput.getAttribute('data-group-id') || ''; + return this.filteredSearchInput.dataset.groupId || ''; } getProjectId() { - return this.filteredSearchInput.getAttribute('data-project-id') || ''; + return this.filteredSearchInput.dataset.projectId || ''; } } diff --git a/app/assets/javascripts/filtered_search/dropdown_hint.js b/app/assets/javascripts/filtered_search/dropdown_hint.js index 9d29782c9a7..93897b4ed6c 100644 --- a/app/assets/javascripts/filtered_search/dropdown_hint.js +++ b/app/assets/javascripts/filtered_search/dropdown_hint.js @@ -25,9 +25,9 @@ export default class DropdownHint extends FilteredSearchDropdown { const { selected } = e.detail; if (selected.tagName === 'LI') { - if (selected.hasAttribute('data-value')) { + if (Object.hasOwn(selected.dataset, 'value')) { this.dismissDropdown(); - } else if (selected.getAttribute('data-action') === 'submit') { + } else if (selected.dataset.action === 'submit') { this.dismissDropdown(); this.dispatchFormSubmitEvent(); } else { diff --git a/app/assets/javascripts/filtered_search/dropdown_operator.js b/app/assets/javascripts/filtered_search/dropdown_operator.js index fb9f25a8c45..cd0f541b4fb 100644 --- a/app/assets/javascripts/filtered_search/dropdown_operator.js +++ b/app/assets/javascripts/filtered_search/dropdown_operator.js @@ -23,7 +23,7 @@ export default class DropdownOperator extends FilteredSearchDropdown { const { selected } = e.detail; if (selected.tagName === 'LI') { - if (selected.hasAttribute('data-value')) { + if (Object.hasOwn(selected.dataset, 'value')) { const name = FilteredSearchVisualTokens.getLastTokenPartial(); const operator = selected.dataset.value; diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js b/app/assets/javascripts/filtered_search/dropdown_user.js index 9a23ff25eac..26507a85fa8 100644 --- a/app/assets/javascripts/filtered_search/dropdown_user.js +++ b/app/assets/javascripts/filtered_search/dropdown_user.js @@ -31,11 +31,11 @@ export default class DropdownUser extends DropdownAjaxFilter { } getGroupId() { - return this.input.getAttribute('data-group-id'); + return this.input.dataset.groupId; } getProjectId() { - return this.input.getAttribute('data-project-id'); + return this.input.dataset.projectId; } projectOrGroupId() { diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js b/app/assets/javascripts/filtered_search/dropdown_utils.js index c98d1f8e064..22e1604871a 100644 --- a/app/assets/javascripts/filtered_search/dropdown_utils.js +++ b/app/assets/javascripts/filtered_search/dropdown_utils.js @@ -87,6 +87,7 @@ export default class DropdownUtils { } static setDataValueIfSelected(filter, operator, selected) { + // eslint-disable-next-line unicorn/prefer-dom-node-dataset const dataValue = selected.getAttribute('data-value'); if (dataValue) { @@ -96,6 +97,7 @@ export default class DropdownUtils { tokenValue: dataValue, clicked: true, options: { + // eslint-disable-next-line unicorn/prefer-dom-node-dataset capitalizeTokenValue: selected.hasAttribute('data-capitalize'), }, }); diff --git a/app/assets/javascripts/filtered_search/droplab/drop_down.js b/app/assets/javascripts/filtered_search/droplab/drop_down.js index 05b741af191..398a7b26677 100644 --- a/app/assets/javascripts/filtered_search/droplab/drop_down.js +++ b/app/assets/javascripts/filtered_search/droplab/drop_down.js @@ -165,8 +165,8 @@ class DropDown { images.forEach((image) => { const img = image; - img.src = img.getAttribute('data-src'); - img.removeAttribute('data-src'); + img.src = img.dataset.src; + delete img.dataset.src; }); } } diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js index 07f2c75f00a..ac2cf27e873 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_manager.js +++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js @@ -814,7 +814,7 @@ export default class FilteredSearchManager { getUsernameParams() { const usernamesById = {}; try { - const attribute = this.filteredSearchInput.getAttribute('data-username-params'); + const attribute = this.filteredSearchInput.dataset.usernameParams; JSON.parse(attribute).forEach((user) => { usernamesById[user.id] = user.username; }); diff --git a/app/assets/javascripts/image_diff/helpers/dom_helper.js b/app/assets/javascripts/image_diff/helpers/dom_helper.js index 3468a629f5a..180e927a3e7 100644 --- a/app/assets/javascripts/image_diff/helpers/dom_helper.js +++ b/app/assets/javascripts/image_diff/helpers/dom_helper.js @@ -6,7 +6,7 @@ export function setPositionDataAttribute(el, options) { const positionObject = { ...JSON.parse(position), x, y, width, height }; - el.setAttribute('data-position', JSON.stringify(positionObject)); + el.dataset.position = JSON.stringify(positionObject); } export function updateDiscussionAvatarBadgeNumber(discussionEl, newBadgeNumber) { diff --git a/app/assets/javascripts/issues/create_merge_request_dropdown.js b/app/assets/javascripts/issues/create_merge_request_dropdown.js index 3ea70c07058..7c611dbf39e 100644 --- a/app/assets/javascripts/issues/create_merge_request_dropdown.js +++ b/app/assets/javascripts/issues/create_merge_request_dropdown.js @@ -81,10 +81,7 @@ export default class CreateMergeRequestDropdown { this.init(); if (isConfidentialIssue()) { - this.createMergeRequestButton.setAttribute( - 'data-dropdown-trigger', - '#create-merge-request-dropdown', - ); + this.createMergeRequestButton.dataset.dropdownTrigger = '#create-merge-request-dropdown'; initConfidentialMergeRequest(); } } diff --git a/app/assets/javascripts/issues/show/components/description.vue b/app/assets/javascripts/issues/show/components/description.vue index 831cef66836..7594676489f 100644 --- a/app/assets/javascripts/issues/show/components/description.vue +++ b/app/assets/javascripts/issues/show/components/description.vue @@ -270,7 +270,7 @@ export default { }, setActiveTask(el) { const { parentElement } = el; - const lineNumbers = parentElement.getAttribute('data-sourcepos').match(/\b\d+(?=:)/g); + const lineNumbers = parentElement.dataset.sourcepos.match(/\b\d+(?=:)/g); this.activeTask = { title: parentElement.innerText, lineNumberStart: lineNumbers[0], diff --git a/app/assets/javascripts/lazy_loader.js b/app/assets/javascripts/lazy_loader.js index 2b4dd205cf1..ba801082377 100644 --- a/app/assets/javascripts/lazy_loader.js +++ b/app/assets/javascripts/lazy_loader.js @@ -127,7 +127,7 @@ export default class LazyLoader { // Loading Images which are in the current viewport or close to them this.lazyImages = this.lazyImages.filter((selectedImage) => { - if (selectedImage.getAttribute('data-src')) { + if (selectedImage.dataset.src) { const imgBoundRect = selectedImage.getBoundingClientRect(); const imgTop = scrollTop + imgBoundRect.top; const imgBound = imgTop + imgBoundRect.height; @@ -156,16 +156,17 @@ export default class LazyLoader { } static loadImage(img) { - if (img.getAttribute('data-src')) { + if (img.dataset.src) { img.setAttribute('loading', 'lazy'); - let imgUrl = img.getAttribute('data-src'); + let imgUrl = img.dataset.src; // Only adding width + height for avatars for now if (imgUrl.indexOf('/avatar/') > -1 && imgUrl.indexOf('?') === -1) { const targetWidth = img.getAttribute('width') || img.width; imgUrl += `?width=${targetWidth}`; } img.setAttribute('src', imgUrl); - img.removeAttribute('data-src'); + // eslint-disable-next-line no-param-reassign + delete img.dataset.src; img.classList.remove('lazy'); img.classList.add('js-lazy-loaded'); img.classList.add('qa-js-lazy-loaded'); diff --git a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js index 1adb6f9c26f..a0e730e9722 100644 --- a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js +++ b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js @@ -52,7 +52,7 @@ export function confirmAction( export function confirmViaGlModal(message, element) { const primaryBtnConfig = {}; - const confirmBtnVariant = element.getAttribute('data-confirm-btn-variant'); + const { confirmBtnVariant } = element.dataset; if (confirmBtnVariant) { primaryBtnConfig.primaryBtnVariant = confirmBtnVariant; diff --git a/app/assets/javascripts/members/components/table/role_dropdown.vue b/app/assets/javascripts/members/components/table/role_dropdown.vue index fa895cf24c4..6cd8bf57313 100644 --- a/app/assets/javascripts/members/components/table/role_dropdown.vue +++ b/app/assets/javascripts/members/components/table/role_dropdown.vue @@ -41,7 +41,7 @@ export default { const dropdownToggle = this.$refs.glDropdown.$el.querySelector('.dropdown-toggle'); if (dropdownToggle) { - dropdownToggle.setAttribute('data-qa-selector', 'access_level_dropdown'); + dropdownToggle.dataset.qaSelector = 'access_level_dropdown'; } }, methods: { diff --git a/app/assets/javascripts/pages/registrations/new/index.js b/app/assets/javascripts/pages/registrations/new/index.js index 8bbe81a9ed5..94a5c1cb29b 100644 --- a/app/assets/javascripts/pages/registrations/new/index.js +++ b/app/assets/javascripts/pages/registrations/new/index.js @@ -3,9 +3,14 @@ import { trackNewRegistrations } from '~/google_tag_manager'; import NoEmojiValidator from '~/emoji/no_emoji_validator'; import LengthValidator from '~/pages/sessions/new/length_validator'; import UsernameValidator from '~/pages/sessions/new/username_validator'; +import Tracking from '~/tracking'; new UsernameValidator(); // eslint-disable-line no-new new LengthValidator(); // eslint-disable-line no-new new NoEmojiValidator(); // eslint-disable-line no-new trackNewRegistrations(); + +Tracking.enableFormTracking({ + forms: { allow: ['new_user'] }, +}); diff --git a/app/assets/javascripts/pages/shared/nav/sidebar_tracking.js b/app/assets/javascripts/pages/shared/nav/sidebar_tracking.js index 79ce1a37d21..47aae36ecbb 100644 --- a/app/assets/javascripts/pages/shared/nav/sidebar_tracking.js +++ b/app/assets/javascripts/pages/shared/nav/sidebar_tracking.js @@ -1,6 +1,6 @@ function onSidebarLinkClick() { const setDataTrackAction = (element, action) => { - element.setAttribute('data-track-action', action); + element.dataset.trackAction = action; }; const setDataTrackExtra = (element, value) => { @@ -12,10 +12,10 @@ function onSidebarLinkClick() { ? SIDEBAR_COLLAPSED : SIDEBAR_EXPANDED; - element.setAttribute( - 'data-track-extra', - JSON.stringify({ sidebar_display: sidebarCollapsed, menu_display: value }), - ); + element.dataset.trackExtra = JSON.stringify({ + sidebar_display: sidebarCollapsed, + menu_display: value, + }); }; const EXPANDED = 'Expanded'; diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js index 996e12bc105..94506d33b33 100644 --- a/app/assets/javascripts/pages/users/activity_calendar.js +++ b/app/assets/javascripts/pages/users/activity_calendar.js @@ -298,7 +298,7 @@ export default class ActivityCalendar { .querySelector(this.activitiesContainer) .querySelectorAll('.js-localtime') .forEach((el) => { - el.setAttribute('title', formatDate(el.getAttribute('data-datetime'))); + el.setAttribute('title', formatDate(el.dataset.datetime)); }); }) .catch(() => diff --git a/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_mini_graph.vue b/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_mini_graph.vue index 1f2fdb7ce36..7beabcfe403 100644 --- a/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_mini_graph.vue +++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_mini_graph.vue @@ -47,6 +47,12 @@ export default { downstreamPipelines() { return this.linkedPipelines?.downstream?.nodes || []; }, + hasDownstreamPipelines() { + return this.downstreamPipelines.length > 0; + }, + hasPipelineStages() { + return this.pipelineStages.length > 0; + }, pipelinePath() { return this.pipeline.detailedStatus?.detailsPath || ''; }, @@ -73,9 +79,6 @@ export default { }; }); }, - showDownstreamPipelines() { - return this.downstreamPipelines.length > 0; - }, upstreamPipeline() { return this.linkedPipelines?.upstream; }, @@ -84,7 +87,10 @@ export default {