mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2026-01-08 05:26:19 +00:00
Improvements: Automator requirements oss (#19128)
* Fix the ingestion success screen text overflow issue * Fix the icon alignment issue in the in the entity header * Fix the permissions API calls for the ingestion pipelines to use fqn instead of names * Introduce the moreActionButtonProps in the PipelineActions component * Add the "Database" field in the advanced search for the "Database Schema" asset. Change the fields listing behavior in the advanced search modal, to show the common fields for the multiple assets instead of union of the fields. Change the search index for the "Name" and "Display Name" field suggestions to use the selected data assets instead of the all "Data Assets" index. * Remove the unnecessary ellipsis prop * Scan and add the missing filters for all the asset to have hierarchical parent filters. * Fix unit test * Fix the advanced search filter field search
This commit is contained in:
parent
678160fbcc
commit
6b230f3440
@ -55,7 +55,7 @@ const EntityHeaderTitle = ({
|
||||
data-testid={`${serviceName}-${name}`}
|
||||
gutter={12}
|
||||
wrap={false}>
|
||||
{icon && <Col>{icon}</Col>}
|
||||
{icon && <Col className="flex-center">{icon}</Col>}
|
||||
<Col
|
||||
className={
|
||||
deleted || badge ? 'w-max-full-140' : 'entity-header-content'
|
||||
|
||||
@ -15,11 +15,18 @@ import { act, render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { mockIngestionListTableProps } from '../../../../../mocks/IngestionListTable.mock';
|
||||
import { usePermissionProvider } from '../../../../../context/PermissionProvider/PermissionProvider';
|
||||
import { mockIngestionData } from '../../../../../mocks/Ingestion.mock';
|
||||
import {
|
||||
mockESIngestionData,
|
||||
mockIngestionListTableProps,
|
||||
} from '../../../../../mocks/IngestionListTable.mock';
|
||||
import { ENTITY_PERMISSIONS } from '../../../../../mocks/Permissions.mock';
|
||||
import { deleteIngestionPipelineById } from '../../../../../rest/ingestionPipelineAPI';
|
||||
import IngestionListTable from './IngestionListTable';
|
||||
|
||||
const mockGetEntityPermissionByFqn = jest.fn();
|
||||
|
||||
jest.mock('../../../../../hooks/useApplicationStore', () => ({
|
||||
useApplicationStore: jest.fn(() => ({
|
||||
theme: { primaryColor: '#fff' },
|
||||
@ -260,4 +267,33 @@ describe('Ingestion', () => {
|
||||
|
||||
expect(deleteIngestionPipelineById).toHaveBeenCalledWith('id');
|
||||
});
|
||||
|
||||
it('should fetch the permissions for all the ingestion pipelines', async () => {
|
||||
(usePermissionProvider as jest.Mock).mockImplementation(() => ({
|
||||
getEntityPermissionByFqn: mockGetEntityPermissionByFqn,
|
||||
}));
|
||||
|
||||
await act(async () => {
|
||||
render(
|
||||
<IngestionListTable
|
||||
{...mockIngestionListTableProps}
|
||||
ingestionData={[mockESIngestionData, mockIngestionData]}
|
||||
/>,
|
||||
{
|
||||
wrapper: MemoryRouter,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
expect(mockGetEntityPermissionByFqn).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'ingestionPipeline',
|
||||
mockESIngestionData.fullyQualifiedName
|
||||
);
|
||||
expect(mockGetEntityPermissionByFqn).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
'ingestionPipeline',
|
||||
mockIngestionData.fullyQualifiedName
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -157,7 +157,10 @@ function IngestionListTable({
|
||||
const fetchIngestionPipelinesPermission = useCallback(async () => {
|
||||
try {
|
||||
const promises = ingestionData.map((item) =>
|
||||
getEntityPermissionByFqn(ResourceEntity.INGESTION_PIPELINE, item.name)
|
||||
getEntityPermissionByFqn(
|
||||
ResourceEntity.INGESTION_PIPELINE,
|
||||
item.fullyQualifiedName ?? ''
|
||||
)
|
||||
);
|
||||
const response = await Promise.allSettled(promises);
|
||||
|
||||
|
||||
@ -11,10 +11,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { IngestionServicePermission } from '../../../../context/PermissionProvider/PermissionProvider.interface';
|
||||
import { ServiceCategory } from '../../../../enums/service.enum';
|
||||
import { IngestionPipeline } from '../../../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||
import { SelectedRowDetails } from './ingestion.interface';
|
||||
import { ButtonProps } from 'antd';
|
||||
import { IngestionServicePermission } from '../../../../../../context/PermissionProvider/PermissionProvider.interface';
|
||||
import { ServiceCategory } from '../../../../../../enums/service.enum';
|
||||
import { IngestionPipeline } from '../../../../../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||
import { SelectedRowDetails } from '../../ingestion.interface';
|
||||
|
||||
export interface PipelineActionsProps {
|
||||
pipeline: IngestionPipeline;
|
||||
@ -28,4 +29,5 @@ export interface PipelineActionsProps {
|
||||
handleEnableDisableIngestion?: (id: string) => Promise<void>;
|
||||
handleIsConfirmationModalOpen: (value: boolean) => void;
|
||||
onIngestionWorkflowsUpdate?: () => void;
|
||||
moreActionButtonProps?: ButtonProps;
|
||||
}
|
||||
@ -22,8 +22,8 @@ import { Operation } from '../../../../../../generated/entity/policies/accessCon
|
||||
import { PipelineType } from '../../../../../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||
import { getLoadingStatus } from '../../../../../../utils/CommonUtils';
|
||||
import { getLogsViewerPath } from '../../../../../../utils/RouterUtils';
|
||||
import { PipelineActionsProps } from '../../PipelineActions.interface';
|
||||
import './pipeline-actions.less';
|
||||
import { PipelineActionsProps } from './PipelineActions.interface';
|
||||
import PipelineActionsDropdown from './PipelineActionsDropdown';
|
||||
|
||||
function PipelineActions({
|
||||
@ -38,6 +38,7 @@ function PipelineActions({
|
||||
handleIsConfirmationModalOpen,
|
||||
onIngestionWorkflowsUpdate,
|
||||
handleEditClick,
|
||||
moreActionButtonProps,
|
||||
}: Readonly<PipelineActionsProps>) {
|
||||
const history = useHistory();
|
||||
const { t } = useTranslation();
|
||||
@ -168,6 +169,7 @@ function PipelineActions({
|
||||
handleIsConfirmationModalOpen={handleIsConfirmationModalOpen}
|
||||
ingestion={pipeline}
|
||||
ingestionPipelinePermissions={ingestionPipelinePermissions}
|
||||
moreActionButtonProps={moreActionButtonProps}
|
||||
serviceCategory={serviceCategory}
|
||||
serviceName={serviceName}
|
||||
triggerIngestion={triggerIngestion}
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ButtonProps } from 'antd';
|
||||
import { IngestionServicePermission } from '../../../../../../context/PermissionProvider/PermissionProvider.interface';
|
||||
import { IngestionPipeline } from '../../../../../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||
import { SelectedRowDetails } from '../../ingestion.interface';
|
||||
@ -26,4 +27,5 @@ export interface PipelineActionsDropdownProps {
|
||||
handleDeleteSelection: (row: SelectedRowDetails) => void;
|
||||
handleIsConfirmationModalOpen: (value: boolean) => void;
|
||||
onIngestionWorkflowsUpdate?: () => void;
|
||||
moreActionButtonProps?: ButtonProps;
|
||||
}
|
||||
|
||||
@ -324,4 +324,26 @@ describe('PipelineActionsDropdown', () => {
|
||||
|
||||
expect(screen.queryByText('KillIngestionPipelineModal')).toBeNull();
|
||||
});
|
||||
|
||||
it('should pass the moreActionButtonProps to the more action button', async () => {
|
||||
const mockOnClick = jest.fn();
|
||||
|
||||
await act(async () => {
|
||||
render(
|
||||
<PipelineActionsDropdown
|
||||
{...mockPipelineActionsDropdownProps}
|
||||
moreActionButtonProps={{
|
||||
onClick: mockOnClick,
|
||||
}}
|
||||
/>,
|
||||
{
|
||||
wrapper: MemoryRouter,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
await clickOnMoreActions();
|
||||
|
||||
expect(mockOnClick).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@ -50,6 +50,7 @@ function PipelineActionsDropdown({
|
||||
handleIsConfirmationModalOpen,
|
||||
onIngestionWorkflowsUpdate,
|
||||
ingestionPipelinePermissions,
|
||||
moreActionButtonProps,
|
||||
}: Readonly<PipelineActionsDropdownProps>) {
|
||||
const history = useHistory();
|
||||
const { t } = useTranslation();
|
||||
@ -270,6 +271,7 @@ function PipelineActionsDropdown({
|
||||
icon={<MoreIcon />}
|
||||
type="link"
|
||||
onClick={() => setIsOpen((value) => !value)}
|
||||
{...moreActionButtonProps}
|
||||
/>
|
||||
</Dropdown>
|
||||
{isKillModalOpen && selectedPipeline && id === selectedPipeline?.id && (
|
||||
|
||||
@ -101,10 +101,7 @@ const SuccessScreen = ({
|
||||
<Card>
|
||||
<Space>
|
||||
<IconSuccessBadge data-testid="success-icon" width="20px" />
|
||||
<Typography.Paragraph
|
||||
className="m-b-0"
|
||||
data-testid="success-line"
|
||||
ellipsis={{ rows: 3 }}>
|
||||
<Typography.Paragraph className="m-b-0" data-testid="success-line">
|
||||
{isUndefined(successMessage) ? (
|
||||
<span>
|
||||
<span className="m-r-xss font-semibold">
|
||||
|
||||
@ -351,3 +351,9 @@ export const EXPLORE_ROOT_INDEX_MAPPING = {
|
||||
],
|
||||
Governance: [SearchIndex.GLOSSARY_TERM],
|
||||
};
|
||||
export const SEARCH_INDICES_WITH_COLUMNS_FIELD = [
|
||||
SearchIndex.TABLE,
|
||||
SearchIndex.DASHBOARD_DATA_MODEL,
|
||||
SearchIndex.DATA_ASSET,
|
||||
SearchIndex.ALL,
|
||||
];
|
||||
|
||||
@ -62,6 +62,7 @@ export enum EntityFields {
|
||||
DATABASE_DISPLAY_NAME = 'database.displayName',
|
||||
DATABASE_SCHEMA_DISPLAY_NAME = 'databaseSchema.displayName',
|
||||
COLUMN = 'columns.name.keyword',
|
||||
API_COLLECTION = 'apiCollection.displayName.keyword',
|
||||
CHART = 'charts.displayName.keyword',
|
||||
TASK = 'tasks.displayName.keyword',
|
||||
GLOSSARY_TERM_STATUS = 'status',
|
||||
|
||||
@ -13,8 +13,8 @@
|
||||
|
||||
import { AddIngestionButtonProps } from '../components/Settings/Services/Ingestion/AddIngestionButton.interface';
|
||||
import { IngestionListTableProps } from '../components/Settings/Services/Ingestion/IngestionListTable/IngestionListTable.interface';
|
||||
import { PipelineActionsProps } from '../components/Settings/Services/Ingestion/IngestionListTable/PipelineActions/PipelineActions.interface';
|
||||
import { PipelineActionsDropdownProps } from '../components/Settings/Services/Ingestion/IngestionListTable/PipelineActions/PipelineActionsDropdown.interface';
|
||||
import { PipelineActionsProps } from '../components/Settings/Services/Ingestion/PipelineActions.interface';
|
||||
import { ServiceCategory } from '../enums/service.enum';
|
||||
import { DatabaseServiceType } from '../generated/entity/data/database';
|
||||
import { ConfigType } from '../generated/entity/services/databaseService';
|
||||
|
||||
@ -11,7 +11,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { EntityFields } from '../enums/AdvancedSearch.enum';
|
||||
import { AdvancedSearchClassBase } from './AdvancedSearchClassBase';
|
||||
import { SearchIndex } from '../enums/search.enum';
|
||||
import advancedSearchClassBase, {
|
||||
AdvancedSearchClassBase,
|
||||
} from './AdvancedSearchClassBase';
|
||||
|
||||
jest.mock('../rest/miscAPI', () => ({
|
||||
getAggregateFieldOptions: jest.fn().mockImplementation(() =>
|
||||
@ -50,3 +53,135 @@ describe('AdvancedSearchClassBase', () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getEntitySpecificQueryBuilderFields', () => {
|
||||
it('should return table specific fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.TABLE,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([
|
||||
EntityFields.DATABASE,
|
||||
EntityFields.DATABASE_SCHEMA,
|
||||
EntityFields.TABLE_TYPE,
|
||||
EntityFields.COLUMN_DESCRIPTION_STATUS,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return pipeline specific fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.PIPELINE,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([EntityFields.TASK]);
|
||||
});
|
||||
|
||||
it('should return dashboard specific fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.DASHBOARD,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([
|
||||
EntityFields.DATA_MODEL,
|
||||
EntityFields.CHART,
|
||||
EntityFields.PROJECT,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return topic specific fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.TOPIC,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([EntityFields.SCHEMA_FIELD]);
|
||||
});
|
||||
|
||||
it('should return mlModel specific fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.MLMODEL,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([EntityFields.FEATURE]);
|
||||
});
|
||||
|
||||
it('should return container specific fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.CONTAINER,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([EntityFields.CONTAINER_COLUMN]);
|
||||
});
|
||||
|
||||
it('should return searchIndex specific fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.SEARCH_INDEX,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([EntityFields.FIELD]);
|
||||
});
|
||||
|
||||
it('should return dataModel specific fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.DASHBOARD_DATA_MODEL,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([
|
||||
EntityFields.DATA_MODEL_TYPE,
|
||||
EntityFields.PROJECT,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return apiEndpoint specific fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.API_ENDPOINT_INDEX,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([
|
||||
EntityFields.API_COLLECTION,
|
||||
EntityFields.REQUEST_SCHEMA_FIELD,
|
||||
EntityFields.RESPONSE_SCHEMA_FIELD,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return glossary specific fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.GLOSSARY_TERM,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([EntityFields.GLOSSARY_TERM_STATUS]);
|
||||
});
|
||||
|
||||
it('should return databaseSchema specific fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.DATABASE_SCHEMA,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([EntityFields.DATABASE]);
|
||||
});
|
||||
|
||||
it('should return empty fields for multiple indices with no common fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.TABLE,
|
||||
SearchIndex.PIPELINE,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return combined fields for multiple indices with common fields', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
SearchIndex.TABLE,
|
||||
SearchIndex.DATABASE_SCHEMA,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([EntityFields.DATABASE]);
|
||||
});
|
||||
|
||||
it('should return empty object for unknown index', () => {
|
||||
const result = advancedSearchClassBase.getEntitySpecificQueryBuilderFields([
|
||||
'UNKNOWN_INDEX' as SearchIndex,
|
||||
]);
|
||||
|
||||
expect(Object.keys(result)).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -22,6 +22,7 @@ import {
|
||||
SelectFieldSettings,
|
||||
} from 'react-awesome-query-builder';
|
||||
import AntdConfig from 'react-awesome-query-builder/lib/config/antd';
|
||||
import { SEARCH_INDICES_WITH_COLUMNS_FIELD } from '../constants/AdvancedSearch.constants';
|
||||
import { EntityFields, SuggestionField } from '../enums/AdvancedSearch.enum';
|
||||
import { SearchIndex } from '../enums/search.enum';
|
||||
import { getAggregateFieldOptions } from '../rest/miscAPI';
|
||||
@ -143,6 +144,24 @@ class AdvancedSearchClassBase {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Fields specific to database schema
|
||||
*/
|
||||
databaseSchemaQueryBuilderFields: Fields = {
|
||||
[EntityFields.DATABASE]: {
|
||||
label: t('label.database'),
|
||||
type: 'select',
|
||||
mainWidgetProps: this.mainWidgetProps,
|
||||
fieldSettings: {
|
||||
asyncFetch: this.autocomplete({
|
||||
searchIndex: SearchIndex.DATABASE_SCHEMA,
|
||||
entityField: EntityFields.DATABASE,
|
||||
}),
|
||||
useAsyncSearch: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Fields specific to tables
|
||||
*/
|
||||
@ -206,6 +225,37 @@ class AdvancedSearchClassBase {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Fields specific to stored procedures
|
||||
*/
|
||||
storedProcedureQueryBuilderFields: Fields = {
|
||||
[EntityFields.DATABASE]: {
|
||||
label: t('label.database'),
|
||||
type: 'select',
|
||||
mainWidgetProps: this.mainWidgetProps,
|
||||
fieldSettings: {
|
||||
asyncFetch: this.autocomplete({
|
||||
searchIndex: SearchIndex.STORED_PROCEDURE,
|
||||
entityField: EntityFields.DATABASE,
|
||||
}),
|
||||
useAsyncSearch: true,
|
||||
},
|
||||
},
|
||||
|
||||
[EntityFields.DATABASE_SCHEMA]: {
|
||||
label: t('label.database-schema'),
|
||||
type: 'select',
|
||||
mainWidgetProps: this.mainWidgetProps,
|
||||
fieldSettings: {
|
||||
asyncFetch: this.autocomplete({
|
||||
searchIndex: SearchIndex.STORED_PROCEDURE,
|
||||
entityField: EntityFields.DATABASE_SCHEMA,
|
||||
}),
|
||||
useAsyncSearch: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Fields specific to pipelines
|
||||
*/
|
||||
@ -246,6 +296,18 @@ class AdvancedSearchClassBase {
|
||||
* Fields specific to API endpoints
|
||||
*/
|
||||
apiEndpointQueryBuilderFields: Fields = {
|
||||
[EntityFields.API_COLLECTION]: {
|
||||
label: t('label.api-collection'),
|
||||
type: 'select',
|
||||
mainWidgetProps: this.mainWidgetProps,
|
||||
fieldSettings: {
|
||||
asyncFetch: this.autocomplete({
|
||||
searchIndex: SearchIndex.API_ENDPOINT_INDEX,
|
||||
entityField: EntityFields.API_COLLECTION,
|
||||
}),
|
||||
useAsyncSearch: true,
|
||||
},
|
||||
},
|
||||
[EntityFields.REQUEST_SCHEMA_FIELD]: {
|
||||
label: t('label.request-schema-field'),
|
||||
type: 'select',
|
||||
@ -438,6 +500,17 @@ class AdvancedSearchClassBase {
|
||||
renderButton: isExplorePage
|
||||
? renderAdvanceSearchButtons
|
||||
: renderQueryBuilderFilterButtons,
|
||||
|
||||
customFieldSelectProps: {
|
||||
...this.baseConfig.settings.customFieldSelectProps,
|
||||
// Adding filterOption to search by label
|
||||
// Since the default search behavior is by value which gives incorrect results
|
||||
// Ex. for search term 'name', it will return 'Task' in results as well
|
||||
// since value for 'Task' is 'tasks.displayName.keyword'
|
||||
filterOption: (input: string, option: { label: string }) => {
|
||||
return option.label.toLowerCase().includes(input.toLowerCase());
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -477,7 +550,7 @@ class AdvancedSearchClassBase {
|
||||
mainWidgetProps: this.mainWidgetProps,
|
||||
fieldSettings: {
|
||||
asyncFetch: this.autocomplete({
|
||||
searchIndex: SearchIndex.DATA_ASSET,
|
||||
searchIndex: entitySearchIndex,
|
||||
entityField: EntityFields.DISPLAY_NAME_KEYWORD,
|
||||
}),
|
||||
useAsyncSearch: true,
|
||||
@ -498,7 +571,7 @@ class AdvancedSearchClassBase {
|
||||
mainWidgetProps: this.mainWidgetProps,
|
||||
fieldSettings: {
|
||||
asyncFetch: this.autocomplete({
|
||||
searchIndex: SearchIndex.DATA_ASSET,
|
||||
searchIndex: entitySearchIndex,
|
||||
entityField: EntityFields.NAME_KEYWORD,
|
||||
}),
|
||||
useAsyncSearch: true,
|
||||
@ -627,18 +700,14 @@ class AdvancedSearchClassBase {
|
||||
}
|
||||
|
||||
// Since the column field key 'columns.name.keyword` is common in table and data model,
|
||||
// Following function is used to get the column field config based on the search index
|
||||
// or if it is an explore page
|
||||
// Following function is used to get the column field config if all the search Indices have columns field
|
||||
// or for ALL and DATA_ASSET search indices
|
||||
public getColumnConfig = (entitySearchIndex: SearchIndex[]) => {
|
||||
const searchIndexWithColumns = entitySearchIndex.filter(
|
||||
(index) =>
|
||||
index === SearchIndex.TABLE ||
|
||||
index === SearchIndex.DASHBOARD_DATA_MODEL ||
|
||||
index === SearchIndex.DATA_ASSET ||
|
||||
index === SearchIndex.ALL
|
||||
const shouldAddColumnField = entitySearchIndex.every((index) =>
|
||||
SEARCH_INDICES_WITH_COLUMNS_FIELD.includes(index)
|
||||
);
|
||||
|
||||
return !isEmpty(searchIndexWithColumns)
|
||||
return shouldAddColumnField
|
||||
? {
|
||||
[EntityFields.COLUMN]: {
|
||||
label: t('label.column'),
|
||||
@ -646,7 +715,7 @@ class AdvancedSearchClassBase {
|
||||
mainWidgetProps: this.mainWidgetProps,
|
||||
fieldSettings: {
|
||||
asyncFetch: this.autocomplete({
|
||||
searchIndex: searchIndexWithColumns,
|
||||
searchIndex: entitySearchIndex,
|
||||
entityField: EntityFields.COLUMN,
|
||||
}),
|
||||
useAsyncSearch: true,
|
||||
@ -674,6 +743,8 @@ class AdvancedSearchClassBase {
|
||||
[SearchIndex.DASHBOARD_DATA_MODEL]: this.dataModelQueryBuilderFields,
|
||||
[SearchIndex.API_ENDPOINT_INDEX]: this.apiEndpointQueryBuilderFields,
|
||||
[SearchIndex.GLOSSARY_TERM]: this.glossaryQueryBuilderFields,
|
||||
[SearchIndex.DATABASE_SCHEMA]: this.databaseSchemaQueryBuilderFields,
|
||||
[SearchIndex.STORED_PROCEDURE]: this.storedProcedureQueryBuilderFields,
|
||||
[SearchIndex.ALL]: {
|
||||
...this.tableQueryBuilderFields,
|
||||
...this.pipelineQueryBuilderFields,
|
||||
@ -699,9 +770,29 @@ class AdvancedSearchClassBase {
|
||||
},
|
||||
};
|
||||
|
||||
entitySearchIndex.forEach((index) => {
|
||||
configs = { ...configs, ...(configIndexMapping[index] ?? {}) };
|
||||
});
|
||||
// Find out the common fields between the selected indices
|
||||
if (!isEmpty(entitySearchIndex)) {
|
||||
const firstIndex = entitySearchIndex[0];
|
||||
|
||||
// Fields config for the first index
|
||||
configs = { ...configIndexMapping[firstIndex] };
|
||||
|
||||
// Iterate over the rest of the indices to see the common fields
|
||||
entitySearchIndex.slice(1).forEach((index) => {
|
||||
// Get the current config for the current iteration index
|
||||
const currentConfig = configIndexMapping[index] ?? {};
|
||||
|
||||
// Filter out the fields that are not common between the current and previous configs
|
||||
configs = Object.keys(configs).reduce((acc, key) => {
|
||||
// If the key exists in the current config, add it to the accumulator
|
||||
if (currentConfig[key]) {
|
||||
acc[key] = configs[key];
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {} as Fields);
|
||||
});
|
||||
}
|
||||
|
||||
return configs;
|
||||
}
|
||||
|
||||
@ -359,7 +359,7 @@ export const getSuccessMessage = (
|
||||
|
||||
return (
|
||||
<Typography.Text>
|
||||
<Typography.Text className="font-medium">{`"${ingestionName}"`}</Typography.Text>
|
||||
<Typography.Text className="font-medium break-word">{`"${ingestionName}"`}</Typography.Text>
|
||||
<Typography.Text>
|
||||
{status === FormSubmitType.ADD ? createMessage : updateMessage}
|
||||
</Typography.Text>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user