From a53bd6c44ddb304384683ac2129c48661ff508c3 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 30 Nov 2020 16:06:47 +0300 Subject: [PATCH 01/14] Disabled ability to edit positions in attribute anntation mode --- .../src/typescript/canvasController.ts | 6 ++ cvat-canvas/src/typescript/canvasModel.ts | 26 ++++---- cvat-canvas/src/typescript/canvasView.ts | 64 +++++++++++-------- .../standard-workspace/canvas-wrapper.tsx | 17 ++++- 4 files changed, 73 insertions(+), 40 deletions(-) diff --git a/cvat-canvas/src/typescript/canvasController.ts b/cvat-canvas/src/typescript/canvasController.ts index 786836d8..065478a6 100644 --- a/cvat-canvas/src/typescript/canvasController.ts +++ b/cvat-canvas/src/typescript/canvasController.ts @@ -14,6 +14,7 @@ import { GroupData, Mode, InteractionData, + Configuration, } from './canvasModel'; export interface CanvasController { @@ -27,6 +28,7 @@ export interface CanvasController { readonly splitData: SplitData; readonly groupData: GroupData; readonly selected: any; + readonly configuration: Configuration; mode: Mode; geometry: Geometry; @@ -151,6 +153,10 @@ export class CanvasControllerImpl implements CanvasController { return this.model.selected; } + public get configuration(): Configuration { + return this.model.configuration; + } + public set mode(value: Mode) { this.model.mode = value; } diff --git a/cvat-canvas/src/typescript/canvasModel.ts b/cvat-canvas/src/typescript/canvasModel.ts index 4521c570..eb5e878b 100644 --- a/cvat-canvas/src/typescript/canvasModel.ts +++ b/cvat-canvas/src/typescript/canvasModel.ts @@ -56,6 +56,7 @@ export interface Configuration { displayAllText?: boolean; undefinedAttrValue?: string; showProjections?: boolean; + forceDisableEditing?: boolean; } export interface DrawData { @@ -288,15 +289,15 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { const mutiplier = Math.sin((angle * Math.PI) / 180) + Math.cos((angle * Math.PI) / 180); if ((angle / 90) % 2) { // 90, 270, .. - this.data.top += - mutiplier * ((x - this.data.imageSize.width / 2) * (oldScale / this.data.scale - 1)) * this.data.scale; - this.data.left -= - mutiplier * ((y - this.data.imageSize.height / 2) * (oldScale / this.data.scale - 1)) * this.data.scale; + const topMultiplier = (x - this.data.imageSize.width / 2) * (oldScale / this.data.scale - 1); + const leftMultiplier = (y - this.data.imageSize.height / 2) * (oldScale / this.data.scale - 1); + this.data.top += mutiplier * topMultiplier * this.data.scale; + this.data.left -= mutiplier * leftMultiplier * this.data.scale; } else { - this.data.left += - mutiplier * ((x - this.data.imageSize.width / 2) * (oldScale / this.data.scale - 1)) * this.data.scale; - this.data.top += - mutiplier * ((y - this.data.imageSize.height / 2) * (oldScale / this.data.scale - 1)) * this.data.scale; + const leftMultiplier = (x - this.data.imageSize.width / 2) * (oldScale / this.data.scale - 1); + const topMultiplier = (y - this.data.imageSize.height / 2) * (oldScale / this.data.scale - 1); + this.data.left += mutiplier * leftMultiplier * this.data.scale; + this.data.top += mutiplier * topMultiplier * this.data.scale; } this.notify(UpdateReasons.IMAGE_ZOOMED); @@ -599,13 +600,16 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { this.data.configuration.undefinedAttrValue = configuration.undefinedAttrValue; } + if (typeof configuration.forceDisableEditing !== 'undefined') { + this.data.configuration.forceDisableEditing = configuration.forceDisableEditing; + } + this.notify(UpdateReasons.CONFIG_UPDATED); } public isAbleToChangeFrame(): boolean { - const isUnable = - [Mode.DRAG, Mode.EDIT, Mode.RESIZE, Mode.INTERACT].includes(this.data.mode) || - (this.data.mode === Mode.DRAW && typeof this.data.drawData.redraw === 'number'); + const isUnable = [Mode.DRAG, Mode.EDIT, Mode.RESIZE, Mode.INTERACT].includes(this.data.mode) + || (this.data.mode === Mode.DRAW && typeof this.data.drawData.redraw === 'number'); return !isUnable; } diff --git a/cvat-canvas/src/typescript/canvasView.ts b/cvat-canvas/src/typescript/canvasView.ts index 8d8e4177..6708545f 100644 --- a/cvat-canvas/src/typescript/canvasView.ts +++ b/cvat-canvas/src/typescript/canvasView.ts @@ -94,6 +94,11 @@ export class CanvasViewImpl implements CanvasView, Listener { return this.serviceFlags.drawHidden[clientID] || false; } + private stateIsLocked(state: any): boolean { + const { configuration } = this.controller; + return state.lock || configuration.forceDisableEditing; + } + private setupServiceHidden(clientID: number, value: boolean): void { this.serviceFlags.drawHidden[clientID] = value; const shape = this.svgShapes[clientID]; @@ -455,8 +460,8 @@ export class CanvasViewImpl implements CanvasView, Listener { // Transform all text for (const key in this.svgShapes) { if ( - Object.prototype.hasOwnProperty.call(this.svgShapes, key) && - Object.prototype.hasOwnProperty.call(this.svgTexts, key) + Object.prototype.hasOwnProperty.call(this.svgShapes, key) + && Object.prototype.hasOwnProperty.call(this.svgTexts, key) ) { this.updateTextPosition(this.svgTexts[key], this.svgShapes[key]); } @@ -874,9 +879,9 @@ export class CanvasViewImpl implements CanvasView, Listener { this.content.addEventListener('mousedown', (event): void => { if ([0, 1].includes(event.button)) { if ( - [Mode.IDLE, Mode.DRAG_CANVAS, Mode.MERGE, Mode.SPLIT].includes(this.mode) || - event.button === 1 || - event.altKey + [Mode.IDLE, Mode.DRAG_CANVAS, Mode.MERGE, Mode.SPLIT].includes(this.mode) + || event.button === 1 + || event.altKey ) { self.controller.enableDrag(event.clientX, event.clientY); } @@ -1325,8 +1330,8 @@ export class CanvasViewImpl implements CanvasView, Listener { } if ( - state.points.length !== drawnState.points.length || - state.points.some((p: number, id: number): boolean => p !== drawnState.points[id]) + state.points.length !== drawnState.points.length + || state.points.some((p: number, id: number): boolean => p !== drawnState.points[id]) ) { const translatedPoints: number[] = translate(state.points); @@ -1542,7 +1547,7 @@ export class CanvasViewImpl implements CanvasView, Listener { if (state && state.shapeType === 'points') { this.svgShapes[clientID] .remember('_selectHandler') - .nested.style('pointer-events', state.lock ? 'none' : ''); + .nested.style('pointer-events', this.stateIsLocked(state) ? 'none' : ''); } if (!state || state.hidden || state.outside) { @@ -1550,8 +1555,14 @@ export class CanvasViewImpl implements CanvasView, Listener { } const shape = this.svgShapes[clientID]; + let text = this.svgTexts[clientID]; + if (!text) { + text = this.addText(state); + this.svgTexts[state.clientID] = text; + } + this.updateTextPosition(text, shape); - if (state.lock) { + if (this.stateIsLocked(state)) { return; } @@ -1567,12 +1578,6 @@ export class CanvasViewImpl implements CanvasView, Listener { (shape as any).attr('projections', true); } - let text = this.svgTexts[clientID]; - if (!text) { - text = this.addText(state); - this.svgTexts[state.clientID] = text; - } - const hideText = (): void => { if (text) { text.addClass('cvat_canvas_hidden'); @@ -1601,12 +1606,14 @@ export class CanvasViewImpl implements CanvasView, Listener { const p2 = e.detail.p; const delta = 1; const { offset } = this.controller.geometry; - if (Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2) >= delta) { + const dx2 = (p1.x - p2.x) ** 2; + const dy2 = (p1.y - p2.y) ** 2; + if (Math.sqrt(dx2 + dy2) >= delta) { const points = pointsToNumberArray( - shape.attr('points') || - `${shape.attr('x')},${shape.attr('y')} ` + - `${shape.attr('x') + shape.attr('width')},` + - `${shape.attr('y') + shape.attr('height')}`, + shape.attr('points') + || `${shape.attr('x')},${shape.attr('y')} ` + + `${shape.attr('x') + shape.attr('width')},` + + `${shape.attr('y') + shape.attr('height')}`, ).map((x: number): number => x - offset); this.drawnStates[state.clientID].points = points; @@ -1677,10 +1684,10 @@ export class CanvasViewImpl implements CanvasView, Listener { const { offset } = this.controller.geometry; const points = pointsToNumberArray( - shape.attr('points') || - `${shape.attr('x')},${shape.attr('y')} ` + - `${shape.attr('x') + shape.attr('width')},` + - `${shape.attr('y') + shape.attr('height')}`, + shape.attr('points') + || `${shape.attr('x')},${shape.attr('y')} ` + + `${shape.attr('x') + shape.attr('width')},` + + `${shape.attr('y') + shape.attr('height')}`, ).map((x: number): number => x - offset); this.drawnStates[state.clientID].points = points; @@ -1697,7 +1704,6 @@ export class CanvasViewImpl implements CanvasView, Listener { } }); - this.updateTextPosition(text, shape); this.canvas.dispatchEvent( new CustomEvent('canvas.activated', { bubbles: false, @@ -1757,8 +1763,8 @@ export class CanvasViewImpl implements CanvasView, Listener { // Find the best place for a text let [clientX, clientY]: number[] = [box.x + box.width, box.y]; if ( - clientX + ((text.node as any) as SVGTextElement).getBBox().width + consts.TEXT_MARGIN > - this.canvas.offsetWidth + clientX + ((text.node as any) as SVGTextElement).getBBox().width + consts.TEXT_MARGIN + > this.canvas.offsetWidth ) { [clientX, clientY] = [box.x, box.y]; } @@ -1778,7 +1784,9 @@ export class CanvasViewImpl implements CanvasView, Listener { private addText(state: any): SVG.Text { const { undefinedAttrValue } = this.configuration; - const { label, clientID, attributes, source } = state; + const { + label, clientID, attributes, source, + } = state; const attrNames = label.attributes.reduce((acc: any, val: any): void => { acc[val.id] = val.name; return acc; diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx index acc697ae..251f2ffa 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx @@ -93,7 +93,9 @@ interface Props { export default class CanvasWrapperComponent extends React.PureComponent { public componentDidMount(): void { - const { automaticBordering, showObjectsTextAlways, canvasInstance } = this.props; + const { + automaticBordering, showObjectsTextAlways, canvasInstance, workspace, + } = this.props; // It's awful approach from the point of view React // But we do not have another way because cvat-canvas returns regular DOM element @@ -104,6 +106,7 @@ export default class CanvasWrapperComponent extends React.PureComponent { autoborders: automaticBordering, undefinedAttrValue: consts.UNDEFINED_ATTRIBUTE_VALUE, displayAllText: showObjectsTextAlways, + forceDisableEditing: workspace === Workspace.ATTRIBUTE_ANNOTATION, }); this.initialSetup(); @@ -247,6 +250,18 @@ export default class CanvasWrapperComponent extends React.PureComponent { canvasInstance.rotate(frameAngle); } + if (prevProps.workspace !== workspace) { + if (workspace === Workspace.ATTRIBUTE_ANNOTATION) { + canvasInstance.configure({ + forceDisableEditing: true, + }); + } else if (prevProps.workspace === Workspace.ATTRIBUTE_ANNOTATION) { + canvasInstance.configure({ + forceDisableEditing: false, + }); + } + } + const loadingAnimation = window.document.getElementById('cvat_canvas_loading_animation'); if (loadingAnimation && frameFetching !== prevProps.frameFetching) { if (frameFetching) { From e2d22d356419662f593f97457c0219da7ccf0a10 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 30 Nov 2020 16:16:30 +0300 Subject: [PATCH 02/14] Updated CHANGELOG & version --- CHANGELOG.md | 1 + cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d91159ab..11ba7265 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Projects view layout fix () - Fixed the tasks view (infinite loading) when it is impossible to get a preview of the task () - Empty frames navigation () +- Disabled position editing in AAM () ### Security diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 9fd70cc3..3ba1e868 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.10.9", + "version": "1.10.10", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index e555f248..0a4083bd 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.10.9", + "version": "1.10.10", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { From fcea8f8d30f2e40133f58ceaf768eb01b9c32c4d Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 30 Nov 2020 16:30:03 +0300 Subject: [PATCH 03/14] Fixed grouping when press escape with drawn region or change a frame --- cvat-canvas/src/typescript/groupHandler.ts | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/cvat-canvas/src/typescript/groupHandler.ts b/cvat-canvas/src/typescript/groupHandler.ts index 84f840cf..c94b5cbf 100644 --- a/cvat-canvas/src/typescript/groupHandler.ts +++ b/cvat-canvas/src/typescript/groupHandler.ts @@ -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 { From b0a945ce4e92b4080b24c6217893f34a6eedc8b0 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 30 Nov 2020 16:33:16 +0300 Subject: [PATCH 04/14] Updated version & changelog --- CHANGELOG.md | 1 + cvat-canvas/package-lock.json | 2 +- cvat-canvas/package.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d91159ab..97a6401c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Projects view layout fix () - Fixed the tasks view (infinite loading) when it is impossible to get a preview of the task () - Empty frames navigation () +- Extra shapes are drawn after Esc, or G pressed while drawing a region in grouping () ### Security diff --git a/cvat-canvas/package-lock.json b/cvat-canvas/package-lock.json index 8fed7d27..f56da299 100644 --- a/cvat-canvas/package-lock.json +++ b/cvat-canvas/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-canvas", - "version": "2.1.3", + "version": "2.1.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-canvas/package.json b/cvat-canvas/package.json index d509f493..dd7b4fcd 100644 --- a/cvat-canvas/package.json +++ b/cvat-canvas/package.json @@ -1,6 +1,6 @@ { "name": "cvat-canvas", - "version": "2.1.3", + "version": "2.1.4", "description": "Part of Computer Vision Annotation Tool which presents its canvas library", "main": "src/canvas.ts", "scripts": { From 9f96c93752d3e9e349f3c71459da4b0318029f5b Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 30 Nov 2020 16:33:53 +0300 Subject: [PATCH 05/14] Updated canvas version --- cvat-canvas/package-lock.json | 2 +- cvat-canvas/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cvat-canvas/package-lock.json b/cvat-canvas/package-lock.json index 8fed7d27..f56da299 100644 --- a/cvat-canvas/package-lock.json +++ b/cvat-canvas/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-canvas", - "version": "2.1.3", + "version": "2.1.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-canvas/package.json b/cvat-canvas/package.json index d509f493..dd7b4fcd 100644 --- a/cvat-canvas/package.json +++ b/cvat-canvas/package.json @@ -1,6 +1,6 @@ { "name": "cvat-canvas", - "version": "2.1.3", + "version": "2.1.4", "description": "Part of Computer Vision Annotation Tool which presents its canvas library", "main": "src/canvas.ts", "scripts": { From abe5da957d5cc323c5e17e28b20793b9f3d73d49 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 30 Nov 2020 18:35:23 +0300 Subject: [PATCH 06/14] Added dedicated component for label selector, added tooltip --- .../controls-side-bar/draw-shape-popover.tsx | 29 ++-- .../controls-side-bar/setup-tag-popover.tsx | 23 ++-- .../controls-side-bar/tools-control.tsx | 124 +++++++++--------- .../objects-side-bar/object-item-basics.tsx | 27 +--- .../objects-side-bar/object-item.tsx | 14 +- .../tag-annotation-sidebar.tsx | 18 +-- .../label-selector/label-selector.tsx | 54 ++++++++ .../controls-side-bar/draw-shape-popover.tsx | 14 +- .../controls-side-bar/setup-tag-popover.tsx | 10 +- .../objects-side-bar/object-item.tsx | 6 +- 10 files changed, 168 insertions(+), 151 deletions(-) create mode 100644 cvat-ui/src/components/label-selector/label-selector.tsx diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx index 6c72c5ec..8a72c39b 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx @@ -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 { - + /> {shapeType === ShapeType.RECTANGLE && ( diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx index 62e8cd6e..a07b16da 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx @@ -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 (
@@ -36,19 +38,18 @@ function SetupTagPopover(props: Props): JSX.Element { - + - + diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx index 01f4658a..a52d7f4d 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx @@ -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 { }; private cancelListener = async (): Promise => { - 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 { }; private onTracking = async (e: Event): Promise => { - 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 { - + labels={labels} + value={activeLabelID} + onChange={(value: any) => this.setState({ activeLabelID: value.id })} + /> @@ -486,8 +477,12 @@ export class ToolsControlComponent extends React.PureComponent { } 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 { onChange={this.setActiveTracker} > {trackers.map( - (interactor: Model): JSX.Element => ( - - {interactor.name} + (tracker: Model): JSX.Element => ( + + {tracker.name} ), )} @@ -650,7 +645,9 @@ export class ToolsControlComponent extends React.PureComponent { } 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 { }); 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 { } 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 ( <> diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item-basics.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item-basics.tsx index a0839ae8..83bef4a5 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item-basics.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item-basics.tsx @@ -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 { @@ -32,7 +32,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; @@ -102,28 +102,7 @@ function ItemTopComponent(props: Props): JSX.Element { - + diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx index c29ef720..472c239a 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx @@ -34,7 +34,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; @@ -96,13 +96,13 @@ function ObjectItemComponent(props: Props): JSX.Element { } = props; const type = - objectType === ObjectType.TAG - ? ObjectType.TAG.toUpperCase() - : `${shapeType.toUpperCase()} ${objectType.toUpperCase()}`; + objectType === ObjectType.TAG ? + ObjectType.TAG.toUpperCase() : + `${shapeType.toUpperCase()} ${objectType.toUpperCase()}`; - const className = !activated - ? 'cvat-objects-sidebar-state-item' - : 'cvat-objects-sidebar-state-item cvat-objects-sidebar-state-active-item'; + const className = !activated ? + 'cvat-objects-sidebar-state-item' : + 'cvat-objects-sidebar-state-item cvat-objects-sidebar-state-active-item'; return (
diff --git a/cvat-ui/src/components/annotation-page/tag-annotation-workspace/tag-annotation-sidebar/tag-annotation-sidebar.tsx b/cvat-ui/src/components/annotation-page/tag-annotation-workspace/tag-annotation-sidebar/tag-annotation-sidebar.tsx index 29fb3a4a..b10d783e 100644 --- a/cvat-ui/src/components/annotation-page/tag-annotation-workspace/tag-annotation-sidebar/tag-annotation-sidebar.tsx +++ b/cvat-ui/src/components/annotation-page/tag-annotation-workspace/tag-annotation-sidebar/tag-annotation-sidebar.tsx @@ -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(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 Tag label - + diff --git a/cvat-ui/src/components/label-selector/label-selector.tsx b/cvat-ui/src/components/label-selector/label-selector.tsx new file mode 100644 index 00000000..1eecc40b --- /dev/null +++ b/cvat-ui/src/components/label-selector/label-selector.tsx @@ -0,0 +1,54 @@ +// 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 ( + + ); +} diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx index f7d1f9e8..937b61f0 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx @@ -102,7 +102,9 @@ class DrawShapePopoverContainer extends React.PureComponent { 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 { }); }; - 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 { labels={labels} shapeType={shapeType} minimumPoints={this.minimumPoints} - selectedLabeID={selectedLabelID} + selectedLabelID={selectedLabelID} numberOfPoints={numberOfPoints} rectDrawingMethod={rectDrawingMethod} cuboidDrawingMethod={cuboidDrawingMethod} diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx index b2d805da..5c0c5b8b 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx @@ -74,14 +74,16 @@ class DrawShapePopoverContainer extends React.PureComponent { }; } - 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 { return ( { } }; - private changeLabel = (labelID: string): void => { - const { objectState, labels } = this.props; - - const [label] = labels.filter((_label: any): boolean => _label.id === +labelID); + private changeLabel = (label: any): void => { + const { objectState } = this.props; objectState.label = label; this.commit(); }; From 19142dd2629acee41ecb811e0a7f806a98cd3c70 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 30 Nov 2020 18:38:02 +0300 Subject: [PATCH 07/14] Updated version & package json --- CHANGELOG.md | 1 + cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d91159ab..5b96360e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added basic projects implementation () +- Tooltips in label selectors () ### Changed diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 9fd70cc3..3ba1e868 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.10.9", + "version": "1.10.10", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index e555f248..0a4083bd 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.10.9", + "version": "1.10.10", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { From 3d97c3b63af4b810c2fe41e91a87775b16a10329 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 30 Nov 2020 18:40:33 +0300 Subject: [PATCH 08/14] Fixed default value --- cvat-ui/src/components/label-selector/label-selector.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat-ui/src/components/label-selector/label-selector.tsx b/cvat-ui/src/components/label-selector/label-selector.tsx index 1eecc40b..c5f5beaf 100644 --- a/cvat-ui/src/components/label-selector/label-selector.tsx +++ b/cvat-ui/src/components/label-selector/label-selector.tsx @@ -34,7 +34,7 @@ export default function LabelSelector(props: Props): JSX.Element { return false; }} - defaultValue={labels[0]} + defaultValue={labels[0].id} onChange={(newValue: string) => { const [label] = labels.filter((_label: any): boolean => _label.id === +newValue); if (label) { From fc1c60f7354c0ac752f568e42aeef6f340b7bb70 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 2 Dec 2020 11:24:29 +0300 Subject: [PATCH 09/14] Fixed issue 2516 --- cvat-ui/src/actions/annotation-actions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cvat-ui/src/actions/annotation-actions.ts b/cvat-ui/src/actions/annotation-actions.ts index fdf86a7f..634aeaf3 100644 --- a/cvat-ui/src/actions/annotation-actions.ts +++ b/cvat-ui/src/actions/annotation-actions.ts @@ -510,13 +510,13 @@ export function removeObjectAsync(sessionInstance: any, objectState: any, force: }, }); } else { - throw new Error('Could not remove the object. Is it locked?'); + throw new Error('Could not remove the locked object'); } } catch (error) { dispatch({ type: AnnotationActionTypes.REMOVE_OBJECT_FAILED, payload: { - objectState, + error, }, }); } From 2cdc7aeef0e73bcc89110e923f583cbc6da92616 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 2 Dec 2020 11:26:37 +0300 Subject: [PATCH 10/14] Updated changelog & version --- CHANGELOG.md | 1 + cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 602b284d..4785f3d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Projects view layout fix () - Fixed the tasks view (infinite loading) when it is impossible to get a preview of the task () - Empty frames navigation () +- TypeError: Cannot read property 'toString' of undefined () ### Security diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 08cea114..59a75dbd 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.11.0", + "version": "1.11.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 4dea1406..35884c24 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.11.0", + "version": "1.11.1", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { From 59cff7b6ca9e2347a5cc87e737e0311d3471e957 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 2 Dec 2020 11:34:53 +0300 Subject: [PATCH 11/14] Removed extra code --- cvat-canvas/src/typescript/canvasView.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/cvat-canvas/src/typescript/canvasView.ts b/cvat-canvas/src/typescript/canvasView.ts index 63c461e9..d4304f22 100644 --- a/cvat-canvas/src/typescript/canvasView.ts +++ b/cvat-canvas/src/typescript/canvasView.ts @@ -125,11 +125,6 @@ export class CanvasViewImpl implements CanvasView, Listener { return this.serviceFlags.drawHidden[clientID] || false; } - private stateIsLocked(state: any): boolean { - const { configuration } = this.controller; - return state.lock || configuration.forceDisableEditing; - } - private setupServiceHidden(clientID: number, value: boolean): void { this.serviceFlags.drawHidden[clientID] = value; const shape = this.svgShapes[clientID]; @@ -1347,8 +1342,7 @@ export class CanvasViewImpl implements CanvasView, Listener { } this.mode = Mode.IDLE; this.canvas.style.cursor = ''; - } - else if (reason === UpdateReasons.DATA_FAILED) { + } else if (reason === UpdateReasons.DATA_FAILED) { const event: CustomEvent = new CustomEvent('canvas.error', { detail: { exception: model.exception, From 71b48ece76121468667e8017b184171e391d6e9d Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 2 Dec 2020 12:30:05 +0300 Subject: [PATCH 12/14] Fixed changelog --- CHANGELOG.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aea017f1..e81da5a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,12 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Manual review pipeline: issues/comments/workspace () - Added basic projects implementation () -<<<<<<< HEAD -- Tooltips in label selectors () -======= - Added documentation on how to mount cloud starage(AWS S3 bucket, Azure container, Google Drive) as FUSE () - Added ability to work with share files without copying inside () ->>>>>>> develop +- Tooltips in label selectors () ### Changed From 7052633b56b2c99cf26c729bffecb776499d8568 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 2 Dec 2020 12:31:19 +0300 Subject: [PATCH 13/14] Merged develop --- cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 59a75dbd..79762999 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.11.1", + "version": "1.11.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 35884c24..79ea5093 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.11.1", + "version": "1.11.2", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { From 7febefe29e1613c1d55c11b94b7e6e8bc9b54fe7 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 2 Dec 2020 15:28:08 +0300 Subject: [PATCH 14/14] Updated version --- cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 79762999..1f8b1862 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.11.2", + "version": "1.11.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 79ea5093..ba970517 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -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": {