2018-12-07 22:12:23 -05:00
|
|
|
import Vue from 'vue';
|
|
|
|
|
2020-09-23 02:09:45 -04:00
|
|
|
import { sanitize } from '~/lib/dompurify';
|
2020-07-09 20:09:13 -04:00
|
|
|
|
2018-12-07 22:12:23 -05:00
|
|
|
import UsersCache from './lib/utils/users_cache';
|
|
|
|
import UserPopover from './vue_shared/components/user_popover/user_popover.vue';
|
|
|
|
|
2020-01-30 16:08:47 -05:00
|
|
|
const removeTitle = el => {
|
|
|
|
// Removing titles so its not showing tooltips also
|
|
|
|
|
|
|
|
el.dataset.originalTitle = '';
|
|
|
|
el.setAttribute('title', '');
|
|
|
|
};
|
|
|
|
|
|
|
|
const getPreloadedUserInfo = dataset => {
|
|
|
|
const userId = dataset.user || dataset.userId;
|
|
|
|
const { username, name, avatarUrl } = dataset;
|
|
|
|
|
|
|
|
return {
|
|
|
|
userId,
|
|
|
|
username,
|
|
|
|
name,
|
|
|
|
avatarUrl,
|
|
|
|
};
|
2018-12-07 22:12:23 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2020-01-30 16:08:47 -05:00
|
|
|
const populateUserInfo = user => {
|
|
|
|
const { userId } = user;
|
|
|
|
|
|
|
|
return Promise.all([UsersCache.retrieveById(userId), UsersCache.retrieveStatusById(userId)]).then(
|
|
|
|
([userData, status]) => {
|
|
|
|
if (userData) {
|
|
|
|
Object.assign(user, {
|
|
|
|
avatarUrl: userData.avatar_url,
|
|
|
|
username: userData.username,
|
|
|
|
name: userData.name,
|
|
|
|
location: userData.location,
|
|
|
|
bio: userData.bio,
|
2020-07-09 20:09:13 -04:00
|
|
|
bioHtml: sanitize(userData.bio_html),
|
2020-04-21 11:21:10 -04:00
|
|
|
workInformation: userData.work_information,
|
2020-10-15 14:08:43 -04:00
|
|
|
websiteUrl: userData.website_url,
|
2020-01-30 16:08:47 -05:00
|
|
|
loaded: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status) {
|
|
|
|
Object.assign(user, {
|
|
|
|
status,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return user;
|
|
|
|
},
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2020-02-06 07:10:29 -05:00
|
|
|
const initializedPopovers = new Map();
|
|
|
|
|
2020-01-30 16:08:47 -05:00
|
|
|
export default (elements = document.querySelectorAll('.js-user-link')) => {
|
|
|
|
const userLinks = Array.from(elements);
|
2020-02-06 07:10:29 -05:00
|
|
|
const UserPopoverComponent = Vue.extend(UserPopover);
|
2020-01-30 16:08:47 -05:00
|
|
|
|
2020-02-17 16:09:20 -05:00
|
|
|
return userLinks
|
|
|
|
.filter(({ dataset }) => dataset.user || dataset.userId)
|
|
|
|
.map(el => {
|
|
|
|
if (initializedPopovers.has(el)) {
|
|
|
|
return initializedPopovers.get(el);
|
2020-01-30 16:08:47 -05:00
|
|
|
}
|
2018-12-07 22:12:23 -05:00
|
|
|
|
2020-02-17 16:09:20 -05:00
|
|
|
const user = {
|
|
|
|
location: null,
|
|
|
|
bio: null,
|
2020-04-21 11:21:10 -04:00
|
|
|
workInformation: null,
|
2020-02-17 16:09:20 -05:00
|
|
|
status: null,
|
|
|
|
loaded: false,
|
|
|
|
};
|
|
|
|
const renderedPopover = new UserPopoverComponent({
|
|
|
|
propsData: {
|
|
|
|
target: el,
|
|
|
|
user,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
initializedPopovers.set(el, renderedPopover);
|
|
|
|
|
|
|
|
renderedPopover.$mount();
|
|
|
|
|
|
|
|
el.addEventListener('mouseenter', ({ target }) => {
|
|
|
|
removeTitle(target);
|
|
|
|
const preloadedUserInfo = getPreloadedUserInfo(target.dataset);
|
|
|
|
|
|
|
|
Object.assign(user, preloadedUserInfo);
|
|
|
|
|
|
|
|
if (preloadedUserInfo.userId) {
|
|
|
|
populateUserInfo(user);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
el.addEventListener('mouseleave', ({ target }) => {
|
|
|
|
target.removeAttribute('aria-describedby');
|
|
|
|
});
|
|
|
|
|
|
|
|
return renderedPopover;
|
|
|
|
});
|
2018-12-07 22:12:23 -05:00
|
|
|
};
|