diff --git a/apps/app/components/analytics/custom-analytics/custom-analytics.tsx b/apps/app/components/analytics/custom-analytics/custom-analytics.tsx index 7f393aa4cb..d1ec7392c7 100644 --- a/apps/app/components/analytics/custom-analytics/custom-analytics.tsx +++ b/apps/app/components/analytics/custom-analytics/custom-analytics.tsx @@ -17,8 +17,8 @@ import { } from "components/analytics"; // ui import { Loader, PrimaryButton } from "components/ui"; -// types -import { convertResponseToBarGraphData } from "constants/analytics"; +// helpers +import { convertResponseToBarGraphData } from "helpers/analytics.helper"; // types import { IAnalyticsParams } from "types"; // fetch-keys @@ -63,11 +63,7 @@ export const CustomAnalytics: React.FC = ({ isProjectLevel = false, fullS ); const yAxisKey = params.y_axis === "issue_count" ? "count" : "effort"; - const barGraphData = convertResponseToBarGraphData( - analytics?.distribution, - watch("segment") ? true : false, - watch("y_axis") - ); + const barGraphData = convertResponseToBarGraphData(analytics?.distribution, params); return ( <> @@ -125,7 +121,7 @@ export const CustomAnalytics: React.FC = ({ isProjectLevel = false, fullS

There was some error in fetching the data.

- Refresh + mutateAnalytics()}>Refresh
diff --git a/apps/app/components/analytics/custom-analytics/graph/custom-tooltip.tsx b/apps/app/components/analytics/custom-analytics/graph/custom-tooltip.tsx index 5ec1d72151..9d392c2147 100644 --- a/apps/app/components/analytics/custom-analytics/graph/custom-tooltip.tsx +++ b/apps/app/components/analytics/custom-analytics/graph/custom-tooltip.tsx @@ -1,5 +1,7 @@ // nivo import { BarTooltipProps } from "@nivo/bar"; +import { DATE_KEYS } from "constants/analytics"; +import { renderMonthAndYear } from "helpers/analytics.helper"; // types import { IAnalyticsParams } from "types"; @@ -8,27 +10,39 @@ type Props = { params: IAnalyticsParams; }; -export const CustomTooltip: React.FC = ({ datum, params }) => ( -
- - = ({ datum, params }) => { + let tooltipValue: string | number = ""; + + if (params.segment) { + if (DATE_KEYS.includes(params.segment)) tooltipValue = renderMonthAndYear(datum.id); + else tooltipValue = datum.id; + } else { + if (DATE_KEYS.includes(params.x_axis)) tooltipValue = datum.indexValue; + else tooltipValue = datum.id === "count" ? "Issue count" : "Effort"; + } + + return ( +
+ + - {params.segment ? datum.id : datum.id === "count" ? "Issue count" : "Effort"}: - - {datum.value} -
-); + }`} + > + {tooltipValue}: +
+ {datum.value} +
+ ); +}; diff --git a/apps/app/components/analytics/custom-analytics/graph/index.tsx b/apps/app/components/analytics/custom-analytics/graph/index.tsx index 0616b08537..12d5803e7b 100644 --- a/apps/app/components/analytics/custom-analytics/graph/index.tsx +++ b/apps/app/components/analytics/custom-analytics/graph/index.tsx @@ -6,10 +6,10 @@ import { CustomTooltip } from "./custom-tooltip"; import { BarGraph } from "components/ui"; // helpers import { findStringWithMostCharacters } from "helpers/array.helper"; +import { generateBarColor } from "helpers/analytics.helper"; // types import { IAnalyticsParams, IAnalyticsResponse } from "types"; // constants -import { generateBarColor } from "constants/analytics"; type Props = { analytics: IAnalyticsResponse; @@ -47,28 +47,7 @@ export const AnalyticsGraph: React.FC = ({ }); else data = barGraphData.data.map((d) => d[yAxisKey] as number); - const minValue = 0; - const maxValue = Math.max(...data); - - const valueRange = maxValue - minValue; - - let tickInterval = 1; - if (valueRange > 10) tickInterval = 2; - if (valueRange > 50) tickInterval = 5; - if (valueRange > 100) tickInterval = 10; - if (valueRange > 200) tickInterval = 50; - if (valueRange > 300) tickInterval = (Math.ceil(valueRange / 100) * 100) / 10; - - const tickValues = []; - let tickValue = minValue; - while (tickValue <= maxValue) { - tickValues.push(tickValue); - tickValue += tickInterval; - } - - if (!tickValues.includes(maxValue)) tickValues.push(maxValue); - - return tickValues; + return data; }; const longestXAxisLabel = findStringWithMostCharacters(barGraphData.data.map((d) => `${d.name}`)); @@ -78,11 +57,6 @@ export const AnalyticsGraph: React.FC = ({ data={barGraphData.data} indexBy="name" keys={barGraphData.xAxisKeys} - axisLeft={{ - tickSize: 0, - tickPadding: 10, - tickValues: generateYAxisTickValues(), - }} colors={(datum) => generateBarColor( params.segment ? `${datum.id}` : `${datum.indexValue}`, @@ -91,6 +65,7 @@ export const AnalyticsGraph: React.FC = ({ params.segment ? "segment" : "x_axis" ) } + customYAxisTickValues={generateYAxisTickValues()} tooltip={(datum) => } height={fullScreen ? "400px" : "300px"} margin={{ right: 20, bottom: longestXAxisLabel.length * 5 + 20 }} diff --git a/apps/app/components/analytics/custom-analytics/table.tsx b/apps/app/components/analytics/custom-analytics/table.tsx index a6ec1cb895..73be595387 100644 --- a/apps/app/components/analytics/custom-analytics/table.tsx +++ b/apps/app/components/analytics/custom-analytics/table.tsx @@ -4,14 +4,13 @@ import { BarDatum } from "@nivo/bar"; import { getPriorityIcon } from "components/icons"; // helpers import { addSpaceIfCamelCase } from "helpers/string.helper"; +// helpers +import { generateBarColor, renderMonthAndYear } from "helpers/analytics.helper"; // types import { IAnalyticsParams, IAnalyticsResponse } from "types"; // constants -import { - ANALYTICS_X_AXIS_VALUES, - ANALYTICS_Y_AXIS_VALUES, - generateBarColor, -} from "constants/analytics"; +import { ANALYTICS_X_AXIS_VALUES, ANALYTICS_Y_AXIS_VALUES, DATE_KEYS } from "constants/analytics"; +import { MONTHS_LIST } from "constants/calendar"; type Props = { analytics: IAnalyticsResponse; @@ -55,7 +54,7 @@ export const AnalyticsTable: React.FC = ({ analytics, barGraphData, param }} /> )} - {key} + {DATE_KEYS.includes(params.segment ?? "") ? renderMonthAndYear(key) : key} )) @@ -74,7 +73,9 @@ export const AnalyticsTable: React.FC = ({ analytics, barGraphData, param > {params.x_axis === "priority" ? ( diff --git a/apps/app/components/analytics/project-modal.tsx b/apps/app/components/analytics/project-modal.tsx index ca185c43ed..7e3e5efeb5 100644 --- a/apps/app/components/analytics/project-modal.tsx +++ b/apps/app/components/analytics/project-modal.tsx @@ -38,7 +38,7 @@ export const AnalyticsProjectModal: React.FC = ({ isOpen, onClose }) => { >

Project Analytics

@@ -80,7 +80,7 @@ export const AnalyticsProjectModal: React.FC = ({ isOpen, onClose }) => { - + diff --git a/apps/app/components/analytics/scope-and-demand/demand.tsx b/apps/app/components/analytics/scope-and-demand/demand.tsx index 6f100416ac..784b3fcb48 100644 --- a/apps/app/components/analytics/scope-and-demand/demand.tsx +++ b/apps/app/components/analytics/scope-and-demand/demand.tsx @@ -10,14 +10,14 @@ type Props = { }; export const AnalyticsDemand: React.FC = ({ defaultAnalytics }) => ( -
+
DEMAND

Total open tasks

{defaultAnalytics.open_issues}

- {defaultAnalytics.open_issues_classified.map((group) => { + {defaultAnalytics?.open_issues_classified.map((group) => { const percentage = ((group.state_count / defaultAnalytics.total_issues) * 100).toFixed(0); return ( diff --git a/apps/app/components/analytics/scope-and-demand/index.ts b/apps/app/components/analytics/scope-and-demand/index.ts index fe18eb0f67..ae756a961e 100644 --- a/apps/app/components/analytics/scope-and-demand/index.ts +++ b/apps/app/components/analytics/scope-and-demand/index.ts @@ -1,3 +1,5 @@ export * from "./demand"; +export * from "./leaderboard"; export * from "./scope-and-demand"; export * from "./scope"; +export * from "./year-wise-issues"; diff --git a/apps/app/components/analytics/scope-and-demand/leaderboard.tsx b/apps/app/components/analytics/scope-and-demand/leaderboard.tsx new file mode 100644 index 0000000000..978e293990 --- /dev/null +++ b/apps/app/components/analytics/scope-and-demand/leaderboard.tsx @@ -0,0 +1,41 @@ +import Image from "next/image"; + +type Props = { + users: { + avatar: string | null; + email: string | null; + count: number; + }[]; + title: string; +}; + +export const AnalyticsLeaderboard: React.FC = ({ users, title }) => ( +
+
{title}
+
+ {users.map((user) => ( +
+
+ {user && user.avatar && user.avatar !== "" ? ( +
+ {user.email +
+ ) : ( +
+ {(user.email ?? "No assignee").charAt(0)} +
+ )} + {user.email ?? "No assignee"} +
+ {user.count} +
+ ))} +
+
+); diff --git a/apps/app/components/analytics/scope-and-demand/scope-and-demand.tsx b/apps/app/components/analytics/scope-and-demand/scope-and-demand.tsx index 1f98672e04..424836a892 100644 --- a/apps/app/components/analytics/scope-and-demand/scope-and-demand.tsx +++ b/apps/app/components/analytics/scope-and-demand/scope-and-demand.tsx @@ -5,7 +5,12 @@ import useSWR from "swr"; // services import analyticsService from "services/analytics.service"; // components -import { AnalyticsDemand, AnalyticsScope } from "components/analytics"; +import { + AnalyticsDemand, + AnalyticsLeaderboard, + AnalyticsScope, + AnalyticsYearWiseIssues, +} from "components/analytics"; // ui import { Loader, PrimaryButton } from "components/ui"; // fetch-keys @@ -13,17 +18,20 @@ import { DEFAULT_ANALYTICS } from "constants/fetch-keys"; type Props = { fullScreen?: boolean; + isProjectLevel?: boolean; }; -export const ScopeAndDemand: React.FC = ({ fullScreen = true }) => { +export const ScopeAndDemand: React.FC = ({ fullScreen = true, isProjectLevel = true }) => { const router = useRouter(); const { workspaceSlug, projectId, cycleId, moduleId } = router.query; - const params = { - project: projectId ? projectId.toString() : null, - cycle: cycleId ? cycleId.toString() : null, - module: moduleId ? moduleId.toString() : null, - }; + const params = isProjectLevel + ? { + project: projectId ? projectId.toString() : null, + cycle: cycleId ? cycleId.toString() : null, + module: moduleId ? moduleId.toString() : null, + } + : undefined; const { data: defaultAnalytics, @@ -41,15 +49,36 @@ export const ScopeAndDemand: React.FC = ({ fullScreen = true }) => { {!defaultAnalyticsError ? ( defaultAnalytics ? (
-
+
+ ({ + avatar: user.created_by__avatar, + email: user.created_by__email, + count: user.count, + }))} + title="Most issues created" + /> + ({ + avatar: user.assignees__avatar, + email: user.assignees__email, + count: user.count, + }))} + title="Most issues closed" + /> +
+ +
) : ( - - + + + + ) ) : ( @@ -57,7 +86,7 @@ export const ScopeAndDemand: React.FC = ({ fullScreen = true }) => {

There was some error in fetching the data.

- Refresh + mutateDefaultAnalytics()}>Refresh
diff --git a/apps/app/components/analytics/scope-and-demand/scope.tsx b/apps/app/components/analytics/scope-and-demand/scope.tsx index a808b83f98..60a50fa127 100644 --- a/apps/app/components/analytics/scope-and-demand/scope.tsx +++ b/apps/app/components/analytics/scope-and-demand/scope.tsx @@ -1,98 +1,65 @@ // ui -import { BarGraph, LineGraph } from "components/ui"; +import { BarGraph } from "components/ui"; // types import { IDefaultAnalyticsResponse } from "types"; -// constants -import { MONTHS_LIST } from "constants/calendar"; type Props = { defaultAnalytics: IDefaultAnalyticsResponse; }; -export const AnalyticsScope: React.FC = ({ defaultAnalytics }) => { - const currentMonth = new Date().getMonth(); - const startMonth = Math.floor(currentMonth / 3) * 3 + 1; - const quarterMonthsList = [startMonth, startMonth + 1, startMonth + 2]; +export const AnalyticsScope: React.FC = ({ defaultAnalytics }) => ( +
+
SCOPE
+
+
+
Pending issues
+ `#f97316`} + customYAxisTickValues={defaultAnalytics.pending_issue_user.map((d) => d.count)} + tooltip={(datum) => ( +
+ + Issue count- {datum.indexValue ?? "No assignee"}:{" "} + + {datum.value} +
+ )} + axisBottom={{ + renderTick: (datum) => { + const avatar = + defaultAnalytics.pending_issue_user[datum.tickIndex].assignees__avatar ?? ""; - return ( -
-
SCOPE
-
-
-
Pending issues
- `#f97316`} - tooltip={(datum) => ( -
- - Issue count- {datum.indexValue ?? "No assignee"}:{" "} - - {datum.value} -
- )} - axisBottom={{ - tickValues: [], - }} - margin={{ top: 20 }} - /> -
-
-
-
Most issues created
-
- {defaultAnalytics.most_issue_created_user.map((user) => ( -
- {user.assignees__email} - {user.count} -
- ))} -
-
-
-
Most issues closed
-
- {defaultAnalytics.most_issue_closed_user.map((user) => ( -
- {user.assignees__email} - {user.count} -
- ))} -
-
-
-
-

Issues closed in a year

- ({ - x: MONTHS_LIST.find((m) => m.value === month)?.label.substring(0, 3), - y: - defaultAnalytics.issue_completed_month_wise.find((data) => data.month === month) - ?.count || 0, - })), - }, - ]} - height="300px" - colors={(datum) => datum.color} - curve="monotoneX" - margin={{ top: 20 }} - enableArea - /> -
+ if (avatar && avatar !== "") + return ( + + + + ); + else + return ( + + + + {(`${datum.value}` ?? "No assignee").toUpperCase().charAt(0)} + + + ); + }, + }} + margin={{ top: 20 }} + />
- ); -}; +
+); diff --git a/apps/app/components/analytics/scope-and-demand/year-wise-issues.tsx b/apps/app/components/analytics/scope-and-demand/year-wise-issues.tsx new file mode 100644 index 0000000000..e9721bd2fd --- /dev/null +++ b/apps/app/components/analytics/scope-and-demand/year-wise-issues.tsx @@ -0,0 +1,47 @@ +// ui +import { LineGraph } from "components/ui"; +// types +import { IDefaultAnalyticsResponse } from "types"; +// constants +import { MONTHS_LIST } from "constants/calendar"; + +type Props = { + defaultAnalytics: IDefaultAnalyticsResponse; +}; + +export const AnalyticsYearWiseIssues: React.FC = ({ defaultAnalytics }) => { + const currentMonth = new Date().getMonth(); + const startMonth = Math.floor(currentMonth / 3) * 3 + 1; + const quarterMonthsList = [startMonth, startMonth + 1, startMonth + 2]; + + return ( +
+

Issues closed in a year

+ ({ + x: month.label.substring(0, 3), + y: + defaultAnalytics.issue_completed_month_wise.find( + (data) => data.month === month.value + )?.count || 0, + })), + }, + ]} + customYAxisTickValues={defaultAnalytics.issue_completed_month_wise.map((data) => { + if (quarterMonthsList.includes(data.month)) return data.count; + + return 0; + })} + height="300px" + colors={(datum) => datum.color} + curve="monotoneX" + margin={{ top: 20 }} + enableArea + /> +
+ ); +}; diff --git a/apps/app/components/analytics/workspace-modal.tsx b/apps/app/components/analytics/workspace-modal.tsx index 2ceb0388e2..fc06324210 100644 --- a/apps/app/components/analytics/workspace-modal.tsx +++ b/apps/app/components/analytics/workspace-modal.tsx @@ -22,7 +22,7 @@ export const AnalyticsWorkspaceModal: React.FC = ({ isOpen, onClose }) => return ( <>
@@ -56,7 +56,7 @@ export const AnalyticsWorkspaceModal: React.FC = ({ isOpen, onClose }) => - + diff --git a/apps/app/components/ui/graphs/bar-graph.tsx b/apps/app/components/ui/graphs/bar-graph.tsx index 1d2b453305..ae4154f363 100644 --- a/apps/app/components/ui/graphs/bar-graph.tsx +++ b/apps/app/components/ui/graphs/bar-graph.tsx @@ -1,5 +1,7 @@ // nivo import { ResponsiveBar, BarSvgProps } from "@nivo/bar"; +// helpers +import { generateYAxisTickValues } from "helpers/graph.helper"; // types import { TGraph } from "./types"; // constants @@ -8,11 +10,13 @@ import { CHARTS_THEME, DEFAULT_MARGIN } from "constants/graph"; type Props = { indexBy: string; keys: string[]; + customYAxisTickValues?: number[]; }; export const BarGraph: React.FC, "height" | "width">> = ({ indexBy, keys, + customYAxisTickValues, height = "400px", width = "100%", margin, @@ -25,6 +29,13 @@ export const BarGraph: React.FC, "height" keys={keys} margin={{ ...DEFAULT_MARGIN, ...(margin ?? {}) }} padding={rest.padding ?? rest.data.length > 7 ? 0.8 : 0.9} + axisLeft={{ + tickSize: 0, + tickPadding: 10, + tickValues: customYAxisTickValues + ? generateYAxisTickValues(customYAxisTickValues) + : undefined, + }} axisBottom={{ tickSize: 0, tickPadding: 10, diff --git a/apps/app/components/ui/graphs/line-graph.tsx b/apps/app/components/ui/graphs/line-graph.tsx index 1e133b7aa5..fb082e5fca 100644 --- a/apps/app/components/ui/graphs/line-graph.tsx +++ b/apps/app/components/ui/graphs/line-graph.tsx @@ -1,11 +1,18 @@ // nivo import { ResponsiveLine, LineSvgProps } from "@nivo/line"; +// helpers +import { generateYAxisTickValues } from "helpers/graph.helper"; // types import { TGraph } from "./types"; // constants import { CHARTS_THEME, DEFAULT_MARGIN } from "constants/graph"; -export const LineGraph: React.FC = ({ +type Props = { + customYAxisTickValues?: number[]; +}; + +export const LineGraph: React.FC = ({ + customYAxisTickValues, height = "400px", width = "100%", margin, @@ -15,6 +22,13 @@ export const LineGraph: React.FC = ({
{ - if (!response || !(typeof response === "object") || Object.keys(response).length === 0) - return { data: [], xAxisKeys: [] }; - - const data: BarDatum[] = []; - - let xAxisKeys: string[] = []; - const yAxisKey = yAxis === "issue_count" ? "count" : "effort"; - - Object.keys(response).forEach((key) => { - const segments: { [key: string]: number } = {}; - - if (segmented) { - response[key].map((item: any) => { - segments[item.segment ?? "None"] = item[yAxisKey] ?? 0; - - // store the segment in the xAxisKeys array - if (!xAxisKeys.includes(item.segment ?? "None")) xAxisKeys.push(item.segment ?? "None"); - }); - - data.push({ - name: key, - ...segments, - }); - } else { - xAxisKeys = [yAxisKey]; - - const item = response[key][0]; - - data.push({ - name: item.dimension ?? "None", - [yAxisKey]: item[yAxisKey] ?? 0, - }); - } - }); - - return { data, xAxisKeys }; -}; - -export const generateBarColor = ( - value: string, - analytics: IAnalyticsResponse, - params: IAnalyticsParams, - type: "x_axis" | "segment" -): string => { - let color: string | undefined = "rgb(var(--color-accent))"; - - if (!analytics) return color; - - if (params[type] === "state__name" || params[type] === "labels__name") - color = analytics?.extras?.colors.find((c) => c.name === value)?.color; - - if (params[type] === "state__group") color = STATE_GROUP_COLORS[value]; - - if (params[type] === "priority") - color = - value === "urgent" - ? "#ef4444" - : value === "high" - ? "#f97316" - : value === "medium" - ? "#eab308" - : value === "low" - ? "#22c55e" - : "#ced4da"; - - return color ?? "rgb(var(--color-accent))"; -}; +export const DATE_KEYS = ["completed_at", "target_date", "start_date", "created_at"]; diff --git a/apps/app/helpers/analytics.helper.ts b/apps/app/helpers/analytics.helper.ts new file mode 100644 index 0000000000..b81d71d519 --- /dev/null +++ b/apps/app/helpers/analytics.helper.ts @@ -0,0 +1,91 @@ +// nivo +import { BarDatum } from "@nivo/bar"; +// types +import { IAnalyticsData, IAnalyticsParams, IAnalyticsResponse } from "types"; +// constants +import { STATE_GROUP_COLORS } from "constants/state"; +import { MONTHS_LIST } from "constants/calendar"; +import { DATE_KEYS } from "constants/analytics"; + +export const convertResponseToBarGraphData = ( + response: IAnalyticsData | undefined, + params: IAnalyticsParams +): { data: BarDatum[]; xAxisKeys: string[] } => { + if (!response || !(typeof response === "object") || Object.keys(response).length === 0) + return { data: [], xAxisKeys: [] }; + + const data: BarDatum[] = []; + + let xAxisKeys: string[] = []; + const yAxisKey = params.y_axis === "issue_count" ? "count" : "effort"; + + Object.keys(response).forEach((key) => { + const segments: { [key: string]: number } = {}; + + if (params.segment) { + response[key].map((item: any) => { + segments[item.segment ?? "None"] = item[yAxisKey] ?? 0; + + // store the segment in the xAxisKeys array + if (!xAxisKeys.includes(item.segment ?? "None")) xAxisKeys.push(item.segment ?? "None"); + }); + + data.push({ + name: DATE_KEYS.includes(params.x_axis) ? renderMonthAndYear(key) : key, + ...segments, + }); + } else { + xAxisKeys = [yAxisKey]; + + const item = response[key][0]; + + data.push({ + name: DATE_KEYS.includes(params.x_axis) + ? renderMonthAndYear(item.dimension) + : item.dimension ?? "None", + [yAxisKey]: item[yAxisKey] ?? 0, + }); + } + }); + + return { data, xAxisKeys }; +}; + +export const generateBarColor = ( + value: string, + analytics: IAnalyticsResponse, + params: IAnalyticsParams, + type: "x_axis" | "segment" +): string => { + let color: string | undefined = "rgb(var(--color-accent))"; + + if (!analytics) return color; + + if (params[type] === "state__name" || params[type] === "labels__name") + color = analytics?.extras?.colors.find((c) => c.name === value)?.color; + + if (params[type] === "state__group") color = STATE_GROUP_COLORS[value]; + + if (params[type] === "priority") + color = + value === "urgent" + ? "#ef4444" + : value === "high" + ? "#f97316" + : value === "medium" + ? "#eab308" + : value === "low" + ? "#22c55e" + : "#ced4da"; + + return color ?? "rgb(var(--color-accent))"; +}; + +export const renderMonthAndYear = (date: string | number | null): string => { + if (!date || date === "") return ""; + + return ( + (MONTHS_LIST.find((m) => `${m.value}` === `${date}`.split("-")[1])?.label.substring(0, 3) ?? + "None") + ` ${date}`.split("-")[0] ?? "" + ); +}; diff --git a/apps/app/helpers/graph.helper.ts b/apps/app/helpers/graph.helper.ts new file mode 100644 index 0000000000..3cc79518ba --- /dev/null +++ b/apps/app/helpers/graph.helper.ts @@ -0,0 +1,24 @@ +export const generateYAxisTickValues = (data: number[]) => { + if (!data || !Array.isArray(data) || data.length === 0) return []; + + const minValue = 0; + const maxValue = Math.max(...data); + + const valueRange = maxValue - minValue; + + let tickInterval = 1; + + if (valueRange < 10) tickInterval = 1; + else if (valueRange < 20) tickInterval = 2; + else if (valueRange < 50) tickInterval = 5; + else tickInterval = (Math.ceil(valueRange / 100) * 100) / 10; + + const tickValues: number[] = []; + let tickValue = minValue; + while (tickValue <= maxValue) { + tickValues.push(tickValue); + tickValue += tickInterval; + } + + return tickValues; +}; diff --git a/apps/app/types/analytics.d.ts b/apps/app/types/analytics.d.ts index c02f85cf79..8501c34a57 100644 --- a/apps/app/types/analytics.d.ts +++ b/apps/app/types/analytics.d.ts @@ -57,26 +57,24 @@ export interface IExportAnalyticsFormData { project?: string[]; } +export interface IDefaultAnalyticsUser { + assignees__avatar: string | null; + assignees__email: string; + count: number; +} + export interface IDefaultAnalyticsResponse { issue_completed_month_wise: { month: number; count: number }[]; - most_issue_closed_user: { - assignees__avatar: string | null; - assignees__email: string; - count: number; - }[]; + most_issue_closed_user: IDefaultAnalyticsUser[]; most_issue_created_user: { - assignees__avatar: string | null; - assignees__email: string; + created_by__avatar: string | null; + created_by__email: string; count: number; }[]; open_estimate_sum: number; open_issues: number; open_issues_classified: { state_group: string; state_count: number }[]; - pending_issue_user: { - assignees__avatar: string | null; - assignees__email: string; - count: number; - }[]; + pending_issue_user: IDefaultAnalyticsUser[]; total_estimate_sum: number; total_issues: number; total_issues_classified: { state_group: string; state_count: number }[];