From df65cc3effad4d867703aeaac3cbfc1dbadffd31 Mon Sep 17 00:00:00 2001 From: HarelM Date: Thu, 21 Dec 2023 15:16:41 +0200 Subject: [PATCH] Migrate more components --- package-lock.json | 19 ++++ package.json | 1 + .../{InputJson.jsx => InputJson.tsx} | 92 ++++++++++--------- ...ilterEditor.jsx => SingleFilterEditor.tsx} | 38 ++++---- 4 files changed, 85 insertions(+), 65 deletions(-) rename src/components/{InputJson.jsx => InputJson.tsx} (64%) rename src/components/{SingleFilterEditor.jsx => SingleFilterEditor.tsx} (61%) diff --git a/package-lock.json b/package-lock.json index 21ee9a7d..0ef80846 100644 --- a/package-lock.json +++ b/package-lock.json @@ -67,6 +67,7 @@ "@storybook/react": "^7.6.5", "@storybook/react-vite": "^7.6.5", "@storybook/theming": "^7.6.5", + "@types/codemirror": "^5.60.15", "@types/color": "^3.0.6", "@types/cors": "^2.8.17", "@types/lodash.capitalize": "^4.2.9", @@ -4589,6 +4590,15 @@ "@types/chai": "*" } }, + "node_modules/@types/codemirror": { + "version": "5.60.15", + "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.15.tgz", + "integrity": "sha512-dTOvwEQ+ouKJ/rE9LT1Ue2hmP6H1mZv5+CCnNWu2qtiOe2LQa9lCprEY20HxiDmV/Bxh+dXjywmy5aKvoGjULA==", + "dev": true, + "dependencies": { + "@types/tern": "*" + } + }, "node_modules/@types/color": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.6.tgz", @@ -4976,6 +4986,15 @@ "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", "dev": true }, + "node_modules/@types/tern": { + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz", + "integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/@types/uuid": { "version": "9.0.7", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", diff --git a/package.json b/package.json index 8bf44847..a217705d 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "@storybook/react": "^7.6.5", "@storybook/react-vite": "^7.6.5", "@storybook/theming": "^7.6.5", + "@types/codemirror": "^5.60.15", "@types/color": "^3.0.6", "@types/cors": "^2.8.17", "@types/lodash.capitalize": "^4.2.9", diff --git a/src/components/InputJson.jsx b/src/components/InputJson.tsx similarity index 64% rename from src/components/InputJson.jsx rename to src/components/InputJson.tsx index 54bac981..21d49bc8 100644 --- a/src/components/InputJson.jsx +++ b/src/components/InputJson.tsx @@ -1,47 +1,45 @@ import React from 'react' -import PropTypes from 'prop-types' import classnames from 'classnames'; - -import Block from './Block' -import FieldString from './FieldString' -import CodeMirror from 'codemirror'; +import CodeMirror, { ModeSpec } from 'codemirror'; import 'codemirror/mode/javascript/javascript' import 'codemirror/addon/lint/lint' import 'codemirror/addon/edit/matchbrackets' import 'codemirror/lib/codemirror.css' import 'codemirror/addon/lint/lint.css' -import jsonlint from 'jsonlint' import stringifyPretty from 'json-stringify-pretty-compact' import '../util/codemirror-mgl'; -export default class InputJson extends React.Component { - static propTypes = { - layer: PropTypes.any.isRequired, - maxHeight: PropTypes.number, - onChange: PropTypes.func, - lineNumbers: PropTypes.bool, - lineWrapping: PropTypes.bool, - getValue: PropTypes.func, - gutters: PropTypes.array, - className: PropTypes.string, - onFocus: PropTypes.func, - onBlur: PropTypes.func, - onJSONValid: PropTypes.func, - onJSONInvalid: PropTypes.func, - mode: PropTypes.object, - lint: PropTypes.oneOfType([ - PropTypes.bool, - PropTypes.object, - ]), - } +type InputJsonProps = { + layer: any + maxHeight?: number + onChange?(...args: unknown[]): unknown + lineNumbers?: boolean + lineWrapping?: boolean + getValue(data: any): string + gutters?: string[] + className?: string + onFocus?(...args: unknown[]): unknown + onBlur?(...args: unknown[]): unknown + onJSONValid?(...args: unknown[]): unknown + onJSONInvalid?(...args: unknown[]): unknown + mode?: ModeSpec + lint?: boolean | object +}; +type InputJsonState = { + isEditing: boolean + showMessage: boolean + prevValue: string +}; + +export default class InputJson extends React.Component { static defaultProps = { lineNumbers: true, lineWrapping: false, gutters: ["CodeMirror-lint-markers"], - getValue: (data) => { + getValue: (data: any) => { return stringifyPretty(data, {indent: 2, maxLength: 40}); }, onFocus: () => {}, @@ -49,8 +47,12 @@ export default class InputJson extends React.Component { onJSONInvalid: () => {}, onJSONValid: () => {}, } + _keyEvent: string; + _doc: CodeMirror.Editor | undefined; + _el: HTMLDivElement | null = null; + _cancelNextChange: boolean = false; - constructor(props) { + constructor(props: InputJsonProps) { super(props); this._keyEvent = "keyboard"; this.state = { @@ -61,7 +63,7 @@ export default class InputJson extends React.Component { } componentDidMount () { - this._doc = CodeMirror(this._el, { + this._doc = CodeMirror(this._el!, { value: this.props.getValue(this.props.layer), mode: this.props.mode || { name: "mgl", @@ -84,12 +86,12 @@ export default class InputJson extends React.Component { this._doc.on('blur', this.onBlur); } - onPointerDown = (cm, e) => { + onPointerDown = () => { this._keyEvent = "pointer"; } - onFocus = (cm, e) => { - this.props.onFocus(); + onFocus = () => { + if (this.props.onFocus) this.props.onFocus(); this.setState({ isEditing: true, showMessage: (this._keyEvent === "keyboard"), @@ -98,7 +100,7 @@ export default class InputJson extends React.Component { onBlur = () => { this._keyEvent = "keyboard"; - this.props.onBlur(); + if (this.props.onBlur) this.props.onBlur(); this.setState({ isEditing: false, showMessage: false, @@ -106,29 +108,29 @@ export default class InputJson extends React.Component { } componentWillUnMount () { - this._doc.off('change', this.onChange); - this._doc.off('focus', this.onFocus); - this._doc.off('blur', this.onBlur); + this._doc!.off('change', this.onChange); + this._doc!.off('focus', this.onFocus); + this._doc!.off('blur', this.onBlur); } - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps: InputJsonProps) { if (!this.state.isEditing && prevProps.layer !== this.props.layer) { this._cancelNextChange = true; - this._doc.setValue( + this._doc!.setValue( this.props.getValue(this.props.layer), ) } } - onChange = (e) => { + onChange = (_e: unknown) => { if (this._cancelNextChange) { this._cancelNextChange = false; this.setState({ - prevValue: this._doc.getValue(), + prevValue: this._doc!.getValue(), }) return; } - const newCode = this._doc.getValue(); + const newCode = this._doc!.getValue(); if (this.state.prevValue !== newCode) { let parsedLayer, err; @@ -139,12 +141,12 @@ export default class InputJson extends React.Component { console.warn(_err) } - if (err) { + if (err && this.props.onJSONInvalid) { this.props.onJSONInvalid(); } else { - this.props.onChange(parsedLayer) - this.props.onJSONValid(); + if (this.props.onChange) this.props.onChange(parsedLayer) + if (this.props.onJSONValid) this.props.onJSONValid(); } } @@ -155,7 +157,7 @@ export default class InputJson extends React.Component { render() { const {showMessage} = this.state; - const style = {}; + const style = {} as {maxHeight?: number}; if (this.props.maxHeight) { style.maxHeight = this.props.maxHeight; } diff --git a/src/components/SingleFilterEditor.jsx b/src/components/SingleFilterEditor.tsx similarity index 61% rename from src/components/SingleFilterEditor.jsx rename to src/components/SingleFilterEditor.tsx index 752a2d5d..63661a60 100644 --- a/src/components/SingleFilterEditor.jsx +++ b/src/components/SingleFilterEditor.tsx @@ -1,18 +1,17 @@ import React from 'react' -import PropTypes from 'prop-types' import {otherFilterOps} from '../libs/filterops' import InputString from './InputString' import InputAutocomplete from './InputAutocomplete' import InputSelect from './InputSelect' -function tryParseInt(v) { +function tryParseInt(v: string | number) { if (v === '') return v - if (isNaN(v)) return v - return parseFloat(v) + if (isNaN(v as number)) return v + return parseFloat(v as string) } -function tryParseBool(v) { +function tryParseBool(v: string | boolean) { const isString = (typeof(v) === "string"); if(!isString) { return v; @@ -29,24 +28,24 @@ function tryParseBool(v) { } } -function parseFilter(v) { - v = tryParseInt(v); - v = tryParseBool(v); +function parseFilter(v: string | boolean | number) { + v = tryParseInt(v as any); + v = tryParseBool(v as any); return v; } -export default class SingleFilterEditor extends React.Component { - static propTypes = { - filter: PropTypes.array.isRequired, - onChange: PropTypes.func.isRequired, - properties: PropTypes.object, - } +type SingleFilterEditorProps = { + filter: any[] + onChange(...args: unknown[]): unknown + properties?: {[key: string]: string} +}; +export default class SingleFilterEditor extends React.Component { static defaultProps = { properties: {}, } - onFilterPartChanged(filterOp, propertyName, filterArgs) { + onFilterPartChanged(filterOp: string, propertyName: string, filterArgs: string[]) { let newFilter = [filterOp, propertyName, ...filterArgs.map(parseFilter)] if(filterOp === 'has' || filterOp === '!has') { newFilter = [filterOp, propertyName] @@ -67,15 +66,15 @@ export default class SingleFilterEditor extends React.Component { [propName, propName])} - onChange={newPropertyName => this.onFilterPartChanged(filterOp, newPropertyName, filterArgs)} + options={Object.keys(this.props.properties!).map(propName => [propName, propName])} + onChange={(newPropertyName: string) => this.onFilterPartChanged(filterOp, newPropertyName, filterArgs)} />
this.onFilterPartChanged(newFilterOp, propertyName, filterArgs)} + onChange={(newFilterOp: string) => this.onFilterPartChanged(newFilterOp, propertyName, filterArgs)} options={otherFilterOps} />
@@ -84,12 +83,11 @@ export default class SingleFilterEditor extends React.Component { this.onFilterPartChanged(filterOp, propertyName, v.split(','))} + onChange={(v: string) => this.onFilterPartChanged(filterOp, propertyName, v.split(','))} /> } } - }