chore: track events for estimates and importers (#1012)

This commit is contained in:
Aaryan Khandelwal 2023-05-05 15:45:38 +05:30 committed by GitHub
parent b34cf0c471
commit 93c105c495
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 133 additions and 18 deletions

View File

@ -63,7 +63,11 @@ const IntegrationGuide = () => {
services. This tool will guide you to relocate the issue to Plane.
</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">
Read More
<ArrowRightIcon width={"18px"} color={"#3F76FF"} />
@ -124,7 +128,7 @@ const IntegrationGuide = () => {
{importerServices ? (
importerServices.length > 0 ? (
<div className="space-y-2">
<div className="divide-y">
<div className="divide-y divide-brand-base">
{importerServices.map((service) => (
<SingleImport
key={service.id}

View File

@ -6,6 +6,8 @@ import { TrashIcon } from "@heroicons/react/24/outline";
import { renderShortDateWithYearFormat } from "helpers/date-time.helper";
// types
import { IImporterService } from "types";
// constants
import { IMPORTERS_EXPORTERS_LIST } from "constants/workspace";
type Props = {
service: IImporterService;
@ -13,17 +15,16 @@ type Props = {
handleDelete: () => void;
};
const importersList: { [key: string]: string } = {
github: "GitHub",
};
export const SingleImport: React.FC<Props> = ({ service, refreshing, handleDelete }) => (
<div className="flex items-center justify-between gap-2 py-3">
<div>
<h4 className="flex items-center gap-2 text-sm">
<span>
Import from <span className="font-medium">{importersList[service.service]}</span> to{" "}
<span className="font-medium">{service.project_detail.name}</span>
Import from{" "}
<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
className={`rounded px-2 py-0.5 text-xs capitalize ${

View File

@ -1,10 +1,14 @@
// services
import APIService from "services/api.service";
// 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 trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class ProjectEstimateServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
@ -16,7 +20,11 @@ class ProjectEstimateServices extends APIService {
data: IEstimateFormData
): Promise<any> {
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) => {
throw error?.response;
});
@ -32,7 +40,11 @@ class ProjectEstimateServices extends APIService {
`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/`,
data
)
.then((response) => response?.data)
.then((response) => {
if (trackEvent)
trackEventServices.trackIssueEstimateEvent(response?.data, "ESTIMATE_UPDATE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
@ -64,7 +76,11 @@ class ProjectEstimateServices extends APIService {
return this.delete(
`/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) => {
throw error?.response?.data;
});

View File

@ -1,10 +1,14 @@
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
import { IGithubRepoInfo, IGithubServiceImportFormData } from "types";
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 {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
@ -41,7 +45,11 @@ class GithubIntegrationService extends APIService {
`/api/workspaces/${workspaceSlug}/projects/importers/${integrationServiceType}/`,
data
)
.then((response) => response?.data)
.then((response) => {
if (trackEvent)
trackEventServices.trackImporterEvent(response?.data, "GITHUB_IMPORTER_CREATE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});

View File

@ -1,9 +1,14 @@
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
// types
import { IAppIntegration, IImporterService, IWorkspaceIntegration } 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 IntegrationService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
@ -49,7 +54,12 @@ class IntegrationService extends APIService {
importerId: string
): Promise<any> {
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) => {
throw error?.response?.data;
});

View File

@ -1,10 +1,14 @@
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
// types
import { IJiraMetadata, IJiraResponse, IJiraImporterForm } 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 JiraImportedService extends APIService {
constructor() {
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> {
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) => {
throw error?.response?.data;
});

View File

@ -7,6 +7,7 @@ const trackEvent =
// types
import type {
ICycle,
IEstimate,
IGptResponse,
IIssue,
IIssueComment,
@ -45,7 +46,10 @@ type PagesEventType = "PAGE_CREATE" | "PAGE_UPDATE" | "PAGE_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 =
| "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 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 {
constructor() {
super("/");
@ -209,7 +220,7 @@ class TrackEventServices extends APIService {
async trackIssueCommentEvent(
data: Partial<IIssueComment> | any,
eventName: IssueCommentType
eventName: IssueCommentEventType
): Promise<any> {
let payload: any;
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();

View File

@ -8,7 +8,9 @@ export interface IEstimate {
updated_by: string;
points: IEstimatePoint[];
project: string;
project_detail: IProject;
workspace: string;
workspace_detail: IWorkspace;
}
export interface IEstimatePoint {