[WEB-4409] refactor: event constants (#7276)

* refactor: event constants

* fix: cycle event keys

* chore: store extension

* chore: update events naming convention

---------

Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
Aaryan Khandelwal 2025-06-27 19:01:00 +05:30 committed by GitHub
parent e09aeab5b8
commit 4a065e14d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
67 changed files with 553 additions and 513 deletions

View file

@ -1,238 +0,0 @@
export type IssueEventProps = {
eventName: string;
payload: any;
updates?: any;
path?: string;
};
export type EventProps = {
eventName: string;
payload: any;
updates?: any;
path?: string;
};
export const getWorkspaceEventPayload = (payload: any) => ({
workspace_id: payload.id,
created_at: payload.created_at,
updated_at: payload.updated_at,
organization_size: payload.organization_size,
first_time: payload.first_time,
state: payload.state,
element: payload.element,
});
export const getProjectEventPayload = (payload: any) => ({
workspace_id: payload.workspace_id,
project_id: payload.id,
identifier: payload.identifier,
project_visibility: payload.network == 2 ? "Public" : "Private",
changed_properties: payload.changed_properties,
lead_id: payload.project_lead,
created_at: payload.created_at,
updated_at: payload.updated_at,
state: payload.state,
element: payload.element,
});
export const getCycleEventPayload = (payload: any) => ({
workspace_id: payload.workspace_id,
project_id: payload.project,
cycle_id: payload.id,
created_at: payload.created_at,
updated_at: payload.updated_at,
start_date: payload.start_date,
target_date: payload.target_date,
cycle_status: payload.status,
changed_properties: payload.changed_properties,
state: payload.state,
element: payload.element,
});
export const getModuleEventPayload = (payload: any) => ({
workspace_id: payload.workspace_id,
project_id: payload.project,
module_id: payload.id,
created_at: payload.created_at,
updated_at: payload.updated_at,
start_date: payload.start_date,
target_date: payload.target_date,
module_status: payload.status,
lead_id: payload.lead,
changed_properties: payload.changed_properties,
member_ids: payload.members,
state: payload.state,
element: payload.element,
});
export const getPageEventPayload = (payload: any) => ({
workspace_id: payload.workspace_id,
project_id: payload.project,
created_at: payload.created_at,
updated_at: payload.updated_at,
access: payload.access === 0 ? "Public" : "Private",
is_locked: payload.is_locked,
archived_at: payload.archived_at,
created_by: payload.created_by,
state: payload.state,
element: payload.element,
});
export const getIssueEventPayload = (props: IssueEventProps) => {
const { eventName, payload, updates, path } = props;
let eventPayload: any = {
issue_id: payload.id,
estimate_point: payload.estimate_point,
link_count: payload.link_count,
target_date: payload.target_date,
is_draft: payload.is_draft,
label_ids: payload.label_ids,
assignee_ids: payload.assignee_ids,
created_at: payload.created_at,
updated_at: payload.updated_at,
sequence_id: payload.sequence_id,
module_ids: payload.module_ids,
sub_issues_count: payload.sub_issues_count,
parent_id: payload.parent_id,
project_id: payload.project_id,
workspace_id: payload.workspace_id,
priority: payload.priority,
state_id: payload.state_id,
start_date: payload.start_date,
attachment_count: payload.attachment_count,
cycle_id: payload.cycle_id,
module_id: payload.module_id,
archived_at: payload.archived_at,
state: payload.state,
view_id:
path?.includes("workspace-views") || path?.includes("views")
? path.split("/").pop()
: "",
};
if (eventName === ISSUE_UPDATED) {
eventPayload = {
...eventPayload,
...updates,
updated_from: props.path?.includes("workspace-views")
? "All views"
: props.path?.includes("cycles")
? "Cycle"
: props.path?.includes("modules")
? "Module"
: props.path?.includes("views")
? "Project view"
: props.path?.includes("inbox")
? "Inbox"
: props.path?.includes("draft")
? "Draft"
: "Project",
};
}
return eventPayload;
};
export const getProjectStateEventPayload = (payload: any) => ({
workspace_id: payload.workspace_id,
project_id: payload.id,
state_id: payload.id,
created_at: payload.created_at,
updated_at: payload.updated_at,
group: payload.group,
color: payload.color,
default: payload.default,
state: payload.state,
element: payload.element,
});
// Workspace crud Events
export const WORKSPACE_CREATED = "Workspace created";
export const WORKSPACE_UPDATED = "Workspace updated";
export const WORKSPACE_DELETED = "Workspace deleted";
// Project Events
export const PROJECT_CREATED = "Project created";
export const PROJECT_UPDATED = "Project updated";
export const PROJECT_DELETED = "Project deleted";
// Cycle Events
export const CYCLE_CREATED = "Cycle created";
export const CYCLE_UPDATED = "Cycle updated";
export const CYCLE_DELETED = "Cycle deleted";
export const CYCLE_FAVORITED = "Cycle favorited";
export const CYCLE_UNFAVORITED = "Cycle unfavorited";
// Module Events
export const MODULE_CREATED = "Module created";
export const MODULE_UPDATED = "Module updated";
export const MODULE_DELETED = "Module deleted";
export const MODULE_FAVORITED = "Module favorited";
export const MODULE_UNFAVORITED = "Module unfavorited";
export const MODULE_LINK_CREATED = "Module link created";
export const MODULE_LINK_UPDATED = "Module link updated";
export const MODULE_LINK_DELETED = "Module link deleted";
// Issue Events
export const ISSUE_CREATED = "Work item created";
export const ISSUE_UPDATED = "Work item updated";
export const ISSUE_DELETED = "Work item deleted";
export const ISSUE_ARCHIVED = "Work item archived";
export const ISSUE_RESTORED = "Work item restored";
export const ISSUE_OPENED = "Work item opened";
// Project State Events
export const STATE_CREATED = "State created";
export const STATE_UPDATED = "State updated";
export const STATE_DELETED = "State deleted";
// Project Page Events
export const PAGE_CREATED = "Page created";
export const PAGE_UPDATED = "Page updated";
export const PAGE_DELETED = "Page deleted";
// Member Events
export const MEMBER_INVITED = "Member invited";
export const MEMBER_ACCEPTED = "Member accepted";
export const PROJECT_MEMBER_ADDED = "Project member added";
export const PROJECT_MEMBER_LEAVE = "Project member leave";
export const WORKSPACE_MEMBER_LEAVE = "Workspace member leave";
// Sign-in & Sign-up Events
export const NAVIGATE_TO_SIGNUP = "Navigate to sign-up page";
export const NAVIGATE_TO_SIGNIN = "Navigate to sign-in page";
export const CODE_VERIFIED = "Code verified";
export const SETUP_PASSWORD = "Password setup";
export const PASSWORD_CREATE_SELECTED = "Password created";
export const PASSWORD_CREATE_SKIPPED = "Skipped to setup";
export const SIGN_IN_WITH_PASSWORD = "Sign in with password";
export const SIGN_UP_WITH_PASSWORD = "Sign up with password";
export const SIGN_IN_WITH_CODE = "Sign in with magic link";
export const FORGOT_PASSWORD = "Forgot password clicked";
export const FORGOT_PASS_LINK = "Forgot password link generated";
export const NEW_PASS_CREATED = "New password created";
// Onboarding Events
export const USER_DETAILS = "User details added";
export const USER_ONBOARDING_COMPLETED = "User onboarding completed";
// Product Tour Events
export const PRODUCT_TOUR_STARTED = "Product tour started";
export const PRODUCT_TOUR_COMPLETED = "Product tour completed";
export const PRODUCT_TOUR_SKIPPED = "Product tour skipped";
// Dashboard Events
export const CHANGELOG_REDIRECTED = "Changelog redirected";
export const GITHUB_REDIRECTED = "GitHub redirected";
// Sidebar Events
export const SIDEBAR_CLICKED = "Sidenav clicked";
// Global View Events
export const GLOBAL_VIEW_CREATED = "Global view created";
export const GLOBAL_VIEW_UPDATED = "Global view updated";
export const GLOBAL_VIEW_DELETED = "Global view deleted";
export const GLOBAL_VIEW_OPENED = "Global view opened";
// Notification Events
export const NOTIFICATION_ARCHIVED = "Notification archived";
export const NOTIFICATION_SNOOZED = "Notification snoozed";
export const NOTIFICATION_READ = "Notification marked read";
export const UNREAD_NOTIFICATIONS = "Unread notifications viewed";
export const NOTIFICATIONS_READ = "All notifications marked read";
export const SNOOZED_NOTIFICATIONS = "Snoozed notifications viewed";
export const ARCHIVED_NOTIFICATIONS = "Archived notifications viewed";
// Groups
export const GROUP_WORKSPACE = "Workspace_metrics";
//Elements
export const E_ONBOARDING = "Onboarding";
export const E_ONBOARDING_STEP_1 = "Onboarding step 1";
export const E_ONBOARDING_STEP_2 = "Onboarding step 2";
// Favorites
export const FAVORITE_ADDED = "Favorite added";

View file

@ -0,0 +1,258 @@
export type IssueEventProps = {
eventName: string;
payload: any;
updates?: any;
path?: string;
};
export type EventProps = {
eventName: string;
payload: any;
updates?: any;
path?: string;
};
export const getWorkspaceEventPayload = (payload: any) => ({
workspace_id: payload.id,
created_at: payload.created_at,
updated_at: payload.updated_at,
organization_size: payload.organization_size,
first_time: payload.first_time,
state: payload.state,
element: payload.element,
});
export const getProjectEventPayload = (payload: any) => ({
workspace_id: payload.workspace_id,
project_id: payload.id,
identifier: payload.identifier,
project_visibility: payload.network == 2 ? "Public" : "Private",
changed_properties: payload.changed_properties,
lead_id: payload.project_lead,
created_at: payload.created_at,
updated_at: payload.updated_at,
state: payload.state,
element: payload.element,
});
export const getCycleEventPayload = (payload: any) => ({
workspace_id: payload.workspace_id,
project_id: payload.project,
cycle_id: payload.id,
created_at: payload.created_at,
updated_at: payload.updated_at,
start_date: payload.start_date,
target_date: payload.target_date,
cycle_status: payload.status,
changed_properties: payload.changed_properties,
state: payload.state,
element: payload.element,
});
export const getModuleEventPayload = (payload: any) => ({
workspace_id: payload.workspace_id,
project_id: payload.project,
module_id: payload.id,
created_at: payload.created_at,
updated_at: payload.updated_at,
start_date: payload.start_date,
target_date: payload.target_date,
module_status: payload.status,
lead_id: payload.lead,
changed_properties: payload.changed_properties,
member_ids: payload.members,
state: payload.state,
element: payload.element,
});
export const getPageEventPayload = (payload: any) => ({
workspace_id: payload.workspace_id,
project_id: payload.project,
created_at: payload.created_at,
updated_at: payload.updated_at,
access: payload.access === 0 ? "Public" : "Private",
is_locked: payload.is_locked,
archived_at: payload.archived_at,
created_by: payload.created_by,
state: payload.state,
element: payload.element,
});
export const getIssueEventPayload = (props: IssueEventProps) => {
const { eventName, payload, updates, path } = props;
let eventPayload: any = {
issue_id: payload.id,
estimate_point: payload.estimate_point,
link_count: payload.link_count,
target_date: payload.target_date,
is_draft: payload.is_draft,
label_ids: payload.label_ids,
assignee_ids: payload.assignee_ids,
created_at: payload.created_at,
updated_at: payload.updated_at,
sequence_id: payload.sequence_id,
module_ids: payload.module_ids,
sub_issues_count: payload.sub_issues_count,
parent_id: payload.parent_id,
project_id: payload.project_id,
workspace_id: payload.workspace_id,
priority: payload.priority,
state_id: payload.state_id,
start_date: payload.start_date,
attachment_count: payload.attachment_count,
cycle_id: payload.cycle_id,
module_id: payload.module_id,
archived_at: payload.archived_at,
state: payload.state,
view_id: path?.includes("workspace-views") || path?.includes("views") ? path.split("/").pop() : "",
};
if (eventName === WORK_ITEM_TRACKER_EVENTS.update) {
eventPayload = {
...eventPayload,
...updates,
updated_from: props.path?.includes("workspace-views")
? "All views"
: props.path?.includes("cycles")
? "Cycle"
: props.path?.includes("modules")
? "Module"
: props.path?.includes("views")
? "Project view"
: props.path?.includes("inbox")
? "Inbox"
: props.path?.includes("draft")
? "Draft"
: "Project",
};
}
return eventPayload;
};
export const getProjectStateEventPayload = (payload: any) => ({
workspace_id: payload.workspace_id,
project_id: payload.id,
state_id: payload.id,
created_at: payload.created_at,
updated_at: payload.updated_at,
group: payload.group,
color: payload.color,
default: payload.default,
state: payload.state,
element: payload.element,
});
// Dashboard Events
export const GITHUB_REDIRECTED_TRACKER_EVENT = "github_redirected";
// Groups
export const GROUP_WORKSPACE_TRACKER_EVENT = "workspace_metrics";
export const WORKSPACE_TRACKER_EVENTS = {
create: "workspace_created",
update: "workspace_updated",
delete: "workspace_deleted",
};
export const PROJECT_TRACKER_EVENTS = {
create: "project_created",
update: "project_updated",
delete: "project_deleted",
};
export const CYCLE_TRACKER_EVENTS = {
create: "cycle_created",
update: "cycle_updated",
delete: "cycle_deleted",
favorite: "cycle_favorited",
unfavorite: "cycle_unfavorited",
};
export const MODULE_TRACKER_EVENTS = {
create: "module_created",
update: "module_updated",
delete: "module_deleted",
favorite: "module_favorited",
unfavorite: "module_unfavorited",
link: {
create: "module_link_created",
update: "module_link_updated",
delete: "module_link_deleted",
},
};
export const WORK_ITEM_TRACKER_EVENTS = {
create: "work_item_created",
update: "work_item_updated",
delete: "work_item_deleted",
archive: "work_item_archived",
restore: "work_item_restored",
};
export const STATE_TRACKER_EVENTS = {
create: "state_created",
update: "state_updated",
delete: "state_deleted",
};
export const PROJECT_PAGE_TRACKER_EVENTS = {
create: "project_page_created",
update: "project_page_updated",
delete: "project_page_deleted",
};
export const MEMBER_TRACKER_EVENTS = {
invite: "member_invited",
accept: "member_accepted",
project: {
add: "project_member_added",
leave: "project_member_left",
},
workspace: {
leave: "workspace_member_left",
},
};
export const AUTH_TRACKER_EVENTS = {
navigate: {
sign_up: "navigate_to_sign_up_page",
sign_in: "navigate_to_sign_in_page",
},
code_verify: "code_verified",
sign_up_with_password: "sign_up_with_password",
sign_in_with_password: "sign_in_with_password",
sign_in_with_code: "sign_in_with_magic_link",
forgot_password: "forgot_password_clicked",
};
export const PRODUCT_TOUR_TRACKER_EVENTS = {
start: "product_tour_started",
complete: "product_tour_completed",
skip: "product_tour_skipped",
};
export const GLOBAL_VIEW_TOUR_TRACKER_EVENTS = {
create: "global_view_created",
update: "global_view_updated",
delete: "global_view_deleted",
open: "global_view_opened",
};
export const NOTIFICATION_TRACKER_EVENTS = {
archive: "notification_archived",
all_marked_read: "all_notifications_marked_read",
};
export const USER_TRACKER_EVENTS = {
add_details: "user_details_added",
onboarding_complete: "user_onboarding_completed",
};
export const ONBOARDING_TRACKER_EVENTS = {
root: "onboarding",
step_1: "onboarding_step_1",
step_2: "onboarding_step_2",
};
export const SIDEBAR_TRACKER_EVENTS = {
click: "sidenav_clicked",
};

View file

@ -0,0 +1 @@
export * from "./core";

View file

@ -7,7 +7,7 @@ import { Home } from "lucide-react";
import githubBlackImage from "/public/logos/github-black.png"; import githubBlackImage from "/public/logos/github-black.png";
import githubWhiteImage from "/public/logos/github-white.png"; import githubWhiteImage from "/public/logos/github-white.png";
// ui // ui
import { GITHUB_REDIRECTED } from "@plane/constants"; import { GITHUB_REDIRECTED_TRACKER_EVENT } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { Breadcrumbs, Header } from "@plane/ui"; import { Breadcrumbs, Header } from "@plane/ui";
// components // components
@ -39,7 +39,7 @@ export const WorkspaceDashboardHeader = () => {
<Header.RightItem> <Header.RightItem>
<a <a
onClick={() => onClick={() =>
captureEvent(GITHUB_REDIRECTED, { captureEvent(GITHUB_REDIRECTED_TRACKER_EVENT, {
element: "navbar", element: "navbar",
}) })
} }

View file

@ -5,7 +5,7 @@ import { observer } from "mobx-react";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
import { Search } from "lucide-react"; import { Search } from "lucide-react";
// types // types
import { MEMBER_INVITED, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; import { EUserPermissions, EUserPermissionsLevel, MEMBER_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { IWorkspaceBulkInviteFormData } from "@plane/types"; import { IWorkspaceBulkInviteFormData } from "@plane/types";
// ui // ui
@ -52,7 +52,7 @@ const WorkspaceMembersSettingsPage = observer(() => {
return inviteMembersToWorkspace(workspaceSlug.toString(), data) return inviteMembersToWorkspace(workspaceSlug.toString(), data)
.then(() => { .then(() => {
setInviteModal(false); setInviteModal(false);
captureEvent(MEMBER_INVITED, { captureEvent(MEMBER_TRACKER_EVENTS.invite, {
emails: [ emails: [
...data.emails.map((email) => ({ ...data.emails.map((email) => ({
email: email.email, email: email.email,
@ -70,7 +70,7 @@ const WorkspaceMembersSettingsPage = observer(() => {
}); });
}) })
.catch((err) => { .catch((err) => {
captureEvent(MEMBER_INVITED, { captureEvent(MEMBER_TRACKER_EVENTS.invite, {
emails: [ emails: [
...data.emails.map((email) => ({ ...data.emails.map((email) => ({
email: email.email, email: email.email,

View file

@ -9,7 +9,7 @@ import { Controller, useForm } from "react-hook-form";
// icons // icons
import { CircleCheck } from "lucide-react"; import { CircleCheck } from "lucide-react";
// plane imports // plane imports
import { FORGOT_PASS_LINK, NAVIGATE_TO_SIGNUP } from "@plane/constants"; import { AUTH_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { Button, Input, TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui"; import { Button, Input, TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui";
import { cn, checkEmailValidity } from "@plane/utils"; import { cn, checkEmailValidity } from "@plane/utils";
@ -71,7 +71,7 @@ const ForgotPasswordPage = observer(() => {
email: formData.email, email: formData.email,
}) })
.then(() => { .then(() => {
captureEvent(FORGOT_PASS_LINK, { captureEvent(AUTH_TRACKER_EVENTS.forgot_password, {
state: "SUCCESS", state: "SUCCESS",
}); });
setToast({ setToast({
@ -82,7 +82,7 @@ const ForgotPasswordPage = observer(() => {
setResendCodeTimer(30); setResendCodeTimer(30);
}) })
.catch((err) => { .catch((err) => {
captureEvent(FORGOT_PASS_LINK, { captureEvent(AUTH_TRACKER_EVENTS.forgot_password, {
state: "FAILED", state: "FAILED",
}); });
setToast({ setToast({
@ -120,7 +120,7 @@ const ForgotPasswordPage = observer(() => {
{t("auth.common.new_to_plane")} {t("auth.common.new_to_plane")}
<Link <Link
href="/" href="/"
onClick={() => captureEvent(NAVIGATE_TO_SIGNUP, {})} onClick={() => captureEvent(AUTH_TRACKER_EVENTS.navigate.sign_up, {})}
className="font-semibold text-custom-primary-100 hover:underline" className="font-semibold text-custom-primary-100 hover:underline"
> >
{t("auth.common.create_account")} {t("auth.common.create_account")}

View file

@ -9,7 +9,7 @@ import { useTheme } from "next-themes";
import useSWR, { mutate } from "swr"; import useSWR, { mutate } from "swr";
import { CheckCircle2 } from "lucide-react"; import { CheckCircle2 } from "lucide-react";
// plane imports // plane imports
import { ROLE, MEMBER_ACCEPTED, EUserPermissions } from "@plane/constants"; import { ROLE, EUserPermissions, MEMBER_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
// types // types
import type { IWorkspaceMemberInvitation } from "@plane/types"; import type { IWorkspaceMemberInvitation } from "@plane/types";
@ -86,7 +86,7 @@ const UserInvitationsPage = observer(() => {
const invitation = invitations?.find((i) => i.id === firstInviteId); const invitation = invitations?.find((i) => i.id === firstInviteId);
const redirectWorkspace = invitations?.find((i) => i.id === firstInviteId)?.workspace; const redirectWorkspace = invitations?.find((i) => i.id === firstInviteId)?.workspace;
joinWorkspaceMetricGroup(redirectWorkspace?.id); joinWorkspaceMetricGroup(redirectWorkspace?.id);
captureEvent(MEMBER_ACCEPTED, { captureEvent(MEMBER_TRACKER_EVENTS.accept, {
member_id: invitation?.id, member_id: invitation?.id,
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
role: getUserRole((invitation?.role as unknown as EUserPermissions)!), role: getUserRole((invitation?.role as unknown as EUserPermissions)!),
@ -112,7 +112,7 @@ const UserInvitationsPage = observer(() => {
}); });
}) })
.catch(() => { .catch(() => {
captureEvent(MEMBER_ACCEPTED, { captureEvent(MEMBER_TRACKER_EVENTS.accept, {
project_id: undefined, project_id: undefined,
accepted_from: "App", accepted_from: "App",
state: "FAILED", state: "FAILED",

View file

@ -4,7 +4,7 @@ import { useEffect, useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import useSWR from "swr"; import useSWR from "swr";
// types // types
import { USER_ONBOARDING_COMPLETED } from "@plane/constants"; import { USER_TRACKER_EVENTS } from "@plane/constants";
import { TOnboardingSteps, TUserProfile } from "@plane/types"; import { TOnboardingSteps, TUserProfile } from "@plane/types";
// ui // ui
import { TOAST_TYPE, setToast } from "@plane/ui"; import { TOAST_TYPE, setToast } from "@plane/ui";
@ -73,7 +73,7 @@ const OnboardingPage = observer(() => {
await finishUserOnboarding() await finishUserOnboarding()
.then(() => { .then(() => {
captureEvent(USER_ONBOARDING_COMPLETED, { captureEvent(USER_TRACKER_EVENTS.onboarding_complete, {
email: user.email, email: user.email,
user_id: user.id, user_id: user.id,
status: "SUCCESS", status: "SUCCESS",

View file

@ -6,7 +6,7 @@ import Link from "next/link";
// ui // ui
import { useTheme } from "next-themes"; import { useTheme } from "next-themes";
// components // components
import { NAVIGATE_TO_SIGNIN } from "@plane/constants"; import { AUTH_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { AuthRoot } from "@/components/account"; import { AuthRoot } from "@/components/account";
// constants // constants
@ -54,7 +54,7 @@ const SignInPage = observer(() => {
{t("auth.common.already_have_an_account")} {t("auth.common.already_have_an_account")}
<Link <Link
href="/" href="/"
onClick={() => captureEvent(NAVIGATE_TO_SIGNIN, {})} onClick={() => captureEvent(AUTH_TRACKER_EVENTS.navigate.sign_in, {})}
className="font-semibold text-custom-primary-100 hover:underline" className="font-semibold text-custom-primary-100 hover:underline"
> >
{t("auth.common.login")} {t("auth.common.login")}

View file

@ -6,7 +6,7 @@ import Link from "next/link";
// ui // ui
import { useTheme } from "next-themes"; import { useTheme } from "next-themes";
// components // components
import { NAVIGATE_TO_SIGNUP } from "@plane/constants"; import { AUTH_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { AuthRoot } from "@/components/account"; import { AuthRoot } from "@/components/account";
import { PageHead } from "@/components/core"; import { PageHead } from "@/components/core";
@ -63,7 +63,7 @@ const HomePage = observer(() => {
{t("auth.common.new_to_plane")} {t("auth.common.new_to_plane")}
<Link <Link
href="/sign-up" href="/sign-up"
onClick={() => captureEvent(NAVIGATE_TO_SIGNUP, {})} onClick={() => captureEvent(AUTH_TRACKER_EVENTS.navigate.sign_up, {})}
className="font-semibold text-custom-primary-100 hover:underline" className="font-semibold text-custom-primary-100 hover:underline"
> >
{t("auth.common.create_account")} {t("auth.common.create_account")}

View file

@ -3,7 +3,7 @@
import { useState, FC } from "react"; import { useState, FC } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { PROJECT_CREATED, DEFAULT_PROJECT_FORM_VALUES } from "@plane/constants"; import { DEFAULT_PROJECT_FORM_VALUES, PROJECT_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
// ui // ui
import { setToast, TOAST_TYPE } from "@plane/ui"; import { setToast, TOAST_TYPE } from "@plane/ui";
@ -75,7 +75,7 @@ export const CreateProjectForm: FC<TCreateProjectFormProps> = observer((props) =
state: "SUCCESS", state: "SUCCESS",
}; };
captureProjectEvent({ captureProjectEvent({
eventName: PROJECT_CREATED, eventName: PROJECT_TRACKER_EVENTS.create,
payload: newPayload, payload: newPayload,
}); });
setToast({ setToast({

View file

@ -0,0 +1,11 @@
import { RootStore } from "@/plane-web/store/root.store";
import { CoreEventTrackerStore, ICoreEventTrackerStore } from "@/store/event-tracker.store";
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface IEventTrackerStore extends ICoreEventTrackerStore {}
export class EventTrackerStore extends CoreEventTrackerStore implements IEventTrackerStore {
constructor(_rootStore: RootStore) {
super(_rootStore);
}
}

View file

@ -6,7 +6,7 @@ import Link from "next/link";
// icons // icons
import { Eye, EyeOff, Info, X, XCircle } from "lucide-react"; import { Eye, EyeOff, Info, X, XCircle } from "lucide-react";
// plane imports // plane imports
import { FORGOT_PASSWORD, SIGN_IN_WITH_CODE, SIGN_IN_WITH_PASSWORD, SIGN_UP_WITH_PASSWORD, API_BASE_URL, E_PASSWORD_STRENGTH } from "@plane/constants"; import { API_BASE_URL, E_PASSWORD_STRENGTH, AUTH_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { Button, Input, Spinner } from "@plane/ui"; import { Button, Input, Spinner } from "@plane/ui";
import { getPasswordStrength } from "@plane/utils"; import { getPasswordStrength } from "@plane/utils";
@ -77,7 +77,7 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
const redirectToUniqueCodeSignIn = async () => { const redirectToUniqueCodeSignIn = async () => {
handleAuthStep(EAuthSteps.UNIQUE_CODE); handleAuthStep(EAuthSteps.UNIQUE_CODE);
captureEvent(SIGN_IN_WITH_CODE); captureEvent(AUTH_TRACKER_EVENTS.sign_in_with_code);
}; };
const passwordSupport = const passwordSupport =
@ -85,7 +85,7 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
<div className="w-full"> <div className="w-full">
{isSMTPConfigured ? ( {isSMTPConfigured ? (
<Link <Link
onClick={() => captureEvent(FORGOT_PASSWORD)} onClick={() => captureEvent(AUTH_TRACKER_EVENTS.forgot_password)}
href={`/accounts/forgot-password?email=${encodeURIComponent(email)}`} href={`/accounts/forgot-password?email=${encodeURIComponent(email)}`}
className="text-xs font-medium text-custom-primary-100" className="text-xs font-medium text-custom-primary-100"
> >
@ -154,7 +154,11 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
: true; : true;
if (isPasswordValid) { if (isPasswordValid) {
setIsSubmitting(true); setIsSubmitting(true);
captureEvent(mode === EAuthModes.SIGN_IN ? SIGN_IN_WITH_PASSWORD : SIGN_UP_WITH_PASSWORD); captureEvent(
mode === EAuthModes.SIGN_IN
? AUTH_TRACKER_EVENTS.sign_in_with_password
: AUTH_TRACKER_EVENTS.sign_up_with_password
);
if (formRef.current) formRef.current.submit(); // Manually submit the form if the condition is met if (formRef.current) formRef.current.submit(); // Manually submit the form if the condition is met
} else { } else {
setBannerMessage(true); setBannerMessage(true);

View file

@ -2,7 +2,7 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { CircleCheck, XCircle } from "lucide-react"; import { CircleCheck, XCircle } from "lucide-react";
import { CODE_VERIFIED, API_BASE_URL } from "@plane/constants"; import { API_BASE_URL, AUTH_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { Button, Input, Spinner } from "@plane/ui"; import { Button, Input, Spinner } from "@plane/ui";
// constants // constants
@ -84,7 +84,7 @@ export const AuthUniqueCodeForm: React.FC<TAuthUniqueCodeForm> = (props) => {
action={`${API_BASE_URL}/auth/${mode === EAuthModes.SIGN_IN ? "magic-sign-in" : "magic-sign-up"}/`} action={`${API_BASE_URL}/auth/${mode === EAuthModes.SIGN_IN ? "magic-sign-in" : "magic-sign-up"}/`}
onSubmit={() => { onSubmit={() => {
setIsSubmitting(true); setIsSubmitting(true);
captureEvent(CODE_VERIFIED, { captureEvent(AUTH_TRACKER_EVENTS.code_verify, {
state: "SUCCESS", state: "SUCCESS",
first_time: !isExistingEmail, first_time: !isExistingEmail,
}); });

View file

@ -5,7 +5,7 @@ import { observer } from "mobx-react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { ArrowRight, ChevronRight } from "lucide-react"; import { ArrowRight, ChevronRight } from "lucide-react";
// Plane Imports // Plane Imports
import { CYCLE_STATUS, CYCLE_UPDATED, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; import { CYCLE_TRACKER_EVENTS, CYCLE_STATUS, EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { ICycle } from "@plane/types"; import { ICycle } from "@plane/types";
import { setToast, TOAST_TYPE } from "@plane/ui"; import { setToast, TOAST_TYPE } from "@plane/ui";
@ -67,7 +67,7 @@ export const CycleSidebarHeader: FC<Props> = observer((props) => {
await updateCycleDetails(workspaceSlug.toString(), projectId.toString(), cycleDetails.id.toString(), data) await updateCycleDetails(workspaceSlug.toString(), projectId.toString(), cycleDetails.id.toString(), data)
.then((res) => { .then((res) => {
captureCycleEvent({ captureCycleEvent({
eventName: CYCLE_UPDATED, eventName: CYCLE_TRACKER_EVENTS.update,
payload: { payload: {
...res, ...res,
changed_properties: [changedProperty], changed_properties: [changedProperty],
@ -79,7 +79,7 @@ export const CycleSidebarHeader: FC<Props> = observer((props) => {
.catch(() => { .catch(() => {
captureCycleEvent({ captureCycleEvent({
eventName: CYCLE_UPDATED, eventName: CYCLE_TRACKER_EVENTS.update,
payload: { payload: {
...data, ...data,
element: "Right side-peek", element: "Right side-peek",

View file

@ -4,7 +4,7 @@ import { useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useParams, useSearchParams } from "next/navigation"; import { useParams, useSearchParams } from "next/navigation";
// types // types
import { PROJECT_ERROR_MESSAGES, CYCLE_DELETED } from "@plane/constants"; import { PROJECT_ERROR_MESSAGES, CYCLE_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { ICycle } from "@plane/types"; import { ICycle } from "@plane/types";
// ui // ui
@ -50,7 +50,7 @@ export const CycleDeleteModal: React.FC<ICycleDelete> = observer((props) => {
message: "Cycle deleted successfully.", message: "Cycle deleted successfully.",
}); });
captureCycleEvent({ captureCycleEvent({
eventName: CYCLE_DELETED, eventName: CYCLE_TRACKER_EVENTS.delete,
payload: { ...cycle, state: "SUCCESS" }, payload: { ...cycle, state: "SUCCESS" },
}); });
}) })
@ -65,7 +65,7 @@ export const CycleDeleteModal: React.FC<ICycleDelete> = observer((props) => {
message: currentError.i18n_message && t(currentError.i18n_message), message: currentError.i18n_message && t(currentError.i18n_message),
}); });
captureCycleEvent({ captureCycleEvent({
eventName: CYCLE_DELETED, eventName: CYCLE_TRACKER_EVENTS.delete,
payload: { ...cycle, state: "FAILED" }, payload: { ...cycle, state: "FAILED" },
}); });
}) })

View file

@ -6,13 +6,7 @@ import { useParams, usePathname, useSearchParams } from "next/navigation";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { Eye, Users, ArrowRight, CalendarDays } from "lucide-react"; import { Eye, Users, ArrowRight, CalendarDays } from "lucide-react";
// types // types
import { import { CYCLE_TRACKER_EVENTS, EUserPermissions, EUserPermissionsLevel, IS_FAVORITE_MENU_OPEN } from "@plane/constants";
CYCLE_FAVORITED,
CYCLE_UNFAVORITED,
EUserPermissions,
EUserPermissionsLevel,
IS_FAVORITE_MENU_OPEN,
} from "@plane/constants";
import { useLocalStorage } from "@plane/hooks"; import { useLocalStorage } from "@plane/hooks";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { ICycle, TCycleGroups } from "@plane/types"; import { ICycle, TCycleGroups } from "@plane/types";
@ -62,7 +56,7 @@ export const CycleListItemAction: FC<Props> = observer((props) => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const pathname = usePathname(); const pathname = usePathname();
// store hooks // store hooks
const { addCycleToFavorites, removeCycleFromFavorites, updateCycleDetails } = useCycle(); const { addCycleToFavorites, removeCycleFromFavorites } = useCycle();
const { captureEvent } = useEventTracker(); const { captureEvent } = useEventTracker();
const { allowPermissions } = useUserPermissions(); const { allowPermissions } = useUserPermissions();
@ -75,7 +69,7 @@ export const CycleListItemAction: FC<Props> = observer((props) => {
const { getUserDetails } = useMember(); const { getUserDetails } = useMember();
// form // form
const { control, reset, getValues } = useForm({ const { reset } = useForm({
defaultValues, defaultValues,
}); });
@ -107,7 +101,7 @@ export const CycleListItemAction: FC<Props> = observer((props) => {
const addToFavoritePromise = addCycleToFavorites(workspaceSlug?.toString(), projectId.toString(), cycleId).then( const addToFavoritePromise = addCycleToFavorites(workspaceSlug?.toString(), projectId.toString(), cycleId).then(
() => { () => {
if (!isFavoriteMenuOpen) toggleFavoriteMenu(true); if (!isFavoriteMenuOpen) toggleFavoriteMenu(true);
captureEvent(CYCLE_FAVORITED, { captureEvent(CYCLE_TRACKER_EVENTS.favorite, {
cycle_id: cycleId, cycle_id: cycleId,
element: "List layout", element: "List layout",
state: "SUCCESS", state: "SUCCESS",
@ -137,7 +131,7 @@ export const CycleListItemAction: FC<Props> = observer((props) => {
projectId.toString(), projectId.toString(),
cycleId cycleId
).then(() => { ).then(() => {
captureEvent(CYCLE_UNFAVORITED, { captureEvent(CYCLE_TRACKER_EVENTS.unfavorite, {
cycle_id: cycleId, cycle_id: cycleId,
element: "List layout", element: "List layout",
state: "SUCCESS", state: "SUCCESS",

View file

@ -4,7 +4,7 @@ import React, { useEffect, useState } from "react";
import { format } from "date-fns"; import { format } from "date-fns";
import { mutate } from "swr"; import { mutate } from "swr";
// types // types
import { CYCLE_CREATED, CYCLE_UPDATED } from "@plane/constants"; import { CYCLE_TRACKER_EVENTS } from "@plane/constants";
import type { CycleDateCheckData, ICycle, TCycleTabOptions } from "@plane/types"; import type { CycleDateCheckData, ICycle, TCycleTabOptions } from "@plane/types";
// ui // ui
import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@plane/ui"; import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@plane/ui";
@ -64,7 +64,7 @@ export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
message: "Cycle created successfully.", message: "Cycle created successfully.",
}); });
captureCycleEvent({ captureCycleEvent({
eventName: CYCLE_CREATED, eventName: CYCLE_TRACKER_EVENTS.create,
payload: { ...res, state: "SUCCESS" }, payload: { ...res, state: "SUCCESS" },
}); });
}) })
@ -75,7 +75,7 @@ export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
message: err?.detail ?? "Error in creating cycle. Please try again.", message: err?.detail ?? "Error in creating cycle. Please try again.",
}); });
captureCycleEvent({ captureCycleEvent({
eventName: CYCLE_CREATED, eventName: CYCLE_TRACKER_EVENTS.create,
payload: { ...payload, state: "FAILED" }, payload: { ...payload, state: "FAILED" },
}); });
}); });
@ -89,7 +89,7 @@ export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
.then((res) => { .then((res) => {
const changed_properties = Object.keys(dirtyFields); const changed_properties = Object.keys(dirtyFields);
captureCycleEvent({ captureCycleEvent({
eventName: CYCLE_UPDATED, eventName: CYCLE_TRACKER_EVENTS.update,
payload: { ...res, changed_properties: changed_properties, state: "SUCCESS" }, payload: { ...res, changed_properties: changed_properties, state: "SUCCESS" },
}); });
setToast({ setToast({
@ -100,7 +100,7 @@ export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
}) })
.catch((err) => { .catch((err) => {
captureCycleEvent({ captureCycleEvent({
eventName: CYCLE_UPDATED, eventName: CYCLE_TRACKER_EVENTS.update,
payload: { ...payload, state: "FAILED" }, payload: { ...payload, state: "FAILED" },
}); });
setToast({ setToast({

View file

@ -2,7 +2,7 @@ import { observer } from "mobx-react";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
// components // components
import useSWR from "swr"; import useSWR from "swr";
import { PRODUCT_TOUR_COMPLETED } from "@plane/constants"; import { PRODUCT_TOUR_TRACKER_EVENTS } from "@plane/constants";
import { ContentWrapper } from "@plane/ui"; import { ContentWrapper } from "@plane/ui";
import { cn } from "@plane/utils"; import { cn } from "@plane/utils";
import { TourRoot } from "@/components/onboarding"; import { TourRoot } from "@/components/onboarding";
@ -38,7 +38,7 @@ export const WorkspaceHomeView = observer(() => {
const handleTourCompleted = () => { const handleTourCompleted = () => {
updateTourCompleted() updateTourCompleted()
.then(() => { .then(() => {
captureEvent(PRODUCT_TOUR_COMPLETED, { captureEvent(PRODUCT_TOUR_TRACKER_EVENTS.complete, {
user_id: currentUser?.id, user_id: currentUser?.id,
state: "SUCCESS", state: "SUCCESS",
}); });

View file

@ -4,7 +4,7 @@ import { Dispatch, SetStateAction, useEffect, useMemo, useRef } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
// plane imports // plane imports
import { EInboxIssueSource, ISSUE_ARCHIVED, ISSUE_DELETED } from "@plane/constants"; import { EInboxIssueSource, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants";
import { EditorRefApi } from "@plane/editor"; import { EditorRefApi } from "@plane/editor";
import { TIssue, TNameDescriptionLoader } from "@plane/types"; import { TIssue, TNameDescriptionLoader } from "@plane/types";
import { Loader, TOAST_TYPE, setToast } from "@plane/ui"; import { Loader, TOAST_TYPE, setToast } from "@plane/ui";
@ -105,7 +105,7 @@ export const InboxIssueMainContent: React.FC<Props> = observer((props) => {
message: "Work item deleted successfully", message: "Work item deleted successfully",
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_DELETED, eventName: WORK_ITEM_TRACKER_EVENTS.delete,
payload: { id: _issueId, state: "SUCCESS", element: "Work item detail page" }, payload: { id: _issueId, state: "SUCCESS", element: "Work item detail page" },
path: pathname, path: pathname,
}); });
@ -117,7 +117,7 @@ export const InboxIssueMainContent: React.FC<Props> = observer((props) => {
message: "Work item delete failed", message: "Work item delete failed",
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_DELETED, eventName: WORK_ITEM_TRACKER_EVENTS.delete,
payload: { id: _issueId, state: "FAILED", element: "Work item detail page" }, payload: { id: _issueId, state: "FAILED", element: "Work item detail page" },
path: pathname, path: pathname,
}); });
@ -156,14 +156,14 @@ export const InboxIssueMainContent: React.FC<Props> = observer((props) => {
try { try {
await archiveIssue(workspaceSlug, projectId, issueId); await archiveIssue(workspaceSlug, projectId, issueId);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_ARCHIVED, eventName: WORK_ITEM_TRACKER_EVENTS.archive,
payload: { id: issueId, state: "SUCCESS", element: "Work item details page" }, payload: { id: issueId, state: "SUCCESS", element: "Work item details page" },
path: pathname, path: pathname,
}); });
} catch (error) { } catch (error) {
console.log("Error in archiving issue:", error); console.log("Error in archiving issue:", error);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_ARCHIVED, eventName: WORK_ITEM_TRACKER_EVENTS.archive,
payload: { id: issueId, state: "FAILED", element: "Work item details page" }, payload: { id: issueId, state: "FAILED", element: "Work item details page" },
path: pathname, path: pathname,
}); });

View file

@ -4,7 +4,7 @@ import { FC, FormEvent, useCallback, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
// plane imports // plane imports
import { ETabIndices, ISSUE_CREATED } from "@plane/constants"; import { ETabIndices, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants";
import { EditorRefApi } from "@plane/editor"; import { EditorRefApi } from "@plane/editor";
// types // types
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
@ -168,7 +168,7 @@ export const InboxIssueCreateRoot: FC<TInboxIssueCreateRoot> = observer((props)
setFormData(defaultIssueData); setFormData(defaultIssueData);
} }
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_CREATED, eventName: WORK_ITEM_TRACKER_EVENTS.create,
payload: { payload: {
...formData, ...formData,
state: "SUCCESS", state: "SUCCESS",
@ -185,7 +185,7 @@ export const InboxIssueCreateRoot: FC<TInboxIssueCreateRoot> = observer((props)
.catch((error) => { .catch((error) => {
console.error(error); console.error(error);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_CREATED, eventName: WORK_ITEM_TRACKER_EVENTS.create,
payload: { payload: {
...formData, ...formData,
state: "FAILED", state: "FAILED",

View file

@ -2,7 +2,7 @@
import { useMemo } from "react"; import { useMemo } from "react";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
// plane imports // plane imports
import { EIssueServiceType, ISSUE_DELETED, ISSUE_UPDATED } from "@plane/constants"; import { EIssueServiceType, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { TIssue, TIssueServiceType } from "@plane/types"; import { TIssue, TIssueServiceType } from "@plane/types";
import { TOAST_TYPE, setToast } from "@plane/ui"; import { TOAST_TYPE, setToast } from "@plane/ui";
@ -41,7 +41,7 @@ export const useRelationOperations = (
try { try {
await updateIssue(workspaceSlug, projectId, issueId, data); await updateIssue(workspaceSlug, projectId, issueId, data);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...data, issueId, state: "SUCCESS", element: "Issue detail page" }, payload: { ...data, issueId, state: "SUCCESS", element: "Issue detail page" },
updates: { updates: {
changed_property: Object.keys(data).join(","), changed_property: Object.keys(data).join(","),
@ -56,7 +56,7 @@ export const useRelationOperations = (
}); });
} catch { } catch {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { state: "FAILED", element: "Issue detail page" }, payload: { state: "FAILED", element: "Issue detail page" },
updates: { updates: {
changed_property: Object.keys(data).join(","), changed_property: Object.keys(data).join(","),
@ -75,14 +75,14 @@ export const useRelationOperations = (
try { try {
return removeIssue(workspaceSlug, projectId, issueId).then(() => { return removeIssue(workspaceSlug, projectId, issueId).then(() => {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_DELETED, eventName: WORK_ITEM_TRACKER_EVENTS.delete,
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
path: pathname, path: pathname,
}); });
}); });
} catch { } catch {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_DELETED, eventName: WORK_ITEM_TRACKER_EVENTS.delete,
payload: { id: issueId, state: "FAILED", element: "Issue detail page" }, payload: { id: issueId, state: "FAILED", element: "Issue detail page" },
path: pathname, path: pathname,
}); });

View file

@ -5,12 +5,11 @@ import { observer } from "mobx-react";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { ArchiveIcon, ArchiveRestoreIcon, LinkIcon, Trash2 } from "lucide-react"; import { ArchiveIcon, ArchiveRestoreIcon, LinkIcon, Trash2 } from "lucide-react";
import { import {
ISSUE_ARCHIVED,
ISSUE_DELETED,
ARCHIVABLE_STATE_GROUPS, ARCHIVABLE_STATE_GROUPS,
EIssuesStoreType, EIssuesStoreType,
EUserPermissions, EUserPermissions,
EUserPermissionsLevel, EUserPermissionsLevel,
WORK_ITEM_TRACKER_EVENTS,
} from "@plane/constants"; } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { TOAST_TYPE, Tooltip, setToast } from "@plane/ui"; import { TOAST_TYPE, Tooltip, setToast } from "@plane/ui";
@ -105,19 +104,19 @@ export const IssueDetailQuickActions: FC<Props> = observer((props) => {
return deleteIssue(workspaceSlug, projectId, issueId).then(() => { return deleteIssue(workspaceSlug, projectId, issueId).then(() => {
router.push(redirectionPath); router.push(redirectionPath);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_DELETED, eventName: WORK_ITEM_TRACKER_EVENTS.delete,
payload: { id: issueId, state: "SUCCESS", element: "Work item detail page" }, payload: { id: issueId, state: "SUCCESS", element: "Work item detail page" },
path: pathname, path: pathname,
}); });
}); });
} catch (error) { } catch {
setToast({ setToast({
title: t("toast.error "), title: t("toast.error "),
type: TOAST_TYPE.ERROR, type: TOAST_TYPE.ERROR,
message: t("entity.delete.failed", { entity: t("issue.label", { count: 1 }) }), message: t("entity.delete.failed", { entity: t("issue.label", { count: 1 }) }),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_DELETED, eventName: WORK_ITEM_TRACKER_EVENTS.delete,
payload: { id: issueId, state: "FAILED", element: "Work item detail page" }, payload: { id: issueId, state: "FAILED", element: "Work item detail page" },
path: pathname, path: pathname,
}); });
@ -130,13 +129,13 @@ export const IssueDetailQuickActions: FC<Props> = observer((props) => {
router.push(`/${workspaceSlug}/projects/${projectId}/archives/issues/${issue.id}`); router.push(`/${workspaceSlug}/projects/${projectId}/archives/issues/${issue.id}`);
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_ARCHIVED, eventName: WORK_ITEM_TRACKER_EVENTS.archive,
payload: { id: issueId, state: "SUCCESS", element: "Issue details page" }, payload: { id: issueId, state: "SUCCESS", element: "Issue details page" },
path: pathname, path: pathname,
}); });
} catch (error) { } catch {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_ARCHIVED, eventName: WORK_ITEM_TRACKER_EVENTS.archive,
payload: { id: issueId, state: "FAILED", element: "Issue details page" }, payload: { id: issueId, state: "FAILED", element: "Issue details page" },
path: pathname, path: pathname,
}); });

View file

@ -4,14 +4,7 @@ import { FC, useMemo } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
// types // types
import { import { EIssuesStoreType, EUserPermissions, EUserPermissionsLevel, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants";
EIssuesStoreType,
ISSUE_UPDATED,
ISSUE_DELETED,
ISSUE_ARCHIVED,
EUserPermissions,
EUserPermissionsLevel,
} from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { TIssue } from "@plane/types"; import { TIssue } from "@plane/types";
// ui // ui
@ -98,7 +91,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
try { try {
await updateIssue(workspaceSlug, projectId, issueId, data); await updateIssue(workspaceSlug, projectId, issueId, data);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...data, issueId, state: "SUCCESS", element: "Issue detail page" }, payload: { ...data, issueId, state: "SUCCESS", element: "Issue detail page" },
updates: { updates: {
changed_property: Object.keys(data).join(","), changed_property: Object.keys(data).join(","),
@ -109,7 +102,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
} catch (error) { } catch (error) {
console.log("Error in updating issue:", error); console.log("Error in updating issue:", error);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { state: "FAILED", element: "Issue detail page" }, payload: { state: "FAILED", element: "Issue detail page" },
updates: { updates: {
changed_property: Object.keys(data).join(","), changed_property: Object.keys(data).join(","),
@ -134,7 +127,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
message: t("entity.delete.success", { entity: t("issue.label") }), message: t("entity.delete.success", { entity: t("issue.label") }),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_DELETED, eventName: WORK_ITEM_TRACKER_EVENTS.delete,
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
path: pathname, path: pathname,
}); });
@ -146,7 +139,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
message: t("entity.delete.failed", { entity: t("issue.label") }), message: t("entity.delete.failed", { entity: t("issue.label") }),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_DELETED, eventName: WORK_ITEM_TRACKER_EVENTS.delete,
payload: { id: issueId, state: "FAILED", element: "Issue detail page" }, payload: { id: issueId, state: "FAILED", element: "Issue detail page" },
path: pathname, path: pathname,
}); });
@ -156,14 +149,14 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
try { try {
await archiveIssue(workspaceSlug, projectId, issueId); await archiveIssue(workspaceSlug, projectId, issueId);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_ARCHIVED, eventName: WORK_ITEM_TRACKER_EVENTS.archive,
payload: { id: issueId, state: "SUCCESS", element: "Issue details page" }, payload: { id: issueId, state: "SUCCESS", element: "Issue details page" },
path: pathname, path: pathname,
}); });
} catch (error) { } catch (error) {
console.log("Error in archiving issue:", error); console.log("Error in archiving issue:", error);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_ARCHIVED, eventName: WORK_ITEM_TRACKER_EVENTS.archive,
payload: { id: issueId, state: "FAILED", element: "Issue details page" }, payload: { id: issueId, state: "FAILED", element: "Issue details page" },
path: pathname, path: pathname,
}); });
@ -173,7 +166,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
try { try {
await addCycleToIssue(workspaceSlug, projectId, cycleId, issueId); await addCycleToIssue(workspaceSlug, projectId, cycleId, issueId);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { issueId, state: "SUCCESS", element: "Issue detail page" }, payload: { issueId, state: "SUCCESS", element: "Issue detail page" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
@ -181,14 +174,14 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
}, },
path: pathname, path: pathname,
}); });
} catch (error) { } catch {
setToast({ setToast({
type: TOAST_TYPE.ERROR, type: TOAST_TYPE.ERROR,
title: t("common.error.label"), title: t("common.error.label"),
message: t("issue.add.cycle.failed"), message: t("issue.add.cycle.failed"),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { state: "FAILED", element: "Issue detail page" }, payload: { state: "FAILED", element: "Issue detail page" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
@ -202,7 +195,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
try { try {
await addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds); await addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issueIds, state: "SUCCESS", element: "Issue detail page" }, payload: { ...issueIds, state: "SUCCESS", element: "Issue detail page" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
@ -210,14 +203,14 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
}, },
path: pathname, path: pathname,
}); });
} catch (error) { } catch {
setToast({ setToast({
type: TOAST_TYPE.ERROR, type: TOAST_TYPE.ERROR,
title: t("common.error.label"), title: t("common.error.label"),
message: t("issue.add.cycle.failed"), message: t("issue.add.cycle.failed"),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { state: "FAILED", element: "Issue detail page" }, payload: { state: "FAILED", element: "Issue detail page" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
@ -243,7 +236,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
}); });
await removeFromCyclePromise; await removeFromCyclePromise;
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { issueId, state: "SUCCESS", element: "Issue detail page" }, payload: { issueId, state: "SUCCESS", element: "Issue detail page" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
@ -251,9 +244,9 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
}, },
path: pathname, path: pathname,
}); });
} catch (error) { } catch {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { state: "FAILED", element: "Issue detail page" }, payload: { state: "FAILED", element: "Issue detail page" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
@ -279,7 +272,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
}); });
await removeFromModulePromise; await removeFromModulePromise;
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
updates: { updates: {
changed_property: "module_id", changed_property: "module_id",
@ -287,9 +280,9 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
}, },
path: pathname, path: pathname,
}); });
} catch (error) { } catch {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { id: issueId, state: "FAILED", element: "Issue detail page" }, payload: { id: issueId, state: "FAILED", element: "Issue detail page" },
updates: { updates: {
changed_property: "module_id", changed_property: "module_id",
@ -308,7 +301,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
) => { ) => {
const promise = await changeModulesInIssue(workspaceSlug, projectId, issueId, addModuleIds, removeModuleIds); const promise = await changeModulesInIssue(workspaceSlug, projectId, issueId, addModuleIds, removeModuleIds);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
updates: { updates: {
changed_property: "module_id", changed_property: "module_id",
@ -333,6 +326,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
removeIssueFromModule, removeIssueFromModule,
captureIssueEvent, captureIssueEvent,
pathname, pathname,
t,
] ]
); );

View file

@ -11,8 +11,10 @@ import {
EIssueFilterType, EIssueFilterType,
EIssuesStoreType, EIssuesStoreType,
EViewAccess, EViewAccess,
GLOBAL_VIEW_UPDATED, EUserPermissions,
EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; EUserPermissionsLevel,
GLOBAL_VIEW_TOUR_TRACKER_EVENTS,
} from "@plane/constants";
import { IIssueFilterOptions, TStaticViewTypes } from "@plane/types"; import { IIssueFilterOptions, TStaticViewTypes } from "@plane/types";
//ui //ui
// components // components
@ -112,7 +114,7 @@ export const GlobalViewsAppliedFiltersRoot = observer((props: Props) => {
updateGlobalView(workspaceSlug.toString(), globalViewId.toString(), viewFilters).then((res) => { updateGlobalView(workspaceSlug.toString(), globalViewId.toString(), viewFilters).then((res) => {
if (res) if (res)
captureEvent(GLOBAL_VIEW_UPDATED, { captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.update, {
view_id: res.id, view_id: res.id,
applied_filters: res.filters, applied_filters: res.filters,
state: "SUCCESS", state: "SUCCESS",

View file

@ -11,9 +11,9 @@ import {
EIssueServiceType, EIssueServiceType,
EIssueFilterType, EIssueFilterType,
EIssuesStoreType, EIssuesStoreType,
ISSUE_DELETED,
EUserPermissions, EUserPermissions,
EUserPermissionsLevel, EUserPermissionsLevel,
WORK_ITEM_TRACKER_EVENTS,
} from "@plane/constants"; } from "@plane/constants";
import { DeleteIssueModal } from "@/components/issues"; import { DeleteIssueModal } from "@/components/issues";
//constants //constants
@ -152,7 +152,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
element, element,
}) })
); );
}, [scrollableContainerRef?.current]); }, []);
// Make the Issue Delete Box a Drop Target // Make the Issue Delete Box a Drop Target
useEffect(() => { useEffect(() => {
@ -181,7 +181,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
}, },
}) })
); );
}, [deleteAreaRef?.current, setIsDragOverDelete, setDraggedIssueId, setDeleteIssueModal]); }, [setIsDragOverDelete, setDraggedIssueId, setDeleteIssueModal]);
const renderQuickActions: TRenderQuickActions = useCallback( const renderQuickActions: TRenderQuickActions = useCallback(
({ issue, parentRef, customActionButton }) => ( ({ issue, parentRef, customActionButton }) => (
@ -210,7 +210,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
setDeleteIssueModal(false); setDeleteIssueModal(false);
setDraggedIssueId(undefined); setDraggedIssueId(undefined);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_DELETED, eventName: WORK_ITEM_TRACKER_EVENTS.delete,
payload: { id: draggedIssueId, state: "FAILED", element: "Kanban layout drag & drop" }, payload: { id: draggedIssueId, state: "FAILED", element: "Kanban layout drag & drop" },
path: pathname, path: pathname,
}); });

View file

@ -7,13 +7,19 @@ import { useParams, usePathname } from "next/navigation";
// icons // icons
import { Layers, Link, Paperclip } from "lucide-react"; import { Layers, Link, Paperclip } from "lucide-react";
// types // types
import { ISSUE_UPDATED } from "@plane/constants"; import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants";
// i18n // i18n
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { TIssue, IIssueDisplayProperties, TIssuePriorities } from "@plane/types"; import { TIssue, IIssueDisplayProperties, TIssuePriorities } from "@plane/types";
// ui // ui
import { Tooltip } from "@plane/ui"; import { Tooltip } from "@plane/ui";
import { cn, getDate, renderFormattedPayloadDate, generateWorkItemLink, shouldHighlightIssueDueDate } from "@plane/utils"; import {
cn,
getDate,
renderFormattedPayloadDate,
generateWorkItemLink,
shouldHighlightIssueDueDate,
} from "@plane/utils";
// components // components
import { import {
EstimateDropdown, EstimateDropdown,
@ -103,7 +109,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (updateIssue) if (updateIssue)
updateIssue(issue.project_id, issue.id, { state_id: stateId }).then(() => { updateIssue(issue.project_id, issue.id, { state_id: stateId }).then(() => {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout }, payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname, path: pathname,
updates: { updates: {
@ -118,7 +124,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (updateIssue) if (updateIssue)
updateIssue(issue.project_id, issue.id, { priority: value }).then(() => { updateIssue(issue.project_id, issue.id, { priority: value }).then(() => {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout }, payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname, path: pathname,
updates: { updates: {
@ -133,7 +139,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (updateIssue) if (updateIssue)
updateIssue(issue.project_id, issue.id, { label_ids: ids }).then(() => { updateIssue(issue.project_id, issue.id, { label_ids: ids }).then(() => {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout }, payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname, path: pathname,
updates: { updates: {
@ -148,7 +154,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (updateIssue) if (updateIssue)
updateIssue(issue.project_id, issue.id, { assignee_ids: ids }).then(() => { updateIssue(issue.project_id, issue.id, { assignee_ids: ids }).then(() => {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout }, payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname, path: pathname,
updates: { updates: {
@ -173,7 +179,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (modulesToRemove.length > 0) issueOperations.removeModulesFromIssue(modulesToRemove); if (modulesToRemove.length > 0) issueOperations.removeModulesFromIssue(modulesToRemove);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout }, payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname, path: pathname,
updates: { changed_property: "module_ids", change_details: { module_ids: moduleIds } }, updates: { changed_property: "module_ids", change_details: { module_ids: moduleIds } },
@ -189,7 +195,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
else issueOperations.removeIssueFromCycle?.(); else issueOperations.removeIssueFromCycle?.();
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout }, payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname, path: pathname,
updates: { changed_property: "cycle", change_details: { cycle_id: cycleId } }, updates: { changed_property: "cycle", change_details: { cycle_id: cycleId } },
@ -203,7 +209,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
updateIssue(issue.project_id, issue.id, { start_date: date ? renderFormattedPayloadDate(date) : null }).then( updateIssue(issue.project_id, issue.id, { start_date: date ? renderFormattedPayloadDate(date) : null }).then(
() => { () => {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout }, payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname, path: pathname,
updates: { updates: {
@ -220,7 +226,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
updateIssue(issue.project_id, issue.id, { target_date: date ? renderFormattedPayloadDate(date) : null }).then( updateIssue(issue.project_id, issue.id, { target_date: date ? renderFormattedPayloadDate(date) : null }).then(
() => { () => {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout }, payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname, path: pathname,
updates: { updates: {
@ -236,7 +242,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (updateIssue) if (updateIssue)
updateIssue(issue.project_id, issue.id, { estimate_point: value }).then(() => { updateIssue(issue.project_id, issue.id, { estimate_point: value }).then(() => {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout }, payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname, path: pathname,
updates: { updates: {

View file

@ -6,7 +6,7 @@ import { useParams, usePathname } from "next/navigation";
import { useForm, UseFormRegister } from "react-hook-form"; import { useForm, UseFormRegister } from "react-hook-form";
import { PlusIcon } from "lucide-react"; import { PlusIcon } from "lucide-react";
// plane constants // plane constants
import { EIssueLayoutTypes, EIssueServiceType, ISSUE_CREATED } from "@plane/constants"; import { EIssueLayoutTypes, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants";
// i18n // i18n
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { IProject, TIssue } from "@plane/types"; import { IProject, TIssue } from "@plane/types";
@ -137,14 +137,14 @@ export const QuickAddIssueRoot: FC<TQuickAddIssueRoot> = observer((props) => {
await quickAddPromise await quickAddPromise
.then((res) => { .then((res) => {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_CREATED, eventName: WORK_ITEM_TRACKER_EVENTS.create,
payload: { ...res, state: "SUCCESS", element: ` ${layout} quick add` }, payload: { ...res, state: "SUCCESS", element: ` ${layout} quick add` },
path: pathname, path: pathname,
}); });
}) })
.catch(() => { .catch(() => {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_CREATED, eventName: WORK_ITEM_TRACKER_EVENTS.create,
payload: { ...payload, state: "FAILED", element: `${layout} quick ad` }, payload: { ...payload, state: "FAILED", element: `${layout} quick ad` },
path: pathname, path: pathname,
}); });

View file

@ -3,7 +3,7 @@
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useParams, usePathname } from "next/navigation"; import { useParams, usePathname } from "next/navigation";
import { EIssuesStoreType, ISSUE_CREATED, ISSUE_UPDATED } from "@plane/constants"; import { EIssuesStoreType, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
// types // types
import type { TBaseIssue, TIssue } from "@plane/types"; import type { TBaseIssue, TIssue } from "@plane/types";
@ -241,7 +241,7 @@ export const CreateUpdateIssueModalBase: React.FC<IssuesModalProps> = observer((
), ),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_CREATED, eventName: WORK_ITEM_TRACKER_EVENTS.create,
payload: { ...response, state: "SUCCESS" }, payload: { ...response, state: "SUCCESS" },
path: pathname, path: pathname,
}); });
@ -257,7 +257,7 @@ export const CreateUpdateIssueModalBase: React.FC<IssuesModalProps> = observer((
message: error?.error ?? t(is_draft_issue ? "draft_creation_failed" : "issue_creation_failed"), message: error?.error ?? t(is_draft_issue ? "draft_creation_failed" : "issue_creation_failed"),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_CREATED, eventName: WORK_ITEM_TRACKER_EVENTS.create,
payload: { ...payload, state: "FAILED" }, payload: { ...payload, state: "FAILED" },
path: pathname, path: pathname,
}); });
@ -303,7 +303,7 @@ export const CreateUpdateIssueModalBase: React.FC<IssuesModalProps> = observer((
message: t("issue_updated_successfully"), message: t("issue_updated_successfully"),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...payload, issueId: data.id, state: "SUCCESS" }, payload: { ...payload, issueId: data.id, state: "SUCCESS" },
path: pathname, path: pathname,
}); });
@ -316,7 +316,7 @@ export const CreateUpdateIssueModalBase: React.FC<IssuesModalProps> = observer((
message: error?.error ?? t("issue_could_not_be_updated"), message: error?.error ?? t("issue_could_not_be_updated"),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...payload, state: "FAILED" }, payload: { ...payload, state: "FAILED" },
path: pathname, path: pathname,
}); });
@ -334,8 +334,6 @@ export const CreateUpdateIssueModalBase: React.FC<IssuesModalProps> = observer((
if (beforeFormSubmit) await beforeFormSubmit(); if (beforeFormSubmit) await beforeFormSubmit();
if (!data?.id) response = await handleCreateIssue(payload, is_draft_issue); if (!data?.id) response = await handleCreateIssue(payload, is_draft_issue);
else response = await handleUpdateIssue(payload); else response = await handleUpdateIssue(payload);
} catch (error) {
throw error;
} finally { } finally {
if (response != undefined && onSubmit) await onSubmit(response); if (response != undefined && onSubmit) await onSubmit(response);
} }

View file

@ -6,13 +6,10 @@ import { usePathname } from "next/navigation";
// plane types // plane types
import { import {
EIssuesStoreType, EIssuesStoreType,
ISSUE_UPDATED,
ISSUE_DELETED,
ISSUE_ARCHIVED,
ISSUE_RESTORED,
EUserPermissions, EUserPermissions,
EUserPermissionsLevel, EUserPermissionsLevel,
EIssueServiceType, EIssueServiceType,
WORK_ITEM_TRACKER_EVENTS,
} from "@plane/constants"; } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { TIssue, IWorkItemPeekOverview } from "@plane/types"; import { TIssue, IWorkItemPeekOverview } from "@plane/types";
@ -26,7 +23,6 @@ import { useEventTracker, useIssueDetail, useIssues, useUserPermissions } from "
import { useIssueStoreType } from "@/hooks/use-issue-layout-store"; import { useIssueStoreType } from "@/hooks/use-issue-layout-store";
import { useWorkItemProperties } from "@/plane-web/hooks/use-issue-properties"; import { useWorkItemProperties } from "@/plane-web/hooks/use-issue-properties";
export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) => { export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) => {
const { const {
embedIssue = false, embedIssue = false,
@ -86,7 +82,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
.then(async () => { .then(async () => {
fetchActivities(workspaceSlug, projectId, issueId); fetchActivities(workspaceSlug, projectId, issueId);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...data, issueId, state: "SUCCESS", element: "Issue peek-overview" }, payload: { ...data, issueId, state: "SUCCESS", element: "Issue peek-overview" },
updates: { updates: {
changed_property: Object.keys(data).join(","), changed_property: Object.keys(data).join(","),
@ -97,7 +93,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
}) })
.catch(() => { .catch(() => {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { state: "FAILED", element: "Issue peek-overview" }, payload: { state: "FAILED", element: "Issue peek-overview" },
path: pathname, path: pathname,
}); });
@ -113,7 +109,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
try { try {
return issues?.removeIssue(workspaceSlug, projectId, issueId).then(() => { return issues?.removeIssue(workspaceSlug, projectId, issueId).then(() => {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_DELETED, eventName: WORK_ITEM_TRACKER_EVENTS.delete,
payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" }, payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" },
path: pathname, path: pathname,
}); });
@ -126,7 +122,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
message: t("entity.delete.failed", { entity: t("issue.label", { count: 1 }) }), message: t("entity.delete.failed", { entity: t("issue.label", { count: 1 }) }),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_DELETED, eventName: WORK_ITEM_TRACKER_EVENTS.delete,
payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" }, payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" },
path: pathname, path: pathname,
}); });
@ -137,13 +133,13 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
if (!issues?.archiveIssue) return; if (!issues?.archiveIssue) return;
await issues.archiveIssue(workspaceSlug, projectId, issueId); await issues.archiveIssue(workspaceSlug, projectId, issueId);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_ARCHIVED, eventName: WORK_ITEM_TRACKER_EVENTS.archive,
payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" }, payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" },
path: pathname, path: pathname,
}); });
} catch { } catch {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_ARCHIVED, eventName: WORK_ITEM_TRACKER_EVENTS.archive,
payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" }, payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" },
path: pathname, path: pathname,
}); });
@ -158,7 +154,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
message: t("issue.restore.success.message"), message: t("issue.restore.success.message"),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_RESTORED, eventName: WORK_ITEM_TRACKER_EVENTS.restore,
payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" }, payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" },
path: pathname, path: pathname,
}); });
@ -169,7 +165,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
message: t("issue.restore.failed.message"), message: t("issue.restore.failed.message"),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_RESTORED, eventName: WORK_ITEM_TRACKER_EVENTS.restore,
payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" }, payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" },
path: pathname, path: pathname,
}); });
@ -180,7 +176,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
await issues.addCycleToIssue(workspaceSlug, projectId, cycleId, issueId); await issues.addCycleToIssue(workspaceSlug, projectId, cycleId, issueId);
fetchActivities(workspaceSlug, projectId, issueId); fetchActivities(workspaceSlug, projectId, issueId);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { issueId, state: "SUCCESS", element: "Issue peek-overview" }, payload: { issueId, state: "SUCCESS", element: "Issue peek-overview" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
@ -195,7 +191,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
message: t("issue.add.cycle.failed"), message: t("issue.add.cycle.failed"),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { state: "FAILED", element: "Issue peek-overview" }, payload: { state: "FAILED", element: "Issue peek-overview" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
@ -209,7 +205,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
try { try {
await issues.addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds); await issues.addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issueIds, state: "SUCCESS", element: "Issue peek-overview" }, payload: { ...issueIds, state: "SUCCESS", element: "Issue peek-overview" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
@ -224,7 +220,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
message: t("issue.add.cycle.failed"), message: t("issue.add.cycle.failed"),
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { state: "FAILED", element: "Issue peek-overview" }, payload: { state: "FAILED", element: "Issue peek-overview" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
@ -251,7 +247,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
await removeFromCyclePromise; await removeFromCyclePromise;
fetchActivities(workspaceSlug, projectId, issueId); fetchActivities(workspaceSlug, projectId, issueId);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { issueId, state: "SUCCESS", element: "Issue peek-overview" }, payload: { issueId, state: "SUCCESS", element: "Issue peek-overview" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
@ -261,7 +257,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
}); });
} catch { } catch {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { state: "FAILED", element: "Issue peek-overview" }, payload: { state: "FAILED", element: "Issue peek-overview" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
@ -287,7 +283,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
); );
fetchActivities(workspaceSlug, projectId, issueId); fetchActivities(workspaceSlug, projectId, issueId);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
updates: { updates: {
changed_property: "module_id", changed_property: "module_id",
@ -314,7 +310,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
await removeFromModulePromise; await removeFromModulePromise;
fetchActivities(workspaceSlug, projectId, issueId); fetchActivities(workspaceSlug, projectId, issueId);
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" }, payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" },
updates: { updates: {
changed_property: "module_id", changed_property: "module_id",
@ -324,7 +320,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
}); });
} catch { } catch {
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" }, payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" },
updates: { updates: {
changed_property: "module_id", changed_property: "module_id",
@ -335,7 +331,7 @@ export const IssuePeekOverview: FC<IWorkItemPeekOverview> = observer((props) =>
} }
}, },
}), }),
[fetchIssue, is_draft, issues, fetchActivities, captureIssueEvent, pathname, removeRoutePeekId, restoreIssue] [fetchIssue, is_draft, issues, fetchActivities, captureIssueEvent, pathname, removeRoutePeekId, restoreIssue, t]
); );
useEffect(() => { useEffect(() => {

View file

@ -6,7 +6,13 @@ import { useParams } from "next/navigation";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { CalendarClock, ChevronDown, ChevronRight, Info, Plus, SquareUser, Users } from "lucide-react"; import { CalendarClock, ChevronDown, ChevronRight, Info, Plus, SquareUser, Users } from "lucide-react";
import { Disclosure, Transition } from "@headlessui/react"; import { Disclosure, Transition } from "@headlessui/react";
import { MODULE_STATUS, MODULE_LINK_CREATED, MODULE_LINK_DELETED, MODULE_LINK_UPDATED, MODULE_UPDATED, EUserPermissions, EUserPermissionsLevel, EEstimateSystem } from "@plane/constants"; import {
MODULE_STATUS,
EUserPermissions,
EUserPermissionsLevel,
EEstimateSystem,
MODULE_TRACKER_EVENTS,
} from "@plane/constants";
// plane types // plane types
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { ILinkDetails, IModule, ModuleLink } from "@plane/types"; import { ILinkDetails, IModule, ModuleLink } from "@plane/types";
@ -74,13 +80,13 @@ export const ModuleAnalyticsSidebar: React.FC<Props> = observer((props) => {
updateModuleDetails(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), data) updateModuleDetails(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), data)
.then((res) => { .then((res) => {
captureModuleEvent({ captureModuleEvent({
eventName: MODULE_UPDATED, eventName: MODULE_TRACKER_EVENTS.update,
payload: { ...res, changed_properties: Object.keys(data)[0], element: "Right side-peek", state: "SUCCESS" }, payload: { ...res, changed_properties: Object.keys(data)[0], element: "Right side-peek", state: "SUCCESS" },
}); });
}) })
.catch(() => { .catch(() => {
captureModuleEvent({ captureModuleEvent({
eventName: MODULE_UPDATED, eventName: MODULE_TRACKER_EVENTS.update,
payload: { ...data, state: "FAILED" }, payload: { ...data, state: "FAILED" },
}); });
}); });
@ -92,7 +98,7 @@ export const ModuleAnalyticsSidebar: React.FC<Props> = observer((props) => {
const payload = { metadata: {}, ...formData }; const payload = { metadata: {}, ...formData };
await createModuleLink(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), payload).then(() => await createModuleLink(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), payload).then(() =>
captureEvent(MODULE_LINK_CREATED, { captureEvent(MODULE_TRACKER_EVENTS.link.create, {
module_id: moduleId, module_id: moduleId,
state: "SUCCESS", state: "SUCCESS",
}) })
@ -106,7 +112,7 @@ export const ModuleAnalyticsSidebar: React.FC<Props> = observer((props) => {
await updateModuleLink(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), linkId, payload).then( await updateModuleLink(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), linkId, payload).then(
() => () =>
captureEvent(MODULE_LINK_UPDATED, { captureEvent(MODULE_TRACKER_EVENTS.link.update, {
module_id: moduleId, module_id: moduleId,
state: "SUCCESS", state: "SUCCESS",
}) })
@ -118,7 +124,7 @@ export const ModuleAnalyticsSidebar: React.FC<Props> = observer((props) => {
deleteModuleLink(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), linkId) deleteModuleLink(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), linkId)
.then(() => { .then(() => {
captureEvent(MODULE_LINK_DELETED, { captureEvent(MODULE_TRACKER_EVENTS.link.delete, {
module_id: moduleId, module_id: moduleId,
state: "SUCCESS", state: "SUCCESS",
}); });

View file

@ -4,7 +4,7 @@ import React, { useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
// types // types
import { PROJECT_ERROR_MESSAGES, MODULE_DELETED } from "@plane/constants"; import { MODULE_TRACKER_EVENTS, PROJECT_ERROR_MESSAGES } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import type { IModule } from "@plane/types"; import type { IModule } from "@plane/types";
// ui // ui
@ -52,7 +52,7 @@ export const DeleteModuleModal: React.FC<Props> = observer((props) => {
message: "Module deleted successfully.", message: "Module deleted successfully.",
}); });
captureModuleEvent({ captureModuleEvent({
eventName: MODULE_DELETED, eventName: MODULE_TRACKER_EVENTS.delete,
payload: { ...data, state: "SUCCESS" }, payload: { ...data, state: "SUCCESS" },
}); });
}) })
@ -67,7 +67,7 @@ export const DeleteModuleModal: React.FC<Props> = observer((props) => {
message: currentError.i18n_message && t(currentError.i18n_message), message: currentError.i18n_message && t(currentError.i18n_message),
}); });
captureModuleEvent({ captureModuleEvent({
eventName: MODULE_DELETED, eventName: MODULE_TRACKER_EVENTS.delete,
payload: { ...data, state: "FAILED" }, payload: { ...data, state: "FAILED" },
}); });
}) })

View file

@ -4,7 +4,7 @@ import React, { useEffect, useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
// types // types
import { MODULE_CREATED, MODULE_UPDATED } from "@plane/constants"; import { MODULE_TRACKER_EVENTS } from "@plane/constants";
import type { IModule } from "@plane/types"; import type { IModule } from "@plane/types";
// ui // ui
import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@plane/ui"; import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@plane/ui";
@ -64,7 +64,7 @@ export const CreateUpdateModuleModal: React.FC<Props> = observer((props) => {
message: "Module created successfully.", message: "Module created successfully.",
}); });
captureModuleEvent({ captureModuleEvent({
eventName: MODULE_CREATED, eventName: MODULE_TRACKER_EVENTS.create,
payload: { ...res, state: "SUCCESS" }, payload: { ...res, state: "SUCCESS" },
}); });
}) })
@ -75,7 +75,7 @@ export const CreateUpdateModuleModal: React.FC<Props> = observer((props) => {
message: err?.detail ?? err?.error ?? "Module could not be created. Please try again.", message: err?.detail ?? err?.error ?? "Module could not be created. Please try again.",
}); });
captureModuleEvent({ captureModuleEvent({
eventName: MODULE_CREATED, eventName: MODULE_TRACKER_EVENTS.create,
payload: { ...data, state: "FAILED" }, payload: { ...data, state: "FAILED" },
}); });
}); });
@ -95,7 +95,7 @@ export const CreateUpdateModuleModal: React.FC<Props> = observer((props) => {
message: "Module updated successfully.", message: "Module updated successfully.",
}); });
captureModuleEvent({ captureModuleEvent({
eventName: MODULE_UPDATED, eventName: MODULE_TRACKER_EVENTS.update,
payload: { ...res, changed_properties: Object.keys(dirtyFields || {}), state: "SUCCESS" }, payload: { ...res, changed_properties: Object.keys(dirtyFields || {}), state: "SUCCESS" },
}); });
}) })
@ -106,7 +106,7 @@ export const CreateUpdateModuleModal: React.FC<Props> = observer((props) => {
message: err?.detail ?? err?.error ?? "Module could not be updated. Please try again.", message: err?.detail ?? err?.error ?? "Module could not be updated. Please try again.",
}); });
captureModuleEvent({ captureModuleEvent({
eventName: MODULE_UPDATED, eventName: MODULE_TRACKER_EVENTS.update,
payload: { ...data, state: "FAILED" }, payload: { ...data, state: "FAILED" },
}); });
}); });

View file

@ -9,11 +9,10 @@ import { Info, SquareUser } from "lucide-react";
import { import {
MODULE_STATUS, MODULE_STATUS,
PROGRESS_STATE_GROUPS_DETAILS, PROGRESS_STATE_GROUPS_DETAILS,
MODULE_FAVORITED,
MODULE_UNFAVORITED,
EUserPermissions, EUserPermissions,
EUserPermissionsLevel, EUserPermissionsLevel,
IS_FAVORITE_MENU_OPEN, IS_FAVORITE_MENU_OPEN,
MODULE_TRACKER_EVENTS,
} from "@plane/constants"; } from "@plane/constants";
import { useLocalStorage } from "@plane/hooks"; import { useLocalStorage } from "@plane/hooks";
import { IModule } from "@plane/types"; import { IModule } from "@plane/types";
@ -80,7 +79,7 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
const addToFavoritePromise = addModuleToFavorites(workspaceSlug.toString(), projectId.toString(), moduleId).then( const addToFavoritePromise = addModuleToFavorites(workspaceSlug.toString(), projectId.toString(), moduleId).then(
() => { () => {
if (!storedValue) toggleFavoriteMenu(true); if (!storedValue) toggleFavoriteMenu(true);
captureEvent(MODULE_FAVORITED, { captureEvent(MODULE_TRACKER_EVENTS.favorite, {
module_id: moduleId, module_id: moduleId,
element: "Grid layout", element: "Grid layout",
state: "SUCCESS", state: "SUCCESS",
@ -111,7 +110,7 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
projectId.toString(), projectId.toString(),
moduleId moduleId
).then(() => { ).then(() => {
captureEvent(MODULE_UNFAVORITED, { captureEvent(MODULE_TRACKER_EVENTS.unfavorite, {
module_id: moduleId, module_id: moduleId,
element: "Grid layout", element: "Grid layout",
state: "SUCCESS", state: "SUCCESS",

View file

@ -8,11 +8,10 @@ import { SquareUser } from "lucide-react";
// types // types
import { import {
MODULE_STATUS, MODULE_STATUS,
MODULE_FAVORITED,
MODULE_UNFAVORITED,
EUserPermissions, EUserPermissions,
EUserPermissionsLevel, EUserPermissionsLevel,
IS_FAVORITE_MENU_OPEN, IS_FAVORITE_MENU_OPEN,
MODULE_TRACKER_EVENTS,
} from "@plane/constants"; } from "@plane/constants";
import { useLocalStorage } from "@plane/hooks"; import { useLocalStorage } from "@plane/hooks";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
@ -69,7 +68,7 @@ export const ModuleListItemAction: FC<Props> = observer((props) => {
() => { () => {
// open favorites menu if closed // open favorites menu if closed
if (!storedValue) toggleFavoriteMenu(true); if (!storedValue) toggleFavoriteMenu(true);
captureEvent(MODULE_FAVORITED, { captureEvent(MODULE_TRACKER_EVENTS.favorite, {
module_id: moduleId, module_id: moduleId,
element: "Grid layout", element: "Grid layout",
state: "SUCCESS", state: "SUCCESS",
@ -100,7 +99,7 @@ export const ModuleListItemAction: FC<Props> = observer((props) => {
projectId.toString(), projectId.toString(),
moduleId moduleId
).then(() => { ).then(() => {
captureEvent(MODULE_UNFAVORITED, { captureEvent(MODULE_TRACKER_EVENTS.unfavorite, {
module_id: moduleId, module_id: moduleId,
element: "Grid layout", element: "Grid layout",
state: "SUCCESS", state: "SUCCESS",

View file

@ -4,7 +4,12 @@ import { useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
// constants // constants
import { ORGANIZATION_SIZE, RESTRICTED_URLS, WORKSPACE_CREATED, E_ONBOARDING } from "@plane/constants"; import {
ONBOARDING_TRACKER_EVENTS,
ORGANIZATION_SIZE,
RESTRICTED_URLS,
WORKSPACE_TRACKER_EVENTS,
} from "@plane/constants";
// types // types
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { IUser, IWorkspace, TOnboardingSteps } from "@plane/types"; import { IUser, IWorkspace, TOnboardingSteps } from "@plane/types";
@ -69,12 +74,12 @@ export const CreateWorkspace: React.FC<Props> = observer((props) => {
message: t("workspace_creation.toast.success.message"), message: t("workspace_creation.toast.success.message"),
}); });
captureWorkspaceEvent({ captureWorkspaceEvent({
eventName: WORKSPACE_CREATED, eventName: WORKSPACE_TRACKER_EVENTS.create,
payload: { payload: {
...workspaceResponse, ...workspaceResponse,
state: "SUCCESS", state: "SUCCESS",
first_time: true, first_time: true,
element: E_ONBOARDING, element: ONBOARDING_TRACKER_EVENTS.root,
}, },
}); });
await fetchWorkspaces(); await fetchWorkspaces();
@ -82,11 +87,11 @@ export const CreateWorkspace: React.FC<Props> = observer((props) => {
}) })
.catch(() => { .catch(() => {
captureWorkspaceEvent({ captureWorkspaceEvent({
eventName: WORKSPACE_CREATED, eventName: WORKSPACE_TRACKER_EVENTS.create,
payload: { payload: {
state: "FAILED", state: "FAILED",
first_time: true, first_time: true,
element: E_ONBOARDING, element: ONBOARDING_TRACKER_EVENTS.root,
}, },
}); });
setToast({ setToast({
@ -263,7 +268,9 @@ export const CreateWorkspace: React.FC<Props> = observer((props) => {
onChange={onChange} onChange={onChange}
label={ label={
ORGANIZATION_SIZE.find((c) => c === value) ?? ( ORGANIZATION_SIZE.find((c) => c === value) ?? (
<span className="text-custom-text-400">{t("workspace_creation.form.organization_size.placeholder")}</span> <span className="text-custom-text-400">
{t("workspace_creation.form.organization_size.placeholder")}
</span>
) )
} }
buttonClassName="!border-[0.5px] !border-onboarding-border-100 !shadow-none !rounded-md" buttonClassName="!border-[0.5px] !border-onboarding-border-100 !shadow-none !rounded-md"

View file

@ -2,7 +2,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
// plane imports // plane imports
import { ROLE, MEMBER_ACCEPTED } from "@plane/constants"; import { ROLE, MEMBER_TRACKER_EVENTS } from "@plane/constants";
// types // types
import { IWorkspaceMemberInvitation } from "@plane/types"; import { IWorkspaceMemberInvitation } from "@plane/types";
// ui // ui
@ -50,7 +50,7 @@ export const Invitations: React.FC<Props> = (props) => {
try { try {
await workspaceService.joinWorkspaces({ invitations: invitationsRespond }); await workspaceService.joinWorkspaces({ invitations: invitationsRespond });
captureEvent(MEMBER_ACCEPTED, { captureEvent(MEMBER_TRACKER_EVENTS.accept, {
member_id: invitation?.id, member_id: invitation?.id,
role: getUserRole(invitation?.role as any), role: getUserRole(invitation?.role as any),
project_id: undefined, project_id: undefined,
@ -63,7 +63,7 @@ export const Invitations: React.FC<Props> = (props) => {
await handleNextStep(); await handleNextStep();
} catch (error) { } catch (error) {
console.error(error); console.error(error);
captureEvent(MEMBER_ACCEPTED, { captureEvent(MEMBER_TRACKER_EVENTS.accept, {
member_id: invitation?.id, member_id: invitation?.id,
role: getUserRole(invitation?.role as any), role: getUserRole(invitation?.role as any),
project_id: undefined, project_id: undefined,

View file

@ -1,6 +1,6 @@
"use client"; "use client";
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import Image from "next/image"; import Image from "next/image";
import { useTheme } from "next-themes"; import { useTheme } from "next-themes";
@ -20,7 +20,7 @@ import { usePopper } from "react-popper";
import { Check, ChevronDown, Plus, XCircle } from "lucide-react"; import { Check, ChevronDown, Plus, XCircle } from "lucide-react";
import { Listbox } from "@headlessui/react"; import { Listbox } from "@headlessui/react";
// plane imports // plane imports
import { ROLE, ROLE_DETAILS, MEMBER_INVITED, EUserPermissions } from "@plane/constants"; import { ROLE, ROLE_DETAILS, EUserPermissions, MEMBER_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
// types // types
import { IUser, IWorkspace } from "@plane/types"; import { IUser, IWorkspace } from "@plane/types";
@ -311,7 +311,7 @@ export const InviteMembers: React.FC<Props> = (props) => {
})), })),
}) })
.then(async () => { .then(async () => {
captureEvent(MEMBER_INVITED, { captureEvent(MEMBER_TRACKER_EVENTS.invite, {
emails: [ emails: [
...payload.emails.map((email) => ({ ...payload.emails.map((email) => ({
email: email.email, email: email.email,
@ -331,7 +331,7 @@ export const InviteMembers: React.FC<Props> = (props) => {
await nextStep(); await nextStep();
}) })
.catch((err) => { .catch((err) => {
captureEvent(MEMBER_INVITED, { captureEvent(MEMBER_TRACKER_EVENTS.invite, {
project_id: undefined, project_id: undefined,
state: "FAILED", state: "FAILED",
element: "Onboarding", element: "Onboarding",

View file

@ -6,7 +6,7 @@ import Image from "next/image";
import { useTheme } from "next-themes"; import { useTheme } from "next-themes";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { Eye, EyeOff } from "lucide-react"; import { Eye, EyeOff } from "lucide-react";
import { USER_DETAILS, E_ONBOARDING_STEP_1, E_ONBOARDING_STEP_2, E_PASSWORD_STRENGTH } from "@plane/constants"; import { E_PASSWORD_STRENGTH, ONBOARDING_TRACKER_EVENTS, USER_TRACKER_EVENTS } from "@plane/constants";
// types // types
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { IUser, TUserProfile, TOnboardingSteps } from "@plane/types"; import { IUser, TUserProfile, TOnboardingSteps } from "@plane/types";
@ -143,11 +143,11 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
updateUserProfile(profileUpdatePayload), updateUserProfile(profileUpdatePayload),
totalSteps > 2 && stepChange({ profile_complete: true }), totalSteps > 2 && stepChange({ profile_complete: true }),
]); ]);
captureEvent(USER_DETAILS, { captureEvent(USER_TRACKER_EVENTS.add_details, {
use_case: formData.use_case, use_case: formData.use_case,
role: formData.role, role: formData.role,
state: "SUCCESS", state: "SUCCESS",
element: E_ONBOARDING_STEP_1, element: ONBOARDING_TRACKER_EVENTS.step_1,
}); });
setToast({ setToast({
type: TOAST_TYPE.SUCCESS, type: TOAST_TYPE.SUCCESS,
@ -159,9 +159,9 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
finishOnboarding(); finishOnboarding();
} }
} catch { } catch {
captureEvent(USER_DETAILS, { captureEvent(USER_TRACKER_EVENTS.add_details, {
state: "FAILED", state: "FAILED",
element: E_ONBOARDING_STEP_1, element: ONBOARDING_TRACKER_EVENTS.step_1,
}); });
setToast({ setToast({
type: TOAST_TYPE.ERROR, type: TOAST_TYPE.ERROR,
@ -183,9 +183,9 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
formData.password && handleSetPassword(formData.password), formData.password && handleSetPassword(formData.password),
]).then(() => setProfileSetupStep(EProfileSetupSteps.USER_PERSONALIZATION)); ]).then(() => setProfileSetupStep(EProfileSetupSteps.USER_PERSONALIZATION));
} catch { } catch {
captureEvent(USER_DETAILS, { captureEvent(USER_TRACKER_EVENTS.add_details, {
state: "FAILED", state: "FAILED",
element: E_ONBOARDING_STEP_1, element: ONBOARDING_TRACKER_EVENTS.step_1,
}); });
setToast({ setToast({
type: TOAST_TYPE.ERROR, type: TOAST_TYPE.ERROR,
@ -205,11 +205,11 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
updateUserProfile(profileUpdatePayload), updateUserProfile(profileUpdatePayload),
totalSteps > 2 && stepChange({ profile_complete: true }), totalSteps > 2 && stepChange({ profile_complete: true }),
]); ]);
captureEvent(USER_DETAILS, { captureEvent(USER_TRACKER_EVENTS.add_details, {
use_case: formData.use_case, use_case: formData.use_case,
role: formData.role, role: formData.role,
state: "SUCCESS", state: "SUCCESS",
element: E_ONBOARDING_STEP_2, element: ONBOARDING_TRACKER_EVENTS.step_2,
}); });
setToast({ setToast({
type: TOAST_TYPE.SUCCESS, type: TOAST_TYPE.SUCCESS,
@ -221,9 +221,9 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
finishOnboarding(); finishOnboarding();
} }
} catch { } catch {
captureEvent(USER_DETAILS, { captureEvent(USER_TRACKER_EVENTS.add_details, {
state: "FAILED", state: "FAILED",
element: E_ONBOARDING_STEP_2, element: ONBOARDING_TRACKER_EVENTS.step_2,
}); });
setToast({ setToast({
type: TOAST_TYPE.ERROR, type: TOAST_TYPE.ERROR,

View file

@ -5,7 +5,7 @@ import { observer } from "mobx-react";
import Image, { StaticImageData } from "next/image"; import Image, { StaticImageData } from "next/image";
import { X } from "lucide-react"; import { X } from "lucide-react";
// ui // ui
import { PRODUCT_TOUR_SKIPPED, PRODUCT_TOUR_STARTED } from "@plane/constants"; import { PRODUCT_TOUR_TRACKER_EVENTS } from "@plane/constants";
import { Button } from "@plane/ui"; import { Button } from "@plane/ui";
// components // components
import { TourSidebar } from "@/components/onboarding"; import { TourSidebar } from "@/components/onboarding";
@ -112,7 +112,7 @@ export const TourRoot: React.FC<Props> = observer((props) => {
<Button <Button
variant="primary" variant="primary"
onClick={() => { onClick={() => {
captureEvent(PRODUCT_TOUR_STARTED); captureEvent(PRODUCT_TOUR_TRACKER_EVENTS.start);
setStep("work-items"); setStep("work-items");
}} }}
> >
@ -122,7 +122,7 @@ export const TourRoot: React.FC<Props> = observer((props) => {
type="button" type="button"
className="bg-transparent text-xs font-medium text-custom-primary-100 outline-custom-text-100" className="bg-transparent text-xs font-medium text-custom-primary-100 outline-custom-text-100"
onClick={() => { onClick={() => {
captureEvent(PRODUCT_TOUR_SKIPPED); captureEvent(PRODUCT_TOUR_TRACKER_EVENTS.skip);
onComplete(); onComplete();
}} }}
> >

View file

@ -1,6 +1,6 @@
import { FC, useEffect, useState } from "react"; import { FC, useEffect, useState } from "react";
// constants // constants
import { EPageAccess, PAGE_CREATED } from "@plane/constants"; import { EPageAccess, PROJECT_PAGE_TRACKER_EVENTS } from "@plane/constants";
import { TPage } from "@plane/types"; import { TPage } from "@plane/types";
// ui // ui
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui"; import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
@ -63,7 +63,7 @@ export const CreatePageModal: FC<Props> = (props) => {
const pageData = await createPage(pageFormData); const pageData = await createPage(pageFormData);
if (pageData) { if (pageData) {
capturePageEvent({ capturePageEvent({
eventName: PAGE_CREATED, eventName: PROJECT_PAGE_TRACKER_EVENTS.create,
payload: { payload: {
...pageData, ...pageData,
state: "SUCCESS", state: "SUCCESS",
@ -74,7 +74,7 @@ export const CreatePageModal: FC<Props> = (props) => {
} }
} catch { } catch {
capturePageEvent({ capturePageEvent({
eventName: PAGE_CREATED, eventName: PROJECT_PAGE_TRACKER_EVENTS.create,
payload: { payload: {
state: "FAILED", state: "FAILED",
}, },

View file

@ -4,7 +4,7 @@ import React, { useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
// ui // ui
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
import { PAGE_DELETED } from "@plane/constants"; import { PROJECT_PAGE_TRACKER_EVENTS } from "@plane/constants";
import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui"; import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui";
// constants // constants
// hooks // hooks
@ -46,7 +46,7 @@ export const DeletePageModal: React.FC<TConfirmPageDeletionProps> = observer((pr
await removePage(pageId) await removePage(pageId)
.then(() => { .then(() => {
capturePageEvent({ capturePageEvent({
eventName: PAGE_DELETED, eventName: PROJECT_PAGE_TRACKER_EVENTS.delete,
payload: { payload: {
...page, ...page,
state: "SUCCESS", state: "SUCCESS",
@ -65,7 +65,7 @@ export const DeletePageModal: React.FC<TConfirmPageDeletionProps> = observer((pr
}) })
.catch(() => { .catch(() => {
capturePageEvent({ capturePageEvent({
eventName: PAGE_DELETED, eventName: PROJECT_PAGE_TRACKER_EVENTS.delete,
payload: { payload: {
...page, ...page,
state: "FAILED", state: "FAILED",

View file

@ -2,7 +2,7 @@
import { FC, useState } from "react"; import { FC, useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { EventProps, STATE_CREATED, STATE_GROUPS } from "@plane/constants"; import { EventProps, STATE_TRACKER_EVENTS, STATE_GROUPS } from "@plane/constants";
import { IState, TStateGroups, TStateOperationsCallbacks } from "@plane/types"; import { IState, TStateGroups, TStateOperationsCallbacks } from "@plane/types";
import { TOAST_TYPE, setToast } from "@plane/ui"; import { TOAST_TYPE, setToast } from "@plane/ui";
// components // components
@ -44,7 +44,7 @@ export const StateCreate: FC<TStateCreate> = observer((props) => {
try { try {
const stateResponse = await createStateCallback({ ...formData, group: groupKey }); const stateResponse = await createStateCallback({ ...formData, group: groupKey });
captureEventIfEnabled({ captureEventIfEnabled({
eventName: STATE_CREATED, eventName: STATE_TRACKER_EVENTS.create,
payload: { payload: {
...stateResponse, ...stateResponse,
state: "SUCCESS", state: "SUCCESS",
@ -61,7 +61,7 @@ export const StateCreate: FC<TStateCreate> = observer((props) => {
} catch (error) { } catch (error) {
const errorStatus = error as unknown as { status: number; data: { error: string } }; const errorStatus = error as unknown as { status: number; data: { error: string } };
captureEventIfEnabled({ captureEventIfEnabled({
eventName: STATE_CREATED, eventName: STATE_TRACKER_EVENTS.create,
payload: { payload: {
...formData, ...formData,
state: "FAILED", state: "FAILED",

View file

@ -2,7 +2,7 @@
import { FC, useState } from "react"; import { FC, useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { EventProps, STATE_UPDATED } from "@plane/constants"; import { EventProps, STATE_TRACKER_EVENTS } from "@plane/constants";
import { IState, TStateOperationsCallbacks } from "@plane/types"; import { IState, TStateOperationsCallbacks } from "@plane/types";
import { TOAST_TYPE, setToast } from "@plane/ui"; import { TOAST_TYPE, setToast } from "@plane/ui";
// components // components
@ -44,7 +44,7 @@ export const StateUpdate: FC<TStateUpdate> = observer((props) => {
try { try {
const stateResponse = await updateStateCallback(state.id, formData); const stateResponse = await updateStateCallback(state.id, formData);
captureEventIfEnabled({ captureEventIfEnabled({
eventName: STATE_UPDATED, eventName: STATE_TRACKER_EVENTS.update,
payload: { payload: {
...stateResponse, ...stateResponse,
state: "SUCCESS", state: "SUCCESS",
@ -74,7 +74,7 @@ export const StateUpdate: FC<TStateUpdate> = observer((props) => {
message: "State could not be updated. Please try again.", message: "State could not be updated. Please try again.",
}); });
captureEventIfEnabled({ captureEventIfEnabled({
eventName: STATE_UPDATED, eventName: STATE_TRACKER_EVENTS.update,
payload: { payload: {
...formData, ...formData,
state: "FAILED", state: "FAILED",

View file

@ -4,7 +4,7 @@ import { FC, useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Loader, X } from "lucide-react"; import { Loader, X } from "lucide-react";
// plane imports // plane imports
import { EventProps, STATE_DELETED } from "@plane/constants"; import { EventProps, STATE_TRACKER_EVENTS } from "@plane/constants";
import { IState, TStateOperationsCallbacks } from "@plane/types"; import { IState, TStateOperationsCallbacks } from "@plane/types";
import { AlertModalCore, TOAST_TYPE, Tooltip, setToast } from "@plane/ui"; import { AlertModalCore, TOAST_TYPE, Tooltip, setToast } from "@plane/ui";
import { cn } from "@plane/utils"; import { cn } from "@plane/utils";
@ -46,7 +46,7 @@ export const StateDelete: FC<TStateDelete> = observer((props) => {
try { try {
await deleteStateCallback(state.id); await deleteStateCallback(state.id);
captureEventIfEnabled({ captureEventIfEnabled({
eventName: STATE_DELETED, eventName: STATE_TRACKER_EVENTS.delete,
payload: { payload: {
...state, ...state,
state: "SUCCESS", state: "SUCCESS",
@ -56,7 +56,7 @@ export const StateDelete: FC<TStateDelete> = observer((props) => {
} catch (error) { } catch (error) {
const errorStatus = error as unknown as { status: number; data: { error: string } }; const errorStatus = error as unknown as { status: number; data: { error: string } };
captureEventIfEnabled({ captureEventIfEnabled({
eventName: STATE_DELETED, eventName: STATE_TRACKER_EVENTS.delete,
payload: { payload: {
...state, ...state,
state: "FAILED", state: "FAILED",

View file

@ -4,7 +4,7 @@ import React, { useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
// types // types
import { STATE_DELETED } from "@plane/constants"; import { STATE_TRACKER_EVENTS } from "@plane/constants";
import type { IState } from "@plane/types"; import type { IState } from "@plane/types";
// ui // ui
import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui"; import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui";
@ -41,7 +41,7 @@ export const StateDeleteModal: React.FC<TStateDeleteModal> = observer((props) =>
await deleteState(workspaceSlug.toString(), data.project_id, data.id) await deleteState(workspaceSlug.toString(), data.project_id, data.id)
.then(() => { .then(() => {
captureProjectStateEvent({ captureProjectStateEvent({
eventName: STATE_DELETED, eventName: STATE_TRACKER_EVENTS.delete,
payload: { payload: {
...data, ...data,
state: "SUCCESS", state: "SUCCESS",
@ -64,7 +64,7 @@ export const StateDeleteModal: React.FC<TStateDeleteModal> = observer((props) =>
message: "State could not be deleted. Please try again.", message: "State could not be deleted. Please try again.",
}); });
captureProjectStateEvent({ captureProjectStateEvent({
eventName: STATE_DELETED, eventName: STATE_TRACKER_EVENTS.delete,
payload: { payload: {
...data, ...data,
state: "FAILED", state: "FAILED",

View file

@ -6,7 +6,7 @@ import { Controller, useForm } from "react-hook-form";
import { AlertTriangle } from "lucide-react"; import { AlertTriangle } from "lucide-react";
import { Dialog, Transition } from "@headlessui/react"; import { Dialog, Transition } from "@headlessui/react";
// types // types
import { PROJECT_DELETED } from "@plane/constants"; import { PROJECT_TRACKER_EVENTS } from "@plane/constants";
import type { IProject } from "@plane/types"; import type { IProject } from "@plane/types";
// ui // ui
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui"; import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
@ -63,7 +63,7 @@ export const DeleteProjectModal: React.FC<DeleteProjectModal> = (props) => {
handleClose(); handleClose();
captureProjectEvent({ captureProjectEvent({
eventName: PROJECT_DELETED, eventName: PROJECT_TRACKER_EVENTS.delete,
payload: { ...project, state: "SUCCESS", element: "Project general settings" }, payload: { ...project, state: "SUCCESS", element: "Project general settings" },
}); });
setToast({ setToast({
@ -74,7 +74,7 @@ export const DeleteProjectModal: React.FC<DeleteProjectModal> = (props) => {
}) })
.catch(() => { .catch(() => {
captureProjectEvent({ captureProjectEvent({
eventName: PROJECT_DELETED, eventName: PROJECT_TRACKER_EVENTS.delete,
payload: { ...project, state: "FAILED", element: "Project general settings" }, payload: { ...project, state: "FAILED", element: "Project general settings" },
}); });
setToast({ setToast({

View file

@ -3,7 +3,7 @@
import { FC, useEffect, useState } from "react"; import { FC, useEffect, useState } from "react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { Info, Lock } from "lucide-react"; import { Info, Lock } from "lucide-react";
import { NETWORK_CHOICES, PROJECT_UPDATED } from "@plane/constants"; import { NETWORK_CHOICES, PROJECT_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
// plane types // plane types
import { IProject, IWorkspace } from "@plane/types"; import { IProject, IWorkspace } from "@plane/types";
@ -95,7 +95,7 @@ export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
const changed_properties = Object.keys(dirtyFields); const changed_properties = Object.keys(dirtyFields);
captureProjectEvent({ captureProjectEvent({
eventName: PROJECT_UPDATED, eventName: PROJECT_TRACKER_EVENTS.update,
payload: { payload: {
...res, ...res,
changed_properties: changed_properties, changed_properties: changed_properties,
@ -111,7 +111,7 @@ export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
}) })
.catch((error) => { .catch((error) => {
captureProjectEvent({ captureProjectEvent({
eventName: PROJECT_UPDATED, eventName: PROJECT_TRACKER_EVENTS.update,
payload: { ...payload, state: "FAILED", element: "Project general settings" }, payload: { ...payload, state: "FAILED", element: "Project general settings" },
}); });
setToast({ setToast({

View file

@ -8,7 +8,7 @@ import { Controller, useForm } from "react-hook-form";
import { AlertTriangleIcon } from "lucide-react"; import { AlertTriangleIcon } from "lucide-react";
import { Dialog, Transition } from "@headlessui/react"; import { Dialog, Transition } from "@headlessui/react";
// types // types
import { PROJECT_MEMBER_LEAVE } from "@plane/constants"; import { MEMBER_TRACKER_EVENTS } from "@plane/constants";
import { IProject } from "@plane/types"; import { IProject } from "@plane/types";
// ui // ui
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui"; import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
@ -64,7 +64,7 @@ export const LeaveProjectModal: FC<ILeaveProjectModal> = observer((props) => {
return leaveProject(workspaceSlug.toString(), project.id) return leaveProject(workspaceSlug.toString(), project.id)
.then(() => { .then(() => {
handleClose(); handleClose();
captureEvent(PROJECT_MEMBER_LEAVE, { captureEvent(MEMBER_TRACKER_EVENTS.project.leave, {
state: "SUCCESS", state: "SUCCESS",
element: "Project settings members page", element: "Project settings members page",
}); });
@ -75,7 +75,7 @@ export const LeaveProjectModal: FC<ILeaveProjectModal> = observer((props) => {
title: "Error!", title: "Error!",
message: "Something went wrong please try again later.", message: "Something went wrong please try again later.",
}); });
captureEvent(PROJECT_MEMBER_LEAVE, { captureEvent(MEMBER_TRACKER_EVENTS.project.leave, {
state: "FAILED", state: "FAILED",
element: "Project settings members page", element: "Project settings members page",
}); });

View file

@ -2,7 +2,7 @@
import { observer } from "mobx-react"; import { observer } from "mobx-react";
// plane imports // plane imports
import { PROJECT_MEMBER_LEAVE } from "@plane/constants"; import { MEMBER_TRACKER_EVENTS } from "@plane/constants";
import { TOAST_TYPE, Table, setToast } from "@plane/ui"; import { TOAST_TYPE, Table, setToast } from "@plane/ui";
// components // components
import { ConfirmProjectMemberRemove } from "@/components/project"; import { ConfirmProjectMemberRemove } from "@/components/project";
@ -44,7 +44,7 @@ export const ProjectMemberListItem: React.FC<Props> = observer((props) => {
await leaveProject(workspaceSlug.toString(), projectId.toString()) await leaveProject(workspaceSlug.toString(), projectId.toString())
.then(async () => { .then(async () => {
router.push(`/${workspaceSlug}/projects`); router.push(`/${workspaceSlug}/projects`);
captureEvent(PROJECT_MEMBER_LEAVE, { captureEvent(MEMBER_TRACKER_EVENTS.project.leave, {
state: "SUCCESS", state: "SUCCESS",
element: "Project settings members page", element: "Project settings members page",
}); });

View file

@ -6,7 +6,7 @@ import { useForm, Controller, useFieldArray } from "react-hook-form";
import { ChevronDown, Plus, X } from "lucide-react"; import { ChevronDown, Plus, X } from "lucide-react";
import { Dialog, Transition } from "@headlessui/react"; import { Dialog, Transition } from "@headlessui/react";
// plane imports // plane imports
import { ROLE, PROJECT_MEMBER_ADDED, EUserPermissions } from "@plane/constants"; import { ROLE, EUserPermissions, MEMBER_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { Avatar, Button, CustomSelect, CustomSearchSelect, TOAST_TYPE, setToast } from "@plane/ui"; import { Avatar, Button, CustomSelect, CustomSearchSelect, TOAST_TYPE, setToast } from "@plane/ui";
// helpers // helpers
@ -86,7 +86,7 @@ export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
type: TOAST_TYPE.SUCCESS, type: TOAST_TYPE.SUCCESS,
message: "Members added successfully.", message: "Members added successfully.",
}); });
captureEvent(PROJECT_MEMBER_ADDED, { captureEvent(MEMBER_TRACKER_EVENTS.project.add, {
members: [ members: [
...payload.members.map((member) => ({ ...payload.members.map((member) => ({
member_id: member.member_id, member_id: member.member_id,
@ -99,7 +99,7 @@ export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
}) })
.catch((error) => { .catch((error) => {
console.error(error); console.error(error);
captureEvent(PROJECT_MEMBER_ADDED, { captureEvent(MEMBER_TRACKER_EVENTS.project.add, {
state: "FAILED", state: "FAILED",
element: "Project settings members page", element: "Project settings members page",
}); });

View file

@ -2,7 +2,7 @@ import { FC } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { CheckCheck, RefreshCw } from "lucide-react"; import { CheckCheck, RefreshCw } from "lucide-react";
// plane imports // plane imports
import { ENotificationLoader, ENotificationQueryParamType, NOTIFICATIONS_READ } from "@plane/constants"; import { ENotificationLoader, ENotificationQueryParamType, NOTIFICATION_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { Spinner, Tooltip } from "@plane/ui"; import { Spinner, Tooltip } from "@plane/ui";
// components // components
@ -50,7 +50,7 @@ export const NotificationSidebarHeaderOptions: FC<TNotificationSidebarHeaderOpti
<div <div
className="flex-shrink-0 w-5 h-5 flex justify-center items-center overflow-hidden cursor-pointer transition-all hover:bg-custom-background-80 rounded-sm" className="flex-shrink-0 w-5 h-5 flex justify-center items-center overflow-hidden cursor-pointer transition-all hover:bg-custom-background-80 rounded-sm"
onClick={() => { onClick={() => {
captureEvent(NOTIFICATIONS_READ); captureEvent(NOTIFICATION_TRACKER_EVENTS.all_marked_read);
handleMarkAllNotificationsAsRead(); handleMarkAllNotificationsAsRead();
}} }}
> >

View file

@ -3,7 +3,7 @@
import { FC } from "react"; import { FC } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { ArchiveRestore } from "lucide-react"; import { ArchiveRestore } from "lucide-react";
import { NOTIFICATION_ARCHIVED } from "@plane/constants"; import { NOTIFICATION_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { ArchiveIcon, TOAST_TYPE, setToast } from "@plane/ui"; import { ArchiveIcon, TOAST_TYPE, setToast } from "@plane/ui";
// components // components
@ -31,7 +31,7 @@ export const NotificationItemArchiveOption: FC<TNotificationItemArchiveOption> =
try { try {
const request = data.archived_at ? unArchiveNotification : archiveNotification; const request = data.archived_at ? unArchiveNotification : archiveNotification;
await request(workspaceSlug); await request(workspaceSlug);
captureEvent(NOTIFICATION_ARCHIVED, { captureEvent(NOTIFICATION_TRACKER_EVENTS.archive, {
issue_id: data?.data?.issue?.id, issue_id: data?.data?.issue?.id,
tab: currentNotificationTab, tab: currentNotificationTab,
state: "SUCCESS", state: "SUCCESS",

View file

@ -3,7 +3,7 @@
import { FC } from "react"; import { FC } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { MessageSquare } from "lucide-react"; import { MessageSquare } from "lucide-react";
import { NOTIFICATIONS_READ } from "@plane/constants"; import { NOTIFICATION_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { TOAST_TYPE, setToast } from "@plane/ui"; import { TOAST_TYPE, setToast } from "@plane/ui";
// components // components
@ -31,7 +31,7 @@ export const NotificationItemReadOption: FC<TNotificationItemReadOption> = obser
try { try {
const request = data.read_at ? markNotificationAsUnRead : markNotificationAsRead; const request = data.read_at ? markNotificationAsUnRead : markNotificationAsRead;
await request(workspaceSlug); await request(workspaceSlug);
captureEvent(NOTIFICATIONS_READ, { captureEvent(NOTIFICATION_TRACKER_EVENTS.all_marked_read, {
issue_id: data?.data?.issue?.id, issue_id: data?.data?.issue?.id,
tab: currentNotificationTab, tab: currentNotificationTab,
state: "SUCCESS", state: "SUCCESS",

View file

@ -3,7 +3,7 @@
import { Dispatch, SetStateAction, useEffect, useState, FC } from "react"; import { Dispatch, SetStateAction, useEffect, useState, FC } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { ORGANIZATION_SIZE, RESTRICTED_URLS, WORKSPACE_CREATED } from "@plane/constants"; import { ORGANIZATION_SIZE, RESTRICTED_URLS, WORKSPACE_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
// constants // constants
// types // types
@ -72,7 +72,7 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
await createWorkspace(formData) await createWorkspace(formData)
.then(async (res) => { .then(async (res) => {
captureWorkspaceEvent({ captureWorkspaceEvent({
eventName: WORKSPACE_CREATED, eventName: WORKSPACE_TRACKER_EVENTS.create,
payload: { payload: {
...res, ...res,
state: "SUCCESS", state: "SUCCESS",
@ -89,7 +89,7 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
}) })
.catch(() => { .catch(() => {
captureWorkspaceEvent({ captureWorkspaceEvent({
eventName: WORKSPACE_CREATED, eventName: WORKSPACE_TRACKER_EVENTS.create,
payload: { payload: {
state: "FAILED", state: "FAILED",
element: "Create workspace page", element: "Create workspace page",
@ -135,8 +135,7 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
rules={{ rules={{
required: t("common.errors.required"), required: t("common.errors.required"),
validate: (value) => validate: (value) =>
/^[\w\s-]*$/.test(value) || /^[\w\s-]*$/.test(value) || t("workspace_creation.errors.validation.name_alphanumeric"),
t("workspace_creation.errors.validation.name_alphanumeric"),
maxLength: { maxLength: {
value: 80, value: 80,
message: t("workspace_creation.errors.validation.name_length"), message: t("workspace_creation.errors.validation.name_length"),
@ -199,7 +198,9 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
)} )}
/> />
</div> </div>
{slugError && <p className="-mt-3 text-sm text-red-500">{t("workspace_creation.errors.validation.url_already_taken")}</p>} {slugError && (
<p className="-mt-3 text-sm text-red-500">{t("workspace_creation.errors.validation.url_already_taken")}</p>
)}
{invalidSlug && ( {invalidSlug && (
<p className="text-sm text-red-500">{t("workspace_creation.errors.validation.url_alphanumeric")}</p> <p className="text-sm text-red-500">{t("workspace_creation.errors.validation.url_alphanumeric")}</p>
)} )}
@ -221,7 +222,9 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
onChange={onChange} onChange={onChange}
label={ label={
ORGANIZATION_SIZE.find((c) => c === value) ?? ( ORGANIZATION_SIZE.find((c) => c === value) ?? (
<span className="text-custom-text-400">{t("workspace_creation.form.organization_size.placeholder")}</span> <span className="text-custom-text-400">
{t("workspace_creation.form.organization_size.placeholder")}
</span>
) )
} }
buttonClassName="!border-[0.5px] !border-custom-border-200 !shadow-none" buttonClassName="!border-[0.5px] !border-custom-border-200 !shadow-none"

View file

@ -5,7 +5,7 @@ import { observer } from "mobx-react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { AlertTriangle } from "lucide-react"; import { AlertTriangle } from "lucide-react";
// types // types
import { WORKSPACE_DELETED } from "@plane/constants"; import { WORKSPACE_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import type { IWorkspace } from "@plane/types"; import type { IWorkspace } from "@plane/types";
// ui // ui
@ -65,7 +65,7 @@ export const DeleteWorkspaceForm: React.FC<Props> = observer((props) => {
handleClose(); handleClose();
router.push(getWorkspaceRedirectionUrl()); router.push(getWorkspaceRedirectionUrl());
captureWorkspaceEvent({ captureWorkspaceEvent({
eventName: WORKSPACE_DELETED, eventName: WORKSPACE_TRACKER_EVENTS.delete,
payload: { payload: {
...data, ...data,
state: "SUCCESS", state: "SUCCESS",
@ -85,7 +85,7 @@ export const DeleteWorkspaceForm: React.FC<Props> = observer((props) => {
message: t("workspace_settings.settings.general.delete_modal.error_message"), message: t("workspace_settings.settings.general.delete_modal.error_message"),
}); });
captureWorkspaceEvent({ captureWorkspaceEvent({
eventName: WORKSPACE_DELETED, eventName: WORKSPACE_TRACKER_EVENTS.delete,
payload: { payload: {
...data, ...data,
state: "FAILED", state: "FAILED",

View file

@ -4,7 +4,7 @@ import { FC } from "react";
import { isEmpty } from "lodash"; import { isEmpty } from "lodash";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
// ui // ui
import { WORKSPACE_MEMBER_LEAVE } from "@plane/constants"; import { MEMBER_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { IWorkspaceMember } from "@plane/types"; import { IWorkspaceMember } from "@plane/types";
import { TOAST_TYPE, Table, setToast } from "@plane/ui"; import { TOAST_TYPE, Table, setToast } from "@plane/ui";
@ -45,7 +45,7 @@ export const WorkspaceMembersListItem: FC<Props> = observer((props) => {
.then(async () => { .then(async () => {
await fetchCurrentUserSettings(); await fetchCurrentUserSettings();
router.push(getWorkspaceRedirectionUrl()); router.push(getWorkspaceRedirectionUrl());
captureEvent(WORKSPACE_MEMBER_LEAVE, { captureEvent(MEMBER_TRACKER_EVENTS.workspace.leave, {
state: "SUCCESS", state: "SUCCESS",
element: "Workspace settings members page", element: "Workspace settings members page",
}); });

View file

@ -5,7 +5,7 @@ import { observer } from "mobx-react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { Pencil } from "lucide-react"; import { Pencil } from "lucide-react";
// constants // constants
import { ORGANIZATION_SIZE, WORKSPACE_UPDATED, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; import { ORGANIZATION_SIZE, EUserPermissions, EUserPermissionsLevel, WORKSPACE_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { IWorkspace } from "@plane/types"; import { IWorkspace } from "@plane/types";
import { Button, CustomSelect, Input, TOAST_TYPE, setToast } from "@plane/ui"; import { Button, CustomSelect, Input, TOAST_TYPE, setToast } from "@plane/ui";
@ -62,7 +62,7 @@ export const WorkspaceDetails: FC = observer(() => {
await updateWorkspace(currentWorkspace.slug, payload) await updateWorkspace(currentWorkspace.slug, payload)
.then((res) => { .then((res) => {
captureWorkspaceEvent({ captureWorkspaceEvent({
eventName: WORKSPACE_UPDATED, eventName: WORKSPACE_TRACKER_EVENTS.update,
payload: { payload: {
...res, ...res,
state: "SUCCESS", state: "SUCCESS",
@ -77,7 +77,7 @@ export const WorkspaceDetails: FC = observer(() => {
}) })
.catch((err) => { .catch((err) => {
captureWorkspaceEvent({ captureWorkspaceEvent({
eventName: WORKSPACE_UPDATED, eventName: WORKSPACE_TRACKER_EVENTS.update,
payload: { payload: {
state: "FAILED", state: "FAILED",
element: "Workspace general settings page", element: "Workspace general settings page",

View file

@ -3,7 +3,7 @@ import { observer } from "mobx-react";
import Link from "next/link"; import Link from "next/link";
import { useParams, usePathname } from "next/navigation"; import { useParams, usePathname } from "next/navigation";
// plane imports // plane imports
import { EUserPermissionsLevel, SIDEBAR_CLICKED, EUserWorkspaceRoles } from "@plane/constants"; import { EUserPermissionsLevel, EUserWorkspaceRoles, SIDEBAR_TRACKER_EVENTS } from "@plane/constants";
import { usePlatformOS } from "@plane/hooks"; import { usePlatformOS } from "@plane/hooks";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { Tooltip } from "@plane/ui"; import { Tooltip } from "@plane/ui";
@ -49,7 +49,7 @@ export const SidebarUserMenuItem: FC<SidebarUserMenuItemProps> = observer((props
if (window.innerWidth < 768) { if (window.innerWidth < 768) {
toggleSidebar(); toggleSidebar();
} }
captureEvent(SIDEBAR_CLICKED, { captureEvent(SIDEBAR_TRACKER_EVENTS.click, {
destination: itemKey, destination: itemKey,
}); });
}; };

View file

@ -4,7 +4,7 @@ import React, { useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
// types // types
import { GLOBAL_VIEW_DELETED } from "@plane/constants"; import { GLOBAL_VIEW_TOUR_TRACKER_EVENTS } from "@plane/constants";
import { IWorkspaceView } from "@plane/types"; import { IWorkspaceView } from "@plane/types";
// ui // ui
import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui"; import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui";
@ -37,13 +37,13 @@ export const DeleteGlobalViewModal: React.FC<Props> = observer((props) => {
await deleteGlobalView(workspaceSlug.toString(), data.id) await deleteGlobalView(workspaceSlug.toString(), data.id)
.then(() => { .then(() => {
captureEvent(GLOBAL_VIEW_DELETED, { captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.delete, {
view_id: data.id, view_id: data.id,
state: "SUCCESS", state: "SUCCESS",
}); });
}) })
.catch((error: any) => { .catch((error: any) => {
captureEvent(GLOBAL_VIEW_DELETED, { captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.delete, {
view_id: data.id, view_id: data.id,
state: "FAILED", state: "FAILED",
}); });

View file

@ -6,9 +6,9 @@ import { Plus } from "lucide-react";
// plane imports // plane imports
import { import {
DEFAULT_GLOBAL_VIEWS_LIST, DEFAULT_GLOBAL_VIEWS_LIST,
GLOBAL_VIEW_OPENED,
EUserPermissions, EUserPermissions,
EUserPermissionsLevel, EUserPermissionsLevel,
GLOBAL_VIEW_TOUR_TRACKER_EVENTS,
} from "@plane/constants"; } from "@plane/constants";
import { TStaticViewTypes } from "@plane/types"; import { TStaticViewTypes } from "@plane/types";
// components // components
@ -77,7 +77,7 @@ export const GlobalViewsHeader: React.FC = observer(() => {
// bring the active view to the centre of the header // bring the active view to the centre of the header
useEffect(() => { useEffect(() => {
if (globalViewId && currentWorkspaceViews) { if (globalViewId && currentWorkspaceViews) {
captureEvent(GLOBAL_VIEW_OPENED, { captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.open, {
view_id: globalViewId, view_id: globalViewId,
view_type: ["all-issues", "assigned", "created", "subscribed"].includes(globalViewId.toString()) view_type: ["all-issues", "assigned", "created", "subscribed"].includes(globalViewId.toString())
? "Default" ? "Default"

View file

@ -4,7 +4,7 @@ import React from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
// types // types
import { GLOBAL_VIEW_CREATED, GLOBAL_VIEW_UPDATED } from "@plane/constants"; import { GLOBAL_VIEW_TOUR_TRACKER_EVENTS } from "@plane/constants";
import { IWorkspaceView } from "@plane/types"; import { IWorkspaceView } from "@plane/types";
// ui // ui
import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@plane/ui"; import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@plane/ui";
@ -47,7 +47,7 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
await createGlobalView(workspaceSlug.toString(), payloadData) await createGlobalView(workspaceSlug.toString(), payloadData)
.then((res) => { .then((res) => {
captureEvent(GLOBAL_VIEW_CREATED, { captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.create, {
view_id: res.id, view_id: res.id,
applied_filters: res.filters, applied_filters: res.filters,
state: "SUCCESS", state: "SUCCESS",
@ -62,7 +62,7 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
handleClose(); handleClose();
}) })
.catch(() => { .catch(() => {
captureEvent(GLOBAL_VIEW_CREATED, { captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.create, {
applied_filters: payload?.filters, applied_filters: payload?.filters,
state: "FAILED", state: "FAILED",
}); });
@ -87,7 +87,7 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
await updateGlobalView(workspaceSlug.toString(), data.id, payloadData) await updateGlobalView(workspaceSlug.toString(), data.id, payloadData)
.then((res) => { .then((res) => {
if (res) { if (res) {
captureEvent(GLOBAL_VIEW_UPDATED, { captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.update, {
view_id: res.id, view_id: res.id,
applied_filters: res.filters, applied_filters: res.filters,
state: "SUCCESS", state: "SUCCESS",
@ -101,7 +101,7 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
} }
}) })
.catch(() => { .catch(() => {
captureEvent(GLOBAL_VIEW_UPDATED, { captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.update, {
view_id: data.id, view_id: data.id,
applied_filters: data.filters, applied_filters: data.filters,
state: "FAILED", state: "FAILED",

View file

@ -2,7 +2,7 @@ import { useContext } from "react";
// mobx store // mobx store
import { StoreContext } from "@/lib/store-context"; import { StoreContext } from "@/lib/store-context";
// types // types
import { IEventTrackerStore } from "@/store/event-tracker.store"; import { IEventTrackerStore } from "@/plane-web/store/event-tracker.store";
export const useEventTracker = (): IEventTrackerStore => { export const useEventTracker = (): IEventTrackerStore => {
const context = useContext(StoreContext); const context = useContext(StoreContext);

View file

@ -7,7 +7,7 @@ import { useParams } from "next/navigation";
import posthog from "posthog-js"; import posthog from "posthog-js";
import { PostHogProvider as PHProvider } from "posthog-js/react"; import { PostHogProvider as PHProvider } from "posthog-js/react";
// constants // constants
import { GROUP_WORKSPACE } from "@plane/constants"; import { GROUP_WORKSPACE_TRACKER_EVENT } from "@plane/constants";
// helpers // helpers
import { getUserRole } from "@plane/utils"; import { getUserRole } from "@plane/utils";
// hooks // hooks
@ -46,7 +46,7 @@ const PostHogProvider: FC<IPosthogWrapper> = observer((props) => {
project_role: currentProjectRole ? getUserRole(currentProjectRole) : undefined, project_role: currentProjectRole ? getUserRole(currentProjectRole) : undefined,
}); });
if (currentWorkspace) { if (currentWorkspace) {
posthog?.group(GROUP_WORKSPACE, currentWorkspace?.id); posthog?.group(GROUP_WORKSPACE_TRACKER_EVENT, currentWorkspace?.id);
} }
} }
}, [user, currentProjectRole, currentWorkspaceRole, currentWorkspace]); }, [user, currentProjectRole, currentWorkspaceRole, currentWorkspace]);

View file

@ -2,8 +2,7 @@ import { action, computed, makeObservable, observable } from "mobx";
import posthog from "posthog-js"; import posthog from "posthog-js";
// store // store
import { import {
GROUP_WORKSPACE, GROUP_WORKSPACE_TRACKER_EVENT,
WORKSPACE_CREATED,
EventProps, EventProps,
IssueEventProps, IssueEventProps,
getCycleEventPayload, getCycleEventPayload,
@ -13,10 +12,11 @@ import {
getProjectStateEventPayload, getProjectStateEventPayload,
getWorkspaceEventPayload, getWorkspaceEventPayload,
getPageEventPayload, getPageEventPayload,
WORKSPACE_TRACKER_EVENTS,
} from "@plane/constants"; } from "@plane/constants";
import { CoreRootStore } from "./root.store"; import { CoreRootStore } from "./root.store";
export interface IEventTrackerStore { export interface ICoreEventTrackerStore {
// properties // properties
trackElement: string | undefined; trackElement: string | undefined;
// computed // computed
@ -35,7 +35,7 @@ export interface IEventTrackerStore {
captureProjectStateEvent: (props: EventProps) => void; captureProjectStateEvent: (props: EventProps) => void;
} }
export class EventTrackerStore implements IEventTrackerStore { export abstract class CoreEventTrackerStore implements ICoreEventTrackerStore {
trackElement: string | undefined = undefined; trackElement: string | undefined = undefined;
rootStore; rootStore;
constructor(_rootStore: CoreRootStore) { constructor(_rootStore: CoreRootStore) {
@ -89,7 +89,7 @@ export class EventTrackerStore implements IEventTrackerStore {
*/ */
joinWorkspaceMetricGroup = (workspaceId?: string) => { joinWorkspaceMetricGroup = (workspaceId?: string) => {
if (!workspaceId) return; if (!workspaceId) return;
posthog?.group(GROUP_WORKSPACE, workspaceId, { posthog?.group(GROUP_WORKSPACE_TRACKER_EVENT, workspaceId, {
date: new Date().toDateString(), date: new Date().toDateString(),
workspace_id: workspaceId, workspace_id: workspaceId,
}); });
@ -115,7 +115,7 @@ export class EventTrackerStore implements IEventTrackerStore {
*/ */
captureWorkspaceEvent = (props: EventProps) => { captureWorkspaceEvent = (props: EventProps) => {
const { eventName, payload } = props; const { eventName, payload } = props;
if (eventName === WORKSPACE_CREATED && payload.state == "SUCCESS") { if (eventName === WORKSPACE_TRACKER_EVENTS.create && payload.state == "SUCCESS") {
this.joinWorkspaceMetricGroup(payload.id); this.joinWorkspaceMetricGroup(payload.id);
} }
const eventPayload: any = getWorkspaceEventPayload({ const eventPayload: any = getWorkspaceEventPayload({

View file

@ -4,6 +4,7 @@ import { FALLBACK_LANGUAGE, LANGUAGE_STORAGE_KEY } from "@plane/i18n";
// plane web store // plane web store
import { AnalyticsStore, IAnalyticsStore } from "@/plane-web/store/analytics.store"; import { AnalyticsStore, IAnalyticsStore } from "@/plane-web/store/analytics.store";
import { CommandPaletteStore, ICommandPaletteStore } from "@/plane-web/store/command-palette.store"; import { CommandPaletteStore, ICommandPaletteStore } from "@/plane-web/store/command-palette.store";
import { EventTrackerStore, IEventTrackerStore } from "@/plane-web/store/event-tracker.store";
import { RootStore } from "@/plane-web/store/root.store"; import { RootStore } from "@/plane-web/store/root.store";
import { IStateStore, StateStore } from "@/plane-web/store/state.store"; import { IStateStore, StateStore } from "@/plane-web/store/state.store";
// stores // stores
@ -12,7 +13,6 @@ import { CycleFilterStore, ICycleFilterStore } from "./cycle_filter.store";
import { DashboardStore, IDashboardStore } from "./dashboard.store"; import { DashboardStore, IDashboardStore } from "./dashboard.store";
import { EditorAssetStore, IEditorAssetStore } from "./editor/asset.store"; import { EditorAssetStore, IEditorAssetStore } from "./editor/asset.store";
import { IProjectEstimateStore, ProjectEstimateStore } from "./estimates/project-estimate.store"; import { IProjectEstimateStore, ProjectEstimateStore } from "./estimates/project-estimate.store";
import { EventTrackerStore, IEventTrackerStore } from "./event-tracker.store";
import { FavoriteStore, IFavoriteStore } from "./favorite.store"; import { FavoriteStore, IFavoriteStore } from "./favorite.store";
import { GlobalViewStore, IGlobalViewStore } from "./global-view.store"; import { GlobalViewStore, IGlobalViewStore } from "./global-view.store";
import { IProjectInboxStore, ProjectInboxStore } from "./inbox/project-inbox.store"; import { IProjectInboxStore, ProjectInboxStore } from "./inbox/project-inbox.store";
@ -86,7 +86,7 @@ export class CoreRootStore {
this.state = new StateStore(this as unknown as RootStore); this.state = new StateStore(this as unknown as RootStore);
this.label = new LabelStore(this); this.label = new LabelStore(this);
this.dashboard = new DashboardStore(this); this.dashboard = new DashboardStore(this);
this.eventTracker = new EventTrackerStore(this); this.eventTracker = new EventTrackerStore(this as unknown as RootStore);
this.multipleSelect = new MultipleSelectStore(); this.multipleSelect = new MultipleSelectStore();
this.projectInbox = new ProjectInboxStore(this); this.projectInbox = new ProjectInboxStore(this);
this.projectPages = new ProjectPageStore(this as unknown as RootStore); this.projectPages = new ProjectPageStore(this as unknown as RootStore);
@ -120,7 +120,7 @@ export class CoreRootStore {
this.state = new StateStore(this as unknown as RootStore); this.state = new StateStore(this as unknown as RootStore);
this.label = new LabelStore(this); this.label = new LabelStore(this);
this.dashboard = new DashboardStore(this); this.dashboard = new DashboardStore(this);
this.eventTracker = new EventTrackerStore(this); this.eventTracker = new EventTrackerStore(this as unknown as RootStore);
this.projectInbox = new ProjectInboxStore(this); this.projectInbox = new ProjectInboxStore(this);
this.projectPages = new ProjectPageStore(this as unknown as RootStore); this.projectPages = new ProjectPageStore(this as unknown as RootStore);
this.multipleSelect = new MultipleSelectStore(); this.multipleSelect = new MultipleSelectStore();

View file

@ -0,0 +1 @@
export * from "ce/store/event-tracker.store";