mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: new analytic events (#699)
* feat: tracking events for issues marked as DONE, issue property update, issue moved to cycle, issue moved to modules * fix: changed events names * chore: sync analytic * chore: new analytic events
This commit is contained in:
parent
65037b5031
commit
cf662f6e6c
@ -34,7 +34,6 @@ import {
|
|||||||
TrashIcon,
|
TrashIcon,
|
||||||
XMarkIcon,
|
XMarkIcon,
|
||||||
ArrowTopRightOnSquareIcon,
|
ArrowTopRightOnSquareIcon,
|
||||||
|
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
// helpers
|
// helpers
|
||||||
import { handleIssuesMutation } from "constants/issue";
|
import { handleIssuesMutation } from "constants/issue";
|
||||||
|
@ -10,6 +10,7 @@ import { DragDropContext, DropResult } from "react-beautiful-dnd";
|
|||||||
import issuesService from "services/issues.service";
|
import issuesService from "services/issues.service";
|
||||||
import stateService from "services/state.service";
|
import stateService from "services/state.service";
|
||||||
import modulesService from "services/modules.service";
|
import modulesService from "services/modules.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
// hooks
|
// hooks
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
import useIssuesView from "hooks/use-issues-view";
|
import useIssuesView from "hooks/use-issues-view";
|
||||||
@ -259,7 +260,22 @@ export const IssuesView: React.FC<Props> = ({
|
|||||||
state: draggedItem.state,
|
state: draggedItem.state,
|
||||||
sort_order: draggedItem.sort_order,
|
sort_order: draggedItem.sort_order,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then((response) => {
|
||||||
|
const sourceStateBeforeDrag = states.find((state) => state.name === source.droppableId);
|
||||||
|
|
||||||
|
if (
|
||||||
|
sourceStateBeforeDrag?.group !== "completed" &&
|
||||||
|
response?.state_detail?.group === "completed"
|
||||||
|
)
|
||||||
|
trackEventServices.trackIssueMarkedAsDoneEvent({
|
||||||
|
workspaceSlug,
|
||||||
|
workspaceId: draggedItem.workspace_detail.id,
|
||||||
|
projectName: draggedItem.project_detail.name,
|
||||||
|
projectIdentifier: draggedItem.project_detail.identifier,
|
||||||
|
projectId,
|
||||||
|
issueId: draggedItem.id,
|
||||||
|
});
|
||||||
|
|
||||||
if (cycleId) {
|
if (cycleId) {
|
||||||
mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params));
|
mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params));
|
||||||
mutate(CYCLE_DETAILS(cycleId as string));
|
mutate(CYCLE_DETAILS(cycleId as string));
|
||||||
@ -282,6 +298,7 @@ export const IssuesView: React.FC<Props> = ({
|
|||||||
orderBy,
|
orderBy,
|
||||||
handleDeleteIssue,
|
handleDeleteIssue,
|
||||||
params,
|
params,
|
||||||
|
states,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import useSWR from "swr";
|
|||||||
|
|
||||||
// services
|
// services
|
||||||
import projectService from "services/project.service";
|
import projectService from "services/project.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
// ui
|
// ui
|
||||||
import { AssigneesList, Avatar, CustomSearchSelect, Tooltip } from "components/ui";
|
import { AssigneesList, Avatar, CustomSearchSelect, Tooltip } from "components/ui";
|
||||||
// icons
|
// icons
|
||||||
@ -71,6 +72,18 @@ export const ViewAssigneeSelect: React.FC<Props> = ({
|
|||||||
else newData.push(data);
|
else newData.push(data);
|
||||||
|
|
||||||
partialUpdateIssue({ assignees_list: data });
|
partialUpdateIssue({ assignees_list: data });
|
||||||
|
|
||||||
|
trackEventServices.trackIssuePartialPropertyUpdateEvent(
|
||||||
|
{
|
||||||
|
workspaceSlug: issue.workspace_detail.slug,
|
||||||
|
workspaceId: issue.workspace_detail.id,
|
||||||
|
projectId: issue.project_detail.id,
|
||||||
|
projectIdentifier: issue.project_detail.identifier,
|
||||||
|
projectName: issue.project_detail.name,
|
||||||
|
issueId: issue.id,
|
||||||
|
},
|
||||||
|
"ISSUE_PROPERTY_UPDATE_ASSIGNEE"
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
options={options}
|
options={options}
|
||||||
label={
|
label={
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
import { CustomDatePicker, Tooltip } from "components/ui";
|
import { CustomDatePicker, Tooltip } from "components/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { findHowManyDaysLeft } from "helpers/date-time.helper";
|
import { findHowManyDaysLeft } from "helpers/date-time.helper";
|
||||||
|
// services
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
// types
|
// types
|
||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
|
|
||||||
@ -25,13 +27,24 @@ export const ViewDueDateSelect: React.FC<Props> = ({ issue, partialUpdateIssue,
|
|||||||
<CustomDatePicker
|
<CustomDatePicker
|
||||||
placeholder="N/A"
|
placeholder="N/A"
|
||||||
value={issue?.target_date}
|
value={issue?.target_date}
|
||||||
onChange={(val) =>
|
onChange={(val) => {
|
||||||
partialUpdateIssue({
|
partialUpdateIssue({
|
||||||
target_date: val,
|
target_date: val,
|
||||||
priority: issue.priority,
|
priority: issue.priority,
|
||||||
state: issue.state,
|
state: issue.state,
|
||||||
})
|
});
|
||||||
}
|
trackEventServices.trackIssuePartialPropertyUpdateEvent(
|
||||||
|
{
|
||||||
|
workspaceSlug: issue.workspace_detail.slug,
|
||||||
|
workspaceId: issue.workspace_detail.id,
|
||||||
|
projectId: issue.project_detail.id,
|
||||||
|
projectIdentifier: issue.project_detail.identifier,
|
||||||
|
projectName: issue.project_detail.name,
|
||||||
|
issueId: issue.id,
|
||||||
|
},
|
||||||
|
"ISSUE_PROPERTY_UPDATE_DUE_DATE"
|
||||||
|
);
|
||||||
|
}}
|
||||||
className={issue?.target_date ? "w-[6.5rem]" : "w-[3rem] text-center"}
|
className={issue?.target_date ? "w-[6.5rem]" : "w-[3rem] text-center"}
|
||||||
disabled={isNotAllowed}
|
disabled={isNotAllowed}
|
||||||
/>
|
/>
|
||||||
|
@ -8,6 +8,8 @@ import { getPriorityIcon } from "components/icons/priority-icon";
|
|||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
// constants
|
// constants
|
||||||
import { PRIORITIES } from "constants/project";
|
import { PRIORITIES } from "constants/project";
|
||||||
|
// services
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
issue: IIssue;
|
issue: IIssue;
|
||||||
@ -26,9 +28,20 @@ export const ViewPrioritySelect: React.FC<Props> = ({
|
|||||||
}) => (
|
}) => (
|
||||||
<CustomSelect
|
<CustomSelect
|
||||||
value={issue.priority}
|
value={issue.priority}
|
||||||
onChange={(data: string) =>
|
onChange={(data: string) => {
|
||||||
partialUpdateIssue({ priority: data, state: issue.state, target_date: issue.target_date })
|
partialUpdateIssue({ priority: data, state: issue.state, target_date: issue.target_date });
|
||||||
}
|
trackEventServices.trackIssuePartialPropertyUpdateEvent(
|
||||||
|
{
|
||||||
|
workspaceSlug: issue.workspace_detail.slug,
|
||||||
|
workspaceId: issue.workspace_detail.id,
|
||||||
|
projectId: issue.project_detail.id,
|
||||||
|
projectIdentifier: issue.project_detail.identifier,
|
||||||
|
projectName: issue.project_detail.name,
|
||||||
|
issueId: issue.id,
|
||||||
|
},
|
||||||
|
"ISSUE_PROPERTY_UPDATE_PRIORITY"
|
||||||
|
);
|
||||||
|
}}
|
||||||
maxHeight="md"
|
maxHeight="md"
|
||||||
customButton={
|
customButton={
|
||||||
<button
|
<button
|
||||||
|
@ -4,6 +4,7 @@ import useSWR from "swr";
|
|||||||
|
|
||||||
// services
|
// services
|
||||||
import stateService from "services/state.service";
|
import stateService from "services/state.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
// ui
|
// ui
|
||||||
import { CustomSearchSelect, Tooltip } from "components/ui";
|
import { CustomSearchSelect, Tooltip } from "components/ui";
|
||||||
// icons
|
// icons
|
||||||
@ -58,13 +59,38 @@ export const ViewStateSelect: React.FC<Props> = ({
|
|||||||
return (
|
return (
|
||||||
<CustomSearchSelect
|
<CustomSearchSelect
|
||||||
value={issue.state}
|
value={issue.state}
|
||||||
onChange={(data: string) =>
|
onChange={(data: string) => {
|
||||||
partialUpdateIssue({
|
partialUpdateIssue({
|
||||||
state: data,
|
state: data,
|
||||||
priority: issue.priority,
|
priority: issue.priority,
|
||||||
target_date: issue.target_date,
|
target_date: issue.target_date,
|
||||||
})
|
});
|
||||||
|
trackEventServices.trackIssuePartialPropertyUpdateEvent(
|
||||||
|
{
|
||||||
|
workspaceSlug: issue.workspace_detail.slug,
|
||||||
|
workspaceId: issue.workspace_detail.id,
|
||||||
|
projectId: issue.project_detail.id,
|
||||||
|
projectIdentifier: issue.project_detail.identifier,
|
||||||
|
projectName: issue.project_detail.name,
|
||||||
|
issueId: issue.id,
|
||||||
|
},
|
||||||
|
"ISSUE_PROPERTY_UPDATE_STATE"
|
||||||
|
);
|
||||||
|
|
||||||
|
const oldState = states.find((s) => s.id === issue.state);
|
||||||
|
const newState = states.find((s) => s.id === data);
|
||||||
|
|
||||||
|
if (oldState?.group !== "completed" && newState?.group !== "completed") {
|
||||||
|
trackEventServices.trackIssueMarkedAsDoneEvent({
|
||||||
|
workspaceSlug: issue.workspace_detail.slug,
|
||||||
|
workspaceId: issue.workspace_detail.id,
|
||||||
|
projectId: issue.project_detail.id,
|
||||||
|
projectIdentifier: issue.project_detail.identifier,
|
||||||
|
projectName: issue.project_detail.name,
|
||||||
|
issueId: issue.id,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
options={options}
|
options={options}
|
||||||
label={
|
label={
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
@ -6,6 +6,7 @@ import useSWR, { mutate } from "swr";
|
|||||||
|
|
||||||
// services
|
// services
|
||||||
import projectService from "services/project.service";
|
import projectService from "services/project.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
// lib
|
// lib
|
||||||
import { requiredAdmin } from "lib/auth";
|
import { requiredAdmin } from "lib/auth";
|
||||||
// layouts
|
// layouts
|
||||||
@ -112,7 +113,19 @@ const FeaturesSettings: NextPage<UserAuth> = (props) => {
|
|||||||
}`}
|
}`}
|
||||||
role="switch"
|
role="switch"
|
||||||
aria-checked={projectDetails?.cycle_view}
|
aria-checked={projectDetails?.cycle_view}
|
||||||
onClick={() => handleSubmit({ cycle_view: !projectDetails?.cycle_view })}
|
onClick={() => {
|
||||||
|
trackEventServices.trackMiscellaneousEvent(
|
||||||
|
{
|
||||||
|
workspaceId: (projectDetails?.workspace as any)?.id,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
projectIdentifier: projectDetails?.identifier,
|
||||||
|
projectName: projectDetails?.name,
|
||||||
|
},
|
||||||
|
!projectDetails?.cycle_view ? "TOGGLE_CYCLE_ON" : "TOGGLE_CYCLE_OFF"
|
||||||
|
);
|
||||||
|
handleSubmit({ cycle_view: !projectDetails?.cycle_view });
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<span className="sr-only">Use cycles</span>
|
<span className="sr-only">Use cycles</span>
|
||||||
<span
|
<span
|
||||||
@ -141,7 +154,19 @@ const FeaturesSettings: NextPage<UserAuth> = (props) => {
|
|||||||
}`}
|
}`}
|
||||||
role="switch"
|
role="switch"
|
||||||
aria-checked={projectDetails?.module_view}
|
aria-checked={projectDetails?.module_view}
|
||||||
onClick={() => handleSubmit({ module_view: !projectDetails?.module_view })}
|
onClick={() => {
|
||||||
|
trackEventServices.trackMiscellaneousEvent(
|
||||||
|
{
|
||||||
|
workspaceId: (projectDetails?.workspace as any)?.id,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
projectIdentifier: projectDetails?.identifier,
|
||||||
|
projectName: projectDetails?.name,
|
||||||
|
},
|
||||||
|
!projectDetails?.module_view ? "TOGGLE_MODULE_ON" : "TOGGLE_MODULE_OFF"
|
||||||
|
);
|
||||||
|
handleSubmit({ module_view: !projectDetails?.module_view });
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<span className="sr-only">Use cycles</span>
|
<span className="sr-only">Use cycles</span>
|
||||||
<span
|
<span
|
||||||
@ -170,7 +195,19 @@ const FeaturesSettings: NextPage<UserAuth> = (props) => {
|
|||||||
}`}
|
}`}
|
||||||
role="switch"
|
role="switch"
|
||||||
aria-checked={projectDetails?.issue_views_view}
|
aria-checked={projectDetails?.issue_views_view}
|
||||||
onClick={() => handleSubmit({ issue_views_view: !projectDetails?.issue_views_view })}
|
onClick={() => {
|
||||||
|
trackEventServices.trackMiscellaneousEvent(
|
||||||
|
{
|
||||||
|
workspaceId: (projectDetails?.workspace as any)?.id,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
projectIdentifier: projectDetails?.identifier,
|
||||||
|
projectName: projectDetails?.name,
|
||||||
|
},
|
||||||
|
!projectDetails?.issue_views_view ? "TOGGLE_VIEW_ON" : "TOGGLE_VIEW_OFF"
|
||||||
|
);
|
||||||
|
handleSubmit({ issue_views_view: !projectDetails?.issue_views_view });
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<span className="sr-only">Use views</span>
|
<span className="sr-only">Use views</span>
|
||||||
<span
|
<span
|
||||||
@ -199,7 +236,19 @@ const FeaturesSettings: NextPage<UserAuth> = (props) => {
|
|||||||
}`}
|
}`}
|
||||||
role="switch"
|
role="switch"
|
||||||
aria-checked={projectDetails?.page_view}
|
aria-checked={projectDetails?.page_view}
|
||||||
onClick={() => handleSubmit({ page_view: !projectDetails?.page_view })}
|
onClick={() => {
|
||||||
|
trackEventServices.trackMiscellaneousEvent(
|
||||||
|
{
|
||||||
|
workspaceId: (projectDetails?.workspace as any)?.id,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
projectIdentifier: projectDetails?.identifier,
|
||||||
|
projectName: projectDetails?.name,
|
||||||
|
},
|
||||||
|
!projectDetails?.page_view ? "TOGGLE_PAGES_ON" : "TOGGLE_PAGES_OFF"
|
||||||
|
);
|
||||||
|
handleSubmit({ page_view: !projectDetails?.page_view });
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<span className="sr-only">Use cycles</span>
|
<span className="sr-only">Use cycles</span>
|
||||||
<span
|
<span
|
||||||
|
@ -99,7 +99,22 @@ class ProjectIssuesServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackIssueMovedToCycleOrModuleEvent(
|
||||||
|
{
|
||||||
|
workspaceSlug,
|
||||||
|
workspaceName: response?.data?.[0]?.issue_detail?.workspace_detail?.name,
|
||||||
|
projectId,
|
||||||
|
projectIdentifier: response?.data?.[0]?.issue_detail?.project_detail?.identifier,
|
||||||
|
projectName: response?.data?.[0]?.issue_detail?.project_detail?.name,
|
||||||
|
issueId: response?.data?.[0]?.issue_detail?.id,
|
||||||
|
cycleId,
|
||||||
|
},
|
||||||
|
response.data.length > 1 ? "ISSUE_MOVED_TO_CYCLE_IN_BULK" : "ISSUE_MOVED_TO_CYCLE"
|
||||||
|
);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -158,7 +173,11 @@ class ProjectIssuesServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackIssueCommentEvent(response.data, "ISSUE_COMMENT_CREATE");
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -175,7 +194,11 @@ class ProjectIssuesServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/${commentId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/${commentId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackIssueCommentEvent(response.data, "ISSUE_COMMENT_UPDATE");
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -190,7 +213,17 @@ class ProjectIssuesServices extends APIService {
|
|||||||
return this.delete(
|
return this.delete(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/${commentId}/`
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/${commentId}/`
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackIssueCommentEvent(
|
||||||
|
{
|
||||||
|
issueId,
|
||||||
|
commentId,
|
||||||
|
},
|
||||||
|
"ISSUE_COMMENT_DELETE"
|
||||||
|
);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -204,9 +237,29 @@ class ProjectIssuesServices extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async createIssueLabel(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
async createIssueLabel(
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
data: any
|
||||||
|
): Promise<IIssueLabels> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/`, data)
|
||||||
.then((response) => response?.data)
|
.then((response: { data: IIssueLabels; [key: string]: any }) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackIssueLabelEvent(
|
||||||
|
{
|
||||||
|
workSpaceId: response?.data?.workspace_detail?.id,
|
||||||
|
workSpaceName: response?.data?.workspace_detail?.name,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
projectIdentifier: response?.data?.project_detail?.identifier,
|
||||||
|
projectName: response?.data?.project_detail?.name,
|
||||||
|
labelId: response?.data?.id,
|
||||||
|
color: response?.data?.color,
|
||||||
|
},
|
||||||
|
"ISSUE_LABEL_CREATE"
|
||||||
|
);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -222,7 +275,23 @@ class ProjectIssuesServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/${labelId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/${labelId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackIssueLabelEvent(
|
||||||
|
{
|
||||||
|
workSpaceId: response?.data?.workspace_detail?.id,
|
||||||
|
workSpaceName: response?.data?.workspace_detail?.name,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
projectIdentifier: response?.data?.project_detail?.identifier,
|
||||||
|
projectName: response?.data?.project_detail?.name,
|
||||||
|
labelId: response?.data?.id,
|
||||||
|
color: response?.data?.color,
|
||||||
|
},
|
||||||
|
"ISSUE_LABEL_UPDATE"
|
||||||
|
);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -232,7 +301,17 @@ class ProjectIssuesServices extends APIService {
|
|||||||
return this.delete(
|
return this.delete(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/${labelId}/`
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/${labelId}/`
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackIssueLabelEvent(
|
||||||
|
{
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
},
|
||||||
|
"ISSUE_LABEL_DELETE"
|
||||||
|
);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -138,7 +138,22 @@ class ProjectIssuesServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-issues/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-issues/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackIssueMovedToCycleOrModuleEvent(
|
||||||
|
{
|
||||||
|
workspaceSlug,
|
||||||
|
workspaceName: response?.data?.[0]?.issue_detail?.workspace_detail?.name,
|
||||||
|
projectId,
|
||||||
|
projectIdentifier: response?.data?.[0]?.issue_detail?.project_detail?.identifier,
|
||||||
|
projectName: response?.data?.[0]?.issue_detail?.project_detail?.name,
|
||||||
|
issueId: response?.data?.[0]?.issue_detail?.id,
|
||||||
|
moduleId,
|
||||||
|
},
|
||||||
|
response?.data?.length > 1 ? "ISSUE_MOVED_TO_MODULE_IN_BULK" : "ISSUE_MOVED_TO_MODULE"
|
||||||
|
);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -89,7 +89,20 @@ class ProjectServices extends APIService {
|
|||||||
|
|
||||||
async inviteProject(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
async inviteProject(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/add/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/add/`, data)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackProjectEvent(
|
||||||
|
{
|
||||||
|
workspaceId: response?.data?.workspace?.id,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
projectName: response?.data?.project?.name,
|
||||||
|
memberEmail: response?.data?.member?.email,
|
||||||
|
},
|
||||||
|
"PROJECT_MEMBER_INVITE"
|
||||||
|
);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -9,6 +9,7 @@ import type {
|
|||||||
ICycle,
|
ICycle,
|
||||||
IGptResponse,
|
IGptResponse,
|
||||||
IIssue,
|
IIssue,
|
||||||
|
IIssueComment,
|
||||||
IModule,
|
IModule,
|
||||||
IPage,
|
IPage,
|
||||||
IPageBlock,
|
IPageBlock,
|
||||||
@ -26,7 +27,11 @@ type WorkspaceEventType =
|
|||||||
| "WORKSPACE_USER_INVITE_ACCEPT"
|
| "WORKSPACE_USER_INVITE_ACCEPT"
|
||||||
| "WORKSPACE_USER_BULK_INVITE_ACCEPT";
|
| "WORKSPACE_USER_BULK_INVITE_ACCEPT";
|
||||||
|
|
||||||
type ProjectEventType = "CREATE_PROJECT" | "UPDATE_PROJECT" | "DELETE_PROJECT";
|
type ProjectEventType =
|
||||||
|
| "CREATE_PROJECT"
|
||||||
|
| "UPDATE_PROJECT"
|
||||||
|
| "DELETE_PROJECT"
|
||||||
|
| "PROJECT_MEMBER_INVITE";
|
||||||
|
|
||||||
type IssueEventType = "ISSUE_CREATE" | "ISSUE_UPDATE" | "ISSUE_DELETE";
|
type IssueEventType = "ISSUE_CREATE" | "ISSUE_UPDATE" | "ISSUE_DELETE";
|
||||||
|
|
||||||
@ -40,12 +45,32 @@ type PagesEventType = "PAGE_CREATE" | "PAGE_UPDATE" | "PAGE_DELETE";
|
|||||||
|
|
||||||
type ViewEventType = "VIEW_CREATE" | "VIEW_UPDATE" | "VIEW_DELETE";
|
type ViewEventType = "VIEW_CREATE" | "VIEW_UPDATE" | "VIEW_DELETE";
|
||||||
|
|
||||||
|
type IssueCommentType = "ISSUE_COMMENT_CREATE" | "ISSUE_COMMENT_UPDATE" | "ISSUE_COMMENT_DELETE";
|
||||||
|
|
||||||
|
type MiscellaneousEventType =
|
||||||
|
| "TOGGLE_CYCLE_ON"
|
||||||
|
| "TOGGLE_CYCLE_OFF"
|
||||||
|
| "TOGGLE_MODULE_ON"
|
||||||
|
| "TOGGLE_MODULE_OFF"
|
||||||
|
| "TOGGLE_VIEW_ON"
|
||||||
|
| "TOGGLE_VIEW_OFF"
|
||||||
|
| "TOGGLE_PAGES_ON"
|
||||||
|
| "TOGGLE_PAGES_OFF"
|
||||||
|
| "TOGGLE_STATE_ON"
|
||||||
|
| "TOGGLE_STATE_OFF";
|
||||||
|
|
||||||
|
type IntegrationEventType = "ADD_WORKSPACE_INTEGRATION" | "REMOVE_WORKSPACE_INTEGRATION";
|
||||||
|
|
||||||
|
type GitHubSyncEventType = "GITHUB_REPO_SYNC";
|
||||||
|
|
||||||
type PageBlocksEventType =
|
type PageBlocksEventType =
|
||||||
| "PAGE_BLOCK_CREATE"
|
| "PAGE_BLOCK_CREATE"
|
||||||
| "PAGE_BLOCK_UPDATE"
|
| "PAGE_BLOCK_UPDATE"
|
||||||
| "PAGE_BLOCK_DELETE"
|
| "PAGE_BLOCK_DELETE"
|
||||||
| "PAGE_BLOCK_CONVERTED_TO_ISSUE";
|
| "PAGE_BLOCK_CONVERTED_TO_ISSUE";
|
||||||
|
|
||||||
|
type IssueLabelEventType = "ISSUE_LABEL_CREATE" | "ISSUE_LABEL_UPDATE" | "ISSUE_LABEL_DELETE";
|
||||||
|
|
||||||
type GptEventType = "ASK_GPT" | "USE_GPT_RESPONSE_IN_ISSUE" | "USE_GPT_RESPONSE_IN_PAGE_BLOCK";
|
type GptEventType = "ASK_GPT" | "USE_GPT_RESPONSE_IN_ISSUE" | "USE_GPT_RESPONSE_IN_PAGE_BLOCK";
|
||||||
|
|
||||||
class TrackEventServices extends APIService {
|
class TrackEventServices extends APIService {
|
||||||
@ -85,7 +110,7 @@ class TrackEventServices extends APIService {
|
|||||||
eventName: ProjectEventType
|
eventName: ProjectEventType
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
let payload: any;
|
let payload: any;
|
||||||
if (eventName !== "DELETE_PROJECT")
|
if (eventName !== "DELETE_PROJECT" && eventName !== "PROJECT_MEMBER_INVITE")
|
||||||
payload = {
|
payload = {
|
||||||
workspaceId: data?.workspace_detail?.id,
|
workspaceId: data?.workspace_detail?.id,
|
||||||
workspaceName: data?.workspace_detail?.name,
|
workspaceName: data?.workspace_detail?.name,
|
||||||
@ -131,7 +156,6 @@ class TrackEventServices extends APIService {
|
|||||||
projectName: data?.project_detail?.name,
|
projectName: data?.project_detail?.name,
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
projectIdentifier: data?.project_detail?.identifier,
|
||||||
issueId: data?.id,
|
issueId: data?.id,
|
||||||
issueTitle: data?.name,
|
|
||||||
};
|
};
|
||||||
else payload = data;
|
else payload = data;
|
||||||
|
|
||||||
@ -147,6 +171,89 @@ class TrackEventServices extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async trackIssueMarkedAsDoneEvent(data: any): Promise<any> {
|
||||||
|
if (!trackEvent) return;
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "ISSUES_MARKED_AS_DONE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackIssuePartialPropertyUpdateEvent(
|
||||||
|
data: any,
|
||||||
|
propertyName:
|
||||||
|
| "ISSUE_PROPERTY_UPDATE_PRIORITY"
|
||||||
|
| "ISSUE_PROPERTY_UPDATE_STATE"
|
||||||
|
| "ISSUE_PROPERTY_UPDATE_ASSIGNEE"
|
||||||
|
| "ISSUE_PROPERTY_UPDATE_DUE_DATE"
|
||||||
|
): Promise<any> {
|
||||||
|
if (!trackEvent) return;
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: propertyName,
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackIssueCommentEvent(
|
||||||
|
data: Partial<IIssueComment> | any,
|
||||||
|
eventName: IssueCommentType
|
||||||
|
): Promise<any> {
|
||||||
|
let payload: any;
|
||||||
|
if (eventName !== "ISSUE_COMMENT_DELETE")
|
||||||
|
payload = {
|
||||||
|
workspaceId: data?.workspace_detail?.id,
|
||||||
|
workspaceName: data?.workspace_detail?.name,
|
||||||
|
workspaceSlug: data?.workspace_detail?.slug,
|
||||||
|
projectId: data?.project_detail?.id,
|
||||||
|
projectName: data?.project_detail?.name,
|
||||||
|
projectIdentifier: data?.project_detail?.identifier,
|
||||||
|
issueId: data?.issue,
|
||||||
|
};
|
||||||
|
else payload = data;
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName,
|
||||||
|
extra: {
|
||||||
|
...payload,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackIssueMovedToCycleOrModuleEvent(
|
||||||
|
data: any,
|
||||||
|
eventName:
|
||||||
|
| "ISSUE_MOVED_TO_CYCLE"
|
||||||
|
| "ISSUE_MOVED_TO_MODULE"
|
||||||
|
| "ISSUE_MOVED_TO_CYCLE_IN_BULK"
|
||||||
|
| "ISSUE_MOVED_TO_MODULE_IN_BULK"
|
||||||
|
): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName,
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async trackIssueBulkDeleteEvent(data: any): Promise<any> {
|
async trackIssueBulkDeleteEvent(data: any): Promise<any> {
|
||||||
return this.request({
|
return this.request({
|
||||||
url: "/api/track-event",
|
url: "/api/track-event",
|
||||||
@ -160,6 +267,19 @@ class TrackEventServices extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async trackIssueLabelEvent(data: any, eventName: IssueLabelEventType): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName,
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async trackStateEvent(data: IState | any, eventName: StateEventType): Promise<any> {
|
async trackStateEvent(data: IState | any, eventName: StateEventType): Promise<any> {
|
||||||
let payload: any;
|
let payload: any;
|
||||||
if (eventName !== "STATE_DELETE")
|
if (eventName !== "STATE_DELETE")
|
||||||
@ -171,7 +291,6 @@ class TrackEventServices extends APIService {
|
|||||||
projectName: data?.project_detail?.name,
|
projectName: data?.project_detail?.name,
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
projectIdentifier: data?.project_detail?.identifier,
|
||||||
stateId: data.id,
|
stateId: data.id,
|
||||||
stateName: data.name,
|
|
||||||
};
|
};
|
||||||
else payload = data;
|
else payload = data;
|
||||||
|
|
||||||
@ -198,7 +317,6 @@ class TrackEventServices extends APIService {
|
|||||||
projectName: data?.project_detail?.name,
|
projectName: data?.project_detail?.name,
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
projectIdentifier: data?.project_detail?.identifier,
|
||||||
cycleId: data.id,
|
cycleId: data.id,
|
||||||
cycleName: data.name,
|
|
||||||
};
|
};
|
||||||
else payload = data;
|
else payload = data;
|
||||||
|
|
||||||
@ -225,7 +343,6 @@ class TrackEventServices extends APIService {
|
|||||||
projectName: data.project_detail?.name,
|
projectName: data.project_detail?.name,
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
projectIdentifier: data?.project_detail?.identifier,
|
||||||
moduleId: data.id,
|
moduleId: data.id,
|
||||||
moduleName: data.name,
|
|
||||||
};
|
};
|
||||||
else payload = data;
|
else payload = data;
|
||||||
|
|
||||||
@ -392,6 +509,45 @@ class TrackEventServices extends APIService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async trackMiscellaneousEvent(data: any, eventName: MiscellaneousEventType): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName,
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackAppIntegrationEvent(data: any, eventName: IntegrationEventType): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName,
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackGitHubSyncEvent(data: any, eventName: GitHubSyncEventType): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName,
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const trackEventServices = new TrackEventServices();
|
const trackEventServices = new TrackEventServices();
|
||||||
|
4
apps/app/types/issues.d.ts
vendored
4
apps/app/types/issues.d.ts
vendored
@ -160,7 +160,9 @@ export interface IIssueComment {
|
|||||||
created_by: string;
|
created_by: string;
|
||||||
updated_by: string;
|
updated_by: string;
|
||||||
project: string;
|
project: string;
|
||||||
|
project_detail: IProjectLite;
|
||||||
workspace: string;
|
workspace: string;
|
||||||
|
workspace_detail: IWorkspaceLite;
|
||||||
issue: string;
|
issue: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +197,9 @@ export interface IIssueLabels {
|
|||||||
created_by: string;
|
created_by: string;
|
||||||
updated_by: string;
|
updated_by: string;
|
||||||
project: string;
|
project: string;
|
||||||
|
project_detail: IProjectLite;
|
||||||
workspace: string;
|
workspace: string;
|
||||||
|
workspace_detail: IWorkspaceLite;
|
||||||
parent: string | null;
|
parent: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user