debian-mirror-gitlab/app/assets/javascripts/user_popovers.js

132 lines
3.3 KiB
JavaScript
Raw Normal View History

2019-02-15 15:39:39 +05:30
import Vue from 'vue';
2021-01-03 14:25:43 +05:30
import { sanitize } from '~/lib/dompurify';
2020-07-28 23:09:34 +05:30
2019-02-15 15:39:39 +05:30
import UsersCache from './lib/utils/users_cache';
import UserPopover from './vue_shared/components/user_popover/user_popover.vue';
2021-03-08 18:12:59 +05:30
const removeTitle = (el) => {
2020-03-13 15:44:24 +05:30
// Removing titles so its not showing tooltips also
el.dataset.originalTitle = '';
el.setAttribute('title', '');
};
2021-03-08 18:12:59 +05:30
const getPreloadedUserInfo = (dataset) => {
2020-03-13 15:44:24 +05:30
const userId = dataset.user || dataset.userId;
const { username, name, avatarUrl } = dataset;
return {
userId,
username,
name,
avatarUrl,
};
2019-02-15 15:39:39 +05:30
};
/**
* 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
*/
2021-03-08 18:12:59 +05:30
const populateUserInfo = (user) => {
2020-03-13 15:44:24 +05:30
const { userId } = user;
return Promise.all([UsersCache.retrieveById(userId), UsersCache.retrieveStatusById(userId)]).then(
([userData, status]) => {
if (userData) {
Object.assign(user, {
avatarUrl: userData.avatar_url,
2021-04-17 20:07:23 +05:30
bot: userData.bot,
2020-03-13 15:44:24 +05:30
username: userData.username,
name: userData.name,
location: userData.location,
bio: userData.bio,
2020-07-28 23:09:34 +05:30
bioHtml: sanitize(userData.bio_html),
2020-04-22 19:07:51 +05:30
workInformation: userData.work_information,
2021-01-03 14:25:43 +05:30
websiteUrl: userData.website_url,
2020-03-13 15:44:24 +05:30
loaded: true,
});
}
if (status) {
Object.assign(user, {
status,
});
}
return user;
},
);
};
const initializedPopovers = new Map();
2021-04-17 20:07:23 +05:30
let domObservedForChanges = false;
2020-03-13 15:44:24 +05:30
2021-04-17 20:07:23 +05:30
const addPopoversToModifiedTree = new MutationObserver(() => {
const userLinks = document?.querySelectorAll('.js-user-link, .gfm-project_member');
if (userLinks) {
addPopovers(userLinks); /* eslint-disable-line no-use-before-define */
}
});
function observeBody() {
if (!domObservedForChanges) {
addPopoversToModifiedTree.observe(document.body, {
subtree: true,
childList: true,
});
domObservedForChanges = true;
}
}
export default function addPopovers(elements = document.querySelectorAll('.js-user-link')) {
2020-03-13 15:44:24 +05:30
const userLinks = Array.from(elements);
const UserPopoverComponent = Vue.extend(UserPopover);
2021-04-17 20:07:23 +05:30
observeBody();
2020-03-13 15:44:24 +05:30
return userLinks
.filter(({ dataset }) => dataset.user || dataset.userId)
2021-03-08 18:12:59 +05:30
.map((el) => {
2020-03-13 15:44:24 +05:30
if (initializedPopovers.has(el)) {
return initializedPopovers.get(el);
}
const user = {
location: null,
bio: null,
2020-04-22 19:07:51 +05:30
workInformation: null,
2020-03-13 15:44:24 +05:30
status: null,
loaded: false,
};
const renderedPopover = new UserPopoverComponent({
2019-02-15 15:39:39 +05:30
propsData: {
2020-03-13 15:44:24 +05:30
target: el,
2019-02-15 15:39:39 +05:30
user,
},
});
2020-03-13 15:44:24 +05:30
initializedPopovers.set(el, renderedPopover);
2019-02-15 15:39:39 +05:30
renderedPopover.$mount();
2020-03-13 15:44:24 +05:30
el.addEventListener('mouseenter', ({ target }) => {
removeTitle(target);
const preloadedUserInfo = getPreloadedUserInfo(target.dataset);
Object.assign(user, preloadedUserInfo);
2019-02-15 15:39:39 +05:30
2020-03-13 15:44:24 +05:30
if (preloadedUserInfo.userId) {
populateUserInfo(user);
}
});
el.addEventListener('mouseleave', ({ target }) => {
target.removeAttribute('aria-describedby');
});
2019-02-15 15:39:39 +05:30
2020-03-13 15:44:24 +05:30
return renderedPopover;
});
2021-04-17 20:07:23 +05:30
}