Welcome to mirror list, hosted at ThFree Co, Russian Federation.

index.js « popover « issuable « javascripts « assets « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9430419685bdab0c5987a9ca39f61740f1e69ee8 (plain)
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import IssuePopover from './components/issue_popover.vue';
import MRPopover from './components/mr_popover.vue';

const componentsByReferenceType = {
  issue: IssuePopover,
  work_item: IssuePopover,
  merge_request: MRPopover,
};

let renderFn;

const handleIssuablePopoverMouseOut = ({ target }) => {
  target.removeEventListener('mouseleave', handleIssuablePopoverMouseOut);

  if (renderFn) {
    clearTimeout(renderFn);
  }
};

const popoverMountedAttr = 'data-popover-mounted';

/**
 * 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 handleIssuablePopoverMount = ({
  apolloProvider,
  projectPath,
  title,
  iid,
  referenceType,
  target,
}) => {
  // Add listener to actually remove it again
  target.addEventListener('mouseleave', handleIssuablePopoverMouseOut);

  renderFn = setTimeout(() => {
    const PopoverComponent = Vue.extend(componentsByReferenceType[referenceType]);
    new PopoverComponent({
      propsData: {
        target,
        projectPath,
        iid,
        cachedTitle: title,
      },
      apolloProvider,
    }).$mount();

    target.setAttribute(popoverMountedAttr, true);
  }, 200); // 200ms delay so not every mouseover triggers Popover + API Call
};

export default (elements) => {
  if (elements.length > 0) {
    Vue.use(VueApollo);

    const apolloProvider = new VueApollo({
      defaultClient: createDefaultClient(),
    });
    const listenerAddedAttr = 'data-popover-listener-added';

    elements.forEach((el) => {
      const { projectPath, iid, referenceType } = el.dataset;
      const title = el.dataset.mrTitle || el.title;

      if (!el.getAttribute(listenerAddedAttr) && projectPath && title && iid && referenceType) {
        el.addEventListener('mouseenter', ({ target }) => {
          if (!el.getAttribute(popoverMountedAttr)) {
            handleIssuablePopoverMount({
              apolloProvider,
              projectPath,
              title,
              iid,
              referenceType,
              target,
            });
          }
        });
        el.setAttribute(listenerAddedAttr, true);
      }
    });
  }
};