mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-31 12:39:01 +00:00
* Fix #5091 Make "Data Quality" column on Table schema page optional to hide * Fix unit test * Improve checks
This commit is contained in:
parent
84aede2eaf
commit
be553eb017
@ -176,13 +176,15 @@ const BotListV1 = ({
|
||||
<ErrorPlaceHolder
|
||||
buttons={
|
||||
<div className="tw-text-lg tw-text-center">
|
||||
<Tooltip
|
||||
title={createPermission ? 'Add Bot' : NO_PERMISSION_FOR_ACTION}>
|
||||
<Button
|
||||
ghost
|
||||
title="Add Team"
|
||||
disabled={!createPermission}
|
||||
type="primary"
|
||||
onClick={handleAddBotClick}>
|
||||
Add Bot
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
}
|
||||
doc={BOTS_DOCS}
|
||||
|
@ -48,11 +48,7 @@ import { getEntityFeedLink } from '../../utils/EntityUtils';
|
||||
import { getDefaultValue } from '../../utils/FeedElementUtils';
|
||||
import { getEntityFieldThreadCounts } from '../../utils/FeedUtils';
|
||||
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
||||
import {
|
||||
getTableTestsValue,
|
||||
getTagsWithoutTier,
|
||||
getUsagePercentile,
|
||||
} from '../../utils/TableUtils';
|
||||
import { getTagsWithoutTier, getUsagePercentile } from '../../utils/TableUtils';
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
import ActivityFeedList from '../ActivityFeed/ActivityFeedList/ActivityFeedList';
|
||||
import ActivityThreadPanel from '../ActivityFeed/ActivityThreadPanel/ActivityThreadPanel';
|
||||
@ -125,7 +121,6 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
|
||||
postFeedHandler,
|
||||
feedCount,
|
||||
entityFieldThreadCount,
|
||||
tableTestCase,
|
||||
createThread,
|
||||
qualityTestFormHandler,
|
||||
deletePostHandler,
|
||||
@ -408,7 +403,6 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
|
||||
key: 'Rows',
|
||||
value: prepareTableRowInfo(),
|
||||
},
|
||||
{ key: 'Tests', value: getTableTestsValue(tableTestCase) },
|
||||
];
|
||||
|
||||
const onDescriptionEdit = (): void => {
|
||||
@ -745,9 +739,7 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
|
||||
)}
|
||||
{activeTab === 5 && (
|
||||
<TableProfilerV1
|
||||
hasEditAccess={
|
||||
tablePermissions.EditAll || tablePermissions.EditDataProfile
|
||||
}
|
||||
permissions={tablePermissions}
|
||||
table={tableDetails}
|
||||
onAddTestClick={qualityTestFormHandler}
|
||||
/>
|
||||
|
@ -833,20 +833,6 @@ const EntityTable = ({
|
||||
return renderCell(TABLE_HEADERS_V1.dataTypeDisplay, record, index);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Data Quality',
|
||||
dataIndex: 'columnTests',
|
||||
key: 'columnTests',
|
||||
accessor: 'columnTests',
|
||||
width: 200,
|
||||
render: (
|
||||
_: Array<unknown>,
|
||||
record: ModifiedTableColumn,
|
||||
index: number
|
||||
) => {
|
||||
return renderCell(TABLE_HEADERS_V1.columnTests, record, index);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Description',
|
||||
dataIndex: 'description',
|
||||
|
@ -10,7 +10,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Button, Col, Form, Radio, Row, Select, Space } from 'antd';
|
||||
import { Button, Col, Form, Radio, Row, Select, Space, Tooltip } from 'antd';
|
||||
import { RadioChangeEvent } from 'antd/lib/radio';
|
||||
import { AxiosError } from 'axios';
|
||||
import { EntityTags, ExtraInfo } from 'Models';
|
||||
@ -25,6 +25,7 @@ import {
|
||||
getTableTabPath,
|
||||
getTeamAndUserDetailsPath,
|
||||
} from '../../constants/constants';
|
||||
import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
|
||||
import { PROFILER_FILTER_RANGE } from '../../constants/profiler.constant';
|
||||
import { EntityType, FqnPart } from '../../enums/entity.enum';
|
||||
import { ServiceCategory } from '../../enums/service.enum';
|
||||
@ -480,9 +481,19 @@ const ProfilerDashboard: React.FC<ProfilerDashboardProps> = ({
|
||||
onChange={handleTimeRangeChange}
|
||||
/>
|
||||
)}
|
||||
<Button type="primary" onClick={handleAddTestClick}>
|
||||
<Tooltip
|
||||
title={
|
||||
permission.EditAll || permission.EditTests
|
||||
? 'Add Test'
|
||||
: NO_PERMISSION_FOR_ACTION
|
||||
}>
|
||||
<Button
|
||||
disabled={!(permission.EditAll || permission.EditTests)}
|
||||
type="primary"
|
||||
onClick={handleAddTestClick}>
|
||||
Add Test
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
</Row>
|
||||
</Col>
|
||||
|
@ -14,6 +14,7 @@
|
||||
import { Column, Table } from '../../generated/entity/data/table';
|
||||
import { TestCase } from '../../generated/tests/testCase';
|
||||
import { DatasetTestModeType } from '../../interface/dataQuality.interface';
|
||||
import { OperationPermission } from '../PermissionProvider/PermissionProvider.interface';
|
||||
|
||||
export interface TableProfilerProps {
|
||||
onAddTestClick: (
|
||||
@ -22,7 +23,7 @@ export interface TableProfilerProps {
|
||||
columnName?: string
|
||||
) => void;
|
||||
table: Table;
|
||||
hasEditAccess: boolean;
|
||||
permissions: OperationPermission;
|
||||
}
|
||||
|
||||
export type TableTestsType = {
|
||||
|
@ -21,6 +21,7 @@ import {
|
||||
} from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { MOCK_TABLE, TEST_CASE } from '../../mocks/TableData.mock';
|
||||
import { OperationPermission } from '../PermissionProvider/PermissionProvider.interface';
|
||||
import { TableProfilerProps } from './TableProfiler.interface';
|
||||
// internal imports
|
||||
import TableProfilerV1 from './TableProfilerV1';
|
||||
@ -60,7 +61,28 @@ jest.mock('../../axiosAPIs/testAPI', () => ({
|
||||
|
||||
const mockProps: TableProfilerProps = {
|
||||
table: MOCK_TABLE,
|
||||
hasEditAccess: true,
|
||||
permissions: {
|
||||
Create: true,
|
||||
Delete: true,
|
||||
EditAll: true,
|
||||
EditCustomFields: true,
|
||||
EditDataProfile: true,
|
||||
EditDescription: true,
|
||||
EditDisplayName: true,
|
||||
EditLineage: true,
|
||||
EditOwner: true,
|
||||
EditQueries: true,
|
||||
EditSampleData: true,
|
||||
EditTags: true,
|
||||
EditTests: true,
|
||||
EditTier: true,
|
||||
ViewAll: true,
|
||||
ViewDataProfile: true,
|
||||
ViewQueries: true,
|
||||
ViewSampleData: true,
|
||||
ViewTests: true,
|
||||
ViewUsage: true,
|
||||
} as OperationPermission,
|
||||
onAddTestClick: jest.fn(),
|
||||
};
|
||||
|
||||
|
@ -57,9 +57,9 @@ import './tableProfiler.less';
|
||||
const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
table,
|
||||
onAddTestClick,
|
||||
hasEditAccess,
|
||||
permissions,
|
||||
}) => {
|
||||
const { profile, columns } = table;
|
||||
const { profile, columns = [] } = table;
|
||||
const history = useHistory();
|
||||
const [settingModalVisible, setSettingModalVisible] = useState(false);
|
||||
const [columnTests, setColumnTests] = useState<TestCase[]>([]);
|
||||
@ -71,6 +71,10 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
ProfilerDashboardTab.SUMMARY
|
||||
);
|
||||
|
||||
const viewTest = permissions.ViewAll || permissions.ViewTests;
|
||||
const viewProfiler = permissions.ViewAll || permissions.ViewDataProfile;
|
||||
const editTest = permissions.EditAll || permissions.EditTests;
|
||||
|
||||
const handleSettingModal = (value: boolean) => {
|
||||
setSettingModalVisible(value);
|
||||
};
|
||||
@ -106,11 +110,18 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
];
|
||||
}, [profile, tableTests]);
|
||||
|
||||
const tabOptions = useMemo(() => {
|
||||
return Object.values(ProfilerDashboardTab).filter(
|
||||
(value) => value !== ProfilerDashboardTab.PROFILER
|
||||
);
|
||||
}, []);
|
||||
const tabOptions = [
|
||||
{
|
||||
label: ProfilerDashboardTab.SUMMARY,
|
||||
value: ProfilerDashboardTab.SUMMARY,
|
||||
disabled: !viewProfiler,
|
||||
},
|
||||
{
|
||||
label: ProfilerDashboardTab.DATA_QUALITY,
|
||||
value: ProfilerDashboardTab.DATA_QUALITY,
|
||||
disabled: !viewTest,
|
||||
},
|
||||
];
|
||||
|
||||
const handleTabChange = (e: RadioChangeEvent) => {
|
||||
const value = e.target.value as ProfilerDashboardTab;
|
||||
@ -158,8 +169,9 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isEmpty(table)) return;
|
||||
if (!isEmpty(table) && viewTest) {
|
||||
fetchAllTests();
|
||||
}
|
||||
}, [table]);
|
||||
|
||||
return (
|
||||
@ -177,11 +189,10 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
/>
|
||||
|
||||
<Space>
|
||||
<Tooltip
|
||||
title={hasEditAccess ? 'Add Test' : NO_PERMISSION_FOR_ACTION}>
|
||||
<Tooltip title={editTest ? 'Add Test' : NO_PERMISSION_FOR_ACTION}>
|
||||
<Link
|
||||
to={
|
||||
hasEditAccess
|
||||
editTest
|
||||
? getAddDataQualityTableTestPath(
|
||||
ProfilerDashboardType.TABLE,
|
||||
`${table.fullyQualifiedName}`
|
||||
@ -191,18 +202,17 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
<Button
|
||||
className="tw-rounded"
|
||||
data-testid="profiler-add-table-test-btn"
|
||||
disabled={!hasEditAccess}
|
||||
disabled={!editTest}
|
||||
type="primary">
|
||||
Add Test
|
||||
</Button>
|
||||
</Link>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
title={hasEditAccess ? 'Settings' : NO_PERMISSION_FOR_ACTION}>
|
||||
<Tooltip title={editTest ? 'Settings' : NO_PERMISSION_FOR_ACTION}>
|
||||
<Button
|
||||
className="profiler-setting-btn tw-border tw-border-primary tw-rounded tw-text-primary"
|
||||
data-testid="profiler-setting-btn"
|
||||
disabled={!hasEditAccess}
|
||||
disabled={!editTest}
|
||||
icon={<SVGIcons alt="setting" icon={Icons.SETTINGS_PRIMERY} />}
|
||||
type="default"
|
||||
onClick={() => handleSettingModal(true)}>
|
||||
@ -258,7 +268,7 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
||||
...col,
|
||||
key: col.name,
|
||||
}))}
|
||||
hasEditAccess={hasEditAccess}
|
||||
hasEditAccess={editTest}
|
||||
onAddTestClick={onAddTestClick}
|
||||
/>
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
import { AxiosError } from 'axios';
|
||||
import { compare } from 'fast-json-patch';
|
||||
import { isEmpty } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
@ -25,6 +26,11 @@ import { getListTestCase } from '../../axiosAPIs/testAPI';
|
||||
import ErrorPlaceHolder from '../../components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import PageContainerV1 from '../../components/containers/PageContainerV1';
|
||||
import Loader from '../../components/Loader/Loader';
|
||||
import { usePermissionProvider } from '../../components/PermissionProvider/PermissionProvider';
|
||||
import {
|
||||
OperationPermission,
|
||||
ResourceEntity,
|
||||
} from '../../components/PermissionProvider/PermissionProvider.interface';
|
||||
import ProfilerDashboard from '../../components/ProfilerDashboard/ProfilerDashboard';
|
||||
import { API_RES_MAX_SIZE } from '../../constants/constants';
|
||||
import { ProfilerDashboardType } from '../../enums/table.enum';
|
||||
@ -35,6 +41,7 @@ import {
|
||||
getNameFromFQN,
|
||||
getTableFQNFromColumnFQN,
|
||||
} from '../../utils/CommonUtils';
|
||||
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
||||
import { generateEntityLink } from '../../utils/TableUtils';
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
|
||||
@ -47,6 +54,27 @@ const ProfilerDashboardPage = () => {
|
||||
const [error, setError] = useState(false);
|
||||
const [testCases, setTestCases] = useState<TestCase[]>([]);
|
||||
|
||||
const [tablePermissions, setTablePermissions] = useState<OperationPermission>(
|
||||
DEFAULT_ENTITY_PERMISSION
|
||||
);
|
||||
|
||||
const { getEntityPermission } = usePermissionProvider();
|
||||
|
||||
const fetchResourcePermission = async () => {
|
||||
try {
|
||||
const tablePermission = await getEntityPermission(
|
||||
ResourceEntity.TABLE,
|
||||
table.id
|
||||
);
|
||||
|
||||
setTablePermissions(tablePermission);
|
||||
} catch (error) {
|
||||
showErrorToast(
|
||||
jsonData['api-error-messages']['fetch-entity-permissions-error']
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchProfilerData = async (fqn: string, days = 3) => {
|
||||
try {
|
||||
const startTs = moment().subtract(days, 'days').unix();
|
||||
@ -98,11 +126,6 @@ const ProfilerDashboardPage = () => {
|
||||
}`;
|
||||
const data = await getTableDetailsByFQN(fqn, field);
|
||||
setTable(data ?? ({} as Table));
|
||||
if (isColumnView) {
|
||||
fetchProfilerData(entityTypeFQN);
|
||||
} else {
|
||||
fetchTestCases(generateEntityLink(entityTypeFQN));
|
||||
}
|
||||
} catch (error) {
|
||||
showErrorToast(
|
||||
error as AxiosError,
|
||||
@ -127,6 +150,16 @@ const ProfilerDashboardPage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const getProfilerDashboard = (permission: OperationPermission) => {
|
||||
if (isColumnView && (permission.ViewAll || permission.ViewDataProfile)) {
|
||||
fetchProfilerData(entityTypeFQN);
|
||||
} else {
|
||||
if (permission.ViewAll || permission.ViewTests) {
|
||||
fetchTestCases(generateEntityLink(entityTypeFQN));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (entityTypeFQN) {
|
||||
fetchTableEntity();
|
||||
@ -136,6 +169,18 @@ const ProfilerDashboardPage = () => {
|
||||
}
|
||||
}, [entityTypeFQN]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEmpty(table)) {
|
||||
fetchResourcePermission();
|
||||
}
|
||||
}, [table]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEmpty(table)) {
|
||||
getProfilerDashboard(tablePermissions);
|
||||
}
|
||||
}, [table, tablePermissions]);
|
||||
|
||||
if (isLoading) {
|
||||
return <Loader />;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user