diff --git a/CHANGELOG.md b/CHANGELOG.md index 93db8bb5f69..9282020880b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Built-in search for labels when create an object or change a label () - Better validation of labels and attributes in raw viewer () - ClamAV antivirus integration () +- Added canvas background color selector () - SCSS files linting with Stylelint tool () - Supported import and export or single boxes in MOT format (https://github.com/opencv/cvat/pull/1764) - [Datumaro] Added `stats` command, which shows some dataset statistics like image mean and std (https://github.com/opencv/cvat/pull/1734) @@ -28,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Removed information about e-mail from the basic user information () - Update https install manual. Makes it easier and more robust. Includes automatic renewing of lets encrypt certificates. +- Settings page move to the modal. () - Implemented import and export of annotations with relative image paths () - Using only single click to start editing or remove a point () @@ -46,6 +48,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Wrong description on register view for the username field () - Wrong resolution for resizing a shape () - React warning because of not unique keys in labels viewer () +- Fixed issue tracker () +- Fixed canvas fit after sidebar open/close event () - A couple of exceptions in AAM related with early object activation () diff --git a/cvat-canvas/package-lock.json b/cvat-canvas/package-lock.json index 0805ead9b1a..65559bdb828 100644 --- a/cvat-canvas/package-lock.json +++ b/cvat-canvas/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-canvas", - "version": "1.2.0", + "version": "1.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-canvas/package.json b/cvat-canvas/package.json index 38a0c145eb7..a27a4c575cb 100644 --- a/cvat-canvas/package.json +++ b/cvat-canvas/package.json @@ -1,6 +1,6 @@ { "name": "cvat-canvas", - "version": "1.2.0", + "version": "1.2.1", "description": "Part of Computer Vision Annotation Tool which presents its canvas library", "main": "src/canvas.ts", "scripts": { diff --git a/cvat-canvas/src/scss/canvas.scss b/cvat-canvas/src/scss/canvas.scss index 1cb62af2c4f..090ec163f8d 100644 --- a/cvat-canvas/src/scss/canvas.scss +++ b/cvat-canvas/src/scss/canvas.scss @@ -188,7 +188,7 @@ polyline.cvat_canvas_shape_splitting { height: calc(100% - 10px); margin: 5px; border-radius: 5px; - background-color: white; + background-color: inherit; overflow: hidden; position: relative; } diff --git a/cvat-canvas/src/typescript/canvasView.ts b/cvat-canvas/src/typescript/canvasView.ts index 8c2fe940c7f..8c3d27fc788 100644 --- a/cvat-canvas/src/typescript/canvasView.ts +++ b/cvat-canvas/src/typescript/canvasView.ts @@ -911,12 +911,32 @@ export class CanvasViewImpl implements CanvasView, Listener { if (reason === UpdateReasons.CONFIG_UPDATED) { const { activeElement } = this; this.deactivate(); + + if (model.configuration.displayAllText && !this.configuration.displayAllText) { + for (const i in this.drawnStates) { + if (!(i in this.svgTexts)) { + this.svgTexts[i] = this.addText(this.drawnStates[i]); + this.updateTextPosition( + this.svgTexts[i], + this.svgShapes[i], + ); + } + } + } else if (model.configuration.displayAllText === false + && this.configuration.displayAllText) { + for (const i in this.drawnStates) { + if (i in this.svgTexts && Number.parseInt(i, 10) !== activeElement.clientID) { + this.svgTexts[i].remove(); + delete this.svgTexts[i]; + } + } + } + this.configuration = model.configuration; this.activate(activeElement); this.editHandler.configurate(this.configuration); this.drawHandler.configurate(this.configuration); - // todo: setup text, add if doesn't exist and enabled // remove if exist and not enabled // this.setupObjects([]); // this.setupObjects(model.objects); @@ -1208,6 +1228,7 @@ export class CanvasViewImpl implements CanvasView, Listener { pinned: state.pinned, updated: state.updated, frame: state.frame, + label: state.label, }; } diff --git a/cvat-canvas/src/typescript/shared.ts b/cvat-canvas/src/typescript/shared.ts index 2d985e63977..d1f9cb8cce1 100644 --- a/cvat-canvas/src/typescript/shared.ts +++ b/cvat-canvas/src/typescript/shared.ts @@ -48,6 +48,7 @@ export interface DrawnState { pinned?: boolean; updated: number; frame: number; + label: any; } // Translate point array from the canvas coordinate system diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index f521fbcedc4..77ecf0a3bd5 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -13,14 +13,19 @@ } }, "@ant-design/create-react-context": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@ant-design/create-react-context/-/create-react-context-0.2.4.tgz", - "integrity": "sha512-8sw+/w6r+aEbd+OJ62ojoSE4zDt/3yfQydmbWFznoftjr8v/opOswGjM+/MU0rSaREbluqzOmZ6xdecHpSaS2w==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@ant-design/create-react-context/-/create-react-context-0.2.5.tgz", + "integrity": "sha512-1rMAa4qgP2lfl/QBH9i78+Gjxtj9FTMpMyDGZsEBW5Kih72EuUo9958mV8PgpRkh4uwPSQ7vVZWXeyNZXVAFDg==", "requires": { "gud": "^1.0.0", "warning": "^4.0.3" } }, + "@ant-design/css-animation": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@ant-design/css-animation/-/css-animation-1.7.2.tgz", + "integrity": "sha512-bvVOe7A+r7lws58B7r+fgnQDK90cV45AXuvGx6i5CCSX1W/M3AJnHsNggDANBxEtWdNdFWcDd5LorB+RdSIlBw==" + }, "@ant-design/icons": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz", @@ -975,6 +980,11 @@ "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==", "dev": true }, + "@icons/material": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==" + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -1056,6 +1066,14 @@ "csstype": "^2.2.0" } }, + "@types/react-color": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-3.0.2.tgz", + "integrity": "sha512-FhrRy0xEYEpysl1iKL11ynJc79H6ztyYc4xD1pliZyygEChleTlHGohb/bClTYPN8XeSw6yaz45l3YW5SGYftQ==", + "requires": { + "@types/react": "*" + } + }, "@types/react-dom": { "version": "16.9.3", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.3.tgz", @@ -1506,9 +1524,9 @@ } }, "antd": { - "version": "3.25.2", - "resolved": "https://registry.npmjs.org/antd/-/antd-3.25.2.tgz", - "integrity": "sha512-+qF1bgU7rUkPIkggIIV0fmm+9pPacl50BBd6NNUR2+kKJOFYjwrnP39ZqJRsYNy5bX9VgR454fz9KEuW7HPjog==", + "version": "3.26.17", + "resolved": "https://registry.npmjs.org/antd/-/antd-3.26.17.tgz", + "integrity": "sha512-P9uSK8SZ/1AvhQCC6aaLEkVrQhjbfZyUnqNV+lDnPqtudnZD2Ycy7Og+/EhuOBsQpYQvVT2aPLMgQWFv8tdJkA==", "requires": { "@ant-design/create-react-context": "^0.2.4", "@ant-design/icons": "~2.1.1", @@ -1521,18 +1539,19 @@ "css-animation": "^1.5.0", "dom-closest": "^0.2.0", "enquire.js": "^2.1.6", + "is-mobile": "^2.1.0", "lodash": "^4.17.13", "moment": "^2.24.0", "omit.js": "^1.0.2", "prop-types": "^15.7.2", "raf": "^3.4.1", "rc-animate": "^2.10.2", - "rc-calendar": "~9.15.5", + "rc-calendar": "~9.15.7", "rc-cascader": "~0.17.4", "rc-checkbox": "~2.1.6", "rc-collapse": "~1.11.3", - "rc-dialog": "~7.5.2", - "rc-drawer": "~3.0.0", + "rc-dialog": "~7.6.0", + "rc-drawer": "~3.1.1", "rc-dropdown": "~2.4.1", "rc-editor-mention": "^1.1.13", "rc-form": "^2.4.10", @@ -1540,7 +1559,7 @@ "rc-mentions": "~0.4.0", "rc-menu": "~7.5.1", "rc-notification": "~3.3.1", - "rc-pagination": "~1.20.5", + "rc-pagination": "~1.20.11", "rc-progress": "~2.5.0", "rc-rate": "~2.5.0", "rc-resize-observer": "^0.1.0", @@ -1548,15 +1567,15 @@ "rc-slider": "~8.7.1", "rc-steps": "~3.5.0", "rc-switch": "~1.9.0", - "rc-table": "~6.9.4", - "rc-tabs": "~9.6.4", + "rc-table": "~6.10.5", + "rc-tabs": "~9.7.0", "rc-time-picker": "~3.7.1", "rc-tooltip": "~3.7.3", "rc-tree": "~2.1.0", "rc-tree-select": "~2.9.1", "rc-trigger": "^2.6.2", "rc-upload": "~2.9.1", - "rc-util": "^4.10.0", + "rc-util": "^4.16.1", "react-lazy-load": "^3.0.13", "react-lifecycles-compat": "^3.0.4", "react-slick": "~0.25.2", @@ -21342,9 +21361,9 @@ } }, "dom-align": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.10.2.tgz", - "integrity": "sha512-AYZUzLepy05E9bCY4ExoqHrrIlM49PEak9oF93JEFoibqKL0F7w5DLM70/rosLOawerWZ3MlepQcl+EmHskOyw==" + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.0.tgz", + "integrity": "sha512-YkoezQuhp3SLFGdOlr5xkqZ640iXrnHAwVYcDg8ZKRUtO7mSzSC2BA5V0VuyAwPSJA4CLIc6EDDJh4bEsD2+zA==" }, "dom-closest": { "version": "0.2.0", @@ -24411,6 +24430,11 @@ "is-extglob": "^2.1.1" } }, + "is-mobile": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-2.2.1.tgz", + "integrity": "sha512-6zELsfVFr326eq2CI53yvqq6YBanOxKBybwDT+MbMS2laBnK6Ez8m5XHSuTQQbnKRfpDzCod1CMWW5q3wZYMvA==" + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -24914,6 +24938,11 @@ "object-visit": "^1.0.0" } }, + "material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -25312,9 +25341,9 @@ "dev": true }, "mutationobserver-shim": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz", - "integrity": "sha512-gciOLNN8Vsf7YzcqRjKzlAJ6y7e+B86u7i3KXes0xfxx/nfLmozlW1Vn+Sc9x3tPIePFgc1AeIFhtRgkqTjzDQ==" + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/mutationobserver-shim/-/mutationobserver-shim-0.3.7.tgz", + "integrity": "sha512-oRIDTyZQU96nAiz2AQyngwx1e89iApl2hN5AOYwyxLUB47UYsU3Wv9lJWqH5y/QdiYkc5HQLi23ZNB3fELdHcQ==" }, "mute-stream": { "version": "0.0.8", @@ -27022,9 +27051,9 @@ } }, "rc-animate": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-2.10.2.tgz", - "integrity": "sha512-cE/A7piAzoWFSgUD69NmmMraqCeqVBa51UErod8NS3LUEqWfppSVagHfa0qHAlwPVPiIBg3emRONyny3eiH0Dg==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-2.11.1.tgz", + "integrity": "sha512-1NyuCGFJG/0Y+9RKh5y/i/AalUCA51opyyS/jO2seELpgymZm2u9QV3xwODwEuzkmeQ1BDPxMLmYLcTJedPlkQ==", "requires": { "babel-runtime": "6.x", "classnames": "^2.2.6", @@ -27036,9 +27065,9 @@ } }, "rc-calendar": { - "version": "9.15.8", - "resolved": "https://registry.npmjs.org/rc-calendar/-/rc-calendar-9.15.8.tgz", - "integrity": "sha512-x3zVaZSRX7FkRNKw7nz3tutwrlIrU1aqMn5GtRUmlf84GnXLtd9fuuydxeNkFWfcHry3BPSto7+r9TK2al0h+g==", + "version": "9.15.11", + "resolved": "https://registry.npmjs.org/rc-calendar/-/rc-calendar-9.15.11.tgz", + "integrity": "sha512-qv0VXfAAnysMWJigxaP6se4bJHvr17D9qsLbi8BOpdgEocsS0RkgY1IUiFaOVYKJDy/EyLC447O02sV/y5YYBg==", "requires": { "babel-runtime": "6.x", "classnames": "2.x", @@ -27075,9 +27104,9 @@ } }, "rc-collapse": { - "version": "1.11.7", - "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-1.11.7.tgz", - "integrity": "sha512-ge3EEzIFtrDGuPX4bxXdQqwb91JnPIdj3B+FU88yNOUeOroNuA2q9kVK+UatpQ1Eft5hNo/ICTDrVFi8+685ng==", + "version": "1.11.8", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-1.11.8.tgz", + "integrity": "sha512-8EhfPyScTYljkbRuIoHniSwZagD5UPpZ3CToYgoNYWC85L2qCbPYF7+OaC713FOrIkp6NbfNqXsITNxmDAmxog==", "requires": { "classnames": "2.x", "css-animation": "1.x", @@ -27089,23 +27118,22 @@ } }, "rc-dialog": { - "version": "7.5.13", - "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-7.5.13.tgz", - "integrity": "sha512-tmubIipW/qoCmRlHHV8tpepDaFhuhk+SeSFSyRhNKW4mYgflsEYQmYWilyCJHy6UzKl84bSyFvJskhc1z1Hniw==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-7.6.1.tgz", + "integrity": "sha512-KUKf+2eZ4YL+lnXMG3hR4ZtIhC9glfH27NtTVz3gcoDIPAf3uUvaXVRNoDCiSi+OGKLyIb/b6EoidFh6nQC5Wg==", "requires": { "babel-runtime": "6.x", "rc-animate": "2.x", - "rc-util": "^4.8.1" + "rc-util": "^4.16.1" } }, "rc-drawer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-3.0.2.tgz", - "integrity": "sha512-oPScGXB/8/ov9gEFLxPH8RBv/9jLTZboZtyF/GgrrnCAvbFwUxXdELH6n6XIowmuDKKvTGIMgZdnao0T46Yv3A==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-3.1.3.tgz", + "integrity": "sha512-2z+RdxmzXyZde/1OhVMfDR1e/GBswFeWSZ7FS3Fdd0qhgVdpV1wSzILzzxRaT481ItB5hOV+e8pZT07vdJE8kg==", "requires": { - "babel-runtime": "^6.26.0", "classnames": "^2.2.6", - "rc-util": "^4.11.2", + "rc-util": "^4.16.1", "react-lifecycles-compat": "^3.0.4" } }, @@ -27151,9 +27179,9 @@ } }, "rc-form": { - "version": "2.4.10", - "resolved": "https://registry.npmjs.org/rc-form/-/rc-form-2.4.10.tgz", - "integrity": "sha512-h6a5Nvn6fMe3BfLpIWwL2RUkfXs1tvtifblTgGgH0UfzGgiQ5M12jiMJaAXek7TDDBUw90/c5vlZ6wFZjW0IgQ==", + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/rc-form/-/rc-form-2.4.11.tgz", + "integrity": "sha512-8BL+FNlFLTOY/A5X6tU35GQJLSIpsmqpwn/tFAYQTczXc4dMJ33ggtH248Cum8+LS0jLTsJKG2L4Qp+1CkY+sA==", "requires": { "async-validator": "~1.11.3", "babel-runtime": "6.x", @@ -27166,9 +27194,9 @@ } }, "rc-hammerjs": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/rc-hammerjs/-/rc-hammerjs-0.6.9.tgz", - "integrity": "sha512-4llgWO3RgLyVbEqUdGsDfzUDqklRlQW5VEhE3x35IvhV+w//VPRG34SBavK3D2mD/UaLKaohgU41V4agiftC8g==", + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/rc-hammerjs/-/rc-hammerjs-0.6.10.tgz", + "integrity": "sha512-Vgh9qIudyN5CHRop4M+v+xUniQBFWXKrsJxQRVtJOi2xgRrCeI52/bkpaL5HWwUhqTK9Ayq0n7lYTItT6ld5rg==", "requires": { "babel-runtime": "6.x", "hammerjs": "^2.0.8", @@ -27176,9 +27204,9 @@ } }, "rc-input-number": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-4.5.1.tgz", - "integrity": "sha512-grO7/Lau7iv3NyHVyCajE1LuGLqGkG1tEAAZSwm9M0esYfrwXVSip4qhb5sF+8g6ACsiI20sOVLIihXuhSoifA==", + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-4.5.7.tgz", + "integrity": "sha512-99PrQ90sTOKyyj7eu0VzwxY17xQ+bwG1XTQd+bTwFQ+IOUkIw7L4qSAYxt58sVYL+Cw+bu/RAtT2IpT9yC2pCQ==", "requires": { "babel-runtime": "6.x", "classnames": "^2.2.0", @@ -27188,9 +27216,9 @@ } }, "rc-mentions": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-0.4.1.tgz", - "integrity": "sha512-XSJp6kcEPydUaM0I/gnxpXggiKgA5FjgFPKZCMQBDQJYUjXpQNyg5ogNkOJt1/4B2P7pwbYPZXgxP/30yZVahA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-0.4.2.tgz", + "integrity": "sha512-DTZurQzacLXOfVuiHydGzqkq7cFMHXF18l2jZ9PhWUn2cqvOSY3W4osN0Pq29AOMOBpcxdZCzgc7Lb0r/bgkDw==", "requires": { "@ant-design/create-react-context": "^0.2.4", "classnames": "^2.2.6", @@ -27201,9 +27229,9 @@ } }, "rc-menu": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-7.5.3.tgz", - "integrity": "sha512-H/jUyGbJxZI/iuVdC6Iu9KHfz7tucoqK0Vn8ahDnv+ppc1PnKb4SkBbXn5LrmUyaj7thCBiaktBxVnUXSmNE2g==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-7.5.5.tgz", + "integrity": "sha512-4YJXJgrpUGEA1rMftXN7bDhrV5rPB8oBJoHqT+GVXtIWCanfQxEnM3fmhHQhatL59JoAFMZhJaNzhJIk4FUWCQ==", "requires": { "classnames": "2.x", "dom-scroll-into-view": "1.x", @@ -27229,9 +27257,9 @@ } }, "rc-pagination": { - "version": "1.20.11", - "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-1.20.11.tgz", - "integrity": "sha512-2wKO5kO+ELx1/zlqTY8TwGBruzofi+1BcZ7Z4xalMlLbDMTuUU4FDljbBBP/n9D2llK+NtgWA619PMBhInozZw==", + "version": "1.20.15", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-1.20.15.tgz", + "integrity": "sha512-/Xr4/3GOa1DtL8iCYl7qRUroEMrRDhZiiuHwcVFfSiwa9LYloMlUWcOJsnr8LN6A7rLPdm3/CHStUNeYd+2pKw==", "requires": { "babel-runtime": "6.x", "classnames": "^2.2.6", @@ -27240,18 +27268,18 @@ } }, "rc-progress": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-2.5.2.tgz", - "integrity": "sha512-ajI+MJkbBz9zYDuE9GQsY5gsyqPF7HFioZEDZ9Fmc+ebNZoiSeSJsTJImPFCg0dW/5WiRGUy2F69SX1aPtSJgA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-2.5.3.tgz", + "integrity": "sha512-K2fa4CnqGehLZoMrdmBeZ86ONSTVcdk5FlqetbwJ3R/+42XfqhwQVOjWp2MH4P7XSQOMAGcNOy1SFfCP3415sg==", "requires": { "babel-runtime": "6.x", "prop-types": "^15.5.8" } }, "rc-rate": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.5.0.tgz", - "integrity": "sha512-aXX5klRqbVZxvLghcKnLqqo7LvLVCHswEDteWsm5Gb7NBIPa1YKTcAbvb5SZ4Z4i4EeRoZaPwygRAWsQgGtbKw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.5.1.tgz", + "integrity": "sha512-3iJkNJT8xlHklPCdeZtUZmJmRVUbr6AHRlfSsztfYTXVlHrv2TcPn3XkHsH+12j812WVB7gvilS2j3+ffjUHXg==", "requires": { "classnames": "^2.2.5", "prop-types": "^15.5.8", @@ -27270,9 +27298,9 @@ } }, "rc-select": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-9.2.1.tgz", - "integrity": "sha512-nW/Zr2OCgxN26OX8ff3xcO1wK0e1l5ixnEfyN15Rbdk7TNI/rIPJIjPCQAoihRpk9A2C/GH8pahjlvKV1Vj++g==", + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-9.2.3.tgz", + "integrity": "sha512-WhswxOMWiNnkXRbxyrj0kiIvyCfo/BaRPaYbsDetSIAU2yEDwKHF798blCP5u86KLOBKBvtxWLFCkSsQw1so5w==", "requires": { "babel-runtime": "^6.23.0", "classnames": "2.x", @@ -27325,9 +27353,9 @@ } }, "rc-table": { - "version": "6.9.5", - "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-6.9.5.tgz", - "integrity": "sha512-STL6387A/izVh6r9F1WDiIIZ0QeubCdTgIlzMeGTSl/bXhB0VqjAZEikvoijPoauTjJIkIzVuQEIDjOhAWbpkQ==", + "version": "6.10.15", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-6.10.15.tgz", + "integrity": "sha512-LAr0M/gqt+irOjvPNBLApmQ0CUHNOfKsEBhu1uIuB3OlN1ynA9z+sdoTQyNd9+8NSl0MYnQOOfhtLChAY7nU0A==", "requires": { "classnames": "^2.2.5", "component-classes": "^1.2.6", @@ -27340,9 +27368,9 @@ } }, "rc-tabs": { - "version": "9.6.7", - "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-9.6.7.tgz", - "integrity": "sha512-OXbDOgaqv2MGK9QaDi6cdva6bNz3XGw+M9BHQpm1gTGmVQEGx5VcclDClH/3xobIzooxy8hrxg/s0rTlgDnC2w==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-9.7.0.tgz", + "integrity": "sha512-kvmgp8/MfLzFZ06hWHignqomFQ5nF7BqKr5O1FfhE4VKsGrep52YSF/1MvS5oe0NPcI9XGNS2p751C5v6cYDpQ==", "requires": { "@ant-design/create-react-context": "^0.2.4", "babel-runtime": "6.x", @@ -27358,9 +27386,9 @@ } }, "rc-time-picker": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/rc-time-picker/-/rc-time-picker-3.7.2.tgz", - "integrity": "sha512-UVWO9HXGyZoM4I2THlJsEAFcZQz+tYwdcpoHXCEFZsRLz9L2+7vV4EMp9Wa3UrtzMFEt83qSAX/90dCJeKl9sg==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/rc-time-picker/-/rc-time-picker-3.7.3.tgz", + "integrity": "sha512-Lv1Mvzp9fRXhXEnRLO4nW6GLNxUkfAZ3RsiIBsWjGjXXvMNjdr4BX/ayElHAFK0DoJqOhm7c5tjmIYpEOwcUXg==", "requires": { "classnames": "2.x", "moment": "2.x", @@ -27381,9 +27409,9 @@ } }, "rc-tree": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.3.tgz", - "integrity": "sha512-COvV65spQ6omrHBUhHRKqKNL5+ddXjlS+qWZchaL9FFuQNvjM5pjp9RnmMWK4fJJ5kBhhpLneh6wh9Vh3kSMXQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.4.tgz", + "integrity": "sha512-Xey794Iavgs8YldFlXcZLOhfcIhlX5Oz/yfKufknBXf2AlZCOkc7aHqSM9uTF7fBPtTGPhPxNEfOqHfY7b7xng==", "requires": { "@ant-design/create-react-context": "^0.2.4", "classnames": "2.x", @@ -27395,51 +27423,27 @@ } }, "rc-tree-select": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-2.9.1.tgz", - "integrity": "sha512-AfJQC1ZzaeH+Onmx84TtVLUL2guBZe7exA8XSfj1RRB1doDbYGTtybzpP3CEw/tuSftSRnz+iPt+iaxRTrgXRw==", + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-2.9.4.tgz", + "integrity": "sha512-0HQkXAN4XbfBW20CZYh3G+V+VMrjX42XRtDCpyv6PDUm5vikC0Ob682ZBCVS97Ww2a5Hf6Ajmu0ahWEdIEpwhg==", "requires": { "classnames": "^2.2.1", "dom-scroll-into-view": "^1.2.1", "prop-types": "^15.5.8", "raf": "^3.4.0", "rc-animate": "^2.8.2", - "rc-tree": "~2.0.0", - "rc-trigger": "^3.0.0-rc.2", + "rc-tree": "~2.1.0", + "rc-trigger": "^3.0.0", "rc-util": "^4.5.0", "react-lifecycles-compat": "^3.0.4", "shallowequal": "^1.0.2", "warning": "^4.0.1" }, "dependencies": { - "rc-tree": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.0.0.tgz", - "integrity": "sha512-DAT/jsbnFbHqG9Df9OaVG93CAVtTsJVnJiwKX+wqsG8TChpty3s6QX3zJZ+gBgjkq4ikLbu1kuFJtX63EKhSAA==", - "requires": { - "babel-runtime": "^6.23.0", - "classnames": "2.x", - "prop-types": "^15.5.8", - "rc-animate": "^2.6.0", - "rc-util": "^4.5.1", - "react-lifecycles-compat": "^3.0.4", - "warning": "^3.0.0" - }, - "dependencies": { - "warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", - "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", - "requires": { - "loose-envify": "^1.0.0" - } - } - } - }, "rc-trigger": { - "version": "3.0.0-rc.3", - "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-3.0.0-rc.3.tgz", - "integrity": "sha512-4vB6cpxcUdm2qO5VtB9q1TZz0MoWm9BzFLvGknulphGrl1qI6uxUsPDCvqnmujdpDdAKGGfjxntFpA7RtAwkFQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-3.0.0.tgz", + "integrity": "sha512-hQxbbJpo23E2QnYczfq3Ec5J5tVl2mUDhkqxrEsQAqk16HfADQg+iKNWzEYXyERSncdxfnzYuaBgy764mNRzTA==", "requires": { "babel-runtime": "6.x", "classnames": "^2.2.6", @@ -27447,25 +27451,37 @@ "raf": "^3.4.0", "rc-align": "^2.4.1", "rc-animate": "^3.0.0-rc.1", - "rc-util": "^4.4.0" + "rc-util": "^4.15.7" }, "dependencies": { "rc-animate": { - "version": "3.0.0-rc.6", - "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.0.0-rc.6.tgz", - "integrity": "sha512-oBLPpiT6Q4t6YvD/pkLcmofBP1p01TX0Otse8Q4+Mxt8J+VSDflLZGIgf62EwkvRwsQUkLPjZVFBsldnPKLzjg==", - "requires": { - "babel-runtime": "6.x", - "classnames": "^2.2.5", - "component-classes": "^1.2.6", - "fbjs": "^0.8.16", - "prop-types": "15.x", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.1.0.tgz", + "integrity": "sha512-8FsM+3B1H+0AyTyGggY6JyVldHTs1CyYT8CfTmG/nGHHXlecvSLeICJhcKgRLjUiQlctNnRtB1rwz79cvBVmrw==", + "requires": { + "@ant-design/css-animation": "^1.7.2", + "classnames": "^2.2.6", "raf": "^3.4.0", - "rc-util": "^4.5.0", - "react-lifecycles-compat": "^3.0.4" + "rc-util": "^5.0.1" + }, + "dependencies": { + "rc-util": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.4.tgz", + "integrity": "sha512-cd19RCrE0DJH6UcJ9+V3eaXA/5sNWyVKOKkWl8ZM2OqgNzVb8fv0obf/TkuvSN43tmTsgqY8k7OqpFYHhmef8g==", + "requires": { + "react-is": "^16.12.0", + "shallowequal": "^1.1.0" + } + } } } } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" } } }, @@ -27484,9 +27500,9 @@ } }, "rc-upload": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-2.9.2.tgz", - "integrity": "sha512-USjuWpTRJl3my32G5woysTaGrAld+S4dvvZ9kW6RX/RkekfmLDjvWc5ho8Mj/+6B6/tDRJnyGyvMxMQNkW7cvw==", + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-2.9.4.tgz", + "integrity": "sha512-WXt0HGxXyzLrPV6iec/96Rbl/6dyrAW8pKuY6wwD7yFYwfU5bjgKjv7vC8KNMJ6wzitFrZjnoiogNL3dF9dj3Q==", "requires": { "babel-runtime": "6.x", "classnames": "^2.2.5", @@ -27495,15 +27511,22 @@ } }, "rc-util": { - "version": "4.15.6", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.15.6.tgz", - "integrity": "sha512-W6HB1gIn+xZLxmQfLkhMnAtaZY9RktcOH2I0Tbam4D4ZDFrkO33f3M7IolN0EPtLMpf4Mv/dEQNclY77/PtBpg==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.21.1.tgz", + "integrity": "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==", "requires": { "add-dom-event-listener": "^1.1.0", - "babel-runtime": "6.x", "prop-types": "^15.5.10", + "react-is": "^16.12.0", "react-lifecycles-compat": "^3.0.4", "shallowequal": "^1.1.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "react": { @@ -27516,6 +27539,19 @@ "prop-types": "^15.6.2" } }, + "react-color": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.18.1.tgz", + "integrity": "sha512-X5XpyJS6ncplZs74ak0JJoqPi+33Nzpv5RYWWxn17bslih+X7OlgmfpmGC1fNvdkK7/SGWYf1JJdn7D2n5gSuQ==", + "requires": { + "@icons/material": "^0.2.4", + "lodash": "^4.17.11", + "material-colors": "^1.2.1", + "prop-types": "^15.5.10", + "reactcss": "^1.2.0", + "tinycolor2": "^1.4.1" + } + }, "react-dom": { "version": "16.11.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.11.0.tgz", @@ -27648,6 +27684,14 @@ "react-svg-core": "^3.0.3" } }, + "reactcss": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", + "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", + "requires": { + "lodash": "^4.0.1" + } + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -28642,9 +28686,9 @@ } }, "shallow-equal": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.0.tgz", - "integrity": "sha512-Z21pVxR4cXsfwpMKMhCEIO1PCi5sp7KEp+CmOpBQ+E8GpHwKOw2sEzk7sgblM3d/j4z4gakoWEoPcjK0VJQogA==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", + "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" }, "shallowequal": { "version": "1.1.0", diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 0db6a04d12e..ce3337caaac 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -47,22 +47,24 @@ "worker-loader": "^2.0.0" }, "dependencies": { - "cvat-core": "file:../cvat-core", - "cvat-canvas": "file:../cvat-canvas", "@types/react": "^16.9.2", + "@types/react-color": "^3.0.2", "@types/react-dom": "^16.9.0", "@types/react-redux": "^7.1.2", "@types/react-router": "^5.0.5", "@types/react-router-dom": "^5.1.0", "@types/react-share": "^3.0.1", "@types/redux-logger": "^3.0.7", - "antd": "^3.25.2", + "antd": "^3.26.17", "copy-to-clipboard": "^3.2.0", + "cvat-canvas": "file:../cvat-canvas", + "cvat-core": "file:../cvat-core", "dotenv-webpack": "^1.7.0", "error-stack-parser": "^2.0.6", "moment": "^2.24.0", "prop-types": "^15.7.2", "react": "^16.9.0", + "react-color": "^2.18.1", "react-dom": "^16.9.0", "react-hotkeys": "^2.0.0", "react-redux": "^7.1.1", diff --git a/cvat-ui/src/actions/auth-actions.ts b/cvat-ui/src/actions/auth-actions.ts index ed6ecd30d72..f7a0f3e9f24 100644 --- a/cvat-ui/src/actions/auth-actions.ts +++ b/cvat-ui/src/actions/auth-actions.ts @@ -52,7 +52,8 @@ export const registerAsync = ( dispatch(authActions.register()); try { - await cvat.server.register(username, firstName, lastName, email, password1, password2, confirmations); + await cvat.server.register(username, firstName, lastName, email, password1, password2, + confirmations); const users = await cvat.users.get({ self: true }); dispatch(authActions.registerSuccess(users[0])); diff --git a/cvat-ui/src/actions/settings-actions.ts b/cvat-ui/src/actions/settings-actions.ts index d84434408e3..9108b02a21a 100644 --- a/cvat-ui/src/actions/settings-actions.ts +++ b/cvat-ui/src/actions/settings-actions.ts @@ -32,6 +32,8 @@ export enum SettingsActionTypes { SWITCH_AUTOMATIC_BORDERING = 'SWITCH_AUTOMATIC_BORDERING', SWITCH_SHOWNIG_INTERPOLATED_TRACKS = 'SWITCH_SHOWNIG_INTERPOLATED_TRACKS', SWITCH_SHOWING_OBJECTS_TEXT_ALWAYS = 'SWITCH_SHOWING_OBJECTS_TEXT_ALWAYS', + CHANGE_CANVAS_BACKGROUND_COLOR = 'CHANGE_CANVAS_BACKGROUND_COLOR', + SWITCH_SETTINGS_DIALOG = 'SWITCH_SETTINGS_DIALOG', } export function changeShapesOpacity(opacity: number): AnyAction { @@ -240,3 +242,21 @@ export function switchAutomaticBordering(automaticBordering: boolean): AnyAction }, }; } + +export function changeCanvasBackgroundColor(color: string): AnyAction { + return { + type: SettingsActionTypes.CHANGE_CANVAS_BACKGROUND_COLOR, + payload: { + color, + }, + }; +} + +export function switchSettingsDialog(show?: boolean): AnyAction { + return { + type: SettingsActionTypes.SWITCH_SETTINGS_DIALOG, + payload: { + show, + }, + }; +} diff --git a/cvat-ui/src/actions/useragreements-actions.ts b/cvat-ui/src/actions/useragreements-actions.ts index 29645ddbf22..95ec7003829 100644 --- a/cvat-ui/src/actions/useragreements-actions.ts +++ b/cvat-ui/src/actions/useragreements-actions.ts @@ -4,7 +4,7 @@ import { ActionUnion, createAction, ThunkAction } from 'utils/redux'; import getCore from 'cvat-core-wrapper'; -import { UserAgreement } from 'reducers/interfaces' +import { UserAgreement } from 'reducers/interfaces'; const core = getCore(); @@ -16,10 +16,12 @@ export enum UserAgreementsActionTypes { const userAgreementsActions = { getUserAgreements: () => createAction(UserAgreementsActionTypes.GET_USER_AGREEMENTS), - getUserAgreementsSuccess: (userAgreements: UserAgreement[]) => - createAction(UserAgreementsActionTypes.GET_USER_AGREEMENTS_SUCCESS, userAgreements), - getUserAgreementsFailed: (error: any) => - createAction(UserAgreementsActionTypes.GET_USER_AGREEMENTS_FAILED, { error }), + getUserAgreementsSuccess: (userAgreements: UserAgreement[]) => ( + createAction(UserAgreementsActionTypes.GET_USER_AGREEMENTS_SUCCESS, userAgreements) + ), + getUserAgreementsFailed: (error: any) => ( + createAction(UserAgreementsActionTypes.GET_USER_AGREEMENTS_FAILED, { error }) + ), }; export type UserAgreementsActions = ActionUnion; diff --git a/cvat-ui/src/components/actions-menu/dump-submenu.tsx b/cvat-ui/src/components/actions-menu/dump-submenu.tsx index 803a5db9892..f88cc62e534 100644 --- a/cvat-ui/src/components/actions-menu/dump-submenu.tsx +++ b/cvat-ui/src/components/actions-menu/dump-submenu.tsx @@ -32,23 +32,22 @@ export default function DumpSubmenu(props: Props): JSX.Element { { dumpers .sort((a: any, b: any) => a.name.localeCompare(b.name)) - .map((dumper: any): JSX.Element => - { - const pending = (dumpActivities || []).includes(dumper.name); - const disabled = !dumper.enabled || pending; - const isDefault = isDefaultFormat(dumper.name, taskMode); - return ( - - - {dumper.name} - {pending && } - - ); - }) + .map((dumper: any): JSX.Element => { + const pending = (dumpActivities || []).includes(dumper.name); + const disabled = !dumper.enabled || pending; + const isDefault = isDefaultFormat(dumper.name, taskMode); + return ( + + + {dumper.name} + {pending && } + + ); + }) } ); diff --git a/cvat-ui/src/components/actions-menu/export-submenu.tsx b/cvat-ui/src/components/actions-menu/export-submenu.tsx index 045d682f85e..8f6bb4f30a8 100644 --- a/cvat-ui/src/components/actions-menu/export-submenu.tsx +++ b/cvat-ui/src/components/actions-menu/export-submenu.tsx @@ -25,22 +25,21 @@ export default function ExportSubmenu(props: Props): JSX.Element { { exporters .sort((a: any, b: any) => a.name.localeCompare(b.name)) - .map((exporter: any): JSX.Element => - { - const pending = (exportActivities || []).includes(exporter.name); - const disabled = !exporter.enabled || pending; - return ( - - - {exporter.name} - {pending && } - - ); - }) + .map((exporter: any): JSX.Element => { + const pending = (exportActivities || []).includes(exporter.name); + const disabled = !exporter.enabled || pending; + return ( + + + {exporter.name} + {pending && } + + ); + }) } ); diff --git a/cvat-ui/src/components/actions-menu/load-submenu.tsx b/cvat-ui/src/components/actions-menu/load-submenu.tsx index 2db41d17649..c167a01b2ba 100644 --- a/cvat-ui/src/components/actions-menu/load-submenu.tsx +++ b/cvat-ui/src/components/actions-menu/load-submenu.tsx @@ -29,39 +29,38 @@ export default function LoadSubmenu(props: Props): JSX.Element { { loaders .sort((a: any, b: any) => a.name.localeCompare(b.name)) - .map((loader: any): JSX.Element => - { - const accept = loader.format - .split(',') - .map((x: string) => '.' + x.trimStart()) - .join(', '); // add '.' to each extension in a list - const pending = loadActivity === loader.name; - const disabled = !loader.enabled || !!loadActivity; - return ( - - { - onFileUpload(file); - return false; - }} + .map((loader: any): JSX.Element => { + const accept = loader.format + .split(',') + .map((x: string) => `.${x.trimStart()}`) + .join(', '); // add '.' to each extension in a list + const pending = loadActivity === loader.name; + const disabled = !loader.enabled || !!loadActivity; + return ( + - - + { + onFileUpload(file); + return false; + }} + > + + - - ); - }) + + ); + }) } ); diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx index 0eb7a5d0fc0..ff4be1d345c 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx @@ -60,9 +60,11 @@ interface Props { resetZoom: boolean; aamZoomMargin: number; showObjectsTextAlways: boolean; + showAllInterpolationTracks: boolean; workspace: Workspace; automaticBordering: boolean; keyMap: Record; + canvasBackgroundColor: string; switchableAutomaticBordering: boolean; onSetupCanvas: () => void; onDragCanvas: (enabled: boolean) => void; @@ -91,6 +93,7 @@ interface Props { onChangeGridColor(color: GridColor): void; onSwitchGrid(enabled: boolean): void; onSwitchAutomaticBordering(enabled: boolean): void; + onFetchAnnotation(): void; } export default class CanvasWrapperComponent extends React.PureComponent { @@ -135,6 +138,7 @@ export default class CanvasWrapperComponent extends React.PureComponent { curZLayer, resetZoom, grid, + gridSize, gridOpacity, gridColor, brightnessLevel, @@ -143,8 +147,11 @@ export default class CanvasWrapperComponent extends React.PureComponent { workspace, frameFetching, showObjectsTextAlways, + showAllInterpolationTracks, automaticBordering, showProjections, + canvasBackgroundColor, + onFetchAnnotation, } = this.props; if (prevProps.showObjectsTextAlways !== showObjectsTextAlways @@ -159,6 +166,10 @@ export default class CanvasWrapperComponent extends React.PureComponent { }); } + if (prevProps.showAllInterpolationTracks !== showAllInterpolationTracks) { + onFetchAnnotation(); + } + if (prevProps.sidebarCollapsed !== sidebarCollapsed) { const [sidebar] = window.document.getElementsByClassName('cvat-objects-sidebar'); if (sidebar) { @@ -177,6 +188,10 @@ export default class CanvasWrapperComponent extends React.PureComponent { } } + if (gridSize !== prevProps.gridSize) { + canvasInstance.grid(gridSize, gridSize); + } + if (gridOpacity !== prevProps.gridOpacity || gridColor !== prevProps.gridColor || grid !== prevProps.grid) { @@ -220,7 +235,8 @@ export default class CanvasWrapperComponent extends React.PureComponent { } if (prevProps.opacity !== opacity || prevProps.blackBorders !== blackBorders - || prevProps.selectedOpacity !== selectedOpacity || prevProps.colorBy !== colorBy) { + || prevProps.selectedOpacity !== selectedOpacity || prevProps.colorBy !== colorBy + ) { this.updateShapesView(); } @@ -241,6 +257,13 @@ export default class CanvasWrapperComponent extends React.PureComponent { } } + if (prevProps.canvasBackgroundColor !== canvasBackgroundColor) { + const canvasWrapperElement = window.document.getElementsByClassName('cvat-canvas-container').item(0) as HTMLElement | null; + if (canvasWrapperElement) { + canvasWrapperElement.style.backgroundColor = canvasBackgroundColor; + } + } + this.activateOnCanvas(); } @@ -634,6 +657,7 @@ export default class CanvasWrapperComponent extends React.PureComponent { brightnessLevel, contrastLevel, saturationLevel, + canvasBackgroundColor, } = this.props; // Size @@ -660,6 +684,11 @@ export default class CanvasWrapperComponent extends React.PureComponent { + `saturate(${saturationLevel / 100})`; } + const canvasWrapperElement = window.document.getElementsByClassName('cvat-canvas-container').item(0) as HTMLElement | null; + if (canvasWrapperElement) { + canvasWrapperElement.style.backgroundColor = canvasBackgroundColor; + } + // Events canvasInstance.html().addEventListener('canvas.setup', () => { const { activatedStateID, activatedAttributeID } = this.props; 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 351ed192b7c..dd3945ca309 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 @@ -6,7 +6,7 @@ import React from 'react'; import Popover from 'antd/lib/popover'; import Icon from 'antd/lib/icon'; -import { Canvas } from 'cvat-canvas'; +import { Canvas } from 'cvat-canvas-wrapper'; import { ShapeType } from 'reducers/interfaces'; import { CubeIcon } from 'icons'; 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 0dfb658b945..ddcbf7a1593 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 @@ -379,7 +379,7 @@ function ItemButtonsComponent(props: ItemButtonsComponentProps): JSX.Element { { locked - ? + ? : } @@ -393,7 +393,7 @@ function ItemButtonsComponent(props: ItemButtonsComponentProps): JSX.Element { diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-side-bar.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-side-bar.tsx index eb3194e3db7..e77c2fe5651 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-side-bar.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-side-bar.tsx @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MIT import './styles.scss'; -import React from 'react'; +import React, { useEffect } from 'react'; import Text from 'antd/lib/typography/Text'; import Icon from 'antd/lib/icon'; import Tabs from 'antd/lib/tabs'; @@ -11,12 +11,14 @@ import Layout from 'antd/lib/layout'; import { RadioChangeEvent } from 'antd/lib/radio'; import { SliderValue } from 'antd/lib/slider'; import { CheckboxChangeEvent } from 'antd/lib/checkbox'; +import { Canvas } from 'cvat-canvas-wrapper'; import { ColorBy } from 'reducers/interfaces'; import ObjectsListContainer from 'containers/annotation-page/standard-workspace/objects-side-bar/objects-list'; import LabelsListContainer from 'containers/annotation-page/standard-workspace/objects-side-bar/labels-list'; import AppearanceBlock from './appearance-block'; + interface Props { sidebarCollapsed: boolean; appearanceCollapsed: boolean; @@ -26,6 +28,7 @@ interface Props { blackBorders: boolean; showBitmap: boolean; showProjections: boolean; + canvasInstance: Canvas; collapseSidebar(): void; collapseAppearance(): void; @@ -48,6 +51,7 @@ function ObjectsSideBar(props: Props): JSX.Element { blackBorders, showBitmap, showProjections, + canvasInstance, collapseSidebar, collapseAppearance, changeShapesColorBy, @@ -76,6 +80,23 @@ function ObjectsSideBar(props: Props): JSX.Element { changeShowProjections, }; + useEffect(() => { + const listener = (event: Event): void => { + if ((event as TransitionEvent).propertyName === 'width' + && ((event.target as any).classList as DOMTokenList).contains('ant-tabs-tab-prev')) { + canvasInstance.fit(); + } + }; + + const [sidebar] = window.document.getElementsByClassName('cvat-objects-sidebar'); + + sidebar.addEventListener('transitionstart', listener); + + return () => { + sidebar.removeEventListener('transitionstart', listener); + }; + }, []); + return ( void; resetMessages: () => void; switchShortcutsDialog: () => void; + switchSettingsDialog: () => void; keyMap: Record; userInitialized: boolean; userFetching: boolean; @@ -62,7 +62,7 @@ interface CVATAppProps { class CVATApplication extends React.PureComponent { public componentDidMount(): void { const core = getCore(); - const { verifyAuthorized, history } = this.props; + const { verifyAuthorized, history, location } = this.props; configure({ ignoreRepeatedEventsWhenKeyHeldDown: false }); // Logger configuration @@ -72,9 +72,9 @@ class CVATApplication extends React.PureComponent window.document.hasFocus, userActivityCallback); - customWaViewHit(history.location.pathname, history.location.search, history.location.hash); - history.listen((location) => { - customWaViewHit(location.pathname, location.search, location.hash); + customWaViewHit(location.pathname, location.search, location.hash); + history.listen((_location) => { + customWaViewHit(_location.pathname, _location.search, _location.hash); }); verifyAuthorized(); @@ -225,8 +225,8 @@ class CVATApplication extends React.PureComponent { - if (event) { - event.preventDefault(); - } + if (event) event.preventDefault(); switchShortcutsDialog(); }, - OPEN_SETTINGS: (event: KeyboardEvent | undefined) => { - if (event) { - event.preventDefault(); - } + SWITCH_SETTINGS: (event: KeyboardEvent | undefined) => { + if (event) event.preventDefault(); - if (history.location.pathname.endsWith('settings')) { - history.goBack(); - } else { - history.push('/settings'); - } + switchSettingsDialog(); }, }; @@ -273,7 +265,6 @@ class CVATApplication extends React.PureComponent - diff --git a/cvat-ui/src/components/header/header.tsx b/cvat-ui/src/components/header/header.tsx index 38925dbb834..dc01678b80b 100644 --- a/cvat-ui/src/components/header/header.tsx +++ b/cvat-ui/src/components/header/header.tsx @@ -17,9 +17,11 @@ import Text from 'antd/lib/typography/Text'; import { CVATLogo, AccountIcon } from 'icons'; import consts from 'consts'; +import SettingsModal from './settings-modal/settings-modal'; interface HeaderContainerProps { onLogout: () => void; + switchSettingsDialog: (show: boolean) => void; logoutFetching: boolean; installedAnalytics: boolean; installedAutoAnnotation: boolean; @@ -34,6 +36,7 @@ interface HeaderContainerProps { canvasVersion: string; uiVersion: string; switchSettingsShortcut: string; + settingsDialogShown: boolean; } type Props = HeaderContainerProps & RouteComponentProps; @@ -54,7 +57,9 @@ function HeaderContainer(props: Props): JSX.Element { uiVersion, onLogout, logoutFetching, + settingsDialogShown, switchSettingsShortcut, + switchSettingsDialog, } = props; const renderModels = installedAutoAnnotation @@ -131,7 +136,7 @@ function HeaderContainer(props: Props): JSX.Element { props.history.push('/settings') + (): void => switchSettingsDialog(true) } > @@ -236,6 +241,10 @@ function HeaderContainer(props: Props): JSX.Element { + switchSettingsDialog(false)} + /> ); } diff --git a/cvat-ui/src/components/settings-page/player-settings.tsx b/cvat-ui/src/components/header/settings-modal/player-settings.tsx similarity index 71% rename from cvat-ui/src/components/settings-page/player-settings.tsx rename to cvat-ui/src/components/header/settings-modal/player-settings.tsx index 6b834122ccb..ef872f67bf1 100644 --- a/cvat-ui/src/components/settings-page/player-settings.tsx +++ b/cvat-ui/src/components/header/settings-modal/player-settings.tsx @@ -9,13 +9,16 @@ import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox'; import Button from 'antd/lib/button'; import Slider from 'antd/lib/slider'; import Select from 'antd/lib/select'; +import Popover from 'antd/lib/popover'; import InputNumber from 'antd/lib/input-number'; import Icon from 'antd/lib/icon'; import Text from 'antd/lib/typography/Text'; +import { CompactPicker } from 'react-color'; import { clamp } from 'utils/math'; import { BackJumpIcon, ForwardJumpIcon } from 'icons'; import { FrameSpeed, GridColor } from 'reducers/interfaces'; +import consts from 'consts'; interface Props { @@ -30,6 +33,7 @@ interface Props { brightnessLevel: number; contrastLevel: number; saturationLevel: number; + canvasBackgroundColor: string; onChangeFrameStep(step: number): void; onChangeFrameSpeed(speed: FrameSpeed): void; onSwitchResetZoom(enabled: boolean): void; @@ -41,6 +45,7 @@ interface Props { onChangeBrightnessLevel(level: number): void; onChangeContrastLevel(level: number): void; onChangeSaturationLevel(level: number): void; + onChangeCanvasBackgroundColor(color: string): void; } export default function PlayerSettingsComponent(props: Props): JSX.Element { @@ -56,6 +61,7 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element { brightnessLevel, contrastLevel, saturationLevel, + canvasBackgroundColor, onChangeFrameStep, onChangeFrameSpeed, onSwitchResetZoom, @@ -67,6 +73,7 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element { onChangeBrightnessLevel, onChangeContrastLevel, onChangeSaturationLevel, + onChangeCanvasBackgroundColor, } = props; const minFrameStep = 2; @@ -74,7 +81,6 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element { const minGridSize = 5; const maxGridSize = 1000; - return (
@@ -122,6 +128,23 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element { + + + onChangeCanvasBackgroundColor(e.hex)} + /> + )} + overlayClassName='canvas-background-color-picker-popover' + trigger='click' + > + + + + - - - Brightness - - - { - onChangeBrightnessLevel(value as number); - }} - /> - - - - - Contrast - - - { - onChangeContrastLevel(value as number); - }} - /> - - - - - Saturation - - - { - onChangeSaturationLevel(value as number); - }} - /> - - - - - + + + + + Brightness + + + { + onChangeBrightnessLevel(value as number); + }} + /> + + + + + Contrast + + + { + onChangeContrastLevel(value as number); + }} + /> + + + + + Saturation + + + { + onChangeSaturationLevel(value as number); + }} + /> + + + + + + +
diff --git a/cvat-ui/src/components/header/settings-modal/settings-modal.tsx b/cvat-ui/src/components/header/settings-modal/settings-modal.tsx new file mode 100644 index 00000000000..b3c3503a5d6 --- /dev/null +++ b/cvat-ui/src/components/header/settings-modal/settings-modal.tsx @@ -0,0 +1,74 @@ +// Copyright (C) 2020 Intel Corporation +// +// SPDX-License-Identifier: MIT + +import './styles.scss'; +import React from 'react'; +import Tabs from 'antd/lib/tabs'; +import Icon from 'antd/lib/icon'; +import Text from 'antd/lib/typography/Text'; +import Modal from 'antd/lib/modal/Modal'; + +import WorkspaceSettingsContainer from 'containers/header/settings-modal/workspace-settings'; +import PlayerSettingsContainer from 'containers/header/settings-modal/player-settings'; +import Button from 'antd/lib/button'; + +interface SettingsModalProps { + visible: boolean; + onClose(): void; +} + +const SettingsModal = (props: SettingsModalProps): JSX.Element => { + const { visible, onClose } = props; + + return ( + + Close + + )} + > +
+ + + + Player + + ) + } + key='player' + > + + + + + Workspace + + ) + } + key='workspace' + > + + + +
+
+ ); +}; + +export default SettingsModal; diff --git a/cvat-ui/src/components/settings-page/styles.scss b/cvat-ui/src/components/header/settings-modal/styles.scss similarity index 79% rename from cvat-ui/src/components/settings-page/styles.scss rename to cvat-ui/src/components/header/settings-modal/styles.scss index 58fdfebb109..bcc778af484 100644 --- a/cvat-ui/src/components/settings-page/styles.scss +++ b/cvat-ui/src/components/header/settings-modal/styles.scss @@ -2,15 +2,15 @@ // // SPDX-License-Identifier: MIT -@import '../../base.scss'; +@import '../../../base.scss'; -.cvat-settings-page { +.cvat-settings-tabs { height: 100%; overflow-y: auto; padding-bottom: 15px; > div:nth-child(1) { - margin-top: 30px; + margin-top: 10px; margin-bottom: 10px; } } @@ -20,7 +20,7 @@ width: 100%; height: max-content; background: $background-color-1; - padding: 50px; + padding: 24px; } .cvat-player-settings-grid, @@ -42,6 +42,7 @@ .cvat-player-settings-speed, .cvat-player-settings-reset-zoom, .cvat-player-settings-rotate-all, +.cvat-player-settings-canvas-background, .cvat-workspace-settings-aam-zoom-margin, .cvat-workspace-settings-auto-save-interval { margin-bottom: 25px; @@ -96,12 +97,20 @@ } } -.cvat-settings-page-back-button { - width: 100px; - margin-top: 15px; +.cvat-player-settings-image-preview { + width: 100%; + max-height: 180px; + object-fit: cover; } -.cvat-settings-page-back-button-wrapper { - display: flex; - justify-content: flex-end; +.canvas-background-color-picker-popover .ant-popover-inner-content { + padding: 6px 12px; + + :first-child:first-child { + box-shadow: unset !important; + } } + +.cvat-settings-modal .ant-modal-body{ + padding-top: 0; +} \ No newline at end of file diff --git a/cvat-ui/src/components/settings-page/workspace-settings.tsx b/cvat-ui/src/components/header/settings-modal/workspace-settings.tsx similarity index 99% rename from cvat-ui/src/components/settings-page/workspace-settings.tsx rename to cvat-ui/src/components/header/settings-modal/workspace-settings.tsx index 5c85b529a79..f07b3dccb52 100644 --- a/cvat-ui/src/components/settings-page/workspace-settings.tsx +++ b/cvat-ui/src/components/header/settings-modal/workspace-settings.tsx @@ -42,7 +42,7 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element { onSwitchAutomaticBordering, } = props; - const minAutoSaveInterval = 5; + const minAutoSaveInterval = 1; const maxAutoSaveInterval = 60; const minAAMMargin = 0; const maxAAMMargin = 1000; diff --git a/cvat-ui/src/components/login-page/cookie-policy-drawer.tsx b/cvat-ui/src/components/login-page/cookie-policy-drawer.tsx index 80a05122c57..6c765c94fca 100644 --- a/cvat-ui/src/components/login-page/cookie-policy-drawer.tsx +++ b/cvat-ui/src/components/login-page/cookie-policy-drawer.tsx @@ -3,12 +3,12 @@ // // SPDX-License-Identifier: MIT -import React, {useState, useEffect} from 'react'; +import React, { useState, useEffect } from 'react'; import Drawer from 'antd/lib/drawer'; import Paragraph from 'antd/lib/typography/Paragraph'; import Button from 'antd/lib/button/button'; -import {isPublic} from 'utils/enviroment'; +import { isPublic } from 'utils/enviroment'; function CookieDrawer(): JSX.Element { @@ -19,12 +19,12 @@ function CookieDrawer(): JSX.Element { if (cookiePolicyAccepted === null && isPublic()) { setDrawerVisible(true); } - }, []) + }, []); - const onClose = () => { + const onClose = (): void => { localStorage.setItem('cookiePolicyAccepted', 'true'); setDrawerVisible(false); - } + }; return ( - This site uses cookies for functionality, analytics, and advertising purposes as described in our Cookie and Similar Technologies Notice. - To see what cookies we serve and set your preferences, please visit our Cookie Consent Tool. - By continuing to use our website, you agree to our use of cookies. + This site uses cookies for functionality, analytics, and advertising purposes + as described in our Cookie and Similar Technologies Notice. + To see what cookies we serve and set your preferences, please visit our + Cookie Consent Tool + . By continuing to use our website, you agree to our use of cookies. - - - - ); -} - -export default SettingsPage; diff --git a/cvat-ui/src/components/task-page/details.tsx b/cvat-ui/src/components/task-page/details.tsx index 504c92adad0..84c9aa1f71e 100644 --- a/cvat-ui/src/components/task-page/details.tsx +++ b/cvat-ui/src/components/task-page/details.tsx @@ -32,6 +32,7 @@ interface Props { interface State { name: string; bugTracker: string; + bugTrackerEditing: boolean; repository: string; repositoryStatus: string; } @@ -52,6 +53,7 @@ export default class DetailsComponent extends React.PureComponent this.state = { name: taskInstance.name, bugTracker: taskInstance.bugTracker, + bugTrackerEditing: false, repository: '', repositoryStatus: '', }; @@ -323,9 +325,14 @@ export default class DetailsComponent extends React.PureComponent taskInstance, onTaskUpdate, } = this.props; - const { bugTracker } = this.state; + const { bugTracker, bugTrackerEditing } = this.state; let shown = false; + const onStart = (): void => { + this.setState({ + bugTrackerEditing: true, + }); + }; const onChangeValue = (value: string): void => { if (value && !patterns.validateURL.pattern.test(value)) { if (!shown) { @@ -341,6 +348,7 @@ export default class DetailsComponent extends React.PureComponent } else { this.setState({ bugTracker: value, + bugTrackerEditing: false, }); taskInstance.bugTracker = value; @@ -377,7 +385,15 @@ export default class DetailsComponent extends React.PureComponent Issue Tracker
- Not specified + + {bugTrackerEditing ? '' : 'Not specified'} + ); diff --git a/cvat-ui/src/components/tasks-page/task-item.tsx b/cvat-ui/src/components/tasks-page/task-item.tsx index 36f1e04ecbf..7eeeeacdeb2 100644 --- a/cvat-ui/src/components/tasks-page/task-item.tsx +++ b/cvat-ui/src/components/tasks-page/task-item.tsx @@ -187,7 +187,7 @@ class TaskItemComponent extends React.PureComponent { e.preventDefault(); - history.push(`/tasks/${id}`) + history.push(`/tasks/${id}`); }} > Open diff --git a/cvat-ui/src/consts.ts b/cvat-ui/src/consts.ts index dfece049046..e0a94454e8c 100644 --- a/cvat-ui/src/consts.ts +++ b/cvat-ui/src/consts.ts @@ -13,6 +13,7 @@ const GITHUB_URL = 'https://github.com/opencv/cvat'; const GITHUB_IMAGE_URL = 'https://raw.githubusercontent.com/opencv/cvat/develop/cvat/apps/documentation/static/documentation/images/cvat.jpg'; const AUTO_ANNOTATION_GUIDE_URL = 'https://github.com/opencv/cvat/blob/develop/cvat/apps/auto_annotation/README.md'; const SHARE_MOUNT_GUIDE_URL = 'https://github.com/opencv/cvat/blob/master/cvat/apps/documentation/installation.md#share-path'; +const CANVAS_BACKGROUND_COLORS = ['#ffffff', '#f1f1f1', '#e5e5e5', '#d8d8d8', '#CCCCCC', '#B3B3B3', '#999999']; export default { UNDEFINED_ATTRIBUTE_VALUE, @@ -26,4 +27,5 @@ export default { GITHUB_IMAGE_URL, AUTO_ANNOTATION_GUIDE_URL, SHARE_MOUNT_GUIDE_URL, + CANVAS_BACKGROUND_COLORS, }; diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/canvas-wrapper.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/canvas-wrapper.tsx index 8ebe9844b1e..4591ad5a160 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/canvas-wrapper.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/canvas-wrapper.tsx @@ -26,6 +26,7 @@ import { updateCanvasContextMenu, addZLayer, switchZLayer, + fetchAnnotationsAsync, } from 'actions/annotation-actions'; import { switchGrid, @@ -78,6 +79,7 @@ interface StateToProps { resetZoom: boolean; aamZoomMargin: number; showObjectsTextAlways: boolean; + showAllInterpolationTracks: boolean; workspace: Workspace; minZLayer: number; maxZLayer: number; @@ -85,6 +87,7 @@ interface StateToProps { automaticBordering: boolean; switchableAutomaticBordering: boolean; keyMap: Record; + canvasBackgroundColor: string; } interface DispatchToProps { @@ -115,6 +118,7 @@ interface DispatchToProps { onChangeGridColor(color: GridColor): void; onSwitchGrid(enabled: boolean): void; onSwitchAutomaticBordering(enabled: boolean): void; + onFetchAnnotation(): void; } function mapStateToProps(state: CombinedState): StateToProps { @@ -155,6 +159,7 @@ function mapStateToProps(state: CombinedState): StateToProps { }, settings: { player: { + canvasBackgroundColor, grid, gridSize, gridColor, @@ -167,6 +172,7 @@ function mapStateToProps(state: CombinedState): StateToProps { workspace: { aamZoomMargin, showObjectsTextAlways, + showAllInterpolationTracks, automaticBordering, }, shapes: { @@ -213,12 +219,14 @@ function mapStateToProps(state: CombinedState): StateToProps { resetZoom, aamZoomMargin, showObjectsTextAlways, + showAllInterpolationTracks, curZLayer, minZLayer, maxZLayer, automaticBordering, workspace, keyMap, + canvasBackgroundColor, switchableAutomaticBordering: activeControl === ActiveControl.DRAW_POLYGON || activeControl === ActiveControl.DRAW_POLYLINE || activeControl === ActiveControl.EDIT, @@ -310,6 +318,9 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { onSwitchAutomaticBordering(enabled: boolean): void { dispatch(switchAutomaticBordering(enabled)); }, + onFetchAnnotation(): void { + dispatch(fetchAnnotationsAsync()); + }, }; } diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/objects-side-bar.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/objects-side-bar.tsx index 906e0fc2835..2873f026117 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/objects-side-bar.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/objects-side-bar/objects-side-bar.tsx @@ -31,6 +31,7 @@ import { changeShowProjections as changeShowProjectionsAction, } from 'actions/settings-actions'; +import { Canvas } from 'cvat-canvas-wrapper'; interface StateToProps { sidebarCollapsed: boolean; @@ -41,6 +42,7 @@ interface StateToProps { blackBorders: boolean; showBitmap: boolean; showProjections: boolean; + canvasInstance: Canvas; } interface DispatchToProps { @@ -60,6 +62,9 @@ function mapStateToProps(state: CombinedState): StateToProps { annotation: { sidebarCollapsed, appearanceCollapsed, + canvas: { + instance: canvasInstance, + }, }, settings: { shapes: { @@ -82,6 +87,7 @@ function mapStateToProps(state: CombinedState): StateToProps { blackBorders, showBitmap, showProjections, + canvasInstance, }; } @@ -213,6 +219,7 @@ class ObjectsSideBarContainer extends React.PureComponent { blackBorders, showBitmap, showProjections, + canvasInstance, collapseSidebar, collapseAppearance, } = this.props; @@ -227,6 +234,7 @@ class ObjectsSideBarContainer extends React.PureComponent { blackBorders={blackBorders} showBitmap={showBitmap} showProjections={showProjections} + canvasInstance={canvasInstance} collapseSidebar={collapseSidebar} collapseAppearance={collapseAppearance} changeShapesColorBy={this.changeShapesColorBy} diff --git a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx index 5f759c4e97b..8c75eeff18e 100644 --- a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx +++ b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx @@ -169,18 +169,12 @@ class AnnotationTopBarContainer extends React.PureComponent { public componentDidMount(): void { const { - autoSave, autoSaveInterval, - saving, history, jobInstance, } = this.props; - this.autoSaveInterval = window.setInterval((): void => { - if (autoSave && !saving) { - this.onSaveAnnotation(); - } - }, autoSaveInterval); + this.autoSaveInterval = window.setInterval(this.autoSave.bind(this), autoSaveInterval); this.unblock = history.block((location: any) => { if (jobInstance.annotations.hasUnsavedChanges() && location.pathname !== '/settings' @@ -193,7 +187,7 @@ class AnnotationTopBarContainer extends React.PureComponent { window.addEventListener('beforeunload', this.beforeUnloadCallback); } - public componentDidUpdate(): void { + public componentDidUpdate(prevProps: Props): void { const { jobInstance, frameSpeed, @@ -204,8 +198,13 @@ class AnnotationTopBarContainer extends React.PureComponent { canvasInstance, onSwitchPlay, onChangeFrame, + autoSaveInterval, } = this.props; + if (autoSaveInterval !== prevProps.autoSaveInterval) { + if (this.autoSaveInterval) window.clearInterval(this.autoSaveInterval); + this.autoSaveInterval = window.setInterval(this.autoSave.bind(this), autoSaveInterval); + } if (playing && canvasIsReady) { if (frameNumber < jobInstance.stopFrame) { @@ -444,6 +443,14 @@ class AnnotationTopBarContainer extends React.PureComponent { copy(url); }; + private autoSave(): void { + const { autoSave, saving } = this.props; + + if (autoSave && !saving) { + this.onSaveAnnotation(); + } + } + private changeFrame(frame: number): void { const { onChangeFrame, canvasInstance } = this.props; if (canvasInstance.isAbleToChangeFrame()) { diff --git a/cvat-ui/src/containers/header/header.tsx b/cvat-ui/src/containers/header/header.tsx index b939b19dd1b..59dc3f023f1 100644 --- a/cvat-ui/src/containers/header/header.tsx +++ b/cvat-ui/src/containers/header/header.tsx @@ -3,11 +3,13 @@ // SPDX-License-Identifier: MIT import { connect } from 'react-redux'; +import { ExtendedKeyMapOptions } from 'react-hotkeys'; import getCore from 'cvat-core-wrapper'; import HeaderComponent from 'components/header/header'; import { SupportedPlugins, CombinedState } from 'reducers/interfaces'; import { logoutAsync } from 'actions/auth-actions'; +import { switchSettingsDialog } from 'actions/settings-actions'; const core = getCore(); @@ -26,10 +28,12 @@ interface StateToProps { canvasVersion: string; uiVersion: string; switchSettingsShortcut: string; + settingsDialogShown: boolean; } interface DispatchToProps { onLogout: typeof logoutAsync; + switchSettingsDialog: (show: boolean) => void; } function mapStateToProps(state: CombinedState): StateToProps { @@ -50,6 +54,9 @@ function mapStateToProps(state: CombinedState): StateToProps { shortcuts: { normalizedKeyMap, }, + settings: { + showDialog: settingsDialogShown, + }, } = state; return { @@ -67,12 +74,16 @@ function mapStateToProps(state: CombinedState): StateToProps { canvasVersion: packageVersion.canvas, uiVersion: packageVersion.ui, switchSettingsShortcut: normalizedKeyMap.OPEN_SETTINGS, + settingsDialogShown, }; } -const mapDispatchToProps: DispatchToProps = { - onLogout: logoutAsync, -}; +function mapDispatchToProps(dispatch: any): DispatchToProps { + return { + onLogout: logoutAsync, + switchSettingsDialog: (show: boolean): void => dispatch(switchSettingsDialog(show)), + }; +} export default connect( mapStateToProps, diff --git a/cvat-ui/src/containers/settings-page/player-settings.tsx b/cvat-ui/src/containers/header/settings-modal/player-settings.tsx similarity index 87% rename from cvat-ui/src/containers/settings-page/player-settings.tsx rename to cvat-ui/src/containers/header/settings-modal/player-settings.tsx index 8903e209fd3..b1476fb18a2 100644 --- a/cvat-ui/src/containers/settings-page/player-settings.tsx +++ b/cvat-ui/src/containers/header/settings-modal/player-settings.tsx @@ -5,7 +5,7 @@ import React from 'react'; import { connect } from 'react-redux'; -import PlayerSettingsComponent from 'components/settings-page/player-settings'; +import PlayerSettingsComponent from 'components/header/settings-modal/player-settings'; import { changeFrameStep, @@ -19,6 +19,7 @@ import { changeBrightnessLevel, changeContrastLevel, changeSaturationLevel, + changeCanvasBackgroundColor, } from 'actions/settings-actions'; import { @@ -39,6 +40,7 @@ interface StateToProps { brightnessLevel: number; contrastLevel: number; saturationLevel: number; + canvasBackgroundColor: string; } interface DispatchToProps { @@ -53,13 +55,17 @@ interface DispatchToProps { onChangeBrightnessLevel(level: number): void; onChangeContrastLevel(level: number): void; onChangeSaturationLevel(level: number): void; + onChangeCanvasBackgroundColor(color: string): void; } function mapStateToProps(state: CombinedState): StateToProps { - const { player } = state.settings; - return { - ...player, - }; + const { + settings: { + player, + }, + } = state; + + return player; } function mapDispatchToProps(dispatch: any): DispatchToProps { @@ -97,6 +103,9 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { onChangeSaturationLevel(level: number): void { dispatch(changeSaturationLevel(level)); }, + onChangeCanvasBackgroundColor(color: string): void { + dispatch(changeCanvasBackgroundColor(color)); + }, }; } diff --git a/cvat-ui/src/containers/settings-page/workspace-settings.tsx b/cvat-ui/src/containers/header/settings-modal/workspace-settings.tsx similarity index 96% rename from cvat-ui/src/containers/settings-page/workspace-settings.tsx rename to cvat-ui/src/containers/header/settings-modal/workspace-settings.tsx index 8f360b724a6..d7e25347395 100644 --- a/cvat-ui/src/containers/settings-page/workspace-settings.tsx +++ b/cvat-ui/src/containers/header/settings-modal/workspace-settings.tsx @@ -16,7 +16,7 @@ import { import { CombinedState } from 'reducers/interfaces'; -import WorkspaceSettingsComponent from 'components/settings-page/workspace-settings'; +import WorkspaceSettingsComponent from 'components/header/settings-modal/workspace-settings'; interface StateToProps { autoSave: boolean; diff --git a/cvat-ui/src/containers/register-page/register-page.tsx b/cvat-ui/src/containers/register-page/register-page.tsx index 1f974fe7041..c05bd31c715 100644 --- a/cvat-ui/src/containers/register-page/register-page.tsx +++ b/cvat-ui/src/containers/register-page/register-page.tsx @@ -6,13 +6,12 @@ import React from 'react'; import { connect } from 'react-redux'; import { registerAsync } from 'actions/auth-actions'; import RegisterPageComponent from 'components/register-page/register-page'; -import { UserConfirmation } from 'components/register-page/register-form' +import { UserConfirmation } from 'components/register-page/register-form'; import { CombinedState, UserAgreement } from 'reducers/interfaces'; interface StateToProps { fetching: boolean; userAgreements: UserAgreement[]; - } interface DispatchToProps { diff --git a/cvat-ui/src/containers/settings-page/settings-page.tsx b/cvat-ui/src/containers/settings-page/settings-page.tsx deleted file mode 100644 index 611d313dd80..00000000000 --- a/cvat-ui/src/containers/settings-page/settings-page.tsx +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2020 Intel Corporation -// -// SPDX-License-Identifier: MIT - -import React from 'react'; -import { connect } from 'react-redux'; - -import { RouteComponentProps } from 'react-router'; -import { withRouter } from 'react-router-dom'; - -import SettingsPageComponent from 'components/settings-page/settings-page'; - - -import { - CombinedState, -} from 'reducers/interfaces'; - -interface StateToProps { - jobInstance: any; -} - -function mapStateToProps(state: CombinedState): StateToProps { - const { - annotation: { - job: { - instance: jobInstance, - }, - }, - } = state; - return { - jobInstance, - }; -} - -type Props = StateToProps & RouteComponentProps; -class SettingsPageContainer extends React.PureComponent { - private unblock: any; - - public componentDidMount(): void { - const { - history, - jobInstance, - } = this.props; - - this.unblock = history.block((location: any) => { - if (jobInstance && jobInstance.annotations.hasUnsavedChanges() - && location.pathname !== `/tasks/${jobInstance.task.id}/jobs/${jobInstance.id}`) { - return 'You have unsaved changes, please confirm leaving this page.'; - } - return undefined; - }); - this.beforeUnloadCallback = this.beforeUnloadCallback.bind(this); - window.addEventListener('beforeunload', this.beforeUnloadCallback); - } - - public componentWillUnmount(): void { - window.removeEventListener('beforeunload', this.beforeUnloadCallback); - this.unblock(); - } - - private beforeUnloadCallback(event: BeforeUnloadEvent): any { - const { jobInstance } = this.props; - if (jobInstance.annotations.hasUnsavedChanges()) { - const confirmationMessage = 'You have unsaved changes, please confirm leaving this page.'; - // eslint-disable-next-line no-param-reassign - event.returnValue = confirmationMessage; - return confirmationMessage; - } - return undefined; - } - - public render(): JSX.Element { - return ( - - ); - } -} - -export default withRouter( - connect( - mapStateToProps, - )(SettingsPageContainer), -); diff --git a/cvat-ui/src/containers/tasks-page/task-item.tsx b/cvat-ui/src/containers/tasks-page/task-item.tsx index 59717a7bd32..682fc34ab7e 100644 --- a/cvat-ui/src/containers/tasks-page/task-item.tsx +++ b/cvat-ui/src/containers/tasks-page/task-item.tsx @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: MIT -import React from 'react'; import { connect } from 'react-redux'; import { diff --git a/cvat-ui/src/index.tsx b/cvat-ui/src/index.tsx index e2c39d29b11..439ba395932 100644 --- a/cvat-ui/src/index.tsx +++ b/cvat-ui/src/index.tsx @@ -21,6 +21,7 @@ import { getUsersAsync } from 'actions/users-actions'; import { getAboutAsync } from 'actions/about-actions'; import { getUserAgreementsAsync } from 'actions/useragreements-actions'; import { shortcutsActions } from 'actions/shortcuts-actions'; +import { switchSettingsDialog } from 'actions/settings-actions'; import { resetErrors, resetMessages, @@ -65,6 +66,7 @@ interface DispatchToProps { resetMessages: () => void; switchShortcutsDialog: () => void; loadUserAgreements: () => void; + switchSettingsDialog: (show: boolean) => void; } function mapStateToProps(state: CombinedState): StateToProps { @@ -109,6 +111,7 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { resetErrors: (): void => dispatch(resetErrors()), resetMessages: (): void => dispatch(resetMessages()), switchShortcutsDialog: (): void => dispatch(shortcutsActions.switchShortcutsDialog()), + switchSettingsDialog: (): void => dispatch(switchSettingsDialog()), }; } diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts index 0cf7ffcd8db..6563d84a5aa 100644 --- a/cvat-ui/src/reducers/interfaces.ts +++ b/cvat-ui/src/reducers/interfaces.ts @@ -429,6 +429,7 @@ export enum ColorBy { } export interface PlayerSettingsState { + canvasBackgroundColor: string; frameStep: number; frameSpeed: FrameSpeed; resetZoom: boolean; @@ -464,6 +465,7 @@ export interface SettingsState { shapes: ShapesSettingsState; workspace: WorkspaceSettingsState; player: PlayerSettingsState; + showDialog: boolean; } export interface ShortcutsState { diff --git a/cvat-ui/src/reducers/notifications-reducer.ts b/cvat-ui/src/reducers/notifications-reducer.ts index b3abbab5c90..f7d4b5db951 100644 --- a/cvat-ui/src/reducers/notifications-reducer.ts +++ b/cvat-ui/src/reducers/notifications-reducer.ts @@ -14,7 +14,7 @@ import { AboutActionTypes } from 'actions/about-actions'; import { AnnotationActionTypes } from 'actions/annotation-actions'; import { NotificationsActionType } from 'actions/notification-actions'; import { BoundariesActionTypes } from 'actions/boundaries-actions'; -import { UserAgreementsActions, UserAgreementsActionTypes } from 'actions/useragreements-actions'; +import { UserAgreementsActionTypes } from 'actions/useragreements-actions'; import { NotificationsState } from './interfaces'; diff --git a/cvat-ui/src/reducers/settings-reducer.ts b/cvat-ui/src/reducers/settings-reducer.ts index 68d39368260..3bd4cf90c5f 100644 --- a/cvat-ui/src/reducers/settings-reducer.ts +++ b/cvat-ui/src/reducers/settings-reducer.ts @@ -34,6 +34,7 @@ const defaultState: SettingsState = { showAllInterpolationTracks: false, }, player: { + canvasBackgroundColor: '#ffffff', frameStep: 10, frameSpeed: FrameSpeed.Usual, resetZoom: false, @@ -46,6 +47,7 @@ const defaultState: SettingsState = { contrastLevel: 100, saturationLevel: 100, }, + showDialog: false, }; export default (state = defaultState, action: AnyAction): SettingsState => { @@ -257,6 +259,21 @@ export default (state = defaultState, action: AnyAction): SettingsState => { }, }; } + case SettingsActionTypes.CHANGE_CANVAS_BACKGROUND_COLOR: { + return { + ...state, + player: { + ...state.player, + canvasBackgroundColor: action.payload.color, + }, + }; + } + case SettingsActionTypes.SWITCH_SETTINGS_DIALOG: { + return { + ...state, + showDialog: typeof action.payload.show === 'undefined' ? !state.showDialog : action.payload.show, + }; + } case BoundariesActionTypes.RESET_AFTER_ERROR: case AnnotationActionTypes.GET_JOB_SUCCESS: { const { job } = action.payload; diff --git a/cvat-ui/src/reducers/shortcuts-reducer.ts b/cvat-ui/src/reducers/shortcuts-reducer.ts index c72aae78f9a..891237ad305 100644 --- a/cvat-ui/src/reducers/shortcuts-reducer.ts +++ b/cvat-ui/src/reducers/shortcuts-reducer.ts @@ -27,9 +27,9 @@ const defaultKeyMap = { sequences: ['f1'], action: 'keydown', }, - OPEN_SETTINGS: { - name: 'Open settings', - description: 'Go to the settings page or go back', + SWITCH_SETTINGS: { + name: 'Show settings', + description: 'Open/hide settings dialog', sequences: ['f2'], action: 'keydown', }, diff --git a/cvat-ui/src/utils/enviroment.ts b/cvat-ui/src/utils/enviroment.ts index 895a510386e..ebc8dd75b84 100644 --- a/cvat-ui/src/utils/enviroment.ts +++ b/cvat-ui/src/utils/enviroment.ts @@ -10,8 +10,8 @@ export function isPublic(): boolean { return process.env.PUBLIC_INSTANCE === 'true'; } -export function customWaViewHit(pageName?: string, queryString?: string, hashInfo?: string) { - const waHitFunctionName = process.env.WA_PAGE_VIEW_HIT +export function customWaViewHit(pageName?: string, queryString?: string, hashInfo?: string): void { + const waHitFunctionName = process.env.WA_PAGE_VIEW_HIT; if (waHitFunctionName) { const waHitFunction = new Function('pageName', 'queryString', 'hashInfo', `if (typeof ${waHitFunctionName} === 'function') { diff --git a/cvat-ui/src/utils/math.ts b/cvat-ui/src/utils/math.ts index 152d9b5a970..7dfaad66dcf 100644 --- a/cvat-ui/src/utils/math.ts +++ b/cvat-ui/src/utils/math.ts @@ -5,8 +5,7 @@ export function clamp(value: number, min: number, max: number): number { export function shift(array: Array, k: number): Array { if (k % array.length !== 0) { - return array.slice(k % array.length).concat(array.slice(0,k % array.length)); - } else { - return array; + return array.slice(k % array.length).concat(array.slice(0, k % array.length)); } -} \ No newline at end of file + return array; +}