Enhanced filtration/sorting for tasks/projects/tasks in projects/cloud storages (#4409)
parent
53f6699d40
commit
1225fbb1bc
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 9.1 KiB |
@ -0,0 +1,83 @@
|
|||||||
|
// Copyright (C) 2022 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
import { Config } from 'react-awesome-query-builder';
|
||||||
|
|
||||||
|
export const config: Partial<Config> = {
|
||||||
|
fields: {
|
||||||
|
id: {
|
||||||
|
label: 'ID',
|
||||||
|
type: 'number',
|
||||||
|
operators: ['equal', 'between', 'greater', 'greater_or_equal', 'less', 'less_or_equal'],
|
||||||
|
fieldSettings: { min: 0 },
|
||||||
|
valueSources: ['value'],
|
||||||
|
},
|
||||||
|
provider_type: {
|
||||||
|
label: 'Provider type',
|
||||||
|
type: 'select',
|
||||||
|
operators: ['select_equals'],
|
||||||
|
valueSources: ['value'],
|
||||||
|
fieldSettings: {
|
||||||
|
listValues: [
|
||||||
|
{ value: 'AWS_S3_BUCKET', title: 'AWS S3' },
|
||||||
|
{ value: 'AZURE_CONTAINER', title: 'Azure' },
|
||||||
|
{ value: 'GOOGLE_CLOUD_STORAGE', title: 'Google cloud' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
credentials_type: {
|
||||||
|
label: 'Credentials type',
|
||||||
|
type: 'select',
|
||||||
|
operators: ['select_equals'],
|
||||||
|
valueSources: ['value'],
|
||||||
|
fieldSettings: {
|
||||||
|
listValues: [
|
||||||
|
{ value: 'KEY_SECRET_KEY_PAIR', title: 'Key & secret key' },
|
||||||
|
{ value: 'ACCOUNT_NAME_TOKEN_PAIR', title: 'Account name & token' },
|
||||||
|
{ value: 'ANONYMOUS_ACCESS', title: 'Anonymous access' },
|
||||||
|
{ value: 'KEY_FILE_PATH', title: 'Key file' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
resource: {
|
||||||
|
label: 'Resource name',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['like'],
|
||||||
|
},
|
||||||
|
display_name: {
|
||||||
|
label: 'Display name',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['like'],
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
label: 'Description',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['like'],
|
||||||
|
},
|
||||||
|
owner: {
|
||||||
|
label: 'Owner',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['equal'],
|
||||||
|
},
|
||||||
|
updated_date: {
|
||||||
|
label: 'Last updated',
|
||||||
|
type: 'datetime',
|
||||||
|
operators: ['between', 'greater', 'greater_or_equal', 'less', 'less_or_equal'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const localStorageRecentCapacity = 10;
|
||||||
|
export const localStorageRecentKeyword = 'recentlyAppliedCloudStoragesFilters';
|
||||||
|
|
||||||
|
export const predefinedFilterValues = {
|
||||||
|
'Owned by me': '{"and":[{"==":[{"var":"owner"},"<username>"]}]}',
|
||||||
|
'AWS storages': '{"and":[{"==":[{"var":"provider_type"},"AWS_S3_BUCKET"]}]}',
|
||||||
|
'Azure storages': '{"and":[{"==":[{"var":"provider_type"},"AZURE_CONTAINER"]}]}',
|
||||||
|
'Google cloud storages': '{"and":[{"==":[{"var":"provider_type"},"GOOGLE_CLOUD_STORAGE"]}]}',
|
||||||
|
};
|
||||||
@ -1,17 +0,0 @@
|
|||||||
// Copyright (C) 2020 Intel Corporation
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import { Row, Col } from 'antd/lib/grid';
|
|
||||||
import Text from 'antd/lib/typography/Text';
|
|
||||||
|
|
||||||
export default function TopBarComponent(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<Row justify='center' align='middle'>
|
|
||||||
<Col md={22} lg={20} xl={16} xxl={14}>
|
|
||||||
<Text className='cvat-title'>Models</Text>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
// Copyright (C) 2022 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
import { Config } from 'react-awesome-query-builder';
|
||||||
|
|
||||||
|
export const config: Partial<Config> = {
|
||||||
|
fields: {
|
||||||
|
dimension: {
|
||||||
|
label: 'Dimension',
|
||||||
|
type: 'select',
|
||||||
|
operators: ['select_equals'],
|
||||||
|
valueSources: ['value'],
|
||||||
|
fieldSettings: {
|
||||||
|
listValues: [
|
||||||
|
{ value: '2d', title: '2D' },
|
||||||
|
{ value: '3d', title: '3D' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
label: 'Status',
|
||||||
|
type: 'select',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['select_equals', 'select_any_in', 'select_not_any_in'],
|
||||||
|
fieldSettings: {
|
||||||
|
listValues: [
|
||||||
|
{ value: 'annotation', title: 'Annotation' },
|
||||||
|
{ value: 'validation', title: 'Validation' },
|
||||||
|
{ value: 'completed', title: 'Completed' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mode: {
|
||||||
|
label: 'Data',
|
||||||
|
type: 'select',
|
||||||
|
valueSources: ['value'],
|
||||||
|
fieldSettings: {
|
||||||
|
listValues: [
|
||||||
|
{ value: 'interpolation', title: 'Video' },
|
||||||
|
{ value: 'annotation', title: 'Images' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
subset: {
|
||||||
|
label: 'Subset',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['equal'],
|
||||||
|
},
|
||||||
|
assignee: {
|
||||||
|
label: 'Assignee',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['equal'],
|
||||||
|
},
|
||||||
|
owner: {
|
||||||
|
label: 'Owner',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['equal'],
|
||||||
|
},
|
||||||
|
updated_date: {
|
||||||
|
label: 'Last updated',
|
||||||
|
type: 'datetime',
|
||||||
|
operators: ['between', 'greater', 'greater_or_equal', 'less', 'less_or_equal'],
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
label: 'ID',
|
||||||
|
type: 'number',
|
||||||
|
operators: ['equal', 'between', 'greater', 'greater_or_equal', 'less', 'less_or_equal'],
|
||||||
|
fieldSettings: { min: 0 },
|
||||||
|
valueSources: ['value'],
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
label: 'Name',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['like'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const localStorageRecentCapacity = 10;
|
||||||
|
export const localStorageRecentKeyword = 'recentlyAppliedProjectTasksFilters';
|
||||||
|
export const predefinedFilterValues = {
|
||||||
|
'Assigned to me': '{"and":[{"==":[{"var":"assignee"},"<username>"]}]}',
|
||||||
|
'Owned by me': '{"and":[{"==":[{"var":"owner"},"<username>"]}]}',
|
||||||
|
'Not completed': '{"!":{"and":[{"==":[{"var":"status"},"completed"]}]}}',
|
||||||
|
};
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
// Copyright (C) 2022 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
import { Config } from 'react-awesome-query-builder';
|
||||||
|
|
||||||
|
export const config: Partial<Config> = {
|
||||||
|
fields: {
|
||||||
|
id: {
|
||||||
|
label: 'ID',
|
||||||
|
type: 'number',
|
||||||
|
operators: ['equal', 'between', 'greater', 'greater_or_equal', 'less', 'less_or_equal'],
|
||||||
|
fieldSettings: { min: 0 },
|
||||||
|
valueSources: ['value'],
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
label: 'Name',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['like'],
|
||||||
|
},
|
||||||
|
assignee: {
|
||||||
|
label: 'Assignee',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['equal'],
|
||||||
|
},
|
||||||
|
owner: {
|
||||||
|
label: 'Owner',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['equal'],
|
||||||
|
},
|
||||||
|
updated_date: {
|
||||||
|
label: 'Last updated',
|
||||||
|
type: 'datetime',
|
||||||
|
operators: ['between', 'greater', 'greater_or_equal', 'less', 'less_or_equal'],
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
label: 'Status',
|
||||||
|
type: 'select',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['select_equals', 'select_any_in', 'select_not_any_in'],
|
||||||
|
fieldSettings: {
|
||||||
|
listValues: [
|
||||||
|
{ value: 'annotation', title: 'Annotation' },
|
||||||
|
{ value: 'validation', title: 'Validation' },
|
||||||
|
{ value: 'completed', title: 'Completed' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const localStorageRecentCapacity = 10;
|
||||||
|
export const localStorageRecentKeyword = 'recentlyAppliedProjectsFilters';
|
||||||
|
export const predefinedFilterValues = {
|
||||||
|
'Assigned to me': '{"and":[{"==":[{"var":"assignee"},"<username>"]}]}',
|
||||||
|
'Owned by me': '{"and":[{"==":[{"var":"owner"},"<username>"]}]}',
|
||||||
|
'Not completed': '{"!":{"and":[{"==":[{"var":"status"},"completed"]}]}}',
|
||||||
|
};
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (C) 2022 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
import './styles.scss';
|
||||||
|
import { Indexable } from 'reducers/interfaces';
|
||||||
|
import SortingComponent from './sorting';
|
||||||
|
import ResourceFilterHOC from './filtering';
|
||||||
|
|
||||||
|
const defaultVisibility = {
|
||||||
|
predefined: false,
|
||||||
|
recent: false,
|
||||||
|
builder: false,
|
||||||
|
sorting: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateHistoryFromQuery(query: Indexable): string {
|
||||||
|
const search = new URLSearchParams({
|
||||||
|
...(query.filter ? { filter: query.filter } : {}),
|
||||||
|
...(query.search ? { search: query.search } : {}),
|
||||||
|
...(query.sort ? { sort: query.sort } : {}),
|
||||||
|
...(query.page ? { page: `${query.page}` } : {}),
|
||||||
|
});
|
||||||
|
|
||||||
|
return decodeURIComponent(search.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
SortingComponent,
|
||||||
|
ResourceFilterHOC,
|
||||||
|
defaultVisibility,
|
||||||
|
updateHistoryFromQuery,
|
||||||
|
};
|
||||||
@ -0,0 +1,139 @@
|
|||||||
|
// Copyright (C) 2022 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
@import '../../base.scss';
|
||||||
|
|
||||||
|
.cvat-resource-page-filters {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
span[aria-label=down] {
|
||||||
|
margin-right: $grid-unit-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
> button {
|
||||||
|
margin-right: $grid-unit-size;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cvat-resource-page-recent-filters-list {
|
||||||
|
max-width: $grid-unit-size * 64;
|
||||||
|
|
||||||
|
.ant-menu {
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
.ant-menu-item {
|
||||||
|
padding: $grid-unit-size;
|
||||||
|
margin: 0;
|
||||||
|
line-height: initial;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cvat-resource-page-filters-builder {
|
||||||
|
background: white;
|
||||||
|
padding: $grid-unit-size;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: $box-shadow-base;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
|
|
||||||
|
// redefine default awesome react query builder styles below
|
||||||
|
.query-builder {
|
||||||
|
margin: $grid-unit-size;
|
||||||
|
|
||||||
|
.group.group-or-rule {
|
||||||
|
background: none !important;
|
||||||
|
border: none !important;
|
||||||
|
|
||||||
|
.group.group-or-rule {
|
||||||
|
&::before {
|
||||||
|
left: -13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
left: -13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.group--actions.group--actions--tr {
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group--conjunctions {
|
||||||
|
div.ant-btn-group {
|
||||||
|
button.ant-btn {
|
||||||
|
width: auto !important;
|
||||||
|
opacity: 1 !important;
|
||||||
|
margin-right: $grid-unit-size !important;
|
||||||
|
padding: 0 $grid-unit-size !important;
|
||||||
|
border-left-color: #d9d9d9 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cvat-resource-page-sorting-list,
|
||||||
|
.cvat-resource-page-predefined-filters-list,
|
||||||
|
.cvat-resource-page-recent-filters-list {
|
||||||
|
background: white;
|
||||||
|
padding: $grid-unit-size;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-shadow: $box-shadow-base;
|
||||||
|
|
||||||
|
.ant-checkbox-wrapper {
|
||||||
|
margin-bottom: $grid-unit-size;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cvat-resource-page-sorting-list {
|
||||||
|
width: $grid-unit-size * 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cvat-sorting-field {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: $grid-unit-size;
|
||||||
|
|
||||||
|
.ant-radio-button-wrapper {
|
||||||
|
width: $grid-unit-size * 16;
|
||||||
|
user-select: none;
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cvat-sorting-anchor {
|
||||||
|
width: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: $grid-unit-size * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: $grid-unit-size * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cvat-sorting-dragged-item {
|
||||||
|
z-index: 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cvat-resource-page-filters-space {
|
||||||
|
justify-content: right;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
@ -1,103 +0,0 @@
|
|||||||
// Copyright (C) 2021 Intel Corporation
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
import './styles.scss';
|
|
||||||
import React from 'react';
|
|
||||||
import Search from 'antd/lib/input/Search';
|
|
||||||
import SearchTooltip from 'components/search-tooltip/search-tooltip';
|
|
||||||
|
|
||||||
interface Query {
|
|
||||||
[key: string]: string | number | boolean | null | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
query: Query;
|
|
||||||
instance: 'task' | 'project' | 'cloudstorage';
|
|
||||||
skipFields?: string[];
|
|
||||||
onSearch(query: object): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function SearchField(props: Props): JSX.Element {
|
|
||||||
const {
|
|
||||||
onSearch,
|
|
||||||
query,
|
|
||||||
instance,
|
|
||||||
skipFields,
|
|
||||||
} = props;
|
|
||||||
const skip = ['page'];
|
|
||||||
if (typeof skipFields !== 'undefined') {
|
|
||||||
skip.push(...skipFields);
|
|
||||||
}
|
|
||||||
|
|
||||||
function parse(_query: Query, _skip: string[]): string {
|
|
||||||
let searchString = '';
|
|
||||||
for (const field of Object.keys(_query)) {
|
|
||||||
const value = _query[field];
|
|
||||||
if (value !== null && typeof value !== 'undefined' && !_skip.includes(field)) {
|
|
||||||
if (field === 'search') {
|
|
||||||
return _query[field] as string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
if (typeof (_query[field] === 'number')) {
|
|
||||||
searchString += `${field}: ${_query[field]} AND `;
|
|
||||||
} else {
|
|
||||||
searchString += `${field}: "${_query[field]}" AND `;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return searchString.slice(0, -5);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSearch = (value: string): void => {
|
|
||||||
const currentQuery = { ...query };
|
|
||||||
const search = value
|
|
||||||
.replace(/\s+/g, ' ')
|
|
||||||
.replace(/\s*:+\s*/g, ':')
|
|
||||||
.trim();
|
|
||||||
|
|
||||||
const fields = Object.keys(query).filter((key) => !skip.includes(key));
|
|
||||||
for (const field of fields) {
|
|
||||||
currentQuery[field] = null;
|
|
||||||
}
|
|
||||||
currentQuery.search = null;
|
|
||||||
|
|
||||||
let specificRequest = false;
|
|
||||||
for (const param of search.split(/[\s]+and[\s]+|[\s]+AND[\s]+/)) {
|
|
||||||
if (param.includes(':')) {
|
|
||||||
const [field, fieldValue] = param.split(':');
|
|
||||||
if (fields.includes(field) && !!fieldValue) {
|
|
||||||
specificRequest = true;
|
|
||||||
if (field === 'id') {
|
|
||||||
if (Number.isInteger(+fieldValue)) {
|
|
||||||
currentQuery[field] = +fieldValue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
currentQuery[field] = fieldValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentQuery.page = 1;
|
|
||||||
if (!specificRequest && value) {
|
|
||||||
currentQuery.search = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
onSearch(currentQuery);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SearchTooltip instance={instance}>
|
|
||||||
<Search
|
|
||||||
className='cvat-search-field'
|
|
||||||
defaultValue={parse(query, skip)}
|
|
||||||
onSearch={handleSearch}
|
|
||||||
size='large'
|
|
||||||
placeholder='Search'
|
|
||||||
/>
|
|
||||||
</SearchTooltip>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
// Copyright (C) 2021 Intel Corporation
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
@import '../../base.scss';
|
|
||||||
|
|
||||||
.cvat-search-field {
|
|
||||||
width: $grid-unit-size * 30;
|
|
||||||
}
|
|
||||||
@ -1,162 +0,0 @@
|
|||||||
// Copyright (C) 2021-2022 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' | 'cloudstorage';
|
|
||||||
children: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
// provider: isEnum.bind(CloudStorageProviderType),
|
|
||||||
// credentialsType: isEnum.bind(CloudStorageCredentialsType),
|
|
||||||
|
|
||||||
export default function SearchTooltip(props: Props): JSX.Element {
|
|
||||||
const { instance, children } = props;
|
|
||||||
const instances = ` ${instance}s `;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<CVATTooltip
|
|
||||||
overlayClassName={`cvat-${instance}s-search-tooltip cvat-search-tooltip`}
|
|
||||||
title={(
|
|
||||||
<>
|
|
||||||
{instance === 'cloudstorage' ? (
|
|
||||||
<Paragraph>
|
|
||||||
<Text strong>displayName: Azure</Text>
|
|
||||||
<Text>
|
|
||||||
all
|
|
||||||
{instances}
|
|
||||||
where name includes the substring
|
|
||||||
<q>Azure</q>
|
|
||||||
</Text>
|
|
||||||
</Paragraph>
|
|
||||||
) : null}
|
|
||||||
{instance === 'cloudstorage' ? (
|
|
||||||
<Paragraph>
|
|
||||||
<Text strong>description: Personal bucket</Text>
|
|
||||||
<Text>
|
|
||||||
all
|
|
||||||
{instances}
|
|
||||||
where description includes the substring
|
|
||||||
<q>Personal bucket</q>
|
|
||||||
</Text>
|
|
||||||
</Paragraph>
|
|
||||||
) : null}
|
|
||||||
{instance === 'cloudstorage' ? (
|
|
||||||
<Paragraph>
|
|
||||||
<Text strong>resource: mycvatbucket</Text>
|
|
||||||
<Text>
|
|
||||||
all
|
|
||||||
{instances}
|
|
||||||
where a name of the resource includes the substring
|
|
||||||
<q>mycvatbucket</q>
|
|
||||||
</Text>
|
|
||||||
</Paragraph>
|
|
||||||
) : null}
|
|
||||||
{instance === 'cloudstorage' ? (
|
|
||||||
<Paragraph>
|
|
||||||
<Text strong>providerType: AWS_S3_BUCKET</Text>
|
|
||||||
<Text>
|
|
||||||
<q>AWS_S3_BUCKET</q>
|
|
||||||
or
|
|
||||||
<q>AZURE_CONTAINER</q>
|
|
||||||
or
|
|
||||||
<q>GOOGLE_CLOUD_STORAGE</q>
|
|
||||||
</Text>
|
|
||||||
</Paragraph>
|
|
||||||
) : null}
|
|
||||||
{instance === 'cloudstorage' ? (
|
|
||||||
<Paragraph>
|
|
||||||
<Text strong>credentialsType: KEY_SECRET_KEY_PAIR</Text>
|
|
||||||
<Text>
|
|
||||||
<q>KEY_SECRET_KEY_PAIR</q>
|
|
||||||
or
|
|
||||||
<q>ACCOUNT_NAME_TOKEN_PAIR</q>
|
|
||||||
or
|
|
||||||
<q>KEY_FILE_PATH</q>
|
|
||||||
or
|
|
||||||
<q>ANONYMOUS_ACCESS</q>
|
|
||||||
</Text>
|
|
||||||
</Paragraph>
|
|
||||||
) : null}
|
|
||||||
<Paragraph>
|
|
||||||
<Text strong>owner: admin</Text>
|
|
||||||
<Text>
|
|
||||||
all
|
|
||||||
{instances}
|
|
||||||
created by users who have the substring
|
|
||||||
<q>admin</q>
|
|
||||||
in their username
|
|
||||||
</Text>
|
|
||||||
</Paragraph>
|
|
||||||
{instance !== 'cloudstorage' ? (
|
|
||||||
<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>
|
|
||||||
) : null}
|
|
||||||
{instance !== 'cloudstorage' ? (
|
|
||||||
<Paragraph>
|
|
||||||
<Text strong>name: training</Text>
|
|
||||||
<Text>
|
|
||||||
all
|
|
||||||
{instances}
|
|
||||||
with the substring
|
|
||||||
<q>training</q>
|
|
||||||
in its name
|
|
||||||
</Text>
|
|
||||||
</Paragraph>
|
|
||||||
) : null}
|
|
||||||
{instance === 'task' ? (
|
|
||||||
<Paragraph>
|
|
||||||
<Text strong>mode: annotation</Text>
|
|
||||||
<Text>
|
|
||||||
annotation tasks are tasks with images, interpolation tasks are tasks with videos
|
|
||||||
</Text>
|
|
||||||
</Paragraph>
|
|
||||||
) : null}
|
|
||||||
{instance !== 'cloudstorage' ? (
|
|
||||||
<Paragraph>
|
|
||||||
<Text strong>status: annotation</Text>
|
|
||||||
<Text>annotation, validation, or completed</Text>
|
|
||||||
</Paragraph>
|
|
||||||
) : null}
|
|
||||||
<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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
// Copyright (C) 2021 Intel Corporation
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
@import '../../base.scss';
|
|
||||||
|
|
||||||
.cvat-search-tooltip {
|
|
||||||
span {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
q {
|
|
||||||
margin: 0 1em 0 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
strong::after {
|
|
||||||
content: ' - ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,103 @@
|
|||||||
|
// Copyright (C) 2022 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
import { Config } from 'react-awesome-query-builder';
|
||||||
|
|
||||||
|
export const config: Partial<Config> = {
|
||||||
|
fields: {
|
||||||
|
dimension: {
|
||||||
|
label: 'Dimension',
|
||||||
|
type: 'select',
|
||||||
|
operators: ['select_equals'],
|
||||||
|
valueSources: ['value'],
|
||||||
|
fieldSettings: {
|
||||||
|
listValues: [
|
||||||
|
{ value: '2d', title: '2D' },
|
||||||
|
{ value: '3d', title: '3D' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
label: 'Status',
|
||||||
|
type: 'select',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['select_equals', 'select_any_in', 'select_not_any_in'],
|
||||||
|
fieldSettings: {
|
||||||
|
listValues: [
|
||||||
|
{ value: 'annotation', title: 'Annotation' },
|
||||||
|
{ value: 'validation', title: 'Validation' },
|
||||||
|
{ value: 'completed', title: 'Completed' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mode: {
|
||||||
|
label: 'Data',
|
||||||
|
type: 'select',
|
||||||
|
valueSources: ['value'],
|
||||||
|
fieldSettings: {
|
||||||
|
listValues: [
|
||||||
|
{ value: 'interpolation', title: 'Video' },
|
||||||
|
{ value: 'annotation', title: 'Images' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
subset: {
|
||||||
|
label: 'Subset',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['equal'],
|
||||||
|
},
|
||||||
|
assignee: {
|
||||||
|
label: 'Assignee',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['equal'],
|
||||||
|
},
|
||||||
|
owner: {
|
||||||
|
label: 'Owner',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['equal'],
|
||||||
|
},
|
||||||
|
updated_date: {
|
||||||
|
label: 'Last updated',
|
||||||
|
type: 'datetime',
|
||||||
|
operators: ['between', 'greater', 'greater_or_equal', 'less', 'less_or_equal'],
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
label: 'ID',
|
||||||
|
type: 'number',
|
||||||
|
operators: ['equal', 'between', 'greater', 'greater_or_equal', 'less', 'less_or_equal'],
|
||||||
|
fieldSettings: { min: 0 },
|
||||||
|
valueSources: ['value'],
|
||||||
|
},
|
||||||
|
project_id: {
|
||||||
|
label: 'Project ID',
|
||||||
|
type: 'number',
|
||||||
|
operators: ['equal', 'between', 'greater', 'greater_or_equal', 'less', 'less_or_equal'],
|
||||||
|
fieldSettings: { min: 0 },
|
||||||
|
valueSources: ['value'],
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
label: 'Name',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['like'],
|
||||||
|
},
|
||||||
|
project_name: {
|
||||||
|
label: 'Project name',
|
||||||
|
type: 'text',
|
||||||
|
valueSources: ['value'],
|
||||||
|
operators: ['like'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const localStorageRecentCapacity = 10;
|
||||||
|
export const localStorageRecentKeyword = 'recentlyAppliedTasksFilters';
|
||||||
|
export const predefinedFilterValues = {
|
||||||
|
'Assigned to me': '{"and":[{"==":[{"var":"assignee"},"<username>"]}]}',
|
||||||
|
'Owned by me': '{"and":[{"==":[{"var":"owner"},"<username>"]}]}',
|
||||||
|
'Not completed': '{"!":{"and":[{"==":[{"var":"status"},"completed"]}]}}',
|
||||||
|
};
|
||||||
@ -1,57 +1,31 @@
|
|||||||
// Copyright (C) 2020-2021 Intel Corporation
|
// Copyright (C) 2020-2022 Intel Corporation
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { Task, TasksQuery, CombinedState } from 'reducers/interfaces';
|
import { Task, TasksQuery, CombinedState } from 'reducers/interfaces';
|
||||||
|
|
||||||
import TasksPageComponent from 'components/tasks-page/tasks-page';
|
import TasksPageComponent from 'components/tasks-page/tasks-page';
|
||||||
|
|
||||||
import { getTasksAsync, hideEmptyTasks, importTaskAsync } from 'actions/tasks-actions';
|
|
||||||
|
|
||||||
interface StateToProps {
|
interface StateToProps {
|
||||||
tasksFetching: boolean;
|
fetching: boolean;
|
||||||
gettingQuery: TasksQuery;
|
query: TasksQuery;
|
||||||
numberOfTasks: number;
|
count: number;
|
||||||
numberOfVisibleTasks: number;
|
countInvisible: number;
|
||||||
numberOfHiddenTasks: number;
|
importing: boolean;
|
||||||
taskImporting: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DispatchToProps {
|
|
||||||
onGetTasks: (gettingQuery: TasksQuery) => void;
|
|
||||||
hideEmptyTasks: (hideEmpty: boolean) => void;
|
|
||||||
onImportTask: (file: File) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state: CombinedState): StateToProps {
|
function mapStateToProps(state: CombinedState): StateToProps {
|
||||||
const { tasks } = state;
|
const { tasks } = state;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tasksFetching: state.tasks.fetching,
|
fetching: state.tasks.fetching,
|
||||||
gettingQuery: tasks.gettingQuery,
|
query: tasks.gettingQuery,
|
||||||
numberOfTasks: state.tasks.count,
|
count: state.tasks.count,
|
||||||
numberOfVisibleTasks: state.tasks.current.length,
|
countInvisible: tasks.hideEmpty ?
|
||||||
numberOfHiddenTasks: tasks.hideEmpty ?
|
|
||||||
tasks.current.filter((task: Task): boolean => !task.instance.jobs.length).length :
|
tasks.current.filter((task: Task): boolean => !task.instance.jobs.length).length :
|
||||||
0,
|
0,
|
||||||
taskImporting: state.tasks.importing,
|
importing: state.tasks.importing,
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch: any): DispatchToProps {
|
|
||||||
return {
|
|
||||||
onGetTasks: (query: TasksQuery): void => {
|
|
||||||
dispatch(getTasksAsync(query));
|
|
||||||
},
|
|
||||||
hideEmptyTasks: (hideEmpty: boolean): void => {
|
|
||||||
dispatch(hideEmptyTasks(hideEmpty));
|
|
||||||
},
|
|
||||||
onImportTask: (file: File): void => {
|
|
||||||
dispatch(importTaskAsync(file));
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(TasksPageComponent);
|
export default connect(mapStateToProps)(TasksPageComponent);
|
||||||
|
|||||||
@ -1,48 +0,0 @@
|
|||||||
// Copyright (C) 2020-2022 Intel Corporation
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
/// <reference types="cypress" />
|
|
||||||
|
|
||||||
import { taskName } from '../../support/const';
|
|
||||||
|
|
||||||
context('Search task feature.', () => {
|
|
||||||
const caseId = '35';
|
|
||||||
|
|
||||||
function searchTask(option, result) {
|
|
||||||
cy.intercept('GET', '/api/tasks**').as('searchTask');
|
|
||||||
cy.get('.cvat-search-field').find('[placeholder="Search"]').clear().type(`${option}{Enter}`);
|
|
||||||
cy.wait('@searchTask').its('response.statusCode').should('equal', 200);
|
|
||||||
cy.get('.cvat-spinner').should('not.exist');
|
|
||||||
cy.contains('.cvat-item-task-name', taskName).should(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
before(() => {
|
|
||||||
cy.openTask(taskName);
|
|
||||||
cy.assignTaskToUser(Cypress.env('user')); // Assign a task to an ures to check filter
|
|
||||||
cy.goToTaskList();
|
|
||||||
});
|
|
||||||
|
|
||||||
after(() => {
|
|
||||||
cy.goToTaskList();
|
|
||||||
cy.openTask(taskName);
|
|
||||||
cy.assignTaskToUser('');
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: rework this test
|
|
||||||
describe(`Testing case "${caseId}"`, () => {
|
|
||||||
it('Tooltip task filter contain all the possible options.', () => {
|
|
||||||
cy.get('.cvat-search-field').trigger('mouseover');
|
|
||||||
cy.get('.cvat-tasks-search-tooltip').should('be.visible');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Type to task search some filter and check result.', () => {
|
|
||||||
searchTask(`${taskName.substring(0, 3)}`, 'exist');
|
|
||||||
searchTask('121212', 'not.exist');
|
|
||||||
searchTask(`owner: ${Cypress.env('user')}`, 'exist');
|
|
||||||
searchTask(`mode: annotation AND assignee: ${Cypress.env('user')}`, 'exist');
|
|
||||||
searchTask('status: annotation', 'exist');
|
|
||||||
searchTask(`mode: interpolation AND owner: ${Cypress.env('user')}`, 'not.exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Loading…
Reference in New Issue