From f8fd882257f3d1671ceacef0cf85dc8ea7e619f7 Mon Sep 17 00:00:00 2001 From: Anupam Dagar Date: Tue, 11 Dec 2018 15:37:33 +0530 Subject: [PATCH 01/10] Add Json editor for Json Data Type. This adds a generic input to json editor toggle component. Fixes: 504 --- console/src/components/Common/Common.scss | 10 +++ .../components/Common/Toggler/Jsontoggler.js | 72 +++++++++++++++++++ .../Services/Data/TableBrowseRows/EditItem.js | 21 +++--- .../Data/TableInsertItem/InsertItem.js | 17 +++-- 4 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 console/src/components/Common/Toggler/Jsontoggler.js diff --git a/console/src/components/Common/Common.scss b/console/src/components/Common/Common.scss index 07032186da4ca..8485ffa0bfaeb 100644 --- a/console/src/components/Common/Common.scss +++ b/console/src/components/Common/Common.scss @@ -20,6 +20,16 @@ table thead tr th color: #4D4D4D; font-weight: 600 !important; } + +.jsonButtonAlign { + position: relative; + float: right; + margin-left: -30px; + margin-right: 5px; + margin-top: 10px; + z-index: 2; +} + .pageSidebar { height: calc(100vh - 50px); overflow: auto; diff --git a/console/src/components/Common/Toggler/Jsontoggler.js b/console/src/components/Common/Toggler/Jsontoggler.js new file mode 100644 index 0000000000000..c14bda1f737a6 --- /dev/null +++ b/console/src/components/Common/Toggler/Jsontoggler.js @@ -0,0 +1,72 @@ +import React, { Component } from 'react'; +import AceEditor from 'react-ace'; + +const styles = require('../Common.scss'); + +class Jsontoggler extends Component { + constructor(props) { + super(props); + + this.state = { + input_json: 0, + input_value: this.props.standardProps.defaultValue, + }; + + this.handleClick = this.handleClick.bind(this); + } + + handleClick(e) { + e.preventDefault(); + const stateValue = this.state.input_json; + if (stateValue === 0) { + this.setState({ input_json: 1 }); + } else { + this.setState({ input_json: 0 }); + } + } + + render() { + return ( + + + + + ); + } +} + +export default Jsontoggler; diff --git a/console/src/components/Services/Data/TableBrowseRows/EditItem.js b/console/src/components/Services/Data/TableBrowseRows/EditItem.js index 9e8f612cbe3e2..d5ed65d939110 100644 --- a/console/src/components/Services/Data/TableBrowseRows/EditItem.js +++ b/console/src/components/Services/Data/TableBrowseRows/EditItem.js @@ -4,7 +4,7 @@ import TableHeader from '../TableCommon/TableHeader'; import { editItem, E_ONGOING_REQ } from './EditActions'; import globals from '../../../../Globals'; import { modalClose } from './EditActions'; - +import Jsontoggler from '../../../Common/Toggler/Jsontoggler'; // import RichTextEditor from 'react-rte'; import { replace } from 'react-router-redux'; @@ -144,15 +144,18 @@ class EditItem extends Component { /> ); } else if (colType === 'json' || colType === 'jsonb') { + const standardEditProps = { + className: `form-control ${styles.insertBox}`, + onClick: clicker, + ref: inputRef, + defaultValue: JSON.stringify(oldItem[colName]), + 'data-test': `typed-input-${i}`, + type: 'text', + }; typedInput = ( - ); } else if (colType === 'boolean') { diff --git a/console/src/components/Services/Data/TableInsertItem/InsertItem.js b/console/src/components/Services/Data/TableInsertItem/InsertItem.js index fdcc669ffd5ba..9eedb7ff60d92 100644 --- a/console/src/components/Services/Data/TableInsertItem/InsertItem.js +++ b/console/src/components/Services/Data/TableInsertItem/InsertItem.js @@ -4,6 +4,7 @@ import TableHeader from '../TableCommon/TableHeader'; import { insertItem, I_RESET } from './InsertActions'; import { ordinalColSort } from '../utils'; import { setTable } from '../DataActions'; +import Jsontoggler from '../../../Common/Toggler/Jsontoggler'; class InsertItem extends Component { constructor() { @@ -152,12 +153,9 @@ class InsertItem extends Component { if (colType === 'json' || colType === 'jsonb') { // JSON/JSONB typedInput = ( - ); } @@ -299,7 +297,12 @@ class InsertItem extends Component { // default return; } else { - inputValues[colName] = refs[colName].valueNode.value; + if (refs[colName].valueNode.props !== undefined) { + inputValues[colName] = + refs[colName].valueNode.refEditor.innerText; + } else { + inputValues[colName] = refs[colName].valueNode.value; + } } }); dispatch(insertItem(tableName, inputValues)).then(() => { From 5bc818fcf72af06029e66f56131da66cf354a081 Mon Sep 17 00:00:00 2001 From: Karthik Venkateswaran Date: Wed, 15 May 2019 18:38:37 +0530 Subject: [PATCH 02/10] Change it to use hooks --- console/src/components/Common/Common.scss | 14 +- .../Common/CustomInputTypes/JsonInput.js | 190 ++++++++++++++++++ .../components/Common/Toggler/Jsontoggler.js | 72 ------- .../Services/Data/TableBrowseRows/EditItem.js | 4 +- .../Data/TableInsertItem/InsertItem.js | 16 +- 5 files changed, 210 insertions(+), 86 deletions(-) create mode 100644 console/src/components/Common/CustomInputTypes/JsonInput.js delete mode 100644 console/src/components/Common/Toggler/Jsontoggler.js diff --git a/console/src/components/Common/Common.scss b/console/src/components/Common/Common.scss index 25faa62ec04f9..496a8689caffb 100644 --- a/console/src/components/Common/Common.scss +++ b/console/src/components/Common/Common.scss @@ -50,12 +50,10 @@ table thead tr th { } .jsonButtonAlign { - position: relative; - float: right; - margin-left: -30px; - margin-right: 5px; - margin-top: 10px; - z-index: 2; + position: absolute; + top: 10px; + right: 10px; + z-index: 100; } .pageSidebar { height: calc(100vh - 50px); @@ -1238,6 +1236,10 @@ code { } } +.relative_position { + position: relative; +} + .fixed_header_internal_link { display: block; position: relative; diff --git a/console/src/components/Common/CustomInputTypes/JsonInput.js b/console/src/components/Common/CustomInputTypes/JsonInput.js new file mode 100644 index 0000000000000..317b7f1d4b653 --- /dev/null +++ b/console/src/components/Common/CustomInputTypes/JsonInput.js @@ -0,0 +1,190 @@ +import React, { useState } from 'react'; +import AceEditor from 'react-ace'; + +const styles = require('../Common.scss'); + +const N = 'normal'; +const J = 'json'; + +const parseJSONData = data => { + try { + if (typeof data === 'object') { + return JSON.stringify(data, null, 4); + } + return JSON.stringify(JSON.parse(data), null, 4); + } catch (e) { + return data; + } +}; + +const createInitialState = data => { + const initialState = { + showEditorType: N, + data: parseJSONData(data), + }; + return initialState; +}; + +const JsonInput = props => { + const { standardProps, placeholderProp } = props; + const { defaultValue } = standardProps; + const allProps = { ...standardProps }; + delete allProps.defaultValue; + const [state, updateState] = useState(createInitialState(defaultValue)); + const { showEditorType, data } = state; + const updateData = newData => { + return { + ...state, + data: newData, + }; + }; + const toggleEditorType = () => { + if (state.showEditorType === J) { + return { + ...state, + showEditorType: N, + }; + } + return { + ...state, + data: parseJSONData(state.data), + showEditorType: J, + }; + }; + const handleKeyUpEvent = e => { + if (e.ctrlKey && e.which === 32) { + console.log( + 'Control space conbination is pressed, toggling between json' + ); + updateState(toggleEditorType()); + } + }; + const renderHtml = + showEditorType === J ? ( + updateState(updateData(val))} + /> + ) : ( + updateState(updateData(e.target.value))} + onKeyUp={handleKeyUpEvent} + /> + ); + return [ + renderHtml, + updateState(toggleEditorType())} + />, + ]; +}; + +/* +class Jsontoggler extends Component { + constructor(props) { + super(props); + + this.state = { + input_json: 0, + }; + + this.handleClick = this.handleClick.bind(this); + this.parseString = this.parseString.bind(this); + } + + handleClick(e) { + e.preventDefault(); + const stateValue = this.state.input_json; + if (stateValue === 0) { + this.setState({ input_json: 1 }); + } else { + this.setState({ input_json: 0 }); + } + } + + parseString() { + const { defaultValue } = this.props.standardProps; + try { + if (typeof defaultValue === 'object') { + return JSON.stringify(defaultValue, null, 4); + } + return JSON.stringify(JSON.parse(defaultValue), null, 4); + } catch (e) { + return defaultValue; + } + } + + getValueFromRelatedInput() { + const { refNode } = this.props; + console.log('RefNode'); + console.log(refNode); + if (refNode && 'valueNode' in refNode && refNode.valueNode) { + if ('props' in refNode.valueNode) { + return refNode.valueNode.refEditor.innerText; + } + return refNode.valueNode.value; + } + return ''; + } + + render() { + const initialVal = this.getValueFromRelatedInput() || this.parseString(); + console.log('initialVal'); + console.log(initialVal); + return ( + + + + + ); + } +} */ + +export default JsonInput; diff --git a/console/src/components/Common/Toggler/Jsontoggler.js b/console/src/components/Common/Toggler/Jsontoggler.js deleted file mode 100644 index c14bda1f737a6..0000000000000 --- a/console/src/components/Common/Toggler/Jsontoggler.js +++ /dev/null @@ -1,72 +0,0 @@ -import React, { Component } from 'react'; -import AceEditor from 'react-ace'; - -const styles = require('../Common.scss'); - -class Jsontoggler extends Component { - constructor(props) { - super(props); - - this.state = { - input_json: 0, - input_value: this.props.standardProps.defaultValue, - }; - - this.handleClick = this.handleClick.bind(this); - } - - handleClick(e) { - e.preventDefault(); - const stateValue = this.state.input_json; - if (stateValue === 0) { - this.setState({ input_json: 1 }); - } else { - this.setState({ input_json: 0 }); - } - } - - render() { - return ( - - - - - ); - } -} - -export default Jsontoggler; diff --git a/console/src/components/Services/Data/TableBrowseRows/EditItem.js b/console/src/components/Services/Data/TableBrowseRows/EditItem.js index 2ca8508524ca2..c37fbdf47deb9 100644 --- a/console/src/components/Services/Data/TableBrowseRows/EditItem.js +++ b/console/src/components/Services/Data/TableBrowseRows/EditItem.js @@ -4,7 +4,7 @@ import TableHeader from '../TableCommon/TableHeader'; import { editItem, E_ONGOING_REQ } from './EditActions'; import globals from '../../../../Globals'; import { modalClose } from './EditActions'; -import Jsontoggler from '../../../Common/Toggler/Jsontoggler'; +import JsonInput from '../../../Common/CustomInputTypes/JsonInput'; import Button from '../../../Common/Button/Button'; import { @@ -178,7 +178,7 @@ class EditItem extends Component { type: 'text', }; typedInput = ( - diff --git a/console/src/components/Services/Data/TableInsertItem/InsertItem.js b/console/src/components/Services/Data/TableInsertItem/InsertItem.js index 81134c6463bfb..c3015da7632e3 100644 --- a/console/src/components/Services/Data/TableInsertItem/InsertItem.js +++ b/console/src/components/Services/Data/TableInsertItem/InsertItem.js @@ -4,7 +4,7 @@ import TableHeader from '../TableCommon/TableHeader'; import { insertItem, I_RESET } from './InsertActions'; import { ordinalColSort } from '../utils'; import { setTable } from '../DataActions'; -import Jsontoggler from '../../../Common/Toggler/Jsontoggler'; +import JsonInput from '../../../Common/CustomInputTypes/JsonInput'; import Button from '../../../Common/Button/Button'; import { getPlaceholder, BOOLEAN, JSONB, JSONDTYPE } from '../utils'; @@ -83,14 +83,12 @@ class InsertItem extends Component { const radioToSelectWhenEmpty = hasDefault ? refs[colName].defaultNode : refs[colName].nullNode; - refs[colName].insertRadioNode.checked = !!textValue.length; radioToSelectWhenEmpty.checked = !textValue.length; }, onFocus: e => { if (isAutoIncrement) return; if (!isNullable && !hasDefault) return; - const textValue = e.target.value; if ( textValue === undefined || @@ -111,7 +109,6 @@ class InsertItem extends Component { }; const colType = col.data_type; - const placeHolder = hasDefault ? col.column_default : getPlaceholder(colType); @@ -129,7 +126,7 @@ class InsertItem extends Component { if (colType === JSONDTYPE || colType === JSONB) { // JSON/JSONB typedInput = ( - @@ -164,7 +161,14 @@ class InsertItem extends Component { > {colName} -