diff --git a/openmetadata-ui/src/main/resources/ui/src/assets/svg/no-data-icon.svg b/openmetadata-ui/src/main/resources/ui/src/assets/svg/no-data-icon.svg new file mode 100644 index 00000000000..3c2bf15a4ae --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/assets/svg/no-data-icon.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ProfilerDashboard/ProfilerDashboard.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ProfilerDashboard/ProfilerDashboard.tsx index 50807298038..68d974ccc23 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ProfilerDashboard/ProfilerDashboard.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/ProfilerDashboard/ProfilerDashboard.tsx @@ -10,7 +10,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Button, Col, Radio, Row, Select, Space } from 'antd'; +import { Button, Col, Form, Radio, Row, Select, Space } from 'antd'; import { RadioChangeEvent } from 'antd/lib/radio'; import { AxiosError } from 'axios'; import { EntityTags, ExtraInfo } from 'Models'; @@ -35,6 +35,7 @@ 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'; @@ -86,6 +87,7 @@ const ProfilerDashboard: React.FC = ({ ); const [selectedTestCaseStatus, setSelectedTestCaseStatus] = useState(''); + const [selectedTestType, setSelectedTestType] = useState(''); const [selectedTimeRange, setSelectedTimeRange] = useState('last3days'); const [activeColumnDetails, setActiveColumnDetails] = useState( @@ -117,7 +119,22 @@ const ProfilerDashboard: React.FC = ({ value: value, })); testCaseStatus.unshift({ - label: 'All Test', + label: 'All', + value: '', + }); + + return testCaseStatus; + }, []); + + const testCaseTypeOption = useMemo(() => { + const testCaseStatus: Record[] = Object.entries( + TestType + ).map(([key, value]) => ({ + label: key, + value: value, + })); + testCaseStatus.unshift({ + label: 'All', value: '', }); @@ -145,11 +162,13 @@ const ProfilerDashboard: React.FC = ({ }, { name: getPartialNameFromTableFQN(fqn, [FqnPart.Database]), - url: getDatabaseDetailsPath(fqn), + url: getDatabaseDetailsPath(table.database?.fullyQualifiedName || ''), }, { name: getPartialNameFromTableFQN(fqn, [FqnPart.Schema]), - url: getDatabaseSchemaDetailsPath(fqn), + url: getDatabaseSchemaDetailsPath( + table.databaseSchema?.fullyQualifiedName || '' + ), }, { name: getEntityName(table), @@ -331,12 +350,29 @@ const ProfilerDashboard: React.FC = ({ } }; + const handleTestCaseTypeChange = (value: string) => { + if (value !== selectedTestType) { + setSelectedTestType(value); + } + }; + const getFilterTestCase = () => { - return testCases.filter( + const dataByStatus = testCases.filter( (data) => selectedTestCaseStatus === '' || data.testCaseResult?.testCaseStatus === selectedTestCaseStatus ); + + return isColumnView + ? dataByStatus + : dataByStatus.filter( + (data) => + selectedTestType === '' || + (selectedTestType === TestType.Table && + entityTypeFQN === data.entityFQN) || + (selectedTestType === TestType.Column && + entityTypeFQN !== data.entityFQN) + ); }; useEffect(() => { @@ -390,13 +426,24 @@ const ProfilerDashboard: React.FC = ({ /> + {activeTab === ProfilerDashboardTab.DATA_QUALITY && + !isColumnView && ( + + + + )} {activeTab === ProfilerDashboardTab.DATA_QUALITY && ( - + + + )} {activeTab === ProfilerDashboardTab.PROFILER && ( = ({ dataIndex: 'description', key: 'description', }, + { + title: 'Table', + dataIndex: 'table', + key: 'table', + render: (_, record) => { + const tableFqn = getEntityFqnFromEntityLink(record.entityLink); + const name = getNameFromFQN(tableFqn); + + return ( + e.stopPropagation()}> + {name} + + ); + }, + }, + { + title: 'Test Suite', + dataIndex: 'testSuite', + key: 'testSuite', + render: (_, record) => { + return ( + e.stopPropagation()}> + {getEntityName(record?.testSuite)} + + ); + }, + }, { title: 'Actions', dataIndex: 'actions', diff --git a/openmetadata-ui/src/main/resources/ui/src/components/TableProfiler/TableProfilerV1.tsx b/openmetadata-ui/src/main/resources/ui/src/components/TableProfiler/TableProfilerV1.tsx index 0a910ac8833..f48def1d92a 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/TableProfiler/TableProfilerV1.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/TableProfiler/TableProfilerV1.tsx @@ -22,9 +22,10 @@ import { } from 'antd'; import { AxiosError } from 'axios'; import classNames from 'classnames'; -import { isEmpty } from 'lodash'; +import { isEmpty, isUndefined } from 'lodash'; import React, { FC, useEffect, useMemo, useState } from 'react'; import { Link, useHistory } 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'; @@ -205,6 +206,25 @@ const TableProfilerV1: FC = ({ + {isUndefined(profile) && ( + + + + Data Profiler is an optional configuration in Ingestion. Please + enable the data profiler by following the documentation + + here. + + + + )} + {overallSummery.map((summery) => ( { const fetchTestCases = async (fqn: string) => { try { const { data } = await getListTestCase({ - fields: 'testDefinition,testCaseResult', + fields: 'testDefinition,testCaseResult,testSuite', entityLink: fqn, + includeAllTests: !isColumnView, limit: API_RES_MAX_SIZE, }); setTestCases(data); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TestSuiteDetailsPage/TestSuiteDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TestSuiteDetailsPage/TestSuiteDetailsPage.component.tsx index f5db6e77d21..134257bc374 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TestSuiteDetailsPage/TestSuiteDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TestSuiteDetailsPage/TestSuiteDetailsPage.component.tsx @@ -123,7 +123,7 @@ const TestSuiteDetailsPage = () => { setIsTestCaseLoaded(false); try { const response = await getListTestCase({ - fields: 'testCaseResult,testDefinition', + fields: 'testCaseResult,testDefinition,testSuite', testSuiteId: testSuiteId, limit: limit || PAGE_SIZE, before: param && param.before, diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx index 294350ce0c7..b40dc450c08 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx @@ -323,6 +323,12 @@ export const generateEntityLink = (fqn: string, includeColumn = false) => { } }; +export const getEntityFqnFromEntityLink = (entityLink: string) => { + const link = entityLink.split('>')[0]; + + return link.split('::')[2]; +}; + export const getTestResultBadgeIcon = (status?: TestCaseStatus) => { switch (status) { case TestCaseStatus.Success:
+ Data Profiler is an optional configuration in Ingestion. Please + enable the data profiler by following the documentation + + here. + +