mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-31 04:14:34 +00:00
fix(ui): fix the errorPlaceholder visible when component is in loading state (#11387)
* fix the errorPlaceholder visible when component is in loading state * changes as per commets
This commit is contained in:
parent
f374bb38b4
commit
f2a62dd60f
@ -11,6 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
@ -21,6 +22,8 @@ import {
|
|||||||
Typography,
|
Typography,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
|
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||||
|
import { ERROR_PLACEHOLDER_TYPE, SIZE } from 'enums/common.enum';
|
||||||
import { isEmpty, isUndefined } from 'lodash';
|
import { isEmpty, isUndefined } from 'lodash';
|
||||||
import React, { FC, useEffect, useMemo, useState } from 'react';
|
import React, { FC, useEffect, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -276,27 +279,27 @@ const KPIChart: FC<Props> = ({ chartFilter, kpiList }) => {
|
|||||||
<Space
|
<Space
|
||||||
className="w-full justify-center items-center"
|
className="w-full justify-center items-center"
|
||||||
direction="vertical">
|
direction="vertical">
|
||||||
<Typography.Text>
|
<ErrorPlaceHolder
|
||||||
{t('message.no-kpi-available-add-new-one')}
|
button={
|
||||||
</Typography.Text>
|
<AntdTooltip
|
||||||
<AntdTooltip
|
title={!isAdminUser && t('message.no-permission-for-action')}>
|
||||||
title={
|
<Button
|
||||||
isAdminUser
|
ghost
|
||||||
? t('label.add-entity', {
|
icon={<PlusOutlined />}
|
||||||
|
type="primary"
|
||||||
|
onClick={handleAddKpi}>
|
||||||
|
{t('label.add-entity', {
|
||||||
entity: t('label.kpi-uppercase'),
|
entity: t('label.kpi-uppercase'),
|
||||||
})
|
})}
|
||||||
: t('message.no-permission-for-action')
|
</Button>
|
||||||
}>
|
</AntdTooltip>
|
||||||
<Button
|
}
|
||||||
className="tw-border-primary tw-text-primary"
|
className="p-y-lg"
|
||||||
disabled={!isAdminUser}
|
permission={isAdminUser}
|
||||||
type="default"
|
size={SIZE.MEDIUM}
|
||||||
onClick={handleAddKpi}>
|
type={ERROR_PLACEHOLDER_TYPE.ASSIGN}>
|
||||||
{t('label.add-entity', {
|
{t('message.no-kpi-available-add-new-one')}
|
||||||
entity: t('label.kpi-uppercase'),
|
</ErrorPlaceHolder>
|
||||||
})}
|
|
||||||
</Button>
|
|
||||||
</AntdTooltip>
|
|
||||||
</Space>
|
</Space>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -11,11 +11,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CheckOutlined } from '@ant-design/icons';
|
import { CheckOutlined, PlusOutlined } from '@ant-design/icons';
|
||||||
import { Button, Col, Popover, Row, Table, Tooltip } from 'antd';
|
import { Button, Col, Popover, Row, Table, Tooltip } from 'antd';
|
||||||
import { ColumnsType } from 'antd/lib/table';
|
import { ColumnsType } from 'antd/lib/table';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
|
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||||
import cronstrue from 'cronstrue';
|
import cronstrue from 'cronstrue';
|
||||||
|
import { ERROR_PLACEHOLDER_TYPE } from 'enums/common.enum';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
import React, { Fragment, useEffect, useMemo, useState } from 'react';
|
import React, { Fragment, useEffect, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useHistory, useLocation, useParams } from 'react-router-dom';
|
import { useHistory, useLocation, useParams } from 'react-router-dom';
|
||||||
@ -550,13 +553,44 @@ const TestSuitePipelineTab = () => {
|
|||||||
currTriggerId,
|
currTriggerId,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const errorPlaceholder = useMemo(
|
||||||
|
() => (
|
||||||
|
<ErrorPlaceHolder
|
||||||
|
button={
|
||||||
|
<Button
|
||||||
|
ghost
|
||||||
|
className="p-x-lg"
|
||||||
|
data-testid="add-placeholder-button"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
history.push(getTestSuiteIngestionPath(testSuiteFQN));
|
||||||
|
}}>
|
||||||
|
{t('label.add')}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
className="mt-24"
|
||||||
|
heading={t('label.pipeline')}
|
||||||
|
permission={createPermission}
|
||||||
|
type={ERROR_PLACEHOLDER_TYPE.ASSIGN}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[testSuiteFQN]
|
||||||
|
);
|
||||||
|
|
||||||
if (isLoading || isFetchingStatus) {
|
if (isLoading || isFetchingStatus) {
|
||||||
return <Loader />;
|
return <Loader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !isAirflowAvailable ? (
|
if (!isAirflowAvailable) {
|
||||||
<ErrorPlaceHolderIngestion />
|
return <ErrorPlaceHolderIngestion />;
|
||||||
) : (
|
}
|
||||||
|
|
||||||
|
if (isEmpty(testSuitePipelines)) {
|
||||||
|
return errorPlaceholder;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
<TestCaseCommonTabContainer
|
<TestCaseCommonTabContainer
|
||||||
buttonName={t('label.add-entity', {
|
buttonName={t('label.add-entity', {
|
||||||
entity: t('label.ingestion'),
|
entity: t('label.ingestion'),
|
||||||
|
@ -159,7 +159,7 @@ const AlertsPage = () => {
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isEmpty(alerts)) {
|
if (isEmpty(alerts) && !loading) {
|
||||||
return (
|
return (
|
||||||
<ErrorPlaceHolder
|
<ErrorPlaceHolder
|
||||||
permission
|
permission
|
||||||
@ -200,7 +200,7 @@ const AlertsPage = () => {
|
|||||||
bordered
|
bordered
|
||||||
columns={columns}
|
columns={columns}
|
||||||
dataSource={alerts}
|
dataSource={alerts}
|
||||||
loading={{ spinning: loading, indicator: <Loader /> }}
|
loading={{ spinning: loading, indicator: <Loader size="small" /> }}
|
||||||
pagination={false}
|
pagination={false}
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
size="middle"
|
size="middle"
|
||||||
|
@ -188,7 +188,7 @@ const KPIList = () => {
|
|||||||
|
|
||||||
if (isEmpty(kpiList)) {
|
if (isEmpty(kpiList)) {
|
||||||
return (
|
return (
|
||||||
<div className="mt-24 w-full">
|
<div className="m-t-lg w-full">
|
||||||
<EmptyGraphPlaceholder />
|
<EmptyGraphPlaceholder />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -331,6 +331,7 @@ const DatabaseSchemaPage: FunctionComponent = () => {
|
|||||||
entity: t('label.database-schema'),
|
entity: t('label.database-schema'),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
setError(errMsg);
|
setError(errMsg);
|
||||||
showErrorToast(errMsg);
|
showErrorToast(errMsg);
|
||||||
})
|
})
|
||||||
@ -638,7 +639,7 @@ const DatabaseSchemaPage: FunctionComponent = () => {
|
|||||||
const getSchemaTableList = () => {
|
const getSchemaTableList = () => {
|
||||||
return (
|
return (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
{isEmpty(tableData) && !showDeletedTables ? (
|
{isEmpty(tableData) && !showDeletedTables && !tableDataLoading ? (
|
||||||
<ErrorPlaceHolder
|
<ErrorPlaceHolder
|
||||||
className="mt-0-important"
|
className="mt-0-important"
|
||||||
type={ERROR_PLACEHOLDER_TYPE.NO_DATA}
|
type={ERROR_PLACEHOLDER_TYPE.NO_DATA}
|
||||||
@ -650,10 +651,6 @@ const DatabaseSchemaPage: FunctionComponent = () => {
|
|||||||
columns={tableColumn}
|
columns={tableColumn}
|
||||||
data-testid="databaseSchema-tables"
|
data-testid="databaseSchema-tables"
|
||||||
dataSource={tableData}
|
dataSource={tableData}
|
||||||
loading={{
|
|
||||||
spinning: tableDataLoading,
|
|
||||||
indicator: <Loader size="small" />,
|
|
||||||
}}
|
|
||||||
locale={{
|
locale={{
|
||||||
emptyText: <FilterTablePlaceHolder />,
|
emptyText: <FilterTablePlaceHolder />,
|
||||||
}}
|
}}
|
||||||
@ -786,162 +783,168 @@ const DatabaseSchemaPage: FunctionComponent = () => {
|
|||||||
appState.inPageSearchText = '';
|
appState.inPageSearchText = '';
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <Loader />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<ErrorPlaceHolder>
|
||||||
|
<p data-testid="error-message">{error}</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{isLoading ? (
|
{databaseSchemaPermission.ViewAll ||
|
||||||
<Loader />
|
databaseSchemaPermission.ViewBasic ? (
|
||||||
) : error ? (
|
<PageContainerV1>
|
||||||
<ErrorPlaceHolder>
|
<PageLayoutV1
|
||||||
<p data-testid="error-message">{error}</p>
|
pageTitle={t('label.entity-detail-plural', {
|
||||||
</ErrorPlaceHolder>
|
entity: getEntityName(databaseSchema),
|
||||||
) : (
|
})}>
|
||||||
<>
|
{IsSchemaDetailsLoading ? (
|
||||||
{databaseSchemaPermission.ViewAll ||
|
<Skeleton
|
||||||
databaseSchemaPermission.ViewBasic ? (
|
active
|
||||||
<PageContainerV1>
|
paragraph={{
|
||||||
<PageLayoutV1
|
rows: 3,
|
||||||
pageTitle={t('label.entity-detail-plural', {
|
width: ['20%', '80%', '60%'],
|
||||||
entity: getEntityName(databaseSchema),
|
}}
|
||||||
})}>
|
/>
|
||||||
{IsSchemaDetailsLoading ? (
|
) : (
|
||||||
<Skeleton
|
<>
|
||||||
active
|
<Col span={24}>
|
||||||
paragraph={{
|
<EntityPageInfo
|
||||||
rows: 3,
|
isRecursiveDelete
|
||||||
width: ['20%', '80%', '60%'],
|
canDelete={databaseSchemaPermission.Delete}
|
||||||
}}
|
currentOwner={databaseSchema?.owner}
|
||||||
|
deleted={databaseSchema?.deleted}
|
||||||
|
entityFieldThreads={getEntityFieldThreadCounts(
|
||||||
|
EntityField.TAGS,
|
||||||
|
entityFieldThreadCount
|
||||||
|
)}
|
||||||
|
entityFqn={databaseSchemaFQN}
|
||||||
|
entityId={databaseSchemaId}
|
||||||
|
entityName={databaseSchemaName}
|
||||||
|
entityType={EntityType.DATABASE_SCHEMA}
|
||||||
|
extraDropdownContent={extraDropdownContent}
|
||||||
|
extraInfo={extraInfo}
|
||||||
|
followersList={[]}
|
||||||
|
isTagEditable={
|
||||||
|
databaseSchemaPermission.EditAll ||
|
||||||
|
databaseSchemaPermission.EditTags
|
||||||
|
}
|
||||||
|
serviceType={databaseSchema?.serviceType ?? ''}
|
||||||
|
tags={tags}
|
||||||
|
tagsHandler={onTagUpdate}
|
||||||
|
tier={tier}
|
||||||
|
titleLinks={slashedTableName}
|
||||||
|
updateOwner={
|
||||||
|
databaseSchemaPermission.EditOwner ||
|
||||||
|
databaseSchemaPermission.EditAll
|
||||||
|
? handleUpdateOwner
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
onRestoreEntity={handleRestoreDatabaseSchema}
|
||||||
|
onThreadLinkSelect={onThreadLinkSelect}
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Col span={24}>
|
|
||||||
<EntityPageInfo
|
|
||||||
isRecursiveDelete
|
|
||||||
canDelete={databaseSchemaPermission.Delete}
|
|
||||||
currentOwner={databaseSchema?.owner}
|
|
||||||
deleted={databaseSchema?.deleted}
|
|
||||||
entityFieldThreads={getEntityFieldThreadCounts(
|
|
||||||
EntityField.TAGS,
|
|
||||||
entityFieldThreadCount
|
|
||||||
)}
|
|
||||||
entityFqn={databaseSchemaFQN}
|
|
||||||
entityId={databaseSchemaId}
|
|
||||||
entityName={databaseSchemaName}
|
|
||||||
entityType={EntityType.DATABASE_SCHEMA}
|
|
||||||
extraDropdownContent={extraDropdownContent}
|
|
||||||
extraInfo={extraInfo}
|
|
||||||
followersList={[]}
|
|
||||||
isTagEditable={
|
|
||||||
databaseSchemaPermission.EditAll ||
|
|
||||||
databaseSchemaPermission.EditTags
|
|
||||||
}
|
|
||||||
serviceType={databaseSchema?.serviceType ?? ''}
|
|
||||||
tags={tags}
|
|
||||||
tagsHandler={onTagUpdate}
|
|
||||||
tier={tier}
|
|
||||||
titleLinks={slashedTableName}
|
|
||||||
updateOwner={
|
|
||||||
databaseSchemaPermission.EditOwner ||
|
|
||||||
databaseSchemaPermission.EditAll
|
|
||||||
? handleUpdateOwner
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
onRestoreEntity={handleRestoreDatabaseSchema}
|
|
||||||
onThreadLinkSelect={onThreadLinkSelect}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<Col span={24}>
|
|
||||||
<Row className="m-t-xss">
|
|
||||||
<Col span={24}>
|
|
||||||
<TabsPane
|
|
||||||
activeTab={activeTab}
|
|
||||||
className="flex-initial"
|
|
||||||
setActiveTab={activeTabHandler}
|
|
||||||
tabs={tabs}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
<Col className="p-y-md" span={24}>
|
|
||||||
{activeTab === 1 && (
|
|
||||||
<Card className="h-full">
|
|
||||||
<Row gutter={[16, 16]}>
|
|
||||||
<Col data-testid="description-container" span={24}>
|
|
||||||
<Description
|
|
||||||
description={description}
|
|
||||||
entityFieldThreads={getEntityFieldThreadCounts(
|
|
||||||
EntityField.DESCRIPTION,
|
|
||||||
entityFieldThreadCount
|
|
||||||
)}
|
|
||||||
entityFqn={databaseSchemaFQN}
|
|
||||||
entityName={databaseSchemaName}
|
|
||||||
entityType={EntityType.DATABASE_SCHEMA}
|
|
||||||
hasEditAccess={
|
|
||||||
databaseSchemaPermission.EditDescription ||
|
|
||||||
databaseSchemaPermission.EditAll
|
|
||||||
}
|
|
||||||
isEdit={isEdit}
|
|
||||||
onCancel={onCancel}
|
|
||||||
onDescriptionEdit={onDescriptionEdit}
|
|
||||||
onDescriptionUpdate={onDescriptionUpdate}
|
|
||||||
onThreadLinkSelect={onThreadLinkSelect}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
{getSchemaTableList()}
|
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
{activeTab === 2 && (
|
|
||||||
<Card className="p-t-xss p-b-md">
|
|
||||||
<Row className="entity-feed-list" id="activityfeed">
|
|
||||||
<Col offset={4} span={16}>
|
|
||||||
<ActivityFeedList
|
|
||||||
hideFeedFilter
|
|
||||||
hideThreadFilter
|
|
||||||
isEntityFeed
|
|
||||||
withSidePanel
|
|
||||||
className=""
|
|
||||||
deletePostHandler={deletePostHandler}
|
|
||||||
entityName={databaseSchemaName}
|
|
||||||
feedList={entityThread}
|
|
||||||
postFeedHandler={postFeedHandler}
|
|
||||||
updateThreadHandler={updateThreadHandler}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
<Col
|
|
||||||
data-testid="observer-element"
|
|
||||||
id="observer-element"
|
|
||||||
ref={elementRef as RefObject<HTMLDivElement>}
|
|
||||||
span={24}>
|
|
||||||
{getLoader()}
|
|
||||||
</Col>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Col>
|
</Col>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<Col span={24}>
|
||||||
|
<Row className="m-t-xss">
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
{threadLink ? (
|
<TabsPane
|
||||||
<ActivityThreadPanel
|
activeTab={activeTab}
|
||||||
createThread={createThread}
|
className="flex-initial"
|
||||||
deletePostHandler={deletePostHandler}
|
setActiveTab={activeTabHandler}
|
||||||
open={Boolean(threadLink)}
|
tabs={tabs}
|
||||||
postFeedHandler={postFeedHandler}
|
/>
|
||||||
threadLink={threadLink}
|
|
||||||
updateThreadHandler={updateThreadHandler}
|
|
||||||
onCancel={onThreadPanelClose}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</Col>
|
</Col>
|
||||||
</PageLayoutV1>
|
<Col className="p-y-md" span={24}>
|
||||||
</PageContainerV1>
|
{activeTab === 1 && (
|
||||||
) : (
|
<Card className="h-full">
|
||||||
<ErrorPlaceHolder
|
{tableDataLoading ? (
|
||||||
className="mt-24"
|
<Loader />
|
||||||
type={ERROR_PLACEHOLDER_TYPE.PERMISSION}
|
) : (
|
||||||
/>
|
<Row gutter={[16, 16]}>
|
||||||
)}
|
<Col data-testid="description-container" span={24}>
|
||||||
</>
|
<Description
|
||||||
|
description={description}
|
||||||
|
entityFieldThreads={getEntityFieldThreadCounts(
|
||||||
|
EntityField.DESCRIPTION,
|
||||||
|
entityFieldThreadCount
|
||||||
|
)}
|
||||||
|
entityFqn={databaseSchemaFQN}
|
||||||
|
entityName={databaseSchemaName}
|
||||||
|
entityType={EntityType.DATABASE_SCHEMA}
|
||||||
|
hasEditAccess={
|
||||||
|
databaseSchemaPermission.EditDescription ||
|
||||||
|
databaseSchemaPermission.EditAll
|
||||||
|
}
|
||||||
|
isEdit={isEdit}
|
||||||
|
onCancel={onCancel}
|
||||||
|
onDescriptionEdit={onDescriptionEdit}
|
||||||
|
onDescriptionUpdate={onDescriptionUpdate}
|
||||||
|
onThreadLinkSelect={onThreadLinkSelect}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
{getSchemaTableList()}
|
||||||
|
</Row>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
{activeTab === 2 && (
|
||||||
|
<Card className="p-t-xss p-b-md">
|
||||||
|
<Row className="entity-feed-list" id="activityfeed">
|
||||||
|
<Col offset={4} span={16}>
|
||||||
|
<ActivityFeedList
|
||||||
|
hideFeedFilter
|
||||||
|
hideThreadFilter
|
||||||
|
isEntityFeed
|
||||||
|
withSidePanel
|
||||||
|
className=""
|
||||||
|
deletePostHandler={deletePostHandler}
|
||||||
|
entityName={databaseSchemaName}
|
||||||
|
feedList={entityThread}
|
||||||
|
postFeedHandler={postFeedHandler}
|
||||||
|
updateThreadHandler={updateThreadHandler}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
<Col
|
||||||
|
data-testid="observer-element"
|
||||||
|
id="observer-element"
|
||||||
|
ref={elementRef as RefObject<HTMLDivElement>}
|
||||||
|
span={24}>
|
||||||
|
{getLoader()}
|
||||||
|
</Col>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Col>
|
||||||
|
<Col span={24}>
|
||||||
|
{threadLink ? (
|
||||||
|
<ActivityThreadPanel
|
||||||
|
createThread={createThread}
|
||||||
|
deletePostHandler={deletePostHandler}
|
||||||
|
open={Boolean(threadLink)}
|
||||||
|
postFeedHandler={postFeedHandler}
|
||||||
|
threadLink={threadLink}
|
||||||
|
updateThreadHandler={updateThreadHandler}
|
||||||
|
onCancel={onThreadPanelClose}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</Col>
|
||||||
|
</PageLayoutV1>
|
||||||
|
</PageContainerV1>
|
||||||
|
) : (
|
||||||
|
<ErrorPlaceHolder
|
||||||
|
className="mt-24"
|
||||||
|
type={ERROR_PLACEHOLDER_TYPE.PERMISSION}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
@ -68,7 +68,7 @@ const TestSuitePage = () => {
|
|||||||
const { isAdminUser } = useAuth();
|
const { isAdminUser } = useAuth();
|
||||||
const { isAuthDisabled } = useAuthContext();
|
const { isAuthDisabled } = useAuthContext();
|
||||||
const [testSuites, setTestSuites] = useState<Array<TestSuite>>([]);
|
const [testSuites, setTestSuites] = useState<Array<TestSuite>>([]);
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||||
const [testSuitePage, setTestSuitePage] = useState(INITIAL_PAGING_VALUE);
|
const [testSuitePage, setTestSuitePage] = useState(INITIAL_PAGING_VALUE);
|
||||||
const [testSuitePaging, setTestSuitePaging] = useState<Paging>(pagingObject);
|
const [testSuitePaging, setTestSuitePaging] = useState<Paging>(pagingObject);
|
||||||
const [selectedTestSuite, setSelectedTestSuite] = useState<TestSuite>();
|
const [selectedTestSuite, setSelectedTestSuite] = useState<TestSuite>();
|
||||||
@ -85,6 +85,7 @@ const TestSuitePage = () => {
|
|||||||
}, [permissions]);
|
}, [permissions]);
|
||||||
|
|
||||||
const handleShowDeleted = (checked: boolean) => {
|
const handleShowDeleted = (checked: boolean) => {
|
||||||
|
setIsLoading(true);
|
||||||
setShowDeleted(checked);
|
setShowDeleted(checked);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -232,11 +233,7 @@ const TestSuitePage = () => {
|
|||||||
[createPermission]
|
[createPermission]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isEmpty(testSuites) && !showDeleted && !isLoading) {
|
||||||
return <Loader />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isEmpty(testSuites) && !showDeleted) {
|
|
||||||
return <PageContainerV1>{errorPlaceHolder}</PageContainerV1>;
|
return <PageContainerV1>{errorPlaceHolder}</PageContainerV1>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +281,10 @@ const TestSuitePage = () => {
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
data-testid="test-suite-table"
|
data-testid="test-suite-table"
|
||||||
dataSource={testSuites}
|
dataSource={testSuites}
|
||||||
loading={{ spinning: isLoading, indicator: <Loader /> }}
|
loading={{
|
||||||
|
spinning: isLoading,
|
||||||
|
indicator: <Loader size="small" />,
|
||||||
|
}}
|
||||||
locale={{
|
locale={{
|
||||||
emptyText: <FilterTablePlaceHolder />,
|
emptyText: <FilterTablePlaceHolder />,
|
||||||
}}
|
}}
|
||||||
@ -306,6 +306,7 @@ const TestSuitePage = () => {
|
|||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
<DeleteWidgetModal
|
<DeleteWidgetModal
|
||||||
|
isRecursiveDelete
|
||||||
afterDeleteAction={fetchTestSuites}
|
afterDeleteAction={fetchTestSuites}
|
||||||
allowSoftDelete={!showDeleted}
|
allowSoftDelete={!showDeleted}
|
||||||
entityId={selectedTestSuite?.id || ''}
|
entityId={selectedTestSuite?.id || ''}
|
||||||
|
@ -770,255 +770,273 @@ const DatabaseDetails: FunctionComponent = () => {
|
|||||||
setIsEditable(false);
|
setIsEditable(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const databaseTable = useMemo(() => {
|
||||||
|
if (schemaDataLoading) {
|
||||||
|
return <Loader />;
|
||||||
|
} else if (!isEmpty(schemaData)) {
|
||||||
|
return (
|
||||||
|
<Col span={24}>
|
||||||
|
<Table
|
||||||
|
bordered
|
||||||
|
className="table-shadow"
|
||||||
|
columns={tableColumn}
|
||||||
|
data-testid="database-databaseSchemas"
|
||||||
|
dataSource={schemaData}
|
||||||
|
loading={{
|
||||||
|
spinning: schemaDataLoading,
|
||||||
|
indicator: <Loader size="small" />,
|
||||||
|
}}
|
||||||
|
pagination={false}
|
||||||
|
rowKey="id"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
{Boolean(
|
||||||
|
!isNil(databaseSchemaPaging.after) ||
|
||||||
|
!isNil(databaseSchemaPaging.before)
|
||||||
|
) && (
|
||||||
|
<NextPrevious
|
||||||
|
currentPage={currentPage}
|
||||||
|
pageSize={PAGE_SIZE}
|
||||||
|
paging={databaseSchemaPaging}
|
||||||
|
pagingHandler={databaseSchemaPagingHandler}
|
||||||
|
totalCount={databaseSchemaPaging.total}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return <ErrorPlaceHolder />;
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
schemaDataLoading,
|
||||||
|
schemaData,
|
||||||
|
tableColumn,
|
||||||
|
databaseSchemaPaging,
|
||||||
|
currentPage,
|
||||||
|
databaseSchemaPagingHandler,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <Loader />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<ErrorPlaceHolder>
|
||||||
|
<p data-testid="error-message">{error}</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isLoading ? (
|
{databasePermission.ViewAll || databasePermission.ViewBasic ? (
|
||||||
<Loader />
|
<PageContainerV1>
|
||||||
) : error ? (
|
<PageLayoutV1
|
||||||
<ErrorPlaceHolder>
|
pageTitle={t('label.entity-detail-plural', {
|
||||||
<p data-testid="error-message">{error}</p>
|
entity: getEntityName(database),
|
||||||
</ErrorPlaceHolder>
|
})}>
|
||||||
) : (
|
{isDatabaseDetailsLoading ? (
|
||||||
<>
|
<Skeleton
|
||||||
{databasePermission.ViewAll || databasePermission.ViewBasic ? (
|
active
|
||||||
<PageContainerV1>
|
paragraph={{
|
||||||
<PageLayoutV1
|
rows: 3,
|
||||||
pageTitle={t('label.entity-detail-plural', {
|
width: ['20%', '80%', '60%'],
|
||||||
entity: getEntityName(database),
|
}}
|
||||||
})}>
|
/>
|
||||||
{isDatabaseDetailsLoading ? (
|
) : (
|
||||||
<Skeleton
|
<>
|
||||||
active
|
<Col span={24}>
|
||||||
paragraph={{
|
{database && (
|
||||||
rows: 3,
|
<EntityHeader
|
||||||
width: ['20%', '80%', '60%'],
|
breadcrumb={slashedDatabaseName}
|
||||||
}}
|
entityData={database}
|
||||||
/>
|
entityType={EntityType.DATABASE}
|
||||||
) : (
|
extra={
|
||||||
<>
|
<ManageButton
|
||||||
<Col span={24}>
|
isRecursiveDelete
|
||||||
{database && (
|
allowSoftDelete={false}
|
||||||
<EntityHeader
|
canDelete={databasePermission.Delete}
|
||||||
breadcrumb={slashedDatabaseName}
|
entityFQN={databaseFQN}
|
||||||
entityData={database}
|
entityId={databaseId}
|
||||||
|
entityName={databaseName}
|
||||||
entityType={EntityType.DATABASE}
|
entityType={EntityType.DATABASE}
|
||||||
extra={
|
|
||||||
<ManageButton
|
|
||||||
isRecursiveDelete
|
|
||||||
allowSoftDelete={false}
|
|
||||||
canDelete={databasePermission.Delete}
|
|
||||||
entityFQN={databaseFQN}
|
|
||||||
entityId={databaseId}
|
|
||||||
entityName={databaseName}
|
|
||||||
entityType={EntityType.DATABASE}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
icon={
|
|
||||||
<img
|
|
||||||
className="h-8"
|
|
||||||
src={serviceTypeLogo(serviceType ?? '')}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
serviceName={database.service.name ?? ''}
|
|
||||||
/>
|
/>
|
||||||
)}
|
}
|
||||||
</Col>
|
icon={
|
||||||
|
<img
|
||||||
<Col className="m-t-xs" span={24}>
|
className="h-8"
|
||||||
<Space
|
src={serviceTypeLogo(serviceType ?? '')}
|
||||||
wrap
|
/>
|
||||||
align="center"
|
}
|
||||||
data-testid="extrainfo"
|
serviceName={database.service.name ?? ''}
|
||||||
size={4}>
|
|
||||||
{extraInfo.map((info, index) => (
|
|
||||||
<span
|
|
||||||
className="tw-flex tw-items-center"
|
|
||||||
data-testid={info.key || `info${index}`}
|
|
||||||
key={index}>
|
|
||||||
<EntitySummaryDetails
|
|
||||||
currentOwner={database?.owner}
|
|
||||||
data={info}
|
|
||||||
removeTier={handleRemoveTier}
|
|
||||||
tier={getTierTags(database?.tags ?? [])}
|
|
||||||
updateOwner={
|
|
||||||
databasePermission.EditOwner ||
|
|
||||||
databasePermission.EditAll
|
|
||||||
? handleUpdateOwner
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
updateTier={
|
|
||||||
databasePermission.EditTags ||
|
|
||||||
databasePermission.EditAll
|
|
||||||
? handleUpdateTier
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{extraInfo.length !== 1 &&
|
|
||||||
index < extraInfo.length - 1 ? (
|
|
||||||
<span className="tw-mx-1.5 tw-inline-block tw-text-gray-400">
|
|
||||||
{t('label.pipe-symbol')}
|
|
||||||
</span>
|
|
||||||
) : null}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</Space>
|
|
||||||
</Col>
|
|
||||||
<Col className="m-t-xs" span={24}>
|
|
||||||
<Space
|
|
||||||
wrap
|
|
||||||
align="center"
|
|
||||||
data-testid="entity-tags"
|
|
||||||
size={6}
|
|
||||||
onClick={() => {
|
|
||||||
if (isTagEditable) {
|
|
||||||
// Fetch tags and terms only once
|
|
||||||
if (tagList.length === 0) {
|
|
||||||
fetchTags();
|
|
||||||
}
|
|
||||||
setIsEditable(true);
|
|
||||||
}
|
|
||||||
}}>
|
|
||||||
{!deleted && (
|
|
||||||
<TagsContainer
|
|
||||||
className="w-min-20"
|
|
||||||
dropDownHorzPosRight={false}
|
|
||||||
editable={isEditable}
|
|
||||||
isLoading={isTagLoading}
|
|
||||||
selectedTags={selectedTags}
|
|
||||||
showAddTagButton={
|
|
||||||
isTagEditable && isEmpty(selectedTags)
|
|
||||||
}
|
|
||||||
showEditTagButton={isTagEditable}
|
|
||||||
size="small"
|
|
||||||
tagList={tagList}
|
|
||||||
onCancel={() => {
|
|
||||||
handleTagSelection();
|
|
||||||
}}
|
|
||||||
onSelectionChange={(tags) => {
|
|
||||||
handleTagSelection(tags);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Space>
|
|
||||||
</Col>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Col span={24}>
|
|
||||||
<Row className="m-t-md">
|
|
||||||
<Col span={24}>
|
|
||||||
<TabsPane
|
|
||||||
activeTab={activeTab}
|
|
||||||
className="flex-initial"
|
|
||||||
setActiveTab={activeTabHandler}
|
|
||||||
tabs={tabs}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
<Col className="p-y-md" span={24}>
|
|
||||||
{activeTab === 1 && (
|
|
||||||
<Card className="h-full">
|
|
||||||
<Row gutter={[16, 16]}>
|
|
||||||
<Col data-testid="description-container" span={24}>
|
|
||||||
<Description
|
|
||||||
description={description}
|
|
||||||
entityFieldThreads={getEntityFieldThreadCounts(
|
|
||||||
EntityField.DESCRIPTION,
|
|
||||||
entityFieldThreadCount
|
|
||||||
)}
|
|
||||||
entityFqn={databaseFQN}
|
|
||||||
entityName={databaseName}
|
|
||||||
entityType={EntityType.DATABASE}
|
|
||||||
hasEditAccess={
|
|
||||||
databasePermission.EditDescription ||
|
|
||||||
databasePermission.EditAll
|
|
||||||
}
|
|
||||||
isEdit={isEdit}
|
|
||||||
onCancel={onCancel}
|
|
||||||
onDescriptionEdit={onDescriptionEdit}
|
|
||||||
onDescriptionUpdate={onDescriptionUpdate}
|
|
||||||
onThreadLinkSelect={onThreadLinkSelect}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
<Col span={24}>
|
|
||||||
<Table
|
|
||||||
bordered
|
|
||||||
className="table-shadow"
|
|
||||||
columns={tableColumn}
|
|
||||||
data-testid="database-databaseSchemas"
|
|
||||||
dataSource={schemaData}
|
|
||||||
loading={{
|
|
||||||
spinning: schemaDataLoading,
|
|
||||||
indicator: <Loader size="small" />,
|
|
||||||
}}
|
|
||||||
pagination={false}
|
|
||||||
rowKey="id"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
{Boolean(
|
|
||||||
!isNil(databaseSchemaPaging.after) ||
|
|
||||||
!isNil(databaseSchemaPaging.before)
|
|
||||||
) && (
|
|
||||||
<NextPrevious
|
|
||||||
currentPage={currentPage}
|
|
||||||
pageSize={PAGE_SIZE}
|
|
||||||
paging={databaseSchemaPaging}
|
|
||||||
pagingHandler={databaseSchemaPagingHandler}
|
|
||||||
totalCount={databaseSchemaPaging.total}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
{activeTab === 2 && (
|
|
||||||
<Card className="p-t-xss p-b-md">
|
|
||||||
<Row className="entity-feed-list" id="activityfeed">
|
|
||||||
<Col offset={4} span={16}>
|
|
||||||
<ActivityFeedList
|
|
||||||
hideFeedFilter
|
|
||||||
hideThreadFilter
|
|
||||||
isEntityFeed
|
|
||||||
withSidePanel
|
|
||||||
className=""
|
|
||||||
deletePostHandler={deletePostHandler}
|
|
||||||
entityName={databaseName}
|
|
||||||
feedList={entityThread}
|
|
||||||
postFeedHandler={postFeedHandler}
|
|
||||||
updateThreadHandler={updateThreadHandler}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
<Col
|
|
||||||
data-testid="observer-element"
|
|
||||||
id="observer-element"
|
|
||||||
ref={elementRef as RefObject<HTMLDivElement>}
|
|
||||||
span={24}>
|
|
||||||
{getLoader()}
|
|
||||||
</Col>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Col>
|
|
||||||
<Col span={24}>
|
|
||||||
{threadLink ? (
|
|
||||||
<ActivityThreadPanel
|
|
||||||
createThread={createThread}
|
|
||||||
deletePostHandler={deletePostHandler}
|
|
||||||
open={Boolean(threadLink)}
|
|
||||||
postFeedHandler={postFeedHandler}
|
|
||||||
threadLink={threadLink}
|
|
||||||
updateThreadHandler={updateThreadHandler}
|
|
||||||
onCancel={onThreadPanelClose}
|
|
||||||
/>
|
/>
|
||||||
) : null}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
</PageLayoutV1>
|
|
||||||
</PageContainerV1>
|
<Col className="m-t-xs" span={24}>
|
||||||
) : (
|
<Space wrap align="center" data-testid="extrainfo" size={4}>
|
||||||
<ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.PERMISSION} />
|
{extraInfo.map((info, index) => (
|
||||||
)}
|
<span
|
||||||
</>
|
className="tw-flex tw-items-center"
|
||||||
|
data-testid={info.key || `info${index}`}
|
||||||
|
key={index}>
|
||||||
|
<EntitySummaryDetails
|
||||||
|
currentOwner={database?.owner}
|
||||||
|
data={info}
|
||||||
|
removeTier={handleRemoveTier}
|
||||||
|
tier={getTierTags(database?.tags ?? [])}
|
||||||
|
updateOwner={
|
||||||
|
databasePermission.EditOwner ||
|
||||||
|
databasePermission.EditAll
|
||||||
|
? handleUpdateOwner
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
updateTier={
|
||||||
|
databasePermission.EditTags ||
|
||||||
|
databasePermission.EditAll
|
||||||
|
? handleUpdateTier
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{extraInfo.length !== 1 &&
|
||||||
|
index < extraInfo.length - 1 ? (
|
||||||
|
<span className="tw-mx-1.5 tw-inline-block tw-text-gray-400">
|
||||||
|
{t('label.pipe-symbol')}
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</Space>
|
||||||
|
</Col>
|
||||||
|
<Col className="m-t-xs" span={24}>
|
||||||
|
<Space
|
||||||
|
wrap
|
||||||
|
align="center"
|
||||||
|
data-testid="entity-tags"
|
||||||
|
size={6}
|
||||||
|
onClick={() => {
|
||||||
|
if (isTagEditable) {
|
||||||
|
// Fetch tags and terms only once
|
||||||
|
if (tagList.length === 0) {
|
||||||
|
fetchTags();
|
||||||
|
}
|
||||||
|
setIsEditable(true);
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
{!deleted && (
|
||||||
|
<TagsContainer
|
||||||
|
className="w-min-20"
|
||||||
|
dropDownHorzPosRight={false}
|
||||||
|
editable={isEditable}
|
||||||
|
isLoading={isTagLoading}
|
||||||
|
selectedTags={selectedTags}
|
||||||
|
showAddTagButton={
|
||||||
|
isTagEditable && isEmpty(selectedTags)
|
||||||
|
}
|
||||||
|
showEditTagButton={isTagEditable}
|
||||||
|
size="small"
|
||||||
|
tagList={tagList}
|
||||||
|
onCancel={() => {
|
||||||
|
handleTagSelection();
|
||||||
|
}}
|
||||||
|
onSelectionChange={(tags) => {
|
||||||
|
handleTagSelection(tags);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
</Col>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Col span={24}>
|
||||||
|
<Row className="m-t-md">
|
||||||
|
<Col span={24}>
|
||||||
|
<TabsPane
|
||||||
|
activeTab={activeTab}
|
||||||
|
className="flex-initial"
|
||||||
|
setActiveTab={activeTabHandler}
|
||||||
|
tabs={tabs}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
<Col className="p-y-md" span={24}>
|
||||||
|
{activeTab === 1 && (
|
||||||
|
<Card className="h-full">
|
||||||
|
<Row gutter={[16, 16]}>
|
||||||
|
<Col data-testid="description-container" span={24}>
|
||||||
|
<Description
|
||||||
|
description={description}
|
||||||
|
entityFieldThreads={getEntityFieldThreadCounts(
|
||||||
|
EntityField.DESCRIPTION,
|
||||||
|
entityFieldThreadCount
|
||||||
|
)}
|
||||||
|
entityFqn={databaseFQN}
|
||||||
|
entityName={databaseName}
|
||||||
|
entityType={EntityType.DATABASE}
|
||||||
|
hasEditAccess={
|
||||||
|
databasePermission.EditDescription ||
|
||||||
|
databasePermission.EditAll
|
||||||
|
}
|
||||||
|
isEdit={isEdit}
|
||||||
|
onCancel={onCancel}
|
||||||
|
onDescriptionEdit={onDescriptionEdit}
|
||||||
|
onDescriptionUpdate={onDescriptionUpdate}
|
||||||
|
onThreadLinkSelect={onThreadLinkSelect}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
{databaseTable}
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
{activeTab === 2 && (
|
||||||
|
<Card className="p-t-xss p-b-md">
|
||||||
|
<Row className="entity-feed-list" id="activityfeed">
|
||||||
|
<Col offset={4} span={16}>
|
||||||
|
<ActivityFeedList
|
||||||
|
hideFeedFilter
|
||||||
|
hideThreadFilter
|
||||||
|
isEntityFeed
|
||||||
|
withSidePanel
|
||||||
|
className=""
|
||||||
|
deletePostHandler={deletePostHandler}
|
||||||
|
entityName={databaseName}
|
||||||
|
feedList={entityThread}
|
||||||
|
postFeedHandler={postFeedHandler}
|
||||||
|
updateThreadHandler={updateThreadHandler}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
<Col
|
||||||
|
data-testid="observer-element"
|
||||||
|
id="observer-element"
|
||||||
|
ref={elementRef as RefObject<HTMLDivElement>}
|
||||||
|
span={24}>
|
||||||
|
{getLoader()}
|
||||||
|
</Col>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Col>
|
||||||
|
<Col span={24}>
|
||||||
|
{threadLink ? (
|
||||||
|
<ActivityThreadPanel
|
||||||
|
createThread={createThread}
|
||||||
|
deletePostHandler={deletePostHandler}
|
||||||
|
open={Boolean(threadLink)}
|
||||||
|
postFeedHandler={postFeedHandler}
|
||||||
|
threadLink={threadLink}
|
||||||
|
updateThreadHandler={updateThreadHandler}
|
||||||
|
onCancel={onThreadPanelClose}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</Col>
|
||||||
|
</PageLayoutV1>
|
||||||
|
</PageContainerV1>
|
||||||
|
) : (
|
||||||
|
<ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.PERMISSION} />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -159,6 +159,7 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
const [serviceDetails, setServiceDetails] = useState<ServicesType>();
|
const [serviceDetails, setServiceDetails] = useState<ServicesType>();
|
||||||
const [data, setData] = useState<Array<ServicePageData>>([]);
|
const [data, setData] = useState<Array<ServicePageData>>([]);
|
||||||
const [isLoading, setIsLoading] = useState(!isOpenMetadataService);
|
const [isLoading, setIsLoading] = useState(!isOpenMetadataService);
|
||||||
|
const [isServiceLoading, setIsServiceLoading] = useState(true);
|
||||||
const [dataModel, setDataModel] = useState<Array<ServicePageData>>([]);
|
const [dataModel, setDataModel] = useState<Array<ServicePageData>>([]);
|
||||||
const [dataModelPaging, setDataModelPaging] = useState<Paging>(pagingObject);
|
const [dataModelPaging, setDataModelPaging] = useState<Paging>(pagingObject);
|
||||||
const [paging, setPaging] = useState<Paging>(pagingObject);
|
const [paging, setPaging] = useState<Paging>(pagingObject);
|
||||||
@ -230,6 +231,23 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const isTestingDisabled = useMemo(
|
||||||
|
() =>
|
||||||
|
!servicePermission.EditAll ||
|
||||||
|
(serviceCategory === ServiceCategory.METADATA_SERVICES &&
|
||||||
|
serviceFQN === OPEN_METADATA) ||
|
||||||
|
isUndefined(connectionDetails),
|
||||||
|
[servicePermission, serviceCategory, serviceFQN, connectionDetails]
|
||||||
|
);
|
||||||
|
|
||||||
|
const goToEditConnection = () => {
|
||||||
|
history.push(getEditConnectionPath(serviceName || '', serviceFQN || ''));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
setDeleteWidgetVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
const activeTabHandler = (tabValue: number) => {
|
const activeTabHandler = (tabValue: number) => {
|
||||||
setActiveTab(tabValue);
|
setActiveTab(tabValue);
|
||||||
const currentTabIndex = tabValue - 1;
|
const currentTabIndex = tabValue - 1;
|
||||||
@ -416,7 +434,7 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const fetchDatabases = async (paging?: PagingWithoutTotal) => {
|
const fetchDatabases = async (paging?: PagingWithoutTotal) => {
|
||||||
setIsLoading(true);
|
setIsServiceLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data, paging: resPaging } = await getDatabases(
|
const { data, paging: resPaging } = await getDatabases(
|
||||||
serviceFQN,
|
serviceFQN,
|
||||||
@ -431,12 +449,12 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(error as AxiosError);
|
showErrorToast(error as AxiosError);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsServiceLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchTopics = async (paging?: PagingWithoutTotal) => {
|
const fetchTopics = async (paging?: PagingWithoutTotal) => {
|
||||||
setIsLoading(true);
|
setIsServiceLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data, paging: resPaging } = await getTopics(
|
const { data, paging: resPaging } = await getTopics(
|
||||||
serviceFQN,
|
serviceFQN,
|
||||||
@ -448,12 +466,12 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(error as AxiosError);
|
showErrorToast(error as AxiosError);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsServiceLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchDashboards = async (paging?: PagingWithoutTotal) => {
|
const fetchDashboards = async (paging?: PagingWithoutTotal) => {
|
||||||
setIsLoading(true);
|
setIsServiceLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data, paging: resPaging } = await getDashboards(
|
const { data, paging: resPaging } = await getDashboards(
|
||||||
serviceFQN,
|
serviceFQN,
|
||||||
@ -465,12 +483,12 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(error as AxiosError);
|
showErrorToast(error as AxiosError);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsServiceLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchDashboardsDataModel = async (paging?: PagingWithoutTotal) => {
|
const fetchDashboardsDataModel = async (paging?: PagingWithoutTotal) => {
|
||||||
setIsLoading(true);
|
setIsServiceLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data, paging: resPaging } = await getDataModels(
|
const { data, paging: resPaging } = await getDataModels(
|
||||||
serviceFQN,
|
serviceFQN,
|
||||||
@ -482,12 +500,12 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(error as AxiosError);
|
showErrorToast(error as AxiosError);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsServiceLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchPipeLines = async (paging?: PagingWithoutTotal) => {
|
const fetchPipeLines = async (paging?: PagingWithoutTotal) => {
|
||||||
setIsLoading(true);
|
setIsServiceLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data, paging: resPaging } = await getPipelines(
|
const { data, paging: resPaging } = await getPipelines(
|
||||||
serviceFQN,
|
serviceFQN,
|
||||||
@ -499,12 +517,12 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(error as AxiosError);
|
showErrorToast(error as AxiosError);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsServiceLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchMlModal = async (paging?: PagingWithoutTotal) => {
|
const fetchMlModal = async (paging?: PagingWithoutTotal) => {
|
||||||
setIsLoading(true);
|
setIsServiceLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data, paging: resPaging } = await getMlModels(
|
const { data, paging: resPaging } = await getMlModels(
|
||||||
serviceFQN,
|
serviceFQN,
|
||||||
@ -516,12 +534,12 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(error as AxiosError);
|
showErrorToast(error as AxiosError);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsServiceLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchContainers = async (paging?: PagingWithoutTotal) => {
|
const fetchContainers = async (paging?: PagingWithoutTotal) => {
|
||||||
setIsLoading(true);
|
setIsServiceLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await getContainers({
|
const response = await getContainers({
|
||||||
service: serviceFQN,
|
service: serviceFQN,
|
||||||
@ -536,7 +554,7 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
setData([]);
|
setData([]);
|
||||||
setPaging(pagingObject);
|
setPaging(pagingObject);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsServiceLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -836,7 +854,7 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
setCurrentPage(activePage ?? 1);
|
setCurrentPage(activePage ?? 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getIngestionTab = () => {
|
const ingestionTab = useMemo(() => {
|
||||||
if (!isAirflowAvailable) {
|
if (!isAirflowAvailable) {
|
||||||
return <ErrorPlaceHolderIngestion />;
|
return <ErrorPlaceHolderIngestion />;
|
||||||
} else if (isUndefined(airflowEndpoint) || isUndefined(serviceDetails)) {
|
} else if (isUndefined(airflowEndpoint) || isUndefined(serviceDetails)) {
|
||||||
@ -863,11 +881,90 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
}, [
|
||||||
|
isAirflowAvailable,
|
||||||
|
airflowEndpoint,
|
||||||
|
serviceDetails,
|
||||||
|
deleteIngestionById,
|
||||||
|
deployIngestion,
|
||||||
|
handleEnableDisableIngestion,
|
||||||
|
ingestions,
|
||||||
|
ingestionPaging,
|
||||||
|
servicePermission,
|
||||||
|
serviceName,
|
||||||
|
serviceList,
|
||||||
|
serviceFQN,
|
||||||
|
triggerIngestionById,
|
||||||
|
getAllIngestionWorkflows,
|
||||||
|
]);
|
||||||
|
|
||||||
const getDataModalTab = () => (
|
const dataModalTab = useMemo(
|
||||||
<DataModelTable data={dataModel} isLoading={isLoading} />
|
() => <DataModelTable data={dataModel} isLoading={isLoading} />,
|
||||||
|
[dataModel, isLoading]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const testConnectionTab = useMemo(() => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Space className="w-full my-4 justify-end">
|
||||||
|
<Tooltip
|
||||||
|
title={
|
||||||
|
servicePermission.EditAll
|
||||||
|
? t('label.edit-entity', {
|
||||||
|
entity: t('label.connection'),
|
||||||
|
})
|
||||||
|
: t('message.no-permission-for-action')
|
||||||
|
}>
|
||||||
|
<Button
|
||||||
|
ghost
|
||||||
|
data-testid="edit-connection-button"
|
||||||
|
disabled={!servicePermission.EditAll}
|
||||||
|
type="primary"
|
||||||
|
onClick={goToEditConnection}>
|
||||||
|
{t('label.edit-entity', {
|
||||||
|
entity: t('label.connection'),
|
||||||
|
})}
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
{allowTestConn && isAirflowAvailable && (
|
||||||
|
<Tooltip
|
||||||
|
title={
|
||||||
|
servicePermission.EditAll
|
||||||
|
? t('label.test-entity', {
|
||||||
|
entity: t('label.connection'),
|
||||||
|
})
|
||||||
|
: t('message.no-permission-for-action')
|
||||||
|
}>
|
||||||
|
<TestConnection
|
||||||
|
connectionType={serviceDetails?.serviceType ?? ''}
|
||||||
|
formData={connectionDetails as ConfigData}
|
||||||
|
isTestingDisabled={isTestingDisabled}
|
||||||
|
serviceCategory={serviceCategory as ServiceCategory}
|
||||||
|
serviceName={serviceDetails?.name}
|
||||||
|
// validation is not required as we have all the data available and not in edit mode
|
||||||
|
shouldValidateForm={false}
|
||||||
|
showDetails={false}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
<ServiceConnectionDetails
|
||||||
|
connectionDetails={connectionDetails || {}}
|
||||||
|
serviceCategory={serviceCategory}
|
||||||
|
serviceFQN={serviceDetails?.serviceType || ''}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}, [
|
||||||
|
servicePermission.EditAll,
|
||||||
|
allowTestConn,
|
||||||
|
isAirflowAvailable,
|
||||||
|
serviceDetails,
|
||||||
|
connectionDetails,
|
||||||
|
isTestingDisabled,
|
||||||
|
serviceCategory,
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
servicePageTabs(getCountLabel(serviceName))[activeTab - 1].path !== tab
|
servicePageTabs(getCountLabel(serviceName))[activeTab - 1].path !== tab
|
||||||
@ -876,18 +973,6 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
}
|
}
|
||||||
}, [tab]);
|
}, [tab]);
|
||||||
|
|
||||||
const goToEditConnection = () => {
|
|
||||||
history.push(getEditConnectionPath(serviceName || '', serviceFQN || ''));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEditConnection = () => {
|
|
||||||
goToEditConnection();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDelete = () => {
|
|
||||||
setDeleteWidgetVisible(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isOpenMetadataService) {
|
if (!isOpenMetadataService) {
|
||||||
fetchServicePermission();
|
fetchServicePermission();
|
||||||
@ -960,18 +1045,53 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
];
|
];
|
||||||
}, [serviceName]);
|
}, [serviceName]);
|
||||||
|
|
||||||
|
const entityServiceTab = useMemo(() => {
|
||||||
|
if (isServiceLoading) {
|
||||||
|
return <Loader />;
|
||||||
|
} else if (!isEmpty(data) && !isServiceLoading) {
|
||||||
|
return (
|
||||||
|
<div data-testid="table-container">
|
||||||
|
<Table
|
||||||
|
bordered
|
||||||
|
className="mt-4 table-shadow"
|
||||||
|
columns={tableColumn}
|
||||||
|
components={tableComponent}
|
||||||
|
data-testid="service-children-table"
|
||||||
|
dataSource={data}
|
||||||
|
pagination={false}
|
||||||
|
rowKey="id"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
{Boolean(!isNil(paging.after) || !isNil(paging.before)) && (
|
||||||
|
<NextPrevious
|
||||||
|
currentPage={currentPage}
|
||||||
|
pageSize={PAGE_SIZE}
|
||||||
|
paging={paging}
|
||||||
|
pagingHandler={pagingHandler}
|
||||||
|
totalCount={paging.total}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return <ErrorPlaceHolder />;
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
isServiceLoading,
|
||||||
|
data,
|
||||||
|
paging,
|
||||||
|
tableColumn,
|
||||||
|
tableComponent,
|
||||||
|
currentPage,
|
||||||
|
pagingHandler,
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isAirflowAvailable && !isOpenMetadataService) {
|
if (isAirflowAvailable && !isOpenMetadataService) {
|
||||||
getAllIngestionWorkflows();
|
getAllIngestionWorkflows();
|
||||||
}
|
}
|
||||||
}, [isAirflowAvailable]);
|
}, [isAirflowAvailable]);
|
||||||
|
|
||||||
const isTestingDisabled =
|
|
||||||
!servicePermission.EditAll ||
|
|
||||||
(serviceCategory === ServiceCategory.METADATA_SERVICES &&
|
|
||||||
serviceFQN === OPEN_METADATA) ||
|
|
||||||
isUndefined(connectionDetails);
|
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<PageContainerV1>
|
<PageContainerV1>
|
||||||
@ -1077,96 +1197,10 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
/>
|
/>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
{activeTab === 1 &&
|
{activeTab === 1 && entityServiceTab}
|
||||||
(isEmpty(data) ? (
|
{activeTab === 4 && dataModalTab}
|
||||||
<ErrorPlaceHolder />
|
{activeTab === 2 && ingestionTab}
|
||||||
) : (
|
{activeTab === 3 && testConnectionTab}
|
||||||
<div data-testid="table-container">
|
|
||||||
<Table
|
|
||||||
bordered
|
|
||||||
className="mt-4 table-shadow"
|
|
||||||
columns={tableColumn}
|
|
||||||
components={tableComponent}
|
|
||||||
data-testid="service-children-table"
|
|
||||||
dataSource={data}
|
|
||||||
loading={{
|
|
||||||
spinning: isLoading,
|
|
||||||
indicator: <Loader size="small" />,
|
|
||||||
}}
|
|
||||||
pagination={false}
|
|
||||||
rowKey="id"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
{Boolean(
|
|
||||||
!isNil(paging.after) || !isNil(paging.before)
|
|
||||||
) && (
|
|
||||||
<NextPrevious
|
|
||||||
currentPage={currentPage}
|
|
||||||
pageSize={PAGE_SIZE}
|
|
||||||
paging={paging}
|
|
||||||
pagingHandler={pagingHandler}
|
|
||||||
totalCount={paging.total}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{activeTab === 4 && getDataModalTab()}
|
|
||||||
{activeTab === 2 && getIngestionTab()}
|
|
||||||
|
|
||||||
{activeTab === 3 && (
|
|
||||||
<>
|
|
||||||
<Space className="w-full my-4 justify-end">
|
|
||||||
<Tooltip
|
|
||||||
title={
|
|
||||||
servicePermission.EditAll
|
|
||||||
? t('label.edit-entity', {
|
|
||||||
entity: t('label.connection'),
|
|
||||||
})
|
|
||||||
: t('message.no-permission-for-action')
|
|
||||||
}>
|
|
||||||
<Button
|
|
||||||
ghost
|
|
||||||
data-testid="edit-connection-button"
|
|
||||||
disabled={!servicePermission.EditAll}
|
|
||||||
type="primary"
|
|
||||||
onClick={handleEditConnection}>
|
|
||||||
{t('label.edit-entity', {
|
|
||||||
entity: t('label.connection'),
|
|
||||||
})}
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
{allowTestConn && isAirflowAvailable && (
|
|
||||||
<Tooltip
|
|
||||||
title={
|
|
||||||
servicePermission.EditAll
|
|
||||||
? t('label.test-entity', {
|
|
||||||
entity: t('label.connection'),
|
|
||||||
})
|
|
||||||
: t('message.no-permission-for-action')
|
|
||||||
}>
|
|
||||||
<TestConnection
|
|
||||||
connectionType={serviceDetails?.serviceType ?? ''}
|
|
||||||
formData={connectionDetails as ConfigData}
|
|
||||||
isTestingDisabled={isTestingDisabled}
|
|
||||||
serviceCategory={
|
|
||||||
serviceCategory as ServiceCategory
|
|
||||||
}
|
|
||||||
serviceName={serviceDetails?.name}
|
|
||||||
// validation is not required as we have all the data available and not in edit mode
|
|
||||||
shouldValidateForm={false}
|
|
||||||
showDetails={false}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</Space>
|
|
||||||
<ServiceConnectionDetails
|
|
||||||
connectionDetails={connectionDetails || {}}
|
|
||||||
serviceCategory={serviceCategory}
|
|
||||||
serviceFQN={serviceDetails?.serviceType || ''}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Col>
|
</Col>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user