mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-16 03:08:13 +00:00
UI : fix request/update task after redirect from frequently joined tables (#17399)
* fix request/update task after redirect from frequently joined tables * fix cypress test * modify persona heading like entity header * change css from fill to stretch and also fix cypress as per comments * change the breadcrumb name to show display name if available like other entites * fix advance search cypress * fix search cypress * fix unit tests * Update the logic to fetch the column field for advanced search * revert permission thing for database --------- Co-authored-by: Chira Madlani <chirag@getcollate.io> Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com> Co-authored-by: karanh37 <karanh37@gmail.com> Co-authored-by: Aniket Katkar <aniketkatkar97@gmail.com>
This commit is contained in:
parent
75f62a7872
commit
fc07324254
@ -160,12 +160,14 @@ describe('Persona operations', { tags: 'Settings' }, () => {
|
||||
|
||||
verifyResponseStatusCode('@getPersonaDetails', 200);
|
||||
|
||||
cy.get(
|
||||
'[data-testid="page-header-container"] [data-testid="heading"]'
|
||||
).should('contain', PERSONA_DETAILS.displayName);
|
||||
cy.get(
|
||||
'[data-testid="page-header-container"] [data-testid="sub-heading"]'
|
||||
).should('contain', PERSONA_DETAILS.name);
|
||||
cy.get('[data-testid="entity-header-name"]').should(
|
||||
'contain',
|
||||
PERSONA_DETAILS.name
|
||||
);
|
||||
cy.get('[data-testid="entity-header-display-name"]').should(
|
||||
'contain',
|
||||
PERSONA_DETAILS.displayName
|
||||
);
|
||||
cy.get(
|
||||
'[data-testid="viewer-container"] [data-testid="markdown-parser"]'
|
||||
).should('contain', PERSONA_DETAILS.description);
|
||||
@ -222,11 +224,14 @@ describe('Persona operations', { tags: 'Settings' }, () => {
|
||||
|
||||
updatePersonaDisplayName('Test Persona');
|
||||
|
||||
cy.get('[data-testid="heading"]').should('contain', 'Test Persona');
|
||||
cy.get('[data-testid="entity-header-display-name"]').should(
|
||||
'contain',
|
||||
'Test Persona'
|
||||
);
|
||||
|
||||
updatePersonaDisplayName(PERSONA_DETAILS.displayName);
|
||||
|
||||
cy.get('[data-testid="heading"]').should(
|
||||
cy.get('[data-testid="entity-header-display-name"]').should(
|
||||
'contain',
|
||||
PERSONA_DETAILS.displayName
|
||||
);
|
||||
|
@ -504,7 +504,7 @@ describe('Glossary page should work properly', { tags: 'Governance' }, () => {
|
||||
interceptURL('GET', `/api/v1/teams/**`, 'getTeams');
|
||||
interceptURL(
|
||||
'GET',
|
||||
`/api/v1/users?fields=teams%2Croles&limit=25&team=${appName}`,
|
||||
`/api/v1/users?fields=*&limit=25&team=${appName}`,
|
||||
'teamUsers'
|
||||
);
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.9 KiB |
@ -30,6 +30,7 @@ import { EntityTags, TagFilterOptions } from 'Models';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as IconEdit } from '../../../assets/svg/edit-new.svg';
|
||||
import { FQN_SEPARATOR_CHAR } from '../../../constants/char.constants';
|
||||
import {
|
||||
DE_ACTIVE_COLOR,
|
||||
ICON_DIMENSION,
|
||||
@ -110,6 +111,16 @@ const SchemaTable = ({
|
||||
const [editColumnDisplayName, setEditColumnDisplayName] = useState<Column>();
|
||||
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||
|
||||
const tableFqn = useMemo(
|
||||
() =>
|
||||
getPartialNameFromTableFQN(
|
||||
decodedEntityFqn,
|
||||
[FqnPart.Service, FqnPart.Database, FqnPart.Schema, FqnPart.Table],
|
||||
FQN_SEPARATOR_CHAR
|
||||
),
|
||||
[decodedEntityFqn]
|
||||
);
|
||||
|
||||
const sortByOrdinalPosition = useMemo(
|
||||
() => sortBy(tableColumns, 'ordinalPosition'),
|
||||
[tableColumns]
|
||||
@ -143,10 +154,10 @@ const SchemaTable = ({
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEmpty(decodedEntityFqn)) {
|
||||
fetchResourcePermission(decodedEntityFqn);
|
||||
if (!isEmpty(tableFqn)) {
|
||||
fetchResourcePermission(tableFqn);
|
||||
}
|
||||
}, [decodedEntityFqn]);
|
||||
}, [tableFqn]);
|
||||
|
||||
const handleEditColumn = (column: Column): void => {
|
||||
setEditColumn(column);
|
||||
@ -253,7 +264,7 @@ const SchemaTable = ({
|
||||
field: record.description,
|
||||
record,
|
||||
}}
|
||||
entityFqn={decodedEntityFqn}
|
||||
entityFqn={tableFqn}
|
||||
entityType={EntityType.TABLE}
|
||||
hasEditPermission={hasDescriptionEditAccess}
|
||||
index={index}
|
||||
@ -422,7 +433,7 @@ const SchemaTable = ({
|
||||
),
|
||||
render: (tags: TagLabel[], record: Column, index: number) => (
|
||||
<TableTags<Column>
|
||||
entityFqn={decodedEntityFqn}
|
||||
entityFqn={tableFqn}
|
||||
entityType={EntityType.TABLE}
|
||||
handleTagSelection={handleTagSelection}
|
||||
hasTagEditAccess={hasTagEditAccess}
|
||||
@ -454,7 +465,7 @@ const SchemaTable = ({
|
||||
),
|
||||
render: (tags: TagLabel[], record: Column, index: number) => (
|
||||
<TableTags<Column>
|
||||
entityFqn={decodedEntityFqn}
|
||||
entityFqn={tableFqn}
|
||||
entityType={EntityType.TABLE}
|
||||
handleTagSelection={handleTagSelection}
|
||||
hasTagEditAccess={hasTagEditAccess}
|
||||
@ -490,7 +501,7 @@ const SchemaTable = ({
|
||||
},
|
||||
],
|
||||
[
|
||||
decodedEntityFqn,
|
||||
tableFqn,
|
||||
isReadOnly,
|
||||
tableConstraints,
|
||||
hasTagEditAccess,
|
||||
|
@ -153,7 +153,7 @@ const TagsV1 = ({
|
||||
{...tagProps}>
|
||||
{/* Wrap only content to avoid redirect on closeable icons */}
|
||||
<Link
|
||||
className="no-underline h-full w-full"
|
||||
className="no-underline h-full w-max-stretch"
|
||||
data-testid="tag-redirect-link"
|
||||
to={redirectLink}>
|
||||
{tagContent}
|
||||
|
@ -143,7 +143,10 @@ jest.mock('react-router-dom', () => ({
|
||||
.mockImplementation(({ children }: { children: React.ReactNode }) => (
|
||||
<p data-testid="link">{children}</p>
|
||||
)),
|
||||
useHistory: jest.fn(),
|
||||
useHistory: () => ({
|
||||
push: jest.fn(),
|
||||
replace: jest.fn(),
|
||||
}),
|
||||
useParams: jest.fn().mockReturnValue({
|
||||
fqn: 'bigquery.shopify',
|
||||
}),
|
||||
|
@ -144,13 +144,18 @@ jest.mock('../../../utils/ToastUtils', () => ({
|
||||
showErrorToast: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock(
|
||||
'../../../components/Entity/EntityHeaderTitle/EntityHeaderTitle.component',
|
||||
() => jest.fn().mockImplementation(() => <div>EntityHeaderTitle</div>)
|
||||
);
|
||||
|
||||
describe('PersonaDetailsPage', () => {
|
||||
it('Component should render', async () => {
|
||||
render(<PersonaDetailsPage />);
|
||||
|
||||
await waitForElementToBeRemoved(() => screen.getByTestId('loader'));
|
||||
|
||||
expect(screen.getByTestId('persona-heading')).toBeInTheDocument();
|
||||
expect(screen.getByText('EntityHeaderTitle')).toBeInTheDocument();
|
||||
expect(screen.getByText('TitleBreadcrumb.component')).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByText('ManageButton.component')
|
||||
|
@ -10,19 +10,22 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Button, Col, Row, Tabs, Typography } from 'antd';
|
||||
import Icon from '@ant-design/icons/lib/components/Icon';
|
||||
import { Button, Col, Row, Tabs } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { compare } from 'fast-json-patch';
|
||||
import { isUndefined } from 'lodash';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { ReactComponent as IconPersona } from '../../../assets/svg/ic-personas.svg';
|
||||
import DescriptionV1 from '../../../components/common/EntityDescription/DescriptionV1';
|
||||
import ManageButton from '../../../components/common/EntityPageInfos/ManageButton/ManageButton';
|
||||
import NoDataPlaceholder from '../../../components/common/ErrorWithPlaceholder/NoDataPlaceholder';
|
||||
import Loader from '../../../components/common/Loader/Loader';
|
||||
import TitleBreadcrumb from '../../../components/common/TitleBreadcrumb/TitleBreadcrumb.component';
|
||||
import { UserSelectableList } from '../../../components/common/UserSelectableList/UserSelectableList.component';
|
||||
import EntityHeaderTitle from '../../../components/Entity/EntityHeaderTitle/EntityHeaderTitle.component';
|
||||
import { EntityName } from '../../../components/Modals/EntityNameModal/EntityNameModal.interface';
|
||||
import PageLayoutV1 from '../../../components/PageLayoutV1/PageLayoutV1';
|
||||
import { UsersTab } from '../../../components/Settings/Users/UsersTab/UsersTabs.component';
|
||||
@ -182,14 +185,18 @@ export const PersonaDetailsPage = () => {
|
||||
<Row className="m-b-md page-container" gutter={[0, 16]}>
|
||||
<Col span={24}>
|
||||
<div className="d-flex justify-between items-start">
|
||||
<div>
|
||||
<div className="w-full">
|
||||
<TitleBreadcrumb titleLinks={breadcrumb} />
|
||||
<Typography.Title
|
||||
className="m-b-0 m-t-xs"
|
||||
data-testid="persona-heading"
|
||||
level={5}>
|
||||
{getEntityName(personaDetails)}
|
||||
</Typography.Title>
|
||||
|
||||
<EntityHeaderTitle
|
||||
className="m-t-xs"
|
||||
displayName={personaDetails.displayName}
|
||||
icon={
|
||||
<Icon component={IconPersona} style={{ fontSize: '36px' }} />
|
||||
}
|
||||
name={personaDetails?.name}
|
||||
serviceName={personaDetails.name}
|
||||
/>
|
||||
</div>
|
||||
<ManageButton
|
||||
afterDeleteAction={handleAfterDeleteAction}
|
||||
|
@ -140,14 +140,24 @@ const TableDetailsPageV1: React.FC = () => {
|
||||
);
|
||||
const [testCaseSummary, setTestCaseSummary] = useState<TestSummary>();
|
||||
|
||||
const tableFqn = useMemo(
|
||||
() =>
|
||||
getPartialNameFromTableFQN(
|
||||
datasetFQN,
|
||||
[FqnPart.Service, FqnPart.Database, FqnPart.Schema, FqnPart.Table],
|
||||
FQN_SEPARATOR_CHAR
|
||||
),
|
||||
[datasetFQN]
|
||||
);
|
||||
|
||||
const extraDropdownContent = useMemo(
|
||||
() =>
|
||||
entityUtilClassBase.getManageExtraOptions(
|
||||
EntityType.TABLE,
|
||||
datasetFQN,
|
||||
tableFqn,
|
||||
tablePermissions
|
||||
),
|
||||
[tablePermissions, datasetFQN]
|
||||
[tablePermissions, tableFqn]
|
||||
);
|
||||
|
||||
const { viewUsagePermission, viewTestCasePermission } = useMemo(
|
||||
@ -160,16 +170,6 @@ const TableDetailsPageV1: React.FC = () => {
|
||||
[tablePermissions]
|
||||
);
|
||||
|
||||
const tableFqn = useMemo(
|
||||
() =>
|
||||
getPartialNameFromTableFQN(
|
||||
datasetFQN,
|
||||
[FqnPart.Service, FqnPart.Database, FqnPart.Schema, FqnPart.Table],
|
||||
FQN_SEPARATOR_CHAR
|
||||
),
|
||||
[datasetFQN]
|
||||
);
|
||||
|
||||
const isViewTableType = useMemo(
|
||||
() => tableDetails?.tableType === TableType.View,
|
||||
[tableDetails?.tableType]
|
||||
@ -560,7 +560,7 @@ const TableDetailsPageV1: React.FC = () => {
|
||||
<DescriptionV1
|
||||
showSuggestions
|
||||
description={tableDetails?.description}
|
||||
entityFqn={datasetFQN}
|
||||
entityFqn={tableFqn}
|
||||
entityName={entityName}
|
||||
entityType={EntityType.TABLE}
|
||||
hasEditAccess={editDescriptionPermission}
|
||||
@ -613,7 +613,7 @@ const TableDetailsPageV1: React.FC = () => {
|
||||
editCustomAttributePermission
|
||||
}
|
||||
editTagPermission={editTagsPermission}
|
||||
entityFQN={datasetFQN}
|
||||
entityFQN={tableFqn}
|
||||
entityId={tableDetails?.id ?? ''}
|
||||
entityType={EntityType.TABLE}
|
||||
selectedTags={tableTags}
|
||||
@ -635,14 +635,22 @@ const TableDetailsPageV1: React.FC = () => {
|
||||
</Row>
|
||||
),
|
||||
[
|
||||
isTourPage,
|
||||
tableTags,
|
||||
joinedTables,
|
||||
tableFqn,
|
||||
isEdit,
|
||||
deleted,
|
||||
tableDetails,
|
||||
entityName,
|
||||
onDescriptionEdit,
|
||||
onDescriptionUpdate,
|
||||
testCaseSummary,
|
||||
editTagsPermission,
|
||||
editDescriptionPermission,
|
||||
editAllPermission,
|
||||
viewAllPermission,
|
||||
editCustomAttributePermission,
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -58,6 +58,9 @@ jest.mock('../../../utils/TasksUtils', () => ({
|
||||
getBreadCrumbList: jest.fn().mockReturnValue([]),
|
||||
getTaskMessage: jest.fn().mockReturnValue('Task message'),
|
||||
getTaskAssignee: jest.fn().mockReturnValue(MOCK_TASK_ASSIGNEE),
|
||||
getTaskEntityFQN: jest
|
||||
.fn()
|
||||
.mockReturnValue('sample_data.ecommerce_db.shopify.dim_location'),
|
||||
}));
|
||||
jest.mock('../shared/Assignees', () =>
|
||||
jest.fn().mockImplementation(() => <div>Assignees.component</div>)
|
||||
|
@ -47,6 +47,7 @@ import {
|
||||
fetchOptions,
|
||||
getBreadCrumbList,
|
||||
getTaskAssignee,
|
||||
getTaskEntityFQN,
|
||||
getTaskMessage,
|
||||
} from '../../../utils/TasksUtils';
|
||||
import { showErrorToast, showSuccessToast } from '../../../utils/ToastUtils';
|
||||
@ -64,7 +65,7 @@ const RequestDescription = () => {
|
||||
|
||||
const { entityType } = useParams<{ entityType: EntityType }>();
|
||||
|
||||
const { fqn: decodedEntityFQN } = useFqn();
|
||||
const { fqn } = useFqn();
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
|
||||
const field = queryParams.get('field');
|
||||
@ -76,6 +77,11 @@ const RequestDescription = () => {
|
||||
const [suggestion, setSuggestion] = useState<string>('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const entityFQN = useMemo(
|
||||
() => getTaskEntityFQN(entityType, fqn),
|
||||
[fqn, entityType]
|
||||
);
|
||||
|
||||
const taskMessage = useMemo(
|
||||
() =>
|
||||
getTaskMessage({
|
||||
@ -116,7 +122,7 @@ const RequestDescription = () => {
|
||||
const data: CreateThread = {
|
||||
from: currentUser?.name as string,
|
||||
message: value.title || taskMessage,
|
||||
about: getEntityFeedLink(entityType, decodedEntityFQN, getTaskAbout()),
|
||||
about: getEntityFeedLink(entityType, entityFQN, getTaskAbout()),
|
||||
taskDetails: {
|
||||
assignees: assignees.map((assignee) => ({
|
||||
id: assignee.value,
|
||||
@ -138,7 +144,7 @@ const RequestDescription = () => {
|
||||
history.push(
|
||||
entityUtilClassBase.getEntityLink(
|
||||
entityType,
|
||||
decodedEntityFQN,
|
||||
entityFQN,
|
||||
EntityTabs.ACTIVITY_FEED,
|
||||
ActivityFeedTabs.TASKS
|
||||
)
|
||||
@ -152,8 +158,8 @@ const RequestDescription = () => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchEntityDetail(entityType, decodedEntityFQN, setEntityData);
|
||||
}, [decodedEntityFQN, entityType]);
|
||||
fetchEntityDetail(entityType, entityFQN, setEntityData);
|
||||
}, [entityFQN, entityType]);
|
||||
|
||||
useEffect(() => {
|
||||
const defaultAssignee = getTaskAssignee(entityData as Glossary);
|
||||
|
@ -59,6 +59,9 @@ jest.mock('../../../utils/TasksUtils', () => ({
|
||||
getBreadCrumbList: jest.fn().mockReturnValue([]),
|
||||
getTaskMessage: jest.fn().mockReturnValue('Task message'),
|
||||
getTaskAssignee: jest.fn().mockReturnValue(MOCK_TASK_ASSIGNEE),
|
||||
getTaskEntityFQN: jest
|
||||
.fn()
|
||||
.mockReturnValue('sample_data.ecommerce_db.shopify.dim_location'),
|
||||
}));
|
||||
jest.mock('../shared/Assignees', () =>
|
||||
jest.fn().mockImplementation(() => <div>Assignees.component</div>)
|
||||
|
@ -46,6 +46,7 @@ import {
|
||||
fetchOptions,
|
||||
getBreadCrumbList,
|
||||
getTaskAssignee,
|
||||
getTaskEntityFQN,
|
||||
getTaskMessage,
|
||||
} from '../../../utils/TasksUtils';
|
||||
import { showErrorToast, showSuccessToast } from '../../../utils/ToastUtils';
|
||||
@ -61,7 +62,7 @@ const RequestTag = () => {
|
||||
const history = useHistory();
|
||||
const [form] = useForm();
|
||||
const { entityType } = useParams<{ entityType: EntityType }>();
|
||||
const { fqn: entityFQN } = useFqn();
|
||||
const { fqn } = useFqn();
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
|
||||
const field = queryParams.get('field');
|
||||
@ -73,6 +74,11 @@ const RequestTag = () => {
|
||||
const [suggestion] = useState<TagLabel[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const entityFQN = useMemo(
|
||||
() => getTaskEntityFQN(entityType, fqn),
|
||||
[fqn, entityType]
|
||||
);
|
||||
|
||||
const taskMessage = useMemo(
|
||||
() =>
|
||||
getTaskMessage({
|
||||
|
@ -80,6 +80,9 @@ jest.mock('../../../utils/TasksUtils', () => ({
|
||||
description: mockTableData.columns[0].description,
|
||||
})),
|
||||
getTaskAssignee: jest.fn().mockReturnValue(MOCK_TASK_ASSIGNEE),
|
||||
getTaskEntityFQN: jest
|
||||
.fn()
|
||||
.mockReturnValue('sample_data.ecommerce_db.shopify.dim_location'),
|
||||
}));
|
||||
jest.mock('../shared/Assignees', () =>
|
||||
jest.fn().mockImplementation(() => <div>Assignees.component</div>)
|
||||
|
@ -50,6 +50,7 @@ import {
|
||||
getColumnObject,
|
||||
getEntityColumnsDetails,
|
||||
getTaskAssignee,
|
||||
getTaskEntityFQN,
|
||||
getTaskMessage,
|
||||
} from '../../../utils/TasksUtils';
|
||||
import { showErrorToast, showSuccessToast } from '../../../utils/ToastUtils';
|
||||
@ -66,7 +67,7 @@ const UpdateDescription = () => {
|
||||
const [form] = useForm();
|
||||
|
||||
const { entityType } = useParams<{ entityType: EntityType }>();
|
||||
const { fqn: entityFQN } = useFqn();
|
||||
const { fqn } = useFqn();
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
|
||||
const field = queryParams.get('field');
|
||||
@ -78,6 +79,11 @@ const UpdateDescription = () => {
|
||||
const [currentDescription, setCurrentDescription] = useState<string>('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const entityFQN = useMemo(
|
||||
() => getTaskEntityFQN(entityType, fqn),
|
||||
[fqn, entityType]
|
||||
);
|
||||
|
||||
const sanitizeValue = useMemo(
|
||||
() => value?.replaceAll(TASK_SANITIZE_VALUE_REGEX, '') ?? '',
|
||||
[value]
|
||||
|
@ -90,6 +90,9 @@ jest.mock('../../../utils/TasksUtils', () => ({
|
||||
getColumnObject: jest.fn().mockImplementation(() => ({
|
||||
tags: mockTableData.columns[0].tags,
|
||||
})),
|
||||
getTaskEntityFQN: jest
|
||||
.fn()
|
||||
.mockReturnValue('sample_data.ecommerce_db.shopify.dim_location'),
|
||||
getTaskAssignee: jest.fn().mockReturnValue(MOCK_TASK_ASSIGNEE),
|
||||
}));
|
||||
jest.mock('../shared/Assignees', () =>
|
||||
|
@ -51,6 +51,7 @@ import {
|
||||
getColumnObject,
|
||||
getEntityColumnsDetails,
|
||||
getTaskAssignee,
|
||||
getTaskEntityFQN,
|
||||
getTaskMessage,
|
||||
} from '../../../utils/TasksUtils';
|
||||
import { showErrorToast, showSuccessToast } from '../../../utils/ToastUtils';
|
||||
@ -68,7 +69,7 @@ const UpdateTag = () => {
|
||||
|
||||
const { entityType } = useParams<{ entityType: EntityType }>();
|
||||
|
||||
const { fqn: entityFQN } = useFqn();
|
||||
const { fqn } = useFqn();
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
|
||||
const field = queryParams.get('field');
|
||||
@ -83,6 +84,11 @@ const UpdateTag = () => {
|
||||
const [suggestion, setSuggestion] = useState<TagLabel[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const entityFQN = useMemo(
|
||||
() => getTaskEntityFQN(entityType, fqn),
|
||||
[fqn, entityType]
|
||||
);
|
||||
|
||||
const sanitizeValue = useMemo(
|
||||
() => value?.replaceAll(TASK_SANITIZE_VALUE_REGEX, '') ?? '',
|
||||
[value]
|
||||
|
@ -174,6 +174,9 @@
|
||||
.w-max-full-140 {
|
||||
max-width: calc(100% - 140px);
|
||||
}
|
||||
.w-max-stretch {
|
||||
max-width: stretch;
|
||||
}
|
||||
|
||||
.w-auto {
|
||||
width: auto;
|
||||
|
@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
import { t } from 'i18next';
|
||||
import { sortBy } from 'lodash';
|
||||
import { isEmpty, sortBy } from 'lodash';
|
||||
import {
|
||||
AsyncFetchListValues,
|
||||
AsyncFetchListValuesResult,
|
||||
@ -97,19 +97,6 @@ class AdvancedSearchClassBase {
|
||||
},
|
||||
},
|
||||
|
||||
'columns.name.keyword': {
|
||||
label: t('label.column'),
|
||||
type: 'select',
|
||||
mainWidgetProps: this.mainWidgetProps,
|
||||
fieldSettings: {
|
||||
asyncFetch: this.autocomplete({
|
||||
searchIndex: SearchIndex.TABLE,
|
||||
entityField: EntityFields.COLUMN,
|
||||
}),
|
||||
useAsyncSearch: true,
|
||||
},
|
||||
},
|
||||
|
||||
tableType: {
|
||||
label: t('label.table-type'),
|
||||
type: 'select',
|
||||
@ -320,18 +307,6 @@ class AdvancedSearchClassBase {
|
||||
useAsyncSearch: true,
|
||||
},
|
||||
},
|
||||
'columns.name.keyword': {
|
||||
label: t('label.data-model-column'),
|
||||
type: 'select',
|
||||
mainWidgetProps: this.mainWidgetProps,
|
||||
fieldSettings: {
|
||||
asyncFetch: this.autocomplete({
|
||||
searchIndex: SearchIndex.DASHBOARD_DATA_MODEL,
|
||||
entityField: EntityFields.COLUMN,
|
||||
}),
|
||||
useAsyncSearch: true,
|
||||
},
|
||||
},
|
||||
'project.keyword': {
|
||||
label: t('label.project'),
|
||||
type: 'select',
|
||||
@ -551,6 +526,36 @@ 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
|
||||
public getColumnConfig = (entitySearchIndex: SearchIndex[]) => {
|
||||
const searchIndexWithColumns = entitySearchIndex.filter(
|
||||
(index) =>
|
||||
index === SearchIndex.TABLE ||
|
||||
index === SearchIndex.DASHBOARD_DATA_MODEL ||
|
||||
index === SearchIndex.DATA_ASSET ||
|
||||
index === SearchIndex.ALL
|
||||
);
|
||||
|
||||
return !isEmpty(searchIndexWithColumns)
|
||||
? {
|
||||
'columns.name.keyword': {
|
||||
label: t('label.column'),
|
||||
type: 'select',
|
||||
mainWidgetProps: this.mainWidgetProps,
|
||||
fieldSettings: {
|
||||
asyncFetch: this.autocomplete({
|
||||
searchIndex: searchIndexWithColumns,
|
||||
entityField: EntityFields.COLUMN,
|
||||
}),
|
||||
useAsyncSearch: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
: {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Get entity specific fields for the query builder
|
||||
*/
|
||||
@ -631,6 +636,7 @@ class AdvancedSearchClassBase {
|
||||
...this.getCommonConfig({ entitySearchIndex, tierOptions }),
|
||||
...(shouldAddServiceField ? serviceQueryBuilderFields : {}),
|
||||
...this.getEntitySpecificQueryBuilderFields(entitySearchIndex),
|
||||
...this.getColumnConfig(entitySearchIndex),
|
||||
};
|
||||
|
||||
// Sort the fields according to the label
|
||||
@ -648,7 +654,7 @@ class AdvancedSearchClassBase {
|
||||
isExplorePage?: boolean
|
||||
) => BasicConfig = (tierOptions, entitySearchIndex, isExplorePage) => {
|
||||
const searchIndexWithServices = [
|
||||
SearchIndex.ALL,
|
||||
SearchIndex.DATA_ASSET,
|
||||
SearchIndex.TABLE,
|
||||
SearchIndex.DASHBOARD,
|
||||
SearchIndex.PIPELINE,
|
||||
|
@ -21,6 +21,7 @@ import {
|
||||
fetchOptions,
|
||||
getEntityTableName,
|
||||
getTaskAssignee,
|
||||
getTaskEntityFQN,
|
||||
getTaskMessage,
|
||||
} from './TasksUtils';
|
||||
|
||||
@ -298,3 +299,28 @@ describe('Tests for getTaskAssignee', () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Tests for getTaskEntityFQN', () => {
|
||||
it('should return fqn for table entity', async () => {
|
||||
const fqn = 'sample_data.ecommerce_db.shopify."dim.product"';
|
||||
const response = getTaskEntityFQN(EntityType.TABLE, fqn);
|
||||
|
||||
expect(response).toEqual(fqn);
|
||||
});
|
||||
|
||||
it('should return table fqn only when column name present in fqn', async () => {
|
||||
const response = getTaskEntityFQN(
|
||||
EntityType.TABLE,
|
||||
'sample_data.ecommerce_db.shopify."dim.product".address_id'
|
||||
);
|
||||
|
||||
expect(response).toEqual('sample_data.ecommerce_db.shopify."dim.product"');
|
||||
});
|
||||
|
||||
it('should return fqn as it is if entity type is not table', async () => {
|
||||
const fqn = 'sample_looker.customers';
|
||||
const response = getTaskEntityFQN(EntityType.DASHBOARD, fqn);
|
||||
|
||||
expect(response).toEqual(fqn);
|
||||
});
|
||||
});
|
||||
|
@ -19,6 +19,7 @@ import { ReactComponent as CancelColored } from '../assets/svg/cancel-colored.sv
|
||||
import { ReactComponent as EditColored } from '../assets/svg/edit-colored.svg';
|
||||
import { ReactComponent as SuccessColored } from '../assets/svg/success-colored.svg';
|
||||
import { ActivityFeedTabs } from '../components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.interface';
|
||||
import { FQN_SEPARATOR_CHAR } from '../constants/char.constants';
|
||||
import {
|
||||
getEntityDetailsPath,
|
||||
getGlossaryTermDetailsPath,
|
||||
@ -901,3 +902,15 @@ export const getTaskAssignee = (entityData: Glossary): Option[] => {
|
||||
|
||||
return defaultAssignee;
|
||||
};
|
||||
|
||||
export const getTaskEntityFQN = (entityType: EntityType, fqn: string) => {
|
||||
if (entityType === EntityType.TABLE) {
|
||||
return getPartialNameFromTableFQN(
|
||||
fqn,
|
||||
[FqnPart.Service, FqnPart.Database, FqnPart.Schema, FqnPart.Table],
|
||||
FQN_SEPARATOR_CHAR
|
||||
);
|
||||
}
|
||||
|
||||
return fqn;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user