This is an automated email from the ASF dual-hosted git repository.
likyh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
The following commit(s) were added to refs/heads/main by this push:
new 7484573f8 feat(config-ui): add no-data status for some pages (#4482)
7484573f8 is described below
commit 7484573f87760de98232da96aa3228ca79245650
Author: 青湛 <[email protected]>
AuthorDate: Wed Feb 22 14:45:26 2023 +0800
feat(config-ui): add no-data status for some pages (#4482)
* refactor(config-ui): adjust the component table
* feat(config-ui): add no-data status for some pages
---
config-ui/src/components/table/styled.ts | 24 ++++--
config-ui/src/components/table/table.tsx | 94 ++++++++++++++--------
config-ui/src/pages/blueprint/home/index.tsx | 14 +++-
config-ui/src/pages/connection/list/connection.tsx | 12 ++-
config-ui/src/pages/project/home/index.tsx | 28 +++----
config-ui/src/pages/transformation/home/index.tsx | 9 ++-
.../plugins/register/webook/connection/index.tsx | 18 ++++-
7 files changed, 132 insertions(+), 67 deletions(-)
diff --git a/config-ui/src/components/table/styled.ts
b/config-ui/src/components/table/styled.ts
index ecfcfaf9b..fb1b97dc7 100644
--- a/config-ui/src/components/table/styled.ts
+++ b/config-ui/src/components/table/styled.ts
@@ -22,16 +22,24 @@ export const Container = styled.div`
position: relative;
`;
-export const TableWrapper = styled.ul<{ loading: number }>`
- margin: 0;
- padding: 0;
- list-style: none;
- transition: opacity 0.3s linear;
+export const Loading = styled.div`
+ text-align: center;
+`;
+export const NoData = styled.div`
+ text-align: center;
+
+ img {
+ display: inline-block;
+ }
+`;
+
+export const Table = styled.ul<{ loading: number }>`
+ transition: opacity 0.3s linear;
${({ loading }) => (loading ? 'opacity: 0.2; ' : '')}
`;
-export const TableRow = styled.li`
+export const Row = styled.li`
display: flex;
align-items: center;
padding: 12px 16px;
@@ -43,13 +51,13 @@ export const TableRow = styled.li`
}
`;
-export const TableHeader = styled(TableRow)`
+export const Header = styled(Row)`
font-size: 14px;
font-weight: 600;
border-top: none;
`;
-export const TableMask = styled.div`
+export const Mask = styled.div`
position: absolute;
top: 0;
right: 0;
diff --git a/config-ui/src/components/table/table.tsx
b/config-ui/src/components/table/table.tsx
index 3a11449e0..71021e739 100644
--- a/config-ui/src/components/table/table.tsx
+++ b/config-ui/src/components/table/table.tsx
@@ -17,7 +17,9 @@
*/
import React from 'react';
+import { Button, Intent } from '@blueprintjs/core';
+import NoData from '@/images/no-data.svg';
import { Loading, Card } from '@/components';
import { ColumnType } from './types';
@@ -27,44 +29,66 @@ interface Props<T> {
loading?: boolean;
columns: ColumnType<T>;
dataSource: T[];
+ noData?: {
+ text?: React.ReactNode;
+ btnText?: string;
+ onCreate?: () => void;
+ };
}
-export const Table = <T extends Record<string, any>>({ loading, columns,
dataSource }: Props<T>) => {
+export const Table = <T extends Record<string, any>>({ loading, columns,
dataSource, noData = {} }: Props<T>) => {
+ const { text, btnText, onCreate } = noData;
+
return (
- <Card style={{ padding: 0 }}>
- <S.Container>
- <S.TableWrapper loading={loading ? 1 : 0}>
- <S.TableHeader>
- {columns.map(({ key, align = 'left', title }) => (
- <span key={key} style={{ textAlign: align }}>
- {title}
- </span>
- ))}
- </S.TableHeader>
- {dataSource.map((data, i) => (
- <S.TableRow key={i}>
- {columns.map(({ key, align = 'left', dataIndex, render }) => {
- const value = Array.isArray(dataIndex)
- ? dataIndex.reduce((acc, cur) => {
- acc[cur] = data[cur];
- return acc;
- }, {} as any)
- : data[dataIndex];
- return (
- <span key={key} style={{ textAlign: align }}>
- {render ? render(value, data) : value}
- </span>
- );
- })}
- </S.TableRow>
- ))}
- </S.TableWrapper>
- {loading && (
- <S.TableMask>
+ <S.Container>
+ {loading ? (
+ <Card>
+ <S.Loading>
<Loading />
- </S.TableMask>
- )}
- </S.Container>
- </Card>
+ </S.Loading>
+ </Card>
+ ) : !dataSource.length ? (
+ <Card>
+ <S.NoData>
+ <img src={NoData} alt="" />
+ <p>{text ?? 'No Data'}</p>
+ {onCreate && (
+ <Button intent={Intent.PRIMARY} icon="plus" onClick={onCreate}>
+ {btnText ?? 'Create'}
+ </Button>
+ )}
+ </S.NoData>
+ </Card>
+ ) : (
+ <Card style={{ padding: 0 }}>
+ <S.Table loading={loading ? 1 : 0}>
+ <S.Header>
+ {columns.map(({ key, align = 'left', title }) => (
+ <span key={key} style={{ textAlign: align }}>
+ {title}
+ </span>
+ ))}
+ </S.Header>
+ {dataSource.map((data, i) => (
+ <S.Row key={i}>
+ {columns.map(({ key, align = 'left', dataIndex, render }) => {
+ const value = Array.isArray(dataIndex)
+ ? dataIndex.reduce((acc, cur) => {
+ acc[cur] = data[cur];
+ return acc;
+ }, {} as any)
+ : data[dataIndex];
+ return (
+ <span key={key} style={{ textAlign: align }}>
+ {render ? render(value, data) : value}
+ </span>
+ );
+ })}
+ </S.Row>
+ ))}
+ </S.Table>
+ </Card>
+ )}
+ </S.Container>
);
};
diff --git a/config-ui/src/pages/blueprint/home/index.tsx
b/config-ui/src/pages/blueprint/home/index.tsx
index 85cea6500..e5ee303e9 100644
--- a/config-ui/src/pages/blueprint/home/index.tsx
+++ b/config-ui/src/pages/blueprint/home/index.tsx
@@ -90,6 +90,8 @@ export const BlueprintHomePage = () => {
[],
);
+ const handleCreate = () => history.push('/blueprints/create');
+
if (loading) {
return <PageLoading />;
}
@@ -113,9 +115,17 @@ export const BlueprintHomePage = () => {
/>
))}
</ButtonGroup>
- <Button intent={Intent.PRIMARY} text="Create Blueprint" onClick={()
=> history.push('/blueprints/create')} />
+ <Button icon="plus" intent={Intent.PRIMARY} text="New Blueprint"
onClick={handleCreate} />
</div>
- <Table columns={columns} dataSource={dataSource} />
+ <Table
+ columns={columns}
+ dataSource={dataSource}
+ noData={{
+ text: 'There is no Blueprint yet. Please add a new Blueprint here
or from a Project.',
+ btnText: 'New Blueprint',
+ onCreate: handleCreate,
+ }}
+ />
</S.Wrapper>
</PageHeader>
);
diff --git a/config-ui/src/pages/connection/list/connection.tsx
b/config-ui/src/pages/connection/list/connection.tsx
index 49387335a..a32909612 100644
--- a/config-ui/src/pages/connection/list/connection.tsx
+++ b/config-ui/src/pages/connection/list/connection.tsx
@@ -121,10 +121,18 @@ export const Connection = ({ plugin }: Props) => {
return (
<S.Wrapper>
<ButtonGroup className="action">
- <Button intent={Intent.PRIMARY} icon="plus" text="Add Connection"
onClick={handleCreate} />
+ <Button intent={Intent.PRIMARY} icon="plus" text="New Connection"
onClick={handleCreate} />
<Button icon="refresh" text="Refresh Connections"
onClick={handleRefresh} />
</ButtonGroup>
- <Table columns={columns} dataSource={connections} />
+ <Table
+ columns={columns}
+ dataSource={connections}
+ noData={{
+ text: 'There is no data connection yet. Please add a new
connection.',
+ btnText: 'New Connection',
+ onCreate: handleCreate,
+ }}
+ />
</S.Wrapper>
);
};
diff --git a/config-ui/src/pages/project/home/index.tsx
b/config-ui/src/pages/project/home/index.tsx
index 4cd3c5e31..2941b8e3e 100644
--- a/config-ui/src/pages/project/home/index.tsx
+++ b/config-ui/src/pages/project/home/index.tsx
@@ -20,8 +20,7 @@ import React, { useMemo, useState } from 'react';
import { Link, useHistory } from 'react-router-dom';
import { Button, InputGroup, Checkbox, Intent } from '@blueprintjs/core';
-import NoData from '@/images/no-data.svg';
-import { PageHeader, Card, Table, ColumnType, Dialog } from '@/components';
+import { PageHeader, Table, ColumnType, Dialog } from '@/components';
import { useProject } from './use-project';
import * as S from './styled';
@@ -87,21 +86,16 @@ export const ProjectHomePage = () => {
}
>
<S.Container>
- {!projects.length ? (
- <Card className="card">
- <div className="logo">
- <img src={NoData} alt="" />
- </div>
- <div className="desc">
- <p>Add new projects to see engineering metrics based on
projects.</p>
- </div>
- <div className="action">
- <Button intent={Intent.PRIMARY} icon="plus" text="New Project"
onClick={handleShowDialog} />
- </div>
- </Card>
- ) : (
- <Table loading={loading} columns={columns} dataSource={projects} />
- )}
+ <Table
+ loading={loading}
+ columns={columns}
+ dataSource={projects}
+ noData={{
+ text: 'Add new projects to see engineering metrics based on
projects.',
+ btnText: 'New Project',
+ onCreate: handleShowDialog,
+ }}
+ />
<Dialog
isOpen={isOpen}
title="Create a New Project"
diff --git a/config-ui/src/pages/transformation/home/index.tsx
b/config-ui/src/pages/transformation/home/index.tsx
index f660bb84d..840af9e9e 100644
--- a/config-ui/src/pages/transformation/home/index.tsx
+++ b/config-ui/src/pages/transformation/home/index.tsx
@@ -33,6 +33,8 @@ export const TransformationHomePage = () => {
const history = useHistory();
+ const handleCreate = () => setIsOpen(true);
+
const columns = useMemo(
() =>
[
@@ -86,11 +88,16 @@ export const TransformationHomePage = () => {
/>
))}
</ButtonGroup>
- <Button intent={Intent.PRIMARY} text="Create Transformation"
onClick={() => setIsOpen(true)} />
+ <Button icon="plus" intent={Intent.PRIMARY} text="New
Transformation" onClick={handleCreate} />
</div>
<Table
columns={columns}
dataSource={transformations.filter((ts) => (active === 'All' ?
true : ts.plugin === active))}
+ noData={{
+ text: 'There is no transformation yet. Please add a new
transformation.',
+ btnText: 'New Transformation',
+ onCreate: handleCreate,
+ }}
/>
<Dialog
isOpen={isOpen}
diff --git a/config-ui/src/plugins/register/webook/connection/index.tsx
b/config-ui/src/plugins/register/webook/connection/index.tsx
index 602011409..c2bc368c9 100644
--- a/config-ui/src/plugins/register/webook/connection/index.tsx
+++ b/config-ui/src/plugins/register/webook/connection/index.tsx
@@ -19,7 +19,7 @@
import React, { useState } from 'react';
import { ButtonGroup, Button, Icon, Intent } from '@blueprintjs/core';
-import { Table, ColumnType } from '@/components';
+import { Table, ColumnType, ExternalLink } from '@/components';
import type { WebhookItemType } from '../types';
import { WebhookCreateDialog } from '../create-dialog';
@@ -83,7 +83,21 @@ export const WebHookConnection = ({ onCreateAfter, ...props
}: Props) => {
<ButtonGroup>
<Button icon="plus" text="Add a Webhook" intent={Intent.PRIMARY}
onClick={() => handleShowDialog('add')} />
</ButtonGroup>
- <Table loading={loading} columns={columns} dataSource={connections} />
+ <Table
+ loading={loading}
+ columns={columns}
+ dataSource={connections}
+ noData={{
+ text: (
+ <>
+ There is no Webhook yet. Please add a new Webhook.{' '}
+ <ExternalLink
link="https://devlake.apache.org/docs/Configuration/webhook">Learn
more</ExternalLink>
+ </>
+ ),
+ btnText: 'Add a Webhook',
+ onCreate: () => handleShowDialog('add'),
+ }}
+ />
{type === 'add' && (
<WebhookCreateDialog
isOpen