CVAT UI: batch of fixes (#1705)

main
Dmitry Kalinin 6 years ago committed by GitHub
parent db24f93d66
commit 49a7ad59ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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 (<https://github.com/opencv/cvat/pull/1683>)
- Better validation of labels and attributes in raw viewer (<https://github.com/opencv/cvat/pull/1727>)
- ClamAV antivirus integration (<https://github.com/opencv/cvat/pull/1712>)
- Added canvas background color selector (<https://github.com/opencv/cvat/pull/1705>)
- SCSS files linting with Stylelint tool (<https://github.com/opencv/cvat/pull/1766>)
- 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 (<https://github.com/opencv/cvat/pull/1627>)
- Update https install manual. Makes it easier and more robust. Includes automatic renewing of lets encrypt certificates.
- Settings page move to the modal. (<https://github.com/opencv/cvat/pull/1705>)
- Implemented import and export of annotations with relative image paths (<https://github.com/opencv/cvat/pull/1463>)
- Using only single click to start editing or remove a point (<https://github.com/opencv/cvat/pull/1571>)
@ -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 (<https://github.com/opencv/cvat/pull/1667>)
- Wrong resolution for resizing a shape (<https://github.com/opencv/cvat/pull/1667>)
- React warning because of not unique keys in labels viewer (<https://github.com/opencv/cvat/pull/1727>)
- Fixed issue tracker (<https://github.com/opencv/cvat/pull/1705>)
- Fixed canvas fit after sidebar open/close event (<https://github.com/opencv/cvat/pull/1705>)
- A couple of exceptions in AAM related with early object activation (<https://github.com/opencv/cvat/pull/1755>)
- Propagation from the latest frame (<https://github.com/opencv/cvat/pull/1800>)
- Number attribute value validation (didn't work well with floats) (<https://github.com/opencv/cvat/pull/1800>)

@ -1,6 +1,6 @@
{
"name": "cvat-canvas",
"version": "1.2.0",
"version": "1.2.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

@ -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": {

@ -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;
}

@ -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,
};
}

@ -48,6 +48,7 @@ export interface DrawnState {
pinned?: boolean;
updated: number;
frame: number;
label: any;
}
// Translate point array from the canvas coordinate system

@ -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,28 +27451,40 @@
"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==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.1.0.tgz",
"integrity": "sha512-8FsM+3B1H+0AyTyGggY6JyVldHTs1CyYT8CfTmG/nGHHXlecvSLeICJhcKgRLjUiQlctNnRtB1rwz79cvBVmrw==",
"requires": {
"babel-runtime": "6.x",
"classnames": "^2.2.5",
"component-classes": "^1.2.6",
"fbjs": "^0.8.16",
"prop-types": "15.x",
"@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=="
}
}
},
"rc-trigger": {
"version": "2.6.5",
"resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-2.6.5.tgz",
@ -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",

@ -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",

@ -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]));

@ -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,
},
};
}

@ -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<typeof userAgreementsActions>;

@ -32,8 +32,7 @@ export default function DumpSubmenu(props: Props): JSX.Element {
{
dumpers
.sort((a: any, b: any) => a.name.localeCompare(b.name))
.map((dumper: any): JSX.Element =>
{
.map((dumper: any): JSX.Element => {
const pending = (dumpActivities || []).includes(dumper.name);
const disabled = !dumper.enabled || pending;
const isDefault = isDefaultFormat(dumper.name, taskMode);

@ -25,8 +25,7 @@ export default function ExportSubmenu(props: Props): JSX.Element {
{
exporters
.sort((a: any, b: any) => a.name.localeCompare(b.name))
.map((exporter: any): JSX.Element =>
{
.map((exporter: any): JSX.Element => {
const pending = (exportActivities || []).includes(exporter.name);
const disabled = !exporter.enabled || pending;
return (

@ -29,11 +29,10 @@ export default function LoadSubmenu(props: Props): JSX.Element {
{
loaders
.sort((a: any, b: any) => a.name.localeCompare(b.name))
.map((loader: any): JSX.Element =>
{
.map((loader: any): JSX.Element => {
const accept = loader.format
.split(',')
.map((x: string) => '.' + x.trimStart())
.map((x: string) => `.${x.trimStart()}`)
.join(', '); // add '.' to each extension in a list
const pending = loadActivity === loader.name;
const disabled = !loader.enabled || !!loadActivity;

@ -60,9 +60,11 @@ interface Props {
resetZoom: boolean;
aamZoomMargin: number;
showObjectsTextAlways: boolean;
showAllInterpolationTracks: boolean;
workspace: Workspace;
automaticBordering: boolean;
keyMap: Record<string, ExtendedKeyMapOptions>;
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<Props> {
@ -135,6 +138,7 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
curZLayer,
resetZoom,
grid,
gridSize,
gridOpacity,
gridColor,
brightnessLevel,
@ -143,8 +147,11 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
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<Props> {
});
}
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<Props> {
}
}
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<Props> {
}
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<Props> {
}
}
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<Props> {
brightnessLevel,
contrastLevel,
saturationLevel,
canvasBackgroundColor,
} = this.props;
// Size
@ -660,6 +684,11 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
+ `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;

@ -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';

@ -379,7 +379,7 @@ function ItemButtonsComponent(props: ItemButtonsComponentProps): JSX.Element {
<Col>
<Tooltip title={`Switch lock property ${switchLockShortcut}`}>
{ locked
? <Icon type='lock' onClick={unlock} theme='filled' />
? <Icon type='lock' theme='filled' onClick={unlock} />
: <Icon type='unlock' onClick={lock} />}
</Tooltip>
</Col>
@ -393,7 +393,7 @@ function ItemButtonsComponent(props: ItemButtonsComponentProps): JSX.Element {
<Col>
<Tooltip title={`Switch hidden property ${switchHiddenShortcut}`}>
{ hidden
? <Icon type='eye-invisible' onClick={show} />
? <Icon type='eye-invisible' theme='filled' onClick={show} />
: <Icon type='eye' onClick={hide} />}
</Tooltip>
</Col>

@ -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 (
<Layout.Sider
className='cvat-objects-sidebar'

@ -8,10 +8,6 @@
height: 100%;
}
.cvat-canvas-container {
background-color: $background-color-1;
}
.cvat-objects-sidebar-filter-input {
width: calc(100% - 35px);
}

@ -14,7 +14,6 @@ import notification from 'antd/lib/notification';
import GlobalErrorBoundary from 'components/global-error-boundary/global-error-boundary';
import ShorcutsDialog from 'components/shortcuts-dialog/shortcuts-dialog';
import SettingsPageContainer from 'containers/settings-page/settings-page';
import TasksPageContainer from 'containers/tasks-page/tasks-page';
import CreateTaskPageContainer from 'containers/create-task-page/create-task-page';
import TaskPageContainer from 'containers/task-page/task-page';
@ -39,6 +38,7 @@ interface CVATAppProps {
resetErrors: () => void;
resetMessages: () => void;
switchShortcutsDialog: () => void;
switchSettingsDialog: () => void;
keyMap: Record<string, ExtendedKeyMapOptions>;
userInitialized: boolean;
userFetching: boolean;
@ -62,7 +62,7 @@ interface CVATAppProps {
class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentProps> {
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<CVATAppProps & RouteComponentP
});
core.logger.configure(() => window.document.hasFocus, userActivityCallback);
customWaViewHit(history.location.pathname, history.location.search, history.location.hash);
history.listen((location) => {
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<CVATAppProps & RouteComponentP
installedTFSegmentation,
installedTFAnnotation,
switchShortcutsDialog,
switchSettingsDialog,
user,
history,
keyMap,
} = this.props;
@ -239,27 +239,19 @@ class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentP
const subKeyMap = {
SWITCH_SHORTCUTS: keyMap.SWITCH_SHORTCUTS,
OPEN_SETTINGS: keyMap.OPEN_SETTINGS,
SWITCH_SETTINGS: keyMap.SWITCH_SETTINGS,
};
const handlers = {
SWITCH_SHORTCUTS: (event: KeyboardEvent | undefined) => {
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<CVATAppProps & RouteComponentP
<ShorcutsDialog />
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers}>
<Switch>
<Route exact path='/settings' component={SettingsPageContainer} />
<Route exact path='/tasks' component={TasksPageContainer} />
<Route exact path='/tasks/create' component={CreateTaskPageContainer} />
<Route exact path='/tasks/:id' component={TaskPageContainer} />

@ -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 {
<Menu.Item
title={`Press ${switchSettingsShortcut} to switch`}
onClick={
(): void => props.history.push('/settings')
(): void => switchSettingsDialog(true)
}
>
<Icon type='setting' />
@ -236,6 +241,10 @@ function HeaderContainer(props: Props): JSX.Element {
</span>
</Dropdown>
</div>
<SettingsModal
visible={settingsDialogShown}
onClose={() => switchSettingsDialog(false)}
/>
</Layout.Header>
);
}

@ -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 (
<div className='cvat-player-settings'>
<Row type='flex' align='bottom' className='cvat-player-settings-step'>
@ -122,6 +128,23 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Select>
</Col>
</Row>
<Row type='flex' className='cvat-player-settings-canvas-background'>
<Col>
<Popover
content={(
<CompactPicker
colors={consts.CANVAS_BACKGROUND_COLORS}
color={canvasBackgroundColor}
onChange={(e) => onChangeCanvasBackgroundColor(e.hex)}
/>
)}
overlayClassName='canvas-background-color-picker-popover'
trigger='click'
>
<Button type='default'>Select canvas background color</Button>
</Popover>
</Col>
</Row>
<Row type='flex'>
<Col>
<Checkbox
@ -220,6 +243,8 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Row>
</Col>
</Row>
<Row>
<Col span={12}>
<Row className='cvat-player-settings-brightness'>
<Col className='cvat-text-color'>
Brightness
@ -278,6 +303,8 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Button>
</Col>
</Row>
</Col>
</Row>
</div>
);
}

@ -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 (
<Modal
title='Settings'
visible={visible}
onCancel={onClose}
width={800}
className='cvat-settings-modal'
footer={(
<Button type='primary' onClick={onClose}>
Close
</Button>
)}
>
<div className='cvat-settings-tabs'>
<Tabs
type='card'
tabBarStyle={{ marginBottom: '0px', marginLeft: '-1px' }}
>
<Tabs.TabPane
tab={
(
<span>
<Icon type='play-circle' />
<Text>Player</Text>
</span>
)
}
key='player'
>
<PlayerSettingsContainer />
</Tabs.TabPane>
<Tabs.TabPane
tab={
(
<span>
<Icon type='laptop' />
<Text>Workspace</Text>
</span>
)
}
key='workspace'
>
<WorkspaceSettingsContainer />
</Tabs.TabPane>
</Tabs>
</div>
</Modal>
);
};
export default SettingsModal;

@ -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;
}
.canvas-background-color-picker-popover .ant-popover-inner-content {
padding: 6px 12px;
:first-child:first-child {
box-shadow: unset !important;
}
}
.cvat-settings-page-back-button-wrapper {
display: flex;
justify-content: flex-end;
.cvat-settings-modal .ant-modal-body{
padding-top: 0;
}

@ -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;

@ -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 (
<Drawer
@ -36,9 +36,11 @@ function CookieDrawer(): JSX.Element {
destroyOnClose
>
<Paragraph>
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 <a href='https://www.intel.com/cookies'>Cookie Consent Tool</a>.
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
<a href='https://www.intel.com/cookies'>Cookie Consent Tool</a>
. By continuing to use our website, you agree to our use of cookies.
</Paragraph>
<Button onClick={onClose} size='large' type='primary'>
Accept

@ -10,7 +10,7 @@ import Title from 'antd/lib/typography/Title';
import Text from 'antd/lib/typography/Text';
import { Row, Col } from 'antd/lib/grid';
import { UserAgreement } from 'reducers/interfaces'
import { UserAgreement } from 'reducers/interfaces';
import CookieDrawer from 'components/login-page/cookie-policy-drawer';
import RegisterForm, { RegisterData, UserConfirmation } from './register-form';

@ -1,78 +0,0 @@
// Copyright (C) 2020 Intel Corporation
//
// SPDX-License-Identifier: MIT
import './styles.scss';
import React from 'react';
import { Row, Col } from 'antd/lib/grid';
import Tabs from 'antd/lib/tabs';
import Icon from 'antd/lib/icon';
import Button from 'antd/lib/button';
import Text from 'antd/lib/typography/Text';
import { RouteComponentProps } from 'react-router';
import WorkspaceSettingsContainer from 'containers/settings-page/workspace-settings';
import PlayerSettingsContainer from 'containers/settings-page/player-settings';
function SettingsPage(props: RouteComponentProps): JSX.Element {
return (
<div className='cvat-settings-page'>
<Row type='flex' justify='center'>
<Col>
<Text className='cvat-title'> Settings </Text>
</Col>
</Row>
<Row type='flex' justify='center'>
<Col md={14} lg={12} xl={10} xxl={9}>
<Tabs
type='card'
tabBarStyle={{ marginBottom: '0px', marginLeft: '-1px' }}
>
<Tabs.TabPane
tab={
(
<span>
<Icon type='play-circle' />
<Text>Player</Text>
</span>
)
}
key='player'
>
<PlayerSettingsContainer />
</Tabs.TabPane>
<Tabs.TabPane
tab={
(
<span>
<Icon type='laptop' />
<Text>Workspace</Text>
</span>
)
}
key='workspace'
>
<WorkspaceSettingsContainer />
</Tabs.TabPane>
</Tabs>
</Col>
</Row>
<Row type='flex' justify='center'>
<Col md={14} lg={12} xl={10} xxl={9} className='cvat-settings-page-back-button-wrapper'>
<Button
className='cvat-settings-page-back-button'
type='primary'
onClick={(): void => {
props.history.goBack();
}}
>
Go Back
</Button>
</Col>
</Row>
</div>
);
}
export default SettingsPage;

@ -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<Props, State>
this.state = {
name: taskInstance.name,
bugTracker: taskInstance.bugTracker,
bugTrackerEditing: false,
repository: '',
repositoryStatus: '',
};
@ -323,9 +325,14 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
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<Props, State>
} else {
this.setState({
bugTracker: value,
bugTrackerEditing: false,
});
taskInstance.bugTracker = value;
@ -377,7 +385,15 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
<Col>
<Text strong className='cvat-text-color'>Issue Tracker</Text>
<br />
<Text editable={{ onChange: onChangeValue }}>Not specified</Text>
<Text
editable={{
editing: bugTrackerEditing,
onStart,
onChange: onChangeValue,
}}
>
{bugTrackerEditing ? '' : 'Not specified'}
</Text>
</Col>
</Row>
);

@ -187,7 +187,7 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
href={`/tasks/${id}`}
onClick={(e: React.MouseEvent): void => {
e.preventDefault();
history.push(`/tasks/${id}`)
history.push(`/tasks/${id}`);
}}
>
Open

@ -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,
};

@ -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<string, ExtendedKeyMapOptions>;
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());
},
};
}

@ -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<Props> {
blackBorders,
showBitmap,
showProjections,
canvasInstance,
collapseSidebar,
collapseAppearance,
} = this.props;
@ -227,6 +234,7 @@ class ObjectsSideBarContainer extends React.PureComponent<Props> {
blackBorders={blackBorders}
showBitmap={showBitmap}
showProjections={showProjections}
canvasInstance={canvasInstance}
collapseSidebar={collapseSidebar}
collapseAppearance={collapseAppearance}
changeShapesColorBy={this.changeShapesColorBy}

@ -169,18 +169,12 @@ class AnnotationTopBarContainer extends React.PureComponent<Props> {
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<Props> {
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<Props> {
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<Props> {
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()) {

@ -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 = {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
onLogout: logoutAsync,
switchSettingsDialog: (show: boolean): void => dispatch(switchSettingsDialog(show)),
};
}
export default connect(
mapStateToProps,

@ -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));
},
};
}

@ -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;

@ -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 {

@ -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<Props> {
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 (
<SettingsPageComponent {...this.props} />
);
}
}
export default withRouter(
connect(
mapStateToProps,
)(SettingsPageContainer),
);

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: MIT
import React from 'react';
import { connect } from 'react-redux';
import {

@ -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()),
};
}

@ -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 {

@ -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';

@ -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;

@ -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',
},

@ -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') {

@ -6,7 +6,6 @@ export function clamp(value: number, min: number, max: number): number {
export function shift<T>(array: Array<T>, k: number): Array<T> {
if (k % array.length !== 0) {
return array.slice(k % array.length).concat(array.slice(0, k % array.length));
} else {
return array;
}
return array;
}
Loading…
Cancel
Save