diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicTable/TableRows/index.js b/packages/core/admin/admin/src/content-manager/components/DynamicTable/TableRows/index.js index 2fcb1da4c0..406b5e4aba 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicTable/TableRows/index.js +++ b/packages/core/admin/admin/src/content-manager/components/DynamicTable/TableRows/index.js @@ -51,7 +51,7 @@ const TableRows = ({ key={data.id} {...onRowClick({ fn: () => { - trackUsage('willEditEntryFromButton'); + trackUsage('willEditEntryFromList'); push({ pathname: `${pathname}/${data.id}`, state: { from: pathname }, @@ -141,7 +141,11 @@ const TableRows = ({ {canDelete && ( onClickDelete(data.id)} + onClick={() => { + trackUsage('willDeleteEntryFromList'); + + onClickDelete(data.id); + }} label={formatMessage( { id: 'app.component.table.delete', defaultMessage: 'Delete {target}' }, { target: itemLineText } diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicTable/index.js b/packages/core/admin/admin/src/content-manager/components/DynamicTable/index.js index e958f00781..94871749cc 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicTable/index.js +++ b/packages/core/admin/admin/src/content-manager/components/DynamicTable/index.js @@ -81,6 +81,7 @@ const DynamicTable = ({ headers={tableHeaders} onConfirmDelete={onConfirmDelete} onConfirmDeleteAll={onConfirmDeleteAll} + onOpenDeleteAllModalTrackedEvent="willBulkDeleteEntries" rows={rows} withBulkActions withMainAction={canDelete && isBulkable} diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/FieldPicker/index.js b/packages/core/admin/admin/src/content-manager/pages/ListView/FieldPicker/index.js index f3be1d19ff..3fe7db35b3 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/FieldPicker/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/ListView/FieldPicker/index.js @@ -26,6 +26,8 @@ const FieldPicker = ({ layout }) => { const values = displayedHeaders.map(({ name }) => name); const handleChange = updatedValues => { + trackUsage('didChangeDisplayedFields'); + // removing a header if (updatedValues.length < values.length) { const removedHeader = values.filter(value => { @@ -34,7 +36,6 @@ const FieldPicker = ({ layout }) => { dispatch(onChangeListHeaders({ name: removedHeader[0], value: true })); } else { - trackUsage('didChangeDisplayedFields'); const addedHeader = updatedValues.filter(value => { return values.indexOf(value) === -1; }); diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/index.js b/packages/core/admin/admin/src/content-manager/pages/ListView/index.js index 10d445ba60..41652efd49 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/ListView/index.js @@ -7,7 +7,6 @@ import { bindActionCreators, compose } from 'redux'; import { useIntl } from 'react-intl'; import { useHistory, useLocation } from 'react-router-dom'; import get from 'lodash/get'; -import isEmpty from 'lodash/isEmpty'; import { stringify } from 'qs'; import { NoPermissions, @@ -171,18 +170,6 @@ function ListView({ const handleConfirmDeleteData = useCallback( async idToDelete => { try { - let trackerProperty = {}; - - if (hasDraftAndPublish) { - const dataToDelete = data.find(obj => obj.id.toString() === idToDelete.toString()); - const isDraftEntry = isEmpty(dataToDelete.publishedAt); - const status = isDraftEntry ? 'draft' : 'published'; - - trackerProperty = { status }; - } - - trackUsageRef.current('willDeleteEntry', trackerProperty); - await axiosInstance.delete(getRequestUrl(`collection-types/${slug}/${idToDelete}`)); const requestUrl = getRequestUrl(`collection-types/${slug}${params}`); @@ -192,8 +179,6 @@ function ListView({ type: 'success', message: { id: getTrad('success.record.delete') }, }); - - trackUsageRef.current('didDeleteEntry', trackerProperty); } catch (err) { const errorMessage = get( err, @@ -207,7 +192,7 @@ function ListView({ }); } }, - [hasDraftAndPublish, slug, params, fetchData, toggleNotification, data, formatMessage] + [slug, params, fetchData, toggleNotification, formatMessage] ); useEffect(() => { @@ -282,8 +267,11 @@ function ListView({ - push({ pathname: `${slug}/configurations/list`, search: pluginsQueryParams })} + onClick={() => { + trackUsage('willEditListLayout'); + + push({ pathname: `${slug}/configurations/list`, search: pluginsQueryParams }); + }} icon={} label={formatMessage({ id: 'app.links.configure-view', diff --git a/packages/core/admin/admin/src/pages/MarketplacePage/index.js b/packages/core/admin/admin/src/pages/MarketplacePage/index.js index 0cbd7e23c7..f6cc804d09 100644 --- a/packages/core/admin/admin/src/pages/MarketplacePage/index.js +++ b/packages/core/admin/admin/src/pages/MarketplacePage/index.js @@ -1,8 +1,8 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { useIntl } from 'react-intl'; import styled from 'styled-components'; import { Helmet } from 'react-helmet'; -import { pxToRem, CheckPagePermissions } from '@strapi/helper-plugin'; +import { pxToRem, CheckPagePermissions, useTracking } from '@strapi/helper-plugin'; import { Layout, HeaderLayout, ContentLayout } from '@strapi/design-system/Layout'; import { Flex } from '@strapi/design-system/Flex'; import { Box } from '@strapi/design-system/Box'; @@ -27,6 +27,11 @@ const StackCentered = styled(Stack)` const MarketPlacePage = () => { const { formatMessage } = useIntl(); + const { trackUsage } = useTracking(); + + useEffect(() => { + trackUsage('didGoToMarketplace'); + }, [trackUsage]); return ( diff --git a/packages/core/admin/admin/src/pages/MarketplacePage/tests/index.test.js b/packages/core/admin/admin/src/pages/MarketplacePage/tests/index.test.js index 69238a7394..1995b8b6a3 100644 --- a/packages/core/admin/admin/src/pages/MarketplacePage/tests/index.test.js +++ b/packages/core/admin/admin/src/pages/MarketplacePage/tests/index.test.js @@ -2,11 +2,13 @@ import React from 'react'; import { render } from '@testing-library/react'; import { IntlProvider } from 'react-intl'; import { ThemeProvider, lightTheme } from '@strapi/design-system'; +import { useTracking } from '@strapi/helper-plugin'; import MarketPlacePage from '../index'; jest.mock('@strapi/helper-plugin', () => ({ pxToRem: jest.fn(), CheckPagePermissions: ({ children }) => children, + useTracking: jest.fn(() => ({ trackUsage: jest.fn() })), })); const App = ( @@ -440,4 +442,12 @@ describe('Marketplace coming soon', () => { `); }); + + it('sends an event when the user enters the marketplace', () => { + const trackUsage = jest.fn(); + useTracking.mockImplementation(() => ({ trackUsage })); + render(App); + + expect(trackUsage).toHaveBeenCalledWith('didGoToMarketplace'); + }); }); diff --git a/packages/core/helper-plugin/lib/src/components/DynamicTable/index.js b/packages/core/helper-plugin/lib/src/components/DynamicTable/index.js index ad6f19d8ca..65bd6f79ac 100644 --- a/packages/core/helper-plugin/lib/src/components/DynamicTable/index.js +++ b/packages/core/helper-plugin/lib/src/components/DynamicTable/index.js @@ -9,6 +9,7 @@ import { useIntl } from 'react-intl'; import Trash from '@strapi/icons/Trash'; import styled from 'styled-components'; import useQueryParams from '../../hooks/useQueryParams'; +import useTracking from '../../hooks/useTracking'; import ConfirmDialog from '../ConfirmDialog'; import EmptyBodyTable from '../EmptyBodyTable'; import TableHead from './TableHead'; @@ -29,6 +30,7 @@ const Table = ({ isLoading, onConfirmDeleteAll, onConfirmDelete, + onOpenDeleteAllModalTrackedEvent, rows, withBulkActions, withMainAction, @@ -40,6 +42,7 @@ const Table = ({ const [isConfirmButtonLoading, setIsConfirmButtonLoading] = useState(false); const [{ query }] = useQueryParams(); const { formatMessage } = useIntl(); + const { trackUsage } = useTracking(); const ROW_COUNT = rows.length + 1; const COL_COUNT = headers.length + (withBulkActions ? 1 : 0) + (withMainAction ? 1 : 0); const hasFilters = query?.filters !== undefined; @@ -88,6 +91,10 @@ const Table = ({ }; const handleToggleConfirmDeleteAll = () => { + if (!showConfirmDeleteAll && onOpenDeleteAllModalTrackedEvent) { + trackUsage(onOpenDeleteAllModalTrackedEvent); + } + setShowConfirmDeleteAll(prev => !prev); }; @@ -203,6 +210,7 @@ Table.defaultProps = { isLoading: false, onConfirmDeleteAll: () => {}, onConfirmDelete: () => {}, + onOpenDeleteAllModalTrackedEvent: undefined, rows: [], withBulkActions: false, withMainAction: false, @@ -229,6 +237,7 @@ Table.propTypes = { isLoading: PropTypes.bool, onConfirmDeleteAll: PropTypes.func, onConfirmDelete: PropTypes.func, + onOpenDeleteAllModalTrackedEvent: PropTypes.string, rows: PropTypes.array, withBulkActions: PropTypes.bool, withMainAction: PropTypes.bool, diff --git a/packages/core/upload/admin/src/components/AssetDialog/index.js b/packages/core/upload/admin/src/components/AssetDialog/index.js index f76e3afad0..2ece995b23 100644 --- a/packages/core/upload/admin/src/components/AssetDialog/index.js +++ b/packages/core/upload/admin/src/components/AssetDialog/index.js @@ -29,6 +29,7 @@ export const AssetDialog = ({ onValidate, multiple, initiallySelectedAssets, + trackedLocation, }) => { const [assetToEdit, setAssetToEdit] = useState(undefined); const { formatMessage } = useIntl(); @@ -153,6 +154,7 @@ export const AssetDialog = ({ canUpdate={canUpdate} canCopyLink={canCopyLink} canDownload={canDownload} + trackedLocation={trackedLocation} /> ); } @@ -232,6 +234,7 @@ AssetDialog.defaultProps = { allowedTypes: [], initiallySelectedAssets: [], multiple: false, + trackedLocation: undefined, }; AssetDialog.propTypes = { @@ -241,4 +244,5 @@ AssetDialog.propTypes = { onAddAsset: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired, onValidate: PropTypes.func.isRequired, + trackedLocation: PropTypes.string, }; diff --git a/packages/core/upload/admin/src/components/EditAssetDialog/ReplaceMediaButton.js b/packages/core/upload/admin/src/components/EditAssetDialog/ReplaceMediaButton.js index eb3ef2b324..4819d6b991 100644 --- a/packages/core/upload/admin/src/components/EditAssetDialog/ReplaceMediaButton.js +++ b/packages/core/upload/admin/src/components/EditAssetDialog/ReplaceMediaButton.js @@ -1,16 +1,23 @@ import PropTypes from 'prop-types'; import React, { useRef } from 'react'; import { useIntl } from 'react-intl'; +import { useTracking } from '@strapi/helper-plugin'; import { Button } from '@strapi/design-system/Button'; import { VisuallyHidden } from '@strapi/design-system/VisuallyHidden'; import { getTrad } from '../../utils'; -export const ReplaceMediaButton = ({ onSelectMedia, acceptedMime, ...props }) => { +export const ReplaceMediaButton = ({ onSelectMedia, acceptedMime, trackedLocation, ...props }) => { const { formatMessage } = useIntl(); const inputRef = useRef(null); + const { trackUsage } = useTracking(); const handleClick = e => { e.preventDefault(); + + if (trackedLocation) { + trackUsage('didReplaceMedia', { location: trackedLocation }); + } + inputRef.current.click(); }; @@ -43,7 +50,12 @@ export const ReplaceMediaButton = ({ onSelectMedia, acceptedMime, ...props }) => ); }; +ReplaceMediaButton.defaultProps = { + trackedLocation: undefined, +}; + ReplaceMediaButton.propTypes = { acceptedMime: PropTypes.string.isRequired, onSelectMedia: PropTypes.func.isRequired, + trackedLocation: PropTypes.string, }; diff --git a/packages/core/upload/admin/src/components/EditAssetDialog/index.js b/packages/core/upload/admin/src/components/EditAssetDialog/index.js index e5f4f41b27..f56f710e28 100644 --- a/packages/core/upload/admin/src/components/EditAssetDialog/index.js +++ b/packages/core/upload/admin/src/components/EditAssetDialog/index.js @@ -36,7 +36,14 @@ const fileInfoSchema = yup.object({ caption: yup.string(), }); -export const EditAssetDialog = ({ onClose, asset, canUpdate, canCopyLink, canDownload }) => { +export const EditAssetDialog = ({ + onClose, + asset, + canUpdate, + canCopyLink, + canDownload, + trackedLocation, +}) => { const { formatMessage, formatDate } = useIntl(); const submitButtonRef = useRef(null); const [isCropping, setIsCropping] = useState(false); @@ -183,6 +190,7 @@ export const EditAssetDialog = ({ onClose, asset, canUpdate, canCopyLink, canDow onSelectMedia={setReplacementFile} acceptedMime={asset.mime} disabled={formDisabled} + trackedLocation={trackedLocation} />