mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
feat: jitsu tracker setup (#542)
* feat: jitsu tracker setup also using it in create, update and delete project & workspace * refactor: added some more check condition on track-event api * fix: added env vars in turbo.json * feat: added user onboard event, workspace invite and workspace invite accept events * feat: add tracker for issues, state, modules and cycles * fix: add @jitsu/nextjs in package.json
This commit is contained in:
parent
9eb9b7bf6c
commit
c3e1d33518
@ -13,6 +13,7 @@
|
|||||||
"@blueprintjs/popover2": "^1.13.3",
|
"@blueprintjs/popover2": "^1.13.3",
|
||||||
"@headlessui/react": "^1.7.3",
|
"@headlessui/react": "^1.7.3",
|
||||||
"@heroicons/react": "^2.0.12",
|
"@heroicons/react": "^2.0.12",
|
||||||
|
"@jitsu/nextjs": "^3.1.5",
|
||||||
"@remirror/core": "^2.0.11",
|
"@remirror/core": "^2.0.11",
|
||||||
"@remirror/extension-react-tables": "^2.2.11",
|
"@remirror/extension-react-tables": "^2.2.11",
|
||||||
"@remirror/pm": "^2.0.3",
|
"@remirror/pm": "^2.0.3",
|
||||||
|
50
apps/app/pages/api/track-event.ts
Normal file
50
apps/app/pages/api/track-event.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
|
||||||
|
// jitsu
|
||||||
|
import { createClient } from "@jitsu/nextjs";
|
||||||
|
import { convertCookieStringToObject } from "lib/cookie";
|
||||||
|
|
||||||
|
const jitsu = createClient({
|
||||||
|
key: process.env.JITSU_ACCESS_KEY || "",
|
||||||
|
tracking_host: "https://t.jitsu.com",
|
||||||
|
});
|
||||||
|
|
||||||
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
const { eventName, extra } = req.body;
|
||||||
|
|
||||||
|
if (!eventName) {
|
||||||
|
return res.status(400).json({ message: "Bad request" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const cookie = convertCookieStringToObject(req.headers.cookie);
|
||||||
|
const accessToken = cookie?.accessToken;
|
||||||
|
|
||||||
|
if (!accessToken) return res.status(401).json({ message: "Unauthorized" });
|
||||||
|
|
||||||
|
const user = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/users/me/`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `Bearer ${accessToken}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((data) => data.user)
|
||||||
|
.catch(() => res.status(401).json({ message: "Unauthorized" }));
|
||||||
|
|
||||||
|
if (!user) return res.status(401).json({ message: "Unauthorized" });
|
||||||
|
|
||||||
|
// TODO: cache user info
|
||||||
|
|
||||||
|
jitsu
|
||||||
|
.id({
|
||||||
|
...user,
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
jitsu.track(eventName, {
|
||||||
|
...extra,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(200).json({ message: "success" });
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
// services
|
// services
|
||||||
import APIService from "services/api.service";
|
import APIService from "services/api.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
|
|
||||||
// types
|
// types
|
||||||
import type {
|
import type {
|
||||||
CycleIssueResponse,
|
CycleIssueResponse,
|
||||||
@ -13,6 +15,9 @@ import type {
|
|||||||
|
|
||||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
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 ProjectCycleServices extends APIService {
|
class ProjectCycleServices extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||||
@ -20,7 +25,10 @@ class ProjectCycleServices extends APIService {
|
|||||||
|
|
||||||
async createCycle(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
async createCycle(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/`, data)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackCycleCreateEvent(response?.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -86,7 +94,10 @@ class ProjectCycleServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackCycleUpdateEvent(response?.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -102,7 +113,10 @@ class ProjectCycleServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackCycleUpdateEvent(response?.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -110,7 +124,10 @@ class ProjectCycleServices extends APIService {
|
|||||||
|
|
||||||
async deleteCycle(workspaceSlug: string, projectId: string, cycleId: string): Promise<any> {
|
async deleteCycle(workspaceSlug: string, projectId: string, cycleId: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackCycleDeleteEvent(response?.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
// services
|
// services
|
||||||
import APIService from "services/api.service";
|
import APIService from "services/api.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
// type
|
// type
|
||||||
import type { IIssue, IIssueActivity, IIssueComment, IIssueViewOptions } from "types";
|
import type { IIssue, IIssueActivity, IIssueComment, IIssueViewOptions } from "types";
|
||||||
|
|
||||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
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 ProjectIssuesServices extends APIService {
|
class ProjectIssuesServices extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||||
@ -12,7 +16,10 @@ class ProjectIssuesServices extends APIService {
|
|||||||
|
|
||||||
async createIssues(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
async createIssues(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, data)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackIssueCreateEvent(response.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -241,7 +248,10 @@ class ProjectIssuesServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackIssueUpdateEvent(data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -257,7 +267,10 @@ class ProjectIssuesServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackIssueUpdateEvent(data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -265,7 +278,10 @@ class ProjectIssuesServices extends APIService {
|
|||||||
|
|
||||||
async deleteIssue(workspaceSlug: string, projectId: string, issuesId: string): Promise<any> {
|
async deleteIssue(workspaceSlug: string, projectId: string, issuesId: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issuesId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issuesId}/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackIssueDeleteEvent({ issuesId });
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -276,7 +292,10 @@ class ProjectIssuesServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/bulk-delete-issues/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/bulk-delete-issues/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackIssueBulkDeleteEvent(data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
// services
|
// services
|
||||||
import APIService from "services/api.service";
|
import APIService from "services/api.service";
|
||||||
|
import trackEventServices from "./track-event.service";
|
||||||
|
|
||||||
// types
|
// types
|
||||||
import type { IIssueViewOptions, IModule, IIssue } from "types";
|
import type { IIssueViewOptions, IModule, IIssue } from "types";
|
||||||
|
|
||||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
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 ProjectIssuesServices extends APIService {
|
class ProjectIssuesServices extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||||
@ -20,7 +25,10 @@ class ProjectIssuesServices extends APIService {
|
|||||||
|
|
||||||
async createModule(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
async createModule(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/`, data)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackModuleCreateEvent(response?.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -36,7 +44,10 @@ class ProjectIssuesServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackModuleUpdateEvent(response?.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -60,7 +71,10 @@ class ProjectIssuesServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackModuleUpdateEvent(response?.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -70,7 +84,10 @@ class ProjectIssuesServices extends APIService {
|
|||||||
return this.delete(
|
return this.delete(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackModuleDeleteEvent(response?.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
// services
|
// services
|
||||||
import APIService from "services/api.service";
|
import APIService from "services/api.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
|
|
||||||
// types
|
// types
|
||||||
import type {
|
import type {
|
||||||
GithubRepositoriesResponse,
|
GithubRepositoriesResponse,
|
||||||
@ -12,6 +14,9 @@ import type {
|
|||||||
|
|
||||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
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 ProjectServices extends APIService {
|
class ProjectServices extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||||
@ -19,7 +24,10 @@ class ProjectServices extends APIService {
|
|||||||
|
|
||||||
async createProject(workspaceSlug: string, data: Partial<IProject>): Promise<IProject> {
|
async createProject(workspaceSlug: string, data: Partial<IProject>): Promise<IProject> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/`, data)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackCreateProjectEvent(response.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
});
|
});
|
||||||
@ -59,7 +67,10 @@ class ProjectServices extends APIService {
|
|||||||
data: Partial<IProject>
|
data: Partial<IProject>
|
||||||
): Promise<IProject> {
|
): Promise<IProject> {
|
||||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`, data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`, data)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackUpdateProjectEvent(response.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -67,7 +78,10 @@ class ProjectServices extends APIService {
|
|||||||
|
|
||||||
async deleteProject(workspaceSlug: string, projectId: string): Promise<any> {
|
async deleteProject(workspaceSlug: string, projectId: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackDeleteProjectEvent({ projectId });
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
// services
|
// services
|
||||||
import APIService from "services/api.service";
|
import APIService from "services/api.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
|
|
||||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||||
|
|
||||||
|
const trackEvent =
|
||||||
|
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
|
||||||
|
|
||||||
// types
|
// types
|
||||||
import type { IState, StateResponse } from "types";
|
import type { IState, StateResponse } from "types";
|
||||||
|
|
||||||
@ -13,7 +17,10 @@ class ProjectStateServices extends APIService {
|
|||||||
|
|
||||||
async createState(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
async createState(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/`, data)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackStateCreateEvent(response?.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -54,7 +61,10 @@ class ProjectStateServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackStateUpdateEvent(response?.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -70,7 +80,10 @@ class ProjectStateServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackStateUpdateEvent(response?.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -78,7 +91,10 @@ class ProjectStateServices extends APIService {
|
|||||||
|
|
||||||
async deleteState(workspaceSlug: string, projectId: string, stateId: string): Promise<any> {
|
async deleteState(workspaceSlug: string, projectId: string, stateId: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackStateDeleteEvent(response?.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
314
apps/app/services/track-event.service.ts
Normal file
314
apps/app/services/track-event.service.ts
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
// services
|
||||||
|
import APIService from "services/api.service";
|
||||||
|
// types
|
||||||
|
import type { IWorkspace } from "types";
|
||||||
|
|
||||||
|
// TODO: as we add more events, we can refactor this to be divided into different classes
|
||||||
|
class TrackEventServices extends APIService {
|
||||||
|
constructor() {
|
||||||
|
super("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackCreateWorkspaceEvent(data: IWorkspace): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "CREATE_WORKSPACE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackUpdateWorkspaceEvent(data: IWorkspace): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "UPDATE_WORKSPACE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackDeleteWorkspaceEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "DELETE_WORKSPACE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackCreateProjectEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "CREATE_PROJECT",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackUpdateProjectEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "UPDATE_PROJECT",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "USER_ONBOARDING_COMPLETE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackIssueCreateEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "ISSUE_CREATE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackIssueUpdateEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "ISSUE_UPDATE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "ISSUE_BULK_DELETE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackStateCreateEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "STATE_CREATE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackStateUpdateEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "STATE_UPDATE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackStateDeleteEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "STATE_DELETE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackCycleCreateEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "CYCLE_CREATE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackCycleUpdateEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "CYCLE_UPDATE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackCycleDeleteEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "CYCLE_DELETE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackModuleCreateEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "MODULE_CREATE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackModuleUpdateEvent(data: any): Promise<any> {
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName: "MODULE_UPDATE",
|
||||||
|
extra: {
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
export default trackEventServices;
|
@ -1,9 +1,14 @@
|
|||||||
// services
|
// services
|
||||||
import APIService from "services/api.service";
|
import APIService from "services/api.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
|
|
||||||
import type { IUser, IUserActivity, IUserWorkspaceDashboard } from "types";
|
import type { IUser, IUserActivity, IUserWorkspaceDashboard } from "types";
|
||||||
|
|
||||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
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 UserService extends APIService {
|
class UserService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||||
@ -44,7 +49,10 @@ class UserService extends APIService {
|
|||||||
|
|
||||||
async updateUserOnBoard(): Promise<any> {
|
async updateUserOnBoard(): Promise<any> {
|
||||||
return this.patch("/api/users/me/onboard/", { is_onboarded: true })
|
return this.patch("/api/users/me/onboard/", { is_onboarded: true })
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackUserOnboardingCompleteEvent(response.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// services
|
// services
|
||||||
import APIService from "services/api.service";
|
import APIService from "services/api.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
|
|
||||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||||
|
|
||||||
@ -14,6 +15,9 @@ import {
|
|||||||
IWorkspaceSearchResults,
|
IWorkspaceSearchResults,
|
||||||
} from "types";
|
} from "types";
|
||||||
|
|
||||||
|
const trackEvent =
|
||||||
|
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
|
||||||
|
|
||||||
class WorkspaceService extends APIService {
|
class WorkspaceService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||||
@ -37,7 +41,10 @@ class WorkspaceService extends APIService {
|
|||||||
|
|
||||||
async createWorkspace(data: Partial<IWorkspace>): Promise<IWorkspace> {
|
async createWorkspace(data: Partial<IWorkspace>): Promise<IWorkspace> {
|
||||||
return this.post("/api/workspaces/", data)
|
return this.post("/api/workspaces/", data)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackCreateWorkspaceEvent(response.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -45,7 +52,10 @@ class WorkspaceService extends APIService {
|
|||||||
|
|
||||||
async updateWorkspace(workspaceSlug: string, data: Partial<IWorkspace>): Promise<IWorkspace> {
|
async updateWorkspace(workspaceSlug: string, data: Partial<IWorkspace>): Promise<IWorkspace> {
|
||||||
return this.patch(`/api/workspaces/${workspaceSlug}/`, data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/`, data)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackUpdateWorkspaceEvent(response.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -53,7 +63,10 @@ class WorkspaceService extends APIService {
|
|||||||
|
|
||||||
async deleteWorkspace(workspaceSlug: string): Promise<any> {
|
async deleteWorkspace(workspaceSlug: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackDeleteWorkspaceEvent({ workspaceSlug });
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -61,7 +74,10 @@ class WorkspaceService extends APIService {
|
|||||||
|
|
||||||
async inviteWorkspace(workspaceSlug: string, data: any): Promise<any> {
|
async inviteWorkspace(workspaceSlug: string, data: any): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/invite/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/invite/`, data)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackWorkspaceUserInviteEvent(response.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -75,7 +91,10 @@ class WorkspaceService extends APIService {
|
|||||||
headers: {},
|
headers: {},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent) trackEventServices.trackWorkspaceUserJoinEvent(response.data);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
"NEXT_PUBLIC_ENABLE_SENTRY",
|
"NEXT_PUBLIC_ENABLE_SENTRY",
|
||||||
"NEXT_PUBLIC_ENABLE_OAUTH",
|
"NEXT_PUBLIC_ENABLE_OAUTH",
|
||||||
"NEXT_PUBLIC_UNSPLASH_ACCESS",
|
"NEXT_PUBLIC_UNSPLASH_ACCESS",
|
||||||
|
"NEXT_PUBLIC_TRACK_EVENTS",
|
||||||
|
"JITSU_ACCESS_KEY",
|
||||||
"NEXT_PUBLIC_CRISP_ID"
|
"NEXT_PUBLIC_CRISP_ID"
|
||||||
],
|
],
|
||||||
"pipeline": {
|
"pipeline": {
|
||||||
|
Loading…
Reference in New Issue
Block a user