diff options
author | Tim Zallmann <tzallmann@gitlab.com> | 2018-12-08 03:12:23 +0000 |
---|---|---|
committer | Clement Ho <clemmakesapps@gmail.com> | 2018-12-08 03:12:23 +0000 |
commit | ddd4cc649f31b490a73e65808d828b2f51ca1917 (patch) | |
tree | fed840b9cd9f9ddc3a8ef96814508c0470d5b38a /app/assets/javascripts/user_popovers.js | |
parent | a89b5269502a0250c7507f3bb1350a7ba602822b (diff) | |
download | gitlab-ce-ddd4cc649f31b490a73e65808d828b2f51ca1917.tar.gz |
Resolve "Extended user centric tooltips"
Diffstat (limited to 'app/assets/javascripts/user_popovers.js')
-rw-r--r-- | app/assets/javascripts/user_popovers.js | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/app/assets/javascripts/user_popovers.js b/app/assets/javascripts/user_popovers.js new file mode 100644 index 00000000000..948f4d5e631 --- /dev/null +++ b/app/assets/javascripts/user_popovers.js @@ -0,0 +1,107 @@ +import Vue from 'vue'; + +import UsersCache from './lib/utils/users_cache'; +import UserPopover from './vue_shared/components/user_popover/user_popover.vue'; + +let renderedPopover; +let renderFn; + +const handleUserPopoverMouseOut = event => { + const { target } = event; + target.removeEventListener('mouseleave', handleUserPopoverMouseOut); + + if (renderFn) { + clearTimeout(renderFn); + } + if (renderedPopover) { + renderedPopover.$destroy(); + renderedPopover = null; + } +}; + +/** + * Adds a UserPopover component to the body, hands over as much data as the target element has in data attributes. + * loads based on data-user-id more data about a user from the API and sets it on the popover + */ +const handleUserPopoverMouseOver = event => { + const { target } = event; + // Add listener to actually remove it again + target.addEventListener('mouseleave', handleUserPopoverMouseOut); + + renderFn = setTimeout(() => { + // Helps us to use current markdown setup without maybe breaking or duplicating for now + if (target.dataset.user) { + target.dataset.userId = target.dataset.user; + // Removing titles so its not showing tooltips also + target.dataset.originalTitle = ''; + target.setAttribute('title', ''); + } + + const { userId, username, name, avatarUrl } = target.dataset; + const user = { + userId, + username, + name, + avatarUrl, + location: null, + bio: null, + organization: null, + status: null, + loaded: false, + }; + if (userId || username) { + const UserPopoverComponent = Vue.extend(UserPopover); + renderedPopover = new UserPopoverComponent({ + propsData: { + target, + user, + }, + }); + + renderedPopover.$mount(); + + UsersCache.retrieveById(userId) + .then(userData => { + if (!userData) { + return; + } + + Object.assign(user, { + avatarUrl: userData.avatar_url, + username: userData.username, + name: userData.name, + location: userData.location, + bio: userData.bio, + organization: userData.organization, + loaded: true, + }); + + UsersCache.retrieveStatusById(userId) + .then(status => { + if (!status) { + return; + } + + Object.assign(user, { + status, + }); + }) + .catch(() => { + throw new Error(`User status for "${userId}" could not be retrieved!`); + }); + }) + .catch(() => { + renderedPopover.$destroy(); + renderedPopover = null; + }); + } + }, 200); // 200ms delay so not every mouseover triggers Popover + API Call +}; + +export default elements => { + const userLinks = elements || [...document.querySelectorAll('.js-user-link')]; + + userLinks.forEach(el => { + el.addEventListener('mouseenter', handleUserPopoverMouseOver); + }); +}; |