@atlaskit/profilecard 19.11.8 → 19.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,284 +1,290 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import React, { Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
- import { useIntl } from 'react-intl-next';
4
- import { useAnalyticsEvents } from '@atlaskit/analytics-next';
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ import React, { Suspense } from 'react';
4
+ import { withAnalyticsEvents } from '@atlaskit/analytics-next';
5
5
  import { GiveKudosLauncherLazy, KudosType } from '@atlaskit/give-kudos';
6
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
6
7
  import Popup from '@atlaskit/popup';
7
8
  import { layers } from '@atlaskit/theme/constants';
8
- import filterActionsInner from '../../internal/filterActions';
9
- import getLabelMessage from '../../internal/getLabelMessage';
9
+ import filterActions from '../../internal/filterActions';
10
10
  import { CardWrapper } from '../../styled/Card';
11
11
  import { cardTriggered, fireEvent } from '../../util/analytics';
12
12
  import { DELAY_MS_HIDE, DELAY_MS_SHOW } from '../../util/config';
13
13
  import { ProfileCardLazy } from './lazyProfileCard';
14
+ import ProfilecardTriggerNext from './ProfileCardTriggerNext';
14
15
  import UserLoadingState from './UserLoadingState';
15
- export default function ProfilecardTrigger({
16
- trigger = 'hover',
17
- userId,
18
- cloudId,
19
- resourceClient,
20
- actions = [],
21
- position = 'bottom-start',
22
- children,
23
- testId,
24
- addFlag,
25
- onReportingLinesClick,
26
- ariaLabel,
27
- ariaLabelledBy,
28
- prepopulatedData,
29
- disabledAriaAttributes,
30
- onVisibilityChange
31
- }) {
32
- const {
33
- createAnalyticsEvent
34
- } = useAnalyticsEvents();
35
- const {
36
- formatMessage
37
- } = useIntl();
38
- const [isMounted, setIsMounted] = useState(false);
39
- const showDelay = trigger === 'click' ? 0 : DELAY_MS_SHOW;
40
- const hideDelay = trigger === 'click' ? 0 : DELAY_MS_HIDE;
41
- const showTimer = useRef(0);
42
- const hideTimer = useRef(0);
43
- const [visible, setVisible] = useState(false);
44
- const [isLoading, setIsLoading] = useState(undefined);
45
- const [hasError, setHasError] = useState(false);
46
- const [error, setError] = useState(null);
47
- const [data, setData] = useState(null);
48
- const [reportingLinesData, setReportingLinesData] = useState(undefined);
49
- const [shouldShowGiveKudos, setShouldShowGiveKudos] = useState(false);
50
- const [teamCentralBaseUrl, setTeamCentralBaseUrl] = useState(undefined);
51
- const [kudosDrawerOpen, setKudosDrawerOpen] = useState(false);
52
- const [isTriggeredUsingKeyboard, setTriggeredUsingKeyboard] = useState(false);
53
- const triggerRef = useRef(null);
54
- useEffect(() => {
55
- setIsMounted(true);
56
- return () => {
57
- setIsMounted(false);
58
- clearTimeout(showTimer.current);
59
- clearTimeout(hideTimer.current);
60
- };
61
- // eslint-disable-next-line react-hooks/exhaustive-deps
62
- }, []);
63
- useEffect(() => {
64
- // Reset state when the userId changes
65
- setIsLoading(undefined);
66
- setHasError(false);
67
- setError(null);
68
- setData(null);
69
- setReportingLinesData(undefined);
70
- setShouldShowGiveKudos(false);
71
- setTeamCentralBaseUrl(undefined);
72
- }, [userId]);
73
- const fireAnalytics = useCallback(payload => {
74
- // Don't fire any analytics if the component is unmounted
75
- if (!isMounted) {
76
- return;
77
- }
78
- fireEvent(createAnalyticsEvent, payload);
79
- }, [createAnalyticsEvent, isMounted]);
80
- const hideProfilecard = useCallback(() => {
81
- clearTimeout(showTimer.current);
82
- clearTimeout(hideTimer.current);
83
- if (!isTriggeredUsingKeyboard) {
84
- hideTimer.current = window.setTimeout(() => {
85
- setVisible(false);
86
- onVisibilityChange && onVisibilityChange(false);
87
- }, hideDelay);
88
- }
89
- }, [hideDelay, isTriggeredUsingKeyboard, onVisibilityChange]);
90
- const handleKeyboardClose = useCallback(event => {
91
- if (event.key && event.key !== 'Escape') {
92
- return;
93
- }
94
- if (triggerRef.current) {
95
- triggerRef.current.focus();
96
- }
97
- setTriggeredUsingKeyboard(false);
98
- setVisible(false);
99
- onVisibilityChange && onVisibilityChange(false);
100
- }, [setTriggeredUsingKeyboard, setVisible, onVisibilityChange]);
101
- const handleClientSuccess = useCallback((profileData, reportingLinesData, shouldShowGiveKudos) => {
102
- if (!isMounted) {
103
- return;
16
+ class ProfilecardTrigger extends React.PureComponent {
17
+ constructor(...args) {
18
+ super(...args);
19
+ _defineProperty(this, "_isMounted", false);
20
+ _defineProperty(this, "showDelay", this.props.trigger === 'click' ? 0 : DELAY_MS_SHOW);
21
+ _defineProperty(this, "hideDelay", this.props.trigger === 'click' ? 0 : DELAY_MS_HIDE);
22
+ _defineProperty(this, "showTimer", 0);
23
+ _defineProperty(this, "hideTimer", 0);
24
+ _defineProperty(this, "fireAnalytics", payload => {
25
+ // Don't fire any analytics if the component is unmounted
26
+ if (!this._isMounted) {
27
+ return;
28
+ }
29
+ if (this.props.createAnalyticsEvent) {
30
+ fireEvent(this.props.createAnalyticsEvent, payload);
31
+ }
32
+ });
33
+ _defineProperty(this, "hideProfilecard", () => {
34
+ clearTimeout(this.showTimer);
35
+ clearTimeout(this.hideTimer);
36
+ this.hideTimer = window.setTimeout(() => {
37
+ this.setState({
38
+ visible: false
39
+ });
40
+ }, this.hideDelay);
41
+ });
42
+ _defineProperty(this, "showProfilecard", () => {
43
+ clearTimeout(this.hideTimer);
44
+ clearTimeout(this.showTimer);
45
+ this.showTimer = window.setTimeout(() => {
46
+ if (!this.state.visible) {
47
+ this.clientFetchProfile();
48
+ this.setState({
49
+ visible: true
50
+ });
51
+ }
52
+ }, this.showDelay);
53
+ });
54
+ _defineProperty(this, "onClick", event => {
55
+ // If the user clicks on the trigger then we don't want that click event to
56
+ // propagate out to parent containers. For example when clicking a mention
57
+ // lozenge in an inline-edit.
58
+ event.stopPropagation();
59
+ this.showProfilecard();
60
+ if (!this.state.visible) {
61
+ this.fireAnalytics(cardTriggered('user', 'click'));
62
+ }
63
+ });
64
+ _defineProperty(this, "onMouseEnter", () => {
65
+ this.showProfilecard();
66
+ if (!this.state.visible) {
67
+ this.fireAnalytics(cardTriggered('user', 'hover'));
68
+ }
69
+ });
70
+ _defineProperty(this, "onKeyPress", event => {
71
+ if (event.key === 'Enter' || event.key === ' ') {
72
+ event.preventDefault();
73
+ this.showProfilecard();
74
+ if (!this.state.visible) {
75
+ this.fireAnalytics(cardTriggered('user', 'click'));
76
+ }
77
+ }
78
+ });
79
+ _defineProperty(this, "onFocus", () => {
80
+ this.showProfilecard();
81
+ });
82
+ _defineProperty(this, "containerListeners", this.props.trigger === 'hover' ? {
83
+ onMouseEnter: this.onMouseEnter,
84
+ onMouseLeave: this.hideProfilecard,
85
+ onBlur: this.hideProfilecard,
86
+ onKeyPress: this.onKeyPress
87
+ } : {
88
+ onClick: this.onClick,
89
+ onKeyPress: this.onKeyPress
90
+ });
91
+ _defineProperty(this, "layerListeners", {
92
+ handleClickOutside: this.hideProfilecard,
93
+ handleEscapeKeydown: this.hideProfilecard
94
+ });
95
+ _defineProperty(this, "state", {
96
+ visible: false,
97
+ isLoading: undefined,
98
+ hasError: false,
99
+ error: null,
100
+ data: null,
101
+ reportingLinesData: undefined,
102
+ shouldShowGiveKudos: false,
103
+ teamCentralBaseUrl: undefined,
104
+ kudosDrawerOpen: false
105
+ });
106
+ _defineProperty(this, "clientFetchProfile", () => {
107
+ const {
108
+ cloudId,
109
+ userId
110
+ } = this.props;
111
+ const {
112
+ isLoading
113
+ } = this.state;
114
+ if (isLoading === true) {
115
+ // don't fetch data when fetching is in process
116
+ return;
117
+ }
118
+ this.setState({
119
+ teamCentralBaseUrl: this.props.resourceClient.getTeamCentralBaseUrl()
120
+ });
121
+ this.setState({
122
+ isLoading: true,
123
+ hasError: false,
124
+ data: null
125
+ }, () => {
126
+ const requests = Promise.all([this.props.resourceClient.getProfile(cloudId || '', userId, this.fireAnalytics), this.props.resourceClient.getReportingLines(userId), this.props.resourceClient.shouldShowGiveKudos()]);
127
+ requests.then(res => this.handleClientSuccess(...res), err => this.handleClientError(err)).catch(err => this.handleClientError(err));
128
+ });
129
+ });
130
+ _defineProperty(this, "openKudosDrawer", () => {
131
+ this.hideProfilecard();
132
+ this.setState({
133
+ kudosDrawerOpen: true
134
+ });
135
+ });
136
+ _defineProperty(this, "closeKudosDrawer", () => {
137
+ this.setState({
138
+ kudosDrawerOpen: false
139
+ });
140
+ });
141
+ _defineProperty(this, "renderCard", () => {
142
+ const {
143
+ isLoading
144
+ } = this.state;
145
+ if (isLoading === true || isLoading === undefined) {
146
+ return /*#__PURE__*/React.createElement(CardWrapper, null, /*#__PURE__*/React.createElement(UserLoadingState, {
147
+ fireAnalytics: this.fireAnalytics
148
+ }));
149
+ } else {
150
+ return this.renderProfileCard();
151
+ }
152
+ });
153
+ }
154
+ componentDidMount() {
155
+ this._isMounted = true;
156
+ }
157
+ componentDidUpdate(prevProps) {
158
+ const {
159
+ userId,
160
+ cloudId,
161
+ resourceClient
162
+ } = this.props;
163
+ const {
164
+ visible
165
+ } = this.state;
166
+
167
+ // just re-fetching data when the card opens
168
+ if (visible && (userId !== prevProps.userId || cloudId !== prevProps.cloudId || resourceClient !== prevProps.resourceClient)) {
169
+ this.setState({
170
+ isLoading: undefined
171
+ }, this.clientFetchProfile);
104
172
  }
105
- setIsLoading(false);
106
- setHasError(false);
107
- setData(profileData);
108
- setReportingLinesData(reportingLinesData);
109
- setShouldShowGiveKudos(shouldShowGiveKudos);
110
- }, [isMounted, setHasError, setIsLoading, setData, setReportingLinesData, setShouldShowGiveKudos]);
111
- const handleClientError = useCallback(err => {
112
- if (!isMounted) {
173
+ }
174
+ componentWillUnmount() {
175
+ this._isMounted = false;
176
+ clearTimeout(this.showTimer);
177
+ clearTimeout(this.hideTimer);
178
+ }
179
+ handleClientSuccess(profileData, reportingLinesData, shouldShowGiveKudos) {
180
+ if (!this._isMounted) {
113
181
  return;
114
182
  }
115
- setIsLoading(false);
116
- setHasError(true);
117
- setError(err);
118
- }, [isMounted, setHasError, setIsLoading, setError]);
119
- const clientFetchProfile = useCallback(async () => {
120
- if (isLoading === true) {
121
- // don't fetch data when fetching is in process
183
+ this.setState({
184
+ isLoading: false,
185
+ hasError: false,
186
+ data: profileData,
187
+ reportingLinesData,
188
+ shouldShowGiveKudos
189
+ });
190
+ }
191
+ handleClientError(err) {
192
+ if (!this._isMounted) {
122
193
  return;
123
194
  }
124
- setTeamCentralBaseUrl(resourceClient.getTeamCentralBaseUrl());
125
- setIsLoading(true);
126
- setHasError(false);
127
- setError(null);
128
- setData(null);
129
- try {
130
- const requests = Promise.all([resourceClient.getProfile(cloudId || '', userId, fireAnalytics), resourceClient.getReportingLines(userId), resourceClient.shouldShowGiveKudos()]);
131
- const responses = await requests;
132
- handleClientSuccess(...responses);
133
- } catch (err) {
134
- handleClientError(err);
135
- }
136
- }, [cloudId, fireAnalytics, isLoading, resourceClient, userId, handleClientSuccess, handleClientError]);
137
- const showProfilecard = useCallback(() => {
138
- clearTimeout(hideTimer.current);
139
- clearTimeout(showTimer.current);
140
- showTimer.current = window.setTimeout(() => {
141
- if (!visible) {
142
- void clientFetchProfile();
143
- setVisible(true);
144
- onVisibilityChange && onVisibilityChange(true);
145
- }
146
- }, showDelay);
147
- }, [showDelay, visible, clientFetchProfile, onVisibilityChange]);
148
- const onClick = useCallback(event => {
149
- // If the user clicks on the trigger then we don't want that click event to
150
- // propagate out to parent containers. For example when clicking a mention
151
- // lozenge in an inline-edit.
152
- event.stopPropagation();
153
- showProfilecard();
154
- if (!visible) {
155
- fireAnalytics(cardTriggered('user', 'click'));
156
- }
157
- }, [fireAnalytics, showProfilecard, visible]);
158
- const onMouseEnter = useCallback(() => {
159
- showProfilecard();
160
- if (!visible) {
161
- fireAnalytics(cardTriggered('user', 'hover'));
162
- }
163
- }, [fireAnalytics, showProfilecard, visible]);
164
- const onKeyPress = useCallback(event => {
165
- if (event.key === 'Enter' || event.key === ' ') {
166
- event.preventDefault();
167
- setTriggeredUsingKeyboard(true);
168
- showProfilecard();
169
- if (!visible) {
170
- fireAnalytics(cardTriggered('user', 'click'));
171
- }
172
- }
173
- }, [fireAnalytics, showProfilecard, visible]);
174
- const onFocus = useCallback(() => {
175
- showProfilecard();
176
- }, [showProfilecard]);
177
- const containerListeners = useMemo(() => trigger === 'hover' ? {
178
- onMouseEnter: onMouseEnter,
179
- onMouseLeave: hideProfilecard,
180
- onBlur: hideProfilecard,
181
- onKeyPress: onKeyPress
182
- } : {
183
- onClick: onClick,
184
- onKeyPress: onKeyPress
185
- }, [hideProfilecard, onClick, onKeyPress, onMouseEnter, trigger]);
186
- const filterActions = useCallback(() => {
187
- return filterActionsInner(actions, data);
188
- }, [actions, data]);
189
- const openKudosDrawer = () => {
190
- hideProfilecard();
191
- setKudosDrawerOpen(true);
192
- };
193
- const closeKudosDrawer = () => {
194
- setKudosDrawerOpen(false);
195
- };
196
- const showLoading = isLoading === true || isLoading === undefined;
197
- const wrapperProps = useMemo(() => trigger === 'hover' ? {
198
- onMouseEnter: onMouseEnter,
199
- onMouseLeave: hideProfilecard,
200
- onFocus: onFocus
201
- } : {}, [hideProfilecard, onFocus, onMouseEnter, trigger]);
202
- const profilecardProps = {
203
- userId: userId,
204
- fullName: prepopulatedData === null || prepopulatedData === void 0 ? void 0 : prepopulatedData.fullName,
205
- isCurrentUser: data === null || data === void 0 ? void 0 : data.isCurrentUser,
206
- clientFetchProfile: clientFetchProfile,
207
- ...data,
208
- reportingLines: reportingLinesData,
209
- onReportingLinesClick: onReportingLinesClick,
210
- isKudosEnabled: shouldShowGiveKudos,
211
- teamCentralBaseUrl: teamCentralBaseUrl,
212
- cloudId: cloudId,
213
- openKudosDrawer: openKudosDrawer,
214
- isTriggeredUsingKeyboard: isTriggeredUsingKeyboard,
215
- disabledAriaAttributes: disabledAriaAttributes
216
- };
217
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Popup, {
218
- isOpen: !!visible,
219
- onClose: event => {
220
- hideProfilecard();
221
- handleKeyboardClose(event);
222
- },
223
- placement: position,
224
- content: () => /*#__PURE__*/React.createElement("div", wrapperProps, showLoading ? /*#__PURE__*/React.createElement(LoadingView, {
225
- fireAnalytics: fireAnalytics
226
- }) : visible && /*#__PURE__*/React.createElement(Suspense, {
195
+ this.setState({
196
+ isLoading: false,
197
+ hasError: true,
198
+ error: err
199
+ });
200
+ }
201
+ filterActions() {
202
+ return filterActions(this.props.actions, this.state.data);
203
+ }
204
+ renderProfileCard() {
205
+ var _this$state$data;
206
+ const newProps = {
207
+ userId: this.props.userId,
208
+ isCurrentUser: (_this$state$data = this.state.data) === null || _this$state$data === void 0 ? void 0 : _this$state$data.isCurrentUser,
209
+ clientFetchProfile: this.clientFetchProfile,
210
+ ...this.state.data,
211
+ reportingLines: this.state.reportingLinesData,
212
+ onReportingLinesClick: this.props.onReportingLinesClick,
213
+ isKudosEnabled: this.state.shouldShowGiveKudos,
214
+ teamCentralBaseUrl: this.state.teamCentralBaseUrl,
215
+ cloudId: this.props.cloudId,
216
+ openKudosDrawer: this.openKudosDrawer
217
+ };
218
+ const wrapperProps = this.props.trigger === 'hover' ? {
219
+ onMouseEnter: this.onMouseEnter,
220
+ onMouseLeave: this.hideProfilecard,
221
+ onFocus: this.onFocus
222
+ } : {};
223
+ return /*#__PURE__*/React.createElement("div", wrapperProps, this.state.visible && /*#__PURE__*/React.createElement(Suspense, {
227
224
  fallback: null
228
- }, /*#__PURE__*/React.createElement(ProfileCardLazy, _extends({}, profilecardProps, {
229
- actions: filterActions(),
230
- hasError: hasError,
231
- errorType: error,
225
+ }, /*#__PURE__*/React.createElement(ProfileCardLazy, _extends({}, newProps, {
226
+ actions: this.filterActions(),
227
+ hasError: this.state.hasError,
228
+ errorType: this.state.error,
232
229
  withoutElevation: true
233
- })))),
234
- trigger: triggerProps => {
235
- const {
236
- ref: callbackRef,
237
- ...innerProps
238
- } = triggerProps;
239
- const ref = element => {
240
- triggerRef.current = element;
241
- if (typeof callbackRef === 'function') {
242
- callbackRef(element);
243
- }
244
- };
245
- const {
246
- 'aria-expanded': _,
247
- 'aria-haspopup': __,
248
- ...restInnerProps
249
- } = innerProps;
250
- return /*#__PURE__*/React.createElement("span", _extends({}, disabledAriaAttributes ? restInnerProps : triggerProps, containerListeners, {
251
- ref: ref,
252
- "data-testid": testId,
253
- "aria-labelledby": ariaLabelledBy
254
- }, disabledAriaAttributes ? {} : {
255
- role: 'button',
256
- tabIndex: 0,
257
- 'aria-label': getLabelMessage(ariaLabel, profilecardProps.fullName, formatMessage)
258
- }), children);
259
- },
260
- zIndex: layers.modal(),
261
- shouldUseCaptureOnOutsideClick: true,
262
- autoFocus: trigger === 'click'
263
- }), shouldShowGiveKudos && /*#__PURE__*/React.createElement(Suspense, {
264
- fallback: null
265
- }, /*#__PURE__*/React.createElement(GiveKudosLauncherLazy, {
266
- isOpen: kudosDrawerOpen,
267
- recipient: {
268
- type: KudosType.INDIVIDUAL,
269
- recipientId: userId
270
- },
271
- analyticsSource: "profile-card",
272
- teamCentralBaseUrl: teamCentralBaseUrl,
273
- cloudId: cloudId,
274
- addFlag: addFlag,
275
- onClose: closeKudosDrawer
276
- })));
230
+ }))));
231
+ }
232
+ renderWithTrigger() {
233
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Popup, {
234
+ isOpen: !!this.state.visible,
235
+ onClose: this.hideProfilecard,
236
+ placement: this.props.position,
237
+ content: this.renderCard,
238
+ trigger: triggerProps => {
239
+ const {
240
+ ref,
241
+ ...innerProps
242
+ } = triggerProps;
243
+ return /*#__PURE__*/React.createElement("span", _extends({}, innerProps, this.containerListeners, {
244
+ ref: ref,
245
+ "data-testid": this.props.testId,
246
+ role: "button",
247
+ tabIndex: 0
248
+ }), this.props.children);
249
+ },
250
+ zIndex: layers.modal(),
251
+ shouldUseCaptureOnOutsideClick: true,
252
+ autoFocus: this.props.trigger === 'click'
253
+ }), this.state.shouldShowGiveKudos && /*#__PURE__*/React.createElement(Suspense, {
254
+ fallback: null
255
+ }, /*#__PURE__*/React.createElement(GiveKudosLauncherLazy, {
256
+ isOpen: this.state.kudosDrawerOpen,
257
+ recipient: {
258
+ type: KudosType.INDIVIDUAL,
259
+ recipientId: this.props.userId
260
+ },
261
+ analyticsSource: "profile-card",
262
+ teamCentralBaseUrl: this.state.teamCentralBaseUrl,
263
+ cloudId: this.props.cloudId,
264
+ addFlag: this.props.addFlag,
265
+ onClose: this.closeKudosDrawer
266
+ })));
267
+ }
268
+ render() {
269
+ if (this.props.children) {
270
+ return this.renderWithTrigger();
271
+ } else {
272
+ throw new Error('Component "ProfileCardTrigger" must have "children" property');
273
+ }
274
+ }
277
275
  }
278
- const LoadingView = ({
279
- fireAnalytics
280
- }) => /*#__PURE__*/React.createElement(CardWrapper, {
281
- "data-testId": "profilecard.profilecardtrigger.loading"
282
- }, /*#__PURE__*/React.createElement(UserLoadingState, {
283
- fireAnalytics: fireAnalytics
284
- }));
276
+ _defineProperty(ProfilecardTrigger, "defaultProps", {
277
+ actions: [],
278
+ trigger: 'hover',
279
+ position: 'bottom-start'
280
+ });
281
+ const ProfilecardTriggerLegacy = withAnalyticsEvents()(ProfilecardTrigger);
282
+ export default function ProfilecardTriggerSwitch(props) {
283
+ return getBooleanFF('platform.profile-card-trigger-next') ? /*#__PURE__*/React.createElement(ProfilecardTriggerNext, _extends({}, props, {
284
+ onVisibilityChange: isVisible => {
285
+ if (props.onVisibilityChange) {
286
+ props.onVisibilityChange(isVisible);
287
+ }
288
+ }
289
+ })) : /*#__PURE__*/React.createElement(ProfilecardTriggerLegacy, props);
290
+ }