From 96532260db4931753ec2246b50f3fc4dfb03d710 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 8 Apr 2020 23:04:11 +0300 Subject: [PATCH 1/7] Fixed: cannot read property 'set' of undefined --- cvat-canvas/src/typescript/svg.patch.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cvat-canvas/src/typescript/svg.patch.ts b/cvat-canvas/src/typescript/svg.patch.ts index 1c532105c797..642add621168 100644 --- a/cvat-canvas/src/typescript/svg.patch.ts +++ b/cvat-canvas/src/typescript/svg.patch.ts @@ -16,7 +16,9 @@ SVG.Element.prototype.draw = function constructor(...args: any): any { if (!handler) { originalDraw.call(this, ...args); handler = this.remember('_paintHandler'); - if (!handler.set) { + // There is use case (drawing a single point when handler is created and destructed immediately in one stack) + // So, we need to check if handler still exists + if (handler && !handler.set) { handler.set = new SVG.Set(); } } else { From 07783b79ef4d3af257cb170c07c89f2c65190687 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 8 Apr 2020 23:57:24 +0300 Subject: [PATCH 2/7] Fixed UI failing: save during drag/resize --- cvat-canvas/README.md | 4 ++- cvat-canvas/src/typescript/canvasModel.ts | 10 ++++-- cvat-canvas/src/typescript/canvasView.ts | 40 +++++++++++++---------- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/cvat-canvas/README.md b/cvat-canvas/README.md index d9cabfa94a8c..7d8e4e1c7d31 100644 --- a/cvat-canvas/README.md +++ b/cvat-canvas/README.md @@ -182,7 +182,7 @@ Standard JS events are used. | | IDLE | GROUP | SPLIT | DRAW | MERGE | EDIT | DRAG | RESIZE | ZOOM_CANVAS | DRAG_CANVAS | |--------------|------|-------|-------|------|-------|------|------|--------|-------------|-------------| | html() | + | + | + | + | + | + | + | + | + | + | -| setup() | + | + | + | + | + | - | - | - | + | + | +| setup() | + | + | + | + | + | +/- | +/- | +/- | + | + | | activate() | + | - | - | - | - | - | - | - | - | - | | rotate() | + | + | + | + | + | + | + | + | + | + | | focus() | + | + | + | + | + | + | + | + | + | + | @@ -199,3 +199,5 @@ Standard JS events are used. | configure() | + | - | - | - | - | - | - | - | - | - | | bitmap() | + | + | + | + | + | + | + | + | + | + | | setZLayer() | + | + | + | + | + | + | + | + | + | + | + +You can call setup() during editing, dragging, and resizing only to update objects, not to change a frame. diff --git a/cvat-canvas/src/typescript/canvasModel.ts b/cvat-canvas/src/typescript/canvasModel.ts index da7d112ad061..15a92f62d760 100644 --- a/cvat-canvas/src/typescript/canvasModel.ts +++ b/cvat-canvas/src/typescript/canvasModel.ts @@ -327,8 +327,10 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { } public setup(frameData: any, objectStates: any[]): void { - if ([Mode.EDIT, Mode.DRAG, Mode.RESIZE].includes(this.data.mode)) { - throw Error(`Canvas is busy. Action: ${this.data.mode}`); + if (this.data.imageID !== frameData.number) { + if ([Mode.EDIT, Mode.DRAG, Mode.RESIZE].includes(this.data.mode)) { + throw Error(`Canvas is busy. Action: ${this.data.mode}`); + } } if (frameData.number === this.data.imageID) { @@ -364,6 +366,10 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { } public activate(clientID: number | null, attributeID: number | null): void { + if (this.data.activeElement.clientID === clientID) { + return; + } + if (this.data.mode !== Mode.IDLE && clientID !== null) { // Exception or just return? throw Error(`Canvas is busy. Action: ${this.data.mode}`); diff --git a/cvat-canvas/src/typescript/canvasView.ts b/cvat-canvas/src/typescript/canvasView.ts index 3bd438b616ca..b347bbc5e529 100644 --- a/cvat-canvas/src/typescript/canvasView.ts +++ b/cvat-canvas/src/typescript/canvasView.ts @@ -385,6 +385,7 @@ export class CanvasViewImpl implements CanvasView, Listener { created.push(state); } else { const drawnState = this.drawnStates[state.clientID]; + // object has been changed or changed frame for a track if (drawnState.updated !== state.updated || drawnState.frame !== state.frame) { updated.push(state); } @@ -395,29 +396,30 @@ export class CanvasViewImpl implements CanvasView, Listener { .filter((id: number): boolean => !newIDs.includes(id)) .map((id: number): any => this.drawnStates[id]); + if (deleted.length || updated.length || created.length) { + if (this.activeElement.clientID !== null) { + this.deactivate(); + } - if (this.activeElement.clientID !== null) { - this.deactivate(); - } + for (const state of deleted) { + if (state.clientID in this.svgTexts) { + this.svgTexts[state.clientID].remove(); + } - for (const state of deleted) { - if (state.clientID in this.svgTexts) { - this.svgTexts[state.clientID].remove(); + this.svgShapes[state.clientID].off('click.canvas'); + this.svgShapes[state.clientID].remove(); + delete this.drawnStates[state.clientID]; } - this.svgShapes[state.clientID].off('click.canvas'); - this.svgShapes[state.clientID].remove(); - delete this.drawnStates[state.clientID]; - } - - this.addObjects(created, translate); - this.updateObjects(updated, translate); - this.sortObjects(); + this.addObjects(created, translate); + this.updateObjects(updated, translate); + this.sortObjects(); - if (this.controller.activeElement.clientID !== null) { - const { clientID } = this.controller.activeElement; - if (states.map((state: any): number => state.clientID).includes(clientID)) { - this.activate(this.controller.activeElement); + if (this.controller.activeElement.clientID !== null) { + const { clientID } = this.controller.activeElement; + if (states.map((state: any): number => state.clientID).includes(clientID)) { + this.activate(this.controller.activeElement); + } } } } @@ -960,6 +962,8 @@ export class CanvasViewImpl implements CanvasView, Listener { attributes: { ...state.attributes }, zOrder: state.zOrder, pinned: state.pinned, + updated: state.updated, + frame: state.frame, }; } From 8874de1ae5ca65e8c8ff5d7f0be6035fcea3a17f Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Thu, 9 Apr 2020 00:07:07 +0300 Subject: [PATCH 3/7] Fixed multiple saving (shortcut sticking) --- cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx index fcfe943b9a8a..67d09d99ba60 100644 --- a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx +++ b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx @@ -520,7 +520,9 @@ class AnnotationTopBarContainer extends React.PureComponent { }, SAVE_JOB: (event: KeyboardEvent | undefined) => { preventDefault(event); - this.onSaveAnnotation(); + if (!saving) { + this.onSaveAnnotation(); + } }, NEXT_FRAME: (event: KeyboardEvent | undefined) => { preventDefault(event); From addf35c0e3c79443af1b3321fa6d608f5b5982bb Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Thu, 9 Apr 2020 00:31:10 +0300 Subject: [PATCH 4/7] Undo/redo fixed --- cvat-core/src/annotations-objects.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/cvat-core/src/annotations-objects.js b/cvat-core/src/annotations-objects.js index 47c65fb9898d..9620d2c4b554 100644 --- a/cvat-core/src/annotations-objects.js +++ b/cvat-core/src/annotations-objects.js @@ -184,8 +184,10 @@ this.history.do(HistoryActions.CHANGED_LOCK, () => { this.lock = undoLock; + this.updated = Date.now(); }, () => { this.lock = redoLock; + this.updated = Date.now(); }, [this.clientID], frame); this.lock = lock; @@ -197,8 +199,10 @@ this.history.do(HistoryActions.CHANGED_COLOR, () => { this.color = undoColor; + this.updated = Date.now(); }, () => { this.color = redoColor; + this.updated = Date.now(); }, [this.clientID], frame); this.color = color; @@ -210,8 +214,10 @@ this.history.do(HistoryActions.CHANGED_HIDDEN, () => { this.hidden = undoHidden; + this.updated = Date.now(); }, () => { this.hidden = redoHidden; + this.updated = Date.now(); }, [this.clientID], frame); this.hidden = hidden; @@ -229,9 +235,11 @@ this.history.do(HistoryActions.CHANGED_LABEL, () => { this.label = undoLabel; this.attributes = undoAttributes; + this.updated = Date.now(); }, () => { this.label = redoLabel; this.attributes = redoAttributes; + this.updated = Date.now(); }, [this.clientID], frame); } @@ -246,8 +254,10 @@ this.history.do(HistoryActions.CHANGED_ATTRIBUTES, () => { this.attributes = undoAttributes; + this.updated = Date.now(); }, () => { this.attributes = redoAttributes; + this.updated = Date.now(); }, [this.clientID], frame); } @@ -373,9 +383,12 @@ this.removed = true; this.history.do(HistoryActions.REMOVED_OBJECT, () => { + this.serverID = undefined; this.removed = false; + this.updated = Date.now(); }, () => { this.removed = true; + this.updated = Date.now(); }, [this.clientID], frame); } @@ -398,8 +411,10 @@ this.history.do(HistoryActions.CHANGED_PINNED, () => { this.pinned = undoPinned; + this.updated = Date.now(); }, () => { this.pinned = redoPinned; + this.updated = Date.now(); }, [this.clientID], frame); this.pinned = pinned; @@ -489,8 +504,10 @@ this.history.do(HistoryActions.CHANGED_POINTS, () => { this.points = undoPoints; + this.updated = Date.now(); }, () => { this.points = redoPoints; + this.updated = Date.now(); }, [this.clientID], frame); this.points = points; @@ -502,8 +519,10 @@ this.history.do(HistoryActions.CHANGED_OCCLUDED, () => { this.occluded = undoOccluded; + this.updated = Date.now(); }, () => { this.occluded = redoOccluded; + this.updated = Date.now(); }, [this.clientID], frame); this.occluded = occluded; @@ -515,8 +534,10 @@ this.history.do(HistoryActions.CHANGED_ZORDER, () => { this.zOrder = undoZOrder; + this.updated = Date.now(); }, () => { this.zOrder = redoZOrder; + this.updated = Date.now(); }, [this.clientID], frame); this.zOrder = zOrder; @@ -777,12 +798,14 @@ for (const mutable of undoAttributes.mutable) { this.shapes[mutable.frame].attributes = mutable.attributes; } + this.updated = Date.now(); }, () => { this.label = redoLabel; this.attributes = redoAttributes.unmutable; for (const mutable of redoAttributes.mutable) { this.shapes[mutable.frame].attributes = mutable.attributes; } + this.updated = Date.now(); }, [this.clientID], frame); } @@ -853,11 +876,13 @@ } else if (redoShape) { delete this.shapes[frame]; } + this.updated = Date.now(); }, () => { this.attributes = redoAttributes; if (redoShape) { this.shapes[frame] = redoShape; } + this.updated = Date.now(); }, [this.clientID], frame); } @@ -868,12 +893,14 @@ } else { this.shapes[frame] = undoShape; } + this.updated = Date.now(); }, () => { if (!redoShape) { delete this.shapes[frame]; } else { this.shapes[frame] = redoShape; } + this.updated = Date.now(); }, [this.clientID], frame); } From 38b3df0861147e9fa112627f8f51d24477a3c1d8 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Thu, 9 Apr 2020 00:38:28 +0300 Subject: [PATCH 5/7] Allowed one interpolated point --- .../controls-side-bar/draw-shape-popover.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 a32f3ba8e204..e5145fd9c801 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 @@ -47,6 +47,9 @@ function DrawShapePopoverComponent(props: Props): JSX.Element { onChangeRectDrawingMethod, } = props; + const trackDisabled = shapeType === ShapeType.POLYGON || shapeType === ShapeType.POLYLINE + || (shapeType === ShapeType.POINTS && numberOfPoints !== 1); + return (
@@ -148,7 +151,7 @@ function DrawShapePopoverComponent(props: Props): JSX.Element { From 88e17a26b98f3ccdbd223a9b1264608eea8033a9 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Thu, 9 Apr 2020 00:45:45 +0300 Subject: [PATCH 6/7] Fixed API reaction when repository synchronization is failed --- cvat-ui/src/components/task-page/details.tsx | 8 +++++++- cvat-ui/src/utils/git-utils.ts | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cvat-ui/src/components/task-page/details.tsx b/cvat-ui/src/components/task-page/details.tsx index ff7083765b0a..ba8fa1b27c38 100644 --- a/cvat-ui/src/components/task-page/details.tsx +++ b/cvat-ui/src/components/task-page/details.tsx @@ -299,8 +299,14 @@ export default class DetailsComponent extends React.PureComponent repositoryStatus: 'sync', }); } - }).catch((): void => { + }).catch((error): void => { if (this.mounted) { + Modal.error({ + width: 800, + title: 'Could not synchronize the repository', + content: error.toString(), + }); + this.setState({ repositoryStatus: '!sync', }); diff --git a/cvat-ui/src/utils/git-utils.ts b/cvat-ui/src/utils/git-utils.ts index 4751598341fa..ae946f29a545 100644 --- a/cvat-ui/src/utils/git-utils.ts +++ b/cvat-ui/src/utils/git-utils.ts @@ -180,10 +180,10 @@ export function syncRepos(tid: number): Promise { resolve(); } else if (response.status === 'failed') { const message = `Can not push to remote repository. Message: ${response.stderr}`; - throw new Error(message); + reject(new Error(message)); } else { const message = `Check returned status "${response.status}".`; - throw new Error(message); + reject(new Error(message)); } } From 67410f4fc4776bd8496dfd1c4039547b5d509bd0 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Thu, 9 Apr 2020 01:00:47 +0300 Subject: [PATCH 7/7] Updated changelog --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40b823f093db..25300a88ecca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Button to reset colors settings (brightness, saturation, contrast) in the new UI - Option to display shape text always - Dedicated message with clarifications when share is unmounted (https://github.com/opencv/cvat/pull/1373) +- Ability to create one tracked point (https://github.com/opencv/cvat/pull/1383) ### Changed - Increase preview size of a task till 256, 256 on the server @@ -33,7 +34,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Hidden points (or outsided) are visible after changing a frame - Merge is allowed for points, but clicks on points conflict with frame dragging logic - Removed objects are visible for search -- Add missed task_id and job_id fields into exception logs for the new UI (https://github.com/opencv/cvat/pull/1372) +- Add missed task_id and job_id fields into exception logs for the new UI (https://github.com/opencv/cvat/pull/1372) +- UI fails when annotations saving occurs during drag/resize/edit (https://github.com/opencv/cvat/pull/1383) +- Multiple savings when hold Ctrl+S (a lot of the same copies of events were sent with the same working time) (https://github.com/opencv/cvat/pull/1383) +- UI doesn't have any reaction when git repos synchronization failed (https://github.com/opencv/cvat/pull/1383) +- Bug when annotations cannot be saved after (delete - save - undo - save) (https://github.com/opencv/cvat/pull/1383) ### Security -