Skip to content

Commit

Permalink
[GSoC2024] Enhancement of empty list components (cvat-ai#7659)
Browse files Browse the repository at this point in the history
### Motivation and context
Fixes cvat-ai#7657 Made all of the empty-list components ui consistent.

### Checklist
- [x] I have created a changelog fragment <!-- see top comment in
CHANGELOG.md -->
- [x] I submit my changes into the `develop` branch
- [x] I have linked related issues (see [GitHub docs](

https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword))

### License

- [x] I submit _my code changes_ under the same [MIT License](
https://github.com/opencv/cvat/blob/develop/LICENSE) that covers the
project.
  Feel free to contact the maintainers if that's a concern.

---------

Co-authored-by: syedbarimanjan <[email protected]>
Co-authored-by: Boris Sekachev <[email protected]>
Co-authored-by: Kirill Lakhov <[email protected]>
  • Loading branch information
4 people authored Apr 5, 2024
1 parent 6c57c03 commit f1db0fd
Show file tree
Hide file tree
Showing 22 changed files with 226 additions and 163 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Fixed

- Standardize the alignment of empty-list components
(<https://github.com/opencv/cvat/pull/7659>)
2 changes: 1 addition & 1 deletion cvat-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-ui",
"version": "1.63.5",
"version": "1.63.6",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand All @@ -7,6 +8,7 @@ import Pagination from 'antd/lib/pagination';
import { Row, Col } from 'antd/lib/grid';

import { CloudStorage } from 'reducers';
import dimensions from 'utils/dimensions';
import CloudStorageItemComponent from './cloud-storage-item';

interface Props {
Expand Down Expand Up @@ -36,7 +38,7 @@ export default function StoragesList(props: Props): JSX.Element {
return (
<>
<Row justify='center' align='middle'>
<Col span={24} className='cvat-cloud-storages-list'>
<Col {...dimensions} className='cvat-cloud-storages-list'>
{groupedStorages.map(
(instances: CloudStorage[]): JSX.Element => (
<Row key={instances[0].id} gutter={[8, 8]}>
Expand Down
95 changes: 44 additions & 51 deletions cvat-ui/src/components/cloud-storages-page/cloud-storages-page.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
// Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import './styles.scss';
import React, { useCallback, useEffect, useState } from 'react';
import { useHistory } from 'react-router';
import { useDispatch, useSelector } from 'react-redux';
import { Row, Col } from 'antd/lib/grid';
import { Row } from 'antd/lib/grid';
import Spin from 'antd/lib/spin';

import { CombinedState, Indexable } from 'reducers';
import { CloudStoragesQuery, CombinedState, Indexable } from 'reducers';
import { getCloudStoragesAsync } from 'actions/cloud-storage-actions';
import { updateHistoryFromQuery } from 'components/resource-sorting-filtering';
import { anySearch } from 'utils/any-search';
import CloudStoragesListComponent from './cloud-storages-list';
import EmptyCloudStorageListComponent from './empty-cloud-storages-list';
import EmptyListComponent from './empty-list';
import TopBarComponent from './top-bar';

export default function StoragesPageComponent(): JSX.Element {
Expand Down Expand Up @@ -57,15 +59,8 @@ export default function StoragesPageComponent(): JSX.Element {
[query],
);

const dimensions = {
md: 22,
lg: 18,
xl: 16,
xxl: 16,
};
const isAnySearch = anySearch<CloudStoragesQuery>(query);

const anySearch = Object.keys(query)
.some((value: string) => value !== 'page' && (query as any)[value] !== null);
const content = current.length ? (
<CloudStoragesListComponent
totalCount={totalCount}
Expand All @@ -74,48 +69,46 @@ export default function StoragesPageComponent(): JSX.Element {
onChangePage={onChangePage}
/>
) : (
<EmptyCloudStorageListComponent notFound={anySearch} />
<EmptyListComponent notFound={isAnySearch} />
);

return (
<Row className='cvat-cloud-storages-page' justify='center' align='top'>
<Col {...dimensions}>
<TopBarComponent
onApplySearch={(_search: string | null) => {
dispatch(
getCloudStoragesAsync({
...query,
search: _search,
page: 1,
}),
);
}}
onApplyFilter={(filter: string | null) => {
dispatch(
getCloudStoragesAsync({
...query,
filter,
page: 1,
}),
);
}}
onApplySorting={(sorting: string | null) => {
dispatch(
getCloudStoragesAsync({
...query,
sort: sorting,
page: 1,
}),
);
}}
query={updatedQuery}
/>
{ fetching ? (
<Row className='cvat-cloud-storages-page' justify='center' align='middle'>
<Spin size='large' />
</Row>
) : content }
</Col>
</Row>
<div className='cvat-cloud-storages-page'>
<TopBarComponent
onApplySearch={(_search: string | null) => {
dispatch(
getCloudStoragesAsync({
...query,
search: _search,
page: 1,
}),
);
}}
onApplyFilter={(filter: string | null) => {
dispatch(
getCloudStoragesAsync({
...query,
filter,
page: 1,
}),
);
}}
onApplySorting={(sorting: string | null) => {
dispatch(
getCloudStoragesAsync({
...query,
sort: sorting,
page: 1,
}),
);
}}
query={updatedQuery}
/>
{ fetching ? (
<Row className='cvat-cloud-storages-page' justify='center' align='middle'>
<Spin size='large' />
</Row>
) : content }
</div>
);
}

This file was deleted.

49 changes: 49 additions & 0 deletions cvat-ui/src/components/cloud-storages-page/empty-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import React from 'react';

import Empty from 'antd/lib/empty';
import { Row, Col } from 'antd/lib/grid';
import Text from 'antd/lib/typography/Text';
import { CloudOutlined } from '@ant-design/icons';
import { Link } from 'react-router-dom';

interface Props {
notFound: boolean;
}

export default function EmptyListComponent(props: Props): JSX.Element {
const { notFound } = props;

return (
<div className='cvat-empty-cloud-storages-list'>
<Empty
description={notFound ? (
<Text strong>No results matched your search...</Text>
) : (
<>
<Row justify='center' align='middle'>
<Col>
<Text strong>No cloud storages attached yet...</Text>
</Col>
</Row>
<Row justify='center' align='middle'>
<Col>
<Text type='secondary'>To get started with your cloud storage</Text>
</Col>
</Row>
<Row justify='center' align='middle'>
<Col>
<Link to='/cloudstorages/create'>attach a new one</Link>
</Col>
</Row>
</>
)}
image={notFound ? Empty.PRESENTED_IMAGE_DEFAULT : <CloudOutlined className='cvat-empty-cloud-storages-list-icon' />}
/>
</div>
);
}
17 changes: 13 additions & 4 deletions cvat-ui/src/components/cloud-storages-page/styles.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

@import '../../base.scss';
@import '../../base';

.cvat-cloud-storages-page {
padding: $grid-unit-size * 2;
padding-top: $grid-unit-size * 2;
padding-bottom: $grid-unit-size;
height: 100%;
width: 100%;
overflow: auto;

.ant-spin {
Expand Down Expand Up @@ -56,7 +58,14 @@

.cvat-cloud-storages-list,
.cvat-empty-cloud-storages-list {
margin-top: $grid-unit-size * 2;
margin-top: $grid-unit-size;

.ant-empty {
top: 50%;
left: 50%;
position: absolute;
transform: translate(-50%, -50%);
}
}

.cvat-cloud-storage-item {
Expand Down
7 changes: 5 additions & 2 deletions cvat-ui/src/components/cloud-storages-page/top-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand All @@ -12,6 +13,8 @@ import { CloudStoragesQuery } from 'reducers';
import Input from 'antd/lib/input';
import { SortingComponent, ResourceFilterHOC, defaultVisibility } from 'components/resource-sorting-filtering';

import dimensions from 'utils/dimensions';

import {
localStorageRecentKeyword, localStorageRecentCapacity,
predefinedFilterValues, config,
Expand All @@ -36,8 +39,8 @@ export default function StoragesTopBar(props: Props): JSX.Element {
const [visibility, setVisibility] = useState(defaultVisibility);

return (
<Row justify='space-between' align='middle' className='cvat-cloud-storages-list-top-bar'>
<Col span={24}>
<Row justify='center' align='middle' className='cvat-cloud-storages-list-top-bar'>
<Col {...dimensions}>
<div className='cvat-cloudstorages-page-filters-wrapper'>
<Input.Search
enterButton
Expand Down
3 changes: 1 addition & 2 deletions cvat-ui/src/components/invitations-page/invitations-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ import Pagination from 'antd/lib/pagination';
import { CombinedState, InvitationsQuery } from 'reducers';
import { Invitation } from 'cvat-core/src/organization';
import { acceptInvitationAsync, getInvitationsAsync, declineInvitationAsync } from 'actions/invitations-actions';
import dimensions from 'utils/dimensions';
import InvitationItem from './invitation-item';

import dimensions from '../projects-page/dimensions';

interface Props {
query: InvitationsQuery;
}
Expand Down
49 changes: 49 additions & 0 deletions cvat-ui/src/components/jobs-page/empty-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import React from 'react';
import { Link } from 'react-router-dom';
import Text from 'antd/lib/typography/Text';
import { Row, Col } from 'antd/lib/grid';

import Empty from 'antd/lib/empty';

interface Props {
notFound: boolean;
}

function EmptyListComponent(props: Props): JSX.Element {
const { notFound } = props;

return (
<div className='cvat-empty-jobs-list'>
<Empty description={notFound ?
(<Text strong>No results matched your search...</Text>) : (
<>
<Row justify='center' align='middle'>
<Col>
<Text strong>No jobs created yet...</Text>
</Col>
</Row>
<Row justify='center' align='middle'>
<Col>
<Text type='secondary'>To get started with your annotation project</Text>
</Col>
</Row>
<Row justify='center' align='middle'>
<Col>
<Link to='/tasks/create'>create a new task</Link>
<Text type='secondary'> or try to </Text>
<Link to='/projects/create'>create a new project</Link>
</Col>
</Row>
</>
)}
/>
</div>
);
}

export default React.memo(EmptyListComponent);
Loading

0 comments on commit f1db0fd

Please sign in to comment.