feat: integrate enhanced new set of event trackers

This commit is contained in:
Jayash Tripathy
2025-12-10 13:32:43 +05:30
parent 6f64e07eb4
commit 4d22ef21f1
14 changed files with 452 additions and 104 deletions

View File

@@ -18,6 +18,9 @@ import { useProject } from "@/hooks/store/use-project";
// plane web imports
import { CommonProjectBreadcrumbs } from "@/plane-web/components/breadcrumbs/common";
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
import { useUser, useUserPermissions } from "@/hooks/store/user";
import { useWorkspace } from "@/hooks/store/use-workspace";
import { getUserRoleString, trackPageCreated } from "@/plane-web/helpers/event-tracker-v2.helper";
export const PagesListHeader = observer(function PagesListHeader() {
// states
@@ -28,6 +31,9 @@ export const PagesListHeader = observer(function PagesListHeader() {
const searchParams = useSearchParams();
const pageType = searchParams.get("type");
// store hooks
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { data: currentUser } = useUser();
const { currentWorkspace } = useWorkspace();
const { currentProjectDetails, loader } = useProject();
const { canCurrentUserCreatePage, createPage } = usePageStore(EPageStoreType.PROJECT);
// handle page create
@@ -40,13 +46,16 @@ export const PagesListHeader = observer(function PagesListHeader() {
await createPage(payload)
.then((res) => {
captureSuccess({
eventName: PROJECT_PAGE_TRACKER_EVENTS.create,
payload: {
id: res?.id,
state: "SUCCESS",
},
});
if (currentWorkspace && currentUser) {
const role = getWorkspaceRoleByWorkspaceSlug(currentWorkspace.slug);
trackPageCreated(
{ id: res?.id ?? "", created_at: new Date().toISOString() },
currentWorkspace,
currentUser,
"project",
getUserRoleString(role)
);
}
const pageId = `/${workspaceSlug}/projects/${currentProjectDetails?.id}/pages/${res?.id}`;
router.push(pageId);
})

View File

@@ -29,6 +29,7 @@ import { useAppRouter } from "@/hooks/use-app-router";
import { AuthenticationWrapper } from "@/lib/wrappers/authentication-wrapper";
// plane web services
import { WorkspaceService } from "@/plane-web/services";
import { joinWorkspaceGroup } from "@/plane-web/helpers/event-tracker-v2.helper";
const workspaceService = new WorkspaceService();
@@ -80,10 +81,9 @@ function UserInvitationsPage() {
const invitation = invitations?.find((i) => i.id === firstInviteId);
const redirectWorkspace = invitations?.find((i) => i.id === firstInviteId)?.workspace;
if (redirectWorkspace?.id) {
joinEventGroup(GROUP_WORKSPACE_TRACKER_EVENT, redirectWorkspace?.id, {
date: new Date().toDateString(),
workspace_id: redirectWorkspace?.id,
});
if (redirectWorkspace) {
joinWorkspaceGroup(redirectWorkspace);
}
}
captureSuccess({
eventName: MEMBER_TRACKER_EVENTS.accept,

View File

@@ -20,6 +20,9 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
import type { TProject } from "@/plane-web/types/projects";
import ProjectAttributes from "./attributes";
import { getProjectFormValues } from "./utils";
import { getUserRoleString, trackProjectCreated } from "@/plane-web/helpers/event-tracker-v2.helper";
import { useUser, useUserPermissions } from "@/hooks/store/user";
import { useWorkspace } from "@/hooks/store/use-workspace";
export type TCreateProjectFormProps = {
setToFavorite?: boolean;
@@ -36,6 +39,9 @@ export const CreateProjectForm = observer(function CreateProjectForm(props: TCre
// store
const { t } = useTranslation();
const { addProjectToFavorites, createProject, updateProject } = useProject();
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { data: currentUser } = useUser();
const { currentWorkspace } = useWorkspace();
// states
const [isChangeInIdentifierRequired, setIsChangeInIdentifierRequired] = useState(true);
// form info
@@ -98,12 +104,15 @@ export const CreateProjectForm = observer(function CreateProjectForm(props: TCre
await updateCoverImageStatus(res.id, coverImage);
await updateProject(workspaceSlug.toString(), res.id, { cover_image_url: coverImage });
}
captureSuccess({
eventName: PROJECT_TRACKER_EVENTS.create,
payload: {
identifier: formData.identifier,
},
});
if (currentUser && currentWorkspace && res) {
const role = getWorkspaceRoleByWorkspaceSlug(currentWorkspace.slug);
trackProjectCreated(
{ id: res.id, created_at: res.created_at instanceof Date ? res.created_at : new Date() },
currentWorkspace,
currentUser,
getUserRoleString(role)
);
}
setToast({
type: TOAST_TYPE.SUCCESS,
title: t("success"),

View File

@@ -0,0 +1,266 @@
import posthog from "posthog-js";
import { EUserPermissions } from "@plane/types";
import type { EUserProjectRoles, EUserWorkspaceRoles, IUser, IWorkspace, TUserProfile } from "@plane/types";
type TUserRole = "guest" | "member" | "admin" | "unknown";
/**
* ============================================================================
* Utilities
* ============================================================================
*/
/**
* Get the user role string from the user role enum
* @param role - The user role enum
* @returns The user role string
*/
export const getUserRoleString = (
role: EUserPermissions | EUserWorkspaceRoles | EUserProjectRoles | undefined
): TUserRole => {
if (!role) return "unknown";
switch (role) {
case EUserPermissions.GUEST:
return "guest";
case EUserPermissions.MEMBER:
return "member";
case EUserPermissions.ADMIN:
return "admin";
default:
return "unknown";
}
};
/**
* ============================================================================
* USER IDENTIFICATION
* ============================================================================
*/
/**
* Identify a user in PostHog with all required person properties
* Call this after signup, login, or whenever session becomes authenticated
*
* @param user - User object from the store
* @param profile - Optional user profile object (for onboarding status, role, use_case)
*/
export const identifyUser = (user: IUser, profile?: TUserProfile) => {
if (!posthog || !user) return;
posthog.identify(user.id, {
id: user.id,
email: user.email,
first_name: user.first_name,
last_name: user.last_name,
display_name: user.display_name,
date_joined: user.date_joined,
last_login_medium: user.last_login_medium || "EMAIL",
timezone: user.user_timezone,
is_email_verified: user.is_email_verified,
is_onboarded: profile?.is_onboarded || false,
role: profile?.role || null,
use_case: profile?.use_case || null,
last_workspace_id: user.last_workspace_id || null,
language: profile?.language || null,
last_login_time: user.last_login_time || null,
});
};
/**
* ============================================================================
* WORKSPACE GROUP TRACKING
* ============================================================================
*/
/**
* Join workspace group properties in PostHog
* Call this whenever a user views a workspace (e.g., on workspace switch)
*
* @param workspace - Workspace object
*/
export const joinWorkspaceGroup = (workspace: Partial<IWorkspace>) => {
if (!posthog || !workspace.slug) return;
posthog.group("workspace", workspace.slug, {
workspace_id: workspace.id,
workspace_name: workspace.name,
workspace_slug: workspace.slug,
workspace_size: workspace.organization_size,
created_at: workspace.created_at instanceof Date ? workspace.created_at.toISOString() : workspace.created_at,
owner_user_id: workspace.owner?.id || workspace.created_by,
is_deleted: false,
deleted_at: null,
});
};
/**
* ============================================================================
* GENERIC EVENT TRACKING
* ============================================================================
*/
/**
* Generic event tracking function with workspace context
* All workspace events must include workspace_id, role, and groups
*
* @param eventName - Event name in snake_case (e.g., "workspace_created")
* @param properties - Event-specific properties
* @param workspaceSlug - Workspace slug for group association
* @param role - User's role in the workspace
*/
export const trackEvent = (eventName: string, properties: Record<string, unknown>, role: TUserRole) => {
if (!posthog) return;
const eventProperties = {
...properties,
role: role || "unknown",
};
posthog.capture(eventName, eventProperties);
};
/**
* ============================================================================
* LIFECYCLE EVENTS
* ============================================================================
*/
/**
* Track workspace creation
* Call this immediately after a workspace is created
*/
export const trackWorkspaceCreated = (workspace: IWorkspace, user: IUser, role: TUserRole) => {
joinWorkspaceGroup(workspace);
trackEvent(
"workspace_created",
{
id: user.id,
workspace_id: workspace.id,
workspace_slug: workspace.slug,
workspace_name: workspace.name,
created_at: workspace.created_at instanceof Date ? workspace.created_at.toISOString() : workspace.created_at,
},
role
);
};
/**
* Track workspace deletion
*/
export const trackWorkspaceDeleted = (workspace: IWorkspace, user: IUser, role: TUserRole) => {
trackEvent(
"workspace_deleted",
{
id: user.id,
workspace_id: workspace.id,
workspace_slug: workspace.slug,
deleted_at: new Date().toISOString(),
},
role
);
};
/**
* ============================================================================
* PRODUCT ACTIVATION EVENTS
* ============================================================================
*/
/**
* Track project creation
*/
export const trackProjectCreated = (
project: { id: string; created_at: string | Date },
workspace: IWorkspace,
user: IUser,
role: TUserRole
) => {
trackEvent(
"project_created",
{
id: user.id,
workspace_id: workspace.id,
workspace_slug: workspace.slug,
project_id: project.id,
created_at: project.created_at instanceof Date ? project.created_at.toISOString() : project.created_at,
},
role
);
};
/**
* Track work item creation
*/
export const trackWorkItemCreated = (
workItem: { id: string; type?: string; created_at: string | Date },
project: { id: string },
workspace: IWorkspace,
user: IUser,
role: TUserRole
) => {
trackEvent(
"work_item_created",
{
id: user.id,
workspace_id: workspace.id,
workspace_slug: workspace.slug,
project_id: project.id,
work_item_id: workItem.id,
work_item_type: workItem.type,
created_at: workItem.created_at instanceof Date ? workItem.created_at.toISOString() : workItem.created_at,
},
role
);
};
/**
* Track cycle creation
*/
export const trackCycleCreated = (
cycle: { id: string; length_days?: number; created_at: string | Date },
project: { id: string },
workspace: IWorkspace,
user: IUser,
role: TUserRole
) => {
trackEvent(
"cycle_created",
{
id: user.id,
workspace_id: workspace.id,
workspace_slug: workspace.slug,
project_id: project.id,
cycle_id: cycle.id,
cycle_length_days: cycle.length_days || null,
created_at: cycle.created_at instanceof Date ? cycle.created_at.toISOString() : cycle.created_at,
},
role
);
};
/**
* Track page creation
*/
export const trackPageCreated = (
page: { id: string; created_at: string | Date; project_id?: string | null },
workspace: IWorkspace,
user: IUser,
location: "project" | "wiki" | "teamspace" | "workitem",
role: TUserRole
) => {
trackEvent(
"page_created",
{
id: user.id,
workspace_id: workspace.id,
workspace_slug: workspace.slug,
page_id: page.id,
location,
project_id: page.project_id || null,
created_at: page.created_at instanceof Date ? page.created_at.toISOString() : page.created_at,
},
role
);
};

View File

@@ -18,6 +18,9 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
import { CycleService } from "@/services/cycle.service";
// local imports
import { CycleForm } from "./form";
import { useUser, useUserPermissions } from "@/hooks/store/user";
import { useWorkspace } from "@/hooks/store/use-workspace";
import { getUserRoleString, trackCycleCreated } from "@/plane-web/helpers/event-tracker-v2.helper";
type CycleModalProps = {
isOpen: boolean;
@@ -39,6 +42,10 @@ export function CycleCreateUpdateModal(props: CycleModalProps) {
const { createCycle, updateCycleDetails } = useCycle();
const { isMobile } = usePlatformOS();
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { data: currentUser } = useUser();
const { currentWorkspace } = useWorkspace();
const { setValue: setCycleTab } = useLocalStorage<TCycleTabOptions>("cycle_tab", "active");
const handleCreateCycle = async (payload: Partial<ICycle>) => {
@@ -62,12 +69,16 @@ export function CycleCreateUpdateModal(props: CycleModalProps) {
title: "Success!",
message: "Cycle created successfully.",
});
captureSuccess({
eventName: CYCLE_TRACKER_EVENTS.create,
payload: {
id: res.id,
},
});
if (currentWorkspace && currentUser) {
const role = getWorkspaceRoleByWorkspaceSlug(currentWorkspace.slug);
trackCycleCreated(
{ id: res.id, created_at: new Date().toISOString() },
{ id: projectId },
currentWorkspace,
currentUser,
getUserRoleString(role)
);
}
})
.catch((err) => {
setToast({

View File

@@ -29,6 +29,8 @@ import { FileService } from "@/services/file.service";
import { InboxIssueDescription } from "./issue-description";
import { InboxIssueProperties } from "./issue-properties";
import { InboxIssueTitle } from "./issue-title";
import { getUserRoleString, trackWorkItemCreated } from "@/plane-web/helpers/event-tracker-v2.helper";
import { useUser, useUserPermissions } from "@/hooks/store/user";
const fileService = new FileService();
@@ -69,6 +71,9 @@ export const InboxIssueCreateRoot = observer(function InboxIssueCreateRoot(props
const workspaceId = getWorkspaceBySlug(workspaceSlug)?.id;
const { isMobile } = usePlatformOS();
const { getProjectById } = useProject();
const { currentWorkspace } = useWorkspace();
const { data: currentUser } = useUser();
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { t } = useTranslation();
// states
const [createMore, setCreateMore] = useState<boolean>(false);
@@ -170,12 +175,16 @@ export const InboxIssueCreateRoot = observer(function InboxIssueCreateRoot(props
descriptionEditorRef?.current?.clearEditor();
setFormData(defaultIssueData);
}
captureSuccess({
eventName: WORK_ITEM_TRACKER_EVENTS.create,
payload: {
id: res?.issue?.id,
},
});
if (currentWorkspace && currentUser) {
const role = getWorkspaceRoleByWorkspaceSlug(currentWorkspace.slug);
trackWorkItemCreated(
{ id: res?.issue?.id ?? "", created_at: new Date().toISOString() },
{ id: projectId },
currentWorkspace,
currentUser,
getUserRoleString(role)
);
}
setToast({
type: TOAST_TYPE.SUCCESS,
title: `Success!`,

View File

@@ -17,6 +17,9 @@ import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { QuickAddIssueFormRoot } from "@/plane-web/components/issues/quick-add";
// local imports
import { CreateIssueToastActionItems } from "../../create-issue-toast-action-items";
import { getUserRoleString, trackWorkItemCreated } from "@/plane-web/helpers/event-tracker-v2.helper";
import { useUser, useUserPermissions } from "@/hooks/store/user";
import { useWorkspace } from "@/hooks/store/use-workspace";
export type TQuickAddIssueForm = {
ref: React.RefObject<HTMLFormElement>;
@@ -67,6 +70,12 @@ export const QuickAddIssueRoot = observer(function QuickAddIssueRoot(props: TQui
const { workspaceSlug, projectId } = useParams();
// states
const [isOpen, setIsOpen] = useState(isQuickAddOpen ?? false);
// store hooks
const { currentWorkspace } = useWorkspace();
const { data: currentUser } = useUser();
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
// form info
const {
reset,
@@ -127,20 +136,26 @@ export const QuickAddIssueRoot = observer(function QuickAddIssueRoot(props: TQui
},
});
await quickAddPromise
.then((res) => {
captureSuccess({
eventName: WORK_ITEM_TRACKER_EVENTS.create,
payload: { id: res?.id },
});
})
.catch((error) => {
captureError({
eventName: WORK_ITEM_TRACKER_EVENTS.create,
payload: { id: payload.id },
error: error as Error,
});
const quickAddRes = await quickAddPromise;
try {
if (currentWorkspace && currentUser && quickAddRes) {
const role = getWorkspaceRoleByWorkspaceSlug(currentWorkspace.slug);
trackWorkItemCreated(
{ id: quickAddRes.id, created_at: new Date().toISOString() },
{ id: projectId.toString() },
currentWorkspace,
currentUser,
getUserRoleString(role)
);
}
} catch (error) {
captureError({
eventName: WORK_ITEM_TRACKER_EVENTS.create,
payload: { id: payload.id },
error: error as Error,
});
}
}
};

View File

@@ -28,6 +28,9 @@ import { DraftIssueLayout } from "./draft-issue-layout";
import { IssueFormRoot } from "./form";
import type { IssueFormProps } from "./form";
import type { IssuesModalProps } from "./modal";
import { getUserRoleString, trackWorkItemCreated } from "@/plane-web/helpers/event-tracker-v2.helper";
import { useWorkspace } from "@/hooks/store/use-workspace";
import { useUser, useUserPermissions } from "@/hooks/store/user";
export const CreateUpdateIssueModalBase = observer(function CreateUpdateIssueModalBase(props: IssuesModalProps) {
const {
@@ -72,6 +75,9 @@ export const CreateUpdateIssueModalBase = observer(function CreateUpdateIssueMod
const { fetchIssue } = useIssueDetail();
const { allowedProjectIds, handleCreateUpdatePropertyValues, handleCreateSubWorkItem } = useIssueModal();
const { getProjectByIdentifier } = useProject();
const { currentWorkspace } = useWorkspace();
const { data: currentUser } = useUser();
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
// current store details
const { createIssue, updateIssue } = useIssuesActions(storeType);
// derived values
@@ -240,10 +246,16 @@ export const CreateUpdateIssueModalBase = observer(function CreateUpdateIssueMod
/>
),
});
captureSuccess({
eventName: WORK_ITEM_TRACKER_EVENTS.create,
payload: { id: response.id },
});
if (currentWorkspace && currentUser && response) {
const role = getWorkspaceRoleByWorkspaceSlug(currentWorkspace.slug);
trackWorkItemCreated(
{ id: response.id, created_at: new Date().toISOString() },
{ id: payload.project_id },
currentWorkspace,
currentUser,
getUserRoleString(role)
);
}
if (!createMore) handleClose();
if (createMore && issueTitleRef) issueTitleRef?.current?.focus();
setDescription("<p></p>");
@@ -319,10 +331,17 @@ export const CreateUpdateIssueModalBase = observer(function CreateUpdateIssueMod
title: t("success"),
message: t("issue_updated_successfully"),
});
captureSuccess({
eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { id: data.id },
});
if (currentWorkspace && currentUser) {
const role = getWorkspaceRoleByWorkspaceSlug(currentWorkspace.slug);
trackWorkItemCreated(
{ id: data.id, created_at: new Date().toISOString() },
{ id: payload.project_id },
currentWorkspace,
currentUser,
getUserRoleString(role)
);
}
handleClose();
} catch (error: any) {
console.error(error);

View File

@@ -14,6 +14,9 @@ import type { EPageStoreType } from "@/plane-web/hooks/store";
import { usePageStore } from "@/plane-web/hooks/store";
// local imports
import { PageForm } from "./page-form";
import { useUser, useUserPermissions } from "@/hooks/store/user";
import { useWorkspace } from "@/hooks/store/use-workspace";
import { getUserRoleString, trackPageCreated } from "@/plane-web/helpers/event-tracker-v2.helper";
type Props = {
workspaceSlug: string;
@@ -45,6 +48,10 @@ export function CreatePageModal(props: Props) {
const router = useAppRouter();
// store hooks
const { createPage } = usePageStore(storeType);
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { data: currentUser } = useUser();
const { currentWorkspace } = useWorkspace();
const handlePageFormData = <T extends keyof TPage>(key: T, value: TPage[T]) =>
setPageFormData((prev) => ({ ...prev, [key]: value }));
@@ -64,12 +71,16 @@ export function CreatePageModal(props: Props) {
try {
const pageData = await createPage(pageFormData);
if (pageData) {
captureSuccess({
eventName: PROJECT_PAGE_TRACKER_EVENTS.create,
payload: {
id: pageData.id,
},
});
if (currentWorkspace && currentUser) {
const role = getWorkspaceRoleByWorkspaceSlug(currentWorkspace.slug);
trackPageCreated(
{ id: pageData.id ?? "", created_at: new Date().toISOString() },
currentWorkspace,
currentUser,
"project",
getUserRoleString(role)
);
}
handleStateClear();
if (redirectionEnabled) router.push(`/${workspaceSlug}/projects/${projectId}/pages/${pageData.id}`);
}

View File

@@ -17,9 +17,11 @@ import { EUserProjectRoles } from "@plane/types";
import { PageLoader } from "@/components/pages/loaders/page-loader";
import { captureClick, captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useProject } from "@/hooks/store/use-project";
import { useUserPermissions } from "@/hooks/store/user";
import { useUser, useUserPermissions } from "@/hooks/store/user";
// plane web hooks
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
import { useWorkspace } from "@/hooks/store/use-workspace";
import { getUserRoleString, trackPageCreated } from "@/plane-web/helpers/event-tracker-v2.helper";
type Props = {
children: React.ReactNode;
@@ -35,8 +37,10 @@ export const PagesListMainContent = observer(function PagesListMainContent(props
const { currentProjectDetails } = useProject();
const { isAnyPageAvailable, getCurrentProjectFilteredPageIdsByTab, getCurrentProjectPageIdsByTab, loader } =
usePageStore(storeType);
const { allowPermissions } = useUserPermissions();
const { allowPermissions, getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { createPage } = usePageStore(EPageStoreType.PROJECT);
const { data: currentUser } = useUser();
const { currentWorkspace } = useWorkspace();
// states
const [isCreatingPage, setIsCreatingPage] = useState(false);
// router
@@ -60,13 +64,16 @@ export const PagesListMainContent = observer(function PagesListMainContent(props
await createPage(payload)
.then((res) => {
captureSuccess({
eventName: PROJECT_PAGE_TRACKER_EVENTS.create,
payload: {
id: res?.id,
state: "SUCCESS",
},
});
if (currentWorkspace && currentUser && res?.id) {
const role = getWorkspaceRoleByWorkspaceSlug(currentWorkspace.slug);
trackPageCreated(
{ id: res.id, created_at: new Date().toISOString() },
currentWorkspace,
currentUser,
"project",
getUserRoleString(role)
);
}
const pageId = `/${workspaceSlug}/projects/${currentProjectDetails?.id}/pages/${res?.id}`;
router.push(pageId);
})

View File

@@ -14,8 +14,9 @@ import { Input } from "@plane/ui";
import { cn } from "@plane/utils";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useWorkspace } from "@/hooks/store/use-workspace";
import { useUserSettings } from "@/hooks/store/user";
import { useUser, useUserPermissions, useUserSettings } from "@/hooks/store/user";
import { useAppRouter } from "@/hooks/use-app-router";
import { getUserRoleString, trackWorkspaceDeleted } from "@/plane-web/helpers/event-tracker-v2.helper";
type Props = {
data: IWorkspace | null;
@@ -36,6 +37,9 @@ export const DeleteWorkspaceForm = observer(function DeleteWorkspaceForm(props:
const { t } = useTranslation();
const { getWorkspaceRedirectionUrl } = useWorkspace();
const { fetchCurrentUserSettings } = useUserSettings();
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { data: currentUser } = useUser();
// form info
const {
control,
@@ -64,10 +68,12 @@ export const DeleteWorkspaceForm = observer(function DeleteWorkspaceForm(props:
await fetchCurrentUserSettings();
handleClose();
router.push(getWorkspaceRedirectionUrl());
captureSuccess({
eventName: WORKSPACE_TRACKER_EVENTS.delete,
payload: { slug: data.slug },
});
if (currentUser && data) {
const role = getWorkspaceRoleByWorkspaceSlug(data.slug);
trackWorkspaceDeleted(data, currentUser, getUserRoleString(role));
}
setToast({
type: TOAST_TYPE.SUCCESS,
title: t("workspace_settings.settings.general.delete_modal.success_title"),

View File

@@ -1,16 +1,15 @@
import type { ReactNode } from "react";
import { lazy, Suspense, useEffect, useCallback, useRef, useState } from "react";
import { PostHogProvider as PHProvider } from "@posthog/react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import posthog from "posthog-js";
import type { ReactNode } from "react";
import { lazy, Suspense, useCallback, useEffect, useRef, useState } from "react";
// constants
import { GROUP_WORKSPACE_TRACKER_EVENT } from "@plane/constants";
// hooks
import { captureClick, joinEventGroup } from "@/helpers/event-tracker.helper";
import { captureClick } from "@/helpers/event-tracker.helper";
import { identifyUser, joinWorkspaceGroup } from "@/plane-web/helpers/event-tracker-v2.helper";
import { useInstance } from "@/hooks/store/use-instance";
import { useUser, useUserProfile } from "@/hooks/store/user";
import { useWorkspace } from "@/hooks/store/use-workspace";
import { useUser, useUserPermissions, useUserProfile } from "@/hooks/store/user";
// dynamic imports
const PostHogPageView = lazy(function PostHogPageView() {
return import("@/lib/posthog-view");
@@ -24,44 +23,27 @@ const PostHogProvider = observer(function PostHogProvider(props: IPosthogWrapper
const { children } = props;
const { data: user } = useUser();
const { data: profile } = useUserProfile();
const { currentWorkspace } = useWorkspace();
const { instance } = useInstance();
const { workspaceSlug, projectId } = useParams();
const { getWorkspaceRoleByWorkspaceSlug, getProjectRoleByWorkspaceSlugAndProjectId } = useUserPermissions();
const { currentWorkspace } = useWorkspace();
// refs
const isInitializedRef = useRef(false);
// states
const [hydrated, setHydrated] = useState(false);
// derived values
const currentProjectRole = getProjectRoleByWorkspaceSlugAndProjectId(
workspaceSlug?.toString(),
projectId?.toString()
);
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug?.toString());
const is_telemetry_enabled = instance?.is_telemetry_enabled || false;
const is_posthog_enabled = process.env.VITE_POSTHOG_KEY && process.env.VITE_POSTHOG_HOST && is_telemetry_enabled;
useEffect(() => {
if (user && profile && hydrated) {
// Identify sends an event, so you want may want to limit how often you call it
posthog?.identify(user.email, {
id: user.id,
first_name: user.first_name,
last_name: user.last_name,
email: user.email,
display_name: user.display_name,
date_joined: user.date_joined,
last_login_medium: user.last_login_medium,
is_email_verified: user.is_email_verified,
timezone: user.user_timezone,
is_onboarded: profile.is_onboarded,
role: profile.role,
use_case: profile.use_case,
language: profile.language,
last_workspace_id: profile.last_workspace_id,
});
if (user && profile && hydrated && is_posthog_enabled) {
identifyUser(user, profile);
}
}, [user, profile, hydrated]);
}, [user, profile, hydrated, is_posthog_enabled]);
useEffect(() => {
if (currentWorkspace && hydrated && is_posthog_enabled) {
joinWorkspaceGroup(currentWorkspace);
}
}, [currentWorkspace, hydrated, is_posthog_enabled]);
useEffect(() => {
if (isInitializedRef.current) return; // prevent multiple initializations

View File

@@ -0,0 +1,3 @@
export * from "ce/helpers/event-tracker-v2.helper";

View File

@@ -43,6 +43,7 @@ export interface IUser extends IUserLite {
user_timezone: string;
username: string;
last_login_medium: TLoginMediums;
last_login_time: string | null;
theme: IUserTheme;
}