mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-02 03:29:03 +00:00
Fixed: Fixed service and services page issue and other miner fixes (#5669)
* Fixed service and services page issue and other miner fixes * fixed failing unit test
This commit is contained in:
parent
3a1dfbdbcb
commit
9b588c998a
@ -1280,60 +1280,56 @@ const Entitylineage: FunctionComponent<EntityLineageProp> = ({
|
|||||||
}
|
}
|
||||||
}, [entityLineage]);
|
}, [entityLineage]);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading || (nodes.length === 0 && !deleted)) {
|
||||||
return <Loader />;
|
return <Loader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return deleted ? (
|
return deleted ? (
|
||||||
getDeletedLineagePlaceholder()
|
getDeletedLineagePlaceholder()
|
||||||
) : (
|
) : (
|
||||||
<Fragment>
|
<div
|
||||||
<div
|
className={classNames('tw-relative tw-h-full tw--ml-4 tw--mr-7 tw--mt-4')}
|
||||||
className={classNames(
|
data-testid="lineage-container">
|
||||||
'tw-relative tw-h-full tw--ml-4 tw--mr-7 tw--mt-4'
|
<div className="tw-w-full tw-h-full" ref={reactFlowWrapper}>
|
||||||
)}
|
<ReactFlowProvider>
|
||||||
data-testid="lineage-container">
|
<ReactFlow
|
||||||
<div className="tw-w-full tw-h-full" ref={reactFlowWrapper}>
|
data-testid="react-flow-component"
|
||||||
<ReactFlowProvider>
|
edgeTypes={{ buttonedge: CustomEdge }}
|
||||||
<ReactFlow
|
edges={edges}
|
||||||
data-testid="react-flow-component"
|
maxZoom={2}
|
||||||
edgeTypes={{ buttonedge: CustomEdge }}
|
minZoom={0.5}
|
||||||
edges={edges}
|
nodeTypes={nodeTypes}
|
||||||
maxZoom={2}
|
nodes={nodes}
|
||||||
minZoom={0.5}
|
nodesConnectable={isEditMode}
|
||||||
nodeTypes={nodeTypes}
|
selectNodesOnDrag={false}
|
||||||
nodes={nodes}
|
zoomOnDoubleClick={false}
|
||||||
nodesConnectable={isEditMode}
|
zoomOnScroll={false}
|
||||||
selectNodesOnDrag={false}
|
onConnect={onConnect}
|
||||||
zoomOnDoubleClick={false}
|
onDragOver={onDragOver}
|
||||||
zoomOnScroll={false}
|
onDrop={onDrop}
|
||||||
onConnect={onConnect}
|
onEdgesChange={onEdgesChange}
|
||||||
onDragOver={onDragOver}
|
onInit={(reactFlowInstance: ReactFlowInstance) => {
|
||||||
onDrop={onDrop}
|
onLoad(reactFlowInstance, nodes.length);
|
||||||
onEdgesChange={onEdgesChange}
|
setReactFlowInstance(reactFlowInstance);
|
||||||
onInit={(reactFlowInstance: ReactFlowInstance) => {
|
}}
|
||||||
onLoad(reactFlowInstance, nodes.length);
|
onNodeClick={(_e, node) => onNodeClick(node)}
|
||||||
setReactFlowInstance(reactFlowInstance);
|
onNodeContextMenu={onNodeContextMenu}
|
||||||
}}
|
onNodeDrag={dragHandle}
|
||||||
onNodeClick={(_e, node) => onNodeClick(node)}
|
onNodeDragStart={dragHandle}
|
||||||
onNodeContextMenu={onNodeContextMenu}
|
onNodeDragStop={dragHandle}
|
||||||
onNodeDrag={dragHandle}
|
onNodeMouseEnter={onNodeMouseEnter}
|
||||||
onNodeDragStart={dragHandle}
|
onNodeMouseLeave={onNodeMouseLeave}
|
||||||
onNodeDragStop={dragHandle}
|
onNodeMouseMove={onNodeMouseMove}
|
||||||
onNodeMouseEnter={onNodeMouseEnter}
|
onNodesChange={onNodesChange}>
|
||||||
onNodeMouseLeave={onNodeMouseLeave}
|
{getCustomControlElements()}
|
||||||
onNodeMouseMove={onNodeMouseMove}
|
{getGraphBackGround()}
|
||||||
onNodesChange={onNodesChange}>
|
</ReactFlow>
|
||||||
{getCustomControlElements()}
|
</ReactFlowProvider>
|
||||||
{getGraphBackGround()}
|
|
||||||
</ReactFlow>
|
|
||||||
</ReactFlowProvider>
|
|
||||||
</div>
|
|
||||||
{getEntityDrawer()}
|
|
||||||
<EntityLineageSidebar newAddedNode={newAddedNode} show={isEditMode} />
|
|
||||||
{getConfirmationModal()}
|
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
{getEntityDrawer()}
|
||||||
|
<EntityLineageSidebar newAddedNode={newAddedNode} show={isEditMode} />
|
||||||
|
{getConfirmationModal()}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -127,6 +127,29 @@ const mockEntityLineageProp = {
|
|||||||
entityLineageHandler: jest.fn(),
|
entityLineageHandler: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mockFlowData = {
|
||||||
|
node: [
|
||||||
|
{
|
||||||
|
id: 'a4b21449-b03b-4527-b482-148f52f92ff2',
|
||||||
|
sourcePosition: 'right',
|
||||||
|
targetPosition: 'left',
|
||||||
|
type: 'default',
|
||||||
|
className: 'leaf-node core',
|
||||||
|
data: {
|
||||||
|
label: 'dim_address etl',
|
||||||
|
isEditMode: false,
|
||||||
|
columns: {},
|
||||||
|
isExpanded: false,
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
edge: [],
|
||||||
|
};
|
||||||
|
|
||||||
jest.mock('../../utils/EntityLineageUtils', () => ({
|
jest.mock('../../utils/EntityLineageUtils', () => ({
|
||||||
dragHandle: jest.fn(),
|
dragHandle: jest.fn(),
|
||||||
getDataLabel: jest
|
getDataLabel: jest
|
||||||
@ -138,8 +161,8 @@ jest.mock('../../utils/EntityLineageUtils', () => ({
|
|||||||
<p>Lineage data is not available for deleted entities.</p>
|
<p>Lineage data is not available for deleted entities.</p>
|
||||||
),
|
),
|
||||||
getHeaderLabel: jest.fn().mockReturnValue(<p>Header label</p>),
|
getHeaderLabel: jest.fn().mockReturnValue(<p>Header label</p>),
|
||||||
getLayoutedElementsV1: jest.fn().mockReturnValue([]),
|
getLayoutedElementsV1: jest.fn().mockImplementation(() => mockFlowData),
|
||||||
getLineageDataV1: jest.fn().mockReturnValue([]),
|
getLineageDataV1: jest.fn().mockImplementation(() => mockFlowData),
|
||||||
getModalBodyText: jest.fn(),
|
getModalBodyText: jest.fn(),
|
||||||
onLoad: jest.fn(),
|
onLoad: jest.fn(),
|
||||||
onNodeContextMenu: jest.fn(),
|
onNodeContextMenu: jest.fn(),
|
||||||
|
|||||||
@ -66,6 +66,10 @@ const ServiceConfig = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
history.goBack();
|
||||||
|
};
|
||||||
|
|
||||||
const getDynamicFields = () => {
|
const getDynamicFields = () => {
|
||||||
return (
|
return (
|
||||||
<ConnectionConfigForm
|
<ConnectionConfigForm
|
||||||
@ -79,6 +83,7 @@ const ServiceConfig = ({
|
|||||||
serviceCategory={serviceCategory}
|
serviceCategory={serviceCategory}
|
||||||
serviceType={serviceType}
|
serviceType={serviceType}
|
||||||
status={status}
|
status={status}
|
||||||
|
onCancel={onCancel}
|
||||||
onSave={handleOnSaveClick}
|
onSave={handleOnSaveClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -606,9 +606,7 @@ const TeamDetails = ({
|
|||||||
blurWithBodyBG
|
blurWithBodyBG
|
||||||
description={currentTeam?.description || ''}
|
description={currentTeam?.description || ''}
|
||||||
entityName={currentTeam?.displayName ?? currentTeam?.name}
|
entityName={currentTeam?.displayName ?? currentTeam?.name}
|
||||||
hasEditAccess={isActionAllowed(
|
hasEditAccess={isOwner()}
|
||||||
userPermissions[Operation.UpdateDescription]
|
|
||||||
)}
|
|
||||||
isEdit={isDescriptionEditable}
|
isEdit={isDescriptionEditable}
|
||||||
onCancel={() => descriptionHandler(false)}
|
onCancel={() => descriptionHandler(false)}
|
||||||
onDescriptionEdit={() => descriptionHandler(true)}
|
onDescriptionEdit={() => descriptionHandler(true)}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import { EntityFieldThreads } from 'Models';
|
|||||||
import React, { FC, Fragment } from 'react';
|
import React, { FC, Fragment } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { useAuthContext } from '../../../authentication/auth-provider/AuthProvider';
|
import { useAuthContext } from '../../../authentication/auth-provider/AuthProvider';
|
||||||
|
import { TITLE_FOR_UPDATE_DESCRIPTION } from '../../../constants/constants';
|
||||||
import { EntityType } from '../../../enums/entity.enum';
|
import { EntityType } from '../../../enums/entity.enum';
|
||||||
import { Operation } from '../../../generated/entity/policies/accessControl/rule';
|
import { Operation } from '../../../generated/entity/policies/accessControl/rule';
|
||||||
import { useAuth } from '../../../hooks/authHooks';
|
import { useAuth } from '../../../hooks/authHooks';
|
||||||
@ -28,6 +29,7 @@ import {
|
|||||||
TASK_ENTITIES,
|
TASK_ENTITIES,
|
||||||
} from '../../../utils/TasksUtils';
|
} from '../../../utils/TasksUtils';
|
||||||
import { ModalWithMarkdownEditor } from '../../Modals/ModalWithMarkdownEditor/ModalWithMarkdownEditor';
|
import { ModalWithMarkdownEditor } from '../../Modals/ModalWithMarkdownEditor/ModalWithMarkdownEditor';
|
||||||
|
import NonAdminAction from '../non-admin-action/NonAdminAction';
|
||||||
import PopOver from '../popover/PopOver';
|
import PopOver from '../popover/PopOver';
|
||||||
import RichTextEditorPreviewer from '../rich-text-editor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../rich-text-editor/RichTextEditorPreviewer';
|
||||||
import { DescriptionProps } from './Description.interface';
|
import { DescriptionProps } from './Description.interface';
|
||||||
@ -68,16 +70,22 @@ const Description: FC<DescriptionProps> = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const checkPermission = () => {
|
||||||
|
if (!isAuthDisabled && !isAdminUser) {
|
||||||
|
if (!isUndefined(hasEditAccess)) {
|
||||||
|
return Boolean(hasEditAccess);
|
||||||
|
} else {
|
||||||
|
return userPermissions[Operation.UpdateDescription];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
const handleUpdate = () => {
|
const handleUpdate = () => {
|
||||||
const check =
|
if (checkPermission()) {
|
||||||
isAdminUser ||
|
|
||||||
hasEditAccess ||
|
|
||||||
isAuthDisabled ||
|
|
||||||
userPermissions[Operation.UpdateDescription] ||
|
|
||||||
!TASK_ENTITIES.includes(entityType as EntityType);
|
|
||||||
if (check) {
|
|
||||||
onDescriptionEdit && onDescriptionEdit();
|
onDescriptionEdit && onDescriptionEdit();
|
||||||
} else {
|
} else if (TASK_ENTITIES.includes(entityType as EntityType)) {
|
||||||
handleUpdateDescription();
|
handleUpdateDescription();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -151,12 +159,19 @@ const Description: FC<DescriptionProps> = ({
|
|||||||
'tw-w-5 tw-min-w-max tw-flex',
|
'tw-w-5 tw-min-w-max tw-flex',
|
||||||
description?.trim() ? 'tw-pl-1' : ''
|
description?.trim() ? 'tw-pl-1' : ''
|
||||||
)}>
|
)}>
|
||||||
<button
|
<NonAdminAction
|
||||||
className="focus:tw-outline-none tw-self-baseline"
|
isOwner={
|
||||||
data-testid="edit-description"
|
checkPermission() ||
|
||||||
onClick={handleUpdate}>
|
TASK_ENTITIES.includes(entityType as EntityType)
|
||||||
<SVGIcons alt="edit" icon="icon-edit" title="Edit" width="16px" />
|
}
|
||||||
</button>
|
title={TITLE_FOR_UPDATE_DESCRIPTION}>
|
||||||
|
<button
|
||||||
|
className="focus:tw-outline-none tw-self-baseline"
|
||||||
|
data-testid="edit-description"
|
||||||
|
onClick={handleUpdate}>
|
||||||
|
<SVGIcons alt="edit" icon="icon-edit" title="Edit" width="16px" />
|
||||||
|
</button>
|
||||||
|
</NonAdminAction>
|
||||||
|
|
||||||
<RequestDescriptionEl descriptionThread={thread} />
|
<RequestDescriptionEl descriptionThread={thread} />
|
||||||
<DescriptionThreadEl descriptionThread={thread} />
|
<DescriptionThreadEl descriptionThread={thread} />
|
||||||
|
|||||||
@ -83,7 +83,7 @@ const TitleBreadcrumb: FunctionComponent<TitleBreadcrumbProps> = ({
|
|||||||
className={classes}
|
className={classes}
|
||||||
style={{
|
style={{
|
||||||
maxWidth,
|
maxWidth,
|
||||||
fontSize: '14px',
|
fontSize: '16px',
|
||||||
}}
|
}}
|
||||||
to={link.url}>
|
to={link.url}>
|
||||||
{link.name}
|
{link.name}
|
||||||
|
|||||||
@ -433,6 +433,9 @@ export const TITLE_FOR_NON_ADMIN_ACTION =
|
|||||||
export const TITLE_FOR_UPDATE_OWNER =
|
export const TITLE_FOR_UPDATE_OWNER =
|
||||||
'You do not have permissions to update the owner.';
|
'You do not have permissions to update the owner.';
|
||||||
|
|
||||||
|
export const TITLE_FOR_UPDATE_DESCRIPTION =
|
||||||
|
'You do not have permissions to update the description.';
|
||||||
|
|
||||||
export const configOptions = {
|
export const configOptions = {
|
||||||
headers: { 'Content-type': 'application/json-patch+json' },
|
headers: { 'Content-type': 'application/json-patch+json' },
|
||||||
};
|
};
|
||||||
|
|||||||
@ -175,6 +175,7 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
isProtected: !isAdminUser && !isAuthDisabled,
|
isProtected: !isAdminUser && !isAuthDisabled,
|
||||||
|
isHidden: !isAdminUser && !isAuthDisabled,
|
||||||
position: 3,
|
position: 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -925,6 +926,7 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
entityFqn={serviceFQN}
|
entityFqn={serviceFQN}
|
||||||
entityName={serviceFQN}
|
entityName={serviceFQN}
|
||||||
entityType={serviceCategory.slice(0, -1)}
|
entityType={serviceCategory.slice(0, -1)}
|
||||||
|
hasEditAccess={isAdminUser || isAuthDisabled}
|
||||||
isEdit={isEdit}
|
isEdit={isEdit}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
onDescriptionEdit={onDescriptionEdit}
|
onDescriptionEdit={onDescriptionEdit}
|
||||||
@ -1033,7 +1035,7 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<ServiceConnectionDetails
|
<ServiceConnectionDetails
|
||||||
connectionDetails={connectionDetails as ConfigData}
|
connectionDetails={connectionDetails || {}}
|
||||||
serviceCategory={serviceCategory}
|
serviceCategory={serviceCategory}
|
||||||
serviceFQN={serviceDetails?.serviceType || ''}
|
serviceFQN={serviceDetails?.serviceType || ''}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -307,7 +307,7 @@ const ServicesPage = () => {
|
|||||||
<span
|
<span
|
||||||
className=" tw-ml-1 tw-font-normal tw-text-grey-body"
|
className=" tw-ml-1 tw-font-normal tw-text-grey-body"
|
||||||
data-testid="dashboard-url">
|
data-testid="dashboard-url">
|
||||||
{getDashboardURL(dashboardService.connection.config)}
|
{getDashboardURL(dashboardService.connection?.config)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@ -323,7 +323,7 @@ const ServicesPage = () => {
|
|||||||
<span
|
<span
|
||||||
className=" tw-ml-1 tw-font-normal tw-text-grey-body"
|
className=" tw-ml-1 tw-font-normal tw-text-grey-body"
|
||||||
data-testid="pipeline-url">
|
data-testid="pipeline-url">
|
||||||
{pipelineService.connection.config?.hostPort}
|
{pipelineService.connection?.config?.hostPort || '--'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@ -340,7 +340,7 @@ const ServicesPage = () => {
|
|||||||
<span
|
<span
|
||||||
className=" tw-ml-1 tw-font-normal tw-text-grey-body"
|
className=" tw-ml-1 tw-font-normal tw-text-grey-body"
|
||||||
data-testid="pipeline-url">
|
data-testid="pipeline-url">
|
||||||
{mlmodel.connection.config?.registryUri}
|
{mlmodel.connection?.config?.registryUri || '--'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="tw-mb-1 tw-truncate" data-testid="additional-field">
|
<div className="tw-mb-1 tw-truncate" data-testid="additional-field">
|
||||||
@ -348,7 +348,7 @@ const ServicesPage = () => {
|
|||||||
<span
|
<span
|
||||||
className=" tw-ml-1 tw-font-normal tw-text-grey-body"
|
className=" tw-ml-1 tw-font-normal tw-text-grey-body"
|
||||||
data-testid="pipeline-url">
|
data-testid="pipeline-url">
|
||||||
{mlmodel.connection.config?.trackingUri}
|
{mlmodel.connection?.config?.trackingUri || '--'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@ -508,7 +508,7 @@ const ServicesPage = () => {
|
|||||||
<p className="tw-text-lg tw-text-center">
|
<p className="tw-text-lg tw-text-center">
|
||||||
{noServicesText(searchText)}
|
{noServicesText(searchText)}
|
||||||
</p>
|
</p>
|
||||||
<p className="tw-text-lg tw-text-center">
|
<div className="tw-text-lg tw-text-center">
|
||||||
<NonAdminAction
|
<NonAdminAction
|
||||||
position="bottom"
|
position="bottom"
|
||||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||||
@ -522,7 +522,7 @@ const ServicesPage = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</NonAdminAction>{' '}
|
</NonAdminAction>{' '}
|
||||||
to add new {servicesDisplayName[serviceName]}
|
to add new {servicesDisplayName[serviceName]}
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user