diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js b/app/assets/javascripts/mini_pipeline_graph_dropdown.js index 2145e531331daa00c2405a68f8cda7ef355f4079..483c201305a831c1e1a60eb5a3fff7d504c5c33f 100644 --- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js +++ b/app/assets/javascripts/mini_pipeline_graph_dropdown.js @@ -21,6 +21,8 @@ this.container = opts.container || ''; this.dropdownListSelector = '.js-builds-dropdown-container'; this.getBuildsList = this.getBuildsList.bind(this); + + this.stopDropdownClickPropagation(); } /** @@ -31,6 +33,20 @@ $(document).off('shown.bs.dropdown', this.container).on('shown.bs.dropdown', this.container, this.getBuildsList); } + /** + * 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() { + $(document).on('click', `${this.container} .js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item`, (e) => { + e.stopPropagation(); + }); + } + /** * For the clicked stage, renders the given data in the dropdown list. * diff --git a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js index 7cdade01e00151b2bba0187c9b109c214ce54bf6..f6b3dc87cd87d58c468b26b74a55fee428669dba 100644 --- a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js +++ b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js @@ -46,6 +46,21 @@ require('~/mini_pipeline_graph_dropdown'); document.querySelector('.js-builds-dropdown-button').click(); expect(ajaxSpy.calls.allArgs()[0][0].url).toEqual('foobar'); }); + + it('should not close when user uses cmd/ctrl + click', () => { + spyOn($, 'ajax').and.callFake(function (params) { + params.success({ + html: '\u003cli\u003e\n\u003ca class="mini-pipeline-graph-dropdown-item" href="#"\u003e\u003cspan class="ci-status-icon ci-status-icon-failed"\u003e\u003c/span\u003e\n\u003cspan class="ci-build-text"\u003ebuild\u003c/span\u003e\n\u003c/a\u003e\u003ca class="ci-action-icon-wrapper js-ci-action-icon" href="#"\u003e\u003c/a\u003e\n\u003c/li\u003e\n', + }); + }); + new gl.MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents(); + + document.querySelector('.js-builds-dropdown-button').click(); + + document.querySelector('a.mini-pipeline-graph-dropdown-item').click(); + + expect($('.js-builds-dropdown-list').is(':visible')).toEqual(true); + }); }); }); })();