mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-25 17:04:54 +00:00
Fix(ui) : Updated tag and selection group style (#22708)
* Updated tag and slection group style * added add testCase drawer in the contract form * added pagination * fixed unit tests * fix the pagination in table schema form --------- Co-authored-by: Ashish Gupta <ashish@getcollate.io>
This commit is contained in:
parent
34cd7178e2
commit
bcc8cc1e39
@ -126,6 +126,9 @@
|
||||
border-radius: 8px;
|
||||
border: 1px solid @border-color-7;
|
||||
box-shadow: @button-box-shadow-default;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: @size-lg;
|
||||
}
|
||||
|
||||
// Table styling
|
||||
|
@ -142,7 +142,11 @@ const ContractDetail: React.FC<{
|
||||
title: t('label.type'),
|
||||
dataIndex: 'dataType',
|
||||
key: 'dataType',
|
||||
render: (type: string) => <Tag color="purple">{type}</Tag>,
|
||||
render: (type: string) => (
|
||||
<Tag className="custom-tag" color="purple">
|
||||
{type}
|
||||
</Tag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t('label.constraint-plural'),
|
||||
@ -151,7 +155,9 @@ const ContractDetail: React.FC<{
|
||||
render: (constraint: string) => (
|
||||
<div>
|
||||
{constraint ? (
|
||||
<Tag color="blue">{constraint}</Tag>
|
||||
<Tag className="custom-tag" color="blue">
|
||||
{constraint}
|
||||
</Tag>
|
||||
) : (
|
||||
<Typography.Text data-testid="no-constraints">
|
||||
{NO_DATA_PLACEHOLDER}
|
||||
|
@ -243,3 +243,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-tag.custom-tag {
|
||||
border-radius: 6px;
|
||||
padding: 2px @size-xs 2px 6px;
|
||||
font-size: @size-sm;
|
||||
font-weight: @font-medium;
|
||||
max-width: 100%;
|
||||
text-wrap: auto;
|
||||
border: none;
|
||||
}
|
||||
|
@ -11,26 +11,39 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ArrowLeftOutlined } from '@ant-design/icons';
|
||||
import { Button, Card, Radio, Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { EntityType } from '../../../enums/entity.enum';
|
||||
import { Table as TableType } from '../../../generated/entity/data/table';
|
||||
import { TestCase, TestCaseStatus } from '../../../generated/tests/testCase';
|
||||
import { EntityReference } from '../../../generated/type/entityReference';
|
||||
import { usePaging } from '../../../hooks/paging/usePaging';
|
||||
import { listTestCases, TestCaseType } from '../../../rest/testAPI';
|
||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||
import Table from '../../common/Table/Table';
|
||||
|
||||
import Icon, { ArrowLeftOutlined } from '@ant-design/icons';
|
||||
import { Button, Card, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import { AxiosError } from 'axios';
|
||||
import { toLower } from 'lodash';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as PlusIcon } from '../../../assets/svg/x-colored.svg';
|
||||
import { DEFAULT_SORT_ORDER } from '../../../constants/profiler.constant';
|
||||
import { EntityType, TabSpecificField } from '../../../enums/entity.enum';
|
||||
import { DataContract } from '../../../generated/entity/data/dataContract';
|
||||
import { Table as TableType } from '../../../generated/entity/data/table';
|
||||
import { TestCase, TestCaseResult } from '../../../generated/tests/testCase';
|
||||
import { EntityReference } from '../../../generated/type/entityReference';
|
||||
import { Include } from '../../../generated/type/include';
|
||||
import { usePaging } from '../../../hooks/paging/usePaging';
|
||||
import {
|
||||
getListTestCaseBySearch,
|
||||
ListTestCaseParamsBySearch,
|
||||
TestCaseType,
|
||||
} from '../../../rest/testAPI';
|
||||
import { TEST_LEVEL_OPTIONS } from '../../../utils/DataQuality/DataQualityUtils';
|
||||
import { generateEntityLink } from '../../../utils/TableUtils';
|
||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||
import { PagingHandlerParams } from '../../common/NextPrevious/NextPrevious.interface';
|
||||
import { SelectionCard } from '../../common/SelectionCardGroup/SelectionCardGroup';
|
||||
import StatusBadge from '../../common/StatusBadge/StatusBadge.component';
|
||||
import { StatusType } from '../../common/StatusBadge/StatusBadge.interface';
|
||||
import Table from '../../common/Table/Table';
|
||||
import { useGenericContext } from '../../Customization/GenericProvider/GenericProvider';
|
||||
import TestCaseFormV1 from '../../DataQuality/AddDataQualityTest/components/TestCaseFormV1';
|
||||
import { TestLevel } from '../../DataQuality/AddDataQualityTest/components/TestCaseFormV1.interface';
|
||||
import './contract-quality-form-tab.less';
|
||||
|
||||
export const ContractQualityFormTab: React.FC<{
|
||||
selectedQuality: string[];
|
||||
@ -41,47 +54,38 @@ export const ContractQualityFormTab: React.FC<{
|
||||
const [testType, setTestType] = useState<TestCaseType>(TestCaseType.table);
|
||||
const [allTestCases, setAllTestCases] = useState<TestCase[]>([]);
|
||||
const { data: table } = useGenericContext<TableType>();
|
||||
const { pageSize, handlePagingChange } = usePaging();
|
||||
const [isTestsLoading, setIsTestsLoading] = useState<boolean>(false);
|
||||
const [selectedKeys, setSelectedKeys] = useState<string[]>(
|
||||
selectedQuality ?? []
|
||||
);
|
||||
const [isTestCaseDrawerOpen, setIsTestCaseDrawerOpen] =
|
||||
useState<boolean>(false);
|
||||
const {
|
||||
currentPage,
|
||||
pageSize,
|
||||
handlePageChange,
|
||||
handlePageSizeChange,
|
||||
showPagination,
|
||||
paging,
|
||||
handlePagingChange,
|
||||
} = usePaging();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const columns: ColumnsType<TestCase> = useMemo(
|
||||
() => [
|
||||
{
|
||||
title: t('label.name'),
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: t('label.status'),
|
||||
dataIndex: 'testCaseStatus',
|
||||
key: 'testCaseStatus',
|
||||
render: (testCaseStatus: TestCaseStatus) => {
|
||||
return (
|
||||
<StatusBadge
|
||||
dataTestId={`status-badge-${testCaseStatus}`}
|
||||
label={testCaseStatus}
|
||||
status={toLower(testCaseStatus) as StatusType}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
const fetchAllTests = async () => {
|
||||
const fetchAllTests = async (params?: ListTestCaseParamsBySearch) => {
|
||||
if (!table?.fullyQualifiedName) {
|
||||
return;
|
||||
}
|
||||
setIsTestsLoading(true);
|
||||
try {
|
||||
const { data, paging } = await listTestCases({
|
||||
entityFQN: table.fullyQualifiedName,
|
||||
const { data, paging } = await getListTestCaseBySearch({
|
||||
...DEFAULT_SORT_ORDER,
|
||||
...params,
|
||||
testCaseType: testType,
|
||||
fields: [TabSpecificField.TEST_CASE_RESULT],
|
||||
entityLink: generateEntityLink(table.fullyQualifiedName ?? ''),
|
||||
includeAllTests: true,
|
||||
limit: pageSize,
|
||||
include: Include.NonDeleted,
|
||||
});
|
||||
|
||||
setAllTestCases(data);
|
||||
@ -93,9 +97,77 @@ export const ContractQualityFormTab: React.FC<{
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleTestPageChange = useCallback(
|
||||
({ currentPage }: PagingHandlerParams) => {
|
||||
fetchAllTests({
|
||||
offset: (currentPage - 1) * pageSize,
|
||||
});
|
||||
|
||||
handlePageChange(currentPage);
|
||||
},
|
||||
[pageSize, fetchAllTests, handlePageChange]
|
||||
);
|
||||
|
||||
const handleOpenTestCaseDrawer = useCallback(() => {
|
||||
setIsTestCaseDrawerOpen(true);
|
||||
}, []);
|
||||
|
||||
const handleCloseTestCaseDrawer = useCallback(() => {
|
||||
setIsTestCaseDrawerOpen(false);
|
||||
}, []);
|
||||
|
||||
const handleTestCaseSubmit = useCallback(() => {
|
||||
handleCloseTestCaseDrawer();
|
||||
fetchAllTests();
|
||||
}, [testType]);
|
||||
}, [handleCloseTestCaseDrawer, fetchAllTests]);
|
||||
|
||||
const columns: ColumnsType<TestCase> = useMemo(
|
||||
() => [
|
||||
{
|
||||
title: t('label.name'),
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: t('label.status'),
|
||||
dataIndex: 'testCaseResult',
|
||||
key: 'testCaseResult',
|
||||
render: (result: TestCaseResult, record) => {
|
||||
return result?.testCaseStatus ? (
|
||||
<StatusBadge
|
||||
dataTestId={`status-badge-${record.name}`}
|
||||
label={result.testCaseStatus}
|
||||
status={toLower(result.testCaseStatus) as StatusType}
|
||||
/>
|
||||
) : (
|
||||
'--'
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
const paginationProps = useMemo(
|
||||
() => ({
|
||||
currentPage,
|
||||
showPagination,
|
||||
isLoading: isTestsLoading,
|
||||
isNumberBased: false,
|
||||
pageSize,
|
||||
paging,
|
||||
pagingHandler: handleTestPageChange,
|
||||
onShowSizeChange: handlePageSizeChange,
|
||||
}),
|
||||
[
|
||||
currentPage,
|
||||
showPagination,
|
||||
isTestsLoading,
|
||||
pageSize,
|
||||
paging,
|
||||
handleTestPageChange,
|
||||
handlePageSizeChange,
|
||||
]
|
||||
);
|
||||
|
||||
const handleSelection = (selectedRowKeys: string[]) => {
|
||||
const qualityExpectations = selectedRowKeys.map((id) => {
|
||||
@ -114,31 +186,47 @@ export const ContractQualityFormTab: React.FC<{
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchAllTests();
|
||||
}, [testType]);
|
||||
|
||||
return (
|
||||
<Card className="container bg-grey p-box">
|
||||
<div>
|
||||
<Typography.Text className="contract-detail-form-tab-title">
|
||||
{t('label.quality')}
|
||||
</Typography.Text>
|
||||
<Typography.Text className="contract-detail-form-tab-description">
|
||||
{t('message.quality-contract-description')}
|
||||
</Typography.Text>
|
||||
<Card className="contract-quality-form-tab-container container bg-grey p-box">
|
||||
<div className="d-flex justify-between">
|
||||
<div>
|
||||
<Typography.Text className="contract-detail-form-tab-title">
|
||||
{t('label.quality')}
|
||||
</Typography.Text>
|
||||
<Typography.Text className="contract-detail-form-tab-description">
|
||||
{t('message.quality-contract-description')}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className="add-test-case-button"
|
||||
data-testid="add-test-button"
|
||||
icon={<Icon className="anticon" component={PlusIcon} />}
|
||||
onClick={handleOpenTestCaseDrawer}>
|
||||
{t('label.add-entity', {
|
||||
entity: t('label.test'),
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="contract-form-content-container">
|
||||
<Radio.Group
|
||||
className="m-b-sm"
|
||||
value={testType}
|
||||
onChange={(e) => setTestType(e.target.value)}>
|
||||
<Radio.Button value={TestCaseType.table}>
|
||||
{t('label.table')}
|
||||
</Radio.Button>
|
||||
<Radio.Button value={TestCaseType.column}>
|
||||
{t('label.column')}
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
<div className="contract-form-content-container ">
|
||||
<div className="w-full selection-card-group">
|
||||
{TEST_LEVEL_OPTIONS.map((option) => (
|
||||
<SelectionCard
|
||||
isSelected={testType === option.value}
|
||||
key={option.value}
|
||||
option={option}
|
||||
onClick={() => setTestType(option.value as TestCaseType)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<Table
|
||||
columns={columns}
|
||||
customPaginationProps={paginationProps}
|
||||
dataSource={allTestCases}
|
||||
loading={isTestsLoading}
|
||||
pagination={false}
|
||||
@ -158,6 +246,18 @@ export const ContractQualityFormTab: React.FC<{
|
||||
{prevLabel ?? t('label.previous')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{isTestCaseDrawerOpen && (
|
||||
<TestCaseFormV1
|
||||
drawerProps={{
|
||||
open: isTestCaseDrawerOpen,
|
||||
}}
|
||||
table={table}
|
||||
testLevel={TestLevel.TABLE}
|
||||
onCancel={handleCloseTestCaseDrawer}
|
||||
onFormSubmit={handleTestCaseSubmit}
|
||||
/>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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 (reference) url('../../../styles/variables.less');
|
||||
|
||||
.contract-quality-form-tab-container {
|
||||
.add-test-case-button {
|
||||
font-weight: 600;
|
||||
color: @grey-700;
|
||||
border: 1px solid @grey-300 !important;
|
||||
box-shadow: 0px 1px 2px rgba(10, 13, 18, 0.05),
|
||||
inset 0px -2px 0px rgba(10, 13, 18, 0.05);
|
||||
|
||||
.anticon {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
}
|
@ -11,25 +11,32 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { ArrowLeftOutlined, ArrowRightOutlined } from '@ant-design/icons';
|
||||
import { Button, Card, Typography } from 'antd';
|
||||
import { Button, Card, Tag, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { Key, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { NO_DATA_PLACEHOLDER } from '../../../constants/constants';
|
||||
import { FQN_SEPARATOR_CHAR } from '../../../constants/char.constants';
|
||||
import {
|
||||
NO_DATA_PLACEHOLDER,
|
||||
PAGE_SIZE_MEDIUM,
|
||||
} from '../../../constants/constants';
|
||||
import { TABLE_COLUMNS_KEYS } from '../../../constants/TableKeys.constants';
|
||||
import { EntityType } from '../../../enums/entity.enum';
|
||||
import { EntityType, FqnPart } from '../../../enums/entity.enum';
|
||||
import { DataContract } from '../../../generated/entity/data/dataContract';
|
||||
import { Column } from '../../../generated/entity/data/table';
|
||||
import { TagSource } from '../../../generated/tests/testCase';
|
||||
import { TagLabel } from '../../../generated/type/tagLabel';
|
||||
import { usePaging } from '../../../hooks/paging/usePaging';
|
||||
import { useFqn } from '../../../hooks/useFqn';
|
||||
import { getTableColumnsByFQN } from '../../../rest/tableAPI';
|
||||
import { getPartialNameFromTableFQN } from '../../../utils/CommonUtils';
|
||||
import {
|
||||
getEntityName,
|
||||
highlightSearchArrayElement,
|
||||
} from '../../../utils/EntityUtils';
|
||||
import { pruneEmptyChildren } from '../../../utils/TableUtils';
|
||||
import { PagingHandlerParams } from '../../common/NextPrevious/NextPrevious.interface';
|
||||
import Table from '../../common/Table/Table';
|
||||
import { TableCellRendered } from '../../Database/SchemaTable/SchemaTable.interface';
|
||||
import TableTags from '../../Database/TableTags/TableTags.component';
|
||||
@ -44,29 +51,103 @@ export const ContractSchemaFormTab: React.FC<{
|
||||
}> = ({ selectedSchema, onNext, onChange, onPrev, nextLabel, prevLabel }) => {
|
||||
const { t } = useTranslation();
|
||||
const { fqn } = useFqn();
|
||||
const [schema, setSchema] = useState<Column[]>([]);
|
||||
const [allColumns, setAllColumns] = useState<Column[]>([]);
|
||||
const [selectedKeys, setSelectedKeys] = useState<string[]>(selectedSchema);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const tableFqn = useMemo(
|
||||
() =>
|
||||
getPartialNameFromTableFQN(
|
||||
fqn,
|
||||
[FqnPart.Service, FqnPart.Database, FqnPart.Schema, FqnPart.Table],
|
||||
FQN_SEPARATOR_CHAR
|
||||
),
|
||||
[fqn]
|
||||
);
|
||||
|
||||
const {
|
||||
currentPage,
|
||||
pageSize,
|
||||
paging,
|
||||
handlePageChange,
|
||||
handlePageSizeChange,
|
||||
handlePagingChange,
|
||||
showPagination,
|
||||
} = usePaging(PAGE_SIZE_MEDIUM);
|
||||
const handleChangeTable = useCallback(
|
||||
(selectedRowKeys: Key[]) => {
|
||||
setSelectedKeys(selectedRowKeys as string[]);
|
||||
onChange({
|
||||
schema: schema.filter((column) =>
|
||||
schema: allColumns.filter((column) =>
|
||||
selectedRowKeys.includes(column.name)
|
||||
),
|
||||
});
|
||||
},
|
||||
[schema, onChange]
|
||||
[allColumns, onChange]
|
||||
);
|
||||
|
||||
const fetchTableColumns = useCallback(async () => {
|
||||
const response = await getTableColumnsByFQN(fqn);
|
||||
setSchema(pruneEmptyChildren(response.data));
|
||||
}, [fqn]);
|
||||
const fetchTableColumns = useCallback(
|
||||
async (page = 1) => {
|
||||
if (!tableFqn) {
|
||||
return;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
fetchTableColumns();
|
||||
}, [fqn]);
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const offset = (page - 1) * pageSize;
|
||||
|
||||
const response = await getTableColumnsByFQN(tableFqn, {
|
||||
limit: pageSize,
|
||||
offset: offset,
|
||||
fields: 'tags',
|
||||
});
|
||||
|
||||
const prunedColumns = pruneEmptyChildren(response.data);
|
||||
setAllColumns(prunedColumns);
|
||||
handlePagingChange(response.paging);
|
||||
} catch {
|
||||
// Set empty state if API fails
|
||||
setAllColumns([]);
|
||||
handlePagingChange({
|
||||
offset: 1,
|
||||
limit: pageSize,
|
||||
total: 0,
|
||||
});
|
||||
}
|
||||
setIsLoading(false);
|
||||
},
|
||||
[tableFqn, pageSize]
|
||||
);
|
||||
|
||||
const handleColumnsPageChange = useCallback(
|
||||
({ currentPage }: PagingHandlerParams) => {
|
||||
fetchTableColumns(currentPage);
|
||||
handlePageChange(currentPage);
|
||||
},
|
||||
[fetchTableColumns]
|
||||
);
|
||||
|
||||
const paginationProps = useMemo(
|
||||
() => ({
|
||||
currentPage,
|
||||
showPagination,
|
||||
isLoading: isLoading,
|
||||
isNumberBased: false,
|
||||
pageSize,
|
||||
paging,
|
||||
pagingHandler: handleColumnsPageChange,
|
||||
onShowSizeChange: handlePageSizeChange,
|
||||
}),
|
||||
[
|
||||
currentPage,
|
||||
showPagination,
|
||||
isLoading,
|
||||
pageSize,
|
||||
paging,
|
||||
handlePageSizeChange,
|
||||
handleColumnsPageChange,
|
||||
]
|
||||
);
|
||||
|
||||
const renderDataTypeDisplay: TableCellRendered<Column, 'dataTypeDisplay'> = (
|
||||
dataTypeDisplay,
|
||||
@ -81,11 +162,29 @@ export const ContractSchemaFormTab: React.FC<{
|
||||
}
|
||||
|
||||
return (
|
||||
<Typography.Paragraph
|
||||
className="cursor-pointer"
|
||||
ellipsis={{ tooltip: displayValue, rows: 3 }}>
|
||||
<Tag
|
||||
className="cursor-pointer custom-tag"
|
||||
color="purple"
|
||||
title={displayValue}>
|
||||
{highlightSearchArrayElement(dataTypeDisplay, '')}
|
||||
</Typography.Paragraph>
|
||||
</Tag>
|
||||
);
|
||||
};
|
||||
|
||||
const renderConstraint: TableCellRendered<Column, 'constraint'> = (
|
||||
constraint
|
||||
) => {
|
||||
if (isEmpty(constraint)) {
|
||||
return NO_DATA_PLACEHOLDER;
|
||||
}
|
||||
|
||||
return (
|
||||
<Tag
|
||||
className="cursor-pointer custom-tag"
|
||||
color="blue"
|
||||
title={constraint}>
|
||||
{constraint}
|
||||
</Tag>
|
||||
);
|
||||
};
|
||||
|
||||
@ -114,7 +213,7 @@ export const ContractSchemaFormTab: React.FC<{
|
||||
render: (tags: TagLabel[], record: Column, index: number) => (
|
||||
<TableTags<Column>
|
||||
isReadOnly
|
||||
entityFqn={fqn}
|
||||
entityFqn={tableFqn}
|
||||
entityType={EntityType.TABLE}
|
||||
handleTagSelection={() => Promise.resolve()}
|
||||
hasTagEditAccess={false}
|
||||
@ -132,7 +231,7 @@ export const ContractSchemaFormTab: React.FC<{
|
||||
render: (tags: TagLabel[], record: Column, index: number) => (
|
||||
<TableTags<Column>
|
||||
isReadOnly
|
||||
entityFqn={fqn}
|
||||
entityFqn={tableFqn}
|
||||
entityType={EntityType.TABLE}
|
||||
handleTagSelection={() => Promise.resolve()}
|
||||
hasTagEditAccess={false}
|
||||
@ -146,11 +245,17 @@ export const ContractSchemaFormTab: React.FC<{
|
||||
{
|
||||
title: t('label.constraint-plural'),
|
||||
dataIndex: 'constraint',
|
||||
key: 'constraint',
|
||||
render: renderConstraint,
|
||||
},
|
||||
],
|
||||
[t]
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
fetchTableColumns();
|
||||
}, [fetchTableColumns]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card className="container bg-grey p-box">
|
||||
@ -164,7 +269,9 @@ export const ContractSchemaFormTab: React.FC<{
|
||||
</div>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={schema}
|
||||
customPaginationProps={paginationProps}
|
||||
dataSource={allColumns}
|
||||
loading={isLoading}
|
||||
pagination={false}
|
||||
rowKey="name"
|
||||
rowSelection={{
|
||||
|
@ -165,6 +165,11 @@ jest.mock('../../../../rest/testAPI', () => ({
|
||||
getListTestCase: jest.fn().mockResolvedValue({ data: [] }),
|
||||
createTestCase: jest.fn().mockResolvedValue(MOCK_TEST_CASE[0]),
|
||||
getTestCaseByFqn: jest.fn().mockResolvedValue(MOCK_TEST_CASE[0]),
|
||||
TestCaseType: {
|
||||
all: 'all',
|
||||
table: 'table',
|
||||
column: 'column',
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../../../rest/ingestionPipelineAPI', () => ({
|
||||
|
@ -121,6 +121,11 @@ jest.mock('../../../hooks/useApplicationStore', () => ({
|
||||
jest.mock('../../../rest/testAPI', () => ({
|
||||
createTestSuites: jest.fn().mockResolvedValue(mockTestSuite),
|
||||
addTestCaseToLogicalTestSuite: jest.fn().mockResolvedValue({}),
|
||||
TestCaseType: {
|
||||
all: 'all',
|
||||
table: 'table',
|
||||
column: 'column',
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../../rest/ingestionPipelineAPI', () => ({
|
||||
|
@ -127,6 +127,11 @@ jest.mock('../../../../rest/testAPI', () => ({
|
||||
updateTestCaseById: jest
|
||||
.fn()
|
||||
.mockImplementation(() => mockUpdateTestCaseById()),
|
||||
TestCaseType: {
|
||||
all: 'all',
|
||||
table: 'table',
|
||||
column: 'column',
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock TagsContainerV2 to capture props
|
||||
|
@ -40,6 +40,11 @@ jest.mock('../../../../rest/testAPI', () => ({
|
||||
getListTestCaseBySearch: jest
|
||||
.fn()
|
||||
.mockResolvedValue({ data: [], paging: {} }),
|
||||
TestCaseType: {
|
||||
all: 'all',
|
||||
table: 'table',
|
||||
column: 'column',
|
||||
},
|
||||
}));
|
||||
jest.mock('../../../../utils/ToastUtils', () => ({
|
||||
showErrorToast: jest.fn(),
|
||||
|
@ -50,6 +50,11 @@ jest.mock('../../../../context/LineageProvider/LineageProvider', () => ({
|
||||
|
||||
jest.mock('../../../../rest/testAPI', () => ({
|
||||
getTestCaseExecutionSummary: jest.fn(),
|
||||
TestCaseType: {
|
||||
all: 'all',
|
||||
table: 'table',
|
||||
column: 'column',
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../../../utils/EntityLink', () => ({
|
||||
|
@ -41,6 +41,11 @@ jest.mock('../../../../rest/tableAPI', () => ({
|
||||
}));
|
||||
jest.mock('../../../../rest/testAPI', () => ({
|
||||
getTestCaseExecutionSummary: jest.fn(),
|
||||
TestCaseType: {
|
||||
all: 'all',
|
||||
table: 'table',
|
||||
column: 'column',
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../SummaryList/SummaryList.component', () =>
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
SelectionCardProps,
|
||||
} from './SelectionCardGroup.interface';
|
||||
|
||||
const SelectionCard: FC<SelectionCardProps> = ({
|
||||
export const SelectionCard: FC<SelectionCardProps> = ({
|
||||
option,
|
||||
isSelected,
|
||||
onClick,
|
||||
|
@ -96,6 +96,11 @@ jest.mock('../../../rest/testAPI', () => ({
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve({ data: mockTestCaseData })),
|
||||
updateTestCaseById: jest.fn(),
|
||||
TestCaseType: {
|
||||
all: 'all',
|
||||
table: 'table',
|
||||
column: 'column',
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../../hooks/useCustomLocation/useCustomLocation', () => {
|
||||
|
@ -112,6 +112,11 @@ jest.mock('../../rest/testAPI', () => {
|
||||
ListTestCaseParamsBySearch: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve({ data: [] })),
|
||||
TestCaseType: {
|
||||
all: 'all',
|
||||
table: 'table',
|
||||
column: 'column',
|
||||
},
|
||||
};
|
||||
});
|
||||
jest.mock('../../context/PermissionProvider/PermissionProvider', () => ({
|
||||
|
@ -51,6 +51,11 @@ jest.mock('../../rest/testAPI', () => {
|
||||
getTestSuiteByName: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve(mockTestSuite)),
|
||||
TestCaseType: {
|
||||
all: 'all',
|
||||
table: 'table',
|
||||
column: 'column',
|
||||
},
|
||||
};
|
||||
});
|
||||
jest.mock('../../rest/ingestionPipelineAPI', () => {
|
||||
|
@ -10,15 +10,19 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { t } from 'i18next';
|
||||
import { isArray, isNil, isUndefined, omit, omitBy } from 'lodash';
|
||||
import { ReactComponent as AccuracyIcon } from '../../assets/svg/ic-accuracy.svg';
|
||||
import { ReactComponent as ColumnIcon } from '../../assets/svg/ic-column.svg';
|
||||
import { ReactComponent as CompletenessIcon } from '../../assets/svg/ic-completeness.svg';
|
||||
import { ReactComponent as ConsistencyIcon } from '../../assets/svg/ic-consistency.svg';
|
||||
import { ReactComponent as IntegrityIcon } from '../../assets/svg/ic-integrity.svg';
|
||||
import { ReactComponent as SqlIcon } from '../../assets/svg/ic-sql.svg';
|
||||
import { ReactComponent as TableIcon } from '../../assets/svg/ic-table-test.svg';
|
||||
import { ReactComponent as UniquenessIcon } from '../../assets/svg/ic-uniqueness.svg';
|
||||
import { ReactComponent as ValidityIcon } from '../../assets/svg/ic-validity.svg';
|
||||
import { ReactComponent as NoDimensionIcon } from '../../assets/svg/no-dimension-icon.svg';
|
||||
import { SelectionOption } from '../../components/common/SelectionCardGroup/SelectionCardGroup.interface';
|
||||
import { TestCaseSearchParams } from '../../components/DataQuality/DataQuality.interface';
|
||||
import { TEST_CASE_FILTERS } from '../../constants/profiler.constant';
|
||||
import { Table } from '../../generated/entity/data/table';
|
||||
@ -322,3 +326,22 @@ export const convertSearchSourceToTable = (
|
||||
...searchSource,
|
||||
columns: searchSource.columns || [],
|
||||
} as Table);
|
||||
|
||||
export const TEST_LEVEL_OPTIONS: SelectionOption[] = [
|
||||
{
|
||||
value: TestCaseType.table,
|
||||
label: t('label.table-level'),
|
||||
description: t('label.test-applied-on-entity', {
|
||||
entity: t('label.table-lowercase'),
|
||||
}),
|
||||
icon: <TableIcon />,
|
||||
},
|
||||
{
|
||||
value: TestCaseType.column,
|
||||
label: t('label.column-level'),
|
||||
description: t('label.test-applied-on-entity', {
|
||||
entity: t('label.column-lowercase'),
|
||||
}),
|
||||
icon: <ColumnIcon />,
|
||||
},
|
||||
];
|
||||
|
Loading…
x
Reference in New Issue
Block a user