mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-23 01:16:27 +02:00
feat: empty state application list improvements (#6579)
This commit is contained in:
parent
45634689f8
commit
59ee0b3bbe
@ -1,201 +0,0 @@
|
|||||||
import { useMemo } from 'react';
|
|
||||||
import { Avatar, CircularProgress, Icon, Link } from '@mui/material';
|
|
||||||
import Warning from '@mui/icons-material/Warning';
|
|
||||||
import { styles as themeStyles } from 'component/common';
|
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
|
||||||
import useApplications from 'hooks/api/getters/useApplications/useApplications';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { Search } from 'component/common/Search/Search';
|
|
||||||
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
|
||||||
import {
|
|
||||||
SortableTableHeader,
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableRow,
|
|
||||||
} from 'component/common/Table';
|
|
||||||
import { useGlobalFilter, useSortBy, useTable } from 'react-table';
|
|
||||||
import { sortTypes } from 'utils/sortTypes';
|
|
||||||
import { IconCell } from 'component/common/Table/cells/IconCell/IconCell';
|
|
||||||
import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell';
|
|
||||||
import { ApplicationUsageCell } from './ApplicationUsageCell/ApplicationUsageCell';
|
|
||||||
import { ApplicationSchema } from 'openapi';
|
|
||||||
|
|
||||||
export const ApplicationList = () => {
|
|
||||||
const { applications: data, loading } = useApplications();
|
|
||||||
|
|
||||||
const renderNoApplications = () => (
|
|
||||||
<>
|
|
||||||
<section style={{ textAlign: 'center' }}>
|
|
||||||
<Warning titleAccess='Warning' /> <br />
|
|
||||||
<br />
|
|
||||||
Oh snap, it does not seem like you have connected any
|
|
||||||
applications. To connect your application to Unleash you will
|
|
||||||
require a Client SDK.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You can read more about how to use Unleash in your application
|
|
||||||
in the{' '}
|
|
||||||
<Link href='https://docs.getunleash.io/docs/sdks/'>
|
|
||||||
documentation.
|
|
||||||
</Link>
|
|
||||||
</section>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
const initialState = useMemo(
|
|
||||||
() => ({
|
|
||||||
sortBy: [{ id: 'name', desc: false }],
|
|
||||||
hiddenColumns: ['description', 'sortOrder'],
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const columns = useMemo(
|
|
||||||
() => [
|
|
||||||
{
|
|
||||||
id: 'Icon',
|
|
||||||
Cell: ({
|
|
||||||
row: {
|
|
||||||
original: { icon },
|
|
||||||
},
|
|
||||||
}: any) => (
|
|
||||||
<IconCell
|
|
||||||
icon={
|
|
||||||
<Avatar>
|
|
||||||
<Icon>{icon || 'apps'}</Icon>
|
|
||||||
</Avatar>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
disableGlobalFilter: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Header: 'Name',
|
|
||||||
accessor: 'appName',
|
|
||||||
width: '50%',
|
|
||||||
Cell: ({
|
|
||||||
row: {
|
|
||||||
original: { appName, description },
|
|
||||||
},
|
|
||||||
}: any) => (
|
|
||||||
<LinkCell
|
|
||||||
title={appName}
|
|
||||||
to={`/applications/${appName}`}
|
|
||||||
subtitle={description}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
sortType: 'alphanumeric',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Header: 'Project(environment)',
|
|
||||||
accessor: 'usage',
|
|
||||||
width: '50%',
|
|
||||||
Cell: ({
|
|
||||||
row: { original },
|
|
||||||
}: {
|
|
||||||
row: { original: ApplicationSchema };
|
|
||||||
}) => <ApplicationUsageCell usage={original.usage} />,
|
|
||||||
sortType: 'alphanumeric',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessor: 'description',
|
|
||||||
disableSortBy: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessor: 'sortOrder',
|
|
||||||
disableGlobalFilter: true,
|
|
||||||
sortType: 'number',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const {
|
|
||||||
getTableProps,
|
|
||||||
getTableBodyProps,
|
|
||||||
headerGroups,
|
|
||||||
rows,
|
|
||||||
prepareRow,
|
|
||||||
state: { globalFilter },
|
|
||||||
setGlobalFilter,
|
|
||||||
} = useTable(
|
|
||||||
{
|
|
||||||
columns: columns as any[], // TODO: fix after `react-table` v8 update
|
|
||||||
data,
|
|
||||||
initialState,
|
|
||||||
sortTypes,
|
|
||||||
autoResetGlobalFilter: false,
|
|
||||||
autoResetSortBy: false,
|
|
||||||
disableSortRemove: true,
|
|
||||||
},
|
|
||||||
useGlobalFilter,
|
|
||||||
useSortBy,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return <CircularProgress variant='indeterminate' />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<PageContent
|
|
||||||
header={
|
|
||||||
<PageHeader
|
|
||||||
title={`Applications (${rows.length})`}
|
|
||||||
actions={
|
|
||||||
<Search
|
|
||||||
initialValue={globalFilter}
|
|
||||||
onChange={setGlobalFilter}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div className={themeStyles.fullwidth}>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={data.length > 0}
|
|
||||||
show={
|
|
||||||
<SearchHighlightProvider value={globalFilter}>
|
|
||||||
<Table {...getTableProps()}>
|
|
||||||
<SortableTableHeader
|
|
||||||
headerGroups={headerGroups}
|
|
||||||
/>
|
|
||||||
<TableBody {...getTableBodyProps()}>
|
|
||||||
{rows.map((row) => {
|
|
||||||
prepareRow(row);
|
|
||||||
return (
|
|
||||||
<TableRow
|
|
||||||
hover
|
|
||||||
{...row.getRowProps()}
|
|
||||||
>
|
|
||||||
{row.cells.map((cell) => (
|
|
||||||
<TableCell
|
|
||||||
{...cell.getCellProps()}
|
|
||||||
>
|
|
||||||
{cell.render(
|
|
||||||
'Cell',
|
|
||||||
)}
|
|
||||||
</TableCell>
|
|
||||||
))}
|
|
||||||
</TableRow>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</SearchHighlightProvider>
|
|
||||||
}
|
|
||||||
elseShow={
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={loading}
|
|
||||||
show={<div>...loading</div>}
|
|
||||||
elseShow={renderNoApplications()}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</PageContent>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
@ -28,9 +28,9 @@ test('Display applications list', async () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Display no applications', async () => {
|
test('Display no applications connected', async () => {
|
||||||
setupApi([]);
|
setupApi([]);
|
||||||
render(<PaginatedApplicationList />);
|
render(<PaginatedApplicationList />);
|
||||||
|
|
||||||
await screen.findByText('Warning');
|
await screen.findByText(/To connect your application to Unleash/);
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { Avatar, Icon, Link } from '@mui/material';
|
import { Avatar, Icon, Link, styled } from '@mui/material';
|
||||||
import Warning from '@mui/icons-material/Warning';
|
|
||||||
import { styles as themeStyles } from 'component/common';
|
import { styles as themeStyles } from 'component/common';
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
@ -26,23 +25,34 @@ import { withTableState } from 'utils/withTableState';
|
|||||||
import useLoading from 'hooks/useLoading';
|
import useLoading from 'hooks/useLoading';
|
||||||
import mapValues from 'lodash.mapvalues';
|
import mapValues from 'lodash.mapvalues';
|
||||||
|
|
||||||
const renderNoApplications = () => (
|
const InfoMessage = styled('div')(({ theme }) => ({
|
||||||
<>
|
textAlign: 'center',
|
||||||
<section style={{ textAlign: 'center' }}>
|
padding: theme.spacing(9, 0, 9, 0),
|
||||||
<Warning titleAccess='Warning' /> <br />
|
minHeight: '150px',
|
||||||
<br />
|
}));
|
||||||
Oh snap, it does not seem like you have connected any applications.
|
|
||||||
To connect your application to Unleash you will require a Client
|
const renderNoResults = (query: string | null | undefined) => {
|
||||||
SDK.
|
if (typeof query === 'string' && query.length > 0) {
|
||||||
<br />
|
return renderNoMatchingSearch(query);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<InfoMessage>
|
||||||
|
You don't have have any connected applications. To connect your
|
||||||
|
application to Unleash you will require a{' '}
|
||||||
|
<Link href='https://docs.getunleash.io/docs/sdks/'>Client SDK</Link>
|
||||||
|
.
|
||||||
<br />
|
<br />
|
||||||
You can read more about how to use Unleash in your application in
|
You can read more about how to use Unleash in your application in
|
||||||
the{' '}
|
the{' '}
|
||||||
<Link href='https://docs.getunleash.io/docs/sdks/'>
|
<Link href='https://docs.getunleash.io/docs/sdks/'>
|
||||||
documentation.
|
documentation.
|
||||||
</Link>
|
</Link>
|
||||||
</section>
|
</InfoMessage>
|
||||||
</>
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderNoMatchingSearch = (query: string) => (
|
||||||
|
<InfoMessage>No application found matching "{query}"</InfoMessage>
|
||||||
);
|
);
|
||||||
|
|
||||||
const columnHelper = createColumnHelper<ApplicationSchema>();
|
const columnHelper = createColumnHelper<ApplicationSchema>();
|
||||||
@ -125,8 +135,6 @@ export const PaginatedApplicationList = () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const rows = table.getRowModel().rows;
|
|
||||||
|
|
||||||
const { offset, limit, query, sortBy, sortOrder, ...filterState } =
|
const { offset, limit, query, sortBy, sortOrder, ...filterState } =
|
||||||
tableState;
|
tableState;
|
||||||
|
|
||||||
@ -165,7 +173,7 @@ export const PaginatedApplicationList = () => {
|
|||||||
</div>
|
</div>
|
||||||
</SearchHighlightProvider>
|
</SearchHighlightProvider>
|
||||||
}
|
}
|
||||||
elseShow={renderNoApplications()}
|
elseShow={renderNoResults(query)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</PageContent>
|
</PageContent>
|
||||||
|
Loading…
Reference in New Issue
Block a user