110 lines
2.9 KiB
JavaScript
110 lines
2.9 KiB
JavaScript
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;
|
|
}
|
|
target.removeAttribute('aria-describedby');
|
|
};
|
|
|
|
/**
|
|
* 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 undefined;
|
|
}
|
|
|
|
Object.assign(user, {
|
|
avatarUrl: userData.avatar_url,
|
|
username: userData.username,
|
|
name: userData.name,
|
|
location: userData.location,
|
|
bio: userData.bio,
|
|
organization: userData.organization,
|
|
status: userData.status,
|
|
loaded: true,
|
|
});
|
|
|
|
if (userData.status) {
|
|
return Promise.resolve();
|
|
}
|
|
|
|
return UsersCache.retrieveStatusById(userId);
|
|
})
|
|
.then(status => {
|
|
if (!status) {
|
|
return;
|
|
}
|
|
|
|
Object.assign(user, {
|
|
status,
|
|
});
|
|
})
|
|
.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);
|
|
});
|
|
};
|