34 changed files with 1151 additions and 360 deletions
@ -0,0 +1,23 @@ |
|||
///
|
|||
/// Copyright © 2016-2019 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
|
|||
export interface JsonFormComponentData { |
|||
model?: any; |
|||
schema?: any; |
|||
form?: any; |
|||
groupInfoes?: any[]; |
|||
} |
|||
@ -0,0 +1,184 @@ |
|||
/* |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
|
|||
import * as React from 'react'; |
|||
import ThingsboardBaseComponent from './json-form-base-component'; |
|||
import reactCSS from 'reactcss'; |
|||
import ReactAce from 'react-ace'; |
|||
import Button from '@material-ui/core/Button'; |
|||
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models'; |
|||
import * as tinycolor from 'tinycolor2'; |
|||
import { IEditorProps } from 'react-ace/src/types'; |
|||
|
|||
interface ThingsboardAceEditorProps extends JsonFormFieldProps { |
|||
mode: string; |
|||
onTidy: (value: string) => string; |
|||
} |
|||
|
|||
interface ThingsboardAceEditorState extends JsonFormFieldState { |
|||
isFull: boolean; |
|||
focused: boolean; |
|||
} |
|||
|
|||
class ThingsboardAceEditor extends React.Component<ThingsboardAceEditorProps, ThingsboardAceEditorState> { |
|||
|
|||
hostElement: HTMLElement; |
|||
private aceEditor: IEditorProps; |
|||
|
|||
constructor(props) { |
|||
super(props); |
|||
this.onValueChanged = this.onValueChanged.bind(this); |
|||
this.onBlur = this.onBlur.bind(this); |
|||
this.onFocus = this.onFocus.bind(this); |
|||
this.onTidy = this.onTidy.bind(this); |
|||
this.onLoad = this.onLoad.bind(this); |
|||
this.onToggleFull = this.onToggleFull.bind(this); |
|||
const value = props.value ? props.value + '' : ''; |
|||
this.state = { |
|||
isFull: false, |
|||
value, |
|||
focused: false |
|||
}; |
|||
} |
|||
|
|||
onValueChanged(value) { |
|||
this.setState({ |
|||
value |
|||
}); |
|||
this.props.onChangeValidate({ |
|||
target: { |
|||
value |
|||
} |
|||
}); |
|||
} |
|||
|
|||
onBlur() { |
|||
this.setState({ focused: false }); |
|||
} |
|||
|
|||
onFocus() { |
|||
this.setState({ focused: true }); |
|||
} |
|||
|
|||
onTidy() { |
|||
if (!this.props.form.readonly) { |
|||
let value = this.state.value; |
|||
value = this.props.onTidy(value); |
|||
this.setState({ |
|||
value |
|||
}); |
|||
this.props.onChangeValidate({ |
|||
target: { |
|||
value |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
onLoad(editor: IEditorProps) { |
|||
this.aceEditor = editor; |
|||
} |
|||
|
|||
onToggleFull() { |
|||
this.setState({ isFull: !this.state.isFull }); |
|||
this.props.onToggleFullscreen(this.hostElement, () => { |
|||
if (this.aceEditor) { |
|||
this.aceEditor.resize(); |
|||
this.aceEditor.renderer.updateFull(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
componentDidUpdate() { |
|||
} |
|||
|
|||
render() { |
|||
|
|||
const styles = reactCSS({ |
|||
default: { |
|||
tidyButtonStyle: { |
|||
color: '#7B7B7B', |
|||
minWidth: '32px', |
|||
minHeight: '15px', |
|||
lineHeight: '15px', |
|||
fontSize: '0.800rem', |
|||
margin: '0', |
|||
padding: '4px', |
|||
height: '23px', |
|||
borderRadius: '5px', |
|||
marginLeft: '5px' |
|||
} |
|||
} |
|||
}); |
|||
|
|||
let labelClass = 'tb-label'; |
|||
if (this.props.form.required) { |
|||
labelClass += ' tb-required'; |
|||
} |
|||
if (this.props.form.readonly) { |
|||
labelClass += ' tb-readonly'; |
|||
} |
|||
if (this.state.focused) { |
|||
labelClass += ' tb-focused'; |
|||
} |
|||
let containerClass = 'tb-container'; |
|||
const style = this.props.form.style || {width: '100%'}; |
|||
if (this.state.isFull) { |
|||
containerClass += ' fullscreen-form-field'; |
|||
} |
|||
return ( |
|||
<div> |
|||
<div className='tb-json-form' ref={c => (this.hostElement = c)}> |
|||
<div className={containerClass}> |
|||
<label className={labelClass}>{this.props.form.title}</label> |
|||
<div className='json-form-ace-editor'> |
|||
<div className='title-panel'> |
|||
<label>{this.props.mode}</label> |
|||
<Button style={ styles.tidyButtonStyle } |
|||
className='tidy-button' onClick={this.onTidy}>Tidy</Button> |
|||
<Button style={ styles.tidyButtonStyle } |
|||
className='tidy-button' onClick={this.onToggleFull}> |
|||
{this.state.isFull ? |
|||
'Exit fullscreen' : 'Fullscreen'} |
|||
</Button> |
|||
</div> |
|||
<ReactAce mode={this.props.mode} |
|||
height={this.state.isFull ? '100%' : '150px'} |
|||
width={this.state.isFull ? '100%' : '300px'} |
|||
theme='github' |
|||
onChange={this.onValueChanged} |
|||
onFocus={this.onFocus} |
|||
onBlur={this.onBlur} |
|||
onLoad={this.onLoad} |
|||
name={this.props.form.title} |
|||
value={this.state.value} |
|||
readOnly={this.props.form.readonly} |
|||
editorProps={{$blockScrolling: Infinity}} |
|||
enableBasicAutocompletion={true} |
|||
enableSnippets={true} |
|||
enableLiveAutocompletion={true} |
|||
style={style}/> |
|||
</div> |
|||
<div className='json-form-error' |
|||
style={{opacity: this.props.valid ? '0' : '1'}}>{this.props.error}</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default ThingsboardBaseComponent(ThingsboardAceEditor); |
|||
@ -0,0 +1,184 @@ |
|||
/* |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
import * as React from 'react'; |
|||
import * as ReactDOM from 'react-dom'; |
|||
import ThingsboardBaseComponent from './json-form-base-component'; |
|||
import reactCSS from 'reactcss'; |
|||
import * as tinycolor from 'tinycolor2'; |
|||
import TextField from '@material-ui/core/TextField'; |
|||
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models'; |
|||
import IconButton from '@material-ui/core/IconButton'; |
|||
import ClearIcon from '@material-ui/icons/Clear'; |
|||
import Tooltip from '@material-ui/core/Tooltip'; |
|||
|
|||
interface ThingsboardColorState extends JsonFormFieldState { |
|||
color: tinycolor.ColorFormats.RGBA | null; |
|||
focused: boolean; |
|||
} |
|||
|
|||
class ThingsboardColor extends React.Component<JsonFormFieldProps, ThingsboardColorState> { |
|||
|
|||
constructor(props) { |
|||
super(props); |
|||
this.onBlur = this.onBlur.bind(this); |
|||
this.onFocus = this.onFocus.bind(this); |
|||
this.onValueChanged = this.onValueChanged.bind(this); |
|||
this.onSwatchClick = this.onSwatchClick.bind(this); |
|||
this.onClear = this.onClear.bind(this); |
|||
const value = props.value ? props.value + '' : null; |
|||
const color = value != null ? tinycolor(value).toRgb() : null; |
|||
this.state = { |
|||
color, |
|||
focused: false |
|||
}; |
|||
} |
|||
|
|||
onBlur() { |
|||
this.setState({focused: false}); |
|||
} |
|||
|
|||
onFocus() { |
|||
this.setState({focused: true}); |
|||
} |
|||
|
|||
componentDidMount() { |
|||
const node = ReactDOM.findDOMNode(this); |
|||
const colContainer = $(node).children('#color-container'); |
|||
colContainer.click((event) => { |
|||
if (!this.props.form.readonly) { |
|||
this.onSwatchClick(event); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
componentWillUnmount() { |
|||
const node = ReactDOM.findDOMNode(this); |
|||
const colContainer = $(node).children('#color-container'); |
|||
colContainer.off( 'click' ); |
|||
} |
|||
|
|||
onValueChanged(value: tinycolor.ColorFormats.RGBA | null) { |
|||
let color: tinycolor.Instance = null; |
|||
if (value != null) { |
|||
color = tinycolor(value); |
|||
} |
|||
this.setState({ |
|||
color: value |
|||
}); |
|||
let colorValue = ''; |
|||
if (color != null && color.getAlpha() !== 1) { |
|||
colorValue = color.toRgbString(); |
|||
} else if (color != null) { |
|||
colorValue = color.toHexString(); |
|||
} |
|||
this.props.onChangeValidate({ |
|||
target: { |
|||
value: colorValue |
|||
} |
|||
}); |
|||
} |
|||
|
|||
onSwatchClick(event) { |
|||
this.props.onColorClick(this.props.form.key, this.state.color, |
|||
(color) => { |
|||
this.onValueChanged(color); |
|||
} |
|||
); |
|||
} |
|||
|
|||
onClear(event) { |
|||
if (event) { |
|||
event.stopPropagation(); |
|||
} |
|||
this.onValueChanged(null); |
|||
} |
|||
|
|||
render() { |
|||
|
|||
let background = 'rgba(0,0,0,0)'; |
|||
if (this.state.color != null) { |
|||
background = `rgba(${ this.state.color.r }, ${ this.state.color.g }, ${ this.state.color.b }, ${ this.state.color.a })`; |
|||
} |
|||
|
|||
const styles = reactCSS({ |
|||
default: { |
|||
color: { |
|||
background: `${ background }` |
|||
}, |
|||
swatch: { |
|||
display: 'inline-block', |
|||
marginRight: '10px', |
|||
marginTop: 'auto', |
|||
marginBottom: 'auto', |
|||
cursor: 'pointer', |
|||
opacity: `${ this.props.form.readonly ? '0.6' : '1' }` |
|||
}, |
|||
swatchText: { |
|||
width: '100%' |
|||
}, |
|||
container: { |
|||
display: 'flex', |
|||
flexDirection: 'row', |
|||
alignItems: 'center' |
|||
}, |
|||
colorContainer: { |
|||
display: 'flex', |
|||
width: '100%' |
|||
} |
|||
}, |
|||
}); |
|||
|
|||
let fieldClass = 'tb-field'; |
|||
if (this.props.form.required) { |
|||
fieldClass += ' tb-required'; |
|||
} |
|||
if (this.props.form.readonly) { |
|||
fieldClass += ' tb-readonly'; |
|||
} |
|||
if (this.state.focused) { |
|||
fieldClass += ' tb-focused'; |
|||
} |
|||
|
|||
let stringColor = ''; |
|||
if (this.state.color != null) { |
|||
const color = tinycolor(this.state.color); |
|||
stringColor = color.toRgbString(); |
|||
} |
|||
|
|||
return ( |
|||
<div style={ styles.container }> |
|||
<div id='color-container' style={ styles.colorContainer }> |
|||
<div className='tb-color-preview' style={ styles.swatch }> |
|||
<div className='tb-color-result' style={ styles.color }/> |
|||
</div> |
|||
<TextField |
|||
className={fieldClass} |
|||
label={this.props.form.title} |
|||
error={!this.props.valid} |
|||
helperText={this.props.valid ? this.props.form.placeholder : this.props.error} |
|||
value={stringColor} |
|||
disabled={this.props.form.readonly} |
|||
onFocus={this.onFocus} |
|||
onBlur={this.onBlur} |
|||
style={ styles.swatchText }/> |
|||
</div> |
|||
<Tooltip title='Clear' placement='top'><IconButton onClick={this.onClear}><ClearIcon/></IconButton></Tooltip> |
|||
</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default ThingsboardBaseComponent(ThingsboardColor); |
|||
@ -0,0 +1,39 @@ |
|||
/* |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
import * as React from 'react'; |
|||
import ThingsboardAceEditor from './json-form-ace-editor'; |
|||
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models'; |
|||
import { css_beautify } from 'js-beautify'; |
|||
|
|||
class ThingsboardCss extends React.Component<JsonFormFieldProps, JsonFormFieldState> { |
|||
|
|||
constructor(props) { |
|||
super(props); |
|||
this.onTidyCss = this.onTidyCss.bind(this); |
|||
} |
|||
|
|||
onTidyCss(css: string): string { |
|||
return css_beautify(css, {indent_size: 4}); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<ThingsboardAceEditor {...this.props} mode='css' onTidy={this.onTidyCss} {...this.state}></ThingsboardAceEditor> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default ThingsboardCss; |
|||
@ -0,0 +1,39 @@ |
|||
/* |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
import * as React from 'react'; |
|||
import ThingsboardAceEditor from './json-form-ace-editor'; |
|||
import { html_beautify } from 'js-beautify'; |
|||
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models'; |
|||
|
|||
class ThingsboardHtml extends React.Component<JsonFormFieldProps, JsonFormFieldState> { |
|||
|
|||
constructor(props) { |
|||
super(props); |
|||
this.onTidyHtml = this.onTidyHtml.bind(this); |
|||
} |
|||
|
|||
onTidyHtml(html: string): string { |
|||
return html_beautify(html, {indent_size: 4}); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<ThingsboardAceEditor {...this.props} mode='html' onTidy={this.onTidyHtml} {...this.state}></ThingsboardAceEditor> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default ThingsboardHtml; |
|||
@ -0,0 +1,109 @@ |
|||
/* |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
import React, {useCallback} from 'react'; |
|||
import { DropzoneState, useDropzone } from 'react-dropzone'; |
|||
import ThingsboardBaseComponent from './json-form-base-component'; |
|||
import Dropzone from 'react-dropzone'; |
|||
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models'; |
|||
import IconButton from '@material-ui/core/IconButton'; |
|||
import ClearIcon from '@material-ui/icons/Clear'; |
|||
import Tooltip from '@material-ui/core/Tooltip'; |
|||
|
|||
interface ThingsboardImageState extends JsonFormFieldState { |
|||
imageUrl: string; |
|||
} |
|||
|
|||
class ThingsboardImage extends React.Component<JsonFormFieldProps, ThingsboardImageState> { |
|||
|
|||
constructor(props) { |
|||
super(props); |
|||
this.onDrop = this.onDrop.bind(this); |
|||
this.onClear = this.onClear.bind(this); |
|||
const value = props.value ? props.value + '' : null; |
|||
this.state = { |
|||
imageUrl: value |
|||
}; |
|||
} |
|||
|
|||
onDrop(acceptedFiles: File[]) { |
|||
const reader = new FileReader(); |
|||
reader.onload = () => { |
|||
this.onValueChanged(reader.result); |
|||
}; |
|||
reader.readAsDataURL(acceptedFiles[0]); |
|||
} |
|||
|
|||
onValueChanged(value) { |
|||
this.setState({ |
|||
imageUrl: value |
|||
}); |
|||
this.props.onChangeValidate({ |
|||
target: { |
|||
value |
|||
} |
|||
}); |
|||
} |
|||
|
|||
onClear(event) { |
|||
if (event) { |
|||
event.stopPropagation(); |
|||
} |
|||
this.onValueChanged(''); |
|||
} |
|||
|
|||
render() { |
|||
|
|||
let labelClass = 'tb-label'; |
|||
if (this.props.form.required) { |
|||
labelClass += ' tb-required'; |
|||
} |
|||
if (this.props.form.readonly) { |
|||
labelClass += ' tb-readonly'; |
|||
} |
|||
|
|||
let previewComponent; |
|||
if (this.state.imageUrl) { |
|||
previewComponent = <img className='tb-image-preview' src={this.state.imageUrl} />; |
|||
} else { |
|||
previewComponent = <div>No image selected</div>; |
|||
} |
|||
|
|||
return ( |
|||
<div className='tb-container'> |
|||
<label className={labelClass}>{this.props.form.title}</label> |
|||
<div className='tb-image-select-container'> |
|||
<div className='tb-image-preview-container'>{previewComponent}</div> |
|||
<div className='tb-image-clear-container'> |
|||
<Tooltip title='Clear' placement='top'> |
|||
<IconButton className='tb-image-clear-btn' onClick={this.onClear}><ClearIcon/></IconButton> |
|||
</Tooltip> |
|||
</div> |
|||
<Dropzone onDrop={this.onDrop} |
|||
accept='image/*' multiple={false}> |
|||
{({getRootProps, getInputProps}) => ( |
|||
<div className='tb-dropzone' {...getRootProps()}> |
|||
<div>Drop an image or click to select a file to upload.</div> |
|||
<input {...getInputProps()} /> |
|||
</div> |
|||
)} |
|||
</Dropzone> |
|||
</div> |
|||
</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default ThingsboardBaseComponent(ThingsboardImage); |
|||
@ -0,0 +1,38 @@ |
|||
/* |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
import * as React from 'react'; |
|||
import ThingsboardAceEditor from './json-form-ace-editor'; |
|||
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models'; |
|||
|
|||
class ThingsboardJavaScript extends React.Component<JsonFormFieldProps, JsonFormFieldState> { |
|||
|
|||
constructor(props) { |
|||
super(props); |
|||
this.onTidyJavascript = this.onTidyJavascript.bind(this); |
|||
} |
|||
|
|||
onTidyJavascript(javascript: string): string { |
|||
return js_beautify(javascript, {indent_size: 4, wrap_line_length: 60}); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<ThingsboardAceEditor {...this.props} mode='javascript' onTidy={this.onTidyJavascript} {...this.state}></ThingsboardAceEditor> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default ThingsboardJavaScript; |
|||
@ -0,0 +1,38 @@ |
|||
/* |
|||
* Copyright © 2016-2019 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
import * as React from 'react'; |
|||
import ThingsboardAceEditor from './json-form-ace-editor'; |
|||
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models'; |
|||
|
|||
class ThingsboardJson extends React.Component<JsonFormFieldProps, JsonFormFieldState> { |
|||
|
|||
constructor(props) { |
|||
super(props); |
|||
this.onTidyJson = this.onTidyJson.bind(this); |
|||
} |
|||
|
|||
onTidyJson(json: string): string { |
|||
return js_beautify(json, {indent_size: 4}); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<ThingsboardAceEditor {...this.props} mode='json' onTidy={this.onTidyJson} {...this.state}></ThingsboardAceEditor> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default ThingsboardJson; |
|||
Loading…
Reference in new issue