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:
Shailesh Parmar 2022-09-13 21:00:46 +05:30 committed by GitHub
parent 747b27c356
commit b8fd072e48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 161 additions and 95 deletions

View File

@ -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

View File

@ -232,6 +232,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
/>
<DeleteWidgetModal
afterDeleteAction={onTestUpdate}
entityId={selectedTestCase?.id || ''}
entityName={selectedTestCase?.name || ''}
entityType="testCase"

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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 */;
}

View File

@ -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';