UI: DataInsight feedback part 4 (#9345)

* UI: Data insight feedback part 4

* layout fix added data assets type field in top view entities table

* Fixed Unit test and added localization
This commit is contained in:
Shailesh Parmar 2022-12-16 20:48:28 +05:30 committed by GitHub
parent a2b34dd0f4
commit 01f3e3f914
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 283 additions and 73 deletions

View File

@ -0,0 +1,86 @@
/*
* Copyright 2022 Collate
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Progress, Typography } from 'antd';
import classNames from 'classnames';
import React from 'react';
import { useTranslation } from 'react-i18next';
import SVGIcons, { Icons } from '../../utils/SvgUtils';
interface DataInsightProgressBarProps {
width?: number;
progress: number;
className?: string;
showLabel?: boolean;
showSuccessInfo?: boolean;
label?: string;
target?: number;
successValue?: number | string;
startValue?: number | string;
suffix?: string;
}
const DataInsightProgressBar = ({
width,
progress,
className,
target,
startValue,
label,
suffix = '%',
successValue = 100,
showLabel = true,
showSuccessInfo = false,
}: DataInsightProgressBarProps) => {
const { t } = useTranslation();
return (
<div className={classNames(className)} style={{ width }}>
{showLabel && (
<Typography.Text className="data-insight-label-text">
{label ?? t('label.latest')}
</Typography.Text>
)}
<div className="flex">
<Progress
className="data-insight-progress-bar"
format={(per) => (
<>
<span>
{startValue ?? per}
{suffix}
</span>
{target && (
<span
className="data-insight-kpi-target"
style={{ width: `${target}%` }}
/>
)}
<span>
{successValue}
{suffix}
</span>
</>
)}
percent={progress}
strokeColor="#B3D4F4"
/>
{showSuccessInfo && progress >= 100 && (
<SVGIcons className="m-l-xs" icon={Icons.SUCCESS_BADGE} />
)}
</div>
</div>
);
};
export default DataInsightProgressBar;

View File

@ -15,7 +15,6 @@ import { render, screen } from '@testing-library/react';
import React from 'react'; import React from 'react';
import { MemoryRouter } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
import { act } from 'react-test-renderer'; import { act } from 'react-test-renderer';
import { DataInsightChartType } from '../../generated/dataInsight/dataInsightChartResult';
import { DataInsightTabs } from '../../interface/data-insight.interface'; import { DataInsightTabs } from '../../interface/data-insight.interface';
import DataInsightSummary from './DataInsightSummary'; import DataInsightSummary from './DataInsightSummary';
@ -55,12 +54,7 @@ describe('Test DataInsightSummary Component', () => {
const summaryCard = screen.getByTestId('summary-card'); const summaryCard = screen.getByTestId('summary-card');
const totalEntitiesByType = screen.getByTestId(
`summary-item-${DataInsightChartType.TotalEntitiesByType}`
);
expect(summaryCard).toBeInTheDocument(); expect(summaryCard).toBeInTheDocument();
expect(totalEntitiesByType).toBeInTheDocument();
}); });
it('Should render only the data assets summary', async () => { it('Should render only the data assets summary', async () => {
@ -74,9 +68,11 @@ describe('Test DataInsightSummary Component', () => {
); );
}); });
const dataAssetSummary = await screen.findByTestId('data-assets-summary'); const dataAssetSummary = await screen.findAllByTestId(
'data-assets-summary'
);
expect(dataAssetSummary).toBeInTheDocument(); expect(dataAssetSummary).toHaveLength(4);
// should not render the app analytics summary // should not render the app analytics summary
expect(screen.queryByTestId('app-analytics-summary')).toBeNull(); expect(screen.queryByTestId('app-analytics-summary')).toBeNull();
@ -95,11 +91,11 @@ describe('Test DataInsightSummary Component', () => {
); );
}); });
const appAnalyticsSummary = await screen.findByTestId( const appAnalyticsSummary = await screen.findAllByTestId(
'app-analytics-summary' 'app-analytics-summary'
); );
expect(appAnalyticsSummary).toBeInTheDocument(); expect(appAnalyticsSummary).toHaveLength(2);
// should not render the data assets summary // should not render the data assets summary
expect(screen.queryByTestId('data-assets-summary')).toBeNull(); expect(screen.queryByTestId('data-assets-summary')).toBeNull();

View File

@ -174,12 +174,12 @@ const DataInsightSummary: FC<Props> = ({ chartFilter, onScrollToChart }) => {
}> }>
<Row data-testid="summary-card-content" gutter={[16, 16]}> <Row data-testid="summary-card-content" gutter={[16, 16]}>
{tab === DataInsightTabs.DATA_ASSETS && ( {tab === DataInsightTabs.DATA_ASSETS && (
<div data-testid="data-assets-summary"> <>
{/* summary of entity charts */} {/* summary of entity charts */}
{entitiesSummaryList.map((summary) => ( {entitiesSummaryList.map((summary) => (
<Col <Col
className="summary-card-item" className="summary-card-item"
data-testid={`summary-item-${summary.id}`} data-testid="data-assets-summary"
key={summary.id} key={summary.id}
span={6} span={6}
onClick={() => onScrollToChart(summary.id)}> onClick={() => onScrollToChart(summary.id)}>
@ -188,19 +188,22 @@ const DataInsightSummary: FC<Props> = ({ chartFilter, onScrollToChart }) => {
</Typography.Text> </Typography.Text>
<Typography className="font-semibold text-2xl m--ml-0.5"> <Typography className="font-semibold text-2xl m--ml-0.5">
{summary.latest} {summary.latest}
{summary.id.startsWith('Percentage') ? '%' : ''} {summary.id.startsWith('Percentage') ||
summary.id.includes(DataInsightChartType.TotalEntitiesByTier)
? '%'
: ''}
</Typography> </Typography>
</Col> </Col>
))} ))}
</div> </>
)} )}
{tab === DataInsightTabs.APP_ANALYTICS && ( {tab === DataInsightTabs.APP_ANALYTICS && (
<div data-testid="app-analytics-summary"> <>
{/* summary for web charts */} {/* summary for web charts */}
{webSummaryList.map((summary) => ( {webSummaryList.map((summary) => (
<Col <Col
className="summary-card-item" className="summary-card-item"
data-testid={`summary-item-${summary.id}`} data-testid="app-analytics-summary"
key={summary.id} key={summary.id}
span={6} span={6}
onClick={() => onScrollToChart(summary.id)}> onClick={() => onScrollToChart(summary.id)}>
@ -237,7 +240,7 @@ const DataInsightSummary: FC<Props> = ({ chartFilter, onScrollToChart }) => {
</UserPopOverCard> </UserPopOverCard>
</Col> </Col>
)} )}
</div> </>
)} )}
</Row> </Row>
</Card> </Card>

View File

@ -62,7 +62,10 @@ describe('Test DescriptionInsight Component', () => {
it('Should render the graph', async () => { it('Should render the graph', async () => {
await act(async () => { await act(async () => {
const { container } = render( const { container } = render(
<DescriptionInsight chartFilter={INITIAL_CHART_FILTER} /> <DescriptionInsight
chartFilter={INITIAL_CHART_FILTER}
kpi={undefined}
/>
); );
const card = screen.getByTestId('entity-description-percentage-card'); const card = screen.getByTestId('entity-description-percentage-card');

View File

@ -25,6 +25,7 @@ import {
ResponsiveContainer, ResponsiveContainer,
Tooltip, Tooltip,
XAxis, XAxis,
YAxis,
} from 'recharts'; } from 'recharts';
import { getAggregateChartData } from '../../axiosAPIs/DataInsightAPI'; import { getAggregateChartData } from '../../axiosAPIs/DataInsightAPI';
import { import {
@ -41,8 +42,12 @@ import {
DataInsightChartResult, DataInsightChartResult,
DataInsightChartType, DataInsightChartType,
} from '../../generated/dataInsight/dataInsightChartResult'; } from '../../generated/dataInsight/dataInsightChartResult';
import { Kpi } from '../../generated/dataInsight/kpi/kpi';
import { ChartFilter } from '../../interface/data-insight.interface'; import { ChartFilter } from '../../interface/data-insight.interface';
import { updateActiveChartFilter } from '../../utils/ChartUtils'; import {
axisTickFormatter,
updateActiveChartFilter,
} from '../../utils/ChartUtils';
import { import {
CustomTooltip, CustomTooltip,
getGraphDataByEntityType, getGraphDataByEntityType,
@ -50,13 +55,15 @@ import {
} from '../../utils/DataInsightUtils'; } from '../../utils/DataInsightUtils';
import { showErrorToast } from '../../utils/ToastUtils'; import { showErrorToast } from '../../utils/ToastUtils';
import './DataInsightDetail.less'; import './DataInsightDetail.less';
import DataInsightProgressBar from './DataInsightProgressBar';
import { EmptyGraphPlaceholder } from './EmptyGraphPlaceholder'; import { EmptyGraphPlaceholder } from './EmptyGraphPlaceholder';
interface Props { interface Props {
chartFilter: ChartFilter; chartFilter: ChartFilter;
kpi: Kpi | undefined;
} }
const DescriptionInsight: FC<Props> = ({ chartFilter }) => { const DescriptionInsight: FC<Props> = ({ chartFilter, kpi }) => {
const [totalEntitiesDescriptionByType, setTotalEntitiesDescriptionByType] = const [totalEntitiesDescriptionByType, setTotalEntitiesDescriptionByType] =
useState<DataInsightChartResult>(); useState<DataInsightChartResult>();
@ -73,6 +80,14 @@ const DescriptionInsight: FC<Props> = ({ chartFilter }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const targetValue = useMemo(() => {
if (kpi?.targetDefinition) {
return Number(kpi.targetDefinition[0].value) * 100;
}
return undefined;
}, [kpi]);
const fetchTotalEntitiesDescriptionByType = async () => { const fetchTotalEntitiesDescriptionByType = async () => {
setIsLoading(true); setIsLoading(true);
try { try {
@ -125,6 +140,12 @@ const DescriptionInsight: FC<Props> = ({ chartFilter }) => {
</Typography.Text> </Typography.Text>
</> </>
}> }>
<DataInsightProgressBar
className="m-b-md"
progress={Number(total)}
target={targetValue}
width={250}
/>
{data.length ? ( {data.length ? (
<ResponsiveContainer <ResponsiveContainer
debounce={1} debounce={1}
@ -133,11 +154,14 @@ const DescriptionInsight: FC<Props> = ({ chartFilter }) => {
<LineChart data={data} margin={BAR_CHART_MARGIN}> <LineChart data={data} margin={BAR_CHART_MARGIN}>
<CartesianGrid stroke={GRAPH_BACKGROUND_COLOR} vertical={false} /> <CartesianGrid stroke={GRAPH_BACKGROUND_COLOR} vertical={false} />
<XAxis dataKey="timestamp" /> <XAxis dataKey="timestamp" />
<YAxis
tickFormatter={(value: number) => axisTickFormatter(value, '%')}
/>
<Tooltip content={<CustomTooltip isPercentage />} /> <Tooltip content={<CustomTooltip isPercentage />} />
<Legend <Legend
align="left" align="left"
content={(props) => content={(props) =>
renderLegend(props as LegendProps, `${total}%`, activeKeys) renderLegend(props as LegendProps, total, activeKeys, false)
} }
layout="vertical" layout="vertical"
verticalAlign="top" verticalAlign="top"

View File

@ -34,11 +34,7 @@ import {
XAxis, XAxis,
YAxis, YAxis,
} from 'recharts'; } from 'recharts';
import { import { getLatestKpiResult, getListKpiResult } from '../../axiosAPIs/KpiAPI';
getLatestKpiResult,
getListKpiResult,
getListKPIs,
} from '../../axiosAPIs/KpiAPI';
import { GRAPH_BACKGROUND_COLOR, ROUTES } from '../../constants/constants'; import { GRAPH_BACKGROUND_COLOR, ROUTES } from '../../constants/constants';
import { import {
BAR_CHART_MARGIN, BAR_CHART_MARGIN,
@ -63,13 +59,14 @@ import KPILatestResults from './KPILatestResults';
interface Props { interface Props {
chartFilter: ChartFilter; chartFilter: ChartFilter;
kpiList: Array<Kpi>;
} }
const KPIChart: FC<Props> = ({ chartFilter }) => { const KPIChart: FC<Props> = ({ chartFilter, kpiList }) => {
const { isAdminUser } = useAuth(); const { isAdminUser } = useAuth();
const { t } = useTranslation(); const { t } = useTranslation();
const history = useHistory(); const history = useHistory();
const [kpiList, setKpiList] = useState<Array<Kpi>>([]);
const [kpiResults, setKpiResults] = useState<KpiResult[]>([]); const [kpiResults, setKpiResults] = useState<KpiResult[]>([]);
const [kpiLatestResults, setKpiLatestResults] = const [kpiLatestResults, setKpiLatestResults] =
useState<Record<string, UIKpiResult>>(); useState<Record<string, UIKpiResult>>();
@ -77,18 +74,6 @@ const KPIChart: FC<Props> = ({ chartFilter }) => {
const handleAddKpi = () => history.push(ROUTES.ADD_KPI); const handleAddKpi = () => history.push(ROUTES.ADD_KPI);
const fetchKpiList = async () => {
try {
setIsLoading(true);
const response = await getListKPIs();
setKpiList(response.data);
} catch (_err) {
setKpiList([]);
} finally {
setIsLoading(false);
}
};
const fetchKpiResults = async () => { const fetchKpiResults = async () => {
setIsLoading(true); setIsLoading(true);
try { try {
@ -167,10 +152,6 @@ const KPIChart: FC<Props> = ({ chartFilter }) => {
return { ...getKpiGraphData(kpiResults, kpiList), kpiTooltipRecord }; return { ...getKpiGraphData(kpiResults, kpiList), kpiTooltipRecord };
}, [kpiResults, kpiList]); }, [kpiResults, kpiList]);
useEffect(() => {
fetchKpiList();
}, []);
useEffect(() => { useEffect(() => {
setKpiResults([]); setKpiResults([]);
setKpiLatestResults(undefined); setKpiLatestResults(undefined);

View File

@ -1,4 +1,4 @@
import { Progress, Space, Typography } from 'antd'; import { Space, Typography } from 'antd';
import { toNumber, uniqueId } from 'lodash'; import { toNumber, uniqueId } from 'lodash';
import React, { FC, useMemo } from 'react'; import React, { FC, useMemo } from 'react';
@ -6,6 +6,7 @@ import { KpiTargetType } from '../../generated/api/dataInsight/kpi/createKpiRequ
import { UIKpiResult } from '../../interface/data-insight.interface'; import { UIKpiResult } from '../../interface/data-insight.interface';
import { getKpiResultFeedback } from '../../utils/DataInsightUtils'; import { getKpiResultFeedback } from '../../utils/DataInsightUtils';
import { getNumberOfDaysForTimestamp } from '../../utils/TimeUtils'; import { getNumberOfDaysForTimestamp } from '../../utils/TimeUtils';
import DataInsightProgressBar from './DataInsightProgressBar';
interface Props { interface Props {
kpiLatestResultsRecord: Record<string, UIKpiResult>; kpiLatestResultsRecord: Record<string, UIKpiResult>;
@ -49,15 +50,18 @@ const KPILatestResults: FC<Props> = ({ kpiLatestResultsRecord }) => {
<Typography.Text className="data-insight-label-text"> <Typography.Text className="data-insight-label-text">
{resultData.displayName ?? name} {resultData.displayName ?? name}
</Typography.Text> </Typography.Text>
<Space className="w-full justify-between">
<Typography.Text>{`${ <DataInsightProgressBar
isPercentage ? targetPercentValue : targetValue showSuccessInfo
}${suffix}`}</Typography.Text> progress={Number(currentProgress)}
<Typography.Text>{`${ showLabel={false}
startValue={isPercentage ? targetPercentValue : targetValue}
successValue={
isPercentage ? targetMetPercentValue : targetMetValue isPercentage ? targetMetPercentValue : targetMetValue
}${suffix}`}</Typography.Text> }
</Space> suffix={suffix}
<Progress percent={currentProgress} showInfo={isTargetMet} /> />
<Typography.Text className="data-insight-label-text"> <Typography.Text className="data-insight-label-text">
{getKpiResultFeedback(daysLeft, Boolean(isTargetMet))} {getKpiResultFeedback(daysLeft, Boolean(isTargetMet))}
</Typography.Text> </Typography.Text>

View File

@ -25,6 +25,7 @@ import {
ResponsiveContainer, ResponsiveContainer,
Tooltip, Tooltip,
XAxis, XAxis,
YAxis,
} from 'recharts'; } from 'recharts';
import { getAggregateChartData } from '../../axiosAPIs/DataInsightAPI'; import { getAggregateChartData } from '../../axiosAPIs/DataInsightAPI';
import { import {
@ -41,8 +42,12 @@ import {
DataInsightChartResult, DataInsightChartResult,
DataInsightChartType, DataInsightChartType,
} from '../../generated/dataInsight/dataInsightChartResult'; } from '../../generated/dataInsight/dataInsightChartResult';
import { Kpi } from '../../generated/dataInsight/kpi/kpi';
import { ChartFilter } from '../../interface/data-insight.interface'; import { ChartFilter } from '../../interface/data-insight.interface';
import { updateActiveChartFilter } from '../../utils/ChartUtils'; import {
axisTickFormatter,
updateActiveChartFilter,
} from '../../utils/ChartUtils';
import { import {
CustomTooltip, CustomTooltip,
getGraphDataByEntityType, getGraphDataByEntityType,
@ -50,13 +55,15 @@ import {
} from '../../utils/DataInsightUtils'; } from '../../utils/DataInsightUtils';
import { showErrorToast } from '../../utils/ToastUtils'; import { showErrorToast } from '../../utils/ToastUtils';
import './DataInsightDetail.less'; import './DataInsightDetail.less';
import DataInsightProgressBar from './DataInsightProgressBar';
import { EmptyGraphPlaceholder } from './EmptyGraphPlaceholder'; import { EmptyGraphPlaceholder } from './EmptyGraphPlaceholder';
interface Props { interface Props {
chartFilter: ChartFilter; chartFilter: ChartFilter;
kpi: Kpi | undefined;
} }
const OwnerInsight: FC<Props> = ({ chartFilter }) => { const OwnerInsight: FC<Props> = ({ chartFilter, kpi }) => {
const [totalEntitiesOwnerByType, setTotalEntitiesOwnerByType] = const [totalEntitiesOwnerByType, setTotalEntitiesOwnerByType] =
useState<DataInsightChartResult>(); useState<DataInsightChartResult>();
@ -71,6 +78,14 @@ const OwnerInsight: FC<Props> = ({ chartFilter }) => {
); );
}, [totalEntitiesOwnerByType]); }, [totalEntitiesOwnerByType]);
const targetValue = useMemo(() => {
if (kpi?.targetDefinition) {
return Number(kpi.targetDefinition[0].value) * 100;
}
return undefined;
}, [kpi]);
const { t } = useTranslation(); const { t } = useTranslation();
const fetchTotalEntitiesOwnerByType = async () => { const fetchTotalEntitiesOwnerByType = async () => {
@ -124,16 +139,25 @@ const OwnerInsight: FC<Props> = ({ chartFilter }) => {
</Typography.Text> </Typography.Text>
</> </>
}> }>
<DataInsightProgressBar
className="m-b-md"
progress={Number(total)}
target={targetValue}
width={250}
/>
{data.length ? ( {data.length ? (
<ResponsiveContainer debounce={1} minHeight={400}> <ResponsiveContainer debounce={1} minHeight={400}>
<LineChart data={data} margin={BAR_CHART_MARGIN}> <LineChart data={data} margin={BAR_CHART_MARGIN}>
<CartesianGrid stroke={GRAPH_BACKGROUND_COLOR} vertical={false} /> <CartesianGrid stroke={GRAPH_BACKGROUND_COLOR} vertical={false} />
<XAxis dataKey="timestamp" /> <XAxis dataKey="timestamp" />
<YAxis
tickFormatter={(value: number) => axisTickFormatter(value, '%')}
/>
<Tooltip content={<CustomTooltip isPercentage />} /> <Tooltip content={<CustomTooltip isPercentage />} />
<Legend <Legend
align="left" align="left"
content={(props) => content={(props) =>
renderLegend(props as LegendProps, `${total}%`, activeKeys) renderLegend(props as LegendProps, total, activeKeys, true)
} }
layout="vertical" layout="vertical"
verticalAlign="top" verticalAlign="top"

View File

@ -51,6 +51,7 @@ import {
} from '../../utils/DataInsightUtils'; } from '../../utils/DataInsightUtils';
import { showErrorToast } from '../../utils/ToastUtils'; import { showErrorToast } from '../../utils/ToastUtils';
import './DataInsightDetail.less'; import './DataInsightDetail.less';
import DataInsightProgressBar from './DataInsightProgressBar';
import { EmptyGraphPlaceholder } from './EmptyGraphPlaceholder'; import { EmptyGraphPlaceholder } from './EmptyGraphPlaceholder';
interface Props { interface Props {
@ -121,6 +122,11 @@ const TierInsight: FC<Props> = ({ chartFilter }) => {
</Typography.Text> </Typography.Text>
</> </>
}> }>
<DataInsightProgressBar
className="m-b-md"
progress={Number(total)}
width={250}
/>
{data.length ? ( {data.length ? (
<ResponsiveContainer debounce={1} minHeight={400}> <ResponsiveContainer debounce={1} minHeight={400}>
<LineChart data={data} margin={BAR_CHART_MARGIN}> <LineChart data={data} margin={BAR_CHART_MARGIN}>
@ -131,7 +137,7 @@ const TierInsight: FC<Props> = ({ chartFilter }) => {
<Legend <Legend
align="left" align="left"
content={(props) => content={(props) =>
renderLegend(props as LegendProps, `${total}%`, activeKeys) renderLegend(props as LegendProps, total, activeKeys, false)
} }
layout="vertical" layout="vertical"
verticalAlign="top" verticalAlign="top"

View File

@ -74,6 +74,14 @@ const TopViewEntities: FC<Props> = ({ chartFilter }) => {
return <Link to={pathname || '#'}>{getDecodedFqn(entityFqn)}</Link>; return <Link to={pathname || '#'}>{getDecodedFqn(entityFqn)}</Link>;
}, },
}, },
{
title: t('label.data-asset-type'),
dataIndex: 'entityType',
key: 'entityType',
render: (entityType: string) => (
<Typography.Text>{entityType}</Typography.Text>
),
},
{ {
title: t('label.owner'), title: t('label.owner'),
dataIndex: 'owner', dataIndex: 'owner',

View File

@ -550,7 +550,8 @@
"dbt-Configuration-source": "DBT Configuration Source", "dbt-Configuration-source": "DBT Configuration Source",
"select-dbt-source": "Select DBT Source", "select-dbt-source": "Select DBT Source",
"no-selected-dbt": "No source selected for DBT Configuration.", "no-selected-dbt": "No source selected for DBT Configuration.",
"dbt": "DBT" "dbt": "DBT",
"latest": "Latest"
}, },
"message": { "message": {
"service-email-required": "Service account Email is required", "service-email-required": "Service account Email is required",

View File

@ -80,3 +80,41 @@
.side-panel-icons { .side-panel-icons {
color: @icon-color; color: @icon-color;
} }
.data-insight-progress-bar {
.ant-progress-bg,
.ant-progress-success-bg {
// library has given height directly via style attribute , so to override need to provide !important
height: 30px !important;
}
.ant-progress-outer {
margin-right: 0;
padding-right: 0;
}
.ant-progress-inner,
.ant-progress-bg,
.ant-progress-success-bg {
border-radius: 4px;
}
.ant-progress-text {
display: flex;
margin: 0;
position: absolute;
width: 100%;
justify-content: space-between;
align-items: center;
height: 100%;
top: 0px;
right: 2px;
left: 2px;
padding: 0 16px 0 8px;
font-size: 12px;
}
.data-insight-kpi-target {
height: 100%;
position: absolute;
left: 0;
border-right: 2px solid #1890ff;
border-radius: 4px;
}
}

View File

@ -23,8 +23,9 @@ import {
Typography, Typography,
} from 'antd'; } from 'antd';
import { t } from 'i18next'; import { t } from 'i18next';
import React, { useEffect, useLayoutEffect, useState } from 'react'; import React, { useEffect, useLayoutEffect, useMemo, useState } from 'react';
import { useHistory, useParams } from 'react-router-dom'; import { useHistory, useParams } from 'react-router-dom';
import { getListKPIs } from '../../axiosAPIs/KpiAPI';
import { searchQuery } from '../../axiosAPIs/searchAPI'; import { searchQuery } from '../../axiosAPIs/searchAPI';
import PageLayoutV1 from '../../components/containers/PageLayoutV1'; import PageLayoutV1 from '../../components/containers/PageLayoutV1';
import DailyActiveUsersChart from '../../components/DataInsightDetail/DailyActiveUsersChart'; import DailyActiveUsersChart from '../../components/DataInsightDetail/DailyActiveUsersChart';
@ -49,6 +50,7 @@ import {
import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil'; import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
import { SearchIndex } from '../../enums/search.enum'; import { SearchIndex } from '../../enums/search.enum';
import { DataInsightChartType } from '../../generated/dataInsight/dataInsightChartResult'; import { DataInsightChartType } from '../../generated/dataInsight/dataInsightChartResult';
import { Kpi } from '../../generated/dataInsight/kpi/kpi';
import { useAuth } from '../../hooks/authHooks'; import { useAuth } from '../../hooks/authHooks';
import { import {
ChartFilter, ChartFilter,
@ -79,9 +81,25 @@ const DataInsightPage = () => {
const [activeTab, setActiveTab] = useState(DataInsightTabs.DATA_ASSETS); const [activeTab, setActiveTab] = useState(DataInsightTabs.DATA_ASSETS);
const [chartFilter, setChartFilter] = const [chartFilter, setChartFilter] =
useState<ChartFilter>(INITIAL_CHART_FILTER); useState<ChartFilter>(INITIAL_CHART_FILTER);
const [kpiList, setKpiList] = useState<Array<Kpi>>([]);
const [selectedChart, setSelectedChart] = useState<DataInsightChartType>(); const [selectedChart, setSelectedChart] = useState<DataInsightChartType>();
const { descriptionKpi, ownerKpi } = useMemo(() => {
return {
descriptionKpi: kpiList.find(
(kpi) =>
kpi.dataInsightChart.name ===
DataInsightChartType.PercentageOfEntitiesWithDescriptionByType
),
ownerKpi: kpiList.find(
(kpi) =>
kpi.dataInsightChart.name ===
DataInsightChartType.PercentageOfEntitiesWithOwnerByType
),
};
}, [kpiList]);
const handleTierChange = (tiers: string[] = []) => { const handleTierChange = (tiers: string[] = []) => {
setChartFilter((previous) => ({ setChartFilter((previous) => ({
...previous, ...previous,
@ -137,6 +155,15 @@ const DataInsightPage = () => {
} }
}; };
const fetchKpiList = async () => {
try {
const response = await getListKPIs({ fields: 'dataInsightChart' });
setKpiList(response.data);
} catch (_err) {
setKpiList([]);
}
};
const handleScrollToChart = (chartType: DataInsightChartType) => { const handleScrollToChart = (chartType: DataInsightChartType) => {
if (ENTITIES_CHARTS.includes(chartType)) { if (ENTITIES_CHARTS.includes(chartType)) {
history.push(getDataInsightPathWithFqn(DataInsightTabs.DATA_ASSETS)); history.push(getDataInsightPathWithFqn(DataInsightTabs.DATA_ASSETS));
@ -162,6 +189,7 @@ const DataInsightPage = () => {
useEffect(() => { useEffect(() => {
fetchDefaultTeamOptions(); fetchDefaultTeamOptions();
fetchKpiList();
}, []); }, []);
useEffect(() => { useEffect(() => {
@ -260,7 +288,7 @@ const DataInsightPage = () => {
{/* Do not show KPIChart for app analytics */} {/* Do not show KPIChart for app analytics */}
{tab !== DataInsightTabs.APP_ANALYTICS && ( {tab !== DataInsightTabs.APP_ANALYTICS && (
<Col span={24}> <Col span={24}>
<KPIChart chartFilter={chartFilter} /> <KPIChart chartFilter={chartFilter} kpiList={kpiList} />
</Col> </Col>
)} )}
{activeTab === DataInsightTabs.DATA_ASSETS && ( {activeTab === DataInsightTabs.DATA_ASSETS && (
@ -269,10 +297,13 @@ const DataInsightPage = () => {
<TotalEntityInsight chartFilter={chartFilter} /> <TotalEntityInsight chartFilter={chartFilter} />
</Col> </Col>
<Col span={24}> <Col span={24}>
<DescriptionInsight chartFilter={chartFilter} /> <DescriptionInsight
chartFilter={chartFilter}
kpi={descriptionKpi}
/>
</Col> </Col>
<Col span={24}> <Col span={24}>
<OwnerInsight chartFilter={chartFilter} /> <OwnerInsight chartFilter={chartFilter} kpi={ownerKpi} />
</Col> </Col>
<Col span={24}> <Col span={24}>
<TierInsight chartFilter={chartFilter} /> <TierInsight chartFilter={chartFilter} />

View File

@ -62,21 +62,26 @@ const checkIsPercentageGraph = (dataInsightChartType: DataInsightChartType) =>
export const renderLegend = ( export const renderLegend = (
legendData: LegendProps, legendData: LegendProps,
latest: string, latest: string | number,
activeKeys = [] as string[] activeKeys = [] as string[],
showLatestValue = true
) => { ) => {
const { payload = [] } = legendData; const { payload = [] } = legendData;
return ( return (
<> <>
<Typography.Text className="data-insight-label-text"> {showLatestValue && (
Latest <>
</Typography.Text> <Typography.Text className="data-insight-label-text">
<Typography Latest
className="font-bold text-lg" </Typography.Text>
style={{ margin: '0px 0px 16px' }}> <Typography
{latest} className="font-bold text-lg"
</Typography> style={{ margin: '0px 0px 16px' }}>
{latest}
</Typography>
</>
)}
<ul className="mr-2"> <ul className="mr-2">
{payload.map((entry, index) => { {payload.map((entry, index) => {
const isActive = const isActive =
@ -399,7 +404,7 @@ export const getGraphDataByTierType = (rawData: TotalEntitiesByTier[]) => {
return { return {
timestamp: timestamp, timestamp: timestamp,
[tiering]: (data?.entityCountFraction || 0) * 100, [tiering]: ((data?.entityCountFraction || 0) * 100).toFixed(2),
}; };
} }