From 0151325dacebb99d54b6effb1d5842c0c712168c Mon Sep 17 00:00:00 2001 From: Fatih Acet Date: Tue, 9 May 2017 04:15:34 +0000 Subject: Merge request widget redesign --- .../diff_notes/components/resolve_btn.js | 1 + .../javascripts/diff_notes/services/resolve.js | 1 + app/assets/javascripts/dispatcher.js | 6 - app/assets/javascripts/lib/utils/simple_poll.js | 15 + app/assets/javascripts/main.js | 2 - app/assets/javascripts/merge_request.js | 15 + .../javascripts/merge_request_widget/ci_bundle.js | 53 --- app/assets/javascripts/merged_buttons.js | 47 --- app/assets/javascripts/notes.js | 12 +- .../javascripts/pipelines/components/stage.js | 104 ++++++ .../components/mr_widget_author.js | 23 ++ .../components/mr_widget_author_time.js | 27 ++ .../components/mr_widget_deployment.js | 118 +++++++ .../components/mr_widget_header.js | 98 ++++++ .../components/mr_widget_memory_usage.js | 109 ++++++ .../components/mr_widget_merge_help.js | 23 ++ .../components/mr_widget_pipeline.js | 76 ++++ .../components/mr_widget_related_links.js | 42 +++ .../components/states/mr_widget_archived.js | 16 + .../states/mr_widget_auto_merge_failed.js | 22 ++ .../components/states/mr_widget_checking.js | 19 + .../components/states/mr_widget_closed.js | 30 ++ .../components/states/mr_widget_conflicts.js | 39 +++ .../components/states/mr_widget_failed_to_merge.js | 76 ++++ .../components/states/mr_widget_locked.js | 24 ++ .../mr_widget_merge_when_pipeline_succeeds.js | 116 ++++++ .../components/states/mr_widget_merged.js | 130 +++++++ .../components/states/mr_widget_missing_branch.js | 34 ++ .../components/states/mr_widget_not_allowed.js | 17 + .../states/mr_widget_nothing_to_merge.js | 17 + .../states/mr_widget_pipeline_blocked.js | 16 + .../components/states/mr_widget_pipeline_failed.js | 16 + .../components/states/mr_widget_ready_to_merge.js | 309 ++++++++++++++++ .../states/mr_widget_squash_before_merge.js | 15 + .../states/mr_widget_unresolved_discussions.js | 27 ++ .../components/states/mr_widget_wip.js | 59 ++++ .../vue_merge_request_widget/dependencies.js | 42 +++ .../vue_merge_request_widget/event_hub.js | 3 + .../javascripts/vue_merge_request_widget/index.js | 12 + .../vue_merge_request_widget/mr_widget_options.js | 234 +++++++++++++ .../services/mr_widget_service.js | 57 +++ .../stores/get_state_key.js | 28 ++ .../stores/mr_widget_store.js | 134 +++++++ .../vue_merge_request_widget/stores/state_maps.js | 36 ++ .../vue_shared/components/memory_graph.js | 36 ++ .../vue_shared/components/pipeline_status_icon.js | 23 ++ .../javascripts/vue_shared/pipeline_svg_icons.js | 43 +++ app/assets/stylesheets/framework.scss | 1 + app/assets/stylesheets/framework/common.scss | 3 +- app/assets/stylesheets/framework/icons.scss | 3 +- app/assets/stylesheets/framework/memory_graph.scss | 16 + app/assets/stylesheets/framework/variables.scss | 1 + app/assets/stylesheets/pages/merge_requests.scss | 257 +++++++++++--- app/controllers/application_controller.rb | 5 +- app/controllers/projects/branches_controller.rb | 1 + app/controllers/projects/builds_controller.rb | 2 +- app/controllers/projects/commit_controller.rb | 2 +- app/controllers/projects/deployments_controller.rb | 14 + .../projects/environments_controller.rb | 18 +- .../projects/merge_requests_controller.rb | 167 ++++----- app/controllers/projects/pipelines_controller.rb | 6 +- app/helpers/issuables_helper.rb | 5 +- app/helpers/merge_requests_helper.rb | 54 --- app/models/deployment.rb | 15 + app/models/merge_request.rb | 4 +- app/models/project_services/monitoring_service.rb | 2 +- app/models/project_services/prometheus_service.rb | 25 +- app/presenters/merge_request_presenter.rb | 168 +++++++++ app/serializers/base_serializer.rb | 6 +- app/serializers/build_action_entity.rb | 2 +- app/serializers/build_entity.rb | 4 +- app/serializers/environment_entity.rb | 2 +- app/serializers/event_entity.rb | 4 + app/serializers/job_group_entity.rb | 2 +- app/serializers/merge_request_basic_entity.rb | 10 + app/serializers/merge_request_basic_serializer.rb | 3 + app/serializers/merge_request_entity.rb | 172 +++++++++ app/serializers/merge_request_serializer.rb | 8 +- app/serializers/pipeline_entity.rb | 8 +- app/serializers/pipeline_serializer.rb | 7 + app/serializers/stage_entity.rb | 2 +- app/views/layouts/nav/_project.html.haml | 2 +- app/views/projects/merge_requests/_show.html.haml | 45 +-- .../cancel_merge_when_pipeline_succeeds.js.haml | 2 - app/views/projects/merge_requests/merge.js.haml | 14 - .../merge_requests/widget/_closed.html.haml | 12 - .../widget/_commit_change_content.html.haml | 4 + .../merge_requests/widget/_heading.html.haml | 50 --- .../merge_requests/widget/_locked.html.haml | 9 - .../merge_requests/widget/_merged.html.haml | 52 --- .../merge_requests/widget/_merged_buttons.haml | 14 - .../projects/merge_requests/widget/_open.html.haml | 49 --- .../projects/merge_requests/widget/_show.html.haml | 40 --- .../merge_requests/widget/open/_accept.html.haml | 50 --- .../merge_requests/widget/open/_archived.html.haml | 4 - .../widget/open/_build_failed.html.haml | 6 - .../merge_requests/widget/open/_check.html.haml | 6 - .../widget/open/_conflicts.html.haml | 27 -- .../merge_requests/widget/open/_manual.html.haml | 4 - .../open/_merge_when_pipeline_succeeds.html.haml | 33 -- .../widget/open/_missing_branch.html.haml | 16 - .../widget/open/_not_allowed.html.haml | 6 - .../merge_requests/widget/open/_nothing.html.haml | 8 - .../merge_requests/widget/open/_reload.html.haml | 6 - .../widget/open/_sha_mismatch.html.haml | 6 - .../widget/open/_unresolved_discussions.html.haml | 10 - .../merge_requests/widget/open/_wip.html.haml | 11 - .../shared/issuable/form/_merge_params.html.haml | 9 - config/routes/project.rb | 9 +- config/webpack.config.js | 2 +- doc/user/project/integrations/prometheus.md | 9 + features/project/commits/revert.feature | 3 + features/project/merge_requests.feature | 7 + features/project/merge_requests/accept.feature | 3 +- features/steps/project/commits/revert.rb | 1 + features/steps/project/forked_merge_requests.rb | 3 + features/steps/project/merge_requests.rb | 25 +- .../steps/project/merge_requests/acceptance.rb | 18 +- features/steps/project/merge_requests/revert.rb | 4 +- features/steps/shared/paths.rb | 6 + features/support/env.rb | 2 +- lib/gitlab/prometheus.rb | 8 +- .../projects/branches_controller_spec.rb | 97 ++++- .../projects/deployments_controller_spec.rb | 55 ++- .../projects/environments_controller_spec.rb | 42 +++ .../projects/merge_requests_controller_spec.rb | 234 +++++-------- spec/features/boards/issue_ordering_spec.rb | 2 + ..._issue_for_discussions_in_merge_request_spec.rb | 8 +- spec/features/merge_requests/assign_issues_spec.rb | 2 +- ...f_mergeable_with_unresolved_discussions_spec.rb | 10 +- spec/features/merge_requests/cherry_pick_spec.rb | 2 +- spec/features/merge_requests/closes_issues_spec.rb | 15 +- .../merge_requests/created_from_fork_spec.rb | 2 +- .../merge_requests/deleted_source_branch_spec.rb | 4 +- spec/features/merge_requests/edit_mr_spec.rb | 12 - .../merge_commit_message_toggle_spec.rb | 19 +- .../merge_immediately_with_pipeline_spec.rb | 2 +- .../merge_when_pipeline_succeeds_spec.rb | 17 +- .../only_allow_merge_if_build_succeeds_spec.rb | 42 ++- spec/features/merge_requests/target_branch_spec.rb | 11 +- .../merge_requests/widget_deployments_spec.rb | 8 +- spec/features/merge_requests/widget_spec.rb | 33 +- .../api/schemas/entities/merge_request.json | 98 ++++++ .../api/schemas/entities/merge_request_basic.json | 14 + spec/helpers/merge_requests_helper_spec.rb | 192 ---------- spec/javascripts/commit/pipelines/mock_data.js | 1 + spec/javascripts/merge_request_widget_spec.js | 199 ----------- spec/javascripts/merged_buttons_spec.js | 44 --- spec/javascripts/test_bundle.js | 1 - .../components/mr_widget_author_spec.js | 39 +++ .../components/mr_widget_author_time_spec.js | 61 ++++ .../components/mr_widget_deployment_spec.js | 184 ++++++++++ .../components/mr_widget_header_spec.js | 95 +++++ .../components/mr_widget_merge_help_spec.js | 51 +++ .../components/mr_widget_pipeline_spec.js | 131 +++++++ .../components/mr_widget_related_links_spec.js | 138 ++++++++ .../components/states/mr_widget_archived_spec.js | 18 + .../states/mr_widget_auto_merge_failed_spec.js | 32 ++ .../components/states/mr_widget_checking_spec.js | 19 + .../components/states/mr_widget_closed_spec.js | 51 +++ .../components/states/mr_widget_conflicts_spec.js | 69 ++++ .../states/mr_widget_failed_to_merge_spec.js | 122 +++++++ .../components/states/mr_widget_locked_spec.js | 33 ++ .../mr_widget_merge_when_pipeline_succeeds_spec.js | 213 +++++++++++ .../components/states/mr_widget_merged_spec.js | 174 +++++++++ .../states/mr_widget_missing_branch_spec.js | 55 +++ .../states/mr_widget_not_allowed_spec.js | 17 + .../states/mr_widget_nothing_to_merge_spec.js | 17 + .../states/mr_widget_pipeline_blocked_spec.js | 16 + .../states/mr_widget_pipeline_failed_spec.js | 16 + .../states/mr_widget_ready_to_merge_spec.js | 389 +++++++++++++++++++++ .../mr_widget_unresolved_discussions_spec.js | 47 +++ .../components/states/mr_widget_wip_spec.js | 96 +++++ spec/javascripts/vue_mr_widget/mock_data.js | 214 ++++++++++++ .../vue_mr_widget/mr_widget_options_spec.js | 326 +++++++++++++++++ .../services/mr_widget_service_spec.js | 46 +++ .../vue_mr_widget/stores/get_state_key_spec.js | 62 ++++ spec/lib/gitlab/prometheus_spec.rb | 20 +- spec/models/deployment_spec.rb | 27 ++ .../project_services/prometheus_service_spec.rb | 23 +- spec/presenters/merge_request_presenter_spec.rb | 356 +++++++++++++++++++ spec/serializers/build_entity_spec.rb | 2 +- spec/serializers/build_serializer_spec.rb | 2 +- spec/serializers/deployment_entity_spec.rb | 2 +- spec/serializers/environment_serializer_spec.rb | 2 +- spec/serializers/event_entity_spec.rb | 13 + .../merge_request_basic_serializer_spec.rb | 12 + spec/serializers/merge_request_entity_spec.rb | 128 +++++++ spec/serializers/merge_request_serializer_spec.rb | 37 ++ spec/serializers/pipeline_entity_spec.rb | 4 +- spec/serializers/pipeline_serializer_spec.rb | 6 +- spec/serializers/stage_entity_spec.rb | 2 +- spec/support/prometheus_helpers.rb | 34 +- spec/support/wait_for_requests.rb | 8 +- spec/support/wait_for_vue_resource.rb | 14 +- 195 files changed, 7028 insertions(+), 1557 deletions(-) create mode 100644 app/assets/javascripts/lib/utils/simple_poll.js delete mode 100644 app/assets/javascripts/merge_request_widget/ci_bundle.js delete mode 100644 app/assets/javascripts/merged_buttons.js create mode 100644 app/assets/javascripts/pipelines/components/stage.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/mr_widget_memory_usage.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_locked.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/dependencies.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/event_hub.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/index.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js create mode 100644 app/assets/javascripts/vue_shared/components/memory_graph.js create mode 100644 app/assets/javascripts/vue_shared/components/pipeline_status_icon.js create mode 100644 app/assets/javascripts/vue_shared/pipeline_svg_icons.js create mode 100644 app/assets/stylesheets/framework/memory_graph.scss create mode 100644 app/presenters/merge_request_presenter.rb create mode 100644 app/serializers/event_entity.rb create mode 100644 app/serializers/merge_request_basic_entity.rb create mode 100644 app/serializers/merge_request_basic_serializer.rb delete mode 100644 app/views/projects/merge_requests/cancel_merge_when_pipeline_succeeds.js.haml delete mode 100644 app/views/projects/merge_requests/merge.js.haml delete mode 100644 app/views/projects/merge_requests/widget/_closed.html.haml create mode 100644 app/views/projects/merge_requests/widget/_commit_change_content.html.haml delete mode 100644 app/views/projects/merge_requests/widget/_heading.html.haml delete mode 100644 app/views/projects/merge_requests/widget/_locked.html.haml delete mode 100644 app/views/projects/merge_requests/widget/_merged.html.haml delete mode 100644 app/views/projects/merge_requests/widget/_merged_buttons.haml delete mode 100644 app/views/projects/merge_requests/widget/_open.html.haml delete mode 100644 app/views/projects/merge_requests/widget/_show.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_accept.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_archived.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_build_failed.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_check.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_conflicts.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_manual.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_merge_when_pipeline_succeeds.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_missing_branch.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_not_allowed.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_nothing.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_reload.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_sha_mismatch.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_unresolved_discussions.html.haml delete mode 100644 app/views/projects/merge_requests/widget/open/_wip.html.haml create mode 100644 spec/fixtures/api/schemas/entities/merge_request.json create mode 100644 spec/fixtures/api/schemas/entities/merge_request_basic.json delete mode 100644 spec/javascripts/merge_request_widget_spec.js delete mode 100644 spec/javascripts/merged_buttons_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/mr_widget_author_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/mr_widget_deployment_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/mr_widget_merge_help_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_closed_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_locked_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_wip_spec.js create mode 100644 spec/javascripts/vue_mr_widget/mock_data.js create mode 100644 spec/javascripts/vue_mr_widget/mr_widget_options_spec.js create mode 100644 spec/javascripts/vue_mr_widget/services/mr_widget_service_spec.js create mode 100644 spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js create mode 100644 spec/presenters/merge_request_presenter_spec.rb create mode 100644 spec/serializers/event_entity_spec.rb create mode 100644 spec/serializers/merge_request_basic_serializer_spec.rb create mode 100644 spec/serializers/merge_request_entity_spec.rb create mode 100644 spec/serializers/merge_request_serializer_spec.rb diff --git a/app/assets/javascripts/diff_notes/components/resolve_btn.js b/app/assets/javascripts/diff_notes/components/resolve_btn.js index 92f6fd654b3..9d51fb53eb2 100644 --- a/app/assets/javascripts/diff_notes/components/resolve_btn.js +++ b/app/assets/javascripts/diff_notes/components/resolve_btn.js @@ -88,6 +88,7 @@ const ResolveBtn = Vue.extend({ CommentsStore.update(this.discussionId, this.noteId, !this.isResolved, resolved_by); this.discussion.updateHeadline(data); + gl.mrWidget.checkStatus(); } else { new Flash(errorFlashMsg); } diff --git a/app/assets/javascripts/diff_notes/services/resolve.js b/app/assets/javascripts/diff_notes/services/resolve.js index 4ea6ba8a73d..ba4f6d36fcb 100644 --- a/app/assets/javascripts/diff_notes/services/resolve.js +++ b/app/assets/javascripts/diff_notes/services/resolve.js @@ -49,6 +49,7 @@ class ResolveServiceClass { discussion.resolveAllNotes(resolved_by); } + gl.mrWidget.checkStatus(); discussion.updateHeadline(data); } else { throw new Error('An error occurred when trying to resolve discussion.'); diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index bf802056d36..abb871c3af0 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -10,7 +10,6 @@ /* global IssuableForm */ /* global LabelsSelect */ /* global MilestoneSelect */ -/* global MergedButtons */ /* global Commit */ /* global NotificationsForm */ /* global TreeView */ @@ -216,15 +215,10 @@ const ShortcutsBlob = require('./shortcuts_blob'); new gl.Diff(); shortcut_handler = new ShortcutsIssuable(true); new ZenMode(); - new MergedButtons(); - break; - case 'projects:merge_requests:commits': - new MergedButtons(); break; case "projects:merge_requests:diffs": new gl.Diff(); new ZenMode(); - new MergedButtons(); break; case 'dashboard:activity': new gl.Activities(); diff --git a/app/assets/javascripts/lib/utils/simple_poll.js b/app/assets/javascripts/lib/utils/simple_poll.js new file mode 100644 index 00000000000..25ca98afbe7 --- /dev/null +++ b/app/assets/javascripts/lib/utils/simple_poll.js @@ -0,0 +1,15 @@ +export default (fn, interval = 2000, timeout = 60000) => { + const startTime = Date.now(); + + return new Promise((resolve, reject) => { + const stop = arg => ((arg instanceof Error) ? reject(arg) : resolve(arg)); + const next = () => { + if (Date.now() - startTime < timeout) { + setTimeout(fn.bind(null, next, stop), interval); + } else { + reject(new Error('SIMPLE_POLL_TIMEOUT')); + } + }; + fn(next, stop); + }); +}; diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index 1b0d5fc92e3..a07aa047293 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -123,8 +123,6 @@ import './member_expiration_date'; import './members'; import './merge_request'; import './merge_request_tabs'; -import './merge_request_widget'; -import './merged_buttons'; import './milestone'; import './milestone_select'; import './mini_pipeline_graph_dropdown'; diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js index 5e01aacf2ba..ed342b9990f 100644 --- a/app/assets/javascripts/merge_request.js +++ b/app/assets/javascripts/merge_request.js @@ -106,6 +106,21 @@ require('./merge_request_tabs'); }); }; + MergeRequest.prototype.updateStatusText = function(classToRemove, classToAdd, newStatusText) { + $('.detail-page-header .status-box') + .removeClass(classToRemove) + .addClass(classToAdd) + .find('span') + .text(newStatusText); + }; + + MergeRequest.prototype.decreaseCounter = function(by = 1) { + const $el = $('.nav-links .js-merge-counter'); + const count = Math.max((parseInt($el.text().replace(/[^\d]/, ''), 10) - by), 0); + + $el.text(gl.text.addDelimiter(count)); + }; + return MergeRequest; })(); }).call(window); diff --git a/app/assets/javascripts/merge_request_widget/ci_bundle.js b/app/assets/javascripts/merge_request_widget/ci_bundle.js deleted file mode 100644 index 21d7c3e168e..00000000000 --- a/app/assets/javascripts/merge_request_widget/ci_bundle.js +++ /dev/null @@ -1,53 +0,0 @@ -/* global merge_request_widget */ - -(() => { - $(() => { - /* TODO: This needs a better home, or should be refactored. It was previously contained - * in a script tag in app/views/projects/merge_requests/widget/open/_accept.html.haml, - * but Vue chokes on script tags and prevents their execution. So it was moved here - * temporarily. - * */ - - $(document) - .off('ajax:send', '.accept-mr-form') - .on('ajax:send', '.accept-mr-form', () => { - $('.accept-mr-form :input').disable(); - }); - - $(document) - .off('click', '.accept-merge-request') - .on('click', '.accept-merge-request', () => { - $('.js-merge-button, .js-merge-when-pipeline-succeeds-button').html(' Merge in progress'); - }); - - $(document) - .off('click', '.merge-when-pipeline-succeeds') - .on('click', '.merge-when-pipeline-succeeds', () => { - $('#merge_when_pipeline_succeeds').val('1'); - }); - - $(document) - .off('click', '.js-merge-dropdown a') - .on('click', '.js-merge-dropdown a', (e) => { - e.preventDefault(); - $(e.target).closest('form').submit(); - }); - if ($('.rebase-in-progress').length) { - merge_request_widget.rebaseInProgress(); - } else if ($('.rebase-mr-form').length) { - $(document) - .off('ajax:send', '.rebase-mr-form') - .on('ajax:send', '.rebase-mr-form', () => { - $('.rebase-mr-form :input').disable(); - }); - - $(document) - .off('click', '.js-rebase-button') - .on('click', '.js-rebase-button', () => { - $('.js-rebase-button').html(" Rebase in progress"); - }); - } else { - setTimeout(() => merge_request_widget.getMergeStatus(), 200); - } - }); -})(); diff --git a/app/assets/javascripts/merged_buttons.js b/app/assets/javascripts/merged_buttons.js deleted file mode 100644 index 7b0997c6520..00000000000 --- a/app/assets/javascripts/merged_buttons.js +++ /dev/null @@ -1,47 +0,0 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, max-len */ - -import '~/lib/utils/url_utility'; - -(function() { - this.MergedButtons = (function() { - function MergedButtons() { - this.removeSourceBranch = this.removeSourceBranch.bind(this); - this.removeBranchSuccess = this.removeBranchSuccess.bind(this); - this.removeBranchError = this.removeBranchError.bind(this); - this.$removeBranchWidget = $('.remove_source_branch_widget'); - this.$removeBranchProgress = $('.remove_source_branch_in_progress'); - this.$removeBranchFailed = $('.remove_source_branch_widget.failed'); - this.cleanEventListeners(); - this.initEventListeners(); - } - - MergedButtons.prototype.cleanEventListeners = function() { - $(document).off('click', '.remove_source_branch'); - $(document).off('ajax:success', '.remove_source_branch'); - return $(document).off('ajax:error', '.remove_source_branch'); - }; - - MergedButtons.prototype.initEventListeners = function() { - $(document).on('click', '.remove_source_branch', this.removeSourceBranch); - $(document).on('ajax:success', '.remove_source_branch', this.removeBranchSuccess); - $(document).on('ajax:error', '.remove_source_branch', this.removeBranchError); - }; - - MergedButtons.prototype.removeSourceBranch = function() { - this.$removeBranchWidget.hide(); - return this.$removeBranchProgress.show(); - }; - - MergedButtons.prototype.removeBranchSuccess = function() { - gl.utils.refreshCurrentPage(); - }; - - MergedButtons.prototype.removeBranchError = function() { - this.$removeBranchWidget.hide(); - this.$removeBranchProgress.hide(); - return this.$removeBranchFailed.show(); - }; - - return MergedButtons; - })(); -}).call(window); diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 55391ebc089..d2e602a0763 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -276,7 +276,7 @@ const normalizeNewlines = function(str) { var votesBlock; if (noteEntity.commands_changes) { if ('merge' in noteEntity.commands_changes) { - $.get(mrRefreshWidgetUrl); + Notes.checkMergeRequestStatus(); } if ('emoji_award' in noteEntity.commands_changes) { @@ -424,6 +424,7 @@ const normalizeNewlines = function(str) { } gl.utils.localTimeAgo($('.js-timeago'), false); + Notes.checkMergeRequestStatus(); return this.updateNotesCount(1); }; @@ -769,7 +770,8 @@ const normalizeNewlines = function(str) { } }; })(this)); - // Decrement the "Discussions" counter only once + + Notes.checkMergeRequestStatus(); return this.updateNotesCount(-1); }; @@ -1115,6 +1117,12 @@ const normalizeNewlines = function(str) { return $form; }; + Notes.checkMergeRequestStatus = function() { + if (gl.utils.getPagePath(1) === 'merge_requests') { + gl.mrWidget.checkStatus(); + } + }; + Notes.animateAppendNote = function(noteHtml, $notesList) { const $note = $(noteHtml); diff --git a/app/assets/javascripts/pipelines/components/stage.js b/app/assets/javascripts/pipelines/components/stage.js new file mode 100644 index 00000000000..034e8d3280e --- /dev/null +++ b/app/assets/javascripts/pipelines/components/stage.js @@ -0,0 +1,104 @@ +/* global Flash */ +import { borderlessStatusIconEntityMap } from '../../vue_shared/ci_status_icons'; + +export default { + data() { + return { + builds: '', + spinner: '', + }; + }, + + props: { + stage: { + type: Object, + required: true, + }, + }, + + updated() { + if (this.builds) { + this.stopDropdownClickPropagation(); + } + }, + + methods: { + fetchBuilds(e) { + const ariaExpanded = e.currentTarget.attributes['aria-expanded']; + + if (ariaExpanded && (ariaExpanded.textContent === 'true')) return null; + + return this.$http.get(this.stage.dropdown_path) + .then((response) => { + this.builds = JSON.parse(response.body).html; + }, () => { + const flash = new Flash('Something went wrong on our end.'); + return flash; + }); + }, + + /** + * When the user right clicks or cmd/ctrl + click in the job name + * the dropdown should not be closed and the link should open in another tab, + * so we stop propagation of the click event inside the dropdown. + * + * Since this component is rendered multiple times per page we need to guarantee we only + * target the click event of this component. + */ + stopDropdownClickPropagation() { + $(this.$el.querySelectorAll('.js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item')).on('click', (e) => { + e.stopPropagation(); + }); + }, + }, + computed: { + buildsOrSpinner() { + return this.builds ? this.builds : this.spinner; + }, + dropdownClass() { + if (this.builds) return 'js-builds-dropdown-container'; + return 'js-builds-dropdown-loading builds-dropdown-loading'; + }, + buildStatus() { + return `Build: ${this.stage.status.label}`; + }, + tooltip() { + return `has-tooltip ci-status-icon ci-status-icon-${this.stage.status.group}`; + }, + triggerButtonClass() { + return `mini-pipeline-graph-dropdown-toggle has-tooltip js-builds-dropdown-button ci-status-icon-${this.stage.status.group}`; + }, + svgHTML() { + return borderlessStatusIconEntityMap[this.stage.status.icon]; + }, + }, + watch: { + 'stage.title': function stageTitle() { + $(this.$refs.button).tooltip('destroy').tooltip(); + }, + }, + template: ` +
+ + +
+ `, +}; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js new file mode 100644 index 00000000000..a01cb8cc202 --- /dev/null +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.js @@ -0,0 +1,23 @@ +export default { + name: 'MRWidgetAuthor', + props: { + author: { type: Object, required: true }, + showAuthorName: { type: Boolean, required: false, default: true }, + showAuthorTooltip: { type: Boolean, required: false, default: false }, + }, + template: ` + + + {{author.name}} + + + `, +}; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.js new file mode 100644 index 00000000000..6d2ed5fda64 --- /dev/null +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.js @@ -0,0 +1,27 @@ +import MRWidgetAuthor from './mr_widget_author'; + +export default { + name: 'MRWidgetAuthorTime', + props: { + actionText: { type: String, required: true }, + author: { type: Object, required: true }, + dateTitle: { type: String, required: true }, + dateReadable: { type: String, required: true }, + }, + components: { + 'mr-widget-author': MRWidgetAuthor, + }, + template: ` +

+ {{actionText}} + + +

+ `, +}; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js new file mode 100644 index 00000000000..630e80a7408 --- /dev/null +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js @@ -0,0 +1,118 @@ +/* global Flash */ + +import '~/lib/utils/datetime_utility'; +import { statusClassToSvgMap } from '../../vue_shared/pipeline_svg_icons'; +import MemoryUsage from './mr_widget_memory_usage'; +import MRWidgetService from '../services/mr_widget_service'; + +export default { + name: 'MRWidgetDeployment', + props: { + mr: { type: Object, required: true }, + service: { type: Object, required: true }, + }, + components: { + 'mr-widget-memory-usage': MemoryUsage, + }, + computed: { + svg() { + return statusClassToSvgMap.icon_status_success; + }, + }, + methods: { + formatDate(date) { + return gl.utils.getTimeago().format(date); + }, + hasExternalUrls(deployment = {}) { + return deployment.external_url && deployment.external_url_formatted; + }, + hasDeploymentTime(deployment = {}) { + return deployment.deployed_at && deployment.deployed_at_formatted; + }, + hasDeploymentMeta(deployment = {}) { + return deployment.url && deployment.name; + }, + stopEnvironment(deployment) { + const msg = 'Are you sure you want to stop this environment?'; + const isConfirmed = confirm(msg); // eslint-disable-line + + if (isConfirmed) { + MRWidgetService.stopEnvironment(deployment.stop_url) + .then(res => res.json()) + .then((res) => { + if (res.redirect_url) { + gl.utils.visitUrl(res.redirect_url); + } + }) + .catch(() => { + new Flash('Something went wrong while stopping this environment. Please try again.'); // eslint-disable-line + }); + } + }, + }, + template: ` +
+
+
+
+ + + +
+ + + Deployed to + + + {{deployment.name}} + + + on + + +