mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-29 00:18:24 +00:00
UI: Fixed Clicking "profiler & data quality" and "data quality" tab making the main tabs disappear #7351 (#7417)
* UI: Fixed Clicking "profiler & data quality" and "data quality" tab making the main tabs disappear #7351 * miner fix * addressing comment
This commit is contained in:
parent
747b27c356
commit
b8fd072e48
@ -36,7 +36,6 @@ import {
|
||||
Table,
|
||||
TestCaseStatus,
|
||||
} from '../../generated/entity/data/table';
|
||||
import { EntityType as TestType } from '../../generated/tests/testDefinition';
|
||||
import { EntityReference } from '../../generated/type/entityReference';
|
||||
import { LabelType, State } from '../../generated/type/tagLabel';
|
||||
import jsonData from '../../jsons/en';
|
||||
@ -100,7 +99,6 @@ const ProfilerDashboard: React.FC<ProfilerDashboardProps> = ({
|
||||
);
|
||||
const [selectedTestCaseStatus, setSelectedTestCaseStatus] =
|
||||
useState<string>('');
|
||||
const [selectedTestType, setSelectedTestType] = useState('');
|
||||
const [selectedTimeRange, setSelectedTimeRange] =
|
||||
useState<keyof typeof PROFILER_FILTER_RANGE>('last3days');
|
||||
const [activeColumnDetails, setActiveColumnDetails] = useState<Column>(
|
||||
@ -156,21 +154,6 @@ const ProfilerDashboard: React.FC<ProfilerDashboardProps> = ({
|
||||
return testCaseStatus;
|
||||
}, []);
|
||||
|
||||
const testCaseTypeOption = useMemo(() => {
|
||||
const testCaseStatus: Record<string, string>[] = Object.entries(
|
||||
TestType
|
||||
).map(([key, value]) => ({
|
||||
label: key,
|
||||
value: value,
|
||||
}));
|
||||
testCaseStatus.unshift({
|
||||
label: 'All',
|
||||
value: '',
|
||||
});
|
||||
|
||||
return testCaseStatus;
|
||||
}, []);
|
||||
|
||||
const tier = useMemo(() => getTierTags(table.tags ?? []), [table]);
|
||||
const breadcrumb = useMemo(() => {
|
||||
const serviceName = getEntityName(table.service);
|
||||
@ -395,12 +378,6 @@ const ProfilerDashboard: React.FC<ProfilerDashboardProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
const handleTestCaseTypeChange = (value: string) => {
|
||||
if (value !== selectedTestType) {
|
||||
setSelectedTestType(value);
|
||||
}
|
||||
};
|
||||
|
||||
const getFilterTestCase = () => {
|
||||
const dataByStatus = testCases.filter(
|
||||
(data) =>
|
||||
@ -408,16 +385,7 @@ const ProfilerDashboard: React.FC<ProfilerDashboardProps> = ({
|
||||
data.testCaseResult?.testCaseStatus === selectedTestCaseStatus
|
||||
);
|
||||
|
||||
return isColumnView
|
||||
? dataByStatus
|
||||
: dataByStatus.filter(
|
||||
(data) =>
|
||||
selectedTestType === '' ||
|
||||
(selectedTestType === TestType.Table &&
|
||||
entityTypeFQN === data.entityFQN) ||
|
||||
(selectedTestType === TestType.Column &&
|
||||
entityTypeFQN !== data.entityFQN)
|
||||
);
|
||||
return dataByStatus;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -482,16 +450,6 @@ const ProfilerDashboard: React.FC<ProfilerDashboardProps> = ({
|
||||
/>
|
||||
|
||||
<Space size={16}>
|
||||
{activeTab === ProfilerDashboardTab.DATA_QUALITY &&
|
||||
!isColumnView && (
|
||||
<Form.Item className="tw-mb-0 tw-w-40" label="Type">
|
||||
<Select
|
||||
options={testCaseTypeOption}
|
||||
value={selectedTestType}
|
||||
onChange={handleTestCaseTypeChange}
|
||||
/>
|
||||
</Form.Item>
|
||||
)}
|
||||
{activeTab === ProfilerDashboardTab.DATA_QUALITY && (
|
||||
<Form.Item className="tw-mb-0 tw-w-40" label="Status">
|
||||
<Select
|
||||
|
||||
@ -232,6 +232,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
||||
/>
|
||||
|
||||
<DeleteWidgetModal
|
||||
afterDeleteAction={onTestUpdate}
|
||||
entityId={selectedTestCase?.id || ''}
|
||||
entityName={selectedTestCase?.name || ''}
|
||||
entityType="testCase"
|
||||
|
||||
@ -14,36 +14,39 @@
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
Form,
|
||||
Radio,
|
||||
RadioChangeEvent,
|
||||
Row,
|
||||
Select,
|
||||
Space,
|
||||
Tooltip,
|
||||
} from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import { isEmpty, isUndefined } from 'lodash';
|
||||
import { SelectableOption } from 'Models';
|
||||
import React, { FC, useEffect, useMemo, useState } from 'react';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ReactComponent as NoDataIcon } from '../../assets/svg/no-data-icon.svg';
|
||||
import { getListTestCase } from '../../axiosAPIs/testAPI';
|
||||
import { API_RES_MAX_SIZE } from '../../constants/constants';
|
||||
import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
|
||||
import { INITIAL_TEST_RESULT_SUMMARY } from '../../constants/profiler.constant';
|
||||
import { ProfilerDashboardType } from '../../enums/table.enum';
|
||||
import { TestCaseStatus } from '../../generated/tests/tableTest';
|
||||
import { TestCase } from '../../generated/tests/testCase';
|
||||
import { EntityType as TestType } from '../../generated/tests/testDefinition';
|
||||
import {
|
||||
formatNumberWithComma,
|
||||
formTwoDigitNmber,
|
||||
} from '../../utils/CommonUtils';
|
||||
import { updateTestResults } from '../../utils/DataQualityAndProfilerUtils';
|
||||
import {
|
||||
getAddDataQualityTableTestPath,
|
||||
getProfilerDashboardWithFqnPath,
|
||||
} from '../../utils/RouterUtils';
|
||||
import { getAddDataQualityTableTestPath } from '../../utils/RouterUtils';
|
||||
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
||||
import { generateEntityLink } from '../../utils/TableUtils';
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
import DataQualityTab from '../ProfilerDashboard/component/DataQualityTab';
|
||||
import { ProfilerDashboardTab } from '../ProfilerDashboard/profilerDashboard.interface';
|
||||
import ColumnProfileTable from './Component/ColumnProfileTable';
|
||||
import ProfilerSettingsModal from './Component/ProfilerSettingsModal';
|
||||
@ -60,16 +63,50 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
permissions,
|
||||
}) => {
|
||||
const { profile, columns = [] } = table;
|
||||
const history = useHistory();
|
||||
const [settingModalVisible, setSettingModalVisible] = useState(false);
|
||||
const [columnTests, setColumnTests] = useState<TestCase[]>([]);
|
||||
const [tableTests, setTableTests] = useState<TableTestsType>({
|
||||
tests: [],
|
||||
results: INITIAL_TEST_RESULT_SUMMARY,
|
||||
});
|
||||
const [activeTab] = useState<ProfilerDashboardTab>(
|
||||
const [activeTab, setActiveTab] = useState<ProfilerDashboardTab>(
|
||||
ProfilerDashboardTab.SUMMARY
|
||||
);
|
||||
const [selectedTestCaseStatus, setSelectedTestCaseStatus] =
|
||||
useState<string>('');
|
||||
const [selectedTestType, setSelectedTestType] = useState('');
|
||||
const isSummary = activeTab === ProfilerDashboardTab.SUMMARY;
|
||||
const isDataQuality = activeTab === ProfilerDashboardTab.DATA_QUALITY;
|
||||
|
||||
const testCaseStatusOption = useMemo(() => {
|
||||
const testCaseStatus: SelectableOption[] = Object.values(
|
||||
TestCaseStatus
|
||||
).map((value) => ({
|
||||
label: value,
|
||||
value: value,
|
||||
}));
|
||||
testCaseStatus.unshift({
|
||||
label: 'All',
|
||||
value: '',
|
||||
});
|
||||
|
||||
return testCaseStatus;
|
||||
}, []);
|
||||
|
||||
const testCaseTypeOption = useMemo(() => {
|
||||
const testCaseStatus: SelectableOption[] = Object.entries(TestType).map(
|
||||
([key, value]) => ({
|
||||
label: key,
|
||||
value: value,
|
||||
})
|
||||
);
|
||||
testCaseStatus.unshift({
|
||||
label: 'All',
|
||||
value: '',
|
||||
});
|
||||
|
||||
return testCaseStatus;
|
||||
}, []);
|
||||
|
||||
const viewTest = permissions.ViewAll || permissions.ViewTests;
|
||||
const viewProfiler = permissions.ViewAll || permissions.ViewDataProfile;
|
||||
@ -125,21 +162,13 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
|
||||
const handleTabChange = (e: RadioChangeEvent) => {
|
||||
const value = e.target.value as ProfilerDashboardTab;
|
||||
if (ProfilerDashboardTab.DATA_QUALITY === value) {
|
||||
history.push(
|
||||
getProfilerDashboardWithFqnPath(
|
||||
ProfilerDashboardType.TABLE,
|
||||
table.fullyQualifiedName || '',
|
||||
ProfilerDashboardTab.DATA_QUALITY
|
||||
)
|
||||
);
|
||||
}
|
||||
setActiveTab(value);
|
||||
};
|
||||
|
||||
const fetchAllTests = async () => {
|
||||
try {
|
||||
const { data } = await getListTestCase({
|
||||
fields: 'testCaseResult',
|
||||
fields: 'testCaseResult,entityLink,testDefinition,testSuite',
|
||||
entityLink: generateEntityLink(table.fullyQualifiedName || ''),
|
||||
includeAllTests: true,
|
||||
limit: API_RES_MAX_SIZE,
|
||||
@ -169,6 +198,35 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
const handleTestCaseStatusChange = (value: string) => {
|
||||
if (value !== selectedTestCaseStatus) {
|
||||
setSelectedTestCaseStatus(value);
|
||||
}
|
||||
};
|
||||
|
||||
const handleTestCaseTypeChange = (value: string) => {
|
||||
if (value !== selectedTestType) {
|
||||
setSelectedTestType(value);
|
||||
}
|
||||
};
|
||||
|
||||
const getFilterTestCase = () => {
|
||||
let tests: TestCase[] = [];
|
||||
if (selectedTestType === TestType.Table) {
|
||||
tests = tableTests.tests;
|
||||
} else if (selectedTestType === TestType.Column) {
|
||||
tests = columnTests;
|
||||
} else {
|
||||
tests = [...tableTests.tests, ...columnTests];
|
||||
}
|
||||
|
||||
return tests.filter(
|
||||
(data) =>
|
||||
selectedTestCaseStatus === '' ||
|
||||
data.testCaseResult?.testCaseStatus === selectedTestCaseStatus
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEmpty(table) && viewTest) {
|
||||
fetchAllTests();
|
||||
@ -191,6 +249,25 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
/>
|
||||
|
||||
<Space>
|
||||
{isDataQuality && (
|
||||
<>
|
||||
<Form.Item className="mb-0 w-40" label="Type">
|
||||
<Select
|
||||
options={testCaseTypeOption}
|
||||
value={selectedTestType}
|
||||
onChange={handleTestCaseTypeChange}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item className="mb-0 w-40" label="Status">
|
||||
<Select
|
||||
options={testCaseStatusOption}
|
||||
value={selectedTestCaseStatus}
|
||||
onChange={handleTestCaseStatusChange}
|
||||
/>
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Tooltip title={editTest ? 'Add Test' : NO_PERMISSION_FOR_ACTION}>
|
||||
<Link
|
||||
to={
|
||||
@ -210,26 +287,27 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
</Button>
|
||||
</Link>
|
||||
</Tooltip>
|
||||
<Tooltip title={editTest ? 'Settings' : NO_PERMISSION_FOR_ACTION}>
|
||||
<Button
|
||||
className={classNames(
|
||||
'profiler-setting-btn tw-border tw-rounded tw-text-primary',
|
||||
{ 'tw-border-primary': editTest }
|
||||
)}
|
||||
data-testid="profiler-setting-btn"
|
||||
disabled={!editTest}
|
||||
icon={
|
||||
<SVGIcons
|
||||
alt="setting"
|
||||
className={classNames({ 'tw-mb-1 tw-mr-2': editTest })}
|
||||
icon={editTest ? Icons.SETTINGS_PRIMERY : Icons.SETTINGS_GRAY}
|
||||
/>
|
||||
}
|
||||
type="default"
|
||||
onClick={() => handleSettingModal(true)}>
|
||||
Settings
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{isSummary && (
|
||||
<Tooltip title={editTest ? 'Settings' : NO_PERMISSION_FOR_ACTION}>
|
||||
<Button
|
||||
ghost
|
||||
data-testid="profiler-setting-btn"
|
||||
disabled={!editTest}
|
||||
icon={
|
||||
<SVGIcons
|
||||
alt="setting"
|
||||
className="mr-2"
|
||||
icon={
|
||||
editTest ? Icons.SETTINGS_PRIMERY : Icons.SETTINGS_GRAY
|
||||
}
|
||||
/>
|
||||
}
|
||||
type="primary"
|
||||
onClick={() => handleSettingModal(true)}>
|
||||
Settings
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Space>
|
||||
</Row>
|
||||
|
||||
@ -273,15 +351,25 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
))}
|
||||
</Row>
|
||||
|
||||
<ColumnProfileTable
|
||||
columnTests={columnTests}
|
||||
columns={columns.map((col) => ({
|
||||
...col,
|
||||
key: col.name,
|
||||
}))}
|
||||
hasEditAccess={editTest}
|
||||
onAddTestClick={onAddTestClick}
|
||||
/>
|
||||
{isSummary && (
|
||||
<ColumnProfileTable
|
||||
columnTests={columnTests}
|
||||
columns={columns.map((col) => ({
|
||||
...col,
|
||||
key: col.name,
|
||||
}))}
|
||||
hasEditAccess={editTest}
|
||||
onAddTestClick={onAddTestClick}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isDataQuality && (
|
||||
<DataQualityTab
|
||||
hasAccess={permissions.EditAll}
|
||||
testCases={getFilterTestCase()}
|
||||
onTestUpdate={fetchAllTests}
|
||||
/>
|
||||
)}
|
||||
|
||||
{settingModalVisible && (
|
||||
<ProfilerSettingsModal
|
||||
|
||||
@ -19,12 +19,6 @@
|
||||
@primary-color-lite: #7147e833;
|
||||
|
||||
.table-profiler-container {
|
||||
.profiler-setting-btn {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.overall-summery-card:not(:first-child) {
|
||||
border-left: 1px solid rgb(229, 231, 235);
|
||||
padding-left: 16px;
|
||||
|
||||
@ -43,6 +43,10 @@
|
||||
border-left: 2px;
|
||||
}
|
||||
|
||||
.mr-2 {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.border-primary {
|
||||
border-color: @primary;
|
||||
}
|
||||
@ -60,6 +64,10 @@
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.mb-0 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.mt-24 {
|
||||
margin-top: 6rem;
|
||||
}
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.w-40 {
|
||||
width: 10rem /* 160px */;
|
||||
}
|
||||
@ -17,6 +17,7 @@ import './antd-master.less';
|
||||
import './app.less';
|
||||
import './components/glossary.less';
|
||||
import './components/profiler.less';
|
||||
import './components/size.less';
|
||||
import './components/step.less';
|
||||
import './fonts.css';
|
||||
import './modal.less';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user