diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-03-29 15:09:53 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-03-29 15:09:53 +0000 |
commit | 9c28b22cfc7b2b9306b9c72d53f5c88c3129eb67 (patch) | |
tree | 92e5e3ac55cfa092d473abca506546cf56e2215c /app/assets/javascripts | |
parent | ef59e05bd14aea8bf19bbe77c52116bfe24c7107 (diff) | |
download | gitlab-ce-9c28b22cfc7b2b9306b9c72d53f5c88c3129eb67.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts')
7 files changed, 74 insertions, 68 deletions
diff --git a/app/assets/javascripts/behaviors/markdown/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js index c4e09efe263..4bfce12c7c5 100644 --- a/app/assets/javascripts/behaviors/markdown/render_gfm.js +++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js @@ -1,6 +1,5 @@ import $ from 'jquery'; import syntaxHighlight from '~/syntax_highlight'; -import initUserPopovers from '../../user_popovers'; import highlightCurrentUser from './highlight_current_user'; import renderMath from './render_math'; import renderMermaid from './render_mermaid'; @@ -20,7 +19,6 @@ $.fn.renderGFM = function renderGFM() { renderMermaid(this.find('.js-render-mermaid')); } 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) { diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue index ba10f6deb29..8d0f6079f8f 100644 --- a/app/assets/javascripts/diffs/components/commit_item.vue +++ b/app/assets/javascripts/diffs/components/commit_item.vue @@ -7,8 +7,6 @@ import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; -import initUserPopovers from '../../user_popovers'; - /** * CommitItem * @@ -82,11 +80,6 @@ export default { return this.commit.description_html.replace(/^
/, ''); }, }, - created() { - this.$nextTick(() => { - initUserPopovers(this.$el.querySelectorAll('.js-user-link')); - }); - }, safeHtmlConfig: { ADD_TAGS: ['gl-emoji'], }, diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js index fa605f8c056..24ec16bf20e 100644 --- a/app/assets/javascripts/flash.js +++ b/app/assets/javascripts/flash.js @@ -94,10 +94,10 @@ const addDismissFlashClickListener = (flashEl, fadeTransition) => { * * 1. Render a new alert * - * import { createAlert, ALERT_VARIANTS } from '~/flash'; + * import { createAlert, VARIANT_WARNING } from '~/flash'; * * createAlert({ message: 'My error message' }); - * createAlert({ message: 'My warning message', variant: ALERT_VARIANTS.WARNING }); + * createAlert({ message: 'My warning message', variant: VARIANT_WARNING }); * * 2. Dismiss this alert programmatically * diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue index 0b97ce7e33e..660fbd79fe3 100644 --- a/app/assets/javascripts/members/components/table/members_table.vue +++ b/app/assets/javascripts/members/components/table/members_table.vue @@ -4,7 +4,6 @@ import { mapState } from 'vuex'; import MembersTableCell from 'ee_else_ce/members/components/table/members_table_cell.vue'; import { canOverride, canRemove, canResend, canUpdate } from 'ee_else_ce/members/utils'; import { mergeUrlParams } from '~/lib/utils/url_utility'; -import initUserPopovers from '~/user_popovers'; import UserDate from '~/vue_shared/components/user_date.vue'; import { FIELD_KEY_ACTIONS, @@ -85,9 +84,6 @@ export default { return this.tabQueryParamValue === TAB_QUERY_PARAM_VALUES.invite; }, }, - mounted() { - initUserPopovers(this.$el.querySelectorAll('.js-user-link')); - }, methods: { hasActionButtons(member) { return ( diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index c4924cd41f5..c8af3c744e8 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -3,7 +3,6 @@ import { mapGetters, mapActions } from 'vuex'; import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user'; import createFlash from '~/flash'; import { __ } from '~/locale'; -import initUserPopovers from '~/user_popovers'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import OrderedLayout from '~/vue_shared/components/ordered_layout.vue'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; @@ -169,7 +168,6 @@ export default { updated() { this.$nextTick(() => { highlightCurrentUser(this.$el.querySelectorAll('.gfm-project_member')); - initUserPopovers(this.$el.querySelectorAll('.js-user-link')); }); }, beforeDestroy() { diff --git a/app/assets/javascripts/user_popovers.js b/app/assets/javascripts/user_popovers.js index 4544373d8aa..597b96ae18c 100644 --- a/app/assets/javascripts/user_popovers.js +++ b/app/assets/javascripts/user_popovers.js @@ -57,41 +57,35 @@ const populateUserInfo = (user) => { ); }; -const initializedPopovers = new Map(); -let domObservedForChanges = false; +function initPopover(el, user, mountPopover) { + const preloadedUserInfo = getPreloadedUserInfo(el.dataset); -const addPopoversToModifiedTree = new MutationObserver(() => { - const userLinks = document?.querySelectorAll('.js-user-link, .gfm-project_member'); + Object.assign(user, preloadedUserInfo); - if (userLinks) { - addPopovers(userLinks); /* eslint-disable-line no-use-before-define */ + if (preloadedUserInfo.userId) { + populateUserInfo(user); } -}); - -function observeBody() { - if (!domObservedForChanges) { - addPopoversToModifiedTree.observe(document.body, { - subtree: true, - childList: true, - }); - - domObservedForChanges = true; - } -} - -export default function addPopovers(elements = document.querySelectorAll('.js-user-link')) { - const userLinks = Array.from(elements); const UserPopoverComponent = Vue.extend(UserPopover); + const popoverInstance = new UserPopoverComponent({ + propsData: { + target: el, + user, + }, + }); + mountPopover(popoverInstance); + // wait for component to actually mount + setTimeout(() => { + // trigger an event to force tooltip to show + const event = new MouseEvent('mouseenter'); + event.isSelfTriggered = true; + el.dispatchEvent(event); + }); +} - observeBody(); - - return userLinks - .filter(({ dataset }) => dataset.user || dataset.userId) - .map((el) => { - if (initializedPopovers.has(el)) { - return initializedPopovers.get(el); - } - +function initPopovers(userLinks, mountPopover) { + userLinks + .filter(({ dataset, user }) => !user && (dataset.user || dataset.userId)) + .forEach((el) => { const user = { location: null, bio: null, @@ -99,31 +93,60 @@ export default function addPopovers(elements = document.querySelectorAll('.js-us status: null, loaded: false, }; - const renderedPopover = new UserPopoverComponent({ - propsData: { - target: el, - user, - }, + el.user = user; + const init = initPopover.bind(null, el, user, mountPopover); + el.addEventListener('mouseenter', init, { once: true }); + el.addEventListener('mouseenter', ({ target, isSelfTriggered }) => { + if (!isSelfTriggered) return; + removeTitle(target); }); + el.addEventListener('mouseleave', ({ target }) => { + target.removeAttribute('aria-describedby'); + }); + }); +} - initializedPopovers.set(el, renderedPopover); +const userLinkSelector = 'a.js-user-link, a.gfm-project_member'; - renderedPopover.$mount(); +const getUserLinkNodes = (node) => { + if (!('matches' in node)) return null; + if (node.matches(userLinkSelector)) return [node]; + return Array.from(node.querySelectorAll(userLinkSelector)); +}; - el.addEventListener('mouseenter', ({ target }) => { - removeTitle(target); - const preloadedUserInfo = getPreloadedUserInfo(target.dataset); +let observer; - Object.assign(user, preloadedUserInfo); +export default function addPopovers( + elements = document.querySelectorAll('.js-user-link'), + mountPopover = (popoverInstance) => popoverInstance.$mount(), +) { + const userLinks = Array.from(elements); - if (preloadedUserInfo.userId) { - populateUserInfo(user); - } - }); - el.addEventListener('mouseleave', ({ target }) => { - target.removeAttribute('aria-describedby'); - }); + initPopovers(userLinks, mountPopover); + + if (!observer) { + observer = new MutationObserver((mutationsList) => { + const newUserLinks = mutationsList + .filter((mutation) => mutation.type === 'childList' && mutation.addedNodes) + .reduce((acc, mutation) => { + const userLinkNodes = Array.from(mutation.addedNodes) + .flatMap(getUserLinkNodes) + .filter(Boolean); + acc.push(...userLinkNodes); + return acc; + }, []); + + if (newUserLinks.length !== 0) { + initPopovers(newUserLinks, mountPopover); + } + }); + observer.observe(document.body, { + subtree: true, + childList: true, + }); - return renderedPopover; + document.addEventListener('beforeunload', () => { + observer.disconnect(); }); + } } diff --git a/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue b/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue index d595c49f9aa..5f6490a9f3f 100644 --- a/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue +++ b/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue @@ -18,7 +18,6 @@ import { toggleContainerClasses } from '~/lib/utils/dom_utils'; import { visitUrl, joinPaths } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; import Tracking from '~/tracking'; -import initUserPopovers from '~/user_popovers'; import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import { PAGE_CONFIG, SEVERITY_LEVELS } from '../constants'; @@ -175,7 +174,6 @@ export default { updated() { this.$nextTick(() => { highlightCurrentUser(this.$el.querySelectorAll('.gfm-project_member')); - initUserPopovers(this.$el.querySelectorAll('.js-user-link')); }); }, methods: { |