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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/issuable/popover/index.js')
-rw-r--r--app/assets/javascripts/issuable/popover/index.js85
1 files changed, 85 insertions, 0 deletions
diff --git a/app/assets/javascripts/issuable/popover/index.js b/app/assets/javascripts/issuable/popover/index.js
new file mode 100644
index 00000000000..de3c8160b7a
--- /dev/null
+++ b/app/assets/javascripts/issuable/popover/index.js
@@ -0,0 +1,85 @@
+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,
+ 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);
+ }
+ });
+ }
+};