mirror of
https://github.com/Unleash/unleash.git
synced 2024-12-22 19:07:54 +01:00
feat: batch operatsion plausible events (#3367)
This commit is contained in:
parent
180c9336cc
commit
55f8d5b09e
@ -11,6 +11,7 @@ import { formatUnknownError } from 'utils/formatUnknownError';
|
|||||||
import { useFeaturesArchive } from 'hooks/api/getters/useFeaturesArchive/useFeaturesArchive';
|
import { useFeaturesArchive } from 'hooks/api/getters/useFeaturesArchive/useFeaturesArchive';
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
import { ArchivedFeatureDeleteConfirm } from './ArchivedFeatureActionCell/ArchivedFeatureDeleteConfirm/ArchivedFeatureDeleteConfirm';
|
import { ArchivedFeatureDeleteConfirm } from './ArchivedFeatureActionCell/ArchivedFeatureDeleteConfirm/ArchivedFeatureDeleteConfirm';
|
||||||
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
|
|
||||||
interface IArchiveBatchActionsProps {
|
interface IArchiveBatchActionsProps {
|
||||||
selectedIds: string[];
|
selectedIds: string[];
|
||||||
@ -25,6 +26,7 @@ export const ArchiveBatchActions: FC<IArchiveBatchActionsProps> = ({
|
|||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
const { refetchArchived } = useFeaturesArchive(projectId);
|
const { refetchArchived } = useFeaturesArchive(projectId);
|
||||||
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
||||||
|
const { trackEvent } = usePlausibleTracker();
|
||||||
|
|
||||||
const onRevive = async () => {
|
const onRevive = async () => {
|
||||||
try {
|
try {
|
||||||
@ -35,6 +37,11 @@ export const ArchiveBatchActions: FC<IArchiveBatchActionsProps> = ({
|
|||||||
title: "And we're back!",
|
title: "And we're back!",
|
||||||
text: 'The feature toggles have been revived.',
|
text: 'The feature toggles have been revived.',
|
||||||
});
|
});
|
||||||
|
trackEvent('batch_operations', {
|
||||||
|
props: {
|
||||||
|
eventType: 'features revived',
|
||||||
|
},
|
||||||
|
});
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(error));
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
@ -76,7 +83,14 @@ export const ArchiveBatchActions: FC<IArchiveBatchActionsProps> = ({
|
|||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
open={deleteModalOpen}
|
open={deleteModalOpen}
|
||||||
setOpen={setDeleteModalOpen}
|
setOpen={setDeleteModalOpen}
|
||||||
refetch={refetchArchived}
|
refetch={() => {
|
||||||
|
refetchArchived();
|
||||||
|
trackEvent('batch_operations', {
|
||||||
|
props: {
|
||||||
|
eventType: 'features deleted',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -12,6 +12,7 @@ interface IExportDialogProps {
|
|||||||
showExportDialog: boolean;
|
showExportDialog: boolean;
|
||||||
data: Pick<FeatureSchema, 'name'>[];
|
data: Pick<FeatureSchema, 'name'>[];
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
onConfirm?: () => void;
|
||||||
environments: string[];
|
environments: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,6 +25,7 @@ export const ExportDialog = ({
|
|||||||
showExportDialog,
|
showExportDialog,
|
||||||
data,
|
data,
|
||||||
onClose,
|
onClose,
|
||||||
|
onConfirm,
|
||||||
environments,
|
environments,
|
||||||
}: IExportDialogProps) => {
|
}: IExportDialogProps) => {
|
||||||
const [selected, setSelected] = useState(environments[0]);
|
const [selected, setSelected] = useState(environments[0]);
|
||||||
@ -66,6 +68,7 @@ export const ExportDialog = ({
|
|||||||
const body = await res.json();
|
const body = await res.json();
|
||||||
downloadFile(body);
|
downloadFile(body);
|
||||||
onClose();
|
onClose();
|
||||||
|
onConfirm?.();
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
setToastApiError(formatUnknownError(e));
|
setToastApiError(formatUnknownError(e));
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import { PermissionHOC } from 'component/common/PermissionHOC/PermissionHOC';
|
|||||||
import { DELETE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
import { DELETE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
||||||
import useProject from 'hooks/api/getters/useProject/useProject';
|
import useProject from 'hooks/api/getters/useProject/useProject';
|
||||||
import { FeatureArchiveDialog } from 'component/common/FeatureArchiveDialog/FeatureArchiveDialog';
|
import { FeatureArchiveDialog } from 'component/common/FeatureArchiveDialog/FeatureArchiveDialog';
|
||||||
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
|
|
||||||
interface IArchiveButtonProps {
|
interface IArchiveButtonProps {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
@ -17,10 +18,16 @@ export const ArchiveButton: VFC<IArchiveButtonProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { refetch } = useProject(projectId);
|
const { refetch } = useProject(projectId);
|
||||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||||
|
const { trackEvent } = usePlausibleTracker();
|
||||||
|
|
||||||
const onConfirm = async () => {
|
const onConfirm = async () => {
|
||||||
setIsDialogOpen(false);
|
setIsDialogOpen(false);
|
||||||
await refetch();
|
await refetch();
|
||||||
|
trackEvent('batch_operations', {
|
||||||
|
props: {
|
||||||
|
eventType: 'features archived',
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -10,6 +10,7 @@ import { formatUnknownError } from 'utils/formatUnknownError';
|
|||||||
import useProject from 'hooks/api/getters/useProject/useProject';
|
import useProject from 'hooks/api/getters/useProject/useProject';
|
||||||
import { PermissionHOC } from 'component/common/PermissionHOC/PermissionHOC';
|
import { PermissionHOC } from 'component/common/PermissionHOC/PermissionHOC';
|
||||||
import { UPDATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
import { UPDATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
||||||
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
|
|
||||||
interface IManageTagsProps {
|
interface IManageTagsProps {
|
||||||
data: FeatureSchema[];
|
data: FeatureSchema[];
|
||||||
@ -20,6 +21,7 @@ export const ManageTags: VFC<IManageTagsProps> = ({ projectId, data }) => {
|
|||||||
const { bulkUpdateTags } = useTagApi();
|
const { bulkUpdateTags } = useTagApi();
|
||||||
const { refetch } = useProject(projectId);
|
const { refetch } = useProject(projectId);
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
|
const { trackEvent } = usePlausibleTracker();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [initialValues, indeterminateValues] = useMemo(() => {
|
const [initialValues, indeterminateValues] = useMemo(() => {
|
||||||
const uniqueTags = data
|
const uniqueTags = data
|
||||||
@ -77,6 +79,11 @@ export const ManageTags: VFC<IManageTagsProps> = ({ projectId, data }) => {
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
autoHideDuration: 12000,
|
autoHideDuration: 12000,
|
||||||
});
|
});
|
||||||
|
trackEvent('batch_operations', {
|
||||||
|
props: {
|
||||||
|
eventType: 'tags updated',
|
||||||
|
},
|
||||||
|
});
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(error));
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import useProjectApi from 'hooks/api/actions/useProjectApi/useProjectApi';
|
|||||||
import useProject from 'hooks/api/getters/useProject/useProject';
|
import useProject from 'hooks/api/getters/useProject/useProject';
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
|
|
||||||
interface IMoreActionsProps {
|
interface IMoreActionsProps {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
@ -31,6 +32,7 @@ export const MoreActions: VFC<IMoreActionsProps> = ({ projectId, data }) => {
|
|||||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||||
const { staleFeatures } = useProjectApi();
|
const { staleFeatures } = useProjectApi();
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
|
const { trackEvent } = usePlausibleTracker();
|
||||||
|
|
||||||
const open = Boolean(anchorEl);
|
const open = Boolean(anchorEl);
|
||||||
const selectedIds = data.map(({ name }) => name);
|
const selectedIds = data.map(({ name }) => name);
|
||||||
@ -55,6 +57,11 @@ export const MoreActions: VFC<IMoreActionsProps> = ({ projectId, data }) => {
|
|||||||
text: 'Feature toggles marked as stale',
|
text: 'Feature toggles marked as stale',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
|
trackEvent('batch_operations', {
|
||||||
|
props: {
|
||||||
|
eventType: 'features staled',
|
||||||
|
},
|
||||||
|
});
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(error));
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
@ -70,6 +77,11 @@ export const MoreActions: VFC<IMoreActionsProps> = ({ projectId, data }) => {
|
|||||||
text: 'Feature toggles unmarked as stale',
|
text: 'Feature toggles unmarked as stale',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
|
trackEvent('batch_operations', {
|
||||||
|
props: {
|
||||||
|
eventType: 'features unstaled',
|
||||||
|
},
|
||||||
|
});
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(error));
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FC, useMemo, useState } from 'react';
|
import { FC, useMemo, useState } from 'react';
|
||||||
import { Button } from '@mui/material';
|
import { Button } from '@mui/material';
|
||||||
import { FileDownload, Label } from '@mui/icons-material';
|
import { FileDownload } from '@mui/icons-material';
|
||||||
import type { FeatureSchema } from 'openapi';
|
import type { FeatureSchema } from 'openapi';
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import { ExportDialog } from 'component/feature/FeatureToggleList/ExportDialog';
|
import { ExportDialog } from 'component/feature/FeatureToggleList/ExportDialog';
|
||||||
@ -8,6 +8,7 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
|
|||||||
import { ArchiveButton } from './ArchiveButton';
|
import { ArchiveButton } from './ArchiveButton';
|
||||||
import { MoreActions } from './MoreActions';
|
import { MoreActions } from './MoreActions';
|
||||||
import { ManageTags } from './ManageTags';
|
import { ManageTags } from './ManageTags';
|
||||||
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
|
|
||||||
interface IProjectFeaturesBatchActionsProps {
|
interface IProjectFeaturesBatchActionsProps {
|
||||||
selectedIds: string[];
|
selectedIds: string[];
|
||||||
@ -20,6 +21,7 @@ export const ProjectFeaturesBatchActions: FC<
|
|||||||
> = ({ selectedIds, data, projectId }) => {
|
> = ({ selectedIds, data, projectId }) => {
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
const [showExportDialog, setShowExportDialog] = useState(false);
|
const [showExportDialog, setShowExportDialog] = useState(false);
|
||||||
|
const { trackEvent } = usePlausibleTracker();
|
||||||
const selectedData = useMemo(
|
const selectedData = useMemo(
|
||||||
() => data.filter(d => selectedIds.includes(d.name)),
|
() => data.filter(d => selectedIds.includes(d.name)),
|
||||||
[data, selectedIds]
|
[data, selectedIds]
|
||||||
@ -33,6 +35,14 @@ export const ProjectFeaturesBatchActions: FC<
|
|||||||
return Array.from(new Set(envs));
|
return Array.from(new Set(envs));
|
||||||
}, [selectedData]);
|
}, [selectedData]);
|
||||||
|
|
||||||
|
const trackExport = () => {
|
||||||
|
trackEvent('batch_operations', {
|
||||||
|
props: {
|
||||||
|
eventType: 'features exported',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ArchiveButton projectId={projectId} features={selectedIds} />
|
<ArchiveButton projectId={projectId} features={selectedIds} />
|
||||||
@ -54,6 +64,7 @@ export const ProjectFeaturesBatchActions: FC<
|
|||||||
data={selectedData}
|
data={selectedData}
|
||||||
onClose={() => setShowExportDialog(false)}
|
onClose={() => setShowExportDialog(false)}
|
||||||
environments={environments}
|
environments={environments}
|
||||||
|
onConfirm={trackExport}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -22,7 +22,8 @@ export type CustomEvents =
|
|||||||
| 'export_import'
|
| 'export_import'
|
||||||
| 'project_api_tokens'
|
| 'project_api_tokens'
|
||||||
| 'project_stickiness_set'
|
| 'project_stickiness_set'
|
||||||
| 'notifications';
|
| 'notifications'
|
||||||
|
| 'batch_operations';
|
||||||
|
|
||||||
export const usePlausibleTracker = () => {
|
export const usePlausibleTracker = () => {
|
||||||
const plausible = useContext(PlausibleContext);
|
const plausible = useContext(PlausibleContext);
|
||||||
|
Loading…
Reference in New Issue
Block a user