Added legend filter, converted stack bar to line graph and converted most view data to clickable link (#9308)

This commit is contained in:
Shailesh Parmar 2022-12-15 17:44:42 +05:30 committed by GitHub
parent b539b299ee
commit e7f3ef02d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 128 additions and 70 deletions

View File

@ -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 />

View File

@ -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 />

View File

@ -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 />

View File

@ -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'),

View File

@ -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 />

View File

@ -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 = [

View File

@ -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'];

View File

@ -248,6 +248,9 @@
.font-semibold {
font-weight: 600;
}
.font-bold {
font-weight: 700;
}
.transform-180 {
transform: rotate(180deg);

View File

@ -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>
</>
);