mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-27 18:36:08 +00:00
* 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 <nahuel@getcollate.io>
This commit is contained in:
parent
27984c25f3
commit
c997d8c80b
@ -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<Column> 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<TagLabel> 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<TagLabel> 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);
|
||||
|
@ -549,20 +549,6 @@
|
||||
"EditDescription"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dataModel",
|
||||
"operations": [
|
||||
"Create",
|
||||
"Delete",
|
||||
"ViewAll",
|
||||
"EditAll",
|
||||
"EditDescription",
|
||||
"EditDisplayName",
|
||||
"EditTags",
|
||||
"EditOwner",
|
||||
"EditLineage"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dashboardDataModel",
|
||||
"operations": [
|
||||
|
@ -33,6 +33,7 @@ ENTITY_TYPE
|
||||
| 'testDefinition'
|
||||
| 'testSuite'
|
||||
| 'testCase'
|
||||
| 'dashboardDataModel'
|
||||
;
|
||||
ENTITY_FIELD
|
||||
: 'columns'
|
||||
|
@ -51,6 +51,7 @@ export enum AssetsType {
|
||||
DASHBOARD = 'dashboard',
|
||||
PIPELINE = 'pipeline',
|
||||
MLMODEL = 'mlmodel',
|
||||
DASHBOARD_DATA_MODEL = 'dashboardDataModel',
|
||||
}
|
||||
|
||||
export enum ChangeType {
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -298,6 +298,7 @@
|
||||
"feature-plural-used": "使用される機能",
|
||||
"february": "2月",
|
||||
"feed-lowercase": "フィード",
|
||||
"feed-plural": "Feeds",
|
||||
"field-change": "フィールドを変更",
|
||||
"field-invalid": "{{field}}は不正です",
|
||||
"field-plural": "フィールド",
|
||||
|
@ -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",
|
||||
|
@ -298,6 +298,7 @@
|
||||
"feature-plural-used": "Features Used",
|
||||
"february": "February",
|
||||
"feed-lowercase": "feed",
|
||||
"feed-plural": "Feeds",
|
||||
"field-change": "域变动",
|
||||
"field-invalid": "{{field}} 无效",
|
||||
"field-plural": "域",
|
||||
|
@ -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<OperationPermission>(DEFAULT_ENTITY_PERMISSION);
|
||||
const [dataModelData, setDataModelData] = useState<DashboardDataModel>();
|
||||
|
||||
const [threadLink, setThreadLink] = useState<string>('');
|
||||
const [entityThread, setEntityThread] = useState<Thread[]>([]);
|
||||
const [isEntityThreadLoading, setIsEntityThreadLoading] =
|
||||
useState<boolean>(false);
|
||||
const [paging, setPaging] = useState<Paging>({} as Paging);
|
||||
|
||||
const [feedCount, setFeedCount] = useState<number>(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}
|
||||
/>
|
||||
<Tabs activeKey={tab} className="h-full" onChange={handleTabChange}>
|
||||
<Tabs.TabPane
|
||||
@ -433,7 +610,7 @@ const DataModelsPage = () => {
|
||||
{t('label.model')}
|
||||
</span>
|
||||
}>
|
||||
<Card className={ENTITY_CARD_CLASS}>
|
||||
<Card className="h-full">
|
||||
<Space className="w-full" direction="vertical" size={8}>
|
||||
<Description
|
||||
description={description}
|
||||
@ -460,6 +637,38 @@ const DataModelsPage = () => {
|
||||
</Card>
|
||||
</Tabs.TabPane>
|
||||
|
||||
<Tabs.TabPane
|
||||
key={DATA_MODELS_DETAILS_TABS.ACTIVITY}
|
||||
tab={
|
||||
<span data-testid={DATA_MODELS_DETAILS_TABS.ACTIVITY}>
|
||||
{t('label.activity-feed-and-task-plural')}{' '}
|
||||
{getCountBadge(
|
||||
feedCount,
|
||||
'',
|
||||
DATA_MODELS_DETAILS_TABS.ACTIVITY === tab
|
||||
)}
|
||||
</span>
|
||||
}>
|
||||
<Card className="m-y-md">
|
||||
<Row justify="center">
|
||||
<Col span={18}>
|
||||
<div id="activityfeed">
|
||||
<ActivityFeedList
|
||||
isEntityFeed
|
||||
withSidePanel
|
||||
deletePostHandler={deletePostHandler}
|
||||
entityName={entityName}
|
||||
feedList={entityThread}
|
||||
isFeedLoading={isEntityThreadLoading}
|
||||
postFeedHandler={postFeedHandler}
|
||||
updateThreadHandler={updateThreadHandler}
|
||||
onFeedFiltersUpdate={handleFeedFilterChange}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
</Tabs.TabPane>
|
||||
{dataModelData?.sql && (
|
||||
<Tabs.TabPane
|
||||
key={DATA_MODELS_DETAILS_TABS.SQL}
|
||||
@ -468,7 +677,7 @@ const DataModelsPage = () => {
|
||||
{t('label.sql-uppercase')}
|
||||
</span>
|
||||
}>
|
||||
<Card className={ENTITY_CARD_CLASS}>
|
||||
<Card className="h-full">
|
||||
<SchemaEditor
|
||||
editorClass="custom-code-mirror-theme full-screen-editor-height"
|
||||
mode={{ name: CSMode.SQL }}
|
||||
@ -500,6 +709,18 @@ const DataModelsPage = () => {
|
||||
</Card>
|
||||
</Tabs.TabPane>
|
||||
</Tabs>
|
||||
|
||||
{threadLink ? (
|
||||
<ActivityThreadPanel
|
||||
createThread={createThread}
|
||||
deletePostHandler={deletePostHandler}
|
||||
open={Boolean(threadLink)}
|
||||
postFeedHandler={postFeedHandler}
|
||||
threadLink={threadLink}
|
||||
updateThreadHandler={updateThreadHandler}
|
||||
onCancel={onThreadPanelClose}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</PageContainerV1>
|
||||
);
|
||||
|
@ -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;
|
||||
|
@ -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<DashboardDataModel>(url);
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const patchDataModelDetails = async (id: string, data: Operation[]) => {
|
||||
const response = await APIClient.patch<
|
||||
Operation[],
|
||||
|
@ -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}`;
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user