提交 6d449dc3 编写于 作者: K Kruchinin

Merge branch 'develop' of https://github.com/openvinotoolkit/cvat into...

Merge branch 'develop' of https://github.com/openvinotoolkit/cvat into dkru/cypress-test-issue-2485-2
......@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added basic projects implementation (<https://github.com/openvinotoolkit/cvat/pull/2255>)
- Added documentation on how to mount cloud starage(AWS S3 bucket, Azure container, Google Drive) as FUSE (<https://github.com/openvinotoolkit/cvat/pull/2377>)
- Added ability to work with share files without copying inside (<https://github.com/openvinotoolkit/cvat/pull/2377>)
- Tooltips in label selectors (<https://github.com/openvinotoolkit/cvat/pull/2509>)
### Changed
......@@ -41,6 +42,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Empty frames navigation (<https://github.com/openvinotoolkit/cvat/pull/2505>)
- Disabled position editing in AAM (<https://github.com/openvinotoolkit/cvat/pull/2506>)
- TypeError: Cannot read property 'toString' of undefined (<https://github.com/openvinotoolkit/cvat/pull/2517>)
- Extra shapes are drawn after Esc, or G pressed while drawing a region in grouping (<https://github.com/openvinotoolkit/cvat/pull/2507>)
### Security
......
......@@ -35,11 +35,11 @@ export class GroupHandlerImpl implements GroupHandler {
private getSelectionBox(
event: MouseEvent,
): {
xtl: number;
ytl: number;
xbr: number;
ybr: number;
} {
xtl: number;
ytl: number;
xbr: number;
ybr: number;
} {
const point = translateToSVG((this.canvas.node as any) as SVGSVGElement, [event.clientX, event.clientY]);
const stopSelectionPoint = {
x: point[0],
......@@ -96,11 +96,11 @@ export class GroupHandlerImpl implements GroupHandler {
const bbox = shape.bbox();
const clientID = shape.attr('clientID');
if (
bbox.x > box.xtl &&
bbox.y > box.ytl &&
bbox.x + bbox.width < box.xbr &&
bbox.y + bbox.height < box.ybr &&
!(clientID in this.highlightedShapes)
bbox.x > box.xtl
&& bbox.y > box.ytl
&& bbox.x + bbox.width < box.xbr
&& bbox.y + bbox.height < box.ybr
&& !(clientID in this.highlightedShapes)
) {
const objectState = this.getStates().filter(
(state: any): boolean => state.clientID === clientID,
......@@ -124,7 +124,6 @@ export class GroupHandlerImpl implements GroupHandler {
this.resetSelectedObjects();
this.initialized = false;
this.selectionRect = null;
this.startSelectionPoint = {
x: null,
y: null,
......@@ -213,6 +212,10 @@ export class GroupHandlerImpl implements GroupHandler {
}
this.statesToBeGroupped = [];
this.highlightedShapes = {};
if (this.selectionRect) {
this.selectionRect.remove();
this.selectionRect = null;
}
}
public cancel(): void {
......
{
"name": "cvat-ui",
"version": "1.11.2",
"version": "1.11.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
{
"name": "cvat-ui",
"version": "1.11.2",
"version": "1.11.3",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
......
......@@ -4,7 +4,6 @@
import React from 'react';
import { Row, Col } from 'antd/lib/grid';
import Select, { OptionProps } from 'antd/lib/select';
import Button from 'antd/lib/button';
import InputNumber from 'antd/lib/input-number';
import Radio, { RadioChangeEvent } from 'antd/lib/radio';
......@@ -14,6 +13,7 @@ import Text from 'antd/lib/typography/Text';
import { RectDrawingMethod, CuboidDrawingMethod } from 'cvat-canvas-wrapper';
import { ShapeType } from 'reducers/interfaces';
import { clamp } from 'utils/math';
import LabelSelector from 'components/label-selector/label-selector';
interface Props {
shapeType: ShapeType;
......@@ -22,7 +22,7 @@ interface Props {
rectDrawingMethod?: RectDrawingMethod;
cuboidDrawingMethod?: CuboidDrawingMethod;
numberOfPoints?: number;
selectedLabeID: number;
selectedLabelID: number;
repeatShapeShortcut: string;
onChangeLabel(value: string): void;
onChangePoints(value: number | undefined): void;
......@@ -37,7 +37,7 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
labels,
shapeType,
minimumPoints,
selectedLabeID,
selectedLabelID,
numberOfPoints,
rectDrawingMethod,
cuboidDrawingMethod,
......@@ -64,25 +64,12 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
</Row>
<Row type='flex' justify='center'>
<Col span={24}>
<Select
showSearch
filterOption={(input: string, option: React.ReactElement<OptionProps>) => {
const { children } = option.props;
if (typeof children === 'string') {
return children.toLowerCase().includes(input.toLowerCase());
}
return false;
}}
value={`${selectedLabeID}`}
<LabelSelector
style={{ width: '100%' }}
labels={labels}
value={selectedLabelID}
onChange={onChangeLabel}
>
{labels.map((label: any) => (
<Select.Option key={label.id} value={`${label.id}`}>
{label.name}
</Select.Option>
))}
</Select>
/>
</Col>
</Row>
{shapeType === ShapeType.RECTANGLE && (
......
......@@ -4,21 +4,23 @@
import React from 'react';
import { Row, Col } from 'antd/lib/grid';
import Select from 'antd/lib/select';
import Button from 'antd/lib/button';
import Tooltip from 'antd/lib/tooltip';
import Text from 'antd/lib/typography/Text';
import LabelSelector from 'components/label-selector/label-selector';
interface Props {
labels: any[];
selectedLabeID: number;
selectedLabelID: number;
repeatShapeShortcut: string;
onChangeLabel(value: string): void;
onSetup(labelID: number): void;
}
function SetupTagPopover(props: Props): JSX.Element {
const { labels, selectedLabeID, repeatShapeShortcut, onChangeLabel, onSetup } = props;
const {
labels, selectedLabelID, repeatShapeShortcut, onChangeLabel, onSetup,
} = props;
return (
<div className='cvat-draw-shape-popover-content'>
......@@ -36,19 +38,18 @@ function SetupTagPopover(props: Props): JSX.Element {
</Row>
<Row type='flex' justify='center'>
<Col span={24}>
<Select value={`${selectedLabeID}`} onChange={onChangeLabel}>
{labels.map((label: any) => (
<Select.Option key={label.id} value={`${label.id}`}>
{label.name}
</Select.Option>
))}
</Select>
<LabelSelector
style={{ width: '100%' }}
labels={labels}
value={selectedLabelID}
onChange={onChangeLabel}
/>
</Col>
</Row>
<Row type='flex' justify='space-around'>
<Col span={24}>
<Tooltip title={`Press ${repeatShapeShortcut} to add a tag again`} mouseLeaveDelay={0}>
<Button onClick={() => onSetup(selectedLabeID)}>Tag</Button>
<Button onClick={() => onSetup(selectedLabelID)}>Tag</Button>
</Tooltip>
</Col>
</Row>
......
......@@ -6,7 +6,7 @@ import React, { MutableRefObject } from 'react';
import { connect } from 'react-redux';
import Icon from 'antd/lib/icon';
import Popover from 'antd/lib/popover';
import Select, { OptionProps } from 'antd/lib/select';
import Select from 'antd/lib/select';
import Button from 'antd/lib/button';
import Modal from 'antd/lib/modal';
import Text from 'antd/lib/typography/Text';
......@@ -14,12 +14,15 @@ import Tabs from 'antd/lib/tabs';
import { Row, Col } from 'antd/lib/grid';
import notification from 'antd/lib/notification';
import Progress from 'antd/lib/progress';
import InputNumber from 'antd/lib/input-number';
import { AIToolsIcon } from 'icons';
import { Canvas } from 'cvat-canvas-wrapper';
import range from 'utils/range';
import getCore from 'cvat-core-wrapper';
import { CombinedState, ActiveControl, Model, ObjectType, ShapeType } from 'reducers/interfaces';
import {
CombinedState, ActiveControl, Model, ObjectType, ShapeType,
} from 'reducers/interfaces';
import {
interactWithCanvas,
fetchAnnotationsAsync,
......@@ -28,7 +31,7 @@ import {
} from 'actions/annotation-actions';
import { InteractionResult } from 'cvat-canvas/src/typescript/canvas';
import DetectorRunner from 'components/model-runner-modal/detector-runner';
import InputNumber from 'antd/lib/input-number';
import LabelSelector from 'components/label-selector/label-selector';
interface StateToProps {
canvasInstance: Canvas;
......@@ -178,7 +181,9 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
};
private cancelListener = async (): Promise<void> => {
const { isActivated, jobInstance, frame, fetchAnnotations } = this.props;
const {
isActivated, jobInstance, frame, fetchAnnotations,
} = this.props;
const { interactiveStateID, fetching } = this.state;
if (isActivated) {
......@@ -313,7 +318,9 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
};
private onTracking = async (e: Event): Promise<void> => {
const { isActivated, jobInstance, frame, curZOrder, fetchAnnotations } = this.props;
const {
isActivated, jobInstance, frame, curZOrder, fetchAnnotations,
} = this.props;
const { activeLabelID } = this.state;
const [label] = jobInstance.task.labels.filter((_label: any): boolean => _label.id === activeLabelID);
......@@ -457,28 +464,12 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
</Row>
<Row type='flex' justify='center'>
<Col span={24}>
<Select
<LabelSelector
style={{ width: '100%' }}
showSearch
filterOption={(input: string, option: React.ReactElement<OptionProps>) => {
const { children } = option.props;
if (typeof children === 'string') {
return children.toLowerCase().includes(input.toLowerCase());
}
return false;
}}
value={`${activeLabelID}`}
onChange={(value: string) => {
this.setState({ activeLabelID: +value });
}}
>
{labels.map((label: any) => (
<Select.Option key={label.id} value={`${label.id}`}>
{label.name}
</Select.Option>
))}
</Select>
labels={labels}
value={activeLabelID}
onChange={(value: any) => this.setState({ activeLabelID: value.id })}
/>
</Col>
</Row>
</>
......@@ -486,8 +477,12 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
}
private renderTrackerBlock(): JSX.Element {
const { trackers, canvasInstance, jobInstance, frame, onInteractionStart } = this.props;
const { activeTracker, activeLabelID, fetching, trackingFrames } = this.state;
const {
trackers, canvasInstance, jobInstance, frame, onInteractionStart,
} = this.props;
const {
activeTracker, activeLabelID, fetching, trackingFrames,
} = this.state;
if (!trackers.length) {
return (
......@@ -516,9 +511,9 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
onChange={this.setActiveTracker}
>
{trackers.map(
(interactor: Model): JSX.Element => (
<Select.Option title={interactor.description} key={interactor.id}>
{interactor.name}
(tracker: Model): JSX.Element => (
<Select.Option title={tracker.description} key={tracker.id}>
{tracker.name}
</Select.Option>
),
)}
......@@ -650,7 +645,9 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
}
private renderDetectorBlock(): JSX.Element {
const { jobInstance, detectors, curZOrder, frame, fetchAnnotations } = this.props;
const {
jobInstance, detectors, curZOrder, frame, fetchAnnotations,
} = this.props;
if (!detectors.length) {
return (
......@@ -682,18 +679,17 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
});
const states = result.map(
(data: any): any =>
new core.classes.ObjectState({
shapeType: data.type,
label: task.labels.filter((label: any): boolean => label.name === data.label)[0],
points: data.points,
objectType: ObjectType.SHAPE,
frame,
occluded: false,
source: 'auto',
attributes: {},
zOrder: curZOrder,
}),
(data: any): any => new core.classes.ObjectState({
shapeType: data.type,
label: task.labels.filter((label: any): boolean => label.name === data.label)[0],
points: data.points,
objectType: ObjectType.SHAPE,
frame,
occluded: false,
source: 'auto',
attributes: {},
zOrder: curZOrder,
}),
);
await jobInstance.annotations.put(states);
......@@ -739,29 +735,31 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
}
public render(): JSX.Element | null {
const { interactors, detectors, trackers, isActivated, canvasInstance } = this.props;
const {
interactors, detectors, trackers, isActivated, canvasInstance,
} = this.props;
const { fetching, trackingProgress } = this.state;
if (![...interactors, ...detectors, ...trackers].length) return null;
const dynamcPopoverPros = isActivated
? {
overlayStyle: {
display: 'none',
},
}
: {};
const dynamicIconProps = isActivated
? {
className: 'cvat-active-canvas-control cvat-tools-control',
onClick: (): void => {
canvasInstance.interact({ enabled: false });
},
}
: {
className: 'cvat-tools-control',
};
const dynamcPopoverPros = isActivated ?
{
overlayStyle: {
display: 'none',
},
} :
{};
const dynamicIconProps = isActivated ?
{
className: 'cvat-active-canvas-control cvat-tools-control',
onClick: (): void => {
canvasInstance.interact({ enabled: false });
},
} :
{
className: 'cvat-tools-control',
};
return (
<>
......
......@@ -5,12 +5,12 @@
import React, { useState } from 'react';
import { Row, Col } from 'antd/lib/grid';
import Icon from 'antd/lib/icon';
import Select, { OptionProps } from 'antd/lib/select';
import Dropdown from 'antd/lib/dropdown';
import Text from 'antd/lib/typography/Text';
import Tooltip from 'antd/lib/tooltip';
import { ObjectType, ShapeType, ColorBy } from 'reducers/interfaces';
import LabelSelector from 'components/label-selector/label-selector';
import ItemMenu from './object-item-menu';
interface Props {
......@@ -33,7 +33,7 @@ interface Props {
toForegroundShortcut: string;
removeShortcut: string;
changeColor(color: string): void;
changeLabel(labelID: string): void;
changeLabel(label: any): void;
copy(): void;
remove(): void;
propagate(): void;
......@@ -103,30 +103,8 @@ function ItemTopComponent(props: Props): JSX.Element {
</Text>
</Col>
<Col span={12}>
<Tooltip title={readonly ? 'Current label' : 'Change current label'} mouseLeaveDelay={0}>
<Select
disabled={readonly}
size='small'
value={`${labelID}`}
onChange={changeLabel}
showSearch
filterOption={(input: string, option: React.ReactElement<OptionProps>) => {
const { children } = option.props;
if (typeof children === 'string') {
return children.toLowerCase().includes(input.toLowerCase());
}
return false;
}}
>
{labels.map(
(label: any): JSX.Element => (
<Select.Option key={label.id} value={`${label.id}`}>
{label.name}
</Select.Option>
),
)}
</Select>
<Tooltip title='Change current label' mouseLeaveDelay={0}>
<LabelSelector disabled={readonly} size='small' labels={labels} value={labelID} onChange={changeLabel} />
</Tooltip>
</Col>
<Col span={2}>
......
......@@ -35,7 +35,7 @@ interface Props {
toBackground(): void;
toForeground(): void;
remove(): void;
changeLabel(labelID: string): void;
changeLabel(label: any): void;
changeAttribute(attrID: number, value: string): void;
changeColor(color: string): void;
collapse(): void;
......
......@@ -12,8 +12,8 @@ import Layout, { SiderProps } from 'antd/lib/layout';
import Button from 'antd/lib/button/button';
import Icon from 'antd/lib/icon';
import Text from 'antd/lib/typography/Text';
import Select from 'antd/lib/select';
import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox/Checkbox';
import Tag from 'antd/lib/tag';
import {
createAnnotationsAsync,
......@@ -23,7 +23,7 @@ import {
} from 'actions/annotation-actions';
import { Canvas } from 'cvat-canvas-wrapper';
import { CombinedState, ObjectType } from 'reducers/interfaces';
import Tag from 'antd/lib/tag';
import LabelSelector from 'components/label-selector/label-selector';
import getCore from 'cvat-core-wrapper';
import ShortcutsSelect from './shortcuts-select';
......@@ -111,7 +111,7 @@ function TagAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.Elemen
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
const [frameTags, setFrameTags] = useState([] as any[]);
const [selectedLabelID, setSelectedLabelID] = useState(defaultLabelID);
const [selectedLabelID, setSelectedLabelID] = useState<number>(defaultLabelID);
const [skipFrame, setSkipFrame] = useState(false);
useEffect(() => {
......@@ -155,8 +155,8 @@ function TagAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.Elemen
collapsed: sidebarCollapsed,
};
const onChangeLabel = (value: string): void => {
setSelectedLabelID(Number.parseInt(value, 10));
const onChangeLabel = (value: any): void => {
setSelectedLabelID(value.id);
};
const onRemoveState = (objectState: any): void => {
......@@ -216,13 +216,7 @@ function TagAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.Elemen
<Row type='flex' justify='start' className='cvat-tag-annotation-sidebar-label-select'>
<Col>
<Text strong>Tag label</Text>
<Select value={`${selectedLabelID}`} onChange={onChangeLabel} size='default'>
{labels.map((label: any) => (
<Select.Option key={label.id} value={`${label.id}`}>
{label.name}
</Select.Option>
))}
</Select>
<LabelSelector labels={labels} value={selectedLabelID} onChange={onChangeLabel} />
</Col>
</Row>
<Row type='flex' justify='space-around' className='cvat-tag-annotation-sidebar-buttons'>
......
// Copyright (C) 2020 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
import Select, { OptionProps, SelectProps } from 'antd/lib/select';
interface Props extends SelectProps {
labels: any[];
value: any | number | null;
onChange: (label: any) => void;
}
export default function LabelSelector(props: Props): JSX.Element {
const {
labels, value, onChange, ...rest
} = props;
const dinamicProps = value ?
{
value: typeof value === 'number' ? value : value.id,
} :
{};
return (
<Select
{...rest}
{...dinamicProps}
showSearch
filterOption={(input: string, option: React.ReactElement<OptionProps>) => {
const { children } = option.props;
if (typeof children === 'string') {
return children.toLowerCase().includes(input.toLowerCase());
}
return false;
}}
defaultValue={labels[0].id}
onChange={(newValue: string) => {
const [label] = labels.filter((_label: any): boolean => _label.id === +newValue);
if (label) {
onChange(label);
} else {
throw new Error(`Label with id ${newValue} was not found within the list`);
}
}}
>
{labels.map((label: any) => (
<Select.Option title={label.name} key={label.id} value={label.id}>
{label.name}
</Select.Option>
))}
</Select>
);
}
......@@ -102,7 +102,9 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
private onDraw(objectType: ObjectType): void {
const { canvasInstance, shapeType, onDrawStart } = this.props;
const { rectDrawingMethod, cuboidDrawingMethod, numberOfPoints, selectedLabelID } = this.state;
const {
rectDrawingMethod, cuboidDrawingMethod, numberOfPoints, selectedLabelID,
} = this.state;
canvasInstance.cancel();
canvasInstance.draw({
......@@ -143,14 +145,16 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
});
};
private onChangeLabel = (value: string): void => {
private onChangeLabel = (value: any): void => {
this.setState({
selectedLabelID: +value,
selectedLabelID: value.id,
});
};
public render(): JSX.Element {
const { rectDrawingMethod, cuboidDrawingMethod, selectedLabelID, numberOfPoints } = this.state;
const {
rectDrawingMethod, cuboidDrawingMethod, selectedLabelID, numberOfPoints,
} = this.state;
const { normalizedKeyMap, labels, shapeType } = this.props;
......@@ -159,7 +163,7 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
labels={labels}
shapeType={shapeType}
minimumPoints={this.minimumPoints}
selectedLabeID={selectedLabelID}
selectedLabelID={selectedLabelID}
numberOfPoints={numberOfPoints}
rectDrawingMethod={rectDrawingMethod}
cuboidDrawingMethod={cuboidDrawingMethod}
......
......@@ -74,14 +74,16 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
};
}
private onChangeLabel = (value: string): void => {
private onChangeLabel = (value: any): void => {
this.setState({
selectedLabelID: +value,
selectedLabelID: value.id,
});
};
private onSetup = (): void => {
const { frame, labels, jobInstance, canvasInstance, onAnnotationCreate, onRememberObject } = this.props;
const {
frame, labels, jobInstance, canvasInstance, onAnnotationCreate, onRememberObject,
} = this.props;
const { selectedLabelID } = this.state;
......@@ -105,7 +107,7 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
return (
<SetupTagPopoverComponent
labels={labels}
selectedLabeID={selectedLabelID}
selectedLabelID={selectedLabelID}
repeatShapeShortcut={normalizedKeyMap.SWITCH_DRAW_MODE}
onChangeLabel={this.onChangeLabel}
onSetup={this.onSetup}
......
......@@ -254,15 +254,12 @@ class ObjectItemContainer extends React.PureComponent<Props> {
}
};
private changeLabel = (labelID: string): void => {
const { objectState, readonly, labels } = this.props;
private changeLabel = (label: any): void => {
const { objectState, readonly } = this.props;
if (!readonly) {
const [label] = labels.filter((_label: any): boolean => _label.id === +labelID);
objectState.label = label;
this.commit();
}
this.commit();
};
private changeAttribute = (id: number, value: string): void => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册