feat: added tracker for page, page block, and gpt (#623)

* refactor: made events function generic

* feat: added tracker for page, page block, and gpt
This commit is contained in:
Dakshesh Jain 2023-03-30 19:27:46 +05:30 committed by GitHub
parent 50275fd2ad
commit 66ed6a1dc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 375 additions and 360 deletions

View File

@ -7,11 +7,13 @@ import dynamic from "next/dynamic";
import { useForm } from "react-hook-form";
// services
import aiService from "services/ai.service";
import trackEventServices from "services/track-event.service";
// hooks
import useToast from "hooks/use-toast";
// ui
import { Input, PrimaryButton, SecondaryButton } from "components/ui";
import { IIssue, IPageBlock } from "types";
type Props = {
isOpen: boolean;
handleClose: () => void;
@ -20,6 +22,8 @@ type Props = {
htmlContent?: string;
onResponse: (response: string) => void;
projectId: string;
block?: IPageBlock;
issue?: IIssue;
};
type FormData = {
@ -39,6 +43,8 @@ export const GptAssistantModal: React.FC<Props> = ({
htmlContent,
onResponse,
projectId,
block,
issue,
}) => {
const [response, setResponse] = useState("");
const [invalidResponse, setInvalidResponse] = useState(false);
@ -166,6 +172,13 @@ export const GptAssistantModal: React.FC<Props> = ({
onClick={() => {
onResponse(response);
onClose();
if (block)
trackEventServices.trackUseGPTResponseEvent(
block,
"USE_GPT_RESPONSE_IN_PAGE_BLOCK"
);
else if (issue)
trackEventServices.trackUseGPTResponseEvent(issue, "USE_GPT_RESPONSE_IN_ISSUE");
}}
>
Use this response

View File

@ -21,11 +21,7 @@ import { CustomMenu, Input, Loader, TextArea } from "components/ui";
// icons
import { LayerDiagonalIcon } from "components/icons";
import { ArrowPathIcon } from "@heroicons/react/20/solid";
import {
BoltIcon,
CheckIcon,
SparklesIcon,
} from "@heroicons/react/24/outline";
import { BoltIcon, CheckIcon, SparklesIcon } from "@heroicons/react/24/outline";
// helpers
import { copyTextToClipboard } from "helpers/string.helper";
// types
@ -326,6 +322,7 @@ export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails }) => {
)}
/>
<GptAssistantModal
block={block}
isOpen={gptAssistantModal}
handleClose={() => setGptAssistantModal(false)}
inset="top-2 left-0"

View File

@ -37,12 +37,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
// TODO: cache user info
jitsu
.id({
id: user.id,
email: user.email,
first_name: user.first_name,
last_name: user.last_name,
})
.id(
{
id: user.id,
email: user.email,
first_name: user.first_name,
last_name: user.last_name,
},
true
)
.then(() => {
jitsu.track(eventName, {
...extra,

View File

@ -1,10 +1,15 @@
// services
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
// types
import { IGptResponse } from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class AiServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
@ -16,7 +21,10 @@ class AiServices extends APIService {
data: { prompt: string; task: string }
): Promise<IGptResponse> {
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/ai-assistant/`, data)
.then((response) => response?.data)
.then((response) => {
if (trackEvent) trackEventServices.trackAskGptEvent(response?.data, "ASK_GPT");
return response?.data;
})
.catch((error) => {
throw error?.response;
});

View File

@ -26,7 +26,7 @@ class ProjectCycleServices extends APIService {
async createCycle(workspaceSlug: string, projectId: string, data: any): Promise<any> {
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/`, data)
.then((response) => {
if (trackEvent) trackEventServices.trackCycleCreateEvent(response?.data);
if (trackEvent) trackEventServices.trackCycleEvent(response?.data, "CYCLE_CREATE");
return response?.data;
})
.catch((error) => {
@ -103,7 +103,7 @@ class ProjectCycleServices extends APIService {
data
)
.then((response) => {
if (trackEvent) trackEventServices.trackCycleUpdateEvent(response?.data);
if (trackEvent) trackEventServices.trackCycleEvent(response?.data, "CYCLE_UPDATE");
return response?.data;
})
.catch((error) => {
@ -122,7 +122,7 @@ class ProjectCycleServices extends APIService {
data
)
.then((response) => {
if (trackEvent) trackEventServices.trackCycleUpdateEvent(response?.data);
if (trackEvent) trackEventServices.trackCycleEvent(response?.data, "CYCLE_UPDATE");
return response?.data;
})
.catch((error) => {
@ -133,7 +133,7 @@ class ProjectCycleServices extends APIService {
async deleteCycle(workspaceSlug: string, projectId: string, cycleId: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`)
.then((response) => {
if (trackEvent) trackEventServices.trackCycleDeleteEvent(response?.data);
if (trackEvent) trackEventServices.trackCycleEvent(response?.data, "CYCLE_DELETE");
return response?.data;
})
.catch((error) => {

View File

@ -17,7 +17,7 @@ class ProjectIssuesServices extends APIService {
async createIssues(workspaceSlug: string, projectId: string, data: any): Promise<any> {
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, data)
.then((response) => {
if (trackEvent) trackEventServices.trackIssueCreateEvent(response.data);
if (trackEvent) trackEventServices.trackIssueEvent(response.data, "ISSUE_CREATE");
return response?.data;
})
.catch((error) => {
@ -249,7 +249,7 @@ class ProjectIssuesServices extends APIService {
data
)
.then((response) => {
if (trackEvent) trackEventServices.trackIssueUpdateEvent(data);
if (trackEvent) trackEventServices.trackIssueEvent(response.data, "ISSUE_UPDATE");
return response?.data;
})
.catch((error) => {
@ -268,7 +268,7 @@ class ProjectIssuesServices extends APIService {
data
)
.then((response) => {
if (trackEvent) trackEventServices.trackIssueUpdateEvent(data);
if (trackEvent) trackEventServices.trackIssueEvent(response.data, "ISSUE_UPDATE");
return response?.data;
})
.catch((error) => {
@ -279,7 +279,7 @@ class ProjectIssuesServices extends APIService {
async deleteIssue(workspaceSlug: string, projectId: string, issuesId: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issuesId}/`)
.then((response) => {
if (trackEvent) trackEventServices.trackIssueDeleteEvent({ issuesId });
if (trackEvent) trackEventServices.trackIssueEvent({ issuesId }, "ISSUE_DELETE");
return response?.data;
})
.catch((error) => {

View File

@ -26,7 +26,7 @@ class ProjectIssuesServices extends APIService {
async createModule(workspaceSlug: string, projectId: string, data: any): Promise<any> {
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/`, data)
.then((response) => {
if (trackEvent) trackEventServices.trackModuleCreateEvent(response?.data);
if (trackEvent) trackEventServices.trackModuleEvent(response?.data, "MODULE_CREATE");
return response?.data;
})
.catch((error) => {
@ -45,7 +45,7 @@ class ProjectIssuesServices extends APIService {
data
)
.then((response) => {
if (trackEvent) trackEventServices.trackModuleUpdateEvent(response?.data);
if (trackEvent) trackEventServices.trackModuleEvent(response?.data, "MODULE_UPDATE");
return response?.data;
})
.catch((error) => {
@ -72,7 +72,7 @@ class ProjectIssuesServices extends APIService {
data
)
.then((response) => {
if (trackEvent) trackEventServices.trackModuleUpdateEvent(response?.data);
if (trackEvent) trackEventServices.trackModuleEvent(response?.data, "MODULE_UPDATE");
return response?.data;
})
.catch((error) => {
@ -85,7 +85,7 @@ class ProjectIssuesServices extends APIService {
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`
)
.then((response) => {
if (trackEvent) trackEventServices.trackModuleDeleteEvent(response?.data);
if (trackEvent) trackEventServices.trackModuleEvent(response?.data, "MODULE_DELETE");
return response?.data;
})
.catch((error) => {

View File

@ -1,11 +1,15 @@
// services
import APIService from "services/api.service";
import { IIssue } from "types";
import trackEventServices from "services/track-event.service";
// types
import { IPage, IPageBlock, RecentPagesResponse } from "types/pages";
import { IPage, IPageBlock, RecentPagesResponse, IIssue } from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class PageServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
@ -13,7 +17,10 @@ class PageServices extends APIService {
async createPage(workspaceSlug: string, projectId: string, data: Partial<IPage>): Promise<IPage> {
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/`, data)
.then((response) => response?.data)
.then((response) => {
if (trackEvent) trackEventServices.trackPageEvent(response?.data, "PAGE_CREATE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
@ -29,7 +36,10 @@ class PageServices extends APIService {
`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`,
data
)
.then((response) => response?.data)
.then((response) => {
if (trackEvent) trackEventServices.trackPageEvent(response?.data, "PAGE_UPDATE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
@ -37,7 +47,10 @@ class PageServices extends APIService {
async deletePage(workspaceSlug: string, projectId: string, pageId: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`)
.then((response) => response?.data)
.then((response) => {
if (trackEvent) trackEventServices.trackPageEvent(response?.data, "PAGE_DELETE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
@ -130,7 +143,10 @@ class PageServices extends APIService {
`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/page-blocks/`,
data
)
.then((response) => response?.data)
.then((response) => {
if (trackEvent) trackEventServices.trackPageBlockEvent(response?.data, "PAGE_BLOCK_CREATE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
@ -162,7 +178,10 @@ class PageServices extends APIService {
`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/page-blocks/${pageBlockId}/`,
data
)
.then((response) => response?.data)
.then((response) => {
if (trackEvent) trackEventServices.trackPageBlockEvent(response?.data, "PAGE_BLOCK_UPDATE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
@ -177,7 +196,10 @@ class PageServices extends APIService {
return this.delete(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/page-blocks/${pageBlockId}/`
)
.then((response) => response?.data)
.then((response) => {
if (trackEvent) trackEventServices.trackPageBlockEvent(response?.data, "PAGE_BLOCK_DELETE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
@ -206,7 +228,11 @@ class PageServices extends APIService {
return this.post(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/page-blocks/${blockId}/issues/`
)
.then((response) => response?.data)
.then((response) => {
if (trackEvent)
trackEventServices.trackPageBlockEvent(response?.data, "PAGE_BLOCK_CONVERTED_TO_ISSUE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});

View File

@ -25,7 +25,7 @@ class ProjectServices extends APIService {
async createProject(workspaceSlug: string, data: Partial<IProject>): Promise<IProject> {
return this.post(`/api/workspaces/${workspaceSlug}/projects/`, data)
.then((response) => {
if (trackEvent) trackEventServices.trackCreateProjectEvent(response.data);
if (trackEvent) trackEventServices.trackProjectEvent(response.data, "CREATE_PROJECT");
return response?.data;
})
.catch((error) => {
@ -68,7 +68,7 @@ class ProjectServices extends APIService {
): Promise<IProject> {
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`, data)
.then((response) => {
if (trackEvent) trackEventServices.trackUpdateProjectEvent(response.data);
if (trackEvent) trackEventServices.trackProjectEvent(response.data, "UPDATE_PROJECT");
return response?.data;
})
.catch((error) => {
@ -79,7 +79,7 @@ class ProjectServices extends APIService {
async deleteProject(workspaceSlug: string, projectId: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`)
.then((response) => {
if (trackEvent) trackEventServices.trackDeleteProjectEvent({ projectId });
if (trackEvent) trackEventServices.trackProjectEvent({ projectId }, "DELETE_PROJECT");
return response?.data;
})
.catch((error) => {

View File

@ -18,7 +18,7 @@ class ProjectStateServices extends APIService {
async createState(workspaceSlug: string, projectId: string, data: any): Promise<any> {
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/`, data)
.then((response) => {
if (trackEvent) trackEventServices.trackStateCreateEvent(response?.data);
if (trackEvent) trackEventServices.trackStateEvent(response?.data, "STATE_CREATE");
return response?.data;
})
.catch((error) => {
@ -62,7 +62,7 @@ class ProjectStateServices extends APIService {
data
)
.then((response) => {
if (trackEvent) trackEventServices.trackStateUpdateEvent(response?.data);
if (trackEvent) trackEventServices.trackStateEvent(response?.data, "STATE_UPDATE");
return response?.data;
})
.catch((error) => {
@ -81,7 +81,7 @@ class ProjectStateServices extends APIService {
data
)
.then((response) => {
if (trackEvent) trackEventServices.trackStateUpdateEvent(response?.data);
if (trackEvent) trackEventServices.trackStateEvent(response?.data, "STATE_UPDATE");
return response?.data;
})
.catch((error) => {
@ -92,7 +92,7 @@ class ProjectStateServices extends APIService {
async deleteState(workspaceSlug: string, projectId: string, stateId: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`)
.then((response) => {
if (trackEvent) trackEventServices.trackStateDeleteEvent(response?.data);
if (trackEvent) trackEventServices.trackStateEvent(response?.data, "STATE_DELETE");
return response?.data;
})
.catch((error) => {

View File

@ -1,25 +1,75 @@
// services
import APIService from "services/api.service";
// types
import type { ICycle, IIssue, IModule, IProject, IState, IWorkspace } from "types";
// TODO: as we add more events, we can refactor this to be divided into different classes
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
// types
import type {
ICycle,
IGptResponse,
IIssue,
IModule,
IPage,
IPageBlock,
IProject,
IState,
IWorkspace,
} from "types";
type WorkspaceEventType =
| "CREATE_WORKSPACE"
| "UPDATE_WORKSPACE"
| "DELETE_WORKSPACE"
| "WORKSPACE_USER_INVITE"
| "WORKSPACE_USER_INVITE_ACCEPT"
| "WORKSPACE_USER_BULK_INVITE_ACCEPT";
type ProjectEventType = "CREATE_PROJECT" | "UPDATE_PROJECT" | "DELETE_PROJECT";
type IssueEventType = "ISSUE_CREATE" | "ISSUE_UPDATE" | "ISSUE_DELETE";
type CycleEventType = "CYCLE_CREATE" | "CYCLE_UPDATE" | "CYCLE_DELETE";
type StateEventType = "STATE_CREATE" | "STATE_UPDATE" | "STATE_DELETE";
type ModuleEventType = "MODULE_CREATE" | "MODULE_UPDATE" | "MODULE_DELETE";
type PagesEventType = "PAGE_CREATE" | "PAGE_UPDATE" | "PAGE_DELETE";
type PageBlocksEventType =
| "PAGE_BLOCK_CREATE"
| "PAGE_BLOCK_UPDATE"
| "PAGE_BLOCK_DELETE"
| "PAGE_BLOCK_CONVERTED_TO_ISSUE";
type GptEventType = "ASK_GPT" | "USE_GPT_RESPONSE_IN_ISSUE" | "USE_GPT_RESPONSE_IN_PAGE_BLOCK";
class TrackEventServices extends APIService {
constructor() {
super("/");
}
async trackCreateWorkspaceEvent(data: IWorkspace): Promise<any> {
const payload = {
workspaceId: data.id,
workspaceSlug: data.slug,
workspaceName: data.name,
};
async trackWorkspaceEvent(data: IWorkspace | any, eventName: WorkspaceEventType): Promise<any> {
let payload: any;
if (
eventName !== "DELETE_WORKSPACE" &&
eventName !== "WORKSPACE_USER_INVITE" &&
eventName !== "WORKSPACE_USER_INVITE_ACCEPT" &&
eventName !== "WORKSPACE_USER_BULK_INVITE_ACCEPT"
)
payload = {
workspaceId: data.id,
workspaceSlug: data.slug,
workspaceName: data.name,
};
else payload = data;
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "CREATE_WORKSPACE",
eventName,
extra: {
...payload,
},
@ -27,17 +77,26 @@ class TrackEventServices extends APIService {
});
}
async trackUpdateWorkspaceEvent(data: Partial<IWorkspace>): Promise<any> {
const payload = {
workspaceId: data.id,
workspaceSlug: data.slug,
workspaceName: data.name,
};
async trackProjectEvent(
data: Partial<IProject> | any,
eventName: ProjectEventType
): Promise<any> {
let payload: any;
if (eventName !== "DELETE_PROJECT")
payload = {
workspaceId: data?.workspace_detail?.id,
workspaceName: data?.workspace_detail?.name,
workspaceSlug: data?.workspace_detail?.slug,
projectId: data?.id,
projectName: data?.name,
};
else payload = data;
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "UPDATE_WORKSPACE",
eventName,
extra: {
...payload,
},
@ -45,111 +104,6 @@ class TrackEventServices extends APIService {
});
}
async trackDeleteWorkspaceEvent(data: any): Promise<any> {
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "DELETE_WORKSPACE",
extra: {
...data,
},
},
});
}
async trackCreateProjectEvent(data: IProject): Promise<any> {
const payload = {
workspaceId: data.workspace_detail.id,
workspaceName: data.workspace_detail.name,
workspaceSlug: data.workspace_detail.slug,
projectId: data.id,
projectName: data.name,
};
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "CREATE_PROJECT",
extra: {
...payload,
},
},
});
}
async trackUpdateProjectEvent(data: Partial<IProject>): Promise<any> {
const payload = {
workspaceId: data?.workspace_detail?.id,
workspaceName: data?.workspace_detail?.name,
workspaceSlug: data?.workspace_detail?.slug,
projectId: data.id,
projectName: data.name,
};
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "UPDATE_PROJECT",
extra: {
...payload,
},
},
});
}
async trackDeleteProjectEvent(data: any): Promise<any> {
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "DELETE_PROJECT",
extra: {
...data,
},
},
});
}
async trackWorkspaceUserInviteEvent(data: any): Promise<any> {
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "WORKSPACE_USER_INVITE",
extra: {
...data,
},
},
});
}
async trackWorkspaceUserJoinEvent(data: any): Promise<any> {
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "WORKSPACE_USER_INVITE_ACCEPT",
extra: {
...data,
},
},
});
}
async trackWorkspaceUserBulkJoinEvent(data: any): Promise<any> {
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "WORKSPACE_USER_BULK_INVITE_ACCEPT",
extra: {
...data,
},
},
});
}
async trackUserOnboardingCompleteEvent(data: any): Promise<any> {
return this.request({
url: "/api/track-event",
@ -163,22 +117,26 @@ class TrackEventServices extends APIService {
});
}
async trackIssueCreateEvent(data: IIssue): Promise<any> {
const 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.id,
issueTitle: data.name,
};
async trackIssueEvent(data: IIssue | any, eventName: IssueEventType): Promise<any> {
let payload: any;
if (eventName !== "ISSUE_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?.id,
issueTitle: data?.name,
};
else payload = data;
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "ISSUE_CREATE",
eventName,
extra: {
...payload,
},
@ -186,42 +144,6 @@ class TrackEventServices extends APIService {
});
}
async trackIssueUpdateEvent(data: Partial<IIssue>): Promise<any> {
const 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.id,
issueTitle: data.name,
};
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "ISSUE_UPDATE",
extra: {
...payload,
},
},
});
}
async trackIssueDeleteEvent(data: any): Promise<any> {
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "ISSUE_DELETE",
extra: {
...data,
},
},
});
}
async trackIssueBulkDeleteEvent(data: any): Promise<any> {
return this.request({
url: "/api/track-event",
@ -235,45 +157,168 @@ class TrackEventServices extends APIService {
});
}
async trackStateCreateEvent(data: IState): Promise<any> {
async trackStateEvent(data: IState | any, eventName: StateEventType): Promise<any> {
let payload: any;
if (eventName !== "STATE_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,
stateId: data.id,
stateName: data.name,
};
else payload = data;
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName,
extra: {
...payload,
},
},
});
}
async trackCycleEvent(data: ICycle | any, eventName: CycleEventType): Promise<any> {
let payload: any;
if (eventName !== "CYCLE_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,
cycleId: data.id,
cycleName: data.name,
};
else payload = data;
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName,
extra: {
...payload,
},
},
});
}
async trackModuleEvent(data: IModule | any, eventName: ModuleEventType): Promise<any> {
let payload: any;
if (eventName !== "MODULE_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,
moduleId: data.id,
moduleName: data.name,
};
else payload = data;
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName,
extra: {
...payload,
},
},
});
}
async trackPageEvent(data: Partial<IPage> | any, eventName: PagesEventType): Promise<any> {
let payload: any;
if (eventName !== "PAGE_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,
pageId: data.id,
};
else payload = data;
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName,
extra: {
...payload,
},
},
});
}
async trackPageBlockEvent(
data: Partial<IPageBlock> | IIssue,
eventName: PageBlocksEventType
): Promise<any> {
let payload: any;
if (eventName !== "PAGE_BLOCK_DELETE" && eventName !== "PAGE_BLOCK_CONVERTED_TO_ISSUE")
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,
pageId: (data as IPageBlock)?.page,
pageBlockId: data.id,
};
else if (eventName === "PAGE_BLOCK_CONVERTED_TO_ISSUE") {
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?.id,
};
} else payload = data;
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName,
extra: {
...payload,
},
},
});
}
async trackAskGptEvent(data: IGptResponse, eventName: GptEventType): Promise<any> {
const 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,
stateId: data.id,
stateName: data.name,
};
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "STATE_CREATE",
extra: {
...payload,
},
},
});
}
async trackStateUpdateEvent(data: Partial<IState>): Promise<any> {
const 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,
stateId: data.id,
stateName: data.name,
count: data?.count,
};
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "STATE_UPDATE",
eventName,
extra: {
...payload,
},
@ -281,134 +326,45 @@ class TrackEventServices extends APIService {
});
}
async trackStateDeleteEvent(data: any): Promise<any> {
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "STATE_DELETE",
extra: {
...data,
},
},
});
}
async trackUseGPTResponseEvent(data: IIssue | IPageBlock, eventName: GptEventType): Promise<any> {
if (!trackEvent) return;
let payload: any;
if (eventName === "USE_GPT_RESPONSE_IN_ISSUE") {
payload = {
workspaceId: data?.workspace_detail?.id,
workspaceName: data?.workspace_detail?.name,
workspaceSlug: data?.workspace_detail?.slug,
projectId: data?.project_detail?.id,
projectIdentifier: data?.project_detail?.identifier,
projectName: data?.project_detail?.name,
issueId: data.id,
};
} else if (eventName === "USE_GPT_RESPONSE_IN_PAGE_BLOCK") {
payload = {
workspaceId: data?.workspace_detail?.id,
workspaceName: data?.workspace_detail?.name,
workspaceSlug: data?.workspace_detail?.slug,
projectId: data?.project_detail?.id,
projectIdentifier: data?.project_detail?.identifier,
projectName: data?.project_detail?.name,
pageId: (data as IPageBlock)?.page,
pageBlockId: data.id,
};
}
async trackCycleCreateEvent(data: ICycle): Promise<any> {
const 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,
cycleId: data.id,
cycleName: data.name,
};
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "CYCLE_CREATE",
eventName,
extra: {
...payload,
},
},
});
}
async trackCycleUpdateEvent(data: Partial<ICycle>): Promise<any> {
const 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,
cycleId: data.id,
cycleName: data.name,
};
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "CYCLE_UPDATE",
extra: {
...payload,
},
},
});
}
async trackCycleDeleteEvent(data: any): Promise<any> {
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "CYCLE_DELETE",
extra: {
...data,
},
},
});
}
async trackModuleCreateEvent(data: IModule): Promise<any> {
const 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,
moduleId: data.id,
moduleName: data.name,
};
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "MODULE_CREATE",
extra: {
...payload,
},
},
});
}
async trackModuleUpdateEvent(data: Partial<IModule>): Promise<any> {
const 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,
moduleId: data.id,
moduleName: data.name,
};
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "MODULE_UPDATE",
extra: {
...payload,
},
},
});
}
async trackModuleDeleteEvent(data: any): Promise<any> {
return this.request({
url: "/api/track-event",
method: "POST",
data: {
eventName: "MODULE_DELETE",
extra: {
...data,
},
},
});
}
}
const trackEventServices = new TrackEventServices();

View File

@ -42,7 +42,7 @@ class WorkspaceService extends APIService {
async createWorkspace(data: Partial<IWorkspace>): Promise<IWorkspace> {
return this.post("/api/workspaces/", data)
.then((response) => {
if (trackEvent) trackEventServices.trackCreateWorkspaceEvent(response.data);
if (trackEvent) trackEventServices.trackWorkspaceEvent(response.data, "CREATE_WORKSPACE");
return response?.data;
})
.catch((error) => {
@ -53,7 +53,7 @@ class WorkspaceService extends APIService {
async updateWorkspace(workspaceSlug: string, data: Partial<IWorkspace>): Promise<IWorkspace> {
return this.patch(`/api/workspaces/${workspaceSlug}/`, data)
.then((response) => {
if (trackEvent) trackEventServices.trackUpdateWorkspaceEvent(response.data);
if (trackEvent) trackEventServices.trackWorkspaceEvent(response.data, "UPDATE_WORKSPACE");
return response?.data;
})
.catch((error) => {
@ -64,7 +64,8 @@ class WorkspaceService extends APIService {
async deleteWorkspace(workspaceSlug: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/`)
.then((response) => {
if (trackEvent) trackEventServices.trackDeleteWorkspaceEvent({ workspaceSlug });
if (trackEvent)
trackEventServices.trackWorkspaceEvent({ workspaceSlug }, "DELETE_WORKSPACE");
return response?.data;
})
.catch((error) => {
@ -75,7 +76,8 @@ class WorkspaceService extends APIService {
async inviteWorkspace(workspaceSlug: string, data: any): Promise<any> {
return this.post(`/api/workspaces/${workspaceSlug}/invite/`, data)
.then((response) => {
if (trackEvent) trackEventServices.trackWorkspaceUserInviteEvent(response.data);
if (trackEvent)
trackEventServices.trackWorkspaceEvent(response.data, "WORKSPACE_USER_INVITE");
return response?.data;
})
.catch((error) => {
@ -92,7 +94,8 @@ class WorkspaceService extends APIService {
}
)
.then((response) => {
if (trackEvent) trackEventServices.trackWorkspaceUserJoinEvent(response.data);
if (trackEvent)
trackEventServices.trackWorkspaceEvent(response.data, "WORKSPACE_USER_INVITE_ACCEPT");
return response?.data;
})
.catch((error) => {

View File

@ -1,4 +1,9 @@
import { IProjectLite, IWorkspaceLite } from "types";
export interface IGptResponse {
response: string;
response_html: string;
count: number;
project_detail: IProjectLite;
workspace_detail: IWorkspaceLite;
}

View File

@ -1,5 +1,5 @@
// types
import { IIssue, IIssueLabels } from "./issues";
import { IIssue, IIssueLabels, IWorkspaceLite, IProjectLite } from "types";
export interface IPage {
access: number;
@ -18,9 +18,11 @@ export interface IPage {
name: string;
owned_by: string;
project: string;
project_detail: IProjectLite;
updated_at: Date;
updated_by: string;
workspace: string;
workspace_detail: IWorkspaceLite;
}
export interface RecentPagesResponse {
@ -40,11 +42,13 @@ export interface IPageBlock {
name: string;
page: string;
project: string;
project_detail: IProjectLite;
sort_order: number;
sync: boolean;
updated_at: Date;
updated_by: string;
workspace: string;
workspace_detail: IWorkspaceLite;
}
export type TPageViewProps = "list" | "detailed" | "masonry";