Skip to content
Snippets Groups Projects
Commit d3e4f155 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu :basketball:
Browse files

Merge branch '25607-issue-reference-popovers' into 'master'

Rename `mr_popover` to `issuable/popover`

See merge request gitlab-org/gitlab!87918
parents 941b6a97 cc258eb4
No related branches found
No related tags found
No related merge requests found
Showing
with 36 additions and 34 deletions
Loading
Loading
@@ -137,7 +137,7 @@ Dangerfile @gl-quality/eng-prod
/app/assets/javascripts/notes @viktomas @jboyson @iamphill @thomasrandolph
/app/assets/javascripts/merge_conflicts @viktomas @jboyson @iamphill @thomasrandolph
/app/assets/javascripts/mr_notes @viktomas @jboyson @iamphill @thomasrandolph
/app/assets/javascripts/mr_popover @viktomas @jboyson @iamphill @thomasrandolph
/app/assets/javascripts/issuable/popover @viktomas @jboyson @iamphill @thomasrandolph
/app/assets/javascripts/vue_merge_request_widget @viktomas @jboyson @iamphill @thomasrandolph
/app/assets/javascripts/merge_request.js @viktomas @jboyson @iamphill @thomasrandolph
/app/assets/javascripts/merge_request_tabs.js @viktomas @jboyson @iamphill @thomasrandolph
Loading
Loading
Loading
Loading
@@ -24,11 +24,11 @@ $.fn.renderGFM = function renderGFM() {
highlightCurrentUser(this.find('.gfm-project_member').get());
initUserPopovers(this.find('.js-user-link').get());
 
const mrPopoverElements = this.find('.gfm-merge_request').get();
if (mrPopoverElements.length) {
import(/* webpackChunkName: 'MrPopoverBundle' */ '~/mr_popover')
.then(({ default: initMRPopovers }) => {
initMRPopovers(mrPopoverElements);
const issuablePopoverElements = this.find('.gfm-merge_request').get();
if (issuablePopoverElements.length) {
import(/* webpackChunkName: 'IssuablePopoverBundle' */ '~/issuable/popover')
.then(({ default: initIssuablePopovers }) => {
initIssuablePopovers(issuablePopoverElements);
})
.catch(() => {});
}
Loading
Loading
Loading
Loading
@@ -6,8 +6,8 @@ import MRPopover from './components/mr_popover.vue';
let renderedPopover;
let renderFn;
 
const handleUserPopoverMouseOut = ({ target }) => {
target.removeEventListener('mouseleave', handleUserPopoverMouseOut);
const handleIssuablePopoverMouseOut = ({ target }) => {
target.removeEventListener('mouseleave', handleIssuablePopoverMouseOut);
 
if (renderFn) {
clearTimeout(renderFn);
Loading
Loading
@@ -22,9 +22,11 @@ const handleUserPopoverMouseOut = ({ target }) => {
* Adds a MergeRequestPopover component to the body, hands over as much data as the target element has in data attributes.
* loads based on data-project-path and data-iid more data about an MR from the API and sets it on the popover
*/
const handleMRPopoverMount = ({ apolloProvider, projectPath, mrTitle, iid }) => ({ target }) => {
const handleIssuablePopoverMount = ({ apolloProvider, projectPath, title, iid }) => ({
target,
}) => {
// Add listener to actually remove it again
target.addEventListener('mouseleave', handleUserPopoverMouseOut);
target.addEventListener('mouseleave', handleIssuablePopoverMouseOut);
 
renderFn = setTimeout(() => {
const MRPopoverComponent = Vue.extend(MRPopover);
Loading
Loading
@@ -33,7 +35,7 @@ const handleMRPopoverMount = ({ apolloProvider, projectPath, mrTitle, iid }) =>
target,
projectPath,
mergeRequestIID: iid,
mergeRequestTitle: mrTitle,
mergeRequestTitle: title,
},
apolloProvider,
});
Loading
Loading
@@ -43,22 +45,22 @@ const handleMRPopoverMount = ({ apolloProvider, projectPath, mrTitle, iid }) =>
};
 
export default (elements) => {
const mrLinks = elements || [...document.querySelectorAll('.gfm-merge_request')];
if (mrLinks.length > 0) {
if (elements.length > 0) {
Vue.use(VueApollo);
 
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
const listenerAddedAttr = 'data-mr-listener-added';
const listenerAddedAttr = 'data-popover-listener-added';
 
mrLinks.forEach((el) => {
const { projectPath, mrTitle, iid } = el.dataset;
elements.forEach((el) => {
const { projectPath, iid } = el.dataset;
const title = el.dataset.mrTitle || el.title;
 
if (!el.getAttribute(listenerAddedAttr) && projectPath && mrTitle && iid) {
if (!el.getAttribute(listenerAddedAttr) && projectPath && title && iid) {
el.addEventListener(
'mouseenter',
handleMRPopoverMount({ apolloProvider, projectPath, mrTitle, iid }),
handleIssuablePopoverMount({ apolloProvider, projectPath, title, iid }),
);
el.setAttribute(listenerAddedAttr, true);
}
Loading
Loading
Loading
Loading
@@ -26,9 +26,9 @@ import {
import $ from 'jquery';
import { mapGetters, mapActions, mapState } from 'vuex';
import descriptionVersionHistoryMixin from 'ee_else_ce/notes/mixins/description_version_history';
import '~/behaviors/markdown/render_gfm';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import initMRPopovers from '~/mr_popover/';
import noteHeader from '~/notes/components/note_header.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { spriteIcon } from '~/lib/utils/common_utils';
Loading
Loading
@@ -94,7 +94,7 @@ export default {
},
},
mounted() {
initMRPopovers(this.$el.querySelectorAll('.gfm-merge_request'));
$(this.$refs['gfm-content']).renderGFM();
},
methods: {
...mapActions(['fetchDescriptionVersion', 'softDeleteDescriptionVersion']),
Loading
Loading
@@ -130,7 +130,7 @@ export default {
<div class="timeline-content">
<div class="note-header">
<note-header :author="note.author" :created-at="note.created_at" :note-id="note.id">
<span v-safe-html="actionTextHtml"></span>
<span ref="gfm-content" v-safe-html="actionTextHtml"></span>
<template
v-if="canSeeDescriptionVersion || note.outdated_line_change_path"
#extra-controls
Loading
Loading
Loading
Loading
@@ -12,7 +12,7 @@ import { spriteIcon } from '~/lib/utils/common_utils';
import { s__, n__, __, sprintf } from '~/locale';
import { componentNames } from 'ee/reports/components/issue_body';
import { fetchPolicies } from '~/lib/graphql';
import { mrStates } from '~/mr_popover/constants';
import { mrStates } from '~/issuable/popover/constants';
import GroupedIssuesList from '~/reports/components/grouped_issues_list.vue';
import ReportSection from '~/reports/components/report_section.vue';
import SummaryRow from '~/reports/components/summary_row.vue';
Loading
Loading
Loading
Loading
@@ -12,7 +12,7 @@ import { trimText } from 'helpers/text_helper';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import { waitForMutation } from 'helpers/vue_test_utils_helper';
import axios from '~/lib/utils/axios_utils';
import { mrStates } from '~/mr_popover/constants';
import { mrStates } from '~/issuable/popover/constants';
import GroupedIssuesList from '~/reports/components/grouped_issues_list.vue';
import ReportSection from '~/reports/components/report_section.vue';
import MergeRequestArtifactDownload from '~/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue';
Loading
Loading
import { setHTMLFixture } from 'helpers/fixtures';
import * as createDefaultClient from '~/lib/graphql';
import initMRPopovers from '~/mr_popover/index';
import initIssuablePopovers from '~/issuable/popover/index';
 
createDefaultClient.default = jest.fn();
 
describe('initMRPopovers', () => {
describe('initIssuablePopovers', () => {
let mr1;
let mr2;
let mr3;
Loading
Loading
@@ -14,7 +14,7 @@ describe('initMRPopovers', () => {
<div id="one" class="gfm-merge_request" data-mr-title="title" data-iid="1" data-project-path="group/project">
MR1
</div>
<div id="two" class="gfm-merge_request" data-mr-title="title" data-iid="1" data-project-path="group/project">
<div id="two" class="gfm-merge_request" title="title" data-iid="1" data-project-path="group/project">
MR2
</div>
<div id="three" class="gfm-merge_request">
Loading
Loading
@@ -32,14 +32,14 @@ describe('initMRPopovers', () => {
});
 
it('does not add the same event listener twice', () => {
initMRPopovers([mr1, mr1, mr2]);
initIssuablePopovers([mr1, mr1, mr2]);
 
expect(mr1.addEventListener).toHaveBeenCalledTimes(1);
expect(mr2.addEventListener).toHaveBeenCalledTimes(1);
});
 
it('does not add listener if it does not have the necessary data attributes', () => {
initMRPopovers([mr1, mr2, mr3]);
initIssuablePopovers([mr1, mr2, mr3]);
 
expect(mr3.addEventListener).not.toHaveBeenCalled();
});
Loading
Loading
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import MRPopover from '~/mr_popover/components/mr_popover.vue';
import MRPopover from '~/issuable/popover/components/mr_popover.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
 
describe('MR Popover', () => {
Loading
Loading
import MockAdapter from 'axios-mock-adapter';
import { mount } from '@vue/test-utils';
import $ from 'jquery';
import waitForPromises from 'helpers/wait_for_promises';
import initMRPopovers from '~/mr_popover/index';
import createStore from '~/notes/stores';
import IssueSystemNote from '~/vue_shared/components/notes/system_note.vue';
import axios from '~/lib/utils/axios_utils';
 
jest.mock('~/mr_popover/index', () => jest.fn());
describe('system note component', () => {
let vm;
let props;
Loading
Loading
@@ -76,10 +74,12 @@ describe('system note component', () => {
expect(vm.find('.system-note-message').html()).toContain('<span>closed</span>');
});
 
it('should initMRPopovers onMount', () => {
it('should renderGFM onMount', () => {
const renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
createComponent(props);
 
expect(initMRPopovers).toHaveBeenCalled();
expect(renderGFMSpy).toHaveBeenCalled();
});
 
it('renders outdated code lines', async () => {
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment