mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-10 14:57:57 +00:00
Refactor: Improvement for data quality overview tab (#18523)
* Refactor: Improvement for data quality overview tab * unite test for new component * minor improvement * remove unused icon
This commit is contained in:
parent
66cf003cc3
commit
b43c2ba4bd
@ -0,0 +1,10 @@
|
||||
<svg viewBox="0 0 25 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.6016 12.2369C12.9898 12.2369 13.3047 11.9221 13.3047 11.5338V9.10254C13.3047 8.71426 12.9898 8.39941 12.6016 8.39941C12.2133 8.39941 11.8984 8.71426 11.8984 9.10254V11.5338C11.8984 11.9221 12.2133 12.2369 12.6016 12.2369Z" fill="#F44336"/>
|
||||
<path d="M12.6016 15.1518C12.9898 15.1518 13.3047 14.8369 13.3047 14.4486V14.2432C13.3047 13.8549 12.9898 13.54 12.6016 13.54C12.2133 13.54 11.8984 13.8549 11.8984 14.2432V14.4486C11.8984 14.8369 12.2133 15.1518 12.6016 15.1518Z" fill="#F44336"/>
|
||||
<path d="M19.768 16.5928V11.7475C19.768 7.7959 16.5531 4.58105 12.6016 4.58105C8.65 4.58105 5.43594 7.7959 5.43594 11.7475V16.5928C3.94844 16.9889 2.84375 18.335 2.84375 19.9451V20.4201C2.84375 21.6357 3.83203 22.624 5.04687 22.624H20.1562C21.3719 22.624 22.3602 21.635 22.3602 20.4201V19.9451C22.3602 18.335 21.2555 16.9896 19.768 16.5928ZM12.6016 5.98809C15.7773 5.98809 18.3609 8.57168 18.3609 11.7475V16.4631H6.84141V11.7475C6.84141 8.57168 9.42578 5.98809 12.6016 5.98809ZM20.9531 20.4209C20.9531 20.8607 20.5953 21.2186 20.1555 21.2186H5.04687C4.60703 21.2186 4.25 20.8607 4.25 20.4209V19.9459C4.25 18.8014 5.18125 17.8709 6.32578 17.8709H18.8789C20.0234 17.8709 20.9539 18.8014 20.9539 19.9459L20.9531 20.4209Z" fill="#F44336"/>
|
||||
<path d="M12.6016 2.81641C12.9898 2.81641 13.3047 2.50156 13.3047 2.11328V1.07813C13.3047 0.689844 12.9898 0.375 12.6016 0.375C12.2133 0.375 11.8984 0.689844 11.8984 1.07813V2.1125C11.8984 2.50078 12.2133 2.81641 12.6016 2.81641Z" fill="#F44336"/>
|
||||
<path d="M3.40156 12.0156C3.40156 11.6273 3.08672 11.3125 2.69844 11.3125H1.66406C1.27578 11.3125 0.960938 11.6273 0.960938 12.0156C0.960938 12.4039 1.27578 12.7187 1.66406 12.7187H2.69844C3.08672 12.7195 3.40156 12.4039 3.40156 12.0156Z" fill="#F44336"/>
|
||||
<path d="M23.539 11.3125H22.5046C22.1164 11.3125 21.8015 11.6273 21.8015 12.0156C21.8015 12.4039 22.1164 12.7187 22.5046 12.7187H23.539C23.9273 12.7187 24.2421 12.4039 24.2421 12.0156C24.2421 11.6273 23.9273 11.3125 23.539 11.3125Z" fill="#F44336"/>
|
||||
<path d="M5.10156 5.51035C5.23906 5.64863 5.41875 5.71738 5.59922 5.71738C5.77969 5.71738 5.95859 5.64863 6.09609 5.51113C6.37109 5.23613 6.37109 4.79082 6.09609 4.51738L5.36484 3.78535C5.09062 3.50879 4.64531 3.50957 4.37031 3.78457C4.09531 4.05957 4.09531 4.5041 4.37031 4.7791L5.10156 5.51035Z" fill="#F44336"/>
|
||||
<path d="M19.604 5.71738C19.7837 5.71738 19.9642 5.64863 20.1017 5.51113L20.8337 4.7791C21.1087 4.5041 21.1087 4.05879 20.8337 3.78457C20.5587 3.51035 20.1134 3.50957 19.8392 3.78457L19.1071 4.5166C18.8321 4.7916 18.8321 5.23691 19.1071 5.51113C19.2438 5.64863 19.4235 5.71738 19.604 5.71738Z" fill="#F44336"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@ -157,6 +157,7 @@ export const DataAssetsHeader = ({
|
||||
onUpdateRetentionPeriod,
|
||||
extraDropdownContent,
|
||||
onMetricUpdate,
|
||||
badge,
|
||||
}: DataAssetsHeaderProps) => {
|
||||
const { currentUser } = useApplicationStore();
|
||||
const USER_ID = currentUser?.id ?? '';
|
||||
@ -368,6 +369,7 @@ export const DataAssetsHeader = ({
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<EntityHeaderTitle
|
||||
badge={badge}
|
||||
deleted={dataAsset?.deleted}
|
||||
displayName={dataAsset.displayName}
|
||||
icon={icon}
|
||||
|
||||
@ -101,6 +101,7 @@ export type DataAssetsHeaderProps = {
|
||||
allowSoftDelete?: boolean;
|
||||
showDomain?: boolean;
|
||||
isRecursiveDelete?: boolean;
|
||||
badge?: React.ReactNode;
|
||||
afterDomainUpdateAction?: (asset: DataAssetWithDomains) => void;
|
||||
afterDeleteAction?: (isSoftDelete?: boolean, version?: number) => void;
|
||||
onTierUpdate: (tier?: Tag) => Promise<void>;
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2024 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 { Card, Typography } from 'antd';
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { DataStatisticWidgetProps } from '../../DataQuality.interface';
|
||||
import './data-statistic-widget.less';
|
||||
|
||||
const DataStatisticWidget = ({
|
||||
name,
|
||||
title,
|
||||
icon,
|
||||
dataLabel,
|
||||
countValue,
|
||||
redirectPath,
|
||||
linkLabel,
|
||||
isLoading,
|
||||
}: DataStatisticWidgetProps) => {
|
||||
const Icon = icon;
|
||||
|
||||
return (
|
||||
<Card
|
||||
className="h-full"
|
||||
data-testid={`${name}-data-statistic-widget`}
|
||||
loading={isLoading}>
|
||||
<Typography.Paragraph className="text-xs text-grey-muted data-statistic-widget-title">
|
||||
{title}
|
||||
</Typography.Paragraph>
|
||||
|
||||
<div className="d-flex gap-2 items-center m-b-sm">
|
||||
<Icon height={22} width={22} />
|
||||
<Typography.Paragraph
|
||||
className="font-medium text-xl m-b-0"
|
||||
data-testid="total-value">
|
||||
{`${countValue} ${dataLabel}`}
|
||||
</Typography.Paragraph>
|
||||
</div>
|
||||
<Typography.Paragraph>
|
||||
<Link to={redirectPath}>{linkLabel}</Link>
|
||||
</Typography.Paragraph>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default DataStatisticWidget;
|
||||
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2024 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 '@testing-library/jest-dom/extend-expect';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { DataStatisticWidgetProps } from '../../DataQuality.interface';
|
||||
import DataStatisticWidget from './DataStatisticWidget.component';
|
||||
|
||||
const mockProps: DataStatisticWidgetProps = {
|
||||
name: 'test-widget',
|
||||
title: 'Test Title',
|
||||
icon: () => <svg data-testid="test-icon" />,
|
||||
dataLabel: 'items',
|
||||
countValue: 10,
|
||||
redirectPath: '/test-path',
|
||||
linkLabel: 'View Details',
|
||||
isLoading: false,
|
||||
};
|
||||
|
||||
describe('DataStatisticWidget component', () => {
|
||||
it('should render the widget with provided props', () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<DataStatisticWidget {...mockProps} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByTestId('test-widget-data-statistic-widget')
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText('Test Title')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('test-icon')).toBeInTheDocument();
|
||||
expect(screen.getByText('10 items')).toBeInTheDocument();
|
||||
expect(screen.getByText('View Details')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show loading state when isLoading is true', () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<DataStatisticWidget {...mockProps} isLoading />
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
expect(screen.getByTestId('test-widget-data-statistic-widget')).toHaveClass(
|
||||
'ant-card-loading'
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2024 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 (reference) url('../../../../styles/variables.less');
|
||||
|
||||
.data-statistic-widget-title {
|
||||
div&.ant-typography {
|
||||
margin-bottom: @margin-xlg;
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,7 @@ const IncidentTimeChartWidget = ({
|
||||
name,
|
||||
title,
|
||||
chartFilter,
|
||||
height,
|
||||
}: IncidentTimeChartWidgetProps) => {
|
||||
const [chartData, setChartData] = useState<CustomAreaChartData[]>([]);
|
||||
const [isChartLoading, setIsChartLoading] = useState(true);
|
||||
@ -86,6 +87,7 @@ const IncidentTimeChartWidget = ({
|
||||
|
||||
<CustomAreaChart
|
||||
data={chartData}
|
||||
height={height}
|
||||
name={name}
|
||||
valueFormatter={convertMillisecondsToHumanReadableFormat}
|
||||
/>
|
||||
|
||||
@ -26,6 +26,7 @@ const TestCaseStatusAreaChartWidget = ({
|
||||
title,
|
||||
chartColorScheme,
|
||||
chartFilter,
|
||||
height,
|
||||
}: TestCaseStatusAreaChartWidgetProps) => {
|
||||
const [chartData, setChartData] = useState<CustomAreaChartData[]>([]);
|
||||
const [isChartLoading, setIsChartLoading] = useState(true);
|
||||
@ -82,6 +83,7 @@ const TestCaseStatusAreaChartWidget = ({
|
||||
<CustomAreaChart
|
||||
colorScheme={chartColorScheme}
|
||||
data={chartData}
|
||||
height={height}
|
||||
name={name}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
@ -55,6 +55,7 @@ export interface IncidentTimeChartWidgetProps {
|
||||
incidentMetricType: IncidentTimeMetricsType;
|
||||
name: string;
|
||||
chartFilter?: DataQualityDashboardChartFilters;
|
||||
height?: number;
|
||||
}
|
||||
export interface TestCaseStatusAreaChartWidgetProps {
|
||||
title: string;
|
||||
@ -62,8 +63,20 @@ export interface TestCaseStatusAreaChartWidgetProps {
|
||||
name: string;
|
||||
chartColorScheme?: AreaChartColorScheme;
|
||||
chartFilter?: DataQualityDashboardChartFilters;
|
||||
height?: number;
|
||||
}
|
||||
|
||||
export interface PieChartWidgetCommonProps {
|
||||
chartFilter?: DataQualityDashboardChartFilters;
|
||||
}
|
||||
|
||||
export interface DataStatisticWidgetProps {
|
||||
name: string;
|
||||
title: string;
|
||||
icon: SvgComponent;
|
||||
dataLabel: string;
|
||||
countValue: number;
|
||||
redirectPath: string;
|
||||
linkLabel: string;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
@ -150,6 +150,7 @@
|
||||
"chart-entity": "{{entity}} Diagramm",
|
||||
"chart-plural": "Diagramme",
|
||||
"chart-type": "Chart type",
|
||||
"check-data-quality-failure": "Check data quality failure",
|
||||
"check-status": "Status überprüfen",
|
||||
"children": "Kinder",
|
||||
"children-lowercase": "kinder",
|
||||
@ -619,6 +620,7 @@
|
||||
"invalid-condition": "Ungültige Bedingung",
|
||||
"invalid-name": "Ungültiger Name",
|
||||
"is-ready-for-preview": "ist bereit zur Vorschau",
|
||||
"issue": "Issue",
|
||||
"issue-plural": "Issues",
|
||||
"items-selected-lowercase": "items selected",
|
||||
"january": "Januar",
|
||||
|
||||
@ -150,6 +150,7 @@
|
||||
"chart-entity": "Chart {{entity}}",
|
||||
"chart-plural": "Charts",
|
||||
"chart-type": "Chart type",
|
||||
"check-data-quality-failure": "Check data quality failure",
|
||||
"check-status": "Check status",
|
||||
"children": "Children",
|
||||
"children-lowercase": "children",
|
||||
@ -619,6 +620,7 @@
|
||||
"invalid-condition": "Invalid condition",
|
||||
"invalid-name": "Invalid Name",
|
||||
"is-ready-for-preview": "is ready for preview",
|
||||
"issue": "Issue",
|
||||
"issue-plural": "Issues",
|
||||
"items-selected-lowercase": "items selected",
|
||||
"january": "January",
|
||||
|
||||
@ -150,6 +150,7 @@
|
||||
"chart-entity": "Gráfico {{entity}}",
|
||||
"chart-plural": "Gráficos",
|
||||
"chart-type": "Chart type",
|
||||
"check-data-quality-failure": "Check data quality failure",
|
||||
"check-status": "Verificar estado",
|
||||
"children": "Hijos",
|
||||
"children-lowercase": "hijos",
|
||||
@ -619,6 +620,7 @@
|
||||
"invalid-condition": "Condición inválida",
|
||||
"invalid-name": "Nombre inválido",
|
||||
"is-ready-for-preview": "está listo para previsualización",
|
||||
"issue": "Issue",
|
||||
"issue-plural": "Problemas",
|
||||
"items-selected-lowercase": "elementos seleccionados",
|
||||
"january": "Enero",
|
||||
|
||||
@ -150,6 +150,7 @@
|
||||
"chart-entity": "Graphique {{entity}}",
|
||||
"chart-plural": "Graphiques",
|
||||
"chart-type": "Chart type",
|
||||
"check-data-quality-failure": "Check data quality failure",
|
||||
"check-status": "Vérifier le Statut",
|
||||
"children": "Enfants",
|
||||
"children-lowercase": "enfants",
|
||||
@ -619,6 +620,7 @@
|
||||
"invalid-condition": "Condition Invalide",
|
||||
"invalid-name": "Nom Invalide",
|
||||
"is-ready-for-preview": "est prêt à être prévisualisé",
|
||||
"issue": "Issue",
|
||||
"issue-plural": "Problèmes",
|
||||
"items-selected-lowercase": "items selected",
|
||||
"january": "Janvier",
|
||||
|
||||
@ -150,6 +150,7 @@
|
||||
"chart-entity": "Gráfico {{entity}}",
|
||||
"chart-plural": "Gráficos",
|
||||
"chart-type": "Tipo de gráfico",
|
||||
"check-data-quality-failure": "Check data quality failure",
|
||||
"check-status": "Verificar estado",
|
||||
"children": "Fillos",
|
||||
"children-lowercase": "fillos",
|
||||
@ -619,6 +620,7 @@
|
||||
"invalid-condition": "Condición non válida",
|
||||
"invalid-name": "Nome non válido",
|
||||
"is-ready-for-preview": "está listo para previsualización",
|
||||
"issue": "Issue",
|
||||
"issue-plural": "Problemas",
|
||||
"items-selected-lowercase": "elementos seleccionados",
|
||||
"january": "Xaneiro",
|
||||
|
||||
@ -150,6 +150,7 @@
|
||||
"chart-entity": "תרשים {{entity}}",
|
||||
"chart-plural": "תרשימים",
|
||||
"chart-type": "Chart type",
|
||||
"check-data-quality-failure": "Check data quality failure",
|
||||
"check-status": "בדוק סטטוס",
|
||||
"children": "ילדים",
|
||||
"children-lowercase": "ילדים",
|
||||
@ -619,6 +620,7 @@
|
||||
"invalid-condition": "תנאי לא תקין",
|
||||
"invalid-name": "שם לא תקין",
|
||||
"is-ready-for-preview": "מוכן לתצוגה מקדימה",
|
||||
"issue": "Issue",
|
||||
"issue-plural": "Issues",
|
||||
"items-selected-lowercase": "items selected",
|
||||
"january": "ינואר",
|
||||
|
||||
@ -150,6 +150,7 @@
|
||||
"chart-entity": "{{entity}}のチャート",
|
||||
"chart-plural": "チャート",
|
||||
"chart-type": "Chart type",
|
||||
"check-data-quality-failure": "Check data quality failure",
|
||||
"check-status": "ステータスチェック",
|
||||
"children": "Children",
|
||||
"children-lowercase": "children",
|
||||
@ -619,6 +620,7 @@
|
||||
"invalid-condition": "不正な条件",
|
||||
"invalid-name": "不正な名称",
|
||||
"is-ready-for-preview": "はプレビューの準備ができました",
|
||||
"issue": "Issue",
|
||||
"issue-plural": "Issues",
|
||||
"items-selected-lowercase": "items selected",
|
||||
"january": "1月",
|
||||
|
||||
@ -150,6 +150,7 @@
|
||||
"chart-entity": "Chart {{entity}}",
|
||||
"chart-plural": "Charts",
|
||||
"chart-type": "Chart type",
|
||||
"check-data-quality-failure": "Check data quality failure",
|
||||
"check-status": "Status controleren",
|
||||
"children": "Kinderen",
|
||||
"children-lowercase": "kinderen",
|
||||
@ -619,6 +620,7 @@
|
||||
"invalid-condition": "Ongeldige voorwaarde",
|
||||
"invalid-name": "Ongeldige naam",
|
||||
"is-ready-for-preview": "is gereed voor voorbeeldweergave",
|
||||
"issue": "Issue",
|
||||
"issue-plural": "Issues",
|
||||
"items-selected-lowercase": "items geselecteerd",
|
||||
"january": "januari",
|
||||
|
||||
@ -150,6 +150,7 @@
|
||||
"chart-entity": "نمودار {{entity}}",
|
||||
"chart-plural": "نمودارها",
|
||||
"chart-type": "نوع نمودار",
|
||||
"check-data-quality-failure": "Check data quality failure",
|
||||
"check-status": "بررسی وضعیت",
|
||||
"children": "فرزندان",
|
||||
"children-lowercase": "فرزندان",
|
||||
@ -619,6 +620,7 @@
|
||||
"invalid-condition": "شرط نامعتبر",
|
||||
"invalid-name": "نام نامعتبر",
|
||||
"is-ready-for-preview": "آماده پیشنمایش است",
|
||||
"issue": "Issue",
|
||||
"issue-plural": "مشکلات",
|
||||
"items-selected-lowercase": "موارد انتخاب شده",
|
||||
"january": "ژانویه",
|
||||
|
||||
@ -150,6 +150,7 @@
|
||||
"chart-entity": "Gráfico {{entity}}",
|
||||
"chart-plural": "Gráficos",
|
||||
"chart-type": "Chart type",
|
||||
"check-data-quality-failure": "Check data quality failure",
|
||||
"check-status": "Verificar status",
|
||||
"children": "Filhos",
|
||||
"children-lowercase": "filhos",
|
||||
@ -619,6 +620,7 @@
|
||||
"invalid-condition": "Condição Inválida",
|
||||
"invalid-name": "Nome Inválido",
|
||||
"is-ready-for-preview": "está pronto para visualização",
|
||||
"issue": "Issue",
|
||||
"issue-plural": "Problemas",
|
||||
"items-selected-lowercase": "Itens Selecionados",
|
||||
"january": "Janeiro",
|
||||
|
||||
@ -150,6 +150,7 @@
|
||||
"chart-entity": "Диаграмма {{entity}}",
|
||||
"chart-plural": "Диаграммы",
|
||||
"chart-type": "Chart type",
|
||||
"check-data-quality-failure": "Check data quality failure",
|
||||
"check-status": "Проверить статус",
|
||||
"children": "Наследники",
|
||||
"children-lowercase": "наследники",
|
||||
@ -619,6 +620,7 @@
|
||||
"invalid-condition": "Недопустимое условие",
|
||||
"invalid-name": "Неверное имя",
|
||||
"is-ready-for-preview": "готов к предварительному просмотру",
|
||||
"issue": "Issue",
|
||||
"issue-plural": "Issues",
|
||||
"items-selected-lowercase": "items selected",
|
||||
"january": "Январь",
|
||||
|
||||
@ -150,6 +150,7 @@
|
||||
"chart-entity": "图表{{entity}}",
|
||||
"chart-plural": "图表",
|
||||
"chart-type": "图表类型",
|
||||
"check-data-quality-failure": "Check data quality failure",
|
||||
"check-status": "检查状态",
|
||||
"children": "子级",
|
||||
"children-lowercase": "子级",
|
||||
@ -619,6 +620,7 @@
|
||||
"invalid-condition": "无效条件",
|
||||
"invalid-name": "无效名称",
|
||||
"is-ready-for-preview": "可预览",
|
||||
"issue": "Issue",
|
||||
"issue-plural": "Issues",
|
||||
"items-selected-lowercase": "已选项",
|
||||
"january": "一月",
|
||||
|
||||
@ -31,4 +31,5 @@ export type DataQualityDashboardChartFilters = {
|
||||
tier?: string[];
|
||||
startTs?: number;
|
||||
endTs?: number;
|
||||
entityFQN?: string;
|
||||
};
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Col, Row, Space, Tabs } from 'antd';
|
||||
import { Col, Row, Space, Tabs, Tooltip } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import { compare } from 'fast-json-patch';
|
||||
@ -20,7 +20,8 @@ import { isEmpty, isEqual, isUndefined } from 'lodash';
|
||||
import { EntityTags } from 'Models';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import { Link, useHistory, useParams } from 'react-router-dom';
|
||||
import { ReactComponent as RedAlertIcon } from '../../assets/svg/ic-alert-red.svg';
|
||||
import { useActivityFeedProvider } from '../../components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
||||
import ActivityThreadPanel from '../../components/ActivityFeed/ActivityThreadPanel/ActivityThreadPanel';
|
||||
import { withActivityFeed } from '../../components/AppRouter/withActivityFeed';
|
||||
@ -75,6 +76,7 @@ import { useFqn } from '../../hooks/useFqn';
|
||||
import { useSub } from '../../hooks/usePubSub';
|
||||
import { FeedCounts } from '../../interface/feed.interface';
|
||||
import { postThread } from '../../rest/feedsAPI';
|
||||
import { getDataQualityLineage } from '../../rest/lineageAPI';
|
||||
import { getQueriesList } from '../../rest/queryAPI';
|
||||
import {
|
||||
addFollower,
|
||||
@ -131,6 +133,7 @@ const TableDetailsPageV1: React.FC = () => {
|
||||
DEFAULT_ENTITY_PERMISSION
|
||||
);
|
||||
const [testCaseSummary, setTestCaseSummary] = useState<TestSummary>();
|
||||
const [dqFailureCount, setDqFailureCount] = useState(0);
|
||||
|
||||
const tableFqn = useMemo(
|
||||
() =>
|
||||
@ -142,6 +145,21 @@ const TableDetailsPageV1: React.FC = () => {
|
||||
[datasetFQN]
|
||||
);
|
||||
|
||||
const alertBadge = useMemo(() => {
|
||||
return tableClassBase.getAlertEnableStatus() && dqFailureCount > 0 ? (
|
||||
<Tooltip placement="right" title={t('label.check-data-quality-failure')}>
|
||||
<Link
|
||||
to={getEntityDetailsPath(
|
||||
EntityType.TABLE,
|
||||
tableFqn,
|
||||
EntityTabs.PROFILER
|
||||
)}>
|
||||
<RedAlertIcon height={24} width={24} />
|
||||
</Link>
|
||||
</Tooltip>
|
||||
) : undefined;
|
||||
}, [dqFailureCount, tableFqn]);
|
||||
|
||||
const extraDropdownContent = useMemo(
|
||||
() =>
|
||||
entityUtilClassBase.getManageExtraOptions(
|
||||
@ -198,16 +216,50 @@ const TableDetailsPageV1: React.FC = () => {
|
||||
}
|
||||
}, [tableFqn, viewUsagePermission]);
|
||||
|
||||
const fetchTestCaseSummary = async () => {
|
||||
if (isUndefined(tableDetails?.testSuite?.id)) {
|
||||
return;
|
||||
const fetchDQFailureCount = async () => {
|
||||
if (!tableClassBase.getAlertEnableStatus()) {
|
||||
setDqFailureCount(0);
|
||||
}
|
||||
|
||||
// Todo: Remove this once we have support for count in API
|
||||
try {
|
||||
const data = await getDataQualityLineage(tableFqn, {
|
||||
upstreamDepth: 3,
|
||||
});
|
||||
const updatedNodes =
|
||||
data.nodes?.filter((node) => node.fullyQualifiedName !== tableFqn) ??
|
||||
[];
|
||||
setDqFailureCount(updatedNodes.length);
|
||||
} catch (error) {
|
||||
setDqFailureCount(0);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchTestCaseSummary = async () => {
|
||||
try {
|
||||
if (isUndefined(tableDetails?.testSuite?.id)) {
|
||||
await fetchDQFailureCount();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await getTestCaseExecutionSummary(
|
||||
tableDetails?.testSuite?.id
|
||||
);
|
||||
setTestCaseSummary(response);
|
||||
|
||||
const failureCount =
|
||||
response.columnTestSummary?.reduce((acc, curr) => {
|
||||
return acc + (curr.failed ?? 0);
|
||||
}, response.failed ?? 0) ??
|
||||
response.failed ??
|
||||
0;
|
||||
|
||||
if (failureCount === 0) {
|
||||
await fetchDQFailureCount();
|
||||
} else {
|
||||
setDqFailureCount(failureCount);
|
||||
}
|
||||
} catch (error) {
|
||||
setTestCaseSummary(undefined);
|
||||
}
|
||||
@ -958,6 +1010,7 @@ const TableDetailsPageV1: React.FC = () => {
|
||||
isRecursiveDelete
|
||||
afterDeleteAction={afterDeleteAction}
|
||||
afterDomainUpdateAction={updateTableDetailsState}
|
||||
badge={alertBadge}
|
||||
dataAsset={tableDetails}
|
||||
entityType={EntityType.TABLE}
|
||||
extraDropdownContent={extraDropdownContent}
|
||||
|
||||
@ -122,6 +122,14 @@ export const fetchTestCaseSummary = (
|
||||
);
|
||||
}
|
||||
|
||||
if (filters?.entityFQN) {
|
||||
mustFilter.push({
|
||||
term: {
|
||||
entityFQN: filters.entityFQN,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return getDataQualityReport({
|
||||
q: JSON.stringify({
|
||||
query: {
|
||||
@ -275,6 +283,13 @@ export const fetchTestCaseStatusMetricsByDays = (
|
||||
)
|
||||
);
|
||||
}
|
||||
if (filters?.entityFQN) {
|
||||
mustFilter.push({
|
||||
term: {
|
||||
'testCase.entityFQN': filters.entityFQN,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return getDataQualityReport({
|
||||
q: JSON.stringify({
|
||||
|
||||
@ -46,6 +46,25 @@ export const getLineageDataByFQN = async (
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getDataQualityLineage = async (
|
||||
fqn: string,
|
||||
config?: Partial<LineageConfig>
|
||||
) => {
|
||||
const { upstreamDepth = 1 } = config ?? {};
|
||||
const response = await APIClient.get<EntityLineageResponse>(
|
||||
`lineage/getDataQualityLineage`,
|
||||
{
|
||||
params: {
|
||||
fqn,
|
||||
upstreamDepth,
|
||||
includeDeleted: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const exportLineage = async (
|
||||
fqn: string,
|
||||
entityType: string,
|
||||
|
||||
@ -47,6 +47,10 @@ class TableClassBase {
|
||||
): TabProps[] {
|
||||
return getTableDetailPageBaseTabs(tableDetailsPageProps);
|
||||
}
|
||||
|
||||
public getAlertEnableStatus() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const tableClassBase = new TableClassBase();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user