forked from github/plane
chore: analytics tracker events (#1119)
* chore: added export analytics event tracker * chore: add analytics view events * chore: workspace analytics view track event added
This commit is contained in:
parent
7e5b26ea82
commit
11b28048bf
@ -7,6 +7,7 @@ import analyticsService from "services/analytics.service";
|
|||||||
import projectService from "services/project.service";
|
import projectService from "services/project.service";
|
||||||
import cyclesService from "services/cycles.service";
|
import cyclesService from "services/cycles.service";
|
||||||
import modulesService from "services/modules.service";
|
import modulesService from "services/modules.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
// hooks
|
// hooks
|
||||||
import useProjects from "hooks/use-projects";
|
import useProjects from "hooks/use-projects";
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
@ -23,7 +24,13 @@ import { ContrastIcon, LayerDiagonalIcon } from "components/icons";
|
|||||||
// helpers
|
// helpers
|
||||||
import { renderShortDate } from "helpers/date-time.helper";
|
import { renderShortDate } from "helpers/date-time.helper";
|
||||||
// types
|
// types
|
||||||
import { IAnalyticsParams, IAnalyticsResponse, IExportAnalyticsFormData, IProject } from "types";
|
import {
|
||||||
|
IAnalyticsParams,
|
||||||
|
IAnalyticsResponse,
|
||||||
|
IExportAnalyticsFormData,
|
||||||
|
IProject,
|
||||||
|
IWorkspace,
|
||||||
|
} from "types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import { ANALYTICS, CYCLE_DETAILS, MODULE_DETAILS, PROJECT_DETAILS } from "constants/fetch-keys";
|
import { ANALYTICS, CYCLE_DETAILS, MODULE_DETAILS, PROJECT_DETAILS } from "constants/fetch-keys";
|
||||||
// constants
|
// constants
|
||||||
@ -82,6 +89,59 @@ export const AnalyticsSidebar: React.FC<Props> = ({
|
|||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const trackExportAnalytics = () => {
|
||||||
|
const eventPayload: any = {
|
||||||
|
workspaceSlug: workspaceSlug?.toString(),
|
||||||
|
params: {
|
||||||
|
x_axis: params.x_axis,
|
||||||
|
y_axis: params.y_axis,
|
||||||
|
group: params.segment,
|
||||||
|
project: params.project,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (projectDetails) {
|
||||||
|
const workspaceDetails = projectDetails.workspace as IWorkspace;
|
||||||
|
|
||||||
|
eventPayload.workspaceId = workspaceDetails.id;
|
||||||
|
eventPayload.workspaceName = workspaceDetails.name;
|
||||||
|
eventPayload.projectId = projectDetails.id;
|
||||||
|
eventPayload.projectIdentifier = projectDetails.identifier;
|
||||||
|
eventPayload.projectName = projectDetails.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cycleDetails || moduleDetails) {
|
||||||
|
const details = cycleDetails || moduleDetails;
|
||||||
|
|
||||||
|
eventPayload.workspaceId = details?.workspace_detail?.id;
|
||||||
|
eventPayload.workspaceName = details?.workspace_detail?.name;
|
||||||
|
eventPayload.projectId = details?.project_detail.id;
|
||||||
|
eventPayload.projectIdentifier = details?.project_detail.identifier;
|
||||||
|
eventPayload.projectName = details?.project_detail.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cycleDetails) {
|
||||||
|
eventPayload.cycleId = cycleDetails.id;
|
||||||
|
eventPayload.cycleName = cycleDetails.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moduleDetails) {
|
||||||
|
eventPayload.moduleId = moduleDetails.id;
|
||||||
|
eventPayload.moduleName = moduleDetails.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
trackEventServices.trackAnalyticsEvent(
|
||||||
|
eventPayload,
|
||||||
|
cycleId
|
||||||
|
? "CYCLE_ANALYTICS_EXPORT"
|
||||||
|
: moduleId
|
||||||
|
? "MODULE_ANALYTICS_EXPORT"
|
||||||
|
: projectId
|
||||||
|
? "PROJECT_ANALYTICS_EXPORT"
|
||||||
|
: "WORKSPACE_ANALYTICS_EXPORT"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const exportAnalytics = () => {
|
const exportAnalytics = () => {
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug) return;
|
||||||
|
|
||||||
@ -95,13 +155,15 @@ export const AnalyticsSidebar: React.FC<Props> = ({
|
|||||||
|
|
||||||
analyticsService
|
analyticsService
|
||||||
.exportAnalytics(workspaceSlug.toString(), data)
|
.exportAnalytics(workspaceSlug.toString(), data)
|
||||||
.then((res) =>
|
.then((res) => {
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: res.message,
|
message: res.message,
|
||||||
|
});
|
||||||
|
|
||||||
|
trackExportAnalytics();
|
||||||
})
|
})
|
||||||
)
|
|
||||||
.catch(() =>
|
.catch(() =>
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
|
@ -13,6 +13,7 @@ import analyticsService from "services/analytics.service";
|
|||||||
import projectService from "services/project.service";
|
import projectService from "services/project.service";
|
||||||
import cyclesService from "services/cycles.service";
|
import cyclesService from "services/cycles.service";
|
||||||
import modulesService from "services/modules.service";
|
import modulesService from "services/modules.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
// components
|
// components
|
||||||
import { CustomAnalytics, ScopeAndDemand } from "components/analytics";
|
import { CustomAnalytics, ScopeAndDemand } from "components/analytics";
|
||||||
// icons
|
// icons
|
||||||
@ -22,7 +23,7 @@ import {
|
|||||||
XMarkIcon,
|
XMarkIcon,
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
// types
|
// types
|
||||||
import { IAnalyticsParams } from "types";
|
import { IAnalyticsParams, IWorkspace } from "types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import { ANALYTICS, CYCLE_DETAILS, MODULE_DETAILS, PROJECT_DETAILS } from "constants/fetch-keys";
|
import { ANALYTICS, CYCLE_DETAILS, MODULE_DETAILS, PROJECT_DETAILS } from "constants/fetch-keys";
|
||||||
|
|
||||||
@ -95,6 +96,50 @@ export const AnalyticsProjectModal: React.FC<Props> = ({ isOpen, onClose }) => {
|
|||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const trackAnalyticsEvent = (tab: string) => {
|
||||||
|
const eventPayload: any = {
|
||||||
|
workspaceSlug: workspaceSlug?.toString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (projectDetails) {
|
||||||
|
const workspaceDetails = projectDetails.workspace as IWorkspace;
|
||||||
|
|
||||||
|
eventPayload.workspaceId = workspaceDetails.id;
|
||||||
|
eventPayload.workspaceName = workspaceDetails.name;
|
||||||
|
eventPayload.projectId = projectDetails.id;
|
||||||
|
eventPayload.projectIdentifier = projectDetails.identifier;
|
||||||
|
eventPayload.projectName = projectDetails.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cycleDetails || moduleDetails) {
|
||||||
|
const details = cycleDetails || moduleDetails;
|
||||||
|
|
||||||
|
eventPayload.workspaceId = details?.workspace_detail?.id;
|
||||||
|
eventPayload.workspaceName = details?.workspace_detail?.name;
|
||||||
|
eventPayload.projectId = details?.project_detail.id;
|
||||||
|
eventPayload.projectIdentifier = details?.project_detail.identifier;
|
||||||
|
eventPayload.projectName = details?.project_detail.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cycleDetails) {
|
||||||
|
eventPayload.cycleId = cycleDetails.id;
|
||||||
|
eventPayload.cycleName = cycleDetails.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moduleDetails) {
|
||||||
|
eventPayload.moduleId = moduleDetails.id;
|
||||||
|
eventPayload.moduleName = moduleDetails.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const eventType =
|
||||||
|
tab === "Scope and Demand" ? "SCOPE_AND_DEMAND_ANALYTICS" : "CUSTOM_ANALYTICS";
|
||||||
|
|
||||||
|
trackEventServices.trackAnalyticsEvent(
|
||||||
|
eventPayload,
|
||||||
|
cycleId ? `CYCLE_${eventType}` : moduleId ? `MODULE_${eventType}` : `PROJECT_${eventType}`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
onClose();
|
onClose();
|
||||||
};
|
};
|
||||||
@ -146,6 +191,7 @@ export const AnalyticsProjectModal: React.FC<Props> = ({ isOpen, onClose }) => {
|
|||||||
selected ? "bg-brand-surface-2" : ""
|
selected ? "bg-brand-surface-2" : ""
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
|
onClick={() => trackAnalyticsEvent(tab)}
|
||||||
>
|
>
|
||||||
{tab}
|
{tab}
|
||||||
</Tab>
|
</Tab>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { Fragment } from "react";
|
import React, { Fragment, useEffect } from "react";
|
||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
@ -10,6 +10,7 @@ import { useForm } from "react-hook-form";
|
|||||||
import { Tab } from "@headlessui/react";
|
import { Tab } from "@headlessui/react";
|
||||||
// services
|
// services
|
||||||
import analyticsService from "services/analytics.service";
|
import analyticsService from "services/analytics.service";
|
||||||
|
import trackEventServices from "services/track-event.service";
|
||||||
// layouts
|
// layouts
|
||||||
import { WorkspaceAuthorizationLayout } from "layouts/auth-layout";
|
import { WorkspaceAuthorizationLayout } from "layouts/auth-layout";
|
||||||
// components
|
// components
|
||||||
@ -48,6 +49,28 @@ const Analytics = () => {
|
|||||||
workspaceSlug ? () => analyticsService.getAnalytics(workspaceSlug.toString(), params) : null
|
workspaceSlug ? () => analyticsService.getAnalytics(workspaceSlug.toString(), params) : null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const trackAnalyticsEvent = (tab: string) => {
|
||||||
|
const eventPayload = {
|
||||||
|
workspaceSlug: workspaceSlug?.toString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const eventType =
|
||||||
|
tab === "Scope and Demand"
|
||||||
|
? "WORKSPACE_SCOPE_AND_DEMAND_ANALYTICS"
|
||||||
|
: "WORKSPACE_CUSTOM_ANALYTICS";
|
||||||
|
|
||||||
|
trackEventServices.trackAnalyticsEvent(eventPayload, eventType);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!workspaceSlug) return;
|
||||||
|
|
||||||
|
trackEventServices.trackAnalyticsEvent(
|
||||||
|
{ workspaceSlug: workspaceSlug?.toString() },
|
||||||
|
"WORKSPACE_SCOPE_AND_DEMAND_ANALYTICS"
|
||||||
|
);
|
||||||
|
}, [workspaceSlug]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WorkspaceAuthorizationLayout
|
<WorkspaceAuthorizationLayout
|
||||||
breadcrumbs={
|
breadcrumbs={
|
||||||
@ -79,6 +102,7 @@ const Analytics = () => {
|
|||||||
selected ? "bg-brand-surface-2" : ""
|
selected ? "bg-brand-surface-2" : ""
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
|
onClick={() => trackAnalyticsEvent(tab)}
|
||||||
>
|
>
|
||||||
{tab}
|
{tab}
|
||||||
</Tab>
|
</Tab>
|
||||||
|
@ -9,7 +9,6 @@ axios.interceptors.response.use(
|
|||||||
if (unAuthorizedStatus.includes(status)) {
|
if (unAuthorizedStatus.includes(status)) {
|
||||||
Cookies.remove("refreshToken", { path: "/" });
|
Cookies.remove("refreshToken", { path: "/" });
|
||||||
Cookies.remove("accessToken", { path: "/" });
|
Cookies.remove("accessToken", { path: "/" });
|
||||||
console.log("window.location.href", window.location.pathname);
|
|
||||||
if (window.location.pathname != "/signin") window.location.href = "/signin";
|
if (window.location.pathname != "/signin") window.location.href = "/signin";
|
||||||
}
|
}
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
|
@ -84,6 +84,21 @@ type ImporterEventType =
|
|||||||
| "GITHUB_IMPORTER_DELETE"
|
| "GITHUB_IMPORTER_DELETE"
|
||||||
| "JIRA_IMPORTER_CREATE"
|
| "JIRA_IMPORTER_CREATE"
|
||||||
| "JIRA_IMPORTER_DELETE";
|
| "JIRA_IMPORTER_DELETE";
|
||||||
|
|
||||||
|
type AnalyticsEventType =
|
||||||
|
| "WORKSPACE_SCOPE_AND_DEMAND_ANALYTICS"
|
||||||
|
| "WORKSPACE_CUSTOM_ANALYTICS"
|
||||||
|
| "WORKSPACE_ANALYTICS_EXPORT"
|
||||||
|
| "PROJECT_SCOPE_AND_DEMAND_ANALYTICS"
|
||||||
|
| "PROJECT_CUSTOM_ANALYTICS"
|
||||||
|
| "PROJECT_ANALYTICS_EXPORT"
|
||||||
|
| "CYCLE_SCOPE_AND_DEMAND_ANALYTICS"
|
||||||
|
| "CYCLE_CUSTOM_ANALYTICS"
|
||||||
|
| "CYCLE_ANALYTICS_EXPORT"
|
||||||
|
| "MODULE_SCOPE_AND_DEMAND_ANALYTICS"
|
||||||
|
| "MODULE_CUSTOM_ANALYTICS"
|
||||||
|
| "MODULE_ANALYTICS_EXPORT";
|
||||||
|
|
||||||
class TrackEventServices extends APIService {
|
class TrackEventServices extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super("/");
|
super("/");
|
||||||
@ -615,6 +630,19 @@ class TrackEventServices extends APIService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async trackAnalyticsEvent(data: any, eventName: AnalyticsEventType): Promise<any> {
|
||||||
|
const payload = { ...data };
|
||||||
|
|
||||||
|
return this.request({
|
||||||
|
url: "/api/track-event",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
eventName,
|
||||||
|
extra: payload,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const trackEventServices = new TrackEventServices();
|
const trackEventServices = new TrackEventServices();
|
||||||
|
Loading…
Reference in New Issue
Block a user