summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-04-20 21:08:12 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-04-20 21:08:12 +0000
commitfc8614660ee6c0963c96925affa7d837c02e0b4b (patch)
treed81cfed376f54ed52cbf540e0aa0c3ac46bf7c2d
parenta174146bf09aa549a4ae43f2b8a0f6aa638f499e (diff)
downloadgitlab-ce-fc8614660ee6c0963c96925affa7d837c02e0b4b.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo.yml6
-rw-r--r--.rubocop_todo/naming/heredoc_delimiter_naming.yml141
-rw-r--r--app/assets/javascripts/content_editor/constants/code_block_languages.js210
-rw-r--r--app/assets/javascripts/content_editor/constants/index.js (renamed from app/assets/javascripts/content_editor/constants.js)0
-rw-r--r--app/assets/javascripts/content_editor/services/code_block_language_loader.js211
-rw-r--r--app/assets/javascripts/diffs/components/diff_expansion_cell.vue158
-rw-r--r--app/assets/javascripts/diffs/components/diff_row.vue8
-rw-r--r--app/assets/javascripts/diffs/components/diff_row_utils.js7
-rw-r--r--app/assets/javascripts/diffs/components/diff_view.vue85
-rw-r--r--app/assets/javascripts/diffs/constants.js1
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js2
-rw-r--r--app/assets/javascripts/diffs/store/utils.js6
-rw-r--r--app/assets/stylesheets/framework/broadcast_messages.scss5
-rw-r--r--app/assets/stylesheets/framework/diffs.scss38
-rw-r--r--app/assets/stylesheets/highlight/common.scss19
-rw-r--r--app/assets/stylesheets/highlight/themes/dark.scss12
-rw-r--r--app/assets/stylesheets/highlight/themes/monokai.scss12
-rw-r--r--app/assets/stylesheets/highlight/themes/none.scss9
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-dark.scss12
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-light.scss12
-rw-r--r--app/assets/stylesheets/highlight/white_base.scss28
-rw-r--r--app/controllers/projects/merge_requests_controller.rb1
-rw-r--r--app/serializers/ci/job_entity.rb1
-rw-r--r--app/views/shared/snippets/_snippet.html.haml27
-rw-r--r--config/feature_flags/development/updated_diff_expansion_buttons.yml8
-rw-r--r--data/deprecations/14-10-dependency-scanning-default-java-version.yml16
-rw-r--r--data/deprecations/14-5-certificate-based-integration-with-kubernetes-saas.yml17
-rw-r--r--data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml18
-rw-r--r--doc/update/deprecations.md77
-rw-r--r--doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md8
-rw-r--r--locale/gitlab.pot9
-rw-r--r--spec/features/merge_request/user_comments_on_diff_spec.rb6
-rw-r--r--spec/features/merge_request/user_views_diffs_spec.rb2
-rw-r--r--spec/frontend/diffs/components/diff_expansion_cell_spec.js21
-rw-r--r--spec/frontend/diffs/store/mutations_spec.js9
-rw-r--r--spec/frontend/diffs/store/utils_spec.js24
-rw-r--r--spec/serializers/ci/job_entity_spec.rb9
37 files changed, 814 insertions, 421 deletions
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index fef456d3d19..1ce7cbaabfb 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -46,12 +46,6 @@ Lint/RedundantCopDisableDirective:
Lint/UselessMethodDefinition:
Enabled: false
-# Offense count: 321
-# Configuration parameters: ForbiddenDelimiters.
-# ForbiddenDelimiters: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$))
-Naming/HeredocDelimiterNaming:
- Enabled: false
-
# Offense count: 218
# Cop supports --auto-correct.
# Configuration parameters: PreferredName.
diff --git a/.rubocop_todo/naming/heredoc_delimiter_naming.yml b/.rubocop_todo/naming/heredoc_delimiter_naming.yml
new file mode 100644
index 00000000000..86d9ae2f24d
--- /dev/null
+++ b/.rubocop_todo/naming/heredoc_delimiter_naming.yml
@@ -0,0 +1,141 @@
+---
+Naming/HeredocDelimiterNaming:
+ # Offense count: 388
+ # Temporarily disabled due to too many offenses
+ Enabled: false
+ Exclude:
+ - 'app/models/ci/build_trace_chunks/redis_base.rb'
+ - 'app/models/concerns/counter_attribute.rb'
+ - 'app/models/concerns/legacy_bulk_insert.rb'
+ - 'app/models/trending_project.rb'
+ - 'app/services/ci/ensure_stage_service.rb'
+ - 'app/services/packages/debian/generate_distribution_key_service.rb'
+ - 'app/workers/concerns/limited_capacity/job_tracker.rb'
+ - 'config/initializers/01_secret_token.rb'
+ - 'ee/app/workers/update_max_seats_used_for_gitlab_com_subscriptions_worker.rb'
+ - 'ee/db/geo/migrate/20180322062741_migrate_ci_job_artifacts_to_separate_registry.rb'
+ - 'ee/db/geo/migrate/20191010204941_migrate_lfs_objects_to_separate_registry.rb'
+ - 'ee/lib/api/elasticsearch_indexed_namespaces.rb'
+ - 'ee/spec/lib/ee/gitlab/ci/config_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/ci/templates/templates_spec.rb'
+ - 'ee/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb'
+ - 'ee/spec/lib/gitlab/elastic/search_results_spec.rb'
+ - 'ee/spec/lib/gitlab/patch/database_config_spec.rb'
+ - 'ee/spec/lib/gitlab/sitemaps/sitemap_file_spec.rb'
+ - 'ee/spec/services/ci/create_pipeline_service/compliance_spec.rb'
+ - 'ee/spec/services/ci/create_pipeline_service/dast_configuration_spec.rb'
+ - 'ee/spec/services/ci/create_pipeline_service/needs_spec.rb'
+ - 'ee/spec/services/ci/create_pipeline_service/runnable_builds_spec.rb'
+ - 'ee/spec/services/ci/create_pipeline_service_spec.rb'
+ - 'ee/spec/services/security/security_orchestration_policies/create_pipeline_service_spec.rb'
+ - 'ee/spec/services/security/security_orchestration_policies/policy_commit_service_spec.rb'
+ - 'ee/spec/support/helpers/ee/ldap_helpers.rb'
+ - 'ee/spec/tasks/gitlab/elastic_rake_spec.rb'
+ - 'lib/api/version.rb'
+ - 'lib/backup/helper.rb'
+ - 'lib/feature/shared.rb'
+ - 'lib/gitlab/cache/import/caching.rb'
+ - 'lib/gitlab/conflict/file_collection.rb'
+ - 'lib/gitlab/database.rb'
+ - 'lib/gitlab/database/migration_helpers.rb'
+ - 'lib/gitlab/database/migration_helpers/v2.rb'
+ - 'lib/gitlab/exclusive_lease.rb'
+ - 'lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb'
+ - 'lib/gitlab/sql/set_operator.rb'
+ - 'lib/gitlab/utils/delegator_override/validator.rb'
+ - 'lib/tasks/gitlab/docs/compile_deprecations.rake'
+ - 'lib/tasks/gitlab/password.rake'
+ - 'qa/qa/scenario/test/sanity/selectors.rb'
+ - 'qa/qa/service/docker_run/gitlab_runner.rb'
+ - 'qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb'
+ - 'qa/qa/specs/features/browser_ui/3_create/web_ide/web_terminal_spec.rb'
+ - 'qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb'
+ - 'qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb'
+ - 'qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb'
+ - 'qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb'
+ - 'rubocop/cop/database/multiple_databases.rb'
+ - 'rubocop/cop/default_scope.rb'
+ - 'rubocop/cop/file_decompression.rb'
+ - 'rubocop/cop/gitlab/httparty.rb'
+ - 'rubocop/cop/gitlab/json.rb'
+ - 'rubocop/cop/gitlab/module_with_instance_variables.rb'
+ - 'rubocop/cop/gitlab/predicate_memoization.rb'
+ - 'spec/controllers/projects/pipelines_controller_spec.rb'
+ - 'spec/deprecation_toolkit_env.rb'
+ - 'spec/factories/packages/debian/distribution.rb'
+ - 'spec/factories/packages/debian/file_metadatum.rb'
+ - 'spec/features/projects/commit/user_comments_on_commit_spec.rb'
+ - 'spec/features/task_lists_spec.rb'
+ - 'spec/helpers/markup_helper_spec.rb'
+ - 'spec/initializers/100_patch_omniauth_oauth2_spec.rb'
+ - 'spec/initializers/rack_multipart_patch_spec.rb'
+ - 'spec/initializers/secret_token_spec.rb'
+ - 'spec/initializers/validate_database_config_spec.rb'
+ - 'spec/lib/banzai/filter/footnote_filter_spec.rb'
+ - 'spec/lib/banzai/pipeline/full_pipeline_spec.rb'
+ - 'spec/lib/gitlab/auth/ldap/config_spec.rb'
+ - 'spec/lib/gitlab/ci/config_spec.rb'
+ - 'spec/lib/gitlab/ci/parsers/coverage/sax_document_spec.rb'
+ - 'spec/lib/gitlab/ci/parsers/test/junit_spec.rb'
+ - 'spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb'
+ - 'spec/lib/gitlab/ci/templates/templates_spec.rb'
+ - 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
+ - 'spec/lib/gitlab/cluster/mixins/puma_cluster_spec.rb'
+ - 'spec/lib/gitlab/conflict/file_collection_spec.rb'
+ - 'spec/lib/gitlab/diff/file_spec.rb'
+ - 'spec/lib/gitlab/diff/pair_selector_spec.rb'
+ - 'spec/lib/gitlab/diff/parser_spec.rb'
+ - 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
+ - 'spec/lib/gitlab/file_hook_spec.rb'
+ - 'spec/lib/gitlab/form_builders/gitlab_ui_form_builder_spec.rb'
+ - 'spec/lib/gitlab/git/diff_spec.rb'
+ - 'spec/lib/gitlab/git_post_receive_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb'
+ - 'spec/lib/gitlab/import_export/attributes_permitter_spec.rb'
+ - 'spec/lib/gitlab/import_export/config_spec.rb'
+ - 'spec/lib/gitlab/kubernetes/helm/v2/delete_command_spec.rb'
+ - 'spec/lib/gitlab/kubernetes/helm/v2/init_command_spec.rb'
+ - 'spec/lib/gitlab/kubernetes/helm/v2/install_command_spec.rb'
+ - 'spec/lib/gitlab/kubernetes/helm/v2/patch_command_spec.rb'
+ - 'spec/lib/gitlab/kubernetes/helm/v2/reset_command_spec.rb'
+ - 'spec/lib/gitlab/kubernetes/helm/v3/delete_command_spec.rb'
+ - 'spec/lib/gitlab/kubernetes/helm/v3/install_command_spec.rb'
+ - 'spec/lib/gitlab/kubernetes/helm/v3/patch_command_spec.rb'
+ - 'spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb'
+ - 'spec/lib/gitlab/patch/database_config_spec.rb'
+ - 'spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb'
+ - 'spec/lib/gitlab/quick_actions/substitution_definition_spec.rb'
+ - 'spec/lib/gitlab/static_site_editor/config/file_config_spec.rb'
+ - 'spec/lib/gitlab/web_ide/config_spec.rb'
+ - 'spec/lib/gitlab/webpack/file_loader_spec.rb'
+ - 'spec/lib/gitlab/webpack/graphql_known_operations_spec.rb'
+ - 'spec/lib/gitlab/webpack/manifest_spec.rb'
+ - 'spec/lib/gitlab/word_diff/parser_spec.rb'
+ - 'spec/models/ci/bridge_spec.rb'
+ - 'spec/models/clusters/applications/cert_manager_spec.rb'
+ - 'spec/models/concerns/ci/maskable_spec.rb'
+ - 'spec/models/integrations/asana_spec.rb'
+ - 'spec/models/ssh_host_key_spec.rb'
+ - 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb'
+ - 'spec/services/ci/after_requeue_job_service_spec.rb'
+ - 'spec/services/ci/create_downstream_pipeline_service_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/cache_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/include_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/merge_requests_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/parallel_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/parameter_content_spec.rb'
+ - 'spec/services/ci/create_pipeline_service/rules_spec.rb'
+ - 'spec/services/ci/create_pipeline_service_spec.rb'
+ - 'spec/services/ci/create_web_ide_terminal_service_spec.rb'
+ - 'spec/services/ci/parse_dotenv_artifact_service_spec.rb'
+ - 'spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb'
+ - 'spec/services/google_cloud/generate_pipeline_service_spec.rb'
+ - 'spec/services/task_list_toggle_service_spec.rb'
+ - 'spec/support/helpers/seed_helper.rb'
+ - 'spec/support/helpers/stub_object_storage.rb'
+ - 'spec/support/shared_examples/helm_commands_shared_examples.rb'
+ - 'spec/support/shared_examples/models/taskable_shared_examples.rb'
+ - 'spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb'
+ - 'spec/support/test_reports/test_reports_helper.rb'
+ - 'spec/workers/post_receive_spec.rb'
diff --git a/app/assets/javascripts/content_editor/constants/code_block_languages.js b/app/assets/javascripts/content_editor/constants/code_block_languages.js
new file mode 100644
index 00000000000..1a4dbe4fa22
--- /dev/null
+++ b/app/assets/javascripts/content_editor/constants/code_block_languages.js
@@ -0,0 +1,210 @@
+/* eslint-disable @gitlab/require-i18n-strings */
+// List of languages referenced from https://github.com/wooorm/lowlight#data
+const CODE_BLOCK_LANGUAGES = [
+ { syntax: '1c', label: '1C:Enterprise' },
+ { syntax: 'abnf', label: 'Augmented Backus-Naur Form' },
+ { syntax: 'accesslog', label: 'Apache Access Log' },
+ { syntax: 'actionscript', variants: 'as', label: 'ActionScript' },
+ { syntax: 'ada', label: 'Ada' },
+ { syntax: 'angelscript', variants: 'asc', label: 'AngelScript' },
+ { syntax: 'apache', variants: 'apacheconf', label: 'Apache config' },
+ { syntax: 'applescript', variants: 'osascript', label: 'AppleScript' },
+ { syntax: 'arcade', label: 'ArcGIS Arcade' },
+ { syntax: 'arduino', variants: 'ino', label: 'Arduino' },
+ { syntax: 'armasm', variants: 'arm', label: 'ARM Assembly' },
+ { syntax: 'asciidoc', variants: 'adoc', label: 'AsciiDoc' },
+ { syntax: 'aspectj', label: 'AspectJ' },
+ { syntax: 'autohotkey', variants: 'ahk', label: 'AutoHotkey' },
+ { syntax: 'autoit', label: 'AutoIt' },
+ { syntax: 'avrasm', label: 'AVR Assembly' },
+ { syntax: 'awk', label: 'Awk' },
+ { syntax: 'axapta', variants: 'x++', label: 'X++' },
+ { syntax: 'bash', variants: 'sh', label: 'Bash' },
+ { syntax: 'basic', label: 'BASIC' },
+ { syntax: 'bnf', label: 'Backus-Naur Form' },
+ { syntax: 'brainfuck', variants: 'bf', label: 'Brainfuck' },
+ { syntax: 'c', variants: 'h', label: 'C' },
+ { syntax: 'cal', label: 'C/AL' },
+ { syntax: 'capnproto', variants: 'capnp', label: "Cap'n Proto" },
+ { syntax: 'ceylon', label: 'Ceylon' },
+ { syntax: 'clean', variants: 'icl, dcl', label: 'Clean' },
+ { syntax: 'clojure', variants: 'clj, edn', label: 'Clojure' },
+ { syntax: 'clojure-repl', label: 'Clojure REPL' },
+ { syntax: 'cmake', variants: 'cmake.in', label: 'CMake' },
+ { syntax: 'coffeescript', variants: 'coffee, cson, iced', label: 'CoffeeScript' },
+ { syntax: 'coq', label: 'Coq' },
+ { syntax: 'cos', variants: 'cls', label: 'Caché Object Script' },
+ { syntax: 'cpp', variants: 'cc, c++, h++, hpp, hh, hxx, cxx', label: 'C++' },
+ { syntax: 'crmsh', variants: 'crm, pcmk', label: 'crmsh' },
+ { syntax: 'crystal', variants: 'cr', label: 'Crystal' },
+ { syntax: 'csharp', variants: 'cs, c#', label: 'C#' },
+ { syntax: 'csp', label: 'CSP' },
+ { syntax: 'css', label: 'CSS' },
+ { syntax: 'd', label: 'D' },
+ { syntax: 'dart', label: 'Dart' },
+ { syntax: 'delphi', variants: 'dpr, dfm, pas, pascal', label: 'Delphi' },
+ { syntax: 'diff', variants: 'patch', label: 'Diff' },
+ { syntax: 'django', variants: 'jinja', label: 'Django' },
+ { syntax: 'dns', variants: 'bind, zone', label: 'DNS Zone' },
+ { syntax: 'dockerfile', variants: 'docker', label: 'Dockerfile' },
+ { syntax: 'dos', variants: 'bat, cmd', label: 'Batch file (DOS)' },
+ { syntax: 'dsconfig', label: 'DSConfig' },
+ { syntax: 'dts', label: 'Device Tree' },
+ { syntax: 'dust', variants: 'dst', label: 'Dust' },
+ { syntax: 'ebnf', label: 'Extended Backus-Naur Form' },
+ { syntax: 'elixir', variants: 'ex, exs', label: 'Elixir' },
+ { syntax: 'elm', label: 'Elm' },
+ { syntax: 'erb', label: 'ERB' },
+ { syntax: 'erlang', variants: 'erl', label: 'Erlang' },
+ { syntax: 'erlang-repl', label: 'Erlang REPL' },
+ { syntax: 'excel', variants: 'xlsx, xls', label: 'Excel formulae' },
+ { syntax: 'fix', label: 'FIX' },
+ { syntax: 'flix', label: 'Flix' },
+ { syntax: 'fortran', variants: 'f90, f95', label: 'Fortran' },
+ { syntax: 'fsharp', variants: 'fs, f#', label: 'F#' },
+ { syntax: 'gams', variants: 'gms', label: 'GAMS' },
+ { syntax: 'gauss', variants: 'gss', label: 'GAUSS' },
+ { syntax: 'gcode', variants: 'nc', label: 'G-code (ISO 6983)' },
+ { syntax: 'gherkin', variants: 'feature', label: 'Gherkin' },
+ { syntax: 'glsl', label: 'GLSL' },
+ { syntax: 'gml', label: 'GML' },
+ { syntax: 'go', variants: 'golang', label: 'Go' },
+ { syntax: 'golo', label: 'Golo' },
+ { syntax: 'gradle', label: 'Gradle' },
+ { syntax: 'graphql', variants: 'gql', label: 'GraphQL' },
+ { syntax: 'groovy', label: 'Groovy' },
+ { syntax: 'haml', label: 'HAML' },
+ {
+ syntax: 'handlebars',
+ variants: 'hbs, html.hbs, html.handlebars, htmlbars',
+ label: 'Handlebars',
+ },
+ { syntax: 'haskell', variants: 'hs', label: 'Haskell' },
+ { syntax: 'haxe', variants: 'hx', label: 'Haxe' },
+ { syntax: 'hsp', label: 'HSP' },
+ { syntax: 'http', variants: 'https', label: 'HTTP' },
+ { syntax: 'hy', variants: 'hylang', label: 'Hy' },
+ { syntax: 'inform7', variants: 'i7', label: 'Inform 7' },
+ { syntax: 'ini', variants: 'toml', label: 'TOML, also INI' },
+ { syntax: 'irpf90', label: 'IRPF90' },
+ { syntax: 'isbl', label: 'ISBL' },
+ { syntax: 'java', variants: 'jsp', label: 'Java' },
+ { syntax: 'javascript', variants: 'js, jsx, mjs, cjs', label: 'Javascript' },
+ { syntax: 'jboss-cli', variants: 'wildfly-cli', label: 'JBoss CLI' },
+ { syntax: 'json', label: 'JSON' },
+ { syntax: 'julia', label: 'Julia' },
+ { syntax: 'julia-repl', variants: 'jldoctest', label: 'Julia REPL' },
+ { syntax: 'kotlin', variants: 'kt, kts', label: 'Kotlin' },
+ { syntax: 'lasso', variants: 'ls, lassoscript', label: 'Lasso' },
+ { syntax: 'latex', variants: 'tex', label: 'LaTeX' },
+ { syntax: 'ldif', label: 'LDIF' },
+ { syntax: 'leaf', label: 'Leaf' },
+ { syntax: 'less', label: 'Less' },
+ { syntax: 'lisp', label: 'Lisp' },
+ { syntax: 'livecodeserver', label: 'LiveCode' },
+ { syntax: 'livescript', variants: 'ls', label: 'LiveScript' },
+ { syntax: 'llvm', label: 'LLVM IR' },
+ { syntax: 'lsl', label: 'LSL (Linden Scripting Language)' },
+ { syntax: 'lua', label: 'Lua' },
+ { syntax: 'makefile', variants: 'mk, mak, make', label: 'Makefile' },
+ { syntax: 'markdown', variants: 'md, mkdown, mkd', label: 'Markdown' },
+ { syntax: 'mathematica', variants: 'mma, wl', label: 'Mathematica' },
+ { syntax: 'matlab', label: 'Matlab' },
+ { syntax: 'maxima', label: 'Maxima' },
+ { syntax: 'mel', label: 'MEL' },
+ { syntax: 'mercury', variants: 'm, moo', label: 'Mercury' },
+ { syntax: 'mipsasm', variants: 'mips', label: 'MIPS Assembly' },
+ { syntax: 'mizar', label: 'Mizar' },
+ { syntax: 'mojolicious', label: 'Mojolicious' },
+ { syntax: 'monkey', label: 'Monkey' },
+ { syntax: 'moonscript', variants: 'moon', label: 'MoonScript' },
+ { syntax: 'n1ql', label: 'N1QL' },
+ { syntax: 'nestedtext', variants: 'nt', label: 'Nested Text' },
+ { syntax: 'nginx', variants: 'nginxconf', label: 'Nginx config' },
+ { syntax: 'nim', label: 'Nim' },
+ { syntax: 'nix', variants: 'nixos', label: 'Nix' },
+ { syntax: 'node-repl', label: 'Node REPL' },
+ { syntax: 'nsis', label: 'NSIS' },
+ {
+ syntax: 'objectivec',
+ variants: 'mm, objc, obj-c, obj-c++, objective-c++',
+ label: 'Objective-C',
+ },
+ { syntax: 'ocaml', variants: 'ml', label: 'OCaml' },
+ { syntax: 'openscad', variants: 'scad', label: 'OpenSCAD' },
+ { syntax: 'oxygene', label: 'Oxygene' },
+ { syntax: 'parser3', label: 'Parser3' },
+ { syntax: 'perl', variants: 'pl, pm', label: 'Perl' },
+ { syntax: 'pf', variants: 'pf.conf', label: 'Packet Filter config' },
+ { syntax: 'pgsql', variants: 'postgres, postgresql', label: 'PostgreSQL' },
+ { syntax: 'php', label: 'PHP' },
+ { syntax: 'php-template', label: 'PHP template' },
+ { syntax: 'plaintext', variants: 'text, txt', label: 'Plain text' },
+ { syntax: 'pony', label: 'Pony' },
+ { syntax: 'powershell', variants: 'pwsh, ps, ps1', label: 'PowerShell' },
+ { syntax: 'processing', variants: 'pde', label: 'Processing' },
+ { syntax: 'profile', label: 'Python profiler' },
+ { syntax: 'prolog', label: 'Prolog' },
+ { syntax: 'properties', label: '.properties' },
+ { syntax: 'protobuf', label: 'Protocol Buffers' },
+ { syntax: 'puppet', variants: 'pp', label: 'Puppet' },
+ { syntax: 'purebasic', variants: 'pb, pbi', label: 'PureBASIC' },
+ { syntax: 'python', variants: 'py, gyp, ipython', label: 'Python' },
+ { syntax: 'python-repl', variants: 'pycon', label: 'Python REPL' },
+ { syntax: 'q', variants: 'k, kdb', label: 'Q' },
+ { syntax: 'qml', variants: 'qt', label: 'QML' },
+ { syntax: 'r', label: 'R' },
+ { syntax: 'reasonml', variants: 're', label: 'ReasonML' },
+ { syntax: 'rib', label: 'RenderMan RIB' },
+ { syntax: 'roboconf', variants: 'graph, instances', label: 'Roboconf' },
+ { syntax: 'routeros', variants: 'mikrotik', label: 'Microtik RouterOS script' },
+ { syntax: 'rsl', label: 'RenderMan RSL' },
+ { syntax: 'ruby', variants: 'rb, gemspec, podspec, thor, irb', label: 'Ruby' },
+ { syntax: 'ruleslanguage', label: 'Oracle Rules Language' },
+ { syntax: 'rust', variants: 'rs', label: 'Rust' },
+ { syntax: 'sas', label: 'SAS' },
+ { syntax: 'scala', label: 'Scala' },
+ { syntax: 'scheme', label: 'Scheme' },
+ { syntax: 'scilab', variants: 'sci', label: 'Scilab' },
+ { syntax: 'scss', label: 'SCSS' },
+ { syntax: 'shell', variants: 'console, shellsession', label: 'Shell Session' },
+ { syntax: 'smali', label: 'Smali' },
+ { syntax: 'smalltalk', variants: 'st', label: 'Smalltalk' },
+ { syntax: 'sml', variants: 'ml', label: 'SML (Standard ML)' },
+ { syntax: 'sqf', label: 'SQF' },
+ { syntax: 'sql', label: 'SQL' },
+ { syntax: 'stan', variants: 'stanfuncs', label: 'Stan' },
+ { syntax: 'stata', variants: 'do, ado', label: 'Stata' },
+ { syntax: 'step21', variants: 'p21, step, stp', label: 'STEP Part 21' },
+ { syntax: 'stylus', variants: 'styl', label: 'Stylus' },
+ { syntax: 'subunit', label: 'SubUnit' },
+ { syntax: 'swift', label: 'Swift' },
+ { syntax: 'taggerscript', label: 'Tagger Script' },
+ { syntax: 'tap', label: 'Test Anything Protocol' },
+ { syntax: 'tcl', variants: 'tk', label: 'Tcl' },
+ { syntax: 'thrift', label: 'Thrift' },
+ { syntax: 'tp', label: 'TP' },
+ { syntax: 'twig', variants: 'craftcms', label: 'Twig' },
+ { syntax: 'typescript', variants: 'ts, tsx', label: 'TypeScript' },
+ { syntax: 'vala', label: 'Vala' },
+ { syntax: 'vbnet', variants: 'vb', label: 'Visual Basic .NET' },
+ { syntax: 'vbscript', variants: 'vbs', label: 'VBScript' },
+ { syntax: 'vbscript-html', label: 'VBScript in HTML' },
+ { syntax: 'verilog', variants: 'v, sv, svh', label: 'Verilog' },
+ { syntax: 'vhdl', label: 'VHDL' },
+ { syntax: 'vim', label: 'Vim Script' },
+ { syntax: 'wasm', label: 'WebAssembly' },
+ { syntax: 'wren', label: 'Wren' },
+ { syntax: 'x86asm', label: 'Intel x86 Assembly' },
+ { syntax: 'xl', variants: 'tao', label: 'XL' },
+ {
+ syntax: 'xml',
+ variants: 'html, xhtml, rss, atom, xjb, xsd, xsl, plist, wsf, svg',
+ label: 'HTML, XML',
+ },
+ { syntax: 'xquery', variants: 'xpath, xq', label: 'XQuery' },
+ { syntax: 'yaml', variants: 'yml', label: 'YAML' },
+ { syntax: 'zephir', variants: 'zep', label: 'Zephir' },
+];
+
+export default CODE_BLOCK_LANGUAGES;
diff --git a/app/assets/javascripts/content_editor/constants.js b/app/assets/javascripts/content_editor/constants/index.js
index a39a243ec6b..a39a243ec6b 100644
--- a/app/assets/javascripts/content_editor/constants.js
+++ b/app/assets/javascripts/content_editor/constants/index.js
diff --git a/app/assets/javascripts/content_editor/services/code_block_language_loader.js b/app/assets/javascripts/content_editor/services/code_block_language_loader.js
index 081400cfd9a..c967dd899de 100644
--- a/app/assets/javascripts/content_editor/services/code_block_language_loader.js
+++ b/app/assets/javascripts/content_editor/services/code_block_language_loader.js
@@ -1,215 +1,6 @@
import { lowlight } from 'lowlight/lib/core';
import { __, sprintf } from '~/locale';
-
-/* eslint-disable @gitlab/require-i18n-strings */
-// List of languages referenced from https://github.com/wooorm/lowlight#data
-const CODE_BLOCK_LANGUAGES = [
- { syntax: '1c', label: '1C:Enterprise' },
- { syntax: 'abnf', label: 'Augmented Backus-Naur Form' },
- { syntax: 'accesslog', label: 'Apache Access Log' },
- { syntax: 'actionscript', variants: 'as', label: 'ActionScript' },
- { syntax: 'ada', label: 'Ada' },
- { syntax: 'angelscript', variants: 'asc', label: 'AngelScript' },
- { syntax: 'apache', variants: 'apacheconf', label: 'Apache config' },
- { syntax: 'applescript', variants: 'osascript', label: 'AppleScript' },
- { syntax: 'arcade', label: 'ArcGIS Arcade' },
- { syntax: 'arduino', variants: 'ino', label: 'Arduino' },
- { syntax: 'armasm', variants: 'arm', label: 'ARM Assembly' },
- { syntax: 'asciidoc', variants: 'adoc', label: 'AsciiDoc' },
- { syntax: 'aspectj', label: 'AspectJ' },
- { syntax: 'autohotkey', variants: 'ahk', label: 'AutoHotkey' },
- { syntax: 'autoit', label: 'AutoIt' },
- { syntax: 'avrasm', label: 'AVR Assembly' },
- { syntax: 'awk', label: 'Awk' },
- { syntax: 'axapta', variants: 'x++', label: 'X++' },
- { syntax: 'bash', variants: 'sh', label: 'Bash' },
- { syntax: 'basic', label: 'BASIC' },
- { syntax: 'bnf', label: 'Backus-Naur Form' },
- { syntax: 'brainfuck', variants: 'bf', label: 'Brainfuck' },
- { syntax: 'c', variants: 'h', label: 'C' },
- { syntax: 'cal', label: 'C/AL' },
- { syntax: 'capnproto', variants: 'capnp', label: "Cap'n Proto" },
- { syntax: 'ceylon', label: 'Ceylon' },
- { syntax: 'clean', variants: 'icl, dcl', label: 'Clean' },
- { syntax: 'clojure', variants: 'clj, edn', label: 'Clojure' },
- { syntax: 'clojure-repl', label: 'Clojure REPL' },
- { syntax: 'cmake', variants: 'cmake.in', label: 'CMake' },
- { syntax: 'coffeescript', variants: 'coffee, cson, iced', label: 'CoffeeScript' },
- { syntax: 'coq', label: 'Coq' },
- { syntax: 'cos', variants: 'cls', label: 'Caché Object Script' },
- { syntax: 'cpp', variants: 'cc, c++, h++, hpp, hh, hxx, cxx', label: 'C++' },
- { syntax: 'crmsh', variants: 'crm, pcmk', label: 'crmsh' },
- { syntax: 'crystal', variants: 'cr', label: 'Crystal' },
- { syntax: 'csharp', variants: 'cs, c#', label: 'C#' },
- { syntax: 'csp', label: 'CSP' },
- { syntax: 'css', label: 'CSS' },
- { syntax: 'd', label: 'D' },
- { syntax: 'dart', label: 'Dart' },
- { syntax: 'delphi', variants: 'dpr, dfm, pas, pascal', label: 'Delphi' },
- { syntax: 'diff', variants: 'patch', label: 'Diff' },
- { syntax: 'django', variants: 'jinja', label: 'Django' },
- { syntax: 'dns', variants: 'bind, zone', label: 'DNS Zone' },
- { syntax: 'dockerfile', variants: 'docker', label: 'Dockerfile' },
- { syntax: 'dos', variants: 'bat, cmd', label: 'Batch file (DOS)' },
- { syntax: 'dsconfig', label: 'DSConfig' },
- { syntax: 'dts', label: 'Device Tree' },
- { syntax: 'dust', variants: 'dst', label: 'Dust' },
- { syntax: 'ebnf', label: 'Extended Backus-Naur Form' },
- { syntax: 'elixir', variants: 'ex, exs', label: 'Elixir' },
- { syntax: 'elm', label: 'Elm' },
- { syntax: 'erb', label: 'ERB' },
- { syntax: 'erlang', variants: 'erl', label: 'Erlang' },
- { syntax: 'erlang-repl', label: 'Erlang REPL' },
- { syntax: 'excel', variants: 'xlsx, xls', label: 'Excel formulae' },
- { syntax: 'fix', label: 'FIX' },
- { syntax: 'flix', label: 'Flix' },
- { syntax: 'fortran', variants: 'f90, f95', label: 'Fortran' },
- { syntax: 'fsharp', variants: 'fs, f#', label: 'F#' },
- { syntax: 'gams', variants: 'gms', label: 'GAMS' },
- { syntax: 'gauss', variants: 'gss', label: 'GAUSS' },
- { syntax: 'gcode', variants: 'nc', label: 'G-code (ISO 6983)' },
- { syntax: 'gherkin', variants: 'feature', label: 'Gherkin' },
- { syntax: 'glsl', label: 'GLSL' },
- { syntax: 'gml', label: 'GML' },
- { syntax: 'go', variants: 'golang', label: 'Go' },
- { syntax: 'golo', label: 'Golo' },
- { syntax: 'gradle', label: 'Gradle' },
- { syntax: 'graphql', variants: 'gql', label: 'GraphQL' },
- { syntax: 'groovy', label: 'Groovy' },
- { syntax: 'haml', label: 'HAML' },
- {
- syntax: 'handlebars',
- variants: 'hbs, html.hbs, html.handlebars, htmlbars',
- label: 'Handlebars',
- },
- { syntax: 'haskell', variants: 'hs', label: 'Haskell' },
- { syntax: 'haxe', variants: 'hx', label: 'Haxe' },
- { syntax: 'hsp', label: 'HSP' },
- { syntax: 'http', variants: 'https', label: 'HTTP' },
- { syntax: 'hy', variants: 'hylang', label: 'Hy' },
- { syntax: 'inform7', variants: 'i7', label: 'Inform 7' },
- { syntax: 'ini', variants: 'toml', label: 'TOML, also INI' },
- { syntax: 'irpf90', label: 'IRPF90' },
- { syntax: 'isbl', label: 'ISBL' },
- { syntax: 'java', variants: 'jsp', label: 'Java' },
- { syntax: 'javascript', variants: 'js, jsx, mjs, cjs', label: 'Javascript' },
- { syntax: 'jboss-cli', variants: 'wildfly-cli', label: 'JBoss CLI' },
- { syntax: 'json', label: 'JSON' },
- { syntax: 'julia', label: 'Julia' },
- { syntax: 'julia-repl', variants: 'jldoctest', label: 'Julia REPL' },
- { syntax: 'kotlin', variants: 'kt, kts', label: 'Kotlin' },
- { syntax: 'lasso', variants: 'ls, lassoscript', label: 'Lasso' },
- { syntax: 'latex', variants: 'tex', label: 'LaTeX' },
- { syntax: 'ldif', label: 'LDIF' },
- { syntax: 'leaf', label: 'Leaf' },
- { syntax: 'less', label: 'Less' },
- { syntax: 'lisp', label: 'Lisp' },
- { syntax: 'livecodeserver', label: 'LiveCode' },
- { syntax: 'livescript', variants: 'ls', label: 'LiveScript' },
- { syntax: 'llvm', label: 'LLVM IR' },
- { syntax: 'lsl', label: 'LSL (Linden Scripting Language)' },
- { syntax: 'lua', label: 'Lua' },
- { syntax: 'makefile', variants: 'mk, mak, make', label: 'Makefile' },
- { syntax: 'markdown', variants: 'md, mkdown, mkd', label: 'Markdown' },
- { syntax: 'mathematica', variants: 'mma, wl', label: 'Mathematica' },
- { syntax: 'matlab', label: 'Matlab' },
- { syntax: 'maxima', label: 'Maxima' },
- { syntax: 'mel', label: 'MEL' },
- { syntax: 'mercury', variants: 'm, moo', label: 'Mercury' },
- { syntax: 'mipsasm', variants: 'mips', label: 'MIPS Assembly' },
- { syntax: 'mizar', label: 'Mizar' },
- { syntax: 'mojolicious', label: 'Mojolicious' },
- { syntax: 'monkey', label: 'Monkey' },
- { syntax: 'moonscript', variants: 'moon', label: 'MoonScript' },
- { syntax: 'n1ql', label: 'N1QL' },
- { syntax: 'nestedtext', variants: 'nt', label: 'Nested Text' },
- { syntax: 'nginx', variants: 'nginxconf', label: 'Nginx config' },
- { syntax: 'nim', label: 'Nim' },
- { syntax: 'nix', variants: 'nixos', label: 'Nix' },
- { syntax: 'node-repl', label: 'Node REPL' },
- { syntax: 'nsis', label: 'NSIS' },
- {
- syntax: 'objectivec',
- variants: 'mm, objc, obj-c, obj-c++, objective-c++',
- label: 'Objective-C',
- },
- { syntax: 'ocaml', variants: 'ml', label: 'OCaml' },
- { syntax: 'openscad', variants: 'scad', label: 'OpenSCAD' },
- { syntax: 'oxygene', label: 'Oxygene' },
- { syntax: 'parser3', label: 'Parser3' },
- { syntax: 'perl', variants: 'pl, pm', label: 'Perl' },
- { syntax: 'pf', variants: 'pf.conf', label: 'Packet Filter config' },
- { syntax: 'pgsql', variants: 'postgres, postgresql', label: 'PostgreSQL' },
- { syntax: 'php', label: 'PHP' },
- { syntax: 'php-template', label: 'PHP template' },
- { syntax: 'plaintext', variants: 'text, txt', label: 'Plain text' },
- { syntax: 'pony', label: 'Pony' },
- { syntax: 'powershell', variants: 'pwsh, ps, ps1', label: 'PowerShell' },
- { syntax: 'processing', variants: 'pde', label: 'Processing' },
- { syntax: 'profile', label: 'Python profiler' },
- { syntax: 'prolog', label: 'Prolog' },
- { syntax: 'properties', label: '.properties' },
- { syntax: 'protobuf', label: 'Protocol Buffers' },
- { syntax: 'puppet', variants: 'pp', label: 'Puppet' },
- { syntax: 'purebasic', variants: 'pb, pbi', label: 'PureBASIC' },
- { syntax: 'python', variants: 'py, gyp, ipython', label: 'Python' },
- { syntax: 'python-repl', variants: 'pycon', label: 'Python REPL' },
- { syntax: 'q', variants: 'k, kdb', label: 'Q' },
- { syntax: 'qml', variants: 'qt', label: 'QML' },
- { syntax: 'r', label: 'R' },
- { syntax: 'reasonml', variants: 're', label: 'ReasonML' },
- { syntax: 'rib', label: 'RenderMan RIB' },
- { syntax: 'roboconf', variants: 'graph, instances', label: 'Roboconf' },
- { syntax: 'routeros', variants: 'mikrotik', label: 'Microtik RouterOS script' },
- { syntax: 'rsl', label: 'RenderMan RSL' },
- { syntax: 'ruby', variants: 'rb, gemspec, podspec, thor, irb', label: 'Ruby' },
- { syntax: 'ruleslanguage', label: 'Oracle Rules Language' },
- { syntax: 'rust', variants: 'rs', label: 'Rust' },
- { syntax: 'sas', label: 'SAS' },
- { syntax: 'scala', label: 'Scala' },
- { syntax: 'scheme', label: 'Scheme' },
- { syntax: 'scilab', variants: 'sci', label: 'Scilab' },
- { syntax: 'scss', label: 'SCSS' },
- { syntax: 'shell', variants: 'console, shellsession', label: 'Shell Session' },
- { syntax: 'smali', label: 'Smali' },
- { syntax: 'smalltalk', variants: 'st', label: 'Smalltalk' },
- { syntax: 'sml', variants: 'ml', label: 'SML (Standard ML)' },
- { syntax: 'sqf', label: 'SQF' },
- { syntax: 'sql', label: 'SQL' },
- { syntax: 'stan', variants: 'stanfuncs', label: 'Stan' },
- { syntax: 'stata', variants: 'do, ado', label: 'Stata' },
- { syntax: 'step21', variants: 'p21, step, stp', label: 'STEP Part 21' },
- { syntax: 'stylus', variants: 'styl', label: 'Stylus' },
- { syntax: 'subunit', label: 'SubUnit' },
- { syntax: 'swift', label: 'Swift' },
- { syntax: 'taggerscript', label: 'Tagger Script' },
- { syntax: 'tap', label: 'Test Anything Protocol' },
- { syntax: 'tcl', variants: 'tk', label: 'Tcl' },
- { syntax: 'thrift', label: 'Thrift' },
- { syntax: 'tp', label: 'TP' },
- { syntax: 'twig', variants: 'craftcms', label: 'Twig' },
- { syntax: 'typescript', variants: 'ts, tsx', label: 'TypeScript' },
- { syntax: 'vala', label: 'Vala' },
- { syntax: 'vbnet', variants: 'vb', label: 'Visual Basic .NET' },
- { syntax: 'vbscript', variants: 'vbs', label: 'VBScript' },
- { syntax: 'vbscript-html', label: 'VBScript in HTML' },
- { syntax: 'verilog', variants: 'v, sv, svh', label: 'Verilog' },
- { syntax: 'vhdl', label: 'VHDL' },
- { syntax: 'vim', label: 'Vim Script' },
- { syntax: 'wasm', label: 'WebAssembly' },
- { syntax: 'wren', label: 'Wren' },
- { syntax: 'x86asm', label: 'Intel x86 Assembly' },
- { syntax: 'xl', variants: 'tao', label: 'XL' },
- {
- syntax: 'xml',
- variants: 'html, xhtml, rss, atom, xjb, xsd, xsl, plist, wsf, svg',
- label: 'HTML, XML',
- },
- { syntax: 'xquery', variants: 'xpath, xq', label: 'XQuery' },
- { syntax: 'yaml', variants: 'yml', label: 'YAML' },
- { syntax: 'zephir', variants: 'zep', label: 'Zephir' },
-];
-/* eslint-enable @gitlab/require-i18n-strings */
+import CODE_BLOCK_LANGUAGES from '../constants/code_block_languages';
const codeBlockLanguageLoader = {
lowlight,
diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
index 4c7b8e8f667..cd726818031 100644
--- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
@@ -1,42 +1,33 @@
<script>
-import { GlIcon } from '@gitlab/ui';
-import { mapState, mapActions } from 'vuex';
+import { GlTooltipDirective, GlSafeHtmlDirective, GlIcon, GlLoadingIcon } from '@gitlab/ui';
+import { mapActions } from 'vuex';
import createFlash from '~/flash';
import { s__, sprintf } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { UNFOLD_COUNT, INLINE_DIFF_VIEW_TYPE, INLINE_DIFF_LINES_KEY } from '../constants';
+import { UNFOLD_COUNT, INLINE_DIFF_LINES_KEY } from '../constants';
import * as utils from '../store/utils';
const EXPAND_ALL = 0;
const EXPAND_UP = 1;
const EXPAND_DOWN = 2;
-const lineNumberByViewType = (viewType, diffLine) => {
- const numberGetters = {
- [INLINE_DIFF_VIEW_TYPE]: (line) => line?.new_line,
- };
- const numberGetter = numberGetters[viewType];
- return numberGetter && numberGetter(diffLine);
-};
-
-const i18n = {
- showMore: sprintf(s__('Diffs|Show %{unfoldCount} lines'), { unfoldCount: UNFOLD_COUNT }),
- showAll: s__('Diffs|Show all unchanged lines'),
-};
-
export default {
- i18n,
+ i18n: {
+ showMore: sprintf(s__('Diffs|Show %{unfoldCount} lines'), { unfoldCount: UNFOLD_COUNT }),
+ showAll: s__('Diffs|Show all unchanged lines'),
+ },
components: {
GlIcon,
+ GlLoadingIcon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ SafeHtml: GlSafeHtmlDirective,
},
mixins: [glFeatureFlagsMixin()],
props: {
- fileHash: {
- type: String,
- required: true,
- },
- contextLinesPath: {
- type: String,
+ file: {
+ type: Object,
required: true,
},
line: {
@@ -53,34 +44,45 @@ export default {
required: false,
default: false,
},
+ inline: {
+ type: Boolean,
+ required: true,
+ },
+ lineCountBetween: {
+ type: Number,
+ required: false,
+ default: -1,
+ },
+ },
+ data() {
+ return { loading: { up: false, down: false, all: false } };
},
computed: {
- ...mapState({
- diffFiles: (state) => state.diffs.diffFiles,
- }),
canExpandUp() {
return !this.isBottom;
},
canExpandDown() {
return this.isBottom || !this.isTop;
},
- },
- created() {
- this.EXPAND_DOWN = EXPAND_DOWN;
- this.EXPAND_UP = EXPAND_UP;
+ isLineCountSmall() {
+ return this.lineCountBetween >= 20 || this.lineCountBetween === -1;
+ },
+ showExpandDown() {
+ return this.canExpandDown && this.isLineCountSmall;
+ },
+ showExpandUp() {
+ return this.canExpandUp && this.isLineCountSmall;
+ },
},
methods: {
...mapActions('diffs', ['loadMoreLines']),
getPrevLineNumber(oldLineNumber, newLineNumber) {
- const diffFile = utils.findDiffFile(this.diffFiles, this.fileHash);
- const index = utils.getPreviousLineIndex(INLINE_DIFF_VIEW_TYPE, diffFile, {
+ const index = utils.getPreviousLineIndex(this.file, {
oldLineNumber,
newLineNumber,
});
- return (
- lineNumberByViewType(INLINE_DIFF_VIEW_TYPE, diffFile[INLINE_DIFF_LINES_KEY][index - 2]) || 0
- );
+ return this.file[INLINE_DIFF_LINES_KEY][index - 2]?.new_line || 0;
},
callLoadMoreLines(
endpoint,
@@ -99,6 +101,9 @@ export default {
message: s__('Diffs|Something went wrong while fetching diff lines.'),
});
this.isRequesting = false;
+ })
+ .finally(() => {
+ this.loading = { up: false, down: false, all: false };
});
},
handleExpandLines(type = EXPAND_ALL) {
@@ -107,25 +112,26 @@ export default {
}
this.isRequesting = true;
- const endpoint = this.contextLinesPath;
- const { fileHash } = this;
- const view = INLINE_DIFF_VIEW_TYPE;
+ const endpoint = this.file.context_lines_path;
const oldLineNumber = this.line.meta_data.old_pos || 0;
const newLineNumber = this.line.meta_data.new_pos || 0;
const offset = newLineNumber - oldLineNumber;
- const expandOptions = { endpoint, fileHash, view, oldLineNumber, newLineNumber, offset };
+ const expandOptions = { endpoint, oldLineNumber, newLineNumber, offset };
if (type === EXPAND_UP) {
+ this.loading.up = true;
this.handleExpandUpLines(expandOptions);
} else if (type === EXPAND_DOWN) {
+ this.loading.down = true;
this.handleExpandDownLines(expandOptions);
} else {
+ this.loading.all = true;
this.handleExpandAllLines(expandOptions);
}
},
handleExpandUpLines(expandOptions) {
- const { endpoint, fileHash, view, oldLineNumber, newLineNumber, offset } = expandOptions;
+ const { endpoint, oldLineNumber, newLineNumber, offset } = expandOptions;
const bottom = this.isBottom;
const lineNumber = newLineNumber - 1;
@@ -139,15 +145,13 @@ export default {
unfold = false;
}
- const params = { since, to, bottom, offset, unfold, view };
+ const params = { since, to, bottom, offset, unfold };
const lineNumbers = { oldLineNumber, newLineNumber };
- this.callLoadMoreLines(endpoint, params, lineNumbers, fileHash);
+ this.callLoadMoreLines(endpoint, params, lineNumbers, this.file.file_hash);
},
handleExpandDownLines(expandOptions) {
const {
endpoint,
- fileHash,
- view,
oldLineNumber: metaOldPos,
newLineNumber: metaNewPos,
offset,
@@ -183,19 +187,19 @@ export default {
}
}
- const params = { since, to, bottom, offset, unfold, view };
+ const params = { since, to, bottom, offset, unfold };
const lineNumbers = { oldLineNumber, newLineNumber };
this.callLoadMoreLines(
endpoint,
params,
lineNumbers,
- fileHash,
+ this.file.file_hash,
isExpandDown,
nextLineNumbers,
);
},
handleExpandAllLines(expandOptions) {
- const { endpoint, fileHash, view, oldLineNumber, newLineNumber, offset } = expandOptions;
+ const { endpoint, oldLineNumber, newLineNumber, offset } = expandOptions;
const bottom = this.isBottom;
const unfold = false;
let since;
@@ -213,21 +217,71 @@ export default {
to = newLineNumber - 1;
}
- const params = { since, to, bottom, offset, unfold, view };
+ const params = { since, to, bottom, offset, unfold };
const lineNumbers = { oldLineNumber, newLineNumber };
- this.callLoadMoreLines(endpoint, params, lineNumbers, fileHash);
+ this.callLoadMoreLines(endpoint, params, lineNumbers, this.file.file_hash);
},
},
+ EXPAND_DOWN,
+ EXPAND_UP,
};
</script>
<template>
- <div class="content js-line-expansion-content">
+ <div
+ v-if="glFeatures.updatedDiffExpansionButtons"
+ class="diff-grid-row diff-grid-row-full diff-tr line_holder match expansion"
+ >
+ <div :class="{ parallel: !inline }" class="diff-grid-left diff-grid-2-col left-side">
+ <div
+ class="diff-td diff-line-num gl-text-center! gl-p-0! gl-w-full! gl-display-flex gl-flex-direction-column"
+ >
+ <button
+ v-if="showExpandDown"
+ v-gl-tooltip
+ :title="s__('Diffs|Next 20 lines')"
+ type="button"
+ class="js-unfold-down gl-rounded-0 gl-border-0 diff-line-expand-button"
+ @click="handleExpandLines($options.EXPAND_DOWN)"
+ >
+ <gl-loading-icon v-if="loading.down" size="sm" color="dark" inline />
+ <gl-icon v-else name="expand-down" />
+ </button>
+ <button
+ v-if="lineCountBetween !== -1 && lineCountBetween < 20"
+ v-gl-tooltip
+ :title="s__('Diffs|Expand all lines')"
+ type="button"
+ class="js-unfold-all gl-rounded-0 gl-border-0 diff-line-expand-button"
+ @click="handleExpandLines()"
+ >
+ <gl-loading-icon v-if="loading.all" size="sm" color="dark" inline />
+ <gl-icon v-else name="expand" />
+ </button>
+ <button
+ v-if="showExpandUp"
+ v-gl-tooltip
+ :title="s__('Diffs|Previous 20 lines')"
+ type="button"
+ class="js-unfold gl-rounded-0 gl-border-0 diff-line-expand-button"
+ @click="handleExpandLines($options.EXPAND_UP)"
+ >
+ <gl-loading-icon v-if="loading.up" size="sm" color="dark" inline />
+ <gl-icon v-else name="expand-up" />
+ </button>
+ </div>
+ <div
+ v-safe-html="line.rich_text"
+ class="gl-display-flex! gl-flex-direction-column gl-justify-content-center diff-td line_content left-side gl-white-space-normal!"
+ ></div>
+ </div>
+ </div>
+ <div v-else class="content js-line-expansion-content">
<button
type="button"
:disabled="!canExpandDown"
class="js-unfold-down gl-mx-2 gl-py-4 gl-cursor-pointer"
- @click="handleExpandLines(EXPAND_DOWN)"
+ @click="handleExpandLines($options.EXPAND_DOWN)"
>
<gl-icon :size="12" name="expand-down" />
<span>{{ $options.i18n.showMore }}</span>
@@ -244,7 +298,7 @@ export default {
type="button"
:disabled="!canExpandUp"
class="js-unfold gl-mx-2 gl-py-4 gl-cursor-pointer"
- @click="handleExpandLines(EXPAND_UP)"
+ @click="handleExpandLines($options.EXPAND_UP)"
>
<gl-icon :size="12" name="expand-up" />
<span>{{ $options.i18n.showMore }}</span>
diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue
index 4893803a3b6..1b07b00d725 100644
--- a/app/assets/javascripts/diffs/components/diff_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_row.vue
@@ -160,7 +160,13 @@ export default {
<!-- eslint-disable-next-line vue/no-deprecated-functional-template -->
<template functional>
- <div :class="$options.classNameMap(props)" class="diff-grid-row diff-tr line_holder">
+ <div
+ :class="[
+ $options.classNameMap(props),
+ { expansion: props.line.left && props.line.left.type === 'expanded' },
+ ]"
+ class="diff-grid-row diff-tr line_holder"
+ >
<div
:id="props.line.left && props.line.left.line_code"
data-testid="left-side"
diff --git a/app/assets/javascripts/diffs/components/diff_row_utils.js b/app/assets/javascripts/diffs/components/diff_row_utils.js
index 99999445c43..f610ac979ca 100644
--- a/app/assets/javascripts/diffs/components/diff_row_utils.js
+++ b/app/assets/javascripts/diffs/components/diff_row_utils.js
@@ -10,6 +10,7 @@ import {
CONFLICT_MARKER_THEIR,
CONFLICT_THEIR,
CONFLICT_OUR,
+ EXPANDED_LINE_TYPE,
} from '../constants';
export const isHighlighted = (highlightedRow, line, isCommented) => {
@@ -118,10 +119,12 @@ export const mapParallel = (content) => (line) => {
if (right) {
right = {
...right,
- renderDiscussion: Boolean(hasExpandedDiscussionOnRight && right.type),
+ renderDiscussion: Boolean(
+ hasExpandedDiscussionOnRight && right.type && right.type !== EXPANDED_LINE_TYPE,
+ ),
hasDraft: content.hasParallelDraftRight(content.diffFile.file_hash, line),
lineDraft: content.draftForLine(content.diffFile.file_hash, line, 'right'),
- hasCommentForm: Boolean(right.hasForm && right.type),
+ hasCommentForm: Boolean(right.hasForm && right.type && right.type !== EXPANDED_LINE_TYPE),
emptyCellClassMap: { conflict_their: line.left?.type === CONFLICT_OUR },
addCommentTooltip: addCommentTooltip(line.right),
};
diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue
index f46b0a538f1..529f8e0a2f9 100644
--- a/app/assets/javascripts/diffs/components/diff_view.vue
+++ b/app/assets/javascripts/diffs/components/diff_view.vue
@@ -141,6 +141,18 @@ export default {
table.classList.add(`${lineClass}-selected`);
}
},
+ getCountBetweenIndex(index) {
+ if (index === 0) {
+ return -1;
+ } else if (!this.diffLines[index + 1]) {
+ return -1;
+ }
+
+ return (
+ Number(this.diffLines[index + 1].left.new_line) -
+ Number(this.diffLines[index - 1].left.new_line)
+ );
+ },
},
userColorScheme: window.gon.user_color_scheme,
};
@@ -158,38 +170,51 @@ export default {
>
<template v-for="(line, index) in diffLines">
<template v-if="line.isMatchLineLeft || line.isMatchLineRight">
- <div :key="`expand-${index}`" class="diff-tr line_expansion match">
- <div class="diff-td text-center gl-font-regular">
- <diff-expansion-cell
- :file-hash="diffFile.file_hash"
- :context-lines-path="diffFile.context_lines_path"
- :line="line.left"
- :is-top="index === 0"
- :is-bottom="index + 1 === diffLinesLength"
- />
+ <diff-expansion-cell
+ v-if="glFeatures.updatedDiffExpansionButtons"
+ :key="`expand-${index}`"
+ :file="diffFile"
+ :line="line.left"
+ :is-top="index === 0"
+ :is-bottom="index + 1 === diffLinesLength"
+ :inline="inline"
+ :line-count-between="getCountBetweenIndex(index)"
+ />
+ <template v-else>
+ <div :key="`expand-${index}`" class="diff-tr line_expansion old-line_expansion match">
+ <div class="diff-td text-center gl-font-regular">
+ <diff-expansion-cell
+ :file="diffFile"
+ :context-lines-path="diffFile.context_lines_path"
+ :line="line.left"
+ :is-top="index === 0"
+ :is-bottom="index + 1 === diffLinesLength"
+ :inline="inline"
+ />
+ </div>
</div>
- </div>
- <div
- v-if="line.left.rich_text"
- :key="`expand-definition-${index}`"
- class="diff-grid-row diff-tr line_holder match"
- >
- <div class="diff-grid-left diff-grid-3-col left-side">
- <div class="diff-td diff-line-num"></div>
- <div v-if="inline" class="diff-td diff-line-num"></div>
- <div
- v-safe-html="line.left.rich_text"
- class="diff-td line_content left-side gl-white-space-normal!"
- ></div>
+ <div
+ v-if="line.left.rich_text"
+ :key="`expand-definition-${index}`"
+ class="diff-grid-row diff-tr line_holder match"
+ >
+ <div class="diff-grid-left diff-grid-3-col left-side">
+ <div class="diff-td diff-line-num"></div>
+ <div v-if="inline" class="diff-td diff-line-num"></div>
+ <div
+ v-safe-html="line.left.rich_text"
+ class="diff-td line_content left-side gl-white-space-normal!"
+ ></div>
+ </div>
+ <div v-if="!inline" class="diff-grid-right diff-grid-3-col right-side">
+ <div class="diff-td diff-line-num"></div>
+ <div
+ v-safe-html="line.left.rich_text"
+ class="diff-td line_content right-side gl-white-space-normal!"
+ ></div>
+ </div>
</div>
- <div v-if="!inline" class="diff-grid-right diff-grid-3-col right-side">
- <div class="diff-td diff-line-num"></div>
- <div
- v-safe-html="line.left.rich_text"
- class="diff-td line_content right-side gl-white-space-normal!"
- ></div>
- </div>
- </div>
+ </template>
</template>
<diff-row
v-if="!line.isMatchLineLeft && !line.isMatchLineRight"
diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js
index bbe27c0dbd6..f4b6bd85b84 100644
--- a/app/assets/javascripts/diffs/constants.js
+++ b/app/assets/javascripts/diffs/constants.js
@@ -1,6 +1,7 @@
export const INLINE_DIFF_VIEW_TYPE = 'inline';
export const PARALLEL_DIFF_VIEW_TYPE = 'parallel';
export const MATCH_LINE_TYPE = 'match';
+export const EXPANDED_LINE_TYPE = 'expanded';
export const OLD_NO_NEW_LINE_TYPE = 'old-nonewline';
export const NEW_NO_NEW_LINE_TYPE = 'new-nonewline';
export const CONTEXT_LINE_TYPE = 'context';
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index fb35114c0a9..d2b798245fc 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -4,6 +4,7 @@ import {
DIFF_FILE_MANUAL_COLLAPSE,
DIFF_FILE_AUTOMATIC_COLLAPSE,
INLINE_DIFF_LINES_KEY,
+ EXPANDED_LINE_TYPE,
} from '../constants';
import * as types from './mutation_types';
import {
@@ -131,6 +132,7 @@ export default {
: line.line_code || `${fileHash}_${line.old_line}_${line.new_line}`;
return {
...line,
+ type: line.type || EXPANDED_LINE_TYPE,
line_code: lineCode,
discussions: line.discussions || [],
hasForm: false,
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index 4526a34a2bd..5656416cf2b 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -15,13 +15,15 @@ import {
CONFLICT_MARKER,
CONFLICT_MARKER_OUR,
CONFLICT_MARKER_THEIR,
+ EXPANDED_LINE_TYPE,
} from '../constants';
import { prepareRawDiffFile } from '../utils/diff_file';
export const isAdded = (line) => ['new', 'new-nonewline'].includes(line.type);
export const isRemoved = (line) => ['old', 'old-nonewline'].includes(line.type);
export const isUnchanged = (line) => !line.type;
-export const isMeta = (line) => ['match', 'new-nonewline', 'old-nonewline'].includes(line.type);
+export const isMeta = (line) =>
+ ['match', EXPANDED_LINE_TYPE, 'new-nonewline', 'old-nonewline'].includes(line.type);
export const isConflictMarker = (line) =>
[CONFLICT_MARKER_OUR, CONFLICT_MARKER_THEIR].includes(line.type);
export const isConflictSeperator = (line) => line.type === CONFLICT_MARKER;
@@ -205,7 +207,7 @@ export const findIndexInInlineLines = (lines, lineNumbers) => {
);
};
-export const getPreviousLineIndex = (diffViewType, file, lineNumbers) => {
+export const getPreviousLineIndex = (file, lineNumbers) => {
return findIndexInInlineLines(file[INLINE_DIFF_LINES_KEY], lineNumbers);
};
diff --git a/app/assets/stylesheets/framework/broadcast_messages.scss b/app/assets/stylesheets/framework/broadcast_messages.scss
index 58f986ec0ae..90a7e2c2da7 100644
--- a/app/assets/stylesheets/framework/broadcast_messages.scss
+++ b/app/assets/stylesheets/framework/broadcast_messages.scss
@@ -19,6 +19,11 @@
p {
margin-bottom: 0;
}
+
+ a {
+ color: inherit;
+ text-decoration: underline;
+ }
}
.broadcast-notification-message {
diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss
index f0495fdc94e..6c14eeafc0b 100644
--- a/app/assets/stylesheets/framework/diffs.scss
+++ b/app/assets/stylesheets/framework/diffs.scss
@@ -582,25 +582,6 @@ table.code {
}
}
-.diff-expansion-cell {
- flex: 1 1;
- min-width: max-content;
-}
-
-.diff-expansion-cell-middle {
- flex: 0 1 max-content;
-}
-
-@media only screen and (min-width: $breakpoint-xl) {
- .diff-expansion-cell-start {
- text-align: right;
- }
-
- .diff-expansion-cell-end {
- text-align: left;
- }
-}
-
// Merge request diff grid layout
.diff-grid {
.diff-td {
@@ -612,6 +593,10 @@ table.code {
.diff-grid-row {
display: grid;
grid-template-columns: 1fr 1fr;
+
+ &.diff-grid-row-full {
+ grid-template-columns: 1fr;
+ }
}
.diff-grid-left,
@@ -626,6 +611,14 @@ table.code {
grid-template-columns: 50px 1fr !important;
}
+ .diff-grid-2-col {
+ grid-template-columns: 100px 1fr !important;
+
+ &.parallel {
+ grid-template-columns: 50px 1fr !important;
+ }
+ }
+
&.inline-diff-view .diff-grid-3-col {
grid-template-columns: 50px 50px 1fr !important;
}
@@ -1209,3 +1202,10 @@ table.code {
position: absolute;
bottom: 100vh;
}
+
+.diff-line-expand-button {
+ &:hover,
+ &:focus {
+ @include gl-bg-gray-200;
+ }
+}
diff --git a/app/assets/stylesheets/highlight/common.scss b/app/assets/stylesheets/highlight/common.scss
index bd327082e20..9d479df64c0 100644
--- a/app/assets/stylesheets/highlight/common.scss
+++ b/app/assets/stylesheets/highlight/common.scss
@@ -19,7 +19,17 @@
background: $dark-diff-match-color;
}
-@mixin diff-expansion($background, $border, $link) {
+@mixin diff-expansion($background, $color, $hover-background, $hover-color) {
+ background-color: $background;
+ color: $color;
+
+ &:hover {
+ background-color: $hover-background;
+ color: $hover-color;
+ }
+}
+
+@mixin old-diff-expansion($background, $border, $link) {
background-color: $background;
.diff-td,
@@ -49,6 +59,13 @@
}
}
+
+@mixin dark-diff-expansion-line {
+ &.expansion .diff-td {
+ background-color: $dark-diff-match-color;
+ }
+}
+
@mixin line-coverage-border-color($coverage, $no-coverage) {
transition: border-left 0.1s ease-out;
diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss
index c51b1f04757..0eeebdb2e7a 100644
--- a/app/assets/stylesheets/highlight/themes/dark.scss
+++ b/app/assets/stylesheets/highlight/themes/dark.scss
@@ -154,8 +154,12 @@ $dark-il: #de935f;
color: $dark-line-color;
}
- .line_expansion {
- @include diff-expansion($dark-main-bg, $dark-border, $dark-na);
+ .old-line_expansion {
+ @include old-diff-expansion($dark-main-bg, $dark-border, $dark-na);
+ }
+
+ .diff-line-expand-button {
+ @include diff-expansion($gray-600, $gray-200, $gray-300, $white);
}
// Diff line
@@ -166,6 +170,10 @@ $dark-il: #de935f;
@include dark-diff-match-line;
}
+ &.diff-grid-row {
+ @include dark-diff-expansion-line;
+ }
+
.diff-td.diff-line-num.hll:not(.empty-cell),
.diff-td.line-coverage.hll:not(.empty-cell),
.diff-td.line-codequality.hll:not(.empty-cell),
diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss
index 270f81c5cba..b8cd97d6504 100644
--- a/app/assets/stylesheets/highlight/themes/monokai.scss
+++ b/app/assets/stylesheets/highlight/themes/monokai.scss
@@ -125,8 +125,12 @@ $monokai-gh: #75715e;
color: $monokai-text-color;
}
- .line_expansion {
- @include diff-expansion($monokai-bg, $monokai-border, $monokai-k);
+ .old-line_expansion {
+ @include old-diff-expansion($monokai-bg, $monokai-border, $monokai-k);
+ }
+
+ .diff-line-expand-button {
+ @include diff-expansion($gray-600, $gray-200, $gray-300, $white);
}
// Diff line
@@ -137,6 +141,10 @@ $monokai-gh: #75715e;
@include dark-diff-match-line;
}
+ &.diff-grid-row {
+ @include dark-diff-expansion-line;
+ }
+
.diff-td.diff-line-num.hll:not(.empty-cell),
.diff-td.line-coverage.hll:not(.empty-cell),
.diff-td.line-codequality.hll:not(.empty-cell),
diff --git a/app/assets/stylesheets/highlight/themes/none.scss b/app/assets/stylesheets/highlight/themes/none.scss
index 7a36aba8be7..99a3de23c26 100644
--- a/app/assets/stylesheets/highlight/themes/none.scss
+++ b/app/assets/stylesheets/highlight/themes/none.scss
@@ -44,10 +44,15 @@
color: $gl-text-color;
}
- .line_expansion {
- @include diff-expansion($gray-light, $white-normal, $gl-text-color);
+ .old-line_expansion {
+ @include old-diff-expansion($gray-light, $white-normal, $gl-text-color);
}
+ .diff-line-expand-button {
+ @include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800);
+ }
+
+
// Diff line
$none-expanded-border: #e0e0e0;
$none-expanded-bg: #e0e0e0;
diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
index d01706446c0..55d17b8f1d2 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-dark.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
@@ -128,8 +128,12 @@ $solarized-dark-il: #2aa198;
color: $solarized-dark-pre-color;
}
- .line_expansion {
- @include diff-expansion($solarized-dark-line-bg, $solarized-dark-border, $solarized-dark-kd);
+ .old-line_expansion {
+ @include old-diff-expansion($solarized-dark-line-bg, $solarized-dark-border, $solarized-dark-kd);
+ }
+
+ .diff-line-expand-button {
+ @include diff-expansion(lighten($solarized-dark-pre-bg, 10%), $gray-200, lighten($solarized-dark-pre-bg, 20%), $white);
}
// Diff line
@@ -140,6 +144,10 @@ $solarized-dark-il: #2aa198;
@include dark-diff-match-line;
}
+ &.diff-grid-row {
+ @include dark-diff-expansion-line;
+ }
+
.diff-td.diff-line-num.hll:not(.empty-cell),
.diff-td.line-coverage.hll:not(.empty-cell),
.diff-td.line-codequality.hll:not(.empty-cell),
diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss
index a4ce29b7bad..72b961097e4 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-light.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss
@@ -134,9 +134,13 @@ $solarized-light-il: #2aa198;
background-color: $solarized-light-pre-bg;
color: $solarized-light-pre-color;
}
+
+ .old-line_expansion {
+ @include old-diff-expansion($solarized-light-line-bg, $solarized-light-border, $solarized-light-kd);
+ }
- .line_expansion {
- @include diff-expansion($solarized-light-line-bg, $solarized-light-border, $solarized-light-kd);
+ .diff-line-expand-button {
+ @include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800);
}
// Diff line
@@ -147,6 +151,10 @@ $solarized-light-il: #2aa198;
@include match-line;
}
+ &.diff-grid-row.expansion .diff-td {
+ background-color: $solarized-light-matchline-bg;
+ }
+
.diff-td.diff-line-num.hll:not(.empty-cell),
.diff-td.line-coverage.hll:not(.empty-cell),
.diff-td.line-codequality.hll:not(.empty-cell),
diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss
index 20a36d2e8b1..b984c194033 100644
--- a/app/assets/stylesheets/highlight/white_base.scss
+++ b/app/assets/stylesheets/highlight/white_base.scss
@@ -77,6 +77,22 @@ $white-gc-bg: #eaf2f5;
background-color: $gray-light;
}
+@mixin diff-match-line {
+ &.expansion {
+ &.match .diff-td {
+ color: $gray-400;
+ }
+
+ .diff-td {
+ background-color: $gray-50;
+
+ &:first-child {
+ border-color: $gray-100;
+ }
+ }
+ }
+}
+
// Line numbers
.file-line-num {
@include line-number-link($black-transparent);
@@ -117,8 +133,8 @@ pre.code,
color: $white-code-color;
}
-.line_expansion {
- @include diff-expansion($gray-light, $border-color, $blue-600);
+.old-line_expansion {
+ @include old-diff-expansion($gray-light, $border-color, $blue-600);
&.diff-tr:last-child {
border-bottom-right-radius: 4px;
@@ -130,6 +146,10 @@ pre.code,
}
}
+.diff-line-expand-button {
+ @include diff-expansion($gray-100, $gray-700, $gray-200, $gray-800);
+}
+
// Diff line
.line_holder {
&.match .line_content,
@@ -138,6 +158,10 @@ pre.code,
@include match-line;
}
+ &.diff-grid-row {
+ @include diff-match-line;
+ }
+
&:not(.match) .diff-grid-left:hover,
&:not(.match) .diff-grid-right:hover,
&.code-search-line:hover {
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 47f82471937..4e6e23ad4e6 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -44,6 +44,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:secure_vulnerability_training, project, default_enabled: :yaml)
push_frontend_feature_flag(:issue_assignees_widget, @project, default_enabled: :yaml)
push_frontend_feature_flag(:realtime_labels, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:updated_diff_expansion_buttons, project, default_enabled: :yaml)
end
before_action do
diff --git a/app/serializers/ci/job_entity.rb b/app/serializers/ci/job_entity.rb
index fca3dec74d4..b6b11e54a16 100644
--- a/app/serializers/ci/job_entity.rb
+++ b/app/serializers/ci/job_entity.rb
@@ -8,6 +8,7 @@ module Ci
expose :name
expose :started?, as: :started
+ expose :started_at, if: -> (job) { job.started? }
expose :complete?, as: :complete
expose :archived?, as: :archived
diff --git a/app/views/shared/snippets/_snippet.html.haml b/app/views/shared/snippets/_snippet.html.haml
index 4e373dda013..3cd70dab4d5 100644
--- a/app/views/shared/snippets/_snippet.html.haml
+++ b/app/views/shared/snippets/_snippet.html.haml
@@ -4,21 +4,20 @@
%li.snippet-row.py-3{ data: { qa_selector: 'snippet_link', qa_snippet_title: snippet.title } }
= image_tag avatar_icon_for_user(snippet.author), class: "avatar s40 d-none d-sm-block", alt: ''
- .title
- = link_to gitlab_snippet_path(snippet) do
- = snippet.title
+ = link_to gitlab_snippet_path(snippet), class: "title" do
+ = snippet.title
- %ul.controls{ data: { qa_selector: 'snippet_file_count_content', qa_snippet_files: snippet.statistics&.file_count } }
- %li
- = snippet_file_count(snippet)
- %li
- = link_to gitlab_snippet_path(snippet, anchor: 'notes'), class: ('no-comments' if notes_count == 0) do
- = sprite_icon('comments', css_class: 'gl-vertical-align-text-bottom')
- = notes_count
- %li
- %span.sr-only{ data: { qa_selector: 'snippet_visibility_content', qa_snippet_visibility: visibility_level_label(snippet.visibility_level) } }
- = visibility_level_label(snippet.visibility_level)
- = visibility_level_icon(snippet.visibility_level)
+ %ul.controls{ data: { qa_selector: 'snippet_file_count_content', qa_snippet_files: snippet.statistics&.file_count } }
+ %li
+ = snippet_file_count(snippet)
+ %li
+ = link_to gitlab_snippet_path(snippet, anchor: 'notes'), class: ('no-comments' if notes_count == 0) do
+ = sprite_icon('comments', css_class: 'gl-vertical-align-text-bottom')
+ = notes_count
+ %li
+ %span.sr-only{ data: { qa_selector: 'snippet_visibility_content', qa_snippet_visibility: visibility_level_label(snippet.visibility_level) } }
+ = visibility_level_label(snippet.visibility_level)
+ = visibility_level_icon(snippet.visibility_level)
.snippet-info
#{snippet.to_reference} &middot;
diff --git a/config/feature_flags/development/updated_diff_expansion_buttons.yml b/config/feature_flags/development/updated_diff_expansion_buttons.yml
new file mode 100644
index 00000000000..70efa024168
--- /dev/null
+++ b/config/feature_flags/development/updated_diff_expansion_buttons.yml
@@ -0,0 +1,8 @@
+---
+name: updated_diff_expansion_buttons
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80890
+rollout_issue_url:
+milestone: '14.10'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/data/deprecations/14-10-dependency-scanning-default-java-version.yml b/data/deprecations/14-10-dependency-scanning-default-java-version.yml
new file mode 100644
index 00000000000..4616592f00c
--- /dev/null
+++ b/data/deprecations/14-10-dependency-scanning-default-java-version.yml
@@ -0,0 +1,16 @@
+- name: "Dependency Scanning default Java version changed to 17"
+ announcement_milestone: "14.10"
+ announcement_date: "2022-04-22"
+ removal_milestone: "15.0"
+ removal_date: "2021-05-22"
+ breaking_change: true
+ reporter: NicoleSchwartz
+ body: |
+ In GitLab 15.0, for Dependency Scanning, the default version of Java will be updated to 17. This is the same as [the most up-to-date Long Term Support (LTS) version](https://en.wikipedia.org/wiki/Java_version_history). GitLab still [supports the same versions as it does today (8, 11, 13, 14, 15, 16, 17)](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning). Only the enabled default is changing. To change the default, set the `DS_Java_Version` variable.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-5-certificate-based-integration-with-kubernetes-saas.yml b/data/deprecations/14-5-certificate-based-integration-with-kubernetes-saas.yml
new file mode 100644
index 00000000000..ebc850a9529
--- /dev/null
+++ b/data/deprecations/14-5-certificate-based-integration-with-kubernetes-saas.yml
@@ -0,0 +1,17 @@
+- name: "SaaS certificate-based integration with Kubernetes"
+ announcement_milestone: "14.5"
+ announcement_date: "2021-11-15"
+ removal_milestone: "15.0"
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
+ breaking_change: true
+ body: |
+ The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab SaaS customer, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0.
+
+ For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the
+ [agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html)
+
+ For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
+ stage: Configure
+ tiers: [Free, Premium, Ultimate]
+ issue_url: 'https://gitlab.com/groups/gitlab-org/configure/-/epics/8'
+ documentation_url: 'https://docs.gitlab.com/ee/user/infrastructure/clusters/#certificate-based-kubernetes-integration-deprecated'
diff --git a/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml b/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
index 5cf9354cd05..c38da0e3c07 100644
--- a/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
+++ b/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
@@ -1,27 +1,21 @@
-- name: "Certificate-based integration with Kubernetes"
+- name: "Self-managed certificate-based integration with Kubernetes"
announcement_milestone: "14.5"
announcement_date: "2021-11-15"
removal_milestone: "15.6"
removal_date: "2022-11-22" # the date of the milestone release when this feature is planned to be removed
breaking_change: true
body: |
- [The certificate-based integration with Kubernetes will be deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
+ The certificate-based integration with Kubernetes [will be deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
- If you are a self-managed customer, in GitLab 15.0, a feature flag will be introduced so you can keep
- certificate-based integration enabled. The flag will be disabled by default.
- The flag and the related code will be removed in GitLab 15.6.
+ As a self-managed customer, we are introducing a feature flag in GitLab 15.0 so you can keep your certificate-based integration enabled. However, the feature flag will be disabled by default, so this change is a **breaking change**.
- Until the final removal in 15.6, features built on the integration will continue to work, and
- GitLab will continue to fix security and critical issues.
-
- If you use GitLab.com, certificate-based integrations will cease functioning in 15.0.
+ In GitLab 15.6 we will remove both the feature, and its related code. Until the final removal in 15.6, features built on this integration will continue to work, if you enable the feature flag. Until the feature is removed, GitLab will continue to fix security and critical issues as they arise.
For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the
- [agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab.
- See the documentation for [how to migrate](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html).
+ [agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html)
For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
stage: Configure
- tiers: [Free, Silver, Gold, Core, Premium, Ultimate]
+ tiers: [Core, Premium, Ultimate]
issue_url: 'https://gitlab.com/groups/gitlab-org/configure/-/epics/8'
documentation_url: 'https://docs.gitlab.com/ee/user/infrastructure/clusters/#certificate-based-kubernetes-integration-deprecated'
diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md
index dcfa6dffa9d..f77a6c8eec2 100644
--- a/doc/update/deprecations.md
+++ b/doc/update/deprecations.md
@@ -44,6 +44,18 @@ Most of the deprecations are **planned for removal in 15.0**, and many of them a
## 14.10
+### Dependency Scanning default Java version changed to 17
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+In GitLab 15.0, for Dependency Scanning, the default version of Java will be updated to 17. This is the same as [the most up-to-date Long Term Support (LTS) version](https://en.wikipedia.org/wiki/Java_version_history). GitLab still [supports the same versions as it does today (8, 11, 13, 14, 15, 16, 17)](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning). Only the enabled default is changing. To change the default, set the `DS_Java_Version` variable.
+
+**Planned removal milestone: 15.0 (2021-05-22)**
+
### Manual iteration management
WARNING:
@@ -1250,33 +1262,6 @@ If you have explicitly excluded bundler-audit using DS_EXCLUDED_ANALYZERS you wi
## 14.5
-### Certificate-based integration with Kubernetes
-
-WARNING:
-This feature will be changed or removed in 15.6
-as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
-Before updating GitLab, review the details carefully to determine if you need to make any
-changes to your code, settings, or workflow.
-
-[The certificate-based integration with Kubernetes will be deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
-
-If you are a self-managed customer, in GitLab 15.0, a feature flag will be introduced so you can keep
-certificate-based integration enabled. The flag will be disabled by default.
-The flag and the related code will be removed in GitLab 15.6.
-
-Until the final removal in 15.6, features built on the integration will continue to work, and
-GitLab will continue to fix security and critical issues.
-
-If you use GitLab.com, certificate-based integrations will cease functioning in 15.0.
-
-For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the
-[agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab.
-See the documentation for [how to migrate](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html).
-
-For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
-
-**Planned removal milestone: 15.6 (2022-11-22)**
-
### Converting an instance (shared) runner to a project (specific) runner
WARNING:
@@ -1349,6 +1334,44 @@ When checking if a runner is `paused`, API users are advised to check the boolea
**Planned removal milestone: 16.0 (2023-04-22)**
+### SaaS certificate-based integration with Kubernetes
+
+WARNING:
+This feature will be changed or removed in 15.0
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab SaaS customer, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0.
+
+For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the
+[agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html)
+
+For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
+
+**Planned removal milestone: 15.0 (2022-05-22)**
+
+### Self-managed certificate-based integration with Kubernetes
+
+WARNING:
+This feature will be changed or removed in 15.6
+as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+Before updating GitLab, review the details carefully to determine if you need to make any
+changes to your code, settings, or workflow.
+
+The certificate-based integration with Kubernetes [will be deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
+
+As a self-managed customer, we are introducing a feature flag in GitLab 15.0 so you can keep your certificate-based integration enabled. However, the feature flag will be disabled by default, so this change is a **breaking change**.
+
+In GitLab 15.6 we will remove both the feature, and its related code. Until the final removal in 15.6, features built on this integration will continue to work, if you enable the feature flag. Until the feature is removed, GitLab will continue to fix security and critical issues as they arise.
+
+For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the
+[agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html)
+
+For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
+
+**Planned removal milestone: 15.6 (2022-11-22)**
+
### Support for SLES 12 SP2
WARNING:
diff --git a/doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md b/doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md
index 61ec0a559f0..b956b1a6f9c 100644
--- a/doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md
+++ b/doc/user/infrastructure/clusters/migrate_to_gitlab_agent.md
@@ -14,9 +14,11 @@ To connect your Kubernetes cluster with GitLab, you can use:
The certificate-based integration is
[**deprecated**](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/)
-in GitLab 14.5. It is expected to be
-[turned off by default in 15.0](../../../update/deprecations.md#certificate-based-integration-with-kubernetes)
-and removed in GitLab 15.6.
+in GitLab 14.5. The removal dates are:
+
+- [GitLab.com customers](../../../update/deprecations.md#saas-certificate-based-integration-with-kubernetes): GitLab 15.0.
+- [Self-managed customers](../../../update/deprecations.md#self-managed-certificate-based-integration-with-kubernetes):
+ Placed behind a disabled feature flag in GitLab 15.0, and removed entirely in GitLab 15.6.
If you are using the certificate-based integration, you should move to another workflow as soon as possible.
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 52d5dc827b2..a16ec4a6cc0 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -13076,9 +13076,18 @@ msgid_plural "Diffs|%d deletions"
msgstr[0] ""
msgstr[1] ""
+msgid "Diffs|Expand all lines"
+msgstr ""
+
+msgid "Diffs|Next 20 lines"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
+msgid "Diffs|Previous 20 lines"
+msgstr ""
+
msgid "Diffs|Show %{unfoldCount} lines"
msgstr ""
diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb
index c06019f6b77..b6f528ceb8b 100644
--- a/spec/features/merge_request/user_comments_on_diff_spec.rb
+++ b/spec/features/merge_request/user_comments_on_diff_spec.rb
@@ -154,7 +154,7 @@ RSpec.describe 'User comments on a diff', :js do
it 'allows comments on previously hidden lines the middle of a file' do
# Click 27, expand up, select 18, add and verify comment
page.within find_by_scrolling('[data-path="files/ruby/popen.rb"]') do
- all('.js-unfold-all')[1].click
+ first('.js-unfold-all').click
end
click_diff_line(find('div[data-path="files/ruby/popen.rb"] .left-side a[data-linenumber="21"]').find(:xpath, '../..'), 'left')
add_comment('18', '21')
@@ -163,10 +163,10 @@ RSpec.describe 'User comments on a diff', :js do
it 'allows comments on previously hidden lines at the bottom of a file' do
# Click +28, expand down, select 37 add and verify comment
page.within find_by_scrolling('[data-path="files/ruby/popen.rb"]') do
- all('.js-unfold-down:not([disabled])')[1].click
+ first('.js-unfold-down').click
end
click_diff_line(find('div[data-path="files/ruby/popen.rb"] .left-side a[data-linenumber="30"]').find(:xpath, '../..'), 'left')
- add_comment('+28', '37')
+ add_comment('+28', '30')
end
end
diff --git a/spec/features/merge_request/user_views_diffs_spec.rb b/spec/features/merge_request/user_views_diffs_spec.rb
index 208ed1f01e7..894292c99eb 100644
--- a/spec/features/merge_request/user_views_diffs_spec.rb
+++ b/spec/features/merge_request/user_views_diffs_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'User views diffs', :js do
it 'unfolds diffs in the middle' do
page.within('.file-holder[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd"]') do
- all('.js-unfold-all')[1].click
+ first('.js-unfold-all').click
expect(page).to have_selector('[data-interop-type="new"] [data-linenumber="24"]', count: 1)
expect(page).not_to have_selector('[data-interop-type="new"] [data-linenumber="1"]')
diff --git a/spec/frontend/diffs/components/diff_expansion_cell_spec.js b/spec/frontend/diffs/components/diff_expansion_cell_spec.js
index cd472920bb9..bd538996349 100644
--- a/spec/frontend/diffs/components/diff_expansion_cell_spec.js
+++ b/spec/frontend/diffs/components/diff_expansion_cell_spec.js
@@ -20,7 +20,6 @@ function makeLoadMoreLinesPayload({
sinceLine,
toLine,
oldLineNumber,
- diffViewType,
fileHash,
nextLineNumbers = {},
unfold = false,
@@ -28,12 +27,11 @@ function makeLoadMoreLinesPayload({
isExpandDown = false,
}) {
return {
- endpoint: 'contextLinesPath',
+ endpoint: diffFileMockData.context_lines_path,
params: {
since: sinceLine,
to: toLine,
offset: toLine + 1 - oldLineNumber,
- view: diffViewType,
unfold,
bottom,
},
@@ -70,10 +68,11 @@ describe('DiffExpansionCell', () => {
const createComponent = (options = {}) => {
const defaults = {
fileHash: mockFile.file_hash,
- contextLinesPath: 'contextLinesPath',
line: mockLine,
isTop: false,
isBottom: false,
+ file: mockFile,
+ inline: true,
};
const propsData = { ...defaults, ...options };
@@ -124,7 +123,7 @@ describe('DiffExpansionCell', () => {
describe('any row', () => {
[
- { diffViewType: INLINE_DIFF_VIEW_TYPE, lineIndex: 8, file: { parallel_diff_lines: [] } },
+ { diffViewType: INLINE_DIFF_VIEW_TYPE, lineIndex: 8, file: cloneDeep(diffFileMockData) },
].forEach(({ diffViewType, file, lineIndex }) => {
describe(`with diffViewType (${diffViewType})`, () => {
beforeEach(() => {
@@ -140,12 +139,12 @@ describe('DiffExpansionCell', () => {
it('on expand all clicked, dispatch loadMoreLines', () => {
const oldLineNumber = mockLine.meta_data.old_pos;
const newLineNumber = mockLine.meta_data.new_pos;
- const previousIndex = getPreviousLineIndex(diffViewType, mockFile, {
+ const previousIndex = getPreviousLineIndex(mockFile, {
oldLineNumber,
newLineNumber,
});
- const wrapper = createComponent();
+ const wrapper = createComponent({ file });
findExpandAll(wrapper).click();
@@ -156,7 +155,6 @@ describe('DiffExpansionCell', () => {
toLine: newLineNumber - 1,
sinceLine: previousIndex,
oldLineNumber,
- diffViewType,
}),
);
});
@@ -168,7 +166,7 @@ describe('DiffExpansionCell', () => {
const oldLineNumber = mockLine.meta_data.old_pos;
const newLineNumber = mockLine.meta_data.new_pos;
- const wrapper = createComponent();
+ const wrapper = createComponent({ file });
findExpandUp(wrapper).trigger('click');
@@ -196,17 +194,16 @@ describe('DiffExpansionCell', () => {
mockLine.meta_data.old_pos = 200;
mockLine.meta_data.new_pos = 200;
- const wrapper = createComponent();
+ const wrapper = createComponent({ file });
findExpandDown(wrapper).trigger('click');
expect(store.dispatch).toHaveBeenCalledWith('diffs/loadMoreLines', {
- endpoint: 'contextLinesPath',
+ endpoint: diffFileMockData.context_lines_path,
params: {
since: 1,
to: 21, // the load amount, plus 1 line
offset: 0,
- view: diffViewType,
unfold: true,
bottom: true,
},
diff --git a/spec/frontend/diffs/store/mutations_spec.js b/spec/frontend/diffs/store/mutations_spec.js
index d8611b1ce1b..57e623b843d 100644
--- a/spec/frontend/diffs/store/mutations_spec.js
+++ b/spec/frontend/diffs/store/mutations_spec.js
@@ -131,7 +131,14 @@ describe('DiffsStoreMutations', () => {
const options = {
lineNumbers: { oldLineNumber: 1, newLineNumber: 2 },
contextLines: [
- { old_line: 1, new_line: 1, line_code: 'ff9200_1_1', discussions: [], hasForm: false },
+ {
+ old_line: 1,
+ new_line: 1,
+ line_code: 'ff9200_1_1',
+ discussions: [],
+ hasForm: false,
+ type: 'expanded',
+ },
],
fileHash: 'ff9200',
params: {
diff --git a/spec/frontend/diffs/store/utils_spec.js b/spec/frontend/diffs/store/utils_spec.js
index 03bcaab0d2b..8ae51a58819 100644
--- a/spec/frontend/diffs/store/utils_spec.js
+++ b/spec/frontend/diffs/store/utils_spec.js
@@ -51,21 +51,19 @@ describe('DiffsStoreUtils', () => {
});
describe('getPreviousLineIndex', () => {
- describe(`with diffViewType (inline) in split diffs`, () => {
- let diffFile;
+ let diffFile;
- beforeEach(() => {
- diffFile = { ...clone(diffFileMockData) };
- });
+ beforeEach(() => {
+ diffFile = { ...clone(diffFileMockData) };
+ });
- it('should return the correct previous line number', () => {
- expect(
- utils.getPreviousLineIndex(INLINE_DIFF_VIEW_TYPE, diffFile, {
- oldLineNumber: 3,
- newLineNumber: 5,
- }),
- ).toBe(4);
- });
+ it('should return the correct previous line number', () => {
+ expect(
+ utils.getPreviousLineIndex(diffFile, {
+ oldLineNumber: 3,
+ newLineNumber: 5,
+ }),
+ ).toBe(4);
});
});
diff --git a/spec/serializers/ci/job_entity_spec.rb b/spec/serializers/ci/job_entity_spec.rb
index ba68b9a6c16..625beeb239c 100644
--- a/spec/serializers/ci/job_entity_spec.rb
+++ b/spec/serializers/ci/job_entity_spec.rb
@@ -128,6 +128,15 @@ RSpec.describe Ci::JobEntity do
end
end
+ context 'when job is running' do
+ let_it_be(:job) { create(:ci_build, :running) }
+
+ it 'contains started_at' do
+ expect(subject[:started]).to be_truthy
+ expect(subject[:started_at]).to eq(job.started_at)
+ end
+ end
+
context 'when job is generic commit status' do
let(:job) { create(:generic_commit_status, target_url: 'http://google.com') }