Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/constants/src/event-tracker/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ export const STATE_TRACKER_EVENTS = {
update: "state_updated",
delete: "state_deleted",
};
export const STATE_TRACKER_ELEMENTS = {
STATE_GROUP_ADD_BUTTON: "state_group_add_button",
STATE_LIST_DELETE_BUTTON: "state_list_delete_button",
STATE_LIST_EDIT_BUTTON: "state_list_edit_button",
};

export const PROJECT_PAGE_TRACKER_EVENTS = {
create: "project_page_created",
Expand Down
49 changes: 19 additions & 30 deletions web/core/components/project-states/create-update/create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import { FC, useState } from "react";
import { observer } from "mobx-react";
import { EventProps, STATE_TRACKER_EVENTS, STATE_GROUPS } from "@plane/constants";
import { STATE_TRACKER_EVENTS, STATE_GROUPS } from "@plane/constants";
import { IState, TStateGroups, TStateOperationsCallbacks } from "@plane/types";
import { TOAST_TYPE, setToast } from "@plane/ui";
// components
import { StateForm } from "@/components/project-states";
// hooks
import { useEventTracker } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";

type TStateCreate = {
groupKey: TStateGroups;
Expand All @@ -19,17 +19,10 @@ type TStateCreate = {

export const StateCreate: FC<TStateCreate> = observer((props) => {
const { groupKey, shouldTrackEvents, createStateCallback, handleClose } = props;
// hooks
const { captureProjectStateEvent, setTrackElement } = useEventTracker();

// states
const [loader, setLoader] = useState(false);

const captureEventIfEnabled = (props: EventProps) => {
if (shouldTrackEvents) {
captureProjectStateEvent(props);
}
};

const onCancel = () => {
setLoader(false);
handleClose();
Expand All @@ -38,19 +31,16 @@ export const StateCreate: FC<TStateCreate> = observer((props) => {
const onSubmit = async (formData: Partial<IState>) => {
if (!groupKey) return { status: "error" };

if (shouldTrackEvents) {
setTrackElement("PROJECT_SETTINGS_STATE_PAGE");
}
try {
const stateResponse = await createStateCallback({ ...formData, group: groupKey });
captureEventIfEnabled({
eventName: STATE_TRACKER_EVENTS.create,
payload: {
...stateResponse,
state: "SUCCESS",
element: "Project settings states page",
},
});
const response = await createStateCallback({ ...formData, group: groupKey });
if (shouldTrackEvents)
captureSuccess({
eventName: STATE_TRACKER_EVENTS.create,
payload: {
state_group: groupKey,
id: response.id,
},
});
setToast({
type: TOAST_TYPE.SUCCESS,
title: "Success!",
Expand All @@ -60,14 +50,13 @@ export const StateCreate: FC<TStateCreate> = observer((props) => {
return { status: "success" };
} catch (error) {
const errorStatus = error as unknown as { status: number; data: { error: string } };
captureEventIfEnabled({
eventName: STATE_TRACKER_EVENTS.create,
payload: {
...formData,
state: "FAILED",
element: "Project settings states page",
},
});
if (shouldTrackEvents)
captureError({
eventName: STATE_TRACKER_EVENTS.create,
payload: {
state_group: groupKey,
},
});
if (errorStatus?.status === 400) {
setToast({
type: TOAST_TYPE.ERROR,
Expand Down
51 changes: 21 additions & 30 deletions web/core/components/project-states/create-update/update.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import { FC, useState } from "react";
import { observer } from "mobx-react";
import { EventProps, STATE_TRACKER_EVENTS } from "@plane/constants";
import { STATE_TRACKER_EVENTS } from "@plane/constants";
import { IState, TStateOperationsCallbacks } from "@plane/types";
import { TOAST_TYPE, setToast } from "@plane/ui";
// components
import { StateForm } from "@/components/project-states";
// hooks
import { useEventTracker } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";

type TStateUpdate = {
state: IState;
Expand All @@ -19,8 +19,6 @@ type TStateUpdate = {

export const StateUpdate: FC<TStateUpdate> = observer((props) => {
const { state, updateStateCallback, shouldTrackEvents, handleClose } = props;
// hooks
const { captureProjectStateEvent, setTrackElement } = useEventTracker();
// states
const [loader, setLoader] = useState(false);

Expand All @@ -29,28 +27,20 @@ export const StateUpdate: FC<TStateUpdate> = observer((props) => {
handleClose();
};

const captureEventIfEnabled = (props: EventProps) => {
if (shouldTrackEvents) {
captureProjectStateEvent(props);
}
};

const onSubmit = async (formData: Partial<IState>) => {
if (!state.id) return { status: "error" };

if (shouldTrackEvents) {
setTrackElement("PROJECT_SETTINGS_STATE_PAGE");
}
try {
const stateResponse = await updateStateCallback(state.id, formData);
captureEventIfEnabled({
eventName: STATE_TRACKER_EVENTS.update,
payload: {
...stateResponse,
state: "SUCCESS",
element: "Project settings states page",
},
});
await updateStateCallback(state.id, formData);
if (shouldTrackEvents) {
captureSuccess({
eventName: STATE_TRACKER_EVENTS.update,
payload: {
state_group: state.group,
id: state.id,
},
});
}
setToast({
type: TOAST_TYPE.SUCCESS,
title: "Success!",
Expand All @@ -73,14 +63,15 @@ export const StateUpdate: FC<TStateUpdate> = observer((props) => {
title: "Error!",
message: "State could not be updated. Please try again.",
});
captureEventIfEnabled({
eventName: STATE_TRACKER_EVENTS.update,
payload: {
...formData,
state: "FAILED",
element: "Project settings states page",
},
});
if (shouldTrackEvents) {
captureError({
eventName: STATE_TRACKER_EVENTS.update,
payload: {
state_group: state.group,
id: state.id,
},
});
}
return { status: "error" };
}
}
Expand Down
3 changes: 2 additions & 1 deletion web/core/components/project-states/group-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { FC, useState, useRef } from "react";
import { observer } from "mobx-react";
import { ChevronDown, Plus } from "lucide-react";
// plane imports
import { EIconSize } from "@plane/constants";
import { EIconSize, STATE_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { IState, TStateGroups, TStateOperationsCallbacks } from "@plane/types";
import { StateGroupIcon } from "@plane/ui";
Expand Down Expand Up @@ -81,6 +81,7 @@ export const GroupItem: FC<TGroupItem> = observer((props) => {
</div>
<button
type="button"
data-ph-element={STATE_TRACKER_ELEMENTS.STATE_GROUP_ADD_BUTTON}
className={cn(
"flex-shrink-0 w-6 h-6 rounded flex justify-center items-center overflow-hidden transition-colors hover:bg-custom-background-80 cursor-pointer text-custom-primary-100/80 hover:text-custom-primary-100",
(!isEditable || createState) && "cursor-not-allowed text-custom-text-400 hover:text-custom-text-400"
Expand Down
47 changes: 21 additions & 26 deletions web/core/components/project-states/options/delete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { FC, useState } from "react";
import { observer } from "mobx-react";
import { Loader, X } from "lucide-react";
// plane imports
import { EventProps, STATE_TRACKER_EVENTS } from "@plane/constants";
import { STATE_TRACKER_EVENTS, STATE_TRACKER_ELEMENTS } from "@plane/constants";
import { IState, TStateOperationsCallbacks } from "@plane/types";
import { AlertModalCore, TOAST_TYPE, Tooltip, setToast } from "@plane/ui";
import { cn } from "@plane/utils";
// hooks
import { useEventTracker } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { usePlatformOS } from "@/hooks/use-platform-os";

type TStateDelete = {
Expand All @@ -23,45 +23,39 @@ export const StateDelete: FC<TStateDelete> = observer((props) => {
const { totalStates, state, deleteStateCallback, shouldTrackEvents } = props;
// hooks
const { isMobile } = usePlatformOS();
const { captureProjectStateEvent, setTrackElement } = useEventTracker();
// states
const [isDeleteModal, setIsDeleteModal] = useState(false);
const [isDelete, setIsDelete] = useState(false);
// derived values
const isDeleteDisabled = state.default ? true : totalStates === 1 ? true : false;

const captureEventIfEnabled = (props: EventProps) => {
if (shouldTrackEvents) {
captureProjectStateEvent(props);
}
};

const handleDeleteState = async () => {
if (isDeleteDisabled) return;
if (shouldTrackEvents) {
setTrackElement("PROJECT_SETTINGS_STATE_PAGE");
}

setIsDelete(true);

try {
await deleteStateCallback(state.id);
captureEventIfEnabled({
eventName: STATE_TRACKER_EVENTS.delete,
payload: {
...state,
state: "SUCCESS",
},
});
if (shouldTrackEvents) {
captureSuccess({
eventName: STATE_TRACKER_EVENTS.delete,
payload: {
id: state.id,
},
});
}

setIsDelete(false);
} catch (error) {
const errorStatus = error as unknown as { status: number; data: { error: string } };
captureEventIfEnabled({
eventName: STATE_TRACKER_EVENTS.delete,
payload: {
...state,
state: "FAILED",
},
});
if (shouldTrackEvents) {
captureError({
eventName: STATE_TRACKER_EVENTS.delete,
payload: {
id: state.id,
},
});
}
if (errorStatus.status === 400) {
setToast({
type: TOAST_TYPE.ERROR,
Expand Down Expand Up @@ -107,6 +101,7 @@ export const StateDelete: FC<TStateDelete> = observer((props) => {
)}
disabled={isDeleteDisabled}
onClick={() => setIsDeleteModal(true)}
data-ph-element={STATE_TRACKER_ELEMENTS.STATE_LIST_DELETE_BUTTON}
>
<Tooltip
tooltipContent={
Expand Down
15 changes: 6 additions & 9 deletions web/core/components/project-states/state-delete-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import type { IState } from "@plane/types";
import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui";
// constants
// hooks
import { useEventTracker, useProjectState } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useProjectState } from "@/hooks/store";

type TStateDeleteModal = {
isOpen: boolean;
Expand All @@ -24,8 +25,6 @@ export const StateDeleteModal: React.FC<TStateDeleteModal> = observer((props) =>
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
// router
const { workspaceSlug } = useParams();
// store hooks
const { captureProjectStateEvent } = useEventTracker();
const { deleteState } = useProjectState();

const handleClose = () => {
Expand All @@ -40,11 +39,10 @@ export const StateDeleteModal: React.FC<TStateDeleteModal> = observer((props) =>

await deleteState(workspaceSlug.toString(), data.project_id, data.id)
.then(() => {
captureProjectStateEvent({
captureSuccess({
eventName: STATE_TRACKER_EVENTS.delete,
payload: {
...data,
state: "SUCCESS",
id: data.id,
},
});
handleClose();
Expand All @@ -63,11 +61,10 @@ export const StateDeleteModal: React.FC<TStateDeleteModal> = observer((props) =>
title: "Error!",
message: "State could not be deleted. Please try again.",
});
captureProjectStateEvent({
captureError({
eventName: STATE_TRACKER_EVENTS.delete,
payload: {
...data,
state: "FAILED",
id: data.id,
},
});
})
Expand Down
3 changes: 2 additions & 1 deletion web/core/components/project-states/state-item-title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { SetStateAction } from "react";
import { observer } from "mobx-react";
import { GripVertical, Pencil } from "lucide-react";
// plane imports
import { EIconSize } from "@plane/constants";
import { EIconSize, STATE_TRACKER_ELEMENTS } from "@plane/constants";
import { IState, TStateOperationsCallbacks } from "@plane/types";
import { StateGroupIcon } from "@plane/ui";
// local imports
Expand Down Expand Up @@ -70,6 +70,7 @@ export const StateItemTitle = observer((props: TStateItemTitleProps) => {
<button
className="flex-shrink-0 w-5 h-5 rounded flex justify-center items-center overflow-hidden transition-colors hover:bg-custom-background-80 cursor-pointer text-custom-text-200 hover:text-custom-text-100"
onClick={() => setUpdateStateModal(true)}
data-ph-element={STATE_TRACKER_ELEMENTS.STATE_LIST_EDIT_BUTTON}
>
<Pencil className="w-3 h-3" />
</button>
Expand Down