diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ecf6017..5cc995a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Django templates for email and user guide () -- Saving relative paths in dummy chunks instead of absolute() +- Saving relative paths in dummy chunks instead of absolute () +- Objects with a specific label cannot be displayed if at least one tag with the label exist () +- Wrong attribute can be removed in labels editor () +- UI fails with the error "Cannot read property 'label' of undefined" () - Exception: "Value must be a user instance" () ### Security diff --git a/Dockerfile.ui b/Dockerfile.ui index a12b60d8..25a2099e 100644 --- a/Dockerfile.ui +++ b/Dockerfile.ui @@ -21,8 +21,6 @@ COPY cvat-canvas/package*.json /tmp/cvat-canvas/ COPY cvat-ui/package*.json /tmp/cvat-ui/ COPY cvat-data/package*.json /tmp/cvat-data/ -RUN npm config set loglevel info - # Install cvat-data dependencies WORKDIR /tmp/cvat-data/ RUN npm ci diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 803412bb..3e71c160 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.10.1", + "version": "1.10.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1854,9 +1854,9 @@ } }, "antd": { - "version": "3.26.18", - "resolved": "https://registry.npmjs.org/antd/-/antd-3.26.18.tgz", - "integrity": "sha512-TPuacNJJNPji+LnapU46uWGqi+6JlyH75paMNs95IH0F7gGYtp4oSkua88gGsoAaUbDxTIF+cWI9mdIsr7ywlw==", + "version": "3.26.19", + "resolved": "https://registry.npmjs.org/antd/-/antd-3.26.19.tgz", + "integrity": "sha512-NcSaI0jMLhdPBoTC7p9qqe8aF9Y+YHWNPNpORY98qYADvO2aXHwyRi0YUAZLauDCvDWNTfeiACBeQaFvUhXApQ==", "requires": { "@ant-design/create-react-context": "^0.2.4", "@ant-design/icons": "~2.1.1", @@ -3779,11 +3779,10 @@ } }, "create-react-class": { - "version": "15.6.3", - "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz", - "integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==", + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.7.0.tgz", + "integrity": "sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==", "requires": { - "fbjs": "^0.8.9", "loose-envify": "^1.3.1", "object-assign": "^4.1.1" } @@ -17052,7 +17051,7 @@ }, "fs-minipass": { "version": "1.2.7", - "resolved": "", + "resolved": false, "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "optional": true, "requires": { @@ -17067,7 +17066,7 @@ }, "gauge": { "version": "2.7.4", - "resolved": "", + "resolved": false, "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "optional": true, "requires": { @@ -17083,7 +17082,7 @@ }, "glob": { "version": "7.1.6", - "resolved": "", + "resolved": false, "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "optional": true, "requires": { @@ -17121,7 +17120,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "", + "resolved": false, "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "optional": true, "requires": { @@ -17173,7 +17172,7 @@ }, "minipass": { "version": "2.9.0", - "resolved": "", + "resolved": false, "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "optional": true, "requires": { @@ -17183,7 +17182,7 @@ }, "minizlib": { "version": "1.3.3", - "resolved": "", + "resolved": false, "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "optional": true, "requires": { @@ -17218,7 +17217,7 @@ }, "node-pre-gyp": { "version": "0.14.0", - "resolved": "", + "resolved": false, "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", "optional": true, "requires": { @@ -17272,7 +17271,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "", + "resolved": false, "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "optional": true, "requires": { @@ -17296,7 +17295,7 @@ }, "once": { "version": "1.4.0", - "resolved": "", + "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "optional": true, "requires": { @@ -17366,7 +17365,7 @@ }, "rimraf": { "version": "2.7.1", - "resolved": "", + "resolved": false, "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "optional": true, "requires": { @@ -17446,7 +17445,7 @@ }, "tar": { "version": "4.4.13", - "resolved": "", + "resolved": false, "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", "optional": true, "requires": { @@ -17476,13 +17475,13 @@ }, "wrappy": { "version": "1.0.2", - "resolved": "", + "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "optional": true }, "yallist": { "version": "3.1.1", - "resolved": "", + "resolved": false, "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "optional": true } @@ -28684,9 +28683,9 @@ } }, "rc-switch": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-1.9.0.tgz", - "integrity": "sha512-Isas+egaK6qSk64jaEw4GgPStY4umYDbT7ZY93bZF1Af+b/JEsKsJdNOU2qG3WI0Z6tXo2DDq0kJCv8Yhu0zww==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-1.9.2.tgz", + "integrity": "sha512-qaK7mY4FLDKy99Hq3A1tf8CcqfzKtHp9LPX8WTnZ0MzdHCTneSARb1XD7Eqeu8BactasYGsi2bF9p18Q+/5JEw==", "requires": { "classnames": "^2.2.1", "prop-types": "^15.5.6", @@ -32254,9 +32253,9 @@ "dev": true }, "whatwg-fetch": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.4.1.tgz", - "integrity": "sha512-sofZVzE1wKwO+EYPbWfiwzaKovWiZXf4coEzjGP9b2GBVgQRLQUZ2QcuPpQExGDAW5GItpEm6Tl4OU5mywnAoQ==" + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz", + "integrity": "sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A==" }, "which": { "version": "1.3.1", diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 05039ea4..3fa2ebb6 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.10.1", + "version": "1.10.4", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { @@ -57,7 +57,7 @@ "@types/react-router-dom": "^5.1.6", "@types/react-share": "^3.0.3", "@types/redux-logger": "^3.0.8", - "antd": "^3.26.18", + "antd": "^3.26.19", "copy-to-clipboard": "^3.3.1", "cvat-canvas": "file:../cvat-canvas", "cvat-core": "file:../cvat-core", diff --git a/cvat-ui/src/components/labels-editor/label-form.tsx b/cvat-ui/src/components/labels-editor/label-form.tsx index b292f41f..3e1a4f58 100644 --- a/cvat-ui/src/components/labels-editor/label-form.tsx +++ b/cvat-ui/src/components/labels-editor/label-form.tsx @@ -18,7 +18,9 @@ import ColorPicker from 'components/annotation-page/standard-workspace/objects-s import { ColorizeIcon } from 'icons'; import patterns from 'utils/validation-patterns'; import consts from 'consts'; -import { equalArrayHead, idGenerator, Label, Attribute } from './common'; +import { + equalArrayHead, idGenerator, Label, Attribute, +} from './common'; export enum AttributeType { SELECT = 'SELECT', @@ -318,9 +320,9 @@ class LabelForm extends React.PureComponent { ); } - private renderAttribute = (key: number, index: number): JSX.Element => { + private renderAttribute = (key: number): JSX.Element => { const { label, form } = this.props; - const attr = label && index < label.attributes.length ? label.attributes[index] : null; + const attr = label ? label.attributes.filter((_attr: any): boolean => _attr.id === key)[0] : null; return ( diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/canvas-context-menu.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/canvas-context-menu.tsx index 43b2ad4a..c172abb5 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/canvas-context-menu.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/canvas-context-menu.tsx @@ -24,7 +24,10 @@ function mapStateToProps(state: CombinedState): StateToProps { annotation: { annotations: { activatedStateID, collapsed, states: objectStates }, canvas: { - contextMenu: { visible, top, left, type }, + contextMenu: { + visible, top, left, type, + }, + ready, }, }, } = state; @@ -33,7 +36,11 @@ function mapStateToProps(state: CombinedState): StateToProps { activatedStateID, collapsed: activatedStateID !== null ? collapsed[activatedStateID] : undefined, objectStates, - visible, + visible: + activatedStateID !== null && + visible && + ready && + objectStates.map((_state: any): number => _state.clientID).includes(activatedStateID), left, top, type, @@ -166,7 +173,9 @@ class CanvasContextMenuContainer extends React.PureComponent { public render(): JSX.Element { const { left, top } = this.state; - const { visible, activatedStateID, objectStates, type } = this.props; + const { + visible, activatedStateID, objectStates, type, + } = this.props; return ( <> diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/label-item.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/label-item.tsx index 8c74f714..8e89e244 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/label-item.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/label-item.tsx @@ -8,7 +8,7 @@ import { connect } from 'react-redux'; import { updateAnnotationsAsync } from 'actions/annotation-actions'; import LabelItemComponent from 'components/annotation-page/standard-workspace/objects-side-bar/label-item'; -import { CombinedState } from 'reducers/interfaces'; +import { CombinedState, ObjectType } from 'reducers/interfaces'; interface OwnProps { labelID: number; @@ -92,8 +92,8 @@ class LabelItemContainer extends React.PureComponent { let statesLocked = true; ownObjectStates.forEach((objectState: any) => { - const { lock } = objectState; - if (!lock) { + const { lock, objectType } = objectState; + if (!lock && objectType !== ObjectType.TAG) { statesHidden = statesHidden && objectState.hidden; statesLocked = statesLocked && objectState.lock; } diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/object-item.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/object-item.tsx index 2d2e6f51..987598f7 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/object-item.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/object-item.tsx @@ -7,7 +7,9 @@ import copy from 'copy-to-clipboard'; import { connect } from 'react-redux'; import { LogType } from 'cvat-logger'; -import { ActiveControl, CombinedState, ColorBy, ShapeType } from 'reducers/interfaces'; +import { + ActiveControl, CombinedState, ColorBy, ShapeType, +} from 'reducers/interfaces'; import { collapseObjectItems, updateAnnotationsAsync, @@ -83,40 +85,25 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps { const stateIDs = states.map((_state: any): number => _state.clientID); const index = stateIDs.indexOf(clientID); - try { - const collapsedState = - typeof statesCollapsed[clientID] === 'undefined' ? initialCollapsed : statesCollapsed[clientID]; - - return { - objectState: states[index], - collapsed: collapsedState, - attributes: jobAttributes[states[index].label.id], - labels, - ready, - activeControl, - colorBy, - jobInstance, - frameNumber, - activated: activatedStateID === clientID, - minZLayer, - maxZLayer, - normalizedKeyMap, - aiToolsRef, - }; - } catch (exception) { - // we have an exception here sometimes - // but I cannot understand when it happens and what is the root reason - // maybe this temporary hack helps us - const dataObject = { - index, - frameNumber, - clientID: own.clientID, - stateIDs, - }; - throw new Error( - `${exception.toString()} in mapStateToProps of ObjectItemContainer. Data are ${JSON.stringify(dataObject)}`, - ); - } + const collapsedState = + typeof statesCollapsed[clientID] === 'undefined' ? initialCollapsed : statesCollapsed[clientID]; + + return { + objectState: states[index], + collapsed: collapsedState, + attributes: jobAttributes[states[index].label.id], + labels, + ready, + activeControl, + colorBy, + jobInstance, + frameNumber, + activated: activatedStateID === clientID, + minZLayer, + maxZLayer, + normalizedKeyMap, + aiToolsRef, + }; } function mapDispatchToProps(dispatch: any): DispatchToProps { @@ -219,7 +206,9 @@ class ObjectItemContainer extends React.PureComponent { }; private activate = (): void => { - const { activateObject, objectState, ready, activeControl } = this.props; + const { + activateObject, objectState, ready, activeControl, + } = this.props; if (ready && activeControl === ActiveControl.CURSOR) { activateObject(objectState.clientID); @@ -324,7 +313,9 @@ class ObjectItemContainer extends React.PureComponent { } public render(): JSX.Element { - const { objectState, collapsed, labels, attributes, activated, colorBy, normalizedKeyMap } = this.props; + const { + objectState, collapsed, labels, attributes, activated, colorBy, normalizedKeyMap, + } = this.props; let stateColor = ''; if (colorBy === ColorBy.INSTANCE) {