Skip to content

Commit

Permalink
Added filters and sorting options for job list, added tooltip for tas…
Browse files Browse the repository at this point in the history
…ks filters (#3030)

* Added filters & sorters for job list

* Added tooltip

* Updated version & changelog

* Added tooltip for project search

* Fixed eslint
  • Loading branch information
Boris Sekachev authored Mar 31, 2021
1 parent 390ff3e commit 8f426ab
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 20 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Annotations filters UI using react-awesome-query-builder (https://github.com/openvinotoolkit/cvat/issues/1418)
- Storing settings in local storage to keep them between browser sessions (<https://github.com/openvinotoolkit/cvat/pull/3017>)
- [ICDAR](https://rrc.cvc.uab.es/?ch=2) format support (<https://github.com/openvinotoolkit/cvat/pull/2866>)
- Added switcher to maintain poylgon crop behaviour (<https://github.com/openvinotoolkit/cvat/pull/3021>)
- Added switcher to maintain poylgon crop behaviour (<https://github.com/openvinotoolkit/cvat/pull/3021>
- Filters and sorting options for job list, added tooltip for tasks filters (<https://github.com/openvinotoolkit/cvat/pull/3030>)

### Changed

Expand Down
2 changes: 1 addition & 1 deletion cvat-ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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.17.0",
"version": "1.18.0",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
Expand Down
22 changes: 14 additions & 8 deletions cvat-ui/src/components/projects-page/search-field.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT

Expand All @@ -7,6 +7,7 @@ import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import Search from 'antd/lib/input/Search';

import SearchTooltip from 'components/search-tooltip/search-tooltip';
import { CombinedState, ProjectsQuery } from 'reducers/interfaces';
import { getProjectsAsync } from 'actions/projects-actions';

Expand Down Expand Up @@ -37,7 +38,10 @@ export default function ProjectSearchField(): JSX.Element {

const handleSearch = (value: string): void => {
const query = { ...gettingQuery };
const search = value.replace(/\s+/g, ' ').replace(/\s*:+\s*/g, ':').trim();
const search = value
.replace(/\s+/g, ' ')
.replace(/\s*:+\s*/g, ':')
.trim();

const fields = Object.keys(query).filter((key) => key !== 'page');
for (const field of fields) {
Expand Down Expand Up @@ -71,11 +75,13 @@ export default function ProjectSearchField(): JSX.Element {
};

return (
<Search
defaultValue={getSearchField(gettingQuery)}
onSearch={handleSearch}
size='large'
placeholder='Search'
/>
<SearchTooltip instance='project'>
<Search
defaultValue={getSearchField(gettingQuery)}
onSearch={handleSearch}
size='large'
placeholder='Search'
/>
</SearchTooltip>
);
}
94 changes: 94 additions & 0 deletions cvat-ui/src/components/search-tooltip/search-tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright (C) 2021 Intel Corporation
//
// SPDX-License-Identifier: MIT

import React from 'react';

import Text from 'antd/lib/typography/Text';
import Paragraph from 'antd/lib/typography/Paragraph';

import './styles.scss';
import CVATTooltip from 'components/common/cvat-tooltip';

interface Props {
instance: 'task' | 'project';
children: JSX.Element;
}

export default function SearchTooltip(props: Props): JSX.Element {
const { instance, children } = props;
const instances = ` ${instance}s `;

return (
<CVATTooltip
overlayClassName={`cvat-${instance}s-search-tooltip`}
title={(
<>
<Paragraph>
<Text strong>owner: admin</Text>
<Text>
all
{instances}
created by the user who has the substring
<q>admin</q>
in their username
</Text>
</Paragraph>
<Paragraph>
<Text strong>assignee: employee</Text>
<Text>
all
{instances}
which are assigned to a user who has the substring
<q>admin</q>
in their username
</Text>
</Paragraph>
<Paragraph>
<Text strong>name: training</Text>
<Text>
all
{instances}
with the substring
<q>training</q>
in its name
</Text>
</Paragraph>
{instance === 'task' ? (
<Paragraph>
<Text strong>mode: annotation</Text>
<Text>
annotation tasks are tasks with images, interpolation tasks are tasks with videos
</Text>
</Paragraph>
) : null}
<Paragraph>
<Text strong>status: annotation</Text>
<Text>annotation, validation, or completed</Text>
</Paragraph>
<Paragraph>
<Text strong>id: 5</Text>
<Text>
the
{` ${instance} `}
with id 5
</Text>
</Paragraph>
<Paragraph>
<Text>
Filters can be combined (to the exclusion of id) using the keyword AND. Example:
<Text type='warning'>
<q>status: annotation AND owner: admin</q>
</Text>
</Text>
</Paragraph>
<Paragraph>
<Text type='success'>Search within all the string fields by default</Text>
</Paragraph>
</>
)}
>
{children}
</CVATTooltip>
);
}
16 changes: 16 additions & 0 deletions cvat-ui/src/components/search-tooltip/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (C) 2021 Intel Corporation
//
// SPDX-License-Identifier: MIT

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

.cvat-projects-search-tooltip,
.cvat-tasks-search-tooltip {
span {
color: white;
}

strong::after {
content: ' - ';
}
}
59 changes: 58 additions & 1 deletion cvat-ui/src/components/task-page/job-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { RouteComponentProps } from 'react-router';
import { withRouter } from 'react-router-dom';
import { Row, Col } from 'antd/lib/grid';
import { LoadingOutlined, QuestionCircleOutlined, CopyOutlined } from '@ant-design/icons';
import { ColumnFilterItem } from 'antd/lib/table/interface';
import Table from 'antd/lib/table';
import Button from 'antd/lib/button';
import Text from 'antd/lib/typography/Text';
Expand Down Expand Up @@ -101,6 +102,46 @@ function JobListComponent(props: Props & RouteComponentProps): JSX.Element {
} = props;

const { jobs, id: taskId } = taskInstance;

function sorter(path: string) {
return (obj1: any, obj2: any): number => {
let currentObj1 = obj1;
let currentObj2 = obj2;
let field1: string | null = null;
let field2: string | null = null;
for (const pathSegment of path.split('.')) {
field1 = currentObj1 && pathSegment in currentObj1 ? currentObj1[pathSegment] : null;
field2 = currentObj2 && pathSegment in currentObj2 ? currentObj2[pathSegment] : null;
currentObj1 = currentObj1 && pathSegment in currentObj1 ? currentObj1[pathSegment] : null;
currentObj2 = currentObj2 && pathSegment in currentObj2 ? currentObj2[pathSegment] : null;
}

if (field1 && field2) {
return field1.localeCompare(field2);
}

if (field1 === null) {
return 1;
}

return -1;
};
}

function collectUsers(path: string): ColumnFilterItem[] {
return Array.from<string | null>(
new Set(
jobs.map((job: any) => {
if (job[path] === null) {
return null;
}

return job[path].username;
}),
),
).map((value: string | null) => ({ text: value || 'Is Empty', value: value || false }));
}

const columns = [
{
title: 'Job',
Expand Down Expand Up @@ -152,6 +193,13 @@ function JobListComponent(props: Props & RouteComponentProps): JSX.Element {
</Text>
);
},
sorter: sorter('status.status'),
filters: [
{ text: 'annotation', value: 'annotation' },
{ text: 'validation', value: 'validation' },
{ text: 'completed', value: 'completed' },
],
onFilter: (value: string | number | boolean, record: any) => record.status.status === value,
},
{
title: 'Started on',
Expand Down Expand Up @@ -180,6 +228,10 @@ function JobListComponent(props: Props & RouteComponentProps): JSX.Element {
}}
/>
),
sorter: sorter('assignee.assignee.username'),
filters: collectUsers('assignee'),
onFilter: (value: string | number | boolean, record: any) =>
(record.assignee.assignee?.username || false) === value,
},
{
title: 'Reviewer',
Expand All @@ -196,6 +248,10 @@ function JobListComponent(props: Props & RouteComponentProps): JSX.Element {
}}
/>
),
sorter: sorter('reviewer.reviewer.username'),
filters: collectUsers('reviewer'),
onFilter: (value: string | number | boolean, record: any) =>
(record.reviewer.reviewer?.username || false) === value,
},
];

Expand All @@ -207,13 +263,14 @@ function JobListComponent(props: Props & RouteComponentProps): JSX.Element {

const created = moment(props.taskInstance.createdDate);

const now = moment(moment.now());
acc.push({
key: job.id,
job: job.id,
frames: `${job.startFrame}-${job.stopFrame}`,
status: job,
started: `${created.format('MMMM Do YYYY HH:MM')}`,
duration: `${moment.duration(moment(moment.now()).diff(created)).humanize()}`,
duration: `${moment.duration(now.diff(created)).humanize()}`,
assignee: job,
reviewer: job,
});
Expand Down
20 changes: 12 additions & 8 deletions cvat-ui/src/components/tasks-page/top-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT

Expand All @@ -10,6 +10,8 @@ import Button from 'antd/lib/button';
import Input from 'antd/lib/input';
import Text from 'antd/lib/typography/Text';

import SearchTooltip from 'components/search-tooltip/search-tooltip';

interface VisibleTopBarProps {
onSearch: (value: string) => void;
searchValue: string;
Expand All @@ -25,13 +27,15 @@ export default function TopBarComponent(props: VisibleTopBarProps): JSX.Element
<Row justify='center' align='middle'>
<Col md={11} lg={9} xl={8} xxl={7}>
<Text className='cvat-title'>Tasks</Text>
<Input.Search
className='cvat-task-page-search-task'
defaultValue={searchValue}
onSearch={onSearch}
size='large'
placeholder='Search'
/>
<SearchTooltip instance='task'>
<Input.Search
className='cvat-task-page-search-task'
defaultValue={searchValue}
onSearch={onSearch}
size='large'
placeholder='Search'
/>
</SearchTooltip>
</Col>
<Col md={{ span: 11 }} lg={{ span: 9 }} xl={{ span: 8 }} xxl={{ span: 7 }}>
<Button
Expand Down

0 comments on commit 8f426ab

Please sign in to comment.