Migrate more components

This commit is contained in:
HarelM
2023-12-21 15:16:41 +02:00
parent c633368a9a
commit df65cc3eff
4 changed files with 85 additions and 65 deletions
+19
View File
@@ -67,6 +67,7 @@
"@storybook/react": "^7.6.5", "@storybook/react": "^7.6.5",
"@storybook/react-vite": "^7.6.5", "@storybook/react-vite": "^7.6.5",
"@storybook/theming": "^7.6.5", "@storybook/theming": "^7.6.5",
"@types/codemirror": "^5.60.15",
"@types/color": "^3.0.6", "@types/color": "^3.0.6",
"@types/cors": "^2.8.17", "@types/cors": "^2.8.17",
"@types/lodash.capitalize": "^4.2.9", "@types/lodash.capitalize": "^4.2.9",
@@ -4589,6 +4590,15 @@
"@types/chai": "*" "@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": { "node_modules/@types/color": {
"version": "3.0.6", "version": "3.0.6",
"resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.6.tgz",
@@ -4976,6 +4986,15 @@
"integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==",
"dev": true "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": { "node_modules/@types/uuid": {
"version": "9.0.7", "version": "9.0.7",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz",
+1
View File
@@ -96,6 +96,7 @@
"@storybook/react": "^7.6.5", "@storybook/react": "^7.6.5",
"@storybook/react-vite": "^7.6.5", "@storybook/react-vite": "^7.6.5",
"@storybook/theming": "^7.6.5", "@storybook/theming": "^7.6.5",
"@types/codemirror": "^5.60.15",
"@types/color": "^3.0.6", "@types/color": "^3.0.6",
"@types/cors": "^2.8.17", "@types/cors": "^2.8.17",
"@types/lodash.capitalize": "^4.2.9", "@types/lodash.capitalize": "^4.2.9",
@@ -1,47 +1,45 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'; import classnames from 'classnames';
import CodeMirror, { ModeSpec } from 'codemirror';
import Block from './Block'
import FieldString from './FieldString'
import CodeMirror from 'codemirror';
import 'codemirror/mode/javascript/javascript' import 'codemirror/mode/javascript/javascript'
import 'codemirror/addon/lint/lint' import 'codemirror/addon/lint/lint'
import 'codemirror/addon/edit/matchbrackets' import 'codemirror/addon/edit/matchbrackets'
import 'codemirror/lib/codemirror.css' import 'codemirror/lib/codemirror.css'
import 'codemirror/addon/lint/lint.css' import 'codemirror/addon/lint/lint.css'
import jsonlint from 'jsonlint'
import stringifyPretty from 'json-stringify-pretty-compact' import stringifyPretty from 'json-stringify-pretty-compact'
import '../util/codemirror-mgl'; import '../util/codemirror-mgl';
export default class InputJson extends React.Component { type InputJsonProps = {
static propTypes = { layer: any
layer: PropTypes.any.isRequired, maxHeight?: number
maxHeight: PropTypes.number, onChange?(...args: unknown[]): unknown
onChange: PropTypes.func, lineNumbers?: boolean
lineNumbers: PropTypes.bool, lineWrapping?: boolean
lineWrapping: PropTypes.bool, getValue(data: any): string
getValue: PropTypes.func, gutters?: string[]
gutters: PropTypes.array, className?: string
className: PropTypes.string, onFocus?(...args: unknown[]): unknown
onFocus: PropTypes.func, onBlur?(...args: unknown[]): unknown
onBlur: PropTypes.func, onJSONValid?(...args: unknown[]): unknown
onJSONValid: PropTypes.func, onJSONInvalid?(...args: unknown[]): unknown
onJSONInvalid: PropTypes.func, mode?: ModeSpec<any>
mode: PropTypes.object, lint?: boolean | object
lint: PropTypes.oneOfType([ };
PropTypes.bool,
PropTypes.object,
]),
}
type InputJsonState = {
isEditing: boolean
showMessage: boolean
prevValue: string
};
export default class InputJson extends React.Component<InputJsonProps, InputJsonState> {
static defaultProps = { static defaultProps = {
lineNumbers: true, lineNumbers: true,
lineWrapping: false, lineWrapping: false,
gutters: ["CodeMirror-lint-markers"], gutters: ["CodeMirror-lint-markers"],
getValue: (data) => { getValue: (data: any) => {
return stringifyPretty(data, {indent: 2, maxLength: 40}); return stringifyPretty(data, {indent: 2, maxLength: 40});
}, },
onFocus: () => {}, onFocus: () => {},
@@ -49,8 +47,12 @@ export default class InputJson extends React.Component {
onJSONInvalid: () => {}, onJSONInvalid: () => {},
onJSONValid: () => {}, onJSONValid: () => {},
} }
_keyEvent: string;
_doc: CodeMirror.Editor | undefined;
_el: HTMLDivElement | null = null;
_cancelNextChange: boolean = false;
constructor(props) { constructor(props: InputJsonProps) {
super(props); super(props);
this._keyEvent = "keyboard"; this._keyEvent = "keyboard";
this.state = { this.state = {
@@ -61,7 +63,7 @@ export default class InputJson extends React.Component {
} }
componentDidMount () { componentDidMount () {
this._doc = CodeMirror(this._el, { this._doc = CodeMirror(this._el!, {
value: this.props.getValue(this.props.layer), value: this.props.getValue(this.props.layer),
mode: this.props.mode || { mode: this.props.mode || {
name: "mgl", name: "mgl",
@@ -84,12 +86,12 @@ export default class InputJson extends React.Component {
this._doc.on('blur', this.onBlur); this._doc.on('blur', this.onBlur);
} }
onPointerDown = (cm, e) => { onPointerDown = () => {
this._keyEvent = "pointer"; this._keyEvent = "pointer";
} }
onFocus = (cm, e) => { onFocus = () => {
this.props.onFocus(); if (this.props.onFocus) this.props.onFocus();
this.setState({ this.setState({
isEditing: true, isEditing: true,
showMessage: (this._keyEvent === "keyboard"), showMessage: (this._keyEvent === "keyboard"),
@@ -98,7 +100,7 @@ export default class InputJson extends React.Component {
onBlur = () => { onBlur = () => {
this._keyEvent = "keyboard"; this._keyEvent = "keyboard";
this.props.onBlur(); if (this.props.onBlur) this.props.onBlur();
this.setState({ this.setState({
isEditing: false, isEditing: false,
showMessage: false, showMessage: false,
@@ -106,29 +108,29 @@ export default class InputJson extends React.Component {
} }
componentWillUnMount () { componentWillUnMount () {
this._doc.off('change', this.onChange); this._doc!.off('change', this.onChange);
this._doc.off('focus', this.onFocus); this._doc!.off('focus', this.onFocus);
this._doc.off('blur', this.onBlur); this._doc!.off('blur', this.onBlur);
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps: InputJsonProps) {
if (!this.state.isEditing && prevProps.layer !== this.props.layer) { if (!this.state.isEditing && prevProps.layer !== this.props.layer) {
this._cancelNextChange = true; this._cancelNextChange = true;
this._doc.setValue( this._doc!.setValue(
this.props.getValue(this.props.layer), this.props.getValue(this.props.layer),
) )
} }
} }
onChange = (e) => { onChange = (_e: unknown) => {
if (this._cancelNextChange) { if (this._cancelNextChange) {
this._cancelNextChange = false; this._cancelNextChange = false;
this.setState({ this.setState({
prevValue: this._doc.getValue(), prevValue: this._doc!.getValue(),
}) })
return; return;
} }
const newCode = this._doc.getValue(); const newCode = this._doc!.getValue();
if (this.state.prevValue !== newCode) { if (this.state.prevValue !== newCode) {
let parsedLayer, err; let parsedLayer, err;
@@ -139,12 +141,12 @@ export default class InputJson extends React.Component {
console.warn(_err) console.warn(_err)
} }
if (err) { if (err && this.props.onJSONInvalid) {
this.props.onJSONInvalid(); this.props.onJSONInvalid();
} }
else { else {
this.props.onChange(parsedLayer) if (this.props.onChange) this.props.onChange(parsedLayer)
this.props.onJSONValid(); if (this.props.onJSONValid) this.props.onJSONValid();
} }
} }
@@ -155,7 +157,7 @@ export default class InputJson extends React.Component {
render() { render() {
const {showMessage} = this.state; const {showMessage} = this.state;
const style = {}; const style = {} as {maxHeight?: number};
if (this.props.maxHeight) { if (this.props.maxHeight) {
style.maxHeight = this.props.maxHeight; style.maxHeight = this.props.maxHeight;
} }
@@ -1,18 +1,17 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import {otherFilterOps} from '../libs/filterops' import {otherFilterOps} from '../libs/filterops'
import InputString from './InputString' import InputString from './InputString'
import InputAutocomplete from './InputAutocomplete' import InputAutocomplete from './InputAutocomplete'
import InputSelect from './InputSelect' import InputSelect from './InputSelect'
function tryParseInt(v) { function tryParseInt(v: string | number) {
if (v === '') return v if (v === '') return v
if (isNaN(v)) return v if (isNaN(v as number)) return v
return parseFloat(v) return parseFloat(v as string)
} }
function tryParseBool(v) { function tryParseBool(v: string | boolean) {
const isString = (typeof(v) === "string"); const isString = (typeof(v) === "string");
if(!isString) { if(!isString) {
return v; return v;
@@ -29,24 +28,24 @@ function tryParseBool(v) {
} }
} }
function parseFilter(v) { function parseFilter(v: string | boolean | number) {
v = tryParseInt(v); v = tryParseInt(v as any);
v = tryParseBool(v); v = tryParseBool(v as any);
return v; return v;
} }
export default class SingleFilterEditor extends React.Component { type SingleFilterEditorProps = {
static propTypes = { filter: any[]
filter: PropTypes.array.isRequired, onChange(...args: unknown[]): unknown
onChange: PropTypes.func.isRequired, properties?: {[key: string]: string}
properties: PropTypes.object, };
}
export default class SingleFilterEditor extends React.Component<SingleFilterEditorProps> {
static defaultProps = { static defaultProps = {
properties: {}, properties: {},
} }
onFilterPartChanged(filterOp, propertyName, filterArgs) { onFilterPartChanged(filterOp: string, propertyName: string, filterArgs: string[]) {
let newFilter = [filterOp, propertyName, ...filterArgs.map(parseFilter)] let newFilter = [filterOp, propertyName, ...filterArgs.map(parseFilter)]
if(filterOp === 'has' || filterOp === '!has') { if(filterOp === 'has' || filterOp === '!has') {
newFilter = [filterOp, propertyName] newFilter = [filterOp, propertyName]
@@ -67,15 +66,15 @@ export default class SingleFilterEditor extends React.Component {
<InputAutocomplete <InputAutocomplete
aria-label="key" aria-label="key"
value={propertyName} value={propertyName}
options={Object.keys(this.props.properties).map(propName => [propName, propName])} options={Object.keys(this.props.properties!).map(propName => [propName, propName])}
onChange={newPropertyName => this.onFilterPartChanged(filterOp, newPropertyName, filterArgs)} onChange={(newPropertyName: string) => this.onFilterPartChanged(filterOp, newPropertyName, filterArgs)}
/> />
</div> </div>
<div className="maputnik-filter-editor-operator"> <div className="maputnik-filter-editor-operator">
<InputSelect <InputSelect
aria-label="function" aria-label="function"
value={filterOp} value={filterOp}
onChange={newFilterOp => this.onFilterPartChanged(newFilterOp, propertyName, filterArgs)} onChange={(newFilterOp: string) => this.onFilterPartChanged(newFilterOp, propertyName, filterArgs)}
options={otherFilterOps} options={otherFilterOps}
/> />
</div> </div>
@@ -84,12 +83,11 @@ export default class SingleFilterEditor extends React.Component {
<InputString <InputString
aria-label="value" aria-label="value"
value={filterArgs.join(',')} value={filterArgs.join(',')}
onChange={ v=> this.onFilterPartChanged(filterOp, propertyName, v.split(','))} onChange={(v: string) => this.onFilterPartChanged(filterOp, propertyName, v.split(','))}
/> />
</div> </div>
} }
</div> </div>
} }
} }