diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(list)/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(list)/header.tsx index 2d13b0d3ee..d9b2cb8ef8 100644 --- a/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(list)/header.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(list)/header.tsx @@ -3,7 +3,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // ui -import { EProjectFeatureKey } from "@plane/constants"; +import { EProjectFeatureKey, PROJECT_VIEW_TRACKER_ELEMENTS } from "@plane/constants"; import { Breadcrumbs, Button, Header } from "@plane/ui"; // components import { ViewListHeader } from "@/components/views"; @@ -34,7 +34,12 @@ export const ProjectViewsHeader = observer(() => {
-
diff --git a/apps/web/app/(all)/accounts/set-password/page.tsx b/apps/web/app/(all)/accounts/set-password/page.tsx index 2464f3dc25..f50a8d987c 100644 --- a/apps/web/app/(all)/accounts/set-password/page.tsx +++ b/apps/web/app/(all)/accounts/set-password/page.tsx @@ -9,7 +9,7 @@ import { useSearchParams } from "next/navigation"; import { useTheme } from "next-themes"; import { Eye, EyeOff } from "lucide-react"; // plane imports -import { E_PASSWORD_STRENGTH } from "@plane/constants"; +import { AUTH_TRACKER_ELEMENTS, AUTH_TRACKER_EVENTS, E_PASSWORD_STRENGTH } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { Button, Input, PasswordStrengthIndicator, TOAST_TYPE, setToast } from "@plane/ui"; // components @@ -17,6 +17,7 @@ import { getPasswordStrength } from "@plane/utils"; // helpers import { EPageTypes } from "@/helpers/authentication.helper"; // hooks +import { captureError, captureSuccess, captureView } from "@/helpers/event-tracker.helper"; import { useUser } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; // wrappers @@ -67,6 +68,12 @@ const SetPasswordPage = observer(() => { const { resolvedTheme } = useTheme(); const { data: user, handleSetPassword } = useUser(); + useEffect(() => { + captureView({ + elementName: AUTH_TRACKER_ELEMENTS.SET_PASSWORD_FORM, + }); + }, []); + useEffect(() => { if (csrfToken === undefined) authService.requestCSRFToken().then((data) => data?.csrf_token && setCsrfToken(data.csrf_token)); @@ -93,6 +100,9 @@ const SetPasswordPage = observer(() => { e.preventDefault(); if (!csrfToken) throw new Error("csrf token not found"); await handleSetPassword(csrfToken, { password: passwordFormData.password }); + captureSuccess({ + eventName: AUTH_TRACKER_EVENTS.password_created, + }); router.push("/"); } catch (error: unknown) { let message = undefined; @@ -100,7 +110,9 @@ const SetPasswordPage = observer(() => { const err = error as Error & { error?: string }; message = err.error; } - + captureError({ + eventName: AUTH_TRACKER_EVENTS.password_created, + }); setToast({ type: TOAST_TYPE.ERROR, title: t("common.errors.default.title"), @@ -116,8 +128,7 @@ const SetPasswordPage = observer(() => { const logo = resolvedTheme === "light" ? BlackHorizontalLogo : WhiteHorizontalLogo; return ( - // TODO: change to EPageTypes.SET_PASSWORD - +
TCommandPaletteActionList = () => { v: { title: "Create a new view", description: "Create a new view in the current project", - action: () => toggleCreateViewModal(true), + action: () => { + toggleCreateViewModal(true); + captureClick({ elementName: PROJECT_VIEW_TRACKER_ELEMENTS.COMMAND_PALETTE_ADD_ITEM }); + }, }, backspace: { title: "Bulk delete work items", diff --git a/apps/web/core/components/command-palette/actions/project-actions.tsx b/apps/web/core/components/command-palette/actions/project-actions.tsx index 677261dc51..0000eac6c7 100644 --- a/apps/web/core/components/command-palette/actions/project-actions.tsx +++ b/apps/web/core/components/command-palette/actions/project-actions.tsx @@ -3,7 +3,12 @@ import { Command } from "cmdk"; import { ContrastIcon, FileText, Layers } from "lucide-react"; // hooks -import { CYCLE_TRACKER_ELEMENTS, MODULE_TRACKER_ELEMENTS, PROJECT_PAGE_TRACKER_ELEMENTS } from "@plane/constants"; +import { + CYCLE_TRACKER_ELEMENTS, + MODULE_TRACKER_ELEMENTS, + PROJECT_PAGE_TRACKER_ELEMENTS, + PROJECT_VIEW_TRACKER_ELEMENTS, +} from "@plane/constants"; import { DiceIcon } from "@plane/ui"; // hooks import { useCommandPalette } from "@/hooks/store"; @@ -55,6 +60,7 @@ export const CommandPaletteProjectActions: React.FC = (props) => { { closePalette(); toggleCreateViewModal(true); diff --git a/apps/web/core/components/global/product-updates/footer.tsx b/apps/web/core/components/global/product-updates/footer.tsx index c6ef12036d..6bc52e2bd2 100644 --- a/apps/web/core/components/global/product-updates/footer.tsx +++ b/apps/web/core/components/global/product-updates/footer.tsx @@ -1,4 +1,5 @@ import Image from "next/image"; +import { USER_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // ui import { getButtonStyling } from "@plane/ui"; @@ -23,6 +24,7 @@ export const ProductUpdatesFooter = () => { = observer((props const { t } = useTranslation(); const { config } = useInstance(); + useEffect(() => { + if (isOpen) { + captureView({ elementName: USER_TRACKER_ELEMENTS.PRODUCT_CHANGELOG_MODAL }); + } + }, [isOpen]); + return ( @@ -32,6 +41,7 @@ export const ProductUpdatesModal: FC = observer((props
{t("please_visit")} { display_filters: issueFilters?.displayFilters, display_properties: issueFilters?.displayProperties, }} + trackerElement={PROJECT_VIEW_TRACKER_ELEMENTS.CYCLE_HEADER_SAVE_AS_VIEW_BUTTON} /> ); diff --git a/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx index 937523e038..bf3fa63cec 100644 --- a/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx @@ -11,6 +11,7 @@ import { EIssueFilterType, EUserPermissions, EUserPermissionsLevel, + GLOBAL_VIEW_TRACKER_ELEMENTS, GLOBAL_VIEW_TRACKER_EVENTS, } from "@plane/constants"; import { EIssuesStoreType, EViewAccess, IIssueFilterOptions, TStaticViewTypes } from "@plane/types"; @@ -189,6 +190,7 @@ export const GlobalViewsAppliedFiltersRoot = observer((props: Props) => { isAuthorizedUser={isAuthorizedUser} setIsModalOpen={setIsModalOpen} handleUpdateView={handleUpdateView} + trackerElement={GLOBAL_VIEW_TRACKER_ELEMENTS.HEADER_SAVE_VIEW_BUTTON} /> ) : ( <> diff --git a/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx index 4e43a730aa..d7174ceefb 100644 --- a/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx @@ -1,6 +1,6 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; -import { EIssueFilterType } from "@plane/constants"; +import { EIssueFilterType, PROJECT_VIEW_TRACKER_ELEMENTS } from "@plane/constants"; import { EIssuesStoreType, IIssueFilterOptions } from "@plane/types"; // hooks import { Header, EHeaderVariant } from "@plane/ui"; @@ -94,6 +94,7 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => { display_filters: issueFilters?.displayFilters, display_properties: issueFilters?.displayProperties, }} + trackerElement={PROJECT_VIEW_TRACKER_ELEMENTS.MODULE_HEADER_SAVE_AS_VIEW_BUTTON} /> ); diff --git a/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx index f20c9613fb..b834eb9da2 100644 --- a/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx @@ -1,7 +1,12 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // types -import { EIssueFilterType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { + EIssueFilterType, + EUserPermissions, + EUserPermissionsLevel, + PROJECT_VIEW_TRACKER_ELEMENTS, +} from "@plane/constants"; import { EIssuesStoreType, IIssueFilterOptions } from "@plane/types"; // ui import { Header, EHeaderVariant } from "@plane/ui"; @@ -94,6 +99,7 @@ export const ProjectAppliedFiltersRoot: React.FC )} diff --git a/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx index beeecf9bb0..c458d692fb 100644 --- a/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx @@ -6,7 +6,12 @@ import isEmpty from "lodash/isEmpty"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // types -import { EIssueFilterType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { + EIssueFilterType, + EUserPermissions, + EUserPermissionsLevel, + PROJECT_VIEW_TRACKER_ELEMENTS, +} from "@plane/constants"; import { EIssuesStoreType, EViewAccess, IIssueFilterOptions } from "@plane/types"; // components import { Header, EHeaderVariant } from "@plane/ui"; @@ -145,6 +150,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => { isAuthorizedUser={isAuthorizedUser} setIsModalOpen={setIsModalOpen} handleUpdateView={handleUpdateView} + trackerElement={PROJECT_VIEW_TRACKER_ELEMENTS.HEADER_SAVE_VIEW_BUTTON} /> diff --git a/apps/web/core/components/issues/issue-layouts/save-filter-view.tsx b/apps/web/core/components/issues/issue-layouts/save-filter-view.tsx index f4a0eca280..524391dba0 100644 --- a/apps/web/core/components/issues/issue-layouts/save-filter-view.tsx +++ b/apps/web/core/components/issues/issue-layouts/save-filter-view.tsx @@ -14,10 +14,11 @@ interface ISaveFilterView { display_filters?: IIssueDisplayFilterOptions; display_properties?: IIssueDisplayProperties; }; + trackerElement: string; } export const SaveFilterView: FC = (props) => { - const { workspaceSlug, projectId, filterParams } = props; + const { workspaceSlug, projectId, filterParams, trackerElement } = props; const [viewModal, setViewModal] = useState(false); @@ -31,7 +32,7 @@ export const SaveFilterView: FC = (props) => { onClose={() => setViewModal(false)} /> -
diff --git a/apps/web/core/components/onboarding/profile-setup.tsx b/apps/web/core/components/onboarding/profile-setup.tsx index 3b950e84f4..b3dc6f267b 100644 --- a/apps/web/core/components/onboarding/profile-setup.tsx +++ b/apps/web/core/components/onboarding/profile-setup.tsx @@ -6,7 +6,12 @@ import Image from "next/image"; import { useTheme } from "next-themes"; import { Controller, useForm } from "react-hook-form"; import { Eye, EyeOff } from "lucide-react"; -import { E_PASSWORD_STRENGTH, ONBOARDING_TRACKER_ELEMENTS, USER_TRACKER_EVENTS } from "@plane/constants"; +import { + AUTH_TRACKER_EVENTS, + E_PASSWORD_STRENGTH, + ONBOARDING_TRACKER_ELEMENTS, + USER_TRACKER_EVENTS, +} from "@plane/constants"; // types import { useTranslation } from "@plane/i18n"; import { IUser, TUserProfile, TOnboardingSteps } from "@plane/types"; @@ -123,7 +128,18 @@ export const ProfileSetup: React.FC = observer((props) => { const handleSetPassword = async (password: string) => { const token = await authService.requestCSRFToken().then((data) => data?.csrf_token); - await authService.setPassword(token, { password }); + await authService + .setPassword(token, { password }) + .then(() => { + captureSuccess({ + eventName: AUTH_TRACKER_EVENTS.password_created, + }); + }) + .catch(() => { + captureError({ + eventName: AUTH_TRACKER_EVENTS.password_created, + }); + }); }; const handleSubmitProfileSetup = async (formData: TProfileSetupFormValues) => { @@ -180,7 +196,18 @@ export const ProfileSetup: React.FC = observer((props) => { await Promise.all([ updateCurrentUser(userDetailsPayload), formData.password && handleSetPassword(formData.password), - ]).then(() => setProfileSetupStep(EProfileSetupSteps.USER_PERSONALIZATION)); + ]).then(() => { + if (formData.password) { + captureView({ + elementName: ONBOARDING_TRACKER_ELEMENTS.PASSWORD_CREATION_SELECTED, + }); + } else { + captureView({ + elementName: ONBOARDING_TRACKER_ELEMENTS.PASSWORD_CREATION_SKIPPED, + }); + } + setProfileSetupStep(EProfileSetupSteps.USER_PERSONALIZATION); + }); } catch { captureError({ eventName: USER_TRACKER_EVENTS.add_details, diff --git a/apps/web/core/components/views/delete-view-modal.tsx b/apps/web/core/components/views/delete-view-modal.tsx index 558469c1c2..d4109eea6e 100644 --- a/apps/web/core/components/views/delete-view-modal.tsx +++ b/apps/web/core/components/views/delete-view-modal.tsx @@ -4,9 +4,12 @@ import React, { useState } from "react"; import { observer } from "mobx-react"; import { useParams, useRouter } from "next/navigation"; // types +import { PROJECT_VIEW_TRACKER_EVENTS } from "@plane/constants"; import { IProjectView } from "@plane/types"; // ui import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui"; +// helpers +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; // hooks import { useProjectView } from "@/hooks/store"; @@ -45,14 +48,26 @@ export const DeleteProjectViewModal: React.FC = observer((props) => { title: "Success!", message: "View deleted successfully.", }); + captureSuccess({ + eventName: PROJECT_VIEW_TRACKER_EVENTS.delete, + payload: { + view_id: data.id, + }, + }); }) - .catch(() => + .catch(() => { setToast({ type: TOAST_TYPE.ERROR, title: "Error!", message: "View could not be deleted. Please try again.", - }) - ) + }); + captureError({ + eventName: PROJECT_VIEW_TRACKER_EVENTS.delete, + payload: { + view_id: data.id, + }, + }); + }) .finally(() => { setIsDeleteLoading(false); }); diff --git a/apps/web/core/components/views/modal.tsx b/apps/web/core/components/views/modal.tsx index 8e708eb2bd..01d3e0bc6d 100644 --- a/apps/web/core/components/views/modal.tsx +++ b/apps/web/core/components/views/modal.tsx @@ -3,12 +3,14 @@ import { FC } from "react"; import { observer } from "mobx-react"; // types +import { PROJECT_VIEW_TRACKER_EVENTS } from "@plane/constants"; import { IProjectView } from "@plane/types"; // ui import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@plane/ui"; // components import { ProjectViewForm } from "@/components/views"; // hooks +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import { useProjectView } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; import useKeypress from "@/hooks/use-keypress"; @@ -43,26 +45,49 @@ export const CreateUpdateProjectViewModal: FC = observer((props) => { title: "Success!", message: "View created successfully.", }); + captureSuccess({ + eventName: PROJECT_VIEW_TRACKER_EVENTS.create, + payload: { + view_id: res.id, + }, + }); }) - .catch(() => + .catch(() => { setToast({ type: TOAST_TYPE.ERROR, title: "Error!", message: "Something went wrong. Please try again.", - }) - ); + }); + captureError({ + eventName: PROJECT_VIEW_TRACKER_EVENTS.create, + }); + }); }; const handleUpdateView = async (payload: IProjectView) => { await updateView(workspaceSlug, projectId, data?.id as string, payload) - .then(() => handleClose()) - .catch((err) => + .then(() => { + handleClose(); + captureSuccess({ + eventName: PROJECT_VIEW_TRACKER_EVENTS.update, + payload: { + view_id: data?.id, + }, + }); + }) + .catch((err) => { setToast({ type: TOAST_TYPE.ERROR, title: "Error!", message: err?.detail ?? "Something went wrong. Please try again.", - }) - ); + }); + captureError({ + eventName: PROJECT_VIEW_TRACKER_EVENTS.update, + payload: { + view_id: data?.id, + }, + }); + }); }; const handleFormSubmit = async (formData: IProjectView) => { diff --git a/apps/web/core/components/views/quick-actions.tsx b/apps/web/core/components/views/quick-actions.tsx index 27b2e73eae..8fb8cc53eb 100644 --- a/apps/web/core/components/views/quick-actions.tsx +++ b/apps/web/core/components/views/quick-actions.tsx @@ -4,7 +4,7 @@ import { useState } from "react"; import { observer } from "mobx-react"; import { ExternalLink, Link, Pencil, Trash2 } from "lucide-react"; // types -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, PROJECT_VIEW_TRACKER_ELEMENTS } from "@plane/constants"; import { IProjectView } from "@plane/types"; // ui import { ContextMenu, CustomMenu, TContextMenuItem, TOAST_TYPE, setToast } from "@plane/ui"; @@ -12,6 +12,7 @@ import { copyUrlToClipboard, cn } from "@plane/utils"; // components import { CreateUpdateProjectViewModal, DeleteProjectViewModal } from "@/components/views"; // helpers +import { captureClick } from "@/helpers/event-tracker.helper"; // hooks import { useUser, useUserPermissions } from "@/hooks/store"; import { PublishViewModal, useViewPublish } from "@/plane-web/components/views/publish"; @@ -83,6 +84,14 @@ export const ViewQuickActions: React.FC = observer((props) => { if (publishContextMenu) MENU_ITEMS.splice(2, 0, publishContextMenu); + const CONTEXT_MENU_ITEMS = MENU_ITEMS.map((item) => ({ + ...item, + action: () => { + captureClick({ elementName: PROJECT_VIEW_TRACKER_ELEMENTS.LIST_ITEM_CONTEXT_MENU }); + item.action(); + }, + })); + return ( <> = observer((props) => { /> setDeleteViewModal(false)} /> setPublishModalOpen(false)} view={view} /> - + {MENU_ITEMS.map((item) => { if (item.shouldRender === false) return null; @@ -104,6 +113,7 @@ export const ViewQuickActions: React.FC = observer((props) => { onClick={(e) => { e.preventDefault(); e.stopPropagation(); + captureClick({ elementName: PROJECT_VIEW_TRACKER_ELEMENTS.QUICK_ACTIONS }); item.action(); }} className={cn( diff --git a/apps/web/core/components/views/update-view-component.tsx b/apps/web/core/components/views/update-view-component.tsx index 0e7990b50e..9b199e0f52 100644 --- a/apps/web/core/components/views/update-view-component.tsx +++ b/apps/web/core/components/views/update-view-component.tsx @@ -1,5 +1,4 @@ import { SetStateAction, useEffect, useState } from "react"; -import { GLOBAL_VIEW_TRACKER_ELEMENTS } from "@plane/constants"; import { Button } from "@plane/ui"; import { LockedComponent } from "../icons/locked-component"; @@ -11,6 +10,7 @@ type Props = { setIsModalOpen: (value: SetStateAction) => void; handleUpdateView: () => void; lockedTooltipContent?: string; + trackerElement: string; }; export const UpdateViewComponent = (props: Props) => { @@ -22,6 +22,7 @@ export const UpdateViewComponent = (props: Props) => { setIsModalOpen, handleUpdateView, lockedTooltipContent, + trackerElement, } = props; const [isUpdating, setIsUpdating] = useState(false); @@ -63,7 +64,7 @@ export const UpdateViewComponent = (props: Props) => { variant="outline-primary" size="md" className="flex-shrink-0" - data-ph-element={GLOBAL_VIEW_TRACKER_ELEMENTS.HEADER_SAVE_VIEW_BUTTON} + data-ph-element={trackerElement} onClick={() => setIsModalOpen(true)} > Save as diff --git a/apps/web/core/components/views/views-list.tsx b/apps/web/core/components/views/views-list.tsx index 6fa5e4b058..372f61ace5 100644 --- a/apps/web/core/components/views/views-list.tsx +++ b/apps/web/core/components/views/views-list.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissionsLevel, PROJECT_VIEW_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { EUserProjectRoles } from "@plane/types"; // components @@ -10,6 +10,7 @@ import { ComicBoxButton, DetailedEmptyState, SimpleEmptyState } from "@/componen import { ViewListLoader } from "@/components/ui"; import { ProjectViewListItem } from "@/components/views"; // hooks +import { captureClick } from "@/helpers/event-tracker.helper"; import { useCommandPalette, useProjectView, useUserPermissions } from "@/hooks/store"; import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; @@ -71,7 +72,10 @@ export const ProjectViewsList = observer(() => { label={t("project_views.empty_state.general.primary_button.text")} title={t("project_views.empty_state.general.primary_button.comic.title")} description={t("project_views.empty_state.general.primary_button.comic.description")} - onClick={() => toggleCreateViewModal(true)} + onClick={() => { + toggleCreateViewModal(true); + captureClick({ elementName: PROJECT_VIEW_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON }); + }} disabled={!canPerformEmptyStateActions} /> } diff --git a/packages/constants/src/event-tracker/core.ts b/packages/constants/src/event-tracker/core.ts index dafbf0e7ec..362cafd59a 100644 --- a/packages/constants/src/event-tracker/core.ts +++ b/packages/constants/src/event-tracker/core.ts @@ -268,6 +268,7 @@ export const AUTH_TRACKER_EVENTS = { sign_in_with_password: "sign_in_with_password", forgot_password: "forgot_password_clicked", new_code_requested: "new_code_requested", + password_created: "password_created", }; export const AUTH_TRACKER_ELEMENTS = { @@ -278,6 +279,7 @@ export const AUTH_TRACKER_ELEMENTS = { SIGN_IN_WITH_UNIQUE_CODE: "sign_in_with_unique_code", REQUEST_NEW_CODE: "request_new_code", VERIFY_CODE: "verify_code", + SET_PASSWORD_FORM: "set_password_form", }; /** @@ -299,6 +301,29 @@ export const GLOBAL_VIEW_TRACKER_ELEMENTS = { LIST_ITEM: "global_view_list_item", }; +/** + * =========================================================================== + * Project View Events and Elements + * =========================================================================== + */ +export const PROJECT_VIEW_TRACKER_EVENTS = { + create: "project_view_created", + update: "project_view_updated", + delete: "project_view_deleted", +}; + +export const PROJECT_VIEW_TRACKER_ELEMENTS = { + RIGHT_HEADER_ADD_BUTTON: "project_view_right_header_add_button", + COMMAND_PALETTE_ADD_ITEM: "command_palette_add_project_view_item", + EMPTY_STATE_CREATE_BUTTON: "project_view_empty_state_create_button", + HEADER_SAVE_VIEW_BUTTON: "project_view_header_save_view_button", + PROJECT_HEADER_SAVE_AS_VIEW_BUTTON: "project_view_header_save_as_view_button", + CYCLE_HEADER_SAVE_AS_VIEW_BUTTON: "cycle_header_save_as_view_button", + MODULE_HEADER_SAVE_AS_VIEW_BUTTON: "module_header_save_as_view_button", + QUICK_ACTIONS: "project_view_quick_actions", + LIST_ITEM_CONTEXT_MENU: "project_view_list_item_context_menu", +}; + /** * =========================================================================== * Product Tour Events and Elements @@ -343,6 +368,11 @@ export const USER_TRACKER_EVENTS = { onboarding_complete: "user_onboarding_completed", }; +export const USER_TRACKER_ELEMENTS = { + PRODUCT_CHANGELOG_MODAL: "product_changelog_modal", + CHANGELOG_REDIRECTED: "changelog_redirected", +}; + /** * =========================================================================== * Onboarding Events and Elements @@ -350,6 +380,8 @@ export const USER_TRACKER_EVENTS = { */ export const ONBOARDING_TRACKER_ELEMENTS = { PROFILE_SETUP_FORM: "onboarding_profile_setup_form", + PASSWORD_CREATION_SELECTED: "onboarding_password_creation_selected", + PASSWORD_CREATION_SKIPPED: "onboarding_password_creation_skipped", }; /**