Skip to content

Instantly share code, notes, and snippets.

@gagangoku
Created July 29, 2018 15:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gagangoku/ff2cf108351920c0997b522929a11cd0 to your computer and use it in GitHub Desktop.
Save gagangoku/ff2cf108351920c0997b522929a11cd0 to your computer and use it in GitHub Desktop.
import React, { Fragment } from 'react'
import { withStyles } from '@material-ui/core/styles'
import fetchJsonp from 'fetch-jsonp'
import TextField from '@material-ui/core/TextField'
import Select from '@material-ui/core/Select'
import FormControl from '@material-ui/core/FormControl'
import InputLabel from '@material-ui/core/InputLabel'
import MenuItem from '@material-ui/core/MenuItem'
import Button from '@material-ui/core/Button'
const styles = theme => ({
root: {
marginTop: theme.spacing.unit * 3,
overflowX: 'auto',
padding: 20,
},
formControl: {
margin: theme.spacing.unit,
minWidth: 120,
},
button: {
padding: 10,
margin: 10,
}
})
class DescriptorWidget extends React.Component {
constructor(props) {
super(props)
this.state = {
desc: props.descriptor,
message: props.message,
}
var obj = this
this.resetFn = function(o) {
props.resetFn()
}
this.submitFn = function(o) {
props.submitFn(obj.state.message)
}
// Bind functions - dont know why
this.handleChange = this.handleChange.bind(this)
}
getKey(level, xpathArray, field) {
return level + '-' + xpathArray.join('/') + '-' + field['name']
}
renderDescriptor(level, xpathArray, desc, message, parentMessage, iPtr) {
// console.log('renderDescriptor desc: ', desc)
// console.log('renderDescriptor message: ', message)
if (message) {
} else {
parentMessage[iPtr] = {}
message = parentMessage[iPtr]
}
var array = []
for (var j = 0; j < desc['field'].length; j++) {
var f = desc['field'][j]
var fieldName = f['name']
var newArray = xpathArray.slice();
newArray.push(j)
var header = this.fieldHeader(level, xpathArray, f, message)
array.push(header)
var l = this.renderField(level, newArray, f, message[fieldName], message, -1)
for (var k = 0; k < l.length; k++) {
array.push(l[k])
}
}
return array
}
renderField(level, xpathArray, field, message, parentMessage) {
// console.log('renderField field: ', field)
// console.log('renderField message: ', message)
if (field['isRepeated']) {
var array = []
var len = message ? message.length : 0
for (var i = 0; i < len; i++) {
var newArray = xpathArray.slice();
newArray.push(i)
var l = this.renderSingleFieldEntry(level, newArray, field, message[i], message, i)
if (l != null) {
array.push(l)
}
}
return array
} else {
var newArray1 = xpathArray.slice();
newArray1.push(0)
return [this.renderSingleFieldEntry(level, newArray1, field, message, parentMessage, -1)]
}
}
renderSingleFieldEntry(level, xpathArray, field, messageValue, parentMessage, iPtr) {
// console.log('renderSingleFieldEntry field: ', field)
// console.log('renderSingleFieldEntry message: ', messageValue)
var type = field['type']
if (type === 'MESSAGE') {
return this.renderDescriptor(level + 1, xpathArray, field['messageDescriptor'], messageValue, parentMessage, field['name'])
} else if (type === 'ENUM') {
return this.renderEnum(level, xpathArray, field, field['possibleEnumValues'], messageValue, parentMessage, iPtr)
} else if (type === 'BOOL') {
return this.renderEnum(level, xpathArray, field, ["true", "false"], messageValue, parentMessage, iPtr)
} else {
return this.renderTextField(level, xpathArray, field, messageValue, parentMessage, iPtr)
}
// if (type.startsWith('INT') || type === 'DOUBLE' || type === 'FLOAT')
// render as number
}
fieldHeader(level, xpathArray, field, parentMessage) {
// console.log('fieldHeader field: ', field)
// console.log('fieldHeader parentMessage: ', parentMessage)
var key = this.getKey(level, xpathArray, field)
if (field['isRepeated'] === 'true' || field['isRepeated']) {
return (
<Fragment key={key}>
<div style={{marginLeft: level*50, marginTop: 30, marginBottom: 30}}>
<span >{field['name']}</span>
<span onClick={this.handleAdd(level, xpathArray, field, parentMessage)} style={{fontSize: 20}}> + </span>
<span onClick={this.handleRemove(level, xpathArray, field, parentMessage)} style={{fontSize: 20}}> - </span>
</div>
</Fragment>
) // Html
} else if (field['type'] === 'MESSAGE') {
return (
<Fragment key={key}>
<div style={{marginLeft: (level)*50, marginTop: 30, marginBottom: 30}} key={key}>
<span >{field['name']}</span>
</div>
</Fragment>
) // Html
} else {
return null
}
}
renderEnum(level, xpathArray, field, possibleEnumValues, messageValue, parentMessage, iPtr) {
// console.log('renderEnum field: ', field)
// console.log('renderEnum message: ', messageValue)
const { classes } = this.props
messageValue = messageValue ? messageValue + '' : '' // TO convert boolean as well
var key = this.getKey(level, xpathArray, field)
var label = field['name'] + ' (' + field['type'].toLowerCase() + ')'
var cbFn = this.handleChange(level, xpathArray, field, parentMessage, iPtr)
var key = this.getKey(level, xpathArray, field)
return (
<Fragment key={key}>
<div>
<FormControl className={classes.formControl} style={{marginLeft: level*50, width: label.length * 10}}>
<InputLabel>{label}</InputLabel>
<Select value={messageValue} onChange={cbFn} id={key}>
{possibleEnumValues.map(o => {
return <MenuItem value={o} key={key + ',' + o}>{o}</MenuItem>
})}
</Select>
</FormControl>
</div>
</Fragment>
) // Html
}
renderTextField(level, xpathArray, field, messageValue, parentMessage, iPtr) {
// console.log('renderTextField field: ', field)
// console.log('renderTextField messageValue: ', messageValue)
const { classes } = this.props
messageValue = messageValue ? messageValue + '' : ''
var label = field['name'] + ' (' + field['type'].toLowerCase() + ')'
var type = ''
var width = Math.max(label.length * 10, messageValue.length * 4)
var cbFn = this.handleChange(level, xpathArray, field, parentMessage, iPtr)
var key = this.getKey(level, xpathArray, field)
return (
<Fragment key={key}>
<TextField label={label} className={classes.textField} autoComplete='off'
style={{marginLeft: level*50, display: 'block', width: width}} fullWidth
value={messageValue} type={type} onChange={cbFn} margin="normal">
</TextField>
</Fragment>
)
}
handleChange(level, xpathArray, field, parentMessage, iPtr) {
var obj = this
return function(event) {
if (field['isRepeated'] === 'true' || field['isRepeated']) {
parentMessage[iPtr] = event.target.value
} else {
parentMessage[field['name']] = event.target.value
}
obj.setState({})
}
}
handleAdd(level, xpathArray, field, parentMessage) {
var obj = this
return function(event) {
if (!(field['name'] in parentMessage)) {
parentMessage[field['name']] = []
}
var newVal = field['type'] === 'MESSAGE' ? {} : ''
parentMessage[field['name']].push(newVal)
obj.setState({})
}
}
handleRemove(level, xpathArray, field, parentMessage) {
var obj = this
return function(event) {
parentMessage[field['name']].splice(-1,1)
obj.setState({})
}
}
render() {
const { classes } = this.props
return (
<Fragment>
<div style={{height: 550, overflowY: 'auto', border: '1px solid black', marginTop: 20, paddingLeft: 10}} key={0}>
{this.renderDescriptor(0, [], this.state.desc, this.state.message, this.state.message, null)}
</div>
<Button variant="outlined" component="span" className={classes.button} onClick={this.submitFn}>
Update
</Button>
<Button variant="outlined" component="span" className={classes.button} onClick={this.resetFn}>
Reset
</Button>
</Fragment>
);
}
}
export default withStyles(styles)(DescriptorWidget)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment