From 34462daf8e24b7a9bb2158cbc31821254f474a32 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Fri, 5 Jul 2019 11:57:18 +0200 Subject: [PATCH 01/69] Setup TypeScript --- package-lock.json | 92 ++++++++++++++++++++++++++++++++++++++++++++--- package.json | 11 ++++-- tsconfig.json | 40 +++++++++++++++++++++ tslint.json | 89 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 226 insertions(+), 6 deletions(-) create mode 100644 tsconfig.json create mode 100644 tslint.json diff --git a/package-lock.json b/package-lock.json index ec603580ef..322a613c4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -762,6 +762,15 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-syntax-typescript": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.3.3.tgz", + "integrity": "sha512-dGwbSMA1YhVS8+31CnPR7LB4pcbrzcV99wQzby4uAfrkZPYZlQ7ImwdpzLqi6Z6IL02b8IAL379CaMwo0x5Lag==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/plugin-transform-arrow-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", @@ -1107,6 +1116,17 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-transform-typescript": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.5.0.tgz", + "integrity": "sha512-z3T4P70XJFUAHzLtEsmJ37BGVDj+55/KX8W8TBSBF0qk0KLazw8xlwVcRHacxNPgprzTdI4QWW+2eS6bTkQbCA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.5.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-typescript": "^7.2.0" + } + }, "@babel/plugin-transform-unicode-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", @@ -1218,6 +1238,16 @@ "@babel/plugin-transform-react-jsx-source": "^7.0.0" } }, + "@babel/preset-typescript": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.3.3.tgz", + "integrity": "sha512-mzMVuIP4lqtn4du2ynEfdO0+RYcslwrZiJHXu4MGaC1ctJiW2fyaeDrtjJGs7R/KebZ1sgowcIoWf4uRpEfKEg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.3.2" + } + }, "@babel/runtime": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.5.tgz", @@ -3034,10 +3064,9 @@ "dev": true }, "@types/node": { - "version": "12.0.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.10.tgz", - "integrity": "sha512-LcsGbPomWsad6wmMNv7nBLw7YYYyfdYcz6xryKYQhx89c3XXan+8Q6AJ43G5XDIaklaVkK3mE4fCb0SBvMiPSQ==", - "dev": true + "version": "12.0.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.12.tgz", + "integrity": "sha512-Uy0PN4R5vgBUXFoJrKryf5aTk3kJ8Rv3PdlHjl6UaX+Cqp1QE0yPQ68MPXGrZOfG7gZVNDIJZYyot0B9ubXUrQ==" }, "@types/normalize-package-data": { "version": "2.4.0", @@ -3061,6 +3090,14 @@ "csstype": "^2.2.0" } }, + "@types/react-dom": { + "version": "16.8.4", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.8.4.tgz", + "integrity": "sha512-eIRpEW73DCzPIMaNBDP5pPIpK1KXyZwNgfxiVagb5iGiz6da+9A5hslSX6GAQKdO7SayVCS/Fr2kjqprgAvkfA==", + "requires": { + "@types/react": "*" + } + }, "@types/react-slick": { "version": "0.23.4", "resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.4.tgz", @@ -4602,6 +4639,12 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -6079,6 +6122,12 @@ "debug": "^2.6.0" } }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, "diff-sequences": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", @@ -17018,6 +17067,36 @@ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "dev": true }, + "tslint": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz", + "integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -17091,6 +17170,11 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typescript": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.2.tgz", + "integrity": "sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA==" + }, "ua-parser-js": { "version": "0.7.20", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.20.tgz", diff --git a/package.json b/package.json index 7eac7e8377..6b56453e0a 100644 --- a/package.json +++ b/package.json @@ -58,17 +58,18 @@ "coveralls": "cat coverage/lcov.info | coveralls", "prepublishOnly": "npm run build", "lint:styleguide": "eslint -c .eslint-styleguide.js --ext md src/", - "lint:src": "eslint -c .eslint-src.js --ext js,jsx src/", + "lint:src": "tslint --project tsconfig.json --config tslint.json && tsc --noEmit --project tsconfig.json", "lint": "npm run lint:styleguide && npm run lint:src", "lint:fix": "npm run lint:styleguide -- --fix && npm run lint:src -- --fix", "start:styleguide": "styleguidist server", "build:styleguide": "npm run clean:build && styleguidist build", - "build:dist": "npm run clean:dist && BABEL_ENV=build babel src --out-dir dist --copy-files --ignore spec.js,example.js,.md", + "build:dist": "npm run clean:dist && BABEL_ENV=build tsc -p ./ && copyfiles \"./src/**/*.css\" dist --up 1", "build:all": "npm run build:styleguide && npm run build:dist", "build": "npm run test -- --coverage && npm run build:all", "release": "np --no-yarn && git push https://github.com/terrestris/react-geo.git master --tags" }, "peerDependencies": { + "@types/react": "^16.8.23", "antd": "^3.0", "ol": "^6.0", "react": "^16.0" @@ -77,6 +78,8 @@ "@terrestris/base-util": "^0.2.2", "@terrestris/ol-util": "^3.0.1", "@turf/turf": "^5.1.6", + "@types/node": "^12.0.12", + "@types/react-dom": "^16.8.4", "ag-grid-community": "^21.2.1", "ag-grid-react": "^21.2.1", "lodash": "^4.17.15", @@ -89,6 +92,7 @@ "react-fa": "^5.0.0", "react-rnd": "^10.0.0", "shpjs": "^3.4.3", + "typescript": "^3.5.2", "url-parse": "^1.4.7", "validator": "^12.0.0" }, @@ -101,6 +105,8 @@ "@babel/polyfill": "^7.4.4", "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", + "@babel/preset-typescript": "^7.3.3", + "@types/react": "^16.8.23", "antd": "^3.23.2", "babel-eslint": "^10.0.3", "babel-jest": "^24.9.0", @@ -130,6 +136,7 @@ "regenerator-runtime": "^0.13.3", "rimraf": "^3.0.0", "style-loader": "^1.0.0", + "tslint": "^5.18.0", "url-loader": "^2.1.0", "webpack": "^4.40.2", "whatwg-fetch": "^3.0.0", diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000..017e94efd0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,40 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "declaration": true, + "outDir": "dist", + "module": "commonjs", + "target": "es5", + "lib": ["es7", "dom"], + "sourceMap": true, + "allowJs": false, + "jsx": "react", + "moduleResolution": "node", + "rootDir": "src", + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": false, //temporal + "strictNullChecks": false, + "suppressImplicitAnyIndexErrors": true, + "noUnusedLocals": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true + }, + "exclude": [ + "node_modules", + "build", + "browser", + "config", + "dist", + "scripts", + "coverage", + "acceptance-tests", + "webpack", + "jest", + "coverage", + "src/Util/**", + "**.config.js", + "**/*.spec.tsx" + ] +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000000..d5a03f7209 --- /dev/null +++ b/tslint.json @@ -0,0 +1,89 @@ +{ + "defaultSeverity": "warning", + "rules": { + "align": [ + true, + "parameters", + "statements" + ], + "ban": false, + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "curly": true, + "eofline": true, + "forin": true, + "indent": [ true, "spaces", 2 ], + "interface-name": [true, "never-prefix"], + "jsdoc-format": true, + "jsx-no-lambda": false, + "jsx-no-multiline-js": false, + "label-position": true, + "max-line-length": [ true, 120 ], + "member-ordering": [ + true, + { + "order": [ + "public-instance-method" + ] + } + ], + "no-any": false, + "no-arg": true, + "no-bitwise": true, + "no-console": false, + "no-consecutive-blank-lines": true, + "no-construct": true, + "no-debugger": false, + "no-duplicate-variable": true, + "no-empty": true, + "no-eval": true, + "no-shadowed-variable": true, + "no-string-literal": true, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": true, + "no-unused-expression": true, + "no-use-before-declare": true, + "one-line": [ + true, + "check-catch", + "check-else", + "check-open-brace", + "check-whitespace" + ], + "quotemark": [true, "single", "jsx-double"], + "radix": true, + "semicolon": [true, "always"], + "switch-default": true, + "trailing-comma": [false], + "triple-equals": [ true, "allow-null-check" ], + "typedef": [ + true, + "parameter", + "property-declaration" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"], + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-module", + "check-operator", + "check-separator", + "check-type", + "check-typecast" + ] + } +} From e5eeff296913b2853f5f6294c47af82aa6f04d94 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Fri, 5 Jul 2019 11:59:56 +0200 Subject: [PATCH 02/69] Transforms constants to TypeScript --- src/{constants.js => constants.ts} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/{constants.js => constants.ts} (59%) diff --git a/src/constants.js b/src/constants.ts similarity index 59% rename from src/constants.js rename to src/constants.ts index 33d1f64658..a5aad2a617 100644 --- a/src/constants.js +++ b/src/constants.ts @@ -1,3 +1,3 @@ const CSS_PREFIX = 'react-geo-'; -export {CSS_PREFIX}; +export { CSS_PREFIX }; From 28e5ecf7fbe5a7972c8b395411456b2ef324a9a4 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Fri, 5 Jul 2019 12:00:26 +0200 Subject: [PATCH 03/69] Transforms UserChip to TypeScript --- .../{UserChip.spec.jsx => UserChip.spec.tsx} | 0 src/UserChip/{UserChip.jsx => UserChip.tsx} | 73 +++++++++---------- 2 files changed, 35 insertions(+), 38 deletions(-) rename src/UserChip/{UserChip.spec.jsx => UserChip.spec.tsx} (100%) rename src/UserChip/{UserChip.jsx => UserChip.tsx} (79%) diff --git a/src/UserChip/UserChip.spec.jsx b/src/UserChip/UserChip.spec.tsx similarity index 100% rename from src/UserChip/UserChip.spec.jsx rename to src/UserChip/UserChip.spec.tsx diff --git a/src/UserChip/UserChip.jsx b/src/UserChip/UserChip.tsx similarity index 79% rename from src/UserChip/UserChip.jsx rename to src/UserChip/UserChip.tsx index b7b9181e67..18515c02bb 100644 --- a/src/UserChip/UserChip.jsx +++ b/src/UserChip/UserChip.tsx @@ -1,71 +1,68 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { Avatar, Dropdown } from 'antd'; import './UserChip.less'; import { CSS_PREFIX } from '../constants'; -/** - * Class representing the user chip containing an image of the user and his/her - * name - * - * @class The UserChip - * @extends React.Component - */ -class UserChip extends React.Component { +// i18n +export interface UserChipLocale { +} +interface UserChipDefaultProps { /** - * The className added to this component. + * The user aname. * @type {String} - * @private */ - className = `${CSS_PREFIX}userchip` + userName: string; +} - static propTypes = { +// non default props +export interface UserChipProps extends Partial { /** * An optional CSS class which should be added. - * @type {String} - */ - className: PropTypes.string, - - /** - * The user aname. - * @type {String} */ - userName: PropTypes.string, - + className: string; /** * The image src. - * @type {String} */ - imageSrc: PropTypes.string, - + imageSrc: string; /** * The react element representing the user menu - * @type {Element} */ - userMenu: PropTypes.element, - + userMenu: React.ReactNode; /** * The style object - * @type {Object} */ - style: PropTypes.object - } + style: any; +} + +/** + * Class representing the user chip containing an image of the user and his/her + * name + * + * @class The UserChip + * @extends React.Component + */ +class UserChip extends React.Component { + + /** + * The className added to this component. + * @private + */ + className: string = `${CSS_PREFIX}userchip`; /** * The default properties. - * @type {Object} */ - static defaultProps = { + static defaultProps: UserChipDefaultProps = { userName: 'John Doe' - } + }; /** * Create a UserChip. * @constructs UserChip */ - constructor(props) { + constructor(props: UserChipProps) { super(props); } @@ -75,11 +72,11 @@ class UserChip extends React.Component { * to the initials. * e.g. 'John Doe' leads to 'JD' * - * @return {String} initials if the user name. + * @return Initials if the user name. * * @method getInitials */ - getInitials() { + getInitials(): string { let splittedName = this.props.userName.split(' '); let initals = []; splittedName.forEach((part) => { @@ -134,7 +131,7 @@ class UserChip extends React.Component { overlay={this.props.userMenu} trigger={['click']} getPopupContainer={() => { - return document.getElementsByClassName(this.className)[0]; + return document.getElementsByClassName(this.className)[0] as HTMLElement; }} > {this.getUserMenu()} From 058344709f22a46eaea4cb91a095fe5ffd2fff38 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Fri, 5 Jul 2019 12:11:42 +0200 Subject: [PATCH 04/69] Transforms Toolbar to TypeScript --- .../{Toolbar.spec.jsx => Toolbar.spec.tsx} | 0 src/Toolbar/{Toolbar.jsx => Toolbar.tsx} | 69 ++++++++----------- 2 files changed, 29 insertions(+), 40 deletions(-) rename src/Toolbar/{Toolbar.spec.jsx => Toolbar.spec.tsx} (100%) rename src/Toolbar/{Toolbar.jsx => Toolbar.tsx} (56%) diff --git a/src/Toolbar/Toolbar.spec.jsx b/src/Toolbar/Toolbar.spec.tsx similarity index 100% rename from src/Toolbar/Toolbar.spec.jsx rename to src/Toolbar/Toolbar.spec.tsx diff --git a/src/Toolbar/Toolbar.jsx b/src/Toolbar/Toolbar.tsx similarity index 56% rename from src/Toolbar/Toolbar.jsx rename to src/Toolbar/Toolbar.tsx index a5f18cdc02..cb277c8154 100644 --- a/src/Toolbar/Toolbar.jsx +++ b/src/Toolbar/Toolbar.tsx @@ -1,9 +1,31 @@ import React from 'react'; -import PropTypes from 'prop-types'; import './Toolbar.less'; import { CSS_PREFIX } from '../constants'; +// i18n +export interface ToolbarLocale { +} + +interface ToolbarDefaultProps { + /** + * The alignment of the sub components. + */ + alignment: 'horizontal' | 'vertical'; +} + +// non default props +export interface ToolbarProps extends Partial { + /** + * An optional CSS class which should be added. + */ + className: string; + /** + * The style object + */ + style: any; +} + /** * A base class representing a toolbar having n children * The child components of this toolbar can be aligned in vertical and @@ -12,54 +34,20 @@ import { CSS_PREFIX } from '../constants'; * @class The Toolbar * @extends React.Component */ -class Toolbar extends React.Component { +class Toolbar extends React.Component { /** * The className added to this component. - * @type {String} * @private */ - className = `${CSS_PREFIX}toolbar` - - /** - * The properties. - * @type {Object} - */ - static propTypes = { - - /** - * An optional CSS class which should be added. - * @type {String} - */ - className: PropTypes.string, - - /** - * The children. - * @type {Array} - */ - children: PropTypes.node, - - /** - * The alignment of the sub components. - * @type {String} - */ - alignment: PropTypes.oneOf(['horizontal', 'vertical']), - - /** - * An object containing style informations. Applied to Toolbar. - * @type {Boolean} - */ - style: PropTypes.object - } + className: string = `${CSS_PREFIX}toolbar`; /** * The default properties. - * @type {Object} */ - static defaultProps = { - children: [], + static defaultProps: ToolbarDefaultProps = { alignment: 'horizontal' - } + }; /** * The render function @@ -67,6 +55,7 @@ class Toolbar extends React.Component { render() { const { style, + children, className } = this.props; @@ -76,7 +65,7 @@ class Toolbar extends React.Component { return (
- {this.props.children} + {children}
); } From 7e84e1bc6e7d8f4f38cd755fdcfd4d340bdca792 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Fri, 5 Jul 2019 12:12:07 +0200 Subject: [PATCH 05/69] Adds @types/jest and @types/enzyme --- package-lock.json | 34 ++++++++++++++++++++++++++++++++++ package.json | 2 ++ 2 files changed, 36 insertions(+) diff --git a/package-lock.json b/package-lock.json index 322a613c4d..115908c29f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3002,6 +3002,25 @@ "@babel/types": "^7.3.0" } }, + "@types/cheerio": { + "version": "0.22.12", + "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.12.tgz", + "integrity": "sha512-aczowyAJNfrkBV+HS8DyAA87OnvkqGrrOmm5s7V6Jbgimzv/1ZoAy91cLJX8GQrUS60KufD7EIzA2LbK8HV4hg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/enzyme": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.1.tgz", + "integrity": "sha512-Jd2hvn3w/0rBH8qD2n+JLMq2GjmZoKTZc5TTg8q9cDnJ9jkR7gzPV+ZdipKwGkWpMRXKDm9kuc9UiUqsW5s20w==", + "dev": true, + "requires": { + "@types/cheerio": "*", + "@types/react": "*" + } + }, "@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", @@ -3044,6 +3063,21 @@ "@types/istanbul-lib-report": "*" } }, + "@types/jest": { + "version": "24.0.15", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.15.tgz", + "integrity": "sha512-MU1HIvWUme74stAoc3mgAi+aMlgKOudgEvQDIm1v4RkrDudBh1T+NFp5sftpBAdXdx1J0PbdpJ+M2EsSOi1djA==", + "dev": true, + "requires": { + "@types/jest-diff": "*" + } + }, + "@types/jest-diff": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz", + "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==", + "dev": true + }, "@types/lodash": { "version": "4.14.138", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.138.tgz", diff --git a/package.json b/package.json index 6b56453e0a..0530cb649c 100644 --- a/package.json +++ b/package.json @@ -106,6 +106,8 @@ "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", "@babel/preset-typescript": "^7.3.3", + "@types/enzyme": "^3.10.1", + "@types/jest": "^24.0.15", "@types/react": "^16.8.23", "antd": "^3.23.2", "babel-eslint": "^10.0.3", From b7069161c92465cfb0f635e6b25ef7f6288898a3 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Mon, 8 Jul 2019 09:58:40 +0200 Subject: [PATCH 06/69] Transforms Window to TypeScript --- package-lock.json | 8 ++ package.json | 1 + .../{Window.spec.jsx => Window.spec.tsx} | 0 src/Window/{Window.jsx => Window.tsx} | 114 +++++++++++------- 4 files changed, 81 insertions(+), 42 deletions(-) rename src/Window/{Window.spec.jsx => Window.spec.tsx} (100%) rename src/Window/{Window.jsx => Window.tsx} (64%) diff --git a/package-lock.json b/package-lock.json index 115908c29f..6f458025b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3132,6 +3132,14 @@ "@types/react": "*" } }, + "@types/react-rnd": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/react-rnd/-/react-rnd-7.4.4.tgz", + "integrity": "sha512-Rh9UdKFiV4fxh/05shQsU3RO+eH5anU6eZCo8NBzobEfB6QU50ISLVP24rEZtIXbYsiiwjo7w960aAZ6JicpMg==", + "requires": { + "@types/react": "*" + } + }, "@types/react-slick": { "version": "0.23.4", "resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.4.tgz", diff --git a/package.json b/package.json index 0530cb649c..2e0968ea5b 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,7 @@ "@turf/turf": "^5.1.6", "@types/node": "^12.0.12", "@types/react-dom": "^16.8.4", + "@types/react-rnd": "^7.4.4", "ag-grid-community": "^21.2.1", "ag-grid-react": "^21.2.1", "lodash": "^4.17.15", diff --git a/src/Window/Window.spec.jsx b/src/Window/Window.spec.tsx similarity index 100% rename from src/Window/Window.spec.jsx rename to src/Window/Window.spec.tsx diff --git a/src/Window/Window.jsx b/src/Window/Window.tsx similarity index 64% rename from src/Window/Window.jsx rename to src/Window/Window.tsx index f5175346dc..8d8e28ee77 100644 --- a/src/Window/Window.jsx +++ b/src/Window/Window.tsx @@ -1,6 +1,5 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import PropTypes from 'prop-types'; import uniqueId from 'lodash/uniqueId'; @@ -10,6 +9,61 @@ import Logger from '@terrestris/base-util/dist/Logger'; import { CSS_PREFIX } from '../constants'; import './Window.less'; +import { ResizeEnable } from 'react-rnd'; + +// i18n +export interface WindowLocale { +} + +interface WindowDefaultProps { + /** + * The id of the parent component + * default: app + */ + parentId: string; + /** + * The title text to be shown in the window header. + */ + title: string; + /** + * The resize options. + */ + resizeOpts: ResizeEnable | boolean; + /** + * Wheter the Window should be collapsible or not. + */ + collapsible: boolean; + /** + * Wheter the Window should be draggable or not. + */ + draggable: boolean; +} + +export interface WindowProps extends Partial { + /** + * Id of the component. Will be filled automatically if not provided. + */ + id: string; + /** + * An optional CSS class which should be added. + */ + className: string; + /** + * The children to show in the Window. + */ + children: React.ReactChildren; +} + +interface WindowState { + /** + * The user aname. + */ + resizing: boolean; + /** + * The id of the Window. + */ + id: string; +} /** * Window component that creates a React portal that renders children into a DOM @@ -19,63 +73,39 @@ import './Window.less'; * @class Window * @extends React.Component */ -export class Window extends React.Component { +export class Window extends React.Component { + + /** + * The parent Element of the Window. + * @private + */ + _parent: Element; + + /** + * The Element of the Window. + * @private + */ + _elementDiv: Element; /** * The className added to this component. - * @type {String} * @private */ - className = `${CSS_PREFIX}window-portal` - - /** - * The properties. - * @type {Object} - */ - static propTypes = { - /** - * id of the component - * will be filled automatically if not provided - * @type {String} - */ - id: PropTypes.string, - /** - * The id of the parent component - * default: app - * - * @type {String} - */ - parentId: PropTypes.string.isRequired, - /** - * An optional CSS class which should be added. - * @type {String} - */ - className: PropTypes.string, - /** - * The children to show in the Window. - * @type {node} - */ - children: PropTypes.node, - /** - * The title text to be shown in the window header. - * @type {string} - */ - title: PropTypes.string - } + className: string = `${CSS_PREFIX}window-portal`; - static defaultProps = { + static defaultProps: WindowDefaultProps = { parentId: 'app', title: 'Window', resizeOpts: true, collapsible: true, draggable: true - } + }; /** * Create a Window. * @constructs Window */ - constructor(props) { + constructor(props: WindowProps) { super(props); const id = props.id || uniqueId('window-'); From b7a7249e9df3dbdbb20bce284f8208d93ff6bcdd Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Mon, 8 Jul 2019 09:59:48 +0200 Subject: [PATCH 07/69] Adjust JS-Docs for TestUtil --- src/Util/TestUtil.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Util/TestUtil.js b/src/Util/TestUtil.js index a17f080a91..2708b27bc7 100644 --- a/src/Util/TestUtil.js +++ b/src/Util/TestUtil.js @@ -23,8 +23,8 @@ export class TestUtil { * Mounts the given component. * * @param {Component} Component The Component to render. - * @param {Object} props The props to be used. - * @param {Object} options The options to be set. + * @param {Object} [props] The props to be used. + * @param {Object} [options] The options to be set. */ static mountComponent = (Component, props, options) => { const wrapper = mount(, options); @@ -70,7 +70,7 @@ export class TestUtil { /** * Creates an ol map. * - * @param {Object} mapOpts Additional options for the map to create. + * @param {Object} [mapOpts] Additional options for the map to create. * @return {ol.Map} The ol map. */ static createMap = (mapOpts) => { @@ -114,8 +114,8 @@ export class TestUtil { * @param {string} type Event type. * @param {number} x Horizontal offset from map center. * @param {number} y Vertical offset from map center. - * @param {boolean} opt_shiftKey Shift key is pressed - * @param {boolean} dragging Whether the map is being dragged or not. + * @param {boolean} [opt_shiftKey] Shift key is pressed + * @param {boolean} [dragging] Whether the map is being dragged or not. */ static simulatePointerEvent = (map, type, x, y, opt_shiftKey, dragging) => { let viewport = map.getViewport(); @@ -133,7 +133,7 @@ export class TestUtil { /** * Creates and returns an empty vector layer. * - * @param {Object} properties The properties to set. + * @param {Object} [properties] The properties to set. * @return {ol.layer.Vector} The layer. */ static createVectorLayer = (properties) => { From 88af885a1ab65c50a5214ab4a47fc407ed817951 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Tue, 9 Jul 2019 09:39:49 +0200 Subject: [PATCH 08/69] Transforms TimeSlider to TypeScript --- package-lock.json | 8 + package.json | 1 + ...imeSlider.spec.jsx => TimeSlider.spec.tsx} | 0 src/Slider/{TimeSlider.jsx => TimeSlider.tsx} | 147 ++++++++++-------- 4 files changed, 87 insertions(+), 69 deletions(-) rename src/Slider/{TimeSlider.spec.jsx => TimeSlider.spec.tsx} (100%) rename src/Slider/{TimeSlider.jsx => TimeSlider.tsx} (61%) diff --git a/package-lock.json b/package-lock.json index 6f458025b1..4d4a01b7a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3097,6 +3097,14 @@ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", "dev": true }, + "@types/moment": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@types/moment/-/moment-2.13.0.tgz", + "integrity": "sha1-YE69GJvDvDShVIaJQE5hoqSqyJY=", + "requires": { + "moment": "*" + } + }, "@types/node": { "version": "12.0.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.12.tgz", diff --git a/package.json b/package.json index 2e0968ea5b..72ffd2514b 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "@terrestris/base-util": "^0.2.2", "@terrestris/ol-util": "^3.0.1", "@turf/turf": "^5.1.6", + "@types/moment": "^2.13.0", "@types/node": "^12.0.12", "@types/react-dom": "^16.8.4", "@types/react-rnd": "^7.4.4", diff --git a/src/Slider/TimeSlider.spec.jsx b/src/Slider/TimeSlider.spec.tsx similarity index 100% rename from src/Slider/TimeSlider.spec.jsx rename to src/Slider/TimeSlider.spec.tsx diff --git a/src/Slider/TimeSlider.jsx b/src/Slider/TimeSlider.tsx similarity index 61% rename from src/Slider/TimeSlider.jsx rename to src/Slider/TimeSlider.tsx index 3108d6635f..3fb57d725b 100644 --- a/src/Slider/TimeSlider.jsx +++ b/src/Slider/TimeSlider.tsx @@ -1,11 +1,69 @@ import React from 'react'; -import PropTypes from 'prop-types'; import moment from 'moment'; import { Slider } from 'antd'; import isArray from 'lodash/isArray'; import isObject from 'lodash/isObject'; +import { SliderMarks, SliderValue } from 'antd/lib/slider'; + +import { CSS_PREFIX } from '../constants'; + +// i18n +export interface TimeSliderLocale { +} + +interface TimeSliderDefaultProps { + /** + * Whether to allow range selection. + * @type {Boolean} + */ + useRange: boolean; + /** + * The default value(s). + */ + defaultValue: string[] | string; + /** + * The minimum value. + */ + min: string; + /** + * The maximum value. + */ + max: string; + /** + * Called when the value changes. + * @type {Function} + */ + onChange: (val: string | string[]) => void; + /** + * The current value(s). + * @type {Array | String} + */ + value: string[] | string; + /** + * The moment.js compliant format string for the slider tooltip. + */ + formatString: string; +} + +/** + * + * @export + * @interface TimeSliderProps + * @extends {Partial} + */ +export interface TimeSliderProps extends Partial { + /** + * An optional CSS class which should be added. + */ + className: string; + /** + * Tick mark of Slider, type of key must be TimeStamp ISOString, and must in + * closed interval min, max,each mark can declare its own style. + */ + marks: SliderMarks; +} /** * Customized slider that uses ISO 8601 time strings as input. @@ -13,65 +71,15 @@ import isObject from 'lodash/isObject'; * @class The TimeSlider * @extends React.Component */ -class TimeSlider extends React.Component { - - static propTypes = { - /** - * An optional CSS class which should be added. - * @type {String} - */ - className: PropTypes.string, - - /** - * Whether to allow range selection. - * @type {Boolean} - */ - useRange: PropTypes.bool, - - /** - * The default value(s). - * @type {Array | String} - */ - defaultValue: PropTypes.any, - - /** - * The minimum value. - * @type {String} - */ - min: PropTypes.string, - - /** - * The maximum value. - * @type {String} - */ - max: PropTypes.string, - - /** - * Tick mark of Slider, type of key must be TimeStamp ISOString, and must in - * closed interval min, max,each mark can declare its own style. - */ - marks: PropTypes.object, - - /** - * Called when the value changes. - * @type {Function} - */ - onChange: PropTypes.func, - - /** - * The current value(s). - * @type {Array | String} - */ - value: PropTypes.any, - - /** - * The moment.js compliant format string for the slider tooltip. - * @type {String} - */ - formatString: PropTypes.string - } +class TimeSlider extends React.Component { - static defaultProps = { + /** + * The className added to this component. + * @private + */ + className: string = `${CSS_PREFIX}timeslider`; + + static defaultProps: TimeSliderDefaultProps = { useRange: false, defaultValue: moment().toISOString(), min: moment().subtract(1, 'hour').toISOString(), @@ -79,7 +87,7 @@ class TimeSlider extends React.Component { onChange: () => undefined, value: moment().toISOString(), formatString: 'DD.MM. HH:mm' - } + }; /** * The constructor. @@ -87,9 +95,10 @@ class TimeSlider extends React.Component { * @constructs TimeSlider * @param {Object} props The properties. */ - constructor(props) { + constructor(props: TimeSliderProps) { super(props); + // TODO: State is never used. Can we remove this? this.state = this.convertTimestamps(); } @@ -110,13 +119,13 @@ class TimeSlider extends React.Component { * @param {Array | String} val the input value(s) * @return {Array | Number} the converted value(s) */ - convert(val) { + convert(val: string[] | string): SliderValue | undefined { if (val === undefined) { - return val; + return val as undefined; } return isArray(val) ? - val.map(iso => moment(iso).unix()) : - moment(val).unix(); + val.map(iso => moment(iso).unix()) as SliderValue : + moment(val).unix() as SliderValue; } /** @@ -125,12 +134,12 @@ class TimeSlider extends React.Component { * @param {Object} marks The marks prop. * @return {Object} The marks prop with converted keys. */ - convertMarks(marks) { + convertMarks(marks: SliderMarks) { let convertedMarks; if (isObject(marks)) { convertedMarks = {}; Object.keys(marks).forEach(key => { - const convertedKey = this.convert(key); + const convertedKey = this.convert(key) as number; convertedMarks[convertedKey] = marks[key]; }); } @@ -142,7 +151,7 @@ class TimeSlider extends React.Component { * @param {Number} unix unix timestamps * @return {String} the formatted timestamps */ - formatTimestamp(unix) { + formatTimestamp(unix: number): string { return moment(unix * 1000).format(this.props.formatString); } @@ -151,7 +160,7 @@ class TimeSlider extends React.Component { * timestrings. * @param {Array | Number} value the new value */ - valueUpdated(value) { + valueUpdated(value: number | number[]) { this.props.onChange(isArray(value) ? [moment(value[0] * 1000).toISOString(), moment(value[1] * 1000).toISOString()] : From 77fb988e0278f5586a5b9454b884a05708204e8f Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Tue, 9 Jul 2019 13:57:30 +0200 Subject: [PATCH 09/69] Transforms LayerTransparencySlider to TypeScript --- ...c.jsx => LayerTransparencySlider.spec.tsx} | 0 ...Slider.jsx => LayerTransparencySlider.tsx} | 51 +++++++++---------- 2 files changed, 24 insertions(+), 27 deletions(-) rename src/Slider/{LayerTransparencySlider.spec.jsx => LayerTransparencySlider.spec.tsx} (100%) rename src/Slider/{LayerTransparencySlider.jsx => LayerTransparencySlider.tsx} (68%) diff --git a/src/Slider/LayerTransparencySlider.spec.jsx b/src/Slider/LayerTransparencySlider.spec.tsx similarity index 100% rename from src/Slider/LayerTransparencySlider.spec.jsx rename to src/Slider/LayerTransparencySlider.spec.tsx diff --git a/src/Slider/LayerTransparencySlider.jsx b/src/Slider/LayerTransparencySlider.tsx similarity index 68% rename from src/Slider/LayerTransparencySlider.jsx rename to src/Slider/LayerTransparencySlider.tsx index 3bf24caf0c..4f6160cd49 100644 --- a/src/Slider/LayerTransparencySlider.jsx +++ b/src/Slider/LayerTransparencySlider.tsx @@ -1,36 +1,27 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { Slider } from 'antd'; import OlLayerBase from 'ol/layer/Base'; /** - * The LayerTransparencySlider. * - * @class The LayerTransparencySlider - * @extends React.Component + * @export + * @interface TimeSliderProps + * @extends {Partial} */ -class LayerTransparencySlider extends React.Component { - +export interface LayerTransparencySliderProps { /** - * The properties. - * @type {Object} + * The layer to handle. */ - static propTypes = { - /** - * The layer to handle. - * @type {ol.layer.Base} - */ - layer: PropTypes.instanceOf(OlLayerBase).isRequired - }; + layer: OlLayerBase; +} - /** - * Create the LayerTransparencySlider. - * - * @constructs LayerTransparencySlider - */ - constructor(props) { - super(props); - } +/** + * The LayerTransparencySlider. + * + * @class The LayerTransparencySlider + * @extends React.Component + */ +class LayerTransparencySlider extends React.Component { /** * Sets the transparency to the provided layer. @@ -39,11 +30,14 @@ class LayerTransparencySlider extends React.Component { * between 0 (fully visible) and 100 (fully * transparent). */ - setLayerTransparency(transparency) { + setLayerTransparency(transparency: number) { + const { + layer + } = this.props; let opacity = 1 - (transparency / 100); // Round the opacity to two digits. opacity = Math.round((opacity) * 100) / 100; - this.props.layer.setOpacity(opacity); + layer.setOpacity(opacity); } /** @@ -52,8 +46,11 @@ class LayerTransparencySlider extends React.Component { * @return {Number} The transparency of the layer. */ getLayerTransparency() { + const { + layer + } = this.props; // 1 = fully opaque/visible. - let opacity = this.props.layer.getOpacity(); + let opacity = layer.getOpacity(); let transparency = (1 - opacity) * 100; // Remove any digits. transparency = Math.round(transparency); @@ -74,7 +71,7 @@ class LayerTransparencySlider extends React.Component { tipFormatter={value => `${value}%`} defaultValue={this.getLayerTransparency()} onChange={(value) => { - this.setLayerTransparency(value); + this.setLayerTransparency(value as number); }} {...passThroughProps} /> From 0b6c0d38d755fb2f794da77f4ebd484f65d2ccee Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Tue, 9 Jul 2019 14:07:06 +0200 Subject: [PATCH 10/69] Transforms MultiLayerSlider to TypeScript --- ...der.spec.jsx => MultiLayerSlider.spec.tsx} | 0 ...tiLayerSlider.jsx => MultiLayerSlider.tsx} | 97 +++++++++++-------- 2 files changed, 56 insertions(+), 41 deletions(-) rename src/Slider/MultiLayerSlider/{MultiLayerSlider.spec.jsx => MultiLayerSlider.spec.tsx} (100%) rename src/Slider/MultiLayerSlider/{MultiLayerSlider.jsx => MultiLayerSlider.tsx} (68%) diff --git a/src/Slider/MultiLayerSlider/MultiLayerSlider.spec.jsx b/src/Slider/MultiLayerSlider/MultiLayerSlider.spec.tsx similarity index 100% rename from src/Slider/MultiLayerSlider/MultiLayerSlider.spec.jsx rename to src/Slider/MultiLayerSlider/MultiLayerSlider.spec.tsx diff --git a/src/Slider/MultiLayerSlider/MultiLayerSlider.jsx b/src/Slider/MultiLayerSlider/MultiLayerSlider.tsx similarity index 68% rename from src/Slider/MultiLayerSlider/MultiLayerSlider.jsx rename to src/Slider/MultiLayerSlider/MultiLayerSlider.tsx index 803cfa885c..a865d4a21d 100644 --- a/src/Slider/MultiLayerSlider/MultiLayerSlider.jsx +++ b/src/Slider/MultiLayerSlider/MultiLayerSlider.tsx @@ -1,9 +1,34 @@ import React from 'react'; -import PropTypes from 'prop-types'; import OlLayerBase from 'ol/layer/Base'; import { Slider } from 'antd'; import { CSS_PREFIX } from '../../constants'; +import { SliderValue } from 'antd/lib/slider'; + +interface MultiLayerSliderDefaultProps { + /** + * The layers that should be handled. Default is: `[]`. + * + */ + layers: OlLayerBase[]; + /** + * The default value(s). Default is `0` + */ + defaultValue: SliderValue; +} + +/** + * + * @export + * @interface TimeSliderProps + * @extends {Partial} + */ +export interface MultiLayerSliderProps extends Partial { + /** + * An optional CSS class which should be added. + */ + className?: string; +} /** * Slider that changes opacity on a set of layers. @@ -11,7 +36,7 @@ import { CSS_PREFIX } from '../../constants'; * @class The MultiLayerSlider * @extends React.Component */ -class MultiLayerSlider extends React.Component { +class MultiLayerSlider extends React.Component { /** * The className added to this component. @@ -20,41 +45,22 @@ class MultiLayerSlider extends React.Component { */ className = `${CSS_PREFIX}multilayerslider`; - static propTypes = { - /** - * An optional CSS class which should be added. - * @type {String} - */ - className: PropTypes.string, - - /** - * The layers that should be handled. Default is: `[]`. - * - * @type {Array} - */ - layers: PropTypes.arrayOf(PropTypes.instanceOf(OlLayerBase)).isRequired, - - /** - * The default value(s). Default is `0` - * @type {Array | String} - */ - defaultValue: PropTypes.any - } - static defaultProps = { layers: [], defaultValue: 0 - } + }; /** * The constructor. * * @constructs MultiLayerSlider - * @param {Object} props The properties. + * @param {MultiLayerSliderProps} props The properties. */ - constructor(props) { + constructor(props: MultiLayerSliderProps) { super(props); - const layers = this.props.layers; + const { + layers + } = props; layers.forEach(l => l.setOpacity(0)); layers[0].setOpacity(1); } @@ -64,9 +70,11 @@ class MultiLayerSlider extends React.Component { * @param {Number} value the slider value * @return {String} the formatted tip value */ - formatTip(value) { + formatTip(value: number) { + const { + layers + } = this.props; const layerIdx = this.getLayerIndexForSliderValue(value); - const layers = this.props.layers; let tip; if (layers[layerIdx]) { const opacity = Math.round(layers[layerIdx].get('opacity') * 100); @@ -79,9 +87,8 @@ class MultiLayerSlider extends React.Component { /** * Called when the value of the slider changed. - * @param {Number} value the new value */ - valueUpdated(value) { + valueUpdated(value: number) { const layerIdx = this.getLayerIndexForSliderValue(value); const opacity = this.getOpacityForValue(value); const layers = this.props.layers; @@ -103,10 +110,13 @@ class MultiLayerSlider extends React.Component { * @param {Number} value The current slider value * @return {Number} The opacity */ - getOpacityForValue(value) { - const length = this.props.layers.length - 1; + getOpacityForValue(value: number) { + const { + layers + } = this.props; + const length = layers.length - 1; const ticksPerLayer = Math.round(100 / length); - const idx = parseInt(value / ticksPerLayer, 10); + const idx = value / ticksPerLayer; const opacity = value / ticksPerLayer - (idx > length ? length : idx); return opacity > 1 ? 1 : opacity; } @@ -116,10 +126,13 @@ class MultiLayerSlider extends React.Component { * @param {Number} value the current slider value * @return {Number} The layer array index */ - getLayerIndexForSliderValue(value) { - const length = this.props.layers.length - 1; + getLayerIndexForSliderValue(value: number) { + const { + layers + } = this.props; + const length = layers.length - 1; const ticksPerLayer = Math.round(100 / length); - const idx = parseInt(value / ticksPerLayer, 10); + const idx = value / ticksPerLayer; return idx > length ? length : idx; } @@ -129,11 +142,13 @@ class MultiLayerSlider extends React.Component { */ getMarks() { const marks = {}; - const layers = this.props.layers; + const { + layers + } = this.props; const length = layers.length - 1; - layers.forEach(function(l, i) { - const layername = l.get('name') || l.get('title') || 'Layer ' + i + 1; - const idx = Math.round(100 / length * i); + layers.forEach((layer, index) => { + const layername = layer.get('name') || layer.get('title') || 'Layer ' + index + 1; + const idx = Math.round(100 / length * index); marks[idx] = layername; }); return marks; From 51f8128b88b15943e743c0b96e02e2bb1891be30 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Tue, 9 Jul 2019 14:23:43 +0200 Subject: [PATCH 11/69] Transforms MapProvider to TypeScript --- src/Provider/MapProvider/MapProvider.jsx | 91 ------------------- ...Provider.spec.jsx => MapProvider.spec.tsx} | 4 +- src/Provider/MapProvider/MapProvider.tsx | 79 ++++++++++++++++ 3 files changed, 81 insertions(+), 93 deletions(-) delete mode 100644 src/Provider/MapProvider/MapProvider.jsx rename src/Provider/MapProvider/{MapProvider.spec.jsx => MapProvider.spec.tsx} (98%) create mode 100644 src/Provider/MapProvider/MapProvider.tsx diff --git a/src/Provider/MapProvider/MapProvider.jsx b/src/Provider/MapProvider/MapProvider.jsx deleted file mode 100644 index bcdcac9b62..0000000000 --- a/src/Provider/MapProvider/MapProvider.jsx +++ /dev/null @@ -1,91 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import OlMap from 'ol/Map'; - -/** - * The MapProvider. - * - * @type {Object} - */ -class MapProvider extends React.Component { - - /** - * The properties. - * @type {Object} - */ - static propTypes = { - /** - * The children of the MapProvider. - * @type {Object} - */ - children: PropTypes.node, - - /** - * The map can be either an OlMap or a Promise that resolves with an OlMap - * if your map is created asynchronously. - * - * @type {ol.Map|Promise} - */ - map: PropTypes.oneOfType([ - PropTypes.instanceOf(OlMap), - PropTypes.instanceOf(Promise) - ]).isRequired - } - - /** - * The child context types. - * @type {Object} - */ - static childContextTypes = { - map: PropTypes.instanceOf(OlMap) - } - - /** - * The constructor of the MapProvider sets the - * - * @constructs MapProvider - * @param {Object} props The initial props. - */ - constructor(props) { - super(props); - - this.state = { - map: null, - ready: false - }; - - Promise.resolve(props.map).then((map) => { - this.setState({ - map: map, - ready: true - }); - }); - - } - - /** - * Returns the context for the children. - * - * @return {Object} The child context. - */ - getChildContext() { - const { - map - } = this.state; - - return { map }; - } - - /** - * The render function. - */ - render() { - if (!this.state.ready) { - return null; - } else { - return this.props.children; - } - } -} - -export default MapProvider; diff --git a/src/Provider/MapProvider/MapProvider.spec.jsx b/src/Provider/MapProvider/MapProvider.spec.tsx similarity index 98% rename from src/Provider/MapProvider/MapProvider.spec.jsx rename to src/Provider/MapProvider/MapProvider.spec.tsx index 5ad083f770..b3e91584bd 100644 --- a/src/Provider/MapProvider/MapProvider.spec.jsx +++ b/src/Provider/MapProvider/MapProvider.spec.tsx @@ -13,8 +13,8 @@ describe('MapProvider', () => { /* eslint-disable require-jsdoc */ class MockComponent extends React.Component { static propTypes = { - map: PropTypes.object.isRequired, - } + map: PropTypes.object.isRequired + }; render() { return (
Mockety-mock
diff --git a/src/Provider/MapProvider/MapProvider.tsx b/src/Provider/MapProvider/MapProvider.tsx new file mode 100644 index 0000000000..22cb8670fb --- /dev/null +++ b/src/Provider/MapProvider/MapProvider.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import OlMap from 'ol/Map'; + +/** + * + * @export + * @interface TimeSliderProps + */ +export interface MapProviderProps { + /** + * The map can be either an OlMap or a Promise that resolves with an OlMap + * if your map is created asynchronously. + * + * @type {ol.Map|Promise} + */ + map: OlMap | Promise; +} + +interface MapProviderState { + map?: OlMap; + ready: boolean; +} + +/** + * The MapProvider. + * + * @type {Object} + */ +class MapProvider extends React.Component { + + /** + * The constructor of the MapProvider sets the + * + * @constructs MapProvider + * @param {Object} props The initial props. + */ + constructor(props: MapProviderProps) { + super(props); + + this.state = { + map: null, + ready: false + }; + + Promise.resolve(props.map) + .then((map) => { + this.setState({ + map: map, + ready: true + }); + }); + } + + /** + * Returns the context for the children. + * + * @return {Object} The child context. + */ + getChildContext() { + const { + map + } = this.state; + + return { map }; + } + + /** + * The render function. + */ + render() { + if (!this.state.ready) { + return null; + } else { + return this.props.children; + } + } +} + +export default MapProvider; From d356bf1e5575fd81a037cc5b55ef1434eef0a2a4 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Tue, 9 Jul 2019 14:29:35 +0200 Subject: [PATCH 12/69] Transforms Titlebar to TypeScript --- .../{Titlebar.spec.jsx => Titlebar.spec.tsx} | 0 .../Titlebar/{Titlebar.jsx => Titlebar.tsx} | 44 ++++++------------- 2 files changed, 14 insertions(+), 30 deletions(-) rename src/Panel/Titlebar/{Titlebar.spec.jsx => Titlebar.spec.tsx} (100%) rename src/Panel/Titlebar/{Titlebar.jsx => Titlebar.tsx} (58%) diff --git a/src/Panel/Titlebar/Titlebar.spec.jsx b/src/Panel/Titlebar/Titlebar.spec.tsx similarity index 100% rename from src/Panel/Titlebar/Titlebar.spec.jsx rename to src/Panel/Titlebar/Titlebar.spec.tsx diff --git a/src/Panel/Titlebar/Titlebar.jsx b/src/Panel/Titlebar/Titlebar.tsx similarity index 58% rename from src/Panel/Titlebar/Titlebar.jsx rename to src/Panel/Titlebar/Titlebar.tsx index ad6b88baa3..c6b83eb90d 100644 --- a/src/Panel/Titlebar/Titlebar.jsx +++ b/src/Panel/Titlebar/Titlebar.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; import isEmpty from 'lodash/isEmpty'; @@ -7,47 +6,32 @@ import { CSS_PREFIX } from '../../constants'; import './Titlebar.less'; +export interface TitlebarProps { + /** + * An optional CSS class which should be added. + * @type {String} + */ + className?: string; + /** + * Additional elements to show at the right side of the Titlebar. + */ + tools: React.ReactNode[]; +} + /** * Class representing the titlebar. Usually used in a panel. * * @class The TitleBar * @extends React.Component */ -export class Titlebar extends React.Component { +export class Titlebar extends React.Component { /** * The className added to this component. * @type {String} * @private */ - className = `${CSS_PREFIX}titlebar` - - /** - * The properties. - * @type {Object} - */ - static propTypes = { - /** - * An optional CSS class which should be added. - * @type {String} - */ - className: PropTypes.string, - /** - * The children to show in the Window. - * @type {node} - */ - children: PropTypes.node, - /** - * The dispatch function. - @type {Function} - */ - dispatch: PropTypes.func, - /** - * Additional elements to show at the right side of the Titlebar. - * @type {Array} - */ - tools: PropTypes.arrayOf(PropTypes.element) - } + className = `${CSS_PREFIX}titlebar`; /** * The render function. From a8cc2084939286e0c39d842b31fafe07ef72881e Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Tue, 9 Jul 2019 14:59:14 +0200 Subject: [PATCH 13/69] Transforms Panel to TypeScript --- .../Panel/{Panel.spec.jsx => Panel.spec.tsx} | 2 +- src/Panel/Panel/{Panel.jsx => Panel.tsx} | 311 ++++++++---------- 2 files changed, 147 insertions(+), 166 deletions(-) rename src/Panel/Panel/{Panel.spec.jsx => Panel.spec.tsx} (98%) rename src/Panel/Panel/{Panel.jsx => Panel.tsx} (59%) diff --git a/src/Panel/Panel/Panel.spec.jsx b/src/Panel/Panel/Panel.spec.tsx similarity index 98% rename from src/Panel/Panel/Panel.spec.jsx rename to src/Panel/Panel/Panel.spec.tsx index cdaae935d4..b1debe2263 100644 --- a/src/Panel/Panel/Panel.spec.jsx +++ b/src/Panel/Panel/Panel.spec.tsx @@ -32,7 +32,7 @@ describe('', () => { // Mock a DOM to play around document.body.className = 'react-geo-panel'; - const element = wrapper.instance().rnd.getSelfElement(); + const element = wrapper.instance()._rnd.getSelfElement(); it('is defined', () => { expect(wrapper.instance().onKeyDown).not.toBeUndefined(); diff --git a/src/Panel/Panel/Panel.jsx b/src/Panel/Panel/Panel.tsx similarity index 59% rename from src/Panel/Panel/Panel.jsx rename to src/Panel/Panel/Panel.tsx index 2dc82ec54d..8aaf4cd48f 100644 --- a/src/Panel/Panel/Panel.jsx +++ b/src/Panel/Panel/Panel.tsx @@ -1,6 +1,11 @@ import React from 'react'; -import PropTypes from 'prop-types'; -import { Rnd } from 'react-rnd'; +import { + Rnd, + ResizeEnable, + RndResizeCallback, + Props as RndProps, + RndResizeStartCallback +} from 'react-rnd'; import uniqueId from 'lodash/uniqueId'; import isNumber from 'lodash/isNumber'; @@ -13,13 +18,110 @@ import { CSS_PREFIX } from '../../constants'; import './Panel.less'; +// i18n +export interface PanelLocale { +} + +interface PanelDefaultProps extends RndProps { + /** + * Whether to allow dragging or not. Default is false. + */ + draggable: boolean; + /** + * Whether to allow collapsing or not. Default is false. + */ + collapsible: boolean; + /** + * Whether to show panel collapsed initially or not. Default is false. + */ + collapsed: boolean; + /** + * The height of the panel. + */ + height: number | 'inherit' | 'initial' | 'auto'; + /** + * The width of the panel. + */ + width: number | 'inherit' | 'initial' | 'auto'; + /** + * The height of the TitleBar. + */ + titleBarHeight: number; + /** + * The tooltip of the collapse button. + */ + collapseTooltip: string; + /** + * + */ + tools: React.ReactElement[]; + /** + * The enableResizing property is used to set the resizable permission of a + * resizable component. + * The permission of top, right, bottom, left, topRight, bottomRight, + * bottomLeft, topLeft direction resizing. If omitted, all resizer are + * enabled. If you want to permit only right direction resizing, set { + * top:false, + * right:true, + * bottom:false, + * left:false, + * topRight:false, + * bottomRight:false, + * bottomLeft:false, + * topLeft:false + * }. + */ + resizeOpts: ResizeEnable | boolean; +} + +export interface PanelProps extends Partial { + id?: string; + /** + * The children to show in the Window. + */ + children?: React.ReactNode; + /** + * The title text to be shown in the window Header. + * @type {string} + */ + title?: string; + /** + * Callback function on `keydown` keyboard event if `escape` key was pressed. + */ + onEscape?: (evt: KeyboardEvent) => void; +} + +interface PanelState { + id?: string; + /** + * Whether to show panel collapsed initially or not. Default is false. + */ + collapsed: boolean; + /** + * The height of the TitleBar. + */ + titleBarHeight: number; + /** + * The height of the panel. + */ + height: number | 'inherit' | 'initial' | 'auto'; + /** + * The width of the panel. + */ + width: number | 'inherit' | 'initial' | 'auto'; + /** + * + */ + resizing: boolean; +} + /** * The Panel. * * @class The Panel * @extends React.Component */ -export class Panel extends React.Component { +export class Panel extends React.Component { /** * The className added to this component. @@ -28,157 +130,25 @@ export class Panel extends React.Component { */ className = `${CSS_PREFIX}panel`; - /** - * Printed representation of the pressed escape keyboard key. - * s. https://developer.mozilla.org/de/docs/Web/API/KeyboardEvent/key/Key_Values - * @type {String} - * @private - */ - _escapeKeyboardEventKey = 'Esc'; + /** + * Printed representation of the pressed escape keyboard key. + * s. https://developer.mozilla.org/de/docs/Web/API/KeyboardEvent/key/Key_Values + * @type {String} + * @private + */ + _escapeKeyboardEventKey = 'Esc'; /** - * The properties. - * @type {Object} + * + * */ - static propTypes = { - - id: PropTypes.string, - - /** - * An optional CSS class which should be added. - * @type {String} - */ - className: PropTypes.string, - - /** - * The children to show in the Window. - * @type {node} - */ - children: PropTypes.node, - - /** - * The title text to be shown in the window Header. - * @type {string} - */ - title: PropTypes.string, - - /** - * The enableResizing property is used to set the resizable permission of a - * resizable component. - * The permission of top, right, bottom, left, topRight, bottomRight, - * bottomLeft, topLeft direction resizing. If omitted, all resizer are - * enabled. If you want to permit only right direction resizing, set { - * top:false, - * right:true, - * bottom:false, - * left:false, - * topRight:false, - * bottomRight:false, - * bottomLeft:false, - * topLeft:false - * }. - * @type {object} - */ - resizeOpts: PropTypes.oneOfType([ - PropTypes.shape({ - top: PropTypes.bool, - right: PropTypes.bool, - bottom: PropTypes.bool, - left: PropTypes.bool, - topRight: PropTypes.bool, - bottomRight: PropTypes.bool, - bottomLeft: PropTypes.bool, - topLeft: PropTypes.bool - }), - PropTypes.bool - ]), - /** - * Function called when onResize is triggered by react-rnd - * @type {Function} - */ - onResize: PropTypes.func, - /** - * Function called when onResizeStart is triggered by react-rnd - * @type {Function} - */ - onResizeStart: PropTypes.func, - /** - * Function called when onResizeStop is triggered by react-rnd - * @type {Function} - */ - onResizeStop: PropTypes.func, - /** - * Callback function on `keydown` keyboard event if `escape` key was pressed. - * @type {Function} - */ - onEscape: PropTypes.func, - /** - * Whether to allow dragging or not. Default is false. - * @type {boolean} - */ - draggable: PropTypes.bool, - - /** - * Whether to allow collapsing or not. Default is false. - * @type {boolean} - */ - collapsible: PropTypes.bool, - - /** - * Whether to show panel collapsed initially or not. Default is false. - * @type {boolean} - */ - collapsed: PropTypes.bool, - - /** - * The height of the panel. - * @type {number|string} - */ - height: PropTypes.oneOfType([ - PropTypes.number, - PropTypes.oneOf([ - 'inherit', - 'initial', - 'auto' - ]) - ]), - - /** - * The width of the panel. - * @type {number|string} - */ - width: PropTypes.oneOfType([ - PropTypes.number, - PropTypes.oneOf([ - 'inherit', - 'initial', - 'auto' - ]) - ]), - - /** - * The height of the TitleBar. - * @type {number} - */ - titleBarHeight: PropTypes.number, - - /** - * The tooltip of the collapse button. - * @type {String} - */ - collapseTooltip: PropTypes.string, - - /** - * - */ - tools: PropTypes.arrayOf(PropTypes.node) - } + _rnd: Rnd; /** * The default properties. * @type {Object} */ - static defaultProps = { + static defaultProps: PanelDefaultProps = { draggable: false, collapsible: false, collapsed: false, @@ -188,14 +158,14 @@ export class Panel extends React.Component { height: 'auto', width: 'auto', collapseTooltip: 'Collapse' - } + }; /** * Create the SimpleButton. * * @constructs SimpleButton */ - constructor(props) { + constructor(props: PanelProps) { super(props); const id = props.id || uniqueId('panel-'); this.state = { @@ -262,7 +232,7 @@ export class Panel extends React.Component { this.setState({ collapsed: !this.state.collapsed }, () => { - this.rnd.updateSize({ + this._rnd.updateSize({ height: this.calculateHeight(), width: this.state.width }); @@ -276,7 +246,7 @@ export class Panel extends React.Component { * @param {String} direction A string discribing where the element was grabed. * @param {HTMLElement} el The element which gets resized. */ - onResize(evt, direction, el) { + onResize(evt: React.MouseEvent, direction: string, el: HTMLElement) { const { onResize } = this.props; if (isFunction(onResize)) { onResize(arguments); @@ -316,12 +286,15 @@ export class Panel extends React.Component { /** * Called on keyboard `keydown` event. Will be only triggered if pressed key * is `Escape` key and `onEscape` function is provided via props. - * @param {React.KeyboardEvent} evt `keydown` event. + * @param {KeyboardEvent} evt `keydown` event. */ - onKeyDown = evt => { - if (evt && evt.key.startsWith(this._escapeKeyboardEventKey) && this.props.onEscape) { - this.rnd.getSelfElement().focus(); - this.props.onEscape(); + onKeyDown = (evt: KeyboardEvent) => { + const { + onEscape + } = this.props; + if (evt && evt.key.startsWith(this._escapeKeyboardEventKey) && onEscape) { + this._rnd.getSelfElement().focus(); + onEscape(evt); } } @@ -350,7 +323,7 @@ export class Panel extends React.Component { ...rndOpts } = this.props; - let toolsClone = tools.map(t => React.cloneElement(t)); + let toolsClone = tools.map(tool => React.cloneElement(tool)); const finalClassName = className ? `${className} ${this.className}` @@ -384,28 +357,36 @@ export class Panel extends React.Component { {title} : null; - const defWidth = this.state.width; - const defHeight = this.calculateHeight(); + const defaultWidth = this.state.width; + const defaultHeight = this.calculateHeight(); const { x, y } = rndOpts; - const defX = x && isNumber(x) ? x : window.innerWidth / 2 - defWidth / 2; - const defY = y && isNumber(y) ? y : window.innerHeight / 2 - defHeight / 2; + const defX = x && isNumber(x) + ? x + : isNumber(defaultWidth) + ? window.innerWidth / 2 - defaultWidth / 2 + : undefined; + const defY = y && isNumber(y) + ? y + : isNumber(defaultHeight) + ? window.innerHeight / 2 - defaultHeight / 2 + : undefined; return ( this.rnd = rnd} + ref={rnd => this._rnd = rnd} default={{ x: defX, y: defY, - width: defWidth, - height: defHeight + width: defaultWidth, + height: defaultHeight }} dragHandleClassName="drag-handle" disableDragging={!draggable} - enableResizing={enableResizing} + enableResizing={enableResizing as ResizeEnable} resizeHandleClasses={{ bottom: 'resize-handle resize-handle-bottom', bottomLeft: 'resize-handle resize-handle-bottom-left', @@ -424,7 +405,7 @@ export class Panel extends React.Component { {titleBar}
Date: Tue, 9 Jul 2019 15:03:54 +0200 Subject: [PATCH 14/69] Transforms MapComponent to TypeScript --- ...mponent.spec.jsx => MapComponent.spec.tsx} | 1 - .../{MapComponent.jsx => MapComponent.tsx} | 31 +++++++++++-------- 2 files changed, 18 insertions(+), 14 deletions(-) rename src/Map/MapComponent/{MapComponent.spec.jsx => MapComponent.spec.tsx} (99%) rename src/Map/MapComponent/{MapComponent.jsx => MapComponent.tsx} (76%) diff --git a/src/Map/MapComponent/MapComponent.spec.jsx b/src/Map/MapComponent/MapComponent.spec.tsx similarity index 99% rename from src/Map/MapComponent/MapComponent.spec.jsx rename to src/Map/MapComponent/MapComponent.spec.tsx index 5f1349777f..6abb14750e 100644 --- a/src/Map/MapComponent/MapComponent.spec.jsx +++ b/src/Map/MapComponent/MapComponent.spec.tsx @@ -1,6 +1,5 @@ /*eslint-env jest*/ - import TestUtil from '../../Util/TestUtil'; import MapComponent from './MapComponent'; diff --git a/src/Map/MapComponent/MapComponent.jsx b/src/Map/MapComponent/MapComponent.tsx similarity index 76% rename from src/Map/MapComponent/MapComponent.jsx rename to src/Map/MapComponent/MapComponent.tsx index e9558f31ac..2cce3eb62f 100644 --- a/src/Map/MapComponent/MapComponent.jsx +++ b/src/Map/MapComponent/MapComponent.tsx @@ -1,24 +1,26 @@ import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; import OlMap from 'ol/Map'; +// i18n +export interface WindowLocale { +} + +interface MapDefaultProps extends React.HTMLAttributes { + mapDivId: string; +} + +export interface MapProps extends Partial { + children?: React.ReactChildren; + map: OlMap; +} + /** * Class representing a map. * * @class The MapComponent. * @extends React.PureComponent */ -export class MapComponent extends PureComponent { - - /** - * The properties. - * @type {Object} - */ - static propTypes = { - children: PropTypes.node, - map: PropTypes.instanceOf(OlMap).isRequired, - mapDivId: PropTypes.string - } +export class MapComponent extends PureComponent { /** * The default properties. @@ -63,7 +65,10 @@ export class MapComponent extends PureComponent { * render. */ componentDidUpdate() { - this.props.map.updateSize(); + const { + map + } = this.props; + map.updateSize(); } /** From 055e69eed3a92ce69128a1a0d8f4a29b2aef19e4 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Tue, 9 Jul 2019 15:11:13 +0200 Subject: [PATCH 15/69] Transforms FloatingMapLogo to TypeScript --- ...Logo.spec.jsx => FloatingMapLogo.spec.tsx} | 0 ...loatingMapLogo.jsx => FloatingMapLogo.tsx} | 65 +++++++++---------- 2 files changed, 30 insertions(+), 35 deletions(-) rename src/Map/FloatingMapLogo/{FloatingMapLogo.spec.jsx => FloatingMapLogo.spec.tsx} (100%) rename src/Map/FloatingMapLogo/{FloatingMapLogo.jsx => FloatingMapLogo.tsx} (59%) diff --git a/src/Map/FloatingMapLogo/FloatingMapLogo.spec.jsx b/src/Map/FloatingMapLogo/FloatingMapLogo.spec.tsx similarity index 100% rename from src/Map/FloatingMapLogo/FloatingMapLogo.spec.jsx rename to src/Map/FloatingMapLogo/FloatingMapLogo.spec.tsx diff --git a/src/Map/FloatingMapLogo/FloatingMapLogo.jsx b/src/Map/FloatingMapLogo/FloatingMapLogo.tsx similarity index 59% rename from src/Map/FloatingMapLogo/FloatingMapLogo.jsx rename to src/Map/FloatingMapLogo/FloatingMapLogo.tsx index 1b0e32b47c..4200958d10 100644 --- a/src/Map/FloatingMapLogo/FloatingMapLogo.jsx +++ b/src/Map/FloatingMapLogo/FloatingMapLogo.tsx @@ -1,8 +1,32 @@ import React from 'react'; -import PropTypes from 'prop-types'; import './FloatingMapLogo.less'; import { CSS_PREFIX } from '../../constants'; +// i18n +export interface WindowLocale { +} + +interface FloatingMapLogoDefaultProps extends React.HTMLAttributes { + /** + * The imageSrc. + */ + imageSrc: string; + /** + * Whether the map-logo is absolutely postioned or not + */ + absolutelyPositioned: boolean; +} + +export interface FloatingMapLogoProps extends Partial { + /** + * An optional CSS class which should be added. + */ + className?: string; + /** + * The image height + */ + imageHeight: string; +} /** * Class representing a floating map logo @@ -10,59 +34,30 @@ import { CSS_PREFIX } from '../../constants'; * @class The FloatingMapLogo * @extends React.Component */ -class FloatingMapLogo extends React.Component { +class FloatingMapLogo extends React.Component { /** * The className added to this component. * @type {String} * @private */ - className = `${CSS_PREFIX}floatingmaplogo` + className = `${CSS_PREFIX}floatingmaplogo`; /** * The properties. * @type {Object} */ static propTypes = { - /** - * An optional CSS class which should be added. - * @type {String} - */ - className: PropTypes.string, - - /** - * The imageSrc (required property). - * @type {String} - */ - imageSrc: PropTypes.string.isRequired, - - /** - * The image height - * @type {String} - */ - imageHeight: PropTypes.string, - - /** - * Whether the map-logo is absolutely postioned or not - * @type {boolean} - */ - absolutelyPositioned: PropTypes.bool, - - /** - * The style object - * @type {Object} - */ - style: PropTypes.object - } + }; /** * The default properties. * @type {Object} */ - static defaultProps = { + static defaultProps: FloatingMapLogoDefaultProps = { imageSrc: 'logo.png', absolutelyPositioned: false - } + }; /** * The render function. From 46c56ae0930523fbacf1b0eac8e8366ff9f0a6e7 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Tue, 9 Jul 2019 15:16:31 +0200 Subject: [PATCH 16/69] Transforms Legend to TypeScript --- .../{Legend.spec.jsx => Legend.spec.tsx} | 0 src/Legend/{Legend.jsx => Legend.tsx} | 67 +++++++++---------- 2 files changed, 33 insertions(+), 34 deletions(-) rename src/Legend/{Legend.spec.jsx => Legend.spec.tsx} (100%) rename src/Legend/{Legend.jsx => Legend.tsx} (73%) diff --git a/src/Legend/Legend.spec.jsx b/src/Legend/Legend.spec.tsx similarity index 100% rename from src/Legend/Legend.spec.jsx rename to src/Legend/Legend.spec.tsx diff --git a/src/Legend/Legend.jsx b/src/Legend/Legend.tsx similarity index 73% rename from src/Legend/Legend.jsx rename to src/Legend/Legend.tsx index e7c557a019..aeb897a8d4 100644 --- a/src/Legend/Legend.jsx +++ b/src/Legend/Legend.tsx @@ -1,63 +1,62 @@ import React from 'react'; -import PropTypes from 'prop-types'; import isEqual from 'lodash/isEqual'; import Logger from '@terrestris/base-util/dist/Logger'; import MapUtil from '@terrestris/ol-util/dist/MapUtil/MapUtil'; +import OlLayer from 'ol/layer/Layer'; import { CSS_PREFIX } from '../constants'; +export interface LegendProps extends React.HTMLAttributes { + /** + * An optional CSS class which should be added. + */ + className: string; + /** + * The layer you want to display the legend of. + */ + layer: OlLayer; + /** + * An object containing additional request params like "{HEIGHT: 400}" will + * be transformed to "&HEIGHT=400" an added to the GetLegendGraphic request. + */ + extraParams: any; +} + +interface LegendState { + /** + * The legend url. + */ + legendUrl: string; +} + /** * Class representing the Legend. * * @class Legend * @extends React.Component */ -export class Legend extends React.Component { +export class Legend extends React.Component { /** * The className added to this component. * @type {String} * @private */ - className = `${CSS_PREFIX}legend` - - /** - * The properties. - * @type {Object} - */ - static propTypes = { - /** - * An optional CSS class which should be added. - * @type {String} - */ - className: PropTypes.string, - - /** - * The layer you want to display the legend of. - * @type {ol.layer.Layer} - */ - layer: PropTypes.object.isRequired, - - /** - * An object containing additional request params like "{HEIGHT: 400}" will - * be transformed to "&HEIGHT=400" an added to the GetLegendGraphic request. - * @type {Object} - */ - extraParams: PropTypes.object - } + className = `${CSS_PREFIX}legend`; /** * Create the Legend. * * @constructs Legend */ - constructor(props) { + constructor(props: LegendProps) { super(props); - - const layer = props.layer; - const extraParams = props.extraParams; + const { + layer, + extraParams + } = props; this.state = { legendUrl: this.getLegendUrl(layer, extraParams) @@ -70,7 +69,7 @@ export class Legend extends React.Component { * * @param {Object} prevProps The previous props. */ - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps: LegendProps) { const { extraParams, layer @@ -91,7 +90,7 @@ export class Legend extends React.Component { * @param {ol.Layer} layer The layer to get the legend graphic request for. * @param {Object} extraParams The extra params. */ - getLegendUrl(layer, extraParams) { + getLegendUrl(layer: OlLayer, extraParams: any) { let legendUrl; if (layer.get('legendUrl')) { From 1fe25bdcc904b5280897bfd8ec49b4d745f93618 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Tue, 9 Jul 2019 15:44:03 +0200 Subject: [PATCH 17/69] Transforms LayerTreeNode to TypeScript --- ...eeNode.spec.jsx => LayerTreeNode.spec.tsx} | 0 .../{LayerTreeNode.jsx => LayerTreeNode.tsx} | 26 +++++-------------- 2 files changed, 6 insertions(+), 20 deletions(-) rename src/LayerTreeNode/{LayerTreeNode.spec.jsx => LayerTreeNode.spec.tsx} (100%) rename src/LayerTreeNode/{LayerTreeNode.jsx => LayerTreeNode.tsx} (74%) diff --git a/src/LayerTreeNode/LayerTreeNode.spec.jsx b/src/LayerTreeNode/LayerTreeNode.spec.tsx similarity index 100% rename from src/LayerTreeNode/LayerTreeNode.spec.jsx rename to src/LayerTreeNode/LayerTreeNode.spec.tsx diff --git a/src/LayerTreeNode/LayerTreeNode.jsx b/src/LayerTreeNode/LayerTreeNode.tsx similarity index 74% rename from src/LayerTreeNode/LayerTreeNode.jsx rename to src/LayerTreeNode/LayerTreeNode.tsx index 6459c50504..d463307e6c 100644 --- a/src/LayerTreeNode/LayerTreeNode.jsx +++ b/src/LayerTreeNode/LayerTreeNode.tsx @@ -1,34 +1,20 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { Tree } from 'antd'; const TreeNode = Tree.TreeNode; import './LayerTreeNode.less'; import { CSS_PREFIX } from '../constants'; +import { AntTreeNodeProps } from 'antd/lib/tree'; + +export interface LayerTreeNodeProps extends AntTreeNodeProps { + inResolutionRange: boolean; +} /** * Class representing a layer tree node */ -class LayerTreeNode extends React.PureComponent { - - /** - * The prop types. - * @type {Object} - */ - static propTypes = { - children: PropTypes.array, - inResolutionRange: PropTypes.bool - } - - /** - * The constructor. - * - * @param {Object} props The initial props. - */ - constructor(props) { - super(props); - } +class LayerTreeNode extends React.PureComponent { /** * The render function. From 7ba46beacfe0c3bf5115febed5b26b3f2847b8fb Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Tue, 9 Jul 2019 16:05:38 +0200 Subject: [PATCH 18/69] Transforms LayerTree to TypeScript --- ...{LayerTree.spec.jsx => LayerTree.spec.tsx} | 0 .../{LayerTree.jsx => LayerTree.tsx} | 162 ++++++++++-------- 2 files changed, 89 insertions(+), 73 deletions(-) rename src/LayerTree/{LayerTree.spec.jsx => LayerTree.spec.tsx} (100%) rename src/LayerTree/{LayerTree.jsx => LayerTree.tsx} (82%) diff --git a/src/LayerTree/LayerTree.spec.jsx b/src/LayerTree/LayerTree.spec.tsx similarity index 100% rename from src/LayerTree/LayerTree.spec.jsx rename to src/LayerTree/LayerTree.spec.tsx diff --git a/src/LayerTree/LayerTree.jsx b/src/LayerTree/LayerTree.tsx similarity index 82% rename from src/LayerTree/LayerTree.jsx rename to src/LayerTree/LayerTree.tsx index fab28e44d4..67a71d4a48 100644 --- a/src/LayerTree/LayerTree.jsx +++ b/src/LayerTree/LayerTree.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { Tree } from 'antd'; @@ -20,6 +19,64 @@ import MapUtil from '@terrestris/ol-util/dist/MapUtil/MapUtil'; import LayerTreeNode from '../LayerTreeNode/LayerTreeNode.jsx'; import { CSS_PREFIX } from '../constants'; +import { + TreeProps, + AntTreeNodeCheckedEvent, + AntTreeNodeExpandedEvent +} from 'antd/lib/tree'; +import { AntTreeNodeDropEvent } from 'antd/lib/tree/Tree'; + +interface LayerTreeDefaultProps extends TreeProps { + /** + * + */ + draggable: boolean; + /** + * + */ + checkable: boolean; + /** + * An optional array-filter function that is applied to every layer and + * subLayer. Return false to exclude this layer from the layerTree or true + * to include it. + * + * Compare MDN Docs for Array.prototype.filter: https://mdn.io/array/filter + * + * @type {Function} + */ + filterFunction: (value: any, index: number, array: any[]) => boolean; +} + +export interface LayerTreeProps extends Partial { + /** + * An optional CSS class which should be added. + * @type {String} + */ + className: string; + /** + * A LayerGroup the Tree should handle. + */ + layerGroup?: OlLayerGroup; + /** + * The OpenLayers map the tree interacts with. + */ + map: OlMap; + + /** + * A function that can be used to pass a custom node title. It can return + * any renderable element (String, Number, Element etc.) and receives + * the layer instance of the current tree node. + */ + nodeTitleRenderer: (layer: OlLayerBase) => React.ReactNode; +} + +interface LayerTreeState { + layerGroup: OlLayerGroup; + layerGroupRevision: null; + treeNodes: []; + checkedKeys: []; + mapResolution: -1; +} /** * The LayerTree. @@ -29,73 +86,32 @@ import { CSS_PREFIX } from '../constants'; * @class LayerTree * @extends React.Component */ -class LayerTree extends React.Component { +class LayerTree extends React.Component { /** * The className added to this component. * @type {String} * @private */ - className = `${CSS_PREFIX}layertree` - + className = `${CSS_PREFIX}layertree`; /** * An array of ol.EventsKey as returned by on() or once(). * @type {Array} * @private */ - olListenerKeys = [] - - /** - * The properties. - * @type {Object} - */ - static propTypes = { - /** - * An optional CSS class which should be added. - * @type {String} - */ - className: PropTypes.string, - - layerGroup: PropTypes.instanceOf(OlLayerGroup), - - map: PropTypes.instanceOf(OlMap).isRequired, - - /** - * A function that can be used to pass a custom node title. It can return - * any renderable element (String, Number, Element etc.) and receives - * the layer instance of the current tree node. - * @type {Function} - */ - nodeTitleRenderer: PropTypes.func, - - /** - * Compare https://ant.design/components/tree/ - */ - onExpand: PropTypes.func, - - /** - * An optional array-filter function that is applied to every layer and - * subLayer. Return false to exclude this layer from the layerTree or true - * to include it. - * - * Compare MDN Docs for Array.prototype.filter: https://mdn.io/array/filter - * - * @type {Function} - */ - filterFunction: PropTypes.func - } + olListenerKeys = []; /** * The default properties. * * @type {Object} */ - static defaultProps = { + static defaultProps: LayerTreeDefaultProps = { draggable: true, checkable: true, filterFunction: () => true - } + }; /** * Invoked after the component is instantiated as well as when it @@ -105,10 +121,10 @@ class LayerTree extends React.Component { * @param {Object} nextProps The next properties. * @param {Object} prevState The previous state. */ - static getDerivedStateFromProps(nextProps, prevState) { + static getDerivedStateFromProps(nextProps: LayerTreeProps, prevState: LayerTreeState) { if (prevState.layerGroup && nextProps.layerGroup) { if (!isEqual(prevState.layerGroup.ol_uid, nextProps.layerGroup.ol_uid) || - !isEqual(prevState.layerGroupRevision, nextProps.layerGroup.getRevision())) { + !isEqual(prevState.layerGroupRevision, nextProps.layerGroup.getRevision())) { return { layerGroup: nextProps.layerGroup, layerGroupRevision: nextProps.layerGroup.getRevision() @@ -123,7 +139,7 @@ class LayerTree extends React.Component { * * @constructs LayerTree */ - constructor(props) { + constructor(props: LayerTreeProps) { super(props); this.state = { @@ -162,7 +178,7 @@ class LayerTree extends React.Component { * @param {Object} prevProps The previous props. * @param {Object} prevState The previous state. */ - componentDidUpdate(prevProps, prevState) { + componentDidUpdate(prevProps: LayerTreeProps, prevState: LayerTreeState) { const { layerGroup, nodeTitleRenderer @@ -178,7 +194,7 @@ class LayerTree extends React.Component { } } - if (nodeTitleRenderer !== prevProps.nodeTitleRenderer){ + if (nodeTitleRenderer !== prevProps.nodeTitleRenderer) { this.rebuildTreeNodes(); } } @@ -195,14 +211,14 @@ class LayerTree extends React.Component { * * @param {ol.layer.Group} groupLayer A grouplayer. */ - treeNodesFromLayerGroup(groupLayer) { + treeNodesFromLayerGroup(groupLayer: OlLayerGroup) { let layerArray = groupLayer.getLayers().getArray() .filter(this.props.filterFunction); const treeNodes = layerArray.map((layer) => { return this.treeNodeFromLayer(layer); }); treeNodes.reverse(); - this.setState({treeNodes}); + this.setState({ treeNodes }); } /** @@ -210,7 +226,7 @@ class LayerTree extends React.Component { * * @param {ol.layer.Group} groupLayer A ol.layer.Group */ - registerAddRemoveListeners(groupLayer) { + registerAddRemoveListeners(groupLayer: OlLayerGroup) { const collection = groupLayer.getLayers(); const addEvtKey = collection.on('add', this.onCollectionAdd); const removeEvtKey = collection.on('remove', this.onCollectionRemove); @@ -242,7 +258,7 @@ class LayerTree extends React.Component { * * @param {ol.Collection.Event} evt The add event. */ - onCollectionAdd = (evt) => { + onCollectionAdd = (evt: any) => { if (evt.element instanceof OlLayerGroup) { this.registerAddRemoveListeners(evt.element); } @@ -255,7 +271,7 @@ class LayerTree extends React.Component { * * @param {ol.Collection.Event} evt The remove event. */ - onCollectionRemove = (evt) => { + onCollectionRemove = (evt: any) => { this.unregisterEventsByLayer(evt.element); if (evt.element instanceof OlLayerGroup) { evt.element.getLayers().forEach((layer) => { @@ -271,7 +287,7 @@ class LayerTree extends React.Component { * * @param {ol.layer.Group.Event} evt The change event. */ - onChangeLayers = (evt) => { + onChangeLayers = (evt: any) => { this.unregisterEventsByLayer(evt.oldValue); if (evt.oldValue instanceof OlCollection) { evt.oldValue.forEach((layer) => this.unregisterEventsByLayer(layer)); @@ -287,14 +303,14 @@ class LayerTree extends React.Component { * * @param {ol.layer.Base} layer An ol.layer.Base. */ - unregisterEventsByLayer = (layer) => { + unregisterEventsByLayer = (layer: OlLayerBase) => { this.olListenerKeys = this.olListenerKeys.filter((key) => { if (layer instanceof OlLayerGroup) { const layers = layer.getLayers(); if (key.target === layers) { if ((key.type === 'add' && key.listener === this.onCollectionAdd) || - (key.type === 'remove' && key.listener === this.onCollectionRemove) || - (key.type === 'change:layers' && key.listener === this.onChangeLayers)) { + (key.type === 'remove' && key.listener === this.onCollectionRemove) || + (key.type === 'change:layers' && key.listener === this.onChangeLayers)) { unByKey(key); return false; @@ -315,7 +331,7 @@ class LayerTree extends React.Component { * @param {ol.MapEvent} evt The OpenLayers MapEvent (passed by moveend) * */ - rebuildTreeNodes = evt => { + rebuildTreeNodes = (evt?: any) => { const { mapResolution } = this.state; if (evt && evt instanceof OlMapEvent && evt.target && evt.target.getView) { @@ -342,7 +358,7 @@ class LayerTree extends React.Component { * @param {ol.layer.Base} layer The layer attached to the tree node. * @return {Element} The title composition to render. */ - getTreeNodeTitle(layer) { + getTreeNodeTitle(layer: OlLayerBase) { if (isFunction(this.props.nodeTitleRenderer)) { return this.props.nodeTitleRenderer.call(this, layer); } else { @@ -356,14 +372,14 @@ class LayerTree extends React.Component { * @param {ol.layer.Base} layer The given layer. * @return {LayerTreeNode} The corresponding LayerTreeNode Element. */ - treeNodeFromLayer(layer) { + treeNodeFromLayer(layer: OlLayerBase) { let childNodes; let treeNode; if (layer instanceof OlLayerGroup) { if (!layer.getVisible()) { Logger.warn('Your map configuration contains layerGroups that are' + - 'invisible. This might lead to buggy behaviour.'); + 'invisible. This might lead to buggy behaviour.'); } let childLayers = layer.getLayers().getArray() .filter(this.props.filterFunction); @@ -439,8 +455,8 @@ class LayerTree extends React.Component { * @param {Array} checkedKeys Contains all checkedKeys. * @param {e} checked The ant-tree event object for this event. See ant docs. */ - onCheck(checkedKeys, e) { - const {checked} = e; + onCheck(checkedKeys: string[], e: AntTreeNodeCheckedEvent) { + const { checked } = e; const eventKey = e.node.props.eventKey; const layer = MapUtil.getLayerByOlUid(this.props.map, eventKey); @@ -453,7 +469,7 @@ class LayerTree extends React.Component { * @param {ol.layer.Base} layer The layer. * @param {Boolean} visiblity The visiblity. */ - setLayerVisibility(layer, visibility) { + setLayerVisibility(layer: OlLayerBase, visibility: boolean) { if (!(layer instanceof OlLayerBase) || !isBoolean(visibility)) { Logger.error('setLayerVisibility called without layer or visiblity.'); return; @@ -473,7 +489,7 @@ class LayerTree extends React.Component { * * @param {Object} e The ant-tree event object for this event. See ant docs. */ - onDrop(e) { + onDrop(e: AntTreeNodeDropEvent) { const dragLayer = MapUtil.getLayerByOlUid(this.props.map, e.dragNode.props.eventKey); const dragInfo = MapUtil.getLayerPositionInfo(dragLayer, this.props.map); const dragCollection = dragInfo.groupLayer.getLayers(); @@ -494,14 +510,14 @@ class LayerTree extends React.Component { } else { dropCollection.insertAt(dropPosition + 1, dragLayer); } - // drop on node + // drop on node } else if (location === 0) { if (dropLayer instanceof OlLayerGroup) { dropLayer.getLayers().push(dragLayer); } else { dropCollection.insertAt(dropPosition + 1, dragLayer); } - // drop after node + // drop after node } else if (location === 1) { dropCollection.insertAt(dropPosition, dragLayer); } @@ -513,13 +529,13 @@ class LayerTree extends React.Component { * Call rebuildTreeNodes onExpand to avoid sync issues. * */ - onExpand = (expandedKeys, {expanded, node}) => { + onExpand = (expandedKeys: string[], expandEvent: AntTreeNodeExpandedEvent) => { const { onExpand } = this.props; this.rebuildTreeNodes(); if (onExpand) { - onExpand(expandedKeys, {expanded, node}); + onExpand(expandedKeys, expandEvent); } } From 1360c519f9ee6fdbe6d0578efb9be1b25eec5c77 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Tue, 9 Jul 2019 17:05:52 +0200 Subject: [PATCH 19/69] Transforms VisibleComponent to TypeScript --- ...ent.spec.jsx => VisibleComponent.spec.tsx} | 0 ...ibleComponent.jsx => VisibleComponent.tsx} | 45 ++++++++++--------- 2 files changed, 23 insertions(+), 22 deletions(-) rename src/HigherOrderComponent/VisibleComponent/{VisibleComponent.spec.jsx => VisibleComponent.spec.tsx} (100%) rename src/HigherOrderComponent/VisibleComponent/{VisibleComponent.jsx => VisibleComponent.tsx} (76%) diff --git a/src/HigherOrderComponent/VisibleComponent/VisibleComponent.spec.jsx b/src/HigherOrderComponent/VisibleComponent/VisibleComponent.spec.tsx similarity index 100% rename from src/HigherOrderComponent/VisibleComponent/VisibleComponent.spec.jsx rename to src/HigherOrderComponent/VisibleComponent/VisibleComponent.spec.tsx diff --git a/src/HigherOrderComponent/VisibleComponent/VisibleComponent.jsx b/src/HigherOrderComponent/VisibleComponent/VisibleComponent.tsx similarity index 76% rename from src/HigherOrderComponent/VisibleComponent/VisibleComponent.jsx rename to src/HigherOrderComponent/VisibleComponent/VisibleComponent.tsx index 018986949b..64987dac9f 100644 --- a/src/HigherOrderComponent/VisibleComponent/VisibleComponent.jsx +++ b/src/HigherOrderComponent/VisibleComponent/VisibleComponent.tsx @@ -1,8 +1,16 @@ import React from 'react'; -import PropTypes from 'prop-types'; import Logger from '@terrestris/base-util/dist/Logger'; +interface IsVisibleComponentProps { + withRef: boolean; +} + +export interface VisibleComponentProps { + activeModules: any[]; + name: string; +} + /** * The HOC factory function. * @@ -14,9 +22,9 @@ import Logger from '@terrestris/base-util/dist/Logger'; * @param {Object} options The options to apply. * @return {Component} The wrapped component. */ -export function isVisibleComponent(WrappedComponent, { +export function isVisibleComponent

(WrappedComponent: React.ComponentType, { withRef = false -} = {}) { +}: IsVisibleComponentProps): React.ComponentType { /** * The wrapper class for the given component. @@ -24,29 +32,23 @@ export function isVisibleComponent(WrappedComponent, { * @class The VisibleComponent * @extends React.Component */ - class VisibleComponent extends React.Component { + return class VisibleComponent extends React.Component

{ - /** - * The props. - * @type {Object} - */ - static propTypes = { - activeModules: PropTypes.arrayOf(PropTypes.object) - } + _wrappedInstance?: React.ReactElement; /** * Create the VisibleComponent. * * @constructs VisibleComponent */ - constructor(props) { + constructor(props: P & IsVisibleComponentProps) { super(props); /** * The wrapped instance. * @type {Element} */ - this.wrappedInstance = null; + this._wrappedInstance = null; } /** @@ -54,9 +56,9 @@ export function isVisibleComponent(WrappedComponent, { * * @return {Element} The wrappend instance. */ - getWrappedInstance = () => { + getWrappedInstance = (): React.ReactElement | void => { if (withRef) { - return this.wrappedInstance; + return this._wrappedInstance; } else { Logger.debug('No wrapped instance referenced, please call the ' + 'isVisibleComponent with option withRef = true.'); @@ -70,7 +72,7 @@ export function isVisibleComponent(WrappedComponent, { */ setWrappedInstance = (instance) => { if (withRef) { - this.wrappedInstance = instance; + this._wrappedInstance = instance; } } @@ -101,24 +103,23 @@ export function isVisibleComponent(WrappedComponent, { // passed through. const { activeModules, + name, ...passThroughProps } = this.props; // Check if the current component should be visible or not. - let isVisibleComponent = this.isVisibleComponent(passThroughProps.name); + let isVisible = this.isVisibleComponent(name); // Inject props into the wrapped component. These are usually state // values or instance methods. return ( - isVisibleComponent ? + isVisible ? : null ); } - } - - return VisibleComponent; + }; } From 9fe71a22d89aa8aef18081c61ae1818e9d1c6956 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Tue, 24 Sep 2019 14:23:17 +0200 Subject: [PATCH 20/69] Misc code improvements --- src/Panel/Panel/Panel.tsx | 4 +--- src/Panel/Titlebar/Titlebar.tsx | 2 +- src/Slider/TimeSlider.tsx | 4 ---- src/Toolbar/Toolbar.tsx | 3 ++- src/UserChip/UserChip.tsx | 6 +++++- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Panel/Panel/Panel.tsx b/src/Panel/Panel/Panel.tsx index 8aaf4cd48f..ef5630ca5f 100644 --- a/src/Panel/Panel/Panel.tsx +++ b/src/Panel/Panel/Panel.tsx @@ -2,9 +2,7 @@ import React from 'react'; import { Rnd, ResizeEnable, - RndResizeCallback, - Props as RndProps, - RndResizeStartCallback + Props as RndProps } from 'react-rnd'; import uniqueId from 'lodash/uniqueId'; diff --git a/src/Panel/Titlebar/Titlebar.tsx b/src/Panel/Titlebar/Titlebar.tsx index c6b83eb90d..51057edad9 100644 --- a/src/Panel/Titlebar/Titlebar.tsx +++ b/src/Panel/Titlebar/Titlebar.tsx @@ -6,7 +6,7 @@ import { CSS_PREFIX } from '../../constants'; import './Titlebar.less'; -export interface TitlebarProps { +export interface TitlebarProps extends React.HTMLAttributes { /** * An optional CSS class which should be added. * @type {String} diff --git a/src/Slider/TimeSlider.tsx b/src/Slider/TimeSlider.tsx index 3fb57d725b..2b9c325273 100644 --- a/src/Slider/TimeSlider.tsx +++ b/src/Slider/TimeSlider.tsx @@ -9,10 +9,6 @@ import { SliderMarks, SliderValue } from 'antd/lib/slider'; import { CSS_PREFIX } from '../constants'; -// i18n -export interface TimeSliderLocale { -} - interface TimeSliderDefaultProps { /** * Whether to allow range selection. diff --git a/src/Toolbar/Toolbar.tsx b/src/Toolbar/Toolbar.tsx index cb277c8154..d359eb1c4e 100644 --- a/src/Toolbar/Toolbar.tsx +++ b/src/Toolbar/Toolbar.tsx @@ -54,6 +54,7 @@ class Toolbar extends React.Component { */ render() { const { + alignment, style, children, className @@ -64,7 +65,7 @@ class Toolbar extends React.Component { : this.className; return ( -

+
{children}
); diff --git a/src/UserChip/UserChip.tsx b/src/UserChip/UserChip.tsx index 18515c02bb..4c8ea9c933 100644 --- a/src/UserChip/UserChip.tsx +++ b/src/UserChip/UserChip.tsx @@ -77,7 +77,11 @@ class UserChip extends React.Component { * @method getInitials */ getInitials(): string { - let splittedName = this.props.userName.split(' '); + const { + userName + } = this.props; + + const splittedName = userName.split(' '); let initals = []; splittedName.forEach((part) => { initals.push(part[0].toUpperCase()); From fc9367f9273faf33f47e353d94420d8197e06ad3 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Wed, 6 Nov 2019 13:46:32 +0100 Subject: [PATCH 21/69] Updates typescript related packages --- package-lock.json | 106 ++++++++++++++++++++++++++-------------------- package.json | 16 +++---- 2 files changed, 67 insertions(+), 55 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4d4a01b7a6..d74296151b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1609,7 +1609,15 @@ "loglevel": "^1.6.3", "query-string": "^6.8.2", "url-parse": "^1.4.7", - "url-search-params": "^1.1.0" + "url-search-params": "^1.1.0", + "validator": "^11.1.0" + }, + "dependencies": { + "validator": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-11.1.0.tgz", + "integrity": "sha512-qiQ5ktdO7CD6C/5/mYV4jku/7qnqzjrxb3C/Q5wR3vGGinHTgJZN/TdFT3ZX4vXhX2R1PXx42fB1cn5W+uJ4lg==" + } } }, "@terrestris/ol-util": { @@ -3003,18 +3011,18 @@ } }, "@types/cheerio": { - "version": "0.22.12", - "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.12.tgz", - "integrity": "sha512-aczowyAJNfrkBV+HS8DyAA87OnvkqGrrOmm5s7V6Jbgimzv/1ZoAy91cLJX8GQrUS60KufD7EIzA2LbK8HV4hg==", + "version": "0.22.13", + "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.13.tgz", + "integrity": "sha512-OZd7dCUOUkiTorf97vJKwZnSja/DmHfuBAroe1kREZZTCf/tlFecwHhsOos3uVHxeKGZDwzolIrCUApClkdLuA==", "dev": true, "requires": { "@types/node": "*" } }, "@types/enzyme": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.1.tgz", - "integrity": "sha512-Jd2hvn3w/0rBH8qD2n+JLMq2GjmZoKTZc5TTg8q9cDnJ9jkR7gzPV+ZdipKwGkWpMRXKDm9kuc9UiUqsW5s20w==", + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.3.tgz", + "integrity": "sha512-f/Kcb84sZOSZiBPCkr4He9/cpuSLcKRyQaEE20Q30Prx0Dn6wcyMAWI0yofL6yvd9Ht9G7EVkQeRqK0n5w8ILw==", "dev": true, "requires": { "@types/cheerio": "*", @@ -3064,9 +3072,9 @@ } }, "@types/jest": { - "version": "24.0.15", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.15.tgz", - "integrity": "sha512-MU1HIvWUme74stAoc3mgAi+aMlgKOudgEvQDIm1v4RkrDudBh1T+NFp5sftpBAdXdx1J0PbdpJ+M2EsSOi1djA==", + "version": "24.0.22", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.22.tgz", + "integrity": "sha512-t2OvhNZnrNjlzi2i0/cxbLVM59WN15I2r1Qtb7wDv28PnV9IzrPtagFRey/S9ezdLD0zyh1XGMQIEQND2YEfrw==", "dev": true, "requires": { "@types/jest-diff": "*" @@ -3106,9 +3114,9 @@ } }, "@types/node": { - "version": "12.0.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.12.tgz", - "integrity": "sha512-Uy0PN4R5vgBUXFoJrKryf5aTk3kJ8Rv3PdlHjl6UaX+Cqp1QE0yPQ68MPXGrZOfG7gZVNDIJZYyot0B9ubXUrQ==" + "version": "12.12.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.6.tgz", + "integrity": "sha512-FjsYUPzEJdGXjwKqSpE0/9QEh6kzhTAeObA54rn6j3rR4C/mzpI9L0KNfoeASSPMMdxIsoJuCLDWcM/rVjIsSA==" }, "@types/normalize-package-data": { "version": "2.4.0", @@ -3117,35 +3125,33 @@ "dev": true }, "@types/prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-f8JzJNWVhKtc9dg/dyDNfliTKNOJSLa7Oht/ElZdF/UbMUmAH3rLmAk3ODNjw0mZajDEgatA03tRjB4+Dp/tzA==", - "dev": true + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, "@types/react": { - "version": "16.9.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.2.tgz", - "integrity": "sha512-jYP2LWwlh+FTqGd9v7ynUKZzjj98T8x7Yclz479QdRhHfuW9yQ+0jjnD31eXSXutmBpppj5PYNLYLRfnZJvcfg==", - "dev": true, + "version": "16.9.11", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.11.tgz", + "integrity": "sha512-UBT4GZ3PokTXSWmdgC/GeCGEJXE5ofWyibCcecRLUVN2ZBpXQGVgQGtG2foS7CrTKFKlQVVswLvf7Js6XA/CVQ==", "requires": { "@types/prop-types": "*", "csstype": "^2.2.0" } }, "@types/react-dom": { - "version": "16.8.4", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.8.4.tgz", - "integrity": "sha512-eIRpEW73DCzPIMaNBDP5pPIpK1KXyZwNgfxiVagb5iGiz6da+9A5hslSX6GAQKdO7SayVCS/Fr2kjqprgAvkfA==", + "version": "16.9.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.3.tgz", + "integrity": "sha512-FUuZKXPr9qlzUT9lhuzrZgLjH63TvNn28Ch3MvKG4B+F52zQtO8DtE0Opbncy3xaucNZM2WIPfuNTgkbKx5Brg==", "requires": { "@types/react": "*" } }, "@types/react-rnd": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/react-rnd/-/react-rnd-7.4.4.tgz", - "integrity": "sha512-Rh9UdKFiV4fxh/05shQsU3RO+eH5anU6eZCo8NBzobEfB6QU50ISLVP24rEZtIXbYsiiwjo7w960aAZ6JicpMg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@types/react-rnd/-/react-rnd-8.0.0.tgz", + "integrity": "sha512-k/exWCXCY3CDqyJUJeny2SgsfWslWh6XU32/S0YJH6p4E8q2FK89WAPzdG0AECA2k95UC75YKErDRQ/IyvDz6g==", "requires": { - "@types/react": "*" + "react-rnd": "*" } }, "@types/react-slick": { @@ -5830,8 +5836,7 @@ "csstype": { "version": "2.6.6", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.6.tgz", - "integrity": "sha512-RpFbQGUE74iyPgvr46U9t1xoQBM8T4BL8SxrN66Le2xYAPSaDJJKeztV3awugusb3g3G9iL8StmkBBXhcbbXhg==", - "dev": true + "integrity": "sha512-RpFbQGUE74iyPgvr46U9t1xoQBM8T4BL8SxrN66Le2xYAPSaDJJKeztV3awugusb3g3G9iL8StmkBBXhcbbXhg==" }, "currently-unhandled": { "version": "0.4.1", @@ -6173,9 +6178,9 @@ } }, "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", + "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", "dev": true }, "diff-sequences": { @@ -8414,9 +8419,9 @@ "dev": true }, "handlebars": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.2.0.tgz", - "integrity": "sha512-Kb4xn5Qh1cxAKvQnzNWZ512DhABzyFNmsaJf3OAkWNa4NkaqWcNI8Tao8Tasi0/F4JD9oyG0YxuFyvyR57d+Gw==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.1.tgz", + "integrity": "sha512-C29UoFzHe9yM61lOsIlCE5/mQVGrnIOrOq7maQl76L7tYPCgC1og0Ajt6uWnX4ZTxBPnjw+CUvawphwCfJgUnA==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -17118,16 +17123,16 @@ "dev": true }, "tslint": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz", - "integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==", + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "builtin-modules": "^1.1.1", "chalk": "^2.3.0", "commander": "^2.12.1", - "diff": "^3.2.0", + "diff": "^4.0.1", "glob": "^7.1.1", "js-yaml": "^3.13.1", "minimatch": "^3.0.4", @@ -17221,9 +17226,9 @@ "dev": true }, "typescript": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.2.tgz", - "integrity": "sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA==" + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz", + "integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==" }, "ua-parser-js": { "version": "0.7.20", @@ -17232,16 +17237,23 @@ "dev": true }, "uglify-js": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", - "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", + "version": "3.6.8", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.8.tgz", + "integrity": "sha512-XhHJ3S3ZyMwP8kY1Gkugqx3CJh2C3O0y8NPiSxtm1tyD/pktLAkFZsFGpuNfTZddKDQ/bbDBLAd2YyA1pbi8HQ==", "dev": true, "optional": true, "requires": { - "commander": "~2.20.0", + "commander": "~2.20.3", "source-map": "~0.6.1" }, "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "optional": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", diff --git a/package.json b/package.json index 72ffd2514b..39d048e690 100644 --- a/package.json +++ b/package.json @@ -79,9 +79,9 @@ "@terrestris/ol-util": "^3.0.1", "@turf/turf": "^5.1.6", "@types/moment": "^2.13.0", - "@types/node": "^12.0.12", - "@types/react-dom": "^16.8.4", - "@types/react-rnd": "^7.4.4", + "@types/node": "^12.12.6", + "@types/react-dom": "^16.9.3", + "@types/react-rnd": "^8.0.0", "ag-grid-community": "^21.2.1", "ag-grid-react": "^21.2.1", "lodash": "^4.17.15", @@ -94,7 +94,7 @@ "react-fa": "^5.0.0", "react-rnd": "^10.0.0", "shpjs": "^3.4.3", - "typescript": "^3.5.2", + "typescript": "^3.7.2", "url-parse": "^1.4.7", "validator": "^12.0.0" }, @@ -108,9 +108,9 @@ "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", "@babel/preset-typescript": "^7.3.3", - "@types/enzyme": "^3.10.1", - "@types/jest": "^24.0.15", - "@types/react": "^16.8.23", + "@types/enzyme": "^3.10.3", + "@types/jest": "^24.0.22", + "@types/react": "^16.9.11", "antd": "^3.23.2", "babel-eslint": "^10.0.3", "babel-jest": "^24.9.0", @@ -140,7 +140,7 @@ "regenerator-runtime": "^0.13.3", "rimraf": "^3.0.0", "style-loader": "^1.0.0", - "tslint": "^5.18.0", + "tslint": "^5.20.1", "url-loader": "^2.1.0", "webpack": "^4.40.2", "whatwg-fetch": "^3.0.0", From bfd6dbe7b30fb53e1ea08014c2ece4f7ba690bb6 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Wed, 6 Nov 2019 13:54:32 +0100 Subject: [PATCH 22/69] Transforms TimeLayerAware to TypeScript --- .../{TimeLayerAware.spec.jsx => TimeLayerAware.spec.tsx} | 0 .../{TimeLayerAware.jsx => TimeLayerAware.tsx} | 6 ++++-- 2 files changed, 4 insertions(+), 2 deletions(-) rename src/HigherOrderComponent/TimeLayerAware/{TimeLayerAware.spec.jsx => TimeLayerAware.spec.tsx} (100%) rename src/HigherOrderComponent/TimeLayerAware/{TimeLayerAware.jsx => TimeLayerAware.tsx} (90%) diff --git a/src/HigherOrderComponent/TimeLayerAware/TimeLayerAware.spec.jsx b/src/HigherOrderComponent/TimeLayerAware/TimeLayerAware.spec.tsx similarity index 100% rename from src/HigherOrderComponent/TimeLayerAware/TimeLayerAware.spec.jsx rename to src/HigherOrderComponent/TimeLayerAware/TimeLayerAware.spec.tsx diff --git a/src/HigherOrderComponent/TimeLayerAware/TimeLayerAware.jsx b/src/HigherOrderComponent/TimeLayerAware/TimeLayerAware.tsx similarity index 90% rename from src/HigherOrderComponent/TimeLayerAware/TimeLayerAware.jsx rename to src/HigherOrderComponent/TimeLayerAware/TimeLayerAware.tsx index 5054970aba..e25af6e256 100644 --- a/src/HigherOrderComponent/TimeLayerAware/TimeLayerAware.jsx +++ b/src/HigherOrderComponent/TimeLayerAware/TimeLayerAware.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import OlLayerBase from 'ol/layer/Base'; import isArray from 'lodash/isArray'; @@ -10,7 +11,7 @@ import isArray from 'lodash/isArray'; * a WMS source that will end up as URL parameters. * @return {String} The key for the time parameter, in the actual spelling. */ -const findTimeParam = (params) => { +const findTimeParam = (params: Object) => { const keys = Object.keys(params); let foundKey = 'TIME'; // fallback keys.some(key => { @@ -19,6 +20,7 @@ const findTimeParam = (params) => { foundKey = key; return true; } + return false; }); return foundKey; }; @@ -30,7 +32,7 @@ const findTimeParam = (params) => { * @param {Array} layers array of layer configurations * @return {React.Component} a time layer aware component */ -export function timeLayerAware(WrappedComponent, layers) { +export function timeLayerAware(WrappedComponent: React.ComponentType, layers: OlLayerBase[]) { return class TimeLayerAware extends React.Component { From 04ca7cacfb4641a228fcac8cd33d3ff9999a73be Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Wed, 6 Nov 2019 14:16:03 +0100 Subject: [PATCH 23/69] Transforms MappifiedComponent to TypeScript --- ...t.spec.jsx => MappifiedComponent.spec.tsx} | 0 ...edComponent.jsx => MappifiedComponent.tsx} | 28 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) rename src/HigherOrderComponent/MappifiedComponent/{MappifiedComponent.spec.jsx => MappifiedComponent.spec.tsx} (100%) rename src/HigherOrderComponent/MappifiedComponent/{MappifiedComponent.jsx => MappifiedComponent.tsx} (78%) diff --git a/src/HigherOrderComponent/MappifiedComponent/MappifiedComponent.spec.jsx b/src/HigherOrderComponent/MappifiedComponent/MappifiedComponent.spec.tsx similarity index 100% rename from src/HigherOrderComponent/MappifiedComponent/MappifiedComponent.spec.jsx rename to src/HigherOrderComponent/MappifiedComponent/MappifiedComponent.spec.tsx diff --git a/src/HigherOrderComponent/MappifiedComponent/MappifiedComponent.jsx b/src/HigherOrderComponent/MappifiedComponent/MappifiedComponent.tsx similarity index 78% rename from src/HigherOrderComponent/MappifiedComponent/MappifiedComponent.jsx rename to src/HigherOrderComponent/MappifiedComponent/MappifiedComponent.tsx index 9bd47d485b..703613b34c 100644 --- a/src/HigherOrderComponent/MappifiedComponent/MappifiedComponent.jsx +++ b/src/HigherOrderComponent/MappifiedComponent/MappifiedComponent.tsx @@ -4,6 +4,10 @@ import OlMap from 'ol/Map'; import Logger from '@terrestris/base-util/dist/Logger'; +interface MappifiedComponentProps { + withRef: boolean; +} + /** * The HOC factory function. * @@ -12,9 +16,9 @@ import Logger from '@terrestris/base-util/dist/Logger'; * @param {Component} WrappedComponent The component to wrap and enhance. * @return {Component} The wrapped component. */ -export function mappify(WrappedComponent, { +export function mappify

(WrappedComponent: React.ComponentType, { withRef = false -} = {}) { +}: MappifiedComponentProps) { /** * The wrapper class for the given component. @@ -22,7 +26,9 @@ export function mappify(WrappedComponent, { * @class The MappifiedComponent * @extends React.Component */ - class MappifiedComponent extends React.Component { + return class MappifiedComponent extends React.Component { + + _wrappedInstance?: React.ReactElement; /** * The context types. @@ -30,21 +36,21 @@ export function mappify(WrappedComponent, { */ static contextTypes = { map: PropTypes.instanceOf(OlMap).isRequired - } + }; /** * Create the MappifiedComponent. * * @constructs MappifiedComponent */ - constructor(props) { + constructor(props: P & MappifiedComponentProps) { super(props); /** * The wrapped instance. * @type {Element} */ - this.wrappedInstance = null; + this._wrappedInstance = null; } /** @@ -52,9 +58,9 @@ export function mappify(WrappedComponent, { * * @return {Element} The wrapped instance. */ - getWrappedInstance = () => { + getWrappedInstance = (): React.ReactElement | void => { if (withRef) { - return this.wrappedInstance; + return this._wrappedInstance; } else { Logger.warn('No wrapped instance referenced, please call the ' + 'mappify with option withRef = true.'); @@ -68,7 +74,7 @@ export function mappify(WrappedComponent, { */ setWrappedInstance = (instance) => { if (withRef) { - this.wrappedInstance = instance; + this._wrappedInstance = instance; } } @@ -94,7 +100,5 @@ export function mappify(WrappedComponent, { ); } - } - - return MappifiedComponent; + }; } From 9f3b3cac3cf50ac15e5fed6db2d867bbafd4c9c4 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Wed, 6 Nov 2019 14:22:06 +0100 Subject: [PATCH 24/69] Transforms LoadifiedComponent to TypeScript --- ...t.spec.jsx => LoadifiedComponent.spec.tsx} | 0 ...edComponent.jsx => LoadifiedComponent.tsx} | 61 +++++-------------- 2 files changed, 16 insertions(+), 45 deletions(-) rename src/HigherOrderComponent/LoadifiedComponent/{LoadifiedComponent.spec.jsx => LoadifiedComponent.spec.tsx} (100%) rename src/HigherOrderComponent/LoadifiedComponent/{LoadifiedComponent.jsx => LoadifiedComponent.tsx} (66%) diff --git a/src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.spec.jsx b/src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.spec.tsx similarity index 100% rename from src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.spec.jsx rename to src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.spec.tsx diff --git a/src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.jsx b/src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.tsx similarity index 66% rename from src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.jsx rename to src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.tsx index d7399096bf..200bd2e55b 100644 --- a/src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.jsx +++ b/src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.tsx @@ -1,7 +1,11 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { Spin } from 'antd'; import Logger from '@terrestris/base-util/dist/Logger'; +import { SpinProps } from 'antd/lib/spin'; + +interface LoadifiedComponentProps { + withRef: boolean; +} /** * The HOC factory function. @@ -14,9 +18,9 @@ import Logger from '@terrestris/base-util/dist/Logger'; * @param {Component} options The options to apply. * @return {Component} The wrapped component. */ -export function loadify(WrappedComponent, { +export function loadify

(WrappedComponent: React.ComponentType, { withRef = false -} = {}) { +}: LoadifiedComponentProps) { /** * The wrapper class for the given component. @@ -24,40 +28,9 @@ export function loadify(WrappedComponent, { * @class The loadify * @extends React.Component */ - class LoadifiedComponent extends React.Component { + return class LoadifiedComponent extends React.Component> { - /** - * The props. - * @type {Object} - */ - static propTypes = { - /** - * Whether the component should be loading or not. - * @type {Boolean} - */ - spinning: PropTypes.bool, - /** - * Size of the loading element. - * @type {string} - */ - size: PropTypes.oneOf(['small', 'default', 'large']), - /** - * The indicator element to use for the loader. - * @type {String} - */ - indicator: PropTypes.any, - /** - * The tip text of loader element - * @type {String} - */ - tip: PropTypes.string, - /** - * The delay time for the loader to show. - * @type {Number} - */ - delay: PropTypes.number, - - } + _wrappedInstance?: React.ReactElement; /** * The default properties. @@ -66,21 +39,21 @@ export function loadify(WrappedComponent, { */ static defaultProps = { spinning: false - } + }; /** * Create the Loadify. * * @constructs Loadify */ - constructor(props) { + constructor(props: Partial) { super(props); /** * The wrapped instance. * @type {Element} */ - this.wrappedInstance = null; + this._wrappedInstance = null; } /** @@ -88,9 +61,9 @@ export function loadify(WrappedComponent, { * * @return {Element} The wrappend instance. */ - getWrappedInstance = () => { + getWrappedInstance = (): React.ReactElement | void => { if (withRef) { - return this.wrappedInstance; + return this._wrappedInstance; } else { Logger.debug('No wrapped instance referenced, please call the ' + 'Loadify with option withRef = true.'); @@ -104,7 +77,7 @@ export function loadify(WrappedComponent, { */ setWrappedInstance = (instance) => { if (withRef) { - this.wrappedInstance = instance; + this._wrappedInstance = instance; } } @@ -139,7 +112,5 @@ export function loadify(WrappedComponent, { ); } - } - - return LoadifiedComponent; + }; } From d5d31d0fe1ec4b455f1e5bf5c34049de99c6b9cc Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Wed, 6 Nov 2019 14:37:32 +0100 Subject: [PATCH 25/69] Transforms DropTargetMap to TypeScript --- ...rgetMap.spec.jsx => DropTargetMap.spec.tsx} | 0 .../{DropTargetMap.jsx => DropTargetMap.tsx} | 18 +++++------------- .../LoadifiedComponent/LoadifiedComponent.tsx | 2 +- 3 files changed, 6 insertions(+), 14 deletions(-) rename src/HigherOrderComponent/DropTargetMap/{DropTargetMap.spec.jsx => DropTargetMap.spec.tsx} (100%) rename src/HigherOrderComponent/DropTargetMap/{DropTargetMap.jsx => DropTargetMap.tsx} (81%) diff --git a/src/HigherOrderComponent/DropTargetMap/DropTargetMap.spec.jsx b/src/HigherOrderComponent/DropTargetMap/DropTargetMap.spec.tsx similarity index 100% rename from src/HigherOrderComponent/DropTargetMap/DropTargetMap.spec.jsx rename to src/HigherOrderComponent/DropTargetMap/DropTargetMap.spec.tsx diff --git a/src/HigherOrderComponent/DropTargetMap/DropTargetMap.jsx b/src/HigherOrderComponent/DropTargetMap/DropTargetMap.tsx similarity index 81% rename from src/HigherOrderComponent/DropTargetMap/DropTargetMap.jsx rename to src/HigherOrderComponent/DropTargetMap/DropTargetMap.tsx index bce77ef23e..f4dbd13af3 100644 --- a/src/HigherOrderComponent/DropTargetMap/DropTargetMap.jsx +++ b/src/HigherOrderComponent/DropTargetMap/DropTargetMap.tsx @@ -1,7 +1,7 @@ -import PropTypes from 'prop-types'; import React from 'react'; import FileUtil from '@terrestris/ol-util/dist/FileUtil/FileUtil'; +import { MapProps } from '../../Map/MapComponent/MapComponent'; /** * HOC that adds layers to the map if GeoJSON files or shapefile zip files are @@ -9,17 +9,9 @@ import FileUtil from '@terrestris/ol-util/dist/FileUtil/FileUtil'; * @param {React.Component} WrappedComponent the map component * @return {React.Component} a time layer aware component */ -export function onDropAware(WrappedComponent) { +export function onDropAware(WrappedComponent: React.ComponentType) { - return class DropTargetMap extends React.Component { - - static propTypes = { - /** - * The openlayers map injected by mappify. - * @type {ol.Map} - */ - map: PropTypes.object - } + return class DropTargetMap extends React.Component { /** * Calls an appropriate addLayer method depending on the fileending. @@ -27,7 +19,7 @@ export function onDropAware(WrappedComponent) { * endings. * @param {Object} event the drop event */ - onDrop(event) { + onDrop(event: DragEvent) { const { map } = this.props; @@ -50,7 +42,7 @@ export function onDropAware(WrappedComponent) { * Prevents default in order to prevent browser navigation/opening the file. * @param {Object} event the dragover event */ - onDragOver(event) { + onDragOver(event: DragEvent) { event.preventDefault(); } diff --git a/src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.tsx b/src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.tsx index 200bd2e55b..9e87bdd262 100644 --- a/src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.tsx +++ b/src/HigherOrderComponent/LoadifiedComponent/LoadifiedComponent.tsx @@ -18,7 +18,7 @@ interface LoadifiedComponentProps { * @param {Component} options The options to apply. * @return {Component} The wrapped component. */ -export function loadify

(WrappedComponent: React.ComponentType, { +export function loadify(WrappedComponent: React.ComponentType, { withRef = false }: LoadifiedComponentProps) { From a1407e50f9e3fa4e3f3cc7faef341efff5bbf27c Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Wed, 6 Nov 2019 14:58:02 +0100 Subject: [PATCH 26/69] Transforms PropertyGrid to TypeScript --- ...rtyGrid.spec.jsx => PropertyGrid.spec.tsx} | 0 .../{PropertyGrid.jsx => PropertyGrid.tsx} | 142 +++++++++--------- 2 files changed, 74 insertions(+), 68 deletions(-) rename src/Grid/PropertyGrid/{PropertyGrid.spec.jsx => PropertyGrid.spec.tsx} (100%) rename src/Grid/PropertyGrid/{PropertyGrid.jsx => PropertyGrid.tsx} (52%) diff --git a/src/Grid/PropertyGrid/PropertyGrid.spec.jsx b/src/Grid/PropertyGrid/PropertyGrid.spec.tsx similarity index 100% rename from src/Grid/PropertyGrid/PropertyGrid.spec.jsx rename to src/Grid/PropertyGrid/PropertyGrid.spec.tsx diff --git a/src/Grid/PropertyGrid/PropertyGrid.jsx b/src/Grid/PropertyGrid/PropertyGrid.tsx similarity index 52% rename from src/Grid/PropertyGrid/PropertyGrid.jsx rename to src/Grid/PropertyGrid/PropertyGrid.tsx index 00a9453b67..80e026bb3e 100644 --- a/src/Grid/PropertyGrid/PropertyGrid.jsx +++ b/src/Grid/PropertyGrid/PropertyGrid.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { Table } from 'antd'; @@ -10,6 +9,56 @@ import get from 'lodash/get'; import { CSS_PREFIX } from '../../constants'; import './PropertyGrid.less'; +import { TableCurrentDataSource, ColumnProps } from 'antd/lib/table'; + +// i18n +export interface UserChipLocale { +} + +type AttributeNames = { + [key: string]: string +}; + +interface PropertyGridDefaultProps { + /** + * Title of the attribute name column + */ + attributeNameColumnTitle?: string; + /** + * Value in percent representing the width of the attribute name column + * The width of attribute value column wil be calculated depending in this + */ + attributeNameColumnWidthInPercent?: number; + /** + * Title of the attribute value column + */ + attributeValueColumnTitle?: string; +} + +export interface PropertyGridProps extends Partial { + /** + * A CSS class which should be added. + */ + className?: string; + /** + * Array of attribute names to filter + */ + attributeFilter?: string[]; + /** + * Object containing a mapping of attribute names in OL feature to custom ones + * + */ + attributeNames?: AttributeNames; + /** + * Feature for which the properties should be shown + */ + feature: OlFeature; +} + +interface PropertyGridState { + dataSource: any[]; + columns: ColumnProps[]; +} /** * Class representing a feature grid showing the attribute values of a simple feature. @@ -17,77 +66,27 @@ import './PropertyGrid.less'; * @class PropertyGrid * @extends React.Component */ -class PropertyGrid extends React.Component { +class PropertyGrid extends React.Component { /** * The CSS-className added to this component. * @type {String} * @private */ - className = `${CSS_PREFIX}propertygrid` + className = `${CSS_PREFIX}propertygrid`; - /** - * The prop types. - * @type {Object} - */ - static propTypes = { - /** - * An optional CSS class which should be added. - * @type {String} - */ - className: PropTypes.string, - - /** - * Optional title of the attribute name column - * @type {String} - */ - attributeNameColumnTitle: PropTypes.string, - - /** - * Optional value in percent representing the width of the attribute name column - * The width of attribute value column wil be calculated depending in this - * @type {String} - */ - attributeNameColumnWidthInPercent: PropTypes.number, - - /** - * Optional title of the attribute value column - * @type {String} - */ - attributeValueColumnTitle: PropTypes.string, - - /** - * Optional array of attribute names to filter - * @type {Array} - */ - attributeFilter: PropTypes.arrayOf(PropTypes.string), - - /** - * Optional object containing a mapping of attribute names in OL feature to custom ones - * - * @type {Object} - */ - attributeNames: PropTypes.object, - - /** - * Feature for which the properties should be shown - * @type {OlFeature} - */ - feature: PropTypes.instanceOf(OlFeature).isRequired - } - - static defaultProps = { + static defaultProps: PropertyGridDefaultProps = { attributeNameColumnTitle: 'Attribute name', + attributeNameColumnWidthInPercent: 50, attributeValueColumnTitle: 'Attribute value', - attributeNameColumnWidthInPercent: 50 - } + }; /** * The constructor. * * @param {Object} props The initial props. */ - constructor(props) { + constructor(props: PropertyGridProps) { super(props); const { @@ -100,8 +99,8 @@ class PropertyGrid extends React.Component { const { dataSource, columns - } = this.generatePropertyGrid(feature, attributeFilter, attributeNames, - attributeNameColumnWidthInPercent); + } = this.generatePropertyGrid({feature, attributeFilter, attributeNames, + attributeNameColumnWidthInPercent}); this.state = { dataSource, @@ -110,15 +109,22 @@ class PropertyGrid extends React.Component { } /** - * generatePropertyGrid function - * Initialize data store and column definitions of table - * - * @param {OlFeature} feature feature to display - * @param {Array} attributeFilter Array of string values to filter the grid rows - * @param {Object} attributeNames Object containing mapping of attribute names names in feature to custom ones - * @param {Number} attributeNameColumnWidthInPercent Column width (in percent) - */ - generatePropertyGrid(feature, attributeFilter, attributeNames, attributeNameColumnWidthInPercent) { + * Initialize data store and column definitions of table + * + * @param feature feature to display + * @param attributeFilter Array of string values to filter the grid rows + * @param {Object} attributeNames Object containing mapping of attribute names names in feature to custom ones + * @param {Number} attributeNameColumnWidthInPercent Column width (in percent) + */ + generatePropertyGrid({feature, attributeFilter, attributeNames, attributeNameColumnWidthInPercent}: { + feature: OlFeature, + attributeFilter: string[], + attributeNames: AttributeNames, + attributeNameColumnWidthInPercent: number + }): { + dataSource: any, + columns: ColumnProps[] + } { if (!attributeFilter) { attributeFilter = feature.getKeys().filter((attrName) => attrName !== 'geometry'); } From 559f33efeaa3dc89be2c0fce27b3f1954624ef26 Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Wed, 6 Nov 2019 15:15:36 +0100 Subject: [PATCH 27/69] Transforms FeatureGrid to TypeScript --- ...tureGrid.spec.jsx => FeatureGrid.spec.tsx} | 0 .../{FeatureGrid.jsx => FeatureGrid.tsx} | 238 ++++++++---------- src/Grid/PropertyGrid/PropertyGrid.tsx | 2 +- 3 files changed, 103 insertions(+), 137 deletions(-) rename src/Grid/FeatureGrid/{FeatureGrid.spec.jsx => FeatureGrid.spec.tsx} (100%) rename src/Grid/FeatureGrid/{FeatureGrid.jsx => FeatureGrid.tsx} (82%) diff --git a/src/Grid/FeatureGrid/FeatureGrid.spec.jsx b/src/Grid/FeatureGrid/FeatureGrid.spec.tsx similarity index 100% rename from src/Grid/FeatureGrid/FeatureGrid.spec.jsx rename to src/Grid/FeatureGrid/FeatureGrid.spec.tsx diff --git a/src/Grid/FeatureGrid/FeatureGrid.jsx b/src/Grid/FeatureGrid/FeatureGrid.tsx similarity index 82% rename from src/Grid/FeatureGrid/FeatureGrid.jsx rename to src/Grid/FeatureGrid/FeatureGrid.tsx index 5f967a5672..7faffdb90d 100644 --- a/src/Grid/FeatureGrid/FeatureGrid.jsx +++ b/src/Grid/FeatureGrid/FeatureGrid.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { Table } from 'antd'; @@ -21,6 +20,91 @@ import kebabCase from 'lodash/kebabCase'; import MapUtil from '@terrestris/ol-util/dist/MapUtil/MapUtil'; import './FeatureGrid.less'; +import { ColumnProps } from 'antd/lib/table'; + +interface FeatureGridDefaultProps { + /** + * The features to show in the grid and the map (if set). + */ + features: OlFeature[]; + /** + */ + attributeBlacklist?: string[]; + /** + * The default style to apply to the features. + */ + featureStyle: OlStyle | (() => OlStyle); + /** + * The highlight style to apply to the features. + */ + highlightStyle: OlStyle | (() => OlStyle); + /** + * The select style to apply to the features. + */ + selectStyle: OlStyle | (() => OlStyle); + /** + * The name of the vector layer presenting the features in the grid. + */ + layerName: string; + /** + * Custom column definitions to apply to the given column (mapping via key). + * See https://ant.design/components/table/#Column. + */ + columnDefs: ColumnProps; + /** + * A Function that creates the rowkey from the given feature. + * Receives the feature as property. + * Default is: feature => feature.ol_uid + * + */ + keyFunction: (feature: OlFeature) => string; + /** + * Whether the map should center on the current feature's extent on init or + * not. + */ + zoomToExtent: boolean; + /** + * Whether rows and features should be selectable or not. + */ + selectable: boolean; +} + +export interface FeatureGridProps extends Partial { + /** + * A CSS class which should be added to the table. + */ + className?: string; + /** + * A CSS class to add to each table row or a function that + * is evaluated for each record. + */ + rowClassName?: string | ((record: any) => string); + /** + * The map the features should be rendered on. If not given, the features + * will be rendered in the table only. + */ + map: OlMap; + /** + * Callback function, that will be called on rowclick. + */ + onRowClick?: () => void; + /** + * Callback function, that will be called on rowmouseover. + */ + onRowMouseOver?: () => void; + /** + * Callback function, that will be called on rowmouseout. + */ + onRowMouseOut?: () => void; + /** + * Callback function, that will be called if the selection changes. + */ + onRowSelectionChange?: () => void; +} + +interface FeatureGridState { + selectedRowKeys: string[]; +} /** * The FeatureGrid. @@ -28,14 +112,21 @@ import './FeatureGrid.less'; * @class The FeatureGrid * @extends React.Component */ -export class FeatureGrid extends React.Component { +export class FeatureGrid extends React.Component { + + /** + * The reference of this grid. + * @type {String} + * @private + */ + _ref; /** * The class name to add to this component. * @type {String} * @private */ - _className = 'react-geo-feature-grid' + _className = 'react-geo-feature-grid'; /** * The class name to add to each table row. @@ -77,140 +168,13 @@ export class FeatureGrid extends React.Component { * @type {Object} */ static propTypes = { - /** - * An optional CSS class which should be added to the table. - * @type {String} - */ - className: PropTypes.string, - - /** - * An optional CSS class to add to each table row or a function that - * is evaluated for each record. - * @type {String|Function} - */ - rowClassName: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.func - ]), - - /** - * The features to show in the grid and the map (if set). - * @type {Array} - */ - features: PropTypes.arrayOf(PropTypes.instanceOf(OlFeature)), - - /** - * The map the features should be rendered on. If not given, the features - * will be rendered in the table only. - * @type {ol.Map} - */ - map: PropTypes.instanceOf(OlMap), - - /** - * A list of attribute names to hide in the table. - * @type {Array} - */ - attributeBlacklist: PropTypes.arrayOf(PropTypes.string), - - /** - * Optional callback function, that will be called on rowclick. - * @type {Function} - */ - onRowClick: PropTypes.func, - - /** - * Optional callback function, that will be called on rowmouseover. - * @type {Function} - */ - onRowMouseOver: PropTypes.func, - - /** - * Optional callback function, that will be called on rowmouseout. - * @type {Function} - */ - onRowMouseOut: PropTypes.func, - - /** - * Optional callback function, that will be called if the selection changes. - * @type {Function} - */ - onRowSelectionChange: PropTypes.func, - - /** - * Whether the map should center on the current feature's extent on init or - * not. - * @type {Boolean} - */ - zoomToExtent: PropTypes.bool, - - /** - * Whether rows and features should be selectable or not. - * - * @type {Boolean} - */ - selectable: PropTypes.bool, - - /** - * The default style to apply to the features. - * @type {ol.Style|ol.FeatureStyleFunction} - */ - featureStyle: PropTypes.oneOfType([ - PropTypes.instanceOf(OlStyle), - PropTypes.func - ]), - - /** - * The highlight style to apply to the features. - * @type {ol.Style|ol.FeatureStyleFunction} - */ - highlightStyle: PropTypes.oneOfType([ - PropTypes.instanceOf(OlStyle), - PropTypes.func - ]), - - /** - * The select style to apply to the features. - * @type {ol.Style|ol.FeatureStyleFunction} - */ - selectStyle: PropTypes.oneOfType([ - PropTypes.instanceOf(OlStyle), - PropTypes.func - ]), - - /** - * The name of the vector layer presenting the features in the grid. - * @type {String} - */ - layerName: PropTypes.string, - - /** - * Custom column definitions to apply to the given column (mapping via key). - * See https://ant.design/components/table/#Column. - * @type {Object} - */ - columnDefs: PropTypes.object, - - /** - * The children to render. - * @type {Element} - */ - children: PropTypes.element, - - /** - * A Function that creates the rowkey from the given feature. - * Receives the feature as property. - * Default is: feature => feature.ol_uid - * - * @type {Function} - */ - keyFunction: PropTypes.func }; /** * The default properties. * @type {Object} */ - static defaultProps = { + static defaultProps: FeatureGridDefaultProps = { features: [], attributeBlacklist: [], featureStyle: new OlStyle({ @@ -272,13 +236,15 @@ export class FeatureGrid extends React.Component { }), layerName: 'react-geo-feature-grid-layer', columnDefs: {}, - keyFunction: feature => feature.ol_uid - } + keyFunction: feature => feature.ol_uid, + zoomToExtent: false, + selectable: false + }; /** * The constructor. */ - constructor(props) { + constructor(props: FeatureGridProps) { super(props); this.state = { @@ -310,7 +276,7 @@ export class FeatureGrid extends React.Component { * * @param {Object} prevProps The previous props. */ - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps: FeatureGridProps) { const { map, features, @@ -619,7 +585,7 @@ export class FeatureGrid extends React.Component { keyFunction } = this.props; - const feature = features.filter(feature => keyFunction(feature) === key); + const feature = features.filter(f => keyFunction(f) === key); return feature[0]; } diff --git a/src/Grid/PropertyGrid/PropertyGrid.tsx b/src/Grid/PropertyGrid/PropertyGrid.tsx index 80e026bb3e..dfab273dfc 100644 --- a/src/Grid/PropertyGrid/PropertyGrid.tsx +++ b/src/Grid/PropertyGrid/PropertyGrid.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { Table } from 'antd'; +import { ColumnProps } from 'antd/lib/table'; import OlFeature from 'ol/Feature'; @@ -9,7 +10,6 @@ import get from 'lodash/get'; import { CSS_PREFIX } from '../../constants'; import './PropertyGrid.less'; -import { TableCurrentDataSource, ColumnProps } from 'antd/lib/table'; // i18n export interface UserChipLocale { From f82a63671a676e595c34a1e7d713b3c18a2e588a Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Wed, 6 Nov 2019 16:05:22 +0100 Subject: [PATCH 28/69] Transforms AgFeatureGrid to TypeScript --- ...reGrid.spec.jsx => AgFeatureGrid.spec.tsx} | 0 .../{AgFeatureGrid.jsx => AgFeatureGrid.tsx} | 336 +++++++----------- 2 files changed, 137 insertions(+), 199 deletions(-) rename src/Grid/AgFeatureGrid/{AgFeatureGrid.spec.jsx => AgFeatureGrid.spec.tsx} (100%) rename src/Grid/AgFeatureGrid/{AgFeatureGrid.jsx => AgFeatureGrid.tsx} (78%) diff --git a/src/Grid/AgFeatureGrid/AgFeatureGrid.spec.jsx b/src/Grid/AgFeatureGrid/AgFeatureGrid.spec.tsx similarity index 100% rename from src/Grid/AgFeatureGrid/AgFeatureGrid.spec.jsx rename to src/Grid/AgFeatureGrid/AgFeatureGrid.spec.tsx diff --git a/src/Grid/AgFeatureGrid/AgFeatureGrid.jsx b/src/Grid/AgFeatureGrid/AgFeatureGrid.tsx similarity index 78% rename from src/Grid/AgFeatureGrid/AgFeatureGrid.jsx rename to src/Grid/AgFeatureGrid/AgFeatureGrid.tsx index aa9d479fd9..b900659e09 100644 --- a/src/Grid/AgFeatureGrid/AgFeatureGrid.jsx +++ b/src/Grid/AgFeatureGrid/AgFeatureGrid.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { AgGridReact } from 'ag-grid-react'; @@ -28,20 +27,144 @@ import 'ag-grid-community/dist/styles/ag-grid.css'; import 'ag-grid-community/dist/styles/ag-theme-balham.css'; import 'ag-grid-community/dist/styles/ag-theme-fresh.css'; +interface AgFeatureGridDefaultProps { + /** + * The height of the grid. + */ + height: number | string; + /** + * The theme to use for the grid. See + * https://www.ag-grid.com/javascript-grid-styling/ for available options. + * Note: CSS must be loaded to use the theme! + */ + theme: string; + /** + * The features to show in the grid and the map (if set). + */ + features: OlFeature[]; + /** + */ + attributeBlacklist?: string[]; + /** + * The default style to apply to the features. + */ + featureStyle: OlStyle | (() => OlStyle); + /** + * The highlight style to apply to the features. + */ + highlightStyle: OlStyle | (() => OlStyle); + /** + * The select style to apply to the features. + */ + selectStyle: OlStyle | (() => OlStyle); + /** + * The name of the vector layer presenting the features in the grid. + */ + layerName: string; + /** + * Custom column definitions to apply to the given column (mapping via key). + */ + columnDefs: any; + /** + * A Function that creates the rowkey from the given feature. + * Receives the feature as property. + * Default is: feature => feature.ol_uid + */ + keyFunction: (feature: OlFeature) => string; + /** + * Whether the map should center on the current feature's extent on init or + * not. + */ + zoomToExtent: boolean; + /** + * Whether rows and features should be selectable or not. + */ + selectable: boolean; +} + +export interface AgFeatureGridProps extends Partial { + /** + * The width of the grid. + * + * @type {Number|String} + */ + width: number | string; + /** + * A CSS class which should be added to the table. + */ + className?: string; + /** + * A CSS class to add to each table row or a function that + * is evaluated for each record. + */ + rowClassName?: string | ((record: any) => string); + /** + * The map the features should be rendered on. If not given, the features + * will be rendered in the table only. + */ + map: OlMap; + /** + * Custom row data to be shown in feature grid. This might be helpful if + * original feature properties should be manipulated in some way before they + * are represented in grid. + * If provided, #getRowData method won't be called. + */ + rowData: any[]; + /** + * Callback function, that will be called on rowclick. + */ + onRowClick?: () => void; + /** + * Callback function, that will be called on rowmouseover. + */ + onRowMouseOver?: () => void; + /** + * Callback function, that will be called on rowmouseout. + */ + onRowMouseOut?: () => void; + /** + * Callback function, that will be called if the selection changes. + */ + onRowSelectionChange?: () => void; + /** + * Optional callback function, that will be called if `selectable` is set + * `true` and the a `click` event on the map occurs, e.g. a feature has been + * selected in the map. The function receives the olEvt and the selected + * features (if any). + */ + onMapSingleClick: () => void; + /* + * A Function that is called once the grid is ready. + */ + onGridIsReady?: (grid: any) => void; +} + +interface AgFeatureGridState { + grid: any; + selectedRows: any[]; +} + /** * The AgFeatureGrid. * * @class The AgFeatureGrid * @extends React.Component */ -export class AgFeatureGrid extends React.Component { +export class AgFeatureGrid extends React.Component { + + /** + * The reference of this grid. + * @type {String} + * @private + */ + _ref; /** * The className added to this component. * @type {String} * @private */ - _className = `${CSS_PREFIX}ag-feature-grid` + _className = `${CSS_PREFIX}ag-feature-grid`; /** * The class name to add to each table row. @@ -78,198 +201,11 @@ export class AgFeatureGrid extends React.Component { */ _layer = null; - /** - * The properties. - * @type {Object} - */ - static propTypes = { - /** - * An optional CSS class which should be added to the table. - * @type {String} - */ - className: PropTypes.string, - - /** - * The height of the grid. - * - * @type {Number|String} - */ - height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - - /** - * The width of the grid. - * - * @type {Number|String} - */ - width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - - /** - * The theme to use for the grid. See - * https://www.ag-grid.com/javascript-grid-styling/ for available options. - * Note: CSS must be loaded to use the theme! - */ - theme: PropTypes.string, - - /** - * An optional CSS class to add to each table row or a function that - * is evaluated for each record. - * @type {String|Function} - */ - rowClassName: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.func - ]), - - /** - * The features to show in the grid and the map (if set). - * @type {Array} - */ - features: PropTypes.arrayOf(PropTypes.instanceOf(OlFeature)), - - /** - * The map the features should be rendered on. If not given, the features - * will be rendered in the table only. - * @type {ol.Map} - */ - map: PropTypes.instanceOf(OlMap), - - /** - * A list of attribute names to hide in the table. - * @type {Array} - */ - attributeBlacklist: PropTypes.arrayOf(PropTypes.string), - - /** - * Optional callback function, that will be called on rowclick. - * @type {Function} - */ - onRowClick: PropTypes.func, - - /** - * Optional callback function, that will be called on rowmouseover. - * @type {Function} - */ - onRowMouseOver: PropTypes.func, - - /** - * Optional callback function, that will be called on rowmouseout. - * @type {Function} - */ - onRowMouseOut: PropTypes.func, - - /** - * Optional callback function, that will be called if the selection changes. - * @type {Function} - */ - onRowSelectionChange: PropTypes.func, - - /** - * Optional callback function, that will be called if `selectable` is set - * `true` and the a `click` event on the map occurs, e.g. a feature has been - * selected in the map. The function receives the olEvt and the selected - * features (if any). - * @type {Function} - */ - onMapSingleClick: PropTypes.func, - - /** - * Whether the map should center on the current feature's extent on init or - * not. - * @type {Boolean} - */ - zoomToExtent: PropTypes.bool, - - /** - * Whether features should be selectable via a map click or not. If you want - * to enable/disable a checkbox, please set checkboxSelection on a column - * in columnDefs. - * - * @type {Boolean} - */ - selectable: PropTypes.bool, - - /** - * The default style to apply to the features. - * @type {ol.Style|ol.FeatureStyleFunction} - */ - featureStyle: PropTypes.oneOfType([ - PropTypes.instanceOf(OlStyle), - PropTypes.func - ]), - - /** - * The highlight style to apply to the features. - * @type {ol.Style|ol.FeatureStyleFunction} - */ - highlightStyle: PropTypes.oneOfType([ - PropTypes.instanceOf(OlStyle), - PropTypes.func - ]), - - /** - * The select style to apply to the features. - * @type {ol.Style|ol.FeatureStyleFunction} - */ - selectStyle: PropTypes.oneOfType([ - PropTypes.instanceOf(OlStyle), - PropTypes.func - ]), - - /** - * The name of the vector layer presenting the features in the grid. - * @type {String} - */ - layerName: PropTypes.string, - - /** - * Custom column definitions to apply to the given column (mapping via key). - * See https://ant.design/components/table/#Column. You can either specify - * an index property on every column definition to get an exact order, or - * get a somewhat random order by not specifying an index property at all. - * If provided as array, #getColumnDefs won't be called. - * @type {Object|Array} - */ - columnDefs: PropTypes.oneOfType([ - PropTypes.object, - PropTypes.arrayOf(PropTypes.object) - ]), - - /** - * Custom row data to be shown in feature grid. This might be helpful if - * original feature properties should be manipulated in some way before they - * are represented in grid. - * If provided, #getRowData method won't be called. - * @type {Array} - */ - rowData: PropTypes.arrayOf(PropTypes.object), - - /** - * The children to render. - * @type {Element} - */ - children: PropTypes.element, - - /** - * A Function that creates the rowkey from the given feature. - * Receives the feature as property. - * Default is: feature => feature.ol_uid - * - * @type {Function} - */ - keyFunction: PropTypes.func, - - /** - * A Function that is called once the grid is ready. - * @type {Function} - */ - onGridIsReady: PropTypes.func - }; - /** * The default properties. * @type {Object} */ - static defaultProps = { + static defaultProps: AgFeatureGridDefaultProps = { theme: 'ag-theme-balham', height: 250, features: [], @@ -333,13 +269,15 @@ export class AgFeatureGrid extends React.Component { }), layerName: 'react-geo-feature-grid-layer', columnDefs: {}, - keyFunction: feature => feature.ol_uid - } + keyFunction: feature => feature.ol_uid, + zoomToExtent: false, + selectable: false + }; /** * The constructor. */ - constructor(props) { + constructor(props: AgFeatureGridProps) { super(props); this.state = { @@ -372,7 +310,7 @@ export class AgFeatureGrid extends React.Component { * * @param {Object} prevProps The previous props. */ - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps: AgFeatureGridProps) { const { map, features, @@ -732,7 +670,7 @@ export class AgFeatureGrid extends React.Component { keyFunction } = this.props; - const feature = features.filter(feature => keyFunction(feature) === key); + const feature = features.filter(f => keyFunction(f) === key); return feature[0]; } @@ -971,7 +909,7 @@ export class AgFeatureGrid extends React.Component { selectedRowsAfter = grid.api.getSelectedRows(); } - const deselectedRows = differenceWith(selectedRows, selectedRowsAfter, (a,b) => a.key === b.key); + const deselectedRows = differenceWith(selectedRows, selectedRowsAfter, (a: any , b: any) => a.key === b.key); const selectedFeatures = selectedRowsAfter.map(row => this.getFeatureFromRowKey(row.key)); const deselectedFeatures = deselectedRows.map(row => this.getFeatureFromRowKey(row.key)); @@ -993,7 +931,7 @@ export class AgFeatureGrid extends React.Component { * * @param {*} grid */ - onGridReady(grid) { + onGridReady(grid: any) { this.setState({ grid }, this.onVisiblityChange); @@ -1071,7 +1009,7 @@ export class AgFeatureGrid extends React.Component { columnDefs={columnDefs && isArray(columnDefs) ? columnDefs : this.getColumnDefs()} rowData={rowData && isArray(rowData) ? rowData : this.getRowData()} onGridReady={this.onGridReady.bind(this)} - rowSelection='multiple' + rowSelection="multiple" suppressRowClickSelection={true} onSelectionChanged={this.onSelectionChanged.bind(this)} onRowClicked={this.onRowClick.bind(this)} From 653f7afa568c7b8f120f16a8173a3b291378f05d Mon Sep 17 00:00:00 2001 From: Kai Volland Date: Wed, 6 Nov 2019 16:51:19 +0100 Subject: [PATCH 29/69] Transforms CRSCombo to TypeScript --- ...> CoordinateReferenceSystemCombo.spec.tsx} | 0 ...jsx => CoordinateReferenceSystemCombo.tsx} | 84 +++++++++---------- 2 files changed, 41 insertions(+), 43 deletions(-) rename src/Field/CoordinateReferenceSystemCombo/{CoordinateReferenceSystemCombo.spec.jsx => CoordinateReferenceSystemCombo.spec.tsx} (100%) rename src/Field/CoordinateReferenceSystemCombo/{CoordinateReferenceSystemCombo.jsx => CoordinateReferenceSystemCombo.tsx} (78%) diff --git a/src/Field/CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo.spec.jsx b/src/Field/CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo.spec.tsx similarity index 100% rename from src/Field/CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo.spec.jsx rename to src/Field/CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo.spec.tsx diff --git a/src/Field/CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo.jsx b/src/Field/CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo.tsx similarity index 78% rename from src/Field/CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo.jsx rename to src/Field/CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo.tsx index 2ca117d4a7..174e3cc81e 100644 --- a/src/Field/CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo.jsx +++ b/src/Field/CoordinateReferenceSystemCombo/CoordinateReferenceSystemCombo.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { AutoComplete } from 'antd'; const Option = AutoComplete.Option; @@ -8,6 +7,39 @@ import Logger from '@terrestris/base-util/dist/Logger'; import { CSS_PREFIX } from '../../constants'; +interface CRSComboDefaultProps { + /** + * The API to query for CRS definitions + * default: https://epsg.io + */ + crsApiUrl: string; + /** + * The empty text set if no value is given / provided + */ + emptyTextPlaceholderText: string; + /** + * A function + */ + onSelect: (crsDefinition: any) => void; +} + +export interface CRSComboProps extends Partial { + /** + * An optional CSS class which should be added. + */ + className: string; + /** + * An array of predefined crs definitions habving at least value (name of + * CRS) and code (e.g. EPSG-code of CRS) property + */ + predefinedCrsDefinitions: {value: string, code: string}[]; +} + +interface CRSComboState { + crsDefinitions: any[]; + value: string; +} + /** * Class representing a combo to choose coordinate projection system via a * dropdown menu and / or autocompletion @@ -15,59 +47,26 @@ import { CSS_PREFIX } from '../../constants'; * @class The CoordinateReferenceSystemCombo * @extends React.Component */ -class CoordinateReferenceSystemCombo extends React.Component { +class CoordinateReferenceSystemCombo extends React.Component { /** * The className added to this component. * @type {String} * @private */ - className = `${CSS_PREFIX}coordinatereferencesystemcombo` - - static propTypes = { - /** - * An optional CSS class which should be added. - * @type {String} - */ - className: PropTypes.string, - /** - * The API to query for CRS definitions - * default: https://epsg.io - * @type {String} - */ - crsApiUrl: PropTypes.string, - /** - * The empty text set if no value is given / provided - * @type {String} - */ - emptyTextPlaceholderText: PropTypes.string, - /** - * An array of predefined crs definitions habving at least value (name of - * CRS) and code (e.g. EPSG-code of CRS) property - * @type {Array} - */ - predefinedCrsDefinitions: PropTypes.arrayOf(PropTypes.shape({ - value: PropTypes.string, - code: PropTypes.string - })), - /** - * A function - * @type {String} - */ - onSelect: PropTypes.func - } + className = `${CSS_PREFIX}coordinatereferencesystemcombo`; - static defaultProps = { + static defaultProps: CRSComboDefaultProps = { emptyTextPlaceholderText: 'Please select a CRS', crsApiUrl: 'https://epsg.io/', - onSelect: () => {} - } + onSelect: () => undefined + }; /** * Create a CRS combo. * @constructs CoordinateReferenceSystemCombo */ - constructor(props) { + constructor(props: CRSComboProps) { super(props); this.state = { @@ -99,9 +98,8 @@ class CoordinateReferenceSystemCombo extends React.Component { * This function gets called when the EPSG.io fetch returns an error. * It logs the error to the console. * - * @param {String} error The error string. */ - onFetchError(error) { + onFetchError(error: string) { Logger.error(`Error while requesting in CoordinateReferenceSystemCombo: ${error}`); } @@ -181,7 +179,7 @@ class CoordinateReferenceSystemCombo extends React.Component { * * @return {Option} Option component to render */ - transformCrsObjectsToOptions(crsObject) { + transformCrsObjectsToOptions(crsObject: any) { return (