mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-28 19:05:53 +00:00
Added legend filter, converted stack bar to line graph and converted most view data to clickable link (#9308)
This commit is contained in:
parent
b539b299ee
commit
e7f3ef02d6
@ -13,15 +13,14 @@
|
||||
|
||||
import { Card, Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { uniqueId } from 'lodash';
|
||||
import React, { FC, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Bar,
|
||||
BarChart,
|
||||
CartesianGrid,
|
||||
Legend,
|
||||
LegendProps,
|
||||
Line,
|
||||
LineChart,
|
||||
ResponsiveContainer,
|
||||
Tooltip,
|
||||
XAxis,
|
||||
@ -29,7 +28,6 @@ import {
|
||||
import { getAggregateChartData } from '../../axiosAPIs/DataInsightAPI';
|
||||
import {
|
||||
BAR_CHART_MARGIN,
|
||||
BAR_SIZE,
|
||||
ENTITIES_BAR_COLO_MAP,
|
||||
} from '../../constants/DataInsight.constants';
|
||||
import { DataReportIndex } from '../../generated/dataInsight/dataInsightChart';
|
||||
@ -38,6 +36,7 @@ import {
|
||||
DataInsightChartType,
|
||||
} from '../../generated/dataInsight/dataInsightChartResult';
|
||||
import { ChartFilter } from '../../interface/data-insight.interface';
|
||||
import { updateActiveChartFilter } from '../../utils/ChartUtils';
|
||||
import {
|
||||
CustomTooltip,
|
||||
getGraphDataByEntityType,
|
||||
@ -56,6 +55,7 @@ const DescriptionInsight: FC<Props> = ({ chartFilter }) => {
|
||||
useState<DataInsightChartResult>();
|
||||
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [activeKeys, setActiveKeys] = useState<string[]>([]);
|
||||
|
||||
const { data, entities, total } = useMemo(() => {
|
||||
return getGraphDataByEntityType(
|
||||
@ -85,6 +85,12 @@ const DescriptionInsight: FC<Props> = ({ chartFilter }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleLegendClick: LegendProps['onClick'] = (event) => {
|
||||
setActiveKeys((prevActiveKeys) =>
|
||||
updateActiveChartFilter(event.dataKey, prevActiveKeys)
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchTotalEntitiesDescriptionByType();
|
||||
}, [chartFilter]);
|
||||
@ -110,29 +116,30 @@ const DescriptionInsight: FC<Props> = ({ chartFilter }) => {
|
||||
debounce={1}
|
||||
id="description-summary-graph"
|
||||
minHeight={400}>
|
||||
<BarChart data={data} margin={BAR_CHART_MARGIN}>
|
||||
<LineChart data={data} margin={BAR_CHART_MARGIN}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="timestamp" />
|
||||
<Tooltip content={<CustomTooltip isPercentage />} />
|
||||
<Legend
|
||||
align="left"
|
||||
content={(props) =>
|
||||
renderLegend(props as LegendProps, `${total}%`)
|
||||
renderLegend(props as LegendProps, `${total}%`, activeKeys)
|
||||
}
|
||||
layout="vertical"
|
||||
verticalAlign="top"
|
||||
wrapperStyle={{ left: '0px' }}
|
||||
wrapperStyle={{ left: '0px', top: '0px' }}
|
||||
onClick={handleLegendClick}
|
||||
/>
|
||||
{entities.map((entity) => (
|
||||
<Bar
|
||||
barSize={BAR_SIZE}
|
||||
<Line
|
||||
dataKey={entity}
|
||||
fill={ENTITIES_BAR_COLO_MAP[entity]}
|
||||
key={uniqueId()}
|
||||
stackId="description"
|
||||
hide={activeKeys.length ? !activeKeys.includes(entity) : false}
|
||||
key={entity}
|
||||
stroke={ENTITIES_BAR_COLO_MAP[entity]}
|
||||
type="monotone"
|
||||
/>
|
||||
))}
|
||||
</BarChart>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
) : (
|
||||
<EmptyGraphPlaceholder />
|
||||
|
@ -13,15 +13,14 @@
|
||||
|
||||
import { Card, Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { uniqueId } from 'lodash';
|
||||
import React, { FC, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Bar,
|
||||
BarChart,
|
||||
CartesianGrid,
|
||||
Legend,
|
||||
LegendProps,
|
||||
Line,
|
||||
LineChart,
|
||||
ResponsiveContainer,
|
||||
Tooltip,
|
||||
XAxis,
|
||||
@ -30,13 +29,13 @@ import {
|
||||
import { getAggregateChartData } from '../../axiosAPIs/DataInsightAPI';
|
||||
import {
|
||||
BAR_CHART_MARGIN,
|
||||
BAR_SIZE,
|
||||
ENTITIES_BAR_COLO_MAP,
|
||||
} from '../../constants/DataInsight.constants';
|
||||
import { DataReportIndex } from '../../generated/dataInsight/dataInsightChart';
|
||||
import { DataInsightChartType } from '../../generated/dataInsight/dataInsightChartResult';
|
||||
import { PageViewsByEntities } from '../../generated/dataInsight/type/pageViewsByEntities';
|
||||
import { ChartFilter } from '../../interface/data-insight.interface';
|
||||
import { updateActiveChartFilter } from '../../utils/ChartUtils';
|
||||
import {
|
||||
CustomTooltip,
|
||||
getGraphDataByEntityType,
|
||||
@ -55,6 +54,7 @@ const PageViewsByEntitiesChart: FC<Props> = ({ chartFilter }) => {
|
||||
useState<PageViewsByEntities[]>();
|
||||
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [activeKeys, setActiveKeys] = useState<string[]>([]);
|
||||
|
||||
const { data, entities, total } = useMemo(() => {
|
||||
return getGraphDataByEntityType(
|
||||
@ -83,6 +83,12 @@ const PageViewsByEntitiesChart: FC<Props> = ({ chartFilter }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleLegendClick: LegendProps['onClick'] = (event) => {
|
||||
setActiveKeys((prevActiveKeys) =>
|
||||
updateActiveChartFilter(event.dataKey, prevActiveKeys)
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchPageViewsByEntities();
|
||||
}, [chartFilter]);
|
||||
@ -105,7 +111,7 @@ const PageViewsByEntitiesChart: FC<Props> = ({ chartFilter }) => {
|
||||
}>
|
||||
{data.length ? (
|
||||
<ResponsiveContainer debounce={1} minHeight={400}>
|
||||
<BarChart data={data} margin={BAR_CHART_MARGIN}>
|
||||
<LineChart data={data} margin={BAR_CHART_MARGIN}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="timestamp" />
|
||||
<YAxis />
|
||||
@ -113,22 +119,23 @@ const PageViewsByEntitiesChart: FC<Props> = ({ chartFilter }) => {
|
||||
<Legend
|
||||
align="left"
|
||||
content={(props) =>
|
||||
renderLegend(props as LegendProps, `${total}`)
|
||||
renderLegend(props as LegendProps, `${total}`, activeKeys)
|
||||
}
|
||||
layout="vertical"
|
||||
verticalAlign="top"
|
||||
wrapperStyle={{ left: '0px' }}
|
||||
wrapperStyle={{ left: '0px', top: '0px' }}
|
||||
onClick={handleLegendClick}
|
||||
/>
|
||||
{entities.map((entity) => (
|
||||
<Bar
|
||||
barSize={BAR_SIZE}
|
||||
<Line
|
||||
dataKey={entity}
|
||||
fill={ENTITIES_BAR_COLO_MAP[entity]}
|
||||
key={uniqueId()}
|
||||
stackId="entityCount"
|
||||
hide={activeKeys.length ? !activeKeys.includes(entity) : false}
|
||||
key={entity}
|
||||
stroke={ENTITIES_BAR_COLO_MAP[entity]}
|
||||
type="monotone"
|
||||
/>
|
||||
))}
|
||||
</BarChart>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
) : (
|
||||
<EmptyGraphPlaceholder />
|
||||
|
@ -13,15 +13,14 @@
|
||||
|
||||
import { Card, Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { uniqueId } from 'lodash';
|
||||
import React, { FC, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Bar,
|
||||
BarChart,
|
||||
CartesianGrid,
|
||||
Legend,
|
||||
LegendProps,
|
||||
Line,
|
||||
LineChart,
|
||||
ResponsiveContainer,
|
||||
Tooltip,
|
||||
XAxis,
|
||||
@ -30,7 +29,6 @@ import {
|
||||
import { getAggregateChartData } from '../../axiosAPIs/DataInsightAPI';
|
||||
import {
|
||||
BAR_CHART_MARGIN,
|
||||
BAR_SIZE,
|
||||
TIER_BAR_COLOR_MAP,
|
||||
} from '../../constants/DataInsight.constants';
|
||||
import { DataReportIndex } from '../../generated/dataInsight/dataInsightChart';
|
||||
@ -39,6 +37,7 @@ import {
|
||||
DataInsightChartType,
|
||||
} from '../../generated/dataInsight/dataInsightChartResult';
|
||||
import { ChartFilter } from '../../interface/data-insight.interface';
|
||||
import { updateActiveChartFilter } from '../../utils/ChartUtils';
|
||||
import {
|
||||
CustomTooltip,
|
||||
getGraphDataByTierType,
|
||||
@ -57,6 +56,7 @@ const TierInsight: FC<Props> = ({ chartFilter }) => {
|
||||
useState<DataInsightChartResult>();
|
||||
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [activeKeys, setActiveKeys] = useState<string[]>([]);
|
||||
|
||||
const { data, tiers, total } = useMemo(() => {
|
||||
return getGraphDataByTierType(totalEntitiesByTier?.data ?? []);
|
||||
@ -82,6 +82,12 @@ const TierInsight: FC<Props> = ({ chartFilter }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleLegendClick: LegendProps['onClick'] = (event) => {
|
||||
setActiveKeys((prevActiveKeys) =>
|
||||
updateActiveChartFilter(event.dataKey, prevActiveKeys)
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchTotalEntitiesByTier();
|
||||
}, [chartFilter]);
|
||||
@ -104,7 +110,7 @@ const TierInsight: FC<Props> = ({ chartFilter }) => {
|
||||
}>
|
||||
{data.length ? (
|
||||
<ResponsiveContainer debounce={1} minHeight={400}>
|
||||
<BarChart data={data} margin={BAR_CHART_MARGIN}>
|
||||
<LineChart data={data} margin={BAR_CHART_MARGIN}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="timestamp" />
|
||||
<YAxis />
|
||||
@ -112,22 +118,23 @@ const TierInsight: FC<Props> = ({ chartFilter }) => {
|
||||
<Legend
|
||||
align="left"
|
||||
content={(props) =>
|
||||
renderLegend(props as LegendProps, `${total}`)
|
||||
renderLegend(props as LegendProps, `${total}`, activeKeys)
|
||||
}
|
||||
layout="vertical"
|
||||
verticalAlign="top"
|
||||
wrapperStyle={{ left: '0px' }}
|
||||
wrapperStyle={{ left: '0px', top: '0px' }}
|
||||
onClick={handleLegendClick}
|
||||
/>
|
||||
{tiers.map((tier) => (
|
||||
<Bar
|
||||
barSize={BAR_SIZE}
|
||||
<Line
|
||||
dataKey={tier}
|
||||
fill={TIER_BAR_COLOR_MAP[tier]}
|
||||
key={uniqueId()}
|
||||
stackId="tier"
|
||||
hide={activeKeys.length ? !activeKeys.includes(tier) : false}
|
||||
key={tier}
|
||||
stroke={TIER_BAR_COLOR_MAP[tier]}
|
||||
type="monotone"
|
||||
/>
|
||||
))}
|
||||
</BarChart>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
) : (
|
||||
<EmptyGraphPlaceholder />
|
||||
|
@ -16,6 +16,7 @@ import { ColumnsType } from 'antd/lib/table';
|
||||
import { AxiosError } from 'axios';
|
||||
import React, { FC, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { getAggregateChartData } from '../../axiosAPIs/DataInsightAPI';
|
||||
import { DataReportIndex } from '../../generated/dataInsight/dataInsightChart';
|
||||
import { DataInsightChartType } from '../../generated/dataInsight/dataInsightChartResult';
|
||||
@ -67,9 +68,11 @@ const TopViewEntities: FC<Props> = ({ chartFilter }) => {
|
||||
title: t('label.data-asset'),
|
||||
dataIndex: 'entityFqn',
|
||||
key: 'dataAsset',
|
||||
render: (entityFqn: string) => (
|
||||
<Typography.Text>{getDecodedFqn(entityFqn)}</Typography.Text>
|
||||
),
|
||||
render: (entityFqn: string, record: MostViewedEntities) => {
|
||||
const { pathname } = new URL(record.entityHref || '');
|
||||
|
||||
return <Link to={pathname || '#'}>{getDecodedFqn(entityFqn)}</Link>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('label.owner'),
|
||||
|
@ -13,15 +13,14 @@
|
||||
|
||||
import { Card, Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { uniqueId } from 'lodash';
|
||||
import React, { FC, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Bar,
|
||||
BarChart,
|
||||
CartesianGrid,
|
||||
Legend,
|
||||
LegendProps,
|
||||
Line,
|
||||
LineChart,
|
||||
ResponsiveContainer,
|
||||
Tooltip,
|
||||
XAxis,
|
||||
@ -30,7 +29,6 @@ import {
|
||||
import { getAggregateChartData } from '../../axiosAPIs/DataInsightAPI';
|
||||
import {
|
||||
BAR_CHART_MARGIN,
|
||||
BAR_SIZE,
|
||||
ENTITIES_BAR_COLO_MAP,
|
||||
} from '../../constants/DataInsight.constants';
|
||||
import { DataReportIndex } from '../../generated/dataInsight/dataInsightChart';
|
||||
@ -39,6 +37,7 @@ import {
|
||||
DataInsightChartType,
|
||||
} from '../../generated/dataInsight/dataInsightChartResult';
|
||||
import { ChartFilter } from '../../interface/data-insight.interface';
|
||||
import { updateActiveChartFilter } from '../../utils/ChartUtils';
|
||||
import {
|
||||
CustomTooltip,
|
||||
getGraphDataByEntityType,
|
||||
@ -57,6 +56,7 @@ const TotalEntityInsight: FC<Props> = ({ chartFilter }) => {
|
||||
useState<DataInsightChartResult>();
|
||||
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [activeKeys, setActiveKeys] = useState<string[]>([]);
|
||||
|
||||
const { data, entities, total } = useMemo(() => {
|
||||
return getGraphDataByEntityType(
|
||||
@ -85,6 +85,12 @@ const TotalEntityInsight: FC<Props> = ({ chartFilter }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleLegendClick: LegendProps['onClick'] = (event) => {
|
||||
setActiveKeys((prevActiveKeys) =>
|
||||
updateActiveChartFilter(event.dataKey, prevActiveKeys)
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchTotalEntitiesByType();
|
||||
}, [chartFilter]);
|
||||
@ -107,7 +113,7 @@ const TotalEntityInsight: FC<Props> = ({ chartFilter }) => {
|
||||
}>
|
||||
{data.length ? (
|
||||
<ResponsiveContainer debounce={1} minHeight={400}>
|
||||
<BarChart data={data} margin={BAR_CHART_MARGIN}>
|
||||
<LineChart data={data} margin={BAR_CHART_MARGIN}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="timestamp" />
|
||||
<YAxis />
|
||||
@ -115,22 +121,23 @@ const TotalEntityInsight: FC<Props> = ({ chartFilter }) => {
|
||||
<Legend
|
||||
align="left"
|
||||
content={(props) =>
|
||||
renderLegend(props as LegendProps, `${total}`)
|
||||
renderLegend(props as LegendProps, `${total}`, activeKeys)
|
||||
}
|
||||
layout="vertical"
|
||||
verticalAlign="top"
|
||||
wrapperStyle={{ left: '0px' }}
|
||||
wrapperStyle={{ left: '0px', top: '0px' }}
|
||||
onClick={handleLegendClick}
|
||||
/>
|
||||
{entities.map((entity) => (
|
||||
<Bar
|
||||
barSize={BAR_SIZE}
|
||||
<Line
|
||||
dataKey={entity}
|
||||
fill={ENTITIES_BAR_COLO_MAP[entity]}
|
||||
key={uniqueId()}
|
||||
stackId="entityCount"
|
||||
hide={activeKeys.length ? !activeKeys.includes(entity) : false}
|
||||
key={entity}
|
||||
stroke={ENTITIES_BAR_COLO_MAP[entity]}
|
||||
type="monotone"
|
||||
/>
|
||||
))}
|
||||
</BarChart>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
) : (
|
||||
<EmptyGraphPlaceholder />
|
||||
|
@ -65,7 +65,7 @@ export const TIER_BAR_COLOR_MAP: Record<string, string> = {
|
||||
'Tier.Tier3': '#66B5AD',
|
||||
'Tier.Tier4': '#8D6AF1',
|
||||
'Tier.Tier5': '#699994',
|
||||
'No Tier': '#6A86EB',
|
||||
NoTier: '#6A86EB',
|
||||
};
|
||||
|
||||
export const DAY_FILTER = [
|
||||
|
@ -27,6 +27,7 @@ export const TEXT_BODY_COLOR = '#37352F';
|
||||
export const SUCCESS_COLOR = '#008376';
|
||||
export const DE_ACTIVE_COLOR = '#6B7280';
|
||||
export const GRAPH_BACKGROUND_COLOR = '#f5f5f5';
|
||||
export const GRAYED_OUT_COLOR = '#CCCCCC';
|
||||
|
||||
export const SUPPORTED_FIELD_TYPES = ['string', 'markdown', 'integer'];
|
||||
|
||||
|
@ -248,6 +248,9 @@
|
||||
.font-semibold {
|
||||
font-weight: 600;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.transform-180 {
|
||||
transform: rotate(180deg);
|
||||
|
@ -28,7 +28,11 @@ import moment from 'moment';
|
||||
import React from 'react';
|
||||
import { ListItem, ListValues } from 'react-awesome-query-builder';
|
||||
import { LegendProps, Surface } from 'recharts';
|
||||
import { PLACEHOLDER_ROUTE_TAB, ROUTES } from '../constants/constants';
|
||||
import {
|
||||
GRAYED_OUT_COLOR,
|
||||
PLACEHOLDER_ROUTE_TAB,
|
||||
ROUTES,
|
||||
} from '../constants/constants';
|
||||
import {
|
||||
ENTITIES_SUMMARY_LIST,
|
||||
KPI_DATE_PICKER_FORMAT,
|
||||
@ -56,7 +60,11 @@ const checkIsPercentageGraph = (dataInsightChartType: DataInsightChartType) =>
|
||||
DataInsightChartType.PercentageOfEntitiesWithOwnerByType,
|
||||
].includes(dataInsightChartType);
|
||||
|
||||
export const renderLegend = (legendData: LegendProps, latest: string) => {
|
||||
export const renderLegend = (
|
||||
legendData: LegendProps,
|
||||
latest: string,
|
||||
activeKeys = [] as string[]
|
||||
) => {
|
||||
const { payload = [] } = legendData;
|
||||
|
||||
return (
|
||||
@ -65,21 +73,36 @@ export const renderLegend = (legendData: LegendProps, latest: string) => {
|
||||
Latest
|
||||
</Typography.Text>
|
||||
<Typography
|
||||
className="font-semibold text-2xl"
|
||||
style={{ margin: '5px 0px' }}>
|
||||
className="font-bold text-lg"
|
||||
style={{ margin: '0px 0px 16px' }}>
|
||||
{latest}
|
||||
</Typography>
|
||||
<ul className="mr-2">
|
||||
{payload.map((entry, index) => (
|
||||
<li
|
||||
className="recharts-legend-item d-flex items-center"
|
||||
key={`item-${index}`}>
|
||||
<Surface className="mr-2" height={14} version="1.1" width={14}>
|
||||
<rect fill={entry.color} height="14" rx="2" width="14" />
|
||||
</Surface>
|
||||
<span>{entry.value}</span>
|
||||
</li>
|
||||
))}
|
||||
{payload.map((entry, index) => {
|
||||
const isActive =
|
||||
activeKeys.length === 0 || activeKeys.includes(entry.value);
|
||||
|
||||
return (
|
||||
<li
|
||||
className="recharts-legend-item d-flex items-center m-t-xss"
|
||||
key={`item-${index}`}
|
||||
onClick={(e) =>
|
||||
legendData.onClick && legendData.onClick({ ...entry, ...e })
|
||||
}>
|
||||
<Surface className="mr-2" height={14} version="1.1" width={14}>
|
||||
<rect
|
||||
fill={isActive ? entry.color : GRAYED_OUT_COLOR}
|
||||
height="14"
|
||||
rx="2"
|
||||
width="14"
|
||||
/>
|
||||
</Surface>
|
||||
<span style={{ color: isActive ? 'inherit' : GRAYED_OUT_COLOR }}>
|
||||
{entry.value}
|
||||
</span>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user