Replace Empty table with error placeholder (#7264)

This commit is contained in:
Ashish Gupta 2022-09-06 20:35:40 +05:30 committed by GitHub
parent 487fd10a6b
commit 66f8fdfd3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 193 additions and 153 deletions

View File

@ -28,10 +28,10 @@ import React, {
} from 'react';
import { Link } from 'react-router-dom';
import { WORKFLOWS_PROFILER_DOCS } from '../../constants/docs.constants';
import { NoDataFoundPlaceHolder } from '../../constants/services.const';
import { TableData } from '../../generated/entity/data/table';
import { withLoader } from '../../hoc/withLoader';
import { isEven } from '../../utils/CommonUtils';
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
import { RowData } from './RowData';
import './SampleDataTable.style.less';
@ -157,32 +157,29 @@ const SampleDataTable: FunctionComponent<Props> = ({ sampleData }: Props) => {
</table>
</div>
) : (
<Space
align="center"
className="no-data-placeholder"
direction="vertical">
<div className="tw-mt-12">
<img alt="No Service" src={NoDataFoundPlaceHolder} width={120} />
</div>
<div className="tw-mt-8 tw-max-w-x tw-text-center">
<Typography.Paragraph style={{ marginBottom: '4px' }}>
{' '}
No sample data available
</Typography.Paragraph>
<Typography.Paragraph>
{' '}
To view Sample Data, run the Profiler Ingestion. Please refer to
this doc to schedule the{' '}
<Link
className="tw-ml-1"
target="_blank"
to={{
pathname: WORKFLOWS_PROFILER_DOCS,
}}>
Profiler Ingestion
</Link>
</Typography.Paragraph>
</div>
<Space align="center" className="w-full" direction="vertical">
<ErrorPlaceHolder>
{' '}
<div className="tw-max-w-x tw-text-center">
<Typography.Paragraph style={{ marginBottom: '4px' }}>
{' '}
No sample data available
</Typography.Paragraph>
<Typography.Paragraph>
{' '}
To view Sample Data, run the Profiler Ingestion. Please refer to
this doc to schedule the{' '}
<Link
className="tw-ml-1"
target="_blank"
to={{
pathname: WORKFLOWS_PROFILER_DOCS,
}}>
Profiler Ingestion
</Link>
</Typography.Paragraph>
</div>
</ErrorPlaceHolder>
</Space>
)}
</div>

View File

@ -17,9 +17,9 @@ import { isUndefined } from 'lodash';
import React, { FC, HTMLAttributes, useState } from 'react';
import { Link } from 'react-router-dom';
import { WORKFLOWS_METADATA_DOCS } from '../../constants/docs.constants';
import { NoDataFoundPlaceHolder } from '../../constants/services.const';
import { TopicSampleData } from '../../generated/entity/data/topic';
import { withLoader } from '../../hoc/withLoader';
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
import SchemaEditor from '../schema-editor/SchemaEditor';
interface SampleDataTopicProp extends HTMLAttributes<HTMLDivElement> {
@ -84,30 +84,30 @@ const SampleDataTopic: FC<SampleDataTopicProp> = ({ sampleData }) => {
} else {
return (
<div
className="tw-flex tw-flex-col tw-justify-center tw-font-medium tw-items-center tw-p-8"
className="tw-flex tw-flex-col tw-justify-center tw-font-medium tw-items-center"
data-testid="no-data">
<div className="tw-mt-12">
<img alt="No Service" src={NoDataFoundPlaceHolder} width={120} />
</div>
<div className="tw-mt-8 tw-max-w-x tw-text-center">
<Typography.Paragraph style={{ marginBottom: '4px' }}>
{' '}
No sample data available
</Typography.Paragraph>
<Typography.Paragraph>
{' '}
To view Sample Data, run the MetaData Ingestion. Please refer to
this doc to schedule the{' '}
<Link
className="tw-ml-1"
target="_blank"
to={{
pathname: WORKFLOWS_METADATA_DOCS,
}}>
MetaData Ingestion
</Link>
</Typography.Paragraph>
</div>
<ErrorPlaceHolder>
{' '}
<div className="tw-max-w-x tw-text-center">
<Typography.Paragraph style={{ marginBottom: '4px' }}>
{' '}
No sample data available
</Typography.Paragraph>
<Typography.Paragraph>
{' '}
To view Sample Data, run the MetaData Ingestion. Please refer to
this doc to schedule the{' '}
<Link
className="tw-ml-1"
target="_blank"
to={{
pathname: WORKFLOWS_METADATA_DOCS,
}}>
MetaData Ingestion
</Link>
</Typography.Paragraph>
</div>
</ErrorPlaceHolder>
</div>
);
}

View File

@ -83,7 +83,7 @@ const WebhooksV1: FC<WebhooksV1Props> = ({
placement="left"
title={
addWebhookPermission
? 'Add Webhook'
? `Add ${WEBHOOKS_INTEGRATION[webhookType]}`
: NO_PERMISSION_FOR_ACTION
}>
<ButtonAntd

View File

@ -13,12 +13,13 @@
import { AxiosError } from 'axios';
import classNames from 'classnames';
import { uniqueId } from 'lodash';
import { isEmpty, uniqueId } from 'lodash';
import React, { FC, useEffect, useState } from 'react';
import { getTypeByFQN } from '../../../axiosAPIs/metadataTypeAPI';
import { Type } from '../../../generated/entity/type';
import { isEven } from '../../../utils/CommonUtils';
import { showErrorToast } from '../../../utils/ToastUtils';
import ErrorPlaceHolder from '../error-with-placeholder/ErrorPlaceHolder';
import { CustomPropertyProps } from './CustomPropertyTable.interface';
import { PropertyValue } from './PropertyValue';
@ -55,60 +56,53 @@ export const CustomPropertyTable: FC<CustomPropertyProps> = ({
}, []);
return (
<div className="tw-table-container">
<table className="tw-w-full" data-testid="custom-properties-table">
<thead data-testid="table-header">
<tr className="tableHead-row">
<th className="tableHead-cell tw-w-2/4" data-testid="property-name">
Name
</th>
<th
className="tableHead-cell tw-w-2/4"
data-testid="property-value">
Value
</th>
</tr>
</thead>
<tbody data-testid="table-body">
{customProperties.length ? (
customProperties.map((property, index) => (
<tr
className={classNames(
`tableBody-row ${!isEven(index + 1) && 'odd-row'}`,
{
'tw-border-b-0': index === customProperties.length - 1,
}
)}
data-testid="data-row"
key={uniqueId()}>
<td className="tableBody-cell">{property.name}</td>
<td className="tableBody-cell">
<PropertyValue
extension={extension}
propertyName={property.name}
propertyType={property.propertyType}
onExtensionUpdate={onExtensionUpdate}
/>
</td>
<>
{isEmpty(customProperties) ? (
<ErrorPlaceHolder heading="Custom Properties" />
) : (
<div className="tw-table-container">
<table className="tw-w-full" data-testid="custom-properties-table">
<thead data-testid="table-header">
<tr className="tableHead-row">
<th
className="tableHead-cell tw-w-2/4"
data-testid="property-name">
Name
</th>
<th
className="tableHead-cell tw-w-2/4"
data-testid="property-value">
Value
</th>
</tr>
))
) : (
<tr
className={classNames(
'tableBody-row tw-border-l-0 tw-border-r-0 tw-border-b-0'
)}
data-testid="no-data-row"
key={uniqueId()}>
<td className="tableBody-cell tw-text-center" colSpan={2}>
<span className="tw-text-grey-muted">
No custom properties available
</span>
</td>
</tr>
)}
</tbody>
</table>
</div>
</thead>
<tbody data-testid="table-body">
{customProperties.map((property, index) => (
<tr
className={classNames(
`tableBody-row ${!isEven(index + 1) && 'odd-row'}`,
{
'tw-border-b-0': index === customProperties.length - 1,
}
)}
data-testid="data-row"
key={uniqueId()}>
<td className="tableBody-cell">{property.name}</td>
<td className="tableBody-cell">
<PropertyValue
extension={extension}
propertyName={property.name}
propertyType={property.propertyType}
onExtensionUpdate={onExtensionUpdate}
/>
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</>
);
};

View File

@ -62,10 +62,30 @@ const ErrorPlaceHolder = ({ doc, type, children, heading, buttons }: Props) => {
width="100"
/>
</div>
{children && (
{children ? (
<div className="tw-flex tw-flex-col tw-items-center tw-mt-8 tw-text-base tw-font-medium">
{children}
</div>
) : (
<div className="tw-flex tw-flex-col tw-items-center tw-mt-8 tw-text-base tw-font-medium">
<Typography.Text className="tw-text-sm">
No Data Available
</Typography.Text>
<Typography.Text className="tw-text-sm">
Go ahead and add a new {heading}!
</Typography.Text>
{doc ? (
<Typography.Text className="tw-text-sm">
Still need help? Refer to our{' '}
<Typography.Link href={doc} target="_blank">
docs
</Typography.Link>{' '}
for more information.
</Typography.Text>
) : (
''
)}
</div>
)}
</div>
);

View File

@ -11,11 +11,13 @@
* limitations under the License.
*/
import { Typography } from 'antd';
import { uniqueId } from 'lodash';
import { observer } from 'mobx-react';
import React from 'react';
import AppState from '../../../AppState';
import { useAuthContext } from '../../../authentication/auth-provider/AuthProvider';
import { CONNECTORS_DOCS } from '../../../constants/docs.constants';
import { NoDataFoundPlaceHolder } from '../../../constants/services.const';
type Props = {
@ -75,14 +77,39 @@ const ErrorPlaceHolderES = ({ type, errorMessage, query = '' }: Props) => {
/>
</div>
<div className="tw-flex tw-flex-col tw-items-center tw-mt-6 tw-text-base tw-font-medium">
No matching data assets found
{query ? (
<>
{' '}
for{' '}
<span className="tw-text-primary tw-font-medium">{query}</span>
No matching data assets found
{query ? (
<>
{' '}
for{' '}
<span className="tw-text-primary tw-font-medium">
{query}
</span>
</>
) : null}
</>
) : null}
) : (
<>
{' '}
<Typography.Text className="tw-text-sm">
No Data Available
</Typography.Text>
<Typography.Text className="tw-text-sm">
Start by adding a service connection to ingest data into
OpenMetadata.
</Typography.Text>
<Typography.Text className="tw-text-sm">
Refer to our{' '}
<Typography.Link href={CONNECTORS_DOCS} target="_blank">
docs
</Typography.Link>{' '}
for more information.
</Typography.Text>
<span />
</>
)}
</div>
</div>
);

View File

@ -14,7 +14,7 @@
import { Col, Row, Space, Tooltip } from 'antd';
import { AxiosError } from 'axios';
import classNames from 'classnames';
import { isNil, isUndefined, startCase } from 'lodash';
import { isEmpty, isNil, isUndefined, startCase } from 'lodash';
import { ExtraInfo, ServiceOption, ServiceTypes } from 'Models';
import React, { Fragment, FunctionComponent, useEffect, useState } from 'react';
import { Link, useHistory, useParams } from 'react-router-dom';
@ -56,8 +56,10 @@ import {
PAGE_SIZE,
pagingObject,
} from '../../constants/constants';
import { CONNECTORS_DOCS } from '../../constants/docs.constants';
import { GlobalSettingsMenuCategory } from '../../constants/globalSettings.constants';
import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
import { servicesDisplayName } from '../../constants/services.const';
import { SearchIndex } from '../../enums/search.enum';
import { ServiceCategory } from '../../enums/service.enum';
import { OwnerType } from '../../enums/user.enum';
@ -995,20 +997,27 @@ const ServicePage: FunctionComponent = () => {
tabs={tabs}
/>
<div className="tw-flex-grow">
{activeTab === 1 && (
<Fragment>
<div
className="tw-my-4 tw-table-container"
data-testid="table-container">
<table
className="tw-bg-white tw-w-full"
data-testid="database-tables">
<thead>
<tr className="tableHead-row">{getTableHeaders()}</tr>
</thead>
<tbody className="tableBody">
{data.length > 0 ? (
data.map((dataObj, index) => (
{activeTab === 1 &&
(isEmpty(data) ? (
<ErrorPlaceHolder
doc={CONNECTORS_DOCS}
heading={servicesDisplayName[serviceName]}
/>
) : (
<Fragment>
<div
className="tw-my-4 tw-table-container"
data-testid="table-container">
<table
className="tw-bg-white tw-w-full"
data-testid="database-tables">
<thead>
<tr className="tableHead-row">
{getTableHeaders()}
</tr>
</thead>
<tbody className="tableBody">
{data.map((dataObj, index) => (
<tr
className={classNames(
'tableBody-row',
@ -1042,30 +1051,23 @@ const ServicePage: FunctionComponent = () => {
</td>
{getOptionalTableCells(dataObj as Database)}
</tr>
))
) : (
<tr className="tableBody-row">
<td
className="tableBody-cell tw-text-center"
colSpan={4}>
No records found.
</td>
</tr>
)}
</tbody>
</table>
</div>
{Boolean(!isNil(paging.after) || !isNil(paging.before)) && (
<NextPrevious
currentPage={currentPage}
pageSize={PAGE_SIZE}
paging={paging}
pagingHandler={pagingHandler}
totalCount={paging.total}
/>
)}
</Fragment>
)}
))}
</tbody>
</table>
</div>
{Boolean(
!isNil(paging.after) || !isNil(paging.before)
) && (
<NextPrevious
currentPage={currentPage}
pageSize={PAGE_SIZE}
paging={paging}
pagingHandler={pagingHandler}
totalCount={paging.total}
/>
)}
</Fragment>
))}
{activeTab === 2 && getIngestionTab()}

View File

@ -496,6 +496,6 @@
}
.tw-table-container {
@apply tw-bg-white tw-border tw-border-main tw-rounded tw-shadow;
@apply tw-bg-white tw-border tw-border-main tw-rounded;
}
}