From 8c7f4e9d5f36cff46365a7f8c4b9c21578c1e781 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 18 Jun 2020 11:18:50 +0000 Subject: Add latest changes from gitlab-org/gitlab@13-1-stable-ee --- app/assets/images/aws_logo.svg | 38 ++ app/assets/images/experienced.svg | 1 + app/assets/images/learn-gitlab-avatar.jpg | Bin 0 -> 4237 bytes app/assets/images/novice.svg | 1 + .../alert_management/components/alert_details.vue | 262 +++++++---- .../components/alert_management_list.vue | 216 +++++++-- .../alert_management/components/alert_sidebar.vue | 61 +++ .../components/sidebar/sidebar_assignee.vue | 51 +++ .../components/sidebar/sidebar_assignees.vue | 278 ++++++++++++ .../components/sidebar/sidebar_header.vue | 34 ++ .../components/sidebar/sidebar_status.vue | 189 ++++++++ .../components/sidebar/sidebar_todo.vue | 29 ++ .../components/system_notes/system_note.vue | 46 ++ .../javascripts/alert_management/constants.js | 57 ++- app/assets/javascripts/alert_management/details.js | 4 +- .../graphql/fragments/alert_note.fragment.graphql | 16 + .../graphql/fragments/detailItem.fragment.graphql | 11 - .../graphql/fragments/detail_item.fragment.graphql | 17 + .../graphql/fragments/listItem.fragment.graphql | 9 - .../graphql/fragments/list_item.fragment.graphql | 15 + .../graphql/mutations/alert_set_assignees.graphql | 15 + .../mutations/create_issue_from_alert.graphql | 8 + .../graphql/mutations/update_alert_status.graphql | 1 + .../graphql/queries/details.query.graphql | 2 +- .../graphql/queries/getAlerts.query.graphql | 11 - .../graphql/queries/get_alerts.query.graphql | 32 ++ .../queries/get_count_by_status.query.graphql | 11 + .../javascripts/alert_management/services/index.js | 7 - .../components/alerts_service_form.vue | 74 ++-- .../javascripts/alerts_service_settings/index.js | 12 +- app/assets/javascripts/api.js | 39 +- app/assets/javascripts/authentication/mount_2fa.js | 14 + .../javascripts/authentication/u2f/authenticate.js | 107 +++++ app/assets/javascripts/authentication/u2f/error.js | 26 ++ app/assets/javascripts/authentication/u2f/index.js | 17 + .../javascripts/authentication/u2f/register.js | 94 ++++ app/assets/javascripts/authentication/u2f/util.js | 40 ++ app/assets/javascripts/avatar_picker.js | 16 - app/assets/javascripts/badges/components/badge.vue | 9 +- .../badges/components/badge_list_row.vue | 2 +- .../batch_comments/components/diff_file_drafts.vue | 41 ++ .../batch_comments/components/draft_note.vue | 113 +++++ .../batch_comments/components/drafts_count.vue | 15 + .../components/inline_draft_comment_row.vue | 32 ++ .../components/parallel_draft_comment_row.vue | 45 ++ .../batch_comments/components/preview_dropdown.vue | 111 +++++ .../batch_comments/components/preview_item.vue | 143 ++++++ .../batch_comments/components/publish_button.vue | 55 +++ .../batch_comments/components/review_bar.vue | 70 +++ app/assets/javascripts/batch_comments/constants.js | 3 + app/assets/javascripts/batch_comments/index.js | 24 + .../batch_comments/mixins/resolved_status.js | 54 ++- .../batch_comments/services/drafts_service.js | 33 ++ .../javascripts/batch_comments/stores/index.js | 14 + .../stores/modules/batch_comments/actions.js | 151 +++++++ .../stores/modules/batch_comments/getters.js | 87 ++++ .../stores/modules/batch_comments/index.js | 12 + .../modules/batch_comments/mutation_types.js | 23 + .../stores/modules/batch_comments/mutations.js | 81 ++++ .../stores/modules/batch_comments/state.js | 9 + app/assets/javascripts/batch_comments/utils.js | 35 ++ .../behaviors/markdown/render_mermaid.js | 3 +- .../javascripts/blob/components/blob_content.vue | 1 + .../javascripts/blob/components/blob_header.vue | 6 + .../components/blob_header_default_actions.vue | 7 + .../blob/components/blob_header_filepath.vue | 2 +- .../javascripts/boards/components/board_column.vue | 254 +---------- .../boards/components/board_content.vue | 82 ++++ .../javascripts/boards/components/board_delete.js | 7 + .../javascripts/boards/components/board_list.vue | 4 +- .../boards/components/board_list_header.vue | 291 +++++++++++++ .../boards/components/board_new_issue.vue | 2 +- .../javascripts/boards/components/board_sidebar.js | 2 +- .../boards/components/issue_card_inner.vue | 8 +- app/assets/javascripts/boards/index.js | 12 +- app/assets/javascripts/boards/models/issue.js | 39 +- app/assets/javascripts/boards/models/list.js | 66 +-- app/assets/javascripts/boards/stores/actions.js | 6 +- .../javascripts/boards/stores/boards_store.js | 144 +++++- app/assets/javascripts/boards/stores/mutations.js | 4 +- app/assets/javascripts/boards/stores/state.js | 1 + .../javascripts/boards/toggle_epics_swimlanes.js | 1 + .../ci_variable_list/components/ci_key_field.vue | 2 +- .../components/ci_variable_modal.vue | 100 ++++- .../components/ci_variable_table.vue | 2 +- .../javascripts/ci_variable_list/constants.js | 6 + app/assets/javascripts/ci_variable_list/index.js | 26 +- app/assets/javascripts/clusters/clusters_bundle.js | 6 + .../clusters/components/application_row.vue | 130 ++++-- .../clusters/components/applications.vue | 402 ++++++++--------- .../components/fluentd_output_settings.vue | 4 +- .../components/ingress_modsecurity_settings.vue | 6 +- .../clusters/components/knative_domain_editor.vue | 5 + .../components/remove_cluster_confirmation.vue | 2 +- .../update_application_confirmation_modal.vue | 65 +++ .../clusters_list/components/clusters.vue | 200 +++++++-- app/assets/javascripts/clusters_list/constants.js | 3 + app/assets/javascripts/clusters_list/index.js | 4 +- .../javascripts/clusters_list/store/actions.js | 49 ++- .../javascripts/clusters_list/store/state.js | 5 + .../code_navigation/components/doc_line.vue | 22 + .../code_navigation/components/popover.vue | 5 +- app/assets/javascripts/commit/image_file.js | 1 + app/assets/javascripts/commons/bootstrap.js | 7 +- app/assets/javascripts/commons/jquery.js | 2 - .../components/custom_metrics_form.vue | 2 +- .../components/design_note_pin.vue | 4 +- .../components/design_notes/design_discussion.vue | 158 ++++++- .../components/design_notes/design_note.vue | 40 +- .../components/design_notes/design_reply_form.vue | 3 +- .../design_notes/toggle_replies_widget.vue | 70 +++ .../components/design_overlay.vue | 42 +- .../components/design_presentation.vue | 10 +- .../components/design_sidebar.vue | 178 ++++++++ .../design_management/components/upload/button.vue | 2 +- .../javascripts/design_management/constants.js | 2 + .../graphql/fragments/design.fragment.graphql | 2 + .../graphql/fragments/designNote.fragment.graphql | 1 + .../discussion_resolved_status.fragment.graphql | 9 + .../toggle_resolve_discussion.mutation.graphql | 17 + .../design_management/pages/design/index.vue | 114 ++--- .../javascripts/design_management/pages/index.vue | 2 +- .../javascripts/design_management/router/index.js | 15 +- .../design_management/utils/cache_update.js | 4 + .../utils/design_management_utils.js | 5 +- .../diff_notes/components/jump_to_discussion.js | 12 +- .../javascripts/diffs/components/commit_item.vue | 2 +- .../diffs/components/compare_versions.vue | 24 +- .../javascripts/diffs/components/diff_content.vue | 8 +- .../diffs/components/diff_line_note_form.vue | 38 +- .../diffs/components/inline_diff_view.vue | 8 +- .../diffs/components/parallel_diff_view.vue | 6 +- .../javascripts/diffs/components/tree_list.vue | 2 +- app/assets/javascripts/diffs/constants.js | 19 + .../javascripts/diffs/mixins/draft_comments.js | 17 +- app/assets/javascripts/diffs/store/actions.js | 24 +- app/assets/javascripts/diffs/store/utils.js | 2 + app/assets/javascripts/diffs/utils/uuids.js | 79 ++++ .../environments/components/environments_app.vue | 14 +- .../error_tracking/components/constants.js | 4 +- .../error_tracking/components/error_details.vue | 51 ++- .../components/error_tracking_list.vue | 21 +- .../error_tracking/store/list/actions.js | 14 +- app/assets/javascripts/error_tracking/utils.js | 26 +- app/assets/javascripts/file_pickers.js | 21 + .../filtered_search_visual_tokens.js | 32 +- .../services/recent_searches_service_error.js | 7 +- app/assets/javascripts/frequent_items/index.js | 76 ++-- app/assets/javascripts/gl_dropdown.js | 2 +- app/assets/javascripts/global_search_input.js | 425 ++++++++++++++++++ .../fragments/pageInfo.fragment.graphql | 2 + app/assets/javascripts/group.js | 70 ++- .../javascripts/groups/components/group_item.vue | 19 +- .../javascripts/groups/components/item_actions.vue | 4 +- .../javascripts/groups/components/item_stats.vue | 8 +- app/assets/javascripts/header.js | 2 +- app/assets/javascripts/ide/commit_icon.js | 11 + .../javascripts/ide/components/activity_bar.vue | 7 +- .../javascripts/ide/components/branches/item.vue | 3 +- .../components/commit_sidebar/editor_header.vue | 4 +- .../ide/components/commit_sidebar/empty_state.vue | 5 +- .../ide/components/commit_sidebar/form.vue | 51 +-- .../ide/components/commit_sidebar/list.vue | 6 +- .../ide/components/commit_sidebar/list_item.vue | 4 +- .../javascripts/ide/components/file_row_extra.vue | 2 +- app/assets/javascripts/ide/components/ide.vue | 23 +- .../javascripts/ide/components/ide_side_bar.vue | 9 +- .../javascripts/ide/components/ide_sidebar_nav.vue | 83 ++++ .../javascripts/ide/components/ide_status_bar.vue | 2 +- .../javascripts/ide/components/ide_status_list.vue | 12 +- .../ide/components/jobs/detail/description.vue | 2 +- .../javascripts/ide/components/jobs/stage.vue | 4 +- .../ide/components/merge_requests/item.vue | 3 +- .../javascripts/ide/components/mr_file_icon.vue | 2 +- .../ide/components/new_dropdown/modal.vue | 11 +- .../ide/components/new_dropdown/upload.vue | 1 - .../ide/components/panes/collapsible_sidebar.vue | 92 +--- .../javascripts/ide/components/panes/right.vue | 35 +- .../javascripts/ide/components/pipelines/list.vue | 8 +- .../ide/components/preview/navigator.vue | 2 +- .../ide/components/repo_commit_section.vue | 48 +- .../javascripts/ide/components/repo_editor.vue | 89 +++- .../javascripts/ide/components/repo_tabs.vue | 14 +- .../javascripts/ide/components/resizable_panel.vue | 13 +- .../ide/components/terminal/empty_state.vue | 71 +++ .../ide/components/terminal/session.vue | 53 +++ .../ide/components/terminal/terminal.vue | 117 +++++ .../ide/components/terminal/terminal_controls.vue | 27 ++ .../javascripts/ide/components/terminal/view.vue | 41 ++ .../terminal_sync/terminal_sync_status.vue | 76 ++++ .../terminal_sync/terminal_sync_status_safe.vue | 22 + app/assets/javascripts/ide/constants.js | 8 + app/assets/javascripts/ide/ide_router.js | 153 +++---- app/assets/javascripts/ide/index.js | 3 +- app/assets/javascripts/ide/lib/common/model.js | 35 +- app/assets/javascripts/ide/lib/create_diff.js | 85 ++++ app/assets/javascripts/ide/lib/create_file_diff.js | 112 +++++ app/assets/javascripts/ide/lib/diff/controller.js | 9 +- app/assets/javascripts/ide/lib/diff/diff.js | 9 +- app/assets/javascripts/ide/lib/editor.js | 32 +- app/assets/javascripts/ide/lib/editor_options.js | 22 +- .../javascripts/ide/lib/editorconfig/parser.js | 55 +++ .../ide/lib/editorconfig/rules_mapper.js | 33 ++ app/assets/javascripts/ide/lib/files.js | 5 - app/assets/javascripts/ide/lib/languages/README.md | 21 + app/assets/javascripts/ide/lib/mirror.js | 154 +++++++ app/assets/javascripts/ide/services/terminals.js | 15 + app/assets/javascripts/ide/stores/actions.js | 42 +- app/assets/javascripts/ide/stores/actions/file.js | 23 +- .../javascripts/ide/stores/actions/project.js | 3 +- app/assets/javascripts/ide/stores/extend.js | 14 + app/assets/javascripts/ide/stores/getters.js | 20 +- app/assets/javascripts/ide/stores/index.js | 35 +- .../ide/stores/modules/branches/index.js | 2 +- .../ide/stores/modules/clientside/actions.js | 3 +- .../ide/stores/modules/commit/actions.js | 8 +- .../ide/stores/modules/commit/getters.js | 3 - .../javascripts/ide/stores/modules/commit/index.js | 2 +- .../ide/stores/modules/file_templates/actions.js | 3 - .../javascripts/ide/stores/modules/pane/actions.js | 3 - .../javascripts/ide/stores/modules/pane/getters.js | 7 +- .../ide/stores/modules/router/actions.js | 6 + .../javascripts/ide/stores/modules/router/index.js | 10 + .../ide/stores/modules/router/mutation_types.js | 2 + .../ide/stores/modules/router/mutations.js | 7 + .../javascripts/ide/stores/modules/router/state.js | 3 + .../ide/stores/modules/terminal/actions/checks.js | 98 +++++ .../ide/stores/modules/terminal/actions/index.js | 5 + .../modules/terminal/actions/session_controls.js | 118 +++++ .../modules/terminal/actions/session_status.js | 64 +++ .../ide/stores/modules/terminal/actions/setup.js | 14 + .../ide/stores/modules/terminal/constants.js | 9 + .../ide/stores/modules/terminal/getters.js | 19 + .../ide/stores/modules/terminal/index.js | 12 + .../ide/stores/modules/terminal/messages.js | 55 +++ .../ide/stores/modules/terminal/mutation_types.js | 11 + .../ide/stores/modules/terminal/mutations.js | 64 +++ .../ide/stores/modules/terminal/state.js | 13 + .../ide/stores/modules/terminal/utils.js | 5 + .../ide/stores/modules/terminal_sync/actions.js | 41 ++ .../ide/stores/modules/terminal_sync/index.js | 10 + .../ide/stores/modules/terminal_sync/messages.js | 5 + .../stores/modules/terminal_sync/mutation_types.js | 4 + .../ide/stores/modules/terminal_sync/mutations.js | 22 + .../ide/stores/modules/terminal_sync/state.js | 6 + .../javascripts/ide/stores/mutation_types.js | 2 - app/assets/javascripts/ide/stores/mutations.js | 12 +- .../javascripts/ide/stores/mutations/file.js | 8 - .../javascripts/ide/stores/mutations/tree.js | 5 - .../javascripts/ide/stores/plugins/terminal.js | 25 ++ .../ide/stores/plugins/terminal_sync.js | 49 +++ app/assets/javascripts/ide/stores/state.js | 3 - app/assets/javascripts/ide/stores/utils.js | 44 +- .../javascripts/ide/sync_router_and_store.js | 55 +++ app/assets/javascripts/ide/utils.js | 61 ++- .../components/bitbucket_status_table.vue | 74 ++++ .../components/import_projects_table.vue | 65 ++- .../components/incompatible_repo_table_row.vue | 30 ++ .../components/provider_repo_table_row.vue | 6 +- app/assets/javascripts/import_projects/index.js | 52 +-- .../javascripts/import_projects/store/actions.js | 66 +-- .../javascripts/import_projects/store/getters.js | 2 + .../javascripts/import_projects/store/index.js | 4 +- .../import_projects/store/mutation_types.js | 2 - .../javascripts/import_projects/store/mutations.js | 10 +- .../javascripts/import_projects/store/state.js | 1 + .../integrations/edit/components/active_toggle.vue | 17 +- .../integrations/edit/components/dynamic_field.vue | 172 ++++++++ .../edit/components/integration_form.vue | 8 + .../edit/components/jira_trigger_fields.vue | 103 ++++- app/assets/javascripts/integrations/edit/index.js | 3 +- .../integrations/integration_settings_form.js | 11 +- .../javascripts/issuable_bulk_update_actions.js | 5 +- .../issuable_suggestions/components/item.vue | 2 +- .../components/issuable_list_root_app.vue | 6 +- .../components/issuables_list_app.vue | 2 +- app/assets/javascripts/issue.js | 26 ++ .../javascripts/issue_show/components/app.vue | 79 +++- .../issue_show/components/pinned_links.vue | 39 +- app/assets/javascripts/issue_show/constants.js | 17 + .../jira_import/components/jira_import_app.vue | 108 ++--- app/assets/javascripts/jira_import/index.js | 1 - .../queries/get_jira_import_details.query.graphql | 12 + app/assets/javascripts/jira_import/utils.js | 59 --- .../javascripts/jira_import/utils/cache_update.js | 37 ++ .../jira_import/utils/jira_import_utils.js | 70 +++ .../jobs/components/artifacts_block.vue | 32 +- .../javascripts/jobs/components/commit_block.vue | 2 +- .../jobs/components/environments_block.vue | 2 +- .../jobs/components/stages_dropdown.vue | 2 +- .../javascripts/jobs/components/stuck_block.vue | 12 +- .../javascripts/jobs/components/trigger_block.vue | 2 +- .../jobs/components/unmet_prerequisites_block.vue | 2 +- app/assets/javascripts/lazy_loader.js | 2 +- app/assets/javascripts/lib/utils/common_utils.js | 14 +- app/assets/javascripts/lib/utils/constants.js | 8 + app/assets/javascripts/lib/utils/datetime_range.js | 15 +- app/assets/javascripts/lib/utils/dom_utils.js | 13 + app/assets/javascripts/lib/utils/text_utility.js | 9 +- app/assets/javascripts/lib/utils/url_utility.js | 17 +- .../logs/components/environment_logs.vue | 4 +- app/assets/javascripts/logs/constants.js | 8 + .../javascripts/logs/logs_tracking_helper.js | 18 + app/assets/javascripts/logs/stores/actions.js | 23 +- .../javascripts/logs/stores/mutation_types.js | 1 + app/assets/javascripts/main.js | 16 +- app/assets/javascripts/merge_request_tabs.js | 50 ++- app/assets/javascripts/milestone_select.js | 9 +- .../monitoring/components/alert_widget.vue | 6 +- .../monitoring/components/alert_widget_form.vue | 2 +- .../monitoring/components/charts/column.vue | 13 +- .../monitoring/components/charts/empty_chart.vue | 4 +- .../monitoring/components/charts/heatmap.vue | 9 +- .../monitoring/components/charts/options.js | 29 +- .../components/charts/stacked_column.vue | 68 ++- .../monitoring/components/charts/time_series.vue | 60 ++- .../monitoring/components/dashboard.vue | 407 +++-------------- .../monitoring/components/dashboard_header.vue | 369 ++++++++++++++++ .../monitoring/components/dashboard_panel.vue | 43 +- .../monitoring/components/graph_group.vue | 11 +- .../monitoring/components/links_section.vue | 32 ++ .../monitoring/components/variables_section.vue | 16 +- app/assets/javascripts/monitoring/constants.js | 23 +- app/assets/javascripts/monitoring/format_date.js | 39 ++ .../javascripts/monitoring/monitoring_app.js | 59 +++ .../javascripts/monitoring/monitoring_bundle.js | 32 -- .../monitoring/monitoring_bundle_with_alerts.js | 13 - .../monitoring/pages/dashboard_page.vue | 18 + .../javascripts/monitoring/router/constants.js | 3 + app/assets/javascripts/monitoring/router/index.js | 15 + app/assets/javascripts/monitoring/router/routes.js | 18 + .../javascripts/monitoring/stores/actions.js | 16 +- .../javascripts/monitoring/stores/getters.js | 22 +- app/assets/javascripts/monitoring/stores/index.js | 12 +- .../monitoring/stores/mutation_types.js | 2 +- .../javascripts/monitoring/stores/mutations.js | 26 +- app/assets/javascripts/monitoring/stores/state.js | 17 +- app/assets/javascripts/monitoring/stores/utils.js | 110 ++++- .../monitoring/stores/variable_mapping.js | 2 +- app/assets/javascripts/monitoring/utils.js | 16 +- app/assets/javascripts/mr_notes/index.js | 2 +- app/assets/javascripts/mr_notes/init_notes.js | 2 +- app/assets/javascripts/mr_notes/stores/index.js | 2 + .../javascripts/namespace_storage_limit_alert.js | 20 + .../javascripts/notes/components/comment_form.vue | 11 +- .../notes/components/diff_with_note.vue | 1 + .../notes/components/multiline_comment_form.vue | 68 +++ .../notes/components/multiline_comment_utils.js | 57 +++ .../javascripts/notes/components/note_actions.vue | 65 ++- .../javascripts/notes/components/note_body.vue | 36 +- .../javascripts/notes/components/note_form.vue | 70 ++- .../notes/components/noteable_discussion.vue | 5 +- .../javascripts/notes/components/noteable_note.vue | 98 ++++- .../notes/mixins/description_version_history.js | 2 +- .../notes/mixins/diff_line_note_form.js | 98 ++++- .../notes/mixins/discussion_navigation.js | 4 +- app/assets/javascripts/notes/mixins/draft.js | 8 - .../javascripts/notes/mixins/get_discussion.js | 7 - app/assets/javascripts/notes/mixins/note_form.js | 24 - app/assets/javascripts/notes/stores/actions.js | 53 ++- .../javascripts/notes/stores/modules/index.js | 1 + .../javascripts/notes/stores/mutation_types.js | 5 + app/assets/javascripts/notes/stores/mutations.js | 36 ++ app/assets/javascripts/onboarding_issues/index.js | 120 +++++ .../components/external_dashboard.vue | 72 --- .../components/form_group/dashboard_timezone.vue | 60 +++ .../components/form_group/external_dashboard.vue | 48 ++ .../components/metrics_settings.vue | 53 +++ app/assets/javascripts/operation_settings/index.js | 4 +- .../operation_settings/store/actions.js | 18 +- .../operation_settings/store/mutation_types.js | 3 +- .../operation_settings/store/mutations.js | 5 +- .../javascripts/operation_settings/store/state.js | 9 +- app/assets/javascripts/pager.js | 5 +- .../pages/admin/application_settings/index.js | 4 + .../javascripts/pages/admin/groups/edit/index.js | 4 +- .../javascripts/pages/admin/groups/new/index.js | 7 +- .../index/components/delete_project_modal.vue | 2 +- .../javascripts/pages/groups/clusters/index.js | 5 + app/assets/javascripts/pages/groups/edit/index.js | 7 +- app/assets/javascripts/pages/groups/index.js | 5 - app/assets/javascripts/pages/groups/new/index.js | 7 +- .../pages/groups/shared/group_details.js | 3 + app/assets/javascripts/pages/ide/index.js | 3 +- .../pages/import/bitbucket/status/index.js | 19 + .../components/bitbucket_server_status_table.vue | 30 ++ .../pages/import/bitbucket_server/status/index.js | 20 + .../pages/import/fogbugz/status/index.js | 7 + .../pages/import/gitlab/status/index.js | 7 + .../pages/ldap/omniauth_callbacks/index.js | 4 +- .../javascripts/pages/omniauth_callbacks/index.js | 4 +- .../pages/profiles/two_factor_auths/index.js | 6 +- .../javascripts/pages/projects/clusters/index.js | 5 + .../javascripts/pages/projects/edit/index.js | 4 +- .../pages/projects/environments/metrics/index.js | 4 +- .../pages/projects/graphs/charts/index.js | 14 + .../projects/graphs/components/code_coverage.vue | 177 ++++++++ app/assets/javascripts/pages/projects/index.js | 3 - .../pages/projects/issues/index/index.js | 2 + .../labels/components/promote_label_modal.vue | 2 +- .../pages/projects/merge_requests/show/index.js | 2 + app/assets/javascripts/pages/projects/new/index.js | 39 ++ .../pages/projects/pipelines/index/index.js | 1 + .../permissions/components/settings_panel.vue | 98 +++-- .../javascripts/pages/projects/show/index.js | 7 + .../javascripts/pages/projects/tree/show/index.js | 2 + .../wikis/components/delete_wiki_modal.vue | 74 ---- .../javascripts/pages/projects/wikis/index.js | 42 +- .../javascripts/pages/projects/wikis/wikis.js | 100 ----- app/assets/javascripts/pages/sessions/index.js | 4 +- .../pages/sessions/new/oauth_remember_me.js | 10 +- .../pages/sessions/new/preserve_url_fragment.js | 10 +- .../shared/wikis/components/delete_wiki_modal.vue | 74 ++++ app/assets/javascripts/pages/shared/wikis/index.js | 41 ++ app/assets/javascripts/pages/shared/wikis/wikis.js | 100 +++++ .../performance_bar/components/detailed_metric.vue | 11 +- .../components/performance_bar_app.vue | 12 +- app/assets/javascripts/persistent_user_callouts.js | 15 + .../pipelines/components/dag/constants.js | 10 + .../javascripts/pipelines/components/dag/dag.vue | 136 ++++++ .../pipelines/components/dag/dag_graph.vue | 299 +++++++++++++ .../pipelines/components/dag/drawing_utils.js | 134 ++++++ .../pipelines/components/dag/interactions.js | 134 ++++++ .../pipelines/components/dag/parsing_utils.js | 164 +++++++ .../javascripts/pipelines/components/pipelines.vue | 24 +- .../pipelines/components/pipelines_artifacts.vue | 2 +- .../components/pipelines_filtered_search.vue | 84 ++-- .../components/test_reports/test_summary.vue | 2 +- .../tokens/pipeline_branch_name_token.vue | 15 +- .../components/tokens/pipeline_status_token.vue | 104 +++++ .../components/tokens/pipeline_tag_name_token.vue | 64 +++ .../tokens/pipeline_trigger_author_token.vue | 13 +- app/assets/javascripts/pipelines/constants.js | 3 + .../pipelines/pipeline_details_bundle.js | 25 ++ .../pipelines/services/pipelines_service.js | 13 +- app/assets/javascripts/pipelines/utils.js | 8 + .../projects/commits/components/author_select.vue | 4 +- .../javascripts/projects/commits/store/actions.js | 5 +- .../components/app.vue | 160 +++++++ .../components/legacy_container.vue | 31 ++ .../components/welcome.vue | 70 +++ .../illustrations/blank-project.svg | 27 ++ .../illustrations/ci-cd-project.svg | 73 ++++ .../illustrations/create-from-template.svg | 54 +++ .../illustrations/import-project.svg | 95 ++++ .../experiment_new_project_creation/index.js | 14 + .../components/details_page/delete_alert.vue | 70 +++ .../components/details_page/delete_modal.vue | 67 +++ .../components/details_page/details_header.vue | 30 ++ .../components/details_page/empty_tags_state.vue | 33 ++ .../components/details_page/tags_loader.vue | 34 ++ .../components/details_page/tags_table.vue | 210 +++++++++ .../explorer/components/group_empty_state.vue | 39 -- .../registry/explorer/components/image_list.vue | 124 ------ .../explorer/components/list_page/cli_commands.vue | 103 +++++ .../components/list_page/group_empty_state.vue | 39 ++ .../explorer/components/list_page/image_list.vue | 52 +++ .../components/list_page/image_list_row.vue | 136 ++++++ .../components/list_page/project_empty_state.vue | 107 +++++ .../components/list_page/registry_header.vue | 138 ++++++ .../explorer/components/project_empty_state.vue | 102 ----- .../explorer/components/project_policy_alert.vue | 68 --- .../explorer/components/quickstart_dropdown.vue | 103 ----- .../javascripts/registry/explorer/constants.js | 130 ------ .../registry/explorer/constants/details.js | 60 +++ .../explorer/constants/expiration_policies.js | 11 + .../registry/explorer/constants/index.js | 4 + .../registry/explorer/constants/list.js | 48 ++ .../registry/explorer/constants/quick_start.js | 9 + .../registry/explorer/pages/details.vue | 401 +++-------------- .../javascripts/registry/explorer/pages/list.vue | 52 +-- app/assets/javascripts/registry/explorer/router.js | 4 +- .../registry/explorer/stores/actions.js | 2 +- .../registry/explorer/stores/getters.js | 6 - .../javascripts/registry/explorer/stores/index.js | 4 +- .../registry/explorer/stores/mutations.js | 8 +- .../releases/components/asset_links_form.vue | 65 ++- .../releases/components/evidence_block.vue | 4 +- .../releases/components/release_block.vue | 2 +- .../releases/components/release_block_assets.vue | 187 ++++++-- .../releases/components/release_block_author.vue | 2 +- .../releases/components/release_block_metadata.vue | 4 +- .../components/release_block_milestone_info.vue | 2 +- app/assets/javascripts/releases/constants.js | 9 + .../releases/stores/modules/detail/actions.js | 30 +- .../stores/modules/detail/mutation_types.js | 1 + .../releases/stores/modules/detail/mutations.js | 7 + .../components/grouped_test_reports_app.vue | 40 +- .../javascripts/reports/components/summary_row.vue | 5 +- .../reports/components/test_issue_body.vue | 2 +- .../repository/components/last_commit.vue | 2 +- .../repository/components/table/row.vue | 7 +- .../queries/getVueFileListLfsBadge.query.graphql | 2 +- app/assets/javascripts/search_autocomplete.js | 482 --------------------- .../serverless/components/function_row.vue | 2 +- .../set_status_modal/set_status_modal_wrapper.vue | 3 +- app/assets/javascripts/shared/sessions/u2f.js | 17 - .../components/time_tracking/help_state.vue | 9 +- .../components/time_tracking/time_tracker.vue | 6 +- .../javascripts/sidebar/mount_milestone_sidebar.js | 1 - .../javascripts/snippets/components/edit.vue | 60 ++- .../snippets/components/snippet_blob_edit.vue | 2 +- .../snippets/components/snippet_blob_view.vue | 10 +- .../components/snippet_description_edit.vue | 32 +- .../components/snippet_description_view.vue | 2 +- .../snippets/components/snippet_header.vue | 3 +- .../snippets/components/snippet_title.vue | 2 +- app/assets/javascripts/snippets/constants.js | 3 + .../static_site_editor/components/edit_area.vue | 45 +- .../components/unsaved_changes_confirm_dialog.vue | 27 ++ .../javascripts/static_site_editor/constants.js | 2 + .../javascripts/static_site_editor/pages/home.vue | 6 +- .../services/parse_source_file.js | 55 +++ .../services/submit_content_changes.js | 13 +- app/assets/javascripts/u2f/authenticate.js | 107 ----- app/assets/javascripts/u2f/error.js | 26 -- app/assets/javascripts/u2f/register.js | 94 ---- app/assets/javascripts/u2f/util.js | 40 -- app/assets/javascripts/user_callout.js | 13 +- .../deployment/deployment_action_button.vue | 2 +- .../deployment/deployment_view_button.vue | 4 +- .../components/mr_widget_header.vue | 4 +- .../components/mr_widget_terraform_plan.vue | 20 +- .../components/source_branch_removal_status.vue | 2 +- .../components/states/mr_widget_rebase.vue | 2 +- .../vue_shared/components/changed_file_icon.vue | 2 +- .../content_viewer/viewers/download_viewer.vue | 2 +- .../date_time_picker/date_time_picker.vue | 106 +++-- .../date_time_picker/date_time_picker_input.vue | 4 +- .../date_time_picker/date_time_picker_lib.js | 65 +-- .../components/diff_viewer/diff_viewer.vue | 5 + .../components/diff_viewer/viewers/renamed.vue | 107 ++++- .../vue_shared/components/file_finder/index.vue | 2 +- .../vue_shared/components/file_finder/item.vue | 8 +- .../components/filtered_search_bar/constants.js | 8 + .../filtered_search_bar_root.vue | 253 +++++++++++ .../filtered_search_bar/tokens/author_token.vue | 114 +++++ .../vue_shared/components/gl_mentions.vue | 84 ++-- .../components/issue/related_issuable_item.vue | 2 +- .../vue_shared/components/markdown/field.vue | 8 +- .../vue_shared/components/markdown/header.vue | 4 +- .../components/markdown/suggestion_diff.vue | 28 ++ .../components/markdown/suggestion_diff_header.vue | 119 ++++- .../vue_shared/components/markdown/suggestions.vue | 21 +- .../vue_shared/components/markdown/toolbar.vue | 72 ++- .../vue_shared/components/notes/system_note.vue | 2 +- .../project_selector/project_selector.vue | 58 ++- .../components/rich_content_editor/constants.js | 10 +- .../rich_content_editor/editor_service.js | 42 ++ .../rich_content_editor/modals/add_image_modal.vue | 74 ++++ .../rich_content_editor/rich_content_editor.vue | 97 ++++- .../rich_content_editor/toolbar_item.vue | 13 +- .../rich_content_editor/toolbar_service.js | 32 -- .../sidebar/labels_select_vue/constants.js | 3 +- .../dropdown_contents_labels_view.vue | 23 +- .../sidebar/labels_select_vue/label_item.vue | 16 +- .../javascripts/vue_shared/components/url_sync.vue | 25 ++ .../vue_shared/mixins/ci_pagination_api_mixin.js | 14 +- .../vue_shared/mixins/related_issuable_mixin.js | 4 +- app/assets/stylesheets/application_dark.scss | 3 + app/assets/stylesheets/bootstrap_migration.scss | 4 +- app/assets/stylesheets/components/avatar.scss | 11 +- .../stylesheets/components/dashboard_skeleton.scss | 6 +- .../components/design_management/design.scss | 59 ++- app/assets/stylesheets/components/popover.scss | 2 +- .../stylesheets/components/related_items_list.scss | 27 +- .../components/rich_content_editor.scss | 22 +- app/assets/stylesheets/framework/animations.scss | 9 +- app/assets/stylesheets/framework/badges.scss | 10 +- app/assets/stylesheets/framework/blank.scss | 14 + .../stylesheets/framework/broadcast_messages.scss | 5 - app/assets/stylesheets/framework/common.scss | 46 +- .../stylesheets/framework/contextual_sidebar.scss | 2 +- app/assets/stylesheets/framework/dropdowns.scss | 5 +- app/assets/stylesheets/framework/files.scss | 2 +- app/assets/stylesheets/framework/filters.scss | 17 +- app/assets/stylesheets/framework/gitlab_theme.scss | 49 ++- .../stylesheets/framework/markdown_area.scss | 2 +- app/assets/stylesheets/framework/selects.scss | 41 +- .../stylesheets/framework/system_messages.scss | 12 +- app/assets/stylesheets/framework/tables.scss | 2 +- app/assets/stylesheets/framework/typography.scss | 18 + app/assets/stylesheets/framework/variables.scss | 244 ++++++----- .../stylesheets/framework/variables_overrides.scss | 23 + app/assets/stylesheets/notify.scss | 2 +- .../page_bundles/_ide_monaco_overrides.scss | 3 +- .../page_bundles/_ide_theme_overrides.scss | 326 +++++++++----- app/assets/stylesheets/page_bundles/ide.scss | 67 ++- .../stylesheets/page_bundles/ide_themes/README.md | 14 +- .../page_bundles/ide_themes/_solarized-dark.scss | 50 +++ .../pages/alert_management/details.scss | 33 +- .../stylesheets/pages/alert_management/list.scss | 93 ++-- app/assets/stylesheets/pages/boards.scss | 29 +- app/assets/stylesheets/pages/diff.scss | 2 +- app/assets/stylesheets/pages/experience_level.scss | 29 ++ app/assets/stylesheets/pages/groups.scss | 32 +- app/assets/stylesheets/pages/issuable.scss | 5 +- app/assets/stylesheets/pages/issues.scss | 66 +++ app/assets/stylesheets/pages/labels.scss | 4 +- app/assets/stylesheets/pages/login.scss | 13 +- app/assets/stylesheets/pages/note_form.scss | 4 +- app/assets/stylesheets/pages/notes.scss | 6 +- app/assets/stylesheets/pages/pipelines.scss | 5 +- .../stylesheets/pages/profiles/preferences.scss | 14 +- app/assets/stylesheets/pages/projects.scss | 2 +- app/assets/stylesheets/pages/prometheus.scss | 8 + app/assets/stylesheets/pages/storage_quota.scss | 17 + app/assets/stylesheets/themes/_dark.scss | 134 ++++++ app/assets/stylesheets/utilities.scss | 70 +-- app/channels/application_cable/channel.rb | 11 + app/channels/application_cable/connection.rb | 8 + app/channels/application_cable/logging.rb | 17 + .../admin/application_settings_controller.rb | 5 + app/controllers/admin/runners_controller.rb | 2 +- app/controllers/admin/users_controller.rb | 3 +- app/controllers/application_controller.rb | 1 + app/controllers/clusters/base_controller.rb | 2 +- app/controllers/clusters/clusters_controller.rb | 1 + .../concerns/enforces_two_factor_authentication.rb | 3 +- app/controllers/concerns/find_snippet.rb | 24 + app/controllers/concerns/integrations_actions.rb | 6 + app/controllers/concerns/issuable_actions.rb | 29 +- app/controllers/concerns/issuable_collections.rb | 3 +- .../concerns/issuable_collections_action.rb | 4 +- app/controllers/concerns/known_sign_in.rb | 2 +- app/controllers/concerns/milestone_actions.rb | 8 +- app/controllers/concerns/notes_actions.rb | 6 +- app/controllers/concerns/preview_markdown.rb | 2 +- app/controllers/concerns/service_params.rb | 3 + app/controllers/concerns/snippet_authorizations.rb | 23 + app/controllers/concerns/snippets_actions.rb | 61 +++ app/controllers/concerns/wiki_actions.rb | 232 ++++++++++ .../concerns/workhorse_import_export_upload.rb | 33 ++ app/controllers/dashboard/milestones_controller.rb | 32 +- app/controllers/dashboard/todos_controller.rb | 10 +- app/controllers/groups/boards_controller.rb | 1 + app/controllers/groups/group_links_controller.rb | 2 +- app/controllers/groups/imports_controller.rb | 19 + app/controllers/groups/milestones_controller.rb | 71 +-- app/controllers/groups_controller.rb | 15 +- app/controllers/ide_controller.rb | 6 +- app/controllers/import/base_controller.rb | 76 ++++ app/controllers/import/bitbucket_controller.rb | 53 ++- .../import/bitbucket_server_controller.rb | 77 +++- app/controllers/import/fogbugz_controller.rb | 33 +- app/controllers/import/github_controller.rb | 2 +- app/controllers/import/gitlab_controller.rb | 29 +- app/controllers/import/gitlab_groups_controller.rb | 65 +++ .../import/gitlab_projects_controller.rb | 27 +- .../projects/alert_management_controller.rb | 4 - .../projects/alerting/notifications_controller.rb | 16 +- app/controllers/projects/badges_controller.rb | 11 +- app/controllers/projects/blame_controller.rb | 3 +- app/controllers/projects/blob_controller.rb | 6 +- app/controllers/projects/branches_controller.rb | 14 +- .../daily_build_group_report_results_controller.rb | 11 +- app/controllers/projects/discussions_controller.rb | 2 +- .../projects/environments_controller.rb | 2 +- app/controllers/projects/graphs_controller.rb | 10 +- app/controllers/projects/group_links_controller.rb | 7 +- app/controllers/projects/import/jira_controller.rb | 54 +-- app/controllers/projects/issues_controller.rb | 1 - app/controllers/projects/jobs_controller.rb | 40 +- .../projects/merge_requests/diffs_controller.rb | 11 +- .../projects/merge_requests/drafts_controller.rb | 129 ++++++ .../projects/merge_requests_controller.rb | 3 + app/controllers/projects/milestones_controller.rb | 4 +- app/controllers/projects/pipelines_controller.rb | 16 +- app/controllers/projects/refs_controller.rb | 2 +- app/controllers/projects/releases_controller.rb | 1 + app/controllers/projects/services_controller.rb | 15 +- .../projects/settings/operations_controller.rb | 2 +- .../projects/snippets/application_controller.rb | 19 + app/controllers/projects/snippets_controller.rb | 86 +--- app/controllers/projects/tags_controller.rb | 18 +- .../projects/web_ide_terminals_controller.rb | 98 +++++ app/controllers/projects/wikis_controller.rb | 199 +-------- app/controllers/projects_controller.rb | 21 +- .../registrations/experience_levels_controller.rb | 44 ++ app/controllers/registrations_controller.rb | 4 + .../repositories/git_http_controller.rb | 2 +- app/controllers/search_controller.rb | 31 +- app/controllers/snippets/application_controller.rb | 22 + app/controllers/snippets_controller.rb | 92 +--- app/finders/admin/runners_finder.rb | 71 --- .../ci/daily_build_group_report_results_finder.rb | 20 +- app/finders/ci/runners_finder.rb | 92 ++++ app/finders/events_finder.rb | 5 +- app/finders/issuable_finder.rb | 2 +- app/finders/issuable_finder/params.rb | 10 +- app/finders/labels_finder.rb | 9 +- app/finders/milestones_finder.rb | 6 +- app/finders/notes_finder.rb | 2 +- app/finders/resource_label_event_finder.rb | 41 -- app/finders/resource_milestone_event_finder.rb | 69 +++ app/finders/uploader_finder.rb | 34 ++ app/finders/users_finder.rb | 19 +- .../alert_management/alerts/set_assignees.rb | 56 +++ app/graphql/mutations/alert_management/base.rb | 4 +- .../alert_management/update_alert_status.rb | 2 +- app/graphql/mutations/base_mutation.rb | 2 +- app/graphql/mutations/branches/create.rb | 2 +- app/graphql/mutations/commits/create.rb | 60 +++ .../concerns/mutations/resolves_issuable.rb | 16 +- .../concerns/mutations/resolves_project.rb | 15 - .../container_expiration_policies/update.rb | 62 +++ .../mutations/discussions/toggle_resolve.rb | 73 ++++ app/graphql/mutations/issues/set_confidential.rb | 2 +- app/graphql/mutations/issues/set_due_date.rb | 2 +- app/graphql/mutations/issues/update.rb | 2 +- app/graphql/mutations/jira_import/import_users.rb | 44 ++ app/graphql/mutations/jira_import/start.rb | 16 +- app/graphql/mutations/merge_requests/create.rb | 63 +++ .../mutations/merge_requests/set_assignees.rb | 2 +- app/graphql/mutations/merge_requests/set_labels.rb | 7 +- app/graphql/mutations/merge_requests/set_locked.rb | 2 +- .../mutations/merge_requests/set_milestone.rb | 2 +- .../mutations/merge_requests/set_subscription.rb | 2 +- app/graphql/mutations/merge_requests/set_wip.rb | 2 +- .../metrics/dashboard/annotations/base.rb | 18 + .../metrics/dashboard/annotations/delete.rb | 32 ++ app/graphql/mutations/snippets/create.rb | 4 +- app/graphql/mutations/todos/mark_all_done.rb | 4 +- app/graphql/mutations/todos/mark_done.rb | 2 +- app/graphql/mutations/todos/restore.rb | 6 +- app/graphql/mutations/todos/restore_many.rb | 2 +- .../resolvers/alert_management/alert_resolver.rb | 42 ++ .../alert_status_counts_resolver.rb | 4 + .../resolvers/alert_management_alert_resolver.rb | 31 -- .../resolvers/assigned_merge_requests_resolver.rb | 9 + .../resolvers/authored_merge_requests_resolver.rb | 9 + app/graphql/resolvers/base_resolver.rb | 33 +- app/graphql/resolvers/concerns/looks_ahead.rb | 52 +++ .../resolvers/concerns/resolves_merge_requests.rb | 67 +++ app/graphql/resolvers/concerns/resolves_project.rb | 15 + app/graphql/resolvers/full_path_resolver.rb | 7 +- app/graphql/resolvers/merge_request_resolver.rb | 18 + app/graphql/resolvers/merge_requests_resolver.rb | 52 +-- app/graphql/resolvers/project_members_resolver.rb | 21 + app/graphql/resolvers/project_pipeline_resolver.rb | 17 + .../resolvers/projects/jira_imports_resolver.rb | 2 - .../resolvers/projects/jira_projects_resolver.rb | 76 ++++ .../resolvers/user_merge_requests_resolver.rb | 68 +++ app/graphql/resolvers/user_resolver.rb | 43 ++ app/graphql/resolvers/users_resolver.rb | 57 +++ app/graphql/types/access_level_enum.rb | 15 + app/graphql/types/access_level_type.rb | 17 + .../types/alert_management/alert_sort_enum.rb | 12 +- app/graphql/types/alert_management/alert_type.rb | 11 + app/graphql/types/base_object.rb | 4 + app/graphql/types/board_type.rb | 2 +- app/graphql/types/ci/pipeline_type.rb | 2 + app/graphql/types/commit_action_mode_enum.rb | 14 + app/graphql/types/commit_action_type.rb | 22 + app/graphql/types/commit_encoding_enum.rb | 10 + .../container_expiration_policy_cadence_enum.rb | 17 + .../types/container_expiration_policy_keep_enum.rb | 18 + .../container_expiration_policy_older_than_enum.rb | 16 + .../types/container_expiration_policy_type.rb | 21 + app/graphql/types/evidence_type.rb | 21 + app/graphql/types/group_member_type.rb | 17 + app/graphql/types/group_type.rb | 39 ++ app/graphql/types/jira_import_type.rb | 6 + app/graphql/types/jira_user_type.rb | 19 + app/graphql/types/member_interface.rb | 22 + app/graphql/types/merge_request_type.rb | 12 +- app/graphql/types/metrics/dashboard_type.rb | 3 + app/graphql/types/milestone_type.rb | 12 + app/graphql/types/mutation_type.rb | 7 + app/graphql/types/notes/discussion_type.rb | 2 + app/graphql/types/notes/note_type.rb | 12 +- app/graphql/types/notes/noteable_type.rb | 2 + app/graphql/types/permission_types/ci/pipeline.rb | 3 +- .../types/permission_types/merge_request.rb | 12 +- app/graphql/types/project_member_type.rb | 25 ++ app/graphql/types/project_type.rb | 63 ++- app/graphql/types/projects/service_type.rb | 2 +- .../types/projects/services/jira_project_type.rb | 21 + .../types/projects/services/jira_service_type.rb | 11 +- app/graphql/types/query_type.rb | 14 + app/graphql/types/release_assets_type.rb | 20 + app/graphql/types/release_link_type.rb | 20 + app/graphql/types/release_link_type_enum.rb | 12 + app/graphql/types/release_source_type.rb | 14 + app/graphql/types/release_type.rb | 4 + app/graphql/types/resolvable_interface.rb | 28 ++ app/graphql/types/snippet_type.rb | 10 +- .../types/snippets/file_input_action_enum.rb | 15 + app/graphql/types/snippets/file_input_type.rb | 26 ++ app/graphql/types/user_state_enum.rb | 12 + app/graphql/types/user_type.rb | 22 +- app/helpers/active_sessions_helper.rb | 2 +- app/helpers/application_helper.rb | 3 +- app/helpers/application_settings_helper.rb | 14 + app/helpers/auto_devops_helper.rb | 2 +- app/helpers/clusters_helper.rb | 24 +- app/helpers/environments_helper.rb | 15 +- app/helpers/events_helper.rb | 2 +- app/helpers/gitlab_routing_helper.rb | 29 +- app/helpers/issuables_helper.rb | 5 +- app/helpers/issues_helper.rb | 39 -- app/helpers/markup_helper.rb | 6 +- app/helpers/milestones_helper.rb | 309 ------------- app/helpers/milestones_routing_helper.rb | 19 - app/helpers/namespaces_helper.rb | 41 +- app/helpers/notes_helper.rb | 23 +- app/helpers/notifications_helper.rb | 2 +- app/helpers/numbers_helper.rb | 5 +- app/helpers/page_layout_helper.rb | 10 + app/helpers/projects/alert_management_helper.rb | 2 +- app/helpers/projects_helper.rb | 51 ++- app/helpers/search_helper.rb | 107 ----- app/helpers/services_helper.rb | 22 + app/helpers/subscribable_banner_helper.rb | 9 + app/helpers/timeboxes_helper.rb | 302 +++++++++++++ app/helpers/timeboxes_routing_helper.rb | 21 + app/helpers/todos_helper.rb | 14 +- app/helpers/visibility_level_helper.rb | 11 + app/helpers/wiki_helper.rb | 51 ++- app/mailers/emails/issues.rb | 2 + app/mailers/emails/profile.rb | 11 +- app/mailers/emails/reviews.rb | 33 ++ app/mailers/notify.rb | 3 +- app/mailers/previews/notify_preview.rb | 2 +- app/models/active_session.rb | 2 +- app/models/alert_management.rb | 7 + app/models/alert_management/alert.rb | 48 +- app/models/alert_management/alert_assignee.rb | 11 + app/models/alert_management/alert_user_mention.rb | 8 + app/models/application_record.rb | 4 + app/models/application_setting.rb | 29 ++ app/models/application_setting_implementation.rb | 33 +- app/models/audit_event.rb | 3 + app/models/badge.rb | 2 +- app/models/blob.rb | 2 + app/models/blob_viewer/go_mod.rb | 43 ++ app/models/blob_viewer/metrics_dashboard_yml.rb | 44 ++ app/models/board_group_recent_visit.rb | 2 +- app/models/board_project_recent_visit.rb | 2 +- app/models/chat_team.rb | 2 +- app/models/ci/bridge.rb | 3 + app/models/ci/build.rb | 49 ++- app/models/ci/build_dependencies.rb | 2 +- app/models/ci/build_report_result.rb | 45 ++ app/models/ci/build_runner_session.rb | 15 +- app/models/ci/daily_build_group_report_result.rb | 2 + app/models/ci/freeze_period.rb | 2 +- app/models/ci/group.rb | 2 +- app/models/ci/instance_variable.rb | 53 +-- app/models/ci/job_artifact.rb | 29 +- app/models/ci/pipeline.rb | 50 ++- app/models/ci/pipeline_enums.rb | 5 +- app/models/ci/processable.rb | 4 - app/models/ci/ref.rb | 71 ++- app/models/ci/runner.rb | 32 +- app/models/clusters/applications/cert_manager.rb | 6 +- app/models/clusters/applications/crossplane.rb | 3 +- app/models/clusters/applications/elastic_stack.rb | 12 +- app/models/clusters/applications/fluentd.rb | 3 +- app/models/clusters/applications/helm.rb | 6 +- app/models/clusters/applications/ingress.rb | 3 +- app/models/clusters/applications/jupyter.rb | 3 +- app/models/clusters/applications/knative.rb | 6 +- app/models/clusters/applications/prometheus.rb | 11 +- app/models/clusters/applications/runner.rb | 5 +- app/models/clusters/cluster.rb | 22 +- app/models/clusters/concerns/application_core.rb | 2 +- app/models/clusters/concerns/application_data.rb | 5 +- app/models/clusters/concerns/application_status.rb | 22 +- app/models/commit_status.rb | 25 +- app/models/concerns/cacheable_attributes.rb | 2 +- app/models/concerns/ci/contextable.rb | 2 +- app/models/concerns/each_batch.rb | 2 +- app/models/concerns/featurable.rb | 99 +++++ app/models/concerns/has_status.rb | 4 +- .../concerns/import_state/sidekiq_job_tracker.rb | 7 +- app/models/concerns/integration.rb | 19 + app/models/concerns/issuable.rb | 30 +- app/models/concerns/limitable.rb | 29 +- app/models/concerns/mentionable.rb | 4 +- app/models/concerns/milestoneish.rb | 20 - app/models/concerns/noteable.rb | 2 +- app/models/concerns/prometheus_adapter.rb | 2 +- app/models/concerns/relative_positioning.rb | 2 +- app/models/concerns/resolvable_discussion.rb | 7 +- app/models/concerns/resolvable_note.rb | 4 +- app/models/concerns/storage/legacy_namespace.rb | 2 +- app/models/concerns/timebox.rb | 51 ++- app/models/concerns/token_authenticatable.rb | 5 + app/models/concerns/update_highest_role.rb | 4 +- app/models/container_expiration_policy.rb | 6 + app/models/container_repository.rb | 14 +- app/models/dashboard_group_milestone.rb | 29 -- app/models/dashboard_milestone.rb | 19 - app/models/data_list.rb | 25 ++ app/models/deployment.rb | 2 +- app/models/design_management/design.rb | 68 +-- app/models/design_management/version.rb | 2 +- app/models/diff_note.rb | 2 +- app/models/discussion.rb | 1 + app/models/draft_note.rb | 122 ++++++ app/models/environment.rb | 2 +- app/models/event.rb | 194 ++++----- app/models/global_milestone.rb | 108 ----- app/models/group.rb | 59 ++- app/models/group_deploy_key.rb | 11 + app/models/group_group_link.rb | 1 + app/models/group_import_state.rb | 7 +- app/models/group_milestone.rb | 49 --- app/models/internal_id.rb | 24 - app/models/issue.rb | 27 +- app/models/issue/metrics.rb | 4 +- app/models/iteration.rb | 25 +- app/models/jira_import_state.rb | 27 +- app/models/label.rb | 4 +- app/models/lfs_object.rb | 4 +- app/models/license_template.rb | 2 +- app/models/member.rb | 2 +- app/models/members/group_member.rb | 11 +- app/models/members/project_member.rb | 2 +- app/models/merge_request.rb | 32 +- app/models/merge_request_context_commit.rb | 2 +- .../merge_request_context_commit_diff_file.rb | 2 +- app/models/merge_request_diff.rb | 4 +- app/models/merge_request_diff_commit.rb | 2 +- app/models/metrics/dashboard/annotation.rb | 13 + app/models/milestone.rb | 49 +-- app/models/namespace.rb | 8 +- app/models/note.rb | 25 +- app/models/pages_domain.rb | 8 +- app/models/pages_domain_acme_order.rb | 2 +- .../performance_monitoring/prometheus_dashboard.rb | 43 +- .../performance_monitoring/prometheus_metric.rb | 26 +- .../performance_monitoring/prometheus_panel.rb | 25 +- .../prometheus_panel_group.rb | 21 +- app/models/project.rb | 132 +++--- app/models/project_ci_cd_setting.rb | 13 - app/models/project_feature.rb | 106 +---- app/models/project_group_link.rb | 6 - app/models/project_import_state.rb | 6 +- app/models/project_metrics_setting.rb | 7 + app/models/project_repository_storage_move.rb | 22 +- app/models/project_services/alerts_service.rb | 2 +- .../project_services/chat_message/alert_message.rb | 74 ++++ .../project_services/chat_message/merge_message.rb | 2 +- .../chat_message/pipeline_message.rb | 6 +- app/models/project_services/hipchat_service.rb | 4 +- app/models/project_services/jira_service.rb | 23 +- .../project_services/pipelines_email_service.rb | 6 - app/models/project_services/prometheus_service.rb | 43 +- app/models/project_services/slack_service.rb | 16 +- app/models/project_setting.rb | 4 - app/models/prometheus_alert_event.rb | 6 - app/models/push_event.rb | 4 +- app/models/releases/evidence.rb | 55 +-- app/models/releases/link.rb | 7 + app/models/remote_mirror.rb | 12 +- app/models/repository.rb | 8 +- app/models/repository_language.rb | 2 +- app/models/resource_label_event.rb | 8 + app/models/resource_milestone_event.rb | 10 + app/models/review.rb | 30 ++ app/models/route.rb | 2 +- app/models/self_managed_prometheus_alert_event.rb | 6 - app/models/service.rb | 26 +- app/models/service_list.rb | 27 ++ app/models/snippet.rb | 2 +- app/models/snippet_input_action.rb | 62 +++ app/models/snippet_input_action_collection.rb | 25 ++ app/models/ssh_host_key.rb | 2 +- app/models/storage/legacy_project.rb | 2 +- app/models/terraform/state.rb | 2 + app/models/todo.rb | 18 +- app/models/uploads/base.rb | 2 +- app/models/user.rb | 61 ++- app/models/user_interacted_project.rb | 14 - app/models/user_preference.rb | 2 + app/models/web_ide_terminal.rb | 51 +++ app/models/wiki.rb | 2 +- app/models/wiki_directory.rb | 2 +- app/models/wiki_page.rb | 8 +- app/models/wiki_page/meta.rb | 2 +- app/models/wiki_page/slug.rb | 4 +- app/policies/ci/build_policy.rb | 22 + app/policies/container_expiration_policy_policy.rb | 5 + app/policies/draft_note_policy.rb | 13 + app/policies/project_policy.rb | 35 +- app/policies/releases/link_policy.rb | 7 + app/policies/releases/source_policy.rb | 13 + app/presenters/gitlab/blame_presenter.rb | 82 ++++ .../projects/prometheus/alert_presenter.rb | 8 +- app/presenters/release_presenter.rb | 2 +- app/presenters/snippet_presenter.rb | 8 +- app/serializers/build_artifact_entity.rb | 34 +- app/serializers/ci/dag_job_entity.rb | 1 + app/serializers/ci/dag_pipeline_entity.rb | 6 +- .../ci/daily_build_group_report_result_entity.rb | 13 + .../daily_build_group_report_result_serializer.rb | 28 ++ app/serializers/cluster_entity.rb | 1 + app/serializers/cluster_serializer.rb | 1 + app/serializers/container_repository_entity.rb | 2 +- app/serializers/diff_file_base_entity.rb | 6 +- app/serializers/diff_file_metadata_entity.rb | 5 +- app/serializers/diffs_entity.rb | 14 +- app/serializers/draft_note_entity.rb | 39 ++ app/serializers/draft_note_serializer.rb | 4 + .../import/base_provider_repo_entity.rb | 8 + .../import/bitbucket_provider_repo_entity.rb | 15 + .../bitbucket_server_provider_repo_entity.rb | 7 + .../import/fogbugz_provider_repo_entity.rb | 17 + .../import/githubish_provider_repo_entity.rb | 19 + .../import/gitlab_provider_repo_entity.rb | 19 + app/serializers/import/provider_repo_serializer.rb | 23 + app/serializers/merge_request_noteable_entity.rb | 2 + app/serializers/paginated_diff_entity.rb | 10 +- app/serializers/pipeline_details_entity.rb | 3 +- app/serializers/pipeline_serializer.rb | 36 +- app/serializers/provider_repo_entity.rb | 25 -- app/serializers/provider_repo_serializer.rb | 5 - app/serializers/service_field_entity.rb | 24 + app/serializers/service_field_serializer.rb | 5 + app/serializers/web_ide_terminal_entity.rb | 12 + app/serializers/web_ide_terminal_serializer.rb | 11 + .../admin/propagate_integration_service.rb | 142 ++++++ .../alert_management/alerts/update_service.rb | 98 +++++ .../alert_management/create_alert_issue_service.rb | 3 +- .../process_prometheus_alert_service.rb | 6 +- app/services/auto_merge/base_service.rb | 54 ++- app/services/award_emojis/destroy_service.rb | 2 +- app/services/ci/authorize_job_artifact_service.rb | 53 +++ app/services/ci/build_report_result_service.rb | 36 ++ .../ci/create_cross_project_pipeline_service.rb | 1 + app/services/ci/create_web_ide_terminal_service.rb | 123 ++++++ .../extract_sections_from_build_trace_service.rb | 2 +- app/services/ci/process_pipeline_service.rb | 2 +- app/services/ci/update_ci_ref_status_service.rb | 1 + app/services/ci/web_ide_config_service.rb | 59 +++ .../applications/prometheus_config_service.rb | 12 +- .../parse_cluster_applications_artifact_service.rb | 27 +- app/services/commits/create_service.rb | 2 + app/services/concerns/exclusive_lease_guard.rb | 2 +- .../concerns/integrations/project_test_data.rb | 62 +++ app/services/concerns/measurable.rb | 2 - app/services/concerns/spam_check_methods.rb | 11 +- .../update_service.rb | 38 ++ .../container_expiration_policy_service.rb | 7 + .../design_management/delete_designs_service.rb | 5 +- .../design_management/save_designs_service.rb | 17 +- app/services/discussions/resolve_service.rb | 55 ++- app/services/draft_notes/base_service.rb | 21 + app/services/draft_notes/create_service.rb | 56 +++ app/services/draft_notes/destroy_service.rb | 23 + app/services/draft_notes/publish_service.rb | 67 +++ app/services/event_create_service.rb | 132 ++++-- app/services/git/wiki_push_service/change.rb | 6 +- app/services/groups/destroy_service.rb | 2 +- app/services/groups/group_links/create_service.rb | 2 +- app/services/groups/group_links/destroy_service.rb | 6 +- .../groups/import_export/export_service.rb | 29 +- .../groups/import_export/import_service.rb | 23 +- app/services/groups/transfer_service.rb | 10 +- app/services/import/github_service.rb | 29 +- app/services/integrations/test/base_service.rb | 36 ++ app/services/integrations/test/project_service.rb | 47 ++ app/services/issuable/bulk_update_service.rb | 13 +- app/services/issuable/clone/attributes_rewriter.rb | 2 +- app/services/issuable_base_service.rb | 12 +- app/services/issues/create_service.rb | 7 +- app/services/issues/import_csv_service.rb | 2 +- app/services/issues/update_service.rb | 6 +- app/services/jira/requests/base.rb | 52 +++ app/services/jira/requests/projects.rb | 32 ++ app/services/jira_import/start_import_service.rb | 4 +- app/services/jira_import/users_importer.rb | 43 ++ app/services/jira_import/users_mapper.rb | 31 ++ app/services/keys/create_service.rb | 8 + app/services/labels/available_labels_service.rb | 6 +- app/services/labels/create_service.rb | 2 +- app/services/labels/promote_service.rb | 2 +- app/services/merge_requests/merge_service.rb | 4 +- app/services/merge_requests/update_service.rb | 4 +- app/services/metrics/dashboard/base_service.rb | 3 +- .../dashboard/self_monitoring_dashboard_service.rb | 4 +- .../metrics/dashboard/system_dashboard_service.rb | 4 +- app/services/milestones/promote_service.rb | 2 +- .../namespaces/check_storage_size_service.rb | 5 +- app/services/notes/create_service.rb | 8 +- app/services/notes/post_process_service.rb | 2 +- .../notification_recipients/build_service.rb | 6 +- .../notification_recipients/builder/new_review.rb | 43 ++ app/services/notification_service.rb | 29 +- app/services/pages/delete_service.rb | 2 +- app/services/projects/after_import_service.rb | 8 +- app/services/projects/alerting/notify_service.rb | 33 +- .../container_repository/cleanup_tags_service.rb | 12 + app/services/projects/create_service.rb | 24 +- app/services/projects/destroy_service.rb | 2 +- .../detect_repository_languages_service.rb | 2 +- .../projects/group_links/create_service.rb | 1 + .../projects/group_links/destroy_service.rb | 4 +- .../projects/group_links/update_service.rb | 29 ++ .../hashed_storage/base_attachment_service.rb | 2 +- .../projects/import_export/export_service.rb | 14 +- app/services/projects/import_service.rb | 2 - .../projects/lfs_pointers/lfs_link_service.rb | 2 +- app/services/projects/lsif_data_service.rb | 101 ----- .../projects/move_deploy_keys_projects_service.rb | 2 +- .../projects/move_lfs_objects_projects_service.rb | 2 +- .../projects/move_notification_settings_service.rb | 2 +- .../projects/move_project_group_links_service.rb | 2 +- .../projects/move_project_members_service.rb | 2 +- app/services/projects/operations/update_service.rb | 4 +- .../prometheus/alerts/create_events_service.rb | 8 +- .../projects/prometheus/alerts/notify_service.rb | 35 +- .../projects/propagate_service_template.rb | 48 +- .../projects/update_remote_mirror_service.rb | 6 +- .../projects/update_repository_storage_service.rb | 7 +- app/services/projects/update_service.rb | 13 +- app/services/projects/update_statistics_service.rb | 2 +- .../prometheus/create_default_alerts_service.rb | 11 + app/services/prometheus/proxy_service.rb | 4 + .../proxy_variable_substitution_service.rb | 24 +- .../legacy_api_update_service.rb | 4 +- app/services/releases/create_evidence_service.rb | 25 ++ app/services/releases/create_service.rb | 33 +- .../resource_events/change_labels_service.rb | 2 +- .../resource_events/change_state_service.rb | 36 ++ .../resource_events/merge_into_notes_service.rb | 5 +- .../synthetic_state_notes_builder_service.rb | 20 + app/services/search_service.rb | 22 +- app/services/service_response.rb | 6 + app/services/snippets/base_service.rb | 33 +- app/services/snippets/bulk_destroy_service.rb | 6 +- app/services/snippets/create_service.rb | 31 +- app/services/snippets/update_service.rb | 41 +- app/services/spam/akismet_service.rb | 4 +- app/services/spam/spam_action_service.rb | 21 +- app/services/spam/spam_constants.rb | 22 +- app/services/spam/spam_verdict_service.rb | 76 +++- app/services/submit_usage_ping_service.rb | 2 +- app/services/suggestions/apply_service.rb | 110 ++--- app/services/suggestions/create_service.rb | 2 +- app/services/system_notes/issuables_service.rb | 14 +- app/services/test_hooks/base_service.rb | 28 +- app/services/test_hooks/project_service.rb | 72 +-- app/services/test_hooks/system_service.rb | 25 +- app/services/todo_service.rb | 98 ++--- .../user_project_access_changed_service.rb | 3 +- app/services/users/build_service.rb | 3 +- app/services/users/destroy_service.rb | 2 +- .../users/migrate_to_ghost_user_service.rb | 5 + app/services/web_hook_service.rb | 2 +- app/services/wiki_pages/create_service.rb | 2 +- app/services/wiki_pages/destroy_service.rb | 2 +- app/services/wiki_pages/update_service.rb | 2 +- app/uploaders/file_mover.rb | 2 +- app/validators/json_schema_validator.rb | 38 ++ .../json_schemas/build_report_result_data.json | 12 + .../build_report_result_data_tests.json | 13 + .../daily_build_group_report_result_data.json | 8 + app/views/admin/appearances/_form.html.haml | 10 +- .../_system_header_footer_form.html.haml | 2 +- .../_account_and_limit.html.haml | 5 + .../application_settings/_issue_limits.html.haml | 2 +- .../admin/application_settings/_outbound.html.haml | 4 +- .../_repository_storage.html.haml | 8 +- .../admin/application_settings/_spam.html.haml | 9 + .../application_settings/ci/_header.html.haml | 20 + .../admin/application_settings/ci_cd.html.haml | 11 + app/views/admin/broadcast_messages/_form.html.haml | 4 +- app/views/admin/broadcast_messages/index.html.haml | 4 +- app/views/admin/groups/_group.html.haml | 43 +- app/views/admin/groups/show.html.haml | 2 + app/views/admin/hook_logs/_index.html.haml | 2 +- app/views/admin/hooks/edit.html.haml | 2 +- app/views/admin/projects/show.html.haml | 2 + app/views/admin/sessions/_two_factor_u2f.html.haml | 17 - app/views/admin/sessions/two_factor.html.haml | 2 +- app/views/admin/users/_admin_notes.html.haml | 7 + app/views/admin/users/_form.html.haml | 2 +- app/views/admin/users/_user_detail.html.haml | 4 +- app/views/admin/users/_user_detail_note.html.haml | 7 + app/views/admin/users/_user_listing_note.html.haml | 3 + app/views/admin/users/show.html.haml | 8 +- app/views/ci/variables/_index.html.haml | 13 +- app/views/clusters/clusters/_banner.html.haml | 2 +- .../clusters/_gcp_signup_offer_banner.html.haml | 2 +- .../clusters/_gitlab_integration_form.html.haml | 2 +- app/views/clusters/clusters/_sidebar.html.haml | 2 +- app/views/clusters/clusters/index.html.haml | 2 +- app/views/clusters/clusters/show.html.haml | 2 +- .../dashboard/milestones/_milestone.html.haml | 1 - app/views/dashboard/milestones/show.html.haml | 5 - app/views/devise/confirmations/almost_there.haml | 2 +- app/views/devise/sessions/two_factor.html.haml | 2 +- app/views/devise/shared/_omniauth_box.html.haml | 2 +- app/views/doorkeeper/applications/index.html.haml | 4 +- app/views/events/event/_note.html.haml | 6 +- app/views/groups/_flash_messages.html.haml | 1 + app/views/groups/_home_panel.html.haml | 6 +- app/views/groups/_import_group_pane.html.haml | 52 +++ app/views/groups/_new_group_fields.html.haml | 22 + app/views/groups/imports/show.html.haml | 10 + app/views/groups/milestones/_form.html.haml | 4 +- app/views/groups/milestones/_milestone.html.haml | 2 - app/views/groups/milestones/index.html.haml | 5 +- app/views/groups/new.html.haml | 73 ++-- .../groups/registry/repositories/index.html.haml | 4 +- app/views/groups/settings/_export.html.haml | 2 +- app/views/groups/settings/_general.html.haml | 2 +- app/views/groups/show.html.haml | 4 - app/views/groups/sidebar/_packages.html.haml | 6 +- app/views/import/_githubish_status.html.haml | 5 +- app/views/import/bitbucket/status.html.haml | 167 +++---- app/views/import/bitbucket_server/new.html.haml | 6 +- app/views/import/bitbucket_server/status.html.haml | 165 +++---- app/views/import/fogbugz/status.html.haml | 99 +++-- app/views/import/gitlab/status.html.haml | 95 ++-- app/views/import/phabricator/new.html.haml | 6 +- app/views/layouts/_head.html.haml | 10 +- app/views/layouts/_page.html.haml | 4 +- app/views/layouts/_search.html.haml | 32 +- app/views/layouts/group.html.haml | 1 + .../header/_current_user_dropdown.html.haml | 4 +- app/views/layouts/header/_default.html.haml | 15 +- .../layouts/header/_logo_with_title.html.haml | 2 +- .../nav/breadcrumbs/_collapsed_dropdown.html.haml | 2 +- app/views/layouts/nav/sidebar/_group.html.haml | 4 +- app/views/layouts/nav/sidebar/_project.html.haml | 35 +- app/views/layouts/project.html.haml | 3 +- app/views/layouts/terms.html.haml | 4 +- .../notify/merged_merge_request_email.html.haml | 2 +- .../notify/merged_merge_request_email.text.haml | 2 +- app/views/notify/new_issue_email.html.haml | 2 +- app/views/notify/new_review_email.html.haml | 16 + app/views/notify/new_review_email.text.erb | 13 + app/views/notify/unknown_sign_in_email.html.haml | 66 ++- app/views/profiles/_event_table.html.haml | 2 +- app/views/profiles/accounts/show.html.haml | 8 +- app/views/profiles/active_sessions/index.html.haml | 2 +- app/views/profiles/audit_log.html.haml | 2 +- app/views/profiles/chat_names/index.html.haml | 2 +- app/views/profiles/emails/index.html.haml | 6 +- app/views/profiles/gpg_keys/index.html.haml | 4 +- app/views/profiles/keys/index.html.haml | 4 +- app/views/profiles/notifications/show.html.haml | 4 +- app/views/profiles/passwords/edit.html.haml | 4 +- .../personal_access_tokens/index.html.haml | 8 +- .../profiles/preferences/_sourcegraph.html.haml | 2 +- app/views/profiles/preferences/show.html.haml | 10 +- app/views/profiles/show.html.haml | 10 +- app/views/profiles/two_factor_auths/show.html.haml | 12 +- app/views/projects/_export.html.haml | 2 +- app/views/projects/_find_file_link.html.haml | 3 +- app/views/projects/_flash_messages.html.haml | 3 +- app/views/projects/_home_panel.html.haml | 10 +- app/views/projects/_import_project_pane.html.haml | 6 +- app/views/projects/_md_preview.html.haml | 36 -- .../_merge_request_merge_checks_settings.html.haml | 7 + ...ge_request_merge_suggestions_settings.html.haml | 4 +- app/views/projects/_new_project_fields.html.haml | 2 +- app/views/projects/_wiki.html.haml | 2 +- app/views/projects/_zen.html.haml | 19 - app/views/projects/blame/_blame_group.html.haml | 26 ++ app/views/projects/blame/show.html.haml | 47 +- app/views/projects/blob/_editor.html.haml | 2 +- app/views/projects/blob/_header_content.html.haml | 2 +- .../projects/blob/_markdown_buttons.html.haml | 13 - .../blob/viewers/_metrics_dashboard_yml.html.haml | 11 + .../_metrics_dashboard_yml_loading.html.haml | 4 + app/views/projects/blob/viewers/_readme.html.haml | 2 +- .../projects/blob/viewers/_route_map.html.haml | 2 +- .../blob/viewers/_route_map_loading.html.haml | 2 +- app/views/projects/branches/_branch.html.haml | 8 +- app/views/projects/branches/_panel.html.haml | 2 +- app/views/projects/branches/index.html.haml | 2 +- app/views/projects/buttons/_fork.html.haml | 2 +- app/views/projects/buttons/_star.html.haml | 4 +- app/views/projects/cleanup/_show.html.haml | 8 +- app/views/projects/commit/_commit_box.html.haml | 4 +- app/views/projects/commits/_commit.html.haml | 2 +- app/views/projects/diffs/_file.html.haml | 2 +- app/views/projects/diffs/_stats.html.haml | 4 +- app/views/projects/empty.html.haml | 6 +- app/views/projects/environments/_form.html.haml | 4 +- .../projects/environments/empty_metrics.html.haml | 2 +- app/views/projects/environments/index.html.haml | 2 +- app/views/projects/environments/metrics.html.haml | 2 +- app/views/projects/environments/show.html.haml | 4 +- app/views/projects/forks/_fork_button.html.haml | 2 +- app/views/projects/forks/new.html.haml | 4 +- app/views/projects/graphs/charts.html.haml | 2 +- app/views/projects/hook_logs/_index.html.haml | 4 +- app/views/projects/hook_logs/show.html.haml | 2 +- app/views/projects/hooks/edit.html.haml | 2 +- app/views/projects/import/jira/show.html.haml | 39 +- app/views/projects/issues/_issue.html.haml | 1 + .../projects/issues/_issue_estimate.html.haml | 7 + app/views/projects/issues/_new_branch.html.haml | 2 +- .../projects/issues/import_csv/_button.html.haml | 28 +- app/views/projects/issues/index.html.haml | 9 +- app/views/projects/issues/show.html.haml | 1 + app/views/projects/logs/empty_logs.html.haml | 2 +- app/views/projects/merge_requests/show.html.haml | 2 + app/views/projects/milestones/_form.html.haml | 4 +- app/views/projects/milestones/_milestone.html.haml | 1 - app/views/projects/new.html.haml | 14 +- .../projects/pipeline_schedules/_form.html.haml | 2 +- app/views/projects/pipelines/_with_tabs.html.haml | 12 +- app/views/projects/pipelines/charts.html.haml | 2 +- app/views/projects/pipelines/index.html.haml | 1 + .../_built_in_templates.html.haml | 2 +- .../projects/protected_branches/show.html.haml | 2 +- app/views/projects/protected_tags/show.html.haml | 2 +- .../projects/registry/repositories/_tag.html.haml | 33 -- .../projects/registry/repositories/index.html.haml | 3 +- app/views/projects/services/_form.html.haml | 3 +- app/views/projects/services/alerts/_help.html.haml | 5 +- .../projects/services/prometheus/_show.html.haml | 2 +- .../settings/access_tokens/index.html.haml | 2 +- app/views/projects/settings/ci_cd/_form.html.haml | 2 +- .../projects/settings/integrations/show.html.haml | 6 +- .../operations/_external_dashboard.html.haml | 3 - .../settings/operations/_incidents.html.haml | 2 +- .../operations/_metrics_dashboard.html.haml | 5 + .../projects/settings/operations/show.html.haml | 2 +- app/views/projects/snippets/_actions.html.haml | 2 +- app/views/projects/tags/_tag.html.haml | 6 +- app/views/projects/tags/new.html.haml | 4 +- app/views/projects/tags/releases/edit.html.haml | 4 +- app/views/projects/triggers/_index.html.haml | 2 +- app/views/projects/triggers/edit.html.haml | 2 +- app/views/projects/wikis/_form.html.haml | 72 --- app/views/projects/wikis/_main_links.html.haml | 9 - .../projects/wikis/_pages_wiki_page.html.haml | 6 - app/views/projects/wikis/_sidebar.html.haml | 22 - .../projects/wikis/_sidebar_wiki_page.html.haml | 3 - app/views/projects/wikis/_wiki_directory.html.haml | 4 - app/views/projects/wikis/_wiki_page.html.haml | 1 - app/views/projects/wikis/edit.html.haml | 31 -- app/views/projects/wikis/empty.html.haml | 4 - app/views/projects/wikis/git_access.html.haml | 10 +- app/views/projects/wikis/history.html.haml | 42 -- app/views/projects/wikis/pages.html.haml | 32 -- app/views/projects/wikis/show.html.haml | 32 -- .../registrations/experience_levels/show.html.haml | 28 ++ app/views/shared/_broadcast_message.html.haml | 4 +- app/views/shared/_choose_avatar_button.html.haml | 5 +- app/views/shared/_custom_attributes.html.haml | 12 + app/views/shared/_field.html.haml | 5 +- app/views/shared/_file_highlight.html.haml | 2 +- app/views/shared/_file_picker_button.html.haml | 6 + app/views/shared/_group_form.html.haml | 4 +- app/views/shared/_md_preview.html.haml | 36 ++ .../_namespace_storage_limit_alert.html.haml | 26 ++ .../shared/_new_merge_request_checkbox.html.haml | 2 +- app/views/shared/_promo.html.haml | 6 +- app/views/shared/_service_settings.html.haml | 10 +- app/views/shared/_visibility_level.html.haml | 2 +- app/views/shared/_visibility_radios.html.haml | 7 +- app/views/shared/_zen.html.haml | 19 + .../access_tokens/_created_container.html.haml | 2 +- app/views/shared/access_tokens/_form.html.haml | 2 +- app/views/shared/blob/_markdown_buttons.html.haml | 13 + app/views/shared/boards/_show.html.haml | 29 +- app/views/shared/deploy_keys/_form.html.haml | 2 +- app/views/shared/deploy_keys/_index.html.haml | 2 +- .../deploy_keys/_project_group_form.html.haml | 4 +- app/views/shared/deploy_tokens/_index.html.haml | 2 +- .../deploy_tokens/_new_deploy_token.html.haml | 2 +- app/views/shared/empty_states/_snippets.html.haml | 4 +- app/views/shared/empty_states/_wikis.html.haml | 19 +- app/views/shared/file_hooks/_index.html.haml | 2 +- .../shared/form_elements/_description.html.haml | 4 +- app/views/shared/groups/_group.html.haml | 37 +- app/views/shared/issuable/_form.html.haml | 2 +- app/views/shared/issuable/_search_bar.html.haml | 2 + app/views/shared/issuable/_sidebar.html.haml | 3 +- .../shared/issuable/_sidebar_assignees.html.haml | 15 +- app/views/shared/issuable/form/_metadata.html.haml | 8 +- .../milestones/_deprecation_message.html.haml | 4 +- app/views/shared/milestones/_form_dates.html.haml | 12 +- app/views/shared/milestones/_header.html.haml | 6 +- app/views/shared/milestones/_milestone.html.haml | 92 ++-- app/views/shared/milestones/_sidebar.html.haml | 56 +-- app/views/shared/milestones/_top.html.haml | 27 +- app/views/shared/notes/_edit_form.html.haml | 4 +- app/views/shared/notes/_form.html.haml | 4 +- .../notifications/_custom_notifications.html.haml | 4 +- .../shared/notifications/_new_button.html.haml | 2 +- app/views/shared/projects/_project.html.haml | 12 +- app/views/shared/snippets/_form.html.haml | 8 +- app/views/shared/snippets/_header.html.haml | 6 +- app/views/shared/tokens/_scopes_list.html.haml | 2 +- app/views/shared/web_hooks/_hook.html.haml | 4 +- .../shared/web_hooks/_title_and_docs.html.haml | 13 +- app/views/shared/wikis/_form.html.haml | 79 ++++ app/views/shared/wikis/_main_links.html.haml | 9 + app/views/shared/wikis/_pages_wiki_page.html.haml | 6 + app/views/shared/wikis/_sidebar.html.haml | 22 + .../shared/wikis/_sidebar_wiki_page.html.haml | 3 + app/views/shared/wikis/_wiki_directory.html.haml | 4 + app/views/shared/wikis/_wiki_page.html.haml | 1 + app/views/shared/wikis/edit.html.haml | 31 ++ app/views/shared/wikis/empty.html.haml | 4 + app/views/shared/wikis/history.html.haml | 41 ++ app/views/shared/wikis/pages.html.haml | 32 ++ app/views/shared/wikis/show.html.haml | 32 ++ app/views/snippets/_actions.html.haml | 2 +- app/views/u2f/_authenticate.html.haml | 19 +- app/views/u2f/_register.html.haml | 2 +- app/views/users/_deletion_guidance.html.haml | 2 +- app/views/users/terms/index.html.haml | 6 +- app/workers/all_queues.yml | 259 +++++++++++ app/workers/authorized_keys_worker.rb | 1 + .../user_refresh_with_low_urgency_worker.rb | 1 + app/workers/authorized_projects_worker.rb | 2 +- app/workers/background_migration_worker.rb | 1 + app/workers/build_finished_worker.rb | 1 + app/workers/ci/build_report_result_worker.rb | 16 + app/workers/cleanup_container_repository_worker.rb | 1 + app/workers/cluster_install_app_worker.rb | 1 + app/workers/cluster_patch_app_worker.rb | 1 + app/workers/cluster_update_app_worker.rb | 1 + app/workers/cluster_upgrade_app_worker.rb | 1 + .../cluster_wait_for_app_installation_worker.rb | 1 + app/workers/cluster_wait_for_app_update_worker.rb | 2 + .../cluster_wait_for_ingress_ip_address_worker.rb | 1 + .../applications/activate_service_worker.rb | 2 + .../applications/check_prometheus_health_worker.rb | 30 ++ .../applications/deactivate_service_worker.rb | 2 + .../clusters/applications/uninstall_worker.rb | 1 + .../applications/wait_for_uninstall_app_worker.rb | 1 + app/workers/concerns/application_worker.rb | 27 +- app/workers/concerns/gitlab/github_import/queue.rb | 11 + .../concerns/gitlab/jira_import/import_worker.rb | 2 +- app/workers/concerns/project_import_options.rb | 2 +- app/workers/concerns/reactive_cacheable_worker.rb | 1 + app/workers/concerns/worker_attributes.rb | 22 + app/workers/container_expiration_policy_worker.rb | 2 + app/workers/create_commit_signature_worker.rb | 4 +- app/workers/create_evidence_worker.rb | 9 +- app/workers/create_pipeline_worker.rb | 1 + app/workers/delete_stored_files_worker.rb | 1 + app/workers/delete_user_worker.rb | 3 +- app/workers/email_receiver_worker.rb | 2 +- .../expire_build_instance_artifacts_worker.rb | 2 +- app/workers/export_csv_worker.rb | 1 + app/workers/file_hook_worker.rb | 1 + app/workers/git_garbage_collect_worker.rb | 1 + .../gitlab/github_import/advance_stage_worker.rb | 1 + app/workers/gitlab/import/stuck_import_job.rb | 82 ++++ .../import/stuck_project_import_jobs_worker.rb | 22 + .../gitlab/jira_import/import_issue_worker.rb | 6 +- .../jira_import/stage/start_import_worker.rb | 1 - .../jira_import/stuck_jira_import_jobs_worker.rb | 21 + .../gitlab/phabricator_import/base_worker.rb | 2 +- app/workers/gitlab_shell_worker.rb | 1 + app/workers/group_export_worker.rb | 1 + app/workers/group_import_worker.rb | 9 +- .../hashed_storage/project_migrate_worker.rb | 1 + .../hashed_storage/project_rollback_worker.rb | 1 + .../process_prometheus_alert_worker.rb | 16 +- app/workers/irker_worker.rb | 117 ++--- .../mail_scheduler/notification_service_worker.rb | 1 + app/workers/merge_worker.rb | 1 + .../dashboard/prune_old_annotations_worker.rb | 23 + .../dashboard/schedule_annotations_prune_worker.rb | 23 + app/workers/new_note_worker.rb | 9 +- .../object_storage/background_move_worker.rb | 1 + .../object_storage/migrate_uploads_worker.rb | 1 + app/workers/pages_worker.rb | 1 + .../personal_access_tokens/expiring_worker.rb | 4 +- app/workers/pipeline_notification_worker.rb | 5 +- app/workers/pipeline_process_worker.rb | 1 + .../pipeline_update_ci_ref_status_worker.rb | 1 + app/workers/post_receive.rb | 1 + app/workers/process_commit_worker.rb | 2 +- app/workers/project_cache_worker.rb | 4 +- app/workers/project_export_worker.rb | 1 + app/workers/propagate_integration_worker.rb | 16 + app/workers/rebase_worker.rb | 1 + app/workers/remove_expired_group_links_worker.rb | 6 +- app/workers/repository_check/batch_worker.rb | 2 + app/workers/repository_import_worker.rb | 7 +- app/workers/repository_remove_remote_worker.rb | 1 + .../repository_update_remote_mirror_worker.rb | 1 + app/workers/stuck_import_jobs_worker.rb | 70 +-- app/workers/todos_destroyer/entity_leave_worker.rb | 2 + .../update_external_pull_requests_worker.rb | 1 + app/workers/update_merge_requests_worker.rb | 1 + app/workers/web_hook_worker.rb | 1 + 1492 files changed, 28066 insertions(+), 10617 deletions(-) create mode 100644 app/assets/images/aws_logo.svg create mode 100644 app/assets/images/experienced.svg create mode 100644 app/assets/images/learn-gitlab-avatar.jpg create mode 100644 app/assets/images/novice.svg create mode 100644 app/assets/javascripts/alert_management/components/alert_sidebar.vue create mode 100644 app/assets/javascripts/alert_management/components/sidebar/sidebar_assignee.vue create mode 100644 app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue create mode 100644 app/assets/javascripts/alert_management/components/sidebar/sidebar_header.vue create mode 100644 app/assets/javascripts/alert_management/components/sidebar/sidebar_status.vue create mode 100644 app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue create mode 100644 app/assets/javascripts/alert_management/components/system_notes/system_note.vue create mode 100644 app/assets/javascripts/alert_management/graphql/fragments/alert_note.fragment.graphql delete mode 100644 app/assets/javascripts/alert_management/graphql/fragments/detailItem.fragment.graphql create mode 100644 app/assets/javascripts/alert_management/graphql/fragments/detail_item.fragment.graphql delete mode 100644 app/assets/javascripts/alert_management/graphql/fragments/listItem.fragment.graphql create mode 100644 app/assets/javascripts/alert_management/graphql/fragments/list_item.fragment.graphql create mode 100644 app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.graphql create mode 100644 app/assets/javascripts/alert_management/graphql/mutations/create_issue_from_alert.graphql delete mode 100644 app/assets/javascripts/alert_management/graphql/queries/getAlerts.query.graphql create mode 100644 app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql create mode 100644 app/assets/javascripts/alert_management/graphql/queries/get_count_by_status.query.graphql delete mode 100644 app/assets/javascripts/alert_management/services/index.js create mode 100644 app/assets/javascripts/authentication/mount_2fa.js create mode 100644 app/assets/javascripts/authentication/u2f/authenticate.js create mode 100644 app/assets/javascripts/authentication/u2f/error.js create mode 100644 app/assets/javascripts/authentication/u2f/index.js create mode 100644 app/assets/javascripts/authentication/u2f/register.js create mode 100644 app/assets/javascripts/authentication/u2f/util.js delete mode 100644 app/assets/javascripts/avatar_picker.js create mode 100644 app/assets/javascripts/batch_comments/components/diff_file_drafts.vue create mode 100644 app/assets/javascripts/batch_comments/components/draft_note.vue create mode 100644 app/assets/javascripts/batch_comments/components/drafts_count.vue create mode 100644 app/assets/javascripts/batch_comments/components/inline_draft_comment_row.vue create mode 100644 app/assets/javascripts/batch_comments/components/parallel_draft_comment_row.vue create mode 100644 app/assets/javascripts/batch_comments/components/preview_dropdown.vue create mode 100644 app/assets/javascripts/batch_comments/components/preview_item.vue create mode 100644 app/assets/javascripts/batch_comments/components/publish_button.vue create mode 100644 app/assets/javascripts/batch_comments/components/review_bar.vue create mode 100644 app/assets/javascripts/batch_comments/constants.js create mode 100644 app/assets/javascripts/batch_comments/index.js create mode 100644 app/assets/javascripts/batch_comments/services/drafts_service.js create mode 100644 app/assets/javascripts/batch_comments/stores/index.js create mode 100644 app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js create mode 100644 app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js create mode 100644 app/assets/javascripts/batch_comments/stores/modules/batch_comments/index.js create mode 100644 app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutation_types.js create mode 100644 app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutations.js create mode 100644 app/assets/javascripts/batch_comments/stores/modules/batch_comments/state.js create mode 100644 app/assets/javascripts/batch_comments/utils.js create mode 100644 app/assets/javascripts/boards/components/board_content.vue create mode 100644 app/assets/javascripts/boards/components/board_list_header.vue create mode 100644 app/assets/javascripts/boards/toggle_epics_swimlanes.js create mode 100644 app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue create mode 100644 app/assets/javascripts/code_navigation/components/doc_line.vue create mode 100644 app/assets/javascripts/design_management/components/design_notes/toggle_replies_widget.vue create mode 100644 app/assets/javascripts/design_management/components/design_sidebar.vue create mode 100644 app/assets/javascripts/design_management/graphql/fragments/discussion_resolved_status.fragment.graphql create mode 100644 app/assets/javascripts/design_management/graphql/mutations/toggle_resolve_discussion.mutation.graphql create mode 100644 app/assets/javascripts/diffs/utils/uuids.js create mode 100644 app/assets/javascripts/file_pickers.js create mode 100644 app/assets/javascripts/global_search_input.js create mode 100644 app/assets/javascripts/ide/commit_icon.js create mode 100644 app/assets/javascripts/ide/components/ide_sidebar_nav.vue create mode 100644 app/assets/javascripts/ide/components/terminal/empty_state.vue create mode 100644 app/assets/javascripts/ide/components/terminal/session.vue create mode 100644 app/assets/javascripts/ide/components/terminal/terminal.vue create mode 100644 app/assets/javascripts/ide/components/terminal/terminal_controls.vue create mode 100644 app/assets/javascripts/ide/components/terminal/view.vue create mode 100644 app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue create mode 100644 app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status_safe.vue create mode 100644 app/assets/javascripts/ide/lib/create_diff.js create mode 100644 app/assets/javascripts/ide/lib/create_file_diff.js create mode 100644 app/assets/javascripts/ide/lib/editorconfig/parser.js create mode 100644 app/assets/javascripts/ide/lib/editorconfig/rules_mapper.js create mode 100644 app/assets/javascripts/ide/lib/languages/README.md create mode 100644 app/assets/javascripts/ide/lib/mirror.js create mode 100644 app/assets/javascripts/ide/services/terminals.js create mode 100644 app/assets/javascripts/ide/stores/extend.js create mode 100644 app/assets/javascripts/ide/stores/modules/router/actions.js create mode 100644 app/assets/javascripts/ide/stores/modules/router/index.js create mode 100644 app/assets/javascripts/ide/stores/modules/router/mutation_types.js create mode 100644 app/assets/javascripts/ide/stores/modules/router/mutations.js create mode 100644 app/assets/javascripts/ide/stores/modules/router/state.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/actions/index.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/actions/setup.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/constants.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/getters.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/index.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/messages.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/mutation_types.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/mutations.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/state.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal/utils.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal_sync/index.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal_sync/messages.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal_sync/mutation_types.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal_sync/mutations.js create mode 100644 app/assets/javascripts/ide/stores/modules/terminal_sync/state.js create mode 100644 app/assets/javascripts/ide/stores/plugins/terminal.js create mode 100644 app/assets/javascripts/ide/stores/plugins/terminal_sync.js create mode 100644 app/assets/javascripts/ide/sync_router_and_store.js create mode 100644 app/assets/javascripts/import_projects/components/bitbucket_status_table.vue create mode 100644 app/assets/javascripts/import_projects/components/incompatible_repo_table_row.vue create mode 100644 app/assets/javascripts/integrations/edit/components/dynamic_field.vue create mode 100644 app/assets/javascripts/issue_show/constants.js delete mode 100644 app/assets/javascripts/jira_import/utils.js create mode 100644 app/assets/javascripts/jira_import/utils/cache_update.js create mode 100644 app/assets/javascripts/jira_import/utils/jira_import_utils.js create mode 100644 app/assets/javascripts/logs/logs_tracking_helper.js create mode 100644 app/assets/javascripts/monitoring/components/dashboard_header.vue create mode 100644 app/assets/javascripts/monitoring/components/links_section.vue create mode 100644 app/assets/javascripts/monitoring/format_date.js create mode 100644 app/assets/javascripts/monitoring/monitoring_app.js delete mode 100644 app/assets/javascripts/monitoring/monitoring_bundle.js delete mode 100644 app/assets/javascripts/monitoring/monitoring_bundle_with_alerts.js create mode 100644 app/assets/javascripts/monitoring/pages/dashboard_page.vue create mode 100644 app/assets/javascripts/monitoring/router/constants.js create mode 100644 app/assets/javascripts/monitoring/router/index.js create mode 100644 app/assets/javascripts/monitoring/router/routes.js create mode 100644 app/assets/javascripts/namespace_storage_limit_alert.js create mode 100644 app/assets/javascripts/notes/components/multiline_comment_form.vue create mode 100644 app/assets/javascripts/notes/components/multiline_comment_utils.js delete mode 100644 app/assets/javascripts/notes/mixins/draft.js delete mode 100644 app/assets/javascripts/notes/mixins/get_discussion.js delete mode 100644 app/assets/javascripts/notes/mixins/note_form.js create mode 100644 app/assets/javascripts/onboarding_issues/index.js delete mode 100644 app/assets/javascripts/operation_settings/components/external_dashboard.vue create mode 100644 app/assets/javascripts/operation_settings/components/form_group/dashboard_timezone.vue create mode 100644 app/assets/javascripts/operation_settings/components/form_group/external_dashboard.vue create mode 100644 app/assets/javascripts/operation_settings/components/metrics_settings.vue create mode 100644 app/assets/javascripts/pages/groups/clusters/index.js delete mode 100644 app/assets/javascripts/pages/groups/index.js create mode 100644 app/assets/javascripts/pages/import/bitbucket/status/index.js create mode 100644 app/assets/javascripts/pages/import/bitbucket_server/status/components/bitbucket_server_status_table.vue create mode 100644 app/assets/javascripts/pages/import/bitbucket_server/status/index.js create mode 100644 app/assets/javascripts/pages/import/fogbugz/status/index.js create mode 100644 app/assets/javascripts/pages/import/gitlab/status/index.js create mode 100644 app/assets/javascripts/pages/projects/clusters/index.js create mode 100644 app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue delete mode 100644 app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue delete mode 100644 app/assets/javascripts/pages/projects/wikis/wikis.js create mode 100644 app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue create mode 100644 app/assets/javascripts/pages/shared/wikis/index.js create mode 100644 app/assets/javascripts/pages/shared/wikis/wikis.js create mode 100644 app/assets/javascripts/persistent_user_callouts.js create mode 100644 app/assets/javascripts/pipelines/components/dag/constants.js create mode 100644 app/assets/javascripts/pipelines/components/dag/dag.vue create mode 100644 app/assets/javascripts/pipelines/components/dag/dag_graph.vue create mode 100644 app/assets/javascripts/pipelines/components/dag/drawing_utils.js create mode 100644 app/assets/javascripts/pipelines/components/dag/interactions.js create mode 100644 app/assets/javascripts/pipelines/components/dag/parsing_utils.js create mode 100644 app/assets/javascripts/pipelines/components/tokens/pipeline_status_token.vue create mode 100644 app/assets/javascripts/pipelines/components/tokens/pipeline_tag_name_token.vue create mode 100644 app/assets/javascripts/pipelines/utils.js create mode 100644 app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue create mode 100644 app/assets/javascripts/projects/experiment_new_project_creation/components/legacy_container.vue create mode 100644 app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue create mode 100644 app/assets/javascripts/projects/experiment_new_project_creation/illustrations/blank-project.svg create mode 100644 app/assets/javascripts/projects/experiment_new_project_creation/illustrations/ci-cd-project.svg create mode 100644 app/assets/javascripts/projects/experiment_new_project_creation/illustrations/create-from-template.svg create mode 100644 app/assets/javascripts/projects/experiment_new_project_creation/illustrations/import-project.svg create mode 100644 app/assets/javascripts/projects/experiment_new_project_creation/index.js create mode 100644 app/assets/javascripts/registry/explorer/components/details_page/delete_alert.vue create mode 100644 app/assets/javascripts/registry/explorer/components/details_page/delete_modal.vue create mode 100644 app/assets/javascripts/registry/explorer/components/details_page/details_header.vue create mode 100644 app/assets/javascripts/registry/explorer/components/details_page/empty_tags_state.vue create mode 100644 app/assets/javascripts/registry/explorer/components/details_page/tags_loader.vue create mode 100644 app/assets/javascripts/registry/explorer/components/details_page/tags_table.vue delete mode 100644 app/assets/javascripts/registry/explorer/components/group_empty_state.vue delete mode 100644 app/assets/javascripts/registry/explorer/components/image_list.vue create mode 100644 app/assets/javascripts/registry/explorer/components/list_page/cli_commands.vue create mode 100644 app/assets/javascripts/registry/explorer/components/list_page/group_empty_state.vue create mode 100644 app/assets/javascripts/registry/explorer/components/list_page/image_list.vue create mode 100644 app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue create mode 100644 app/assets/javascripts/registry/explorer/components/list_page/project_empty_state.vue create mode 100644 app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue delete mode 100644 app/assets/javascripts/registry/explorer/components/project_empty_state.vue delete mode 100644 app/assets/javascripts/registry/explorer/components/project_policy_alert.vue delete mode 100644 app/assets/javascripts/registry/explorer/components/quickstart_dropdown.vue delete mode 100644 app/assets/javascripts/registry/explorer/constants.js create mode 100644 app/assets/javascripts/registry/explorer/constants/details.js create mode 100644 app/assets/javascripts/registry/explorer/constants/expiration_policies.js create mode 100644 app/assets/javascripts/registry/explorer/constants/index.js create mode 100644 app/assets/javascripts/registry/explorer/constants/list.js create mode 100644 app/assets/javascripts/registry/explorer/constants/quick_start.js delete mode 100644 app/assets/javascripts/search_autocomplete.js delete mode 100644 app/assets/javascripts/shared/sessions/u2f.js create mode 100644 app/assets/javascripts/static_site_editor/components/unsaved_changes_confirm_dialog.vue create mode 100644 app/assets/javascripts/static_site_editor/services/parse_source_file.js delete mode 100644 app/assets/javascripts/u2f/authenticate.js delete mode 100644 app/assets/javascripts/u2f/error.js delete mode 100644 app/assets/javascripts/u2f/register.js delete mode 100644 app/assets/javascripts/u2f/util.js create mode 100644 app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js create mode 100644 app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue create mode 100644 app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue create mode 100644 app/assets/javascripts/vue_shared/components/rich_content_editor/editor_service.js create mode 100644 app/assets/javascripts/vue_shared/components/rich_content_editor/modals/add_image_modal.vue delete mode 100644 app/assets/javascripts/vue_shared/components/rich_content_editor/toolbar_service.js create mode 100644 app/assets/javascripts/vue_shared/components/url_sync.vue create mode 100644 app/assets/stylesheets/application_dark.scss create mode 100644 app/assets/stylesheets/page_bundles/ide_themes/_solarized-dark.scss create mode 100644 app/assets/stylesheets/pages/experience_level.scss create mode 100644 app/assets/stylesheets/pages/storage_quota.scss create mode 100644 app/assets/stylesheets/themes/_dark.scss create mode 100644 app/channels/application_cable/logging.rb create mode 100644 app/controllers/concerns/find_snippet.rb create mode 100644 app/controllers/concerns/snippet_authorizations.rb create mode 100644 app/controllers/concerns/wiki_actions.rb create mode 100644 app/controllers/concerns/workhorse_import_export_upload.rb create mode 100644 app/controllers/groups/imports_controller.rb create mode 100644 app/controllers/import/gitlab_groups_controller.rb create mode 100644 app/controllers/projects/merge_requests/drafts_controller.rb create mode 100644 app/controllers/projects/snippets/application_controller.rb create mode 100644 app/controllers/projects/web_ide_terminals_controller.rb create mode 100644 app/controllers/registrations/experience_levels_controller.rb create mode 100644 app/controllers/snippets/application_controller.rb delete mode 100644 app/finders/admin/runners_finder.rb create mode 100644 app/finders/ci/runners_finder.rb delete mode 100644 app/finders/resource_label_event_finder.rb create mode 100644 app/finders/resource_milestone_event_finder.rb create mode 100644 app/finders/uploader_finder.rb create mode 100644 app/graphql/mutations/alert_management/alerts/set_assignees.rb create mode 100644 app/graphql/mutations/commits/create.rb delete mode 100644 app/graphql/mutations/concerns/mutations/resolves_project.rb create mode 100644 app/graphql/mutations/container_expiration_policies/update.rb create mode 100644 app/graphql/mutations/discussions/toggle_resolve.rb create mode 100644 app/graphql/mutations/jira_import/import_users.rb create mode 100644 app/graphql/mutations/merge_requests/create.rb create mode 100644 app/graphql/mutations/metrics/dashboard/annotations/base.rb create mode 100644 app/graphql/mutations/metrics/dashboard/annotations/delete.rb create mode 100644 app/graphql/resolvers/alert_management/alert_resolver.rb delete mode 100644 app/graphql/resolvers/alert_management_alert_resolver.rb create mode 100644 app/graphql/resolvers/assigned_merge_requests_resolver.rb create mode 100644 app/graphql/resolvers/authored_merge_requests_resolver.rb create mode 100644 app/graphql/resolvers/concerns/looks_ahead.rb create mode 100644 app/graphql/resolvers/concerns/resolves_merge_requests.rb create mode 100644 app/graphql/resolvers/concerns/resolves_project.rb create mode 100644 app/graphql/resolvers/merge_request_resolver.rb create mode 100644 app/graphql/resolvers/project_members_resolver.rb create mode 100644 app/graphql/resolvers/project_pipeline_resolver.rb create mode 100644 app/graphql/resolvers/projects/jira_projects_resolver.rb create mode 100644 app/graphql/resolvers/user_merge_requests_resolver.rb create mode 100644 app/graphql/resolvers/user_resolver.rb create mode 100644 app/graphql/resolvers/users_resolver.rb create mode 100644 app/graphql/types/access_level_enum.rb create mode 100644 app/graphql/types/access_level_type.rb create mode 100644 app/graphql/types/commit_action_mode_enum.rb create mode 100644 app/graphql/types/commit_action_type.rb create mode 100644 app/graphql/types/commit_encoding_enum.rb create mode 100644 app/graphql/types/container_expiration_policy_cadence_enum.rb create mode 100644 app/graphql/types/container_expiration_policy_keep_enum.rb create mode 100644 app/graphql/types/container_expiration_policy_older_than_enum.rb create mode 100644 app/graphql/types/container_expiration_policy_type.rb create mode 100644 app/graphql/types/evidence_type.rb create mode 100644 app/graphql/types/group_member_type.rb create mode 100644 app/graphql/types/jira_user_type.rb create mode 100644 app/graphql/types/member_interface.rb create mode 100644 app/graphql/types/project_member_type.rb create mode 100644 app/graphql/types/projects/services/jira_project_type.rb create mode 100644 app/graphql/types/release_assets_type.rb create mode 100644 app/graphql/types/release_link_type.rb create mode 100644 app/graphql/types/release_link_type_enum.rb create mode 100644 app/graphql/types/release_source_type.rb create mode 100644 app/graphql/types/resolvable_interface.rb create mode 100644 app/graphql/types/snippets/file_input_action_enum.rb create mode 100644 app/graphql/types/snippets/file_input_type.rb create mode 100644 app/graphql/types/user_state_enum.rb delete mode 100644 app/helpers/milestones_helper.rb delete mode 100644 app/helpers/milestones_routing_helper.rb create mode 100644 app/helpers/subscribable_banner_helper.rb create mode 100644 app/helpers/timeboxes_helper.rb create mode 100644 app/helpers/timeboxes_routing_helper.rb create mode 100644 app/mailers/emails/reviews.rb create mode 100644 app/models/alert_management.rb create mode 100644 app/models/alert_management/alert_assignee.rb create mode 100644 app/models/alert_management/alert_user_mention.rb create mode 100644 app/models/blob_viewer/go_mod.rb create mode 100644 app/models/blob_viewer/metrics_dashboard_yml.rb create mode 100644 app/models/ci/build_report_result.rb create mode 100644 app/models/concerns/featurable.rb create mode 100644 app/models/concerns/integration.rb delete mode 100644 app/models/dashboard_group_milestone.rb delete mode 100644 app/models/dashboard_milestone.rb create mode 100644 app/models/data_list.rb create mode 100644 app/models/draft_note.rb delete mode 100644 app/models/global_milestone.rb create mode 100644 app/models/group_deploy_key.rb delete mode 100644 app/models/group_milestone.rb create mode 100644 app/models/project_services/chat_message/alert_message.rb create mode 100644 app/models/review.rb create mode 100644 app/models/service_list.rb create mode 100644 app/models/snippet_input_action.rb create mode 100644 app/models/snippet_input_action_collection.rb create mode 100644 app/models/web_ide_terminal.rb create mode 100644 app/policies/container_expiration_policy_policy.rb create mode 100644 app/policies/draft_note_policy.rb create mode 100644 app/policies/releases/link_policy.rb create mode 100644 app/policies/releases/source_policy.rb create mode 100644 app/presenters/gitlab/blame_presenter.rb create mode 100644 app/serializers/ci/daily_build_group_report_result_entity.rb create mode 100644 app/serializers/ci/daily_build_group_report_result_serializer.rb create mode 100644 app/serializers/draft_note_entity.rb create mode 100644 app/serializers/draft_note_serializer.rb create mode 100644 app/serializers/import/base_provider_repo_entity.rb create mode 100644 app/serializers/import/bitbucket_provider_repo_entity.rb create mode 100644 app/serializers/import/bitbucket_server_provider_repo_entity.rb create mode 100644 app/serializers/import/fogbugz_provider_repo_entity.rb create mode 100644 app/serializers/import/githubish_provider_repo_entity.rb create mode 100644 app/serializers/import/gitlab_provider_repo_entity.rb create mode 100644 app/serializers/import/provider_repo_serializer.rb delete mode 100644 app/serializers/provider_repo_entity.rb delete mode 100644 app/serializers/provider_repo_serializer.rb create mode 100644 app/serializers/service_field_entity.rb create mode 100644 app/serializers/service_field_serializer.rb create mode 100644 app/serializers/web_ide_terminal_entity.rb create mode 100644 app/serializers/web_ide_terminal_serializer.rb create mode 100644 app/services/admin/propagate_integration_service.rb create mode 100644 app/services/alert_management/alerts/update_service.rb create mode 100644 app/services/ci/authorize_job_artifact_service.rb create mode 100644 app/services/ci/build_report_result_service.rb create mode 100644 app/services/ci/create_web_ide_terminal_service.rb create mode 100644 app/services/ci/web_ide_config_service.rb create mode 100644 app/services/concerns/integrations/project_test_data.rb create mode 100644 app/services/container_expiration_policies/update_service.rb create mode 100644 app/services/draft_notes/base_service.rb create mode 100644 app/services/draft_notes/create_service.rb create mode 100644 app/services/draft_notes/destroy_service.rb create mode 100644 app/services/draft_notes/publish_service.rb create mode 100644 app/services/integrations/test/base_service.rb create mode 100644 app/services/integrations/test/project_service.rb create mode 100644 app/services/jira/requests/base.rb create mode 100644 app/services/jira/requests/projects.rb create mode 100644 app/services/jira_import/users_importer.rb create mode 100644 app/services/jira_import/users_mapper.rb create mode 100644 app/services/notification_recipients/builder/new_review.rb create mode 100644 app/services/projects/group_links/update_service.rb delete mode 100644 app/services/projects/lsif_data_service.rb create mode 100644 app/services/releases/create_evidence_service.rb create mode 100644 app/services/resource_events/change_state_service.rb create mode 100644 app/services/resource_events/synthetic_state_notes_builder_service.rb create mode 100644 app/validators/json_schema_validator.rb create mode 100644 app/validators/json_schemas/build_report_result_data.json create mode 100644 app/validators/json_schemas/build_report_result_data_tests.json create mode 100644 app/validators/json_schemas/daily_build_group_report_result_data.json create mode 100644 app/views/admin/application_settings/ci/_header.html.haml delete mode 100644 app/views/admin/sessions/_two_factor_u2f.html.haml create mode 100644 app/views/admin/users/_admin_notes.html.haml create mode 100644 app/views/admin/users/_user_detail_note.html.haml create mode 100644 app/views/admin/users/_user_listing_note.html.haml delete mode 100644 app/views/dashboard/milestones/show.html.haml create mode 100644 app/views/groups/_import_group_pane.html.haml create mode 100644 app/views/groups/_new_group_fields.html.haml create mode 100644 app/views/groups/imports/show.html.haml create mode 100644 app/views/notify/new_review_email.html.haml create mode 100644 app/views/notify/new_review_email.text.erb delete mode 100644 app/views/projects/_md_preview.html.haml delete mode 100644 app/views/projects/_zen.html.haml create mode 100644 app/views/projects/blame/_blame_group.html.haml delete mode 100644 app/views/projects/blob/_markdown_buttons.html.haml create mode 100644 app/views/projects/blob/viewers/_metrics_dashboard_yml.html.haml create mode 100644 app/views/projects/blob/viewers/_metrics_dashboard_yml_loading.html.haml create mode 100644 app/views/projects/issues/_issue_estimate.html.haml delete mode 100644 app/views/projects/registry/repositories/_tag.html.haml delete mode 100644 app/views/projects/settings/operations/_external_dashboard.html.haml create mode 100644 app/views/projects/settings/operations/_metrics_dashboard.html.haml delete mode 100644 app/views/projects/wikis/_form.html.haml delete mode 100644 app/views/projects/wikis/_main_links.html.haml delete mode 100644 app/views/projects/wikis/_pages_wiki_page.html.haml delete mode 100644 app/views/projects/wikis/_sidebar.html.haml delete mode 100644 app/views/projects/wikis/_sidebar_wiki_page.html.haml delete mode 100644 app/views/projects/wikis/_wiki_directory.html.haml delete mode 100644 app/views/projects/wikis/_wiki_page.html.haml delete mode 100644 app/views/projects/wikis/edit.html.haml delete mode 100644 app/views/projects/wikis/empty.html.haml delete mode 100644 app/views/projects/wikis/history.html.haml delete mode 100644 app/views/projects/wikis/pages.html.haml delete mode 100644 app/views/projects/wikis/show.html.haml create mode 100644 app/views/registrations/experience_levels/show.html.haml create mode 100644 app/views/shared/_custom_attributes.html.haml create mode 100644 app/views/shared/_file_picker_button.html.haml create mode 100644 app/views/shared/_md_preview.html.haml create mode 100644 app/views/shared/_namespace_storage_limit_alert.html.haml create mode 100644 app/views/shared/_zen.html.haml create mode 100644 app/views/shared/blob/_markdown_buttons.html.haml create mode 100644 app/views/shared/wikis/_form.html.haml create mode 100644 app/views/shared/wikis/_main_links.html.haml create mode 100644 app/views/shared/wikis/_pages_wiki_page.html.haml create mode 100644 app/views/shared/wikis/_sidebar.html.haml create mode 100644 app/views/shared/wikis/_sidebar_wiki_page.html.haml create mode 100644 app/views/shared/wikis/_wiki_directory.html.haml create mode 100644 app/views/shared/wikis/_wiki_page.html.haml create mode 100644 app/views/shared/wikis/edit.html.haml create mode 100644 app/views/shared/wikis/empty.html.haml create mode 100644 app/views/shared/wikis/history.html.haml create mode 100644 app/views/shared/wikis/pages.html.haml create mode 100644 app/views/shared/wikis/show.html.haml create mode 100644 app/workers/ci/build_report_result_worker.rb create mode 100644 app/workers/clusters/applications/check_prometheus_health_worker.rb create mode 100644 app/workers/gitlab/import/stuck_import_job.rb create mode 100644 app/workers/gitlab/import/stuck_project_import_jobs_worker.rb create mode 100644 app/workers/gitlab/jira_import/stuck_jira_import_jobs_worker.rb create mode 100644 app/workers/metrics/dashboard/prune_old_annotations_worker.rb create mode 100644 app/workers/metrics/dashboard/schedule_annotations_prune_worker.rb create mode 100644 app/workers/propagate_integration_worker.rb (limited to 'app') diff --git a/app/assets/images/aws_logo.svg b/app/assets/images/aws_logo.svg new file mode 100644 index 00000000000..e028fd1b1c0 --- /dev/null +++ b/app/assets/images/aws_logo.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + diff --git a/app/assets/images/experienced.svg b/app/assets/images/experienced.svg new file mode 100644 index 00000000000..1c93cfcf1ee --- /dev/null +++ b/app/assets/images/experienced.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/learn-gitlab-avatar.jpg b/app/assets/images/learn-gitlab-avatar.jpg new file mode 100644 index 00000000000..65ec29444cb Binary files /dev/null and b/app/assets/images/learn-gitlab-avatar.jpg differ diff --git a/app/assets/images/novice.svg b/app/assets/images/novice.svg new file mode 100644 index 00000000000..c6744fa4550 --- /dev/null +++ b/app/assets/images/novice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/javascripts/alert_management/components/alert_details.vue b/app/assets/javascripts/alert_management/components/alert_details.vue index 89db7db77d5..ed6b4b7fdb2 100644 --- a/app/assets/javascripts/alert_management/components/alert_details.vue +++ b/app/assets/javascripts/alert_management/components/alert_details.vue @@ -2,31 +2,32 @@ import * as Sentry from '@sentry/browser'; import { GlAlert, + GlBadge, GlIcon, GlLoadingIcon, - GlDropdown, - GlDropdownItem, GlSprintf, GlTabs, GlTab, GlButton, GlTable, } from '@gitlab/ui'; -import createFlash from '~/flash'; import { s__ } from '~/locale'; import query from '../graphql/queries/details.query.graphql'; import { fetchPolicies } from '~/lib/graphql'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; -import { ALERTS_SEVERITY_LABELS } from '../constants'; -import updateAlertStatus from '../graphql/mutations/update_alert_status.graphql'; +import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user'; +import initUserPopovers from '~/user_popovers'; +import { ALERTS_SEVERITY_LABELS, trackAlertsDetailsViewsOptions } from '../constants'; +import createIssueQuery from '../graphql/mutations/create_issue_from_alert.graphql'; +import { visitUrl, joinPaths } from '~/lib/utils/url_utility'; +import Tracking from '~/tracking'; +import { toggleContainerClasses } from '~/lib/utils/dom_utils'; +import SystemNote from './system_notes/system_note.vue'; +import AlertSidebar from './alert_sidebar.vue'; + +const containerEl = document.querySelector('.page-with-contextual-sidebar'); export default { - statuses: { - TRIGGERED: s__('AlertManagement|Triggered'), - ACKNOWLEDGED: s__('AlertManagement|Acknowledged'), - RESOLVED: s__('AlertManagement|Resolved'), - }, i18n: { errorMsg: s__( 'AlertManagement|There was an error displaying the alert. Please refresh the page to try again.', @@ -38,19 +39,19 @@ export default { }, severityLabels: ALERTS_SEVERITY_LABELS, components: { + GlBadge, GlAlert, GlIcon, GlLoadingIcon, GlSprintf, - GlDropdown, - GlDropdownItem, GlTab, GlTabs, GlButton, GlTable, TimeAgoTooltip, + AlertSidebar, + SystemNote, }, - mixins: [glFeatureFlagsMixin()], props: { alertId: { type: String, @@ -60,7 +61,7 @@ export default { type: String, required: true, }, - newIssuePath: { + projectIssuesPath: { type: String, required: true, }, @@ -85,7 +86,15 @@ export default { }, }, data() { - return { alert: null, errored: false, isErrorDismissed: false }; + return { + alert: null, + errored: false, + isErrorDismissed: false, + createIssueError: '', + issueCreationInProgress: false, + sidebarCollapsed: false, + sidebarErrorMessage: '', + }; }, computed: { loading() { @@ -100,38 +109,92 @@ export default { return this.errored && !this.isErrorDismissed; }, }, + mounted() { + this.trackPageViews(); + toggleContainerClasses(containerEl, { + 'issuable-bulk-update-sidebar': true, + 'right-sidebar-expanded': true, + }); + }, + updated() { + this.$nextTick(() => { + highlightCurrentUser(this.$el.querySelectorAll('.gfm-project_member')); + initUserPopovers(this.$el.querySelectorAll('.js-user-link')); + }); + }, methods: { dismissError() { this.isErrorDismissed = true; + this.sidebarErrorMessage = ''; }, - updateAlertStatus(status) { + toggleSidebar() { + this.sidebarCollapsed = !this.sidebarCollapsed; + toggleContainerClasses(containerEl, { + 'right-sidebar-collapsed': this.sidebarCollapsed, + 'right-sidebar-expanded': !this.sidebarCollapsed, + }); + }, + handleAlertSidebarError(errorMessage) { + this.errored = true; + this.sidebarErrorMessage = errorMessage; + }, + createIssue() { + this.issueCreationInProgress = true; + this.$apollo .mutate({ - mutation: updateAlertStatus, + mutation: createIssueQuery, variables: { - iid: this.alertId, - status: status.toUpperCase(), + iid: this.alert.iid, projectPath: this.projectPath, }, }) - .catch(() => { - createFlash( - s__( - 'AlertManagement|There was an error while updating the status of the alert. Please try again.', - ), - ); + .then(({ data: { createAlertIssue: { errors, issue } } }) => { + if (errors?.length) { + [this.createIssueError] = errors; + this.issueCreationInProgress = false; + } else if (issue) { + visitUrl(this.issuePath(issue.iid)); + } + }) + .catch(error => { + this.createIssueError = error; + this.issueCreationInProgress = false; }); }, + issuePath(issueId) { + return joinPaths(this.projectIssuesPath, issueId); + }, + trackPageViews() { + const { category, action } = trackAlertsDetailsViewsOptions; + Tracking.event(category, action); + }, + alertRefresh() { + this.$apollo.queries.alert.refetch(); + }, }, }; + diff --git a/app/assets/javascripts/alert_management/components/alert_management_list.vue b/app/assets/javascripts/alert_management/components/alert_management_list.vue index 74fc19ff3d4..37901c21f9b 100644 --- a/app/assets/javascripts/alert_management/components/alert_management_list.vue +++ b/app/assets/javascripts/alert_management/components/alert_management_list.vue @@ -10,23 +10,41 @@ import { GlDropdownItem, GlTabs, GlTab, + GlBadge, + GlPagination, } from '@gitlab/ui'; import createFlash from '~/flash'; import { s__ } from '~/locale'; import { joinPaths, visitUrl } from '~/lib/utils/url_utility'; +import { fetchPolicies } from '~/lib/graphql'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; -import getAlerts from '../graphql/queries/getAlerts.query.graphql'; -import { ALERTS_STATUS, ALERTS_STATUS_TABS, ALERTS_SEVERITY_LABELS } from '../constants'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import getAlerts from '../graphql/queries/get_alerts.query.graphql'; +import getAlertsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql'; +import { + ALERTS_STATUS_TABS, + ALERTS_SEVERITY_LABELS, + DEFAULT_PAGE_SIZE, + trackAlertListViewsOptions, + trackAlertStatusUpdateOptions, +} from '../constants'; import updateAlertStatus from '../graphql/mutations/update_alert_status.graphql'; -import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; +import { convertToSnakeCase } from '~/lib/utils/text_utility'; +import Tracking from '~/tracking'; -const tdClass = 'table-col d-flex d-md-table-cell align-items-center'; +const tdClass = 'table-col gl-display-flex d-md-table-cell gl-align-items-center'; +const thClass = 'gl-hover-bg-blue-50'; const bodyTrClass = - 'gl-border-1 gl-border-t-solid gl-border-gray-100 hover-bg-blue-50 hover-gl-cursor-pointer hover-gl-border-b-solid hover-gl-border-blue-200'; + 'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-bg-blue-50 gl-hover-cursor-pointer gl-hover-border-b-solid gl-hover-border-blue-200'; + +const initialPaginationState = { + currentPage: 1, + prevPageCursor: '', + nextPageCursor: '', + firstPageSize: DEFAULT_PAGE_SIZE, + lastPageSize: null, +}; export default { - bodyTrClass, i18n: { noAlertsMsg: s__( "AlertManagement|No alerts available to display. If you think you're seeing this message in error, refresh the page.", @@ -40,40 +58,54 @@ export default { key: 'severity', label: s__('AlertManagement|Severity'), tdClass: `${tdClass} rounded-top text-capitalize`, + thClass, + sortable: true, }, { key: 'startedAt', label: s__('AlertManagement|Start time'), + thClass: `${thClass} js-started-at`, tdClass, + sortable: true, }, { key: 'endedAt', label: s__('AlertManagement|End time'), + thClass, tdClass, + sortable: true, }, { key: 'title', label: s__('AlertManagement|Alert'), - thClass: 'w-30p', + thClass: `${thClass} w-30p gl-pointer-events-none`, tdClass, + sortable: false, }, { key: 'eventCount', label: s__('AlertManagement|Events'), - thClass: 'text-right event-count', - tdClass: `${tdClass} text-md-right event-count`, + thClass: `${thClass} text-right gl-pr-9 w-3rem`, + tdClass: `${tdClass} text-md-right`, + sortable: true, + }, + { + key: 'assignees', + label: s__('AlertManagement|Assignees'), + tdClass, }, { key: 'status', - thClass: 'w-15p', + thClass: `${thClass} w-15p`, label: s__('AlertManagement|Status'), tdClass: `${tdClass} rounded-bottom`, + sortable: true, }, ], statuses: { - [ALERTS_STATUS.TRIGGERED]: s__('AlertManagement|Triggered'), - [ALERTS_STATUS.ACKNOWLEDGED]: s__('AlertManagement|Acknowledged'), - [ALERTS_STATUS.RESOLVED]: s__('AlertManagement|Resolved'), + TRIGGERED: s__('AlertManagement|Triggered'), + ACKNOWLEDGED: s__('AlertManagement|Acknowledged'), + RESOLVED: s__('AlertManagement|Resolved'), }, severityLabels: ALERTS_SEVERITY_LABELS, statusTabs: ALERTS_STATUS_TABS, @@ -89,8 +121,9 @@ export default { GlIcon, GlTabs, GlTab, + GlBadge, + GlPagination, }, - mixins: [glFeatureFlagsMixin()], props: { projectPath: { type: String, @@ -115,33 +148,63 @@ export default { }, apollo: { alerts: { + fetchPolicy: fetchPolicies.CACHE_AND_NETWORK, query: getAlerts, variables() { return { projectPath: this.projectPath, statuses: this.statusFilter, + sort: this.sort, + firstPageSize: this.pagination.firstPageSize, + lastPageSize: this.pagination.lastPageSize, + prevPageCursor: this.pagination.prevPageCursor, + nextPageCursor: this.pagination.nextPageCursor, }; }, update(data) { - return data.project.alertManagementAlerts.nodes; + const { alertManagementAlerts: { nodes: list = [], pageInfo = {} } = {} } = + data.project || {}; + + return { + list, + pageInfo, + }; }, error() { this.errored = true; }, }, + alertsCount: { + query: getAlertsCountByStatus, + variables() { + return { + projectPath: this.projectPath, + }; + }, + update(data) { + return data.project?.alertManagementAlertStatusCounts; + }, + }, }, data() { return { - alerts: null, errored: false, isAlertDismissed: false, isErrorAlertDismissed: false, - statusFilter: this.$options.statusTabs[4].filters, + sort: 'STARTED_AT_DESC', + statusFilter: [], + filteredByStatus: '', + pagination: initialPaginationState, + sortBy: 'startedAt', + sortDesc: true, + sortDirection: 'desc', }; }, computed: { showNoAlertsMsg() { - return !this.errored && !this.loading && !this.alerts?.length && !this.isAlertDismissed; + return ( + !this.errored && !this.loading && this.alertsCount?.all === 0 && !this.isAlertDismissed + ); }, showErrorMsg() { return this.errored && !this.isErrorAlertDismissed; @@ -149,12 +212,43 @@ export default { loading() { return this.$apollo.queries.alerts.loading; }, + hasAlerts() { + return this.alerts?.list?.length; + }, + tbodyTrClass() { + return !this.loading && this.hasAlerts ? bodyTrClass : ''; + }, + showPaginationControls() { + return Boolean(this.prevPage || this.nextPage); + }, + alertsForCurrentTab() { + return this.alertsCount ? this.alertsCount[this.filteredByStatus.toLowerCase()] : 0; + }, + prevPage() { + return Math.max(this.pagination.currentPage - 1, 0); + }, + nextPage() { + const nextPage = this.pagination.currentPage + 1; + return nextPage > Math.ceil(this.alertsForCurrentTab / DEFAULT_PAGE_SIZE) ? null : nextPage; + }, + }, + mounted() { + this.trackPageViews(); }, methods: { filterAlertsByStatus(tabIndex) { - this.statusFilter = this.$options.statusTabs[tabIndex].filters; + this.resetPagination(); + const { filters, status } = this.$options.statusTabs[tabIndex]; + this.statusFilter = filters; + this.filteredByStatus = status; + }, + fetchSortedData({ sortBy, sortDesc }) { + const sortingDirection = sortDesc ? 'DESC' : 'ASC'; + const sortingColumn = convertToSnakeCase(sortBy).toUpperCase(); + + this.resetPagination(); + this.sort = `${sortingColumn}_${sortingDirection}`; }, - capitalizeFirstCharacter, updateAlertStatus(status, iid) { this.$apollo .mutate({ @@ -166,7 +260,10 @@ export default { }, }) .then(() => { + this.trackStatusUpdate(status); this.$apollo.queries.alerts.refetch(); + this.$apollo.queries.alertsCount.refetch(); + this.resetPagination(); }) .catch(() => { createFlash( @@ -179,6 +276,42 @@ export default { navigateToAlertDetails({ iid }) { return visitUrl(joinPaths(window.location.pathname, iid, 'details')); }, + trackPageViews() { + const { category, action } = trackAlertListViewsOptions; + Tracking.event(category, action); + }, + trackStatusUpdate(status) { + const { category, action, label } = trackAlertStatusUpdateOptions; + Tracking.event(category, action, { label, property: status }); + }, + getAssignees(assignees) { + // TODO: Update to show list of assignee(s) after https://gitlab.com/gitlab-org/gitlab/-/issues/218405 + return assignees.nodes?.length > 0 + ? assignees.nodes[0]?.username + : s__('AlertManagement|Unassigned'); + }, + handlePageChange(page) { + const { startCursor, endCursor } = this.alerts.pageInfo; + + if (page > this.pagination.currentPage) { + this.pagination = { + ...initialPaginationState, + nextPageCursor: endCursor, + currentPage: page, + }; + } else { + this.pagination = { + lastPageSize: DEFAULT_PAGE_SIZE, + firstPageSize: null, + prevPageCursor: startCursor, + nextPageCursor: '', + currentPage: page, + }; + } + }, + resetPagination() { + this.pagination = initialPaginationState; + }, }, }; @@ -192,10 +325,13 @@ export default { {{ $options.i18n.errorMsg }} - + @@ -205,13 +341,19 @@ export default { + + + + + + +import SidebarHeader from './sidebar/sidebar_header.vue'; +import SidebarTodo from './sidebar/sidebar_todo.vue'; +import SidebarStatus from './sidebar/sidebar_status.vue'; +import SidebarAssignees from './sidebar/sidebar_assignees.vue'; + +export default { + components: { + SidebarAssignees, + SidebarHeader, + SidebarTodo, + SidebarStatus, + }, + props: { + sidebarCollapsed: { + type: Boolean, + required: true, + }, + projectPath: { + type: String, + required: true, + }, + alert: { + type: Object, + required: true, + }, + }, + computed: { + sidebarCollapsedClass() { + return this.sidebarCollapsed ? 'right-sidebar-collapsed' : 'right-sidebar-expanded'; + }, + }, +}; + + + diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignee.vue b/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignee.vue new file mode 100644 index 00000000000..df07038151e --- /dev/null +++ b/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignee.vue @@ -0,0 +1,51 @@ + + + diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue b/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue new file mode 100644 index 00000000000..453a3901665 --- /dev/null +++ b/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue @@ -0,0 +1,278 @@ + + + diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_header.vue b/app/assets/javascripts/alert_management/components/sidebar/sidebar_header.vue new file mode 100644 index 00000000000..047793d8cee --- /dev/null +++ b/app/assets/javascripts/alert_management/components/sidebar/sidebar_header.vue @@ -0,0 +1,34 @@ + + + diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_status.vue b/app/assets/javascripts/alert_management/components/sidebar/sidebar_status.vue new file mode 100644 index 00000000000..89dbbedd9c1 --- /dev/null +++ b/app/assets/javascripts/alert_management/components/sidebar/sidebar_status.vue @@ -0,0 +1,189 @@ + + + diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue b/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue new file mode 100644 index 00000000000..87090165f82 --- /dev/null +++ b/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue @@ -0,0 +1,29 @@ + + + + diff --git a/app/assets/javascripts/alert_management/components/system_notes/system_note.vue b/app/assets/javascripts/alert_management/components/system_notes/system_note.vue new file mode 100644 index 00000000000..9042d51aecf --- /dev/null +++ b/app/assets/javascripts/alert_management/components/system_notes/system_note.vue @@ -0,0 +1,46 @@ + + + diff --git a/app/assets/javascripts/alert_management/constants.js b/app/assets/javascripts/alert_management/constants.js index 9df01d9d0b5..b9670466c0f 100644 --- a/app/assets/javascripts/alert_management/constants.js +++ b/app/assets/javascripts/alert_management/constants.js @@ -9,38 +9,59 @@ export const ALERTS_SEVERITY_LABELS = { UNKNOWN: s__('AlertManagement|Unknown'), }; -export const ALERTS_STATUS = { - OPEN: 'OPEN', - TRIGGERED: 'TRIGGERED', - ACKNOWLEDGED: 'ACKNOWLEDGED', - RESOLVED: 'RESOLVED', - ALL: 'ALL', -}; - export const ALERTS_STATUS_TABS = [ { title: s__('AlertManagement|Open'), - status: ALERTS_STATUS.OPEN, - filters: [ALERTS_STATUS.TRIGGERED, ALERTS_STATUS.ACKNOWLEDGED], + status: 'OPEN', + filters: ['TRIGGERED', 'ACKNOWLEDGED'], }, { title: s__('AlertManagement|Triggered'), - status: ALERTS_STATUS.TRIGGERED, - filters: [ALERTS_STATUS.TRIGGERED], + status: 'TRIGGERED', + filters: 'TRIGGERED', }, { title: s__('AlertManagement|Acknowledged'), - status: ALERTS_STATUS.ACKNOWLEDGED, - filters: [ALERTS_STATUS.ACKNOWLEDGED], + status: 'ACKNOWLEDGED', + filters: 'ACKNOWLEDGED', }, { title: s__('AlertManagement|Resolved'), - status: ALERTS_STATUS.RESOLVED, - filters: [ALERTS_STATUS.RESOLVED], + status: 'RESOLVED', + filters: 'RESOLVED', }, { title: s__('AlertManagement|All alerts'), - status: ALERTS_STATUS.ALL, - filters: [ALERTS_STATUS.TRIGGERED, ALERTS_STATUS.ACKNOWLEDGED, ALERTS_STATUS.RESOLVED], + status: 'ALL', + filters: ['TRIGGERED', 'ACKNOWLEDGED', 'RESOLVED'], }, ]; + +/* eslint-disable @gitlab/require-i18n-strings */ + +/** + * Tracks snowplow event when user views alerts list + */ +export const trackAlertListViewsOptions = { + category: 'Alert Management', + action: 'view_alerts_list', +}; + +/** + * Tracks snowplow event when user views alert details + */ +export const trackAlertsDetailsViewsOptions = { + category: 'Alert Management', + action: 'view_alert_details', +}; + +/** + * Tracks snowplow event when alert status is updated + */ +export const trackAlertStatusUpdateOptions = { + category: 'Alert Management', + action: 'update_alert_status', + label: 'Status', +}; + +export const DEFAULT_PAGE_SIZE = 10; diff --git a/app/assets/javascripts/alert_management/details.js b/app/assets/javascripts/alert_management/details.js index d3523e0a29d..aa8a839ea3f 100644 --- a/app/assets/javascripts/alert_management/details.js +++ b/app/assets/javascripts/alert_management/details.js @@ -8,7 +8,7 @@ Vue.use(VueApollo); export default selector => { const domEl = document.querySelector(selector); - const { alertId, projectPath, newIssuePath } = domEl.dataset; + const { alertId, projectPath, projectIssuesPath } = domEl.dataset; const apolloProvider = new VueApollo({ defaultClient: createDefaultClient( @@ -39,7 +39,7 @@ export default selector => { props: { alertId, projectPath, - newIssuePath, + projectIssuesPath, }, }); }, diff --git a/app/assets/javascripts/alert_management/graphql/fragments/alert_note.fragment.graphql b/app/assets/javascripts/alert_management/graphql/fragments/alert_note.fragment.graphql new file mode 100644 index 00000000000..c72300e9757 --- /dev/null +++ b/app/assets/javascripts/alert_management/graphql/fragments/alert_note.fragment.graphql @@ -0,0 +1,16 @@ +#import "~/graphql_shared/fragments/author.fragment.graphql" + +fragment AlertNote on Note { + id + author { + id + state + ...Author + } + body + bodyHtml + createdAt + discussion { + id + } +} diff --git a/app/assets/javascripts/alert_management/graphql/fragments/detailItem.fragment.graphql b/app/assets/javascripts/alert_management/graphql/fragments/detailItem.fragment.graphql deleted file mode 100644 index df802616e97..00000000000 --- a/app/assets/javascripts/alert_management/graphql/fragments/detailItem.fragment.graphql +++ /dev/null @@ -1,11 +0,0 @@ -#import "./listItem.fragment.graphql" - -fragment AlertDetailItem on AlertManagementAlert { - ...AlertListItem - createdAt - monitoringTool - service - description - updatedAt - details -} diff --git a/app/assets/javascripts/alert_management/graphql/fragments/detail_item.fragment.graphql b/app/assets/javascripts/alert_management/graphql/fragments/detail_item.fragment.graphql new file mode 100644 index 00000000000..cbe7e169be3 --- /dev/null +++ b/app/assets/javascripts/alert_management/graphql/fragments/detail_item.fragment.graphql @@ -0,0 +1,17 @@ +#import "./list_item.fragment.graphql" +#import "./alert_note.fragment.graphql" + +fragment AlertDetailItem on AlertManagementAlert { + ...AlertListItem + createdAt + monitoringTool + service + description + updatedAt + details + notes { + nodes { + ...AlertNote + } + } +} diff --git a/app/assets/javascripts/alert_management/graphql/fragments/listItem.fragment.graphql b/app/assets/javascripts/alert_management/graphql/fragments/listItem.fragment.graphql deleted file mode 100644 index fffe07b0cfd..00000000000 --- a/app/assets/javascripts/alert_management/graphql/fragments/listItem.fragment.graphql +++ /dev/null @@ -1,9 +0,0 @@ -fragment AlertListItem on AlertManagementAlert { - iid - title - severity - status - startedAt - endedAt - eventCount -} diff --git a/app/assets/javascripts/alert_management/graphql/fragments/list_item.fragment.graphql b/app/assets/javascripts/alert_management/graphql/fragments/list_item.fragment.graphql new file mode 100644 index 00000000000..746c4435f38 --- /dev/null +++ b/app/assets/javascripts/alert_management/graphql/fragments/list_item.fragment.graphql @@ -0,0 +1,15 @@ +fragment AlertListItem on AlertManagementAlert { + iid + title + severity + status + startedAt + endedAt + eventCount + issueIid + assignees { + nodes { + username + } + } +} diff --git a/app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.graphql b/app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.graphql new file mode 100644 index 00000000000..efeaf8fa372 --- /dev/null +++ b/app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.graphql @@ -0,0 +1,15 @@ +mutation($projectPath: ID!, $assigneeUsernames: [String!]!, $iid: String!) { + alertSetAssignees( + input: { iid: $iid, assigneeUsernames: $assigneeUsernames, projectPath: $projectPath } + ) { + errors + alert { + iid + assignees { + nodes { + username + } + } + } + } +} diff --git a/app/assets/javascripts/alert_management/graphql/mutations/create_issue_from_alert.graphql b/app/assets/javascripts/alert_management/graphql/mutations/create_issue_from_alert.graphql new file mode 100644 index 00000000000..664596ab88f --- /dev/null +++ b/app/assets/javascripts/alert_management/graphql/mutations/create_issue_from_alert.graphql @@ -0,0 +1,8 @@ +mutation ($projectPath: ID!, $iid: String!) { + createAlertIssue(input: { iid: $iid, projectPath: $projectPath }) { + errors + issue { + iid + } + } +} diff --git a/app/assets/javascripts/alert_management/graphql/mutations/update_alert_status.graphql b/app/assets/javascripts/alert_management/graphql/mutations/update_alert_status.graphql index 009ae0b2930..09151f233f5 100644 --- a/app/assets/javascripts/alert_management/graphql/mutations/update_alert_status.graphql +++ b/app/assets/javascripts/alert_management/graphql/mutations/update_alert_status.graphql @@ -4,6 +4,7 @@ mutation ($projectPath: ID!, $status: AlertManagementStatus!, $iid: String!) { alert { iid, status, + endedAt } } } diff --git a/app/assets/javascripts/alert_management/graphql/queries/details.query.graphql b/app/assets/javascripts/alert_management/graphql/queries/details.query.graphql index 7c77715fad2..c02b8accdd1 100644 --- a/app/assets/javascripts/alert_management/graphql/queries/details.query.graphql +++ b/app/assets/javascripts/alert_management/graphql/queries/details.query.graphql @@ -1,4 +1,4 @@ -#import "../fragments/detailItem.fragment.graphql" +#import "../fragments/detail_item.fragment.graphql" query alertDetails($fullPath: ID!, $alertId: String) { project(fullPath: $fullPath) { diff --git a/app/assets/javascripts/alert_management/graphql/queries/getAlerts.query.graphql b/app/assets/javascripts/alert_management/graphql/queries/getAlerts.query.graphql deleted file mode 100644 index 54b66389d5b..00000000000 --- a/app/assets/javascripts/alert_management/graphql/queries/getAlerts.query.graphql +++ /dev/null @@ -1,11 +0,0 @@ -#import "../fragments/listItem.fragment.graphql" - -query getAlerts($projectPath: ID!, $statuses: [AlertManagementStatus!]) { - project(fullPath: $projectPath) { - alertManagementAlerts(statuses: $statuses) { - nodes { - ...AlertListItem - } - } - } -} diff --git a/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql b/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql new file mode 100644 index 00000000000..1d3c3c83cc1 --- /dev/null +++ b/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql @@ -0,0 +1,32 @@ +#import "../fragments/list_item.fragment.graphql" + +query getAlerts( + $projectPath: ID!, + $statuses: [AlertManagementStatus!], + $sort: AlertManagementAlertSort, + $firstPageSize: Int, + $lastPageSize: Int, + $prevPageCursor: String = "" + $nextPageCursor: String = "" +) { + project(fullPath: $projectPath, ) { + alertManagementAlerts( + statuses: $statuses, + sort: $sort, + first: $firstPageSize + last: $lastPageSize, + after: $nextPageCursor, + before: $prevPageCursor + ) { + nodes { + ...AlertListItem + }, + pageInfo { + hasNextPage + endCursor + hasPreviousPage + startCursor + } + } + } +} diff --git a/app/assets/javascripts/alert_management/graphql/queries/get_count_by_status.query.graphql b/app/assets/javascripts/alert_management/graphql/queries/get_count_by_status.query.graphql new file mode 100644 index 00000000000..1143050200c --- /dev/null +++ b/app/assets/javascripts/alert_management/graphql/queries/get_count_by_status.query.graphql @@ -0,0 +1,11 @@ +query getAlertsCount($projectPath: ID!) { + project(fullPath: $projectPath) { + alertManagementAlertStatusCounts { + all + open + acknowledged + resolved + triggered + } + } +} diff --git a/app/assets/javascripts/alert_management/services/index.js b/app/assets/javascripts/alert_management/services/index.js deleted file mode 100644 index 787603d3e7a..00000000000 --- a/app/assets/javascripts/alert_management/services/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import axios from '~/lib/utils/axios_utils'; - -export default { - getAlertManagementList({ endpoint }) { - return axios.get(endpoint); - }, -}; diff --git a/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue b/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue index 410c5c00e8a..ac30b086875 100644 --- a/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue +++ b/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue @@ -1,26 +1,37 @@ + + diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue new file mode 100644 index 00000000000..963d104b6b3 --- /dev/null +++ b/app/assets/javascripts/batch_comments/components/draft_note.vue @@ -0,0 +1,113 @@ + + diff --git a/app/assets/javascripts/batch_comments/components/drafts_count.vue b/app/assets/javascripts/batch_comments/components/drafts_count.vue new file mode 100644 index 00000000000..f1180760c4d --- /dev/null +++ b/app/assets/javascripts/batch_comments/components/drafts_count.vue @@ -0,0 +1,15 @@ + + diff --git a/app/assets/javascripts/batch_comments/components/inline_draft_comment_row.vue b/app/assets/javascripts/batch_comments/components/inline_draft_comment_row.vue new file mode 100644 index 00000000000..385725cd109 --- /dev/null +++ b/app/assets/javascripts/batch_comments/components/inline_draft_comment_row.vue @@ -0,0 +1,32 @@ + + + diff --git a/app/assets/javascripts/batch_comments/components/parallel_draft_comment_row.vue b/app/assets/javascripts/batch_comments/components/parallel_draft_comment_row.vue new file mode 100644 index 00000000000..68fd20e56bc --- /dev/null +++ b/app/assets/javascripts/batch_comments/components/parallel_draft_comment_row.vue @@ -0,0 +1,45 @@ + + + diff --git a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue new file mode 100644 index 00000000000..195e1b7ec5c --- /dev/null +++ b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue @@ -0,0 +1,111 @@ + + + diff --git a/app/assets/javascripts/batch_comments/components/preview_item.vue b/app/assets/javascripts/batch_comments/components/preview_item.vue new file mode 100644 index 00000000000..22495eb4d7d --- /dev/null +++ b/app/assets/javascripts/batch_comments/components/preview_item.vue @@ -0,0 +1,143 @@ + + + diff --git a/app/assets/javascripts/batch_comments/components/publish_button.vue b/app/assets/javascripts/batch_comments/components/publish_button.vue new file mode 100644 index 00000000000..f4dc0f04dc3 --- /dev/null +++ b/app/assets/javascripts/batch_comments/components/publish_button.vue @@ -0,0 +1,55 @@ + + + diff --git a/app/assets/javascripts/batch_comments/components/review_bar.vue b/app/assets/javascripts/batch_comments/components/review_bar.vue new file mode 100644 index 00000000000..b0e8b806701 --- /dev/null +++ b/app/assets/javascripts/batch_comments/components/review_bar.vue @@ -0,0 +1,70 @@ + + diff --git a/app/assets/javascripts/batch_comments/constants.js b/app/assets/javascripts/batch_comments/constants.js new file mode 100644 index 00000000000..b309c339fc8 --- /dev/null +++ b/app/assets/javascripts/batch_comments/constants.js @@ -0,0 +1,3 @@ +export const CHANGES_TAB = 'diffs'; +export const DISCUSSION_TAB = 'notes'; +export const SHOW_TAB = 'show'; diff --git a/app/assets/javascripts/batch_comments/index.js b/app/assets/javascripts/batch_comments/index.js new file mode 100644 index 00000000000..e06285c0b37 --- /dev/null +++ b/app/assets/javascripts/batch_comments/index.js @@ -0,0 +1,24 @@ +import Vue from 'vue'; +import { mapActions } from 'vuex'; +import store from '~/mr_notes/stores'; +import ReviewBar from './components/review_bar.vue'; + +// eslint-disable-next-line import/prefer-default-export +export const initReviewBar = () => { + const el = document.getElementById('js-review-bar'); + + // eslint-disable-next-line no-new + new Vue({ + el, + store, + mounted() { + this.fetchDrafts(); + }, + methods: { + ...mapActions('batchComments', ['fetchDrafts']), + }, + render(createElement) { + return createElement(ReviewBar); + }, + }); +}; diff --git a/app/assets/javascripts/batch_comments/mixins/resolved_status.js b/app/assets/javascripts/batch_comments/mixins/resolved_status.js index 3bbbaa86b51..2517fb198f0 100644 --- a/app/assets/javascripts/batch_comments/mixins/resolved_status.js +++ b/app/assets/javascripts/batch_comments/mixins/resolved_status.js @@ -1,9 +1,58 @@ -import { sprintf, __ } from '~/locale'; +import { mapGetters } from 'vuex'; +import { sprintf, s__, __ } from '~/locale'; export default { + props: { + discussionId: { + type: String, + required: false, + default: null, + }, + resolveDiscussion: { + type: Boolean, + required: false, + default: false, + }, + isDraft: { + type: Boolean, + required: false, + default: false, + }, + }, computed: { + ...mapGetters(['isDiscussionResolved']), + resolvedStatusMessage() { + let message; + const discussionResolved = this.isDiscussionResolved( + this.draft ? this.draft.discussion_id : this.discussionId, + ); + const discussionToBeResolved = this.draft + ? this.draft.resolve_discussion + : this.resolveDiscussion; + + if (discussionToBeResolved && discussionResolved && !this.$options.showStaysResolved) { + return undefined; + } + + if (discussionToBeResolved) { + message = discussionResolved + ? s__('MergeRequests|Thread stays resolved') + : s__('MergeRequests|Thread will be resolved'); + } else if (discussionResolved) { + message = s__('MergeRequests|Thread will be unresolved'); + } else if (this.$options.showStaysResolved) { + message = s__('MergeRequests|Thread stays unresolved'); + } + + return message; + }, + componentClasses() { + return this.resolveDiscussion ? 'is-resolving-discussion' : 'is-unresolving-discussion'; + }, resolveButtonTitle() { - let title = __('Mark comment as resolved'); + if (this.isDraft || this.discussionId) return this.resolvedStatusMessage; + + let title = __('Mark as resolved'); if (this.resolvedBy) { title = sprintf(__('Resolved by %{name}'), { name: this.resolvedBy.name }); @@ -12,4 +61,5 @@ export default { return title; }, }, + showStaysResolved: true, }; diff --git a/app/assets/javascripts/batch_comments/services/drafts_service.js b/app/assets/javascripts/batch_comments/services/drafts_service.js new file mode 100644 index 00000000000..36d2f8df612 --- /dev/null +++ b/app/assets/javascripts/batch_comments/services/drafts_service.js @@ -0,0 +1,33 @@ +import axios from '~/lib/utils/axios_utils'; + +export default { + createNewDraft(endpoint, data) { + const postData = { ...data, draft_note: data.note }; + delete postData.note; + + return axios.post(endpoint, postData); + }, + deleteDraft(endpoint, draftId) { + return axios.delete(`${endpoint}/${draftId}`); + }, + publishDraft(endpoint, draftId) { + return axios.post(endpoint, { id: draftId }); + }, + addDraftToDiscussion(endpoint, data) { + return axios.post(endpoint, data); + }, + fetchDrafts(endpoint) { + return axios.get(endpoint); + }, + publish(endpoint) { + return axios.post(endpoint); + }, + discard(endpoint) { + return axios.delete(endpoint); + }, + update(endpoint, { draftId, note, resolveDiscussion, position }) { + return axios.put(`${endpoint}/${draftId}`, { + draft_note: { note, resolve_discussion: resolveDiscussion, position }, + }); + }, +}; diff --git a/app/assets/javascripts/batch_comments/stores/index.js b/app/assets/javascripts/batch_comments/stores/index.js new file mode 100644 index 00000000000..08dc9ea70f8 --- /dev/null +++ b/app/assets/javascripts/batch_comments/stores/index.js @@ -0,0 +1,14 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; +import batchComments from './modules/batch_comments'; + +Vue.use(Vuex); + +export const createStore = () => + new Vuex.Store({ + modules: { + batchComments: batchComments(), + }, + }); + +export default createStore(); diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js new file mode 100644 index 00000000000..1ef012696c5 --- /dev/null +++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js @@ -0,0 +1,151 @@ +import flash from '~/flash'; +import { __ } from '~/locale'; +import { scrollToElement } from '~/lib/utils/common_utils'; +import service from '../../../services/drafts_service'; +import * as types from './mutation_types'; +import { CHANGES_TAB, DISCUSSION_TAB, SHOW_TAB } from '../../../constants'; + +export const saveDraft = ({ dispatch }, draft) => + dispatch('saveNote', { ...draft, isDraft: true }, { root: true }); + +export const addDraftToDiscussion = ({ commit }, { endpoint, data }) => + service + .addDraftToDiscussion(endpoint, data) + .then(res => res.data) + .then(res => { + commit(types.ADD_NEW_DRAFT, res); + return res; + }) + .catch(() => { + flash(__('An error occurred adding a draft to the thread.')); + }); + +export const createNewDraft = ({ commit }, { endpoint, data }) => + service + .createNewDraft(endpoint, data) + .then(res => res.data) + .then(res => { + commit(types.ADD_NEW_DRAFT, res); + return res; + }) + .catch(() => { + flash(__('An error occurred adding a new draft.')); + }); + +export const deleteDraft = ({ commit, getters }, draft) => + service + .deleteDraft(getters.getNotesData.draftsPath, draft.id) + .then(() => { + commit(types.DELETE_DRAFT, draft.id); + }) + .catch(() => flash(__('An error occurred while deleting the comment'))); + +export const fetchDrafts = ({ commit, getters }) => + service + .fetchDrafts(getters.getNotesData.draftsPath) + .then(res => res.data) + .then(data => commit(types.SET_BATCH_COMMENTS_DRAFTS, data)) + .catch(() => flash(__('An error occurred while fetching pending comments'))); + +export const publishSingleDraft = ({ commit, dispatch, getters }, draftId) => { + commit(types.REQUEST_PUBLISH_DRAFT, draftId); + + service + .publishDraft(getters.getNotesData.draftsPublishPath, draftId) + .then(() => dispatch('updateDiscussionsAfterPublish')) + .then(() => commit(types.RECEIVE_PUBLISH_DRAFT_SUCCESS, draftId)) + .catch(() => commit(types.RECEIVE_PUBLISH_DRAFT_ERROR, draftId)); +}; + +export const publishReview = ({ commit, dispatch, getters }) => { + commit(types.REQUEST_PUBLISH_REVIEW); + + return service + .publish(getters.getNotesData.draftsPublishPath) + .then(() => dispatch('updateDiscussionsAfterPublish')) + .then(() => commit(types.RECEIVE_PUBLISH_REVIEW_SUCCESS)) + .catch(() => commit(types.RECEIVE_PUBLISH_REVIEW_ERROR)); +}; + +export const updateDiscussionsAfterPublish = ({ dispatch, getters, rootGetters }) => + dispatch('fetchDiscussions', { path: getters.getNotesData.discussionsPath }, { root: true }).then( + () => + dispatch('diffs/assignDiscussionsToDiff', rootGetters.discussionsStructuredByLineCode, { + root: true, + }), + ); + +export const discardReview = ({ commit, getters }) => { + commit(types.REQUEST_DISCARD_REVIEW); + + return service + .discard(getters.getNotesData.draftsDiscardPath) + .then(() => commit(types.RECEIVE_DISCARD_REVIEW_SUCCESS)) + .catch(() => commit(types.RECEIVE_DISCARD_REVIEW_ERROR)); +}; + +export const updateDraft = ( + { commit, getters }, + { note, noteText, resolveDiscussion, position, callback }, +) => + service + .update(getters.getNotesData.draftsPath, { + draftId: note.id, + note: noteText, + resolveDiscussion, + position: JSON.stringify(position), + }) + .then(res => res.data) + .then(data => commit(types.RECEIVE_DRAFT_UPDATE_SUCCESS, data)) + .then(callback) + .catch(() => flash(__('An error occurred while updating the comment'))); + +export const scrollToDraft = ({ dispatch, rootGetters }, draft) => { + const discussion = draft.discussion_id && rootGetters.getDiscussion(draft.discussion_id); + const tab = + draft.file_hash || (discussion && discussion.diff_discussion) ? CHANGES_TAB : SHOW_TAB; + const tabEl = tab === CHANGES_TAB ? CHANGES_TAB : DISCUSSION_TAB; + const draftID = `note_${draft.id}`; + const el = document.querySelector(`#${tabEl} #${draftID}`); + + dispatch('closeReviewDropdown'); + + window.location.hash = draftID; + + if (window.mrTabs.currentAction !== tab) { + window.mrTabs.tabShown(tab); + } + + if (discussion) { + dispatch('expandDiscussion', { discussionId: discussion.id }, { root: true }); + } + + if (el) { + setTimeout(() => scrollToElement(el.closest('.draft-note-component'))); + } +}; + +export const toggleReviewDropdown = ({ dispatch, state }) => { + if (state.showPreviewDropdown) { + dispatch('closeReviewDropdown'); + } else { + dispatch('openReviewDropdown'); + } +}; + +export const openReviewDropdown = ({ commit }) => commit(types.OPEN_REVIEW_DROPDOWN); +export const closeReviewDropdown = ({ commit }) => commit(types.CLOSE_REVIEW_DROPDOWN); + +export const expandAllDiscussions = ({ dispatch, state }) => + state.drafts + .filter(draft => draft.discussion_id) + .forEach(draft => { + dispatch('expandDiscussion', { discussionId: draft.discussion_id }, { root: true }); + }); + +export const toggleResolveDiscussion = ({ commit }, draftId) => { + commit(types.TOGGLE_RESOLVE_DISCUSSION, draftId); +}; + +// prevent babel-plugin-rewire from generating an invalid default during karma tests +export default () => {}; diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js new file mode 100644 index 00000000000..43f43c983aa --- /dev/null +++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/getters.js @@ -0,0 +1,87 @@ +import { parallelLineKey, showDraftOnSide } from '../../../utils'; + +export const draftsCount = state => state.drafts.length; + +export const getNotesData = (state, getters, rootState, rootGetters) => rootGetters.getNotesData; + +export const hasDrafts = state => state.drafts.length > 0; + +export const draftsPerDiscussionId = state => + state.drafts.reduce((acc, draft) => { + if (draft.discussion_id) { + acc[draft.discussion_id] = draft; + } + + return acc; + }, {}); + +export const draftsPerFileHashAndLine = state => + state.drafts.reduce((acc, draft) => { + if (draft.file_hash) { + if (!acc[draft.file_hash]) { + acc[draft.file_hash] = {}; + } + + acc[draft.file_hash][draft.line_code] = draft; + } + + return acc; + }, {}); + +export const shouldRenderDraftRow = (state, getters) => (diffFileSha, line) => + Boolean( + diffFileSha in getters.draftsPerFileHashAndLine && + getters.draftsPerFileHashAndLine[diffFileSha][line.line_code], + ); + +export const shouldRenderParallelDraftRow = (state, getters) => (diffFileSha, line) => { + const draftsForFile = getters.draftsPerFileHashAndLine[diffFileSha]; + const [lkey, rkey] = [parallelLineKey(line, 'left'), parallelLineKey(line, 'right')]; + + return draftsForFile ? Boolean(draftsForFile[lkey] || draftsForFile[rkey]) : false; +}; + +export const hasParallelDraftLeft = (state, getters) => (diffFileSha, line) => { + const draftsForFile = getters.draftsPerFileHashAndLine[diffFileSha]; + const lkey = parallelLineKey(line, 'left'); + + return draftsForFile ? Boolean(draftsForFile[lkey]) : false; +}; + +export const hasParallelDraftRight = (state, getters) => (diffFileSha, line) => { + const draftsForFile = getters.draftsPerFileHashAndLine[diffFileSha]; + const rkey = parallelLineKey(line, 'left'); + + return draftsForFile ? Boolean(draftsForFile[rkey]) : false; +}; + +export const shouldRenderDraftRowInDiscussion = (state, getters) => discussionId => + typeof getters.draftsPerDiscussionId[discussionId] !== 'undefined'; + +export const draftForDiscussion = (state, getters) => discussionId => + getters.draftsPerDiscussionId[discussionId] || {}; + +export const draftForLine = (state, getters) => (diffFileSha, line, side = null) => { + const draftsForFile = getters.draftsPerFileHashAndLine[diffFileSha]; + + const key = side !== null ? parallelLineKey(line, side) : line.line_code; + + if (draftsForFile) { + const draft = draftsForFile[key]; + if (draft && showDraftOnSide(line, side)) { + return draft; + } + } + return {}; +}; + +export const draftsForFile = state => diffFileSha => + state.drafts.filter(draft => draft.file_hash === diffFileSha); + +export const isPublishingDraft = state => draftId => + state.currentlyPublishingDrafts.indexOf(draftId) !== -1; + +export const sortedDrafts = state => [...state.drafts].sort((a, b) => a.id > b.id); + +// prevent babel-plugin-rewire from generating an invalid default during karma tests +export default () => {}; diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/index.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/index.js new file mode 100644 index 00000000000..81dab0566c1 --- /dev/null +++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/index.js @@ -0,0 +1,12 @@ +import state from './state'; +import mutations from './mutations'; +import * as actions from './actions'; +import * as getters from './getters'; + +export default () => ({ + namespaced: true, + state: state(), + mutations, + actions, + getters, +}); diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutation_types.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutation_types.js new file mode 100644 index 00000000000..c8f0658c21c --- /dev/null +++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutation_types.js @@ -0,0 +1,23 @@ +export const ENABLE_BATCH_COMMENTS = 'ENABLE_BATCH_COMMENTS'; +export const ADD_NEW_DRAFT = 'ADD_NEW_DRAFT'; +export const DELETE_DRAFT = 'DELETE_DRAFT'; +export const SET_BATCH_COMMENTS_DRAFTS = 'SET_BATCH_COMMENTS_DRAFTS'; + +export const REQUEST_PUBLISH_DRAFT = 'REQUEST_PUBLISH_DRAFT'; +export const RECEIVE_PUBLISH_DRAFT_SUCCESS = 'RECEIVE_PUBLISH_DRAFT_SUCCESS'; +export const RECEIVE_PUBLISH_DRAFT_ERROR = 'RECEIVE_PUBLISH_DRAFT_ERROR'; + +export const REQUEST_PUBLISH_REVIEW = 'REQUEST_PUBLISH_REVIEW'; +export const RECEIVE_PUBLISH_REVIEW_SUCCESS = 'RECEIVE_PUBLISH_REVIEW_SUCCESS'; +export const RECEIVE_PUBLISH_REVIEW_ERROR = 'RECEIVE_PUBLISH_REVIEW_ERROR'; + +export const REQUEST_DISCARD_REVIEW = 'REQUEST_DISCARD_REVIEW'; +export const RECEIVE_DISCARD_REVIEW_SUCCESS = 'RECEIVE_DISCARD_REVIEW_SUCCESS'; +export const RECEIVE_DISCARD_REVIEW_ERROR = 'RECEIVE_DISCARD_REVIEW_ERROR'; + +export const RECEIVE_DRAFT_UPDATE_SUCCESS = 'RECEIVE_DRAFT_UPDATE_SUCCESS'; + +export const OPEN_REVIEW_DROPDOWN = 'OPEN_REVIEW_DROPDOWN'; +export const CLOSE_REVIEW_DROPDOWN = 'CLOSE_REVIEW_DROPDOWN'; + +export const TOGGLE_RESOLVE_DISCUSSION = 'TOGGLE_RESOLVE_DISCUSSION'; diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutations.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutations.js new file mode 100644 index 00000000000..81ceef7b160 --- /dev/null +++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/mutations.js @@ -0,0 +1,81 @@ +import * as types from './mutation_types'; + +const processDraft = draft => ({ + ...draft, + isDraft: true, +}); + +export default { + [types.ADD_NEW_DRAFT](state, draft) { + state.drafts.push(processDraft(draft)); + }, + + [types.DELETE_DRAFT](state, draftId) { + state.drafts = state.drafts.filter(draft => draft.id !== draftId); + }, + + [types.SET_BATCH_COMMENTS_DRAFTS](state, drafts) { + state.drafts = drafts.map(processDraft); + }, + + [types.REQUEST_PUBLISH_DRAFT](state, draftId) { + state.currentlyPublishingDrafts.push(draftId); + }, + [types.RECEIVE_PUBLISH_DRAFT_SUCCESS](state, draftId) { + state.currentlyPublishingDrafts = state.currentlyPublishingDrafts.filter( + publishingDraftId => publishingDraftId !== draftId, + ); + state.drafts = state.drafts.filter(d => d.id !== draftId); + }, + [types.RECEIVE_PUBLISH_DRAFT_ERROR](state, draftId) { + state.currentlyPublishingDrafts = state.currentlyPublishingDrafts.filter( + publishingDraftId => publishingDraftId !== draftId, + ); + }, + + [types.REQUEST_PUBLISH_REVIEW](state) { + state.isPublishing = true; + }, + [types.RECEIVE_PUBLISH_REVIEW_SUCCESS](state) { + state.isPublishing = false; + state.drafts = []; + }, + [types.RECEIVE_PUBLISH_REVIEW_ERROR](state) { + state.isPublishing = false; + }, + [types.REQUEST_DISCARD_REVIEW](state) { + state.isDiscarding = true; + }, + [types.RECEIVE_DISCARD_REVIEW_SUCCESS](state) { + state.isDiscarding = false; + state.drafts = []; + }, + [types.RECEIVE_DISCARD_REVIEW_ERROR](state) { + state.isDiscarding = false; + }, + [types.RECEIVE_DRAFT_UPDATE_SUCCESS](state, data) { + const index = state.drafts.findIndex(draft => draft.id === data.id); + + if (index >= 0) { + state.drafts.splice(index, 1, processDraft(data)); + } + }, + [types.OPEN_REVIEW_DROPDOWN](state) { + state.showPreviewDropdown = true; + }, + [types.CLOSE_REVIEW_DROPDOWN](state) { + state.showPreviewDropdown = false; + }, + [types.TOGGLE_RESOLVE_DISCUSSION](state, draftId) { + state.drafts = state.drafts.map(draft => { + if (draft.id === draftId) { + return { + ...draft, + resolve_discussion: !draft.resolve_discussion, + }; + } + + return draft; + }); + }, +}; diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/state.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/state.js new file mode 100644 index 00000000000..80c710deab0 --- /dev/null +++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/state.js @@ -0,0 +1,9 @@ +export default () => ({ + withBatchComments: true, + isDraftsFetched: false, + drafts: [], + isPublishing: false, + currentlyPublishingDrafts: [], + isDiscarding: false, + showPreviewDropdown: false, +}); diff --git a/app/assets/javascripts/batch_comments/utils.js b/app/assets/javascripts/batch_comments/utils.js new file mode 100644 index 00000000000..cf4f7af0ebb --- /dev/null +++ b/app/assets/javascripts/batch_comments/utils.js @@ -0,0 +1,35 @@ +import { getFormData } from '~/diffs/store/utils'; + +export const getDraftReplyFormData = data => ({ + endpoint: data.notesData.draftsPath, + data, +}); + +export const getDraftFormData = params => ({ + endpoint: params.notesData.draftsPath, + data: getFormData(params), +}); + +export const parallelLineKey = (line, side) => (line[side] ? line[side].line_code : ''); + +export const showDraftOnSide = (line, side) => { + // inline mode + if (side === null) { + return true; + } + + // parallel + if (side === 'left' || side === 'right') { + const otherSide = side === 'left' ? 'right' : 'left'; + const thisCode = (line[side] && line[side].line_code) || ''; + const otherCode = (line[otherSide] && line[otherSide].line_code) || ''; + + // either the lineCodes are different + // or if they're the same, only show on the left side + if (thisCode !== otherCode || (side === 'left' && thisCode === otherCode)) { + return true; + } + } + + return false; +}; diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js index 057cdb6cc4c..e4c69a114e0 100644 --- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js +++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js @@ -25,9 +25,10 @@ function importMermaidModule() { return import(/* webpackChunkName: 'mermaid' */ 'mermaid') .then(mermaid => { let theme = 'neutral'; + const ideDarkThemes = ['dark', 'solarized-dark']; if ( - window.gon?.user_color_scheme === 'dark' && + ideDarkThemes.includes(window.gon?.user_color_scheme) && // if on the Web IDE page document.querySelector('.ide') ) { diff --git a/app/assets/javascripts/blob/components/blob_content.vue b/app/assets/javascripts/blob/components/blob_content.vue index 4f433bd8dfd..eb7f45cba6f 100644 --- a/app/assets/javascripts/blob/components/blob_content.vue +++ b/app/assets/javascripts/blob/components/blob_content.vue @@ -66,6 +66,7 @@ export default { ref="contentViewer" :content="content" :type="activeViewer.fileType" + data-qa-selector="file_content" /> diff --git a/app/assets/javascripts/blob/components/blob_header.vue b/app/assets/javascripts/blob/components/blob_header.vue index e5e01caa9a5..76c5779f3ae 100644 --- a/app/assets/javascripts/blob/components/blob_header.vue +++ b/app/assets/javascripts/blob/components/blob_header.vue @@ -30,6 +30,11 @@ export default { required: false, default: SIMPLE_BLOB_VIEWER, }, + hasRenderError: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { @@ -75,6 +80,7 @@ export default { v-if="showDefaultActions" :raw-path="blob.rawPath" :active-viewer="viewer" + :has-render-error="hasRenderError" @copy="proxyCopyRequest" /> diff --git a/app/assets/javascripts/blob/components/blob_header_default_actions.vue b/app/assets/javascripts/blob/components/blob_header_default_actions.vue index 63ae70a37f4..62fef108b47 100644 --- a/app/assets/javascripts/blob/components/blob_header_default_actions.vue +++ b/app/assets/javascripts/blob/components/blob_header_default_actions.vue @@ -27,6 +27,11 @@ export default { default: SIMPLE_BLOB_VIEWER, required: false, }, + hasRenderError: { + type: Boolean, + required: false, + default: false, + }, }, computed: { downloadUrl() { @@ -44,11 +49,13 @@ export default { diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue index fb854616a04..0ed7579e8e1 100644 --- a/app/assets/javascripts/boards/components/board_column.vue +++ b/app/assets/javascripts/boards/components/board_column.vue @@ -1,33 +1,22 @@ + + diff --git a/app/assets/javascripts/boards/components/board_delete.js b/app/assets/javascripts/boards/components/board_delete.js index cc15dc82db9..b74234a2e3c 100644 --- a/app/assets/javascripts/boards/components/board_delete.js +++ b/app/assets/javascripts/boards/components/board_delete.js @@ -1,8 +1,15 @@ import $ from 'jquery'; import Vue from 'vue'; +import { GlButton, GlTooltipDirective } from '@gitlab/ui'; import { __ } from '~/locale'; export default Vue.extend({ + components: { + GlButton, + }, + directives: { + GlTooltip: GlTooltipDirective, + }, props: { list: { type: Object, diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue index c4e2c398d45..4270ad5783d 100644 --- a/app/assets/javascripts/boards/components/board_list.vue +++ b/app/assets/javascripts/boards/components/board_list.vue @@ -104,7 +104,7 @@ export default { }, }, created() { - eventHub.$on(`hide-issue-form-${this.list.id}`, this.toggleForm); + eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm); eventHub.$on(`scroll-board-list-${this.list.id}`, this.scrollToTop); }, mounted() { @@ -381,7 +381,7 @@ export default { this.$refs.list.addEventListener('scroll', this.onScroll); }, beforeDestroy() { - eventHub.$off(`hide-issue-form-${this.list.id}`, this.toggleForm); + eventHub.$off(`toggle-issue-form-${this.list.id}`, this.toggleForm); eventHub.$off(`scroll-board-list-${this.list.id}`, this.scrollToTop); this.$refs.list.removeEventListener('scroll', this.onScroll); }, diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue new file mode 100644 index 00000000000..eb12617a66e --- /dev/null +++ b/app/assets/javascripts/boards/components/board_list_header.vue @@ -0,0 +1,291 @@ + + + diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue index deebe122109..c72fb7b30f9 100644 --- a/app/assets/javascripts/boards/components/board_new_issue.vue +++ b/app/assets/javascripts/boards/components/board_new_issue.vue @@ -92,7 +92,7 @@ export default { }, cancel() { this.title = ''; - eventHub.$emit(`hide-issue-form-${this.list.id}`); + eventHub.$emit(`toggle-issue-form-${this.list.id}`); }, setSelectedProject(selectedProject) { this.selectedProject = selectedProject; diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js index c8953158811..056a7b48212 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js +++ b/app/assets/javascripts/boards/components/board_sidebar.js @@ -54,7 +54,7 @@ export default Vue.extend({ return this.issue.milestone ? this.issue.milestone.title : __('No milestone'); }, canRemove() { - return !this.list.preset; + return !this.list?.preset; }, hasLabels() { return this.issue.labels && this.issue.labels.length; diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue index a589fb325b2..f2e198eaedb 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.vue +++ b/app/assets/javascripts/boards/components/issue_card_inner.vue @@ -147,7 +147,7 @@ export default {