UNPKG

@atlaskit/profilecard

Version:

A React component to display a card with user information.

423 lines 17.5 kB
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _extends from "@babel/runtime/helpers/extends"; var _excluded = ["ref"], _excluded2 = ["aria-expanded", "aria-haspopup"]; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import _regeneratorRuntime from "@babel/runtime/regenerator"; import React, { Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useIntl } from 'react-intl-next'; import { useAnalyticsEvents } from '@atlaskit/analytics-next'; import { GiveKudosLauncherLazy, KudosType } from '@atlaskit/give-kudos'; import { fg } from '@atlaskit/platform-feature-flags'; import Popup from '@atlaskit/popup'; import { layers } from '@atlaskit/theme/constants'; import filterActionsInner from '../../internal/filterActions'; import getLabelMessage from '../../internal/getLabelMessage'; import { CardWrapper } from '../../styled/Card'; import { cardTriggered, fireEvent } from '../../util/analytics'; import { DELAY_MS_HIDE, DELAY_MS_SHOW } from '../../util/config'; import { AgentProfileCardResourced } from '../Agent/AgentProfileCardResourced'; import { ProfileCardLazy } from './lazyProfileCard'; import UserLoadingState from './UserLoadingState'; function ProfileCardContent(_ref) { var profilecardProps = _ref.profilecardProps, userId = _ref.userId, cloudId = _ref.cloudId, resourceClient = _ref.resourceClient, viewingUserId = _ref.viewingUserId, trigger = _ref.trigger, product = _ref.product, isAgent = _ref.isAgent, profileCardAction = _ref.profileCardAction, hasError = _ref.hasError, errorType = _ref.errorType, agentActions = _ref.agentActions, addFlag = _ref.addFlag; if (isAgent) { return /*#__PURE__*/React.createElement(AgentProfileCardResourced, { accountId: userId, cloudId: cloudId, resourceClient: resourceClient, viewingUserId: viewingUserId, trigger: trigger, product: product, onChatClick: agentActions === null || agentActions === void 0 ? void 0 : agentActions.onChatClick, onConversationStartersClick: agentActions === null || agentActions === void 0 ? void 0 : agentActions.onConversationStartersClick, addFlag: addFlag }); } else { return /*#__PURE__*/React.createElement(Suspense, { fallback: null }, /*#__PURE__*/React.createElement(ProfileCardLazy, _extends({}, profilecardProps, { actions: profileCardAction, hasError: hasError, errorType: errorType, withoutElevation: true }))); } } export default function ProfilecardTriggerNext(_ref2) { var autoFocus = _ref2.autoFocus, _ref2$trigger = _ref2.trigger, trigger = _ref2$trigger === void 0 ? 'hover' : _ref2$trigger, userId = _ref2.userId, cloudId = _ref2.cloudId, resourceClient = _ref2.resourceClient, _ref2$actions = _ref2.actions, actions = _ref2$actions === void 0 ? [] : _ref2$actions, _ref2$position = _ref2.position, position = _ref2$position === void 0 ? 'bottom-start' : _ref2$position, children = _ref2.children, testId = _ref2.testId, addFlag = _ref2.addFlag, onReportingLinesClick = _ref2.onReportingLinesClick, ariaLabel = _ref2.ariaLabel, ariaLabelledBy = _ref2.ariaLabelledBy, prepopulatedData = _ref2.prepopulatedData, disabledAriaAttributes = _ref2.disabledAriaAttributes, onVisibilityChange = _ref2.onVisibilityChange, offset = _ref2.offset, viewingUserId = _ref2.viewingUserId, product = _ref2.product, agentActions = _ref2.agentActions, _ref2$ariaHideProfile = _ref2.ariaHideProfileTrigger, ariaHideProfileTrigger = _ref2$ariaHideProfile === void 0 ? false : _ref2$ariaHideProfile, propsIsVisible = _ref2.isVisible; var _useAnalyticsEvents = useAnalyticsEvents(), createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent; var _useIntl = useIntl(), formatMessage = _useIntl.formatMessage; var isMounted = useRef(false); var showDelay = trigger === 'click' || propsIsVisible && fg('fix_profilecard_trigger_isvisible') ? 0 : DELAY_MS_SHOW; var hideDelay = trigger === 'click' || propsIsVisible && fg('fix_profilecard_trigger_isvisible') ? 0 : DELAY_MS_HIDE; var showTimer = useRef(0); var hideTimer = useRef(0); var _useState = useState(false), _useState2 = _slicedToArray(_useState, 2), visible = _useState2[0], setVisible = _useState2[1]; var _useState3 = useState(undefined), _useState4 = _slicedToArray(_useState3, 2), isLoading = _useState4[0], setIsLoading = _useState4[1]; var _useState5 = useState(false), _useState6 = _slicedToArray(_useState5, 2), hasError = _useState6[0], setHasError = _useState6[1]; var _useState7 = useState(null), _useState8 = _slicedToArray(_useState7, 2), error = _useState8[0], setError = _useState8[1]; var _useState9 = useState(null), _useState10 = _slicedToArray(_useState9, 2), data = _useState10[0], setData = _useState10[1]; var _useState11 = useState(undefined), _useState12 = _slicedToArray(_useState11, 2), reportingLinesData = _useState12[0], setReportingLinesData = _useState12[1]; var _useState13 = useState(false), _useState14 = _slicedToArray(_useState13, 2), shouldShowGiveKudos = _useState14[0], setShouldShowGiveKudos = _useState14[1]; var _useState15 = useState(undefined), _useState16 = _slicedToArray(_useState15, 2), teamCentralBaseUrl = _useState16[0], setTeamCentralBaseUrl = _useState16[1]; var _useState17 = useState(false), _useState18 = _slicedToArray(_useState17, 2), kudosDrawerOpen = _useState18[0], setKudosDrawerOpen = _useState18[1]; var _useState19 = useState(false), _useState20 = _slicedToArray(_useState19, 2), isTriggeredUsingKeyboard = _useState20[0], setTriggeredUsingKeyboard = _useState20[1]; var triggerRef = useRef(null); useEffect(function () { isMounted.current = true; return function () { isMounted.current = false; clearTimeout(showTimer.current); clearTimeout(hideTimer.current); }; }, []); useEffect(function () { // Reset state when the userId changes setIsLoading(undefined); setHasError(false); setError(null); setData(null); setReportingLinesData(undefined); setShouldShowGiveKudos(false); setTeamCentralBaseUrl(undefined); }, [userId]); var fireAnalytics = useCallback(function (payload) { // Don't fire any analytics if the component is unmounted if (!isMounted.current) { return; } fireEvent(createAnalyticsEvent, payload); }, [createAnalyticsEvent]); var hideProfilecard = useCallback(function () { clearTimeout(showTimer.current); clearTimeout(hideTimer.current); if (!isTriggeredUsingKeyboard) { hideTimer.current = window.setTimeout(function () { setVisible(false); onVisibilityChange && onVisibilityChange(false); }, hideDelay); } }, [hideDelay, isTriggeredUsingKeyboard, onVisibilityChange]); var handleKeyboardClose = useCallback(function (event) { if (event.key && event.key !== 'Escape') { return; } if (triggerRef.current) { triggerRef.current.focus(); } setTriggeredUsingKeyboard(false); setVisible(false); onVisibilityChange && onVisibilityChange(false); }, [setTriggeredUsingKeyboard, setVisible, onVisibilityChange]); var handleClientSuccess = useCallback(function (profileData, reportingLinesData, shouldShowGiveKudos, teamCentralBaseUrl) { if (!isMounted.current) { return; } setIsLoading(false); setHasError(false); setData(profileData); setReportingLinesData(reportingLinesData); setTeamCentralBaseUrl(teamCentralBaseUrl); setShouldShowGiveKudos(shouldShowGiveKudos); }, [setHasError, setIsLoading, setData, setReportingLinesData, setShouldShowGiveKudos]); var handleClientError = useCallback(function (err) { if (!isMounted.current) { return; } setIsLoading(false); setHasError(true); setError(err); }, [setHasError, setIsLoading, setError]); var clientFetchProfile = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() { var requests, responses; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: if (!(isLoading === true)) { _context.next = 2; break; } return _context.abrupt("return"); case 2: setIsLoading(true); setHasError(false); setError(null); setData(null); _context.prev = 6; requests = Promise.all([resourceClient.getProfile(cloudId || '', userId, fireAnalytics), resourceClient.getReportingLines(userId), resourceClient.shouldShowGiveKudos(), resourceClient.getTeamCentralBaseUrl({ withOrgContext: true, withSiteContext: true })]); _context.next = 10; return requests; case 10: responses = _context.sent; handleClientSuccess.apply(void 0, _toConsumableArray(responses)); _context.next = 17; break; case 14: _context.prev = 14; _context.t0 = _context["catch"](6); handleClientError(_context.t0); case 17: case "end": return _context.stop(); } }, _callee, null, [[6, 14]]); })), [cloudId, fireAnalytics, isLoading, resourceClient, userId, handleClientSuccess, handleClientError]); var showProfilecard = useCallback(function () { clearTimeout(hideTimer.current); clearTimeout(showTimer.current); showTimer.current = window.setTimeout(function () { if (!visible) { void clientFetchProfile(); setVisible(true); onVisibilityChange && onVisibilityChange(true); } }, showDelay); }, [showDelay, visible, clientFetchProfile, onVisibilityChange]); var onClick = useCallback(function (event) { // If the user clicks on the trigger then we don't want that click event to // propagate out to parent containers. For example when clicking a mention // lozenge in an inline-edit. event.stopPropagation(); showProfilecard(); if (!visible) { fireAnalytics(cardTriggered('user', 'click')); } }, [fireAnalytics, showProfilecard, visible]); var onMouseEnter = useCallback(function () { showProfilecard(); if (!visible) { fireAnalytics(cardTriggered('user', 'hover')); } }, [fireAnalytics, showProfilecard, visible]); var onKeyPress = useCallback(function (event) { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); setTriggeredUsingKeyboard(true); showProfilecard(); if (!visible) { fireAnalytics(cardTriggered('user', 'click')); } } }, [fireAnalytics, showProfilecard, visible]); var onFocus = useCallback(function () { showProfilecard(); }, [showProfilecard]); useEffect(function () { if (!fg('fix_profilecard_trigger_isvisible')) { return; } // If the prop isVisible is not defined, we don't want to do anything if (propsIsVisible === undefined) { return; } // If the prop isVisible is defined, we want to show or hide the profile card based on the value if (propsIsVisible) { showProfilecard(); } else { hideProfilecard(); } }, [hideProfilecard, propsIsVisible, showProfilecard]); var containerListeners = useMemo(function () { return trigger === 'hover' ? { onMouseEnter: onMouseEnter, onMouseLeave: hideProfilecard, onBlur: hideProfilecard, onKeyPress: onKeyPress } : { onClick: onClick, onKeyPress: onKeyPress }; }, [hideProfilecard, onClick, onKeyPress, onMouseEnter, trigger]); var filterActions = useCallback(function () { return filterActionsInner(actions, data); }, [actions, data]); var openKudosDrawer = function openKudosDrawer() { hideProfilecard(); setKudosDrawerOpen(true); }; var closeKudosDrawer = function closeKudosDrawer() { setKudosDrawerOpen(false); }; var showLoading = isLoading === true || isLoading === undefined; var wrapperProps = useMemo(function () { return trigger === 'hover' ? { onMouseEnter: onMouseEnter, onMouseLeave: hideProfilecard, onFocus: onFocus } : {}; }, [hideProfilecard, onFocus, onMouseEnter, trigger]); var profilecardProps = _objectSpread(_objectSpread({ userId: userId, fullName: prepopulatedData === null || prepopulatedData === void 0 ? void 0 : prepopulatedData.fullName, isCurrentUser: userId === viewingUserId, clientFetchProfile: clientFetchProfile }, data), {}, { reportingLines: reportingLinesData, onReportingLinesClick: onReportingLinesClick, isKudosEnabled: shouldShowGiveKudos, teamCentralBaseUrl: teamCentralBaseUrl, cloudId: cloudId, openKudosDrawer: openKudosDrawer, isTriggeredUsingKeyboard: isTriggeredUsingKeyboard, disabledAriaAttributes: disabledAriaAttributes }); return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Popup, { isOpen: !!visible, onClose: function onClose(event) { hideProfilecard(); handleKeyboardClose(event); }, placement: position, offset: offset !== null && offset !== void 0 ? offset : [0, 8], content: function content() { return /*#__PURE__*/React.createElement("div", wrapperProps, showLoading ? /*#__PURE__*/React.createElement(LoadingView, { fireAnalytics: fireAnalytics }) : visible && /*#__PURE__*/React.createElement(ProfileCardContent, { profilecardProps: profilecardProps, isAgent: !!(data !== null && data !== void 0 && data.isAgent), userId: userId, cloudId: cloudId, resourceClient: resourceClient, viewingUserId: viewingUserId, trigger: trigger, product: product, profileCardAction: filterActions(), errorType: error, hasError: hasError, agentActions: agentActions, addFlag: addFlag })); }, trigger: function trigger(triggerProps) { var callbackRef = triggerProps.ref, innerProps = _objectWithoutProperties(triggerProps, _excluded); var ref = function ref(element) { triggerRef.current = element; if (typeof callbackRef === 'function') { callbackRef(element); } }; var _ = innerProps['aria-expanded'], __ = innerProps['aria-haspopup'], restInnerProps = _objectWithoutProperties(innerProps, _excluded2); return /*#__PURE__*/React.createElement("span", _extends({}, disabledAriaAttributes ? restInnerProps : triggerProps, containerListeners, { ref: ref, "data-testid": testId }, !ariaHideProfileTrigger && { 'aria-labelledby': ariaLabelledBy }, disabledAriaAttributes ? {} : { role: 'button', // aria-hidden cannot contain focusable elements: https://dequeuniversity.com/rules/axe/3.5/aria-hidden-focus tabIndex: ariaHideProfileTrigger ? -1 : 0, 'aria-label': ariaHideProfileTrigger ? undefined : getLabelMessage(ariaLabel, profilecardProps.fullName, formatMessage) }, ariaHideProfileTrigger && { 'aria-hidden': 'true' }), children); }, zIndex: layers.modal(), shouldUseCaptureOnOutsideClick: true, autoFocus: autoFocus !== null && autoFocus !== void 0 ? autoFocus : trigger === 'click' // This feature gate is currently enabled only for Jira_Web to avoid UI issues in Confluence_Web. , shouldRenderToParent: fg('enable_appropriate_reading_order_in_profile_card') }), shouldShowGiveKudos && teamCentralBaseUrl && /*#__PURE__*/React.createElement(Suspense, { fallback: null }, /*#__PURE__*/React.createElement(GiveKudosLauncherLazy, { isOpen: kudosDrawerOpen, recipient: { type: KudosType.INDIVIDUAL, recipientId: userId }, analyticsSource: "profile-card", teamCentralBaseUrl: teamCentralBaseUrl, cloudId: cloudId, addFlag: addFlag, onClose: closeKudosDrawer }))); } var LoadingView = function LoadingView(_ref4) { var fireAnalytics = _ref4.fireAnalytics; return /*#__PURE__*/React.createElement(CardWrapper, { testId: "profilecard.profilecardtrigger.loading" }, /*#__PURE__*/React.createElement(UserLoadingState, { fireAnalytics: fireAnalytics })); };