From d575e8ec6b148cc0efa41d4768745b6c747cdc2b Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Tue, 16 May 2023 15:11:40 +0530 Subject: [PATCH] chore: x-axis tick values for assignees (#1060) * style: new custom analytics ui * fix: x-axis assignee tick values * chore: assignee names in the custom analytics table --- .../custom-analytics/graph/index.tsx | 45 ++++- .../analytics/custom-analytics/select-bar.tsx | 4 +- .../analytics/custom-analytics/sidebar.tsx | 8 +- .../analytics/custom-analytics/table.tsx | 189 ++++++++++-------- .../analytics/scope-and-demand/demand.tsx | 2 +- .../scope-and-demand/leaderboard.tsx | 7 +- .../scope-and-demand/scope-and-demand.tsx | 2 + .../components/analytics/select/project.tsx | 1 - .../components/analytics/select/segment.tsx | 59 +++--- .../components/analytics/select/x-axis.tsx | 46 +++-- .../components/analytics/select/y-axis.tsx | 2 +- apps/app/types/analytics.d.ts | 8 + 12 files changed, 233 insertions(+), 140 deletions(-) diff --git a/apps/app/components/analytics/custom-analytics/graph/index.tsx b/apps/app/components/analytics/custom-analytics/graph/index.tsx index 419294c30..6ae28f02b 100644 --- a/apps/app/components/analytics/custom-analytics/graph/index.tsx +++ b/apps/app/components/analytics/custom-analytics/graph/index.tsx @@ -68,7 +68,50 @@ export const AnalyticsGraph: React.FC = ({ customYAxisTickValues={generateYAxisTickValues()} tooltip={(datum) => } height={fullScreen ? "400px" : "300px"} - margin={{ right: 20, bottom: longestXAxisLabel.length * 5 + 20 }} + margin={{ + right: 20, + bottom: params.x_axis === "assignees__email" ? 50 : longestXAxisLabel.length * 5 + 20, + }} + axisBottom={{ + tickSize: 0, + tickPadding: 10, + tickRotation: barGraphData.data.length > 7 ? -45 : 0, + renderTick: + params.x_axis === "assignees__email" + ? (datum) => { + const avatar = analytics.extras.assignee_details?.find( + (a) => a.assignees__email === datum.value + )?.assignees__avatar; + + console.log(avatar); + + if (avatar && avatar !== "") + return ( + + + + ); + else + return ( + + + + {datum.value && datum.value !== "None" + ? `${datum.value}`.toUpperCase()[0] + : "?"} + + + ); + } + : undefined, + }} theme={{ background: "rgb(var(--color-bg-base))", axis: {}, diff --git a/apps/app/components/analytics/custom-analytics/select-bar.tsx b/apps/app/components/analytics/custom-analytics/select-bar.tsx index 5f667b035..7286a9cf8 100644 --- a/apps/app/components/analytics/custom-analytics/select-bar.tsx +++ b/apps/app/components/analytics/custom-analytics/select-bar.tsx @@ -23,9 +23,9 @@ export const AnalyticsSelectBar: React.FC = ({ isProjectLevel, }) => (
{!isProjectLevel && (
diff --git a/apps/app/components/analytics/custom-analytics/sidebar.tsx b/apps/app/components/analytics/custom-analytics/sidebar.tsx index e0b88b23b..6d92424a0 100644 --- a/apps/app/components/analytics/custom-analytics/sidebar.tsx +++ b/apps/app/components/analytics/custom-analytics/sidebar.tsx @@ -108,9 +108,9 @@ export const AnalyticsSidebar: React.FC = ({ return (
@@ -176,7 +176,7 @@ export const AnalyticsSidebar: React.FC = ({ {projectId ? ( cycleId && cycleDetails ? (
-

{cycleDetails.name}

+

Analytics for {cycleDetails.name}

Lead
@@ -204,7 +204,7 @@ export const AnalyticsSidebar: React.FC = ({
) : moduleId && moduleDetails ? (
-

{moduleDetails.name}

+

Analytics for {moduleDetails.name}

Lead
diff --git a/apps/app/components/analytics/custom-analytics/table.tsx b/apps/app/components/analytics/custom-analytics/table.tsx index 900f3c692..df3953b35 100644 --- a/apps/app/components/analytics/custom-analytics/table.tsx +++ b/apps/app/components/analytics/custom-analytics/table.tsx @@ -21,96 +21,115 @@ type Props = { yAxisKey: "count" | "estimate"; }; -export const AnalyticsTable: React.FC = ({ analytics, barGraphData, params, yAxisKey }) => ( -
-
-
- - - - - {params.segment ? ( - barGraphData.xAxisKeys.map((key) => ( - + ))} + +
- {ANALYTICS_X_AXIS_VALUES.find((v) => v.value === params.x_axis)?.label} - = ({ analytics, barGraphData, params, yAxisKey }) => { + const renderAssigneeName = (email: string): string => { + const assignee = analytics.extras.assignee_details.find((a) => a.assignees__email === email); + + if (!assignee) return "No assignee"; + + if (assignee.assignees__first_name !== "") + return assignee.assignees__first_name + " " + assignee.assignees__last_name; + + return email; + }; + + return ( +
+
+
+ + + + + {params.segment ? ( + barGraphData.xAxisKeys.map((key) => ( + + )) + ) : ( + + )} + + + + {barGraphData.data.map((item, index) => ( + + - )} - - - - {barGraphData.data.map((item, index) => ( - - + {params.segment ? ( + barGraphData.xAxisKeys.map((key, index) => ( + + )) ) : ( - + )} - {addSpaceIfCamelCase(`${item.name}`)} - - {params.segment ? ( - barGraphData.xAxisKeys.map((key, index) => ( - - )) - ) : ( - - )} - - ))} - -
+ {ANALYTICS_X_AXIS_VALUES.find((v) => v.value === params.x_axis)?.label} + +
+ {params.segment === "priority" ? ( + getPriorityIcon(key) + ) : ( + + )} + {DATE_KEYS.includes(params.segment ?? "") + ? renderMonthAndYear(key) + : params.segment === "assignees__email" + ? renderAssigneeName(key) + : key} +
+
+ {ANALYTICS_Y_AXIS_VALUES.find((v) => v.value === params.y_axis)?.label} +
-
- {params.segment === "priority" ? ( - getPriorityIcon(key) - ) : ( - - )} - {DATE_KEYS.includes(params.segment ?? "") ? renderMonthAndYear(key) : key} -
- - )) - ) : ( -
- {ANALYTICS_Y_AXIS_VALUES.find((v) => v.value === params.y_axis)?.label} -
- {params.x_axis === "priority" ? ( - getPriorityIcon(`${item.name}`) + {params.x_axis === "priority" ? ( + getPriorityIcon(`${item.name}`) + ) : ( + + )} + {params.x_axis === "assignees__email" + ? renderAssigneeName(`${item.name}`) + : addSpaceIfCamelCase(`${item.name}`)} + + {item[key] ?? 0} + {item[yAxisKey]} - {item[key] ?? 0} - {item[yAxisKey]}
+
+
-
-); + ); +}; diff --git a/apps/app/components/analytics/scope-and-demand/demand.tsx b/apps/app/components/analytics/scope-and-demand/demand.tsx index 1ab750c93..4a454b564 100644 --- a/apps/app/components/analytics/scope-and-demand/demand.tsx +++ b/apps/app/components/analytics/scope-and-demand/demand.tsx @@ -37,7 +37,7 @@ export const AnalyticsDemand: React.FC = ({ defaultAnalytics }) => (

{percentage}%

-
+
= ({ users, title }) => (
{title}
- {users.map((user, index) => ( -
+ {users.map((user) => ( +
{user && user.avatar && user.avatar !== "" ? (
@@ -24,7 +25,7 @@ export const AnalyticsLeaderboard: React.FC = ({ users, title }) => ( height="100%" width="100%" className="rounded-full" - alt={user.firstName + " " + user.lastName} + alt={user.email ?? "None"} />
) : ( 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 ee0ee4019..6549f58b4 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 @@ -56,6 +56,7 @@ export const ScopeAndDemand: React.FC = ({ fullScreen = true }) => { ({ avatar: user.created_by__avatar, + email: user.created_by__email, firstName: user.created_by__first_name, lastName: user.created_by__last_name, count: user.count, @@ -65,6 +66,7 @@ export const ScopeAndDemand: React.FC = ({ fullScreen = true }) => { ({ avatar: user.assignees__avatar, + email: user.assignees__email, firstName: user.assignees__first_name, lastName: user.assignees__last_name, count: user.count, diff --git a/apps/app/components/analytics/select/project.tsx b/apps/app/components/analytics/select/project.tsx index bfb975d11..efee62ba6 100644 --- a/apps/app/components/analytics/select/project.tsx +++ b/apps/app/components/analytics/select/project.tsx @@ -30,7 +30,6 @@ export const SelectProject: React.FC = ({ value, onChange, projects }) => : "All projects" } optionsClassName="min-w-full" - position="right" noChevron multiple /> diff --git a/apps/app/components/analytics/select/segment.tsx b/apps/app/components/analytics/select/segment.tsx index 4358cdfa1..ef6a2fe51 100644 --- a/apps/app/components/analytics/select/segment.tsx +++ b/apps/app/components/analytics/select/segment.tsx @@ -1,3 +1,5 @@ +import { useRouter } from "next/router"; + // ui import { CustomSelect } from "components/ui"; // types @@ -11,29 +13,36 @@ type Props = { params: IAnalyticsParams; }; -export const SelectSegment: React.FC = ({ value, onChange, params }) => ( - - {ANALYTICS_X_AXIS_VALUES.find((v) => v.value === value)?.label ?? ( - No value - )} - - } - onChange={onChange} - width="w-full" - maxHeight="lg" - > - No value - {ANALYTICS_X_AXIS_VALUES.map((item) => { - if (params.x_axis === item.value) return null; +export const SelectSegment: React.FC = ({ value, onChange, params }) => { + const router = useRouter(); + const { cycleId, moduleId } = router.query; - return ( - - {item.label} - - ); - })} - -); + return ( + + {ANALYTICS_X_AXIS_VALUES.find((v) => v.value === value)?.label ?? ( + No value + )} + + } + onChange={onChange} + width="w-full" + maxHeight="lg" + > + No value + {ANALYTICS_X_AXIS_VALUES.map((item) => { + if (params.x_axis === item.value) return null; + if (cycleId && item.value === "issue_cycle__cycle__name") return null; + if (moduleId && item.value === "issue_module__module__name") return null; + + return ( + + {item.label} + + ); + })} + + ); +}; diff --git a/apps/app/components/analytics/select/x-axis.tsx b/apps/app/components/analytics/select/x-axis.tsx index a284ae807..a403cad39 100644 --- a/apps/app/components/analytics/select/x-axis.tsx +++ b/apps/app/components/analytics/select/x-axis.tsx @@ -1,27 +1,39 @@ +import { useRouter } from "next/router"; + // ui import { CustomSelect } from "components/ui"; // types -import { IAnalyticsParams, TXAxisValues, TYAxisValues } from "types"; +import { TXAxisValues } from "types"; // constants -import { ANALYTICS_X_AXIS_VALUES, ANALYTICS_Y_AXIS_VALUES } from "constants/analytics"; +import { ANALYTICS_X_AXIS_VALUES } from "constants/analytics"; type Props = { value: TXAxisValues; onChange: (val: string) => void; }; -export const SelectXAxis: React.FC = ({ value, onChange }) => ( - {ANALYTICS_X_AXIS_VALUES.find((v) => v.value === value)?.label}} - onChange={onChange} - width="w-full" - maxHeight="lg" - > - {ANALYTICS_X_AXIS_VALUES.map((item) => ( - - {item.label} - - ))} - -); +export const SelectXAxis: React.FC = ({ value, onChange }) => { + const router = useRouter(); + const { cycleId, moduleId } = router.query; + + return ( + {ANALYTICS_X_AXIS_VALUES.find((v) => v.value === value)?.label}} + onChange={onChange} + width="w-full" + maxHeight="lg" + > + {ANALYTICS_X_AXIS_VALUES.map((item) => { + if (cycleId && item.value === "issue_cycle__cycle__name") return null; + if (moduleId && item.value === "issue_module__module__name") return null; + + return ( + + {item.label} + + ); + })} + + ); +}; diff --git a/apps/app/components/analytics/select/y-axis.tsx b/apps/app/components/analytics/select/y-axis.tsx index 248852620..ef22332bd 100644 --- a/apps/app/components/analytics/select/y-axis.tsx +++ b/apps/app/components/analytics/select/y-axis.tsx @@ -1,7 +1,7 @@ // ui import { CustomSelect } from "components/ui"; // types -import { IAnalyticsParams, TYAxisValues } from "types"; +import { TYAxisValues } from "types"; // constants import { ANALYTICS_Y_AXIS_VALUES } from "constants/analytics"; diff --git a/apps/app/types/analytics.d.ts b/apps/app/types/analytics.d.ts index eb5d75e58..67bc0cd10 100644 --- a/apps/app/types/analytics.d.ts +++ b/apps/app/types/analytics.d.ts @@ -3,6 +3,12 @@ export interface IAnalyticsResponse { distribution: IAnalyticsData; extras: { colors: IAnalyticsExtra[]; + assignee_details: { + assignees__avatar: string | null; + assignees__email: string; + assignees__first_name: string; + assignees__last_name: string; + }[]; }; } @@ -59,6 +65,7 @@ export interface IExportAnalyticsFormData { export interface IDefaultAnalyticsUser { assignees__avatar: string | null; + assignees__email: string | null; assignees__first_name: string; assignees__last_name: string; count: number; @@ -69,6 +76,7 @@ export interface IDefaultAnalyticsResponse { most_issue_closed_user: IDefaultAnalyticsUser[]; most_issue_created_user: { created_by__avatar: string | null; + created_by__email: string | null; created_by__first_name: string; created_by__last_name: string; count: number;