mirror of
https://github.com/makeplane/plane
synced 2025-08-07 19:59:33 +00:00
[WEB-1616] chore: improving the graphs ui and label in analytics (#4872)
* chore: improving the graphs ui and label in analytics * chore: automatic width in tabel
This commit is contained in:
@@ -8,7 +8,7 @@ import { Tooltip } from "@plane/ui";
|
||||
// ui
|
||||
import { BarGraph } from "@/components/ui";
|
||||
// helpers
|
||||
import { generateBarColor, generateDisplayName } from "@/helpers/analytics.helper";
|
||||
import { generateBarColor, generateDisplayName, renderChartDynamicLabel } from "@/helpers/analytics.helper";
|
||||
import { findStringWithMostCharacters } from "@/helpers/array.helper";
|
||||
// types
|
||||
import { CustomTooltip } from "./custom-tooltip";
|
||||
@@ -66,7 +66,7 @@ export const AnalyticsGraph: React.FC<Props> = ({ analytics, barGraphData, param
|
||||
height={fullScreen ? "400px" : "300px"}
|
||||
margin={{
|
||||
right: 20,
|
||||
bottom: params.x_axis === "assignees__id" ? 50 : longestXAxisLabel.length * 5 + 20,
|
||||
bottom: params.x_axis === "assignees__id" ? 50 : renderChartDynamicLabel(longestXAxisLabel)?.length * 5 + 20,
|
||||
}}
|
||||
axisBottom={{
|
||||
tickSize: 0,
|
||||
@@ -111,18 +111,20 @@ export const AnalyticsGraph: React.FC<Props> = ({ analytics, barGraphData, param
|
||||
);
|
||||
}
|
||||
: (datum) => (
|
||||
<g transform={`translate(${datum.x},${datum.y + 10})`}>
|
||||
<text
|
||||
x={0}
|
||||
y={datum.y}
|
||||
textAnchor={`${barGraphData.data.length > 7 ? "end" : "middle"}`}
|
||||
fontSize={10}
|
||||
fill="rgb(var(--color-text-200))"
|
||||
className={`${barGraphData.data.length > 7 ? "-rotate-45" : ""}`}
|
||||
>
|
||||
{generateDisplayName(datum.value, analytics, params, "x_axis")}
|
||||
</text>
|
||||
</g>
|
||||
<Tooltip tooltipContent={generateDisplayName(datum.value, analytics, params, "x_axis")}>
|
||||
<g transform={`translate(${datum.x},${datum.y + 20})`}>
|
||||
<text
|
||||
x={0}
|
||||
y={datum.y}
|
||||
textAnchor={`${barGraphData.data.length > 7 ? "end" : "middle"}`}
|
||||
fontSize={10}
|
||||
fill="rgb(var(--color-text-200))"
|
||||
className={`${barGraphData.data.length > 7 ? "-rotate-45" : ""}`}
|
||||
>
|
||||
{renderChartDynamicLabel(generateDisplayName(datum.value, analytics, params, "x_axis"))?.label}
|
||||
</text>
|
||||
</g>
|
||||
</Tooltip>
|
||||
),
|
||||
}}
|
||||
theme={{
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { BarDatum } from "@nivo/bar";
|
||||
// icons
|
||||
import { IAnalyticsParams, IAnalyticsResponse, TIssuePriorities } from "@plane/types";
|
||||
import { PriorityIcon } from "@plane/ui";
|
||||
import { PriorityIcon, Tooltip } from "@plane/ui";
|
||||
// helpers
|
||||
import { ANALYTICS_X_AXIS_VALUES, ANALYTICS_Y_AXIS_VALUES } from "@/constants/analytics";
|
||||
import { generateBarColor, generateDisplayName } from "@/helpers/analytics.helper";
|
||||
// types
|
||||
// constants
|
||||
import { generateBarColor, generateDisplayName, renderChartDynamicLabel } from "@/helpers/analytics.helper";
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
|
||||
type Props = {
|
||||
analytics: IAnalyticsResponse;
|
||||
@@ -21,80 +19,87 @@ type Props = {
|
||||
};
|
||||
|
||||
export const AnalyticsTable: React.FC<Props> = ({ analytics, barGraphData, params, yAxisKey }) => (
|
||||
<div className="flow-root">
|
||||
<div className="overflow-x-auto">
|
||||
<div className="inline-block min-w-full align-middle">
|
||||
<table className="min-w-full divide-y divide-custom-border-200 whitespace-nowrap border-y border-custom-border-200">
|
||||
<thead className="bg-custom-background-80">
|
||||
<tr className="divide-x divide-custom-border-200 text-sm text-custom-text-100">
|
||||
<th scope="col" className="px-2.5 py-3 text-left font-medium">
|
||||
{ANALYTICS_X_AXIS_VALUES.find((v) => v.value === params.x_axis)?.label}
|
||||
</th>
|
||||
{params.segment ? (
|
||||
barGraphData.xAxisKeys.map((key) => (
|
||||
<th
|
||||
key={`segment-${key}`}
|
||||
scope="col"
|
||||
className={`px-2.5 py-3 text-left font-medium ${
|
||||
params.segment === "priority" || params.segment === "state__group" ? "capitalize" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
{params.segment === "priority" ? (
|
||||
<PriorityIcon priority={key as TIssuePriorities} />
|
||||
) : (
|
||||
<span
|
||||
className="h-3 w-3 flex-shrink-0 rounded"
|
||||
style={{
|
||||
backgroundColor: generateBarColor(key, analytics, params, "segment"),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{generateDisplayName(key, analytics, params, "segment")}
|
||||
</div>
|
||||
</th>
|
||||
))
|
||||
) : (
|
||||
<th scope="col" className="px-2.5 py-3 text-left font-medium sm:pr-0">
|
||||
{ANALYTICS_Y_AXIS_VALUES.find((v) => v.value === params.y_axis)?.label}
|
||||
</th>
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-custom-border-200">
|
||||
{barGraphData.data.map((item, index) => (
|
||||
<tr key={`table-row-${index}`} className="divide-x divide-custom-border-200 text-xs text-custom-text-200">
|
||||
<td
|
||||
className={`flex items-center gap-2 whitespace-nowrap px-2.5 py-2 font-medium ${
|
||||
params.x_axis === "priority" || params.x_axis === "state__group" ? "capitalize" : ""
|
||||
}`}
|
||||
>
|
||||
{params.x_axis === "priority" ? (
|
||||
<PriorityIcon priority={item.name as TIssuePriorities} />
|
||||
<div className="w-full overflow-hidden overflow-x-auto">
|
||||
<table className="w-full overflow-hidden divide-y divide-custom-border-200 whitespace-nowrap border-y border-custom-border-200">
|
||||
<thead className="bg-custom-background-80">
|
||||
<tr className="divide-x divide-custom-border-200 text-sm text-custom-text-100">
|
||||
<th scope="col" className="px-2.5 py-3 text-left font-medium">
|
||||
{ANALYTICS_X_AXIS_VALUES.find((v) => v.value === params.x_axis)?.label}
|
||||
</th>
|
||||
{params.segment ? (
|
||||
barGraphData.xAxisKeys.map((key) => (
|
||||
<th
|
||||
key={`segment-${key}`}
|
||||
scope="col"
|
||||
className={`px-2.5 py-3 text-left font-medium ${
|
||||
params.segment === "priority" || params.segment === "state__group" ? "capitalize" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
{params.segment === "priority" ? (
|
||||
<PriorityIcon priority={key as TIssuePriorities} />
|
||||
) : (
|
||||
<span
|
||||
className="h-3 w-3 rounded"
|
||||
className="h-3 w-3 flex-shrink-0 rounded"
|
||||
style={{
|
||||
backgroundColor: generateBarColor(key, analytics, params, "segment"),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{renderChartDynamicLabel(generateDisplayName(key, analytics, params, "segment"))?.label}
|
||||
</div>
|
||||
</th>
|
||||
))
|
||||
) : (
|
||||
<th scope="col" className="px-2.5 py-3 text-left font-medium sm:pr-0">
|
||||
{ANALYTICS_Y_AXIS_VALUES.find((v) => v.value === params.y_axis)?.label}
|
||||
</th>
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-custom-border-200">
|
||||
{barGraphData.data.map((item, index) => (
|
||||
<tr key={`table-row-${index}`} className="divide-x divide-custom-border-200 text-xs text-custom-text-200">
|
||||
<td className="px-2.5 py-2">
|
||||
<div className="relative flex items-center gap-2 w-full overflow-hidden">
|
||||
<div className="flex-shrink-0 h-3 w-3 rounded overflow-hidden">
|
||||
{params.x_axis === "priority" ? (
|
||||
<PriorityIcon priority={(item.name as string).toLowerCase() as TIssuePriorities} />
|
||||
) : (
|
||||
<div
|
||||
className="w-full h-full"
|
||||
style={{
|
||||
backgroundColor: generateBarColor(`${item.name}`, analytics, params, "x_axis"),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{generateDisplayName(`${item.name}`, analytics, params, "x_axis")}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
"font-medium",
|
||||
["priority", "state__group"].includes(params.x_axis) ? `capitalize` : ``
|
||||
)}
|
||||
>
|
||||
<Tooltip tooltipContent={generateDisplayName(`${item.name}`, analytics, params, "x_axis")}>
|
||||
<div className="overflow-hidden w-full whitespace-normal break-words truncate line-clamp-1">
|
||||
{generateDisplayName(`${item.name}`, analytics, params, "x_axis")}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
{params.segment ? (
|
||||
barGraphData.xAxisKeys.map((key, index) => (
|
||||
<td key={`segment-value-${index}`} className="whitespace-nowrap px-2.5 py-2 sm:pr-0">
|
||||
{item[key] ?? 0}
|
||||
</td>
|
||||
{params.segment ? (
|
||||
barGraphData.xAxisKeys.map((key, index) => (
|
||||
<td key={`segment-value-${index}`} className="whitespace-nowrap px-2.5 py-2 sm:pr-0">
|
||||
{item[key] ?? 0}
|
||||
</td>
|
||||
))
|
||||
) : (
|
||||
<td className="whitespace-nowrap px-2.5 py-2 sm:pr-0">{item[yAxisKey]}</td>
|
||||
)}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<td className="whitespace-nowrap px-2.5 py-2 sm:pr-0">{item[yAxisKey]}</td>
|
||||
)}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user