Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added dedicated component for label selection, added tooltip #2509

Merged
merged 9 commits into from
Dec 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

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.11.2",
"version": "1.11.3",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -37,7 +37,7 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
labels,
shapeType,
minimumPoints,
selectedLabeID,
selectedLabelID,
numberOfPoints,
rectDrawingMethod,
cuboidDrawingMethod,
Expand All @@ -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 && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'>
Expand All @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,23 @@ 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';
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,
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -457,37 +464,25 @@ 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>
</>
);
}

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 (
Expand Down Expand Up @@ -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>
),
)}
Expand Down Expand Up @@ -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 (
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 (
<>
Expand Down
Loading