Add tracked event to upload plugin

Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
soupette 2021-11-15 11:47:23 +01:00
parent f2259ee269
commit 610d5976bc
11 changed files with 146 additions and 62 deletions

View File

@ -29,6 +29,7 @@ export const AssetDialog = ({
onValidate, onValidate,
multiple, multiple,
initiallySelectedAssets, initiallySelectedAssets,
trackedLocation,
}) => { }) => {
const [assetToEdit, setAssetToEdit] = useState(undefined); const [assetToEdit, setAssetToEdit] = useState(undefined);
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
@ -153,6 +154,7 @@ export const AssetDialog = ({
canUpdate={canUpdate} canUpdate={canUpdate}
canCopyLink={canCopyLink} canCopyLink={canCopyLink}
canDownload={canDownload} canDownload={canDownload}
trackedLocation={trackedLocation}
/> />
); );
} }
@ -232,6 +234,7 @@ AssetDialog.defaultProps = {
allowedTypes: [], allowedTypes: [],
initiallySelectedAssets: [], initiallySelectedAssets: [],
multiple: false, multiple: false,
trackedLocation: undefined,
}; };
AssetDialog.propTypes = { AssetDialog.propTypes = {
@ -241,4 +244,5 @@ AssetDialog.propTypes = {
onAddAsset: PropTypes.func.isRequired, onAddAsset: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
onValidate: PropTypes.func.isRequired, onValidate: PropTypes.func.isRequired,
trackedLocation: PropTypes.string,
}; };

View File

@ -1,16 +1,23 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { useRef } from 'react'; import React, { useRef } from 'react';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { useTracking } from '@strapi/helper-plugin';
import { Button } from '@strapi/design-system/Button'; import { Button } from '@strapi/design-system/Button';
import { VisuallyHidden } from '@strapi/design-system/VisuallyHidden'; import { VisuallyHidden } from '@strapi/design-system/VisuallyHidden';
import { getTrad } from '../../utils'; import { getTrad } from '../../utils';
export const ReplaceMediaButton = ({ onSelectMedia, acceptedMime, ...props }) => { export const ReplaceMediaButton = ({ onSelectMedia, acceptedMime, trackedLocation, ...props }) => {
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const inputRef = useRef(null); const inputRef = useRef(null);
const { trackUsage } = useTracking();
const handleClick = e => { const handleClick = e => {
e.preventDefault(); e.preventDefault();
if (trackedLocation) {
trackUsage('didReplaceMedia', { location: trackedLocation });
}
inputRef.current.click(); inputRef.current.click();
}; };
@ -43,7 +50,12 @@ export const ReplaceMediaButton = ({ onSelectMedia, acceptedMime, ...props }) =>
); );
}; };
ReplaceMediaButton.defaultProps = {
trackedLocation: undefined,
};
ReplaceMediaButton.propTypes = { ReplaceMediaButton.propTypes = {
acceptedMime: PropTypes.string.isRequired, acceptedMime: PropTypes.string.isRequired,
onSelectMedia: PropTypes.func.isRequired, onSelectMedia: PropTypes.func.isRequired,
trackedLocation: PropTypes.string,
}; };

View File

@ -36,7 +36,14 @@ const fileInfoSchema = yup.object({
caption: yup.string(), 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 { formatMessage, formatDate } = useIntl();
const submitButtonRef = useRef(null); const submitButtonRef = useRef(null);
const [isCropping, setIsCropping] = useState(false); const [isCropping, setIsCropping] = useState(false);
@ -183,6 +190,7 @@ export const EditAssetDialog = ({ onClose, asset, canUpdate, canCopyLink, canDow
onSelectMedia={setReplacementFile} onSelectMedia={setReplacementFile}
acceptedMime={asset.mime} acceptedMime={asset.mime}
disabled={formDisabled} disabled={formDisabled}
trackedLocation={trackedLocation}
/> />
<Button <Button
@ -200,10 +208,15 @@ export const EditAssetDialog = ({ onClose, asset, canUpdate, canCopyLink, canDow
); );
}; };
EditAssetDialog.defaultProps = {
trackedLocation: undefined,
};
EditAssetDialog.propTypes = { EditAssetDialog.propTypes = {
asset: AssetDefinition.isRequired, asset: AssetDefinition.isRequired,
canUpdate: PropTypes.bool.isRequired, canUpdate: PropTypes.bool.isRequired,
canCopyLink: PropTypes.bool.isRequired, canCopyLink: PropTypes.bool.isRequired,
canDownload: PropTypes.bool.isRequired, canDownload: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
trackedLocation: PropTypes.string,
}; };

View File

@ -23,6 +23,7 @@ export const CarouselAssets = ({
onNext, onNext,
onPrevious, onPrevious,
selectedAssetIndex, selectedAssetIndex,
trackedLocation,
}) => { }) => {
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const [isEditingAsset, setIsEditingAsset] = useState(false); const [isEditingAsset, setIsEditingAsset] = useState(false);
@ -105,6 +106,7 @@ export const CarouselAssets = ({
canUpdate canUpdate
canCopyLink canCopyLink
canDownload canDownload
trackedLocation={trackedLocation}
/> />
)} )}
</> </>
@ -116,6 +118,7 @@ CarouselAssets.defaultProps = {
error: undefined, error: undefined,
hint: undefined, hint: undefined,
onDropAsset: undefined, onDropAsset: undefined,
trackedLocation: undefined,
}; };
CarouselAssets.propTypes = { CarouselAssets.propTypes = {
@ -132,4 +135,5 @@ CarouselAssets.propTypes = {
onNext: PropTypes.func.isRequired, onNext: PropTypes.func.isRequired,
onPrevious: PropTypes.func.isRequired, onPrevious: PropTypes.func.isRequired,
selectedAssetIndex: PropTypes.number.isRequired, selectedAssetIndex: PropTypes.number.isRequired,
trackedLocation: PropTypes.string,
}; };

View File

@ -150,6 +150,7 @@ export const MediaLibraryInput = ({
error={errorMessage} error={errorMessage}
hint={hint} hint={hint}
selectedAssetIndex={selectedIndex} selectedAssetIndex={selectedIndex}
trackedLocation="content-manager"
/> />
{step === Steps.SelectAsset && ( {step === Steps.SelectAsset && (
@ -160,6 +161,7 @@ export const MediaLibraryInput = ({
onValidate={handleValidation} onValidate={handleValidation}
multiple={multiple} multiple={multiple}
onAddAsset={() => setStep(Steps.UploadAsset)} onAddAsset={() => setStep(Steps.UploadAsset)}
trackedLocation="content-manager"
/> />
)} )}
@ -168,6 +170,7 @@ export const MediaLibraryInput = ({
onClose={() => setStep(Steps.SelectAsset)} onClose={() => setStep(Steps.SelectAsset)}
initialAssetsToAdd={droppedAssets} initialAssetsToAdd={droppedAssets}
addUploadedFiles={handleFilesUploadSucceeded} addUploadedFiles={handleFilesUploadSucceeded}
trackedLocation="content-manager"
/> />
)} )}
</> </>

View File

@ -10,7 +10,7 @@ import { FromUrlForm } from './FromUrlForm';
import { FromComputerForm } from './FromComputerForm'; import { FromComputerForm } from './FromComputerForm';
import getTrad from '../../../utils/getTrad'; import getTrad from '../../../utils/getTrad';
export const AddAssetStep = ({ onClose, onAddAsset }) => { export const AddAssetStep = ({ onClose, onAddAsset, trackedLocation }) => {
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
return ( return (
@ -51,10 +51,18 @@ export const AddAssetStep = ({ onClose, onAddAsset }) => {
</Box> </Box>
<TabPanels> <TabPanels>
<TabPanel> <TabPanel>
<FromComputerForm onClose={onClose} onAddAssets={onAddAsset} /> <FromComputerForm
onClose={onClose}
onAddAssets={onAddAsset}
trackedLocation={trackedLocation}
/>
</TabPanel> </TabPanel>
<TabPanel> <TabPanel>
<FromUrlForm onClose={onClose} onAddAsset={onAddAsset} /> <FromUrlForm
onClose={onClose}
onAddAsset={onAddAsset}
trackedLocation={trackedLocation}
/>
</TabPanel> </TabPanel>
</TabPanels> </TabPanels>
</TabGroup> </TabGroup>
@ -62,7 +70,12 @@ export const AddAssetStep = ({ onClose, onAddAsset }) => {
); );
}; };
AddAssetStep.defaultProps = {
trackedLocation: undefined,
};
AddAssetStep.propTypes = { AddAssetStep.propTypes = {
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
onAddAsset: PropTypes.func.isRequired, onAddAsset: PropTypes.func.isRequired,
trackedLocation: PropTypes.string,
}; };

View File

@ -5,6 +5,7 @@ import styled from 'styled-components';
import { Box } from '@strapi/design-system/Box'; import { Box } from '@strapi/design-system/Box';
import { Flex } from '@strapi/design-system/Flex'; import { Flex } from '@strapi/design-system/Flex';
import { H3 } from '@strapi/design-system/Text'; import { H3 } from '@strapi/design-system/Text';
import { useTracking } from '@strapi/helper-plugin';
import { ModalFooter } from '@strapi/design-system/ModalLayout'; import { ModalFooter } from '@strapi/design-system/ModalLayout';
import { Button } from '@strapi/design-system/Button'; import { Button } from '@strapi/design-system/Button';
import PicturePlus from '@strapi/icons/PicturePlus'; import PicturePlus from '@strapi/icons/PicturePlus';
@ -34,10 +35,11 @@ const OpaqueBox = styled(Box)`
cursor: pointer; cursor: pointer;
`; `;
export const FromComputerForm = ({ onClose, onAddAssets }) => { export const FromComputerForm = ({ onClose, onAddAssets, trackedLocation }) => {
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const [dragOver, setDragOver] = useState(false); const [dragOver, setDragOver] = useState(false);
const inputRef = useRef(null); const inputRef = useRef(null);
const { trackUsage } = useTracking();
const handleDragEnter = () => setDragOver(true); const handleDragEnter = () => setDragOver(true);
const handleDragLeave = () => setDragOver(false); const handleDragLeave = () => setDragOver(false);
@ -58,6 +60,10 @@ export const FromComputerForm = ({ onClose, onAddAssets }) => {
assets.push(asset); assets.push(asset);
} }
if (trackedLocation) {
trackUsage('didSelectFile', { source: 'computer', location: trackedLocation });
}
onAddAssets(assets); onAddAssets(assets);
}; };
@ -136,7 +142,12 @@ export const FromComputerForm = ({ onClose, onAddAssets }) => {
); );
}; };
FromComputerForm.defaultProps = {
trackedLocation: undefined,
};
FromComputerForm.propTypes = { FromComputerForm.propTypes = {
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
onAddAssets: PropTypes.func.isRequired, onAddAssets: PropTypes.func.isRequired,
trackedLocation: PropTypes.string,
}; };

View File

@ -5,16 +5,17 @@ import { ModalFooter } from '@strapi/design-system/ModalLayout';
import { Textarea } from '@strapi/design-system/Textarea'; import { Textarea } from '@strapi/design-system/Textarea';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { Button } from '@strapi/design-system/Button'; import { Button } from '@strapi/design-system/Button';
import { Form } from '@strapi/helper-plugin'; import { Form, useTracking } from '@strapi/helper-plugin';
import { Formik } from 'formik'; import { Formik } from 'formik';
import getTrad from '../../../utils/getTrad'; import getTrad from '../../../utils/getTrad';
import { urlSchema } from '../../../utils/urlYupSchema'; import { urlSchema } from '../../../utils/urlYupSchema';
import { urlsToAssets } from '../../../utils/urlsToAssets'; import { urlsToAssets } from '../../../utils/urlsToAssets';
export const FromUrlForm = ({ onClose, onAddAsset }) => { export const FromUrlForm = ({ onClose, onAddAsset, trackedLocation }) => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState(undefined); const [error, setError] = useState(undefined);
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const { trackUsage } = useTracking();
const handleSubmit = async ({ urls }) => { const handleSubmit = async ({ urls }) => {
setLoading(true); setLoading(true);
@ -22,6 +23,10 @@ export const FromUrlForm = ({ onClose, onAddAsset }) => {
try { try {
const assets = await urlsToAssets(urlArray); const assets = await urlsToAssets(urlArray);
if (trackedLocation) {
trackUsage('didSelectFile', { source: 'url', location: trackedLocation });
}
// no need to set the loading to false since the component unmounts // no need to set the loading to false since the component unmounts
onAddAsset(assets); onAddAsset(assets);
} catch (e) { } catch (e) {
@ -83,7 +88,12 @@ export const FromUrlForm = ({ onClose, onAddAsset }) => {
); );
}; };
FromUrlForm.defaultProps = {
trackedLocation: undefined,
};
FromUrlForm.propTypes = { FromUrlForm.propTypes = {
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
onAddAsset: PropTypes.func.isRequired, onAddAsset: PropTypes.func.isRequired,
trackedLocation: PropTypes.string,
}; };

View File

@ -106,55 +106,6 @@ describe('FromComputerForm', () => {
color: #666687; color: #666687;
} }
.c16 {
background: #f6f6f9;
padding-top: 16px;
padding-right: 20px;
padding-bottom: 16px;
padding-left: 20px;
}
.c18 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c19 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c17 {
border-radius: 0 0 4px 4px;
border-top: 1px solid #eaeaef;
}
.c20 > * + * {
margin-left: 8px;
}
.c15 { .c15 {
font-weight: 600; font-weight: 600;
color: #32324d; color: #32324d;
@ -232,7 +183,7 @@ describe('FromComputerForm', () => {
background: #4945ff; background: #4945ff;
} }
.c13 .sc-jcRCNh { .c13 .sc-gfaqzF {
display: -webkit-box; display: -webkit-box;
display: -webkit-flex; display: -webkit-flex;
display: -ms-flexbox; display: -ms-flexbox;
@ -297,7 +248,7 @@ describe('FromComputerForm', () => {
background: #ffffff; background: #ffffff;
} }
.c21 .sc-jcRCNh { .c21 .sc-gfaqzF {
display: -webkit-box; display: -webkit-box;
display: -webkit-flex; display: -webkit-flex;
display: -ms-flexbox; display: -ms-flexbox;
@ -357,6 +308,55 @@ describe('FromComputerForm', () => {
fill: #32324d; fill: #32324d;
} }
.c16 {
background: #f6f6f9;
padding-top: 16px;
padding-right: 20px;
padding-bottom: 16px;
padding-left: 20px;
}
.c18 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c19 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c17 {
border-radius: 0 0 4px 4px;
border-top: 1px solid #eaeaef;
}
.c20 > * + * {
margin-left: 8px;
}
.c5 { .c5 {
-webkit-flex-direction: column; -webkit-flex-direction: column;
-ms-flex-direction: column; -ms-flex-direction: column;

View File

@ -10,7 +10,12 @@ const Steps = {
PendingAsset: 'PendingAsset', PendingAsset: 'PendingAsset',
}; };
export const UploadAssetDialog = ({ initialAssetsToAdd, onClose, addUploadedFiles }) => { export const UploadAssetDialog = ({
initialAssetsToAdd,
onClose,
addUploadedFiles,
trackedLocation,
}) => {
const [step, setStep] = useState(initialAssetsToAdd ? Steps.PendingAsset : Steps.AddAsset); const [step, setStep] = useState(initialAssetsToAdd ? Steps.PendingAsset : Steps.AddAsset);
const [assets, setAssets] = useState(initialAssetsToAdd || []); const [assets, setAssets] = useState(initialAssetsToAdd || []);
@ -45,7 +50,11 @@ export const UploadAssetDialog = ({ initialAssetsToAdd, onClose, addUploadedFile
return ( return (
<ModalLayout onClose={onClose} labelledBy="title"> <ModalLayout onClose={onClose} labelledBy="title">
{step === Steps.AddAsset && ( {step === Steps.AddAsset && (
<AddAssetStep onClose={onClose} onAddAsset={handleAddToPendingAssets} /> <AddAssetStep
onClose={onClose}
onAddAsset={handleAddToPendingAssets}
trackedLocation={trackedLocation}
/>
)} )}
{step === Steps.PendingAsset && ( {step === Steps.PendingAsset && (
<PendingAssetStep <PendingAssetStep
@ -65,10 +74,12 @@ export const UploadAssetDialog = ({ initialAssetsToAdd, onClose, addUploadedFile
UploadAssetDialog.defaultProps = { UploadAssetDialog.defaultProps = {
addUploadedFiles: undefined, addUploadedFiles: undefined,
initialAssetsToAdd: undefined, initialAssetsToAdd: undefined,
trackedLocation: undefined,
}; };
UploadAssetDialog.propTypes = { UploadAssetDialog.propTypes = {
addUploadedFiles: PropTypes.func, addUploadedFiles: PropTypes.func,
initialAssetsToAdd: PropTypes.arrayOf(AssetDefinition), initialAssetsToAdd: PropTypes.arrayOf(AssetDefinition),
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
trackedLocation: PropTypes.string,
}; };

View File

@ -198,7 +198,9 @@ export const MediaLibrary = () => {
</ContentLayout> </ContentLayout>
</Main> </Main>
{showUploadAssetDialog && <UploadAssetDialog onClose={toggleUploadAssetDialog} />} {showUploadAssetDialog && (
<UploadAssetDialog onClose={toggleUploadAssetDialog} trackedLocation="upload" />
)}
{assetToEdit && ( {assetToEdit && (
<EditAssetDialog <EditAssetDialog
onClose={() => setAssetToEdit(undefined)} onClose={() => setAssetToEdit(undefined)}
@ -206,6 +208,7 @@ export const MediaLibrary = () => {
canUpdate={canUpdate} canUpdate={canUpdate}
canCopyLink={canCopyLink} canCopyLink={canCopyLink}
canDownload={canDownload} canDownload={canDownload}
trackedLocation="upload"
/> />
)} )}
</Layout> </Layout>