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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,7 +6,7 @@ import Link from "next/link";
// ui
import { useTheme } from "next-themes";
// components
import { NAVIGATE_TO_SIGNUP } from "@plane/constants";
import { AUTH_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { AuthRoot } from "@/components/account";
import { PageHead } from "@/components/core";
@ -63,7 +63,7 @@ const HomePage = observer(() => {
{t("auth.common.new_to_plane")}
<Link
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"
>
{t("auth.common.create_account")}

View file

@ -3,7 +3,7 @@
import { useState, FC } from "react";
import { observer } from "mobx-react";
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";
// ui
import { setToast, TOAST_TYPE } from "@plane/ui";
@ -75,7 +75,7 @@ export const CreateProjectForm: FC<TCreateProjectFormProps> = observer((props) =
state: "SUCCESS",
};
captureProjectEvent({
eventName: PROJECT_CREATED,
eventName: PROJECT_TRACKER_EVENTS.create,
payload: newPayload,
});
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
import { Eye, EyeOff, Info, X, XCircle } from "lucide-react";
// 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 { Button, Input, Spinner } from "@plane/ui";
import { getPasswordStrength } from "@plane/utils";
@ -77,7 +77,7 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
const redirectToUniqueCodeSignIn = async () => {
handleAuthStep(EAuthSteps.UNIQUE_CODE);
captureEvent(SIGN_IN_WITH_CODE);
captureEvent(AUTH_TRACKER_EVENTS.sign_in_with_code);
};
const passwordSupport =
@ -85,7 +85,7 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
<div className="w-full">
{isSMTPConfigured ? (
<Link
onClick={() => captureEvent(FORGOT_PASSWORD)}
onClick={() => captureEvent(AUTH_TRACKER_EVENTS.forgot_password)}
href={`/accounts/forgot-password?email=${encodeURIComponent(email)}`}
className="text-xs font-medium text-custom-primary-100"
>
@ -154,7 +154,11 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
: true;
if (isPasswordValid) {
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
} else {
setBannerMessage(true);

View file

@ -2,7 +2,7 @@
import React, { useEffect, useState } from "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 { Button, Input, Spinner } from "@plane/ui";
// 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"}/`}
onSubmit={() => {
setIsSubmitting(true);
captureEvent(CODE_VERIFIED, {
captureEvent(AUTH_TRACKER_EVENTS.code_verify, {
state: "SUCCESS",
first_time: !isExistingEmail,
});

View file

@ -5,7 +5,7 @@ import { observer } from "mobx-react";
import { Controller, useForm } from "react-hook-form";
import { ArrowRight, ChevronRight } from "lucide-react";
// 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 { ICycle } from "@plane/types";
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)
.then((res) => {
captureCycleEvent({
eventName: CYCLE_UPDATED,
eventName: CYCLE_TRACKER_EVENTS.update,
payload: {
...res,
changed_properties: [changedProperty],
@ -79,7 +79,7 @@ export const CycleSidebarHeader: FC<Props> = observer((props) => {
.catch(() => {
captureCycleEvent({
eventName: CYCLE_UPDATED,
eventName: CYCLE_TRACKER_EVENTS.update,
payload: {
...data,
element: "Right side-peek",

View file

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

View file

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

View file

@ -4,7 +4,7 @@ import React, { useEffect, useState } from "react";
import { format } from "date-fns";
import { mutate } from "swr";
// types
import { CYCLE_CREATED, CYCLE_UPDATED } from "@plane/constants";
import { CYCLE_TRACKER_EVENTS } from "@plane/constants";
import type { CycleDateCheckData, ICycle, TCycleTabOptions } from "@plane/types";
// 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.",
});
captureCycleEvent({
eventName: CYCLE_CREATED,
eventName: CYCLE_TRACKER_EVENTS.create,
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.",
});
captureCycleEvent({
eventName: CYCLE_CREATED,
eventName: CYCLE_TRACKER_EVENTS.create,
payload: { ...payload, state: "FAILED" },
});
});
@ -89,7 +89,7 @@ export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
.then((res) => {
const changed_properties = Object.keys(dirtyFields);
captureCycleEvent({
eventName: CYCLE_UPDATED,
eventName: CYCLE_TRACKER_EVENTS.update,
payload: { ...res, changed_properties: changed_properties, state: "SUCCESS" },
});
setToast({
@ -100,7 +100,7 @@ export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
})
.catch((err) => {
captureCycleEvent({
eventName: CYCLE_UPDATED,
eventName: CYCLE_TRACKER_EVENTS.update,
payload: { ...payload, state: "FAILED" },
});
setToast({

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -7,13 +7,19 @@ import { useParams, usePathname } from "next/navigation";
// icons
import { Layers, Link, Paperclip } from "lucide-react";
// types
import { ISSUE_UPDATED } from "@plane/constants";
import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants";
// i18n
import { useTranslation } from "@plane/i18n";
import { TIssue, IIssueDisplayProperties, TIssuePriorities } from "@plane/types";
// 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
import {
EstimateDropdown,
@ -103,7 +109,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (updateIssue)
updateIssue(issue.project_id, issue.id, { state_id: stateId }).then(() => {
captureIssueEvent({
eventName: ISSUE_UPDATED,
eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname,
updates: {
@ -118,7 +124,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (updateIssue)
updateIssue(issue.project_id, issue.id, { priority: value }).then(() => {
captureIssueEvent({
eventName: ISSUE_UPDATED,
eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname,
updates: {
@ -133,7 +139,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (updateIssue)
updateIssue(issue.project_id, issue.id, { label_ids: ids }).then(() => {
captureIssueEvent({
eventName: ISSUE_UPDATED,
eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname,
updates: {
@ -148,7 +154,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (updateIssue)
updateIssue(issue.project_id, issue.id, { assignee_ids: ids }).then(() => {
captureIssueEvent({
eventName: ISSUE_UPDATED,
eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname,
updates: {
@ -173,7 +179,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (modulesToRemove.length > 0) issueOperations.removeModulesFromIssue(modulesToRemove);
captureIssueEvent({
eventName: ISSUE_UPDATED,
eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname,
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?.();
captureIssueEvent({
eventName: ISSUE_UPDATED,
eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname,
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(
() => {
captureIssueEvent({
eventName: ISSUE_UPDATED,
eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname,
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(
() => {
captureIssueEvent({
eventName: ISSUE_UPDATED,
eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname,
updates: {
@ -236,7 +242,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
if (updateIssue)
updateIssue(issue.project_id, issue.id, { estimate_point: value }).then(() => {
captureIssueEvent({
eventName: ISSUE_UPDATED,
eventName: WORK_ITEM_TRACKER_EVENTS.update,
payload: { ...issue, state: "SUCCESS", element: currentLayout },
path: pathname,
updates: {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -4,7 +4,7 @@ import React, { useEffect, useState } from "react";
import { observer } from "mobx-react";
import { useForm } from "react-hook-form";
// types
import { MODULE_CREATED, MODULE_UPDATED } from "@plane/constants";
import { MODULE_TRACKER_EVENTS } from "@plane/constants";
import type { IModule } from "@plane/types";
// 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.",
});
captureModuleEvent({
eventName: MODULE_CREATED,
eventName: MODULE_TRACKER_EVENTS.create,
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.",
});
captureModuleEvent({
eventName: MODULE_CREATED,
eventName: MODULE_TRACKER_EVENTS.create,
payload: { ...data, state: "FAILED" },
});
});
@ -95,7 +95,7 @@ export const CreateUpdateModuleModal: React.FC<Props> = observer((props) => {
message: "Module updated successfully.",
});
captureModuleEvent({
eventName: MODULE_UPDATED,
eventName: MODULE_TRACKER_EVENTS.update,
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.",
});
captureModuleEvent({
eventName: MODULE_UPDATED,
eventName: MODULE_TRACKER_EVENTS.update,
payload: { ...data, state: "FAILED" },
});
});

View file

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

View file

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

View file

@ -4,7 +4,12 @@ import { useState } from "react";
import { observer } from "mobx-react";
import { Controller, useForm } from "react-hook-form";
// 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
import { useTranslation } from "@plane/i18n";
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"),
});
captureWorkspaceEvent({
eventName: WORKSPACE_CREATED,
eventName: WORKSPACE_TRACKER_EVENTS.create,
payload: {
...workspaceResponse,
state: "SUCCESS",
first_time: true,
element: E_ONBOARDING,
element: ONBOARDING_TRACKER_EVENTS.root,
},
});
await fetchWorkspaces();
@ -82,11 +87,11 @@ export const CreateWorkspace: React.FC<Props> = observer((props) => {
})
.catch(() => {
captureWorkspaceEvent({
eventName: WORKSPACE_CREATED,
eventName: WORKSPACE_TRACKER_EVENTS.create,
payload: {
state: "FAILED",
first_time: true,
element: E_ONBOARDING,
element: ONBOARDING_TRACKER_EVENTS.root,
},
});
setToast({
@ -263,7 +268,9 @@ export const CreateWorkspace: React.FC<Props> = observer((props) => {
onChange={onChange}
label={
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"

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@
import { observer } from "mobx-react";
// plane imports
import { PROJECT_MEMBER_LEAVE } from "@plane/constants";
import { MEMBER_TRACKER_EVENTS } from "@plane/constants";
import { TOAST_TYPE, Table, setToast } from "@plane/ui";
// components
import { ConfirmProjectMemberRemove } from "@/components/project";
@ -44,7 +44,7 @@ export const ProjectMemberListItem: React.FC<Props> = observer((props) => {
await leaveProject(workspaceSlug.toString(), projectId.toString())
.then(async () => {
router.push(`/${workspaceSlug}/projects`);
captureEvent(PROJECT_MEMBER_LEAVE, {
captureEvent(MEMBER_TRACKER_EVENTS.project.leave, {
state: "SUCCESS",
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 { Dialog, Transition } from "@headlessui/react";
// 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 { Avatar, Button, CustomSelect, CustomSearchSelect, TOAST_TYPE, setToast } from "@plane/ui";
// helpers
@ -86,7 +86,7 @@ export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
type: TOAST_TYPE.SUCCESS,
message: "Members added successfully.",
});
captureEvent(PROJECT_MEMBER_ADDED, {
captureEvent(MEMBER_TRACKER_EVENTS.project.add, {
members: [
...payload.members.map((member) => ({
member_id: member.member_id,
@ -99,7 +99,7 @@ export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
})
.catch((error) => {
console.error(error);
captureEvent(PROJECT_MEMBER_ADDED, {
captureEvent(MEMBER_TRACKER_EVENTS.project.add, {
state: "FAILED",
element: "Project settings members page",
});

View file

@ -2,7 +2,7 @@ import { FC } from "react";
import { observer } from "mobx-react";
import { CheckCheck, RefreshCw } from "lucide-react";
// 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 { Spinner, Tooltip } from "@plane/ui";
// components
@ -50,7 +50,7 @@ export const NotificationSidebarHeaderOptions: FC<TNotificationSidebarHeaderOpti
<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"
onClick={() => {
captureEvent(NOTIFICATIONS_READ);
captureEvent(NOTIFICATION_TRACKER_EVENTS.all_marked_read);
handleMarkAllNotificationsAsRead();
}}
>

View file

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

View file

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

View file

@ -3,7 +3,7 @@
import { Dispatch, SetStateAction, useEffect, useState, FC } from "react";
import { observer } from "mobx-react";
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";
// constants
// types
@ -72,7 +72,7 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
await createWorkspace(formData)
.then(async (res) => {
captureWorkspaceEvent({
eventName: WORKSPACE_CREATED,
eventName: WORKSPACE_TRACKER_EVENTS.create,
payload: {
...res,
state: "SUCCESS",
@ -89,7 +89,7 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
})
.catch(() => {
captureWorkspaceEvent({
eventName: WORKSPACE_CREATED,
eventName: WORKSPACE_TRACKER_EVENTS.create,
payload: {
state: "FAILED",
element: "Create workspace page",
@ -135,8 +135,7 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
rules={{
required: t("common.errors.required"),
validate: (value) =>
/^[\w\s-]*$/.test(value) ||
t("workspace_creation.errors.validation.name_alphanumeric"),
/^[\w\s-]*$/.test(value) || t("workspace_creation.errors.validation.name_alphanumeric"),
maxLength: {
value: 80,
message: t("workspace_creation.errors.validation.name_length"),
@ -199,7 +198,9 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
)}
/>
</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 && (
<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}
label={
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"

View file

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

View file

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

View file

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

View file

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

View file

@ -4,7 +4,7 @@ import React, { useState } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// types
import { GLOBAL_VIEW_DELETED } from "@plane/constants";
import { GLOBAL_VIEW_TOUR_TRACKER_EVENTS } from "@plane/constants";
import { IWorkspaceView } from "@plane/types";
// 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)
.then(() => {
captureEvent(GLOBAL_VIEW_DELETED, {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.delete, {
view_id: data.id,
state: "SUCCESS",
});
})
.catch((error: any) => {
captureEvent(GLOBAL_VIEW_DELETED, {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.delete, {
view_id: data.id,
state: "FAILED",
});

View file

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

View file

@ -4,7 +4,7 @@ import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// 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";
// 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)
.then((res) => {
captureEvent(GLOBAL_VIEW_CREATED, {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.create, {
view_id: res.id,
applied_filters: res.filters,
state: "SUCCESS",
@ -62,7 +62,7 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
handleClose();
})
.catch(() => {
captureEvent(GLOBAL_VIEW_CREATED, {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.create, {
applied_filters: payload?.filters,
state: "FAILED",
});
@ -87,7 +87,7 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
await updateGlobalView(workspaceSlug.toString(), data.id, payloadData)
.then((res) => {
if (res) {
captureEvent(GLOBAL_VIEW_UPDATED, {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.update, {
view_id: res.id,
applied_filters: res.filters,
state: "SUCCESS",
@ -101,7 +101,7 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
}
})
.catch(() => {
captureEvent(GLOBAL_VIEW_UPDATED, {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.update, {
view_id: data.id,
applied_filters: data.filters,
state: "FAILED",

View file

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

View file

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

View file

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

View file

@ -4,6 +4,7 @@ import { FALLBACK_LANGUAGE, LANGUAGE_STORAGE_KEY } from "@plane/i18n";
// plane web store
import { AnalyticsStore, IAnalyticsStore } from "@/plane-web/store/analytics.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 { IStateStore, StateStore } from "@/plane-web/store/state.store";
// stores
@ -12,7 +13,6 @@ import { CycleFilterStore, ICycleFilterStore } from "./cycle_filter.store";
import { DashboardStore, IDashboardStore } from "./dashboard.store";
import { EditorAssetStore, IEditorAssetStore } from "./editor/asset.store";
import { IProjectEstimateStore, ProjectEstimateStore } from "./estimates/project-estimate.store";
import { EventTrackerStore, IEventTrackerStore } from "./event-tracker.store";
import { FavoriteStore, IFavoriteStore } from "./favorite.store";
import { GlobalViewStore, IGlobalViewStore } from "./global-view.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.label = new LabelStore(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.projectInbox = new ProjectInboxStore(this);
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.label = new LabelStore(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.projectPages = new ProjectPageStore(this as unknown as RootStore);
this.multipleSelect = new MultipleSelectStore();

View file

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