From 5bd61a43a4038ea3e7ad929741589b953daaef5d Mon Sep 17 00:00:00 2001 From: Dmitry Kruchinin <33020454+dvkruchinin@users.noreply.github.com> Date: Mon, 1 Mar 2021 13:04:09 +0300 Subject: [PATCH 01/17] Cypress test. Maintenance of popups visibility. (#2838) * Cypress test. Issue 2230. * Typo fix * rename the file --- ...sue_2230_maintenance_popover_visibility.js | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/cypress/integration/actions_tasks_objects/issue_2230_maintenance_popover_visibility.js diff --git a/tests/cypress/integration/actions_tasks_objects/issue_2230_maintenance_popover_visibility.js b/tests/cypress/integration/actions_tasks_objects/issue_2230_maintenance_popover_visibility.js new file mode 100644 index 00000000000..176b9087e1f --- /dev/null +++ b/tests/cypress/integration/actions_tasks_objects/issue_2230_maintenance_popover_visibility.js @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Intel Corporation +// +// SPDX-License-Identifier: MIT + +/// + +import { taskName } from '../../support/const'; + +context('Check maintenance of popups visibility.', () => { + const issueId = '2230'; + + before(() => { + cy.openTaskJob(taskName); + }); + + describe(`Testing issue "${issueId}"`, () => { + it('Open a popover for draw an object and apply the "mouseout" event to it. The popover be visible.', () => { + cy.interactControlButton('draw-rectangle'); + cy.get('.cvat-draw-rectangle-popover-visible').trigger('mouseout').wait(500); + cy.get('.cvat-draw-rectangle-popover-visible').should('exist'); + }); + + it('Click to another element. The popover hidden.', () => { + cy.get('.cvat-canvas-container').click(); + cy.get('.cvat-draw-rectangle-popover-visible').should('not.exist'); + }); + }); +}); From 55b20e197d74bae12786a849dc315fb2f71a2cec Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 1 Mar 2021 16:15:26 +0300 Subject: [PATCH 02/17] Added simple extra popover to keep other controls out of display (#2880) * Added simple extra popover to keep other controls out of display * Removed extra change * Fixed part of tests * Added extra comments * Updated version & changelog --- CHANGELOG.md | 1 + cvat-ui/package-lock.json | 9 +- cvat-ui/package.json | 3 +- .../annotation-page/annotation-page.tsx | 2 +- .../control-visibility-observer.tsx | 114 ++++++++++++++++++ .../controls-side-bar/controls-side-bar.tsx | 82 ++++++++----- .../controls-side-bar/cursor-control.tsx | 2 +- .../controls-side-bar/draw-cuboid-control.tsx | 2 +- .../controls-side-bar/draw-points-control.tsx | 2 +- .../draw-polygon-control.tsx | 2 +- .../draw-polyline-control.tsx | 2 +- .../draw-rectangle-control.tsx | 2 +- .../controls-side-bar/fit-control.tsx | 2 +- .../controls-side-bar/group-control.tsx | 2 +- .../controls-side-bar/merge-control.tsx | 2 +- .../controls-side-bar/move-control.tsx | 2 +- .../controls-side-bar/resize-control.tsx | 2 +- .../controls-side-bar/rotate-control.tsx | 2 +- .../controls-side-bar/setup-tag-control.tsx | 2 +- .../controls-side-bar/split-control.tsx | 2 +- .../standard-workspace/styles.scss | 11 +- 21 files changed, 200 insertions(+), 50 deletions(-) create mode 100644 cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/control-visibility-observer.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 28020188943..609f41fe85b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Persistent queue added to logstash () - Improved maintanance of popups visibility () - Image visualizations settings on canvas for faster access () +- Better scale management of left panel when screen is too small () ### Deprecated diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index ce87ebabe05..0cd1ddc4cb3 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.15.0", + "version": "1.15.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1335,6 +1335,11 @@ "redux": "^4.0.0" } }, + "@types/resize-observer-browser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@types/resize-observer-browser/-/resize-observer-browser-0.1.5.tgz", + "integrity": "sha512-8k/67Z95Goa6Lznuykxkfhq9YU3l1Qe6LNZmwde1u7802a3x8v44oq0j91DICclxatTr0rNnhXx7+VTIetSrSQ==" + }, "@typescript-eslint/eslint-plugin": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.5.0.tgz", @@ -15392,7 +15397,7 @@ "cvat-data": { "version": "file:../cvat-data", "requires": { - "async-mutex": "^0.2.6", + "async-mutex": "^0.3.0", "jszip": "3.5.0" }, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 49d93b64f86..5d8bf3b4b3e 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.15.0", + "version": "1.15.1", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { @@ -59,6 +59,7 @@ "@types/react-router-dom": "^5.1.7", "@types/react-share": "^3.0.3", "@types/redux-logger": "^3.0.8", + "@types/resize-observer-browser": "^0.1.5", "antd": "^4.12.2", "copy-to-clipboard": "^3.3.1", "cvat-canvas": "file:../cvat-canvas", diff --git a/cvat-ui/src/components/annotation-page/annotation-page.tsx b/cvat-ui/src/components/annotation-page/annotation-page.tsx index feb6f7b6d72..48499859758 100644 --- a/cvat-ui/src/components/annotation-page/annotation-page.tsx +++ b/cvat-ui/src/components/annotation-page/annotation-page.tsx @@ -39,7 +39,7 @@ export default function AnnotationPageComponent(props: Props): JSX.Element { saveLogs(); const root = window.document.getElementById('root'); if (root) { - root.style.minHeight = '768px'; + root.style.minHeight = '600px'; } return () => { diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/control-visibility-observer.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/control-visibility-observer.tsx new file mode 100644 index 00000000000..c900c306666 --- /dev/null +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/control-visibility-observer.tsx @@ -0,0 +1,114 @@ +// Copyright (C) 2021 Intel Corporation +// +// SPDX-License-Identifier: MIT + +/// + +import { SmallDashOutlined } from '@ant-design/icons'; +import Popover from 'antd/lib/popover'; +import React, { useEffect, useRef, useState } from 'react'; +import ReactDOM from 'react-dom'; + +const extraControlsContentClassName = 'cvat-extra-controls-control-content'; + +let onUpdateChildren: Function | null = null; +export function ExtraControlsControl(): JSX.Element { + const [hasChildren, setHasChildren] = useState(false); + const [initialized, setInitialized] = useState(false); + + useEffect(() => { + if (!initialized) { + setInitialized(true); + } + + window.document.body.dispatchEvent(new MouseEvent('mousedown', { bubbles: true })); + }, []); + + onUpdateChildren = () => { + const contentElement = window.document.getElementsByClassName(extraControlsContentClassName)[0]; + if (contentElement) { + setHasChildren(contentElement.children.length > 0); + } + }; + + return ( + } + > + + + ); +} + +export default function ControlVisibilityObserver

( + ControlComponent: React.FunctionComponent

, +): React.FunctionComponent

{ + let visibilityHeightThreshold = 0; // minimum value of height when element can be pushed to main panel + + return (props: P): JSX.Element | null => { + const ref = useRef(null); + const [visible, setVisible] = useState(true); + + useEffect(() => { + if (ref && ref.current) { + const wrapper = ref.current; + const parentElement = ref.current.parentElement as HTMLElement; + + const reservedHeight = 45; // for itself + const observer = new ResizeObserver(() => { + // when parent size was changed, check again can we put the control + // into the side panel or not + const availableHeight = parentElement.offsetHeight; + setVisible(availableHeight - reservedHeight >= visibilityHeightThreshold); + }); + + if (ref && ref.current) { + const availableHeight = parentElement.offsetHeight; + // when first mount, remember bottom coordinate which equal to minimum parent width + // to put the control into side panel + visibilityHeightThreshold = wrapper.offsetTop + wrapper.offsetHeight; + // start observing parent size + observer.observe(ref.current.parentElement as HTMLElement); + // then put it to extra controls if parent height is not enought + setVisible(availableHeight - reservedHeight >= visibilityHeightThreshold); + } + + return () => { + observer.disconnect(); + }; + } + + return () => {}; + }, []); + + useEffect(() => { + // when visibility changed, we notify extra content element because now its children changed + if (onUpdateChildren) { + onUpdateChildren(); + } + }, [visible]); + + if (!visible) { + const extraControlsContent = window.document.getElementsByClassName(extraControlsContentClassName)[0]; + if (extraControlsContent) { + return ReactDOM.createPortal(, extraControlsContent); + } + + return null; + } + + // first mount always to side panel + return ( +

+ +
+ ); + }; +} diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/controls-side-bar.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/controls-side-bar.tsx index 2c03ef043ea..2ac25ef204d 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/controls-side-bar.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/controls-side-bar.tsx @@ -9,22 +9,23 @@ import Layout from 'antd/lib/layout'; import { ActiveControl, Rotation } from 'reducers/interfaces'; import { Canvas } from 'cvat-canvas-wrapper'; -import RotateControl from './rotate-control'; -import CursorControl from './cursor-control'; -import MoveControl from './move-control'; -import FitControl from './fit-control'; -import ResizeControl from './resize-control'; +import ControlVisibilityObserver, { ExtraControlsControl } from './control-visibility-observer'; +import RotateControl, { Props as RotateControlProps } from './rotate-control'; +import CursorControl, { Props as CursorControlProps } from './cursor-control'; +import MoveControl, { Props as MoveControlProps } from './move-control'; +import FitControl, { Props as FitControlProps } from './fit-control'; +import ResizeControl, { Props as ResizeControlProps } from './resize-control'; import ToolsControl from './tools-control'; import OpenCVControl from './opencv-control'; -import DrawRectangleControl from './draw-rectangle-control'; -import DrawPolygonControl from './draw-polygon-control'; -import DrawPolylineControl from './draw-polyline-control'; -import DrawPointsControl from './draw-points-control'; -import DrawCuboidControl from './draw-cuboid-control'; -import SetupTagControl from './setup-tag-control'; -import MergeControl from './merge-control'; -import GroupControl from './group-control'; -import SplitControl from './split-control'; +import DrawRectangleControl, { Props as DrawRectangleControlProps } from './draw-rectangle-control'; +import DrawPolygonControl, { Props as DrawPolygonControlProps } from './draw-polygon-control'; +import DrawPolylineControl, { Props as DrawPolylineControlProps } from './draw-polyline-control'; +import DrawPointsControl, { Props as DrawPointsControlProps } from './draw-points-control'; +import DrawCuboidControl, { Props as DrawCuboidControlProps } from './draw-cuboid-control'; +import SetupTagControl, { Props as SetupTagControlProps } from './setup-tag-control'; +import MergeControl, { Props as MergeControlProps } from './merge-control'; +import GroupControl, { Props as GroupControlProps } from './group-control'; +import SplitControl, { Props as SplitControlProps } from './split-control'; interface Props { canvasInstance: Canvas; @@ -42,6 +43,25 @@ interface Props { redrawShape(): void; } +// We use the observer to see if these controls are in the viewport +// They automatically put to extra if not +const ObservedCursorControl = ControlVisibilityObserver(CursorControl); +const ObservedMoveControl = ControlVisibilityObserver(MoveControl); +const ObservedRotateControl = ControlVisibilityObserver(RotateControl); +const ObservedFitControl = ControlVisibilityObserver(FitControl); +const ObservedResizeControl = ControlVisibilityObserver(ResizeControl); +const ObservedToolsControl = ControlVisibilityObserver(ToolsControl); +const ObservedOpenCVControl = ControlVisibilityObserver(OpenCVControl); +const ObservedDrawRectangleControl = ControlVisibilityObserver(DrawRectangleControl); +const ObservedDrawPolygonControl = ControlVisibilityObserver(DrawPolygonControl); +const ObservedDrawPolylineControl = ControlVisibilityObserver(DrawPolylineControl); +const ObservedDrawPointsControl = ControlVisibilityObserver(DrawPointsControl); +const ObservedDrawCuboidControl = ControlVisibilityObserver(DrawCuboidControl); +const ObservedSetupTagControl = ControlVisibilityObserver(SetupTagControl); +const ObservedMergeControl = ControlVisibilityObserver(MergeControl); +const ObservedGroupControl = ControlVisibilityObserver(GroupControl); +const ObservedSplitControl = ControlVisibilityObserver(SplitControl); + export default function ControlsSideBarComponent(props: Props): JSX.Element { const { canvasInstance, @@ -170,13 +190,13 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element { return ( - - - + - - + +
- - - + + - - - - - +
- - - + +
); } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/cursor-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/cursor-control.tsx index dd26d376f25..826e7990875 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/cursor-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/cursor-control.tsx @@ -10,7 +10,7 @@ import { ActiveControl } from 'reducers/interfaces'; import { Canvas } from 'cvat-canvas-wrapper'; import CVATTooltip from 'components/common/cvat-tooltip'; -interface Props { +export interface Props { canvasInstance: Canvas; cursorShortkey: string; activeControl: ActiveControl; diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-cuboid-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-cuboid-control.tsx index 0a86df2ebe9..50e28fecae5 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-cuboid-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-cuboid-control.tsx @@ -14,7 +14,7 @@ import { CubeIcon } from 'icons'; import DrawShapePopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover'; import withVisibilityHandling from './handle-popover-visibility'; -interface Props { +export interface Props { canvasInstance: Canvas; isDrawing: boolean; } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-points-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-points-control.tsx index 462e78c9d69..6a513be11d9 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-points-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-points-control.tsx @@ -13,7 +13,7 @@ import { ShapeType } from 'reducers/interfaces'; import DrawShapePopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover'; import withVisibilityHandling from './handle-popover-visibility'; -interface Props { +export interface Props { canvasInstance: Canvas; isDrawing: boolean; } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-polygon-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-polygon-control.tsx index f07a324d7cf..61da0d3d106 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-polygon-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-polygon-control.tsx @@ -13,7 +13,7 @@ import { ShapeType } from 'reducers/interfaces'; import DrawShapePopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover'; import withVisibilityHandling from './handle-popover-visibility'; -interface Props { +export interface Props { canvasInstance: Canvas; isDrawing: boolean; } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-polyline-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-polyline-control.tsx index a1d3c157b3d..766c15c425c 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-polyline-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-polyline-control.tsx @@ -13,7 +13,7 @@ import { ShapeType } from 'reducers/interfaces'; import DrawShapePopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover'; import withVisibilityHandling from './handle-popover-visibility'; -interface Props { +export interface Props { canvasInstance: Canvas; isDrawing: boolean; } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-rectangle-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-rectangle-control.tsx index 0d0462818f5..a94dabea55c 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-rectangle-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-rectangle-control.tsx @@ -13,7 +13,7 @@ import { ShapeType } from 'reducers/interfaces'; import DrawShapePopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover'; import withVisibilityHandling from './handle-popover-visibility'; -interface Props { +export interface Props { canvasInstance: Canvas; isDrawing: boolean; } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/fit-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/fit-control.tsx index baa544ff412..9921d86d6b9 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/fit-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/fit-control.tsx @@ -9,7 +9,7 @@ import { FitIcon } from 'icons'; import { Canvas } from 'cvat-canvas-wrapper'; import CVATTooltip from 'components/common/cvat-tooltip'; -interface Props { +export interface Props { canvasInstance: Canvas; } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/group-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/group-control.tsx index 8b93c7577e5..e26158437bf 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/group-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/group-control.tsx @@ -10,7 +10,7 @@ import { Canvas } from 'cvat-canvas-wrapper'; import { ActiveControl } from 'reducers/interfaces'; import CVATTooltip from 'components/common/cvat-tooltip'; -interface Props { +export interface Props { canvasInstance: Canvas; activeControl: ActiveControl; switchGroupShortcut: string; diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/merge-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/merge-control.tsx index 2d29fb21196..e1c96c3baf8 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/merge-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/merge-control.tsx @@ -10,7 +10,7 @@ import { Canvas } from 'cvat-canvas-wrapper'; import { ActiveControl } from 'reducers/interfaces'; import CVATTooltip from 'components/common/cvat-tooltip'; -interface Props { +export interface Props { canvasInstance: Canvas; activeControl: ActiveControl; switchMergeShortcut: string; diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/move-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/move-control.tsx index 760a59ddb22..ffbaeb3585f 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/move-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/move-control.tsx @@ -10,7 +10,7 @@ import { ActiveControl } from 'reducers/interfaces'; import { Canvas } from 'cvat-canvas-wrapper'; import CVATTooltip from 'components/common/cvat-tooltip'; -interface Props { +export interface Props { canvasInstance: Canvas; activeControl: ActiveControl; } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/resize-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/resize-control.tsx index ac7806cb070..ec461b1d7e4 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/resize-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/resize-control.tsx @@ -10,7 +10,7 @@ import { ActiveControl } from 'reducers/interfaces'; import { Canvas } from 'cvat-canvas-wrapper'; import CVATTooltip from 'components/common/cvat-tooltip'; -interface Props { +export interface Props { canvasInstance: Canvas; activeControl: ActiveControl; } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/rotate-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/rotate-control.tsx index 9fa1e2f9796..5c5a33cb457 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/rotate-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/rotate-control.tsx @@ -11,7 +11,7 @@ import { Rotation } from 'reducers/interfaces'; import CVATTooltip from 'components/common/cvat-tooltip'; import withVisibilityHandling from './handle-popover-visibility'; -interface Props { +export interface Props { clockwiseShortcut: string; anticlockwiseShortcut: string; rotateFrame(rotation: Rotation): void; diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-control.tsx index 5b57b98c451..d8b4a2998f8 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-control.tsx @@ -12,7 +12,7 @@ import { TagIcon } from 'icons'; import SetupTagPopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover'; import withVisibilityHandling from './handle-popover-visibility'; -interface Props { +export interface Props { canvasInstance: Canvas; isDrawing: boolean; } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/split-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/split-control.tsx index 61d6bfcee71..c6877459698 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/split-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/split-control.tsx @@ -10,7 +10,7 @@ import { Canvas } from 'cvat-canvas-wrapper'; import { ActiveControl } from 'reducers/interfaces'; import CVATTooltip from 'components/common/cvat-tooltip'; -interface Props { +export interface Props { canvasInstance: Canvas; activeControl: ActiveControl; switchSplitShortcut: string; diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss b/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss index 5c34151403f..80f275d7e85 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss +++ b/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss @@ -36,8 +36,7 @@ .cvat-canvas-controls-sidebar { background-color: $background-color-2; border-right: 1px solid $border-color-1; - overflow-y: auto; - overflow-x: hidden; + overflow: hidden; } .cvat-cursor-control, @@ -56,6 +55,7 @@ .cvat-split-track-control, .cvat-issue-control, .cvat-tools-control, +.cvat-extra-controls-control, .cvat-opencv-control { border-radius: 3.3px; transform: scale(0.65); @@ -75,6 +75,13 @@ } } +.cvat-extra-controls-control { + > svg { + width: 40px; + height: 40px; + } +} + .cvat-active-canvas-control { background: $header-color; transform: scale(0.75); From c793baf91073da451165aeb39d7e0e02697a80df Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Mon, 1 Mar 2021 17:40:41 +0300 Subject: [PATCH 03/17] Label form validator fix (#2879) * Fixed label form validator * Added CHANGELOG and increased package npm version * Update Cypress test "Creating a label with existing label name" for PR 2879 (#2883) * Fix case 43 for PR 2879 * Try restart CI Co-authored-by: Dmitry Kruchinin <33020454+dvkruchinin@users.noreply.github.com> --- CHANGELOG.md | 1 + cvat-ui/src/components/labels-editor/label-form.tsx | 9 +++++---- .../case_43_create_label_with_existing_label_name.js | 7 +++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 609f41fe85b..b514f510413 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated the path to python for DL models inside automatic annotation documentation () - Fixed of receiving function variable () - Shortcuts with CAPSLOCK enabled and with non-US languages activated () +- Fixed label editor name field validator () ### Security diff --git a/cvat-ui/src/components/labels-editor/label-form.tsx b/cvat-ui/src/components/labels-editor/label-form.tsx index c0f78329a53..23f16c962c6 100644 --- a/cvat-ui/src/components/labels-editor/label-form.tsx +++ b/cvat-ui/src/components/labels-editor/label-form.tsx @@ -390,10 +390,11 @@ export default class LabelForm extends React.Component { message: patterns.validateAttributeName.message, }, { - validator: async (_rule: any, labelName: string, callback: Function) => { + validator: (_rule: any, labelName: string) => { if (labelNames && labelNames.includes(labelName)) { - callback('Label name must be unique for the task'); + return Promise.reject(new Error('Label name must be unique for the task')); } + return Promise.resolve(); }, }, ]} @@ -522,7 +523,7 @@ export default class LabelForm extends React.Component { public render(): JSX.Element { return (
- + {this.renderLabelNameInput()} {this.renderChangeColorButton()} @@ -531,7 +532,7 @@ export default class LabelForm extends React.Component { {this.renderNewAttributeButton()} - + {this.renderAttributes()} diff --git a/tests/cypress/integration/actions_tasks_objects/case_43_create_label_with_existing_label_name.js b/tests/cypress/integration/actions_tasks_objects/case_43_create_label_with_existing_label_name.js index 198f7788986..796e41d1a57 100644 --- a/tests/cypress/integration/actions_tasks_objects/case_43_create_label_with_existing_label_name.js +++ b/tests/cypress/integration/actions_tasks_objects/case_43_create_label_with_existing_label_name.js @@ -24,11 +24,10 @@ context('Creating a label with existing label name.', () => { // Try to create a label with existing label name cy.get('.cvat-constructor-viewer-new-item').click(); cy.get('[placeholder="Label name"]').type(firstLabelName); - cy.contains('[type="submit"]', 'Done').click(); + cy.contains('[role="alert"]', 'Label name must be unique for the task') // Checking alert visibility + .should('exist') + .and('be.visible'); }); - cy.get('.cvat-notification-notice-update-task-failed') - .should('exist') - .and('contain.text', 'label names must be unique'); }); }); }); From cc2b8ad64bc077eac72fab3c8e665905194d7e13 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 1 Mar 2021 17:51:53 +0300 Subject: [PATCH 04/17] Added linting rule to specify import ordering (#2889) --- cvat-ui/.eslintrc.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cvat-ui/.eslintrc.js b/cvat-ui/.eslintrc.js index 28d9241e9e3..18dd267ca35 100644 --- a/cvat-ui/.eslintrc.js +++ b/cvat-ui/.eslintrc.js @@ -55,6 +55,12 @@ module.exports = { }, }, ], + 'import/order': [ + 'error', + { + 'groups': ['builtin', 'external', 'internal'], + } + ] }, settings: { 'import/resolver': { From daf479e9073c9469382f349864b2c38b6fa94cd6 Mon Sep 17 00:00:00 2001 From: Dmitry Kruchinin <33020454+dvkruchinin@users.noreply.github.com> Date: Mon, 1 Mar 2021 21:24:52 +0300 Subject: [PATCH 05/17] Linters. Selecting files if the status is not "removed". (#2888) * Add select files if have`t status "removed". * SOme fix --- .github/workflows/bandit.yml | 2 +- .github/workflows/eslint.yml | 2 +- .github/workflows/pylint.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/bandit.yml b/.github/workflows/bandit.yml index a7f25b2bca3..96d1c52f2ea 100644 --- a/.github/workflows/bandit.yml +++ b/.github/workflows/bandit.yml @@ -9,7 +9,7 @@ jobs: - name: Run checks run: | URL="https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files" - PR_FILES=$(curl -s -X GET -G $URL | jq -r '.[] | .filename') + PR_FILES=$(curl -s -X GET -G $URL | jq -r '.[] | select(.status != "removed") | .filename') for files in $PR_FILES; do extension="${files##*.}" if [[ $extension == 'py' ]]; then diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml index 66709d05209..012b5d7a9a3 100644 --- a/.github/workflows/eslint.yml +++ b/.github/workflows/eslint.yml @@ -12,7 +12,7 @@ jobs: - name: Run checks run: | URL="https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files" - PR_FILES=$(curl -s -X GET -G $URL | jq -r '.[] | .filename') + PR_FILES=$(curl -s -X GET -G $URL | jq -r '.[] | select(.status != "removed") | .filename') for files in $PR_FILES; do extension="${files##*.}" if [[ $extension == 'js' || $extension == 'ts' || $extension == 'jsx' || $extension == 'tsx' ]]; then diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 612e16a1eb0..c796214e172 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -9,7 +9,7 @@ jobs: - name: Run checks run: | URL="https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files" - PR_FILES=$(curl -s -X GET -G $URL | jq -r '.[] | .filename') + PR_FILES=$(curl -s -X GET -G $URL | jq -r '.[] | select(.status != "removed") | .filename') for files in $PR_FILES; do extension="${files##*.}" if [[ $extension == 'py' ]]; then From 638850aa10f4489dc288159037aae812c33f9a39 Mon Sep 17 00:00:00 2001 From: Dmitry Kruchinin <33020454+dvkruchinin@users.noreply.github.com> Date: Tue, 2 Mar 2021 10:26:47 +0300 Subject: [PATCH 06/17] Cypress test. Redraw feature. (#2882) * Cypress test. Redraw feature. * Add draw a tag * Move draw coboid to end and skip * Use keyCode * Remove it to redraw a tag --- .../case_54_redraw_feature.js | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 tests/cypress/integration/actions_tasks_objects/case_54_redraw_feature.js diff --git a/tests/cypress/integration/actions_tasks_objects/case_54_redraw_feature.js b/tests/cypress/integration/actions_tasks_objects/case_54_redraw_feature.js new file mode 100644 index 00000000000..f64c3ca7e9c --- /dev/null +++ b/tests/cypress/integration/actions_tasks_objects/case_54_redraw_feature.js @@ -0,0 +1,149 @@ +// Copyright (C) 2021 Intel Corporation +// +// SPDX-License-Identifier: MIT + +/// + +import { taskName, labelName } from '../../support/const'; + +context('Redraw feature.', () => { + const caseId = '54'; + const createRectangleShape2Points = { + points: 'By 2 Points', + type: 'Shape', + labelName: labelName, + firstX: 150, + firstY: 350, + secondX: 250, + secondY: 450, + }; + const createCuboidShape2Points = { + points: 'From rectangle', + type: 'Shape', + labelName: labelName, + firstX: 300, + firstY: 350, + secondX: 400, + secondY: 450, + }; + const createPolygonShape = { + reDraw: false, + type: 'Shape', + labelName: labelName, + pointsMap: [ + { x: 450, y: 350 }, + { x: 550, y: 350 }, + { x: 550, y: 450 }, + ], + complete: true, + numberOfPoints: null, + }; + const createPolylinesShape = { + type: 'Shape', + labelName: labelName, + pointsMap: [ + { x: 600, y: 350 }, + { x: 700, y: 350 }, + { x: 700, y: 450 }, + ], + complete: true, + numberOfPoints: null, + }; + const createPointsShape = { + type: 'Shape', + labelName: labelName, + pointsMap: [{ x: 750, y: 400 }], + complete: true, + numberOfPoints: null, + }; + const keyCodeN = 78; + + before(() => { + cy.openTaskJob(taskName); + }); + + describe(`Testing case "${caseId}"`, () => { + it('Draw and redraw a rectangle.', () => { + cy.createRectangle(createRectangleShape2Points); + cy.get('.cvat-canvas-container').trigger('mousemove', 200, 400); + cy.get('#cvat_canvas_shape_1').should('have.class', 'cvat_canvas_shape_activated'); + cy.get('body').trigger('keydown', { keyCode: keyCodeN, shiftKey: true }); // Start redraw the rectangle + cy.get('.cvat-canvas-container') + .click(createRectangleShape2Points.firstX, createRectangleShape2Points.firstY - 50) + .click(createRectangleShape2Points.secondX, createRectangleShape2Points.secondY - 50); + cy.get('.cvat_canvas_shape').then(($shape) => { + expect($shape.length).to.be.equal(1); + }); + cy.get('.cvat-objects-sidebar-state-item').then(($sidebarItem) => { + expect($sidebarItem.length).to.be.equal(1); + }); + }); + + it('Draw and redraw a polygon.', () => { + cy.createPolygon(createPolygonShape); + cy.get('.cvat-canvas-container').trigger('mousemove', 520, 400); + cy.get('#cvat_canvas_shape_2').should('have.class', 'cvat_canvas_shape_activated'); + cy.get('body').trigger('keydown', { keyCode: keyCodeN, shiftKey: true }); // Start redraw the polygon + createPolygonShape.pointsMap.forEach((element) => { + cy.get('.cvat-canvas-container').click(element.x, element.y - 50); + }); + cy.get('.cvat-canvas-container').trigger('keydown', { keyCode: keyCodeN }).trigger('keyup'); + cy.get('.cvat_canvas_shape').then(($shape) => { + expect($shape.length).to.be.equal(2); + }); + cy.get('.cvat-objects-sidebar-state-item').then(($sidebarItem) => { + expect($sidebarItem.length).to.be.equal(2); + }); + }); + + it('Draw and redraw a polyline.', () => { + cy.createPolyline(createPolylinesShape); + cy.get('.cvat-canvas-container').trigger('mousemove', 700, 400); + cy.get('#cvat_canvas_shape_3').should('have.class', 'cvat_canvas_shape_activated'); + cy.get('body').trigger('keydown', { keyCode: keyCodeN, shiftKey: true }); // Start redraw the polyline + createPolylinesShape.pointsMap.forEach((element) => { + cy.get('.cvat-canvas-container').click(element.x, element.y - 50); + }); + cy.get('.cvat-canvas-container').trigger('keydown', { keyCode: keyCodeN }).trigger('keyup'); + cy.get('.cvat_canvas_shape').then(($shape) => { + expect($shape.length).to.be.equal(3); + }); + cy.get('.cvat-objects-sidebar-state-item').then(($sidebarItem) => { + expect($sidebarItem.length).to.be.equal(3); + }); + }); + + it('Draw and redraw a point.', () => { + cy.createPoint(createPointsShape); + cy.get('.cvat-canvas-container').trigger('mousemove', 750, 400); + cy.get('body').trigger('keydown', { keyCode: keyCodeN, shiftKey: true }); // Start redraw the point + createPointsShape.pointsMap.forEach((element) => { + cy.get('.cvat-canvas-container').click(element.x, element.y - 50); + }); + cy.get('.cvat-canvas-container').trigger('keydown', { keyCode: keyCodeN }).trigger('keyup'); + cy.get('.cvat_canvas_shape').then(($shape) => { + expect($shape.length).to.be.equal(4); + }); + cy.get('.cvat-objects-sidebar-state-item').then(($sidebarItem) => { + expect($sidebarItem.length).to.be.equal(4); + }); + }); + + it.skip('Draw and redraw a cuboid.', () => { + // Need to fix issue https://github.com/openvinotoolkit/cvat/issues/2873 + cy.createCuboid(createCuboidShape2Points); + cy.get('.cvat-canvas-container').trigger('mousemove', 300, 400); + cy.get('#cvat_canvas_shape_5').should('have.class', 'cvat_canvas_shape_activated'); + cy.get('body').trigger('keydown', { keyCode: keyCodeN, shiftKey: true }); // Start redraw the cuboid + cy.get('.cvat-canvas-container') + .click(createCuboidShape2Points.firstX, createCuboidShape2Points.firstY - 50) + .click(createCuboidShape2Points.secondX, createCuboidShape2Points.secondY - 50); + cy.get('.cvat_canvas_shape').then(($shape) => { + expect($shape.length).to.be.equal(5); + }); + cy.get('.cvat-objects-sidebar-state-item').then(($sidebarItem) => { + expect($sidebarItem.length).to.be.equal(5); + }); + }); + }); +}); From a77b7f6b3d62ea9770b41b5dd1c835f4f93a285a Mon Sep 17 00:00:00 2001 From: Dmitry Kruchinin <33020454+dvkruchinin@users.noreply.github.com> Date: Tue, 2 Mar 2021 21:59:00 +0300 Subject: [PATCH 07/17] Cypress test. Repeat draw feature. (#2887) * Cypress test. Repeat draw feature. * Add css class * Rework the test. Apply comments. --- .../objects-side-bar/object-item-basics.tsx | 6 +- .../case_55_repeat_draw_feature.js | 149 ++++++++++++++++++ 2 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 tests/cypress/integration/actions_tasks_objects/case_55_repeat_draw_feature.js 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 0e7cda1ecd0..d33a578540c 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 @@ -98,7 +98,11 @@ function ItemTopComponent(props: Props): JSX.Element { {clientID}
- + {type} diff --git a/tests/cypress/integration/actions_tasks_objects/case_55_repeat_draw_feature.js b/tests/cypress/integration/actions_tasks_objects/case_55_repeat_draw_feature.js new file mode 100644 index 00000000000..fe1738ca1ed --- /dev/null +++ b/tests/cypress/integration/actions_tasks_objects/case_55_repeat_draw_feature.js @@ -0,0 +1,149 @@ +// Copyright (C) 2021 Intel Corporation +// +// SPDX-License-Identifier: MIT + +/// + +import { taskName, labelName } from '../../support/const'; + +context('Repeat draw feature.', () => { + const caseId = '55'; + const createRectangleShape2Points = { + points: 'By 2 Points', + type: 'Shape', + labelName: labelName, + firstX: 150, + firstY: 350, + secondX: 250, + secondY: 450, + }; + const createCuboidShape2Points = { + points: 'From rectangle', + type: 'Shape', + labelName: labelName, + firstX: 300, + firstY: 350, + secondX: 400, + secondY: 450, + }; + const createPolygonShape = { + redraw: false, + type: 'Shape', + labelName: labelName, + pointsMap: [ + { x: 450, y: 350 }, + { x: 550, y: 350 }, + { x: 550, y: 450 }, + ], + complete: true, + numberOfPoints: null, + }; + const createPolylinesShape = { + type: 'Shape', + labelName: labelName, + pointsMap: [ + { x: 600, y: 350 }, + { x: 700, y: 350 }, + { x: 700, y: 450 }, + ], + complete: true, + numberOfPoints: null, + }; + const createPointsShape = { + type: 'Shape', + labelName: labelName, + pointsMap: [{ x: 750, y: 400 }], + complete: true, + numberOfPoints: null, + }; + const keyCodeN = 78; + + function checkCountShapes(expectedCount) { + cy.get('.cvat-objects-sidebar-state-item').then(($sidebarItem) => { + expect($sidebarItem.length).to.be.equal(expectedCount); + }); + } + + function checkShapeType(id, expectedType) { + cy.get(id).find('.cvat-objects-sidebar-state-item-object-type-text').should('have.text', expectedType); + } + + function repeatDrawningStart() { + cy.get('body').trigger('keydown', { keyCode: keyCodeN }); + } + + function repeatDrawningFinish() { + cy.get('.cvat-canvas-container').trigger('keydown', { keyCode: keyCodeN }).trigger('keyup'); + } + + before(() => { + cy.openTaskJob(taskName); + }); + + describe(`Testing case "${caseId}"`, () => { + it('Draw and repeat the drawing of the rectangle.', () => { + cy.createRectangle(createRectangleShape2Points); + repeatDrawningStart(); // Repeat the drawing the rectangle + cy.get('.cvat-canvas-container') + .click(createRectangleShape2Points.firstX, createRectangleShape2Points.firstY - 200) + .click(createRectangleShape2Points.secondX, createRectangleShape2Points.secondY - 200); + cy.get('#cvat_canvas_shape_2').should('exist'); + checkCountShapes(2); + checkShapeType('#cvat-objects-sidebar-state-item-2', 'RECTANGLE SHAPE'); + }); + + it('Draw and repeat the drawing of the polygon.', () => { + cy.createPolygon(createPolygonShape); + repeatDrawningStart(); // Repeat the drawing the polygon + createPolygonShape.pointsMap.forEach((element) => { + cy.get('.cvat-canvas-container').click(element.x, element.y - 200); + }); + repeatDrawningFinish(); + cy.get('#cvat_canvas_shape_4').should('exist'); + checkCountShapes(4); + checkShapeType('#cvat-objects-sidebar-state-item-4', 'POLYGON SHAPE'); + }); + + it('Draw and repeat the drawing of the polyline.', () => { + cy.createPolyline(createPolylinesShape); + repeatDrawningStart(); // Repeat the drawing the polyline + createPolylinesShape.pointsMap.forEach((element) => { + cy.get('.cvat-canvas-container').click(element.x, element.y - 200); + }); + repeatDrawningFinish(); + cy.get('#cvat_canvas_shape_6').should('exist'); + checkCountShapes(6); + checkShapeType('#cvat-objects-sidebar-state-item-6', 'POLYLINE SHAPE'); + }); + + it('Draw and repeat the drawing of the point.', () => { + cy.createPoint(createPointsShape); + repeatDrawningStart(); // Repeat the drawing the point + createPointsShape.pointsMap.forEach((element) => { + cy.get('.cvat-canvas-container').click(element.x, element.y - 200); + }); + repeatDrawningFinish(); + cy.get('#cvat_canvas_shape_8').should('exist'); + checkCountShapes(8); + checkShapeType('#cvat-objects-sidebar-state-item-8', 'POINTS SHAPE'); + }); + + it('Draw and repeat the drawing of the cuboid.', () => { + cy.createCuboid(createCuboidShape2Points); + repeatDrawningStart(); // Repeat the drawing the cuboid + cy.get('.cvat-canvas-container') + .click(createCuboidShape2Points.firstX, createCuboidShape2Points.firstY - 200) + .click(createCuboidShape2Points.secondX, createCuboidShape2Points.secondY - 200); + cy.get('#cvat_canvas_shape_10').should('exist'); + checkCountShapes(10); + checkShapeType('#cvat-objects-sidebar-state-item-10', 'CUBOID SHAPE'); + }); + + it('Cteate and repeat the creating of the tag.', () => { + cy.createTag(labelName); + repeatDrawningStart(); // Repeat the creating the tag + cy.get('#cvat-objects-sidebar-state-item-12').should('exist'); + checkShapeType('#cvat-objects-sidebar-state-item-12', 'TAG'); + }); + }); +}); From 4191ea2df668b888c709babfe184fde389f9cc19 Mon Sep 17 00:00:00 2001 From: Dmitry Kruchinin <33020454+dvkruchinin@users.noreply.github.com> Date: Tue, 2 Mar 2021 22:01:24 +0300 Subject: [PATCH 08/17] Cypress test. Update case "Dump/upload annotation" (#2893) * Add css classes * Update cypress test * Add negative scenario --- .../components/actions-menu/actions-menu.tsx | 3 +- cvat-ui/src/reducers/notifications-reducer.ts | 3 +- .../case_52_dump_upload_annotation.js | 80 ++++++++++++++++++- 3 files changed, 80 insertions(+), 6 deletions(-) diff --git a/cvat-ui/src/components/actions-menu/actions-menu.tsx b/cvat-ui/src/components/actions-menu/actions-menu.tsx index ad7b6d55c88..52e0f05bcb1 100644 --- a/cvat-ui/src/components/actions-menu/actions-menu.tsx +++ b/cvat-ui/src/components/actions-menu/actions-menu.tsx @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation // // SPDX-License-Identifier: MIT @@ -66,6 +66,7 @@ export default function ActionsMenuComponent(props: Props): JSX.Element { Modal.confirm({ title: 'Current annotation will be lost', content: 'You are going to upload new annotations to this task. Continue?', + className: 'cvat-modal-content-load-task-annotation', onOk: () => { onClickMenu(copyParams, file); }, diff --git a/cvat-ui/src/reducers/notifications-reducer.ts b/cvat-ui/src/reducers/notifications-reducer.ts index 3bac02373db..5451eba9002 100644 --- a/cvat-ui/src/reducers/notifications-reducer.ts +++ b/cvat-ui/src/reducers/notifications-reducer.ts @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation // // SPDX-License-Identifier: MIT @@ -345,6 +345,7 @@ export default function (state = defaultState, action: AnyAction): Notifications 'Could not upload annotation for the ' + `task ${taskID}`, reason: action.payload.error.toString(), + className: 'cvat-notification-notice-load-annotation-failed', }, }, }, diff --git a/tests/cypress/integration/actions_tasks_objects/case_52_dump_upload_annotation.js b/tests/cypress/integration/actions_tasks_objects/case_52_dump_upload_annotation.js index e5d34b89f3b..ae1d9e01ba3 100644 --- a/tests/cypress/integration/actions_tasks_objects/case_52_dump_upload_annotation.js +++ b/tests/cypress/integration/actions_tasks_objects/case_52_dump_upload_annotation.js @@ -18,9 +18,47 @@ context('Dump/Upload annotation.', { browser: '!firefox' }, () => { secondY: 450, }; + const labelNameSecond = `Case ${caseId}`; + const taskNameSecond = `New annotation task for ${labelNameSecond}`; + const attrName = `Attr for ${labelNameSecond}`; + const textDefaultValue = 'Some default value for type Text'; + const imagesCount = 1; + const imageFileName = `image_${labelNameSecond.replace(' ', '_').toLowerCase()}`; + const width = 800; + const height = 800; + const posX = 10; + const posY = 10; + const color = 'gray'; + const archiveName = `${imageFileName}.zip`; + const archivePath = `cypress/fixtures/${archiveName}`; + const imagesFolder = `cypress/fixtures/${imageFileName}`; + const directoryToArchive = imagesFolder; + const dumpType = 'CVAT for images'; let annotationArchiveName = ''; + function uploadToTask(toTaskName) { + cy.contains('.cvat-item-task-name', toTaskName) + .parents('.cvat-tasks-list-item') + .find('.cvat-menu-icon') + .trigger('mouseover'); + cy.contains('Upload annotations').trigger('mouseover'); + cy.contains('.cvat-menu-load-submenu-item', dumpType.split(' ')[0]) + .should('be.visible') + .within(() => { + cy.get('.cvat-menu-load-submenu-item-button') + .click() + .get('input[type=file]') + .attachFile(annotationArchiveName); + }); + } + + function confirmUpdate(modalWindowClassName) { + cy.get(modalWindowClassName).within(() => { + cy.contains('button', 'Update').click(); + }); + } + before(() => { cy.openTaskJob(taskName); cy.createRectangle(createRectangleTrack2Points); @@ -49,7 +87,7 @@ context('Dump/Upload annotation.', { browser: '!firefox' }, () => { }); }); - it('Upload annotation.', () => { + it('Upload annotation to job.', () => { cy.interactMenu('Upload annotations'); cy.contains('.cvat-menu-load-submenu-item', dumpType.split(' ')[0]) .should('be.visible') @@ -61,14 +99,48 @@ context('Dump/Upload annotation.', { browser: '!firefox' }, () => { }); cy.intercept('PUT', '/api/v1/jobs/**/annotations**').as('uploadAnnotationsPut'); cy.intercept('GET', '/api/v1/jobs/**/annotations**').as('uploadAnnotationsGet'); - cy.get('.cvat-modal-content-load-job-annotation').within(() => { - cy.contains('button', 'Update').click(); - }); + confirmUpdate('.cvat-modal-content-load-job-annotation'); cy.wait('@uploadAnnotationsPut', { timeout: 5000 }).its('response.statusCode').should('equal', 202); cy.wait('@uploadAnnotationsPut').its('response.statusCode').should('equal', 201); cy.wait('@uploadAnnotationsGet').its('response.statusCode').should('equal', 200); cy.get('#cvat_canvas_shape_1').should('exist'); cy.get('#cvat-objects-sidebar-state-item-1').should('exist'); + cy.removeAnnotations(); + }); + + it('Upload annotation to task.', () => { + cy.goToTaskList(); + uploadToTask(taskName); + confirmUpdate('.cvat-modal-content-load-task-annotation'); + cy.contains('Annotations have been loaded').should('be.visible'); + cy.get('[data-icon="close"]').click(); + cy.openTaskJob(taskName, 0, false); + cy.get('#cvat_canvas_shape_1').should('exist'); + cy.get('#cvat-objects-sidebar-state-item-1').should('exist'); + }); + + it('Upload annotation to task which does not match the parameters. The error should be exist.', () => { + cy.goToTaskList(); + cy.imageGenerator( + imagesFolder, + imageFileName, + width, + height, + color, + posX, + posY, + labelNameSecond, + imagesCount, + ); + cy.createZipArchive(directoryToArchive, archivePath); + cy.createAnnotationTask(taskNameSecond, labelNameSecond, attrName, textDefaultValue, archiveName); + uploadToTask(taskNameSecond); + confirmUpdate('.cvat-modal-content-load-task-annotation'); + cy.get('.cvat-notification-notice-load-annotation-failed') + .should('exist') + .find('[aria-label="close"]') + .click(); + cy.deleteTask(taskNameSecond); }); }); }); From 5e6a51acf4a6b3dd8372424dbe61579f90414eb4 Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Wed, 3 Mar 2021 13:36:41 +0300 Subject: [PATCH 09/17] Fix 2827 (#2890) * Fix 2827 * update changelog --- CHANGELOG.md | 1 + cvat/apps/dataset_manager/annotation.py | 6 +- cvat/apps/dataset_manager/bindings.py | 5 ++ .../dataset_manager/tests/test_formats.py | 58 ++++++++++++++++++- 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b514f510413..14cfa6c6ae4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed of receiving function variable () - Shortcuts with CAPSLOCK enabled and with non-US languages activated () - Fixed label editor name field validator () +- An error about track shapes outside of the task frames during export () ### Security diff --git a/cvat/apps/dataset_manager/annotation.py b/cvat/apps/dataset_manager/annotation.py index b6dbe1c1748..f10c3af587e 100644 --- a/cvat/apps/dataset_manager/annotation.py +++ b/cvat/apps/dataset_manager/annotation.py @@ -110,7 +110,7 @@ def filter_track_shapes(shapes): # Track and TrackedShape models don't expect these fields del track['interpolated_shapes'] for shape in segment_shapes: - del shape['keyframe'] + shape.pop('keyframe', None) track['shapes'] = segment_shapes track['frame'] = track['shapes'][0]['frame'] @@ -746,6 +746,10 @@ def interpolate(shape0, shape1): curr_frame = shape["frame"] prev_shape = shape + # keep at least 1 shape + if end_frame <= curr_frame: + break + if not prev_shape["outside"]: shape = copy(prev_shape) shape["frame"] = end_frame diff --git a/cvat/apps/dataset_manager/bindings.py b/cvat/apps/dataset_manager/bindings.py index 38444d4d18b..a336a00715d 100644 --- a/cvat/apps/dataset_manager/bindings.py +++ b/cvat/apps/dataset_manager/bindings.py @@ -267,6 +267,11 @@ def get_frame(idx): anno_manager = AnnotationManager(self._annotation_ir) for shape in sorted(anno_manager.to_shapes(self._db_task.data.size), key=lambda shape: shape.get("z_order", 0)): + if shape['frame'] not in self._frame_info: + # After interpolation there can be a finishing frame + # outside of the task boundaries. Filter it out to avoid errors. + # https://github.com/openvinotoolkit/cvat/issues/2827 + continue if 'track_id' in shape: if shape['outside']: continue diff --git a/cvat/apps/dataset_manager/tests/test_formats.py b/cvat/apps/dataset_manager/tests/test_formats.py index a01e60b78ae..0c23eea73db 100644 --- a/cvat/apps/dataset_manager/tests/test_formats.py +++ b/cvat/apps/dataset_manager/tests/test_formats.py @@ -71,6 +71,13 @@ def _put_api_v1_task_id_annotations(self, tid, data): return response + def _put_api_v1_job_id_annotations(self, jid, data): + with ForceLogin(self.user, self.client): + response = self.client.put("/api/v1/jobs/%s/annotations" % jid, + data=data, format="json") + + return response + def _create_task(self, data, image_data): with ForceLogin(self.user, self.client): response = self.client.post('/api/v1/tasks', data=data, format="json") @@ -87,6 +94,10 @@ def _create_task(self, data, image_data): return task class TaskExportTest(_DbTestBase): + def _generate_custom_annotations(self, annotations, task): + self._put_api_v1_task_id_annotations(task["id"], annotations) + return annotations + def _generate_annotations(self, task): annotations = { "version": 0, @@ -204,8 +215,7 @@ def _generate_annotations(self, task): }, ] } - self._put_api_v1_task_id_annotations(task["id"], annotations) - return annotations + return self._generate_custom_annotations(annotations, task) def _generate_task_images(self, count): # pylint: disable=no-self-use images = { @@ -215,7 +225,7 @@ def _generate_task_images(self, count): # pylint: disable=no-self-use images["image_quality"] = 75 return images - def _generate_task(self, images): + def _generate_task(self, images, **overrides): task = { "name": "my task #1", "overlap": 0, @@ -242,6 +252,7 @@ def _generate_task(self, images): {"name": "person"}, ] } + task.update(overrides) return self._create_task(task, images) @staticmethod @@ -422,6 +433,47 @@ def test_can_make_abs_frame_id_from_known(self): self.assertEqual(5, task_data.abs_frame_id(2)) + def test_frames_outside_are_not_generated(self): + # https://github.com/openvinotoolkit/cvat/issues/2827 + images = self._generate_task_images(10) + images['start_frame'] = 0 + task = self._generate_task(images, overlap=3, segment_size=6) + annotations = { + "version": 0, + "tags": [], + "shapes": [], + "tracks": [ + { + "frame": 6, + "label_id": task["labels"][0]["id"], + "group": None, + "source": "manual", + "attributes": [], + "shapes": [ + { + "frame": 6, + "points": [1.0, 2.1, 100, 300.222], + "type": "rectangle", + "occluded": False, + "outside": False, + "attributes": [], + }, + ] + }, + ] + } + self._put_api_v1_job_id_annotations( + task["segments"][2]["jobs"][0]["id"], annotations) + + task_ann = TaskAnnotation(task["id"]) + task_ann.init_from_db() + task_data = TaskData(task_ann.ir_data, Task.objects.get(pk=task['id'])) + + i = -1 + for i, frame in enumerate(task_data.group_by_frame()): + self.assertTrue(frame.frame in range(6, 10)) + self.assertEqual(i + 1, 4) + class FrameMatchingTest(_DbTestBase): def _generate_task_images(self, paths): # pylint: disable=no-self-use f = BytesIO() From d5312df891f134a6a8f1ca9afe74d927a5889693 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 3 Mar 2021 13:45:17 +0300 Subject: [PATCH 10/17] Fixed: cannot close some issues (#2868) * Squashed commits * Merged develop * Aborted chanegs * Added ability to scroll issues * Aborted change * Updated version --- CHANGELOG.md | 1 + cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- .../annotation-page/review/hidden-issue-label.tsx | 15 ++++++++++++++- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14cfa6c6ae4..7bb9bdc3e86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated the path to python for DL models inside automatic annotation documentation () - Fixed of receiving function variable () - Shortcuts with CAPSLOCK enabled and with non-US languages activated () +- Prevented creating several issues for the same object () - Fixed label editor name field validator () - An error about track shapes outside of the task frames during export () diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 0cd1ddc4cb3..a51ba06021b 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.15.1", + "version": "1.15.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 5d8bf3b4b3e..027fffe5897 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.15.1", + "version": "1.15.2", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { diff --git a/cvat-ui/src/components/annotation-page/review/hidden-issue-label.tsx b/cvat-ui/src/components/annotation-page/review/hidden-issue-label.tsx index 579bec3129f..1be37564d95 100644 --- a/cvat-ui/src/components/annotation-page/review/hidden-issue-label.tsx +++ b/cvat-ui/src/components/annotation-page/review/hidden-issue-label.tsx @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: MIT -import React, { ReactPortal, useEffect } from 'react'; +import React, { ReactPortal, useEffect, useRef } from 'react'; import ReactDOM from 'react-dom'; import Tag from 'antd/lib/tag'; import { CheckOutlined, CloseCircleOutlined } from '@ant-design/icons'; @@ -25,6 +25,8 @@ export default function HiddenIssueLabel(props: Props): ReactPortal { id, message, top, left, resolved, onClick, highlight, blur, } = props; + const ref = useRef(null); + useEffect(() => { if (!resolved) { setTimeout(highlight); @@ -37,10 +39,21 @@ export default function HiddenIssueLabel(props: Props): ReactPortal { return ReactDOM.createPortal( { + if (ref.current !== null) { + const selfElement = ref.current; + if (event.deltaX > 0) { + selfElement.parentElement?.appendChild(selfElement); + } else { + selfElement.parentElement?.prepend(selfElement); + } + } + }} style={{ top, left }} className='cvat-hidden-issue-label' > From 9b62b71ab13f03258d698b4128669aab4c54fde5 Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Wed, 3 Mar 2021 14:35:53 +0300 Subject: [PATCH 11/17] Update CVAT formats to use changes in Datumaro API (#2794) * update cvat formats to use datumaro changes * Update datumaro dependency * Add comments on datumaro install in requirements * fix linter * Fix test * fix linter * Update datumaro version to 0.1.6.1 --- cvat/apps/dataset_manager/formats/camvid.py | 22 ++++++++-------- cvat/apps/dataset_manager/formats/coco.py | 15 +++++------ cvat/apps/dataset_manager/formats/cvat.py | 3 ++- cvat/apps/dataset_manager/formats/imagenet.py | 20 +++++++-------- cvat/apps/dataset_manager/formats/labelme.py | 14 +++++------ cvat/apps/dataset_manager/formats/mask.py | 21 +++++++--------- cvat/apps/dataset_manager/formats/mot.py | 13 +++++----- cvat/apps/dataset_manager/formats/mots.py | 25 ++++++++----------- .../dataset_manager/formats/pascal_voc.py | 16 ++++++------ cvat/apps/dataset_manager/formats/tfrecord.py | 9 +++---- cvat/apps/dataset_manager/formats/yolo.py | 13 +++++----- .../dataset_manager/tests/test_formats.py | 7 +++--- cvat/requirements/base.txt | 8 ++++-- 13 files changed, 88 insertions(+), 98 deletions(-) diff --git a/cvat/apps/dataset_manager/formats/camvid.py b/cvat/apps/dataset_manager/formats/camvid.py index bcd00b7a7bf..a8fb50592e9 100644 --- a/cvat/apps/dataset_manager/formats/camvid.py +++ b/cvat/apps/dataset_manager/formats/camvid.py @@ -4,7 +4,7 @@ from tempfile import TemporaryDirectory -from datumaro.components.project import Dataset +from datumaro.components.dataset import Dataset from pyunpack import Archive from cvat.apps.dataset_manager.bindings import (CvatTaskDataExtractor, @@ -17,16 +17,15 @@ @exporter(name='CamVid', ext='ZIP', version='1.0') def _export(dst_file, task_data, save_images=False): - extractor = CvatTaskDataExtractor(task_data, include_images=save_images) - envt = dm_env.transforms - extractor = extractor.transform(envt.get('polygons_to_masks')) - extractor = extractor.transform(envt.get('boxes_to_masks')) - extractor = extractor.transform(envt.get('merge_instance_segments')) - extractor = Dataset.from_extractors(extractor) # apply lazy transforms + dataset = Dataset.from_extractors(CvatTaskDataExtractor( + task_data, include_images=save_images), env=dm_env) + dataset.transform('polygons_to_masks') + dataset.transform('boxes_to_masks') + dataset.transform('merge_instance_segments') label_map = make_colormap(task_data) with TemporaryDirectory() as temp_dir: - dm_env.converters.get('camvid').convert(extractor, - save_dir=temp_dir, save_images=save_images, apply_colormap=True, + dataset.export(temp_dir, 'camvid', + save_images=save_images, apply_colormap=True, label_map={label: label_map[label][0] for label in label_map}) make_zip_archive(temp_dir, dst_file) @@ -36,7 +35,6 @@ def _import(src_file, task_data): with TemporaryDirectory() as tmp_dir: Archive(src_file.name).extractall(tmp_dir) - dataset = dm_env.make_importer('camvid')(tmp_dir).make_dataset() - masks_to_polygons = dm_env.transforms.get('masks_to_polygons') - dataset = dataset.transform(masks_to_polygons) + dataset = Dataset.import_from(tmp_dir, 'camvid', env=dm_env) + dataset.transform('masks_to_polygons') import_dm_annotations(dataset, task_data) diff --git a/cvat/apps/dataset_manager/formats/coco.py b/cvat/apps/dataset_manager/formats/coco.py index 84472d3aab1..3ec3ab18e82 100644 --- a/cvat/apps/dataset_manager/formats/coco.py +++ b/cvat/apps/dataset_manager/formats/coco.py @@ -5,7 +5,8 @@ import zipfile from tempfile import TemporaryDirectory -from datumaro.components.project import Dataset +from datumaro.components.dataset import Dataset + from cvat.apps.dataset_manager.bindings import CvatTaskDataExtractor, \ import_dm_annotations from cvat.apps.dataset_manager.util import make_zip_archive @@ -15,11 +16,10 @@ @exporter(name='COCO', ext='ZIP', version='1.0') def _export(dst_file, task_data, save_images=False): - extractor = CvatTaskDataExtractor(task_data, include_images=save_images) - extractor = Dataset.from_extractors(extractor) # apply lazy transforms + dataset = Dataset.from_extractors(CvatTaskDataExtractor( + task_data, include_images=save_images), env=dm_env) with TemporaryDirectory() as temp_dir: - dm_env.converters.get('coco_instances').convert(extractor, - save_dir=temp_dir, save_images=save_images) + dataset.export(temp_dir, 'coco_instances', save_images=save_images) make_zip_archive(temp_dir, dst_file) @@ -29,8 +29,9 @@ def _import(src_file, task_data): with TemporaryDirectory() as tmp_dir: zipfile.ZipFile(src_file).extractall(tmp_dir) - dataset = dm_env.make_importer('coco')(tmp_dir).make_dataset() + dataset = Dataset.import_from(tmp_dir, 'coco', env=dm_env) import_dm_annotations(dataset, task_data) else: - dataset = dm_env.make_extractor('coco_instances', src_file.name) + dataset = Dataset.import_from(src_file.name, + 'coco_instances', env=dm_env) import_dm_annotations(dataset, task_data) \ No newline at end of file diff --git a/cvat/apps/dataset_manager/formats/cvat.py b/cvat/apps/dataset_manager/formats/cvat.py index d825dae0c65..02025afc750 100644 --- a/cvat/apps/dataset_manager/formats/cvat.py +++ b/cvat/apps/dataset_manager/formats/cvat.py @@ -9,10 +9,11 @@ from glob import glob from tempfile import TemporaryDirectory +from datumaro.components.extractor import DatasetItem + from cvat.apps.dataset_manager.bindings import match_dm_item from cvat.apps.dataset_manager.util import make_zip_archive from cvat.apps.engine.frame_provider import FrameProvider -from datumaro.components.extractor import DatasetItem from .registry import exporter, importer diff --git a/cvat/apps/dataset_manager/formats/imagenet.py b/cvat/apps/dataset_manager/formats/imagenet.py index d9847549f9e..2ed0cb47484 100644 --- a/cvat/apps/dataset_manager/formats/imagenet.py +++ b/cvat/apps/dataset_manager/formats/imagenet.py @@ -3,12 +3,12 @@ # SPDX-License-Identifier: MIT import os.path as osp -from glob import glob - import zipfile +from glob import glob from tempfile import TemporaryDirectory -from datumaro.components.project import Dataset +from datumaro.components.dataset import Dataset + from cvat.apps.dataset_manager.bindings import CvatTaskDataExtractor, \ import_dm_annotations from cvat.apps.dataset_manager.util import make_zip_archive @@ -18,15 +18,13 @@ @exporter(name='ImageNet', ext='ZIP', version='1.0') def _export(dst_file, task_data, save_images=False): - extractor = CvatTaskDataExtractor(task_data, include_images=save_images) - extractor = Dataset.from_extractors(extractor) # apply lazy transform + dataset = Dataset.from_extractors(CvatTaskDataExtractor( + task_data, include_images=save_images), env=dm_env) with TemporaryDirectory() as temp_dir: if save_images: - dm_env.converters.get('imagenet').convert(extractor, - save_dir=temp_dir, save_images=save_images) + dataset.export(temp_dir, 'imagenet', save_images=save_images) else: - dm_env.converters.get('imagenet_txt').convert(extractor, - save_dir=temp_dir, save_images=save_images) + dataset.export(temp_dir, 'imagenet_txt', save_images=save_images) make_zip_archive(temp_dir, dst_file) @@ -35,7 +33,7 @@ def _import(src_file, task_data): with TemporaryDirectory() as tmp_dir: zipfile.ZipFile(src_file).extractall(tmp_dir) if glob(osp.join(tmp_dir, '*.txt')): - dataset = dm_env.make_importer('imagenet_txt')(tmp_dir).make_dataset() + dataset = Dataset.import_from(tmp_dir, 'imagenet_txt', env=dm_env) else: - dataset = dm_env.make_importer('imagenet')(tmp_dir).make_dataset() + dataset = Dataset.import_from(tmp_dir, 'imagenet', env=dm_env) import_dm_annotations(dataset, task_data) \ No newline at end of file diff --git a/cvat/apps/dataset_manager/formats/labelme.py b/cvat/apps/dataset_manager/formats/labelme.py index d3bd074d4d3..744b11faab0 100644 --- a/cvat/apps/dataset_manager/formats/labelme.py +++ b/cvat/apps/dataset_manager/formats/labelme.py @@ -4,23 +4,22 @@ from tempfile import TemporaryDirectory +from datumaro.components.dataset import Dataset from pyunpack import Archive from cvat.apps.dataset_manager.bindings import (CvatTaskDataExtractor, import_dm_annotations) from cvat.apps.dataset_manager.util import make_zip_archive -from datumaro.components.project import Dataset from .registry import dm_env, exporter, importer @exporter(name='LabelMe', ext='ZIP', version='3.0') def _export(dst_file, task_data, save_images=False): - extractor = CvatTaskDataExtractor(task_data, include_images=save_images) - extractor = Dataset.from_extractors(extractor) # apply lazy transforms + dataset = Dataset.from_extractors(CvatTaskDataExtractor( + task_data, include_images=save_images), env=dm_env) with TemporaryDirectory() as temp_dir: - dm_env.converters.get('label_me').convert(extractor, save_dir=temp_dir, - save_images=save_images) + dataset.export(temp_dir, 'label_me', save_images=save_images) make_zip_archive(temp_dir, dst_file) @@ -29,7 +28,6 @@ def _import(src_file, task_data): with TemporaryDirectory() as tmp_dir: Archive(src_file.name).extractall(tmp_dir) - dataset = dm_env.make_importer('label_me')(tmp_dir).make_dataset() - masks_to_polygons = dm_env.transforms.get('masks_to_polygons') - dataset = dataset.transform(masks_to_polygons) + dataset = Dataset.import_from(tmp_dir, 'label_me', env=dm_env) + dataset.transform('masks_to_polygons') import_dm_annotations(dataset, task_data) diff --git a/cvat/apps/dataset_manager/formats/mask.py b/cvat/apps/dataset_manager/formats/mask.py index b1307a9cead..3e3780e8c6a 100644 --- a/cvat/apps/dataset_manager/formats/mask.py +++ b/cvat/apps/dataset_manager/formats/mask.py @@ -4,12 +4,12 @@ from tempfile import TemporaryDirectory +from datumaro.components.dataset import Dataset from pyunpack import Archive from cvat.apps.dataset_manager.bindings import (CvatTaskDataExtractor, import_dm_annotations) from cvat.apps.dataset_manager.util import make_zip_archive -from datumaro.components.project import Dataset from .registry import dm_env, exporter, importer from .utils import make_colormap @@ -17,15 +17,13 @@ @exporter(name='Segmentation mask', ext='ZIP', version='1.1') def _export(dst_file, task_data, save_images=False): - extractor = CvatTaskDataExtractor(task_data, include_images=save_images) - envt = dm_env.transforms - extractor = extractor.transform(envt.get('polygons_to_masks')) - extractor = extractor.transform(envt.get('boxes_to_masks')) - extractor = extractor.transform(envt.get('merge_instance_segments')) - extractor = Dataset.from_extractors(extractor) # apply lazy transforms + dataset = Dataset.from_extractors(CvatTaskDataExtractor( + task_data, include_images=save_images), env=dm_env) + dataset.transform('polygons_to_masks') + dataset.transform('boxes_to_masks') + dataset.transform('merge_instance_segments') with TemporaryDirectory() as temp_dir: - dm_env.converters.get('voc_segmentation').convert(extractor, - save_dir=temp_dir, save_images=save_images, + dataset.export(temp_dir, 'voc_segmentation', save_images=save_images, apply_colormap=True, label_map=make_colormap(task_data)) make_zip_archive(temp_dir, dst_file) @@ -35,7 +33,6 @@ def _import(src_file, task_data): with TemporaryDirectory() as tmp_dir: Archive(src_file.name).extractall(tmp_dir) - dataset = dm_env.make_importer('voc')(tmp_dir).make_dataset() - masks_to_polygons = dm_env.transforms.get('masks_to_polygons') - dataset = dataset.transform(masks_to_polygons) + dataset = Dataset.import_from(tmp_dir, 'voc', env=dm_env) + dataset.transform('masks_to_polygons') import_dm_annotations(dataset, task_data) diff --git a/cvat/apps/dataset_manager/formats/mot.py b/cvat/apps/dataset_manager/formats/mot.py index 81131dc1504..29d5182a674 100644 --- a/cvat/apps/dataset_manager/formats/mot.py +++ b/cvat/apps/dataset_manager/formats/mot.py @@ -4,23 +4,22 @@ from tempfile import TemporaryDirectory +import datumaro.components.extractor as datumaro +from datumaro.components.dataset import Dataset from pyunpack import Archive -import datumaro.components.extractor as datumaro from cvat.apps.dataset_manager.bindings import CvatTaskDataExtractor from cvat.apps.dataset_manager.util import make_zip_archive -from datumaro.components.project import Dataset from .registry import dm_env, exporter, importer @exporter(name='MOT', ext='ZIP', version='1.1') def _export(dst_file, task_data, save_images=False): - extractor = CvatTaskDataExtractor(task_data, include_images=save_images) - extractor = Dataset.from_extractors(extractor) # apply lazy transforms + dataset = Dataset.from_extractors(CvatTaskDataExtractor( + task_data, include_images=save_images), env=dm_env) with TemporaryDirectory() as temp_dir: - dm_env.converters.get('mot_seq_gt').convert(extractor, - save_dir=temp_dir, save_images=save_images) + dataset.export(temp_dir, 'mot_seq_gt', save_images=save_images) make_zip_archive(temp_dir, dst_file) @@ -29,7 +28,7 @@ def _import(src_file, task_data): with TemporaryDirectory() as tmp_dir: Archive(src_file.name).extractall(tmp_dir) - dataset = dm_env.make_importer('mot_seq')(tmp_dir).make_dataset() + dataset = Dataset.import_from(tmp_dir, 'mot_seq', env=dm_env) tracks = {} label_cat = dataset.categories()[datumaro.AnnotationType.label] diff --git a/cvat/apps/dataset_manager/formats/mots.py b/cvat/apps/dataset_manager/formats/mots.py index 52bf0fa623a..22b9dd08c7e 100644 --- a/cvat/apps/dataset_manager/formats/mots.py +++ b/cvat/apps/dataset_manager/formats/mots.py @@ -4,13 +4,13 @@ from tempfile import TemporaryDirectory +from datumaro.components.dataset import Dataset +from datumaro.components.extractor import AnnotationType, Transform from pyunpack import Archive from cvat.apps.dataset_manager.bindings import (CvatTaskDataExtractor, find_dataset_root, match_dm_item) from cvat.apps.dataset_manager.util import make_zip_archive -from datumaro.components.extractor import AnnotationType, Transform -from datumaro.components.project import Dataset from .registry import dm_env, exporter, importer @@ -22,16 +22,14 @@ def transform_item(self, item): @exporter(name='MOTS PNG', ext='ZIP', version='1.0') def _export(dst_file, task_data, save_images=False): - extractor = CvatTaskDataExtractor(task_data, include_images=save_images) - envt = dm_env.transforms - extractor = extractor.transform(KeepTracks) # can only export tracks - extractor = extractor.transform(envt.get('polygons_to_masks')) - extractor = extractor.transform(envt.get('boxes_to_masks')) - extractor = extractor.transform(envt.get('merge_instance_segments')) - extractor = Dataset.from_extractors(extractor) # apply lazy transforms + dataset = Dataset.from_extractors(CvatTaskDataExtractor( + task_data, include_images=save_images), env=dm_env) + dataset.transform(KeepTracks) # can only export tracks + dataset.transform('polygons_to_masks') + dataset.transform('boxes_to_masks') + dataset.transform('merge_instance_segments') with TemporaryDirectory() as temp_dir: - dm_env.converters.get('mots_png').convert(extractor, - save_dir=temp_dir, save_images=save_images) + dataset.export(temp_dir, 'mots_png', save_images=save_images) make_zip_archive(temp_dir, dst_file) @@ -40,9 +38,8 @@ def _import(src_file, task_data): with TemporaryDirectory() as tmp_dir: Archive(src_file.name).extractall(tmp_dir) - dataset = dm_env.make_importer('mots')(tmp_dir).make_dataset() - masks_to_polygons = dm_env.transforms.get('masks_to_polygons') - dataset = dataset.transform(masks_to_polygons) + dataset = Dataset.import_from(tmp_dir, 'mots', env=dm_env) + dataset.transform('masks_to_polygons') tracks = {} label_cat = dataset.categories()[AnnotationType.label] diff --git a/cvat/apps/dataset_manager/formats/pascal_voc.py b/cvat/apps/dataset_manager/formats/pascal_voc.py index ee30564bc1e..3f10b93aa93 100644 --- a/cvat/apps/dataset_manager/formats/pascal_voc.py +++ b/cvat/apps/dataset_manager/formats/pascal_voc.py @@ -6,26 +6,25 @@ import os.path as osp import shutil from glob import glob - from tempfile import TemporaryDirectory +from datumaro.components.dataset import Dataset from pyunpack import Archive from cvat.apps.dataset_manager.bindings import (CvatTaskDataExtractor, import_dm_annotations) from cvat.apps.dataset_manager.util import make_zip_archive -from datumaro.components.project import Dataset from .registry import dm_env, exporter, importer @exporter(name='PASCAL VOC', ext='ZIP', version='1.1') def _export(dst_file, task_data, save_images=False): - extractor = CvatTaskDataExtractor(task_data, include_images=save_images) - extractor = Dataset.from_extractors(extractor) # apply lazy transforms + dataset = Dataset.from_extractors(CvatTaskDataExtractor( + task_data, include_images=save_images), env=dm_env) with TemporaryDirectory() as temp_dir: - dm_env.converters.get('voc').convert(extractor, - save_dir=temp_dir, save_images=save_images, label_map='source') + dataset.export(temp_dir, 'voc', save_images=save_images, + label_map='source') make_zip_archive(temp_dir, dst_file) @@ -56,7 +55,6 @@ def _import(src_file, task_data): for f in anno_files: shutil.move(f, anno_dir) - dataset = dm_env.make_importer('voc')(tmp_dir).make_dataset() - masks_to_polygons = dm_env.transforms.get('masks_to_polygons') - dataset = dataset.transform(masks_to_polygons) + dataset = Dataset.import_from(tmp_dir, 'voc', env=dm_env) + dataset.transform('masks_to_polygons') import_dm_annotations(dataset, task_data) diff --git a/cvat/apps/dataset_manager/formats/tfrecord.py b/cvat/apps/dataset_manager/formats/tfrecord.py index 3b7e123eb63..9847bf61b66 100644 --- a/cvat/apps/dataset_manager/formats/tfrecord.py +++ b/cvat/apps/dataset_manager/formats/tfrecord.py @@ -24,11 +24,10 @@ @exporter(name='TFRecord', ext='ZIP', version='1.0', enabled=tf_available) def _export(dst_file, task_data, save_images=False): - extractor = CvatTaskDataExtractor(task_data, include_images=save_images) - extractor = Dataset.from_extractors(extractor) # apply lazy transforms + dataset = Dataset.from_extractors(CvatTaskDataExtractor( + task_data, include_images=save_images), env=dm_env) with TemporaryDirectory() as temp_dir: - dm_env.converters.get('tf_detection_api').convert(extractor, - save_dir=temp_dir, save_images=save_images) + dataset.export(temp_dir, 'tf_detection_api', save_images=save_images) make_zip_archive(temp_dir, dst_file) @@ -37,5 +36,5 @@ def _import(src_file, task_data): with TemporaryDirectory() as tmp_dir: Archive(src_file.name).extractall(tmp_dir) - dataset = dm_env.make_importer('tf_detection_api')(tmp_dir).make_dataset() + dataset = Dataset.import_from(tmp_dir, 'tf_detection_api', env=dm_env) import_dm_annotations(dataset, task_data) diff --git a/cvat/apps/dataset_manager/formats/yolo.py b/cvat/apps/dataset_manager/formats/yolo.py index bea73b3c3bd..0df6f5fe27a 100644 --- a/cvat/apps/dataset_manager/formats/yolo.py +++ b/cvat/apps/dataset_manager/formats/yolo.py @@ -20,11 +20,10 @@ @exporter(name='YOLO', ext='ZIP', version='1.1') def _export(dst_file, task_data, save_images=False): - extractor = CvatTaskDataExtractor(task_data, include_images=save_images) - extractor = Dataset.from_extractors(extractor) # apply lazy transforms + dataset = Dataset.from_extractors(CvatTaskDataExtractor( + task_data, include_images=save_images), env=dm_env) with TemporaryDirectory() as temp_dir: - dm_env.converters.get('yolo').convert(extractor, - save_dir=temp_dir, save_images=save_images) + dataset.export(temp_dir, 'yolo', save_images=save_images) make_zip_archive(temp_dir, dst_file) @@ -44,11 +43,11 @@ def _import(src_file, task_data): frame_id = match_dm_item(DatasetItem(id=frame), task_data, root_hint=root_hint) frame_info = task_data.frame_info[frame_id] - except Exception: + except Exception: # nosec pass if frame_info is not None: image_info[frame] = (frame_info['height'], frame_info['width']) - dataset = dm_env.make_importer('yolo')(tmp_dir, image_info=image_info) \ - .make_dataset() + dataset = Dataset.import_from(tmp_dir, 'yolo', + env=dm_env, image_info=image_info) import_dm_annotations(dataset, task_data) diff --git a/cvat/apps/dataset_manager/tests/test_formats.py b/cvat/apps/dataset_manager/tests/test_formats.py index 0c23eea73db..5103da65ba3 100644 --- a/cvat/apps/dataset_manager/tests/test_formats.py +++ b/cvat/apps/dataset_manager/tests/test_formats.py @@ -357,17 +357,18 @@ def load_dataset(src): project.config.remove('sources') return project.make_dataset() - return dm_env.make_importer(importer_name)(src) \ - .make_dataset() + return datumaro.components.dataset. \ + Dataset.import_from(src, importer_name, env=dm_env) if zipfile.is_zipfile(file_path): with tempfile.TemporaryDirectory() as tmp_dir: zipfile.ZipFile(file_path).extractall(tmp_dir) dataset = load_dataset(tmp_dir) + self.assertEqual(len(dataset), task["size"]) else: dataset = load_dataset(file_path) + self.assertEqual(len(dataset), task["size"]) - self.assertEqual(len(dataset), task["size"]) self._test_export(check, task, format_name, save_images=False) def test_can_skip_outside(self): diff --git a/cvat/requirements/base.txt b/cvat/requirements/base.txt index c8a6bda4791..98ea74c5fec 100644 --- a/cvat/requirements/base.txt +++ b/cvat/requirements/base.txt @@ -45,5 +45,9 @@ tensorflow==2.4.1 # Optional requirement of Datumaro patool==1.12 diskcache==5.0.2 open3d==0.11.2 -# workaround for binary incompatibility with numpy when pycocotools is installed by wheel -datumaro==0.1.5.1 --no-binary=datumaro --no-binary=pycocotools +# --no-binary=datumaro: workaround for pip to install +# opencv-headless instead of regular opencv, to actually run setup script +# --no-binary=pycocotools: workaround for binary incompatibility on numpy 1.20 +# of pycocotools and tensorflow 2.4.1 +# when pycocotools is installed by wheel in python 3.8+ +datumaro==0.1.6.1 --no-binary=datumaro --no-binary=pycocotools From 277a3bad98b120b0f4eb65dc0fb5471edb0b3430 Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Wed, 3 Mar 2021 18:23:37 +0300 Subject: [PATCH 12/17] Fixed project search field (#2901) * Fixed project search field clearing * Added CHANGELOG and incresed npm package version --- CHANGELOG.md | 1 + cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- .../create-task-page/project-search-field.tsx | 30 +++++++++++-------- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bb9bdc3e86..f1b2c03a858 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Prevented creating several issues for the same object () - Fixed label editor name field validator () - An error about track shapes outside of the task frames during export () +- Fixed project search field updating () ### Security diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index a51ba06021b..88465e0711b 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.15.2", + "version": "1.15.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 027fffe5897..dff1015e2fc 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.15.2", + "version": "1.15.3", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { diff --git a/cvat-ui/src/components/create-task-page/project-search-field.tsx b/cvat-ui/src/components/create-task-page/project-search-field.tsx index 450cbf953d1..9bab28e2b4f 100644 --- a/cvat-ui/src/components/create-task-page/project-search-field.tsx +++ b/cvat-ui/src/components/create-task-page/project-search-field.tsx @@ -59,19 +59,23 @@ export default function ProjectSearchField(props: Props): JSX.Element { }; useEffect(() => { - if (value && !projects.filter((project) => project.id === value).length) { - core.projects.get({ id: value }).then((result: Project[]) => { - const [project] = result; - setProjects([ - ...projects, - { - id: project.id, - name: project.name, - }, - ]); - setSearchPhrase(project.name); - onSelect(project.id); - }); + if (value) { + if (!projects.filter((project) => project.id === value).length) { + core.projects.get({ id: value }).then((result: Project[]) => { + const [project] = result; + setProjects([ + ...projects, + { + id: project.id, + name: project.name, + }, + ]); + setSearchPhrase(project.name); + onSelect(project.id); + }); + } + } else { + setSearchPhrase(''); } }, [value]); From a8b82e2d237480024820ab51ea806a957208fb78 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Thu, 4 Mar 2021 08:41:41 +0300 Subject: [PATCH 13/17] fix: upgrade antd from 4.12.2 to 4.12.3 (#2905) Snyk has created this PR to upgrade antd from 4.12.2 to 4.12.3. See this package in npm: https://www.npmjs.com/package/antd See this project in Snyk: https://app.snyk.io/org/cvat/project/c1f463ee-3776-44c4-b0fa-cd2254d0a094?utm_source=github&utm_medium=upgrade-pr Co-authored-by: snyk-bot --- cvat-ui/package-lock.json | 265 +++++++++++++++++++++----------------- cvat-ui/package.json | 2 +- 2 files changed, 146 insertions(+), 121 deletions(-) diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 88465e0711b..e3be999c8a8 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -58,9 +58,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -1886,12 +1886,12 @@ } }, "antd": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/antd/-/antd-4.12.2.tgz", - "integrity": "sha512-xB7sGg2qM/Sl3azjbc2RbJQ6cTr2Fos0AYZw2gTLLWtKhOyO3FUH7EBsL17GOkVnEDwMmBYtVXLhMgPM+e4gbA==", + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/antd/-/antd-4.12.3.tgz", + "integrity": "sha512-opzbxm6jZB+Pc9M0Kuo6+4WmniB59NJ4i/qBr6ExyMtl9hMgsGNH8GuDXsp2xgTzfq5hyobdLci2DAuPMrf0Zg==", "requires": { - "@ant-design/colors": "^5.0.0", - "@ant-design/icons": "^4.4.0", + "@ant-design/colors": "^6.0.0", + "@ant-design/icons": "^4.5.0", "@ant-design/react-slick": "~0.28.1", "@babel/runtime": "^7.12.5", "array-tree-filter": "^2.1.0", @@ -1934,14 +1934,40 @@ "warning": "^4.0.3" }, "dependencies": { + "@ant-design/colors": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-6.0.0.tgz", + "integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==", + "requires": { + "@ctrl/tinycolor": "^3.4.0" + } + }, + "@ant-design/icons": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-4.5.0.tgz", + "integrity": "sha512-ZAKJcmr4DBV3NWr8wm2dCxNKN4eFrX+qCaPsuFejP6FRsf+m5OKxvCVi9bSp1lmKWeOI5yECAx5s0uFm4QHuPw==", + "requires": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons-svg": "^4.0.0", + "@babel/runtime": "^7.11.2", + "classnames": "^2.2.6", + "insert-css": "^2.0.0", + "rc-util": "^5.0.1" + } + }, "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } }, + "@ctrl/tinycolor": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz", + "integrity": "sha512-JZButFdZ1+/xAfpguQHoabIXkcqRRKpMrWKBkpEZZyxfY9C1DpADFB8PEqGSTeFr135SaTRfKqGKx5xSCLI7ZQ==" + }, "rc-util": { "version": "5.8.1", "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.8.1.tgz", @@ -15397,7 +15423,6 @@ "cvat-data": { "version": "file:../cvat-data", "requires": { - "async-mutex": "^0.3.0", "jszip": "3.5.0" }, "dependencies": { @@ -21332,9 +21357,9 @@ } }, "date-fns": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.17.0.tgz", - "integrity": "sha512-ZEhqxUtEZeGgg9eHNSOAJ8O9xqSgiJdrL0lzSSfMF54x6KXWJiOH/xntSJ9YomJPrYH/p08t6gWjGWq1SDJlSA==" + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.18.0.tgz", + "integrity": "sha512-NYyAg4wRmGVU4miKq5ivRACOODdZRY3q5WLmOJSq8djyzftYphU7dTHLcEtLqEvfqMKQ0jVv91P4BAwIjsXIcw==" }, "debug": { "version": "4.1.1", @@ -27898,9 +27923,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -27925,9 +27950,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -27949,9 +27974,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -27976,9 +28001,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28002,9 +28027,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28042,9 +28067,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28082,9 +28107,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28107,9 +28132,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28133,9 +28158,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28158,9 +28183,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28186,9 +28211,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28216,9 +28241,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28256,9 +28281,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28271,9 +28296,9 @@ } }, "rc-notification": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-4.5.4.tgz", - "integrity": "sha512-VsN0ouF4uglE5g3C9oDsXLNYX0Sz++ZNUFYCswkxhpImYJ9u6nJOpyA71uOYDVCu6bAF54Y5Hi/b+EcnMzkepg==", + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-4.5.5.tgz", + "integrity": "sha512-YIfhTSw+h5GsSdgMnuMx24wqiPlg3FeamuOlkh9RkyHx+SeZVAKzQ0juy2NGvPEF2hDWi5xTqxUqLdo0L2AmGg==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "2.x", @@ -28282,9 +28307,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28308,9 +28333,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28347,9 +28372,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28376,9 +28401,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28400,9 +28425,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28425,9 +28450,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28451,9 +28476,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28466,9 +28491,9 @@ } }, "rc-select": { - "version": "12.1.3", - "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-12.1.3.tgz", - "integrity": "sha512-pMJ27VQRh5QbyGLSE+by4tORYucNFbZxON+Ywj81qjXAGMjvhMcOOvlv1RZRNdnZxaMwH//3iDPOf80b0AJxZg==", + "version": "12.1.5", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-12.1.5.tgz", + "integrity": "sha512-UElTMw0+XvYJmVfsHTWvLR42RKNf5qyN3Ed/JfuZQceIPK1/3ugGRjdEOKBsPmPyNB5389NAROCV4tQd9fmqwg==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "2.x", @@ -28480,9 +28505,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28507,9 +28532,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28532,9 +28557,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28557,9 +28582,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28584,9 +28609,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28612,9 +28637,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28638,9 +28663,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28677,9 +28702,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28692,9 +28717,9 @@ } }, "rc-tree": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-4.1.1.tgz", - "integrity": "sha512-ufq7CkWfvTQa+xMPzEWYfOjTfsEALlPr0/IyujEG4+4d8NdaR3e+0dc8LkkVWoe1VCcXV2FQqAsgr2z/ThFUrQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-4.1.2.tgz", + "integrity": "sha512-9yhhDqHxG8gOZfkZeHYT6oarzarzi37lDe5c2r72tq5dflvoayGqD2bMkL2KC7GQJPLknZrtCwAbewqvD/T6NQ==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "2.x", @@ -28704,9 +28729,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28731,9 +28756,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28758,9 +28783,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -28783,9 +28808,9 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.13.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", - "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } diff --git a/cvat-ui/package.json b/cvat-ui/package.json index dff1015e2fc..ec483998db8 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -60,7 +60,7 @@ "@types/react-share": "^3.0.3", "@types/redux-logger": "^3.0.8", "@types/resize-observer-browser": "^0.1.5", - "antd": "^4.12.2", + "antd": "^4.12.3", "copy-to-clipboard": "^3.3.1", "cvat-canvas": "file:../cvat-canvas", "cvat-canvas3d": "file:../cvat-canvas3d", From 8d862b3517742250e5206cd3d9b046b133b8784d Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Thu, 4 Mar 2021 08:41:57 +0300 Subject: [PATCH 14/17] fix: upgrade @ant-design/icons from 4.4.0 to 4.5.0 (#2904) Snyk has created this PR to upgrade @ant-design/icons from 4.4.0 to 4.5.0. See this package in npm: https://www.npmjs.com/package/@ant-design/icons See this project in Snyk: https://app.snyk.io/org/cvat/project/c1f463ee-3776-44c4-b0fa-cd2254d0a094?utm_source=github&utm_medium=upgrade-pr Co-authored-by: snyk-bot --- cvat-ui/package-lock.json | 27 ++++++++++++++++++++------- cvat-ui/package.json | 2 +- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index e3be999c8a8..a9d2a5e9591 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -13,11 +13,11 @@ } }, "@ant-design/icons": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-4.4.0.tgz", - "integrity": "sha512-+X44IouK56JbP3r7zM+Zoykv5wQlXBlxY0NTaFXGpiyYSS/Bh6HIo9aTF62QkSuDTqA3UpeNVTRFioKKRmkWDQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-4.5.0.tgz", + "integrity": "sha512-ZAKJcmr4DBV3NWr8wm2dCxNKN4eFrX+qCaPsuFejP6FRsf+m5OKxvCVi9bSp1lmKWeOI5yECAx5s0uFm4QHuPw==", "requires": { - "@ant-design/colors": "^5.0.0", + "@ant-design/colors": "^6.0.0", "@ant-design/icons-svg": "^4.0.0", "@babel/runtime": "^7.11.2", "classnames": "^2.2.6", @@ -25,14 +25,27 @@ "rc-util": "^5.0.1" }, "dependencies": { + "@ant-design/colors": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-6.0.0.tgz", + "integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==", + "requires": { + "@ctrl/tinycolor": "^3.4.0" + } + }, "@babel/runtime": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.13.tgz", - "integrity": "sha512-8+3UMPBrjFa/6TtKi/7sehPKqfAm4g6K+YQjyyFOLUTxzOngcRZTlAVY8sc2CORJYqdHQY8gRPHmn+qo15rCBw==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.9.tgz", + "integrity": "sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA==", "requires": { "regenerator-runtime": "^0.13.4" } }, + "@ctrl/tinycolor": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz", + "integrity": "sha512-JZButFdZ1+/xAfpguQHoabIXkcqRRKpMrWKBkpEZZyxfY9C1DpADFB8PEqGSTeFr135SaTRfKqGKx5xSCLI7ZQ==" + }, "regenerator-runtime": { "version": "0.13.7", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", diff --git a/cvat-ui/package.json b/cvat-ui/package.json index ec483998db8..9f1c1460624 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -48,7 +48,7 @@ "worker-loader": "^2.0.0" }, "dependencies": { - "@ant-design/icons": "^4.4.0", + "@ant-design/icons": "^4.5.0", "@types/lodash": "^4.14.168", "@types/platform": "^1.3.3", "@types/react": "^16.14.3", From dcfdddfd35d1b18f12c5456b86092b405574f702 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Thu, 4 Mar 2021 08:42:24 +0300 Subject: [PATCH 15/17] fix: upgrade jszip from 3.5.0 to 3.6.0 (#2906) Snyk has created this PR to upgrade jszip from 3.5.0 to 3.6.0. See this package in npm: https://www.npmjs.com/package/jszip See this project in Snyk: https://app.snyk.io/org/cvat/project/6457ad1f-89ea-4fc9-a983-bdb963e74086?utm_source=github&utm_medium=upgrade-pr Co-authored-by: snyk-bot --- cvat-data/package-lock.json | 12 ++++++------ cvat-data/package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cvat-data/package-lock.json b/cvat-data/package-lock.json index 75279ba3c41..32dfd645e30 100644 --- a/cvat-data/package-lock.json +++ b/cvat-data/package-lock.json @@ -4709,9 +4709,9 @@ "dev": true }, "jszip": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.5.0.tgz", - "integrity": "sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.6.0.tgz", + "integrity": "sha512-jgnQoG9LKnWO3mnVNBnfhkh0QknICd1FGSrXcgrl67zioyJ4wgx25o9ZqwNtrROSflGBCGYnJfjrIyRIby1OoQ==", "requires": { "lie": "~3.3.0", "pako": "~1.0.2", @@ -5423,9 +5423,9 @@ } }, "pako": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", - "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "parent-module": { "version": "1.0.1", diff --git a/cvat-data/package.json b/cvat-data/package.json index d57e36c9986..cd792695614 100644 --- a/cvat-data/package.json +++ b/cvat-data/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "async-mutex": "^0.3.0", - "jszip": "3.5.0" + "jszip": "3.6.0" }, "scripts": { "patch": "cd src/js && patch --dry-run --forward -p0 < 3rdparty_patch.diff >> /dev/null && patch -p0 < 3rdparty_patch.diff; true", From f2f6463043ea78a4fc922842f1fccb22ee026541 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Thu, 4 Mar 2021 10:11:14 +0300 Subject: [PATCH 16/17] fix: cvat/requirements/base.txt to reduce vulnerabilities (#2907) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-PILLOW-1081494 - https://snyk.io/vuln/SNYK-PYTHON-PILLOW-1081501 - https://snyk.io/vuln/SNYK-PYTHON-PILLOW-1081502 Co-authored-by: snyk-bot --- cvat/requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/requirements/base.txt b/cvat/requirements/base.txt index 98ea74c5fec..c62d91e3ff8 100644 --- a/cvat/requirements/base.txt +++ b/cvat/requirements/base.txt @@ -6,7 +6,7 @@ django-cacheops==5.0.1 django-compressor==2.4 django-rq==2.3.2 EasyProcess==0.3 -Pillow==7.2.0 +Pillow==8.1.1 numpy==1.19.5 python-ldap==3.3.1 pytz==2020.1 From 1be3194fb3cff7925109d69a7b8c65168131db70 Mon Sep 17 00:00:00 2001 From: Andrey Zhavoronkov Date: Thu, 4 Mar 2021 12:05:56 +0300 Subject: [PATCH 17/17] fix: cvat/requirements/base.txt to reduce vulnerabilities (#2908) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-DJANGO-1076802 Co-authored-by: snyk-bot --- cvat/requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/requirements/base.txt b/cvat/requirements/base.txt index c62d91e3ff8..45cb5f16630 100644 --- a/cvat/requirements/base.txt +++ b/cvat/requirements/base.txt @@ -1,5 +1,5 @@ click==7.1.2 -Django==3.1.1 +Django==3.1.7 django-appconf==1.0.4 django-auth-ldap==2.2.0 django-cacheops==5.0.1