mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-13 00:22:23 +00:00
fix: show all the category for cardinality distribution graph (#24098)
* fix: show all the category for cardinality distribution graph * feat: enhance CardinalityDistributionChart with category selection and custom Y-axis ticks * fix: update cursor fill color in visualisation charts for better visibility --------- Co-authored-by: Harsh Vador <58542468+harsh-vador@users.noreply.github.com>
This commit is contained in:
parent
4da984cd56
commit
dd8b6481b1
@ -13,13 +13,13 @@
|
||||
|
||||
import { Box, Card, Divider, Typography, useTheme } from '@mui/material';
|
||||
import { isUndefined } from 'lodash';
|
||||
import { useMemo } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Bar,
|
||||
BarChart,
|
||||
CartesianGrid,
|
||||
Legend,
|
||||
Cell,
|
||||
ResponsiveContainer,
|
||||
Tooltip,
|
||||
TooltipProps,
|
||||
@ -52,6 +52,7 @@ const CardinalityDistributionChart = ({
|
||||
}: CardinalityDistributionChartProps) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
|
||||
|
||||
const firstDayAllUnique =
|
||||
data.firstDayData?.cardinalityDistribution?.allValuesUnique ?? false;
|
||||
@ -170,6 +171,52 @@ const CardinalityDistributionChart = ({
|
||||
'message.all-values-unique-no-distribution-available'
|
||||
);
|
||||
|
||||
const handleCategoryClick = (categoryName: string) => {
|
||||
setSelectedCategory((prev) =>
|
||||
prev === categoryName ? null : categoryName
|
||||
);
|
||||
};
|
||||
|
||||
const CustomYAxisTick = (props: {
|
||||
x?: number;
|
||||
y?: number;
|
||||
payload?: { value: string };
|
||||
}) => {
|
||||
const { x, y, payload } = props;
|
||||
if (!payload) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const categoryName = payload.value;
|
||||
const isSelected = selectedCategory === categoryName;
|
||||
const isHighlighted = selectedCategory && selectedCategory !== categoryName;
|
||||
|
||||
return (
|
||||
<g transform={`translate(${x},${y})`}>
|
||||
<text
|
||||
cursor="pointer"
|
||||
dy={4}
|
||||
fill={
|
||||
isSelected
|
||||
? theme.palette.primary.main
|
||||
: isHighlighted
|
||||
? theme.palette.grey[400]
|
||||
: theme.palette.grey[700]
|
||||
}
|
||||
fontSize={12}
|
||||
fontWeight={isSelected ? 600 : 400}
|
||||
opacity={isHighlighted ? 0.5 : 1}
|
||||
textAnchor="end"
|
||||
x={-8}
|
||||
onClick={() => handleCategoryClick(categoryName)}>
|
||||
{categoryName.length > 15
|
||||
? `${categoryName.slice(0, 15)}...`
|
||||
: categoryName}
|
||||
</text>
|
||||
</g>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
data-testid="chart-container"
|
||||
@ -203,6 +250,8 @@ const CardinalityDistributionChart = ({
|
||||
'MMM dd, yyyy'
|
||||
);
|
||||
|
||||
const containerHeight = Math.max(350, graphData.length * 30);
|
||||
|
||||
return (
|
||||
<Box
|
||||
key={key}
|
||||
@ -236,16 +285,21 @@ const CardinalityDistributionChart = ({
|
||||
})}: ${cardinalityData.categories?.length || 0}`}
|
||||
</DataPill>
|
||||
</Box>
|
||||
<Box sx={{ flex: 1, minHeight: 350 }}>
|
||||
<Box
|
||||
sx={{
|
||||
flex: 1,
|
||||
minHeight: 350,
|
||||
overflowX: 'hidden',
|
||||
}}>
|
||||
<ResponsiveContainer
|
||||
debounce={200}
|
||||
height={containerHeight}
|
||||
id={`${key}-cardinality`}
|
||||
minHeight={300}>
|
||||
width="100%">
|
||||
<BarChart
|
||||
className="w-full"
|
||||
data={graphData}
|
||||
layout="vertical"
|
||||
margin={{ left: 16 }}>
|
||||
layout="vertical">
|
||||
<CartesianGrid
|
||||
horizontal={renderHorizontalGridLine}
|
||||
stroke={GRAPH_BACKGROUND_COLOR}
|
||||
@ -267,29 +321,49 @@ const CardinalityDistributionChart = ({
|
||||
axisLine={false}
|
||||
dataKey="name"
|
||||
padding={{ top: 16, bottom: 16 }}
|
||||
tick={{ fontSize: 12 }}
|
||||
tickFormatter={(value: string) =>
|
||||
value?.length > 15
|
||||
? `${value.slice(0, 15)}...`
|
||||
: value
|
||||
}
|
||||
tick={<CustomYAxisTick />}
|
||||
tickLine={false}
|
||||
type="category"
|
||||
width={120}
|
||||
/>
|
||||
<Legend />
|
||||
<Tooltip
|
||||
content={renderTooltip}
|
||||
cursor={{
|
||||
fill: theme.palette.grey[100],
|
||||
stroke: theme.palette.grey[200],
|
||||
strokeDasharray: '3 3',
|
||||
}}
|
||||
/>
|
||||
<Bar
|
||||
barSize={22}
|
||||
dataKey="percentage"
|
||||
fill={CHART_BLUE_1}
|
||||
radius={[0, 8, 8, 0]}
|
||||
/>
|
||||
radius={[0, 8, 8, 0]}>
|
||||
{graphData.map((entry) => {
|
||||
const isSelected =
|
||||
selectedCategory === entry.name;
|
||||
const isHighlighted =
|
||||
selectedCategory &&
|
||||
selectedCategory !== entry.name;
|
||||
|
||||
return (
|
||||
<Cell
|
||||
cursor="pointer"
|
||||
fill={
|
||||
isSelected
|
||||
? theme.palette.primary.main
|
||||
: isHighlighted
|
||||
? theme.palette.grey[300]
|
||||
: CHART_BLUE_1
|
||||
}
|
||||
key={`cell-${entry.name}`}
|
||||
opacity={isHighlighted ? 0.3 : 1}
|
||||
onClick={() =>
|
||||
handleCategoryClick(entry.name)
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Bar>
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</Box>
|
||||
|
||||
@ -117,6 +117,7 @@ const CustomBarChart = ({
|
||||
/>
|
||||
}
|
||||
cursor={{
|
||||
fill: theme.palette.grey[100],
|
||||
stroke: theme.palette.grey[200],
|
||||
strokeDasharray: '3 3',
|
||||
}}
|
||||
|
||||
@ -180,6 +180,7 @@ const DataDistributionHistogram = ({
|
||||
/>
|
||||
}
|
||||
cursor={{
|
||||
fill: theme.palette.grey[100],
|
||||
stroke: theme.palette.grey[200],
|
||||
strokeDasharray: '3 3',
|
||||
}}
|
||||
|
||||
@ -15,11 +15,17 @@ import React from 'react';
|
||||
window.React = React;
|
||||
|
||||
jest.mock('recharts', () => ({
|
||||
Bar: jest.fn().mockImplementation(() => <div>Bar</div>),
|
||||
Bar: jest.fn().mockImplementation(({ children }) => (
|
||||
<div>
|
||||
<p>Bar</p>
|
||||
{children}
|
||||
</div>
|
||||
)),
|
||||
Line: jest.fn().mockImplementation(() => <div>Line</div>),
|
||||
Brush: jest.fn().mockImplementation(() => <div>Brush</div>),
|
||||
Area: jest.fn().mockImplementation(() => <div>Area</div>),
|
||||
Scatter: jest.fn().mockImplementation(() => <div>Scatter</div>),
|
||||
Cell: jest.fn().mockImplementation(() => <div>Cell</div>),
|
||||
CartesianGrid: jest.fn().mockImplementation(() => <div>CartesianGrid</div>),
|
||||
Legend: jest.fn().mockImplementation(() => <div>Legend</div>),
|
||||
Tooltip: jest.fn().mockImplementation(() => <div>Tooltip</div>),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user