[WEB-4423] refactor: event trackers (#7289)

* feat: event tracker helper

* feat: track click events for `data-ph-element`

* fix: handled click events

* fix: handled name

* chore: tracker element updates

* chore: remove export

* chore: tracker element type

* chore: track element and event helper.

* chore: minor improvements

* chore: minor refactors

* fix: workspace events

* fix: added slug

* fix: changes nomenclature

* fix: nomenclature

* chore: update event tracker helper types

* fix: data id

* refactor: cycle events (#7290)

* chore: update event tracker helper types

* refactor: cycle events

* refactor: cycle events

* refactor: cycle event tracker

* chore: update tracker elements

* chore: check for closest element with data-ph-element attribute

---------

Co-authored-by: Prateek Shourya <prateekshourya@Prateeks-MacBook-Pro.local>

* Refactor module events (#7291)

* chore: update event tracker helper types

* refactor: cycle events

* refactor: cycle events

* refactor: cycle event tracker

* refactor: module tracker event and element

* chore: update tracker element

* chore: revert unnecessary changes

---------

Co-authored-by: Prateek Shourya <prateekshourya@Prateeks-MacBook-Pro.local>

* refactor: global views, product tour, notifications, onboarding, users and sidebar related events

* chore: member tracker events (#7302)

* chore: member-tracker-events

* fix: constants

* refactor: update event tracker constants

* refactor: auth related event trackers (#7306)

* Chore: state events (#7307)

* chore: state events

* fix: refactor

* chore: project events (#7305)

* chore: project-events

* fix: refactor

* fix: removed hardcoded values

* fix: github redirection event

* chore: project page tracker events (#7304)

* added events for most page events

* refactor: simplify lock button event handling in PageLockControl

---------

Co-authored-by: Palanikannan M <akashmalinimurugu@gmail.com>
Co-authored-by: M. Palanikannan <73993394+Palanikannan1437@users.noreply.github.com>

* chore: minor cleanup and import fixes

* refactor: added tracker elements for buttons (#7308)

Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>

* fix: event type

* refactor: posthog group event

* chore: removed instances of event tracker (#7309)

* refactor: remove event tracker stores and hooks

* refactor: remove event tracker store

* fix: build errors

* clean up event tracker payloads

* fix: coderabbit suggestions

---------

Co-authored-by: Prateek Shourya <prateekshourya@Prateeks-MacBook-Pro.local>
Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
Co-authored-by: Palanikannan M <akashmalinimurugu@gmail.com>
Co-authored-by: M. Palanikannan <73993394+Palanikannan1437@users.noreply.github.com>
Co-authored-by: Vamsi Krishna <46787868+vamsikrishnamathala@users.noreply.github.com>
This commit is contained in:
Akshita Goyal 2025-07-02 15:23:18 +05:30 committed by GitHub
parent fa9c63716c
commit cfe169c6d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
139 changed files with 2095 additions and 1888 deletions

View file

@ -3,7 +3,12 @@
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_TRACKER_EVENTS } from "@plane/constants";
import {
ORGANIZATION_SIZE,
RESTRICTED_URLS,
WORKSPACE_TRACKER_ELEMENTS,
WORKSPACE_TRACKER_EVENTS,
} from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// constants
// types
@ -11,7 +16,8 @@ import { IWorkspace } from "@plane/types";
// ui
import { Button, CustomSelect, Input, TOAST_TYPE, setToast } from "@plane/ui";
// hooks
import { useEventTracker, useWorkspace } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useWorkspace } from "@/hooks/store";
import { useAppRouter } from "@/hooks/use-app-router";
// services
import { WorkspaceService } from "@/plane-web/services";
@ -51,7 +57,6 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
// router
const router = useAppRouter();
// store hooks
const { captureWorkspaceEvent } = useEventTracker();
const { createWorkspace } = useWorkspace();
// form info
const {
@ -71,13 +76,9 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
await createWorkspace(formData)
.then(async (res) => {
captureWorkspaceEvent({
captureSuccess({
eventName: WORKSPACE_TRACKER_EVENTS.create,
payload: {
...res,
state: "SUCCESS",
element: "Create workspace page",
},
payload: { slug: formData.slug },
});
setToast({
type: TOAST_TYPE.SUCCESS,
@ -88,12 +89,10 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
if (onSubmit) await onSubmit(res);
})
.catch(() => {
captureWorkspaceEvent({
captureError({
eventName: WORKSPACE_TRACKER_EVENTS.create,
payload: {
state: "FAILED",
element: "Create workspace page",
},
payload: { slug: formData.slug },
error: new Error("Error creating workspace"),
});
setToast({
type: TOAST_TYPE.ERROR,
@ -248,7 +247,14 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
<div className="flex items-center gap-4">
{secondaryButton}
<Button variant="primary" type="submit" size="md" disabled={!isValid} loading={isSubmitting}>
<Button
data-ph-element={WORKSPACE_TRACKER_ELEMENTS.CREATE_WORKSPACE_BUTTON}
variant="primary"
type="submit"
size="md"
disabled={!isValid}
loading={isSubmitting}
>
{isSubmitting ? t(primaryButtonText.loading) : t(primaryButtonText.default)}
</Button>
{!secondaryButton && (

View file

@ -13,7 +13,8 @@ import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
// constants
// hooks
import { cn } from "@plane/utils";
import { useEventTracker, useUserSettings, useWorkspace } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useUserSettings, useWorkspace } from "@/hooks/store";
import { useAppRouter } from "@/hooks/use-app-router";
type Props = {
@ -31,7 +32,6 @@ export const DeleteWorkspaceForm: React.FC<Props> = observer((props) => {
// router
const router = useAppRouter();
// store hooks
const { captureWorkspaceEvent } = useEventTracker();
const { deleteWorkspace } = useWorkspace();
const { t } = useTranslation();
const { getWorkspaceRedirectionUrl } = useWorkspace();
@ -64,13 +64,9 @@ export const DeleteWorkspaceForm: React.FC<Props> = observer((props) => {
await fetchCurrentUserSettings();
handleClose();
router.push(getWorkspaceRedirectionUrl());
captureWorkspaceEvent({
captureSuccess({
eventName: WORKSPACE_TRACKER_EVENTS.delete,
payload: {
...data,
state: "SUCCESS",
element: "Workspace general settings page",
},
payload: { slug: data.slug },
});
setToast({
type: TOAST_TYPE.SUCCESS,
@ -84,13 +80,10 @@ export const DeleteWorkspaceForm: React.FC<Props> = observer((props) => {
title: t("workspace_settings.settings.general.delete_modal.error_title"),
message: t("workspace_settings.settings.general.delete_modal.error_message"),
});
captureWorkspaceEvent({
captureError({
eventName: WORKSPACE_TRACKER_EVENTS.delete,
payload: {
...data,
state: "FAILED",
element: "Workspace general settings page",
},
payload: { slug: data.slug },
error: new Error("Error deleting workspace"),
});
});
};

View file

@ -5,13 +5,14 @@ import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { ChevronDown, LinkIcon, Trash2 } from "lucide-react";
// plane imports
import { ROLE, EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { ROLE, EUserPermissions, EUserPermissionsLevel, MEMBER_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { CustomSelect, TOAST_TYPE, setToast, TContextMenuItem, CustomMenu } from "@plane/ui";
import { cn, copyTextToClipboard } from "@plane/utils";
// components
import { ConfirmWorkspaceMemberRemove } from "@/components/workspace";
// hooks
import { captureClick } from "@/helpers/event-tracker.helper";
import { useMember, useUserPermissions } from "@/hooks/store";
type Props = {
@ -93,7 +94,12 @@ export const WorkspaceInvitationsListItem: FC<Props> = observer((props) => {
},
{
key: "remove",
action: () => setRemoveMemberModal(true),
action: () => {
captureClick({
elementName: MEMBER_TRACKER_ELEMENTS.WORKSPACE_INVITATIONS_LIST_CONTEXT_MENU,
});
setRemoveMemberModal(true);
},
title: t("common.remove"),
icon: Trash2,
shouldRender: isAdmin,

View file

@ -4,7 +4,7 @@ import { Controller, useForm } from "react-hook-form";
import { Trash2 } from "lucide-react";
import { Disclosure } from "@headlessui/react";
// plane imports
import { ROLE, EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { ROLE, EUserPermissions, EUserPermissionsLevel, MEMBER_TRACKER_ELEMENTS } from "@plane/constants";
import { IUser, IWorkspaceMember } from "@plane/types";
// plane ui
import { CustomSelect, PopoverMenu, TOAST_TYPE, setToast } from "@plane/ui";
@ -74,6 +74,7 @@ export const NameColumn: React.FC<NameProps> = (props) => {
<div
className="flex items-center gap-x-3 cursor-pointer"
onClick={() => setRemoveMemberModal(rowData)}
data-ph-element={MEMBER_TRACKER_ELEMENTS.WORKSPACE_MEMBER_TABLE_CONTEXT_MENU}
>
<Trash2 className="size-3.5 align-middle" /> {id === currentUser?.id ? "Leave " : "Remove "}
</div>

View file

@ -13,7 +13,8 @@ import { MembersLayoutLoader } from "@/components/ui/loader/layouts/members-layo
import { ConfirmWorkspaceMemberRemove } from "@/components/workspace";
// constants
// hooks
import { useEventTracker, useMember, useUser, useUserPermissions, useUserSettings, useWorkspace } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useMember, useUser, useUserPermissions, useUserSettings, useWorkspace } from "@/hooks/store";
import { useAppRouter } from "@/hooks/use-app-router";
import { useMemberColumns } from "@/plane-web/components/workspace/settings/useMemberColumns";
@ -32,7 +33,6 @@ export const WorkspaceMembersListItem: FC<Props> = observer((props) => {
workspace: { removeMemberFromWorkspace },
} = useMember();
const { leaveWorkspace } = useUserPermissions();
const { captureEvent } = useEventTracker();
const { getWorkspaceRedirectionUrl } = useWorkspace();
const { fetchCurrentUserSettings } = useUserSettings();
const { t } = useTranslation();
@ -45,18 +45,27 @@ export const WorkspaceMembersListItem: FC<Props> = observer((props) => {
.then(async () => {
await fetchCurrentUserSettings();
router.push(getWorkspaceRedirectionUrl());
captureEvent(MEMBER_TRACKER_EVENTS.workspace.leave, {
state: "SUCCESS",
element: "Workspace settings members page",
captureSuccess({
eventName: MEMBER_TRACKER_EVENTS.workspace.leave,
payload: {
workspace: workspaceSlug,
},
});
})
.catch((err: any) =>
.catch((err: any) => {
captureError({
eventName: MEMBER_TRACKER_EVENTS.workspace.leave,
payload: {
workspace: workspaceSlug,
},
error: err,
});
setToast({
type: TOAST_TYPE.ERROR,
title: "Error!",
message: err?.error || t("something_went_wrong_please_try_again"),
})
);
});
});
};
const handleRemoveMember = async (memberId: string) => {

View file

@ -5,7 +5,13 @@ import { observer } from "mobx-react";
import { Controller, useForm } from "react-hook-form";
import { Pencil } from "lucide-react";
// constants
import { ORGANIZATION_SIZE, EUserPermissions, EUserPermissionsLevel, WORKSPACE_TRACKER_EVENTS } from "@plane/constants";
import {
ORGANIZATION_SIZE,
EUserPermissions,
EUserPermissionsLevel,
WORKSPACE_TRACKER_EVENTS,
WORKSPACE_TRACKER_ELEMENTS,
} from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { IWorkspace } from "@plane/types";
import { Button, CustomSelect, Input, TOAST_TYPE, setToast } from "@plane/ui";
@ -15,7 +21,8 @@ import { LogoSpinner } from "@/components/common";
import { WorkspaceImageUploadModal } from "@/components/core";
// helpers
// hooks
import { useEventTracker, useUserPermissions, useWorkspace } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useUserPermissions, useWorkspace } from "@/hooks/store";
// plane web components
import { DeleteWorkspaceSection } from "@/plane-web/components/workspace";
@ -31,7 +38,6 @@ export const WorkspaceDetails: FC = observer(() => {
const [isLoading, setIsLoading] = useState(false);
const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false);
// store hooks
const { captureWorkspaceEvent } = useEventTracker();
const { currentWorkspace, updateWorkspace } = useWorkspace();
const { allowPermissions } = useUserPermissions();
const { t } = useTranslation();
@ -61,13 +67,9 @@ export const WorkspaceDetails: FC = observer(() => {
await updateWorkspace(currentWorkspace.slug, payload)
.then((res) => {
captureWorkspaceEvent({
captureSuccess({
eventName: WORKSPACE_TRACKER_EVENTS.update,
payload: {
...res,
state: "SUCCESS",
element: "Workspace general settings page",
},
payload: { slug: currentWorkspace.slug },
});
setToast({
title: "Success!",
@ -76,12 +78,10 @@ export const WorkspaceDetails: FC = observer(() => {
});
})
.catch((err) => {
captureWorkspaceEvent({
captureError({
eventName: WORKSPACE_TRACKER_EVENTS.update,
payload: {
state: "FAILED",
element: "Workspace general settings page",
},
payload: { slug: currentWorkspace.slug },
error: err,
});
console.error(err);
});
@ -282,7 +282,12 @@ export const WorkspaceDetails: FC = observer(() => {
{isAdmin && (
<div className="flex items-center justify-between py-2">
<Button variant="primary" onClick={handleSubmit(onSubmit)} loading={isLoading}>
<Button
data-ph-element={WORKSPACE_TRACKER_ELEMENTS.UPDATE_WORKSPACE_BUTTON}
variant="primary"
onClick={handleSubmit(onSubmit)}
loading={isLoading}
>
{isLoading ? t("updating") : t("workspace_settings.settings.general.update_workspace")}
</Button>
</div>

View file

@ -12,7 +12,7 @@ import { createRoot } from "react-dom/client";
import { LinkIcon, Settings, Share2, LogOut, MoreHorizontal, ChevronRight } from "lucide-react";
import { Disclosure, Transition } from "@headlessui/react";
// plane helpers
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { EUserPermissions, EUserPermissionsLevel, MEMBER_TRACKER_ELEMENTS } from "@plane/constants";
import { useOutsideClickDetector } from "@plane/hooks";
import { useTranslation } from "@plane/i18n";
// ui
@ -23,7 +23,7 @@ import { Logo } from "@/components/common/logo";
import { LeaveProjectModal, PublishProjectModal } from "@/components/project";
// helpers
// hooks
import { useAppTheme, useCommandPalette, useEventTracker, useProject, useUserPermissions } from "@/hooks/store";
import { useAppTheme, useCommandPalette, useProject, useUserPermissions } from "@/hooks/store";
import { usePlatformOS } from "@/hooks/use-platform-os";
// plane-web components
import { ProjectNavigationRoot } from "@/plane-web/components/sidebar";
@ -59,7 +59,6 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
// store hooks
const { sidebarCollapsed } = useAppTheme();
const { t } = useTranslation();
const { setTrackElement } = useEventTracker();
const { getPartialProjectById } = useProject();
const { isMobile } = usePlatformOS();
const { allowPermissions } = useUserPermissions();
@ -97,7 +96,6 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
);
const handleLeaveProject = () => {
setTrackElement("APP_SIDEBAR_PROJECT_DROPDOWN");
setLeaveProjectModal(true);
};
@ -376,7 +374,10 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
</CustomMenu.MenuItem>
{/* leave project */}
{!isAuthorized && (
<CustomMenu.MenuItem onClick={handleLeaveProject}>
<CustomMenu.MenuItem
onClick={handleLeaveProject}
data-ph-element={MEMBER_TRACKER_ELEMENTS.SIDEBAR_PROJECT_QUICK_ACTIONS}
>
<div className="flex items-center justify-start gap-2">
<LogOut className="h-3.5 w-3.5 stroke-[1.5]" />
<span>{t("leave_project")}</span>

View file

@ -7,7 +7,7 @@ import { observer } from "mobx-react";
import { useParams, usePathname } from "next/navigation";
import { Briefcase, ChevronRight, Plus } from "lucide-react";
import { Disclosure, Transition } from "@headlessui/react";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// ui
import { Loader, TOAST_TYPE, Tooltip, setToast } from "@plane/ui";
@ -17,7 +17,7 @@ import { CreateProjectModal } from "@/components/project";
import { SidebarProjectsListItem } from "@/components/workspace";
// helpers
// hooks
import { useAppTheme, useCommandPalette, useEventTracker, useProject, useUserPermissions } from "@/hooks/store";
import { useAppTheme, useCommandPalette, useProject, useUserPermissions } from "@/hooks/store";
// plane web types
import { TProject } from "@/plane-web/types";
@ -33,7 +33,6 @@ export const SidebarProjectsList: FC = observer(() => {
const { t } = useTranslation();
const { toggleCreateProjectModal } = useCommandPalette();
const { sidebarCollapsed } = useAppTheme();
const { setTrackElement } = useEventTracker();
const { allowPermissions } = useUserPermissions();
const { loader, getPartialProjectById, joinedProjectIds: joinedProjects, updateProjectView } = useProject();
@ -193,9 +192,9 @@ export const SidebarProjectsList: FC = observer(() => {
<Tooltip tooltipHeading={t("create_project")} tooltipContent="">
<button
type="button"
data-ph-element={PROJECT_TRACKER_ELEMENTS.SIDEBAR_CREATE_PROJECT_TOOLTIP}
className="p-0.5 rounded hover:bg-custom-sidebar-background-80 flex-shrink-0"
onClick={() => {
setTrackElement(`APP_SIDEBAR_JOINED_BLOCK`);
setIsProjectModalOpen(true);
}}
aria-label={t("aria_labels.projects_sidebar.create_new_project")}
@ -277,8 +276,8 @@ export const SidebarProjectsList: FC = observer(() => {
"p-0 size-8 aspect-square justify-center mx-auto": sidebarCollapsed,
}
)}
data-ph-element={PROJECT_TRACKER_ELEMENTS.SIDEBAR_CREATE_PROJECT_BUTTON}
onClick={() => {
setTrackElement("Sidebar");
toggleCreateProjectModal(true);
}}
>

View file

@ -2,7 +2,7 @@ import { useRef, useState } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { PenSquare } from "lucide-react";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { EUserPermissions, EUserPermissionsLevel, SIDEBAR_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// types
import { TIssue } from "@plane/types";
@ -12,7 +12,7 @@ import { CreateUpdateIssueModal } from "@/components/issues";
// constants
// helpers
// hooks
import { useAppTheme, useCommandPalette, useEventTracker, useProject, useUserPermissions } from "@/hooks/store";
import { useAppTheme, useCommandPalette, useProject, useUserPermissions } from "@/hooks/store";
import useLocalStorage from "@/hooks/use-local-storage";
// plane web components
import { AppSearch } from "@/plane-web/components/workspace";
@ -31,7 +31,6 @@ export const SidebarQuickActions = observer(() => {
// store hooks
const { toggleCreateIssueModal } = useCommandPalette();
const { sidebarCollapsed: isSidebarCollapsed } = useAppTheme();
const { setTrackElement } = useEventTracker();
const { joinedProjectIds } = useProject();
const { allowPermissions } = useUserPermissions();
// local storage
@ -89,8 +88,8 @@ export const SidebarQuickActions = observer(() => {
"px-3 border-[0.5px] border-custom-sidebar-border-300": !isSidebarCollapsed,
}
)}
data-ph-element={SIDEBAR_TRACKER_ELEMENTS.CREATE_WORK_ITEM_BUTTON}
onClick={() => {
setTrackElement("APP_SIDEBAR_QUICK_ACTIONS");
toggleCreateIssueModal(true);
}}
onMouseEnter={handleMouseEnter}

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_TRACKER_EVENTS } from "@plane/constants";
import { EUserPermissionsLevel, SIDEBAR_TRACKER_ELEMENTS } from "@plane/constants";
import { usePlatformOS } from "@plane/hooks";
import { useTranslation } from "@plane/i18n";
import { EUserWorkspaceRoles } from "@plane/types";
@ -12,7 +12,8 @@ import { Tooltip } from "@plane/ui";
import { SidebarNavItem } from "@/components/sidebar";
import { NotificationAppSidebarOption } from "@/components/workspace-notifications";
// hooks
import { useAppTheme, useEventTracker, useUserPermissions } from "@/hooks/store";
import { captureClick } from "@/helpers/event-tracker.helper";
import { useAppTheme, useUserPermissions } from "@/hooks/store";
export interface SidebarUserMenuItemProps {
item: {
@ -34,7 +35,6 @@ export const SidebarUserMenuItem: FC<SidebarUserMenuItemProps> = observer((props
// package hooks
const { t } = useTranslation();
// store hooks
const { captureEvent } = useEventTracker();
const { allowPermissions } = useUserPermissions();
const { toggleSidebar, sidebarCollapsed } = useAppTheme();
const { isMobile } = usePlatformOS();
@ -50,8 +50,11 @@ export const SidebarUserMenuItem: FC<SidebarUserMenuItemProps> = observer((props
if (window.innerWidth < 768) {
toggleSidebar();
}
captureEvent(SIDEBAR_TRACKER_EVENTS.click, {
destination: itemKey,
captureClick({
elementName: SIDEBAR_TRACKER_ELEMENTS.USER_MENU_ITEM,
context: {
destination: itemKey,
},
});
};

View file

@ -4,13 +4,14 @@ import React, { useState } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// types
import { GLOBAL_VIEW_TOUR_TRACKER_EVENTS } from "@plane/constants";
import { GLOBAL_VIEW_TRACKER_EVENTS } from "@plane/constants";
import { IWorkspaceView } from "@plane/types";
// ui
import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui";
// constants
// hooks
import { useGlobalView, useEventTracker } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useGlobalView } from "@/hooks/store";
type Props = {
data: IWorkspaceView;
@ -26,7 +27,6 @@ export const DeleteGlobalViewModal: React.FC<Props> = observer((props) => {
const { workspaceSlug } = useParams();
// store hooks
const { deleteGlobalView } = useGlobalView();
const { captureEvent } = useEventTracker();
const handleClose = () => onClose();
@ -37,15 +37,20 @@ export const DeleteGlobalViewModal: React.FC<Props> = observer((props) => {
await deleteGlobalView(workspaceSlug.toString(), data.id)
.then(() => {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.delete, {
view_id: data.id,
state: "SUCCESS",
captureSuccess({
eventName: GLOBAL_VIEW_TRACKER_EVENTS.delete,
payload: {
view_id: data.id,
},
});
})
.catch((error: any) => {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.delete, {
view_id: data.id,
state: "FAILED",
captureError({
eventName: GLOBAL_VIEW_TRACKER_EVENTS.delete,
payload: {
view_id: data.id,
},
error: error,
});
setToast({
type: TOAST_TYPE.ERROR,

View file

@ -8,7 +8,8 @@ import {
DEFAULT_GLOBAL_VIEWS_LIST,
EUserPermissions,
EUserPermissionsLevel,
GLOBAL_VIEW_TOUR_TRACKER_EVENTS,
GLOBAL_VIEW_TRACKER_ELEMENTS,
GLOBAL_VIEW_TRACKER_EVENTS,
} from "@plane/constants";
import { TStaticViewTypes } from "@plane/types";
// components
@ -20,7 +21,8 @@ import {
} from "@/components/workspace";
// constants
// store hooks
import { useEventTracker, useGlobalView, useUserPermissions } from "@/hooks/store";
import { captureSuccess } from "@/helpers/event-tracker.helper";
import { useGlobalView, useUserPermissions } from "@/hooks/store";
const ViewTab = observer((props: { viewId: string }) => {
const { viewId } = props;
@ -72,16 +74,17 @@ export const GlobalViewsHeader: React.FC = observer(() => {
const { currentWorkspaceViews } = useGlobalView();
const { allowPermissions } = useUserPermissions();
const { captureEvent } = useEventTracker();
// bring the active view to the centre of the header
useEffect(() => {
if (globalViewId && currentWorkspaceViews) {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.open, {
view_id: globalViewId,
view_type: ["all-issues", "assigned", "created", "subscribed"].includes(globalViewId.toString())
? "Default"
: "Custom",
captureSuccess({
eventName: GLOBAL_VIEW_TRACKER_EVENTS.open,
payload: {
view_id: globalViewId,
view_type: ["all-issues", "assigned", "created", "subscribed"].includes(globalViewId.toString())
? "Default"
: "Custom",
},
});
const activeTabElement = document.querySelector(`#global-view-${globalViewId.toString()}`);
if (activeTabElement && containerRef.current) {
@ -91,7 +94,7 @@ export const GlobalViewsHeader: React.FC = observer(() => {
activeTabElement.scrollIntoView({ behavior: "smooth", inline: diff > 500 ? "center" : "nearest" });
}
}
}, [globalViewId, currentWorkspaceViews, containerRef, captureEvent]);
}, [globalViewId, currentWorkspaceViews, containerRef]);
const isAuthorizedUser = allowPermissions(
[EUserPermissions.ADMIN, EUserPermissions.MEMBER],
@ -115,6 +118,7 @@ export const GlobalViewsHeader: React.FC = observer(() => {
{isAuthorizedUser ? (
<button
type="button"
data-ph-element={GLOBAL_VIEW_TRACKER_ELEMENTS.RIGHT_HEADER_ADD_BUTTON}
className="sticky -right-4 flex flex-shrink-0 items-center justify-center border-transparent bg-custom-background-100 py-3 hover:border-custom-border-200 hover:text-custom-text-400"
onClick={() => setCreateViewModal(true)}
>

View file

@ -4,7 +4,7 @@ import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// types
import { GLOBAL_VIEW_TOUR_TRACKER_EVENTS } from "@plane/constants";
import { GLOBAL_VIEW_TRACKER_EVENTS } from "@plane/constants";
import { IWorkspaceView } from "@plane/types";
// ui
import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@plane/ui";
@ -12,7 +12,8 @@ import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@p
import { WorkspaceViewForm } from "@/components/workspace";
// constants
// store hooks
import { useEventTracker, useGlobalView } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useGlobalView } from "@/hooks/store";
import { useAppRouter } from "@/hooks/use-app-router";
type Props = {
@ -29,7 +30,6 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
const { workspaceSlug } = useParams();
// store hooks
const { createGlobalView, updateGlobalView } = useGlobalView();
const { captureEvent } = useEventTracker();
const handleClose = () => {
onClose();
@ -47,10 +47,11 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
await createGlobalView(workspaceSlug.toString(), payloadData)
.then((res) => {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.create, {
view_id: res.id,
applied_filters: res.filters,
state: "SUCCESS",
captureSuccess({
eventName: GLOBAL_VIEW_TRACKER_EVENTS.create,
payload: {
id: res.id,
},
});
setToast({
type: TOAST_TYPE.SUCCESS,
@ -62,9 +63,8 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
handleClose();
})
.catch(() => {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.create, {
applied_filters: payload?.filters,
state: "FAILED",
captureError({
eventName: GLOBAL_VIEW_TRACKER_EVENTS.create,
});
setToast({
type: TOAST_TYPE.ERROR,
@ -87,10 +87,11 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
await updateGlobalView(workspaceSlug.toString(), data.id, payloadData)
.then((res) => {
if (res) {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.update, {
view_id: res.id,
applied_filters: res.filters,
state: "SUCCESS",
captureSuccess({
eventName: GLOBAL_VIEW_TRACKER_EVENTS.update,
payload: {
id: res.id,
},
});
setToast({
type: TOAST_TYPE.SUCCESS,
@ -101,10 +102,11 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
}
})
.catch(() => {
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.update, {
view_id: data.id,
applied_filters: data.filters,
state: "FAILED",
captureError({
eventName: GLOBAL_VIEW_TRACKER_EVENTS.update,
payload: {
id: data.id,
},
});
setToast({
type: TOAST_TYPE.ERROR,

View file

@ -4,7 +4,7 @@ import { useState } from "react";
import { observer } from "mobx-react";
import { ExternalLink, LinkIcon, Pencil, Trash2 } from "lucide-react";
// types
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { EUserPermissions, EUserPermissionsLevel, GLOBAL_VIEW_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { IWorkspaceView } from "@plane/types";
import { CustomMenu, TContextMenuItem, TOAST_TYPE, setToast } from "@plane/ui";
@ -14,6 +14,7 @@ import { CreateUpdateWorkspaceViewModal, DeleteGlobalViewModal } from "@/compone
// constants
// helpers
// hooks
import { captureClick } from "@/helpers/event-tracker.helper";
import { useUser, useUserPermissions } from "@/hooks/store";
type Props = {
@ -93,6 +94,9 @@ export const WorkspaceViewQuickActions: React.FC<Props> = observer((props) => {
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
captureClick({
elementName: GLOBAL_VIEW_TRACKER_ELEMENTS.QUICK_ACTIONS,
});
item.action();
}}
className={cn(

View file

@ -7,13 +7,15 @@ import { useParams } from "next/navigation";
// icons
import { Pencil, Trash2 } from "lucide-react";
// ui
import { GLOBAL_VIEW_TRACKER_ELEMENTS } from "@plane/constants";
import { CustomMenu } from "@plane/ui";
import { calculateTotalFilters, truncateText } from "@plane/utils";
// components
import { CreateUpdateWorkspaceViewModal, DeleteGlobalViewModal } from "@/components/workspace";
// helpers
// store hooks
import { useEventTracker, useGlobalView } from "@/hooks/store";
import { captureClick } from "@/helpers/event-tracker.helper";
import { useGlobalView } from "@/hooks/store";
type Props = { viewId: string };
@ -26,7 +28,6 @@ export const GlobalViewListItem: React.FC<Props> = observer((props) => {
const { workspaceSlug } = useParams();
// store hooks
const { getViewDetailsById } = useGlobalView();
const { setTrackElement } = useEventTracker();
// derived data
const view = getViewDetailsById(viewId);
@ -58,7 +59,9 @@ export const GlobalViewListItem: React.FC<Props> = observer((props) => {
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setTrackElement("List view");
captureClick({
elementName: GLOBAL_VIEW_TRACKER_ELEMENTS.LIST_ITEM,
});
setUpdateViewModal(true);
}}
>
@ -71,6 +74,9 @@ export const GlobalViewListItem: React.FC<Props> = observer((props) => {
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
captureClick({
elementName: GLOBAL_VIEW_TRACKER_ELEMENTS.LIST_ITEM,
});
setDeleteViewModal(true);
}}
>