Skip to content

Commit

Permalink
EPMRPP-85839 || Add events for API KEYS (#3637)
Browse files Browse the repository at this point in the history
* EPMRPP-85839 || Add events for API KEYS

* EPMRPP-85839 || fix accessibility bugs

* EPMRPP-85839 || Code Review fix - 1
  • Loading branch information
BlazarQSO authored Nov 8, 2023
1 parent 70b4f49 commit 8f51d16
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,69 @@
* limitations under the License.
*/

import { getBasicClickEventParameters } from '../common/ga4Utils';

const PROFILE_PAGE = 'profile';

const BASIC_EVENT_PARAMETERS_PROFILE = {
action: 'click',
category: PROFILE_PAGE,
place: PROFILE_PAGE,
};
const BASIC_EVENT_PARAMETERS_PROFILE = getBasicClickEventParameters(PROFILE_PAGE);

export const PROFILE_EVENT = {
export const PROFILE_EVENTS = {
CHANGE_LANGUAGE: (lang) => ({
...BASIC_EVENT_PARAMETERS_PROFILE,
place: PROFILE_PAGE,
type: lang,
element_name: 'language_drop_down',
}),

CLICK_API_KEYS_TAB_EVENT: {
...BASIC_EVENT_PARAMETERS_PROFILE,
element_name: 'tab_api_keys',
},

CLICK_GENERATE_BUTTON_WITH_API_KEY: {
...BASIC_EVENT_PARAMETERS_PROFILE,
element_name: 'generate_api_key',
type: 'with_api_key',
},

CLICK_GENERATE_BUTTON_NO_API_KEY: {
...BASIC_EVENT_PARAMETERS_PROFILE,
element_name: 'generate_api_key',
type: 'no_api_key',
},

CLICK_GENERATE_API_KEY_BUTTON_IN_MODAL: {
...BASIC_EVENT_PARAMETERS_PROFILE,
element_name: 'generate',
modal: 'generate_api_key',
},

CLICK_COPY_TO_CLIPBOARD_BUTTON: {
...BASIC_EVENT_PARAMETERS_PROFILE,
element_name: 'copy',
modal: 'api_key_generated',
},

CLICK_DOCUMENTATION_LINK_WITH_API_KEY: {
...BASIC_EVENT_PARAMETERS_PROFILE,
link_name: 'documentation',
place: 'with_api_key',
},

CLICK_DOCUMENTATION_LINK_NO_API_KEY: {
...BASIC_EVENT_PARAMETERS_PROFILE,
link_name: 'documentation',
place: 'no_api_key',
},

CLICK_REVOKE_BUTTON: {
...BASIC_EVENT_PARAMETERS_PROFILE,
element_name: 'revoke',
},

CLICK_REVOKE_BUTTON_IN_MODAL: {
...BASIC_EVENT_PARAMETERS_PROFILE,
element_name: 'revoke',
modal: 'revoke_api_key',
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import React from 'react';
import Parser from 'html-react-parser';
import { useIntl, defineMessages } from 'react-intl';
import { useTracking } from 'react-tracking';
import PropTypes from 'prop-types';
import classNames from 'classnames/bind';
import { useDispatch } from 'react-redux';
Expand All @@ -26,6 +27,8 @@ import { ScrollWrapper } from 'components/main/scrollWrapper';
import { daysFromNow, createExternalLink } from 'common/utils';
import { GhostButton } from 'components/buttons/ghostButton';
import { docsReferences } from 'common/utils/referenceDictionary';
import { PROFILE_EVENTS } from 'analyticsEvents/profilePageEvent';
import { ENTER_KEY_CODE } from 'common/constants/keyCodes';
import styles from './apiKeysBlock.scss';

const cx = classNames.bind(styles);
Expand Down Expand Up @@ -56,13 +59,42 @@ const messages = defineMessages({
export const ApiKeysBlock = ({ apiKeys }) => {
const { formatMessage } = useIntl();
const dispatch = useDispatch();
const { trackEvent } = useTracking();

const onGenerateClick = () => dispatch(showModalAction({ id: 'generateApiKeyModal' }));
const onRevokeClick = (key) => dispatch(showModalAction({ id: 'revokeApiKeyModal', data: key }));
const onGenerateClick = () => {
dispatch(showModalAction({ id: 'generateApiKeyModal' }));
trackEvent(PROFILE_EVENTS.CLICK_GENERATE_BUTTON_WITH_API_KEY);
};

const onRevokeClick = (key) => {
dispatch(showModalAction({ id: 'revokeApiKeyModal', data: key }));
trackEvent(PROFILE_EVENTS.CLICK_REVOKE_BUTTON);
};

const onDocumentationClick = (event) => {
const { tagName } = event.target;

if (tagName === 'A') {
trackEvent(PROFILE_EVENTS.CLICK_DOCUMENTATION_LINK_WITH_API_KEY);
}
};

const onDocumentationKeyDown = (event) => {
const { keyCode } = event;
const { tagName } = event.target;

if (tagName === 'A' && keyCode === ENTER_KEY_CODE) {
trackEvent(PROFILE_EVENTS.CLICK_DOCUMENTATION_LINK_WITH_API_KEY);
}
};

return (
<>
<div className={cx('description')}>
<div
className={cx('description')}
onClick={onDocumentationClick}
onKeyDown={onDocumentationKeyDown}
>
{Parser(
formatMessage(messages.description, {
a: (data) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@

import React from 'react';
import { useIntl, defineMessages } from 'react-intl';
import { useTracking } from 'react-tracking';
import classNames from 'classnames/bind';
import { useDispatch } from 'react-redux';
import { showModalAction } from 'controllers/modal';
import { GhostButton } from 'components/buttons/ghostButton';
import { docsReferences } from 'common/utils/referenceDictionary';
import { PROFILE_EVENTS } from 'analyticsEvents/profilePageEvent';
import { ENTER_KEY_CODE } from 'common/constants/keyCodes';
import styles from './noApiKeysBlock.scss';

const cx = classNames.bind(styles);
Expand All @@ -46,9 +49,23 @@ const messages = defineMessages({

export const NoApiKeysBlock = () => {
const { formatMessage } = useIntl();
const { trackEvent } = useTracking();
const dispatch = useDispatch();

const onGenerateClick = () => dispatch(showModalAction({ id: 'generateApiKeyModal' }));
const onGenerateClick = () => {
dispatch(showModalAction({ id: 'generateApiKeyModal' }));
trackEvent(PROFILE_EVENTS.CLICK_GENERATE_BUTTON_NO_API_KEY);
};

const onDocumentationClick = () => {
trackEvent(PROFILE_EVENTS.CLICK_DOCUMENTATION_LINK_NO_API_KEY);
};

const onDocumentationKeyDown = ({ keyCode }) => {
if (keyCode === ENTER_KEY_CODE) {
trackEvent(PROFILE_EVENTS.CLICK_DOCUMENTATION_LINK_NO_API_KEY);
}
};

return (
<div className={cx('no-api-keys-block')}>
Expand All @@ -60,7 +77,12 @@ export const NoApiKeysBlock = () => {
{formatMessage(messages.generateApiKey)}
</GhostButton>
</div>
<div className={cx('documentation')} title={formatMessage(messages.documentation)}>
<div
className={cx('documentation')}
onClick={onDocumentationClick}
onKeyDown={onDocumentationKeyDown}
title={formatMessage(messages.documentation)}
>
<a
className={cx('documentation-link')}
href={docsReferences.authorizationWithUsersApiKeyForAgents}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
} from 'common/constants/supportedLanguages';
import { langSelector, setLangAction } from 'controllers/lang';
import { InputDropdown } from 'components/inputs/inputDropdown';
import { PROFILE_EVENT } from 'analyticsEvents/profilePageEvent';
import { PROFILE_EVENTS } from 'analyticsEvents/profilePageEvent';
import styles from './localizationBlock.scss';
import EnglishFlagIcon from './img/en-flag-inline.svg';
import UkrainianFlagIcon from './img/ua-flag-inline.svg';
Expand Down Expand Up @@ -154,7 +154,7 @@ export class LocalizationBlock extends Component {

onChangeLanguage = (lang) => {
const { trackEvent } = this.props.tracking;
trackEvent(PROFILE_EVENT.CHANGE_LANGUAGE(langNameByCode(lang)));
trackEvent(PROFILE_EVENTS.CHANGE_LANGUAGE(langNameByCode(lang)));
updateStorageItem(APPLICATION_SETTINGS, { appLanguage: lang });
this.props.setLangAction(lang);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useDispatch } from 'react-redux';
import { useTracking } from 'react-tracking';
import { defineMessages, useIntl } from 'react-intl';
import classNames from 'classnames/bind';
import { ModalLayout, withModal } from 'components/main/modal';
Expand All @@ -25,6 +26,7 @@ import { Input } from 'components/inputs/input';
import { NOTIFICATION_TYPES, showNotification } from 'controllers/notification';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import { BigButton } from 'components/buttons/bigButton';
import { PROFILE_EVENTS } from 'analyticsEvents/profilePageEvent';
import styles from './apiKeyGeneratedModal.scss';

const cx = classNames.bind(styles);
Expand Down Expand Up @@ -54,6 +56,7 @@ const messages = defineMessages({
const ApiKeyGenerated = ({ data }) => {
const { formatMessage } = useIntl();
const dispatch = useDispatch();
const { trackEvent } = useTracking();
const { apiKey } = data;

const onCopy = () => {
Expand All @@ -63,6 +66,7 @@ const ApiKeyGenerated = ({ data }) => {
message: formatMessage(messages.successNotification),
}),
);
trackEvent(PROFILE_EVENTS.CLICK_COPY_TO_CLIPBOARD_BUTTON);
};

const copyButton = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { defineMessages, useIntl } from 'react-intl';
import { connect, useDispatch } from 'react-redux';
import { useTracking } from 'react-tracking';
import { formValueSelector, reduxForm } from 'redux-form';
import classNames from 'classnames/bind';
import { LoaderBlock } from 'pages/inside/profilePage/modals/loaderBlock';
Expand All @@ -34,6 +35,7 @@ import {
import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
import { showModalAction } from 'controllers/modal';
import { addApiKeyAction, apiKeysSelector } from 'controllers/user';
import { PROFILE_EVENTS } from 'analyticsEvents/profilePageEvent';
import styles from './generateApiKeyModal.scss';

const LABEL_WIDTH = 85;
Expand Down Expand Up @@ -87,6 +89,7 @@ const lengthAndUniqueNameValidator = (existNames) =>
const GenerateApiKey = ({ invalid, handleSubmit, apiKeyName }) => {
const { formatMessage } = useIntl();
const dispatch = useDispatch();
const { trackEvent } = useTracking();
const [loading, setLoading] = useState(false);

const onSuccessfulGeneration = (apiKey) => {
Expand All @@ -103,6 +106,7 @@ const GenerateApiKey = ({ invalid, handleSubmit, apiKeyName }) => {
onSuccessfulGeneration,
),
);
trackEvent(PROFILE_EVENTS.CLICK_GENERATE_API_KEY_BUTTON_IN_MODAL);
};

const okButton = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@

import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import { useTracking } from 'react-tracking';
import PropTypes from 'prop-types';
import { defineMessages, useIntl } from 'react-intl';
import classNames from 'classnames/bind';
import { LoaderBlock } from 'pages/inside/profilePage/modals/loaderBlock';
import { ModalLayout, withModal } from 'components/main/modal';
import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
import { deleteApiKeyAction } from 'controllers/user';
import { PROFILE_EVENTS } from 'analyticsEvents/profilePageEvent';
import styles from './revokeApiKeyModal.scss';

const cx = classNames.bind(styles);
Expand Down Expand Up @@ -56,6 +58,7 @@ const messages = defineMessages({
const RevokeApiKey = ({ data }) => {
const { formatMessage } = useIntl();
const dispatch = useDispatch();
const { trackEvent } = useTracking();
const { name, id } = data;
const [loading, setLoading] = useState(false);

Expand All @@ -69,6 +72,7 @@ const RevokeApiKey = ({ data }) => {
closeModal,
),
);
trackEvent(PROFILE_EVENTS.CLICK_REVOKE_BUTTON_IN_MODAL);
};

const revokeButton = {
Expand Down
2 changes: 2 additions & 0 deletions app/src/pages/inside/profilePage/profilePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
PROJECT_ASSIGNMENT_ROUTE,
} from 'common/constants/userProfileRoutes';
import { DeleteAccountBlock } from 'pages/inside/profilePage/deleteAccountBlock';
import { PROFILE_EVENTS } from 'analyticsEvents/profilePageEvent';
import { PersonalInfoBlock } from './personalInfoBlock';
import { ApiKeys } from './apiKeys';
import { AssignedProjectsBlock } from './assignedProjectsBlock';
Expand Down Expand Up @@ -76,6 +77,7 @@ const getNavigationTabsConfig = (formatMessage) => ({
name: formatMessage(messages.profilePageProjectApiKeysTab),
link: getProfilePageLink(API_KEYS_ROUTE),
component: <ApiKeys />,
eventInfo: PROFILE_EVENTS.CLICK_API_KEYS_TAB_EVENT,
},
[CONFIG_EXAMPLES_ROUTE]: {
name: formatMessage(messages.profilePageConfigurationExamplesTab),
Expand Down

0 comments on commit 8f51d16

Please sign in to comment.