@atlaskit/profilecard
Version:
A React component to display a card with user information.
423 lines • 17.5 kB
JavaScript
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
}));
};