znamenica/dneslov

View on GitHub
app/components/JsonEditor.jsx

Summary

Maintainability
A
2 hrs
Test Coverage
import { Component } from 'react'
import PropTypes from 'prop-types'
import { mixin, flow } from 'lodash-decorators'
import { CharacterCounter } from 'materialize-css'
import JSONInput from '@soon92/react-json-editor-ajrm/es'
import locale from '@soon92/react-json-editor-ajrm/locale/ru'

import ErrorSpan from 'ErrorSpan'
import Validation from 'Validation'
import Subscribed from 'mixins/Subscribed'

import { valueToObject } from 'support'

@mixin(Subscribed)
@mixin(Validation)
export default class JsonEditor extends Component {
   static defaultProps = {
      name: 'text',
      value: "",
      wrapperClassName: null,
      placeholder: null,
      data: {},
      validations: {},
   }

   static propTypes = {
      name: PropTypes.string.isRequired,
      value: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
      wrapperClassName: PropTypes.string.isRequired,
      placeholder: PropTypes.string.isRequired,
      data: PropTypes.object,
      validations: PropTypes.object.isRequired,
   }

   // system
   state = { value: this.props.value }

   @flow('componentDidMountBefore')
   componentDidMount() {}

   @flow('componentWillUnmountBefore')
   componentWillUnmount() {}

   shouldComponentUpdate(nextProps, nextState) {
      return this.props.value !== nextProps.value
   }

   // events
   onChange(valueIn) {
      console.debug("[onChange] <<< valueIn:", valueIn["json"], valueIn)
      let object = valueToObject(this.props.name, valueIn["json"]),
          ce = new CustomEvent('dneslov-update-path', { detail: { value: object, path: this.props.name }})

      document.dispatchEvent(ce)
   }

   className() {
      return [ "input-field",
               this.props.wrapperClassName,
               this.getErrorText(this.props.value) && 'invalid' ].
         filter((x) => { return x }).join(" ")
   }

   renderValue() {
      if (this.props.value) {
         switch (this.props.value.constructor.name) {
            case "String":
               try {
                  return JSON.parse(this.props.value)
               } catch (e) {}
            case "Object":
               return this.props.value
         }
      }

      return {}
   }

   // NOTE: reset: false is required for the avoiding internal JSONInput error
   render() {
      console.log("[render] * this.props:", this.props, "this.state", this.state)

      return (
         <div
            className={this.className()}>
            <JSONInput
               id={this.props.name}
               locale={locale}
               onChange={this.onChange.bind(this)}
               placeholder={this.renderValue()}
               reset={false}
               theme="light_mitsuketa_tribute"
               height='15em'
               width='inherited' />
            <label
               className="active"
               htmlFor={this.props.name}>
               {this.props.title}
               <ErrorSpan
                  error={this.error && this.getErrorText(this.props.value)} />
            </label>
         </div>)
   }
}