MINOR: Fix PII Charts (#20481)

This commit is contained in:
Mayur Singal 2025-04-08 18:03:23 +05:30 committed by GitHub
parent a990a597f4
commit 202519fd2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 109 additions and 8 deletions

View File

@ -291,9 +291,9 @@ public class MigrationUtil {
"assets_with_pii_bar", "assets_with_pii_bar",
new LineChart() new LineChart()
.withMetrics(List.of(new LineChartMetric().withFormula("count(k='id.keyword')"))) .withMetrics(List.of(new LineChartMetric().withFormula("count(k='id.keyword')")))
.withxAxisField("tags.tagFQN") .withxAxisField("columns.tags.tagFQN")
.withIncludeXAxisFiled("pii.*") .withIncludeXAxisFiled("pii.*")
.withGroupBy("tags.name.keyword"), .withGroupBy("columns.tags.name.keyword"),
DataInsightCustomChart.ChartType.BAR_CHART); DataInsightCustomChart.ChartType.BAR_CHART);
createChart( createChart(
@ -330,8 +330,7 @@ public class MigrationUtil {
List.of( List.of(
new LineChartMetric() new LineChartMetric()
.withFormula( .withFormula(
"(count(q='tags.tagFQN: pii.sensitive OR tags.tagFQN:" "(count(q='columns.tags.tagFQN: pii.*')/count(k='id.keyword'))*100"))));
+ " pii.nonsensitive OR tags.tagFQN: pii.none')/count(k='id.keyword'))*100"))));
createChart( createChart(
"assets_with_tier", "assets_with_tier",

View File

@ -15,7 +15,7 @@ import { CloseOutlined } from '@ant-design/icons';
import { Alert, Col, Row } from 'antd'; import { Alert, Col, Row } from 'antd';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import classNames from 'classnames'; import classNames from 'classnames';
import { isUndefined, toLower } from 'lodash'; import { isUndefined } from 'lodash';
import { ServiceTypes } from 'Models'; import { ServiceTypes } from 'Models';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
@ -28,6 +28,7 @@ import {
getDayAgoStartGMTinMillis, getDayAgoStartGMTinMillis,
} from '../../utils/date-time/DateTimeUtils'; } from '../../utils/date-time/DateTimeUtils';
import { import {
filterDistributionChartItem,
getPlatformInsightsChartDataFormattingMethod, getPlatformInsightsChartDataFormattingMethod,
getStatusIconFromStatusType, getStatusIconFromStatusType,
} from '../../utils/ServiceInsightsTabUtils'; } from '../../utils/ServiceInsightsTabUtils';
@ -88,10 +89,10 @@ const ServiceInsightsTab = ({
const piiDistributionChart = chartsData[ const piiDistributionChart = chartsData[
SystemChartType.PIIDistribution SystemChartType.PIIDistribution
]?.results.filter((item) => item.term.includes(toLower(item.group))); ]?.results.filter(filterDistributionChartItem);
const tierDistributionChart = chartsData[ const tierDistributionChart = chartsData[
SystemChartType.TierDistribution SystemChartType.TierDistribution
]?.results.filter((item) => item.term.includes(toLower(item.group))); ]?.results.filter(filterDistributionChartItem);
setChartsResults({ setChartsResults({
platformInsightsChart, platformInsightsChart,

View File

@ -0,0 +1,84 @@
/*
* Copyright 2025 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 { filterDistributionChartItem } from './ServiceInsightsTabUtils';
describe('ServiceInsightsTabUtils', () => {
describe('filterDistributionChartItem', () => {
it('should return true when term has exactly 2 parts and second part matches group', () => {
const item = {
term: 'service.group',
group: 'group',
};
const result = filterDistributionChartItem(item);
expect(result).toBe(true);
});
it('should return false when term has more than 2 parts', () => {
const item = {
term: 'service.group.extra',
group: 'group',
};
const result = filterDistributionChartItem(item);
expect(result).toBe(false);
});
it('should return false when term has less than 2 parts', () => {
const item = {
term: 'service',
group: 'group',
};
const result = filterDistributionChartItem(item);
expect(result).toBe(false);
});
it('should return false when second part does not match group', () => {
const item = {
term: 'service.different',
group: 'group',
};
const result = filterDistributionChartItem(item);
expect(result).toBe(false);
});
it('should handle case-insensitive comparison', () => {
const item = {
term: 'service.GROUP',
group: 'group',
};
const result = filterDistributionChartItem(item);
expect(result).toBe(true);
});
it('should handle case-insensitive comparison with . in name', () => {
const item = {
term: 'service."Random.group"',
group: 'random.group',
};
const result = filterDistributionChartItem(item);
expect(result).toBe(true);
});
});
});

View File

@ -12,7 +12,7 @@
*/ */
import { ExclamationCircleOutlined } from '@ant-design/icons'; import { ExclamationCircleOutlined } from '@ant-design/icons';
import { Typography } from 'antd'; import { Typography } from 'antd';
import { first, isEmpty, last, round, sortBy } from 'lodash'; import { first, isEmpty, last, round, sortBy, toLower } from 'lodash';
import { ServiceTypes } from 'Models'; import { ServiceTypes } from 'Models';
import React, { FunctionComponent } from 'react'; import React, { FunctionComponent } from 'react';
import { ReactComponent as SuccessIcon } from '../assets/svg/ic-check-circle-new.svg'; import { ReactComponent as SuccessIcon } from '../assets/svg/ic-check-circle-new.svg';
@ -35,6 +35,7 @@ import { DataInsightCustomChartResult } from '../rest/DataInsightAPI';
import i18n from '../utils/i18next/LocalUtil'; import i18n from '../utils/i18next/LocalUtil';
import { Transi18next } from './CommonUtils'; import { Transi18next } from './CommonUtils';
import documentationLinksClassBase from './DocumentationLinksClassBase'; import documentationLinksClassBase from './DocumentationLinksClassBase';
import Fqn from './Fqn';
const { t } = i18n; const { t } = i18n;
@ -279,3 +280,19 @@ export const getServiceInsightsWidgetPlaceholder = ({
</ErrorPlaceHolder> </ErrorPlaceHolder>
); );
}; };
export const filterDistributionChartItem = (item: {
term: string;
group: string;
}) => {
if (Fqn.split(item.term).length !== 2) {
// Invalid Tag FQN
return false;
}
// clean start and end quotes
let tag_name = Fqn.split(item.term)[1];
tag_name = tag_name.replace(/(^["']+|["']+$)/g, '');
return toLower(tag_name) === toLower(item.group);
};