From 16c0c57359858aefd9759a50e3d21658064ff693 Mon Sep 17 00:00:00 2001
From: Boris Sekachev
Date: Thu, 5 Dec 2019 13:41:58 +0300
Subject: [PATCH 01/17] Installed airbnb fullsettings
---
.vscode/settings.json | 3 +-
cvat-ui/.eslintrc.js | 2 +-
cvat-ui/package-lock.json | 194 +++++++++++++++++++++++++++++++-------
cvat-ui/package.json | 7 +-
4 files changed, 166 insertions(+), 40 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..31fededabe4e 100644
--- a/cvat-ui/.eslintrc.js
+++ b/cvat-ui/.eslintrc.js
@@ -19,7 +19,7 @@ module.exports = {
],
'extends': [
'plugin:@typescript-eslint/recommended',
- 'airbnb-typescript/base',
+ 'airbnb-typescript',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
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"
From 50ab7e77f987cbb724517baab3e543a0078ba4ee Mon Sep 17 00:00:00 2001
From: Boris Sekachev
Date: Thu, 5 Dec 2019 14:10:53 +0300
Subject: [PATCH 02/17] Fixed actions menu
---
cvat-ui/.eslintrc.js | 4 ++
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 +++++----
6 files changed, 99 insertions(+), 54 deletions(-)
diff --git a/cvat-ui/.eslintrc.js b/cvat-ui/.eslintrc.js
index 31fededabe4e..41e6a107fef1 100644
--- a/cvat-ui/.eslintrc.js
+++ b/cvat-ui/.eslintrc.js
@@ -26,6 +26,10 @@ module.exports = {
],
'rules': {
'@typescript-eslint/indent': ['warn', 4],
+ 'react/jsx-indent': ['warn', 4],
+ 'react/jsx-indent-props': ['warn', 4],
+ 'jsx-quotes': ['error', 'prefer-single'],
+ 'arrow-parens': ['error', 'always'],
'@typescript-eslint/no-explicit-any': [0],
'no-restricted-syntax': [0, {'selector': 'ForOfStatement'}],
'no-plusplus': [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..49a32a1c99ef 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 (
-
- { !!this.state.files.local.length &&
- <>
-
-
- {`${this.state.files.local.length} file(s) selected`}
-
- >
+ { !!files.local.length
+ && (
+ <>
+
+
+ {`${files.local.length} file(s) selected`}
+
+ >
+ )
}
);
}
- private renderShareSelector() {
- function renderTreeNodes(data: TreeNodeNormal[]) {
+ private renderShareSelector(): JSX.Element {
+ function renderTreeNodes(data: TreeNodeNormal[]): JSX.Element[] {
return data.map((item: TreeNodeNormal) => {
if (item.children) {
- return (
-
- {renderTreeNodes(item.children)}
-
- );
+ return (
+
+ {renderTreeNodes(item.children)}
+
+ );
}
return ;
});
}
+ const { treeData } = this.props;
+ const {
+ expandedKeys,
+ files,
+ } = this.state;
+
return (
- { this.props.treeData.length ?
- {
- return this.loadData(node.props.dataRef.key);
- }}
- onExpand={(expandedKeys: string[]) => {
- this.setState({
- expandedKeys,
- });
- }}
- onCheck={(checkedKeys: string[] | {checked: string[], halfChecked: string[]}) => {
- const keys = checkedKeys as string[];
- this.setState({
- files: {
- ...this.state.files,
- share: keys,
- },
- });
- }}>
- { renderTreeNodes(this.props.treeData) }
- : {'No data found'}
+ { treeData.length
+ ? (
+ => this.loadData(
+ node.props.dataRef.key,
+ )}
+ onExpand={(newExpandedKeys: string[]): void => {
+ this.setState({
+ expandedKeys: newExpandedKeys,
+ });
+ }}
+ onCheck={
+ (checkedKeys: string[] | {
+ checked: string[];
+ halfChecked: string[];
+ }): void => {
+ const keys = checkedKeys as string[];
+ this.setState({
+ files: {
+ ...files,
+ share: keys,
+ },
+ });
+ }}
+ >
+ { renderTreeNodes(treeData) }
+
+ ) : No data found
}
);
}
- private renderRemoteSelector() {
+ private renderRemoteSelector(): JSX.Element {
+ const { files } = this.state;
+
return (
) => {
+ value={[...files.remote].join('\n')}
+ onChange={(event: React.ChangeEvent): void => {
this.setState({
files: {
- ...this.state.files,
+ ...files,
remote: event.target.value.split('\n'),
},
});
- }}/>
+ }}
+ />
);
}
- public getFiles(): Files {
- return {
- local: this.state.active === 'local' ? this.state.files.local : [],
- share: this.state.active === 'share' ? this.state.files.share : [],
- remote: this.state.active === 'remote' ? this.state.files.remote : [],
- };
- }
-
- public reset() {
- this.setState({
- expandedKeys: [],
- active: 'local',
- files: {
- local: [],
- share: [],
- remote: [],
- },
- });
- }
+ public render(): JSX.Element {
+ const { withRemote } = this.props;
- public render() {
return (
<>
- this.setState({
- active: activeKey as any,
- })}>
+ this.setState({
+ active: activeKey as any,
+ })
+ }
+ >
{ this.renderLocalSelector() }
{ this.renderShareSelector() }
- { this.props.withRemote && this.renderRemoteSelector() }
+ { withRemote && this.renderRemoteSelector() }
>
);
diff --git a/cvat-ui/src/components/header/header.tsx b/cvat-ui/src/components/header/header.tsx
index 451d93fd9333..707d7de6a48d 100644
--- a/cvat-ui/src/components/header/header.tsx
+++ b/cvat-ui/src/components/header/header.tsx
@@ -15,6 +15,7 @@ import Text from 'antd/lib/typography/Text';
import getCore from '../../core';
const core = getCore();
+const serverHost = core.config.backendAPI.slice(0, -7);
interface HeaderContainerProps {
onLogout: () => void;
@@ -28,66 +29,121 @@ interface HeaderContainerProps {
type Props = HeaderContainerProps & RouteComponentProps;
-const cvatLogo = () => ;
-const userLogo = () => ;
+const cvatLogo = (): JSX.Element => ;
+const userLogo = (): JSX.Element => ;
+
+function HeaderContainer(props: Props): JSX.Element {
+ const {
+ installedTFSegmentation,
+ installedAutoAnnotation,
+ installedTFAnnotation,
+ installedAnalytics,
+ username,
+ onLogout,
+ logoutFetching,
+ } = props;
+
+ const renderModels = installedAutoAnnotation
+ || installedTFAnnotation
+ || installedTFSegmentation;
-function HeaderContainer(props: Props) {
- const renderModels = props.installedAutoAnnotation
- || props.installedTFAnnotation
- || props.installedTFSegmentation;
return (
-
+
-
- { renderModels ?
- : null
+
+ { renderModels
+ && (
+
+ )
}
- { props.installedAnalytics ?
- : null
+ { installedAnalytics
+ && (
+
+ )
}
-
);
}
- private renderAttribute = (key: number, index: number) => {
- const attr = (this.props.label && index < this.props.label.attributes.length
- ? this.props.label.attributes[index]
+ private renderAttribute = (key: number, index: number): JSX.Element => {
+ const {
+ label,
+ form,
+ } = this.props;
+
+ const attr = (label && index < label.attributes.length
+ ? label.attributes[index]
: null);
return (
@@ -306,23 +332,23 @@ class LabelForm extends React.PureComponent
{
{ this.renderAttributeNameInput(key, attr) }
{ this.renderAttributeTypeInput(key, attr) }
- {
- (() => {
- const type = this.props.form.getFieldValue(`type[${key}]`);
+
+ {((): JSX.Element => {
+ const type = form.getFieldValue(`type[${key}]`);
let element = null;
-
- [AttributeType.SELECT, AttributeType.RADIO]
- .includes(type) ?
- element = this.renderAttributeValuesInput(key, attr)
- : type === AttributeType.CHECKBOX ?
- element = this.renderBooleanValueInput(key, attr)
- : type === AttributeType.NUMBER ?
- element = this.renderNumberRangeInput(key, attr)
- : element = this.renderDefaultValueInput(key, attr)
+ if ([AttributeType.SELECT, AttributeType.RADIO].includes(type)) {
+ element = this.renderAttributeValuesInput(key, attr);
+ } else if (type === AttributeType.CHECKBOX) {
+ element = this.renderBooleanValueInput(key, attr);
+ } else if (type === AttributeType.NUMBER) {
+ element = this.renderNumberRangeInput(key, attr);
+ } else {
+ element = this.renderDefaultValueInput(key, attr);
+ }
return element;
- })()
- }
+ })()}
+
{ this.renderMutableAttributeInput(key, attr) }
@@ -332,16 +358,20 @@ class LabelForm extends React.PureComponent {
);
- }
+ };
- private renderLabelNameInput() {
- const value = this.props.label ? this.props.label.name : '';
- const locked = this.props.label ? this.props.label.id >= 0 : false;
+ private renderLabelNameInput(): JSX.Element {
+ const {
+ label,
+ form,
+ } = this.props;
+ const value = label ? label.name : '';
+ const locked = label ? label.id >= 0 : false;
return (
- {
- this.props.form.getFieldDecorator('labelName', {
+
+ {form.getFieldDecorator('labelName', {
initialValue: value,
rules: [{
required: true,
@@ -349,99 +379,119 @@ class LabelForm extends React.PureComponent {
}, {
pattern: patterns.validateAttributeName.pattern,
message: patterns.validateAttributeName.message,
- }]
- })()
- }
+ }],
+ })()}
+
);
}
- private renderNewAttributeButton() {
+ private renderNewAttributeButton(): JSX.Element {
return (
- Add an attribute
+ Add an attribute
+
);
}
- private renderDoneButton() {
+ private renderDoneButton(): JSX.Element {
return (
{
+ onClick={(): void => {
this.continueAfterSubmit = false;
}}
- > Done
+ >
+ Done
+
);
}
- private renderContinueButton() {
+ private renderContinueButton(): JSX.Element {
+ const { label } = this.props;
+
return (
- this.props.label ? :
-
-
- {
- this.continueAfterSubmit = true;
- }}
- > Continue
-
-
- );
+ label ?
+ : (
+
+
+ {
+ this.continueAfterSubmit = true;
+ }}
+ >
+ Continue
+
+
+
+ )
+ );
}
- private renderCancelButton() {
+ private renderCancelButton(): JSX.Element {
+ const { onSubmit } = this.props;
+
return (
{
- this.props.onSubmit(null);
+ onClick={(): void => {
+ onSubmit(null);
}}
- > Cancel
+ >
+ Cancel
+
);
}
- public render() {
- this.props.form.getFieldDecorator('keys', {
- initialValue: this.props.label
- ? this.props.label.attributes.map((attr: Attribute) => attr.id)
- : []
+ public render(): JSX.Element {
+ const {
+ label,
+ form,
+ } = this.props;
+
+ form.getFieldDecorator('keys', {
+ initialValue: label
+ ? label.attributes.map((attr: Attribute) => attr.id)
+ : [],
});
- let keys = this.props.form.getFieldValue('keys');
+ const keys = form.getFieldValue('keys');
const attributeItems = keys.map(this.renderAttribute);
return (
+ { withMapping
+ && (
+
+ this.setState({
+ cleanOut: e.target.checked,
+ })}
+ >
+ Clean old annotations
+
+
+ )
}
);
}
- private renderSpin() {
- return (
-
- );
- }
+ public render(): JSX.Element | false {
+ const {
+ selectedModel,
+ mapping,
+ cleanOut,
+ } = this.state;
- public componentDidUpdate(prevProps: Props, prevState: State) {
- if (!this.props.modelsInitialized && !this.props.modelsFetching) {
- this.props.getModels();
- }
+ const {
+ models,
+ visible,
+ taskInstance,
+ modelsInitialized,
+ runInference,
+ closeDialog,
+ } = this.props;
- if (!prevProps.visible && this.props.visible) {
- this.setState({
- selectedModel: null,
- mapping: {},
- matching: {
- model: '',
- task: '',
- },
- cleanOut: false,
- });
- }
-
- if (this.state.selectedModel && prevState.selectedModel !== this.state.selectedModel) {
- const model = this.props.models
- .filter((model) => model.name === this.state.selectedModel)[0];
- if (!model.primary) {
- let taskLabels: string[] = this.props.taskInstance.labels
- .map((label: any) => label.name);
- const defaultMapping: StringObject = model.labels
- .reduce((acc: StringObject, label) => {
- if (taskLabels.includes(label)) {
- acc[label] = label;
- taskLabels = taskLabels.filter((_label) => _label !== label)
- }
-
- return acc;
- }, {});
-
- this.setState({
- mapping: defaultMapping,
- });
- }
- }
- }
-
- public render() {
- const activeModel = this.props.models.filter(
- (model) => model.name === this.state.selectedModel
+ const activeModel = models.filter(
+ (model) => model.name === selectedModel,
)[0];
- let enabledSubmit = !!activeModel
- && activeModel.primary || !!Object.keys(this.state.mapping).length;
+ const enabledSubmit = (!!activeModel
+ && activeModel.primary) || !!Object.keys(mapping).length;
return (
- this.props.visible && {
- this.props.runInference(
- this.props.taskInstance,
- this.props.models
- .filter((model) => model.name === this.state.selectedModel)[0],
- this.state.mapping,
- this.state.cleanOut,
- );
- this.props.closeDialog()
- }}
- onCancel={() => this.props.closeDialog()}
- okButtonProps={{disabled: !enabledSubmit}}
- title='Automatic annotation'
- visible={true}
- >
- {!this.props.modelsInitialized && this.renderSpin()}
- {this.props.modelsInitialized && this.renderContent()}
-
+ visible && (
+ {
+ runInference(
+ taskInstance,
+ models
+ .filter((model) => model.name === selectedModel)[0],
+ mapping,
+ cleanOut,
+ );
+ closeDialog();
+ }}
+ onCancel={(): void => closeDialog()}
+ okButtonProps={{ disabled: !enabledSubmit }}
+ title='Automatic annotation'
+ visible
+ >
+ {!modelsInitialized
+ && }
+ {modelsInitialized && this.renderContent()}
+
+ )
);
}
-}
\ No newline at end of file
+}
diff --git a/cvat-ui/src/components/models-page/built-model-item.tsx b/cvat-ui/src/components/models-page/built-model-item.tsx
index 0bfd1bb71501..d03021546753 100644
--- a/cvat-ui/src/components/models-page/built-model-item.tsx
+++ b/cvat-ui/src/components/models-page/built-model-item.tsx
@@ -15,7 +15,9 @@ interface Props {
model: Model;
}
-export default function BuiltModelItemComponent(props: Props) {
+export default function BuiltModelItemComponent(props: Props): JSX.Element {
+ const { model } = props;
+
return (
@@ -23,24 +25,26 @@ export default function BuiltModelItemComponent(props: Props) {
- {props.model.name}
+ {model.name}
-
+
);
}
diff --git a/cvat-ui/src/components/models-page/built-models-list.tsx b/cvat-ui/src/components/models-page/built-models-list.tsx
index 50e76de58111..c0ca093c8c00 100644
--- a/cvat-ui/src/components/models-page/built-models-list.tsx
+++ b/cvat-ui/src/components/models-page/built-models-list.tsx
@@ -14,10 +14,9 @@ interface Props {
models: Model[];
}
-export default function IntegratedModelsListComponent(props: Props) {
- const items = props.models.map((model) =>
-
- );
+export default function IntegratedModelsListComponent(props: Props): JSX.Element {
+ const { models } = props;
+ const items = models.map((model) => );
return (
<>
@@ -28,12 +27,12 @@ export default function IntegratedModelsListComponent(props: Props) {
-
+
- {'Framework'}
+ Framework
- {'Name'}
+ Name
Labels
diff --git a/cvat-ui/src/components/models-page/empty-list.tsx b/cvat-ui/src/components/models-page/empty-list.tsx
index 1746eaa8471a..b48417a03d29 100644
--- a/cvat-ui/src/components/models-page/empty-list.tsx
+++ b/cvat-ui/src/components/models-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 models uploaded yet ...'}
+ No models uploaded yet ...
- {'To annotate your tasks automatically'}
+ To annotate your tasks automatically
-
+
- {'upload a new model'}
+ upload a new model
-
- )
-}
\ No newline at end of file
+ );
+}
diff --git a/cvat-ui/src/components/models-page/models-page.tsx b/cvat-ui/src/components/models-page/models-page.tsx
index 8db88abedf09..3aca57e49bc9 100644
--- a/cvat-ui/src/components/models-page/models-page.tsx
+++ b/cvat-ui/src/components/models-page/models-page.tsx
@@ -22,36 +22,48 @@ interface Props {
deleteModel(id: number): void;
}
-export default function ModelsPageComponent(props: Props) {
- if (!props.modelsInitialized && !props.modelsFetching) {
- props.getModels();
- return (
-
- );
- } else {
- const uploadedModels = props.models.filter((model) => model.id !== null);
- const integratedModels = props.models.filter((model) => model.id === null);
+export default function ModelsPageComponent(props: Props): JSX.Element {
+ const {
+ installedAutoAnnotation,
+ installedTFSegmentation,
+ installedTFAnnotation,
+ modelsInitialized,
+ modelsFetching,
+ registeredUsers,
+ models,
+
+ deleteModel,
+ } = props;
+ if (!modelsInitialized && !modelsFetching) {
+ props.getModels();
return (
-
-
- { !!integratedModels.length &&
-
- }
- { !!uploadedModels.length &&
-
- }
- { props.installedAutoAnnotation &&
- !uploadedModels.length &&
- !props.installedTFAnnotation &&
- !props.installedTFSegmentation &&
-
- }
-
+
);
}
+
+ const uploadedModels = models.filter((model) => model.id !== null);
+ const integratedModels = models.filter((model) => model.id === null);
+
+ return (
+
+
+ { !!integratedModels.length
+ &&
+ }
+ { !!uploadedModels.length && (
+
+ )}
+ { installedAutoAnnotation
+ && !uploadedModels.length
+ && !installedTFAnnotation
+ && !installedTFSegmentation
+ &&
+ }
+
+ );
}
diff --git a/cvat-ui/src/components/models-page/top-bar.tsx b/cvat-ui/src/components/models-page/top-bar.tsx
index 2b394cd24c7e..b28c7d024710 100644
--- a/cvat-ui/src/components/models-page/top-bar.tsx
+++ b/cvat-ui/src/components/models-page/top-bar.tsx
@@ -14,26 +14,40 @@ type Props = {
installedAutoAnnotation: boolean;
} & RouteComponentProps;
-function TopBarComponent(props: Props) {
+function TopBarComponent(props: Props): JSX.Element {
+ const {
+ installedAutoAnnotation,
+ history,
+ } = props;
+
return (
Models
- { props.installedAutoAnnotation &&
- props.history.push('/models/create')
- }> Create new model
+ { installedAutoAnnotation
+ && (
+ history.push('/models/create')
+ }
+ >
+ Create new model
+
+ )
}
- )
+ );
}
export default withRouter(TopBarComponent);
diff --git a/cvat-ui/src/components/models-page/uploaded-model-item.tsx b/cvat-ui/src/components/models-page/uploaded-model-item.tsx
index bad3f1a63cae..bbd6c565f3dd 100644
--- a/cvat-ui/src/components/models-page/uploaded-model-item.tsx
+++ b/cvat-ui/src/components/models-page/uploaded-model-item.tsx
@@ -21,8 +21,13 @@ interface Props {
onDelete(): void;
}
-export default function UploadedModelItem(props: Props) {
- const subMenuIcon = () => ();
+export default function UploadedModelItem(props: Props): JSX.Element {
+ const subMenuIcon = (): JSX.Element => ();
+ const {
+ model,
+ owner,
+ onDelete,
+ } = props;
return (
@@ -31,43 +36,52 @@ export default function UploadedModelItem(props: Props) {
- {props.model.name}
+ {model.name}
- {props.owner ? props.owner.username : 'undefined'}
+ {owner ? owner.username : 'undefined'}
- {moment(props.model.uploadDate).format('MMMM Do YYYY')}
+ {moment(model.uploadDate).format('MMMM Do YYYY')}
Actions
- {
- props.onDelete();
- }}key='delete'>Delete
+ {
+ onDelete();
+ }}
+ key='delete'
+ >
+ Delete
+
- }>
-
+ )}
+ >
+
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..f5eca0df1887 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) => {
+ 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 }
From ba52e3e55628fda85925dae7631e5b051d4f7a12 Mon Sep 17 00:00:00 2001
From: Boris Sekachev
Date: Thu, 5 Dec 2019 18:24:24 +0300
Subject: [PATCH 08/17] Tasks page
---
cvat-ui/src/components/task-page/details.tsx | 362 ++++++++++--------
cvat-ui/src/components/task-page/job-list.tsx | 51 ++-
.../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 +-
5 files changed, 313 insertions(+), 222 deletions(-)
diff --git a/cvat-ui/src/components/task-page/details.tsx b/cvat-ui/src/components/task-page/details.tsx
index 355f2e279df9..71e59bc392dc 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) => {
+ 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 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(() => {
+ if (this.mounted) {
+ this.setState({
+ repositoryStatus: 'sync',
+ });
+ }
+ }).catch(() => {
+ 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}
- {
- window.open(bugTracker, '_blank');
- }} className='cvat-open-bug-tracker-button'>{'Open the issue'}
-
-
- );
- } else {
- return (
-
-
- {'Issue Tracker'}
-
- {'Not specified'}
+ Issue Tracker
+
+ {bugTracker}
+ {
+ // false positive
+ // eslint-disable-next-line
+ window.open(bugTracker, '_blank');
+ }}
+ className='cvat-open-bug-tracker-button'
+ >
+ Open the issue
+
);
}
+
+ 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) => 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) => 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..01086e28d371 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,25 @@ 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;
}
- jobInstance.assignee = userInstance;
- props.onJobUpdate(jobInstance);
+ onJobUpdate({
+ ...jobInstance,
+ assignee: userInstance,
+ });
}}
/>
);
@@ -129,4 +140,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) {
- }>
+ (
+
+ )}
+ >
Actions
-
+
);
-}
\ 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..07338f524968 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) => (
+
+ {user.username}
+
+ ))}
+
);
-}
\ No newline at end of file
+}
From 2583817566ddf7aa63726e977d50d2ddca9636cd Mon Sep 17 00:00:00 2001
From: Boris Sekachev
Date: Thu, 5 Dec 2019 18:43:52 +0300
Subject: [PATCH 09/17] Feedback and base app
---
cvat-ui/src/components/cvat-app.tsx | 206 +++++++++++++++++-----------
cvat-ui/src/components/feedback.tsx | 161 +++++++++++-----------
cvat-ui/src/index.tsx | 35 ++---
3 files changed, 211 insertions(+), 191 deletions(-)
diff --git a/cvat-ui/src/components/cvat-app.tsx b/cvat-ui/src/components/cvat-app.tsx
index 09e3d4762300..7b954d1b9fd5 100644
--- a/cvat-ui/src/components/cvat-app.tsx
+++ b/cvat-ui/src/components/cvat-app.tsx
@@ -46,28 +46,73 @@ type CVATAppProps = {
installedTFSegmentation: boolean;
notifications: NotificationsState;
user: any;
-}
+};
export default class CVATApplication extends React.PureComponent {
- constructor(props: any) {
- super(props);
+ public componentDidMount(): void {
+ const { verifyAuthorized } = this.props;
+ verifyAuthorized();
}
- private showMessages() {
- function showMessage(title: string) {
+ public componentDidUpdate(): void {
+ const {
+ loadFormats,
+ loadUsers,
+ initPlugins,
+ userInitialized,
+ formatsInitialized,
+ formatsFetching,
+ usersInitialized,
+ usersFetching,
+ pluginsInitialized,
+ pluginsFetching,
+ user,
+ } = this.props;
+
+ this.showErrors();
+ this.showMessages();
+
+ if (!userInitialized || user == null) {
+ // not authorized user
+ return;
+ }
+
+ if (!formatsInitialized && !formatsFetching) {
+ loadFormats();
+ }
+
+ if (!usersInitialized && !usersFetching) {
+ loadUsers();
+ }
+
+ if (!pluginsInitialized && !pluginsFetching) {
+ initPlugins();
+ }
+ }
+
+ private showMessages(): void {
+ function showMessage(title: string): void {
notification.info({
message: (
-
+
),
duration: null,
});
}
- const { tasks } = this.props.notifications.messages;
- const { models } = this.props.notifications.messages;
- let shown = !!tasks.loadingDone || !!models.inferenceDone;
+ const {
+ notifications,
+ resetMessages,
+ } = this.props;
+
+ const { tasks } = notifications.messages;
+ const { models } = notifications.messages;
+ const shown = !!tasks.loadingDone || !!models.inferenceDone;
if (tasks.loadingDone) {
showMessage(tasks.loadingDone);
@@ -77,18 +122,21 @@ export default class CVATApplication extends React.PureComponent {
}
if (shown) {
- this.props.resetMessages();
+ resetMessages();
}
}
- private showErrors() {
- function showError(title: string, _error: any) {
+ private showErrors(): void {
+ function showError(title: string, _error: any): void {
const error = _error.toString();
notification.error({
message: (
-
+
),
duration: null,
description: error.length > 200 ? '' : error,
@@ -97,14 +145,19 @@ export default class CVATApplication extends React.PureComponent {
console.error(error);
}
- const { auth } = this.props.notifications.errors;
- const { tasks } = this.props.notifications.errors;
- const { formats } = this.props.notifications.errors;
- const { users } = this.props.notifications.errors;
- const { share } = this.props.notifications.errors;
- const { models } = this.props.notifications.errors;
+ const {
+ notifications,
+ resetErrors,
+ } = this.props;
+
+ const { auth } = notifications.errors;
+ const { tasks } = notifications.errors;
+ const { formats } = notifications.errors;
+ const { users } = notifications.errors;
+ const { share } = notifications.errors;
+ const { models } = notifications.errors;
- let shown = !!auth.authorized || !!auth.login || !!auth.logout || !!auth.register
+ const shown = !!auth.authorized || !!auth.login || !!auth.logout || !!auth.register
|| !!tasks.fetching || !!tasks.updating || !!tasks.dumping || !!tasks.loading
|| !!tasks.exporting || !!tasks.deleting || !!tasks.creating || !!formats.fetching
|| !!users.fetching || !!share.fetching || !!models.creating || !!models.starting
@@ -169,89 +222,76 @@ export default class CVATApplication extends React.PureComponent {
showError(models.metaFetching.message, models.metaFetching.reason);
}
if (models.inferenceStatusFetching) {
- showError(models.inferenceStatusFetching.message, models.inferenceStatusFetching.reason);
+ showError(
+ models.inferenceStatusFetching.message,
+ models.inferenceStatusFetching.reason,
+ );
}
if (shown) {
- this.props.resetErrors();
- }
- }
-
- public componentDidMount() {
- this.props.verifyAuthorized();
- }
-
- public componentDidUpdate() {
- this.showErrors();
- this.showMessages();
-
- if (!this.props.userInitialized || this.props.user == null) {
- // not authorized user
- return;
- }
-
- if (!this.props.formatsInitialized && !this.props.formatsFetching) {
- this.props.loadFormats();
- }
-
- if (!this.props.usersInitialized && !this.props.usersFetching) {
- this.props.loadUsers();
- }
-
- if (!this.props.pluginsInitialized && !this.props.pluginsFetching) {
- this.props.initPlugins();
+ resetErrors();
}
}
// Where you go depends on your URL
- public render() {
- const readyForRender =
- (this.props.userInitialized && this.props.user == null) ||
- (this.props.userInitialized && this.props.formatsInitialized &&
- this.props.pluginsInitialized && this.props.usersInitialized);
+ public render(): JSX.Element {
+ const {
+ userInitialized,
+ usersInitialized,
+ pluginsInitialized,
+ formatsInitialized,
+ installedAutoAnnotation,
+ installedTFSegmentation,
+ installedTFAnnotation,
+ user,
+ } = this.props;
- const withModels = this.props.installedAutoAnnotation
- || this.props.installedTFAnnotation || this.props.installedTFSegmentation;
+ const readyForRender = (userInitialized && user == null)
+ || (userInitialized && formatsInitialized
+ && pluginsInitialized && usersInitialized);
+
+ const withModels = installedAutoAnnotation
+ || installedTFAnnotation || installedTFSegmentation;
if (readyForRender) {
- if (this.props.user) {
+ if (user) {
return (
-
-
-
-
- { withModels &&
- }
- { this.props.installedAutoAnnotation &&
- }
-
+
+
+
+
+ { withModels
+ && }
+ { installedAutoAnnotation
+ && }
+
-
-
+
+
);
- } else {
- return (
-
-
-
-
-
-
-
- );
}
- } else {
+
return (
-
+
+
+
+
+
+
+
);
}
+
+ return (
+
+ );
}
}
diff --git a/cvat-ui/src/components/feedback.tsx b/cvat-ui/src/components/feedback.tsx
index 475d3ed71884..ead88caee65c 100644
--- a/cvat-ui/src/components/feedback.tsx
+++ b/cvat-ui/src/components/feedback.tsx
@@ -31,88 +31,87 @@ interface State {
active: boolean;
}
-export default class Feedback extends React.PureComponent<{}, State> {
- public constructor(props: {}) {
- super(props);
- this.state = {
- active: false,
- }
- }
+function renderContent(): JSX.Element {
+ const githubURL = 'https://github.com/opencv/cvat';
+ const githubImage = 'https://raw.githubusercontent.com/opencv/'
+ + 'cvat/develop/cvat/apps/documentation/static/documentation/images/cvat.jpg';
+ const questionsURL = 'https://gitter.im/opencv-cvat/public';
+ const feedbackURL = 'https://gitter.im/opencv-cvat/public';
- private renderContent() {
- const githubURL = 'https://github.com/opencv/cvat';
- const githubImage = 'https://raw.githubusercontent.com/opencv/'
- + 'cvat/develop/cvat/apps/documentation/static/documentation/images/cvat.jpg';
- const questionsURL = 'https://gitter.im/opencv-cvat/public';
- const feedbackURL = 'https://gitter.im/opencv-cvat/public';
+ return (
+ <>
+
+
+ Star us on
+ GitHub
+
+
+
+
+ Leave a
+ feedback
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Do you need help? Contact us on
+ gitter
+
+ >
+ );
+}
- return (
- <>
-
-
- Star us on GitHub
-
-
-
-
- Leave a feedback
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Do you need help? Contact us on gitter
-
- >
- );
- }
+export default function Feedback(): JSX.Element {
+ const [visible, setVisible] = React.useState(false);
- public render() {
- return (
- <>
- Help to make CVAT better
- }
- content={this.renderContent()}
- visible={this.state.active}
+ return (
+ <>
+ Help to make CVAT better
+ }
+ content={renderContent()}
+ visible={visible}
+ >
+ {
+ setVisible(!visible);
+ }}
>
- {
- this.setState({
- active: !this.state.active,
- });
- }}>
- { this.state.active ? :
- }
-
-
- >
- );
- }
-}
\ No newline at end of file
+ { visible ?
+ : }
+
+
+ >
+ );
+}
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'),
+);
From c4bab65d85e956fcc079743853a0ddce0ebb1d67 Mon Sep 17 00:00:00 2001
From: Boris Sekachev
Date: Fri, 6 Dec 2019 12:15:23 +0300
Subject: [PATCH 10/17] Tasks page
---
.../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 | 180 ++++++++++--------
cvat-ui/src/components/tasks-page/top-bar.tsx | 41 ++--
cvat-ui/src/stylesheet.css | 4 +
6 files changed, 248 insertions(+), 188 deletions(-)
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..4c5461006146 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) => 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 (
- this.props.history.push(`/tasks/${id}`)
- }> Open
+ history.push(`/tasks/${id}`)}
+ >
+ Open
+
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..da7f79c13e13 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) => ,
);
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..25b2db39d795 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 };
+ const {
+ gettingQuery,
+ onGetTasks,
+ } = this.props;
+ const query = { ...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);
+ 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
- props.history.push('/tasks/create')
- }> Create new task
+ md={{ span: 11 }}
+ lg={{ span: 9 }}
+ xl={{ span: 8 }}
+ xxl={{ span: 7 }}
+ >
+ history.push('/tasks/create')
+ }
+ >
+ Create new task
+
>
- )
+ );
}
export default withRouter(TopBarComponent);
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;
}
From fc234eb48a12538840d6ff86c4c5d4bafe538fa6 Mon Sep 17 00:00:00 2001
From: Boris Sekachev
Date: Fri, 6 Dec 2019 12:32:49 +0300
Subject: [PATCH 11/17] Containers
---
.../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 ++++-----
16 files changed, 140 insertions(+), 186 deletions(-)
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..31021c1a0221 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) => 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 (
-
+
);
}
From 8b5b48b6174d5380118e3d8e4104f12624d6295d Mon Sep 17 00:00:00 2001
From: Boris Sekachev
Date: Fri, 6 Dec 2019 12:34:36 +0300
Subject: [PATCH 12/17] Reducers
---
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 +-
9 files changed, 20 insertions(+), 25 deletions(-)
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 {
From afefad922bc91c8f74ca9f2ff83f42cc00ee7174 Mon Sep 17 00:00:00 2001
From: Nobody
Date: Fri, 6 Dec 2019 10:38:19 +0000
Subject: [PATCH 13/17] Initial commit
From b4052c45a6d307b3ff6477fd2adc975ef16913f8 Mon Sep 17 00:00:00 2001
From: Nobody
Date: Fri, 6 Dec 2019 10:38:20 +0000
Subject: [PATCH 14/17] Initial commit
From d5b2a633ba4779affdce074459081b95aa2f6605 Mon Sep 17 00:00:00 2001
From: Nobody
Date: Fri, 6 Dec 2019 10:38:23 +0000
Subject: [PATCH 15/17] Initial commit
From cf8cf3b1f45b8c0fe2915ef1894c5a63405fdc2b Mon Sep 17 00:00:00 2001
From: Boris Sekachev
Date: Fri, 6 Dec 2019 13:50:49 +0300
Subject: [PATCH 16/17] Fixed additional issues
---
cvat-ui/.eslintrc.js | 1 +
.../components/actions-menu/actions-menu.tsx | 6 +++---
.../create-model-page/create-model-form.tsx | 2 +-
.../advanced-configuration-form.tsx | 2 +-
.../basic-configuration-form.tsx | 2 +-
.../create-task-page/create-task-content.tsx | 6 +++---
.../components/file-manager/file-manager.tsx | 2 +-
.../components/labels-editor/label-form.tsx | 8 ++++----
.../components/labels-editor/labels-editor.tsx | 2 +-
.../components/labels-editor/raw-viewer.tsx | 7 ++++---
.../src/components/login-page/login-form.tsx | 2 +-
.../src/components/login-page/login-page.tsx | 2 +-
.../model-runner-modal/model-runner-modal.tsx | 18 +++++++++---------
.../models-page/built-model-item.tsx | 2 +-
.../models-page/built-models-list.tsx | 4 +++-
.../src/components/models-page/models-page.tsx | 4 ++--
.../models-page/uploaded-model-item.tsx | 2 +-
.../models-page/uploaded-models-list.tsx | 2 +-
.../components/register-page/register-form.tsx | 2 +-
cvat-ui/src/components/task-page/details.tsx | 12 ++++++------
cvat-ui/src/components/task-page/job-list.tsx | 7 +++----
.../src/components/task-page/user-selector.tsx | 2 +-
.../src/components/tasks-page/task-item.tsx | 2 +-
.../src/components/tasks-page/task-list.tsx | 2 +-
.../src/containers/tasks-page/tasks-list.tsx | 2 +-
25 files changed, 53 insertions(+), 50 deletions(-)
diff --git a/cvat-ui/.eslintrc.js b/cvat-ui/.eslintrc.js
index 90bb054240ad..f40cac1879fe 100644
--- a/cvat-ui/.eslintrc.js
+++ b/cvat-ui/.eslintrc.js
@@ -28,6 +28,7 @@ module.exports = {
'@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],
diff --git a/cvat-ui/src/components/actions-menu/actions-menu.tsx b/cvat-ui/src/components/actions-menu/actions-menu.tsx
index 49a32a1c99ef..a9be862bba44 100644
--- a/cvat-ui/src/components/actions-menu/actions-menu.tsx
+++ b/cvat-ui/src/components/actions-menu/actions-menu.tsx
@@ -92,7 +92,7 @@ export default function ActionsMenuComponent(props: ActionsMenuComponentProps):
>
{
- dumpers.map((dumper) => DumperItemComponent({
+ dumpers.map((dumper): JSX.Element => DumperItemComponent({
dumper,
taskInstance: props.taskInstance,
dumpActivity: (props.dumpActivities || [])
@@ -103,7 +103,7 @@ export default function ActionsMenuComponent(props: ActionsMenuComponentProps):
{
- loaders.map((loader) => LoaderItemComponent({
+ loaders.map((loader): JSX.Element => LoaderItemComponent({
loader,
taskInstance: props.taskInstance,
loadActivity: props.loadActivity,
@@ -113,7 +113,7 @@ export default function ActionsMenuComponent(props: ActionsMenuComponentProps):
{
- exporters.map((exporter) => ExportItemComponent({
+ exporters.map((exporter): JSX.Element => ExportItemComponent({
exporter,
taskInstance: props.taskInstance,
exportActivity: (props.exportActivities || [])
diff --git a/cvat-ui/src/components/create-model-page/create-model-form.tsx b/cvat-ui/src/components/create-model-page/create-model-form.tsx
index df42cdda16fe..b33d83b0e756 100644
--- a/cvat-ui/src/components/create-model-page/create-model-form.tsx
+++ b/cvat-ui/src/components/create-model-page/create-model-form.tsx
@@ -18,7 +18,7 @@ export class CreateModelForm extends React.PureComponent {
public submit(): Promise<{name: string; global: boolean}> {
const { form } = this.props;
return new Promise((resolve, reject) => {
- form.validateFields((errors, values) => {
+ form.validateFields((errors, values): void => {
if (!errors) {
resolve({
name: values.name,
diff --git a/cvat-ui/src/components/create-task-page/advanced-configuration-form.tsx b/cvat-ui/src/components/create-task-page/advanced-configuration-form.tsx
index 29fcadcc4c39..c12cf88236d2 100644
--- a/cvat-ui/src/components/create-task-page/advanced-configuration-form.tsx
+++ b/cvat-ui/src/components/create-task-page/advanced-configuration-form.tsx
@@ -40,7 +40,7 @@ class AdvancedConfigurationForm extends React.PureComponent {
onSubmit,
} = this.props;
- form.validateFields((error, values) => {
+ form.validateFields((error, values): void => {
if (!error) {
const filteredValues = { ...values };
delete filteredValues.frameStep;
diff --git a/cvat-ui/src/components/create-task-page/basic-configuration-form.tsx b/cvat-ui/src/components/create-task-page/basic-configuration-form.tsx
index 805000f4b842..7bb56b65c5d2 100644
--- a/cvat-ui/src/components/create-task-page/basic-configuration-form.tsx
+++ b/cvat-ui/src/components/create-task-page/basic-configuration-form.tsx
@@ -22,7 +22,7 @@ class BasicConfigurationForm extends React.PureComponent {
onSubmit,
} = this.props;
- form.validateFields((error, values) => {
+ form.validateFields((error, values): void => {
if (!error) {
onSubmit({
name: values.name,
diff --git a/cvat-ui/src/components/create-task-page/create-task-content.tsx b/cvat-ui/src/components/create-task-page/create-task-content.tsx
index 07f3fb798ac9..f7d3347d1512 100644
--- a/cvat-ui/src/components/create-task-page/create-task-content.tsx
+++ b/cvat-ui/src/components/create-task-page/create-task-content.tsx
@@ -131,13 +131,13 @@ export default class CreateTaskContent extends React.PureComponent
return this.advancedConfigurationComponent.submit();
}
- return new Promise((resolve) => {
+ return new Promise((resolve): void => {
resolve();
});
- }).then(() => {
+ }).then((): void => {
const { onCreate } = this.props;
onCreate(this.state);
- }).catch(() => {
+ }).catch((): void => {
notification.error({
message: 'Could not create a task',
description: 'Please, check configuration you specified',
diff --git a/cvat-ui/src/components/file-manager/file-manager.tsx b/cvat-ui/src/components/file-manager/file-manager.tsx
index 3c3eca0d5bbb..1f12d563e6c2 100644
--- a/cvat-ui/src/components/file-manager/file-manager.tsx
+++ b/cvat-ui/src/components/file-manager/file-manager.tsx
@@ -59,7 +59,7 @@ export default class FileManager extends React.PureComponent {
}
private loadData = (key: string): Promise => new Promise(
- (resolve, reject) => {
+ (resolve, reject): void => {
const { onLoadData } = this.props;
const success = (): void => resolve();
diff --git a/cvat-ui/src/components/labels-editor/label-form.tsx b/cvat-ui/src/components/labels-editor/label-form.tsx
index 8f463c6b2e0c..ff76073f4136 100644
--- a/cvat-ui/src/components/labels-editor/label-form.tsx
+++ b/cvat-ui/src/components/labels-editor/label-form.tsx
@@ -52,12 +52,12 @@ class LabelForm extends React.PureComponent {
onSubmit,
} = this.props;
- form.validateFields((error, values) => {
+ form.validateFields((error, values): void => {
if (!error) {
onSubmit({
name: values.labelName,
id: label ? label.id : idGenerator(),
- attributes: values.keys.map((key: number, index: number) => (
+ attributes: values.keys.map((key: number, index: number): Attribute => (
{
name: values.attrName[key],
type: values.type[key],
@@ -223,7 +223,7 @@ class LabelForm extends React.PureComponent {
const validator = (_: any, strNumbers: string, callback: any): void => {
const numbers = strNumbers
.split(';')
- .map((number) => Number.parseFloat(number));
+ .map((number): number => Number.parseFloat(number));
if (numbers.length !== 3) {
callback('Invalid input');
}
@@ -470,7 +470,7 @@ class LabelForm extends React.PureComponent {
form.getFieldDecorator('keys', {
initialValue: label
- ? label.attributes.map((attr: Attribute) => attr.id)
+ ? label.attributes.map((attr: Attribute): number => attr.id)
: [],
});
diff --git a/cvat-ui/src/components/labels-editor/labels-editor.tsx b/cvat-ui/src/components/labels-editor/labels-editor.tsx
index 545dd5bbb0f2..912caf378c6c 100644
--- a/cvat-ui/src/components/labels-editor/labels-editor.tsx
+++ b/cvat-ui/src/components/labels-editor/labels-editor.tsx
@@ -179,7 +179,7 @@ export default class LabelsEditor
} = this.state;
const filteredUnsavedLabels = unsavedLabels.filter(
- (_label: Label) => _label.id !== label.id,
+ (_label: Label): boolean => _label.id !== label.id,
);
this.setState({
diff --git a/cvat-ui/src/components/labels-editor/raw-viewer.tsx b/cvat-ui/src/components/labels-editor/raw-viewer.tsx
index 0c7f5cd1dd32..f6af19673f2f 100644
--- a/cvat-ui/src/components/labels-editor/raw-viewer.tsx
+++ b/cvat-ui/src/components/labels-editor/raw-viewer.tsx
@@ -13,6 +13,7 @@ import { FormComponentProps } from 'antd/lib/form/Form';
import {
Label,
+ Attribute,
} from './common';
type Props = FormComponentProps & {
@@ -38,7 +39,7 @@ class RawViewer extends React.PureComponent {
} = this.props;
e.preventDefault();
- form.validateFields((error, values) => {
+ form.validateFields((error, values): void => {
if (!error) {
onSubmit(JSON.parse(values.labels));
}
@@ -47,11 +48,11 @@ class RawViewer extends React.PureComponent {
public render(): JSX.Element {
const { labels } = this.props;
- const convertedLabels = labels.map((label: any) => (
+ const convertedLabels = labels.map((label: any): Label => (
{
...label,
id: label.id < 0 ? undefined : label.id,
- attributes: label.attributes.map((attribute: any) => (
+ attributes: label.attributes.map((attribute: any): Attribute => (
{
...attribute,
id: attribute.id < 0 ? undefined : attribute.id,
diff --git a/cvat-ui/src/components/login-page/login-form.tsx b/cvat-ui/src/components/login-page/login-form.tsx
index 510747184368..e2afeef32164 100644
--- a/cvat-ui/src/components/login-page/login-form.tsx
+++ b/cvat-ui/src/components/login-page/login-form.tsx
@@ -25,7 +25,7 @@ class LoginFormComponent extends React.PureComponent {
onSubmit,
} = this.props;
- form.validateFields((error, values) => {
+ form.validateFields((error, values): void => {
if (!error) {
onSubmit(values);
}
diff --git a/cvat-ui/src/components/login-page/login-page.tsx b/cvat-ui/src/components/login-page/login-page.tsx
index d36dec17cfb6..56e6dd7249ee 100644
--- a/cvat-ui/src/components/login-page/login-page.tsx
+++ b/cvat-ui/src/components/login-page/login-page.tsx
@@ -45,7 +45,7 @@ function LoginPageComponent(props: LoginPageComponentProps & RouteComponentProps
New to CVAT? Create
- an account
+ an account
diff --git a/cvat-ui/src/components/model-runner-modal/model-runner-modal.tsx b/cvat-ui/src/components/model-runner-modal/model-runner-modal.tsx
index bc5d5cd3edb9..dec8bb2dbbcb 100644
--- a/cvat-ui/src/components/model-runner-modal/model-runner-modal.tsx
+++ b/cvat-ui/src/components/model-runner-modal/model-runner-modal.tsx
@@ -118,13 +118,13 @@ export default class ModelRunnerModalComponent extends React.PureComponent label.name);
+ .map((label: any): string => label.name);
const [defaultMapping, defaultColors]: StringObject[] = selectedModelInstance.labels
- .reduce((acc: StringObject[], label) => {
+ .reduce((acc: StringObject[], label): StringObject[] => {
if (taskLabels.includes(label)) {
acc[0][label] = label;
acc[1][label] = nextColor();
- taskLabels = taskLabels.filter((_label) => _label !== label);
+ taskLabels = taskLabels.filter((_label): boolean => _label !== label);
}
return acc;
@@ -153,7 +153,7 @@ export default class ModelRunnerModalComponent extends React.PureComponent
- {models.map((model) => (
+ {models.map((model): JSX.Element => (
{model.name}
@@ -250,7 +250,7 @@ export default class ModelRunnerModalComponent extends React.PureComponent
- {options.map((label: string) => (
+ {options.map((label: string): JSX.Element => (
{label}
@@ -301,7 +301,7 @@ export default class ModelRunnerModalComponent extends React.PureComponent _model.name === selectedModel)[0];
+ .filter((_model): boolean => _model.name === selectedModel)[0];
const excludedLabels: {
model: string[];
@@ -330,7 +330,7 @@ export default class ModelRunnerModalComponent extends React.PureComponent label.name,
- ).filter((label: string) => !excludedLabels.task.includes(label));
+ ).filter((label: string): boolean => !excludedLabels.task.includes(label));
const mappingISAvailable = !!availableModelLabels.length
&& !!availableTaskLabels.length;
@@ -378,7 +378,7 @@ export default class ModelRunnerModalComponent extends React.PureComponent model.name === selectedModel,
+ (model): boolean => model.name === selectedModel,
)[0];
const enabledSubmit = (!!activeModel
@@ -394,7 +394,7 @@ export default class ModelRunnerModalComponent extends React.PureComponent model.name === selectedModel)[0],
+ .filter((model): boolean => model.name === selectedModel)[0],
mapping,
cleanOut,
);
diff --git a/cvat-ui/src/components/models-page/built-model-item.tsx b/cvat-ui/src/components/models-page/built-model-item.tsx
index d03021546753..2e0adfa1c385 100644
--- a/cvat-ui/src/components/models-page/built-model-item.tsx
+++ b/cvat-ui/src/components/models-page/built-model-item.tsx
@@ -36,7 +36,7 @@ export default function BuiltModelItemComponent(props: Props): JSX.Element {
value='Supported labels'
>
{model.labels.map(
- (label) => (
+ (label): JSX.Element => (
{label}
diff --git a/cvat-ui/src/components/models-page/built-models-list.tsx b/cvat-ui/src/components/models-page/built-models-list.tsx
index c0ca093c8c00..5ce892e64c8b 100644
--- a/cvat-ui/src/components/models-page/built-models-list.tsx
+++ b/cvat-ui/src/components/models-page/built-models-list.tsx
@@ -16,7 +16,9 @@ interface Props {
export default function IntegratedModelsListComponent(props: Props): JSX.Element {
const { models } = props;
- const items = models.map((model) => );
+ const items = models.map((model): JSX.Element => (
+
+ ));
return (
<>
diff --git a/cvat-ui/src/components/models-page/models-page.tsx b/cvat-ui/src/components/models-page/models-page.tsx
index 3aca57e49bc9..bd26271dc8de 100644
--- a/cvat-ui/src/components/models-page/models-page.tsx
+++ b/cvat-ui/src/components/models-page/models-page.tsx
@@ -42,8 +42,8 @@ export default function ModelsPageComponent(props: Props): JSX.Element {
);
}
- const uploadedModels = models.filter((model) => model.id !== null);
- const integratedModels = models.filter((model) => model.id === null);
+ const uploadedModels = models.filter((model): boolean => model.id !== null);
+ const integratedModels = models.filter((model): boolean => model.id === null);
return (
diff --git a/cvat-ui/src/components/models-page/uploaded-model-item.tsx b/cvat-ui/src/components/models-page/uploaded-model-item.tsx
index bbd6c565f3dd..9f93246b4746 100644
--- a/cvat-ui/src/components/models-page/uploaded-model-item.tsx
+++ b/cvat-ui/src/components/models-page/uploaded-model-item.tsx
@@ -57,7 +57,7 @@ export default function UploadedModelItem(props: Props): JSX.Element {
value='Supported labels'
>
{model.labels.map(
- (label) => (
+ (label): JSX.Element => (
{label}
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 f5eca0df1887..233359293abc 100644
--- a/cvat-ui/src/components/models-page/uploaded-models-list.tsx
+++ b/cvat-ui/src/components/models-page/uploaded-models-list.tsx
@@ -23,7 +23,7 @@ export default function UploadedModelsListComponent(props: Props): JSX.Element {
deleteModel,
} = props;
- const items = models.map((model) => {
+ const items = models.map((model): JSX.Element => {
const owner = registeredUsers.filter((user) => user.id === model.ownerID)[0];
return (
{
onSubmit,
} = this.props;
- form.validateFields((error, values) => {
+ form.validateFields((error, values): void => {
if (!error) {
onSubmit(values);
}
diff --git a/cvat-ui/src/components/task-page/details.tsx b/cvat-ui/src/components/task-page/details.tsx
index 71e59bc392dc..52425be8c7ce 100644
--- a/cvat-ui/src/components/task-page/details.tsx
+++ b/cvat-ui/src/components/task-page/details.tsx
@@ -60,7 +60,7 @@ export default class DetailsComponent extends React.PureComponent
this.mounted = true;
getReposData(taskInstance.id)
- .then((data) => {
+ .then((data): void => {
if (data !== null && this.mounted) {
if (data.status.error) {
notification.error({
@@ -77,7 +77,7 @@ export default class DetailsComponent extends React.PureComponent
repository: data.url,
});
}
- }).catch((error) => {
+ }).catch((error): void => {
if (this.mounted) {
notification.error({
message: 'Could not receive repository status',
@@ -272,13 +272,13 @@ export default class DetailsComponent extends React.PureComponent
repositoryStatus: 'syncing',
});
- syncRepos(taskInstance.id).then(() => {
+ syncRepos(taskInstance.id).then((): void => {
if (this.mounted) {
this.setState({
repositoryStatus: 'sync',
});
}
- }).catch(() => {
+ }).catch((): void => {
if (this.mounted) {
this.setState({
repositoryStatus: '!sync',
@@ -374,11 +374,11 @@ export default class DetailsComponent extends React.PureComponent
label.toJSON(),
+ (label: any): string => label.toJSON(),
)}
onSubmit={(labels: any[]): void => {
taskInstance.labels = labels
- .map((labelData) => new core.classes.Label(labelData));
+ .map((labelData): any => new core.classes.Label(labelData));
onTaskUpdate(taskInstance);
}}
/>
diff --git a/cvat-ui/src/components/task-page/job-list.tsx b/cvat-ui/src/components/task-page/job-list.tsx
index 01086e28d371..ad13707d2462 100644
--- a/cvat-ui/src/components/task-page/job-list.tsx
+++ b/cvat-ui/src/components/task-page/job-list.tsx
@@ -89,10 +89,9 @@ export default function JobListComponent(props: Props): JSX.Element {
userInstance = null;
}
- onJobUpdate({
- ...jobInstance,
- assignee: userInstance,
- });
+ // eslint-disable-next-line
+ jobInstance.assignee = userInstance;
+ onJobUpdate(jobInstance);
}}
/>
);
diff --git a/cvat-ui/src/components/task-page/user-selector.tsx b/cvat-ui/src/components/task-page/user-selector.tsx
index 07338f524968..b58b85a90c41 100644
--- a/cvat-ui/src/components/task-page/user-selector.tsx
+++ b/cvat-ui/src/components/task-page/user-selector.tsx
@@ -26,7 +26,7 @@ export default function UserSelector(props: Props): JSX.Element {
onChange={onChange}
>
—
- { users.map((user) => (
+ { users.map((user): JSX.Element => (
{user.username}
diff --git a/cvat-ui/src/components/tasks-page/task-item.tsx b/cvat-ui/src/components/tasks-page/task-item.tsx
index 4c5461006146..c7322cf59058 100644
--- a/cvat-ui/src/components/tasks-page/task-item.tsx
+++ b/cvat-ui/src/components/tasks-page/task-item.tsx
@@ -74,7 +74,7 @@ class TaskItemComponent extends React.PureComponent job.status === 'completed',
+ (job: any): boolean => job.status === 'completed',
).length;
// Progress appearence depends on number of jobs
diff --git a/cvat-ui/src/components/tasks-page/task-list.tsx b/cvat-ui/src/components/tasks-page/task-list.tsx
index da7f79c13e13..ce8381096004 100644
--- a/cvat-ui/src/components/tasks-page/task-list.tsx
+++ b/cvat-ui/src/components/tasks-page/task-list.tsx
@@ -23,7 +23,7 @@ export default function TaskListComponent(props: ContentListProps): JSX.Element
onSwitchPage,
} = props;
const taskViews = currentTasksIndexes.map(
- (tid, id) => ,
+ (tid, id): 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 31021c1a0221..7afd17b8de23 100644
--- a/cvat-ui/src/containers/tasks-page/tasks-list.tsx
+++ b/cvat-ui/src/containers/tasks-page/tasks-list.tsx
@@ -50,7 +50,7 @@ function TasksListContainer(props: TasksListContainerProps): JSX.Element {
return (
task.instance.id)}
+ currentTasksIndexes={tasks.current.map((task): number => task.instance.id)}
currentPage={tasks.gettingQuery.page}
numberOfTasks={tasks.count}
/>
From 0b5ab47fe6f7c523cbbe9ebb3ab2f1ef75b007c9 Mon Sep 17 00:00:00 2001
From: Boris Sekachev
Date: Fri, 6 Dec 2019 14:02:29 +0300
Subject: [PATCH 17/17] Small pagination fix
---
cvat-ui/src/components/tasks-page/tasks-page.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cvat-ui/src/components/tasks-page/tasks-page.tsx b/cvat-ui/src/components/tasks-page/tasks-page.tsx
index 25b2db39d795..a0ebf786abbd 100644
--- a/cvat-ui/src/components/tasks-page/tasks-page.tsx
+++ b/cvat-ui/src/components/tasks-page/tasks-page.tsx
@@ -124,8 +124,8 @@ class TasksPageComponent extends React.PureComponent