Merge branch 'master' into qa/gb/validate-qa-selectors
* master: (429 commits)
|
|
@ -16,6 +16,7 @@ engines:
|
|||
enabled: true
|
||||
rubocop:
|
||||
enabled: true
|
||||
channel: "gitlab-rubocop-0-52"
|
||||
ratings:
|
||||
paths:
|
||||
- Gemfile.lock
|
||||
|
|
|
|||
|
|
@ -431,6 +431,7 @@ ee_compat_check:
|
|||
- master
|
||||
- tags
|
||||
- /^[\d-]+-stable(-ee)?/
|
||||
- /^security-/
|
||||
- branches@gitlab-org/gitlab-ee
|
||||
- branches@gitlab/gitlab-ee
|
||||
retry: 0
|
||||
|
|
@ -508,7 +509,7 @@ db:rollback-mysql:
|
|||
<<: *db-rollback
|
||||
<<: *use-mysql
|
||||
|
||||
.db-seed_fu: &db-seed_fu
|
||||
.gitlab-setup: &gitlab-setup
|
||||
<<: *dedicated-runner
|
||||
<<: *except-docs-and-qa
|
||||
<<: *pull-cache
|
||||
|
|
@ -517,22 +518,24 @@ db:rollback-mysql:
|
|||
SIZE: "1"
|
||||
SETUP_DB: "false"
|
||||
CREATE_DB_USER: "true"
|
||||
FIXTURE_PATH: db/fixtures/development
|
||||
script:
|
||||
- git clone https://gitlab.com/gitlab-org/gitlab-test.git
|
||||
/home/git/repositories/gitlab-org/gitlab-test.git
|
||||
- bundle exec rake db:setup db:seed_fu
|
||||
- scripts/gitaly-test-spawn
|
||||
- force=yes bundle exec rake gitlab:setup
|
||||
artifacts:
|
||||
when: on_failure
|
||||
expire_in: 1d
|
||||
paths:
|
||||
- log/development.log
|
||||
|
||||
db:seed_fu-pg:
|
||||
<<: *db-seed_fu
|
||||
gitlab:setup-pg:
|
||||
<<: *gitlab-setup
|
||||
<<: *use-pg
|
||||
|
||||
db:seed_fu-mysql:
|
||||
<<: *db-seed_fu
|
||||
gitlab:setup-mysql:
|
||||
<<: *gitlab-setup
|
||||
<<: *use-mysql
|
||||
|
||||
# Frontend-related jobs
|
||||
|
|
@ -594,12 +597,20 @@ codequality:
|
|||
script:
|
||||
- cp .rubocop.yml .rubocop.yml.bak
|
||||
- grep -v "rubocop-gitlab-security" .rubocop.yml.bak > .rubocop.yml
|
||||
- docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate analyze -f json > raw_codeclimate.json
|
||||
- docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc dev.gitlab.org:5005/gitlab/gitlab-build-images:gitlab-codeclimate-v2 analyze -f json > raw_codeclimate.json
|
||||
- cat raw_codeclimate.json | docker run -i stedolan/jq -c 'map({check_name,fingerprint,location})' > codeclimate.json
|
||||
- mv .rubocop.yml.bak .rubocop.yml
|
||||
artifacts:
|
||||
paths: [codeclimate.json]
|
||||
|
||||
sast:
|
||||
image: registry.gitlab.com/gitlab-org/gl-sast:latest
|
||||
before_script: []
|
||||
script:
|
||||
- /app/bin/run .
|
||||
artifacts:
|
||||
paths: [gl-sast-report.json]
|
||||
|
||||
qa:internal:
|
||||
<<: *dedicated-runner
|
||||
<<: *except-docs
|
||||
|
|
|
|||
1219
.rubocop.yml
|
|
@ -1,53 +1,111 @@
|
|||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --exclude-limit 0`
|
||||
# on 2017-07-10 01:48:30 +0900 using RuboCop version 0.49.1.
|
||||
# `rubocop --auto-gen-config`
|
||||
# on 2017-12-14 12:04:26 +0100 using RuboCop version 0.52.0.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of RuboCop, may require this file to be generated again.
|
||||
|
||||
# Offense count: 181
|
||||
# Offense count: 174
|
||||
Capybara/CurrentPathExpectation:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 951
|
||||
Capybara/FeatureMethods:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 24
|
||||
FactoryBot/DynamicAttributeDefinedStatically:
|
||||
Exclude:
|
||||
- 'spec/factories/broadcast_messages.rb'
|
||||
- 'spec/factories/ci/builds.rb'
|
||||
- 'spec/factories/ci/runners.rb'
|
||||
- 'spec/factories/clusters/applications/helm.rb'
|
||||
- 'spec/factories/clusters/applications/ingress.rb'
|
||||
- 'spec/factories/clusters/platforms/kubernetes.rb'
|
||||
- 'spec/factories/emails.rb'
|
||||
- 'spec/factories/gpg_keys.rb'
|
||||
- 'spec/factories/group_members.rb'
|
||||
- 'spec/factories/merge_requests.rb'
|
||||
- 'spec/factories/notes.rb'
|
||||
- 'spec/factories/oauth_access_grants.rb'
|
||||
- 'spec/factories/project_members.rb'
|
||||
- 'spec/factories/todos.rb'
|
||||
- 'spec/factories/uploads.rb'
|
||||
|
||||
# Offense count: 65
|
||||
# Cop supports --auto-correct.
|
||||
Layout/EmptyLinesAroundArguments:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 249
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowForAlignment, ForceEqualSignAlignment.
|
||||
Layout/ExtraSpacing:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 119
|
||||
# Offense count: 82
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
||||
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
||||
# SupportedStyles: special_inside_parentheses, consistent, align_brackets
|
||||
Layout/IndentArray:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 208
|
||||
# Offense count: 239
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
||||
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
||||
# SupportedStyles: special_inside_parentheses, consistent, align_braces
|
||||
Layout/IndentHash:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 8
|
||||
# Offense count: 15
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: .
|
||||
# SupportedStyles: space, no_space
|
||||
# SupportedStylesForEmptyBraces: space, no_space
|
||||
Layout/SpaceBeforeBlockBraces:
|
||||
EnforcedStyle: space
|
||||
EnforcedStyleForEmptyBraces: space
|
||||
|
||||
# Offense count: 11
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowForAlignment.
|
||||
Layout/SpaceBeforeFirstArg:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'config/routes/project.rb'
|
||||
- 'db/migrate/20170506185517_add_foreign_key_pipeline_schedules_and_pipelines.rb'
|
||||
- 'features/steps/project/source/browse_files.rb'
|
||||
- 'features/steps/project/source/markdown_render.rb'
|
||||
- 'lib/api/runners.rb'
|
||||
- 'spec/features/search/user_uses_search_filters_spec.rb'
|
||||
- 'spec/routing/project_routing_spec.rb'
|
||||
- 'spec/services/system_note_service_spec.rb'
|
||||
|
||||
# Offense count: 64
|
||||
# Offense count: 93
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: require_no_space, require_space
|
||||
Layout/SpaceInLambdaLiteral:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 256
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces, SpaceBeforeBlockParameters.
|
||||
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets.
|
||||
# SupportedStyles: space, no_space, compact
|
||||
# SupportedStylesForEmptyBrackets: space, no_space
|
||||
Layout/SpaceInsideArrayLiteralBrackets:
|
||||
Exclude:
|
||||
- 'spec/lib/gitlab/import_export/relation_factory_spec.rb'
|
||||
|
||||
# Offense count: 323
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
|
||||
# SupportedStyles: space, no_space
|
||||
# SupportedStylesForEmptyBraces: space, no_space
|
||||
Layout/SpaceInsideBlockBraces:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 135
|
||||
# Offense count: 146
|
||||
# Cop supports --auto-correct.
|
||||
Layout/SpaceInsideParens:
|
||||
Enabled: false
|
||||
|
|
@ -55,178 +113,535 @@ Layout/SpaceInsideParens:
|
|||
# Offense count: 14
|
||||
# Cop supports --auto-correct.
|
||||
Layout/SpaceInsidePercentLiteralDelimiters:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'lib/gitlab/git_access.rb'
|
||||
- 'lib/gitlab/health_checks/fs_shards_check.rb'
|
||||
- 'spec/lib/gitlab/health_checks/fs_shards_check_spec.rb'
|
||||
|
||||
# Offense count: 272
|
||||
RSpec/EmptyLineAfterFinalLet:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 181
|
||||
RSpec/EmptyLineAfterSubject:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 9
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: it_behaves_like, it_should_behave_like
|
||||
RSpec/ItBehavesLike:
|
||||
Enabled: false
|
||||
# Offense count: 25
|
||||
Lint/DuplicateMethods:
|
||||
Exclude:
|
||||
- 'app/models/application_setting.rb'
|
||||
- 'app/models/commit.rb'
|
||||
- 'app/models/note.rb'
|
||||
- 'app/services/merge_requests/merge_service.rb'
|
||||
- 'lib/bitbucket/representation/repo.rb'
|
||||
- 'lib/declarative_policy/base.rb'
|
||||
- 'lib/gitlab/ci/build/artifacts/metadata/entry.rb'
|
||||
- 'lib/gitlab/cycle_analytics/base_event_fetcher.rb'
|
||||
- 'lib/gitlab/diff/formatters/base_formatter.rb'
|
||||
- 'lib/gitlab/git/blob.rb'
|
||||
- 'lib/gitlab/git/repository.rb'
|
||||
- 'lib/gitlab/git/tree.rb'
|
||||
- 'lib/gitlab/git/wiki_page.rb'
|
||||
- 'lib/gitlab/ldap/person.rb'
|
||||
- 'lib/gitlab/o_auth/user.rb'
|
||||
|
||||
# Offense count: 4
|
||||
RSpec/IteratedExpectation:
|
||||
Lint/InterpolationCheck:
|
||||
Exclude:
|
||||
- 'spec/features/issues/filtered_search/filter_issues_spec.rb'
|
||||
- 'spec/features/users_spec.rb'
|
||||
- 'spec/services/quick_actions/interpret_service_spec.rb'
|
||||
|
||||
# Offense count: 198
|
||||
# Configuration parameters: MaximumRangeSize.
|
||||
Lint/MissingCopEnableDirective:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 2
|
||||
RSpec/OverwritingSetup:
|
||||
Lint/NestedPercentLiteral:
|
||||
Exclude:
|
||||
- 'lib/gitlab/git/repository.rb'
|
||||
- 'spec/support/email_format_shared_examples.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Lint/ReturnInVoidContext:
|
||||
Exclude:
|
||||
- 'app/models/project.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: IgnoreImplicitReferences.
|
||||
Lint/ShadowedArgument:
|
||||
Exclude:
|
||||
- 'lib/gitlab/database/sha_attribute.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Lint/UnneededRequireStatement:
|
||||
Exclude:
|
||||
- 'db/post_migrate/20161221153951_rename_reserved_project_names.rb'
|
||||
- 'db/post_migrate/20170313133418_rename_more_reserved_project_names.rb'
|
||||
- 'lib/declarative_policy.rb'
|
||||
|
||||
# Offense count: 9
|
||||
Lint/UriEscapeUnescape:
|
||||
Exclude:
|
||||
- 'app/controllers/application_controller.rb'
|
||||
- 'app/models/project_services/drone_ci_service.rb'
|
||||
- 'spec/lib/google_api/auth_spec.rb'
|
||||
- 'spec/requests/api/files_spec.rb'
|
||||
- 'spec/requests/api/internal_spec.rb'
|
||||
- 'spec/requests/api/issues_spec.rb'
|
||||
- 'spec/requests/api/v3/issues_spec.rb'
|
||||
|
||||
# Offense count: 2
|
||||
Naming/ConstantName:
|
||||
Exclude:
|
||||
- 'lib/gitlab/import_sources.rb'
|
||||
- 'lib/gitlab/ssh_public_key.rb'
|
||||
|
||||
# Offense count: 11
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: lowercase, uppercase
|
||||
Naming/HeredocDelimiterCase:
|
||||
Exclude:
|
||||
- 'spec/lib/gitlab/diff/parser_spec.rb'
|
||||
- 'spec/lib/json_web_token/rsa_token_spec.rb'
|
||||
- 'spec/models/commit_spec.rb'
|
||||
- 'spec/support/repo_helpers.rb'
|
||||
- 'spec/support/seed_repo.rb'
|
||||
|
||||
# Offense count: 101
|
||||
# Configuration parameters: Blacklist.
|
||||
# Blacklist: END, (?-mix:EO[A-Z]{1})
|
||||
Naming/HeredocDelimiterNaming:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 36
|
||||
RSpec/RepeatedExample:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 86
|
||||
RSpec/ScatteredLet:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 20
|
||||
RSpec/ScatteredSetup:
|
||||
# Offense count: 28
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AutoCorrect.
|
||||
Performance/HashEachMethods:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 1
|
||||
RSpec/SharedContext:
|
||||
Performance/UnfreezeString:
|
||||
Exclude:
|
||||
- 'features/steps/project/commits/commits.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Performance/UriDefaultParser:
|
||||
Exclude:
|
||||
- 'lib/gitlab/url_sanitizer.rb'
|
||||
|
||||
# Offense count: 3745
|
||||
# Configuration parameters: Prefixes.
|
||||
# Prefixes: when, with, without
|
||||
RSpec/ContextWording:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 115
|
||||
# Offense count: 291
|
||||
RSpec/EmptyLineAfterFinalLet:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 180
|
||||
RSpec/EmptyLineAfterSubject:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 220
|
||||
RSpec/ExpectInHook:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 7
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: implicit, each, example
|
||||
RSpec/HookArgument:
|
||||
Exclude:
|
||||
- 'spec/spec_helper.rb'
|
||||
- 'spec/support/carrierwave.rb'
|
||||
- 'spec/support/db_cleaner.rb'
|
||||
- 'spec/support/gitaly.rb'
|
||||
- 'spec/support/setup_builds_storage.rb'
|
||||
|
||||
# Offense count: 19
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: it_behaves_like, it_should_behave_like
|
||||
RSpec/ItBehavesLike:
|
||||
Exclude:
|
||||
- 'spec/lib/gitlab/git/commit_spec.rb'
|
||||
- 'spec/lib/gitlab/git/repository_spec.rb'
|
||||
- 'spec/lib/gitlab/shell_spec.rb'
|
||||
- 'spec/services/notification_service_spec.rb'
|
||||
- 'spec/workers/git_garbage_collect_worker_spec.rb'
|
||||
|
||||
# Offense count: 5
|
||||
RSpec/IteratedExpectation:
|
||||
Exclude:
|
||||
- 'spec/features/admin/admin_settings_spec.rb'
|
||||
- 'spec/features/merge_requests/diff_notes_resolve_spec.rb'
|
||||
- 'spec/features/projects/awards/user_interacts_with_awards_in_issue_spec.rb'
|
||||
- 'spec/lib/gitlab/gitlab_import/client_spec.rb'
|
||||
- 'spec/lib/gitlab/legacy_github_import/client_spec.rb'
|
||||
|
||||
# Offense count: 75
|
||||
RSpec/LetBeforeExamples:
|
||||
Exclude:
|
||||
- 'spec/controllers/projects/commit_controller_spec.rb'
|
||||
- 'spec/lib/banzai/filter/issue_reference_filter_spec.rb'
|
||||
- 'spec/lib/banzai/filter/user_reference_filter_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
|
||||
- 'spec/models/commit_range_spec.rb'
|
||||
- 'spec/models/milestone_spec.rb'
|
||||
- 'spec/models/project_services/packagist_service_spec.rb'
|
||||
- 'spec/models/repository_spec.rb'
|
||||
- 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb'
|
||||
- 'spec/serializers/pipeline_details_entity_spec.rb'
|
||||
- 'spec/views/ci/lints/show.html.haml_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
RSpec/MultipleSubjects:
|
||||
Exclude:
|
||||
- 'spec/services/merge_requests/create_from_issue_service_spec.rb'
|
||||
|
||||
# Offense count: 4
|
||||
RSpec/OverwritingSetup:
|
||||
Exclude:
|
||||
- 'spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb'
|
||||
- 'spec/models/email_spec.rb'
|
||||
- 'spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb'
|
||||
- 'spec/services/notes/quick_actions_service_spec.rb'
|
||||
|
||||
# Offense count: 917
|
||||
# Configuration parameters: Strict, EnforcedStyle.
|
||||
# SupportedStyles: inflected, explicit
|
||||
RSpec/PredicateMatcher:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 35
|
||||
RSpec/RepeatedExample:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 132
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: and_return, block
|
||||
RSpec/ReturnFromStub:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 105
|
||||
RSpec/ScatteredLet:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 22
|
||||
RSpec/ScatteredSetup:
|
||||
Exclude:
|
||||
- 'spec/controllers/projects/templates_controller_spec.rb'
|
||||
- 'spec/lib/gitlab/bitbucket_import/importer_spec.rb'
|
||||
- 'spec/lib/gitlab/git/env_spec.rb'
|
||||
- 'spec/requests/api/jobs_spec.rb'
|
||||
- 'spec/requests/api/v3/builds_spec.rb'
|
||||
- 'spec/requests/api/v3/projects_spec.rb'
|
||||
- 'spec/services/projects/create_service_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
RSpec/SharedContext:
|
||||
Exclude:
|
||||
- 'spec/features/admin/admin_groups_spec.rb'
|
||||
|
||||
# Offense count: 90
|
||||
RSpec/SingleLineHook:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 5
|
||||
RSpec/VoidExpect:
|
||||
Exclude:
|
||||
- 'spec/features/projects/artifacts/download_spec.rb'
|
||||
- 'spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb'
|
||||
- 'spec/models/ci/group_spec.rb'
|
||||
- 'spec/models/ci/runner_spec.rb'
|
||||
- 'spec/services/users/destroy_service_spec.rb'
|
||||
|
||||
# Offense count: 40
|
||||
# Configuration parameters: Include.
|
||||
# Include: db/migrate/*.rb
|
||||
Rails/CreateTableWithTimestamps:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 149
|
||||
Rails/FilePath:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 119
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/HasManyOrHasOneDependent:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 113
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/InverseOf:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 48
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/controllers/**/*.rb
|
||||
Rails/LexicallyScopedActionFilter:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 14
|
||||
# Cop supports --auto-correct.
|
||||
Rails/Presence:
|
||||
Exclude:
|
||||
- 'app/controllers/projects/blob_controller.rb'
|
||||
- 'app/models/ci/pipeline.rb'
|
||||
- 'app/models/clusters/platforms/kubernetes.rb'
|
||||
- 'app/models/concerns/mentionable.rb'
|
||||
- 'app/models/concerns/token_authenticatable.rb'
|
||||
- 'app/models/project_services/hipchat_service.rb'
|
||||
- 'app/models/project_services/irker_service.rb'
|
||||
- 'app/models/project_services/jira_service.rb'
|
||||
- 'app/models/project_services/kubernetes_service.rb'
|
||||
- 'app/models/project_services/packagist_service.rb'
|
||||
- 'app/models/wiki_page.rb'
|
||||
- 'lib/gitlab/git/hook.rb'
|
||||
- 'lib/gitlab/github_import/importer/releases_importer.rb'
|
||||
|
||||
# Offense count: 14
|
||||
# Cop supports --auto-correct.
|
||||
Rails/RedundantReceiverInWithOptions:
|
||||
Exclude:
|
||||
- 'config/initializers/doorkeeper_openid_connect.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Configuration parameters: Include.
|
||||
# Include: db/migrate/*.rb
|
||||
Rails/ReversibleMigration:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'db/migrate/20160824103857_drop_unused_ci_tables.rb'
|
||||
|
||||
# Offense count: 336
|
||||
# Offense count: 430
|
||||
# Configuration parameters: Blacklist.
|
||||
# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters
|
||||
Rails/SkipsModelValidations:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 11
|
||||
# Offense count: 1
|
||||
# Configuration parameters: Environments.
|
||||
# Environments: development, test, production
|
||||
Rails/UnknownEnv:
|
||||
Exclude:
|
||||
- 'db/migrate/20171124125748_populate_missing_merge_request_statuses.rb'
|
||||
|
||||
# Offense count: 13
|
||||
# Cop supports --auto-correct.
|
||||
Security/YAMLLoad:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'config/initializers/carrierwave.rb'
|
||||
- 'lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb'
|
||||
- 'lib/gitlab/redis/wrapper.rb'
|
||||
- 'lib/system_check/incoming_email/imap_authentication_check.rb'
|
||||
- 'spec/config/mail_room_spec.rb'
|
||||
- 'spec/initializers/secret_token_spec.rb'
|
||||
- 'spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb'
|
||||
- 'spec/models/clusters/platforms/kubernetes_spec.rb'
|
||||
- 'spec/models/project_services/kubernetes_service_spec.rb'
|
||||
|
||||
# Offense count: 58
|
||||
# Offense count: 63
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: percent_q, bare_percent
|
||||
Style/BarePercentLiterals:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
Style/EachWithObject:
|
||||
# Offense count: 5
|
||||
Style/CommentedKeyword:
|
||||
Exclude:
|
||||
- 'lib/tasks/gitlab/backup.rake'
|
||||
- 'spec/tasks/gitlab/backup_rake_spec.rb'
|
||||
|
||||
# Offense count: 30
|
||||
Style/DateTime:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 31
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
Style/Dir:
|
||||
Exclude:
|
||||
- 'qa/qa.rb'
|
||||
|
||||
# Offense count: 9
|
||||
# Cop supports --auto-correct.
|
||||
Style/EachWithObject:
|
||||
Exclude:
|
||||
- 'config/initializers/gollum.rb'
|
||||
- 'lib/expand_variables.rb'
|
||||
- 'lib/gitlab/ci/ansi2html.rb'
|
||||
- 'lib/gitlab/ee_compat_check.rb'
|
||||
- 'lib/gitlab/hook_data/issuable_builder.rb'
|
||||
- 'lib/gitlab/i18n/po_linter.rb'
|
||||
- 'lib/gitlab/import_export/members_mapper.rb'
|
||||
- 'lib/gitlab/import_export/relation_factory.rb'
|
||||
- 'scripts/static-analysis'
|
||||
|
||||
# Offense count: 24
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: empty, nil, both
|
||||
Style/EmptyElse:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 9
|
||||
# Offense count: 14
|
||||
# Cop supports --auto-correct.
|
||||
Style/EmptyLambdaParameter:
|
||||
Exclude:
|
||||
- 'app/models/ci/build.rb'
|
||||
- 'app/models/ci/runner.rb'
|
||||
|
||||
# Offense count: 12
|
||||
# Cop supports --auto-correct.
|
||||
Style/EmptyLiteral:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'features/steps/project/commits/commits.rb'
|
||||
- 'lib/gitlab/fogbugz_import/importer.rb'
|
||||
- 'lib/gitlab/git/diff_collection.rb'
|
||||
- 'lib/gitlab/gitaly_client.rb'
|
||||
- 'scripts/trigger-build-omnibus'
|
||||
- 'spec/features/merge_requests/versions_spec.rb'
|
||||
- 'spec/helpers/merge_requests_helper_spec.rb'
|
||||
- 'spec/lib/gitlab/request_context_spec.rb'
|
||||
- 'spec/lib/gitlab/workhorse_spec.rb'
|
||||
- 'spec/requests/api/jobs_spec.rb'
|
||||
- 'spec/support/chat_slash_commands_shared_examples.rb'
|
||||
|
||||
# Offense count: 78
|
||||
# Offense count: 98
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: compact, expanded
|
||||
Style/EmptyMethod:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 23
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
Style/Encoding:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 2
|
||||
Style/EvalWithLocation:
|
||||
Exclude:
|
||||
- 'app/models/service.rb'
|
||||
|
||||
# Offense count: 52
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: Autocorrect, EnforcedStyle.
|
||||
# SupportedStyles: module_function, extend_self
|
||||
Style/ExtendSelf:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 34
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: format, sprintf, percent
|
||||
Style/FormatString:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 301
|
||||
# Offense count: 371
|
||||
# Configuration parameters: MinBodyLength.
|
||||
Style/GuardClause:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 18
|
||||
# Offense count: 21
|
||||
Style/IfInsideElse:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 182
|
||||
# Offense count: 781
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: MaxLineLength.
|
||||
Style/IfUnlessModifier:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 52
|
||||
# Offense count: 71
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: line_count_dependent, lambda, literal
|
||||
Style/Lambda:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 6
|
||||
# Offense count: 11
|
||||
# Cop supports --auto-correct.
|
||||
Style/LineEndConcatenation:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'app/helpers/tree_helper.rb'
|
||||
- 'spec/features/issuables/markdown_references_spec.rb'
|
||||
- 'spec/lib/gitlab/checks/project_moved_spec.rb'
|
||||
- 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
|
||||
- 'spec/lib/gitlab/incoming_email_spec.rb'
|
||||
|
||||
# Offense count: 40
|
||||
# Offense count: 39
|
||||
# Cop supports --auto-correct.
|
||||
Style/MethodCallWithoutArgsParentheses:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 13
|
||||
# Offense count: 17
|
||||
Style/MethodMissing:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 7
|
||||
Style/MixinUsage:
|
||||
Exclude:
|
||||
- 'features/support/env.rb'
|
||||
- 'spec/factories/ci/builds.rb'
|
||||
- 'spec/factories/ci/job_artifacts.rb'
|
||||
- 'spec/factories/lfs_objects.rb'
|
||||
- 'spec/factories/notes.rb'
|
||||
- 'spec/lib/gitlab/import_export/project_tree_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/version_checker_spec.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
Style/MultilineIfModifier:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'app/helpers/snippets_helper.rb'
|
||||
- 'app/models/project_wiki.rb'
|
||||
- 'app/services/ci/process_pipeline_service.rb'
|
||||
- 'app/services/create_deployment_service.rb'
|
||||
- 'lib/api/commit_statuses.rb'
|
||||
- 'lib/gitlab/ci/trace.rb'
|
||||
|
||||
# Offense count: 26
|
||||
# Offense count: 23
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: Whitelist.
|
||||
# Whitelist: be, be_a, be_an, be_between, be_falsey, be_kind_of, be_instance_of, be_truthy, be_within, eq, eql, end_with, include, match, raise_error, respond_to, start_with
|
||||
Style/NestedParenthesizedCalls:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 20
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles.
|
||||
# Configuration parameters: EnforcedStyle, MinBodyLength.
|
||||
# SupportedStyles: skip_modifier_ifs, always
|
||||
Style/Next:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 45
|
||||
# Offense count: 58
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedOctalStyle, SupportedOctalStyles.
|
||||
# Configuration parameters: EnforcedOctalStyle.
|
||||
# SupportedOctalStyles: zero_with_o, zero_only
|
||||
Style/NumericLiteralPrefix:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 98
|
||||
# Offense count: 112
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AutoCorrect, EnforcedStyle, SupportedStyles.
|
||||
# Configuration parameters: AutoCorrect, EnforcedStyle.
|
||||
# SupportedStyles: predicate, comparison
|
||||
Style/NumericPredicate:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 42
|
||||
# Offense count: 4
|
||||
# Cop supports --auto-correct.
|
||||
Style/OrAssignment:
|
||||
Exclude:
|
||||
- 'app/models/concerns/token_authenticatable.rb'
|
||||
- 'lib/api/commit_statuses.rb'
|
||||
- 'lib/api/v3/members.rb'
|
||||
- 'lib/gitlab/project_transfer.rb'
|
||||
|
||||
# Offense count: 50
|
||||
# Cop supports --auto-correct.
|
||||
Style/ParallelAssignment:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 800
|
||||
# Offense count: 891
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: PreferredDelimiters.
|
||||
Style/PercentLiteralDelimiters:
|
||||
|
|
@ -235,106 +650,194 @@ Style/PercentLiteralDelimiters:
|
|||
# Offense count: 15
|
||||
# Cop supports --auto-correct.
|
||||
Style/PerlBackrefs:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'app/controllers/projects/application_controller.rb'
|
||||
- 'app/helpers/submodule_helper.rb'
|
||||
- 'lib/backup/manager.rb'
|
||||
- 'lib/banzai/filter/abstract_reference_filter.rb'
|
||||
- 'lib/banzai/filter/autolink_filter.rb'
|
||||
- 'lib/banzai/filter/emoji_filter.rb'
|
||||
- 'lib/banzai/filter/gollum_tags_filter.rb'
|
||||
- 'lib/expand_variables.rb'
|
||||
- 'lib/gitlab/diff/highlight.rb'
|
||||
- 'lib/gitlab/search_results.rb'
|
||||
- 'lib/gitlab/sherlock/query.rb'
|
||||
|
||||
# Offense count: 58
|
||||
# Offense count: 82
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: compact, exploded
|
||||
Style/RaiseArgs:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 6
|
||||
# Offense count: 8
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantBegin:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'app/controllers/projects/clusters/gcp_controller.rb'
|
||||
- 'app/models/merge_request.rb'
|
||||
- 'app/services/projects/import_service.rb'
|
||||
- 'lib/api/branches.rb'
|
||||
- 'lib/gitlab/current_settings.rb'
|
||||
- 'lib/gitlab/git/commit.rb'
|
||||
- 'lib/gitlab/health_checks/base_abstract_check.rb'
|
||||
- 'lib/tasks/gitlab/task_helpers.rb'
|
||||
|
||||
# Offense count: 37
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantConditional:
|
||||
Exclude:
|
||||
- 'lib/system_check/helpers.rb'
|
||||
|
||||
# Offense count: 58
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantFreeze:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 14
|
||||
# Offense count: 15
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowMultipleReturnValues.
|
||||
Style/RedundantReturn:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'app/controllers/application_controller.rb'
|
||||
- 'app/controllers/concerns/issuable_actions.rb'
|
||||
- 'app/controllers/groups/application_controller.rb'
|
||||
- 'app/controllers/omniauth_callbacks_controller.rb'
|
||||
- 'app/controllers/profiles/keys_controller.rb'
|
||||
- 'app/controllers/projects/application_controller.rb'
|
||||
- 'app/services/access_token_validation_service.rb'
|
||||
- 'lib/gitlab/utils.rb'
|
||||
- 'lib/google_api/auth.rb'
|
||||
|
||||
# Offense count: 406
|
||||
# Offense count: 454
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantSelf:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 115
|
||||
# Offense count: 140
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes.
|
||||
# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
|
||||
# SupportedStyles: slashes, percent_r, mixed
|
||||
Style/RegexpLiteral:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 29
|
||||
# Offense count: 35
|
||||
# Cop supports --auto-correct.
|
||||
Style/RescueModifier:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 105
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: implicit, explicit
|
||||
Style/RescueStandardError:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 91
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: ConvertCodeThatCanStartToReturnNil.
|
||||
Style/SafeNavigation:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 8
|
||||
# Cop supports --auto-correct.
|
||||
Style/SelfAssignment:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'app/models/concerns/bulk_member_access_load.rb'
|
||||
- 'app/serializers/base_serializer.rb'
|
||||
- 'app/services/notification_service.rb'
|
||||
- 'lib/api/runners.rb'
|
||||
- 'spec/features/merge_requests/diff_notes_resolve_spec.rb'
|
||||
- 'spec/features/projects/clusters/interchangeability_spec.rb'
|
||||
- 'spec/support/import_export/configuration_helper.rb'
|
||||
|
||||
# Offense count: 50
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowIfMethodIsEmpty.
|
||||
Style/SingleLineMethods:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'lib/gitlab/ci/ansi2html.rb'
|
||||
|
||||
# Offense count: 64
|
||||
# Offense count: 66
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: SupportedStyles.
|
||||
# Configuration parameters: .
|
||||
# SupportedStyles: use_perl_names, use_english_names
|
||||
Style/SpecialGlobalVars:
|
||||
EnforcedStyle: use_perl_names
|
||||
|
||||
# Offense count: 44
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
Style/StderrPuts:
|
||||
Exclude:
|
||||
- 'config/initializers/rspec_profiling.rb'
|
||||
|
||||
# Offense count: 45
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: single_quotes, double_quotes
|
||||
Style/StringLiteralsInInterpolation:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 84
|
||||
# Offense count: 99
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: IgnoredMethods.
|
||||
# IgnoredMethods: respond_to, define_method
|
||||
Style/SymbolProc:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 8
|
||||
# Offense count: 9
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowSafeAssignment.
|
||||
# Configuration parameters: EnforcedStyle, AllowSafeAssignment.
|
||||
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
|
||||
Style/TernaryParentheses:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'app/finders/projects_finder.rb'
|
||||
- 'app/helpers/namespaces_helper.rb'
|
||||
- 'features/support/capybara.rb'
|
||||
- 'lib/api/v3/projects.rb'
|
||||
- 'lib/gitlab/ci/build/artifacts/metadata/entry.rb'
|
||||
- 'spec/requests/api/pipeline_schedules_spec.rb'
|
||||
- 'spec/support/capybara.rb'
|
||||
|
||||
# Offense count: 17
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowNamedUnderscoreVariables.
|
||||
Style/TrailingUnderscoreVariable:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'app/controllers/admin/background_jobs_controller.rb'
|
||||
- 'app/controllers/invites_controller.rb'
|
||||
- 'app/helpers/tab_helper.rb'
|
||||
- 'lib/backup/manager.rb'
|
||||
- 'lib/gitlab/logger.rb'
|
||||
- 'lib/gitlab/upgrader.rb'
|
||||
- 'lib/system_check/app/migrations_are_up_check.rb'
|
||||
- 'lib/system_check/incoming_email/mail_room_running_check.rb'
|
||||
- 'lib/tasks/gitlab/check.rake'
|
||||
- 'lib/tasks/gitlab/task_helpers.rb'
|
||||
- 'spec/lib/gitlab/etag_caching/middleware_spec.rb'
|
||||
- 'spec/services/quick_actions/interpret_service_spec.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Offense count: 5
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist.
|
||||
# Whitelist: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym
|
||||
Style/TrivialAccessors:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'app/models/external_issue.rb'
|
||||
- 'app/serializers/base_serializer.rb'
|
||||
- 'lib/gitlab/ldap/person.rb'
|
||||
- 'lib/system_check/base_check.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Offense count: 4
|
||||
# Cop supports --auto-correct.
|
||||
Style/UnlessElse:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'lib/backup/manager.rb'
|
||||
- 'lib/gitlab/project_search_results.rb'
|
||||
- 'lib/tasks/gitlab/check.rake'
|
||||
- 'spec/features/issues/award_emoji_spec.rb'
|
||||
|
||||
# Offense count: 28
|
||||
# Offense count: 30
|
||||
# Cop supports --auto-correct.
|
||||
Style/UnneededInterpolation:
|
||||
Enabled: false
|
||||
|
|
@ -342,4 +845,19 @@ Style/UnneededInterpolation:
|
|||
# Offense count: 11
|
||||
# Cop supports --auto-correct.
|
||||
Style/ZeroLengthPredicate:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'app/models/deploy_key.rb'
|
||||
- 'app/models/network/commit.rb'
|
||||
- 'app/models/network/graph.rb'
|
||||
- 'app/models/project_services/asana_service.rb'
|
||||
- 'app/services/boards/create_service.rb'
|
||||
- 'app/services/merge_requests/conflicts/list_service.rb'
|
||||
- 'lib/declarative_policy/dsl.rb'
|
||||
- 'lib/extracts_path.rb'
|
||||
- 'lib/gitlab/git/repository.rb'
|
||||
|
||||
# Offense count: 22050
|
||||
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
||||
# URISchemes: http, https
|
||||
Metrics/LineLength:
|
||||
Max: 1310
|
||||
|
|
|
|||
29
CHANGELOG.md
|
|
@ -2,6 +2,35 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 10.3.3 (2018-01-02)
|
||||
|
||||
### Fixed (3 changes)
|
||||
|
||||
- Fix links to old commits in merge request comments.
|
||||
- Fix 404 errors after a user edits an issue description and solves the reCAPTCHA.
|
||||
- Gracefully handle orphaned write deploy keys in /internal/post_receive.
|
||||
|
||||
|
||||
## 10.3.2 (2017-12-28)
|
||||
|
||||
### Fixed (1 change)
|
||||
|
||||
- Fix migration for removing orphaned issues.moved_to_id values in MySQL and PostgreSQL.
|
||||
|
||||
|
||||
## 10.3.1 (2017-12-27)
|
||||
|
||||
### Fixed (3 changes)
|
||||
|
||||
- Don't link LFS objects to a project when unlinking forks when they were already linked. !16006
|
||||
- Execute project hooks and services after commit when moving an issue.
|
||||
- Fix Error 500s with anonymous clones for a project that has moved.
|
||||
|
||||
### Changed (1 change)
|
||||
|
||||
- Reduce the number of buckets in gitlab_cache_operation_duration_seconds metric. !15881
|
||||
|
||||
|
||||
## 10.3.0 (2017-12-22)
|
||||
|
||||
### Security (1 change, 1 of them is from the community)
|
||||
|
|
|
|||
|
|
@ -104,9 +104,13 @@ the remaining issues on the GitHub issue tracker.
|
|||
|
||||
## I want to contribute!
|
||||
|
||||
If you want to contribute to GitLab, [issues with the label `Accepting Merge Requests` and small weight][accepting-mrs-weight] is a great place to start. Issues with a lower weight (1 or 2) are deemed suitable for beginners.
|
||||
These issues will be of reasonable size and challenge, for anyone to start
|
||||
contributing to GitLab.
|
||||
If you want to contribute to GitLab [issues with the label `Accepting Merge Requests` and small weight][accepting-mrs-weight]
|
||||
is a great place to start. Issues with a lower weight (1 or 2) are deemed
|
||||
suitable for beginners. These issues will be of reasonable size and challenge,
|
||||
for anyone to start contributing to GitLab. If you have any questions or need help visit [Getting Help](https://about.gitlab.com/getting-help/#discussion) to
|
||||
learn how to communicate with GitLab. If you're looking for a Gitter or Slack channel
|
||||
please consider we favor
|
||||
[asynchronous communication](https://about.gitlab.com/handbook/communication/#internal-communication) over real time communication. Thanks for your contribution!
|
||||
|
||||
## Workflow labels
|
||||
|
||||
|
|
@ -553,7 +557,7 @@ the feature you contribute through all of these steps.
|
|||
|
||||
1. Description explaining the relevancy (see following item)
|
||||
1. Working and clean code that is commented where needed
|
||||
1. [Unit and system tests][testing] that pass on the CI server
|
||||
1. [Unit, integration, and system tests][testing] that pass on the CI server
|
||||
1. Performance/scalability implications have been considered, addressed, and tested
|
||||
1. [Documented][doc-styleguide] in the `/doc` directory
|
||||
1. [Changelog entry added][changelog], if necessary
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
0.60.0
|
||||
0.66.0
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.3.1
|
||||
3.4.0
|
||||
|
|
|
|||
18
Gemfile
|
|
@ -12,7 +12,7 @@ gem 'sprockets', '~> 3.7.0'
|
|||
gem 'default_value_for', '~> 3.0.0'
|
||||
|
||||
# Supported DBs
|
||||
gem 'mysql2', '~> 0.4.5', group: :mysql
|
||||
gem 'mysql2', '~> 0.4.10', group: :mysql
|
||||
gem 'pg', '~> 0.18.2', group: :postgres
|
||||
|
||||
gem 'rugged', '~> 0.26.0'
|
||||
|
|
@ -78,7 +78,7 @@ gem 'github-linguist', '~> 4.7.0', require: 'linguist'
|
|||
# API
|
||||
gem 'grape', '~> 1.0'
|
||||
gem 'grape-entity', '~> 0.6.0'
|
||||
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
|
||||
gem 'rack-cors', '~> 1.0.0', require: 'rack/cors'
|
||||
|
||||
# Disable strong_params so that Mash does not respond to :permitted?
|
||||
gem 'hashie-forbidden_attributes'
|
||||
|
|
@ -283,7 +283,7 @@ group :metrics do
|
|||
gem 'influxdb', '~> 0.2', require: false
|
||||
|
||||
# Prometheus
|
||||
gem 'prometheus-client-mmap', '~> 0.7.0.beta43'
|
||||
gem 'prometheus-client-mmap', '~> 0.7.0.beta44'
|
||||
gem 'raindrops', '~> 0.18'
|
||||
end
|
||||
|
||||
|
|
@ -334,10 +334,12 @@ group :development, :test do
|
|||
gem 'spring-commands-rspec', '~> 1.0.4'
|
||||
gem 'spring-commands-spinach', '~> 1.1.0'
|
||||
|
||||
gem 'rubocop', '~> 0.49.1', require: false
|
||||
gem 'rubocop-rspec', '~> 1.15.1', require: false
|
||||
gem 'rubocop-gitlab-security', '~> 0.1.0', require: false
|
||||
gem 'scss_lint', '~> 0.54.0', require: false
|
||||
gem 'gitlab-styles', '~> 2.2.0', require: false
|
||||
# Pin these dependencies, otherwise a new rule could break the CI pipelines
|
||||
gem 'rubocop', '~> 0.52.0'
|
||||
gem 'rubocop-rspec', '~> 1.20.1'
|
||||
|
||||
gem 'scss_lint', '~> 0.56.0', require: false
|
||||
gem 'haml_lint', '~> 0.26.0', require: false
|
||||
gem 'simplecov', '~> 0.14.0', require: false
|
||||
gem 'flay', '~> 2.8.0', require: false
|
||||
|
|
@ -400,7 +402,7 @@ group :ed25519 do
|
|||
end
|
||||
|
||||
# Gitaly GRPC client
|
||||
gem 'gitaly-proto', '~> 0.61.0', require: 'gitaly'
|
||||
gem 'gitaly-proto', '~> 0.64.0', require: 'gitaly'
|
||||
|
||||
gem 'toml-rb', '~> 0.3.15', require: false
|
||||
|
||||
|
|
|
|||
67
Gemfile.lock
|
|
@ -284,7 +284,7 @@ GEM
|
|||
po_to_json (>= 1.0.0)
|
||||
rails (>= 3.2.0)
|
||||
gherkin-ruby (0.3.2)
|
||||
gitaly-proto (0.61.0)
|
||||
gitaly-proto (0.64.0)
|
||||
google-protobuf (~> 3.1)
|
||||
grpc (~> 1.0)
|
||||
github-linguist (4.7.6)
|
||||
|
|
@ -303,6 +303,10 @@ GEM
|
|||
mime-types (>= 1.16)
|
||||
posix-spawn (~> 0.3)
|
||||
gitlab-markup (1.6.3)
|
||||
gitlab-styles (2.2.0)
|
||||
rubocop (~> 0.51)
|
||||
rubocop-gitlab-security (~> 0.1.0)
|
||||
rubocop-rspec (~> 1.19)
|
||||
gitlab_omniauth-ldap (2.0.4)
|
||||
net-ldap (~> 0.16)
|
||||
omniauth (~> 1.3)
|
||||
|
|
@ -501,7 +505,7 @@ GEM
|
|||
mustermann (1.0.0)
|
||||
mustermann-grape (1.0.0)
|
||||
mustermann (~> 1.0.0)
|
||||
mysql2 (0.4.5)
|
||||
mysql2 (0.4.10)
|
||||
net-ldap (0.16.0)
|
||||
net-ssh (4.1.0)
|
||||
netrc (0.11.0)
|
||||
|
|
@ -630,7 +634,7 @@ GEM
|
|||
parser
|
||||
unparser
|
||||
procto (0.0.3)
|
||||
prometheus-client-mmap (0.7.0.beta43)
|
||||
prometheus-client-mmap (0.7.0.beta44)
|
||||
pry (0.10.4)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.8.1)
|
||||
|
|
@ -647,7 +651,7 @@ GEM
|
|||
rack (>= 0.4)
|
||||
rack-attack (4.4.1)
|
||||
rack
|
||||
rack-cors (0.4.0)
|
||||
rack-cors (1.0.2)
|
||||
rack-oauth2 (1.2.3)
|
||||
activesupport (>= 2.3)
|
||||
attr_required (>= 0.0.5)
|
||||
|
|
@ -691,6 +695,9 @@ GEM
|
|||
rake
|
||||
raindrops (0.18.0)
|
||||
rake (12.3.0)
|
||||
rb-fsevent (0.10.2)
|
||||
rb-inotify (0.9.10)
|
||||
ffi (>= 0.5.0, < 2)
|
||||
rblineprof (0.3.6)
|
||||
debugger-ruby_core_source (~> 1.3)
|
||||
rbnacl (4.0.2)
|
||||
|
|
@ -704,7 +711,7 @@ GEM
|
|||
json
|
||||
recursive-open-struct (1.0.0)
|
||||
redcarpet (3.4.0)
|
||||
redis (3.3.3)
|
||||
redis (3.3.5)
|
||||
redis-actionpack (5.0.2)
|
||||
actionpack (>= 4.0, < 6)
|
||||
redis-rack (>= 1, < 3)
|
||||
|
|
@ -714,7 +721,7 @@ GEM
|
|||
redis-store (>= 1.3, < 2)
|
||||
redis-namespace (1.5.2)
|
||||
redis (~> 3.0, >= 3.0.4)
|
||||
redis-rack (2.0.3)
|
||||
redis-rack (2.0.4)
|
||||
rack (>= 1.5, < 3)
|
||||
redis-store (>= 1.2, < 2)
|
||||
redis-rails (5.0.2)
|
||||
|
|
@ -777,21 +784,21 @@ GEM
|
|||
pg
|
||||
rails
|
||||
sqlite3
|
||||
rubocop (0.49.1)
|
||||
rubocop (0.52.0)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.3.3.1, < 3.0)
|
||||
parser (>= 2.4.0.2, < 3.0)
|
||||
powerpack (~> 0.1)
|
||||
rainbow (>= 1.99.1, < 3.0)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
||||
rubocop-gitlab-security (0.1.0)
|
||||
rubocop (>= 0.47.1)
|
||||
rubocop-rspec (1.15.1)
|
||||
rubocop (>= 0.42.0)
|
||||
rubocop-gitlab-security (0.1.1)
|
||||
rubocop (>= 0.51)
|
||||
rubocop-rspec (1.20.1)
|
||||
rubocop (>= 0.51.0)
|
||||
ruby-fogbugz (0.2.1)
|
||||
crack (~> 0.4)
|
||||
ruby-prof (0.16.2)
|
||||
ruby-progressbar (1.8.1)
|
||||
ruby-progressbar (1.9.0)
|
||||
ruby-saml (1.4.1)
|
||||
nokogiri (>= 1.5.10)
|
||||
ruby_parser (3.9.0)
|
||||
|
|
@ -805,7 +812,11 @@ GEM
|
|||
safe_yaml (1.0.4)
|
||||
sanitize (2.1.0)
|
||||
nokogiri (>= 1.4.4)
|
||||
sass (3.4.22)
|
||||
sass (3.5.5)
|
||||
sass-listen (~> 4.0.0)
|
||||
sass-listen (4.0.0)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
sass-rails (5.0.6)
|
||||
railties (>= 4.0.0, < 6)
|
||||
sass (~> 3.1)
|
||||
|
|
@ -815,9 +826,9 @@ GEM
|
|||
sawyer (0.8.1)
|
||||
addressable (>= 2.3.5, < 2.6)
|
||||
faraday (~> 0.8, < 1.0)
|
||||
scss_lint (0.54.0)
|
||||
scss_lint (0.56.0)
|
||||
rake (>= 0.9, < 13)
|
||||
sass (~> 3.4.20)
|
||||
sass (~> 3.5.3)
|
||||
securecompare (1.0.0)
|
||||
seed-fu (2.3.6)
|
||||
activerecord (>= 3.1)
|
||||
|
|
@ -835,11 +846,11 @@ GEM
|
|||
rack
|
||||
shoulda-matchers (3.1.2)
|
||||
activesupport (>= 4.0.0)
|
||||
sidekiq (5.0.4)
|
||||
sidekiq (5.0.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
connection_pool (~> 2.2, >= 2.2.0)
|
||||
rack-protection (>= 1.5.0)
|
||||
redis (~> 3.3, >= 3.3.3)
|
||||
redis (>= 3.3.4, < 5)
|
||||
sidekiq-cron (0.6.0)
|
||||
rufus-scheduler (>= 3.3.0)
|
||||
sidekiq (>= 4.2.1)
|
||||
|
|
@ -1042,10 +1053,11 @@ DEPENDENCIES
|
|||
gettext (~> 3.2.2)
|
||||
gettext_i18n_rails (~> 1.8.0)
|
||||
gettext_i18n_rails_js (~> 1.2.0)
|
||||
gitaly-proto (~> 0.61.0)
|
||||
gitaly-proto (~> 0.64.0)
|
||||
github-linguist (~> 4.7.0)
|
||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||
gitlab-markup (~> 1.6.2)
|
||||
gitlab-styles (~> 2.2.0)
|
||||
gitlab_omniauth-ldap (~> 2.0.4)
|
||||
gollum-lib (~> 4.2)
|
||||
gollum-rugged_adapter (~> 0.4.4)
|
||||
|
|
@ -1082,7 +1094,7 @@ DEPENDENCIES
|
|||
method_source (~> 0.8)
|
||||
minitest (~> 5.7.0)
|
||||
mousetrap-rails (~> 1.4.6)
|
||||
mysql2 (~> 0.4.5)
|
||||
mysql2 (~> 0.4.10)
|
||||
net-ldap
|
||||
net-ssh (~> 4.1.0)
|
||||
nokogiri (~> 1.8.1)
|
||||
|
|
@ -1117,11 +1129,11 @@ DEPENDENCIES
|
|||
peek-sidekiq (~> 1.0.3)
|
||||
pg (~> 0.18.2)
|
||||
premailer-rails (~> 1.9.7)
|
||||
prometheus-client-mmap (~> 0.7.0.beta43)
|
||||
prometheus-client-mmap (~> 0.7.0.beta44)
|
||||
pry-byebug (~> 3.4.1)
|
||||
pry-rails (~> 0.3.4)
|
||||
rack-attack (~> 4.4.1)
|
||||
rack-cors (~> 0.4.0)
|
||||
rack-cors (~> 1.0.0)
|
||||
rack-oauth2 (~> 1.2.1)
|
||||
rack-proxy (~> 0.6.0)
|
||||
rails (= 4.2.10)
|
||||
|
|
@ -1148,9 +1160,8 @@ DEPENDENCIES
|
|||
rspec-retry (~> 0.4.5)
|
||||
rspec-set (~> 0.1.3)
|
||||
rspec_profiling (~> 0.0.5)
|
||||
rubocop (~> 0.49.1)
|
||||
rubocop-gitlab-security (~> 0.1.0)
|
||||
rubocop-rspec (~> 1.15.1)
|
||||
rubocop (~> 0.52.0)
|
||||
rubocop-rspec (~> 1.20.1)
|
||||
ruby-fogbugz (~> 0.2.1)
|
||||
ruby-prof (~> 0.16.2)
|
||||
ruby_parser (~> 3.8)
|
||||
|
|
@ -1158,7 +1169,7 @@ DEPENDENCIES
|
|||
rugged (~> 0.26.0)
|
||||
sanitize (~> 2.0)
|
||||
sass-rails (~> 5.0.6)
|
||||
scss_lint (~> 0.54.0)
|
||||
scss_lint (~> 0.56.0)
|
||||
seed-fu (= 2.3.6)
|
||||
select2-rails (~> 3.5.9)
|
||||
selenium-webdriver (~> 3.5)
|
||||
|
|
@ -1201,4 +1212,4 @@ DEPENDENCIES
|
|||
wikicloth (= 0.8.1)
|
||||
|
||||
BUNDLED WITH
|
||||
1.16.0
|
||||
1.16.1
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 388 KiB |
|
|
@ -1 +1 @@
|
|||
{"iconCount":181,"spriteSize":81482,"icons":["abuse","account","admin","angle-double-left","angle-double-right","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-down","arrow-right","assignee","bold","book","branch","bullhorn","calendar","cancel","chart","chevron-down","chevron-left","chevron-right","chevron-up","clock","close","code","collapse","comment-dots","comment-next","comment","comments","commit","credit-card","cut","dashboard","disk","doc_code","doc_image","doc_text","double-headed-arrow","download","duplicate","earth","ellipsis_v","emoji_slightly_smiling_face","emoji_smile","emoji_smiley","epic","external-link","eye-slash","eye","file-addition","file-deletion","file-modified","filter","folder","fork","geo-nodes","git-merge","group","history","home","hook","hourglass","image-comment-dark","image-comment-light","import","issue-block","issue-child","issue-close","issue-duplicate","issue-new","issue-open-m","issue-open","issue-parent","issues","italic","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","menu","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil-square","pencil","pipeline","play","plus-square-o","plus-square","plus","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","scroll_down","scroll_up","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","spinner","star-o","star","status_canceled_borderless","status_canceled","status_closed","status_created_borderless","status_created","status_failed_borderless","status_failed","status_manual_borderless","status_manual","status_notfound_borderless","status_open","status_pending_borderless","status_pending","status_running_borderless","status_running","status_skipped_borderless","status_skipped","status_success_borderless","status_success_solid","status_success","status_warning_borderless","status_warning","stop","task-done","template","terminal","thumb-down","thumb-up","thumbtack","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","user","users","volume-up","warning","work"]}
|
||||
{"iconCount":189,"spriteSize":85766,"icons":["abuse","account","admin","angle-double-left","angle-double-right","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-down","arrow-right","assignee","bold","book","bookmark","branch","bullhorn","calendar","cancel","chart","chevron-down","chevron-left","chevron-right","chevron-up","clock","close","code","collapse","comment-dots","comment-next","comment","comments","commit","credit-card","cut","dashboard","disk","doc_code","doc_image","doc_text","double-headed-arrow","download","duplicate","earth","ellipsis_v","emoji_slightly_smiling_face","emoji_smile","emoji_smiley","epic","external-link","eye-slash","eye","file-addition","file-deletion","file-modified","filter","folder-o-open","folder-o","folder-open","folder","fork","geo-nodes","git-merge","group","history","home","hook","hourglass","image-comment-dark","image-comment-light","import","issue-block","issue-child","issue-close","issue-duplicate","issue-external","issue-new","issue-open-m","issue-open","issue-parent","issues","italic","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","menu","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil-square","pencil","pipeline","play","plus-square-o","plus-square","plus","podcast","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","scroll_down","scroll_up","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","spinner","staged","star-o","star","status_canceled_borderless","status_canceled","status_closed","status_created_borderless","status_created","status_failed_borderless","status_failed","status_manual_borderless","status_manual","status_notfound_borderless","status_open","status_pending_borderless","status_pending","status_running_borderless","status_running","status_skipped_borderless","status_skipped","status_success_borderless","status_success_solid","status_success","status_warning_borderless","status_warning","stop","task-done","template","terminal","thumb-down","thumb-up","thumbtack","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","unstaged","user","users","volume-up","warning","work"]}
|
||||
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="430" height="300"><g fill="none" fill-rule="evenodd" transform="translate(35 29)"><path fill="#EEE" fill-rule="nonzero" d="M90 23a2 2 0 1 1 0-4h10a2 2 0 0 1 0 4H90zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h1a11.98 11.98 0 0 1 9.457 4.612 2 2 0 0 1-3.151 2.464A7.981 7.981 0 0 0 331 23h-1zm9 11.39a2 2 0 0 1 4 0v10a2 2 0 0 1-4 0v-10zm0 180a2 2 0 1 1 4 0V223c0 .56-.038 1.114-.114 1.662a2 2 0 0 1-3.962-.55A8.21 8.21 0 0 0 339 223v-8.61zm-4.769 15.931a2 2 0 0 1 1.618 3.658A11.967 11.967 0 0 1 331 235h-5.782a2 2 0 0 1 0-4H331c1.13 0 2.224-.233 3.231-.679zm-19.013.679a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zM115 231a2 2 0 0 1 0 4h-10a2 2 0 0 1 0-4h10zm-26.2 4c.131-.646.2-1.315.2-2v-2h4a2 2 0 0 1 0 4h-4.2z"/><path fill="#EEE" fill-rule="nonzero" d="M103 211h258a6 6 0 0 0 6-6V63a6 6 0 0 0-6-6H166a5 5 0 0 1-5-5v-8.5a5.5 5.5 0 0 0-5.5-5.5H109a6 6 0 0 0-6 6v167zm62-167.5V52a1 1 0 0 0 1 1h195c5.523 0 10 4.477 10 10v142c0 5.523-4.477 10-10 10H99V44c0-5.523 4.477-10 10-10h46.5a9.5 9.5 0 0 1 9.5 9.5z"/><rect width="40" height="4" x="118" y="78" fill="#6B4FBB" rx="2"/><rect width="30" height="4" x="118" y="90" fill="#EFEDF8" rx="2"/><rect width="30" height="4" x="153" y="90" fill="#E1DBF1" rx="2"/><rect width="150" height="4" x="118" y="102" fill="#EFEDF8" rx="2"/><rect width="90" height="4" x="118" y="114" fill="#E1DBF1" rx="2"/><rect width="60" height="4" x="118" y="138" fill="#EFEDF8" rx="2"/><rect width="20" height="4" x="118" y="150" fill="#6B4FBB" rx="2"/><rect width="20" height="4" x="144" y="150" fill="#C3B8E3" rx="2"/><rect width="20" height="4" x="170" y="150" fill="#E1DBF1" rx="2"/><rect width="130" height="4" x="118" y="162" fill="#EFEDF8" rx="2"/><rect width="30" height="4" x="118" y="174" fill="#C3B8E3" rx="2"/><rect width="30" height="4" x="154" y="174" fill="#EFEDF8" rx="2"/><rect width="30" height="4" x="190" y="174" fill="#EFEDF8" rx="2"/><rect width="40" height="4" x="118" y="186" fill="#E1DBF1" rx="2"/><path fill="#F9F9F9" d="M89 24.292l11.434 19.326v170.326L89 226.336V24.292z"/><path fill="#EEE" fill-rule="nonzero" d="M89 229.286v-5.9l9.434-10.223V44.165L89 28.22v-7.856l13.434 22.707v171.655L89 229.286zM10 4a6 6 0 0 0-6 6v223a6 6 0 0 0 6 6h69a6 6 0 0 0 6-6V10a6 6 0 0 0-6-6H10zm0-4h69c5.523 0 10 4.477 10 10v223c0 5.523-4.477 10-10 10H10c-5.523 0-10-4.477-10-10V10C0 4.477 4.477 0 10 0z"/><circle cx="25" cy="23" r="11" fill="#FEF0E8"/><path fill="#FEE1D3" d="M46 17h16a2 2 0 1 1 0 4H46a2 2 0 1 1 0-4zm0 8h27a2 2 0 1 1 0 4H46a2 2 0 1 1 0-4z"/><path fill="#EEE" d="M16 50h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H30a2 2 0 1 1 0-4zm-4 12h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H40a2 2 0 1 1 0-4zM26 78h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H40a2 2 0 1 1 0-4z"/><g transform="translate(14 110)"><rect width="8" height="8" fill="#FEE1D3" rx="2"/><rect width="28" height="4" x="14" y="2" fill="#FEF0E8" rx="2"/></g><path fill="#EEE" d="M16 140h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H30a2 2 0 1 1 0-4zm-14 14h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H30a2 2 0 1 1 0-4zm-14 14h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H30a2 2 0 1 1 0-4zm-14 14h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H30a2 2 0 1 1 0-4z"/><g transform="translate(24 124)"><rect width="8" height="8" fill="#FEE1D3" rx="2"/><rect width="28" height="4" x="14" y="2" fill="#FEF0E8" rx="2"/></g><g fill="#FC6D26" transform="translate(24 92)"><rect width="8" height="8" rx="2"/><rect width="28" height="4" x="14" y="2" rx="2"/></g><path fill="#FDC4A8" fill-rule="nonzero" d="M152 50.5a4.5 4.5 0 1 1 0-9 4.5 4.5 0 0 1 0 9zm0-3a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="82" viewBox="0 0 78 82"><g fill="none" fill-rule="evenodd"><path fill="#F9F9F9" d="M2.12 42c-.08.99-.12 1.99-.12 3 0 20.435 16.565 37 37 37s37-16.565 37-37c0-1.01-.04-2.01-.12-3C74.353 61.032 58.425 76 39 76 19.575 76 3.647 61.032 2.12 42z"/><path fill="#EEE" fill-rule="nonzero" d="M39 78C17.46 78 0 60.54 0 39S17.46 0 39 0s39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S58.33 4 39 4 4 19.67 4 39s15.67 35 35 35z"/><rect width="7" height="1" x="59" y="38" fill="#E1DBF2" rx=".5"/><path fill="#6B4FBB" d="M60.5 42a3.5 3.5 0 0 0 0-7v7z"/><rect width="7" height="1" x="12" y="38" fill="#E1DBF2" transform="matrix(-1 0 0 1 31 0)" rx=".5"/><path fill="#6B4FBB" d="M17.5 42a3.5 3.5 0 0 1 0-7v7z"/><path fill="#E1DBF1" fill-rule="nonzero" d="M39 58c10.493 0 19-8.507 19-19s-8.507-19-19-19-19 8.507-19 19 8.507 19 19 19zm0 4c-12.703 0-23-10.297-23-23s10.297-23 23-23 23 10.297 23 23-10.297 23-23 23z"/><path fill="#6B4FBB" d="M35 56a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/><path fill="#E1DBF1" fill-rule="nonzero" d="M26.5 40c0 4.143 3.355 7.5 7.494 7.5h10.012A7.497 7.497 0 0 0 51.5 40c0-4.143-3.355-7.5-7.494-7.5H33.994A7.497 7.497 0 0 0 26.5 40zm-3 0c0-5.799 4.698-10.5 10.494-10.5h10.012C49.802 29.5 54.5 34.2 54.5 40c0 5.799-4.698 10.5-10.494 10.5H33.994C28.198 50.5 23.5 45.8 23.5 40z"/><path fill="#6B4FBB" fill-rule="nonzero" d="M35.255 42.406a1 1 0 1 1 1.872-.703 2.001 2.001 0 0 0 3.76-.038 1 1 0 1 1 1.886.665 4 4 0 0 1-7.518.076zM31.5 40a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm15 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/><path fill="#6B4FBB" d="M38 22h2a1 1 0 0 1 0 2h-2a1 1 0 0 1 0-2zm0 3h2a1 1 0 0 1 0 2h-2a1 1 0 0 1 0-2z" style="mix-blend-mode:multiply"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
|
@ -74,6 +74,18 @@ const gfmRules = {
|
|||
return `})`;
|
||||
},
|
||||
},
|
||||
MermaidFilter: {
|
||||
'svg.mermaid'(el, text) {
|
||||
const sourceEl = el.querySelector('text.source');
|
||||
if (!sourceEl) return false;
|
||||
|
||||
return `\`\`\`mermaid\n${CopyAsGFM.nodeToGFM(sourceEl)}\n\`\`\``;
|
||||
},
|
||||
'svg.mermaid style, svg.mermaid g'(el, text) {
|
||||
// We don't want to include the content of these elements in the copied text.
|
||||
return '';
|
||||
},
|
||||
},
|
||||
MathFilter: {
|
||||
'pre.code.math[data-math-style=display]'(el, text) {
|
||||
return `\`\`\`math\n${text.trim()}\n\`\`\``;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
/* eslint-disable no-new */
|
||||
import Vue from 'vue';
|
||||
import VueResource from 'vue-resource';
|
||||
import axios from '../../lib/utils/axios_utils';
|
||||
import notebookLab from '../../notebook/index.vue';
|
||||
|
||||
Vue.use(VueResource);
|
||||
|
||||
export default () => {
|
||||
const el = document.getElementById('js-notebook-viewer');
|
||||
|
||||
|
|
@ -50,14 +48,14 @@ export default () => {
|
|||
`,
|
||||
methods: {
|
||||
loadFile() {
|
||||
this.$http.get(el.dataset.endpoint)
|
||||
.then(response => response.json())
|
||||
.then((res) => {
|
||||
this.json = res;
|
||||
axios.get(el.dataset.endpoint)
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
this.json = data;
|
||||
this.loading = false;
|
||||
})
|
||||
.catch((e) => {
|
||||
if (e.status) {
|
||||
if (e.status !== 200) {
|
||||
this.loadError = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import _ from 'underscore';
|
||||
import Vue from 'vue';
|
||||
import VueResource from 'vue-resource';
|
||||
import Flash from '../flash';
|
||||
import { __ } from '../locale';
|
||||
import FilteredSearchBoards from './filtered_search_boards';
|
||||
|
|
@ -25,8 +24,6 @@ import './components/new_list_dropdown';
|
|||
import './components/modal/index';
|
||||
import '../vue_shared/vue_resource_interceptor';
|
||||
|
||||
Vue.use(VueResource);
|
||||
|
||||
$(() => {
|
||||
const $boardApp = document.getElementById('board-app');
|
||||
const Store = gl.issueBoards.BoardsStore;
|
||||
|
|
@ -95,14 +92,13 @@ $(() => {
|
|||
|
||||
Store.disabled = this.disabled;
|
||||
gl.boardService.all()
|
||||
.then(response => response.json())
|
||||
.then((resp) => {
|
||||
resp.forEach((board) => {
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
data.forEach((board) => {
|
||||
const list = Store.addList(board, this.defaultAvatar);
|
||||
|
||||
if (list.type === 'closed') {
|
||||
list.position = Infinity;
|
||||
list.label = { description: 'Shows all closed issues. Moving an issue to this list closes it' };
|
||||
} else if (list.type === 'backlog') {
|
||||
list.position = -1;
|
||||
}
|
||||
|
|
@ -113,7 +109,9 @@ $(() => {
|
|||
Store.addBlankState();
|
||||
this.loading = false;
|
||||
})
|
||||
.catch(() => new Flash('An error occurred. Please try again.'));
|
||||
.catch(() => {
|
||||
Flash('An error occurred while fetching the board lists. Please try again.');
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
updateTokens() {
|
||||
|
|
@ -124,7 +122,7 @@ $(() => {
|
|||
if (sidebarInfoEndpoint && newIssue.subscribed === undefined) {
|
||||
newIssue.setFetchingState('subscriptions', true);
|
||||
BoardService.getIssueInfo(sidebarInfoEndpoint)
|
||||
.then(res => res.json())
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
newIssue.setFetchingState('subscriptions', false);
|
||||
newIssue.updateData({
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export default {
|
|||
|
||||
// Save the labels
|
||||
gl.boardService.generateDefaultLists()
|
||||
.then(resp => resp.json())
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
data.forEach((listObj) => {
|
||||
const list = Store.findList('title', listObj.title);
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
const options = gl.issueBoards.getBoardSortableDefaultOptions({
|
||||
scroll: document.querySelectorAll('.boards-list')[0],
|
||||
scroll: true,
|
||||
group: 'issues',
|
||||
disabled: this.disabled,
|
||||
filter: '.board-list-count, .is-disabled',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
/* eslint-disable comma-dangle, space-before-function-paren, no-new */
|
||||
/* global MilestoneSelect */
|
||||
|
||||
import Vue from 'vue';
|
||||
import Flash from '../../flash';
|
||||
|
|
@ -12,6 +11,7 @@ import './sidebar/remove_issue';
|
|||
import IssuableContext from '../../issuable_context';
|
||||
import LabelsSelect from '../../labels_select';
|
||||
import subscriptions from '../../sidebar/components/subscriptions/subscriptions.vue';
|
||||
import MilestoneSelect from '../../milestone_select';
|
||||
|
||||
const Store = gl.issueBoards.BoardsStore;
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ gl.issueBoards.IssuesModal = Vue.extend({
|
|||
page: this.page,
|
||||
per: this.perPage,
|
||||
}))
|
||||
.then(resp => resp.json())
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
if (clearIssues) {
|
||||
this.issues = [];
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class List {
|
|||
|
||||
save () {
|
||||
return gl.boardService.createList(this.label.id)
|
||||
.then(resp => resp.json())
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
this.id = data.id;
|
||||
this.type = data.list_type;
|
||||
|
|
@ -90,7 +90,7 @@ class List {
|
|||
}
|
||||
|
||||
return gl.boardService.getIssuesForList(this.id, data)
|
||||
.then(resp => resp.json())
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
this.loading = false;
|
||||
this.issuesSize = data.size;
|
||||
|
|
@ -108,7 +108,7 @@ class List {
|
|||
this.issuesSize += 1;
|
||||
|
||||
return gl.boardService.newIssue(this.id, issue)
|
||||
.then(resp => resp.json())
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
issue.id = data.id;
|
||||
issue.iid = data.iid;
|
||||
|
|
|
|||
|
|
@ -1,82 +1,79 @@
|
|||
/* eslint-disable space-before-function-paren, comma-dangle, no-param-reassign, camelcase, max-len, no-unused-vars */
|
||||
|
||||
import Vue from 'vue';
|
||||
import axios from '../../lib/utils/axios_utils';
|
||||
import { mergeUrlParams } from '../../lib/utils/url_utility';
|
||||
|
||||
export default class BoardService {
|
||||
constructor ({ boardsEndpoint, listsEndpoint, bulkUpdatePath, boardId }) {
|
||||
this.boards = Vue.resource(`${boardsEndpoint}{/id}.json`, {}, {
|
||||
issues: {
|
||||
method: 'GET',
|
||||
url: `${gon.relative_url_root}/-/boards/${boardId}/issues.json`,
|
||||
}
|
||||
});
|
||||
this.lists = Vue.resource(`${listsEndpoint}{/id}`, {}, {
|
||||
generate: {
|
||||
method: 'POST',
|
||||
url: `${listsEndpoint}/generate.json`
|
||||
}
|
||||
});
|
||||
this.issue = Vue.resource(`${gon.relative_url_root}/-/boards/${boardId}/issues{/id}`, {});
|
||||
this.issues = Vue.resource(`${listsEndpoint}{/id}/issues`, {}, {
|
||||
bulkUpdate: {
|
||||
method: 'POST',
|
||||
url: bulkUpdatePath,
|
||||
constructor({ boardsEndpoint, listsEndpoint, bulkUpdatePath, boardId }) {
|
||||
this.boardsEndpoint = boardsEndpoint;
|
||||
this.boardId = boardId;
|
||||
this.listsEndpoint = listsEndpoint;
|
||||
this.listsEndpointGenerate = `${listsEndpoint}/generate.json`;
|
||||
this.bulkUpdatePath = bulkUpdatePath;
|
||||
}
|
||||
|
||||
generateBoardsPath(id) {
|
||||
return `${this.boardsEndpoint}${id ? `/${id}` : ''}.json`;
|
||||
}
|
||||
|
||||
generateIssuesPath(id) {
|
||||
return `${this.listsEndpoint}${id ? `/${id}` : ''}/issues`;
|
||||
}
|
||||
|
||||
static generateIssuePath(boardId, id) {
|
||||
return `${gon.relative_url_root}/-/boards/${boardId ? `/${boardId}` : ''}/issues${id ? `/${id}` : ''}`;
|
||||
}
|
||||
|
||||
all() {
|
||||
return axios.get(this.listsEndpoint);
|
||||
}
|
||||
|
||||
generateDefaultLists() {
|
||||
return axios.post(this.listsEndpointGenerate, {});
|
||||
}
|
||||
|
||||
createList(labelId) {
|
||||
return axios.post(this.listsEndpoint, {
|
||||
list: {
|
||||
label_id: labelId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
all () {
|
||||
return this.lists.get();
|
||||
}
|
||||
|
||||
generateDefaultLists () {
|
||||
return this.lists.generate({});
|
||||
}
|
||||
|
||||
createList (label_id) {
|
||||
return this.lists.save({}, {
|
||||
updateList(id, position) {
|
||||
return axios.put(`${this.listsEndpoint}/${id}`, {
|
||||
list: {
|
||||
label_id
|
||||
}
|
||||
position,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
updateList (id, position) {
|
||||
return this.lists.update({ id }, {
|
||||
list: {
|
||||
position
|
||||
}
|
||||
});
|
||||
destroyList(id) {
|
||||
return axios.delete(`${this.listsEndpoint}/${id}`);
|
||||
}
|
||||
|
||||
destroyList (id) {
|
||||
return this.lists.delete({ id });
|
||||
}
|
||||
|
||||
getIssuesForList (id, filter = {}) {
|
||||
getIssuesForList(id, filter = {}) {
|
||||
const data = { id };
|
||||
Object.keys(filter).forEach((key) => { data[key] = filter[key]; });
|
||||
|
||||
return this.issues.get(data);
|
||||
return axios.get(mergeUrlParams(data, this.generateIssuesPath(id)));
|
||||
}
|
||||
|
||||
moveIssue (id, from_list_id = null, to_list_id = null, move_before_id = null, move_after_id = null) {
|
||||
return this.issue.update({ id }, {
|
||||
from_list_id,
|
||||
to_list_id,
|
||||
move_before_id,
|
||||
move_after_id,
|
||||
moveIssue(id, fromListId = null, toListId = null, moveBeforeId = null, moveAfterId = null) {
|
||||
return axios.put(BoardService.generateIssuePath(this.boardId, id), {
|
||||
from_list_id: fromListId,
|
||||
to_list_id: toListId,
|
||||
move_before_id: moveBeforeId,
|
||||
move_after_id: moveAfterId,
|
||||
});
|
||||
}
|
||||
|
||||
newIssue (id, issue) {
|
||||
return this.issues.save({ id }, {
|
||||
issue
|
||||
newIssue(id, issue) {
|
||||
return axios.post(this.generateIssuesPath(id), {
|
||||
issue,
|
||||
});
|
||||
}
|
||||
|
||||
getBacklog(data) {
|
||||
return this.boards.issues(data);
|
||||
return axios.get(mergeUrlParams(data, `${gon.relative_url_root}/-/boards/${this.boardId}/issues.json`));
|
||||
}
|
||||
|
||||
bulkUpdate(issueIds, extraData = {}) {
|
||||
|
|
@ -86,15 +83,15 @@ export default class BoardService {
|
|||
}),
|
||||
};
|
||||
|
||||
return this.issues.bulkUpdate(data);
|
||||
return axios.post(this.bulkUpdatePath, data);
|
||||
}
|
||||
|
||||
static getIssueInfo(endpoint) {
|
||||
return Vue.http.get(endpoint);
|
||||
return axios.get(endpoint);
|
||||
}
|
||||
|
||||
static toggleIssueSubscription(endpoint) {
|
||||
return Vue.http.post(endpoint);
|
||||
return axios.post(endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ export default class Clusters {
|
|||
installHelmPath,
|
||||
installIngressPath,
|
||||
installRunnerPath,
|
||||
installPrometheusPath,
|
||||
clusterStatus,
|
||||
clusterStatusReason,
|
||||
helpPath,
|
||||
|
|
@ -44,6 +45,7 @@ export default class Clusters {
|
|||
installHelmEndpoint: installHelmPath,
|
||||
installIngressEndpoint: installIngressPath,
|
||||
installRunnerEndpoint: installRunnerPath,
|
||||
installPrometheusEndpoint: installPrometheusPath,
|
||||
});
|
||||
|
||||
this.toggle = this.toggle.bind(this);
|
||||
|
|
|
|||
|
|
@ -67,6 +67,16 @@ export default {
|
|||
and send the results back to GitLab.`,
|
||||
));
|
||||
},
|
||||
prometheusDescription() {
|
||||
return sprintf(
|
||||
_.escape(s__('ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications.')), {
|
||||
gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html", target="_blank" rel="noopener noreferrer">
|
||||
${_.escape(s__('ClusterIntegration|Gitlab Integration'))}
|
||||
</a>`,
|
||||
},
|
||||
false,
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -105,6 +115,16 @@ export default {
|
|||
:status-reason="applications.ingress.statusReason"
|
||||
:request-status="applications.ingress.requestStatus"
|
||||
:request-reason="applications.ingress.requestReason"
|
||||
/>
|
||||
<application-row
|
||||
id="prometheus"
|
||||
:title="applications.prometheus.title"
|
||||
title-link="https://prometheus.io/docs/introduction/overview/"
|
||||
:description="prometheusDescription"
|
||||
:status="applications.prometheus.status"
|
||||
:status-reason="applications.prometheus.statusReason"
|
||||
:request-status="applications.prometheus.requestStatus"
|
||||
:request-reason="applications.prometheus.requestReason"
|
||||
/>
|
||||
<!-- NOTE: Don't forget to update `clusters.scss` min-height for this block and uncomment `application_spec` tests -->
|
||||
<!-- Add GitLab Runner row, all other plumbing is complete -->
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export default class ClusterService {
|
|||
helm: this.options.installHelmEndpoint,
|
||||
ingress: this.options.installIngressEndpoint,
|
||||
runner: this.options.installRunnerEndpoint,
|
||||
prometheus: this.options.installPrometheusEndpoint,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,13 @@ export default class ClusterStore {
|
|||
requestStatus: null,
|
||||
requestReason: null,
|
||||
},
|
||||
prometheus: {
|
||||
title: s__('ClusterIntegration|Prometheus'),
|
||||
status: null,
|
||||
statusReason: null,
|
||||
requestStatus: null,
|
||||
requestReason: null,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,13 +276,13 @@ export default class CreateMergeRequestDropdown {
|
|||
let target;
|
||||
let value;
|
||||
|
||||
if (event.srcElement === this.branchInput) {
|
||||
if (event.target === this.branchInput) {
|
||||
target = 'branch';
|
||||
value = this.branchInput.value;
|
||||
} else if (event.srcElement === this.refInput) {
|
||||
} else if (event.target === this.refInput) {
|
||||
target = 'ref';
|
||||
value = event.srcElement.value.slice(0, event.srcElement.selectionStart) +
|
||||
event.srcElement.value.slice(event.srcElement.selectionEnd);
|
||||
value = event.target.value.slice(0, event.target.selectionStart) +
|
||||
event.target.value.slice(event.target.selectionEnd);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import limitWarning from './limit_warning_component.vue';
|
||||
import totalTime from './total_time_component.vue';
|
||||
import icon from '../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
|
@ -12,6 +13,7 @@
|
|||
userAvatarImage,
|
||||
totalTime,
|
||||
limitWarning,
|
||||
icon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -52,7 +54,10 @@
|
|||
</template>
|
||||
<template v-else>
|
||||
<span class="merge-request-branch" v-if="mergeRequest.branch">
|
||||
<i class= "fa fa-code-fork"></i>
|
||||
<icon
|
||||
name="fork"
|
||||
:size="16">
|
||||
</icon>
|
||||
<a :href="mergeRequest.branch.url">{{ mergeRequest.branch.name }}</a>
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import iconBranch from '../svg/icon_branch.svg';
|
||||
import limitWarning from './limit_warning_component.vue';
|
||||
import totalTime from './total_time_component.vue';
|
||||
import icon from '../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
|
@ -13,6 +14,7 @@
|
|||
userAvatarImage,
|
||||
totalTime,
|
||||
limitWarning,
|
||||
icon,
|
||||
},
|
||||
computed: {
|
||||
iconBranch() {
|
||||
|
|
@ -37,7 +39,10 @@
|
|||
<user-avatar-image :img-src="build.author.avatarUrl"/>
|
||||
<h5 class="item-title">
|
||||
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
||||
<i class="fa fa-code-fork"></i>
|
||||
<icon
|
||||
name="fork"
|
||||
:size="16">
|
||||
</icon>
|
||||
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
|
||||
<span class="icon-branch" v-html="iconBranch"></span>
|
||||
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import iconBranch from '../svg/icon_branch.svg';
|
||||
import limitWarning from './limit_warning_component.vue';
|
||||
import totalTime from './total_time_component.vue';
|
||||
import icon from '../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
|
@ -12,6 +13,7 @@
|
|||
components: {
|
||||
totalTime,
|
||||
limitWarning,
|
||||
icon,
|
||||
},
|
||||
computed: {
|
||||
iconBuildStatus() {
|
||||
|
|
@ -40,7 +42,10 @@
|
|||
<a :href="build.url" class="item-build-name">{{ build.name }}</a>
|
||||
·
|
||||
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
||||
<i class="fa fa-code-fork"></i>
|
||||
<icon
|
||||
name="fork"
|
||||
:size="16">
|
||||
</icon>
|
||||
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
|
||||
<span class="icon-branch" v-html="iconBranch"></span>
|
||||
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import IssuableIndex from './issuable_index';
|
|||
import Milestone from './milestone';
|
||||
import IssuableForm from './issuable_form';
|
||||
import LabelsSelect from './labels_select';
|
||||
/* global MilestoneSelect */
|
||||
import MilestoneSelect from './milestone_select';
|
||||
import NewBranchForm from './new_branch_form';
|
||||
import NotificationsForm from './notifications_form';
|
||||
import notificationsDropdown from './notifications_dropdown';
|
||||
|
|
@ -56,7 +56,6 @@ import GfmAutoComplete from './gfm_auto_complete';
|
|||
import ShortcutsBlob from './shortcuts_blob';
|
||||
import SigninTabsMemoizer from './signin_tabs_memoizer';
|
||||
import Star from './star';
|
||||
import Todos from './todos';
|
||||
import TreeView from './tree';
|
||||
import UsagePing from './usage_ping';
|
||||
import UsernameValidator from './username_validator';
|
||||
|
|
@ -111,6 +110,7 @@ import Activities from './activities';
|
|||
}
|
||||
|
||||
const fail = () => Flash('Error loading dynamic module');
|
||||
const callDefault = m => m.default();
|
||||
|
||||
path = page.split(':');
|
||||
shortcut_handler = null;
|
||||
|
|
@ -212,7 +212,7 @@ import Activities from './activities';
|
|||
projectSelect();
|
||||
break;
|
||||
case 'dashboard:todos:index':
|
||||
new Todos();
|
||||
import('./pages/dashboard/todos/index').then(callDefault).catch(fail);
|
||||
break;
|
||||
case 'dashboard:projects:index':
|
||||
case 'dashboard:projects:starred':
|
||||
|
|
@ -542,7 +542,7 @@ import Activities from './activities';
|
|||
new CILintEditor();
|
||||
break;
|
||||
case 'users:show':
|
||||
import('./pages/users/show').then(m => m.default()).catch(fail);
|
||||
import('./pages/users/show').then(callDefault).catch(fail);
|
||||
break;
|
||||
case 'admin:conversational_development_index:show':
|
||||
new UserCallout();
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ class FilteredSearchManager {
|
|||
this.handleInputVisualTokenWrapper = this.handleInputVisualToken.bind(this);
|
||||
this.checkForEnterWrapper = this.checkForEnter.bind(this);
|
||||
this.onClearSearchWrapper = this.onClearSearch.bind(this);
|
||||
this.checkForBackspaceWrapper = this.checkForBackspace.bind(this);
|
||||
this.checkForBackspaceWrapper = this.checkForBackspace.call(this);
|
||||
this.removeSelectedTokenKeydownWrapper = this.removeSelectedTokenKeydown.bind(this);
|
||||
this.unselectEditTokensWrapper = this.unselectEditTokens.bind(this);
|
||||
this.editTokenWrapper = this.editToken.bind(this);
|
||||
|
|
@ -180,22 +180,34 @@ class FilteredSearchManager {
|
|||
this.unbindStateEvents();
|
||||
}
|
||||
|
||||
checkForBackspace(e) {
|
||||
// 8 = Backspace Key
|
||||
// 46 = Delete Key
|
||||
if (e.keyCode === 8 || e.keyCode === 46) {
|
||||
const { lastVisualToken } = gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
||||
checkForBackspace() {
|
||||
let backspaceCount = 0;
|
||||
|
||||
const { tokenName, tokenValue } = gl.DropdownUtils.getVisualTokenValues(lastVisualToken);
|
||||
const canEdit = tokenName && this.canEdit && this.canEdit(tokenName, tokenValue);
|
||||
if (this.filteredSearchInput.value === '' && lastVisualToken && canEdit) {
|
||||
this.filteredSearchInput.value = gl.FilteredSearchVisualTokens.getLastTokenPartial();
|
||||
gl.FilteredSearchVisualTokens.removeLastTokenPartial();
|
||||
// closure for keeping track of the number of backspace keystrokes
|
||||
return (e) => {
|
||||
// 8 = Backspace Key
|
||||
// 46 = Delete Key
|
||||
if (e.keyCode === 8 || e.keyCode === 46) {
|
||||
const { lastVisualToken } = gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
||||
const { tokenName, tokenValue } = gl.DropdownUtils.getVisualTokenValues(lastVisualToken);
|
||||
const canEdit = tokenName && this.canEdit && this.canEdit(tokenName, tokenValue);
|
||||
|
||||
if (this.filteredSearchInput.value === '' && lastVisualToken && canEdit) {
|
||||
backspaceCount += 1;
|
||||
|
||||
if (backspaceCount === 2) {
|
||||
backspaceCount = 0;
|
||||
this.filteredSearchInput.value = gl.FilteredSearchVisualTokens.getLastTokenPartial();
|
||||
gl.FilteredSearchVisualTokens.removeLastTokenPartial();
|
||||
}
|
||||
}
|
||||
|
||||
// Reposition dropdown so that it is aligned with cursor
|
||||
this.dropdownManager.updateCurrentDropdownOffset();
|
||||
} else {
|
||||
backspaceCount = 0;
|
||||
}
|
||||
|
||||
// Reposition dropdown so that it is aligned with cursor
|
||||
this.dropdownManager.updateCurrentDropdownOffset();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
checkForEnter(e) {
|
||||
|
|
|
|||
|
|
@ -57,12 +57,12 @@ class GfmAutoComplete {
|
|||
displayTpl(value) {
|
||||
if (GfmAutoComplete.isLoading(value)) return GfmAutoComplete.Loading.template;
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
let tpl = '<li>/${name}';
|
||||
let tpl = '<li><span class="name">/${name}</span>';
|
||||
if (value.aliases.length > 0) {
|
||||
tpl += ' <small>(or /<%- aliases.join(", /") %>)</small>';
|
||||
tpl += ' <small class="aliases">(or /<%- aliases.join(", /") %>)</small>';
|
||||
}
|
||||
if (value.params.length > 0) {
|
||||
tpl += ' <small><%- params.join(" ") %></small>';
|
||||
tpl += ' <small class="params"><%- params.join(" ") %></small>';
|
||||
}
|
||||
if (value.description !== '') {
|
||||
tpl += '<small class="description"><i><%- description %></i></small>';
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ export default {
|
|||
class="group-row"
|
||||
>
|
||||
<div
|
||||
class="group-row-contents">
|
||||
class="group-row-contents"
|
||||
:class="{ 'project-row-contents': !isGroup }">
|
||||
<item-actions
|
||||
v-if="isGroup"
|
||||
:group="group"
|
||||
|
|
@ -97,7 +98,7 @@ export default {
|
|||
/>
|
||||
</div>
|
||||
<div
|
||||
class="avatar-container s40 hidden-xs"
|
||||
class="avatar-container prepend-top-8 prepend-left-5 s24 hidden-xs"
|
||||
:class="{ 'content-loading': group.isChildrenLoading }"
|
||||
>
|
||||
<a
|
||||
|
|
@ -106,11 +107,12 @@ export default {
|
|||
>
|
||||
<img
|
||||
v-if="hasAvatar"
|
||||
class="avatar s40"
|
||||
class="avatar s24"
|
||||
:src="group.avatarUrl"
|
||||
/>
|
||||
<identicon
|
||||
v-else
|
||||
size-class="s24"
|
||||
:entity-id=group.id
|
||||
:entity-name="group.name"
|
||||
/>
|
||||
|
|
@ -123,7 +125,7 @@ export default {
|
|||
:href="group.relativePath"
|
||||
:title="group.fullName"
|
||||
class="no-expand"
|
||||
data-placement="top"
|
||||
data-placement="bottom"
|
||||
>{{
|
||||
// ending bracket must be by closing tag to prevent
|
||||
// link hover text-decoration from over-extending
|
||||
|
|
@ -139,7 +141,8 @@ export default {
|
|||
<div
|
||||
v-if="group.description"
|
||||
class="description">
|
||||
{{group.description}}
|
||||
<span v-html="group.description">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<group-folder
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<script>
|
||||
import { s__ } from '../../locale';
|
||||
import tooltip from '../../vue_shared/directives/tooltip';
|
||||
import modal from '../../vue_shared/components/modal.vue';
|
||||
import { s__ } from '~/locale';
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
import icon from '~/vue_shared/components/icon.vue';
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import eventHub from '../event_hub';
|
||||
import { COMMON_STR } from '../constants';
|
||||
import Icon from '../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Icon,
|
||||
icon,
|
||||
modal,
|
||||
},
|
||||
directives: {
|
||||
|
|
@ -45,11 +45,9 @@ export default {
|
|||
onLeaveGroup() {
|
||||
this.modalStatus = true;
|
||||
},
|
||||
leaveGroup(leaveConfirmed) {
|
||||
leaveGroup() {
|
||||
this.modalStatus = false;
|
||||
if (leaveConfirmed) {
|
||||
eventHub.$emit('leaveGroup', this.group, this.parentGroup);
|
||||
}
|
||||
eventHub.$emit('leaveGroup', this.group, this.parentGroup);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -64,10 +62,9 @@ export default {
|
|||
:title="editBtnTitle"
|
||||
:aria-label="editBtnTitle"
|
||||
data-container="body"
|
||||
data-placement="bottom"
|
||||
class="edit-group btn no-expand">
|
||||
<icon
|
||||
name="settings">
|
||||
</icon>
|
||||
<icon name="settings"/>
|
||||
</a>
|
||||
<a
|
||||
v-tooltip
|
||||
|
|
@ -77,10 +74,9 @@ export default {
|
|||
:title="leaveBtnTitle"
|
||||
:aria-label="leaveBtnTitle"
|
||||
data-container="body"
|
||||
data-placement="bottom"
|
||||
class="leave-group btn no-expand">
|
||||
<i
|
||||
class="fa fa-sign-out"
|
||||
aria-hidden="true"/>
|
||||
<icon name="leave"/>
|
||||
</a>
|
||||
<modal
|
||||
v-show="modalStatus"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<script>
|
||||
import icon from '~/vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
isGroupOpen: {
|
||||
|
|
@ -7,9 +9,12 @@ export default {
|
|||
default: false,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
icon,
|
||||
},
|
||||
computed: {
|
||||
iconClass() {
|
||||
return this.isGroupOpen ? 'fa-caret-down' : 'fa-caret-right';
|
||||
return this.isGroupOpen ? 'angle-down' : 'angle-right';
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -17,9 +22,9 @@ export default {
|
|||
|
||||
<template>
|
||||
<span class="folder-caret">
|
||||
<i
|
||||
:class="iconClass"
|
||||
class="fa"
|
||||
aria-hidden="true"/>
|
||||
<icon
|
||||
:size="12"
|
||||
:name="iconClass"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
<script>
|
||||
import tooltip from '../../vue_shared/directives/tooltip';
|
||||
import icon from '~/vue_shared/components/icon.vue';
|
||||
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import { ITEM_TYPE, VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE, PROJECT_VISIBILITY_TYPE } from '../constants';
|
||||
import itemStatsValue from './item_stats_value.vue';
|
||||
|
||||
export default {
|
||||
directives: {
|
||||
tooltip,
|
||||
components: {
|
||||
icon,
|
||||
timeAgoTooltip,
|
||||
itemStatsValue,
|
||||
},
|
||||
props: {
|
||||
item: {
|
||||
|
|
@ -34,65 +38,47 @@ export default {
|
|||
|
||||
<template>
|
||||
<div class="stats">
|
||||
<span
|
||||
v-tooltip
|
||||
<item-stats-value
|
||||
v-if="isGroup"
|
||||
:title="s__('Subgroups')"
|
||||
class="number-subgroups"
|
||||
data-placement="top"
|
||||
data-container="body">
|
||||
<i
|
||||
class="fa fa-folder"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{{item.subgroupCount}}
|
||||
</span>
|
||||
<span
|
||||
v-tooltip
|
||||
css-class="number-subgroups"
|
||||
icon-name="folder"
|
||||
:title="__('Subgroups')"
|
||||
:value="item.subgroupCount"
|
||||
/>
|
||||
<item-stats-value
|
||||
v-if="isGroup"
|
||||
:title="s__('Projects')"
|
||||
class="number-projects"
|
||||
data-placement="top"
|
||||
data-container="body">
|
||||
<i
|
||||
class="fa fa-bookmark"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{{item.projectCount}}
|
||||
</span>
|
||||
<span
|
||||
v-tooltip
|
||||
css-class="number-projects"
|
||||
icon-name="bookmark"
|
||||
:title="__('Projects')"
|
||||
:value="item.projectCount"
|
||||
/>
|
||||
<item-stats-value
|
||||
v-if="isGroup"
|
||||
:title="s__('Members')"
|
||||
class="number-users"
|
||||
data-placement="top"
|
||||
data-container="body">
|
||||
<i
|
||||
class="fa fa-users"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{{item.memberCount}}
|
||||
</span>
|
||||
<span
|
||||
css-class="number-users"
|
||||
icon-name="users"
|
||||
:title="__('Members')"
|
||||
:value="item.memberCount"
|
||||
/>
|
||||
<item-stats-value
|
||||
v-if="isProject"
|
||||
class="project-stars">
|
||||
<i
|
||||
class="fa fa-star"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{{item.starCount}}
|
||||
</span>
|
||||
<span
|
||||
v-tooltip
|
||||
css-class="project-stars"
|
||||
icon-name="star"
|
||||
:value="item.starCount"
|
||||
/>
|
||||
<item-stats-value
|
||||
css-class="item-visibility"
|
||||
tooltip-placement="left"
|
||||
:icon-name="visibilityIcon"
|
||||
:title="visibilityTooltip"
|
||||
data-placement="left"
|
||||
data-container="body"
|
||||
class="item-visibility">
|
||||
<i
|
||||
:class="visibilityIcon"
|
||||
class="fa"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div
|
||||
class="last-updated"
|
||||
v-if="isProject"
|
||||
>
|
||||
<time-ago-tooltip
|
||||
tooltip-placement="bottom"
|
||||
:time="item.updatedAt"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
<script>
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
import icon from '~/vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
cssClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
iconName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
tooltipPlacement: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'bottom',
|
||||
},
|
||||
/**
|
||||
* value could either be number or string
|
||||
* as `memberCount` is always passed as string
|
||||
* while `subgroupCount` & `projectCount`
|
||||
* are always number
|
||||
*/
|
||||
value: {
|
||||
type: [Number, String],
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
components: {
|
||||
icon,
|
||||
},
|
||||
computed: {
|
||||
isValuePresent() {
|
||||
return this.value !== '';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span
|
||||
v-tooltip
|
||||
data-container="body"
|
||||
:data-placement="tooltipPlacement"
|
||||
:class="cssClass"
|
||||
:title="title"
|
||||
>
|
||||
<icon :name="iconName"/>
|
||||
<span
|
||||
v-if="isValuePresent"
|
||||
class="stat-value"
|
||||
>
|
||||
{{value}}
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
|
|
@ -1,7 +1,11 @@
|
|||
<script>
|
||||
import icon from '~/vue_shared/components/icon.vue';
|
||||
import { ITEM_TYPE } from '../constants';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
icon,
|
||||
},
|
||||
props: {
|
||||
itemType: {
|
||||
type: String,
|
||||
|
|
@ -16,9 +20,9 @@ export default {
|
|||
computed: {
|
||||
iconClass() {
|
||||
if (this.itemType === ITEM_TYPE.GROUP) {
|
||||
return this.isGroupOpen ? 'fa-folder-open' : 'fa-folder';
|
||||
return this.isGroupOpen ? 'folder-open' : 'folder';
|
||||
}
|
||||
return 'fa-bookmark';
|
||||
return 'bookmark';
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -26,9 +30,6 @@ export default {
|
|||
|
||||
<template>
|
||||
<span class="item-type-icon">
|
||||
<i
|
||||
:class="iconClass"
|
||||
class="fa"
|
||||
aria-hidden="true"/>
|
||||
<icon :name="iconClass"/>
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export const PROJECT_VISIBILITY_TYPE = {
|
|||
};
|
||||
|
||||
export const VISIBILITY_TYPE_ICON = {
|
||||
public: 'fa-globe',
|
||||
internal: 'fa-shield',
|
||||
private: 'fa-lock',
|
||||
public: 'earth',
|
||||
internal: 'shield',
|
||||
private: 'lock',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ export default class GroupsStore {
|
|||
id: rawGroupItem.id,
|
||||
name: rawGroupItem.name,
|
||||
fullName: rawGroupItem.full_name,
|
||||
description: rawGroupItem.description,
|
||||
description: rawGroupItem.markdown_description,
|
||||
visibility: rawGroupItem.visibility,
|
||||
avatarUrl: rawGroupItem.avatar_url,
|
||||
relativePath: rawGroupItem.relative_path,
|
||||
|
|
@ -91,6 +91,7 @@ export default class GroupsStore {
|
|||
subgroupCount: rawGroupItem.subgroup_count,
|
||||
memberCount: rawGroupItem.number_users_with_delimiter,
|
||||
starCount: rawGroupItem.star_count,
|
||||
updatedAt: rawGroupItem.updated_at,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@ import repoPreview from './repo_preview.vue';
|
|||
import repoEditor from './repo_editor.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
emptyStateSvgPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
'currentBlobView',
|
||||
|
|
@ -64,7 +70,23 @@ export default {
|
|||
<template
|
||||
v-else>
|
||||
<div class="ide-empty-state">
|
||||
<h2 class="clgray">Welcome to the GitLab IDE</h2>
|
||||
<div class="row js-empty-state">
|
||||
<div class="col-xs-12">
|
||||
<div class="svg-content svg-250">
|
||||
<img :src="emptyStateSvgPath">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12">
|
||||
<div class="text-content text-center">
|
||||
<h4>
|
||||
Welcome to the GitLab IDE
|
||||
</h4>
|
||||
<p>
|
||||
You can select a file in the left sidebar to begin editing and use the right sidebar to commit your changes.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,11 +2,18 @@
|
|||
import { mapGetters, mapState, mapActions } from 'vuex';
|
||||
import repoCommitSection from './repo_commit_section.vue';
|
||||
import icon from '../../vue_shared/components/icon.vue';
|
||||
import panelResizer from '../../vue_shared/components/panel_resizer.vue';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
width: 290,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
repoCommitSection,
|
||||
icon,
|
||||
panelResizer,
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
|
|
@ -18,10 +25,20 @@ export default {
|
|||
currentIcon() {
|
||||
return this.rightPanelCollapsed ? 'angle-double-left' : 'angle-double-right';
|
||||
},
|
||||
maxSize() {
|
||||
return window.innerWidth / 2;
|
||||
},
|
||||
panelStyle() {
|
||||
if (!this.rightPanelCollapsed) {
|
||||
return { width: `${this.width}px` };
|
||||
}
|
||||
return {};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
'setPanelCollapsedStatus',
|
||||
'setResizingStatus',
|
||||
]),
|
||||
toggleCollapsed() {
|
||||
this.setPanelCollapsedStatus({
|
||||
|
|
@ -29,6 +46,12 @@ export default {
|
|||
collapsed: !this.rightPanelCollapsed,
|
||||
});
|
||||
},
|
||||
resizingStarted() {
|
||||
this.setResizingStatus(true);
|
||||
},
|
||||
resizingEnded() {
|
||||
this.setResizingStatus(false);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -39,6 +62,7 @@ export default {
|
|||
:class="{
|
||||
'is-collapsed': rightPanelCollapsed,
|
||||
}"
|
||||
:style="panelStyle"
|
||||
>
|
||||
<div
|
||||
class="multi-file-commit-panel-section">
|
||||
|
|
@ -71,5 +95,14 @@ export default {
|
|||
<repo-commit-section
|
||||
class=""/>
|
||||
</div>
|
||||
<panel-resizer
|
||||
:size.sync="width"
|
||||
:enabled="!rightPanelCollapsed"
|
||||
:start-size="290"
|
||||
:min-size="200"
|
||||
:max-size="maxSize"
|
||||
@resize-start="resizingStarted"
|
||||
@resize-end="resizingEnded"
|
||||
side="left"/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import RepoPreviousDirectory from './repo_prev_directory.vue';
|
||||
import RepoFile from './repo_file.vue';
|
||||
import RepoLoadingFile from './repo_loading_file.vue';
|
||||
import repoPreviousDirectory from './repo_prev_directory.vue';
|
||||
import repoFile from './repo_file.vue';
|
||||
import skeletonLoadingContainer from '../../vue_shared/components/skeleton_loading_container.vue';
|
||||
import { treeList } from '../stores/utils';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
'repo-previous-directory': RepoPreviousDirectory,
|
||||
'repo-file': RepoFile,
|
||||
'repo-loading-file': RepoLoadingFile,
|
||||
repoPreviousDirectory,
|
||||
repoFile,
|
||||
skeletonLoadingContainer,
|
||||
},
|
||||
props: {
|
||||
treeId: {
|
||||
|
|
@ -19,7 +19,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
'loading',
|
||||
'trees',
|
||||
'isRoot',
|
||||
]),
|
||||
...mapState({
|
||||
|
|
@ -34,7 +34,10 @@ export default {
|
|||
return !this.isRoot && this.fetchedList.length;
|
||||
},
|
||||
showLoading() {
|
||||
return this.loading;
|
||||
if (this.trees[this.treeId]) {
|
||||
return this.trees[this.treeId].loading;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -49,11 +52,13 @@ export default {
|
|||
<repo-previous-directory
|
||||
v-if="hasPreviousDirectory"
|
||||
/>
|
||||
<repo-loading-file
|
||||
<div
|
||||
class="multi-file-loading-container"
|
||||
v-if="showLoading"
|
||||
v-for="n in 5"
|
||||
:key="n"
|
||||
/>
|
||||
v-for="n in 3"
|
||||
:key="n">
|
||||
<skeleton-loading-container/>
|
||||
</div>
|
||||
<repo-file
|
||||
v-for="file in fetchedList"
|
||||
:key="file.key"
|
||||
|
|
|
|||
|
|
@ -2,24 +2,47 @@
|
|||
import { mapState, mapActions } from 'vuex';
|
||||
import projectTree from './ide_project_tree.vue';
|
||||
import icon from '../../vue_shared/components/icon.vue';
|
||||
import panelResizer from '../../vue_shared/components/panel_resizer.vue';
|
||||
import skeletonLoadingContainer from '../../vue_shared/components/skeleton_loading_container.vue';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
width: 290,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
projectTree,
|
||||
icon,
|
||||
panelResizer,
|
||||
skeletonLoadingContainer,
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
'loading',
|
||||
'projects',
|
||||
'leftPanelCollapsed',
|
||||
]),
|
||||
currentIcon() {
|
||||
return this.leftPanelCollapsed ? 'angle-double-right' : 'angle-double-left';
|
||||
},
|
||||
maxSize() {
|
||||
return window.innerWidth / 2;
|
||||
},
|
||||
panelStyle() {
|
||||
if (!this.leftPanelCollapsed) {
|
||||
return { width: `${this.width}px` };
|
||||
}
|
||||
return {};
|
||||
},
|
||||
showLoading() {
|
||||
return this.loading;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
'setPanelCollapsedStatus',
|
||||
'setResizingStatus',
|
||||
]),
|
||||
toggleCollapsed() {
|
||||
this.setPanelCollapsedStatus({
|
||||
|
|
@ -27,6 +50,12 @@ export default {
|
|||
collapsed: !this.leftPanelCollapsed,
|
||||
});
|
||||
},
|
||||
resizingStarted() {
|
||||
this.setResizingStatus(true);
|
||||
},
|
||||
resizingEnded() {
|
||||
this.setResizingStatus(false);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -37,8 +66,16 @@ export default {
|
|||
:class="{
|
||||
'is-collapsed': leftPanelCollapsed,
|
||||
}"
|
||||
:style="panelStyle"
|
||||
>
|
||||
<div class="multi-file-commit-panel-inner">
|
||||
<div
|
||||
class="multi-file-loading-container"
|
||||
v-if="showLoading"
|
||||
v-for="n in 3"
|
||||
:key="n">
|
||||
<skeleton-loading-container/>
|
||||
</div>
|
||||
<project-tree
|
||||
v-for="(project, index) in projects"
|
||||
:key="project.id"
|
||||
|
|
@ -58,5 +95,14 @@ export default {
|
|||
class="collapse-text"
|
||||
>Collapse sidebar</span>
|
||||
</button>
|
||||
<panel-resizer
|
||||
:size.sync="width"
|
||||
:enabled="!leftPanelCollapsed"
|
||||
:start-size="290"
|
||||
:min-size="200"
|
||||
:max-size="maxSize"
|
||||
@resize-start="resizingStarted"
|
||||
@resize-end="resizingEnded"
|
||||
side="right"/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@
|
|||
methods: {
|
||||
createNewItem(type) {
|
||||
this.modalType = type;
|
||||
this.toggleModalOpen();
|
||||
this.openModal = true;
|
||||
},
|
||||
toggleModalOpen() {
|
||||
this.openModal = !this.openModal;
|
||||
hideModal() {
|
||||
this.openModal = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -95,7 +95,7 @@
|
|||
:branch-id="branch"
|
||||
:path="path"
|
||||
:parent="parent"
|
||||
@toggle="toggleModalOpen"
|
||||
@hide="hideModal"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@
|
|||
type: this.type,
|
||||
});
|
||||
|
||||
this.toggleModalOpen();
|
||||
this.hideModal();
|
||||
},
|
||||
toggleModalOpen() {
|
||||
this.$emit('toggle');
|
||||
hideModal() {
|
||||
this.$emit('hide');
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
:title="modalTitle"
|
||||
:primary-button-label="buttonLabel"
|
||||
kind="success"
|
||||
@toggle="toggleModalOpen"
|
||||
@cancel="hideModal"
|
||||
@submit="createEntryInStore"
|
||||
>
|
||||
<form
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ export default {
|
|||
kind="primary"
|
||||
:title="__('Branch has changed')"
|
||||
:text="__('This branch has changed since you started editing. Would you like to create a new branch?')"
|
||||
@toggle="showNewBranchModal = false"
|
||||
@cancel="showNewBranchModal = false"
|
||||
@submit="makeCommit(true)"
|
||||
/>
|
||||
<commit-files-list
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export default {
|
|||
kind="warning"
|
||||
:title="__('Are you sure?')"
|
||||
:text="__('Are you sure you want to discard your changes?')"
|
||||
@toggle="closeDiscardPopup"
|
||||
@cancel="closeDiscardPopup"
|
||||
@submit="toggleEditMode(true)"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -90,6 +90,11 @@ export default {
|
|||
rightPanelCollapsed() {
|
||||
this.editor.updateDimensions();
|
||||
},
|
||||
panelResizing(isResizing) {
|
||||
if (isResizing === false) {
|
||||
this.editor.updateDimensions();
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
|
|
@ -99,6 +104,7 @@ export default {
|
|||
...mapState([
|
||||
'leftPanelCollapsed',
|
||||
'rightPanelCollapsed',
|
||||
'panelResizing',
|
||||
]),
|
||||
shouldHideEditor() {
|
||||
return this.activeFile.binary && !this.activeFile.raw;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import timeAgoMixin from '../../vue_shared/mixins/timeago';
|
||||
import skeletonLoadingContainer from '../../vue_shared/components/skeleton_loading_container.vue';
|
||||
import newDropdown from './new_dropdown/index.vue';
|
||||
import fileIcon from '../../vue_shared/components/file_icon.vue';
|
||||
|
||||
export default {
|
||||
mixins: [
|
||||
|
|
@ -11,6 +12,7 @@
|
|||
components: {
|
||||
skeletonLoadingContainer,
|
||||
newDropdown,
|
||||
fileIcon,
|
||||
},
|
||||
props: {
|
||||
file: {
|
||||
|
|
@ -26,13 +28,6 @@
|
|||
...mapState([
|
||||
'leftPanelCollapsed',
|
||||
]),
|
||||
fileIcon() {
|
||||
return {
|
||||
'fa-spinner fa-spin': this.file.loading,
|
||||
[this.file.icon]: !this.file.loading,
|
||||
'fa-folder-open': !this.file.loading && this.file.opened,
|
||||
};
|
||||
},
|
||||
isSubmodule() {
|
||||
return this.file.type === 'submodule';
|
||||
},
|
||||
|
|
@ -94,16 +89,18 @@
|
|||
class="multi-file-table-name"
|
||||
:colspan="submoduleColSpan"
|
||||
>
|
||||
<i
|
||||
class="fa fa-fw file-icon"
|
||||
:class="fileIcon"
|
||||
:style="levelIndentation"
|
||||
aria-hidden="true"
|
||||
>
|
||||
</i>
|
||||
<a
|
||||
class="repo-file-name"
|
||||
>
|
||||
<file-icon
|
||||
:file-name="file.name"
|
||||
:loading="file.loading"
|
||||
:folder="file.type === 'tree'"
|
||||
:opened="file.opened"
|
||||
:style="levelIndentation"
|
||||
:size="16"
|
||||
>
|
||||
</file-icon>
|
||||
{{ file.name }}
|
||||
</a>
|
||||
<new-dropdown
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { mapActions } from 'vuex';
|
||||
import fileIcon from '../../vue_shared/components/file_icon.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
|
@ -8,7 +9,9 @@ export default {
|
|||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
fileIcon,
|
||||
},
|
||||
computed: {
|
||||
closeLabel() {
|
||||
if (this.tab.changed || this.tab.tempFile) {
|
||||
|
|
@ -63,6 +66,11 @@ export default {
|
|||
:class="{active : tab.active }"
|
||||
:title="tab.url"
|
||||
>
|
||||
<file-icon
|
||||
:file-name="tab.name"
|
||||
:size="16"
|
||||
>
|
||||
</file-icon>
|
||||
{{ tab.name }}
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
import Vue from 'vue';
|
||||
import { mapActions } from 'vuex';
|
||||
import { convertPermissionToBoolean } from '../lib/utils/common_utils';
|
||||
import ide from './components/ide.vue';
|
||||
|
||||
import store from './stores';
|
||||
import router from './ide_router';
|
||||
import Translate from '../vue_shared/translate';
|
||||
import ContextualSidebar from '../contextual_sidebar';
|
||||
|
||||
function initIde(el) {
|
||||
if (!el) return null;
|
||||
|
|
@ -18,29 +14,12 @@ function initIde(el) {
|
|||
components: {
|
||||
ide,
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
'setInitialData',
|
||||
]),
|
||||
},
|
||||
created() {
|
||||
const data = el.dataset;
|
||||
|
||||
this.setInitialData({
|
||||
endpoints: {
|
||||
rootEndpoint: data.url,
|
||||
newMergeRequestUrl: data.newMergeRequestUrl,
|
||||
rootUrl: data.rootUrl,
|
||||
},
|
||||
canCommit: convertPermissionToBoolean(data.canCommit),
|
||||
onTopOfBranch: convertPermissionToBoolean(data.onTopOfBranch),
|
||||
path: data.currentPath,
|
||||
isRoot: convertPermissionToBoolean(data.root),
|
||||
isInitialRoot: convertPermissionToBoolean(data.root),
|
||||
});
|
||||
},
|
||||
render(createElement) {
|
||||
return createElement('ide');
|
||||
return createElement('ide', {
|
||||
props: {
|
||||
emptyStateSvgPath: el.dataset.emptyStateSvgPath,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -50,6 +29,3 @@ const ideElement = document.getElementById('ide');
|
|||
Vue.use(Translate);
|
||||
|
||||
initIde(ideElement);
|
||||
|
||||
const contextualSidebar = new ContextualSidebar();
|
||||
contextualSidebar.bindEvents();
|
||||
|
|
|
|||
|
|
@ -63,6 +63,10 @@ export const setPanelCollapsedStatus = ({ commit }, { side, collapsed }) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const setResizingStatus = ({ commit }, resizing) => {
|
||||
commit(types.SET_RESIZING_STATUS, resizing);
|
||||
};
|
||||
|
||||
export const checkCommitStatus = ({ state }) =>
|
||||
service
|
||||
.getBranchData(state.currentProjectId, state.currentBranchId)
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ export const getProjectData = (
|
|||
{ namespace, projectId, force = false } = {},
|
||||
) => new Promise((resolve, reject) => {
|
||||
if (!state.projects[`${namespace}/${projectId}`] || force) {
|
||||
commit(types.TOGGLE_LOADING, state);
|
||||
service.getProjectData(namespace, projectId)
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
commit(types.TOGGLE_LOADING, state);
|
||||
commit(types.SET_PROJECT, { projectPath: `${namespace}/${projectId}`, project: data });
|
||||
if (!state.currentProjectId) commit(types.SET_CURRENT_PROJECT, `${namespace}/${projectId}`);
|
||||
resolve(data);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ export const SET_ROOT = 'SET_ROOT';
|
|||
export const SET_LAST_COMMIT_DATA = 'SET_LAST_COMMIT_DATA';
|
||||
export const SET_LEFT_PANEL_COLLAPSED = 'SET_LEFT_PANEL_COLLAPSED';
|
||||
export const SET_RIGHT_PANEL_COLLAPSED = 'SET_RIGHT_PANEL_COLLAPSED';
|
||||
export const SET_RESIZING_STATUS = 'SET_RESIZING_STATUS';
|
||||
|
||||
// Project Mutation Types
|
||||
export const SET_PROJECT = 'SET_PROJECT';
|
||||
|
|
|
|||
|
|
@ -49,6 +49,11 @@ export default {
|
|||
rightPanelCollapsed: collapsed,
|
||||
});
|
||||
},
|
||||
[types.SET_RESIZING_STATUS](state, resizing) {
|
||||
Object.assign(state, {
|
||||
panelResizing: resizing,
|
||||
});
|
||||
},
|
||||
[types.SET_LAST_COMMIT_DATA](state, { entry, lastCommit }) {
|
||||
Object.assign(entry.lastCommit, {
|
||||
id: lastCommit.commit.id,
|
||||
|
|
|
|||
|
|
@ -19,4 +19,5 @@ export default () => ({
|
|||
projects: {},
|
||||
leftPanelCollapsed: false,
|
||||
rightPanelCollapsed: true,
|
||||
panelResizing: false,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* eslint-disable no-new */
|
||||
/* global MilestoneSelect */
|
||||
|
||||
import MilestoneSelect from './milestone_select';
|
||||
import LabelsSelect from './labels_select';
|
||||
import IssuableContext from './issuable_context';
|
||||
import Sidebar from './right_sidebar';
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
/* eslint-disable no-new */
|
||||
import LabelsSelect from './labels_select';
|
||||
/* global MilestoneSelect */
|
||||
import subscriptionSelect from './subscription_select';
|
||||
import UsersSelect from './users_select';
|
||||
import issueStatusSelect from './issue_status_select';
|
||||
import MilestoneSelect from './milestone_select';
|
||||
|
||||
export default () => {
|
||||
new UsersSelect();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
/* eslint-disable class-methods-use-this, no-new */
|
||||
/* global MilestoneSelect */
|
||||
|
||||
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
|
||||
import './milestone_select';
|
||||
import MilestoneSelect from './milestone_select';
|
||||
import issueStatusSelect from './issue_status_select';
|
||||
import subscriptionSelect from './subscription_select';
|
||||
import LabelsSelect from './labels_select';
|
||||
|
|
|
|||
|
|
@ -172,8 +172,8 @@ export default {
|
|||
},
|
||||
|
||||
updateIssuable() {
|
||||
this.service.updateIssuable(this.store.formState)
|
||||
.then(res => res.json())
|
||||
return this.service.updateIssuable(this.store.formState)
|
||||
.then(res => res.data)
|
||||
.then(data => this.checkForSpam(data))
|
||||
.then((data) => {
|
||||
if (location.pathname !== data.web_url) {
|
||||
|
|
@ -182,7 +182,7 @@ export default {
|
|||
|
||||
return this.service.getData();
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
this.store.updateState(data);
|
||||
eventHub.$emit('close.form');
|
||||
|
|
@ -207,7 +207,7 @@ export default {
|
|||
|
||||
deleteIssuable() {
|
||||
this.service.deleteIssuable()
|
||||
.then(res => res.json())
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
// Stop the poll so we don't get 404's with the issuable not existing
|
||||
this.poll.stop();
|
||||
|
|
@ -225,7 +225,7 @@ export default {
|
|||
this.poll = new Poll({
|
||||
resource: this.service,
|
||||
method: 'getData',
|
||||
successCallback: res => res.json().then(data => this.store.updateState(data)),
|
||||
successCallback: res => this.store.updateState(res.data),
|
||||
errorCallback(err) {
|
||||
throw new Error(err);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,29 +1,20 @@
|
|||
import Vue from 'vue';
|
||||
import VueResource from 'vue-resource';
|
||||
|
||||
Vue.use(VueResource);
|
||||
import axios from '../../lib/utils/axios_utils';
|
||||
|
||||
export default class Service {
|
||||
constructor(endpoint) {
|
||||
this.endpoint = endpoint;
|
||||
|
||||
this.resource = Vue.resource(`${this.endpoint}.json`, {}, {
|
||||
realtimeChanges: {
|
||||
method: 'GET',
|
||||
url: `${this.endpoint}/realtime_changes`,
|
||||
},
|
||||
});
|
||||
this.endpoint = `${endpoint}.json`;
|
||||
this.realtimeEndpoint = `${endpoint}/realtime_changes`;
|
||||
}
|
||||
|
||||
getData() {
|
||||
return this.resource.realtimeChanges();
|
||||
return axios.get(this.realtimeEndpoint);
|
||||
}
|
||||
|
||||
deleteIssuable() {
|
||||
return this.resource.delete();
|
||||
return axios.delete(this.endpoint);
|
||||
}
|
||||
|
||||
updateIssuable(data) {
|
||||
return this.resource.update(data);
|
||||
return axios.put(this.endpoint, data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import _ from 'underscore';
|
||||
import { visitUrl } from './lib/utils/url_utility';
|
||||
import bp from './breakpoints';
|
||||
import { bytesToKiB } from './lib/utils/number_utils';
|
||||
import { numberToHumanSize } from './lib/utils/number_utils';
|
||||
import { setCiStatusFavicon } from './lib/utils/common_utils';
|
||||
import { timeFor } from './lib/utils/datetime_utility';
|
||||
|
||||
|
|
@ -96,14 +96,15 @@ export default class Job {
|
|||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
canScroll() {
|
||||
return this.$document.height() > this.$window.height();
|
||||
return $(document).height() > $(window).height();
|
||||
}
|
||||
|
||||
toggleScroll() {
|
||||
const currentPosition = this.$document.scrollTop();
|
||||
const scrollHeight = this.$document.height();
|
||||
const $document = $(document);
|
||||
const currentPosition = $document.scrollTop();
|
||||
const scrollHeight = $document.height();
|
||||
|
||||
const windowHeight = this.$window.height();
|
||||
const windowHeight = $(window).height();
|
||||
if (this.canScroll()) {
|
||||
if (currentPosition > 0 &&
|
||||
(scrollHeight - currentPosition !== windowHeight)) {
|
||||
|
|
@ -127,18 +128,22 @@ export default class Job {
|
|||
this.toggleDisableButton(this.$scrollBottomBtn, true);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
isScrolledToBottom() {
|
||||
const currentPosition = this.$document.scrollTop();
|
||||
const scrollHeight = this.$document.height();
|
||||
const $document = $(document);
|
||||
|
||||
const currentPosition = $document.scrollTop();
|
||||
const scrollHeight = $document.height();
|
||||
|
||||
const windowHeight = $(window).height();
|
||||
|
||||
const windowHeight = this.$window.height();
|
||||
return scrollHeight - currentPosition === windowHeight;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
scrollDown() {
|
||||
this.$document.scrollTop(this.$document.height());
|
||||
const $document = $(document);
|
||||
$document.scrollTop($document.height());
|
||||
}
|
||||
|
||||
scrollToBottom() {
|
||||
|
|
@ -148,7 +153,7 @@ export default class Job {
|
|||
}
|
||||
|
||||
scrollToTop() {
|
||||
this.$document.scrollTop(0);
|
||||
$(document).scrollTop(0);
|
||||
this.hasBeenScrolled = true;
|
||||
this.toggleScroll();
|
||||
}
|
||||
|
|
@ -193,7 +198,7 @@ export default class Job {
|
|||
// we need to show a message warning the user about that.
|
||||
if (this.logBytes < log.total) {
|
||||
// size is in bytes, we need to calculate KiB
|
||||
const size = bytesToKiB(this.logBytes);
|
||||
const size = numberToHumanSize(this.logBytes);
|
||||
$('.js-truncated-info-size').html(`${size}`);
|
||||
this.$truncatedInfo.removeClass('hidden');
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
shouldRenderContent() {
|
||||
return !this.isLoading && Object.keys(this.job).length;
|
||||
},
|
||||
jobStarted() {
|
||||
return this.job.started;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getActions() {
|
||||
|
|
@ -63,8 +66,9 @@
|
|||
:time="job.created_at"
|
||||
:user="job.user"
|
||||
:actions="actions"
|
||||
:hasSidebarButton="true"
|
||||
/>
|
||||
:has-sidebar-button="true"
|
||||
:should-render-triggered-label="jobStarted"
|
||||
/>
|
||||
<loading-icon
|
||||
v-if="isLoading"
|
||||
size="2"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import axios from 'axios';
|
|||
import csrf from './csrf';
|
||||
|
||||
axios.defaults.headers.common[csrf.headerKey] = csrf.token;
|
||||
// Used by Rails to check if it is a valid XHR request
|
||||
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
// Maintain a global counter for active requests
|
||||
// see: spec/support/wait_for_requests.rb
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ export const nodeMatchesSelector = (node, selector) => {
|
|||
export const normalizeHeaders = (headers) => {
|
||||
const upperCaseHeaders = {};
|
||||
|
||||
Object.keys(headers).forEach((e) => {
|
||||
Object.keys(headers || {}).forEach((e) => {
|
||||
upperCaseHeaders[e.toUpperCase()] = headers[e];
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -64,3 +64,12 @@ export const truncate = (string, maxLength) => `${string.substr(0, (maxLength -
|
|||
export function capitalizeFirstCharacter(text) {
|
||||
return `${text[0].toUpperCase()}${text.slice(1)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all html tags from a string with the given replacement.
|
||||
*
|
||||
* @param {String} string
|
||||
* @param {*} replace
|
||||
* @returns {String}
|
||||
*/
|
||||
export const stripeHtml = (string, replace = '') => string.replace(/<[^>]*>/g, replace);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export function getParameterValues(sParam) {
|
|||
// @param {String} url
|
||||
export function mergeUrlParams(params, url) {
|
||||
let newUrl = Object.keys(params).reduce((acc, paramName) => {
|
||||
const paramValue = params[paramName];
|
||||
const paramValue = encodeURIComponent(params[paramName]);
|
||||
const pattern = new RegExp(`\\b(${paramName}=).*?(&|$)`);
|
||||
|
||||
if (paramValue === null) {
|
||||
|
|
|
|||
|
|
@ -1,237 +1,228 @@
|
|||
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, one-var-declaration-per-line, no-unused-vars, object-shorthand, comma-dangle, no-else-return, no-self-compare, consistent-return, no-param-reassign, no-shadow */
|
||||
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, one-var-declaration-per-line, no-unused-vars, object-shorthand, comma-dangle, no-else-return, no-self-compare, consistent-return, no-param-reassign, no-shadow */
|
||||
/* global Issuable */
|
||||
/* global ListMilestone */
|
||||
import _ from 'underscore';
|
||||
import { timeFor } from './lib/utils/datetime_utility';
|
||||
|
||||
(function() {
|
||||
this.MilestoneSelect = (function() {
|
||||
function MilestoneSelect(currentProject, els, options = {}) {
|
||||
var _this, $els;
|
||||
if (currentProject != null) {
|
||||
_this = this;
|
||||
this.currentProject = typeof currentProject === 'string' ? JSON.parse(currentProject) : currentProject;
|
||||
}
|
||||
|
||||
$els = $(els);
|
||||
|
||||
if (!els) {
|
||||
$els = $('.js-milestone-select');
|
||||
}
|
||||
|
||||
$els.each(function(i, dropdown) {
|
||||
var $block, $dropdown, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, collapsedSidebarLabelTemplate, defaultLabel, defaultNo, issuableId, issueUpdateURL, milestoneLinkNoneTemplate, milestoneLinkTemplate, milestonesUrl, projectId, selectedMilestone, selectedMilestoneDefault, showAny, showNo, showUpcoming, showStarted, useId, showMenuAbove;
|
||||
$dropdown = $(dropdown);
|
||||
projectId = $dropdown.data('project-id');
|
||||
milestonesUrl = $dropdown.data('milestones');
|
||||
issueUpdateURL = $dropdown.data('issueUpdate');
|
||||
showNo = $dropdown.data('show-no');
|
||||
showAny = $dropdown.data('show-any');
|
||||
showMenuAbove = $dropdown.data('showMenuAbove');
|
||||
showUpcoming = $dropdown.data('show-upcoming');
|
||||
showStarted = $dropdown.data('show-started');
|
||||
useId = $dropdown.data('use-id');
|
||||
defaultLabel = $dropdown.data('default-label');
|
||||
defaultNo = $dropdown.data('default-no');
|
||||
issuableId = $dropdown.data('issuable-id');
|
||||
abilityName = $dropdown.data('ability-name');
|
||||
$selectbox = $dropdown.closest('.selectbox');
|
||||
$block = $selectbox.closest('.block');
|
||||
$sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon');
|
||||
$value = $block.find('.value');
|
||||
$loading = $block.find('.block-loading').fadeOut();
|
||||
selectedMilestoneDefault = (showAny ? '' : null);
|
||||
selectedMilestoneDefault = (showNo && defaultNo ? 'No Milestone' : selectedMilestoneDefault);
|
||||
selectedMilestone = $dropdown.data('selected') || selectedMilestoneDefault;
|
||||
if (issueUpdateURL) {
|
||||
milestoneLinkTemplate = _.template('<a href="/<%- full_path %>/milestones/<%- iid %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %></a>');
|
||||
milestoneLinkNoneTemplate = '<span class="no-value">None</span>';
|
||||
collapsedSidebarLabelTemplate = _.template('<span class="has-tooltip" data-container="body" title="<%- name %><br /><%- remaining %>" data-placement="left" data-html="true"> <%- title %> </span>');
|
||||
}
|
||||
return $dropdown.glDropdown({
|
||||
showMenuAbove: showMenuAbove,
|
||||
data: function(term, callback) {
|
||||
return $.ajax({
|
||||
url: milestonesUrl
|
||||
}).done(function(data) {
|
||||
var extraOptions = [];
|
||||
if (showAny) {
|
||||
extraOptions.push({
|
||||
id: 0,
|
||||
name: '',
|
||||
title: 'Any Milestone'
|
||||
});
|
||||
}
|
||||
if (showNo) {
|
||||
extraOptions.push({
|
||||
id: -1,
|
||||
name: 'No Milestone',
|
||||
title: 'No Milestone'
|
||||
});
|
||||
}
|
||||
if (showUpcoming) {
|
||||
extraOptions.push({
|
||||
id: -2,
|
||||
name: '#upcoming',
|
||||
title: 'Upcoming'
|
||||
});
|
||||
}
|
||||
if (showStarted) {
|
||||
extraOptions.push({
|
||||
id: -3,
|
||||
name: '#started',
|
||||
title: 'Started'
|
||||
});
|
||||
}
|
||||
if (extraOptions.length) {
|
||||
extraOptions.push('divider');
|
||||
}
|
||||
|
||||
callback(extraOptions.concat(data));
|
||||
if (showMenuAbove) {
|
||||
$dropdown.data('glDropdown').positionMenuAbove();
|
||||
}
|
||||
$(`[data-milestone-id="${selectedMilestone}"] > a`).addClass('is-active');
|
||||
});
|
||||
},
|
||||
renderRow: function(milestone) {
|
||||
return `
|
||||
<li data-milestone-id="${milestone.name}">
|
||||
<a href='#' class='dropdown-menu-milestone-link'>
|
||||
${_.escape(milestone.title)}
|
||||
</a>
|
||||
</li>
|
||||
`;
|
||||
},
|
||||
filterable: true,
|
||||
search: {
|
||||
fields: ['title']
|
||||
},
|
||||
selectable: true,
|
||||
toggleLabel: function(selected, el, e) {
|
||||
if (selected && 'id' in selected && $(el).hasClass('is-active')) {
|
||||
return selected.title;
|
||||
} else {
|
||||
return defaultLabel;
|
||||
}
|
||||
},
|
||||
defaultLabel: defaultLabel,
|
||||
fieldName: $dropdown.data('field-name'),
|
||||
text: function(milestone) {
|
||||
return _.escape(milestone.title);
|
||||
},
|
||||
id: function(milestone) {
|
||||
if (!useId && !$dropdown.is('.js-issuable-form-dropdown')) {
|
||||
return milestone.name;
|
||||
} else {
|
||||
return milestone.id;
|
||||
}
|
||||
},
|
||||
isSelected: function(milestone) {
|
||||
return milestone.name === selectedMilestone;
|
||||
},
|
||||
hidden: function() {
|
||||
$selectbox.hide();
|
||||
// display:block overrides the hide-collapse rule
|
||||
return $value.css('display', '');
|
||||
},
|
||||
opened: function(e) {
|
||||
const $el = $(e.currentTarget);
|
||||
if ($dropdown.hasClass('js-issue-board-sidebar') || options.handleClick) {
|
||||
selectedMilestone = $dropdown[0].dataset.selected || selectedMilestoneDefault;
|
||||
}
|
||||
$('a.is-active', $el).removeClass('is-active');
|
||||
$(`[data-milestone-id="${selectedMilestone}"] > a`, $el).addClass('is-active');
|
||||
},
|
||||
vue: $dropdown.hasClass('js-issue-board-sidebar'),
|
||||
clicked: function(clickEvent) {
|
||||
const { $el, e } = clickEvent;
|
||||
let selected = clickEvent.selectedObj;
|
||||
|
||||
var data, isIssueIndex, isMRIndex, isSelecting, page, boardsStore;
|
||||
if (!selected) return;
|
||||
|
||||
if (options.handleClick) {
|
||||
e.preventDefault();
|
||||
options.handleClick(selected);
|
||||
return;
|
||||
}
|
||||
|
||||
page = $('body').attr('data-page');
|
||||
isIssueIndex = page === 'projects:issues:index';
|
||||
isMRIndex = (page === page && page === 'projects:merge_requests:index');
|
||||
isSelecting = (selected.name !== selectedMilestone);
|
||||
selectedMilestone = isSelecting ? selected.name : selectedMilestoneDefault;
|
||||
if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if ($dropdown.closest('.add-issues-modal').length) {
|
||||
boardsStore = gl.issueBoards.ModalStore.store.filter;
|
||||
}
|
||||
|
||||
if (boardsStore) {
|
||||
boardsStore[$dropdown.data('field-name')] = selected.name;
|
||||
e.preventDefault();
|
||||
} else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
|
||||
return Issuable.filterResults($dropdown.closest('form'));
|
||||
} else if ($dropdown.hasClass('js-filter-submit')) {
|
||||
return $dropdown.closest('form').submit();
|
||||
} else if ($dropdown.hasClass('js-issue-board-sidebar')) {
|
||||
if (selected.id !== -1 && isSelecting) {
|
||||
gl.issueBoards.boardStoreIssueSet('milestone', new ListMilestone({
|
||||
id: selected.id,
|
||||
title: selected.name
|
||||
}));
|
||||
} else {
|
||||
gl.issueBoards.boardStoreIssueDelete('milestone');
|
||||
}
|
||||
|
||||
$dropdown.trigger('loading.gl.dropdown');
|
||||
$loading.removeClass('hidden').fadeIn();
|
||||
|
||||
gl.issueBoards.BoardsStore.detail.issue.update($dropdown.attr('data-issue-update'))
|
||||
.then(function () {
|
||||
$dropdown.trigger('loaded.gl.dropdown');
|
||||
$loading.fadeOut();
|
||||
})
|
||||
.catch(() => {
|
||||
$loading.fadeOut();
|
||||
});
|
||||
} else {
|
||||
selected = $selectbox.find('input[type="hidden"]').val();
|
||||
data = {};
|
||||
data[abilityName] = {};
|
||||
data[abilityName].milestone_id = selected != null ? selected : null;
|
||||
$loading.removeClass('hidden').fadeIn();
|
||||
$dropdown.trigger('loading.gl.dropdown');
|
||||
return $.ajax({
|
||||
type: 'PUT',
|
||||
url: issueUpdateURL,
|
||||
data: data
|
||||
}).done(function(data) {
|
||||
$dropdown.trigger('loaded.gl.dropdown');
|
||||
$loading.fadeOut();
|
||||
$selectbox.hide();
|
||||
$value.css('display', '');
|
||||
if (data.milestone != null) {
|
||||
data.milestone.full_path = _this.currentProject.full_path;
|
||||
data.milestone.remaining = timeFor(data.milestone.due_date);
|
||||
data.milestone.name = data.milestone.title;
|
||||
$value.html(milestoneLinkTemplate(data.milestone));
|
||||
return $sidebarCollapsedValue.find('span').html(collapsedSidebarLabelTemplate(data.milestone));
|
||||
} else {
|
||||
$value.html(milestoneLinkNoneTemplate);
|
||||
return $sidebarCollapsedValue.find('span').text('No');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
export default class MilestoneSelect {
|
||||
constructor(currentProject, els, options = {}) {
|
||||
if (currentProject !== null) {
|
||||
this.currentProject = typeof currentProject === 'string' ? JSON.parse(currentProject) : currentProject;
|
||||
}
|
||||
|
||||
return MilestoneSelect;
|
||||
})();
|
||||
}).call(window);
|
||||
this.init(els, options);
|
||||
}
|
||||
|
||||
init(els, options) {
|
||||
let $els = $(els);
|
||||
|
||||
if (!els) {
|
||||
$els = $('.js-milestone-select');
|
||||
}
|
||||
|
||||
$els.each((i, dropdown) => {
|
||||
let collapsedSidebarLabelTemplate, milestoneLinkNoneTemplate, milestoneLinkTemplate, selectedMilestone, selectedMilestoneDefault;
|
||||
const $dropdown = $(dropdown);
|
||||
const projectId = $dropdown.data('project-id');
|
||||
const milestonesUrl = $dropdown.data('milestones');
|
||||
const issueUpdateURL = $dropdown.data('issueUpdate');
|
||||
const showNo = $dropdown.data('show-no');
|
||||
const showAny = $dropdown.data('show-any');
|
||||
const showMenuAbove = $dropdown.data('showMenuAbove');
|
||||
const showUpcoming = $dropdown.data('show-upcoming');
|
||||
const showStarted = $dropdown.data('show-started');
|
||||
const useId = $dropdown.data('use-id');
|
||||
const defaultLabel = $dropdown.data('default-label');
|
||||
const defaultNo = $dropdown.data('default-no');
|
||||
const issuableId = $dropdown.data('issuable-id');
|
||||
const abilityName = $dropdown.data('ability-name');
|
||||
const $selectBox = $dropdown.closest('.selectbox');
|
||||
const $block = $selectBox.closest('.block');
|
||||
const $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon');
|
||||
const $value = $block.find('.value');
|
||||
const $loading = $block.find('.block-loading').fadeOut();
|
||||
selectedMilestoneDefault = (showAny ? '' : null);
|
||||
selectedMilestoneDefault = (showNo && defaultNo ? 'No Milestone' : selectedMilestoneDefault);
|
||||
selectedMilestone = $dropdown.data('selected') || selectedMilestoneDefault;
|
||||
|
||||
if (issueUpdateURL) {
|
||||
milestoneLinkTemplate = _.template('<a href="/<%- full_path %>/milestones/<%- iid %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %></a>');
|
||||
milestoneLinkNoneTemplate = '<span class="no-value">None</span>';
|
||||
collapsedSidebarLabelTemplate = _.template('<span class="has-tooltip" data-container="body" title="<%- name %><br /><%- remaining %>" data-placement="left" data-html="true"> <%- title %> </span>');
|
||||
}
|
||||
return $dropdown.glDropdown({
|
||||
showMenuAbove: showMenuAbove,
|
||||
data: (term, callback) => $.ajax({
|
||||
url: milestonesUrl
|
||||
}).done((data) => {
|
||||
const extraOptions = [];
|
||||
if (showAny) {
|
||||
extraOptions.push({
|
||||
id: 0,
|
||||
name: '',
|
||||
title: 'Any Milestone'
|
||||
});
|
||||
}
|
||||
if (showNo) {
|
||||
extraOptions.push({
|
||||
id: -1,
|
||||
name: 'No Milestone',
|
||||
title: 'No Milestone'
|
||||
});
|
||||
}
|
||||
if (showUpcoming) {
|
||||
extraOptions.push({
|
||||
id: -2,
|
||||
name: '#upcoming',
|
||||
title: 'Upcoming'
|
||||
});
|
||||
}
|
||||
if (showStarted) {
|
||||
extraOptions.push({
|
||||
id: -3,
|
||||
name: '#started',
|
||||
title: 'Started'
|
||||
});
|
||||
}
|
||||
if (extraOptions.length) {
|
||||
extraOptions.push('divider');
|
||||
}
|
||||
|
||||
callback(extraOptions.concat(data));
|
||||
if (showMenuAbove) {
|
||||
$dropdown.data('glDropdown').positionMenuAbove();
|
||||
}
|
||||
$(`[data-milestone-id="${selectedMilestone}"] > a`).addClass('is-active');
|
||||
}),
|
||||
renderRow: milestone => `
|
||||
<li data-milestone-id="${milestone.name}">
|
||||
<a href='#' class='dropdown-menu-milestone-link'>
|
||||
${_.escape(milestone.title)}
|
||||
</a>
|
||||
</li>
|
||||
`,
|
||||
filterable: true,
|
||||
search: {
|
||||
fields: ['title']
|
||||
},
|
||||
selectable: true,
|
||||
toggleLabel: (selected, el, e) => {
|
||||
if (selected && 'id' in selected && $(el).hasClass('is-active')) {
|
||||
return selected.title;
|
||||
} else {
|
||||
return defaultLabel;
|
||||
}
|
||||
},
|
||||
defaultLabel: defaultLabel,
|
||||
fieldName: $dropdown.data('field-name'),
|
||||
text: milestone => _.escape(milestone.title),
|
||||
id: (milestone) => {
|
||||
if (!useId && !$dropdown.is('.js-issuable-form-dropdown')) {
|
||||
return milestone.name;
|
||||
} else {
|
||||
return milestone.id;
|
||||
}
|
||||
},
|
||||
isSelected: milestone => milestone.name === selectedMilestone,
|
||||
hidden: () => {
|
||||
$selectBox.hide();
|
||||
// display:block overrides the hide-collapse rule
|
||||
return $value.css('display', '');
|
||||
},
|
||||
opened: (e) => {
|
||||
const $el = $(e.currentTarget);
|
||||
if ($dropdown.hasClass('js-issue-board-sidebar') || options.handleClick) {
|
||||
selectedMilestone = $dropdown[0].dataset.selected || selectedMilestoneDefault;
|
||||
}
|
||||
$('a.is-active', $el).removeClass('is-active');
|
||||
$(`[data-milestone-id="${selectedMilestone}"] > a`, $el).addClass('is-active');
|
||||
},
|
||||
vue: $dropdown.hasClass('js-issue-board-sidebar'),
|
||||
clicked: (clickEvent) => {
|
||||
const { $el, e } = clickEvent;
|
||||
let selected = clickEvent.selectedObj;
|
||||
|
||||
let data, boardsStore;
|
||||
if (!selected) return;
|
||||
|
||||
if (options.handleClick) {
|
||||
e.preventDefault();
|
||||
options.handleClick(selected);
|
||||
return;
|
||||
}
|
||||
|
||||
const page = $('body').attr('data-page');
|
||||
const isIssueIndex = page === 'projects:issues:index';
|
||||
const isMRIndex = (page === page && page === 'projects:merge_requests:index');
|
||||
const isSelecting = (selected.name !== selectedMilestone);
|
||||
selectedMilestone = isSelecting ? selected.name : selectedMilestoneDefault;
|
||||
if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if ($dropdown.closest('.add-issues-modal').length) {
|
||||
boardsStore = gl.issueBoards.ModalStore.store.filter;
|
||||
}
|
||||
|
||||
if (boardsStore) {
|
||||
boardsStore[$dropdown.data('field-name')] = selected.name;
|
||||
e.preventDefault();
|
||||
} else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
|
||||
return Issuable.filterResults($dropdown.closest('form'));
|
||||
} else if ($dropdown.hasClass('js-filter-submit')) {
|
||||
return $dropdown.closest('form').submit();
|
||||
} else if ($dropdown.hasClass('js-issue-board-sidebar')) {
|
||||
if (selected.id !== -1 && isSelecting) {
|
||||
gl.issueBoards.boardStoreIssueSet('milestone', new ListMilestone({
|
||||
id: selected.id,
|
||||
title: selected.name
|
||||
}));
|
||||
} else {
|
||||
gl.issueBoards.boardStoreIssueDelete('milestone');
|
||||
}
|
||||
|
||||
$dropdown.trigger('loading.gl.dropdown');
|
||||
$loading.removeClass('hidden').fadeIn();
|
||||
|
||||
gl.issueBoards.BoardsStore.detail.issue.update($dropdown.attr('data-issue-update'))
|
||||
.then(() => {
|
||||
$dropdown.trigger('loaded.gl.dropdown');
|
||||
$loading.fadeOut();
|
||||
})
|
||||
.catch(() => {
|
||||
$loading.fadeOut();
|
||||
});
|
||||
} else {
|
||||
selected = $selectBox.find('input[type="hidden"]').val();
|
||||
data = {};
|
||||
data[abilityName] = {};
|
||||
data[abilityName].milestone_id = selected != null ? selected : null;
|
||||
$loading.removeClass('hidden').fadeIn();
|
||||
$dropdown.trigger('loading.gl.dropdown');
|
||||
return $.ajax({
|
||||
type: 'PUT',
|
||||
url: issueUpdateURL,
|
||||
data: data
|
||||
}).done((data) => {
|
||||
$dropdown.trigger('loaded.gl.dropdown');
|
||||
$loading.fadeOut();
|
||||
$selectBox.hide();
|
||||
$value.css('display', '');
|
||||
if (data.milestone != null) {
|
||||
data.milestone.full_path = this.currentProject.full_path;
|
||||
data.milestone.remaining = timeFor(data.milestone.due_date);
|
||||
data.milestone.name = data.milestone.title;
|
||||
$value.html(milestoneLinkTemplate(data.milestone));
|
||||
return $sidebarCollapsedValue.find('span').html(collapsedSidebarLabelTemplate(data.milestone));
|
||||
} else {
|
||||
$value.html(milestoneLinkNoneTemplate);
|
||||
return $sidebarCollapsedValue.find('span').text('No');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@
|
|||
currentFlagPosition: 0,
|
||||
showFlag: false,
|
||||
showFlagContent: false,
|
||||
showDeployInfo: true,
|
||||
timeSeries: [],
|
||||
realPixelRatio: 1,
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -87,10 +87,7 @@
|
|||
},
|
||||
|
||||
innerViewBox() {
|
||||
if ((this.baseGraphWidth - 150) > 0) {
|
||||
return `0 0 ${this.baseGraphWidth - 150} ${this.baseGraphHeight}`;
|
||||
}
|
||||
return '0 0 0 0';
|
||||
return `0 0 ${this.baseGraphWidth - 150} ${this.baseGraphHeight}`;
|
||||
},
|
||||
|
||||
axisTransform() {
|
||||
|
|
@ -102,6 +99,10 @@
|
|||
paddingBottom: `${(Math.ceil(this.baseGraphHeight * 100) / this.baseGraphWidth) || 0}%`,
|
||||
};
|
||||
},
|
||||
|
||||
deploymentFlagData() {
|
||||
return this.reducedDeploymentData.find(deployment => deployment.showDeploymentFlag);
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
@ -122,6 +123,10 @@
|
|||
this.graphHeight = this.graphHeight - this.margin.top - this.margin.bottom;
|
||||
this.baseGraphHeight = this.graphHeight;
|
||||
this.baseGraphWidth = this.graphWidth;
|
||||
|
||||
// pixel offsets inside the svg and outside are not 1:1
|
||||
this.realPixelRatio = (this.$refs.baseSvg.clientWidth / this.baseGraphWidth);
|
||||
|
||||
this.renderAxesPaths();
|
||||
this.formatDeployments();
|
||||
},
|
||||
|
|
@ -261,6 +266,11 @@
|
|||
:line-color="path.lineColor"
|
||||
:area-color="path.areaColor"
|
||||
/>
|
||||
<graph-deployment
|
||||
:deployment-data="reducedDeploymentData"
|
||||
:graph-height="graphHeight"
|
||||
:graph-height-offset="graphHeightOffset"
|
||||
/>
|
||||
<rect
|
||||
class="prometheus-graph-overlay"
|
||||
:width="(graphWidth - 70)"
|
||||
|
|
@ -269,24 +279,21 @@
|
|||
ref="graphOverlay"
|
||||
@mousemove="handleMouseOverGraph($event)">
|
||||
</rect>
|
||||
<graph-deployment
|
||||
:show-deploy-info="showDeployInfo"
|
||||
:deployment-data="reducedDeploymentData"
|
||||
:graph-width="graphWidth"
|
||||
:graph-height="graphHeight"
|
||||
:graph-height-offset="graphHeightOffset"
|
||||
/>
|
||||
<graph-flag
|
||||
v-if="showFlag"
|
||||
:current-x-coordinate="currentXCoordinate"
|
||||
:current-data="currentData"
|
||||
:current-flag-position="currentFlagPosition"
|
||||
:graph-height="graphHeight"
|
||||
:graph-height-offset="graphHeightOffset"
|
||||
:show-flag-content="showFlagContent"
|
||||
/>
|
||||
</svg>
|
||||
</svg>
|
||||
<graph-flag
|
||||
:real-pixel-ratio="realPixelRatio"
|
||||
:current-x-coordinate="currentXCoordinate"
|
||||
:current-data="currentData"
|
||||
:graph-height="graphHeight"
|
||||
:graph-height-offset="graphHeightOffset"
|
||||
:show-flag-content="showFlagContent"
|
||||
:time-series="timeSeries"
|
||||
:unit-of-display="unitOfDisplay"
|
||||
:current-data-index="currentDataIndex"
|
||||
:legend-title="legendTitle"
|
||||
:deployment-flag-data="deploymentFlagData"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
<script>
|
||||
import { dateFormatWithName, timeFormat } from '../../utils/date_time_formatters';
|
||||
import Icon from '../../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
showDeployInfo: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
deploymentData: {
|
||||
type: Array,
|
||||
required: true,
|
||||
|
|
@ -20,14 +13,6 @@
|
|||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
graphWidth: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
Icon,
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
@ -37,52 +22,17 @@
|
|||
},
|
||||
|
||||
methods: {
|
||||
refText(d) {
|
||||
return d.tag ? d.ref : d.sha.slice(0, 8);
|
||||
},
|
||||
|
||||
formatTime(deploymentTime) {
|
||||
return timeFormat(deploymentTime);
|
||||
},
|
||||
|
||||
formatDate(deploymentTime) {
|
||||
return dateFormatWithName(deploymentTime);
|
||||
},
|
||||
|
||||
nameDeploymentClass(deployment) {
|
||||
return `deploy-info-${deployment.id}`;
|
||||
},
|
||||
|
||||
transformDeploymentGroup(deployment) {
|
||||
return `translate(${Math.floor(deployment.xPos) + 1}, 20)`;
|
||||
},
|
||||
|
||||
positionFlag(deployment) {
|
||||
let xPosition = 3;
|
||||
if (deployment.xPos > (this.graphWidth - 225)) {
|
||||
xPosition = -142;
|
||||
}
|
||||
return xPosition;
|
||||
},
|
||||
|
||||
svgContainerHeight(tag) {
|
||||
let svgHeight = 80;
|
||||
if (!tag) {
|
||||
svgHeight -= 20;
|
||||
}
|
||||
return svgHeight;
|
||||
return `translate(${Math.floor(deployment.xPos) - 5}, 20)`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<g
|
||||
class="deploy-info"
|
||||
v-if="showDeployInfo">
|
||||
<g class="deploy-info">
|
||||
<g
|
||||
v-for="(deployment, index) in deploymentData"
|
||||
:key="index"
|
||||
:class="nameDeploymentClass(deployment)"
|
||||
:transform="transformDeploymentGroup(deployment)">
|
||||
<rect
|
||||
x="0"
|
||||
|
|
@ -99,81 +49,6 @@
|
|||
:y2="calculatedHeight"
|
||||
stroke="#000">
|
||||
</line>
|
||||
<svg
|
||||
v-if="deployment.showDeploymentFlag"
|
||||
class="js-deploy-info-box"
|
||||
:x="positionFlag(deployment)"
|
||||
y="0"
|
||||
width="134"
|
||||
:height="svgContainerHeight(deployment.tag)">
|
||||
<rect
|
||||
class="rect-text-metric deploy-info-rect rect-metric"
|
||||
x="1"
|
||||
y="1"
|
||||
rx="2"
|
||||
width="132"
|
||||
:height="svgContainerHeight(deployment.tag) - 2">
|
||||
</rect>
|
||||
<text
|
||||
class="deploy-info-text text-metric-bold"
|
||||
transform="translate(5, 2)">
|
||||
Deployed
|
||||
</text>
|
||||
<!--The date info-->
|
||||
<g transform="translate(5, 20)">
|
||||
<text class="deploy-info-text">
|
||||
{{formatDate(deployment.time)}}
|
||||
</text>
|
||||
<text
|
||||
class="deploy-info-text text-metric-bold"
|
||||
x="62">
|
||||
{{formatTime(deployment.time)}}
|
||||
</text>
|
||||
</g>
|
||||
<line
|
||||
class="divider-line"
|
||||
x1="0"
|
||||
y1="38"
|
||||
x2="132"
|
||||
:y2="38"
|
||||
stroke="#000">
|
||||
</line>
|
||||
<!--Commit information-->
|
||||
<g transform="translate(5, 40)">
|
||||
<icon
|
||||
name="commit"
|
||||
:width="12"
|
||||
:height="12"
|
||||
:y="3">
|
||||
</icon>
|
||||
<a :xlink:href="deployment.commitUrl">
|
||||
<text
|
||||
class="deploy-info-text deploy-info-text-link"
|
||||
transform="translate(20, 2)">
|
||||
{{refText(deployment)}}
|
||||
</text>
|
||||
</a>
|
||||
</g>
|
||||
<!--Tag information-->
|
||||
<g
|
||||
transform="translate(5, 55)"
|
||||
v-if="deployment.tag">
|
||||
<icon
|
||||
name="label"
|
||||
:width="12"
|
||||
:height="12"
|
||||
:y="5">
|
||||
</icon>
|
||||
<a :xlink:href="deployment.tagUrl">
|
||||
<text
|
||||
class="deploy-info-text deploy-info-text-link"
|
||||
transform="translate(20, 2)"
|
||||
y="2">
|
||||
{{deployment.tag}}
|
||||
</text>
|
||||
</a>
|
||||
</g>
|
||||
</svg>
|
||||
</g>
|
||||
<svg
|
||||
height="0"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<script>
|
||||
import { dateFormat, timeFormat } from '../../utils/date_time_formatters';
|
||||
import { formatRelevantDigits } from '../../../lib/utils/number_utils';
|
||||
import Icon from '../../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
|
@ -7,14 +9,15 @@
|
|||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
currentFlagPosition: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
currentData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
deploymentFlagData: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
graphHeight: {
|
||||
type: Number,
|
||||
required: true,
|
||||
|
|
@ -23,71 +26,173 @@
|
|||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
realPixelRatio: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
showFlagContent: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
timeSeries: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
unitOfDisplay: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
currentDataIndex: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
legendTitle: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
circleColorRgb: '#8fbce8',
|
||||
};
|
||||
components: {
|
||||
Icon,
|
||||
},
|
||||
|
||||
computed: {
|
||||
formatTime() {
|
||||
return timeFormat(this.currentData.time);
|
||||
return this.deploymentFlagData ?
|
||||
timeFormat(this.deploymentFlagData.time) :
|
||||
timeFormat(this.currentData.time);
|
||||
},
|
||||
|
||||
formatDate() {
|
||||
return dateFormat(this.currentData.time);
|
||||
return this.deploymentFlagData ?
|
||||
dateFormat(this.deploymentFlagData.time) :
|
||||
dateFormat(this.currentData.time);
|
||||
},
|
||||
|
||||
calculatedHeight() {
|
||||
return this.graphHeight - this.graphHeightOffset;
|
||||
cursorStyle() {
|
||||
const xCoordinate = this.deploymentFlagData ?
|
||||
this.deploymentFlagData.xPos :
|
||||
this.currentXCoordinate;
|
||||
|
||||
const offsetTop = 20 * this.realPixelRatio;
|
||||
const offsetLeft = (70 + xCoordinate) * this.realPixelRatio;
|
||||
const height = (this.graphHeight - this.graphHeightOffset) * this.realPixelRatio;
|
||||
|
||||
return {
|
||||
top: `${offsetTop}px`,
|
||||
left: `${offsetLeft}px`,
|
||||
height: `${height}px`,
|
||||
};
|
||||
},
|
||||
|
||||
flagOrientation() {
|
||||
if (this.currentXCoordinate * this.realPixelRatio > 120) {
|
||||
return 'left';
|
||||
}
|
||||
return 'right';
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
seriesMetricValue(series) {
|
||||
const index = this.deploymentFlagData ?
|
||||
this.deploymentFlagData.seriesIndex :
|
||||
this.currentDataIndex;
|
||||
const value = series.values[index] &&
|
||||
series.values[index].value;
|
||||
if (isNaN(value)) {
|
||||
return '-';
|
||||
}
|
||||
return `${formatRelevantDigits(value)}${this.unitOfDisplay}`;
|
||||
},
|
||||
|
||||
seriesMetricLabel(index, series) {
|
||||
if (this.timeSeries.length < 2) {
|
||||
return this.legendTitle;
|
||||
}
|
||||
if (series.metricTag) {
|
||||
return series.metricTag;
|
||||
}
|
||||
return `series ${index + 1}`;
|
||||
},
|
||||
|
||||
strokeDashArray(type) {
|
||||
if (type === 'dashed') return '6, 3';
|
||||
if (type === 'dotted') return '3, 3';
|
||||
return null;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<g class="mouse-over-flag">
|
||||
<line
|
||||
class="selected-metric-line"
|
||||
:x1="currentXCoordinate"
|
||||
:y1="0"
|
||||
:x2="currentXCoordinate"
|
||||
:y2="calculatedHeight"
|
||||
transform="translate(-5, 20)">
|
||||
</line>
|
||||
<svg
|
||||
<div
|
||||
class="prometheus-graph-cursor"
|
||||
:style="cursorStyle"
|
||||
>
|
||||
<div
|
||||
v-if="showFlagContent"
|
||||
class="rect-text-metric"
|
||||
:x="currentFlagPosition"
|
||||
y="0">
|
||||
<rect
|
||||
class="rect-metric"
|
||||
x="4"
|
||||
y="1"
|
||||
rx="2"
|
||||
width="90"
|
||||
height="40"
|
||||
transform="translate(-3, 20)">
|
||||
</rect>
|
||||
<text
|
||||
class="text-metric text-metric-bold"
|
||||
x="16"
|
||||
y="35"
|
||||
transform="translate(-5, 20)">
|
||||
{{formatTime}}
|
||||
</text>
|
||||
<text
|
||||
class="text-metric"
|
||||
x="16"
|
||||
y="15"
|
||||
transform="translate(-5, 20)">
|
||||
{{formatDate}}
|
||||
</text>
|
||||
</svg>
|
||||
</g>
|
||||
class="prometheus-graph-flag popover"
|
||||
:class="flagOrientation"
|
||||
>
|
||||
<div class="arrow"></div>
|
||||
<div class="popover-title">
|
||||
<h5 v-if="this.deploymentFlagData">
|
||||
Deployed
|
||||
</h5>
|
||||
{{formatDate}} at
|
||||
<strong>{{formatTime}}</strong>
|
||||
</div>
|
||||
<div
|
||||
v-if="this.deploymentFlagData"
|
||||
class="popover-content deploy-meta-content"
|
||||
>
|
||||
<div>
|
||||
<icon
|
||||
name="commit"
|
||||
:size="12">
|
||||
</icon>
|
||||
<a :href="deploymentFlagData.commitUrl">
|
||||
{{deploymentFlagData.sha.slice(0, 8)}}
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
v-if="deploymentFlagData.tag">
|
||||
<icon
|
||||
name="label"
|
||||
:size="12">
|
||||
</icon>
|
||||
<a :href="deploymentFlagData.tagUrl">
|
||||
{{deploymentFlagData.ref}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="popover-content">
|
||||
<table>
|
||||
<tr
|
||||
v-for="(series, index) in timeSeries"
|
||||
:key="index"
|
||||
>
|
||||
<td>
|
||||
<svg width="15" height="6">
|
||||
<line
|
||||
:stroke="series.lineColor"
|
||||
:stroke-dasharray="strokeDashArray(series.lineStyle)"
|
||||
stroke-width="4"
|
||||
x1="0"
|
||||
x2="15"
|
||||
y1="2"
|
||||
y2="2">
|
||||
</line>
|
||||
</svg>
|
||||
</td>
|
||||
<td>{{seriesMetricLabel(index, series)}}</td>
|
||||
<td>
|
||||
<strong>{{seriesMetricValue(series)}}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -29,15 +29,18 @@ const mixins = {
|
|||
time.setSeconds(this.timeSeries[0].values[0].time.getSeconds());
|
||||
|
||||
if (xPos >= 0) {
|
||||
const seriesIndex = bisectDate(this.timeSeries[0].values, time, 1);
|
||||
|
||||
deploymentDataArray.push({
|
||||
id: deployment.id,
|
||||
time,
|
||||
sha: deployment.sha,
|
||||
commitUrl: `${this.projectPath}/commit/${deployment.sha}`,
|
||||
tag: deployment.tag,
|
||||
tagUrl: `${this.tagsPath}/${deployment.tag}`,
|
||||
tagUrl: deployment.tag ? `${this.tagsPath}/${deployment.ref.name}` : null,
|
||||
ref: deployment.ref.name,
|
||||
xPos,
|
||||
seriesIndex,
|
||||
showDeploymentFlag: false,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,20 @@
|
|||
import { timeFormat as time } from 'd3-time-format';
|
||||
import { timeSecond, timeMinute, timeHour, timeDay, timeMonth, timeYear } from 'd3-time';
|
||||
import { timeSecond, timeMinute, timeHour, timeDay, timeWeek, timeMonth, timeYear } from 'd3-time';
|
||||
import { bisector } from 'd3-array';
|
||||
|
||||
const d3 = { time, bisector, timeSecond, timeMinute, timeHour, timeDay, timeMonth, timeYear };
|
||||
const d3 = {
|
||||
time,
|
||||
bisector,
|
||||
timeSecond,
|
||||
timeMinute,
|
||||
timeHour,
|
||||
timeDay,
|
||||
timeWeek,
|
||||
timeMonth,
|
||||
timeYear,
|
||||
};
|
||||
|
||||
export const dateFormat = d3.time('%b %-d, %Y');
|
||||
export const dateFormat = d3.time('%a, %b %-d');
|
||||
export const timeFormat = d3.time('%-I:%M%p');
|
||||
export const dateFormatWithName = d3.time('%a, %b %-d');
|
||||
export const bisectDate = d3.bisector(d => d.time).left;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
import Todos from './todos';
|
||||
|
||||
export default () => new Todos();
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/* eslint-disable class-methods-use-this, no-unneeded-ternary, quote-props */
|
||||
import { visitUrl } from './lib/utils/url_utility';
|
||||
import UsersSelect from './users_select';
|
||||
import { isMetaClick } from './lib/utils/common_utils';
|
||||
import { visitUrl } from '~/lib/utils/url_utility';
|
||||
import UsersSelect from '~/users_select';
|
||||
import { isMetaClick } from '~/lib/utils/common_utils';
|
||||
|
||||
export default class Todos {
|
||||
constructor() {
|
||||
|
|
@ -17,6 +17,11 @@ export default {
|
|||
required: true,
|
||||
},
|
||||
|
||||
resetCachePath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
ciLintPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
|
@ -45,6 +50,14 @@ export default {
|
|||
Get started with Pipelines
|
||||
</a>
|
||||
|
||||
<a
|
||||
data-method="post"
|
||||
rel="nofollow"
|
||||
:href="resetCachePath"
|
||||
class="btn btn-default">
|
||||
Clear runner caches
|
||||
</a>
|
||||
|
||||
<a
|
||||
:href="ciLintPath"
|
||||
class="btn btn-default">
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
canCreatePipeline: pipelinesData.canCreatePipeline,
|
||||
hasCi: pipelinesData.hasCi,
|
||||
ciLintPath: pipelinesData.ciLintPath,
|
||||
resetCachePath: pipelinesData.resetCachePath,
|
||||
state: this.store.state,
|
||||
scope: getParameterByName('scope') || 'all',
|
||||
page: getParameterByName('page') || '1',
|
||||
|
|
@ -220,6 +221,7 @@
|
|||
:new-pipeline-path="newPipelinePath"
|
||||
:has-ci-enabled="hasCiEnabled"
|
||||
:help-page-path="helpPagePath"
|
||||
:resetCachePath="resetCachePath"
|
||||
:ci-lint-path="ciLintPath"
|
||||
:can-create-pipeline="canCreatePipelineParsed "
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import tooltip from '../../vue_shared/directives/tooltip';
|
||||
import icon from '../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
|
@ -11,6 +12,9 @@
|
|||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
components: {
|
||||
icon,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
|
|
@ -24,10 +28,9 @@
|
|||
data-placement="top"
|
||||
data-toggle="dropdown"
|
||||
aria-label="Artifacts">
|
||||
<i
|
||||
class="fa fa-download"
|
||||
aria-hidden="true">
|
||||
</i>
|
||||
<icon
|
||||
name="download">
|
||||
</icon>
|
||||
<i
|
||||
class="fa fa-caret-down"
|
||||
aria-hidden="true">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import modal from '../../../vue_shared/components/modal.vue';
|
||||
import { __, s__, sprintf } from '../../../locale';
|
||||
import csrf from '../../../lib/utils/csrf';
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import { __, s__, sprintf } from '~/locale';
|
||||
import csrf from '~/lib/utils/csrf';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
|
@ -22,7 +22,6 @@
|
|||
return {
|
||||
enteredPassword: '',
|
||||
enteredUsername: '',
|
||||
isOpen: false,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
|
|
@ -69,78 +68,58 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
|
|||
|
||||
return this.enteredUsername === this.username;
|
||||
},
|
||||
onSubmit(status) {
|
||||
if (status) {
|
||||
if (!this.canSubmit()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$refs.form.submit();
|
||||
}
|
||||
|
||||
this.toggleOpen(false);
|
||||
},
|
||||
toggleOpen(isOpen) {
|
||||
this.isOpen = isOpen;
|
||||
onSubmit() {
|
||||
this.$refs.form.submit();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<modal
|
||||
v-if="isOpen"
|
||||
:title="s__('Profiles|Delete your account?')"
|
||||
:text="text"
|
||||
:kind="`danger ${!canSubmit() && 'disabled'}`"
|
||||
:primary-button-label="s__('Profiles|Delete account')"
|
||||
@toggle="toggleOpen"
|
||||
@submit="onSubmit">
|
||||
<modal
|
||||
id="delete-account-modal"
|
||||
:title="s__('Profiles|Delete your account?')"
|
||||
:text="text"
|
||||
kind="danger"
|
||||
:primary-button-label="s__('Profiles|Delete account')"
|
||||
@submit="onSubmit"
|
||||
:submit-disabled="!canSubmit()">
|
||||
|
||||
<template slot="body" slot-scope="props">
|
||||
<p v-html="props.text"></p>
|
||||
<template slot="body" slot-scope="props">
|
||||
<p v-html="props.text"></p>
|
||||
|
||||
<form
|
||||
ref="form"
|
||||
:action="actionUrl"
|
||||
method="post">
|
||||
<form
|
||||
ref="form"
|
||||
:action="actionUrl"
|
||||
method="post">
|
||||
|
||||
<input
|
||||
type="hidden"
|
||||
name="_method"
|
||||
value="delete" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="authenticity_token"
|
||||
:value="csrfToken" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="_method"
|
||||
value="delete" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="authenticity_token"
|
||||
:value="csrfToken" />
|
||||
|
||||
<p id="input-label" v-html="inputLabel"></p>
|
||||
<p id="input-label" v-html="inputLabel"></p>
|
||||
|
||||
<input
|
||||
v-if="confirmWithPassword"
|
||||
name="password"
|
||||
class="form-control"
|
||||
type="password"
|
||||
v-model="enteredPassword"
|
||||
aria-labelledby="input-label" />
|
||||
<input
|
||||
v-else
|
||||
name="username"
|
||||
class="form-control"
|
||||
type="text"
|
||||
v-model="enteredUsername"
|
||||
aria-labelledby="input-label" />
|
||||
</form>
|
||||
</template>
|
||||
<input
|
||||
v-if="confirmWithPassword"
|
||||
name="password"
|
||||
class="form-control"
|
||||
type="password"
|
||||
v-model="enteredPassword"
|
||||
aria-labelledby="input-label" />
|
||||
<input
|
||||
v-else
|
||||
name="username"
|
||||
class="form-control"
|
||||
type="text"
|
||||
v-model="enteredUsername"
|
||||
aria-labelledby="input-label" />
|
||||
</form>
|
||||
</template>
|
||||
|
||||
</modal>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-danger"
|
||||
@click="toggleOpen(true)">
|
||||
{{ s__('Profiles|Delete account') }}
|
||||
</button>
|
||||
</div>
|
||||
</modal>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
import Translate from '~/vue_shared/translate';
|
||||
|
||||
import deleteAccountModal from './components/delete_account_modal.vue';
|
||||
|
||||
Vue.use(Translate);
|
||||
|
||||
const deleteAccountButton = document.getElementById('delete-account-button');
|
||||
const deleteAccountModalEl = document.getElementById('delete-account-modal');
|
||||
// eslint-disable-next-line no-new
|
||||
new Vue({
|
||||
|
|
@ -9,6 +14,9 @@ new Vue({
|
|||
components: {
|
||||
deleteAccountModal,
|
||||
},
|
||||
mounted() {
|
||||
deleteAccountButton.classList.remove('disabled');
|
||||
},
|
||||
render(createElement) {
|
||||
return createElement('delete-account-modal', {
|
||||
props: {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/* eslint-disable comma-dangle, no-unused-vars, class-methods-use-this, quotes, consistent-return, func-names, prefer-arrow-callback, space-before-function-paren, max-len */
|
||||
import Cookies from 'js-cookie';
|
||||
import Flash from '../flash';
|
||||
import { getPagePath } from '../lib/utils/common_utils';
|
||||
|
||||
|
|
@ -7,6 +8,8 @@ import { getPagePath } from '../lib/utils/common_utils';
|
|||
constructor({ form } = {}) {
|
||||
this.onSubmitForm = this.onSubmitForm.bind(this);
|
||||
this.form = form || $('.edit-user');
|
||||
this.newRepoActivated = Cookies.get('new_repo');
|
||||
this.setRepoRadio();
|
||||
this.bindEvents();
|
||||
this.initAvatarGlCrop();
|
||||
}
|
||||
|
|
@ -25,6 +28,7 @@ import { getPagePath } from '../lib/utils/common_utils';
|
|||
|
||||
bindEvents() {
|
||||
$('.js-preferences-form').on('change.preference', 'input[type=radio]', this.submitForm);
|
||||
$('input[name="user[multi_file]"]').on('change', this.setNewRepoCookie);
|
||||
$('#user_notification_email').on('change', this.submitForm);
|
||||
$('#user_notified_of_own_activity').on('change', this.submitForm);
|
||||
$('.update-username').on('ajax:before', this.beforeUpdateUsername);
|
||||
|
|
@ -82,6 +86,23 @@ import { getPagePath } from '../lib/utils/common_utils';
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
setNewRepoCookie() {
|
||||
if (this.value === 'off') {
|
||||
Cookies.remove('new_repo');
|
||||
} else {
|
||||
Cookies.set('new_repo', true, { expires_in: 365 });
|
||||
}
|
||||
}
|
||||
|
||||
setRepoRadio() {
|
||||
const multiEditRadios = $('input[name="user[multi_file]"]');
|
||||
if (this.newRepoActivated || this.newRepoActivated === 'true') {
|
||||
multiEditRadios.filter('[value=on]').prop('checked', true);
|
||||
} else {
|
||||
multiEditRadios.filter('[value=off]').prop('checked', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(function() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
let hasUserDefinedProjectPath = false;
|
||||
|
||||
const deriveProjectPathFromUrl = ($projectImportUrl, $projectPath) => {
|
||||
const deriveProjectPathFromUrl = ($projectImportUrl) => {
|
||||
const $currentProjectPath = $projectImportUrl.parents('.toggle-import-form').find('#project_path');
|
||||
if (hasUserDefinedProjectPath) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -21,7 +22,7 @@ const deriveProjectPathFromUrl = ($projectImportUrl, $projectPath) => {
|
|||
// extract everything after the last slash
|
||||
const pathMatch = /\/([^/]+)$/.exec(importUrl);
|
||||
if (pathMatch) {
|
||||
$projectPath.val(pathMatch[1]);
|
||||
$currentProjectPath.val(pathMatch[1]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ const bindEvents = () => {
|
|||
hasUserDefinedProjectPath = $projectPath.val().trim().length > 0;
|
||||
});
|
||||
|
||||
$projectImportUrl.keyup(() => deriveProjectPathFromUrl($projectImportUrl, $projectPath));
|
||||
$projectImportUrl.keyup(() => deriveProjectPathFromUrl($projectImportUrl));
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', bindEvents);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,25 @@ export default function renderMermaid($els) {
|
|||
});
|
||||
|
||||
$els.each((i, el) => {
|
||||
mermaid.init(undefined, el);
|
||||
const source = el.textContent;
|
||||
|
||||
mermaid.init(undefined, el, (id) => {
|
||||
const svg = document.getElementById(id);
|
||||
|
||||
svg.classList.add('mermaid');
|
||||
|
||||
// pre > code > svg
|
||||
svg.closest('pre').replaceWith(svg);
|
||||
|
||||
// We need to add the original source into the DOM to allow Copy-as-GFM
|
||||
// to access it.
|
||||
const sourceEl = document.createElement('text');
|
||||
sourceEl.classList.add('source');
|
||||
sourceEl.setAttribute('display', 'none');
|
||||
sourceEl.textContent = source;
|
||||
|
||||
svg.appendChild(sourceEl);
|
||||
});
|
||||
});
|
||||
}).catch((err) => {
|
||||
Flash(`Can't load mermaid module: ${err}`);
|
||||
|
|
|
|||
|
|
@ -541,7 +541,6 @@ function UsersSelect(currentUser, els, options = {}) {
|
|||
options.projectId = $(select).data('project-id');
|
||||
options.groupId = $(select).data('group-id');
|
||||
options.showCurrentUser = $(select).data('current-user');
|
||||
options.pushCodeToProtectedBranches = $(select).data('push-code-to-protected-branches');
|
||||
options.authorId = $(select).data('author-id');
|
||||
options.skipUsers = $(select).data('skip-users');
|
||||
showNullUser = $(select).data('null-user');
|
||||
|
|
@ -688,7 +687,6 @@ UsersSelect.prototype.users = function(query, options, callback) {
|
|||
todo_filter: options.todoFilter || null,
|
||||
todo_state_filter: options.todoStateFilter || null,
|
||||
current_user: options.showCurrentUser || null,
|
||||
push_code_to_protected_branches: options.pushCodeToProtectedBranches || null,
|
||||
author_id: options.authorId || null,
|
||||
skip_users: options.skipUsers || null
|
||||
},
|
||||
|
|
|
|||
|
|
@ -34,10 +34,10 @@ export default {
|
|||
|
||||
if (isConfirmed) {
|
||||
MRWidgetService.stopEnvironment(deployment.stop_url)
|
||||
.then(res => res.json())
|
||||
.then((res) => {
|
||||
if (res.redirect_url) {
|
||||
visitUrl(res.redirect_url);
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
if (data.redirect_url) {
|
||||
visitUrl(data.redirect_url);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import tooltip from '../../vue_shared/directives/tooltip';
|
||||
import { pluralize } from '../../lib/utils/text_utility';
|
||||
import icon from '../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
name: 'MRWidgetHeader',
|
||||
|
|
@ -9,6 +10,9 @@ export default {
|
|||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
components: {
|
||||
icon,
|
||||
},
|
||||
computed: {
|
||||
shouldShowCommitsBehindText() {
|
||||
return this.mr.divergedCommitsCount > 0;
|
||||
|
|
@ -81,10 +85,9 @@ export default {
|
|||
data-toggle="dropdown"
|
||||
aria-label="Download as"
|
||||
role="button">
|
||||
<i
|
||||
class="fa fa-download"
|
||||
aria-hidden="true">
|
||||
</i>
|
||||
<icon
|
||||
name="download">
|
||||
</icon>
|
||||
<i
|
||||
class="fa fa-caret-down"
|
||||
aria-hidden="true">
|
||||
|
|
|
|||
|
|
@ -102,11 +102,11 @@ export default {
|
|||
return res;
|
||||
}
|
||||
|
||||
return res.json();
|
||||
return res.data;
|
||||
})
|
||||
.then((res) => {
|
||||
this.computeGraphData(res.metrics, res.deployment_time);
|
||||
return res;
|
||||
.then((data) => {
|
||||
this.computeGraphData(data.metrics, data.deployment_time);
|
||||
return data;
|
||||
})
|
||||
.catch(() => {
|
||||
this.loadFailed = true;
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ export default {
|
|||
<div class="media-body">
|
||||
<mr-widget-author-and-time
|
||||
actionText="Closed by"
|
||||
:author="mr.closedEvent.author"
|
||||
:dateTitle="mr.closedEvent.updatedAt"
|
||||
:dateReadable="mr.closedEvent.formattedUpdatedAt"
|
||||
:author="mr.metrics.closedBy"
|
||||
:dateTitle="mr.metrics.closedAt"
|
||||
:dateReadable="mr.metrics.readableClosedAt"
|
||||
/>
|
||||
<section class="mr-info-list">
|
||||
<p>
|
||||
|
|
|
|||