chore: added sign-up/in, onboarding, dashboard, all-issues related events (#3595)

* chore: added event constants

* chore: added workspace events

* chore: added workspace group for events

* chore: member invitation event added

* chore: added project pages related events.

* fix: member integer role to string

* chore: added sign-up & sign-in events

* chore: added global-view related events

* chore: added notification related events

* chore: project, cycle property change added

* chore: cycle favourite, and change-properties added

* chore: module davorite, and sidebar property changes added

* fix: build errors

* chore: all events defined in constants
This commit is contained in:
Lakhan Baheti 2024-02-09 16:22:08 +05:30 committed by GitHub
parent 8d730e6680
commit 4f72ebded9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
80 changed files with 1276 additions and 507 deletions

View file

@ -13,6 +13,7 @@ import { Button, CustomSelect, Input } from "@plane/ui";
import { IWorkspace } from "@plane/types";
// constants
import { ORGANIZATION_SIZE, RESTRICTED_URLS } from "constants/workspace";
import { WORKSPACE_CREATED } from "constants/event-tracker";
type Props = {
onSubmit?: (res: IWorkspace) => Promise<void>;
@ -48,7 +49,7 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
// router
const router = useRouter();
// store hooks
const { captureEvent } = useEventTracker();
const { captureWorkspaceEvent } = useEventTracker();
const { createWorkspace } = useWorkspace();
// toast alert
const { setToastAlert } = useToast();
@ -70,9 +71,13 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
await createWorkspace(formData)
.then(async (res) => {
captureEvent("Workspace created", {
...res,
state: "SUCCESS",
captureWorkspaceEvent({
eventName: WORKSPACE_CREATED,
payload: {
...res,
state: "SUCCESS",
element: "Create workspace page",
},
});
setToastAlert({
type: "success",
@ -83,14 +88,18 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
if (onSubmit) await onSubmit(res);
})
.catch(() => {
captureWorkspaceEvent({
eventName: WORKSPACE_CREATED,
payload: {
state: "FAILED",
element: "Create workspace page",
},
});
setToastAlert({
type: "error",
title: "Error!",
message: "Workspace could not be created. Please try again.",
});
captureEvent("Workspace created", {
state: "FAILED",
});
});
} else setSlugError(true);
})
@ -100,9 +109,6 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
title: "Error!",
message: "Some error occurred while creating workspace. Please try again.",
});
captureEvent("Workspace created", {
state: "FAILED",
});
});
};

View file

@ -11,6 +11,8 @@ import useToast from "hooks/use-toast";
import { Button, Input } from "@plane/ui";
// types
import type { IWorkspace } from "@plane/types";
// constants
import { WORKSPACE_DELETED } from "constants/event-tracker";
type Props = {
isOpen: boolean;
@ -28,7 +30,7 @@ export const DeleteWorkspaceModal: React.FC<Props> = observer((props) => {
// router
const router = useRouter();
// store hooks
const { captureEvent } = useEventTracker();
const { captureWorkspaceEvent } = useEventTracker();
const { deleteWorkspace } = useWorkspace();
// toast alert
const { setToastAlert } = useToast();
@ -59,9 +61,13 @@ export const DeleteWorkspaceModal: React.FC<Props> = observer((props) => {
.then((res) => {
handleClose();
router.push("/");
captureEvent("Workspace deleted", {
res,
state: "SUCCESS",
captureWorkspaceEvent({
eventName: WORKSPACE_DELETED,
payload: {
...data,
state: "SUCCESS",
element: "Workspace general settings page",
},
});
setToastAlert({
type: "success",
@ -75,8 +81,13 @@ export const DeleteWorkspaceModal: React.FC<Props> = observer((props) => {
title: "Error!",
message: "Something went wrong. Please try again later.",
});
captureEvent("Workspace deleted", {
state: "FAILED",
captureWorkspaceEvent({
eventName: WORKSPACE_DELETED,
payload: {
...data,
state: "FAILED",
element: "Workspace general settings page",
},
});
});
};

View file

@ -4,7 +4,7 @@ import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import { ChevronDown, Dot, XCircle } from "lucide-react";
// hooks
import { useMember, useUser } from "hooks/store";
import { useEventTracker, useMember, useUser } from "hooks/store";
import useToast from "hooks/use-toast";
// components
import { ConfirmWorkspaceMemberRemove } from "components/workspace";
@ -12,6 +12,7 @@ import { ConfirmWorkspaceMemberRemove } from "components/workspace";
import { CustomSelect, Tooltip } from "@plane/ui";
// constants
import { EUserWorkspaceRoles, ROLE } from "constants/workspace";
import { WORKSPACE_MEMBER_lEAVE } from "constants/event-tracker";
type Props = {
memberId: string;
@ -33,6 +34,7 @@ export const WorkspaceMembersListItem: FC<Props> = observer((props) => {
const {
workspace: { updateMember, removeMemberFromWorkspace, getWorkspaceMemberDetails },
} = useMember();
const { captureEvent } = useEventTracker();
// toast alert
const { setToastAlert } = useToast();
// derived values
@ -42,7 +44,13 @@ export const WorkspaceMembersListItem: FC<Props> = observer((props) => {
if (!workspaceSlug || !currentUserSettings) return;
await leaveWorkspace(workspaceSlug.toString())
.then(() => router.push("/profile"))
.then(() => {
captureEvent(WORKSPACE_MEMBER_lEAVE, {
state: "SUCCESS",
element: "Workspace settings members page",
});
router.push("/profile");
})
.catch((err) =>
setToastAlert({
type: "error",

View file

@ -19,6 +19,7 @@ import { copyUrlToClipboard } from "helpers/string.helper";
import { IWorkspace } from "@plane/types";
// constants
import { EUserWorkspaceRoles, ORGANIZATION_SIZE } from "constants/workspace";
import { WORKSPACE_UPDATED } from "constants/event-tracker";
const defaultValues: Partial<IWorkspace> = {
name: "",
@ -37,7 +38,7 @@ export const WorkspaceDetails: FC = observer(() => {
const [isImageRemoving, setIsImageRemoving] = useState(false);
const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false);
// store hooks
const { captureEvent } = useEventTracker();
const { captureWorkspaceEvent } = useEventTracker();
const {
membership: { currentWorkspaceRole },
} = useUser();
@ -68,9 +69,13 @@ export const WorkspaceDetails: FC = observer(() => {
await updateWorkspace(currentWorkspace.slug, payload)
.then((res) => {
captureEvent("Workspace updated", {
...res,
state: "SUCCESS",
captureWorkspaceEvent({
eventName: WORKSPACE_UPDATED,
payload: {
...res,
state: "SUCCESS",
element: "Workspace general settings page",
},
});
setToastAlert({
title: "Success",
@ -79,8 +84,12 @@ export const WorkspaceDetails: FC = observer(() => {
});
})
.catch((err) => {
captureEvent("Workspace updated", {
state: "FAILED",
captureWorkspaceEvent({
eventName: WORKSPACE_UPDATED,
payload: {
state: "FAILED",
element: "Workspace general settings page",
},
});
console.error(err);
});

View file

@ -222,7 +222,6 @@ export const WorkspaceSidebarDropdown = observer(() => {
<div className="flex w-full flex-col items-start justify-start gap-2 px-4 py-2 text-sm">
<Link
href="/create-workspace"
onClick={() => setTrackElement("APP_SIDEBAR_WORKSPACE_DROPDOWN")}
className="w-full"
>
<Menu.Item

View file

@ -3,7 +3,7 @@ import Link from "next/link";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
// hooks
import { useApplication, useUser } from "hooks/store";
import { useApplication, useEventTracker, useUser } from "hooks/store";
// components
import { NotificationPopover } from "components/notifications";
// ui
@ -12,12 +12,14 @@ import { Crown } from "lucide-react";
// constants
import { EUserWorkspaceRoles } from "constants/workspace";
import { SIDEBAR_MENU_ITEMS } from "constants/dashboard";
import { SIDEBAR_CLICKED } from "constants/event-tracker";
// helper
import { cn } from "helpers/common.helper";
export const WorkspaceSidebarMenu = observer(() => {
// store hooks
const { theme: themeStore } = useApplication();
const { captureEvent } = useEventTracker();
const {
membership: { currentWorkspaceRole },
} = useUser();
@ -27,10 +29,13 @@ export const WorkspaceSidebarMenu = observer(() => {
// computed
const workspaceMemberInfo = currentWorkspaceRole || EUserWorkspaceRoles.GUEST;
const handleLinkClick = () => {
const handleLinkClick = (itemKey: string) => {
if (window.innerWidth < 768) {
themeStore.toggleSidebar();
}
captureEvent(SIDEBAR_CLICKED, {
destination: itemKey,
});
};
return (
@ -38,11 +43,8 @@ export const WorkspaceSidebarMenu = observer(() => {
{SIDEBAR_MENU_ITEMS.map(
(link) =>
workspaceMemberInfo >= link.access && (
<Link key={link.key}
href={`/${workspaceSlug}${link.href}`}
onClick={handleLinkClick}
>
<span className="block w-full my-1">
<Link key={link.key} href={`/${workspaceSlug}${link.href}`} onClick={() => handleLinkClick(link.key)}>
<span className="my-1 block w-full">
<Tooltip
tooltipContent={link.label}
position="right"
@ -50,10 +52,11 @@ export const WorkspaceSidebarMenu = observer(() => {
disabled={!themeStore?.sidebarCollapsed}
>
<div
className={`group flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium outline-none ${link.highlight(router.asPath, `/${workspaceSlug}`)
? "bg-custom-primary-100/10 text-custom-primary-100"
: "text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80"
} ${themeStore?.sidebarCollapsed ? "justify-center" : ""}`}
className={`group flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium outline-none ${
link.highlight(router.asPath, `/${workspaceSlug}`)
? "bg-custom-primary-100/10 text-custom-primary-100"
: "text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80"
} ${themeStore?.sidebarCollapsed ? "justify-center" : ""}`}
>
{
<link.Icon

View file

@ -4,12 +4,14 @@ import { Dialog, Transition } from "@headlessui/react";
import { observer } from "mobx-react-lite";
import { AlertTriangle } from "lucide-react";
// store hooks
import { useGlobalView } from "hooks/store";
import { useGlobalView, useEventTracker } from "hooks/store";
import useToast from "hooks/use-toast";
// ui
import { Button } from "@plane/ui";
// types
import { IWorkspaceView } from "@plane/types";
// constants
import { GLOBAL_VIEW_DELETED } from "constants/event-tracker";
type Props = {
data: IWorkspaceView;
@ -26,6 +28,7 @@ export const DeleteGlobalViewModal: React.FC<Props> = observer((props) => {
const { workspaceSlug } = router.query;
// store hooks
const { deleteGlobalView } = useGlobalView();
const { captureEvent } = useEventTracker();
// toast alert
const { setToastAlert } = useToast();
@ -39,13 +42,23 @@ export const DeleteGlobalViewModal: React.FC<Props> = observer((props) => {
setIsDeleteLoading(true);
await deleteGlobalView(workspaceSlug.toString(), data.id)
.catch(() =>
.then(() => {
captureEvent(GLOBAL_VIEW_DELETED, {
view_id: data.id,
state: "SUCCESS",
});
})
.catch(() => {
captureEvent(GLOBAL_VIEW_DELETED, {
view_id: data.id,
state: "FAILED",
});
setToastAlert({
type: "error",
title: "Error!",
message: "Something went wrong while deleting the view. Please try again.",
})
)
});
})
.finally(() => {
setIsDeleteLoading(false);
handleClose();

View file

@ -4,11 +4,12 @@ import Link from "next/link";
import { observer } from "mobx-react-lite";
import { Plus } from "lucide-react";
// store hooks
import { useGlobalView, useUser } from "hooks/store";
import { useEventTracker, useGlobalView, useUser } from "hooks/store";
// components
import { CreateUpdateWorkspaceViewModal } from "components/workspace";
// constants
import { DEFAULT_GLOBAL_VIEWS_LIST, EUserWorkspaceRoles } from "constants/workspace";
import { GLOBAL_VIEW_OPENED } from "constants/event-tracker";
const ViewTab = observer((props: { viewId: string }) => {
const { viewId } = props;
@ -49,11 +50,19 @@ export const GlobalViewsHeader: React.FC = observer(() => {
const {
membership: { currentWorkspaceRole },
} = useUser();
const { captureEvent } = useEventTracker();
// bring the active view to the centre of the header
useEffect(() => {
if (!globalViewId) return;
captureEvent(GLOBAL_VIEW_OPENED, {
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) activeTabElement.scrollIntoView({ behavior: "smooth", inline: "center" });

View file

@ -3,12 +3,14 @@ import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import { Dialog, Transition } from "@headlessui/react";
// store hooks
import { useGlobalView } from "hooks/store";
import { useEventTracker, useGlobalView } from "hooks/store";
import useToast from "hooks/use-toast";
// components
import { WorkspaceViewForm } from "components/workspace";
// types
import { IWorkspaceView } from "@plane/types";
// constants
import { GLOBAL_VIEW_CREATED, GLOBAL_VIEW_UPDATED } from "constants/event-tracker";
type Props = {
data?: IWorkspaceView;
@ -24,6 +26,7 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
const { workspaceSlug } = router.query;
// store hooks
const { createGlobalView, updateGlobalView } = useGlobalView();
const { captureEvent } = useEventTracker();
// toast alert
const { setToastAlert } = useToast();
@ -43,6 +46,11 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
await createGlobalView(workspaceSlug.toString(), payloadData)
.then((res) => {
captureEvent(GLOBAL_VIEW_CREATED, {
view_id: res.id,
applied_filters: res.filters,
state: "SUCCESS",
});
setToastAlert({
type: "success",
title: "Success!",
@ -52,13 +60,17 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
router.push(`/${workspaceSlug}/workspace-views/${res.id}`);
handleClose();
})
.catch(() =>
.catch(() => {
captureEvent(GLOBAL_VIEW_CREATED, {
applied_filters: payload?.filters,
state: "FAILED",
});
setToastAlert({
type: "error",
title: "Error!",
message: "View could not be created. Please try again.",
})
);
});
});
};
const handleUpdateView = async (payload: Partial<IWorkspaceView>) => {
@ -72,7 +84,12 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
};
await updateGlobalView(workspaceSlug.toString(), data.id, payloadData)
.then(() => {
.then((res) => {
captureEvent(GLOBAL_VIEW_UPDATED, {
view_id: res.id,
applied_filters: res.filters,
state: "SUCCESS",
});
setToastAlert({
type: "success",
title: "Success!",
@ -80,13 +97,18 @@ export const CreateUpdateWorkspaceViewModal: React.FC<Props> = observer((props)
});
handleClose();
})
.catch(() =>
.catch(() => {
captureEvent(GLOBAL_VIEW_UPDATED, {
view_id: data.id,
applied_filters: data.filters,
state: "FAILED",
});
setToastAlert({
type: "error",
title: "Error!",
message: "View could not be updated. Please try again.",
})
);
});
});
};
const handleFormSubmit = async (formData: Partial<IWorkspaceView>) => {

View file

@ -4,7 +4,7 @@ import Link from "next/link";
import { observer } from "mobx-react-lite";
import { Pencil, Trash2 } from "lucide-react";
// store hooks
import { useGlobalView } from "hooks/store";
import { useEventTracker, useGlobalView } from "hooks/store";
// components
import { CreateUpdateWorkspaceViewModal, DeleteGlobalViewModal } from "components/workspace";
// ui
@ -25,6 +25,7 @@ export const GlobalViewListItem: React.FC<Props> = observer((props) => {
const { workspaceSlug } = router.query;
// store hooks
const { getViewDetailsById } = useGlobalView();
const {setTrackElement} = useEventTracker();
// derived data
const view = getViewDetailsById(viewId);
@ -59,6 +60,7 @@ export const GlobalViewListItem: React.FC<Props> = observer((props) => {
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setTrackElement("List view");
setUpdateViewModal(true);
}}
>