mirror of
https://github.com/strapi/strapi.git
synced 2025-11-18 02:58:05 +00:00
fix: update tracking on homepage widgets (#24153)
This commit is contained in:
parent
9651e7ce33
commit
330c50cc41
@ -1,4 +1,4 @@
|
|||||||
import { useAuth } from '@strapi/admin/strapi-admin';
|
import { useAuth, useTracking } from '@strapi/admin/strapi-admin';
|
||||||
import { Avatar, Badge, Box, Flex, Typography } from '@strapi/design-system';
|
import { Avatar, Badge, Box, Flex, Typography } from '@strapi/design-system';
|
||||||
import { Earth, Images, User, Key, Files, Layout, Graph, Webhooks } from '@strapi/icons';
|
import { Earth, Images, User, Key, Files, Layout, Graph, Webhooks } from '@strapi/icons';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
@ -85,6 +85,7 @@ const LinkCell = styled(Link)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const KeyStatisticsWidget = () => {
|
const KeyStatisticsWidget = () => {
|
||||||
|
const { trackUsage } = useTracking();
|
||||||
const { formatMessage, locale } = useIntl();
|
const { formatMessage, locale } = useIntl();
|
||||||
const { data: countDocuments, isLoading: isLoadingCountDocuments } = useGetCountDocumentsQuery();
|
const { data: countDocuments, isLoading: isLoadingCountDocuments } = useGetCountDocumentsQuery();
|
||||||
const { data: countKeyStatistics, isLoading: isLoadingKeyStatistics } =
|
const { data: countKeyStatistics, isLoading: isLoadingKeyStatistics } =
|
||||||
@ -216,6 +217,7 @@ const KeyStatisticsWidget = () => {
|
|||||||
to={item.link}
|
to={item.link}
|
||||||
key={`key-statistics-${key}`}
|
key={`key-statistics-${key}`}
|
||||||
data-testid={`stat-${key}`}
|
data-testid={`stat-${key}`}
|
||||||
|
onClick={() => trackUsage('didOpenKeyStatisticsWidgetLink', { itemKey: key })}
|
||||||
>
|
>
|
||||||
<Flex alignItems="center" gap={2}>
|
<Flex alignItems="center" gap={2}>
|
||||||
<Flex
|
<Flex
|
||||||
|
|||||||
@ -7,7 +7,11 @@ import { Widget } from '../WidgetHelpers';
|
|||||||
describe('Homepage Widget component', () => {
|
describe('Homepage Widget component', () => {
|
||||||
it('should render the widget with info from props', () => {
|
it('should render the widget with info from props', () => {
|
||||||
render(
|
render(
|
||||||
<WidgetRoot title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }} icon={Cog}>
|
<WidgetRoot
|
||||||
|
title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}
|
||||||
|
icon={Cog}
|
||||||
|
uid="plugin::test.test-widget"
|
||||||
|
>
|
||||||
actual widget content
|
actual widget content
|
||||||
</WidgetRoot>
|
</WidgetRoot>
|
||||||
);
|
);
|
||||||
@ -19,7 +23,10 @@ describe('Homepage Widget component', () => {
|
|||||||
|
|
||||||
it('should render a spinner while a widget is loading', () => {
|
it('should render a spinner while a widget is loading', () => {
|
||||||
render(
|
render(
|
||||||
<WidgetRoot title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}>
|
<WidgetRoot
|
||||||
|
title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}
|
||||||
|
uid="plugin::test.test-widget"
|
||||||
|
>
|
||||||
<Widget.Loading />
|
<Widget.Loading />
|
||||||
</WidgetRoot>
|
</WidgetRoot>
|
||||||
);
|
);
|
||||||
@ -30,7 +37,10 @@ describe('Homepage Widget component', () => {
|
|||||||
|
|
||||||
it('should render an error message when a widget fails to load', () => {
|
it('should render an error message when a widget fails to load', () => {
|
||||||
render(
|
render(
|
||||||
<WidgetRoot title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}>
|
<WidgetRoot
|
||||||
|
title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}
|
||||||
|
uid="plugin::test.test-widget"
|
||||||
|
>
|
||||||
<Widget.Error />
|
<Widget.Error />
|
||||||
</WidgetRoot>
|
</WidgetRoot>
|
||||||
);
|
);
|
||||||
@ -41,7 +51,10 @@ describe('Homepage Widget component', () => {
|
|||||||
|
|
||||||
it('should render a custom error message when provided', () => {
|
it('should render a custom error message when provided', () => {
|
||||||
render(
|
render(
|
||||||
<WidgetRoot title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}>
|
<WidgetRoot
|
||||||
|
title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}
|
||||||
|
uid="plugin::test.test-widget"
|
||||||
|
>
|
||||||
<Widget.Error>Custom error message</Widget.Error>
|
<Widget.Error>Custom error message</Widget.Error>
|
||||||
</WidgetRoot>
|
</WidgetRoot>
|
||||||
);
|
);
|
||||||
@ -52,7 +65,10 @@ describe('Homepage Widget component', () => {
|
|||||||
|
|
||||||
it('should render a no data message when a widget has no data', () => {
|
it('should render a no data message when a widget has no data', () => {
|
||||||
render(
|
render(
|
||||||
<WidgetRoot title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}>
|
<WidgetRoot
|
||||||
|
title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}
|
||||||
|
uid="plugin::test.test-widget"
|
||||||
|
>
|
||||||
<Widget.NoData />
|
<Widget.NoData />
|
||||||
</WidgetRoot>
|
</WidgetRoot>
|
||||||
);
|
);
|
||||||
@ -62,7 +78,10 @@ describe('Homepage Widget component', () => {
|
|||||||
|
|
||||||
it('should render a custom no data message when provided', () => {
|
it('should render a custom no data message when provided', () => {
|
||||||
render(
|
render(
|
||||||
<WidgetRoot title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}>
|
<WidgetRoot
|
||||||
|
title={{ defaultMessage: 'Cool widget title', id: 'notarealid' }}
|
||||||
|
uid="plugin::test.test-widget"
|
||||||
|
>
|
||||||
<Widget.NoData>Custom no data message</Widget.NoData>
|
<Widget.NoData>Custom no data message</Widget.NoData>
|
||||||
</WidgetRoot>
|
</WidgetRoot>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -175,7 +175,6 @@ export interface EventWithoutProperties {
|
|||||||
| 'willEditEditLayout'
|
| 'willEditEditLayout'
|
||||||
| 'willEditEmailTemplates'
|
| 'willEditEmailTemplates'
|
||||||
| 'willEditEntryFromButton'
|
| 'willEditEntryFromButton'
|
||||||
| 'willEditEntryFromHome'
|
|
||||||
| 'willEditEntryFromList'
|
| 'willEditEntryFromList'
|
||||||
| 'willEditReleaseFromHome'
|
| 'willEditReleaseFromHome'
|
||||||
| 'willEditFieldOfContentType'
|
| 'willEditFieldOfContentType'
|
||||||
@ -187,7 +186,7 @@ export interface EventWithoutProperties {
|
|||||||
| 'willEditStage'
|
| 'willEditStage'
|
||||||
| 'willFilterEntries'
|
| 'willFilterEntries'
|
||||||
| 'willInstallPlugin'
|
| 'willInstallPlugin'
|
||||||
| 'willOpenAuditLogDetails'
|
| 'willOpenAuditLogDetailsFromHome'
|
||||||
| 'willUnpublishEntry'
|
| 'willUnpublishEntry'
|
||||||
| 'willSaveComponent'
|
| 'willSaveComponent'
|
||||||
| 'willSaveContentType'
|
| 'willSaveContentType'
|
||||||
@ -411,6 +410,27 @@ interface DidStartGuidedTour {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface WillEditEntryFromHome {
|
||||||
|
name: 'willEditEntryFromHome';
|
||||||
|
properties: {
|
||||||
|
entryType: 'edited' | 'published' | 'assigned';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DidOpenHomeWidgetLink {
|
||||||
|
name: 'didOpenHomeWidgetLink';
|
||||||
|
properties: {
|
||||||
|
widgetUID: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DidOpenKeyStatisticsWidgetLink {
|
||||||
|
name: 'didOpenKeyStatisticsWidgetLink';
|
||||||
|
properties: {
|
||||||
|
itemKey: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
type EventsWithProperties =
|
type EventsWithProperties =
|
||||||
| CreateEntryEvents
|
| CreateEntryEvents
|
||||||
| PublishEntryEvents
|
| PublishEntryEvents
|
||||||
@ -436,7 +456,10 @@ type EventsWithProperties =
|
|||||||
| DidUpdateCTBSchema
|
| DidUpdateCTBSchema
|
||||||
| DidSkipGuidedTour
|
| DidSkipGuidedTour
|
||||||
| DidCompleteGuidedTour
|
| DidCompleteGuidedTour
|
||||||
| DidStartGuidedTour;
|
| DidStartGuidedTour
|
||||||
|
| DidOpenHomeWidgetLink
|
||||||
|
| DidOpenKeyStatisticsWidgetLink
|
||||||
|
| WillEditEntryFromHome;
|
||||||
|
|
||||||
export type TrackingEvent = EventWithoutProperties | EventsWithProperties;
|
export type TrackingEvent = EventWithoutProperties | EventsWithProperties;
|
||||||
export interface UseTrackingReturn {
|
export interface UseTrackingReturn {
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import { Widget } from '../../components/WidgetHelpers';
|
|||||||
import { useEnterprise } from '../../ee';
|
import { useEnterprise } from '../../ee';
|
||||||
import { useAuth } from '../../features/Auth';
|
import { useAuth } from '../../features/Auth';
|
||||||
import { useStrapiApp } from '../../features/StrapiApp';
|
import { useStrapiApp } from '../../features/StrapiApp';
|
||||||
|
import { useTracking } from '../../features/Tracking';
|
||||||
|
|
||||||
import { FreeTrialEndedModal } from './components/FreeTrialEndedModal';
|
import { FreeTrialEndedModal } from './components/FreeTrialEndedModal';
|
||||||
import { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal';
|
import { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal';
|
||||||
@ -23,15 +24,21 @@ import type { WidgetType } from '@strapi/admin/strapi-admin';
|
|||||||
* WidgetRoot
|
* WidgetRoot
|
||||||
* -----------------------------------------------------------------------------------------------*/
|
* -----------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
interface WidgetRootProps extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link'> {
|
interface WidgetRootProps
|
||||||
|
extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link' | 'uid'> {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WidgetRoot = ({ title, icon = PuzzlePiece, children, link }: WidgetRootProps) => {
|
export const WidgetRoot = ({ title, icon = PuzzlePiece, children, link, uid }: WidgetRootProps) => {
|
||||||
|
const { trackUsage } = useTracking();
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const id = React.useId();
|
const id = React.useId();
|
||||||
const Icon = icon;
|
const Icon = icon;
|
||||||
|
|
||||||
|
const handleClickOnLink = () => {
|
||||||
|
trackUsage('didOpenHomeWidgetLink', { widgetUID: uid });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
width="100%"
|
width="100%"
|
||||||
@ -61,6 +68,7 @@ export const WidgetRoot = ({ title, icon = PuzzlePiece, children, link }: Widget
|
|||||||
style={{ textDecoration: 'none' }}
|
style={{ textDecoration: 'none' }}
|
||||||
textAlign="right"
|
textAlign="right"
|
||||||
to={link.href}
|
to={link.href}
|
||||||
|
onClick={handleClickOnLink}
|
||||||
>
|
>
|
||||||
{formatMessage(link.label)}
|
{formatMessage(link.label)}
|
||||||
</Typography>
|
</Typography>
|
||||||
@ -157,7 +165,12 @@ const HomePageCE = () => {
|
|||||||
<Grid.Root gap={5}>
|
<Grid.Root gap={5}>
|
||||||
{filteredWidgets.map((widget) => (
|
{filteredWidgets.map((widget) => (
|
||||||
<Grid.Item col={6} s={12} key={widget.uid}>
|
<Grid.Item col={6} s={12} key={widget.uid}>
|
||||||
<WidgetRoot title={widget.title} icon={widget.icon} link={widget.link}>
|
<WidgetRoot
|
||||||
|
title={widget.title}
|
||||||
|
icon={widget.icon}
|
||||||
|
link={widget.link}
|
||||||
|
uid={widget.uid}
|
||||||
|
>
|
||||||
<WidgetComponent component={widget.component} />
|
<WidgetComponent component={widget.component} />
|
||||||
</WidgetRoot>
|
</WidgetRoot>
|
||||||
</Grid.Item>
|
</Grid.Item>
|
||||||
|
|||||||
@ -30,7 +30,7 @@ const LastActivityTable = ({ items }: { items: AuditLog[] }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleRowClick = (document: AuditLog) => () => {
|
const handleRowClick = (document: AuditLog) => () => {
|
||||||
trackUsage('willOpenAuditLogDetails');
|
trackUsage('willOpenAuditLogDetailsFromHome');
|
||||||
const link = getAuditLogDetailsLink(document);
|
const link = getAuditLogDetailsLink(document);
|
||||||
navigate(link);
|
navigate(link);
|
||||||
};
|
};
|
||||||
@ -74,7 +74,7 @@ const LastActivityTable = ({ items }: { items: AuditLog[] }) => {
|
|||||||
<IconButton
|
<IconButton
|
||||||
tag={Link}
|
tag={Link}
|
||||||
to={getAuditLogDetailsLink(item)}
|
to={getAuditLogDetailsLink(item)}
|
||||||
onClick={() => trackUsage('willOpenAuditLogDetails')}
|
onClick={() => trackUsage('willOpenAuditLogDetailsFromHome')}
|
||||||
label={formatMessage({
|
label={formatMessage({
|
||||||
id: 'global.details',
|
id: 'global.details',
|
||||||
defaultMessage: 'Details',
|
defaultMessage: 'Details',
|
||||||
|
|||||||
@ -32,7 +32,13 @@ const CellTypography = styled(Typography)`
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const RecentDocumentsTable = ({ documents }: { documents: RecentDocument[] }) => {
|
const RecentDocumentsTable = ({
|
||||||
|
documents,
|
||||||
|
type,
|
||||||
|
}: {
|
||||||
|
documents: RecentDocument[];
|
||||||
|
type: 'edited' | 'published';
|
||||||
|
}) => {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const { trackUsage } = useTracking();
|
const { trackUsage } = useTracking();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -46,7 +52,9 @@ const RecentDocumentsTable = ({ documents }: { documents: RecentDocument[] }) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleRowClick = (document: RecentDocument) => () => {
|
const handleRowClick = (document: RecentDocument) => () => {
|
||||||
trackUsage('willEditEntryFromHome');
|
trackUsage('willEditEntryFromHome', {
|
||||||
|
entryType: type,
|
||||||
|
});
|
||||||
const link = getEditViewLink(document);
|
const link = getEditViewLink(document);
|
||||||
navigate(link);
|
navigate(link);
|
||||||
};
|
};
|
||||||
@ -95,7 +103,7 @@ const RecentDocumentsTable = ({ documents }: { documents: RecentDocument[] }) =>
|
|||||||
<IconButton
|
<IconButton
|
||||||
tag={Link}
|
tag={Link}
|
||||||
to={getEditViewLink(document)}
|
to={getEditViewLink(document)}
|
||||||
onClick={() => trackUsage('willEditEntryFromHome')}
|
onClick={() => trackUsage('willEditEntryFromHome', { type })}
|
||||||
label={formatMessage({
|
label={formatMessage({
|
||||||
id: 'content-manager.actions.edit.label',
|
id: 'content-manager.actions.edit.label',
|
||||||
defaultMessage: 'Edit',
|
defaultMessage: 'Edit',
|
||||||
@ -140,7 +148,7 @@ const LastEditedWidget = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <RecentDocumentsTable documents={data} />;
|
return <RecentDocumentsTable documents={data} type="edited" />;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------------------------------
|
/* -------------------------------------------------------------------------------------------------
|
||||||
@ -170,7 +178,7 @@ const LastPublishedWidget = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <RecentDocumentsTable documents={data} />;
|
return <RecentDocumentsTable documents={data} type="published" />;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------------------------------
|
/* -------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@ -19,7 +19,13 @@ const CellTypography = styled(Typography)`
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const RecentDocumentsTable = ({ documents }: { documents: RecentDocument[] }) => {
|
const RecentDocumentsTable = ({
|
||||||
|
documents,
|
||||||
|
type,
|
||||||
|
}: {
|
||||||
|
documents: RecentDocument[];
|
||||||
|
type: 'assigned';
|
||||||
|
}) => {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const { trackUsage } = useTracking();
|
const { trackUsage } = useTracking();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -33,7 +39,7 @@ const RecentDocumentsTable = ({ documents }: { documents: RecentDocument[] }) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleRowClick = (document: RecentDocument) => () => {
|
const handleRowClick = (document: RecentDocument) => () => {
|
||||||
trackUsage('willEditEntryFromHome');
|
trackUsage('willEditEntryFromHome', { entryType: type });
|
||||||
const link = getEditViewLink(document);
|
const link = getEditViewLink(document);
|
||||||
navigate(link);
|
navigate(link);
|
||||||
};
|
};
|
||||||
@ -85,7 +91,7 @@ const RecentDocumentsTable = ({ documents }: { documents: RecentDocument[] }) =>
|
|||||||
<IconButton
|
<IconButton
|
||||||
tag={Link}
|
tag={Link}
|
||||||
to={getEditViewLink(document)}
|
to={getEditViewLink(document)}
|
||||||
onClick={() => trackUsage('willEditEntryFromHome')}
|
onClick={() => trackUsage('willEditEntryFromHome', { entryType: type })}
|
||||||
label={formatMessage({
|
label={formatMessage({
|
||||||
id: 'content-manager.actions.edit.label',
|
id: 'content-manager.actions.edit.label',
|
||||||
defaultMessage: 'Edit',
|
defaultMessage: 'Edit',
|
||||||
@ -130,7 +136,7 @@ const AssignedWidget = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <RecentDocumentsTable documents={data} />;
|
return <RecentDocumentsTable documents={data} type="assigned" />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export { AssignedWidget };
|
export { AssignedWidget };
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user