mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-31 12:39:01 +00:00
ui: worked on ui feedback part 2 (#12228)
* updated request description in topic details * miner fix * worked on feedback * fixed redirection link for activity feed * fixed failing test * miner fix * fixed infinite loading issue when there is no permission
This commit is contained in:
parent
a8c6f8bce0
commit
ccf585efba
@ -140,9 +140,9 @@ const TestCaseForm: React.FC<TestCaseFormProps> = ({
|
|||||||
);
|
);
|
||||||
const name =
|
const name =
|
||||||
value.testName?.trim() ||
|
value.testName?.trim() ||
|
||||||
`${columnName ? columnName : table.name}_${snakeCase(
|
`${replaceAllSpacialCharWith_(
|
||||||
selectedTestType
|
columnName ? columnName : table.name
|
||||||
)}_${cryptoRandomString({
|
)}_${snakeCase(selectedTestType)}_${cryptoRandomString({
|
||||||
length: 4,
|
length: 4,
|
||||||
type: 'alphanumeric',
|
type: 'alphanumeric',
|
||||||
})}`;
|
})}`;
|
||||||
|
@ -319,9 +319,9 @@ const Appbar: React.FC = (): JSX.Element => {
|
|||||||
{remainingTeamsCount} {t('label.more')}
|
{remainingTeamsCount} {t('label.more')}
|
||||||
</Link>
|
</Link>
|
||||||
) : null}
|
) : null}
|
||||||
|
<hr className="m-t-sm" />
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<hr className="m-t-sm" />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
import { Badge, Button, List, Tabs, Typography } from 'antd';
|
import { Badge, Button, List, Tabs, Typography } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
|
import { ActivityFeedTabs } from 'components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.interface';
|
||||||
|
import { EntityTabs } from 'enums/entity.enum';
|
||||||
import { UserProfileTab } from 'enums/user.enum';
|
import { UserProfileTab } from 'enums/user.enum';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
@ -52,9 +54,11 @@ const NotificationBox = ({
|
|||||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
const [viewAllPath, setViewAllPath] = useState<string>(
|
const [viewAllPath, setViewAllPath] = useState<string>(
|
||||||
`${getUserPath(currentUser?.name as string)}/tasks?feedFilter=${
|
getUserPath(
|
||||||
FeedFilter.ASSIGNED_TO
|
currentUser?.name as string,
|
||||||
}`
|
EntityTabs.ACTIVITY_FEED,
|
||||||
|
ActivityFeedTabs.TASKS
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const notificationDropDownList = useMemo(() => {
|
const notificationDropDownList = useMemo(() => {
|
||||||
|
@ -169,7 +169,7 @@ const Services = ({
|
|||||||
<div>
|
<div>
|
||||||
<Link
|
<Link
|
||||||
to={getServiceDetailsPath(
|
to={getServiceDetailsPath(
|
||||||
service.name,
|
service.fullyQualifiedName ?? service.name,
|
||||||
serviceName
|
serviceName
|
||||||
)}>
|
)}>
|
||||||
<button>
|
<button>
|
||||||
|
@ -158,11 +158,11 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
|||||||
excludeColumns,
|
excludeColumns,
|
||||||
} = tableProfilerConfig;
|
} = tableProfilerConfig;
|
||||||
handleStateChange({
|
handleStateChange({
|
||||||
sqlQuery: profileQuery || '',
|
sqlQuery: profileQuery ?? '',
|
||||||
profileSample: profileSample,
|
profileSample: profileSample,
|
||||||
excludeCol: excludeColumns || [],
|
excludeCol: excludeColumns ?? [],
|
||||||
selectedProfileSampleType:
|
selectedProfileSampleType:
|
||||||
profileSampleType || ProfileSampleType.Percentage,
|
profileSampleType ?? ProfileSampleType.Percentage,
|
||||||
});
|
});
|
||||||
|
|
||||||
const profileSampleTypeCheck =
|
const profileSampleTypeCheck =
|
||||||
@ -429,6 +429,7 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
|||||||
})}
|
})}
|
||||||
name="profileSampleType">
|
name="profileSampleType">
|
||||||
<Select
|
<Select
|
||||||
|
autoFocus
|
||||||
className="w-full"
|
className="w-full"
|
||||||
data-testid="profile-sample"
|
data-testid="profile-sample"
|
||||||
options={PROFILE_SAMPLE_OPTIONS}
|
options={PROFILE_SAMPLE_OPTIONS}
|
||||||
@ -477,13 +478,13 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<SchemaEditor
|
<SchemaEditor
|
||||||
className="custom-query-editor query-editor-h-200"
|
className="sql-editor-container custom-query-editor query-editor-h-200 custom-code-mirror-theme"
|
||||||
data-testid="profiler-setting-sql-editor"
|
data-testid="profiler-setting-sql-editor"
|
||||||
mode={{ name: CSMode.SQL }}
|
mode={{ name: CSMode.SQL }}
|
||||||
options={{
|
options={{
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
}}
|
}}
|
||||||
value={state?.sqlQuery || ''}
|
value={state?.sqlQuery ?? ''}
|
||||||
onChange={handleCodeMirrorChange}
|
onChange={handleCodeMirrorChange}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -53,6 +53,13 @@
|
|||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.sql-editor-container {
|
||||||
|
.CodeMirror {
|
||||||
|
.CodeMirror-foldgutter {
|
||||||
|
width: 2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.include-columns-add-button.ant-btn-icon-only.ant-btn-sm {
|
.include-columns-add-button.ant-btn-icon-only.ant-btn-sm {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
|
@ -22,7 +22,9 @@ import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlac
|
|||||||
import QueryViewer from 'components/common/QueryViewer/QueryViewer.component';
|
import QueryViewer from 'components/common/QueryViewer/QueryViewer.component';
|
||||||
import PageLayoutV1 from 'components/containers/PageLayoutV1';
|
import PageLayoutV1 from 'components/containers/PageLayoutV1';
|
||||||
import { DataAssetsHeader } from 'components/DataAssets/DataAssetsHeader/DataAssetsHeader.component';
|
import { DataAssetsHeader } from 'components/DataAssets/DataAssetsHeader/DataAssetsHeader.component';
|
||||||
|
import EntityLineageComponent from 'components/EntityLineage/EntityLineage.component';
|
||||||
import { EntityName } from 'components/Modals/EntityNameModal/EntityNameModal.interface';
|
import { EntityName } from 'components/Modals/EntityNameModal/EntityNameModal.interface';
|
||||||
|
import SampleDataTopic from 'components/SampleDataTopic/SampleDataTopic';
|
||||||
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
|
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
|
||||||
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
|
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
|
||||||
import { getTopicDetailsPath } from 'constants/constants';
|
import { getTopicDetailsPath } from 'constants/constants';
|
||||||
@ -51,8 +53,6 @@ import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
|||||||
import ActivityThreadPanel from '../ActivityFeed/ActivityThreadPanel/ActivityThreadPanel';
|
import ActivityThreadPanel from '../ActivityFeed/ActivityThreadPanel/ActivityThreadPanel';
|
||||||
import { CustomPropertyTable } from '../common/CustomPropertyTable/CustomPropertyTable';
|
import { CustomPropertyTable } from '../common/CustomPropertyTable/CustomPropertyTable';
|
||||||
import { CustomPropertyProps } from '../common/CustomPropertyTable/CustomPropertyTable.interface';
|
import { CustomPropertyProps } from '../common/CustomPropertyTable/CustomPropertyTable.interface';
|
||||||
import EntityLineageComponent from '../EntityLineage/EntityLineage.component';
|
|
||||||
import SampleDataTopic from '../SampleDataTopic/SampleDataTopic';
|
|
||||||
import { TopicDetailsProps } from './TopicDetails.interface';
|
import { TopicDetailsProps } from './TopicDetails.interface';
|
||||||
import TopicSchemaFields from './TopicSchema/TopicSchema';
|
import TopicSchemaFields from './TopicSchema/TopicSchema';
|
||||||
|
|
||||||
@ -294,6 +294,15 @@ const TopicDetails: React.FC<TopicDetailsProps> = ({
|
|||||||
onThreadLinkSelect={onThreadLinkSelect}
|
onThreadLinkSelect={onThreadLinkSelect}
|
||||||
/>
|
/>
|
||||||
<TopicSchemaFields
|
<TopicSchemaFields
|
||||||
|
entityFieldTasks={getEntityFieldThreadCounts(
|
||||||
|
EntityField.COLUMNS,
|
||||||
|
entityFieldTaskCount
|
||||||
|
)}
|
||||||
|
entityFieldThreads={getEntityFieldThreadCounts(
|
||||||
|
EntityField.COLUMNS,
|
||||||
|
entityFieldThreadCount
|
||||||
|
)}
|
||||||
|
entityFqn={topicDetails.fullyQualifiedName ?? ''}
|
||||||
hasDescriptionEditAccess={
|
hasDescriptionEditAccess={
|
||||||
topicPermissions.EditAll || topicPermissions.EditDescription
|
topicPermissions.EditAll || topicPermissions.EditDescription
|
||||||
}
|
}
|
||||||
@ -302,6 +311,7 @@ const TopicDetails: React.FC<TopicDetailsProps> = ({
|
|||||||
}
|
}
|
||||||
isReadOnly={Boolean(topicDetails.deleted)}
|
isReadOnly={Boolean(topicDetails.deleted)}
|
||||||
messageSchema={topicDetails.messageSchema}
|
messageSchema={topicDetails.messageSchema}
|
||||||
|
onThreadLinkSelect={onThreadLinkSelect}
|
||||||
onUpdate={handleSchemaFieldsUpdate}
|
onUpdate={handleSchemaFieldsUpdate}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -464,6 +474,7 @@ const TopicDetails: React.FC<TopicDetailsProps> = ({
|
|||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Tabs
|
<Tabs
|
||||||
|
destroyInactiveTabPane
|
||||||
activeKey={activeTab ?? EntityTabs.SCHEMA}
|
activeKey={activeTab ?? EntityTabs.SCHEMA}
|
||||||
className="entity-details-page-tabs"
|
className="entity-details-page-tabs"
|
||||||
data-testid="tabs"
|
data-testid="tabs"
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { TableProps } from 'antd';
|
import { TableProps } from 'antd';
|
||||||
|
import { ThreadType } from 'generated/api/feed/createThread';
|
||||||
|
import { EntityFieldThreads } from 'interface/feed.interface';
|
||||||
import { HTMLAttributes, ReactNode } from 'react';
|
import { HTMLAttributes, ReactNode } from 'react';
|
||||||
import { Field, Topic } from '../../../generated/entity/data/topic';
|
import { Field, Topic } from '../../../generated/entity/data/topic';
|
||||||
|
|
||||||
@ -27,9 +29,13 @@ export interface TopicSchemaFieldsProps
|
|||||||
hasDescriptionEditAccess: boolean;
|
hasDescriptionEditAccess: boolean;
|
||||||
hasTagEditAccess: boolean;
|
hasTagEditAccess: boolean;
|
||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
|
entityFqn: string;
|
||||||
defaultExpandAllRows?: boolean;
|
defaultExpandAllRows?: boolean;
|
||||||
showSchemaDisplayTypeSwitch?: boolean;
|
showSchemaDisplayTypeSwitch?: boolean;
|
||||||
onUpdate?: (updatedMessageSchema: Topic['messageSchema']) => Promise<void>;
|
onUpdate?: (updatedMessageSchema: Topic['messageSchema']) => Promise<void>;
|
||||||
|
entityFieldThreads?: EntityFieldThreads[];
|
||||||
|
entityFieldTasks?: EntityFieldThreads[];
|
||||||
|
onThreadLinkSelect?: (value: string, threadType?: ThreadType) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SchemaViewType {
|
export enum SchemaViewType {
|
||||||
|
@ -35,6 +35,7 @@ const mockProps: TopicSchemaFieldsProps = {
|
|||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
onUpdate: mockOnUpdate,
|
onUpdate: mockOnUpdate,
|
||||||
hasTagEditAccess: true,
|
hasTagEditAccess: true,
|
||||||
|
entityFqn: 'topic.fqn',
|
||||||
};
|
};
|
||||||
|
|
||||||
jest.mock('utils/TagsUtils', () => ({
|
jest.mock('utils/TagsUtils', () => ({
|
||||||
|
@ -28,14 +28,28 @@ import classNames from 'classnames';
|
|||||||
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
|
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||||
import SchemaEditor from 'components/schema-editor/SchemaEditor';
|
import SchemaEditor from 'components/schema-editor/SchemaEditor';
|
||||||
import TableTags from 'components/TableTags/TableTags.component';
|
import TableTags from 'components/TableTags/TableTags.component';
|
||||||
|
import { FQN_SEPARATOR_CHAR } from 'constants/char.constants';
|
||||||
|
import { DE_ACTIVE_COLOR } from 'constants/constants';
|
||||||
|
import { EntityField } from 'constants/Feeds.constants';
|
||||||
import { TABLE_SCROLL_VALUE } from 'constants/Table.constants';
|
import { TABLE_SCROLL_VALUE } from 'constants/Table.constants';
|
||||||
import { CSMode } from 'enums/codemirror.enum';
|
import { CSMode } from 'enums/codemirror.enum';
|
||||||
|
import { EntityType } from 'enums/entity.enum';
|
||||||
|
import { ThreadType } from 'generated/api/feed/createThread';
|
||||||
import { TagLabel, TagSource } from 'generated/type/tagLabel';
|
import { TagLabel, TagSource } from 'generated/type/tagLabel';
|
||||||
|
import { EntityFieldThreads } from 'interface/feed.interface';
|
||||||
import { cloneDeep, isEmpty, isUndefined, map } from 'lodash';
|
import { cloneDeep, isEmpty, isUndefined, map } from 'lodash';
|
||||||
import { EntityTags, TagOption } from 'Models';
|
import { EntityTags, TagOption } from 'Models';
|
||||||
import React, { FC, useMemo, useState } from 'react';
|
import React, { FC, Fragment, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { getEntityName } from 'utils/EntityUtils';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
import { getPartialNameFromTopicFQN } from 'utils/CommonUtils';
|
||||||
|
import { ENTITY_LINK_SEPARATOR, getEntityName } from 'utils/EntityUtils';
|
||||||
|
import { getFieldThreadElement } from 'utils/FeedElementUtils';
|
||||||
|
import {
|
||||||
|
getRequestDescriptionPath,
|
||||||
|
getUpdateDescriptionPath,
|
||||||
|
} from 'utils/TasksUtils';
|
||||||
|
import { ReactComponent as IconRequest } from '../../../assets/svg/request-icon.svg';
|
||||||
import { DataTypeTopic, Field } from '../../../generated/entity/data/topic';
|
import { DataTypeTopic, Field } from '../../../generated/entity/data/topic';
|
||||||
import { getTableExpandableConfig } from '../../../utils/TableUtils';
|
import { getTableExpandableConfig } from '../../../utils/TableUtils';
|
||||||
import {
|
import {
|
||||||
@ -59,13 +73,28 @@ const TopicSchemaFields: FC<TopicSchemaFieldsProps> = ({
|
|||||||
hasTagEditAccess,
|
hasTagEditAccess,
|
||||||
defaultExpandAllRows = false,
|
defaultExpandAllRows = false,
|
||||||
showSchemaDisplayTypeSwitch = true,
|
showSchemaDisplayTypeSwitch = true,
|
||||||
|
entityFqn,
|
||||||
|
entityFieldThreads,
|
||||||
|
onThreadLinkSelect,
|
||||||
|
entityFieldTasks,
|
||||||
}) => {
|
}) => {
|
||||||
|
const history = useHistory();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [editFieldDescription, setEditFieldDescription] = useState<Field>();
|
const [editFieldDescription, setEditFieldDescription] = useState<Field>();
|
||||||
const [viewType, setViewType] = useState<SchemaViewType>(
|
const [viewType, setViewType] = useState<SchemaViewType>(
|
||||||
SchemaViewType.FIELDS
|
SchemaViewType.FIELDS
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getColumnName = (cell: Field) => {
|
||||||
|
const fqn = cell?.fullyQualifiedName || '';
|
||||||
|
const columnName = getPartialNameFromTopicFQN(fqn);
|
||||||
|
// wrap it in quotes if dot is present
|
||||||
|
|
||||||
|
return columnName.includes(FQN_SEPARATOR_CHAR)
|
||||||
|
? `"${columnName}"`
|
||||||
|
: columnName;
|
||||||
|
};
|
||||||
|
|
||||||
const handleFieldTagsChange = async (
|
const handleFieldTagsChange = async (
|
||||||
selectedTags: EntityTags[],
|
selectedTags: EntityTags[],
|
||||||
editColumnTag: Field
|
editColumnTag: Field
|
||||||
@ -101,6 +130,66 @@ const TopicSchemaFields: FC<TopicSchemaFieldsProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onUpdateDescriptionHandler = (cell: Field) => {
|
||||||
|
const field = EntityField.COLUMNS;
|
||||||
|
const value = getColumnName(cell);
|
||||||
|
history.push(
|
||||||
|
getUpdateDescriptionPath(
|
||||||
|
EntityType.TOPIC,
|
||||||
|
entityFqn as string,
|
||||||
|
field,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onRequestDescriptionHandler = (cell: Field) => {
|
||||||
|
const field = EntityField.COLUMNS;
|
||||||
|
const value = getColumnName(cell);
|
||||||
|
history.push(
|
||||||
|
getRequestDescriptionPath(
|
||||||
|
EntityType.TOPIC,
|
||||||
|
entityFqn as string,
|
||||||
|
field,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRequestDescriptionElement = (cell: Field) => {
|
||||||
|
const hasDescription = Boolean(cell?.description ?? '');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
className="p-0 w-7 h-7 flex-none flex-center link-text focus:tw-outline-none hover-cell-icon m-r-xss"
|
||||||
|
data-testid="request-description"
|
||||||
|
type="text"
|
||||||
|
onClick={() =>
|
||||||
|
hasDescription
|
||||||
|
? onUpdateDescriptionHandler(cell)
|
||||||
|
: onRequestDescriptionHandler(cell)
|
||||||
|
}>
|
||||||
|
<Popover
|
||||||
|
destroyTooltipOnHide
|
||||||
|
content={
|
||||||
|
hasDescription
|
||||||
|
? t('message.request-update-description')
|
||||||
|
: t('message.request-description')
|
||||||
|
}
|
||||||
|
overlayClassName="ant-popover-request-description"
|
||||||
|
trigger="hover"
|
||||||
|
zIndex={9999}>
|
||||||
|
<IconRequest
|
||||||
|
height={14}
|
||||||
|
name={t('message.request-description')}
|
||||||
|
style={{ color: DE_ACTIVE_COLOR }}
|
||||||
|
width={14}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const renderFieldDescription: CellRendered<Field, 'description'> = (
|
const renderFieldDescription: CellRendered<Field, 'description'> = (
|
||||||
description,
|
description,
|
||||||
record,
|
record,
|
||||||
@ -110,28 +199,68 @@ const TopicSchemaFields: FC<TopicSchemaFieldsProps> = ({
|
|||||||
<Space
|
<Space
|
||||||
className="custom-group w-full"
|
className="custom-group w-full"
|
||||||
data-testid="description"
|
data-testid="description"
|
||||||
|
direction={isEmpty(description) ? 'horizontal' : 'vertical'}
|
||||||
id={`field-description-${index}`}
|
id={`field-description-${index}`}
|
||||||
size={4}>
|
size={4}>
|
||||||
<>
|
<div>
|
||||||
{description ? (
|
{description ? (
|
||||||
<RichTextEditorPreviewer markdown={description} />
|
<RichTextEditorPreviewer markdown={description} />
|
||||||
) : (
|
) : (
|
||||||
<Typography.Text className="text-grey-muted">
|
<span className="text-grey-muted">
|
||||||
{t('label.no-entity', {
|
{t('label.no-entity', {
|
||||||
entity: t('label.description'),
|
entity: t('label.description'),
|
||||||
})}
|
})}
|
||||||
</Typography.Text>
|
</span>
|
||||||
)}
|
)}
|
||||||
</>
|
</div>
|
||||||
{isReadOnly && !hasDescriptionEditAccess ? null : (
|
<div className="d-flex tw--mt-1.5">
|
||||||
|
{!isReadOnly ? (
|
||||||
|
<Fragment>
|
||||||
|
{hasDescriptionEditAccess && (
|
||||||
|
<>
|
||||||
<Button
|
<Button
|
||||||
className="p-0 opacity-0 group-hover-opacity-100"
|
className="p-0 tw-self-start flex-center w-7 h-7 d-flex-none hover-cell-icon"
|
||||||
data-testid="edit-button"
|
data-testid="edit-button"
|
||||||
icon={<EditIcon width={16} />}
|
|
||||||
type="text"
|
type="text"
|
||||||
onClick={() => setEditFieldDescription(record)}
|
onClick={() => setEditFieldDescription(record)}>
|
||||||
|
<EditIcon
|
||||||
|
height={14}
|
||||||
|
name={t('label.edit')}
|
||||||
|
style={{ color: DE_ACTIVE_COLOR }}
|
||||||
|
width={14}
|
||||||
/>
|
/>
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
{getRequestDescriptionElement(record)}
|
||||||
|
{getFieldThreadElement(
|
||||||
|
getColumnName(record),
|
||||||
|
EntityField.DESCRIPTION,
|
||||||
|
entityFieldThreads as EntityFieldThreads[],
|
||||||
|
onThreadLinkSelect,
|
||||||
|
EntityType.TOPIC,
|
||||||
|
entityFqn,
|
||||||
|
`columns${ENTITY_LINK_SEPARATOR}${getColumnName(
|
||||||
|
record
|
||||||
|
)}${ENTITY_LINK_SEPARATOR}description`,
|
||||||
|
Boolean(record)
|
||||||
|
)}
|
||||||
|
{getFieldThreadElement(
|
||||||
|
getColumnName(record),
|
||||||
|
EntityField.DESCRIPTION,
|
||||||
|
entityFieldTasks as EntityFieldThreads[],
|
||||||
|
onThreadLinkSelect,
|
||||||
|
EntityType.TOPIC,
|
||||||
|
entityFqn,
|
||||||
|
`columns${ENTITY_LINK_SEPARATOR}${getColumnName(
|
||||||
|
record
|
||||||
|
)}${ENTITY_LINK_SEPARATOR}description`,
|
||||||
|
Boolean(record),
|
||||||
|
ThreadType.Task
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -264,6 +393,7 @@ const TopicSchemaFields: FC<TopicSchemaFieldsProps> = ({
|
|||||||
isEmpty(messageSchema?.schemaFields) ? (
|
isEmpty(messageSchema?.schemaFields) ? (
|
||||||
messageSchema?.schemaText && (
|
messageSchema?.schemaText && (
|
||||||
<SchemaEditor
|
<SchemaEditor
|
||||||
|
className="custom-code-mirror-theme custom-query-editor"
|
||||||
editorClass={classNames('table-query-editor')}
|
editorClass={classNames('table-query-editor')}
|
||||||
mode={{ name: CSMode.JAVASCRIPT }}
|
mode={{ name: CSMode.JAVASCRIPT }}
|
||||||
options={{
|
options={{
|
||||||
|
@ -127,6 +127,7 @@ const TopicVersion: FC<TopicVersionProp> = ({
|
|||||||
<TopicSchemaFields
|
<TopicSchemaFields
|
||||||
defaultExpandAllRows
|
defaultExpandAllRows
|
||||||
isReadOnly
|
isReadOnly
|
||||||
|
entityFqn={currentVersionData?.fullyQualifiedName ?? ''}
|
||||||
hasDescriptionEditAccess={false}
|
hasDescriptionEditAccess={false}
|
||||||
hasTagEditAccess={false}
|
hasTagEditAccess={false}
|
||||||
messageSchema={messageSchemaDiff}
|
messageSchema={messageSchemaDiff}
|
||||||
|
@ -273,8 +273,7 @@ const Users = ({
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div className="p-x-sm">
|
<Typography.Paragraph className="m-b-0">
|
||||||
<p className="m-t-xs">
|
|
||||||
{userData.description || (
|
{userData.description || (
|
||||||
<span className="text-grey-muted">
|
<span className="text-grey-muted">
|
||||||
{t('label.no-entity', {
|
{t('label.no-entity', {
|
||||||
@ -282,8 +281,7 @@ const Users = ({
|
|||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</p>
|
</Typography.Paragraph>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -584,7 +582,11 @@ const Users = ({
|
|||||||
)}
|
)}
|
||||||
<Space className="p-sm w-full" direction="vertical" size={8}>
|
<Space className="p-sm w-full" direction="vertical" size={8}>
|
||||||
{getDisplayNameComponent()}
|
{getDisplayNameComponent()}
|
||||||
<p>{userData.email}</p>
|
<Typography.Paragraph
|
||||||
|
className="m-b-0"
|
||||||
|
ellipsis={{ tooltip: true }}>
|
||||||
|
{userData.email}
|
||||||
|
</Typography.Paragraph>
|
||||||
{getDescriptionComponent()}
|
{getDescriptionComponent()}
|
||||||
{isAuthProviderBasic &&
|
{isAuthProviderBasic &&
|
||||||
(isAdminUser || isLoggedinUser) &&
|
(isAdminUser || isLoggedinUser) &&
|
||||||
@ -719,7 +721,7 @@ const Users = ({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ErrorPlaceHolder>
|
<ErrorPlaceHolder className="m-0">
|
||||||
<Typography.Paragraph>
|
<Typography.Paragraph>
|
||||||
{tab === UserPageTabs.MY_DATA
|
{tab === UserPageTabs.MY_DATA
|
||||||
? t('server.you-have-not-action-anything-yet', {
|
? t('server.you-have-not-action-anything-yet', {
|
||||||
|
@ -31,6 +31,7 @@ import { getMlModelByFQN } from 'rest/mlModelAPI';
|
|||||||
import { getPipelineByFqn } from 'rest/pipelineAPI';
|
import { getPipelineByFqn } from 'rest/pipelineAPI';
|
||||||
import { getTableDetailsByFQN } from 'rest/tableAPI';
|
import { getTableDetailsByFQN } from 'rest/tableAPI';
|
||||||
import { getTopicByFqn } from 'rest/topicsAPI';
|
import { getTopicByFqn } from 'rest/topicsAPI';
|
||||||
|
import { getTableFQNFromColumnFQN } from 'utils/CommonUtils';
|
||||||
import { getEntityName } from 'utils/EntityUtils';
|
import { getEntityName } from 'utils/EntityUtils';
|
||||||
import AppState from '../../../AppState';
|
import AppState from '../../../AppState';
|
||||||
import { EntityType } from '../../../enums/entity.enum';
|
import { EntityType } from '../../../enums/entity.enum';
|
||||||
@ -60,6 +61,13 @@ const PopoverContent: React.FC<{
|
|||||||
case EntityType.TABLE:
|
case EntityType.TABLE:
|
||||||
promise = getTableDetailsByFQN(entityFQN, fields);
|
promise = getTableDetailsByFQN(entityFQN, fields);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case EntityType.TEST_CASE:
|
||||||
|
promise = getTableDetailsByFQN(
|
||||||
|
getTableFQNFromColumnFQN(entityFQN),
|
||||||
|
fields
|
||||||
|
);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case EntityType.TOPIC:
|
case EntityType.TOPIC:
|
||||||
promise = getTopicByFqn(entityFQN, fields);
|
promise = getTopicByFqn(entityFQN, fields);
|
||||||
|
@ -508,6 +508,7 @@
|
|||||||
"loading": "Loading",
|
"loading": "Loading",
|
||||||
"local-config-source": "Local Config Source",
|
"local-config-source": "Local Config Source",
|
||||||
"log-plural": "Logs",
|
"log-plural": "Logs",
|
||||||
|
"log-viewer": "Log Viewer",
|
||||||
"logged-in-user-lowercase": "logged-in user",
|
"logged-in-user-lowercase": "logged-in user",
|
||||||
"login": "Login",
|
"login": "Login",
|
||||||
"logo-url": "Logo URL",
|
"logo-url": "Logo URL",
|
||||||
|
@ -508,6 +508,7 @@
|
|||||||
"loading": "Cargando",
|
"loading": "Cargando",
|
||||||
"local-config-source": "Origen de configuración local",
|
"local-config-source": "Origen de configuración local",
|
||||||
"log-plural": "Registros",
|
"log-plural": "Registros",
|
||||||
|
"log-viewer": "Log Viewer",
|
||||||
"logged-in-user-lowercase": "usuario conectado",
|
"logged-in-user-lowercase": "usuario conectado",
|
||||||
"login": "Iniciar sesión",
|
"login": "Iniciar sesión",
|
||||||
"logo-url": "Logo URL",
|
"logo-url": "Logo URL",
|
||||||
|
@ -508,6 +508,7 @@
|
|||||||
"loading": "Chargement",
|
"loading": "Chargement",
|
||||||
"local-config-source": "Source de Configuration Locale",
|
"local-config-source": "Source de Configuration Locale",
|
||||||
"log-plural": "Journal",
|
"log-plural": "Journal",
|
||||||
|
"log-viewer": "Log Viewer",
|
||||||
"logged-in-user-lowercase": "Utilisateur Connecté",
|
"logged-in-user-lowercase": "Utilisateur Connecté",
|
||||||
"login": "Se Connecter",
|
"login": "Se Connecter",
|
||||||
"logo-url": "Logo URL",
|
"logo-url": "Logo URL",
|
||||||
|
@ -508,6 +508,7 @@
|
|||||||
"loading": "読み込み中",
|
"loading": "読み込み中",
|
||||||
"local-config-source": "Local Config Source",
|
"local-config-source": "Local Config Source",
|
||||||
"log-plural": "ログ",
|
"log-plural": "ログ",
|
||||||
|
"log-viewer": "Log Viewer",
|
||||||
"logged-in-user-lowercase": "logged-in user",
|
"logged-in-user-lowercase": "logged-in user",
|
||||||
"login": "ログイン",
|
"login": "ログイン",
|
||||||
"logo-url": "Logo URL",
|
"logo-url": "Logo URL",
|
||||||
|
@ -508,6 +508,7 @@
|
|||||||
"loading": "Carregando",
|
"loading": "Carregando",
|
||||||
"local-config-source": "Origem da configuração local",
|
"local-config-source": "Origem da configuração local",
|
||||||
"log-plural": "Logs",
|
"log-plural": "Logs",
|
||||||
|
"log-viewer": "Log Viewer",
|
||||||
"logged-in-user-lowercase": "conectar com usuário",
|
"logged-in-user-lowercase": "conectar com usuário",
|
||||||
"login": "Entrar",
|
"login": "Entrar",
|
||||||
"logo-url": "Logo URL",
|
"logo-url": "Logo URL",
|
||||||
|
@ -508,6 +508,7 @@
|
|||||||
"loading": "加载中",
|
"loading": "加载中",
|
||||||
"local-config-source": "本地配置源",
|
"local-config-source": "本地配置源",
|
||||||
"log-plural": "日志",
|
"log-plural": "日志",
|
||||||
|
"log-viewer": "Log Viewer",
|
||||||
"logged-in-user-lowercase": "已登录用户",
|
"logged-in-user-lowercase": "已登录用户",
|
||||||
"login": "登录",
|
"login": "登录",
|
||||||
"logo-url": "Logo URL",
|
"logo-url": "Logo URL",
|
||||||
|
@ -267,11 +267,11 @@ const AddQueryPage = () => {
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
placement="top"
|
placement="top"
|
||||||
title={
|
title={
|
||||||
!permissions.query.Create && NO_PERMISSION_FOR_ACTION
|
!permissions.query?.Create && NO_PERMISSION_FOR_ACTION
|
||||||
}>
|
}>
|
||||||
<Button
|
<Button
|
||||||
data-testid="save-btn"
|
data-testid="save-btn"
|
||||||
disabled={!permissions.query.Create}
|
disabled={!permissions.query?.Create}
|
||||||
htmlType="submit"
|
htmlType="submit"
|
||||||
loading={isSaving}
|
loading={isSaving}
|
||||||
type="primary">
|
type="primary">
|
||||||
|
@ -22,11 +22,19 @@ jest.mock('react-router-dom', () => ({
|
|||||||
ingestionName: 'ingestion_123456',
|
ingestionName: 'ingestion_123456',
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
jest.mock('../../utils/LogsViewer.utils', () => ({
|
||||||
|
getLogBreadCrumbs: jest
|
||||||
|
.fn()
|
||||||
|
.mockReturnValue({ name: 'getLogBreadCrumbs', url: '' }),
|
||||||
|
}));
|
||||||
|
|
||||||
jest.mock(
|
jest.mock(
|
||||||
'components/common/title-breadcrumb/title-breadcrumb.component',
|
'components/common/title-breadcrumb/title-breadcrumb.component',
|
||||||
() => () => <>TitleBreadcrumb.component</>
|
() => () => <>TitleBreadcrumb.component</>
|
||||||
);
|
);
|
||||||
|
jest.mock('components/containers/PageLayoutV1', () =>
|
||||||
|
jest.fn().mockImplementation(({ children }) => <div>{children}</div>)
|
||||||
|
);
|
||||||
|
|
||||||
jest.mock('react-lazylog', () => ({
|
jest.mock('react-lazylog', () => ({
|
||||||
LazyLog: jest
|
LazyLog: jest
|
||||||
|
@ -11,10 +11,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Button, Card, Col, Row, Space, Typography } from 'antd';
|
import { Button, Col, Row, Space, Typography } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import { CopyToClipboardButton } from 'components/buttons/CopyToClipboardButton/CopyToClipboardButton';
|
import { CopyToClipboardButton } from 'components/buttons/CopyToClipboardButton/CopyToClipboardButton';
|
||||||
import TitleBreadcrumb from 'components/common/title-breadcrumb/title-breadcrumb.component';
|
import TitleBreadcrumb from 'components/common/title-breadcrumb/title-breadcrumb.component';
|
||||||
|
import PageLayoutV1 from 'components/containers/PageLayoutV1';
|
||||||
import { IngestionRecentRuns } from 'components/Ingestion/IngestionRecentRun/IngestionRecentRuns.component';
|
import { IngestionRecentRuns } from 'components/Ingestion/IngestionRecentRun/IngestionRecentRuns.component';
|
||||||
import Loader from 'components/Loader/Loader';
|
import Loader from 'components/Loader/Loader';
|
||||||
import { isEmpty, isNil, isUndefined, toNumber } from 'lodash';
|
import { isEmpty, isNil, isUndefined, toNumber } from 'lodash';
|
||||||
@ -220,10 +221,12 @@ const LogsViewer = () => {
|
|||||||
};
|
};
|
||||||
}, [ingestionDetails]);
|
}, [ingestionDetails]);
|
||||||
|
|
||||||
return isLoading ? (
|
if (isLoading) {
|
||||||
<Loader />
|
return <Loader />;
|
||||||
) : (
|
}
|
||||||
<div className="m-xs ">
|
|
||||||
|
return (
|
||||||
|
<PageLayoutV1 pageTitle={t('label.log-viewer')}>
|
||||||
<Space align="start" className="w-full m-md m-t-xs" direction="vertical">
|
<Space align="start" className="w-full m-md m-t-xs" direction="vertical">
|
||||||
<Space align="center">
|
<Space align="center">
|
||||||
<TitleBreadcrumb
|
<TitleBreadcrumb
|
||||||
@ -241,10 +244,9 @@ const LogsViewer = () => {
|
|||||||
</Space>
|
</Space>
|
||||||
</Space>
|
</Space>
|
||||||
|
|
||||||
<Card className="h-full p-0 log-card">
|
|
||||||
{!isEmpty(logs) ? (
|
{!isEmpty(logs) ? (
|
||||||
<Row>
|
<Row className="border-top">
|
||||||
<Col className="p-md" span={18}>
|
<Col className="p-md border-right" span={18}>
|
||||||
<Row className="relative" gutter={[16, 16]}>
|
<Row className="relative" gutter={[16, 16]}>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Row justify="end">
|
<Row justify="end">
|
||||||
@ -277,8 +279,10 @@ const LogsViewer = () => {
|
|||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={6}>
|
<Col span={6}>
|
||||||
<Card className="h-full" data-testid="summary-card">
|
<Space
|
||||||
<Space className="p-md w-full" direction="vertical">
|
className="p-md w-full"
|
||||||
|
data-testid="summary-card"
|
||||||
|
direction="vertical">
|
||||||
<Typography.Title level={5}>
|
<Typography.Title level={5}>
|
||||||
{t('label.summary')}
|
{t('label.summary')}
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
@ -304,14 +308,12 @@ const LogsViewer = () => {
|
|||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
</Space>
|
</Space>
|
||||||
</Card>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
) : (
|
) : (
|
||||||
<LogViewerSkeleton />
|
<LogViewerSkeleton />
|
||||||
)}
|
)}
|
||||||
</Card>
|
</PageLayoutV1>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -254,6 +254,8 @@ const TableDetailsPageV1 = () => {
|
|||||||
entity: t('label.resource-permission-lowercase'),
|
entity: t('label.resource-permission-lowercase'),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[getEntityPermissionByFqn, setTablePermissions]
|
[getEntityPermissionByFqn, setTablePermissions]
|
||||||
@ -862,7 +864,12 @@ const TableDetailsPageV1 = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(tablePermissions.ViewAll || tablePermissions.ViewBasic)) {
|
if (!(tablePermissions.ViewAll || tablePermissions.ViewBasic)) {
|
||||||
return <ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.PERMISSION} />;
|
return (
|
||||||
|
<ErrorPlaceHolder
|
||||||
|
className="m-0"
|
||||||
|
type={ERROR_PLACEHOLDER_TYPE.PERMISSION}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tableDetails) {
|
if (!tableDetails) {
|
||||||
|
@ -977,3 +977,7 @@ export const getEntityDetailLink = (
|
|||||||
|
|
||||||
return path;
|
return path;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getPartialNameFromTopicFQN = (fqn: string): string => {
|
||||||
|
return Fqn.split(fqn).slice(2).join(FQN_SEPARATOR_CHAR);
|
||||||
|
};
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
import { OPEN_METADATA } from 'constants/service-guide.constant';
|
import { OPEN_METADATA } from 'constants/service-guide.constant';
|
||||||
import { isUndefined, startCase } from 'lodash';
|
import { isUndefined, startCase } from 'lodash';
|
||||||
import { IngestionPipeline } from '../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
import { IngestionPipeline } from '../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||||
|
import { getNameFromFQN } from './CommonUtils';
|
||||||
|
import Fqn from './Fqn';
|
||||||
import { getSettingsPathFromPipelineType } from './IngestionUtils';
|
import { getSettingsPathFromPipelineType } from './IngestionUtils';
|
||||||
import { getLogEntityPath } from './RouterUtils';
|
import { getLogEntityPath } from './RouterUtils';
|
||||||
|
|
||||||
@ -32,7 +34,8 @@ export const getLogBreadCrumbs = (
|
|||||||
ingestionName: string,
|
ingestionName: string,
|
||||||
ingestionDetails: IngestionPipeline | undefined
|
ingestionDetails: IngestionPipeline | undefined
|
||||||
) => {
|
) => {
|
||||||
if (ingestionName.split('.')[0] === OPEN_METADATA && ingestionDetails) {
|
const updateIngestionName = Fqn.split(ingestionName);
|
||||||
|
if (updateIngestionName.includes(OPEN_METADATA) && ingestionDetails) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: startCase(ingestionDetails.pipelineType),
|
name: startCase(ingestionDetails.pipelineType),
|
||||||
@ -40,7 +43,7 @@ export const getLogBreadCrumbs = (
|
|||||||
activeTitle: true,
|
activeTitle: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: startCase(ingestionName.split('.')[1]),
|
name: getNameFromFQN(ingestionName),
|
||||||
url: '',
|
url: '',
|
||||||
activeTitle: true,
|
activeTitle: true,
|
||||||
},
|
},
|
||||||
@ -50,7 +53,7 @@ export const getLogBreadCrumbs = (
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const urlPath = [serviceType, ...ingestionName.split('.')];
|
const urlPath = [serviceType, ...updateIngestionName];
|
||||||
|
|
||||||
return urlPath.map((path, index) => {
|
return urlPath.map((path, index) => {
|
||||||
return {
|
return {
|
||||||
|
@ -124,7 +124,11 @@ import {
|
|||||||
PipelineServiceType,
|
PipelineServiceType,
|
||||||
} from '../generated/entity/services/pipelineService';
|
} from '../generated/entity/services/pipelineService';
|
||||||
import { ServicesType } from '../interface/service.interface';
|
import { ServicesType } from '../interface/service.interface';
|
||||||
import { getEntityDeleteMessage, pluralize } from './CommonUtils';
|
import {
|
||||||
|
getEntityDeleteMessage,
|
||||||
|
pluralize,
|
||||||
|
replaceAllSpacialCharWith_,
|
||||||
|
} from './CommonUtils';
|
||||||
import { getDashboardURL } from './DashboardServiceUtils';
|
import { getDashboardURL } from './DashboardServiceUtils';
|
||||||
import { getBrokers } from './MessagingServiceUtils';
|
import { getBrokers } from './MessagingServiceUtils';
|
||||||
import { showErrorToast } from './ToastUtils';
|
import { showErrorToast } from './ToastUtils';
|
||||||
@ -604,7 +608,9 @@ export const getIngestionName = (
|
|||||||
IngestionPipelineType.Dbt,
|
IngestionPipelineType.Dbt,
|
||||||
].includes(type)
|
].includes(type)
|
||||||
) {
|
) {
|
||||||
return `${serviceName}_${type}_${cryptoRandomString({
|
return `${replaceAllSpacialCharWith_(
|
||||||
|
serviceName
|
||||||
|
)}_${type}_${cryptoRandomString({
|
||||||
length: 8,
|
length: 8,
|
||||||
type: 'alphanumeric',
|
type: 'alphanumeric',
|
||||||
})}`;
|
})}`;
|
||||||
|
@ -51,12 +51,13 @@ import {
|
|||||||
getPipelineDetailsPath,
|
getPipelineDetailsPath,
|
||||||
getServiceDetailsPath,
|
getServiceDetailsPath,
|
||||||
getTableDetailsPath,
|
getTableDetailsPath,
|
||||||
|
getTableTabPath,
|
||||||
getTagsDetailsPath,
|
getTagsDetailsPath,
|
||||||
getTopicDetailsPath,
|
getTopicDetailsPath,
|
||||||
TEXT_BODY_COLOR,
|
TEXT_BODY_COLOR,
|
||||||
} from '../constants/constants';
|
} from '../constants/constants';
|
||||||
import { GlobalSettingsMenuCategory } from '../constants/GlobalSettings.constants';
|
import { GlobalSettingsMenuCategory } from '../constants/GlobalSettings.constants';
|
||||||
import { EntityType, FqnPart } from '../enums/entity.enum';
|
import { EntityTabs, EntityType, FqnPart } from '../enums/entity.enum';
|
||||||
import { SearchIndex } from '../enums/search.enum';
|
import { SearchIndex } from '../enums/search.enum';
|
||||||
import { ConstraintTypes, PrimaryTableDataTypes } from '../enums/table.enum';
|
import { ConstraintTypes, PrimaryTableDataTypes } from '../enums/table.enum';
|
||||||
import {
|
import {
|
||||||
@ -272,6 +273,12 @@ export const getEntityLink = (
|
|||||||
case EntityType.DASHBOARD_DATA_MODEL:
|
case EntityType.DASHBOARD_DATA_MODEL:
|
||||||
return getDataModelDetailsPath(fullyQualifiedName);
|
return getDataModelDetailsPath(fullyQualifiedName);
|
||||||
|
|
||||||
|
case EntityType.TEST_CASE:
|
||||||
|
return `${getTableTabPath(
|
||||||
|
getTableFQNFromColumnFQN(fullyQualifiedName),
|
||||||
|
EntityTabs.PROFILER
|
||||||
|
)}?activeTab=Data Quality`;
|
||||||
|
|
||||||
case SearchIndex.TABLE:
|
case SearchIndex.TABLE:
|
||||||
case EntityType.TABLE:
|
case EntityType.TABLE:
|
||||||
default:
|
default:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user