From 32027ce884c0584015874c4ae99ba7f53ffb46c0 Mon Sep 17 00:00:00 2001
From: Boris Sekachev <40690378+bsekachev@users.noreply.github.com>
Date: Sat, 7 Dec 2019 07:58:31 +0300
Subject: [PATCH] UI eslint fixes (#908)
* Installed airbnb fullsettings
* Fixed actions menu
* Create model/task page
* File manager, header
* Labels editor
* Login, register
* Models page & model runner
* Tasks page
* Feedback and base app
* Tasks page
* Containers
* Reducers
* Fixed additional issues
* Small pagination fix
---
.vscode/settings.json | 3 +-
cvat-ui/.eslintrc.js | 9 +-
cvat-ui/package-lock.json | 194 ++++++++--
cvat-ui/package.json | 7 +-
cvat-ui/src/actions/models-actions.ts | 2 +-
.../components/actions-menu/actions-menu.tsx | 60 ++-
.../components/actions-menu/dumper-item.tsx | 28 +-
.../components/actions-menu/export-item.tsx | 31 +-
.../components/actions-menu/loader-item.tsx | 28 +-
.../create-model-content.tsx | 96 +++--
.../create-model-page/create-model-form.tsx | 35 +-
.../create-model-page/create-model-page.tsx | 16 +-
.../advanced-configuration-form.tsx | 138 ++++---
.../basic-configuration-form.tsx | 31 +-
.../create-task-page/create-task-content.tsx | 143 +++----
.../create-task-page/create-task-page.tsx | 14 +-
cvat-ui/src/components/cvat-app.tsx | 207 ++++++----
cvat-ui/src/components/feedback.tsx | 161 ++++----
.../components/file-manager/file-manager.tsx | 207 ++++++----
cvat-ui/src/components/header/header.tsx | 142 ++++---
.../labels-editor/constructor-creator.tsx | 27 +-
.../labels-editor/constructor-updater.tsx | 28 +-
.../labels-editor/constructor-viewer-item.tsx | 41 +-
.../labels-editor/constructor-viewer.tsx | 16 +-
.../components/labels-editor/label-form.tsx | 308 ++++++++-------
.../labels-editor/labels-editor.tsx | 281 ++++++++------
.../components/labels-editor/raw-viewer.tsx | 82 ++--
.../src/components/login-page/login-form.tsx | 46 ++-
.../src/components/login-page/login-page.tsx | 21 +-
.../model-runner-modal/model-runner-modal.tsx | 350 ++++++++++-------
.../models-page/built-model-item.tsx | 22 +-
.../models-page/built-models-list.tsx | 15 +-
.../src/components/models-page/empty-list.tsx | 19 +-
.../components/models-page/models-page.tsx | 68 ++--
.../src/components/models-page/top-bar.tsx | 34 +-
.../models-page/uploaded-model-item.tsx | 46 ++-
.../models-page/uploaded-models-list.tsx | 24 +-
.../register-page/register-form.tsx | 115 +++---
.../register-page/register-page.tsx | 39 +-
cvat-ui/src/components/task-page/details.tsx | 362 ++++++++++--------
cvat-ui/src/components/task-page/job-list.tsx | 48 ++-
.../src/components/task-page/task-page.tsx | 62 +--
cvat-ui/src/components/task-page/top-bar.tsx | 21 +-
.../components/task-page/user-selector.tsx | 39 +-
.../src/components/tasks-page/empty-list.tsx | 19 +-
.../src/components/tasks-page/task-item.tsx | 171 +++++----
.../src/components/tasks-page/task-list.tsx | 21 +-
.../src/components/tasks-page/tasks-page.tsx | 188 +++++----
cvat-ui/src/components/tasks-page/top-bar.tsx | 41 +-
.../containers/actions-menu/actions-menu.tsx | 44 +--
.../annotation-page/annotation-page.tsx | 10 +-
.../create-model-page/create-model-page.tsx | 12 +-
.../create-task-page/create-task-page.tsx | 12 +-
.../containers/file-manager/file-manager.tsx | 24 +-
cvat-ui/src/containers/header/header.tsx | 18 +-
.../src/containers/login-page/login-page.tsx | 11 +-
.../model-runner-dialog.tsx | 33 +-
.../containers/models-page/models-page.tsx | 31 +-
.../register-page/register-page.tsx | 13 +-
cvat-ui/src/containers/task-page/details.tsx | 28 +-
cvat-ui/src/containers/task-page/job-list.tsx | 18 +-
.../src/containers/task-page/task-page.tsx | 14 +-
.../src/containers/tasks-page/task-item.tsx | 17 +-
.../src/containers/tasks-page/tasks-list.tsx | 21 +-
.../src/containers/tasks-page/tasks-page.tsx | 20 +-
cvat-ui/src/index.tsx | 35 +-
cvat-ui/src/reducers/auth-reducer.ts | 15 +-
cvat-ui/src/reducers/formats-reducer.ts | 2 +-
cvat-ui/src/reducers/interfaces.ts | 4 +-
cvat-ui/src/reducers/models-reducer.ts | 2 +-
cvat-ui/src/reducers/notifications-reducer.ts | 14 +-
cvat-ui/src/reducers/plugins-reducer.ts | 2 +-
cvat-ui/src/reducers/share-reducer.ts | 2 +-
cvat-ui/src/reducers/tasks-reducer.ts | 2 +-
cvat-ui/src/reducers/users-reducer.ts | 2 +-
cvat-ui/src/stylesheet.css | 4 +
76 files changed, 2620 insertions(+), 1896 deletions(-)
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 971c0a063eec..f83561156008 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -3,7 +3,8 @@
"eslint.enable": true,
"eslint.validate": [
"javascript",
- "typescript"
+ "typescript",
+ "typescriptreact",
],
"eslint.workingDirectories": [
{
diff --git a/cvat-ui/.eslintrc.js b/cvat-ui/.eslintrc.js
index 48445ed0d297..f40cac1879fe 100644
--- a/cvat-ui/.eslintrc.js
+++ b/cvat-ui/.eslintrc.js
@@ -19,16 +19,23 @@ module.exports = {
],
'extends': [
'plugin:@typescript-eslint/recommended',
- 'airbnb-typescript/base',
+ 'airbnb-typescript',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
],
'rules': {
'@typescript-eslint/indent': ['warn', 4],
+ 'react/jsx-indent': ['warn', 4],
+ 'react/jsx-indent-props': ['warn', 4],
+ 'react/jsx-props-no-spreading': 0,
+ 'jsx-quotes': ['error', 'prefer-single'],
+ 'arrow-parens': ['error', 'always'],
'@typescript-eslint/no-explicit-any': [0],
'no-restricted-syntax': [0, {'selector': 'ForOfStatement'}],
'no-plusplus': [0],
+ 'lines-between-class-members': 0,
+ 'react/no-did-update-set-state': 0, // https://github.com/airbnb/javascript/issues/1875
},
'settings': {
'import/resolver': {
diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json
index 9422a2bc8456..a10d1935690b 100644
--- a/cvat-ui/package-lock.json
+++ b/cvat-ui/package-lock.json
@@ -899,6 +899,24 @@
}
}
},
+ "@babel/runtime-corejs3": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.7.4.tgz",
+ "integrity": "sha512-BBIEhzk8McXDcB3IbOi8zQPzzINUp4zcLesVlBSOcyGhzPUU8Xezk5GAG7Sy5GVhGmAO0zGd2qRSeY2g4Obqxw==",
+ "dev": true,
+ "requires": {
+ "core-js-pure": "^3.0.0",
+ "regenerator-runtime": "^0.13.2"
+ },
+ "dependencies": {
+ "regenerator-runtime": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
+ "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==",
+ "dev": true
+ }
+ }
+ },
"@babel/template": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz",
@@ -1059,27 +1077,39 @@
}
},
"@typescript-eslint/eslint-plugin": {
- "version": "1.13.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.13.0.tgz",
- "integrity": "sha512-WQHCozMnuNADiqMtsNzp96FNox5sOVpU8Xt4meaT4em8lOG1SrOv92/mUbEHQVh90sldKSfcOc/I0FOb/14G1g==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.10.0.tgz",
+ "integrity": "sha512-rT51fNLW0u3fnDGnAHVC5nu+Das+y2CpW10yqvf6/j5xbuUV3FxA3mBaIbM24CXODXjbgUznNb4Kg9XZOUxKAw==",
"dev": true,
"requires": {
- "@typescript-eslint/experimental-utils": "1.13.0",
- "eslint-utils": "^1.3.1",
+ "@typescript-eslint/experimental-utils": "2.10.0",
+ "eslint-utils": "^1.4.3",
"functional-red-black-tree": "^1.0.1",
- "regexpp": "^2.0.1",
- "tsutils": "^3.7.0"
+ "regexpp": "^3.0.0",
+ "tsutils": "^3.17.1"
}
},
"@typescript-eslint/experimental-utils": {
- "version": "1.13.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz",
- "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.10.0.tgz",
+ "integrity": "sha512-FZhWq6hWWZBP76aZ7bkrfzTMP31CCefVIImrwP3giPLcoXocmLTmr92NLZxuIcTL4GTEOE33jQMWy9PwelL+yQ==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.3",
- "@typescript-eslint/typescript-estree": "1.13.0",
- "eslint-scope": "^4.0.0"
+ "@typescript-eslint/typescript-estree": "2.10.0",
+ "eslint-scope": "^5.0.0"
+ },
+ "dependencies": {
+ "eslint-scope": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
+ "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ }
}
},
"@typescript-eslint/parser": {
@@ -1092,22 +1122,70 @@
"@typescript-eslint/experimental-utils": "1.13.0",
"@typescript-eslint/typescript-estree": "1.13.0",
"eslint-visitor-keys": "^1.0.0"
+ },
+ "dependencies": {
+ "@typescript-eslint/experimental-utils": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz",
+ "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.3",
+ "@typescript-eslint/typescript-estree": "1.13.0",
+ "eslint-scope": "^4.0.0"
+ }
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz",
+ "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==",
+ "dev": true,
+ "requires": {
+ "lodash.unescape": "4.0.1",
+ "semver": "5.5.0"
+ }
+ },
+ "semver": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+ "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+ "dev": true
+ }
}
},
"@typescript-eslint/typescript-estree": {
- "version": "1.13.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz",
- "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.10.0.tgz",
+ "integrity": "sha512-oOYnplddQNm/LGVkqbkAwx4TIBuuZ36cAQq9v3nFIU9FmhemHuVzAesMSXNQDdAzCa5bFgCrfD3JWhYVKlRN2g==",
"dev": true,
"requires": {
+ "debug": "^4.1.1",
+ "eslint-visitor-keys": "^1.1.0",
+ "glob": "^7.1.6",
+ "is-glob": "^4.0.1",
"lodash.unescape": "4.0.1",
- "semver": "5.5.0"
+ "semver": "^6.3.0",
+ "tsutils": "^3.17.1"
},
"dependencies": {
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
"semver": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
- "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
}
}
@@ -1634,12 +1712,30 @@
"dev": true
},
"axobject-query": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
- "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.1.1.tgz",
+ "integrity": "sha512-lF98xa/yvy6j3fBHAgQXIYl+J4eZadOSqsPojemUqClzNbBV38wWGpUbQbVEyf4eUF5yF7eHmGgGA2JiHyjeqw==",
"dev": true,
"requires": {
- "ast-types-flow": "0.0.7"
+ "@babel/runtime": "^7.7.4",
+ "@babel/runtime-corejs3": "^7.7.4"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.4.tgz",
+ "integrity": "sha512-r24eVUUr0QqNZa+qrImUk8fn5SPhHq+IfYvIoIMg0do3GdK9sMdiLKP3GYVVaxpPKORgm8KRKaNTEhAjgIpLMw==",
+ "dev": true,
+ "requires": {
+ "regenerator-runtime": "^0.13.2"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
+ "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==",
+ "dev": true
+ }
}
},
"babel": {
@@ -2580,6 +2676,12 @@
}
}
},
+ "core-js-pure": {
+ "version": "3.4.7",
+ "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.4.7.tgz",
+ "integrity": "sha512-Am3uRS8WCdTFA3lP7LtKR0PxgqYzjAMGKXaZKSNSC/8sqU0Wfq8R/YzoRs2rqtOVEunfgH+0q3O0BKOg0AvjPw==",
+ "dev": true
+ },
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@@ -3484,6 +3586,12 @@
}
}
},
+ "eslint-plugin-eslint-plugin": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-2.1.0.tgz",
+ "integrity": "sha512-kT3A/ZJftt28gbl/Cv04qezb/NQ1dwYIbi8lyf806XMxkus7DvOVCLIfTXMrorp322Pnoez7+zabXH29tADIDg==",
+ "dev": true
+ },
"eslint-plugin-import": {
"version": "2.18.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz",
@@ -3538,20 +3646,21 @@
}
},
"eslint-plugin-react": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.16.0.tgz",
- "integrity": "sha512-GacBAATewhhptbK3/vTP09CbFrgUJmBSaaRcWdbQLFvUZy9yVcQxigBNHGPU/KE2AyHpzj3AWXpxoMTsIDiHug==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.17.0.tgz",
+ "integrity": "sha512-ODB7yg6lxhBVMeiH1c7E95FLD4E/TwmFjltiU+ethv7KPdCwgiFuOZg9zNRHyufStTDLl/dEFqI2Q1VPmCd78A==",
"dev": true,
"requires": {
"array-includes": "^3.0.3",
"doctrine": "^2.1.0",
+ "eslint-plugin-eslint-plugin": "^2.1.0",
"has": "^1.0.3",
- "jsx-ast-utils": "^2.2.1",
+ "jsx-ast-utils": "^2.2.3",
"object.entries": "^1.1.0",
- "object.fromentries": "^2.0.0",
+ "object.fromentries": "^2.0.1",
"object.values": "^1.1.0",
"prop-types": "^15.7.2",
- "resolve": "^1.12.0"
+ "resolve": "^1.13.1"
},
"dependencies": {
"doctrine": {
@@ -3562,9 +3671,24 @@
"requires": {
"esutils": "^2.0.2"
}
+ },
+ "resolve": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz",
+ "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
}
}
},
+ "eslint-plugin-react-hooks": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.7.0.tgz",
+ "integrity": "sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA==",
+ "dev": true
+ },
"eslint-scope": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
@@ -8141,9 +8265,9 @@
}
},
"regexpp": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
- "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz",
+ "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==",
"dev": true
},
"regexpu-core": {
@@ -9444,9 +9568,9 @@
"dev": true
},
"typescript": {
- "version": "3.6.4",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.4.tgz",
- "integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==",
+ "version": "3.7.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz",
+ "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==",
"dev": true
},
"ua-parser-js": {
diff --git a/cvat-ui/package.json b/cvat-ui/package.json
index 50d78f82c35b..59b3196f2529 100644
--- a/cvat-ui/package.json
+++ b/cvat-ui/package.json
@@ -14,7 +14,7 @@
"@babel/preset-env": "^7.6.0",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.6.0",
- "@typescript-eslint/eslint-plugin": "^1.13.0",
+ "@typescript-eslint/eslint-plugin": "^2.10.0",
"babel": "^6.23.0",
"babel-loader": "^8.0.6",
"babel-plugin-import": "^1.12.2",
@@ -22,11 +22,12 @@
"eslint-config-airbnb-typescript": "^4.0.1",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jsx-a11y": "^6.2.3",
- "eslint-plugin-react": "^7.14.3",
+ "eslint-plugin-react": "^7.17.0",
+ "eslint-plugin-react-hooks": "^1.7.0",
"html-webpack-plugin": "^3.2.0",
"nodemon": "^1.19.2",
"style-loader": "^1.0.0",
- "typescript": "^3.6.3",
+ "typescript": "^3.7.3",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.8",
"webpack-dev-server": "^3.8.0"
diff --git a/cvat-ui/src/actions/models-actions.ts b/cvat-ui/src/actions/models-actions.ts
index 50fc54a9ad8c..e8b60da56096 100644
--- a/cvat-ui/src/actions/models-actions.ts
+++ b/cvat-ui/src/actions/models-actions.ts
@@ -431,7 +431,7 @@ async function timeoutCallback(
dispatch(getInferenceStatusSuccess(taskID, activeInference));
} catch (error) {
dispatch(getInferenceStatusFailed(taskID, new Error(
- `Server request for the task ${taskID} was failed`
+ `Server request for the task ${taskID} was failed`,
)));
}
}
diff --git a/cvat-ui/src/components/actions-menu/actions-menu.tsx b/cvat-ui/src/components/actions-menu/actions-menu.tsx
index f6057cb8574b..a9be862bba44 100644
--- a/cvat-ui/src/components/actions-menu/actions-menu.tsx
+++ b/cvat-ui/src/components/actions-menu/actions-menu.tsx
@@ -36,14 +36,16 @@ interface MinActionsMenuProps {
onOpenRunWindow: (taskInstance: any) => void;
}
-export function handleMenuClick(props: MinActionsMenuProps, params: ClickParam) {
+export function handleMenuClick(props: MinActionsMenuProps, params: ClickParam): void {
const { taskInstance } = props;
const tracker = taskInstance.bugTracker;
if (params.keyPath.length !== 2) {
switch (params.key) {
case 'tracker': {
- window.open(`${tracker}`, '_blank')
+ // false positive eslint(security/detect-non-literal-fs-filename)
+ // eslint-disable-next-line
+ window.open(`${tracker}`, '_blank');
return;
} case 'auto_annotation': {
props.onOpenRunWindow(taskInstance);
@@ -57,36 +59,51 @@ export function handleMenuClick(props: MinActionsMenuProps, params: ClickParam)
props.onDeleteTask(taskInstance);
},
});
- return;
+ break;
} default: {
- return;
+ // do nothing
}
}
}
}
-export default function ActionsMenuComponent(props: ActionsMenuComponentProps) {
- const tracker = props.taskInstance.bugTracker;
- const renderModelRunner = props.installedAutoAnnotation ||
- props.installedTFAnnotation || props.installedTFSegmentation;
+export default function ActionsMenuComponent(props: ActionsMenuComponentProps): JSX.Element {
+ const {
+ taskInstance,
+ installedAutoAnnotation,
+ installedTFAnnotation,
+ installedTFSegmentation,
+ dumpers,
+ loaders,
+ exporters,
+ inferenceIsActive,
+ } = props;
+ const tracker = taskInstance.bugTracker;
+ const renderModelRunner = installedAutoAnnotation
+ || installedTFAnnotation || installedTFSegmentation;
return (
-
- }>
-
+ )}
+ >
+
diff --git a/cvat-ui/src/components/models-page/uploaded-models-list.tsx b/cvat-ui/src/components/models-page/uploaded-models-list.tsx
index 6cc6a1391fb9..233359293abc 100644
--- a/cvat-ui/src/components/models-page/uploaded-models-list.tsx
+++ b/cvat-ui/src/components/models-page/uploaded-models-list.tsx
@@ -16,15 +16,21 @@ interface Props {
deleteModel(id: number): void;
}
-export default function UploadedModelsListComponent(props: Props) {
- const items = props.models.map((model) => {
- const owner = props.registeredUsers.filter((user) => user.id === model.ownerID)[0];
+export default function UploadedModelsListComponent(props: Props): JSX.Element {
+ const {
+ models,
+ registeredUsers,
+ deleteModel,
+ } = props;
+
+ const items = models.map((model): JSX.Element => {
+ const owner = registeredUsers.filter((user) => user.id === model.ownerID)[0];
return (
props.deleteModel(model.id as number)}
+ onDelete={(): void => deleteModel(model.id as number)}
/>
);
});
@@ -33,17 +39,17 @@ export default function UploadedModelsListComponent(props: Props) {
<>
- {'Uploaded by a user'}
+ Uploaded by a user
-
+
- {'Framework'}
+ Framework
- {'Name'}
+ Name
Owner
@@ -54,7 +60,7 @@ export default function UploadedModelsListComponent(props: Props) {
Labels
-
+
{ items }
diff --git a/cvat-ui/src/components/register-page/register-form.tsx b/cvat-ui/src/components/register-page/register-form.tsx
index 2122aec4b962..8683b3ce670a 100644
--- a/cvat-ui/src/components/register-page/register-form.tsx
+++ b/cvat-ui/src/components/register-page/register-form.tsx
@@ -7,6 +7,8 @@ import {
Form,
} from 'antd';
+import patterns from '../../utils/validation-patterns';
+
export interface RegisterData {
username: string;
firstName: string;
@@ -16,28 +18,22 @@ export interface RegisterData {
password2: string;
}
-import patterns from '../../utils/validation-patterns';
-
type RegisterFormProps = {
fetching: boolean;
onSubmit(registerData: RegisterData): void;
} & FormComponentProps;
class RegisterFormComponent extends React.PureComponent {
- constructor(props: RegisterFormProps) {
- super(props);
- }
-
- private validateConfirmation = (rule: any, value: any, callback: any) => {
+ private validateConfirmation = (rule: any, value: any, callback: any): void => {
const { form } = this.props;
if (value && value !== form.getFieldValue('password1')) {
- callback('Two passwords that you enter is inconsistent!');
+ callback('Two passwords that you enter is inconsistent!');
} else {
- callback();
+ callback();
}
- };
+ };
- private validatePassword = (_: any, value: any, callback: any) => {
+ private validatePassword = (_: any, value: any, callback: any): void => {
const { form } = this.props;
if (!patterns.validatePasswordLength.pattern.test(value)) {
callback(patterns.validatePasswordLength.message);
@@ -56,12 +52,12 @@ class RegisterFormComponent extends React.PureComponent {
}
if (value) {
- form.validateFields(['password2'], { force: true });
+ form.validateFields(['password2'], { force: true });
}
callback();
};
- private validateUsername = (_: any, value: any, callback: any) => {
+ private validateUsername = (_: any, value: any, callback: any): void => {
if (!patterns.validateUsernameLength.pattern.test(value)) {
callback(patterns.validateUsernameLength.message);
}
@@ -73,19 +69,26 @@ class RegisterFormComponent extends React.PureComponent {
callback();
};
- private handleSubmit = (e: React.FormEvent) => {
+ private handleSubmit = (e: React.FormEvent): void => {
e.preventDefault();
- this.props.form.validateFields((error, values) => {
+ const {
+ form,
+ onSubmit,
+ } = this.props;
+
+ form.validateFields((error, values): void => {
if (!error) {
- this.props.onSubmit(values);
+ onSubmit(values);
}
});
- }
+ };
+
+ private renderFirstNameField(): JSX.Element {
+ const { form } = this.props;
- private renderFirstNameField() {
return (
- {this.props.form.getFieldDecorator('firstName', {
+ {form.getFieldDecorator('firstName', {
rules: [{
required: true,
message: 'Please specify a first name',
@@ -93,18 +96,20 @@ class RegisterFormComponent extends React.PureComponent {
}],
})(
}
+ prefix={}
placeholder='First name'
- />
+ />,
)}
- )
+ );
}
- private renderLastNameField() {
+ private renderLastNameField(): JSX.Element {
+ const { form } = this.props;
+
return (
- {this.props.form.getFieldDecorator('lastName', {
+ {form.getFieldDecorator('lastName', {
rules: [{
required: true,
message: 'Please specify a last name',
@@ -112,18 +117,20 @@ class RegisterFormComponent extends React.PureComponent {
}],
})(
}
+ prefix={}
placeholder='Last name'
- />
+ />,
)}
- )
+ );
}
- private renderUsernameField() {
+ private renderUsernameField(): JSX.Element {
+ const { form } = this.props;
+
return (
- {this.props.form.getFieldDecorator('username', {
+ {form.getFieldDecorator('username', {
rules: [{
required: true,
message: 'Please specify a username',
@@ -132,40 +139,44 @@ class RegisterFormComponent extends React.PureComponent {
}],
})(
}
+ prefix={}
placeholder='Username'
- />
+ />,
)}
- )
+ );
}
- private renderEmailField() {
+ private renderEmailField(): JSX.Element {
+ const { form } = this.props;
+
return (
- {this.props.form.getFieldDecorator('email', {
+ {form.getFieldDecorator('email', {
rules: [{
type: 'email',
message: 'The input is not valid E-mail!',
- }, {
+ }, {
required: true,
message: 'Please specify an email address',
}],
})(
}
+ prefix={}
placeholder='Email address'
- />
+ />,
)}
- )
+ );
}
- private renderPasswordField() {
+ private renderPasswordField(): JSX.Element {
+ const { form } = this.props;
+
return (
- {this.props.form.getFieldDecorator('password1', {
+ {form.getFieldDecorator('password1', {
rules: [{
required: true,
message: 'Please input your password!',
@@ -174,17 +185,19 @@ class RegisterFormComponent extends React.PureComponent {
}],
})(}
+ prefix={}
placeholder='Password'
/>)}
- )
+ );
}
- private renderPasswordConfirmationField() {
+ private renderPasswordConfirmationField(): JSX.Element {
+ const { form } = this.props;
+
return (
- {this.props.form.getFieldDecorator('password2', {
+ {form.getFieldDecorator('password2', {
rules: [{
required: true,
message: 'Please confirm your password!',
@@ -193,16 +206,16 @@ class RegisterFormComponent extends React.PureComponent {
}],
})(}
+ prefix={}
placeholder='Confirm password'
/>)}
- )
+ );
}
+ public render(): JSX.Element {
+ const { fetching } = this.props;
-
- public render() {
return (
{this.renderFirstNameField()}
@@ -217,8 +230,8 @@ class RegisterFormComponent extends React.PureComponent {
type='primary'
htmlType='submit'
className='register-form-button'
- loading={this.props.fetching}
- disabled={this.props.fetching}
+ loading={fetching}
+ disabled={fetching}
>
Submit
@@ -228,4 +241,4 @@ class RegisterFormComponent extends React.PureComponent {
}
}
-export default Form.create()(RegisterFormComponent);
\ No newline at end of file
+export default Form.create()(RegisterFormComponent);
diff --git a/cvat-ui/src/components/register-page/register-page.tsx b/cvat-ui/src/components/register-page/register-page.tsx
index 5fd4025e63ad..ea82f7995d36 100644
--- a/cvat-ui/src/components/register-page/register-page.tsx
+++ b/cvat-ui/src/components/register-page/register-page.tsx
@@ -10,7 +10,7 @@ import {
Row,
} from 'antd';
-import RegisterForm, { RegisterData } from '../../components/register-page/register-form';
+import RegisterForm, { RegisterData } from './register-form';
interface RegisterPageComponentProps {
fetching: boolean;
@@ -19,33 +19,44 @@ interface RegisterPageComponentProps {
password1: string, password2: string) => void;
}
-function RegisterPageComponent(props: RegisterPageComponentProps & RouteComponentProps) {
+function RegisterPageComponent(
+ props: RegisterPageComponentProps & RouteComponentProps,
+): JSX.Element {
const sizes = {
xs: { span: 14 },
sm: { span: 14 },
md: { span: 10 },
lg: { span: 4 },
xl: { span: 4 },
- }
+ };
+
+ const {
+ fetching,
+ onRegister,
+ } = props;
return (
Create an account
- {
- props.onRegister(
- registerData.username,
- registerData.firstName,
- registerData.lastName,
- registerData.email,
- registerData.password1,
- registerData.password2,
- );
- }}/>
+ {
+ onRegister(
+ registerData.username,
+ registerData.firstName,
+ registerData.lastName,
+ registerData.email,
+ registerData.password1,
+ registerData.password2,
+ );
+ }}
+ />
- Already have an account? Login
+ Already have an account?
+ Login
diff --git a/cvat-ui/src/components/task-page/details.tsx b/cvat-ui/src/components/task-page/details.tsx
index 355f2e279df9..52425be8c7ce 100644
--- a/cvat-ui/src/components/task-page/details.tsx
+++ b/cvat-ui/src/components/task-page/details.tsx
@@ -55,36 +55,91 @@ export default class DetailsComponent extends React.PureComponent
};
}
- private renderTaskName() {
+ public componentDidMount(): void {
const { taskInstance } = this.props;
+ this.mounted = true;
+
+ getReposData(taskInstance.id)
+ .then((data): void => {
+ if (data !== null && this.mounted) {
+ if (data.status.error) {
+ notification.error({
+ message: 'Could not receive repository status',
+ description: data.status.error,
+ });
+ } else {
+ this.setState({
+ repositoryStatus: data.status.value,
+ });
+ }
+
+ this.setState({
+ repository: data.url,
+ });
+ }
+ }).catch((error): void => {
+ if (this.mounted) {
+ notification.error({
+ message: 'Could not receive repository status',
+ description: error.toString(),
+ });
+ }
+ });
+ }
+
+
+ public componentDidUpdate(prevProps: Props): void {
+ const { taskInstance } = this.props;
+
+ if (prevProps !== this.props) {
+ this.setState({
+ name: taskInstance.name,
+ bugTracker: taskInstance.bugTracker,
+ });
+ }
+ }
+
+ public componentWillUnmount(): void {
+ this.mounted = false;
+ }
+
+ private renderTaskName(): JSX.Element {
const { name } = this.state;
+ const {
+ taskInstance,
+ onTaskUpdate,
+ } = this.props;
+
return (
{
+ onChange: (value: string): void => {
this.setState({
name: value,
});
taskInstance.name = value;
- this.props.onTaskUpdate(taskInstance);
+ onTaskUpdate(taskInstance);
},
}}
className='cvat-black-color'
- >{name}
+ >
+ {name}
+
);
}
- private renderPreview() {
+ private renderPreview(): JSX.Element {
+ const { previewImage } = this.props;
return (
-
+
);
}
- private renderParameters() {
+ private renderParameters(): JSX.Element {
const { taskInstance } = this.props;
const { overlap } = taskInstance;
const { segmentSize } = taskInstance;
@@ -95,25 +150,25 @@ export default class DetailsComponent extends React.PureComponent
<>
- {'Overlap size'}
-
+ Overlap size
+
{overlap}
- {'Segment size'}
-
+ Segment size
+
{segmentSize}
- {'Image quality'}
-
+ Image quality
+
{imageQuality}
- {'Z-order'}
-
+ Z-order
+
{zOrder}
@@ -121,39 +176,47 @@ export default class DetailsComponent extends React.PureComponent
);
}
- private renderUsers() {
- const { taskInstance } = this.props;
+ private renderUsers(): JSX.Element {
+ const {
+ taskInstance,
+ registeredUsers,
+ onTaskUpdate,
+ } = this.props;
const owner = taskInstance.owner ? taskInstance.owner.username : null;
const assignee = taskInstance.assignee ? taskInstance.assignee.username : null;
const created = moment(taskInstance.createdDate).format('MMMM Do YYYY');
- const assigneeSelect = {
- let [userInstance] = this.props.registeredUsers
- .filter((user: any) => user.username === value);
-
- if (userInstance === undefined) {
- userInstance = null;
- }
+ const assigneeSelect = (
+ {
+ let [userInstance] = registeredUsers
+ .filter((user: any) => user.username === value);
+
+ if (userInstance === undefined) {
+ userInstance = null;
+ }
- taskInstance.assignee = userInstance;
- this.props.onTaskUpdate(taskInstance);
+ taskInstance.assignee = userInstance;
+ onTaskUpdate(taskInstance);
+ }
}
- }
- />
+ />
+ );
return (
- { owner ?
- Created by {owner} on {created}
- : null }
+ { owner && (
+
+ {`Created by ${owner} on ${created}`}
+
+ )}
- {'Assigned to'}
+ Assigned to
{ assigneeSelect }
@@ -161,57 +224,89 @@ export default class DetailsComponent extends React.PureComponent
);
}
- private renderDatasetRepository() {
- const { repository } = this.state;
- const { repositoryStatus } = this.state;
+ private renderDatasetRepository(): JSX.Element | boolean {
+ const { taskInstance } = this.props;
+ const {
+ repository,
+ repositoryStatus,
+ } = this.state;
return (
- repository ?
-
-
- {'Dataset Repository'}
-
- {repository}
- {repositoryStatus === 'sync' ?
-
- Synchronized
- : repositoryStatus === 'merged' ?
-
- Merged
- : repositoryStatus === 'syncing' ?
-
- Syncing :
- {
- this.setState({
- repositoryStatus: 'syncing',
- });
-
- syncRepos(this.props.taskInstance.id).then(() => {
- if (this.mounted) {
- this.setState({
- repositoryStatus: 'sync',
- });
- }
- }).catch(() => {
- if (this.mounted) {
- this.setState({
- repositoryStatus: '!sync',
- });
- }
- });
- }}> Synchronize
- }
-
-
: null
+ !!repository
+ && (
+
+
+ Dataset Repository
+
+ {repository}
+ {repositoryStatus === 'sync'
+ && (
+
+
+ Synchronized
+
+ )
+ }
+ {repositoryStatus === 'merged'
+ && (
+
+
+ Merged
+
+ )
+ }
+ {repositoryStatus === 'syncing'
+ && (
+
+
+ Syncing
+
+ )
+ }
+ {repositoryStatus === '!sync'
+ && (
+ {
+ this.setState({
+ repositoryStatus: 'syncing',
+ });
+
+ syncRepos(taskInstance.id).then((): void => {
+ if (this.mounted) {
+ this.setState({
+ repositoryStatus: 'sync',
+ });
+ }
+ }).catch((): void => {
+ if (this.mounted) {
+ this.setState({
+ repositoryStatus: '!sync',
+ });
+ }
+ });
+ }}
+ >
+
+ Synchronize
+
+ )
+ }
+
+
+ )
);
}
- private renderBugTracker() {
- const { taskInstance } = this.props;
+ private renderBugTracker(): JSX.Element {
+ const {
+ taskInstance,
+ onTaskUpdate,
+ } = this.props;
const { bugTracker } = this.state;
let shown = false;
- const onChangeValue = (value: string) => {
+ const onChangeValue = (value: string): void => {
if (value && !patterns.validateURL.pattern.test(value)) {
if (!shown) {
Modal.error({
@@ -229,52 +324,62 @@ export default class DetailsComponent extends React.PureComponent
});
taskInstance.bugTracker = value;
- this.props.onTaskUpdate(taskInstance);
+ onTaskUpdate(taskInstance);
}
- }
+ };
if (bugTracker) {
return (
- {'Issue Tracker'}
-
- {bugTracker}
-
-
-
- );
- } else {
- return (
-
-
- {'Issue Tracker'}
-
- {'Not specified'}
+ Issue Tracker
+
+ {bugTracker}
+
);
}
+
+ return (
+
+
+ Issue Tracker
+
+ Not specified
+
+
+ );
}
- private renderLabelsEditor() {
- const { taskInstance } = this.props;
+ private renderLabelsEditor(): JSX.Element {
+ const {
+ taskInstance,
+ onTaskUpdate,
+ } = this.props;
return (
label.toJSON()
+ (label: any): string => label.toJSON(),
)}
- onSubmit={(labels: any[]) => {
- taskInstance.labels = labels.map((labelData) => {
- return new core.classes.Label(labelData);
- });
-
- this.props.onTaskUpdate(taskInstance);
+ onSubmit={(labels: any[]): void => {
+ taskInstance.labels = labels
+ .map((labelData): any => new core.classes.Label(labelData));
+ onTaskUpdate(taskInstance);
}}
/>
@@ -282,50 +387,7 @@ export default class DetailsComponent extends React.PureComponent
);
}
- public componentDidMount() {
- this.mounted = true;
- getReposData(this.props.taskInstance.id)
- .then((data) => {
- if (data !== null && this.mounted) {
- if (data.status.error) {
- notification.error({
- message: 'Could not receive repository status',
- description: data.status.error
- });
- } else {
- this.setState({
- repositoryStatus: data.status.value,
- });
- }
-
- this.setState({
- repository: data.url,
- });
- }
- }).catch((error) => {
- if (this.mounted) {
- notification.error({
- message: 'Could not receive repository status',
- description: error.toString(),
- });
- }
- });
- }
-
- public componentWillUnmount() {
- this.mounted = false;
- }
-
- public componentDidUpdate(prevProps: Props) {
- if (prevProps !== this.props) {
- this.setState({
- name: this.props.taskInstance.name,
- bugTracker: this.props.taskInstance.bugTracker,
- });
- }
- }
-
- public render() {
+ public render(): JSX.Element {
return (
diff --git a/cvat-ui/src/components/task-page/job-list.tsx b/cvat-ui/src/components/task-page/job-list.tsx
index 3f8319fa2a92..ad13707d2462 100644
--- a/cvat-ui/src/components/task-page/job-list.tsx
+++ b/cvat-ui/src/components/task-page/job-list.tsx
@@ -24,17 +24,19 @@ interface Props {
onJobUpdate(jobInstance: any): void;
}
-export default function JobListComponent(props: Props) {
- const { jobs } = props.taskInstance;
+export default function JobListComponent(props: Props): JSX.Element {
+ const {
+ taskInstance,
+ registeredUsers,
+ onJobUpdate,
+ } = props;
+
+ const { jobs } = taskInstance;
const columns = [{
title: 'Job',
dataIndex: 'job',
key: 'job',
- render: (id: number) => {
- return (
- { `Job #${id++}` }
- );
- }
+ render: (id: number): JSX.Element => ({ `Job #${id}` }),
}, {
title: 'Frames',
dataIndex: 'frames',
@@ -44,14 +46,20 @@ export default function JobListComponent(props: Props) {
title: 'Status',
dataIndex: 'status',
key: 'status',
- render: (status: string) => {
- const progressColor = status === 'completed' ? 'cvat-job-completed-color':
- status === 'validation' ? 'cvat-job-validation-color' : 'cvat-job-annotation-color';
+ render: (status: string): JSX.Element => {
+ let progressColor = null;
+ if (status === 'completed') {
+ progressColor = 'cvat-job-completed-color';
+ } else if (status === 'validation') {
+ progressColor = 'cvat-job-validation-color';
+ } else {
+ progressColor = 'cvat-job-annotation-color';
+ }
return (
{ status }
);
- }
+ },
}, {
title: 'Started on',
dataIndex: 'started',
@@ -66,22 +74,24 @@ export default function JobListComponent(props: Props) {
title: 'Assignee',
dataIndex: 'assignee',
key: 'assignee',
- render: (jobInstance: any) => {
- const assignee = jobInstance.assignee ? jobInstance.assignee.username : null
+ render: (jobInstance: any): JSX.Element => {
+ const assignee = jobInstance.assignee ? jobInstance.assignee.username : null;
+
return (
{
- let [userInstance] = props.registeredUsers
- .filter((user: any) => user.username === value);
+ onChange={(value: string): void => {
+ let [userInstance] = [...registeredUsers]
+ .filter((user: any) => user.username === value);
if (userInstance === undefined) {
userInstance = null;
}
+ // eslint-disable-next-line
jobInstance.assignee = userInstance;
- props.onJobUpdate(jobInstance);
+ onJobUpdate(jobInstance);
}}
/>
);
@@ -129,4 +139,4 @@ export default function JobListComponent(props: Props) {
/>
);
-}
\ No newline at end of file
+}
diff --git a/cvat-ui/src/components/task-page/task-page.tsx b/cvat-ui/src/components/task-page/task-page.tsx
index 615788996d82..81eda43f1a09 100644
--- a/cvat-ui/src/components/task-page/task-page.tsx
+++ b/cvat-ui/src/components/task-page/task-page.tsx
@@ -25,52 +25,64 @@ interface TaskPageComponentProps {
type Props = TaskPageComponentProps & RouteComponentProps<{id: string}>;
class TaskPageComponent extends React.PureComponent {
- private attempts: number = 0;
+ private attempts = 0;
- public componentDidUpdate() {
- if (this.props.deleteActivity) {
- this.props.history.replace('/tasks');
+ public componentDidUpdate(): void {
+ const {
+ deleteActivity,
+ history,
+ } = this.props;
+
+ if (deleteActivity) {
+ history.replace('/tasks');
}
- if (this.attempts == 2) {
+ if (this.attempts === 2) {
notification.warning({
message: 'Something wrong with the task. It cannot be fetched from the server',
});
}
}
- public render() {
- const { id } = this.props.match.params;
- const fetchTask = !this.props.task;
+ public render(): JSX.Element {
+ const {
+ match,
+ task,
+ fetching,
+ onFetchTask,
+ } = this.props;
+ const { id } = match.params;
+ const fetchTask = !task;
if (fetchTask) {
- if (!this.props.fetching) {
+ if (!fetching) {
if (!this.attempts) {
- this.attempts ++;
- this.props.onFetchTask(+id);
+ this.attempts++;
+ onFetchTask(+id);
} else {
- this.attempts ++;
+ this.attempts++;
}
}
return (
-
+
);
- } else if (typeof(this.props.task) === 'undefined') {
+ }
+
+ if (typeof (task) === 'undefined') {
return (
- )
- } else {
- const task = this.props.task as Task;
- return (
-
-
-
-
-
-
-
);
}
+
+ return (
+
+
+
+
+
+
+
+ );
}
}
diff --git a/cvat-ui/src/components/task-page/top-bar.tsx b/cvat-ui/src/components/task-page/top-bar.tsx
index 3cbd31393048..8c368771f764 100644
--- a/cvat-ui/src/components/task-page/top-bar.tsx
+++ b/cvat-ui/src/components/task-page/top-bar.tsx
@@ -16,10 +16,11 @@ interface DetailsComponentProps {
taskInstance: any;
}
-export default function DetailsComponent(props: DetailsComponentProps) {
- const subMenuIcon = () => ();
+export default function DetailsComponent(props: DetailsComponentProps): JSX.Element {
+ const subMenuIcon = (): JSX.Element => ();
- const { id } = props.taskInstance;
+ const { taskInstance } = props;
+ const { id } = taskInstance;
return (
@@ -28,16 +29,18 @@ export default function DetailsComponent(props: DetailsComponentProps) {
- }>
+ (
+
+ )}
+ >
);
-}
\ No newline at end of file
+}
diff --git a/cvat-ui/src/components/task-page/user-selector.tsx b/cvat-ui/src/components/task-page/user-selector.tsx
index b02870faeca3..b58b85a90c41 100644
--- a/cvat-ui/src/components/task-page/user-selector.tsx
+++ b/cvat-ui/src/components/task-page/user-selector.tsx
@@ -1,7 +1,6 @@
import React from 'react';
import {
- Icon,
Select,
} from 'antd';
@@ -11,23 +10,27 @@ interface Props {
onChange: (user: string) => void;
}
-export default function UserSelector(props: Props) {
+export default function UserSelector(props: Props): JSX.Element {
+ const {
+ value,
+ users,
+ onChange,
+ } = props;
+
return (
+ defaultValue={value || '—'}
+ size='small'
+ showSearch
+ className='cvat-user-selector'
+ onChange={onChange}
+ >
+ —
+ { users.map((user): JSX.Element => (
+
+ {user.username}
+
+ ))}
+
);
-}
\ No newline at end of file
+}
diff --git a/cvat-ui/src/components/tasks-page/empty-list.tsx b/cvat-ui/src/components/tasks-page/empty-list.tsx
index 8b631631142a..bbc89e00fdd0 100644
--- a/cvat-ui/src/components/tasks-page/empty-list.tsx
+++ b/cvat-ui/src/components/tasks-page/empty-list.tsx
@@ -8,32 +8,31 @@ import {
Icon,
} from 'antd';
-export default function EmptyListComponent() {
- const emptyTasksIcon = () => ();
+export default function EmptyListComponent(): JSX.Element {
+ const emptyTasksIcon = (): JSX.Element => ();
return (
-
+
- {'No tasks created yet ...'}
+ No tasks created yet ...
- {'To get started with your annotation project'}
+ To get started with your annotation project
-
+
- {'create a new task'}
+ create a new task
-
- )
-}
\ No newline at end of file
+ );
+}
diff --git a/cvat-ui/src/components/tasks-page/task-item.tsx b/cvat-ui/src/components/tasks-page/task-item.tsx
index 02dd8ba5a219..c7322cf59058 100644
--- a/cvat-ui/src/components/tasks-page/task-item.tsx
+++ b/cvat-ui/src/components/tasks-page/task-item.tsx
@@ -25,71 +25,80 @@ export interface TaskItemProps {
}
class TaskItemComponent extends React.PureComponent {
- constructor(props: TaskItemProps & RouteComponentProps) {
- super(props);
- }
-
- private renderPreview() {
+ private renderPreview(): JSX.Element {
+ const { previewImage } = this.props;
return (
-
+
- )
+ );
}
- private renderDescription() {
+ private renderDescription(): JSX.Element {
// Task info
- const task = this.props.taskInstance;
- const { id } = task;
- const owner = task.owner ? task.owner.username : null;
- const updated = moment(task.updatedDate).fromNow();
- const created = moment(task.createdDate).format('MMMM Do YYYY');
+ const { taskInstance } = this.props;
+ const { id } = taskInstance;
+ const owner = taskInstance.owner ? taskInstance.owner.username : null;
+ const updated = moment(taskInstance.updatedDate).fromNow();
+ const created = moment(taskInstance.createdDate).format('MMMM Do YYYY');
// Get and truncate a task name
- const name = `${task.name.substring(0, 70)}${task.name.length > 70 ? '...' : ''}`;
+ const name = `${taskInstance.name.substring(0, 70)}${taskInstance.name.length > 70 ? '...' : ''}`;
return (
- {`${id} ${name}`}
- { owner ?
- <>
-
- Created { owner ? 'by ' + owner : '' } on {created}
-
- > : null
+ {`${id} ${name}`}
+
+ { owner
+ && (
+ <>
+
+ {`Created ${owner ? `by ${owner}` : ''} on ${created}`}
+
+
+ >
+ )
}
{`Last updated ${updated}`}
- )
+ );
}
- private renderProgress() {
- const task = this.props.taskInstance;
+ private renderProgress(): JSX.Element {
+ const {
+ taskInstance,
+ activeInference,
+ } = this.props;
// Count number of jobs and performed jobs
- const numOfJobs = task.jobs.length;
- const numOfCompleted = task.jobs.filter(
- (job: any) => job.status === 'completed'
+ const numOfJobs = taskInstance.jobs.length;
+ const numOfCompleted = taskInstance.jobs.filter(
+ (job: any): boolean => job.status === 'completed',
).length;
// Progress appearence depends on number of jobs
- const progressColor = numOfCompleted === numOfJobs ? 'cvat-task-completed-progress':
- numOfCompleted ? 'cvat-task-progress-progress' : 'cvat-task-pending-progress';
+ let progressColor = null;
+ let progressText = null;
+ if (numOfCompleted === numOfJobs) {
+ progressColor = 'cvat-task-completed-progress';
+ progressText = Completed;
+ } else if (numOfCompleted) {
+ progressColor = 'cvat-task-progress-progress';
+ progressText = In Progress;
+ } else {
+ progressColor = 'cvat-task-pending-progress';
+ progressText = Pending;
+ }
return (
- { numOfCompleted === numOfJobs ?
- {'Completed'}
- : numOfCompleted ?
- {'In Progress'}
- : {'Pending'}
- }
+ { progressText }
{`${numOfCompleted} of ${numOfJobs} jobs`}
@@ -107,78 +116,86 @@ class TaskItemComponent extends React.PureComponent
- { this.props.activeInference ?
- <>
-
-
- Automatic annotation
-
-
-
-
-
-
-
- > : null
+ { activeInference
+ && (
+ <>
+
+
+ Automatic annotation
+
+
+
+
+
+
+
+ >
+ )
}
- )
+ );
}
- private renderNavigation() {
- const subMenuIcon = () => ();
- const { id } = this.props.taskInstance;
+ private renderNavigation(): JSX.Element {
+ const subMenuIcon = (): JSX.Element => ();
+ const {
+ taskInstance,
+ history,
+ } = this.props;
+ const { id } = taskInstance;
return (
-
+
Actions
-
- }>
-
+ }>
+
- )
+ );
}
- public render() {
+ public render(): JSX.Element {
+ const { deleted } = this.props;
const style = {};
- if (this.props.deleted) {
+ if (deleted) {
(style as any).pointerEvents = 'none';
(style as any).opacity = 0.5;
}
return (
-
+
{this.renderPreview()}
{this.renderDescription()}
{this.renderProgress()}
{this.renderNavigation()}
- )
- };
+ );
+ }
}
export default withRouter(TaskItemComponent);
diff --git a/cvat-ui/src/components/tasks-page/task-list.tsx b/cvat-ui/src/components/tasks-page/task-list.tsx
index bfce6f0796c3..ce8381096004 100644
--- a/cvat-ui/src/components/tasks-page/task-list.tsx
+++ b/cvat-ui/src/components/tasks-page/task-list.tsx
@@ -15,10 +15,15 @@ export interface ContentListProps {
numberOfTasks: number;
}
-export default function TaskListComponent(props: ContentListProps) {
- const tasks = props.currentTasksIndexes;
- const taskViews = tasks.map(
- (tid, id) =>
+export default function TaskListComponent(props: ContentListProps): JSX.Element {
+ const {
+ currentTasksIndexes,
+ numberOfTasks,
+ currentPage,
+ onSwitchPage,
+ } = props;
+ const taskViews = currentTasksIndexes.map(
+ (tid, id): JSX.Element => ,
);
return (
@@ -32,14 +37,14 @@ export default function TaskListComponent(props: ContentListProps) {
>
- )
+ );
}
diff --git a/cvat-ui/src/components/tasks-page/tasks-page.tsx b/cvat-ui/src/components/tasks-page/tasks-page.tsx
index 2b8da555cc01..a0ebf786abbd 100644
--- a/cvat-ui/src/components/tasks-page/tasks-page.tsx
+++ b/cvat-ui/src/components/tasks-page/tasks-page.tsx
@@ -22,135 +22,155 @@ interface TasksPageProps {
onGetTasks: (gettingQuery: TasksQuery) => void;
}
-class TasksPageComponent extends React.PureComponent {
- constructor(props: any) {
- super(props);
- }
+function getSearchField(gettingQuery: TasksQuery): string {
+ let searchString = '';
+ for (const field of Object.keys(gettingQuery)) {
+ if (gettingQuery[field] !== null && field !== 'page') {
+ if (field === 'search') {
+ return (gettingQuery[field] as any) as string;
+ }
- private updateURL(gettingQuery: TasksQuery) {
- let queryString = '?';
- for (const field of Object.keys(gettingQuery)) {
- if (gettingQuery[field] !== null) {
- queryString += `${field}=${gettingQuery[field]}&`;
+ // not constant condition
+ // eslint-disable-next-line
+ if (typeof (gettingQuery[field] === 'number')) {
+ searchString += `${field}:${gettingQuery[field]} AND `;
+ } else {
+ searchString += `${field}:"${gettingQuery[field]}" AND `;
}
}
- this.props.history.replace({
- search: queryString.slice(0, -1),
- });
}
- private getSearchField(gettingQuery: TasksQuery): string {
- let searchString = '';
- for (const field of Object.keys(gettingQuery)) {
- if (gettingQuery[field] !== null && field !== 'page') {
- if (field === 'search') {
- return (gettingQuery[field] as any) as string;
- } else {
- if (typeof (gettingQuery[field] === 'number')) {
- searchString += `${field}:${gettingQuery[field]} AND `;
+ return searchString.slice(0, -5);
+}
+
+class TasksPageComponent extends React.PureComponent {
+ public componentDidMount(): void {
+ const {
+ gettingQuery,
+ location,
+ onGetTasks,
+ } = this.props;
+ const params = new URLSearchParams(location.search);
+
+ const query = { ...gettingQuery };
+ for (const field of Object.keys(query)) {
+ if (params.has(field)) {
+ const value = params.get(field);
+ if (value) {
+ if (field === 'id' || field === 'page') {
+ if (Number.isInteger(+value)) {
+ query[field] = +value;
+ }
} else {
- searchString += `${field}:"${gettingQuery[field]}" AND `;
+ query[field] = value;
}
}
+ } else if (field === 'page') {
+ query[field] = 1;
+ } else {
+ query[field] = null;
}
}
- return searchString.slice(0, -5);
+ this.updateURL(query);
+ onGetTasks(query);
}
private handleSearch = (value: string): void => {
- const gettingQuery = { ...this.props.gettingQuery };
+ const {
+ gettingQuery,
+ onGetTasks,
+ } = this.props;
+
+ const query = { ...gettingQuery };
const search = value.replace(/\s+/g, ' ').replace(/\s*:+\s*/g, ':').trim();
const fields = ['name', 'mode', 'owner', 'assignee', 'status', 'id'];
for (const field of fields) {
- gettingQuery[field] = null;
+ query[field] = null;
}
- gettingQuery.search = null;
+ query.search = null;
let specificRequest = false;
for (const param of search.split(/[\s]+and[\s]+|[\s]+AND[\s]+/)) {
if (param.includes(':')) {
- const [name, value] = param.split(':');
- if (fields.includes(name) && !!value) {
+ const [field, fieldValue] = param.split(':');
+ if (fields.includes(field) && !!fieldValue) {
specificRequest = true;
- if (name === 'id') {
- if (Number.isInteger(+value)) {
- gettingQuery[name] = +value;
+ if (field === 'id') {
+ if (Number.isInteger(+fieldValue)) {
+ query[field] = +fieldValue;
}
} else {
- gettingQuery[name] = value;
+ query[field] = fieldValue;
}
}
}
}
- gettingQuery.page = 1;
+ query.page = 1;
if (!specificRequest && value) { // only id
- gettingQuery.search = value;
+ query.search = value;
}
- this.updateURL(gettingQuery);
- this.props.onGetTasks(gettingQuery);
- }
+ this.updateURL(query);
+ onGetTasks(query);
+ };
private handlePagination = (page: number): void => {
- const gettingQuery = { ...this.props.gettingQuery };
-
- gettingQuery.page = page;
- this.updateURL(gettingQuery);
- this.props.onGetTasks(gettingQuery);
- }
-
- public componentDidMount() {
- const gettingQuery = { ...this.props.gettingQuery };
- const params = new URLSearchParams(this.props.location.search);
-
+ const {
+ gettingQuery,
+ onGetTasks,
+ } = this.props;
+ const query = { ...gettingQuery };
+
+ query.page = page;
+ this.updateURL(query);
+ onGetTasks(query);
+ };
+
+ private updateURL(gettingQuery: TasksQuery): void {
+ const { history } = this.props;
+ let queryString = '?';
for (const field of Object.keys(gettingQuery)) {
- if (params.has(field)) {
- const value = params.get(field);
- if (value) {
- if (field === 'id' || field === 'page') {
- if (Number.isInteger(+value)) {
- gettingQuery[field] = +value;
- }
- } else {
- gettingQuery[field] = value;
- }
- }
- } else {
- if (field === 'page') {
- gettingQuery[field] = 1;
- } else {
- gettingQuery[field] = null;
- }
+ if (gettingQuery[field] !== null) {
+ queryString += `${field}=${gettingQuery[field]}&`;
}
}
-
- this.updateURL(gettingQuery);
- this.props.onGetTasks(gettingQuery);
+ history.replace({
+ search: queryString.slice(0, -1),
+ });
}
- public render() {
- if (this.props.tasksFetching) {
+ public render(): JSX.Element {
+ const {
+ tasksFetching,
+ gettingQuery,
+ numberOfVisibleTasks,
+ } = this.props;
+
+ if (tasksFetching) {
return (
-
+
);
- } else {
- return (
-
-
- {this.props.numberOfVisibleTasks ?
+ }
+
+ return (
+
+
+ {numberOfVisibleTasks
+ ? (
: }
-
- )
- }
+ />
+ ) :
+ }
+
+ );
}
}
-export default withRouter(TasksPageComponent);
\ No newline at end of file
+export default withRouter(TasksPageComponent);
diff --git a/cvat-ui/src/components/tasks-page/top-bar.tsx b/cvat-ui/src/components/tasks-page/top-bar.tsx
index b8cfea73f738..486e1dbb1f33 100644
--- a/cvat-ui/src/components/tasks-page/top-bar.tsx
+++ b/cvat-ui/src/components/tasks-page/top-bar.tsx
@@ -16,35 +16,50 @@ interface VisibleTopBarProps {
searchValue: string;
}
-function TopBarComponent(props: VisibleTopBarProps & RouteComponentProps) {
+function TopBarComponent(props: VisibleTopBarProps & RouteComponentProps): JSX.Element {
+ const {
+ searchValue,
+ history,
+ onSearch,
+ } = props;
+
return (
<>
- {'Default project'}
+ Default project
Tasks
-
+ md={{ span: 11 }}
+ lg={{ span: 9 }}
+ xl={{ span: 8 }}
+ xxl={{ span: 7 }}
+ >
+
>
- )
+ );
}
export default withRouter(TopBarComponent);
diff --git a/cvat-ui/src/containers/actions-menu/actions-menu.tsx b/cvat-ui/src/containers/actions-menu/actions-menu.tsx
index 1fab00afa0f3..dc8692c61454 100644
--- a/cvat-ui/src/containers/actions-menu/actions-menu.tsx
+++ b/cvat-ui/src/containers/actions-menu/actions-menu.tsx
@@ -4,7 +4,6 @@ import { connect } from 'react-redux';
import ActionsMenuComponent from '../../components/actions-menu/actions-menu';
import {
CombinedState,
- ActiveInference,
} from '../../reducers/interfaces';
import { showRunModelDialog } from '../../actions/models-actions';
@@ -30,7 +29,7 @@ interface StateToProps {
installedTFSegmentation: boolean;
installedAutoAnnotation: boolean;
inferenceIsActive: boolean;
-};
+}
interface DispatchToProps {
onLoadAnnotation: (taskInstance: any, loader: any, file: File) => void;
@@ -45,16 +44,16 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
const { activities } = state.tasks;
const { dumps } = activities;
const { loads } = activities;
- const _exports = activities.exports;
+ const activeExports = activities.exports;
const { plugins } = state.plugins;
- const id = own.taskInstance.id;
+ const { id } = own.taskInstance;
return {
installedTFAnnotation: plugins.TF_ANNOTATION,
installedTFSegmentation: plugins.TF_SEGMENTATION,
installedAutoAnnotation: plugins.AUTO_ANNOTATION,
dumpActivities: dumps.byTask[id] ? dumps.byTask[id] : null,
- exportActivities: _exports.byTask[id] ? _exports.byTask[id] : null,
+ exportActivities: activeExports.byTask[id] ? activeExports.byTask[id] : null,
loadActivity: loads.byTask[id] ? loads.byTask[id] : null,
loaders: formats.annotationFormats
.map((format: any): any[] => format.loaders).flat(),
@@ -62,49 +61,32 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
.map((format: any): any[] => format.dumpers).flat(),
exporters: formats.datasetFormats,
inferenceIsActive: id in state.models.inferences,
- };
+ };
}
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- onLoadAnnotation: (taskInstance: any, loader: any, file: File) => {
+ onLoadAnnotation: (taskInstance: any, loader: any, file: File): void => {
dispatch(loadAnnotationsAsync(taskInstance, loader, file));
},
- onDumpAnnotation: (taskInstance: any, dumper: any) => {
+ onDumpAnnotation: (taskInstance: any, dumper: any): void => {
dispatch(dumpAnnotationsAsync(taskInstance, dumper));
},
- onExportDataset: (taskInstance: any, exporter: any) => {
+ onExportDataset: (taskInstance: any, exporter: any): void => {
dispatch(exportDatasetAsync(taskInstance, exporter));
},
- onDeleteTask: (taskInstance: any) => {
+ onDeleteTask: (taskInstance: any): void => {
dispatch(deleteTaskAsync(taskInstance));
},
- onOpenRunWindow: (taskInstance: any) => {
+ onOpenRunWindow: (taskInstance: any): void => {
dispatch(showRunModelDialog(taskInstance));
- }
+ },
};
}
-function ActionsMenuContainer(props: OwnProps & StateToProps & DispatchToProps) {
+function ActionsMenuContainer(props: OwnProps & StateToProps & DispatchToProps): JSX.Element {
return (
-
+
);
}
diff --git a/cvat-ui/src/containers/annotation-page/annotation-page.tsx b/cvat-ui/src/containers/annotation-page/annotation-page.tsx
index d0e482ace13d..07f5a7ca9665 100644
--- a/cvat-ui/src/containers/annotation-page/annotation-page.tsx
+++ b/cvat-ui/src/containers/annotation-page/annotation-page.tsx
@@ -1,15 +1,11 @@
import React from 'react';
export default class AnnotationPageContainer extends React.PureComponent {
- constructor(props: any) {
- super(props);
- }
-
- public render() {
+ public render(): JSX.Element {
return (
- "AnnotationPage"
+ AnnotationPage
);
}
-}
\ No newline at end of file
+}
diff --git a/cvat-ui/src/containers/create-model-page/create-model-page.tsx b/cvat-ui/src/containers/create-model-page/create-model-page.tsx
index 188589f47ea6..a20b6fb56283 100644
--- a/cvat-ui/src/containers/create-model-page/create-model-page.tsx
+++ b/cvat-ui/src/containers/create-model-page/create-model-page.tsx
@@ -18,7 +18,7 @@ interface DispatchToProps {
}
function mapStateToProps(state: CombinedState): StateToProps {
- const { models} = state;
+ const { models } = state;
return {
isAdmin: state.auth.user.isAdmin,
@@ -28,19 +28,15 @@ function mapStateToProps(state: CombinedState): StateToProps {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- createModel(name: string, files: ModelFiles, global: boolean) {
+ createModel(name: string, files: ModelFiles, global: boolean): void {
dispatch(createModelAsync(name, files, global));
},
};
}
-function CreateModelPageContainer(props: StateToProps & DispatchToProps) {
+function CreateModelPageContainer(props: StateToProps & DispatchToProps): JSX.Element {
return (
-
+
);
}
diff --git a/cvat-ui/src/containers/create-task-page/create-task-page.tsx b/cvat-ui/src/containers/create-task-page/create-task-page.tsx
index a7655dce34ea..aac98fa42ed4 100644
--- a/cvat-ui/src/containers/create-task-page/create-task-page.tsx
+++ b/cvat-ui/src/containers/create-task-page/create-task-page.tsx
@@ -12,12 +12,12 @@ interface StateToProps {
}
interface DispatchToProps {
- create: (data: CreateTaskData) => void;
+ onCreate: (data: CreateTaskData) => void;
}
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- create: (data: CreateTaskData) => dispatch(createTaskAsync(data)),
+ onCreate: (data: CreateTaskData): void => dispatch(createTaskAsync(data)),
};
}
@@ -29,13 +29,9 @@ function mapStateToProps(state: CombinedState): StateToProps {
};
}
-function CreateTaskPageContainer(props: StateToProps & DispatchToProps) {
+function CreateTaskPageContainer(props: StateToProps & DispatchToProps): JSX.Element {
return (
-
+
);
}
diff --git a/cvat-ui/src/containers/file-manager/file-manager.tsx b/cvat-ui/src/containers/file-manager/file-manager.tsx
index 9cdbd9ed9fd5..40147d1111e2 100644
--- a/cvat-ui/src/containers/file-manager/file-manager.tsx
+++ b/cvat-ui/src/containers/file-manager/file-manager.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { connect } from 'react-redux';
-import { TreeNodeNormal } from 'antd/lib/tree/Tree'
+import { TreeNodeNormal } from 'antd/lib/tree/Tree';
import FileManagerComponent, { Files } from '../../components/file-manager/file-manager';
import { loadShareDataAsync } from '../../actions/share-actions';
@@ -44,9 +44,9 @@ function mapStateToProps(state: CombinedState): StateToProps {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- getTreeData: (key: string, success: () => void, failure: () => void) => {
+ getTreeData: (key: string, success: () => void, failure: () => void): void => {
dispatch(loadShareDataAsync(key, success, failure));
- }
+ },
};
}
@@ -63,13 +63,21 @@ export class FileManagerContainer extends React.PureComponent {
return this.managerComponentRef.reset();
}
- public render() {
+ public render(): JSX.Element {
+ const {
+ treeData,
+ getTreeData,
+ withRemote,
+ } = this.props;
+
return (
this.managerComponentRef = component}
+ treeData={treeData}
+ onLoadData={getTreeData}
+ withRemote={withRemote}
+ ref={(component): void => {
+ this.managerComponentRef = component;
+ }}
/>
);
}
diff --git a/cvat-ui/src/containers/header/header.tsx b/cvat-ui/src/containers/header/header.tsx
index f3ec07fbe633..b434c18b6b12 100644
--- a/cvat-ui/src/containers/header/header.tsx
+++ b/cvat-ui/src/containers/header/header.tsx
@@ -19,7 +19,7 @@ interface StateToProps {
}
interface DispatchToProps {
- logout(): void;
+ onLogout(): void;
}
function mapStateToProps(state: CombinedState): StateToProps {
@@ -37,21 +37,13 @@ function mapStateToProps(state: CombinedState): StateToProps {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- logout: () => dispatch(logoutAsync()),
- }
+ onLogout: (): void => dispatch(logoutAsync()),
+ };
}
-function HeaderContainer(props: StateToProps & DispatchToProps) {
+function HeaderContainer(props: StateToProps & DispatchToProps): JSX.Element {
return (
-
+
);
}
diff --git a/cvat-ui/src/containers/login-page/login-page.tsx b/cvat-ui/src/containers/login-page/login-page.tsx
index f04e0e3c2392..b6b9b57dee84 100644
--- a/cvat-ui/src/containers/login-page/login-page.tsx
+++ b/cvat-ui/src/containers/login-page/login-page.tsx
@@ -9,7 +9,7 @@ interface StateToProps {
}
interface DispatchToProps {
- login(username: string, password: string): void;
+ onLogin(username: string, password: string): void;
}
function mapStateToProps(state: CombinedState): StateToProps {
@@ -20,16 +20,13 @@ function mapStateToProps(state: CombinedState): StateToProps {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- login: (...args) => dispatch(loginAsync(...args)),
+ onLogin: (...args): void => dispatch(loginAsync(...args)),
};
}
-function LoginPageContainer(props: DispatchToProps & StateToProps) {
+function LoginPageContainer(props: DispatchToProps & StateToProps): JSX.Element {
return (
-
+
);
}
diff --git a/cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx b/cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx
index 290c4df86e36..1da1386caef2 100644
--- a/cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx
+++ b/cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx
@@ -18,18 +18,18 @@ interface StateToProps {
modelsInitialized: boolean;
models: Model[];
activeProcesses: {
- [index: string]: string
+ [index: string]: string;
};
taskInstance: any;
visible: boolean;
}
interface DispatchToProps {
- inferModelAsync(
+ runInference(
taskInstance: any,
model: Model,
mapping: {
- [index: string]: string
+ [index: string]: string;
},
cleanOut: boolean,
): void;
@@ -52,42 +52,33 @@ function mapStateToProps(state: CombinedState): StateToProps {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return ({
- inferModelAsync(
+ runInference(
taskInstance: any,
model: Model,
mapping: {
- [index: string]: string
+ [index: string]: string;
},
- cleanOut: boolean): void {
- dispatch(inferModelAsync(taskInstance, model, mapping, cleanOut));
+ cleanOut: boolean,
+ ): void {
+ dispatch(inferModelAsync(taskInstance, model, mapping, cleanOut));
},
getModels(): void {
dispatch(getModelsAsync());
},
closeDialog(): void {
dispatch(closeRunModelDialog());
- }
+ },
});
}
-function ModelRunnerModalContainer(props: StateToProps & DispatchToProps) {
+function ModelRunnerModalContainer(props: StateToProps & DispatchToProps): JSX.Element {
return (
-
+
);
}
export default connect(
mapStateToProps,
mapDispatchToProps,
-) (ModelRunnerModalContainer);
+)(ModelRunnerModalContainer);
diff --git a/cvat-ui/src/containers/models-page/models-page.tsx b/cvat-ui/src/containers/models-page/models-page.tsx
index 76c2e7f81b8a..ba56bb97e255 100644
--- a/cvat-ui/src/containers/models-page/models-page.tsx
+++ b/cvat-ui/src/containers/models-page/models-page.tsx
@@ -43,33 +43,28 @@ function mapStateToProps(state: CombinedState): StateToProps {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- getModels() {
+ getModels(): void {
dispatch(getModelsAsync());
},
- deleteModel(id: number) {
+ deleteModel(id: number): void {
dispatch(deleteModelAsync(id));
},
};
}
-function ModelsPageContainer(props: DispatchToProps & StateToProps) {
- const render = props.installedAutoAnnotation
- || props.installedTFAnnotation
- || props.installedTFSegmentation;
+function ModelsPageContainer(props: DispatchToProps & StateToProps): JSX.Element | null {
+ const {
+ installedAutoAnnotation,
+ installedTFSegmentation,
+ installedTFAnnotation,
+ } = props;
+
+ const render = installedAutoAnnotation
+ || installedTFAnnotation
+ || installedTFSegmentation;
return (
- render ?
- : null
+ render ? : null
);
}
diff --git a/cvat-ui/src/containers/register-page/register-page.tsx b/cvat-ui/src/containers/register-page/register-page.tsx
index f989ece22bc2..c11310865444 100644
--- a/cvat-ui/src/containers/register-page/register-page.tsx
+++ b/cvat-ui/src/containers/register-page/register-page.tsx
@@ -9,7 +9,7 @@ interface StateToProps {
}
interface DispatchToProps {
- register: (username: string, firstName: string,
+ onRegister: (username: string, firstName: string,
lastName: string, email: string,
password1: string, password2: string) => void;
}
@@ -22,16 +22,13 @@ function mapStateToProps(state: CombinedState): StateToProps {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- register: (...args) => dispatch(registerAsync(...args))
- }
+ onRegister: (...args): void => dispatch(registerAsync(...args)),
+ };
}
-function RegisterPageContainer(props: StateToProps & DispatchToProps) {
+function RegisterPageContainer(props: StateToProps & DispatchToProps): JSX.Element {
return (
-
+
);
}
diff --git a/cvat-ui/src/containers/task-page/details.tsx b/cvat-ui/src/containers/task-page/details.tsx
index 1f5155f34d65..913bbdf19ddf 100644
--- a/cvat-ui/src/containers/task-page/details.tsx
+++ b/cvat-ui/src/containers/task-page/details.tsx
@@ -21,7 +21,7 @@ interface DispatchToProps {
onTaskUpdate: (taskInstance: any) => void;
}
-function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
+function mapStateToProps(state: CombinedState): StateToProps {
const { plugins } = state.plugins;
return {
@@ -33,20 +33,26 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- onTaskUpdate: (taskInstance: any) =>
- dispatch(updateTaskAsync(taskInstance))
- }
+ onTaskUpdate: (taskInstance: any): void => dispatch(updateTaskAsync(taskInstance)),
+ };
}
-function TaskPageContainer(props: StateToProps & DispatchToProps & OwnProps) {
+function TaskPageContainer(props: StateToProps & DispatchToProps & OwnProps): JSX.Element {
+ const {
+ task,
+ installedGit,
+ registeredUsers,
+ onTaskUpdate,
+ } = props;
+
return (
);
}
@@ -54,4 +60,4 @@ function TaskPageContainer(props: StateToProps & DispatchToProps & OwnProps) {
export default connect(
mapStateToProps,
mapDispatchToProps,
-)(TaskPageContainer);
\ No newline at end of file
+)(TaskPageContainer);
diff --git a/cvat-ui/src/containers/task-page/job-list.tsx b/cvat-ui/src/containers/task-page/job-list.tsx
index 1714c585bda9..c7e32c589ccb 100644
--- a/cvat-ui/src/containers/task-page/job-list.tsx
+++ b/cvat-ui/src/containers/task-page/job-list.tsx
@@ -28,16 +28,22 @@ function mapStateToProps(state: CombinedState): StateToProps {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- onJobUpdate: (jobInstance: any) => dispatch(updateJobAsync(jobInstance)),
+ onJobUpdate: (jobInstance: any): void => dispatch(updateJobAsync(jobInstance)),
};
}
-function TaskPageContainer(props: StateToProps & DispatchToProps & OwnProps) {
+function TaskPageContainer(props: StateToProps & DispatchToProps & OwnProps): JSX.Element {
+ const {
+ task,
+ registeredUsers,
+ onJobUpdate,
+ } = props;
+
return (
);
}
@@ -45,4 +51,4 @@ function TaskPageContainer(props: StateToProps & DispatchToProps & OwnProps) {
export default connect(
mapStateToProps,
mapDispatchToProps,
-)(TaskPageContainer);
\ No newline at end of file
+)(TaskPageContainer);
diff --git a/cvat-ui/src/containers/task-page/task-page.tsx b/cvat-ui/src/containers/task-page/task-page.tsx
index 844df0844ff8..1133e16620b3 100644
--- a/cvat-ui/src/containers/task-page/task-page.tsx
+++ b/cvat-ui/src/containers/task-page/task-page.tsx
@@ -21,7 +21,7 @@ interface StateToProps {
}
interface DispatchToProps {
- fetchTask: (tid: number) => void;
+ onFetchTask: (tid: number) => void;
}
function mapStateToProps(state: CombinedState, own: Props): StateToProps {
@@ -47,7 +47,7 @@ function mapStateToProps(state: CombinedState, own: Props): StateToProps {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- fetchTask: (tid: number) => {
+ onFetchTask: (tid: number): void => {
dispatch(getTasksAsync({
id: tid,
page: 1,
@@ -62,15 +62,9 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
};
}
-function TaskPageContainer(props: StateToProps & DispatchToProps) {
+function TaskPageContainer(props: StateToProps & DispatchToProps): JSX.Element {
return (
-
+
);
}
diff --git a/cvat-ui/src/containers/tasks-page/task-item.tsx b/cvat-ui/src/containers/tasks-page/task-item.tsx
index e13390d7e3f5..38e5c1931167 100644
--- a/cvat-ui/src/containers/tasks-page/task-item.tsx
+++ b/cvat-ui/src/containers/tasks-page/task-item.tsx
@@ -7,14 +7,14 @@ import {
ActiveInference,
} from '../../reducers/interfaces';
-import TaskItemComponent from '../../components/tasks-page/task-item'
+import TaskItemComponent from '../../components/tasks-page/task-item';
import {
getTasksAsync,
} from '../../actions/tasks-actions';
interface StateToProps {
- deleteActivity: boolean | null;
+ deleted: boolean;
previewImage: string;
taskInstance: any;
activeInference: ActiveInference | null;
@@ -35,7 +35,7 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
const id = own.taskID;
return {
- deleteActivity: deletes.byTask[id] ? deletes.byTask[id] : null,
+ deleted: deletes.byTask[id] ? deletes.byTask[id] === true : false,
previewImage: task.preview,
taskInstance: task.instance,
activeInference: state.models.inferences[id] || null,
@@ -47,19 +47,14 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
getTasks: (query: TasksQuery): void => {
dispatch(getTasksAsync(query));
},
- }
+ };
}
type TasksItemContainerProps = StateToProps & DispatchToProps & OwnProps;
-function TaskItemContainer(props: TasksItemContainerProps) {
+function TaskItemContainer(props: TasksItemContainerProps): JSX.Element {
return (
-
+
);
}
diff --git a/cvat-ui/src/containers/tasks-page/tasks-list.tsx b/cvat-ui/src/containers/tasks-page/tasks-list.tsx
index 8782e3f9fb15..7afd17b8de23 100644
--- a/cvat-ui/src/containers/tasks-page/tasks-list.tsx
+++ b/cvat-ui/src/containers/tasks-page/tasks-list.tsx
@@ -33,19 +33,26 @@ function mapStateToProps(state: CombinedState): StateToProps {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- getTasks: (query: TasksQuery) => {dispatch(getTasksAsync(query))}
- }
+ getTasks: (query: TasksQuery): void => {
+ dispatch(getTasksAsync(query));
+ },
+ };
}
type TasksListContainerProps = StateToProps & DispatchToProps & OwnProps;
-function TasksListContainer(props: TasksListContainerProps) {
+function TasksListContainer(props: TasksListContainerProps): JSX.Element {
+ const {
+ tasks,
+ onSwitchPage,
+ } = props;
+
return (
task.instance.id)}
- currentPage={props.tasks.gettingQuery.page}
- numberOfTasks={props.tasks.count}
+ onSwitchPage={onSwitchPage}
+ currentTasksIndexes={tasks.current.map((task): number => task.instance.id)}
+ currentPage={tasks.gettingQuery.page}
+ numberOfTasks={tasks.count}
/>
);
}
diff --git a/cvat-ui/src/containers/tasks-page/tasks-page.tsx b/cvat-ui/src/containers/tasks-page/tasks-page.tsx
index 1420ca58927c..006e2c7d3e21 100644
--- a/cvat-ui/src/containers/tasks-page/tasks-page.tsx
+++ b/cvat-ui/src/containers/tasks-page/tasks-page.tsx
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import {
TasksQuery,
- CombinedState
+ CombinedState,
} from '../../reducers/interfaces';
import TasksPageComponent from '../../components/tasks-page/tasks-page';
@@ -18,7 +18,7 @@ interface StateToProps {
}
interface DispatchToProps {
- getTasks: (gettingQuery: TasksQuery) => void;
+ onGetTasks: (gettingQuery: TasksQuery) => void;
}
function mapStateToProps(state: CombinedState): StateToProps {
@@ -34,21 +34,17 @@ function mapStateToProps(state: CombinedState): StateToProps {
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
- getTasks: (query: TasksQuery) => {dispatch(getTasksAsync(query))}
- }
+ onGetTasks: (query: TasksQuery): void => {
+ dispatch(getTasksAsync(query));
+ },
+ };
}
type TasksPageContainerProps = StateToProps & DispatchToProps;
-function TasksPageContainer(props: TasksPageContainerProps) {
+function TasksPageContainer(props: TasksPageContainerProps): JSX.Element {
return (
-
+
);
}
diff --git a/cvat-ui/src/index.tsx b/cvat-ui/src/index.tsx
index 621c4813a3da..3ef428246f11 100644
--- a/cvat-ui/src/index.tsx
+++ b/cvat-ui/src/index.tsx
@@ -19,7 +19,7 @@ import {
import {
CombinedState,
NotificationsState,
- } from './reducers/interfaces';
+} from './reducers/interfaces';
createCVATStore(createRootReducer);
const cvatStore = getCVATStore();
@@ -65,7 +65,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
installedAutoAnnotation: plugins.plugins.AUTO_ANNOTATION,
installedTFSegmentation: plugins.plugins.TF_SEGMENTATION,
installedTFAnnotation: plugins.plugins.TF_ANNOTATION,
- notifications: {...state.notifications},
+ notifications: { ...state.notifications },
user: auth.user,
};
}
@@ -81,29 +81,10 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
};
}
-function reduxAppWrapper(props: StateToProps & DispatchToProps) {
+function reduxAppWrapper(props: StateToProps & DispatchToProps): JSX.Element {
return (
-
- )
+
+ );
}
const ReduxAppWrapper = connect(
@@ -114,8 +95,8 @@ const ReduxAppWrapper = connect(
ReactDOM.render(
(
-
+
),
- document.getElementById('root')
-)
+ document.getElementById('root'),
+);
diff --git a/cvat-ui/src/reducers/auth-reducer.ts b/cvat-ui/src/reducers/auth-reducer.ts
index 023aad82cf9d..63fecdf67ece 100644
--- a/cvat-ui/src/reducers/auth-reducer.ts
+++ b/cvat-ui/src/reducers/auth-reducer.ts
@@ -18,15 +18,15 @@ export default (state = defaultState, action: AnyAction): AuthState => {
user: action.payload.user,
};
case AuthActionTypes.AUTHORIZED_FAILED:
- return {
- ...state,
- initialized: true,
- };
+ return {
+ ...state,
+ initialized: true,
+ };
case AuthActionTypes.LOGIN:
return {
...state,
fetching: true,
- }
+ };
case AuthActionTypes.LOGIN_SUCCESS:
return {
...state,
@@ -49,11 +49,6 @@ export default (state = defaultState, action: AnyAction): AuthState => {
fetching: false,
user: null,
};
- case AuthActionTypes.LOGIN_FAILED:
- return {
- ...state,
- fetching: false,
- };
case AuthActionTypes.REGISTER:
return {
...state,
diff --git a/cvat-ui/src/reducers/formats-reducer.ts b/cvat-ui/src/reducers/formats-reducer.ts
index 01fa6e43d716..40fd2a80506f 100644
--- a/cvat-ui/src/reducers/formats-reducer.ts
+++ b/cvat-ui/src/reducers/formats-reducer.ts
@@ -37,7 +37,7 @@ export default (state = defaultState, action: AnyAction): FormatsState => {
case AuthActionTypes.LOGOUT_SUCCESS: {
return {
...defaultState,
- }
+ };
}
default:
return state;
diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts
index c08af738c529..6a18564671fc 100644
--- a/cvat-ui/src/reducers/interfaces.ts
+++ b/cvat-ui/src/reducers/interfaces.ts
@@ -147,8 +147,8 @@ export interface ModelFiles {
}
export interface ErrorState {
- message: string,
- reason: string,
+ message: string;
+ reason: string;
}
export interface NotificationsState {
diff --git a/cvat-ui/src/reducers/models-reducer.ts b/cvat-ui/src/reducers/models-reducer.ts
index 8636b224ab5f..664622fecffe 100644
--- a/cvat-ui/src/reducers/models-reducer.ts
+++ b/cvat-ui/src/reducers/models-reducer.ts
@@ -110,7 +110,7 @@ export default function (state = defaultState, action: AnyAction): ModelsState {
case AuthActionTypes.LOGOUT_SUCCESS: {
return {
...defaultState,
- }
+ };
}
default: {
return {
diff --git a/cvat-ui/src/reducers/notifications-reducer.ts b/cvat-ui/src/reducers/notifications-reducer.ts
index 86074948396a..e6fa34873860 100644
--- a/cvat-ui/src/reducers/notifications-reducer.ts
+++ b/cvat-ui/src/reducers/notifications-reducer.ts
@@ -67,7 +67,7 @@ export default function (state = defaultState, action: AnyAction): Notifications
authorized: {
message: 'Could not check authorization on the server',
reason: action.payload.error.toString(),
- }
+ },
},
},
};
@@ -82,7 +82,7 @@ export default function (state = defaultState, action: AnyAction): Notifications
login: {
message: 'Could not login on the server',
reason: action.payload.error.toString(),
- }
+ },
},
},
};
@@ -323,7 +323,7 @@ export default function (state = defaultState, action: AnyAction): Notifications
}
case ModelsActionTypes.GET_INFERENCE_STATUS_SUCCESS: {
if (action.payload.activeInference.status === 'finished') {
- const taskID = action.payload.taskID;
+ const { taskID } = action.payload;
return {
...state,
messages: {
@@ -351,7 +351,7 @@ export default function (state = defaultState, action: AnyAction): Notifications
metaFetching: {
message: 'Could not fetch models meta information',
reason: action.payload.error.toString(),
- }
+ },
},
},
};
@@ -368,7 +368,7 @@ export default function (state = defaultState, action: AnyAction): Notifications
message: 'Could not fetch inference status for the '
+ `task ${taskID}`,
reason: action.payload.error.toString(),
- }
+ },
},
},
};
@@ -400,7 +400,7 @@ export default function (state = defaultState, action: AnyAction): Notifications
message: 'Could not infer model for the '
+ `task ${taskID}`,
reason: action.payload.error.toString(),
- }
+ },
},
},
};
@@ -424,7 +424,7 @@ export default function (state = defaultState, action: AnyAction): Notifications
case AuthActionTypes.LOGOUT_SUCCESS: {
return {
...defaultState,
- }
+ };
}
default: {
return {
diff --git a/cvat-ui/src/reducers/plugins-reducer.ts b/cvat-ui/src/reducers/plugins-reducer.ts
index 29290e18d456..1a7e1f160787 100644
--- a/cvat-ui/src/reducers/plugins-reducer.ts
+++ b/cvat-ui/src/reducers/plugins-reducer.ts
@@ -45,7 +45,7 @@ export default function (state = defaultState, action: AnyAction): PluginsState
case AuthActionTypes.LOGOUT_SUCCESS: {
return {
...defaultState,
- }
+ };
}
default:
return { ...state };
diff --git a/cvat-ui/src/reducers/share-reducer.ts b/cvat-ui/src/reducers/share-reducer.ts
index 66a989f1970c..185bf2565e90 100644
--- a/cvat-ui/src/reducers/share-reducer.ts
+++ b/cvat-ui/src/reducers/share-reducer.ts
@@ -46,7 +46,7 @@ export default function (state = defaultState, action: AnyAction): ShareState {
case AuthActionTypes.LOGOUT_SUCCESS: {
return {
...defaultState,
- }
+ };
}
default:
return {
diff --git a/cvat-ui/src/reducers/tasks-reducer.ts b/cvat-ui/src/reducers/tasks-reducer.ts
index 200d4f4d0d10..cb6c975ff814 100644
--- a/cvat-ui/src/reducers/tasks-reducer.ts
+++ b/cvat-ui/src/reducers/tasks-reducer.ts
@@ -408,7 +408,7 @@ export default (state: TasksState = defaultState, action: AnyAction): TasksState
case AuthActionTypes.LOGOUT_SUCCESS: {
return {
...defaultState,
- }
+ };
}
default:
return state;
diff --git a/cvat-ui/src/reducers/users-reducer.ts b/cvat-ui/src/reducers/users-reducer.ts
index b1f10d427427..bb37e6dfc470 100644
--- a/cvat-ui/src/reducers/users-reducer.ts
+++ b/cvat-ui/src/reducers/users-reducer.ts
@@ -35,7 +35,7 @@ export default function (state: UsersState = defaultState, action: AnyAction): U
case AuthActionTypes.LOGOUT_SUCCESS: {
return {
...defaultState,
- }
+ };
}
default:
return {
diff --git a/cvat-ui/src/stylesheet.css b/cvat-ui/src/stylesheet.css
index 1a2aef1828a4..4c3c2b34c05f 100644
--- a/cvat-ui/src/stylesheet.css
+++ b/cvat-ui/src/stylesheet.css
@@ -275,6 +275,10 @@
border: 1px solid #40a9ff;
}
+.cvat-tasks-list-item > div:nth-child(2) {
+ word-break: break-all;
+}
+
.cvat-tasks-list-item > div:nth-child(4) > div {
margin-right: 20px;
}