diff --git a/apps/app/components/analytics/custom-analytics/sidebar.tsx b/apps/app/components/analytics/custom-analytics/sidebar.tsx index e9a9d5d7f..7910c2cc8 100644 --- a/apps/app/components/analytics/custom-analytics/sidebar.tsx +++ b/apps/app/components/analytics/custom-analytics/sidebar.tsx @@ -7,6 +7,7 @@ import analyticsService from "services/analytics.service"; import projectService from "services/project.service"; import cyclesService from "services/cycles.service"; import modulesService from "services/modules.service"; +import trackEventServices from "services/track-event.service"; // hooks import useProjects from "hooks/use-projects"; import useToast from "hooks/use-toast"; @@ -23,7 +24,13 @@ import { ContrastIcon, LayerDiagonalIcon } from "components/icons"; // helpers import { renderShortDate } from "helpers/date-time.helper"; // types -import { IAnalyticsParams, IAnalyticsResponse, IExportAnalyticsFormData, IProject } from "types"; +import { + IAnalyticsParams, + IAnalyticsResponse, + IExportAnalyticsFormData, + IProject, + IWorkspace, +} from "types"; // fetch-keys import { ANALYTICS, CYCLE_DETAILS, MODULE_DETAILS, PROJECT_DETAILS } from "constants/fetch-keys"; // constants @@ -82,6 +89,59 @@ export const AnalyticsSidebar: React.FC = ({ : 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 = () => { if (!workspaceSlug) return; @@ -95,13 +155,15 @@ export const AnalyticsSidebar: React.FC = ({ analyticsService .exportAnalytics(workspaceSlug.toString(), data) - .then((res) => + .then((res) => { setToastAlert({ type: "success", title: "Success!", message: res.message, - }) - ) + }); + + trackExportAnalytics(); + }) .catch(() => setToastAlert({ type: "error", diff --git a/apps/app/components/analytics/project-modal.tsx b/apps/app/components/analytics/project-modal.tsx index c2072642c..728ca4ed5 100644 --- a/apps/app/components/analytics/project-modal.tsx +++ b/apps/app/components/analytics/project-modal.tsx @@ -13,6 +13,7 @@ import analyticsService from "services/analytics.service"; import projectService from "services/project.service"; import cyclesService from "services/cycles.service"; import modulesService from "services/modules.service"; +import trackEventServices from "services/track-event.service"; // components import { CustomAnalytics, ScopeAndDemand } from "components/analytics"; // icons @@ -22,7 +23,7 @@ import { XMarkIcon, } from "@heroicons/react/24/outline"; // types -import { IAnalyticsParams } from "types"; +import { IAnalyticsParams, IWorkspace } from "types"; // fetch-keys import { ANALYTICS, CYCLE_DETAILS, MODULE_DETAILS, PROJECT_DETAILS } from "constants/fetch-keys"; @@ -95,6 +96,50 @@ export const AnalyticsProjectModal: React.FC = ({ isOpen, onClose }) => { : 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 = () => { onClose(); }; @@ -146,6 +191,7 @@ export const AnalyticsProjectModal: React.FC = ({ isOpen, onClose }) => { selected ? "bg-brand-surface-2" : "" }` } + onClick={() => trackAnalyticsEvent(tab)} > {tab} diff --git a/apps/app/pages/[workspaceSlug]/analytics.tsx b/apps/app/pages/[workspaceSlug]/analytics.tsx index b32399448..ce161fbc4 100644 --- a/apps/app/pages/[workspaceSlug]/analytics.tsx +++ b/apps/app/pages/[workspaceSlug]/analytics.tsx @@ -1,4 +1,4 @@ -import React, { Fragment } from "react"; +import React, { Fragment, useEffect } from "react"; import { useRouter } from "next/router"; @@ -10,6 +10,7 @@ import { useForm } from "react-hook-form"; import { Tab } from "@headlessui/react"; // services import analyticsService from "services/analytics.service"; +import trackEventServices from "services/track-event.service"; // layouts import { WorkspaceAuthorizationLayout } from "layouts/auth-layout"; // components @@ -48,6 +49,28 @@ const Analytics = () => { 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 ( { selected ? "bg-brand-surface-2" : "" }` } + onClick={() => trackAnalyticsEvent(tab)} > {tab} diff --git a/apps/app/services/api.service.ts b/apps/app/services/api.service.ts index 958205005..5434742ba 100644 --- a/apps/app/services/api.service.ts +++ b/apps/app/services/api.service.ts @@ -9,7 +9,6 @@ axios.interceptors.response.use( if (unAuthorizedStatus.includes(status)) { Cookies.remove("refreshToken", { path: "/" }); Cookies.remove("accessToken", { path: "/" }); - console.log("window.location.href", window.location.pathname); if (window.location.pathname != "/signin") window.location.href = "/signin"; } return Promise.reject(error); diff --git a/apps/app/services/track-event.service.ts b/apps/app/services/track-event.service.ts index 54de7119b..29ea0084a 100644 --- a/apps/app/services/track-event.service.ts +++ b/apps/app/services/track-event.service.ts @@ -84,6 +84,21 @@ type ImporterEventType = | "GITHUB_IMPORTER_DELETE" | "JIRA_IMPORTER_CREATE" | "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 { constructor() { super("/"); @@ -615,6 +630,19 @@ class TrackEventServices extends APIService { }, }); } + + async trackAnalyticsEvent(data: any, eventName: AnalyticsEventType): Promise { + const payload = { ...data }; + + return this.request({ + url: "/api/track-event", + method: "POST", + data: { + eventName, + extra: payload, + }, + }); + } } const trackEventServices = new TrackEventServices();