@@ -268,7 +262,6 @@ function AttributeEditor(props: Props): JSX.Element {
{renderInputElement({
attrID,
- ref,
inputType,
currentValue,
values,
diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx
index 9ee0f8a9..73786bc3 100644
--- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx
+++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx
@@ -4,20 +4,16 @@
import React from 'react';
-import {
- Row,
- Col,
- Select,
- Button,
- InputNumber,
- Radio,
-} from 'antd';
-
-import { RadioChangeEvent } from 'antd/lib/radio';
+import { Row, Col } from 'antd/lib/grid';
+import Select from 'antd/lib/select';
+import Button from 'antd/lib/button';
+import InputNumber from 'antd/lib/input-number';
+import Radio, { RadioChangeEvent } from 'antd/lib/radio';
import Text from 'antd/lib/typography/Text';
import { RectDrawingMethod } from 'cvat-canvas';
import { ShapeType } from 'reducers/interfaces';
+import { clamp } from 'utils/math';
interface Props {
shapeType: ShapeType;
@@ -117,7 +113,15 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
{
+ if (typeof (value) === 'number') {
+ onChangePoints(Math.floor(
+ clamp(value, minimumPoints, Number.MAX_SAFE_INTEGER),
+ ));
+ } else if (!value) {
+ onChangePoints(undefined);
+ }
+ }}
className='cvat-draw-shape-popover-points-selector'
min={minimumPoints}
value={numberOfPoints}
diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx
index dc7952cf..12ccd044 100644
--- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx
+++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx
@@ -4,26 +4,21 @@
import React from 'react';
-import {
- Row,
- Col,
- Icon,
- Select,
- Radio,
- Input,
- Collapse,
- Checkbox,
- InputNumber,
- Dropdown,
- Menu,
- Button,
- Modal,
- Popover,
-} from 'antd';
-
+import { Row, Col } from 'antd/lib/grid';
+import Icon from 'antd/lib/icon';
+import Select from 'antd/lib/select';
+import Radio, { RadioChangeEvent } from 'antd/lib/radio';
+import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox';
+import Input from 'antd/lib/input';
+import InputNumber from 'antd/lib/input-number';
+import Collapse from 'antd/lib/collapse';
+import Dropdown from 'antd/lib/dropdown';
+import Menu from 'antd/lib/menu';
+import Button from 'antd/lib/button';
+import Modal from 'antd/lib/modal';
+import Popover from 'antd/lib/popover';
import Text from 'antd/lib/typography/Text';
-import { RadioChangeEvent } from 'antd/lib/radio';
-import { CheckboxChangeEvent } from 'antd/lib/checkbox';
+
import ColorChanger from 'components/annotation-page/standard-workspace/objects-side-bar/color-changer';
import {
@@ -36,9 +31,8 @@ import {
ForegroundIcon,
} from 'icons';
-import {
- ObjectType, ShapeType,
-} from 'reducers/interfaces';
+import { ObjectType, ShapeType } from 'reducers/interfaces';
+import { clamp } from 'utils/math';
function ItemMenu(
serverID: number | undefined,
@@ -463,7 +457,7 @@ function ItemAttributeComponent(props: ItemAttributeComponentProps): JSX.Element
}
if (attrInputType === 'number') {
- const [min, max, step] = attrValues;
+ const [min, max, step] = attrValues.map((value: string): number => +value);
return (
<>
@@ -476,15 +470,17 @@ function ItemAttributeComponent(props: ItemAttributeComponentProps): JSX.Element
{
- if (typeof (value) !== 'undefined') {
- changeAttribute(attrID, `${value}`);
+ if (typeof (value) === 'number') {
+ changeAttribute(
+ attrID, `${clamp(value, min, max)}`,
+ );
}
}}
value={+attrValue}
className='cvat-object-item-number-attribute'
- min={+min}
- max={+max}
- step={+step}
+ min={min}
+ max={max}
+ step={step}
/>
>
diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/propagate-confirm.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/propagate-confirm.tsx
index f47d5b12..66bebffa 100644
--- a/cvat-ui/src/components/annotation-page/standard-workspace/propagate-confirm.tsx
+++ b/cvat-ui/src/components/annotation-page/standard-workspace/propagate-confirm.tsx
@@ -4,21 +4,21 @@
import React from 'react';
-import {
- Modal,
- InputNumber,
-} from 'antd';
-
+import Modal from 'antd/lib/modal';
+import InputNumber from 'antd/lib/input-number';
import Text from 'antd/lib/typography/Text';
+import { clamp } from 'utils/math';
interface Props {
visible: boolean;
propagateFrames: number;
propagateUpToFrame: number;
+ stopFrame: number;
+ frameNumber: number;
propagateObject(): void;
cancel(): void;
- changePropagateFrames(value: number | undefined): void;
- changeUpToFrame(value: number | undefined): void;
+ changePropagateFrames(value: number): void;
+ changeUpToFrame(value: number): void;
}
export default function PropagateConfirmComponent(props: Props): JSX.Element {
@@ -26,12 +26,16 @@ export default function PropagateConfirmComponent(props: Props): JSX.Element {
visible,
propagateFrames,
propagateUpToFrame,
+ stopFrame,
+ frameNumber,
propagateObject,
changePropagateFrames,
changeUpToFrame,
cancel,
} = props;
+ const minPropagateFrames = 1;
+
return (
Do you want to make a copy of the object on
-
+ {
+ if (typeof (value) === 'number') {
+ changePropagateFrames(Math.floor(
+ clamp(value, minPropagateFrames, Number.MAX_SAFE_INTEGER),
+ ));
+ }
+ }}
+ />
{
propagateFrames > 1
? frames
: frame
}
up to the
-
+ {
+ if (typeof (value) === 'number') {
+ changeUpToFrame(Math.floor(
+ clamp(value, frameNumber + 1, stopFrame),
+ ));
+ }
+ }}
+ />
frame
diff --git a/cvat-ui/src/components/annotation-page/top-bar/player-navigation.tsx b/cvat-ui/src/components/annotation-page/top-bar/player-navigation.tsx
index 397bf8d6..b5c846d0 100644
--- a/cvat-ui/src/components/annotation-page/top-bar/player-navigation.tsx
+++ b/cvat-ui/src/components/annotation-page/top-bar/player-navigation.tsx
@@ -2,27 +2,24 @@
//
// SPDX-License-Identifier: MIT
-import React from 'react';
+import React, { useState, useEffect } from 'react';
-import {
- Row,
- Col,
- Icon,
- Slider,
- Tooltip,
- InputNumber,
-} from 'antd';
-
-import { SliderValue } from 'antd/lib/slider';
+import { Row, Col } from 'antd/lib/grid';
+import Icon from 'antd/lib/icon';
+import Slider, { SliderValue } from 'antd/lib/slider';
+import Tooltip from 'antd/lib/tooltip';
+import InputNumber from 'antd/lib/input-number';
import Text from 'antd/lib/typography/Text';
+import { clamp } from 'utils/math';
+
interface Props {
startFrame: number;
stopFrame: number;
frameNumber: number;
inputFrameRef: React.RefObject;
onSliderChange(value: SliderValue): void;
- onInputChange(value: number | undefined): void;
+ onInputChange(value: number): void;
onURLIconClick(): void;
}
@@ -37,6 +34,14 @@ function PlayerNavigation(props: Props): JSX.Element {
onURLIconClick,
} = props;
+ const [frameInputValue, setFrameInputValue] = useState(frameNumber);
+
+ useEffect(() => {
+ if (frameNumber !== frameInputValue) {
+ setFrameInputValue(frameNumber);
+ }
+ }, [frameNumber]);
+
return (
<>
@@ -68,9 +73,21 @@ function PlayerNavigation(props: Props): JSX.Element {
{
+ if (typeof (value) === 'number') {
+ setFrameInputValue(Math.floor(
+ clamp(value, startFrame, stopFrame),
+ ));
+ }
+ }}
+ onBlur={() => {
+ onInputChange(frameInputValue);
+ }}
+ onPressEnter={() => {
+ onInputChange(frameInputValue);
+ }}
ref={inputFrameRef}
/>
diff --git a/cvat-ui/src/components/annotation-page/top-bar/top-bar.tsx b/cvat-ui/src/components/annotation-page/top-bar/top-bar.tsx
index 370702fe..53648454 100644
--- a/cvat-ui/src/components/annotation-page/top-bar/top-bar.tsx
+++ b/cvat-ui/src/components/annotation-page/top-bar/top-bar.tsx
@@ -4,12 +4,8 @@
import React from 'react';
-import {
- Row,
- Col,
- InputNumber,
-} from 'antd';
-
+import { Row, Col } from 'antd/lib/grid';
+import InputNumber from 'antd/lib/input-number';
import { SliderValue } from 'antd/lib/slider';
import { Workspace } from 'reducers/interfaces';
@@ -40,7 +36,7 @@ interface Props {
onFirstFrame(): void;
onLastFrame(): void;
onSliderChange(value: SliderValue): void;
- onInputChange(value: number | undefined): void;
+ onInputChange(value: number): void;
onURLIconClick(): void;
onUndoClick(): void;
onRedoClick(): void;
diff --git a/cvat-ui/src/components/settings-page/player-settings.tsx b/cvat-ui/src/components/settings-page/player-settings.tsx
index 73f2a00a..779a03b0 100644
--- a/cvat-ui/src/components/settings-page/player-settings.tsx
+++ b/cvat-ui/src/components/settings-page/player-settings.tsx
@@ -4,28 +4,17 @@
import React from 'react';
-import {
- Row,
- Col,
- Checkbox,
- Slider,
- Select,
- InputNumber,
- Icon,
-} from 'antd';
-
+import { Row, Col } from 'antd/lib/grid';
+import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox';
+import Slider from 'antd/lib/slider';
+import Select from 'antd/lib/select';
+import InputNumber from 'antd/lib/input-number';
+import Icon from 'antd/lib/icon';
import Text from 'antd/lib/typography/Text';
-import { CheckboxChangeEvent } from 'antd/lib/checkbox';
-
-import {
- BackJumpIcon,
- ForwardJumpIcon,
-} from 'icons';
-import {
- FrameSpeed,
- GridColor,
-} from 'reducers/interfaces';
+import { clamp } from 'utils/math';
+import { BackJumpIcon, ForwardJumpIcon } from 'icons';
+import { FrameSpeed, GridColor } from 'reducers/interfaces';
interface Props {
frameStep: number;
@@ -78,18 +67,28 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
onChangeSaturationLevel,
} = props;
+ const minFrameStep = 2;
+ const maxFrameStep = 1000;
+ const minGridSize = 5;
+ const maxGridSize = 1000;
+
+
return (
Player step
{
- if (value) {
- onChangeFrameStep(value);
+ if (typeof (value) === 'number') {
+ onChangeFrameStep(
+ Math.floor(
+ clamp(value, minFrameStep, maxFrameStep),
+ ),
+ );
}
}}
/>
@@ -138,14 +137,15 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
Grid size
{
- if (value) {
- onChangeGridSize(value);
+ if (typeof (value) === 'number') {
+ onChangeGridSize(Math.floor(
+ clamp(value, minGridSize, maxGridSize),
+ ));
}
}}
/>
diff --git a/cvat-ui/src/components/settings-page/workspace-settings.tsx b/cvat-ui/src/components/settings-page/workspace-settings.tsx
index a7a5fd2c..52ba4a50 100644
--- a/cvat-ui/src/components/settings-page/workspace-settings.tsx
+++ b/cvat-ui/src/components/settings-page/workspace-settings.tsx
@@ -4,15 +4,12 @@
import React from 'react';
-import {
- Row,
- Col,
- Checkbox,
- InputNumber,
-} from 'antd';
-
+import { Row, Col } from 'antd/lib/grid';
+import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox';
+import InputNumber from 'antd/lib/input-number';
import Text from 'antd/lib/typography/Text';
-import { CheckboxChangeEvent } from 'antd/lib/checkbox';
+
+import { clamp } from 'utils/math';
interface Props {
autoSave: boolean;
@@ -37,6 +34,11 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element {
onSwitchShowingInterpolatedTracks,
} = props;
+ const minAutoSaveInterval = 5;
+ const maxAutoSaveInterval = 60;
+ const minAAMMargin = 0;
+ const maxAAMMargin = 1000;
+
return (
@@ -56,13 +58,19 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element {
Auto save every
{
- if (value) {
- onChangeAutoSaveInterval(value * 60 * 1000);
+ if (typeof (value) === 'number') {
+ onChangeAutoSaveInterval(Math.floor(
+ clamp(
+ value,
+ minAutoSaveInterval,
+ maxAutoSaveInterval,
+ ),
+ ) * 60 * 1000);
}
}}
/>
@@ -89,12 +97,14 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element {
Attribute annotation mode (AAM) zoom margin
{
if (typeof (value) === 'number') {
- onChangeAAMZoomMargin(value);
+ onChangeAAMZoomMargin(Math.floor(
+ clamp(value, minAAMMargin, maxAAMMargin),
+ ));
}
}}
/>
diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx
index 868b1ddb..e92c0f26 100644
--- a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx
+++ b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx
@@ -145,15 +145,9 @@ class DrawShapePopoverContainer extends React.PureComponent {
};
private onChangePoints = (value: number | undefined): void => {
- if (typeof (value) === 'undefined') {
- this.setState({
- numberOfPoints: value,
- });
- } else if (typeof (value) === 'number') {
- this.setState({
- numberOfPoints: Math.max(value, this.minimumPoints),
- });
- }
+ this.setState({
+ numberOfPoints: value,
+ });
};
private onChangeLabel = (value: string): void => {
diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/propagate-confirm.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/propagate-confirm.tsx
index e7c4d706..f0de8809 100644
--- a/cvat-ui/src/containers/annotation-page/standard-workspace/propagate-confirm.tsx
+++ b/cvat-ui/src/containers/annotation-page/standard-workspace/propagate-confirm.tsx
@@ -88,23 +88,20 @@ class PropagateConfirmContainer extends React.PureComponent {
propagateObject(jobInstance, objectState, frameNumber + 1, propagateUpToFrame);
};
- private changePropagateFrames = (value: number | undefined): void => {
+ private changePropagateFrames = (value: number): void => {
const { changePropagateFrames } = this.props;
- if (typeof (value) !== 'undefined') {
- changePropagateFrames(value);
- }
+ changePropagateFrames(value);
};
- private changeUpToFrame = (value: number | undefined): void => {
+ private changeUpToFrame = (value: number): void => {
const {
stopFrame,
frameNumber,
changePropagateFrames,
} = this.props;
- if (typeof (value) !== 'undefined') {
- const propagateFrames = Math.max(0, Math.min(stopFrame, value)) - frameNumber;
- changePropagateFrames(propagateFrames);
- }
+
+ const propagateFrames = Math.max(0, Math.min(stopFrame, value)) - frameNumber;
+ changePropagateFrames(propagateFrames);
};
public render(): JSX.Element {
@@ -122,6 +119,8 @@ class PropagateConfirmContainer extends React.PureComponent {
{
onChangeFrame(value as number);
};
- private onChangePlayerInputValue = (value: number | undefined): void => {
+ private onChangePlayerInputValue = (value: number): void => {
const {
onSwitchPlay,
onChangeFrame,
playing,
+ frameNumber,
} = this.props;
- if (typeof (value) !== 'undefined') {
+ if (value !== frameNumber) {
if (playing) {
onSwitchPlay(false);
}
diff --git a/cvat-ui/src/utils/math.ts b/cvat-ui/src/utils/math.ts
new file mode 100644
index 00000000..960bd4d1
--- /dev/null
+++ b/cvat-ui/src/utils/math.ts
@@ -0,0 +1,4 @@
+/* eslint-disable-next-line import/prefer-default-export */
+export function clamp(value: number, min: number, max: number): number {
+ return Math.max(Math.min(value, max), min);
+}