forked from github/plane
chore: track events for estimates and importers (#1012)
This commit is contained in:
parent
b34cf0c471
commit
93c105c495
@ -63,7 +63,11 @@ const IntegrationGuide = () => {
|
|||||||
services. This tool will guide you to relocate the issue to Plane.
|
services. This tool will guide you to relocate the issue to Plane.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a href="https://docs.plane.so" target="_blank" rel="noopener noreferrer">
|
<a
|
||||||
|
href="https://docs.plane.so/importers/github"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
<div className="flex flex-shrink-0 cursor-pointer items-center gap-2 whitespace-nowrap text-sm font-medium text-[#3F76FF] hover:text-opacity-80">
|
<div className="flex flex-shrink-0 cursor-pointer items-center gap-2 whitespace-nowrap text-sm font-medium text-[#3F76FF] hover:text-opacity-80">
|
||||||
Read More
|
Read More
|
||||||
<ArrowRightIcon width={"18px"} color={"#3F76FF"} />
|
<ArrowRightIcon width={"18px"} color={"#3F76FF"} />
|
||||||
@ -124,7 +128,7 @@ const IntegrationGuide = () => {
|
|||||||
{importerServices ? (
|
{importerServices ? (
|
||||||
importerServices.length > 0 ? (
|
importerServices.length > 0 ? (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="divide-y">
|
<div className="divide-y divide-brand-base">
|
||||||
{importerServices.map((service) => (
|
{importerServices.map((service) => (
|
||||||
<SingleImport
|
<SingleImport
|
||||||
key={service.id}
|
key={service.id}
|
||||||
|
@ -6,6 +6,8 @@ import { TrashIcon } from "@heroicons/react/24/outline";
|
|||||||
import { renderShortDateWithYearFormat } from "helpers/date-time.helper";
|
import { renderShortDateWithYearFormat } from "helpers/date-time.helper";
|
||||||
// types
|
// types
|
||||||
import { IImporterService } from "types";
|
import { IImporterService } from "types";
|
||||||
|
// constants
|
||||||
|
import { IMPORTERS_EXPORTERS_LIST } from "constants/workspace";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
service: IImporterService;
|
service: IImporterService;
|
||||||
@ -13,17 +15,16 @@ type Props = {
|
|||||||
handleDelete: () => void;
|
handleDelete: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const importersList: { [key: string]: string } = {
|
|
||||||
github: "GitHub",
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SingleImport: React.FC<Props> = ({ service, refreshing, handleDelete }) => (
|
export const SingleImport: React.FC<Props> = ({ service, refreshing, handleDelete }) => (
|
||||||
<div className="flex items-center justify-between gap-2 py-3">
|
<div className="flex items-center justify-between gap-2 py-3">
|
||||||
<div>
|
<div>
|
||||||
<h4 className="flex items-center gap-2 text-sm">
|
<h4 className="flex items-center gap-2 text-sm">
|
||||||
<span>
|
<span>
|
||||||
Import from <span className="font-medium">{importersList[service.service]}</span> to{" "}
|
Import from{" "}
|
||||||
<span className="font-medium">{service.project_detail.name}</span>
|
<span className="font-medium">
|
||||||
|
{IMPORTERS_EXPORTERS_LIST.find((i) => i.provider === service.service)?.title}
|
||||||
|
</span>{" "}
|
||||||
|
to <span className="font-medium">{service.project_detail.name}</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`rounded px-2 py-0.5 text-xs capitalize ${
|
className={`rounded px-2 py-0.5 text-xs capitalize ${
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
// services
|
// services
|
||||||
import APIService from "services/api.service";
|
import APIService from "services/api.service";
|
||||||
// types
|
// types
|
||||||
import type { IEstimate, IEstimateFormData, IEstimatePoint } from "types";
|
import type { IEstimate, IEstimateFormData } from "types";
|
||||||
|
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";
|
||||||
|
|
||||||
class ProjectEstimateServices extends APIService {
|
class ProjectEstimateServices extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||||
@ -16,7 +20,11 @@ class ProjectEstimateServices extends APIService {
|
|||||||
data: IEstimateFormData
|
data: IEstimateFormData
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/`, data)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackIssueEstimateEvent(response?.data, "ESTIMATE_CREATE");
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
});
|
});
|
||||||
@ -32,7 +40,11 @@ class ProjectEstimateServices extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackIssueEstimateEvent(response?.data, "ESTIMATE_UPDATE");
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -64,7 +76,11 @@ class ProjectEstimateServices extends APIService {
|
|||||||
return this.delete(
|
return this.delete(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/`
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/`
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackIssueEstimateEvent(response?.data, "ESTIMATE_DELETE");
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
import APIService from "services/api.service";
|
import APIService from "services/api.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
|
|
||||||
import { IGithubRepoInfo, IGithubServiceImportFormData } from "types";
|
import { IGithubRepoInfo, IGithubServiceImportFormData } from "types";
|
||||||
|
|
||||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||||
|
|
||||||
const integrationServiceType: string = "github";
|
const trackEvent =
|
||||||
|
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
|
||||||
|
|
||||||
|
const integrationServiceType: string = "github";
|
||||||
class GithubIntegrationService extends APIService {
|
class GithubIntegrationService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||||
@ -41,7 +45,11 @@ class GithubIntegrationService extends APIService {
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/importers/${integrationServiceType}/`,
|
`/api/workspaces/${workspaceSlug}/projects/importers/${integrationServiceType}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackImporterEvent(response?.data, "GITHUB_IMPORTER_CREATE");
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
import APIService from "services/api.service";
|
import APIService from "services/api.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
|
|
||||||
// types
|
// types
|
||||||
import { IAppIntegration, IImporterService, IWorkspaceIntegration } from "types";
|
import { IAppIntegration, IImporterService, IWorkspaceIntegration } 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 IntegrationService extends APIService {
|
class IntegrationService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||||
@ -49,7 +54,12 @@ class IntegrationService extends APIService {
|
|||||||
importerId: string
|
importerId: string
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/importers/${service}/${importerId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/importers/${service}/${importerId}/`)
|
||||||
.then((res) => res?.data)
|
.then((response) => {
|
||||||
|
const eventName = service === "github" ? "GITHUB_IMPORTER_DELETE" : "JIRA_IMPORTER_DELETE";
|
||||||
|
|
||||||
|
if (trackEvent) trackEventServices.trackImporterEvent(response?.data, eventName);
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
import APIService from "services/api.service";
|
import APIService from "services/api.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
|
|
||||||
// types
|
// types
|
||||||
import { IJiraMetadata, IJiraResponse, IJiraImporterForm } from "types";
|
import { IJiraMetadata, IJiraResponse, IJiraImporterForm } 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 JiraImportedService extends APIService {
|
class JiraImportedService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||||
@ -22,7 +26,11 @@ class JiraImportedService extends APIService {
|
|||||||
|
|
||||||
async createJiraImporter(workspaceSlug: string, data: IJiraImporterForm): Promise<IJiraResponse> {
|
async createJiraImporter(workspaceSlug: string, data: IJiraImporterForm): Promise<IJiraResponse> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/importers/jira/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/importers/jira/`, data)
|
||||||
.then((response) => response?.data)
|
.then((response) => {
|
||||||
|
if (trackEvent)
|
||||||
|
trackEventServices.trackImporterEvent(response?.data, "JIRA_IMPORTER_CREATE");
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -7,6 +7,7 @@ const trackEvent =
|
|||||||
// types
|
// types
|
||||||
import type {
|
import type {
|
||||||
ICycle,
|
ICycle,
|
||||||
|
IEstimate,
|
||||||
IGptResponse,
|
IGptResponse,
|
||||||
IIssue,
|
IIssue,
|
||||||
IIssueComment,
|
IIssueComment,
|
||||||
@ -45,7 +46,10 @@ 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 IssueCommentEventType =
|
||||||
|
| "ISSUE_COMMENT_CREATE"
|
||||||
|
| "ISSUE_COMMENT_UPDATE"
|
||||||
|
| "ISSUE_COMMENT_DELETE";
|
||||||
|
|
||||||
export type MiscellaneousEventType =
|
export type MiscellaneousEventType =
|
||||||
| "TOGGLE_CYCLE_ON"
|
| "TOGGLE_CYCLE_ON"
|
||||||
@ -73,6 +77,13 @@ type IssueLabelEventType = "ISSUE_LABEL_CREATE" | "ISSUE_LABEL_UPDATE" | "ISSUE_
|
|||||||
|
|
||||||
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";
|
||||||
|
|
||||||
|
type IssueEstimateEventType = "ESTIMATE_CREATE" | "ESTIMATE_UPDATE" | "ESTIMATE_DELETE";
|
||||||
|
|
||||||
|
type ImporterEventType =
|
||||||
|
| "GITHUB_IMPORTER_CREATE"
|
||||||
|
| "GITHUB_IMPORTER_DELETE"
|
||||||
|
| "JIRA_IMPORTER_CREATE"
|
||||||
|
| "JIRA_IMPORTER_DELETE";
|
||||||
class TrackEventServices extends APIService {
|
class TrackEventServices extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super("/");
|
super("/");
|
||||||
@ -209,7 +220,7 @@ class TrackEventServices extends APIService {
|
|||||||
|
|
||||||
async trackIssueCommentEvent(
|
async trackIssueCommentEvent(
|
||||||
data: Partial<IIssueComment> | any,
|
data: Partial<IIssueComment> | any,
|
||||||
eventName: IssueCommentType
|
eventName: IssueCommentEventType
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
let payload: any;
|
let payload: any;
|
||||||
if (eventName !== "ISSUE_COMMENT_DELETE")
|
if (eventName !== "ISSUE_COMMENT_DELETE")
|
||||||
@ -549,6 +560,61 @@ class TrackEventServices extends APIService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async trackIssueEstimateEvent(
|
||||||
|
data: { estimate: IEstimate },
|
||||||
|
eventName: IssueEstimateEventType
|
||||||
|
): Promise<any> {
|
||||||
|
let payload: any;
|
||||||
|
if (eventName === "ESTIMATE_DELETE") payload = data;
|
||||||
|
else
|
||||||
|
payload = {
|
||||||
|
workspaceId: data?.estimate?.workspace_detail?.id,
|
||||||
|
workspaceName: data?.estimate?.workspace_detail?.name,
|
||||||
|
workspaceSlug: data?.estimate?.workspace_detail?.slug,
|
||||||
|
projectId: data?.estimate?.project_detail?.id,
|
||||||
|
projectName: data?.estimate?.project_detail?.name,
|
||||||
|
projectIdentifier: data?.estimate?.project_detail?.identifier,
|
||||||
|
estimateId: data.estimate?.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName,
|
||||||
|
extra: {
|
||||||
|
...payload,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async trackImporterEvent(data: any, eventName: ImporterEventType): Promise<any> {
|
||||||
|
let payload: any;
|
||||||
|
if (eventName === "GITHUB_IMPORTER_DELETE" || eventName === "JIRA_IMPORTER_DELETE")
|
||||||
|
payload = data;
|
||||||
|
else
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName,
|
||||||
|
extra: {
|
||||||
|
...payload,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const trackEventServices = new TrackEventServices();
|
const trackEventServices = new TrackEventServices();
|
||||||
|
2
apps/app/types/estimate.d.ts
vendored
2
apps/app/types/estimate.d.ts
vendored
@ -8,7 +8,9 @@ export interface IEstimate {
|
|||||||
updated_by: string;
|
updated_by: string;
|
||||||
points: IEstimatePoint[];
|
points: IEstimatePoint[];
|
||||||
project: string;
|
project: string;
|
||||||
|
project_detail: IProject;
|
||||||
workspace: string;
|
workspace: string;
|
||||||
|
workspace_detail: IWorkspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEstimatePoint {
|
export interface IEstimatePoint {
|
||||||
|
Loading…
Reference in New Issue
Block a user