All files / app/assets/javascripts/mr_popover index.js

54.17% Statements 13/24
64.29% Branches 9/14
50% Functions 3/6
52.17% Lines 12/23

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68                14x                               14x                                         7x 7x 2x   2x     2x   2x 6x   6x 4x       4x          
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import MRPopover from './components/mr_popover.vue';
 
let renderedPopover;
let renderFn;
 
const handleUserPopoverMouseOut = ({ target }) => {
  target.removeEventListener('mouseleave', handleUserPopoverMouseOut);
 
  if (renderFn) {
    clearTimeout(renderFn);
  }
  if (renderedPopover) {
    renderedPopover.$destroy();
    renderedPopover = null;
  }
};
 
/**
 * 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 }) => {
  // Add listener to actually remove it again
  target.addEventListener('mouseleave', handleUserPopoverMouseOut);
 
  renderFn = setTimeout(() => {
    const MRPopoverComponent = Vue.extend(MRPopover);
    renderedPopover = new MRPopoverComponent({
      propsData: {
        target,
        projectPath,
        mergeRequestIID: iid,
        mergeRequestTitle: mrTitle,
      },
      apolloProvider,
    });
 
    renderedPopover.$mount();
  }, 200); // 200ms delay so not every mouseover triggers Popover + API Call
};
 
export default (elements) => {
  const mrLinks = elements || [...document.querySelectorAll('.gfm-merge_request')];
  if (mrLinks.length > 0) {
    Vue.use(VueApollo);
 
    const apolloProvider = new VueApollo({
      defaultClient: createDefaultClient(),
    });
    const listenerAddedAttr = 'data-mr-listener-added';
 
    mrLinks.forEach((el) => {
      const { projectPath, mrTitle, iid } = el.dataset;
 
      if (!el.getAttribute(listenerAddedAttr) && projectPath && mrTitle && iid) {
        el.addEventListener(
          'mouseenter',
          handleMRPopoverMount({ apolloProvider, projectPath, mrTitle, iid }),
        );
        el.setAttribute(listenerAddedAttr, true);
      }
    });
  }
};