From 4b510b8dfd395a95bf551b45b7cbfb2916d6d712 Mon Sep 17 00:00:00 2001 From: gakshita Date: Mon, 30 Jun 2025 19:25:09 +0530 Subject: [PATCH 1/3] fix: workspace events --- .../onboarding/create-workspace.tsx | 39 +++++++------------ .../workspace/create-workspace-form.tsx | 30 ++++++-------- .../workspace/delete-workspace-form.tsx | 31 ++++++--------- .../workspace/settings/workspace-details.tsx | 28 +++++-------- web/core/store/event-tracker.store.ts | 20 ---------- web/helpers/event-tracker.helper.ts | 15 ++----- 6 files changed, 50 insertions(+), 113 deletions(-) diff --git a/web/core/components/onboarding/create-workspace.tsx b/web/core/components/onboarding/create-workspace.tsx index 157beec74a9..238729a0a73 100644 --- a/web/core/components/onboarding/create-workspace.tsx +++ b/web/core/components/onboarding/create-workspace.tsx @@ -4,19 +4,15 @@ import { useState } from "react"; import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; // constants -import { - ONBOARDING_TRACKER_EVENTS, - ORGANIZATION_SIZE, - RESTRICTED_URLS, - WORKSPACE_TRACKER_EVENTS, -} from "@plane/constants"; +import { ORGANIZATION_SIZE, RESTRICTED_URLS, WORKSPACE_TRACKER_EVENTS } from "@plane/constants"; // types import { useTranslation } from "@plane/i18n"; import { IUser, IWorkspace, TOnboardingSteps } from "@plane/types"; // ui import { Button, CustomSelect, Input, Spinner, TOAST_TYPE, setToast } from "@plane/ui"; // hooks -import { useEventTracker, useUserProfile, useUserSettings, useWorkspace } from "@/hooks/store"; +import { trackError, trackSuccess } from "@/helpers/event-tracker.helper"; +import { useUserProfile, useUserSettings, useWorkspace } from "@/hooks/store"; // services import { WorkspaceService } from "@/plane-web/services"; @@ -41,7 +37,6 @@ export const CreateWorkspace: React.FC = observer((props) => { const { updateUserProfile } = useUserProfile(); const { fetchCurrentUserSettings } = useUserSettings(); const { createWorkspace, fetchWorkspaces } = useWorkspace(); - const { captureWorkspaceEvent } = useEventTracker(); // form info const { handleSubmit, @@ -73,27 +68,12 @@ export const CreateWorkspace: React.FC = observer((props) => { title: t("workspace_creation.toast.success.title"), message: t("workspace_creation.toast.success.message"), }); - captureWorkspaceEvent({ - eventName: WORKSPACE_TRACKER_EVENTS.create, - payload: { - ...workspaceResponse, - state: "SUCCESS", - first_time: true, - element: ONBOARDING_TRACKER_EVENTS.root, - }, - }); + trackSuccess(WORKSPACE_TRACKER_EVENTS.create, { ...workspaceResponse }); await fetchWorkspaces(); await completeStep(workspaceResponse.id); }) .catch(() => { - captureWorkspaceEvent({ - eventName: WORKSPACE_TRACKER_EVENTS.create, - payload: { - state: "FAILED", - first_time: true, - element: ONBOARDING_TRACKER_EVENTS.root, - }, - }); + trackError(WORKSPACE_TRACKER_EVENTS.create); setToast({ type: TOAST_TYPE.ERROR, title: t("workspace_creation.toast.error.title"), @@ -290,7 +270,14 @@ export const CreateWorkspace: React.FC = observer((props) => { )} - diff --git a/web/core/components/workspace/create-workspace-form.tsx b/web/core/components/workspace/create-workspace-form.tsx index 0f51e74b26f..adf60d0dc8b 100644 --- a/web/core/components/workspace/create-workspace-form.tsx +++ b/web/core/components/workspace/create-workspace-form.tsx @@ -11,7 +11,8 @@ import { IWorkspace } from "@plane/types"; // ui import { Button, CustomSelect, Input, TOAST_TYPE, setToast } from "@plane/ui"; // hooks -import { useEventTracker, useWorkspace } from "@/hooks/store"; +import { trackError, trackSuccess } from "@/helpers/event-tracker.helper"; +import { useWorkspace } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; // services import { WorkspaceService } from "@/plane-web/services"; @@ -51,7 +52,6 @@ export const CreateWorkspaceForm: FC = observer((props) => { // router const router = useAppRouter(); // store hooks - const { captureWorkspaceEvent } = useEventTracker(); const { createWorkspace } = useWorkspace(); // form info const { @@ -71,14 +71,7 @@ export const CreateWorkspaceForm: FC = observer((props) => { await createWorkspace(formData) .then(async (res) => { - captureWorkspaceEvent({ - eventName: WORKSPACE_TRACKER_EVENTS.create, - payload: { - ...res, - state: "SUCCESS", - element: "Create workspace page", - }, - }); + trackSuccess(WORKSPACE_TRACKER_EVENTS.create, { ...formData }); setToast({ type: TOAST_TYPE.SUCCESS, title: t("workspace_creation.toast.success.title"), @@ -88,13 +81,7 @@ export const CreateWorkspaceForm: FC = observer((props) => { if (onSubmit) await onSubmit(res); }) .catch(() => { - captureWorkspaceEvent({ - eventName: WORKSPACE_TRACKER_EVENTS.create, - payload: { - state: "FAILED", - element: "Create workspace page", - }, - }); + trackError(WORKSPACE_TRACKER_EVENTS.create, { ...formData }); setToast({ type: TOAST_TYPE.ERROR, title: t("workspace_creation.toast.error.title"), @@ -248,7 +235,14 @@ export const CreateWorkspaceForm: FC = observer((props) => {
{secondaryButton} - {!secondaryButton && ( diff --git a/web/core/components/workspace/delete-workspace-form.tsx b/web/core/components/workspace/delete-workspace-form.tsx index c668ad300c6..ae891f0fae6 100644 --- a/web/core/components/workspace/delete-workspace-form.tsx +++ b/web/core/components/workspace/delete-workspace-form.tsx @@ -13,7 +13,8 @@ import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui"; // constants // hooks import { cn } from "@plane/utils"; -import { useEventTracker, useUserSettings, useWorkspace } from "@/hooks/store"; +import { trackError, trackSuccess } from "@/helpers/event-tracker.helper"; +import { useUserSettings, useWorkspace } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; type Props = { @@ -31,7 +32,6 @@ export const DeleteWorkspaceForm: React.FC = observer((props) => { // router const router = useAppRouter(); // store hooks - const { captureWorkspaceEvent } = useEventTracker(); const { deleteWorkspace } = useWorkspace(); const { t } = useTranslation(); const { getWorkspaceRedirectionUrl } = useWorkspace(); @@ -64,14 +64,7 @@ export const DeleteWorkspaceForm: React.FC = observer((props) => { await fetchCurrentUserSettings(); handleClose(); router.push(getWorkspaceRedirectionUrl()); - captureWorkspaceEvent({ - eventName: WORKSPACE_TRACKER_EVENTS.delete, - payload: { - ...data, - state: "SUCCESS", - element: "Workspace general settings page", - }, - }); + trackSuccess(WORKSPACE_TRACKER_EVENTS.delete); setToast({ type: TOAST_TYPE.SUCCESS, title: t("workspace_settings.settings.general.delete_modal.success_title"), @@ -84,14 +77,7 @@ export const DeleteWorkspaceForm: React.FC = observer((props) => { title: t("workspace_settings.settings.general.delete_modal.error_title"), message: t("workspace_settings.settings.general.delete_modal.error_message"), }); - captureWorkspaceEvent({ - eventName: WORKSPACE_TRACKER_EVENTS.delete, - payload: { - ...data, - state: "FAILED", - element: "Workspace general settings page", - }, - }); + trackError(WORKSPACE_TRACKER_EVENTS.delete); }); }; @@ -169,7 +155,14 @@ export const DeleteWorkspaceForm: React.FC = observer((props) => { -
diff --git a/web/core/components/workspace/settings/workspace-details.tsx b/web/core/components/workspace/settings/workspace-details.tsx index e9a83784b58..675cc0bcee6 100644 --- a/web/core/components/workspace/settings/workspace-details.tsx +++ b/web/core/components/workspace/settings/workspace-details.tsx @@ -15,7 +15,8 @@ import { LogoSpinner } from "@/components/common"; import { WorkspaceImageUploadModal } from "@/components/core"; // helpers // hooks -import { useEventTracker, useUserPermissions, useWorkspace } from "@/hooks/store"; +import { trackError, trackSuccess } from "@/helpers/event-tracker.helper"; +import { useUserPermissions, useWorkspace } from "@/hooks/store"; // plane web components import { DeleteWorkspaceSection } from "@/plane-web/components/workspace"; @@ -31,7 +32,6 @@ export const WorkspaceDetails: FC = observer(() => { const [isLoading, setIsLoading] = useState(false); const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false); // store hooks - const { captureWorkspaceEvent } = useEventTracker(); const { currentWorkspace, updateWorkspace } = useWorkspace(); const { allowPermissions } = useUserPermissions(); const { t } = useTranslation(); @@ -61,14 +61,7 @@ export const WorkspaceDetails: FC = observer(() => { await updateWorkspace(currentWorkspace.slug, payload) .then((res) => { - captureWorkspaceEvent({ - eventName: WORKSPACE_TRACKER_EVENTS.update, - payload: { - ...res, - state: "SUCCESS", - element: "Workspace general settings page", - }, - }); + trackSuccess(WORKSPACE_TRACKER_EVENTS.update); setToast({ title: "Success!", type: TOAST_TYPE.SUCCESS, @@ -76,13 +69,7 @@ export const WorkspaceDetails: FC = observer(() => { }); }) .catch((err) => { - captureWorkspaceEvent({ - eventName: WORKSPACE_TRACKER_EVENTS.update, - payload: { - state: "FAILED", - element: "Workspace general settings page", - }, - }); + trackError(WORKSPACE_TRACKER_EVENTS.update); console.error(err); }); setTimeout(() => { @@ -282,7 +269,12 @@ export const WorkspaceDetails: FC = observer(() => { {isAdmin && (
-
diff --git a/web/core/store/event-tracker.store.ts b/web/core/store/event-tracker.store.ts index 8116eaaf0f3..a72f12a026e 100644 --- a/web/core/store/event-tracker.store.ts +++ b/web/core/store/event-tracker.store.ts @@ -10,9 +10,7 @@ import { getModuleEventPayload, getProjectEventPayload, getProjectStateEventPayload, - getWorkspaceEventPayload, getPageEventPayload, - WORKSPACE_TRACKER_EVENTS, } from "@plane/constants"; import { CoreRootStore } from "./root.store"; @@ -26,7 +24,6 @@ export interface ICoreEventTrackerStore { setTrackElement: (element: string) => void; captureEvent: (eventName: string, payload?: any) => void; joinWorkspaceMetricGroup: (workspaceId?: string) => void; - captureWorkspaceEvent: (props: EventProps) => void; captureProjectEvent: (props: EventProps) => void; captureCycleEvent: (props: EventProps) => void; captureModuleEvent: (props: EventProps) => void; @@ -109,23 +106,6 @@ export abstract class CoreEventTrackerStore implements ICoreEventTrackerStore { this.setTrackElement(undefined); }; - /** - * @description: Captures the workspace crud related events. - * @param {EventProps} props - */ - captureWorkspaceEvent = (props: EventProps) => { - const { eventName, payload } = props; - if (eventName === WORKSPACE_TRACKER_EVENTS.create && payload.state == "SUCCESS") { - this.joinWorkspaceMetricGroup(payload.id); - } - const eventPayload: any = getWorkspaceEventPayload({ - ...payload, - element: payload.element ?? this.trackElement, - }); - posthog?.capture(eventName, eventPayload); - this.setTrackElement(undefined); - }; - /** * @description: Captures the project related events. * @param {EventProps} props diff --git a/web/helpers/event-tracker.helper.ts b/web/helpers/event-tracker.helper.ts index 6f4d3e33280..d230c5e3076 100644 --- a/web/helpers/event-tracker.helper.ts +++ b/web/helpers/event-tracker.helper.ts @@ -13,11 +13,7 @@ export type TInteractionType = "clicked" | "viewed" | "hovered"; * @param element - Generic UI element type * @param context - Context about where and why the interaction happened */ -const trackElement = ( - element: TTrackingElement, - interaction_type: TInteractionType, - context?: TElementContext -) => { +const trackElement = (element: TTrackingElement, interaction_type: TInteractionType, context?: TElementContext) => { if (!posthog) return; const elementEvent = `${element}_${interaction_type}`; @@ -67,12 +63,7 @@ export const trackHover = (element: TTrackingElement, context?: TElementContext) * @param payload - Event-specific data * @param context - Additional context */ -const trackEvent = ( - eventName: string, - state: TEventState, - payload?: Record, - context?: TEventContext -) => { +const trackEvent = (eventName: string, state: TEventState, payload?: Record, context?: TEventContext) => { if (!posthog) return; const finalPayload = { @@ -104,8 +95,8 @@ export const trackSuccess = (eventName: string, payload?: Record, c */ export const trackError = ( eventName: string, - error?: Error | string, payload?: Record, + error?: Error | string, context?: TEventContext ) => { trackEvent( From 9f8872e43171fe13756f6b4a88cd56521f6e377a Mon Sep 17 00:00:00 2001 From: gakshita Date: Mon, 30 Jun 2025 19:29:44 +0530 Subject: [PATCH 2/3] fix: added slug --- web/core/components/workspace/delete-workspace-form.tsx | 4 ++-- web/core/components/workspace/settings/workspace-details.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/web/core/components/workspace/delete-workspace-form.tsx b/web/core/components/workspace/delete-workspace-form.tsx index ae891f0fae6..b36ae566efc 100644 --- a/web/core/components/workspace/delete-workspace-form.tsx +++ b/web/core/components/workspace/delete-workspace-form.tsx @@ -64,7 +64,7 @@ export const DeleteWorkspaceForm: React.FC = observer((props) => { await fetchCurrentUserSettings(); handleClose(); router.push(getWorkspaceRedirectionUrl()); - trackSuccess(WORKSPACE_TRACKER_EVENTS.delete); + trackSuccess(WORKSPACE_TRACKER_EVENTS.delete, { slug: data.slug }); setToast({ type: TOAST_TYPE.SUCCESS, title: t("workspace_settings.settings.general.delete_modal.success_title"), @@ -77,7 +77,7 @@ export const DeleteWorkspaceForm: React.FC = observer((props) => { title: t("workspace_settings.settings.general.delete_modal.error_title"), message: t("workspace_settings.settings.general.delete_modal.error_message"), }); - trackError(WORKSPACE_TRACKER_EVENTS.delete); + trackError(WORKSPACE_TRACKER_EVENTS.delete, { slug: data.slug }); }); }; diff --git a/web/core/components/workspace/settings/workspace-details.tsx b/web/core/components/workspace/settings/workspace-details.tsx index 675cc0bcee6..3a3de5d10cf 100644 --- a/web/core/components/workspace/settings/workspace-details.tsx +++ b/web/core/components/workspace/settings/workspace-details.tsx @@ -61,7 +61,7 @@ export const WorkspaceDetails: FC = observer(() => { await updateWorkspace(currentWorkspace.slug, payload) .then((res) => { - trackSuccess(WORKSPACE_TRACKER_EVENTS.update); + trackSuccess(WORKSPACE_TRACKER_EVENTS.update, { slug: currentWorkspace.slug }); setToast({ title: "Success!", type: TOAST_TYPE.SUCCESS, @@ -69,7 +69,7 @@ export const WorkspaceDetails: FC = observer(() => { }); }) .catch((err) => { - trackError(WORKSPACE_TRACKER_EVENTS.update); + trackError(WORKSPACE_TRACKER_EVENTS.update, { slug: currentWorkspace.slug }); console.error(err); }); setTimeout(() => { From 0d58c18fdd49a44b506acd52094877b33a396dea Mon Sep 17 00:00:00 2001 From: gakshita Date: Mon, 30 Jun 2025 19:33:48 +0530 Subject: [PATCH 3/3] fix: changes nomenclature --- web/core/components/onboarding/create-workspace.tsx | 6 +++--- web/core/components/workspace/create-workspace-form.tsx | 6 +++--- web/core/components/workspace/delete-workspace-form.tsx | 6 +++--- .../components/workspace/settings/workspace-details.tsx | 6 +++--- web/helpers/event-tracker.helper.ts | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/web/core/components/onboarding/create-workspace.tsx b/web/core/components/onboarding/create-workspace.tsx index 238729a0a73..c7643045644 100644 --- a/web/core/components/onboarding/create-workspace.tsx +++ b/web/core/components/onboarding/create-workspace.tsx @@ -11,7 +11,7 @@ import { IUser, IWorkspace, TOnboardingSteps } from "@plane/types"; // ui import { Button, CustomSelect, Input, Spinner, TOAST_TYPE, setToast } from "@plane/ui"; // hooks -import { trackError, trackSuccess } from "@/helpers/event-tracker.helper"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import { useUserProfile, useUserSettings, useWorkspace } from "@/hooks/store"; // services import { WorkspaceService } from "@/plane-web/services"; @@ -68,12 +68,12 @@ export const CreateWorkspace: React.FC = observer((props) => { title: t("workspace_creation.toast.success.title"), message: t("workspace_creation.toast.success.message"), }); - trackSuccess(WORKSPACE_TRACKER_EVENTS.create, { ...workspaceResponse }); + captureSuccess(WORKSPACE_TRACKER_EVENTS.create, { ...workspaceResponse }); await fetchWorkspaces(); await completeStep(workspaceResponse.id); }) .catch(() => { - trackError(WORKSPACE_TRACKER_EVENTS.create); + captureError(WORKSPACE_TRACKER_EVENTS.create); setToast({ type: TOAST_TYPE.ERROR, title: t("workspace_creation.toast.error.title"), diff --git a/web/core/components/workspace/create-workspace-form.tsx b/web/core/components/workspace/create-workspace-form.tsx index adf60d0dc8b..d35c94657c5 100644 --- a/web/core/components/workspace/create-workspace-form.tsx +++ b/web/core/components/workspace/create-workspace-form.tsx @@ -11,7 +11,7 @@ import { IWorkspace } from "@plane/types"; // ui import { Button, CustomSelect, Input, TOAST_TYPE, setToast } from "@plane/ui"; // hooks -import { trackError, trackSuccess } from "@/helpers/event-tracker.helper"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import { useWorkspace } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; // services @@ -71,7 +71,7 @@ export const CreateWorkspaceForm: FC = observer((props) => { await createWorkspace(formData) .then(async (res) => { - trackSuccess(WORKSPACE_TRACKER_EVENTS.create, { ...formData }); + captureSuccess(WORKSPACE_TRACKER_EVENTS.create, { ...formData }); setToast({ type: TOAST_TYPE.SUCCESS, title: t("workspace_creation.toast.success.title"), @@ -81,7 +81,7 @@ export const CreateWorkspaceForm: FC = observer((props) => { if (onSubmit) await onSubmit(res); }) .catch(() => { - trackError(WORKSPACE_TRACKER_EVENTS.create, { ...formData }); + captureError(WORKSPACE_TRACKER_EVENTS.create, { ...formData }); setToast({ type: TOAST_TYPE.ERROR, title: t("workspace_creation.toast.error.title"), diff --git a/web/core/components/workspace/delete-workspace-form.tsx b/web/core/components/workspace/delete-workspace-form.tsx index b36ae566efc..7784b4f08db 100644 --- a/web/core/components/workspace/delete-workspace-form.tsx +++ b/web/core/components/workspace/delete-workspace-form.tsx @@ -13,7 +13,7 @@ import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui"; // constants // hooks import { cn } from "@plane/utils"; -import { trackError, trackSuccess } from "@/helpers/event-tracker.helper"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import { useUserSettings, useWorkspace } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; @@ -64,7 +64,7 @@ export const DeleteWorkspaceForm: React.FC = observer((props) => { await fetchCurrentUserSettings(); handleClose(); router.push(getWorkspaceRedirectionUrl()); - trackSuccess(WORKSPACE_TRACKER_EVENTS.delete, { slug: data.slug }); + captureSuccess(WORKSPACE_TRACKER_EVENTS.delete, { slug: data.slug }); setToast({ type: TOAST_TYPE.SUCCESS, title: t("workspace_settings.settings.general.delete_modal.success_title"), @@ -77,7 +77,7 @@ export const DeleteWorkspaceForm: React.FC = observer((props) => { title: t("workspace_settings.settings.general.delete_modal.error_title"), message: t("workspace_settings.settings.general.delete_modal.error_message"), }); - trackError(WORKSPACE_TRACKER_EVENTS.delete, { slug: data.slug }); + captureError(WORKSPACE_TRACKER_EVENTS.delete, { slug: data.slug }); }); }; diff --git a/web/core/components/workspace/settings/workspace-details.tsx b/web/core/components/workspace/settings/workspace-details.tsx index 3a3de5d10cf..1318a246a2e 100644 --- a/web/core/components/workspace/settings/workspace-details.tsx +++ b/web/core/components/workspace/settings/workspace-details.tsx @@ -15,7 +15,7 @@ import { LogoSpinner } from "@/components/common"; import { WorkspaceImageUploadModal } from "@/components/core"; // helpers // hooks -import { trackError, trackSuccess } from "@/helpers/event-tracker.helper"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import { useUserPermissions, useWorkspace } from "@/hooks/store"; // plane web components import { DeleteWorkspaceSection } from "@/plane-web/components/workspace"; @@ -61,7 +61,7 @@ export const WorkspaceDetails: FC = observer(() => { await updateWorkspace(currentWorkspace.slug, payload) .then((res) => { - trackSuccess(WORKSPACE_TRACKER_EVENTS.update, { slug: currentWorkspace.slug }); + captureSuccess(WORKSPACE_TRACKER_EVENTS.update, { slug: currentWorkspace.slug }); setToast({ title: "Success!", type: TOAST_TYPE.SUCCESS, @@ -69,7 +69,7 @@ export const WorkspaceDetails: FC = observer(() => { }); }) .catch((err) => { - trackError(WORKSPACE_TRACKER_EVENTS.update, { slug: currentWorkspace.slug }); + captureError(WORKSPACE_TRACKER_EVENTS.update, { slug: currentWorkspace.slug }); console.error(err); }); setTimeout(() => { diff --git a/web/helpers/event-tracker.helper.ts b/web/helpers/event-tracker.helper.ts index d230c5e3076..6a08c323f8a 100644 --- a/web/helpers/event-tracker.helper.ts +++ b/web/helpers/event-tracker.helper.ts @@ -82,7 +82,7 @@ const trackEvent = (eventName: string, state: TEventState, payload?: Record, context?: TEventContext) => { +export const captureSuccess = (eventName: string, payload?: Record, context?: TEventContext) => { trackEvent(eventName, "SUCCESS", payload, context); }; @@ -93,7 +93,7 @@ export const trackSuccess = (eventName: string, payload?: Record, c * @param payload - Additional payload * @param context - Additional context */ -export const trackError = ( +export const captureError = ( eventName: string, payload?: Record, error?: Error | string,