From c997d8c80b0bc79bbd43b2f72bed9c9e5f9fc9f6 Mon Sep 17 00:00:00 2001 From: Ashish Gupta Date: Fri, 7 Apr 2023 11:35:40 +0530 Subject: [PATCH] Feat #10584 : Support Activity tab for DataModel Entity (#10941) * Supported DataModel in Dashboard Page * url fqn changes * Support Activity tab for DataModel Entity * Remove dataModel resource descriptor * Fix tasks for dashboard data models * changes as per comments * minor fix * changes as per comments and minor improvements --------- Co-authored-by: Nahuel Verdugo Revigliono --- .../service/jdbi3/FeedRepository.java | 46 ++++ .../json/data/ResourceDescriptors.json | 14 - .../org/openmetadata/schema/EntityLink.g4 | 1 + .../resources/ui/src/enums/entity.enum.ts | 1 + .../ui/src/locale/languages/en-us.json | 1 + .../ui/src/locale/languages/es-es.json | 1 + .../ui/src/locale/languages/fr-fr.json | 1 + .../ui/src/locale/languages/ja-jp.json | 1 + .../ui/src/locale/languages/pt-br.json | 1 + .../ui/src/locale/languages/zh-cn.json | 1 + .../DataModelPage/DataModelPage.component.tsx | 245 +++++++++++++++++- .../pages/TasksPage/TasksPage.interface.ts | 4 +- .../resources/ui/src/rest/dataModelsAPI.ts | 15 ++ .../resources/ui/src/utils/DataModelsUtils.ts | 4 + .../resources/ui/src/utils/TableUtils.tsx | 4 + .../main/resources/ui/src/utils/TasksUtils.ts | 12 + 16 files changed, 325 insertions(+), 27 deletions(-) diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/FeedRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/FeedRepository.java index 59bec1607f8..3ef455353c5 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/FeedRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/FeedRepository.java @@ -19,6 +19,7 @@ import static org.openmetadata.schema.type.Relationship.CREATED; import static org.openmetadata.schema.type.Relationship.IS_ABOUT; import static org.openmetadata.schema.type.Relationship.REPLIED_TO; import static org.openmetadata.service.Entity.DASHBOARD; +import static org.openmetadata.service.Entity.DASHBOARD_DATA_MODEL; import static org.openmetadata.service.Entity.DATABASE_SCHEMA; import static org.openmetadata.service.Entity.FIELD_DESCRIPTION; import static org.openmetadata.service.Entity.PIPELINE; @@ -61,6 +62,7 @@ import org.openmetadata.schema.api.feed.EntityLinkThreadCount; import org.openmetadata.schema.api.feed.ResolveTask; import org.openmetadata.schema.api.feed.ThreadCount; import org.openmetadata.schema.entity.data.Dashboard; +import org.openmetadata.schema.entity.data.DashboardDataModel; import org.openmetadata.schema.entity.data.DatabaseSchema; import org.openmetadata.schema.entity.data.Pipeline; import org.openmetadata.schema.entity.data.Table; @@ -312,6 +314,50 @@ public class FeedRepository { patch = JsonUtils.getJsonPatch(oldJson, updatedEntityJson); repository.patch(uriInfo, dashboard.getId(), user, patch); break; + case DASHBOARD_DATA_MODEL: + DashboardDataModel dashboardDataModel = JsonUtils.readValue(json, DashboardDataModel.class); + oldJson = JsonUtils.pojoToJson(dashboardDataModel); + if (entityLink.getFieldName() != null) { + if (entityLink.getFieldName().equals("columns")) { + Optional col = + dashboardDataModel.getColumns().stream() + .filter(c -> c.getName().equals(entityLink.getArrayFieldName())) + .findFirst(); + if (col.isPresent()) { + Column column = col.get(); + if (descriptionTasks.contains(taskType)) { + column.setDescription(newValue); + } else if (tagTasks.contains(taskType)) { + List tags = JsonUtils.readObjects(newValue, TagLabel.class); + column.setTags(tags); + } + } else { + throw new IllegalArgumentException( + String.format( + "The Column with name '%s' is not found in the dashboard data model.", + entityLink.getArrayFieldName())); + } + } else if (descriptionTasks.contains(taskType) && entityLink.getFieldName().equals(FIELD_DESCRIPTION)) { + dashboardDataModel.setDescription(newValue); + } else if (tagTasks.contains(taskType) && entityLink.getFieldName().equals("tags")) { + List tags = JsonUtils.readObjects(newValue, TagLabel.class); + dashboardDataModel.setTags(tags); + } else { + // Not supported + throw new IllegalArgumentException( + String.format(UNSUPPORTED_FIELD_NAME_FOR_TASK, entityLink.getFieldName(), task.getType())); + } + } else { + // Not supported + throw new IllegalArgumentException( + String.format( + "The Entity link with no field name - %s is not supported for %s task.", + entityLink, task.getType())); + } + updatedEntityJson = JsonUtils.pojoToJson(dashboardDataModel); + patch = JsonUtils.getJsonPatch(oldJson, updatedEntityJson); + repository.patch(uriInfo, dashboardDataModel.getId(), user, patch); + break; case PIPELINE: Pipeline pipeline = JsonUtils.readValue(json, Pipeline.class); oldJson = JsonUtils.pojoToJson(pipeline); diff --git a/openmetadata-service/src/main/resources/json/data/ResourceDescriptors.json b/openmetadata-service/src/main/resources/json/data/ResourceDescriptors.json index ebd92bf71be..2f43d1720b0 100644 --- a/openmetadata-service/src/main/resources/json/data/ResourceDescriptors.json +++ b/openmetadata-service/src/main/resources/json/data/ResourceDescriptors.json @@ -549,20 +549,6 @@ "EditDescription" ] }, - { - "name": "dataModel", - "operations": [ - "Create", - "Delete", - "ViewAll", - "EditAll", - "EditDescription", - "EditDisplayName", - "EditTags", - "EditOwner", - "EditLineage" - ] - }, { "name": "dashboardDataModel", "operations": [ diff --git a/openmetadata-spec/src/main/antlr4/org/openmetadata/schema/EntityLink.g4 b/openmetadata-spec/src/main/antlr4/org/openmetadata/schema/EntityLink.g4 index e66b3e5e62e..b39f4947ce5 100644 --- a/openmetadata-spec/src/main/antlr4/org/openmetadata/schema/EntityLink.g4 +++ b/openmetadata-spec/src/main/antlr4/org/openmetadata/schema/EntityLink.g4 @@ -33,6 +33,7 @@ ENTITY_TYPE | 'testDefinition' | 'testSuite' | 'testCase' + | 'dashboardDataModel' ; ENTITY_FIELD : 'columns' diff --git a/openmetadata-ui/src/main/resources/ui/src/enums/entity.enum.ts b/openmetadata-ui/src/main/resources/ui/src/enums/entity.enum.ts index 98b701d5371..dc39e7e3153 100644 --- a/openmetadata-ui/src/main/resources/ui/src/enums/entity.enum.ts +++ b/openmetadata-ui/src/main/resources/ui/src/enums/entity.enum.ts @@ -51,6 +51,7 @@ export enum AssetsType { DASHBOARD = 'dashboard', PIPELINE = 'pipeline', MLMODEL = 'mlmodel', + DASHBOARD_DATA_MODEL = 'dashboardDataModel', } export enum ChangeType { diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json index a879204be8e..5b7655e82fe 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json @@ -298,6 +298,7 @@ "feature-plural-used": "Features Used", "february": "February", "feed-lowercase": "feed", + "feed-plural": "Feeds", "field-change": "Field Change", "field-invalid": "{{field}} is invalid", "field-plural": "Fields", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json index 2e8052dcc00..180966a6496 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json @@ -298,6 +298,7 @@ "feature-plural-used": "Funcionalidades utilizadas", "february": "Febrero", "feed-lowercase": "feed", + "feed-plural": "Feeds", "field-change": "Cambio de Campo", "field-invalid": "{{field}} es inválido", "field-plural": "Campos", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json index 610073eced1..d7c5261fe59 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json @@ -298,6 +298,7 @@ "feature-plural-used": "Features Used", "february": "February", "feed-lowercase": "feed", + "feed-plural": "Feeds", "field-change": "Field Change", "field-invalid": "{{field}} est imvalide", "field-plural": "Champs", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json index 0b3f0256f37..8cf673f0686 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json @@ -298,6 +298,7 @@ "feature-plural-used": "使用される機能", "february": "2月", "feed-lowercase": "フィード", + "feed-plural": "Feeds", "field-change": "フィールドを変更", "field-invalid": "{{field}}は不正です", "field-plural": "フィールド", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json index 7e4d5525b1b..6db3b538e9c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json @@ -298,6 +298,7 @@ "feature-plural-used": "Funções usadas", "february": "Fevereiro", "feed-lowercase": "feed", + "feed-plural": "Feeds", "field-change": "Mudança de campo", "field-invalid": "{{field}} inválido", "field-plural": "Campos", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json index 2eb2bf45c8f..0d568e20238 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json @@ -298,6 +298,7 @@ "feature-plural-used": "Features Used", "february": "February", "feed-lowercase": "feed", + "feed-plural": "Feeds", "field-change": "域变动", "field-invalid": "{{field}} 无效", "field-plural": "域", diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx index bd42f92da56..eadadfed591 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx @@ -11,9 +11,11 @@ * limitations under the License. */ -import { Card, Space, Tabs } from 'antd'; +import { Card, Col, Row, Space, Tabs } from 'antd'; import AppState from 'AppState'; import { AxiosError } from 'axios'; +import ActivityFeedList from 'components/ActivityFeed/ActivityFeedList/ActivityFeedList'; +import ActivityThreadPanel from 'components/ActivityFeed/ActivityThreadPanel/ActivityThreadPanel'; import Description from 'components/common/description/Description'; import EntityPageInfo from 'components/common/entityPageInfo/EntityPageInfo'; import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder'; @@ -29,16 +31,22 @@ import { import SchemaEditor from 'components/schema-editor/SchemaEditor'; import { FQN_SEPARATOR_CHAR } from 'constants/char.constants'; import { getServiceDetailsPath } from 'constants/constants'; -import { ENTITY_CARD_CLASS } from 'constants/entity.constants'; +import { EntityField } from 'constants/Feeds.constants'; import { NO_PERMISSION_TO_VIEW } from 'constants/HelperTextUtil'; import { CSMode } from 'enums/codemirror.enum'; import { EntityInfo, EntityType } from 'enums/entity.enum'; +import { FeedFilter } from 'enums/mydata.enum'; import { ServiceCategory } from 'enums/service.enum'; import { OwnerType } from 'enums/user.enum'; -import { compare } from 'fast-json-patch'; +import { compare, Operation } from 'fast-json-patch'; +import { CreateThread } from 'generated/api/feed/createThread'; import { DashboardDataModel } from 'generated/entity/data/dashboardDataModel'; +import { Post, Thread, ThreadType } from 'generated/entity/feed/thread'; +import { Paging } from 'generated/type/paging'; import { LabelType, State, TagSource } from 'generated/type/tagLabel'; -import { isUndefined, omitBy } from 'lodash'; +import { EntityFieldThreadCount } from 'interface/feed.interface'; +import jsonData from 'jsons/en'; +import { isUndefined, omitBy, toString } from 'lodash'; import { EntityTags, ExtraInfo } from 'Models'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -49,14 +57,22 @@ import { patchDataModelDetails, removeDataModelFollower, } from 'rest/dataModelsAPI'; +import { getAllFeeds, postFeedById, postThread } from 'rest/feedsAPI'; import { + getCountBadge, getCurrentUserId, getEntityMissingError, getEntityPlaceHolder, + getFeedCounts, getOwnerValue, } from 'utils/CommonUtils'; import { getDataModelsDetailPath } from 'utils/DataModelsUtils'; -import { getEntityName } from 'utils/EntityUtils'; +import { getEntityFeedLink, getEntityName } from 'utils/EntityUtils'; +import { + deletePost, + getEntityFieldThreadCounts, + updateThreadData, +} from 'utils/FeedUtils'; import { DEFAULT_ENTITY_PERMISSION } from 'utils/PermissionsUtils'; import { serviceTypeLogo } from 'utils/ServiceUtils'; import { getTagsWithoutTier, getTierTags } from 'utils/TableUtils'; @@ -77,6 +93,21 @@ const DataModelsPage = () => { useState(DEFAULT_ENTITY_PERMISSION); const [dataModelData, setDataModelData] = useState(); + const [threadLink, setThreadLink] = useState(''); + const [entityThread, setEntityThread] = useState([]); + const [isEntityThreadLoading, setIsEntityThreadLoading] = + useState(false); + const [paging, setPaging] = useState({} as Paging); + + const [feedCount, setFeedCount] = useState(0); + const [entityFieldThreadCount, setEntityFieldThreadCount] = useState< + EntityFieldThreadCount[] + >([]); + + const [entityFieldTaskCount, setEntityFieldTaskCount] = useState< + EntityFieldThreadCount[] + >([]); + // get current user details const currentUser = useMemo( () => AppState.getCurrentUserDetails(), @@ -159,6 +190,110 @@ const DataModelsPage = () => { ]; }, [dataModelData, dashboardDataModelFQN, entityName]); + const getFeedData = useCallback( + async ( + after?: string, + feedFilter?: FeedFilter, + threadType?: ThreadType + ) => { + setIsEntityThreadLoading(true); + !after && setEntityThread([]); + + try { + const { data, paging: pagingObj } = await getAllFeeds( + getEntityFeedLink( + EntityType.DASHBOARD_DATA_MODEL, + dashboardDataModelFQN + ), + after, + threadType, + feedFilter, + undefined, + currentUser?.id + ); + setPaging(pagingObj); + setEntityThread((prevData) => [...prevData, ...data]); + } catch (err) { + showErrorToast( + err as AxiosError, + t('server.entity-fetch-error', { + entity: t('label.feed-plural'), + }) + ); + } finally { + setIsEntityThreadLoading(false); + } + }, + [dashboardDataModelFQN] + ); + + const getEntityFeedCount = () => { + getFeedCounts( + EntityType.DASHBOARD_DATA_MODEL, + dashboardDataModelFQN, + setEntityFieldThreadCount, + setEntityFieldTaskCount, + setFeedCount + ); + }; + + const deletePostHandler = ( + threadId: string, + postId: string, + isThread: boolean + ) => { + deletePost(threadId, postId, isThread, setEntityThread); + }; + + const onThreadLinkSelect = (link: string) => { + setThreadLink(link); + }; + + const postFeedHandler = (value: string, id: string) => { + const currentUser = AppState.userDetails?.name ?? AppState.users[0]?.name; + + const data = { + message: value, + from: currentUser, + } as Post; + postFeedById(id, data) + .then((res) => { + if (res) { + const { id, posts } = res; + setEntityThread((pre) => { + return pre.map((thread) => { + if (thread.id === id) { + return { ...res, posts: posts?.slice(-3) }; + } else { + return thread; + } + }); + }); + getEntityFeedCount(); + } else { + throw jsonData['api-error-messages']['unexpected-server-response']; + } + }) + .catch((err: AxiosError) => { + showErrorToast(err, jsonData['api-error-messages']['add-feed-error']); + }); + }; + + const updateThreadHandler = ( + threadId: string, + postId: string, + isThread: boolean, + data: Operation[] + ) => { + updateThreadData(threadId, postId, isThread, data, setEntityThread); + }; + + const handleFeedFilterChange = useCallback( + (feedType, threadType) => { + getFeedData(undefined, feedType, threadType); + }, + [paging] + ); const fetchResourcePermission = async (dashboardDataModelFQN: string) => { setIsLoading(true); try { @@ -178,6 +313,25 @@ const DataModelsPage = () => { } }; + const createThread = (data: CreateThread) => { + postThread(data) + .then((res) => { + if (res) { + setEntityThread((pre) => [...pre, res]); + getEntityFeedCount(); + } else { + showErrorToast( + jsonData['api-error-messages']['unexpected-server-response'] + ); + } + }) + .catch((err: AxiosError) => { + showErrorToast( + err, + jsonData['api-error-messages']['create-conversation-error'] + ); + }); + }; const fetchDataModelDetails = async (dashboardDataModelFQN: string) => { setIsLoading(true); try { @@ -194,10 +348,8 @@ const DataModelsPage = () => { } }; - const handleUpdateDataModelData = (updatedData: DashboardDataModel) => { - const jsonPatch = compare(omitBy(dataModelData, isUndefined), updatedData); - - return patchDataModelDetails(dataModelData?.id ?? '', jsonPatch); + const onThreadPanelClose = () => { + setThreadLink(''); }; const handleTabChange = (tabValue: string) => { @@ -208,6 +360,12 @@ const DataModelsPage = () => { } }; + const handleUpdateDataModelData = (updatedData: DashboardDataModel) => { + const jsonPatch = compare(omitBy(dataModelData, isUndefined), updatedData); + + return patchDataModelDetails(dataModelData?.id ?? '', jsonPatch); + }; + const handleUpdateDescription = async (updatedDescription: string) => { try { const { description: newDescription, version } = @@ -301,6 +459,7 @@ const DataModelsPage = () => { tags: newTags, version, })); + getEntityFeedCount(); } catch (error) { showErrorToast(error as AxiosError); } @@ -319,6 +478,7 @@ const DataModelsPage = () => { owner: newOwner, version, })); + getEntityFeedCount(); } catch (error) { showErrorToast(error as AxiosError); } @@ -347,6 +507,7 @@ const DataModelsPage = () => { tags: newTags, version, })); + getEntityFeedCount(); } } catch (error) { showErrorToast(error as AxiosError); @@ -372,9 +533,16 @@ const DataModelsPage = () => { } }; + useEffect(() => { + if (tab === DATA_MODELS_DETAILS_TABS.ACTIVITY) { + getFeedData(); + } + }, [tab, dashboardDataModelFQN]); + useEffect(() => { if (hasViewPermission) { fetchDataModelDetails(dashboardDataModelFQN); + getEntityFeedCount(); } }, [dashboardDataModelFQN, dataModelPermissions]); @@ -406,6 +574,14 @@ const DataModelsPage = () => { canDelete={dataModelPermissions.Delete} currentOwner={owner} deleted={deleted} + entityFieldTasks={getEntityFieldThreadCounts( + EntityField.TAGS, + entityFieldTaskCount + )} + entityFieldThreads={getEntityFieldThreadCounts( + EntityField.TAGS, + entityFieldThreadCount + )} entityFqn={dashboardDataModelFQN} entityId={entityId} entityName={entityName || ''} @@ -423,7 +599,8 @@ const DataModelsPage = () => { titleLinks={breadcrumbTitles} updateOwner={hasEditOwnerPermission ? handleUpdateOwner : undefined} updateTier={hasEditTierPermission ? handleUpdateTier : undefined} - version={version + ''} + version={toString(version)} + onThreadLinkSelect={onThreadLinkSelect} /> { {t('label.model')} }> - + { + + {t('label.activity-feed-and-task-plural')}{' '} + {getCountBadge( + feedCount, + '', + DATA_MODELS_DETAILS_TABS.ACTIVITY === tab + )} + + }> + + + +
+ +
+ +
+
+
{dataModelData?.sql && ( { {t('label.sql-uppercase')} }> - + {
+ + {threadLink ? ( + + ) : null} ); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/TasksPage.interface.ts b/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/TasksPage.interface.ts index be7ec3445d7..4872fc757d4 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/TasksPage.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TasksPage/TasksPage.interface.ts @@ -11,6 +11,7 @@ * limitations under the License. */ +import { DashboardDataModel } from 'generated/entity/data/dashboardDataModel'; import { DatabaseSchema } from 'generated/entity/data/databaseSchema'; import { Dashboard } from '../../generated/entity/data/dashboard'; import { Mlmodel } from '../../generated/entity/data/mlmodel'; @@ -24,7 +25,8 @@ export type EntityData = | Dashboard | Pipeline | Mlmodel - | DatabaseSchema; + | DatabaseSchema + | DashboardDataModel; export interface Option { label: string; diff --git a/openmetadata-ui/src/main/resources/ui/src/rest/dataModelsAPI.ts b/openmetadata-ui/src/main/resources/ui/src/rest/dataModelsAPI.ts index c749e882cad..e1567077265 100644 --- a/openmetadata-ui/src/main/resources/ui/src/rest/dataModelsAPI.ts +++ b/openmetadata-ui/src/main/resources/ui/src/rest/dataModelsAPI.ts @@ -14,6 +14,7 @@ import { AxiosResponse } from 'axios'; import { Operation } from 'fast-json-patch'; import { DashboardDataModel } from 'generated/entity/data/dashboardDataModel'; import { EntityReference } from 'generated/type/entityReference'; +import { getURLWithQueryFields } from 'utils/APIUtils'; import APIClient from './index'; const URL = '/dashboard/datamodels'; @@ -37,6 +38,20 @@ export const getDataModelsByName = async ( return response.data; }; +export const getDataModelDetailsByFQN = async ( + databaseSchemaName: string, + arrQueryFields?: string | string[] +) => { + const url = `${getURLWithQueryFields( + `/dashboard/datamodels/name/${databaseSchemaName}`, + arrQueryFields + )}`; + + const response = await APIClient.get(url); + + return response.data; +}; + export const patchDataModelDetails = async (id: string, data: Operation[]) => { const response = await APIClient.patch< Operation[], diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/DataModelsUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/DataModelsUtils.ts index 0a6b96c0e8e..e682c6a3014 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/DataModelsUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/DataModelsUtils.ts @@ -15,6 +15,7 @@ import { PLACEHOLDER_ROUTE_TAB, ROUTES, } from 'constants/constants'; +import { TabSpecificField } from 'enums/entity.enum'; import { Column } from 'generated/entity/data/dashboardDataModel'; import { LabelType, State, TagLabel } from 'generated/type/tagLabel'; import { isEmpty } from 'lodash'; @@ -112,3 +113,6 @@ export const updateDataModelColumnTags = ( } }); }; + +export const defaultFields = `${TabSpecificField.TAGS}, ${TabSpecificField.OWNER}, +${TabSpecificField.FOLLOWERS}`; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx index 02f7454c3a1..674e4eb1785 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx @@ -43,6 +43,7 @@ import { getDashboardDetailsPath, getDatabaseDetailsPath, getDatabaseSchemaDetailsPath, + getDataModelDetailsPath, getEditWebhookPath, getMlModelPath, getPipelineDetailsPath, @@ -260,6 +261,9 @@ export const getEntityLink = ( case SearchIndex.TAG: return getTagsDetailsPath(fullyQualifiedName); + case EntityType.DASHBOARD_DATA_MODEL: + return getDataModelDetailsPath(fullyQualifiedName); + case SearchIndex.TABLE: case EntityType.TABLE: default: diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TasksUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/TasksUtils.ts index 5baae88ed85..130118bfb31 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/TasksUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TasksUtils.ts @@ -23,6 +23,7 @@ import { } from 'pages/TasksPage/TasksPage.interface'; import { getDashboardByFqn } from 'rest/dashboardAPI'; import { getDatabaseSchemaDetailsByFQN } from 'rest/databaseAPI'; +import { getDataModelDetailsByFQN } from 'rest/dataModelsAPI'; import { getUserSuggestions } from 'rest/miscAPI'; import { getMlModelByFQN } from 'rest/mlModelAPI'; import { getPipelineByFqn } from 'rest/pipelineAPI'; @@ -44,6 +45,7 @@ import { TaskType } from '../generated/entity/feed/thread'; import { getPartialNameFromTableFQN } from './CommonUtils'; import { defaultFields as DashboardFields } from './DashboardDetailsUtils'; import { defaultFields as DatabaseSchemaFields } from './DatabaseSchemaDetailsUtils'; +import { defaultFields as DataModelFields } from './DataModelsUtils'; import { defaultFields as TableFields } from './DatasetDetailsUtils'; import { getEntityName } from './EntityUtils'; import { defaultFields as MlModelFields } from './MlModelDetailsUtils'; @@ -189,6 +191,7 @@ export const TASK_ENTITIES = [ EntityType.PIPELINE, EntityType.MLMODEL, EntityType.DATABASE_SCHEMA, + EntityType.DASHBOARD_DATA_MODEL, ]; export const getBreadCrumbList = ( @@ -327,6 +330,15 @@ export const fetchEntityDetail = ( break; + case EntityType.DASHBOARD_DATA_MODEL: + getDataModelDetailsByFQN(entityFQN, DataModelFields) + .then((res) => { + setEntityData(res); + }) + .catch((err: AxiosError) => showErrorToast(err)); + + break; + default: break; }