diff --git a/web/components/estimates/create-update-estimate-modal.tsx b/web/components/estimates/create-update-estimate-modal.tsx index 0a607e88d..72f942120 100644 --- a/web/components/estimates/create-update-estimate-modal.tsx +++ b/web/components/estimates/create-update-estimate-modal.tsx @@ -4,7 +4,7 @@ import { Controller, useForm } from "react-hook-form"; import { Dialog, Transition } from "@headlessui/react"; import { observer } from "mobx-react-lite"; // store hooks -import { useEstimate } from "hooks/store"; +import { useEstimate, useEventTracker } from "hooks/store"; import useToast from "hooks/use-toast"; // ui import { Button, Input, TextArea } from "@plane/ui"; @@ -12,6 +12,8 @@ import { Button, Input, TextArea } from "@plane/ui"; import { checkDuplicates } from "helpers/array.helper"; // types import { IEstimate, IEstimateFormData } from "@plane/types"; +// constants +import { ESTIMATE_CREATED, ESTIMATE_UPDATED } from "constants/event-tracker"; type Props = { isOpen: boolean; @@ -39,6 +41,7 @@ export const CreateUpdateEstimateModal: React.FC = observer((props) => { const { workspaceSlug, projectId } = router.query; // store hooks const { createEstimate, updateEstimate } = useEstimate(); + const { captureEvent } = useEventTracker(); // form info // toast alert const { setToastAlert } = useToast(); @@ -60,7 +63,15 @@ export const CreateUpdateEstimateModal: React.FC = observer((props) => { if (!workspaceSlug || !projectId) return; await createEstimate(workspaceSlug.toString(), projectId.toString(), payload) - .then(() => { + .then((res) => { + captureEvent(ESTIMATE_CREATED, { + estimate_id: res.id, + estimate_points: res.points.map((point) => ({ + id: point.id, + value: point.value, + key: point.key, + })), + }); onClose(); }) .catch((err) => { @@ -83,6 +94,10 @@ export const CreateUpdateEstimateModal: React.FC = observer((props) => { await updateEstimate(workspaceSlug.toString(), projectId.toString(), data.id, payload) .then(() => { + captureEvent(ESTIMATE_UPDATED, { + estimate_id: data.id, + estimate_points: payload.estimate_points + }); onClose(); }) .catch((err) => { diff --git a/web/components/estimates/delete-estimate-modal.tsx b/web/components/estimates/delete-estimate-modal.tsx index 8055ddb90..cefb9cf5b 100644 --- a/web/components/estimates/delete-estimate-modal.tsx +++ b/web/components/estimates/delete-estimate-modal.tsx @@ -4,12 +4,14 @@ import { Dialog, Transition } from "@headlessui/react"; import { observer } from "mobx-react-lite"; import { AlertTriangle } from "lucide-react"; // store hooks -import { useEstimate } from "hooks/store"; +import { useEstimate, useEventTracker } from "hooks/store"; import useToast from "hooks/use-toast"; // types import { IEstimate } from "@plane/types"; // ui import { Button } from "@plane/ui"; +// constants +import { ESTIMATE_DELETED } from "constants/event-tracker"; type Props = { isOpen: boolean; @@ -26,6 +28,7 @@ export const DeleteEstimateModal: React.FC = observer((props) => { const { workspaceSlug, projectId } = router.query; // store hooks const { deleteEstimate } = useEstimate(); + const { captureEvent } = useEventTracker(); // toast alert const { setToastAlert } = useToast(); @@ -36,6 +39,9 @@ export const DeleteEstimateModal: React.FC = observer((props) => { deleteEstimate(workspaceSlug.toString(), projectId.toString(), estimateId) .then(() => { + captureEvent(ESTIMATE_DELETED, { + estimate_id: estimateId, + }); setIsDeleteLoading(false); handleClose(); }) diff --git a/web/components/estimates/estimate-list-item.tsx b/web/components/estimates/estimate-list-item.tsx index b6effa711..b825b9a13 100644 --- a/web/components/estimates/estimate-list-item.tsx +++ b/web/components/estimates/estimate-list-item.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useRouter } from "next/router"; import { observer } from "mobx-react-lite"; // hooks -import { useProject } from "hooks/store"; +import { useEventTracker, useProject } from "hooks/store"; import useToast from "hooks/use-toast"; // ui import { Button, CustomMenu } from "@plane/ui"; @@ -12,6 +12,8 @@ import { Pencil, Trash2 } from "lucide-react"; import { orderArrayBy } from "helpers/array.helper"; // types import { IEstimate } from "@plane/types"; +// constants +import { ESTIMATE_USED } from "constants/event-tracker"; type Props = { estimate: IEstimate; @@ -26,6 +28,7 @@ export const EstimateListItem: React.FC = observer((props) => { const { workspaceSlug, projectId } = router.query; // store hooks const { currentProjectDetails, updateProject } = useProject(); + const { captureEvent } = useEventTracker(); // hooks const { setToastAlert } = useToast(); @@ -34,16 +37,22 @@ export const EstimateListItem: React.FC = observer((props) => { await updateProject(workspaceSlug.toString(), projectId.toString(), { estimate: estimate.id, - }).catch((err) => { - const error = err?.error; - const errorString = Array.isArray(error) ? error[0] : error; + }) + .then(() => { + captureEvent(ESTIMATE_USED, { + estimate_id: estimate.id, + }); + }) + .catch((err) => { + const error = err?.error; + const errorString = Array.isArray(error) ? error[0] : error; - setToastAlert({ - type: "error", - title: "Error!", - message: errorString ?? "Estimate points could not be used. Please try again.", + setToastAlert({ + type: "error", + title: "Error!", + message: errorString ?? "Estimate points could not be used. Please try again.", + }); }); - }); }; return ( diff --git a/web/components/estimates/estimates-list.tsx b/web/components/estimates/estimates-list.tsx index 1dabc6181..9b22b856a 100644 --- a/web/components/estimates/estimates-list.tsx +++ b/web/components/estimates/estimates-list.tsx @@ -3,7 +3,7 @@ import { useRouter } from "next/router"; import { observer } from "mobx-react-lite"; import { useTheme } from "next-themes"; // store hooks -import { useEstimate, useProject, useUser } from "hooks/store"; +import { useEstimate, useEventTracker, useProject, useUser } from "hooks/store"; import useToast from "hooks/use-toast"; // components import { CreateUpdateEstimateModal, DeleteEstimateModal, EstimateListItem } from "components/estimates"; @@ -16,6 +16,7 @@ import { IEstimate } from "@plane/types"; import { orderArrayBy } from "helpers/array.helper"; // constants import { PROJECT_SETTINGS_EMPTY_STATE_DETAILS } from "constants/empty-state"; +import { ESTIMATE_DISABLED } from "constants/event-tracker"; export const EstimatesList: React.FC = observer(() => { // states @@ -31,6 +32,7 @@ export const EstimatesList: React.FC = observer(() => { const { updateProject, currentProjectDetails } = useProject(); const { projectEstimates, getProjectEstimateById } = useEstimate(); const { currentUser } = useUser(); + const { captureEvent } = useEventTracker(); // toast alert const { setToastAlert } = useToast(); @@ -46,16 +48,22 @@ export const EstimatesList: React.FC = observer(() => { const disableEstimates = () => { if (!workspaceSlug || !projectId) return; - updateProject(workspaceSlug.toString(), projectId.toString(), { estimate: null }).catch((err) => { - const error = err?.error; - const errorString = Array.isArray(error) ? error[0] : error; + updateProject(workspaceSlug.toString(), projectId.toString(), { estimate: null }) + .then(() => { + captureEvent(ESTIMATE_DISABLED, { + current_estimate_id : currentProjectDetails?.estimate, + }); + }) + .catch((err) => { + const error = err?.error; + const errorString = Array.isArray(error) ? error[0] : error; - setToastAlert({ - type: "error", - title: "Error!", - message: errorString ?? "Estimate could not be disabled. Please try again", + setToastAlert({ + type: "error", + title: "Error!", + message: errorString ?? "Estimate could not be disabled. Please try again", + }); }); - }); }; const emptyStateDetail = PROJECT_SETTINGS_EMPTY_STATE_DETAILS["estimate"]; diff --git a/web/constants/event-tracker.ts b/web/constants/event-tracker.ts index 8d99cbfbd..047b73407 100644 --- a/web/constants/event-tracker.ts +++ b/web/constants/event-tracker.ts @@ -246,6 +246,12 @@ export const AUTO_ARCHIVE_TOGGLED = "Auto archive toggled"; export const AUTO_ARCHIVE_UPDATED = "Auto archive updated"; export const AUTO_CLOSE_Toggled = "Auto close toggled"; export const AUTO_CLOSE_UPDATED = "Auto close updated"; +// Estimate Events +export const ESTIMATE_CREATED = "Estimate created"; +export const ESTIMATE_UPDATED = "Estimate updated"; +export const ESTIMATE_DELETED = "Estimate deleted"; +export const ESTIMATE_USED = "Estimate used"; +export const ESTIMATE_DISABLED = "Estimate disabled"; // Project Page Events export const PAGE_CREATED = "Page created"; export const PAGE_UPDATED = "Page updated"; diff --git a/web/store/estimate.store.ts b/web/store/estimate.store.ts index beddd52ab..4635a89b6 100644 --- a/web/store/estimate.store.ts +++ b/web/store/estimate.store.ts @@ -184,7 +184,7 @@ export class EstimateStore implements IEstimateStore { runInAction(() => { set(this.estimateMap, [responseEstimate.id], responseEstimate); }); - return response.estimate; + return responseEstimate; }); /**