From 202519fd2d97d11a6dffd79aceb0a0b6797ec02f Mon Sep 17 00:00:00 2001 From: Mayur Singal <39544459+ulixius9@users.noreply.github.com> Date: Tue, 8 Apr 2025 18:03:23 +0530 Subject: [PATCH] MINOR: Fix PII Charts (#20481) --- .../migration/utils/v170/MigrationUtil.java | 7 +- .../ServiceInsights/ServiceInsightsTab.tsx | 7 +- .../utils/ServiceInsightsTabUtils.test.tsx | 84 +++++++++++++++++++ .../ui/src/utils/ServiceInsightsTabUtils.tsx | 19 ++++- 4 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/ServiceInsightsTabUtils.test.tsx diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v170/MigrationUtil.java b/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v170/MigrationUtil.java index 5f0ce28c0ca..7c1e2797a41 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v170/MigrationUtil.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v170/MigrationUtil.java @@ -291,9 +291,9 @@ public class MigrationUtil { "assets_with_pii_bar", new LineChart() .withMetrics(List.of(new LineChartMetric().withFormula("count(k='id.keyword')"))) - .withxAxisField("tags.tagFQN") + .withxAxisField("columns.tags.tagFQN") .withIncludeXAxisFiled("pii.*") - .withGroupBy("tags.name.keyword"), + .withGroupBy("columns.tags.name.keyword"), DataInsightCustomChart.ChartType.BAR_CHART); createChart( @@ -330,8 +330,7 @@ public class MigrationUtil { List.of( new LineChartMetric() .withFormula( - "(count(q='tags.tagFQN: pii.sensitive OR tags.tagFQN:" - + " pii.nonsensitive OR tags.tagFQN: pii.none')/count(k='id.keyword'))*100")))); + "(count(q='columns.tags.tagFQN: pii.*')/count(k='id.keyword'))*100")))); createChart( "assets_with_tier", diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ServiceInsights/ServiceInsightsTab.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ServiceInsights/ServiceInsightsTab.tsx index 09c2b44b464..bfcd4e22ae1 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ServiceInsights/ServiceInsightsTab.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/ServiceInsights/ServiceInsightsTab.tsx @@ -15,7 +15,7 @@ import { CloseOutlined } from '@ant-design/icons'; import { Alert, Col, Row } from 'antd'; import { AxiosError } from 'axios'; import classNames from 'classnames'; -import { isUndefined, toLower } from 'lodash'; +import { isUndefined } from 'lodash'; import { ServiceTypes } from 'Models'; import React, { useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; @@ -28,6 +28,7 @@ import { getDayAgoStartGMTinMillis, } from '../../utils/date-time/DateTimeUtils'; import { + filterDistributionChartItem, getPlatformInsightsChartDataFormattingMethod, getStatusIconFromStatusType, } from '../../utils/ServiceInsightsTabUtils'; @@ -88,10 +89,10 @@ const ServiceInsightsTab = ({ const piiDistributionChart = chartsData[ SystemChartType.PIIDistribution - ]?.results.filter((item) => item.term.includes(toLower(item.group))); + ]?.results.filter(filterDistributionChartItem); const tierDistributionChart = chartsData[ SystemChartType.TierDistribution - ]?.results.filter((item) => item.term.includes(toLower(item.group))); + ]?.results.filter(filterDistributionChartItem); setChartsResults({ platformInsightsChart, diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/ServiceInsightsTabUtils.test.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/ServiceInsightsTabUtils.test.tsx new file mode 100644 index 00000000000..430d66fd113 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/utils/ServiceInsightsTabUtils.test.tsx @@ -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); + }); + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/ServiceInsightsTabUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/ServiceInsightsTabUtils.tsx index 4c4f9872e7a..c7b15e37c05 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/ServiceInsightsTabUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/ServiceInsightsTabUtils.tsx @@ -12,7 +12,7 @@ */ import { ExclamationCircleOutlined } from '@ant-design/icons'; 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 React, { FunctionComponent } from 'react'; 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 { Transi18next } from './CommonUtils'; import documentationLinksClassBase from './DocumentationLinksClassBase'; +import Fqn from './Fqn'; const { t } = i18n; @@ -279,3 +280,19 @@ export const getServiceInsightsWidgetPlaceholder = ({ ); }; + +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); +};