From 0d4c21f1cf558e9a1e1b40ca20bb268ca5ec18d5 Mon Sep 17 00:00:00 2001 From: Ronnie Mitra Date: Tue, 22 Aug 2017 15:41:22 +0100 Subject: [PATCH] cosmetic changes --- package.json | 1 + spec/modules/login/LoginForm_spec.jsx | 9 +- spec/modules/projects/ProjectForm_spec.jsx | 66 ++++++-- src/css/app.scss | 24 +-- src/css/header.scss | 16 -- src/css/sketch.scss | 58 ++++++- src/css/tree.scss | 37 +++- src/js/adapter/Backend.js | 11 ++ src/js/d3/CRUDTree.jsx | 54 ++++++ src/js/modules/App.jsx | 4 +- src/js/modules/AuthenticatedApp.jsx | 34 ++-- src/js/modules/Sketch.jsx | 159 +++++++++--------- src/js/modules/header/AuthenticatedHeader.jsx | 36 ++-- src/js/modules/projects/ProjectForm.jsx | 17 +- src/js/modules/projects/ProjectSelection.jsx | 2 +- src/js/modules/sketch/NodeEditor.jsx | 1 - src/js/modules/sketch/tree/BodyEditor.jsx | 80 +++++++-- 17 files changed, 400 insertions(+), 209 deletions(-) diff --git a/package.json b/package.json index c7e7f7d..afccccf 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "babel-preset-es2015": "~6.18.0", "babel-preset-react": "^6.5.0", "bootstrap": "^3.3.6", + "bootstrap-toggle": "^2.2.2", "brace": "~0.9.1", "css-loader": "~0.26.1", "d3": "^4.2.3", diff --git a/spec/modules/login/LoginForm_spec.jsx b/spec/modules/login/LoginForm_spec.jsx index 8e9910a..cb0df45 100644 --- a/spec/modules/login/LoginForm_spec.jsx +++ b/spec/modules/login/LoginForm_spec.jsx @@ -176,7 +176,8 @@ describe('LoginForm Component', function() { wrapper.setState({formStarted: true}); // Click submit - wrapper.find('button #login-button').get(0).click(); + //wrapper.find('button #login-button').get(0).click(); + wrapper.find('button #login-button').simulate('submit'); }) @@ -212,7 +213,8 @@ describe('LoginForm Component', function() { wrapper.setState({rememberMe: true}); // Click submit - wrapper.find('button #login-button').get(0).click(); + //wrapper.find('button #login-button').get(0).click(); + wrapper.find('button #login-button').simulate('submit'); var store = {}; @@ -263,7 +265,8 @@ describe('LoginForm Component', function() { wrapper.setState({rememberMe: false}); // Click submit - wrapper.find('button #login-button').get(0).click(); + //wrapper.find('button #login-button').get(0).click(); + wrapper.find('button #login-button').simulate('submit'); var store = {}; diff --git a/spec/modules/projects/ProjectForm_spec.jsx b/spec/modules/projects/ProjectForm_spec.jsx index ea9f9d8..f2c757e 100644 --- a/spec/modules/projects/ProjectForm_spec.jsx +++ b/spec/modules/projects/ProjectForm_spec.jsx @@ -58,7 +58,7 @@ describe('ProjectForm Component', function() { it('should reject an attempt to create a project without a name', function() { - spyOn(ProjectForm.prototype, "showAlert").and.callThrough() + //spyOn(ProjectForm.prototype, "showAlert").and.callThrough() let projectCreated = jasmine.createSpy('projectCreated'); const wrapper = mount(); @@ -66,26 +66,55 @@ describe('ProjectForm Component', function() { // Try resetting the state of LoginForm wrapper.setState({formStarted: true}); - const emailInputField = wrapper.find('input[name="projectName"]'); - let simulatedEmailElement = createSimulatedElement('projectName', '', { valueMissing: true}); - emailInputField.simulate('change', simulatedEmailElement); + const projectNameField = wrapper.find('input[name="projectName"]'); + let simulatedProjectNameElement = createSimulatedElement('projectName', '', { valueMissing: true}); + projectNameField.simulate('change', simulatedProjectNameElement); - wrapper.find('button#create-project-button').get(0).click(); + //wrapper.find('button#create-project-button').get(0).click(); - expect(ProjectForm.prototype.showAlert).toHaveBeenCalledWith('Project Name is a required field'); + expect(wrapper.find('div#projectNameError').text()).toBe('Project Name is a required field') expect(projectCreated).not.toHaveBeenCalled(); }) - it('should reject an attempt to submit a pristine form', function() { - spyOn(ProjectForm.prototype, "showAlert").and.callThrough() + //TODO: For some reason enabling this test case causes subsequent ones to fail. + // Need to look into this when I have time. + xit('should call the alert function when attempting to submit an invalid project', function(done) { + //spyOn(ProjectForm.prototype, "showAlert").and.callThrough() + let errorMessageHandler = { + error: function(message, time, type, icon) { + console.log('error: ', message); + done(); + } + } let projectCreated = jasmine.createSpy('projectCreated'); - const wrapper = mount(); + const wrapper = mount(); // Try resetting the state of LoginForm + //wrapper.setState({formStarted: true}); + + const projectNameField = wrapper.find('input[name="projectName"]'); + let simulatedProjectNameElement = createSimulatedElement('projectName', '', { valueMissing: true}); + projectNameField.simulate('change', simulatedProjectNameElement); + expect(wrapper.find('div#projectNameError').text()).toBe('Project Name is a required field') + + //wrapper.find('button#create-project-button').get(0).click(); + wrapper.find('button #create-project-button').simulate('submit'); + + expect(projectCreated).not.toHaveBeenCalled(); + }) + + it('should reject an attempt to submit a pristine form', function() { + let projectCreated = jasmine.createSpy('projectCreated'); + + const wrapper = mount(); wrapper.setState({formStarted: false}); + console.log('projectName: ' + wrapper.state('projectName')); + console.log('errorMessages: ', wrapper.state('errorMessages')); - wrapper.find('button#create-project-button').get(0).click(); + //wrapper.find('button#create-project-button').get(0).click(); + wrapper.find('button #create-project-button').simulate('submit'); + console.log('errorMessages: ', wrapper.state('errorMessages')); expect(wrapper.find('div#projectNameError').text()).toBe('Please provide a name for the new project.'); expect(projectCreated).not.toHaveBeenCalled(); @@ -135,13 +164,16 @@ describe('ProjectForm Component', function() { const wrapper = mount(); // Set the component state so that a form can be submitted - wrapper.setState({projectName: project.name}); - wrapper.setState({projectDescription: project.description}); - wrapper.setState({formStarted: true}); - wrapper.setState({style: 'CRUD'}); + const projectNameField = wrapper.find('input[name="projectName"]'); + let simulatedProjectNameElement = createSimulatedElement('projectName', project.name, {valid: true}); + projectNameField.simulate('change', simulatedProjectNameElement); + + const projectDescriptionField = wrapper.find('input[name="projectName"]'); + let simulatedProjectDescriptionElement = createSimulatedElement('projectDescription', project.description, {valid: true}); + projectDescriptionField.simulate('change', simulatedProjectDescriptionElement); // Click create - wrapper.find('button #create-project-button').get(0).click(); + wrapper.find('button #create-project-button').simulate('submit'); expect(ProjectForm.prototype.showAlert).not.toHaveBeenCalled(); @@ -188,7 +220,9 @@ describe('ProjectForm Component', function() { wrapper.setState({style: 'CRUD'}); // Click submit - wrapper.find('button #create-project-button').get(0).click(); + //wrapper.find('button #create-project-button').get(0).click(); + wrapper.find('button #create-project-button').simulate('submit'); + }); diff --git a/src/css/app.scss b/src/css/app.scss index 3401d5e..e75ddc6 100644 --- a/src/css/app.scss +++ b/src/css/app.scss @@ -1,35 +1,15 @@ -/* -body { - width: 100%; - height: 100%; - overflow: hidden; - margin: 0; -} - -html { - width: 100%; - height: 100%; - overflow: hidden; -} -*/ - .github-corner-badge { position: absolute; top: 0; right: 0; } -.top-buffer { +.button-bar-buffer { margin-top:20px; } +/* Sketchy buttons */ .btn { border-radius: 255px 15px 225px 13px/15px 225px 15px 255px; border:solid 2px #41403E; } - -/* -.main-content { - padding-left:50px; -} -*/ diff --git a/src/css/header.scss b/src/css/header.scss index ce04820..05e53fb 100644 --- a/src/css/header.scss +++ b/src/css/header.scss @@ -12,19 +12,3 @@ #logo h1 { font-color: blue; } - -.topnav { - border-radius: 50% !important; - width:50px; - height: 50px; -} - - -a.profilemenu{ - font-color: green; - position:relative; - top:50%; - transform: translateY(-50%); - -webkit-transform: translateY(-50%); - -ms-transform: translateY(-50%); -} diff --git a/src/css/sketch.scss b/src/css/sketch.scss index 2e020e0..c9087ac 100644 --- a/src/css/sketch.scss +++ b/src/css/sketch.scss @@ -1,3 +1,8 @@ +/** Need to override the width:100% inline style to avoid showing a scroll bar **/ +.SplitPane { + width:auto !important; +} + .svg-wrapper { width: 100%; height: 100%; @@ -50,11 +55,8 @@ backface-visibility: hidden; height: 100%; position: absolute; top: -20px; - /* Hide the side-nav until we implement the vocab function left: -250px; - */ - left: -300px; - background: black; + background: #eee; padding: 15px; } @@ -89,7 +91,11 @@ backface-visibility: hidden; } .sketch-canvas { - padding-left: 1.0em; + padding-left: 55px; + box-sizing: border-box; + -moz-box-sizing:border-box; + -webkit-box-sizing:border-box; + -ms-box-sizing:border-box; } .property-pane { @@ -150,3 +156,45 @@ backface-visibility: hidden; border-color: transparent; } /*ENd of React split pane */ + + +/* Method Labels */ +.label.get { + background-color: #179603; +} + +.label.get.disabled { + background-color: grey; +} + +.label.put { + background-color: #1400f5; +} + +.label.put.disabled { + background-color: grey; +} + +.label.post { + background-color: #706900; +} + +.label.post.disabled { + background-color: grey; +} + +.label.delete { + background-color: #ad0300; +} + +.label.delete.disabled { + background-color: grey; +} + +.label.patch { + background-color: #008ead; +} + +.label.patch.disabled { + background-color: grey; +} diff --git a/src/css/tree.scss b/src/css/tree.scss index 093dbb8..0e3892d 100644 --- a/src/css/tree.scss +++ b/src/css/tree.scss @@ -15,9 +15,9 @@ } .selected-node-uri { - fill:yellow; + fill: #fffde5; stroke:gray; - stroke-width: 2px; + stroke-width: 5px; } .node-internal-border { stroke: gray; @@ -41,23 +41,46 @@ fill: black; } +.context-menu { + fill: white; + stroke: black; +} +.delete-button { + cursor: pointer; + fill: black; +} + +.fa-icon-text { + fill: black; +} + .badges { font-weight: bold; text-shadow: 2px -1px 2 gray; .get { - fill: green; + fill: #179603; + stroke: white; + stroke-width: 2; } .post { - fill: blue; + fill: #706900; + stroke: white; + stroke-width: 2; } .put { - fill: orange; + fill: #1400f5; + stroke: white; + stroke-width: 2; } .delete { - fill: red; + fill: #ad0300; + stroke: white; + stroke-width: 2; } .patch { - fill: brown; + fill: #008ead; + stroke: white; + stroke-width: 2; } text { fill: white; diff --git a/src/js/adapter/Backend.js b/src/js/adapter/Backend.js index 76219fb..8714ede 100644 --- a/src/js/adapter/Backend.js +++ b/src/js/adapter/Backend.js @@ -158,6 +158,17 @@ export default class { }); } + static deleteNode(token, projectId, sketchId, nodeId) { + let url = '/api/projects/' + projectId + '/sketches/' + sketchId + '/nodes/' + nodeId; + + return this._authenticatedCall(token, "DELETE", url, null, function(responseBody) { + return { + node: responseBody.node, + tree: responseBody.tree + } + }); + } + static export(token, projectId, sketchIndex, format) { let url = '/api/projects/' + projectId + '/sketches/' + sketchIndex + '/export?format='+format; return this._authenticatedCall(token, "GET", url, null, function(responseBody) { diff --git a/src/js/d3/CRUDTree.jsx b/src/js/d3/CRUDTree.jsx index 5116858..08932b7 100644 --- a/src/js/d3/CRUDTree.jsx +++ b/src/js/d3/CRUDTree.jsx @@ -117,6 +117,7 @@ export default class { }); + node.append("text") .attr("font-size", "18") .text("+") @@ -126,6 +127,52 @@ export default class { }) .style("pointer-events", "none") +/*** + // context menu + let contextMenuGroup = node.append("g") + .attr("transform", "translate(" + ((resourceBoxWidth/2) - 30) + "," + (resourceBoxHeight - 15) + ")") + .attr("visibility", function(d) { + if (selectedNode && d.data.id === selectedNode.id && selectedNode != '/'){ + return "visible"; + }else { + return "hidden"; + } + }) + + contextMenuGroup.append("rect") + .attr("width", 60) + .attr("height", 30) + .attr("rx", 5) + .attr("ry", 5) + .attr("class", "context-menu") + + contextMenuGroup.append("circle") + .attr("r", "15") + .attr("class", "delete-button") + .attr("x", "37") + .attr("y", "15") + .on("click", function(d) { + console.log('delete menu clicked.'); + d3.event.stopPropagation(); + handler({ + name: "delete", + source: d.data.id, + }) + }) + + contextMenuGroup.append("text") + .attr("font-family", "FontAwesome") + .attr("font-size", function(d) { + //return d.size +'em'; + return '1.4em'; + }) + .text(() => { return '\uf014'}) + .style("pointer-events", "none") + .attr("class", "fa-icon-text") + .attr("text-anchor", "middle") + .attr("x", "37") + .attr("y", "15") +**/ // Full URI path node.append("text") @@ -133,6 +180,13 @@ export default class { .text(function(d) { return d.data.fullpath;}) .attr("transform", "translate(10," + (resourceBoxHeight-7) + ")") .style("pointer-events", "none") + .attr("visibility", function(d) { + if (selectedNode && d.data.id === selectedNode.id ){ + return "visible"; + }else { + return "hidden"; + } + }) // Method badges diff --git a/src/js/modules/App.jsx b/src/js/modules/App.jsx index 1e2a8e1..f45dd3a 100644 --- a/src/js/modules/App.jsx +++ b/src/js/modules/App.jsx @@ -60,7 +60,7 @@ export default class extends React.Component { // Setup the body if( authenticated ) { return ( -
+
) @@ -73,5 +73,5 @@ export default class extends React.Component { ); } } - + } diff --git a/src/js/modules/AuthenticatedApp.jsx b/src/js/modules/AuthenticatedApp.jsx index dedf34d..1dbdce2 100644 --- a/src/js/modules/AuthenticatedApp.jsx +++ b/src/js/modules/AuthenticatedApp.jsx @@ -48,22 +48,24 @@ export default class extends React.Component{ return(
-
- this.msg = a} {...this.alertOptions} /> - - { - return this.authErrorHandler(error)} - setProjectHandler={project => {this.setProject(project)}} - setSketchIndexHandler={sketchIndex => {this.setSketchIndex(sketchIndex)}}/> - }}/> - { - return this.authErrorHandler(error)} - userObject={this.props.userObject}/>}} /> - +
+
+ this.msg = a} {...this.alertOptions} /> + + { + return this.authErrorHandler(error)} + setProjectHandler={project => {this.setProject(project)}} + setSketchIndexHandler={sketchIndex => {this.setSketchIndex(sketchIndex)}}/> + }}/> + { + return this.authErrorHandler(error)} + userObject={this.props.userObject}/>}} /> + +
); diff --git a/src/js/modules/Sketch.jsx b/src/js/modules/Sketch.jsx index c1aa5d0..cc408ef 100644 --- a/src/js/modules/Sketch.jsx +++ b/src/js/modules/Sketch.jsx @@ -29,7 +29,7 @@ export default class extends React.Component{ componentDidMount() { let sketch = this.props.sketches[this.props.sketchIteration-1]; - this.setState({sketchId: sketch.id}); + this.setState({sketchId: sketch.index}); this.parseTree(sketch.tree); this.setState({tree: sketch.tree}); @@ -42,6 +42,7 @@ export default class extends React.Component{ } toggleSideNav() { + console.log('toggleSideNav'); if( this.state.navState === 'show-nav') { // show the side nave and change the state this.setState({navState: 'nav-hidden'}); @@ -87,53 +88,6 @@ export default class extends React.Component{ }) } - __scheduleUpdate(nodeId, updateObject) { - - const intervalTime = 2000; - - // check if a timeout is already scheduled - if(this.timeoutID) { - // Cancel the last timeout - window.clearTimeout(this.timeoutID); - - if( this.pendingUpdate.id === nodeId) { - // This is another update for the same node, so merge the updateObjects - if( updateObject.name ) { - this.pendingUpdate.updateObject.name = updateObject.name; - } - if( updateObject.fullpath ) { - this.pendingUpdate.updateObject.fullpath = updateObject.fullpath; - } - if( updateObject.data ) { - this.pendingUpdate.updateObject.data = updateObject.data; - } - }else { - // This is an update for a new node, so fire off the old one immediately - Backend.updateNode(this.props.userObject.token, - this.state.sketchId, - this.pendingUpdate.id, - this.pendingUpdate.updateObject); - } - } - - // Save the update details - this.pendingUpdate = { - id: nodeId, - updateObject: updateObject - } - - // Scheudle the new update - this.timeoutID = window.setTimeout(() => { - Backend.updateNode(this.props.userObject.token, - this.state.sketchId, - this.pendingUpdate.id, - this.pendingUpdate.updateObject); - - // TODO: alert with a toast - - }, intervalTime) - } - uriChanged(nodeId, value) { // fullpath: (parentPath) + / + name @@ -198,7 +152,6 @@ export default class extends React.Component{ this.forceUpdate(); } - //TODO: schedule this update this.delayedNodeUpdate.write(this.props.userObject.token, this.props.projectId, this.state.sketchId, @@ -225,6 +178,10 @@ export default class extends React.Component{ //let parentPath = parent ? parent.fullpath : ''; //newNode.fullpath = parentPath; this.setState({selectedNode: newNode}); + // If the split panel is hidden, create a split by setting the default splitPaneSize + if( this.state.splitPaneSize === "100%") { + this.setState({splitPaneSize: "150px"}); + } }) } @@ -243,6 +200,7 @@ export default class extends React.Component{ parent = this.findNode(event.source, tree); } + //TODO: use the delayedNodeUpdate function // If there is a pending change, trigger it first. if(this.timeoutID) { Backend.updateNode(this.props.userObject.token, @@ -264,6 +222,9 @@ export default class extends React.Component{ if( this.state.splitPaneSize === "100%") { this.setState({splitPaneSize: "150px"}); } + }else if( eventType === 'delete') { + // Popup a confirmation modal + $('#deleteConfirmationModal').modal(); } } @@ -275,6 +236,13 @@ export default class extends React.Component{ this.setState({splitPaneSize: "100%"}); } + handleDeleteConfirmed() { + let selectedNode = this.state.selectedNode; + if( selectedNode && selectedNode != '/') { + + } + } + handleKeyPress(event) { //console.log(event); if( event.key === 'Escape') { @@ -292,6 +260,12 @@ export default class extends React.Component{ let selectedNode = this.state.selectedNode; console.log('to be implemented'); //this.addChild(selectedNode); + }else if( event.key === 'Delete') { + let selectedNode = this.state.selectedNode; + if( selectedNode && selectedNode != '/') { + // Popup a confirmation modal + $('#deleteConfirmationModal').modal(); + } }else if(event.key === 'ArrowLeft') { // Try to move to the parent node let selectedNode = this.state.selectedNode; @@ -385,48 +359,69 @@ export default class extends React.Component{ dataChangeHandler={(id,key,fields)=>{this.dataChanged(id,key,fields)}} /> :
; - - return( -
{this.slideWrapper = input;}} - > -
-
- -

Vocabulary

- - +
+ + + +
{this.slideWrapper = input;}}> +
+ +
+ +

Vocabulary

+ +
-
-
- -
- {this.clickHandler(e)}} - width="100%" - height="100%" - selectedNode={this.state.selectedNode} /> -
-
-
- {EditPane} -
+
+
+ +
+ {this.clickHandler(e)}} + width="100%" + height="100%" + selectedNode={this.state.selectedNode} /> +
+
+
+ {EditPane}
- -
+
+
-
+
+
+
) } } diff --git a/src/js/modules/header/AuthenticatedHeader.jsx b/src/js/modules/header/AuthenticatedHeader.jsx index 67ce772..1841eeb 100644 --- a/src/js/modules/header/AuthenticatedHeader.jsx +++ b/src/js/modules/header/AuthenticatedHeader.jsx @@ -60,27 +60,25 @@ export default class extends React.Component{ } return ( -
-
+
+
+ Rápido +

{this.props.project.name}

+ {downloadMenu} - Rápido -

{this.props.project.name}

- {downloadMenu} - -
+ + +
) } diff --git a/src/js/modules/projects/ProjectForm.jsx b/src/js/modules/projects/ProjectForm.jsx index 790d957..5583c36 100644 --- a/src/js/modules/projects/ProjectForm.jsx +++ b/src/js/modules/projects/ProjectForm.jsx @@ -29,7 +29,6 @@ export default class extends React.Component{ transition: 'scale' }; this.handleChange = this.handleChange.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); } componentDidMount() { @@ -59,16 +58,18 @@ export default class extends React.Component{ /* Method to handle form submission */ handleSubmit(e) { + console.log('handleSubmit'); e.preventDefault(); if( !this.state.formStarted ) { + console.log('pristine'); // Project name is the only required field, so set an error message jsut for that field + console.log(this); this.setState({errorMessages: {projectName: 'Please provide a name for the new project.'}}); + console.log('set errormessage'); + console.log(this.state.errorMessages); }else if (Object.keys(this.state.errorMessages).length !== 0 ) { - const thisForm = this; - // Remind the user know that there are problems with the form - Object.keys(this.state.errorMessages).forEach(function(key) { - thisForm.showAlert(thisForm.state.errorMessages[key]); - }); + // Remind the user that there are problems with the form + this.showAlert('There are problems with the form. Please correct them before continuing.'); } else { Backend.createProject(this.props.userObject.token, { @@ -93,8 +94,6 @@ export default class extends React.Component{ if( !validityState.valid ) { if (validityState.valueMissing) { errorMessages[input.name] = `${label} is a required field`; - } else if (validityState.typeMismatch) { - errorMessages[input.name] = `${label} should be a valid email address`; } else { console.warn('unexpected conformance validator problem: ', validityState); errorMessages[input.name] = `Invalid field value`; @@ -110,7 +109,7 @@ export default class extends React.Component{ return(
-
+ {this.handleSubmit(e)}}>
{ this.setState({view: 'list'}) }}>
-
+
{projectsView}
diff --git a/src/js/modules/sketch/NodeEditor.jsx b/src/js/modules/sketch/NodeEditor.jsx index 82d252a..7f9355b 100644 --- a/src/js/modules/sketch/NodeEditor.jsx +++ b/src/js/modules/sketch/NodeEditor.jsx @@ -47,7 +47,6 @@ export default class extends React.Component{ return(
-
{this.state.prePath} diff --git a/src/js/modules/sketch/tree/BodyEditor.jsx b/src/js/modules/sketch/tree/BodyEditor.jsx index 5cf1302..24627ff 100644 --- a/src/js/modules/sketch/tree/BodyEditor.jsx +++ b/src/js/modules/sketch/tree/BodyEditor.jsx @@ -4,10 +4,13 @@ import AceEditor from 'react-ace'; import * as Ace from 'brace'; import SplitPane from 'react-split-pane'; +import BootstrapToggle from 'bootstrap-toggle'; import 'brace/mode/javascript'; import 'brace/theme/github'; +import 'bootstrap-toggle/css/bootstrap-toggle.min.css'; + export default class extends React.Component{ constructor(props) { @@ -16,6 +19,13 @@ export default class extends React.Component{ selectedMethodIndex: 0, activeTab: 'get', tabClasses: {get: 'active'}, + methodLabels: { + get: 'label get disabled', + put: 'label put disabled', + post: 'label post disabled', + patch: 'label patch disabled', + delete: 'label delete disabled' + }, data: {}, isMethodEnabled: false } @@ -43,6 +53,17 @@ export default class extends React.Component{ } + // Sets the state of the method label classes based on whether they are enabled + setMethodLabelClass(methodName) { + let classValue = 'label ' + methodName; + if( this.state.data[methodName].enabled === false ) { + classValue = classValue + ' disabled'; + } + let methodLabels = this.state.methodLabels; + methodLabels[methodName] = classValue; + this.setState({methodLabels: methodLabels}); + } + // Loads editor state values based on node data loadNodeData(node) { let buildMethodData = function(methodName, data) { @@ -70,7 +91,20 @@ export default class extends React.Component{ } // Store the message body data and set the editor tab to 'get' - this.setState({data: data}, () => {this.setView('get')}); + this.setState({data: data}, () => { + this.setView('get') + + // Set the classnames for all method labels + this.setMethodLabelClass('get'); + this.setMethodLabelClass('put'); + this.setMethodLabelClass('post'); + this.setMethodLabelClass('delete'); + this.setMethodLabelClass('patch'); + + }); + + + } componentWillReceiveProps(nextProps){ @@ -108,11 +142,14 @@ export default class extends React.Component{ } onFieldChange(e) { - console.log(e); - console.log(e.target); if( e.target.name === 'requestParams') { - console.log(e.target.value) this.setState({requestParams: e.target.value}); + this.props.updateHandler(this.state.activeTab, + { request: { queryParams: e.target.value }} ); + }else if( e.target.name === 'statusCode') { + this.setState({statusCode: e.target.value}); + this.props.updateHandler(this.state.activeTab, + { response: { status: e.target.value } } ); } } @@ -125,9 +162,12 @@ export default class extends React.Component{ if( editorName === 'responseBody') { // If the response body was empty, automatically enable this method if( data[this.state.activeTab].response.body.length === 0 ) { + /* this.setState({isMethodEnabled: true}); data[this.state.activeTab].enabled = true; this.props.updateHandler(this.state.activeTab, {enabled: true}); + */ + this.handleEnabledChange(); } data[this.state.activeTab].response.body = this.responseEditor.getValue(); }else if( editorName === 'requestBody' ) { @@ -153,6 +193,14 @@ export default class extends React.Component{ let newCheckBoxState = !this.state.isMethodEnabled; this.setState({isMethodEnabled: newCheckBoxState}); this.props.updateHandler(this.state.activeTab, {enabled: newCheckBoxState }) + + // Update the method class Labels + let data = this.state.data; + let methodName = this.state.activeTab; + data[this.state.activeTab].enabled = newCheckBoxState; + this.setState({data: data}, () => { + this.setMethodLabelClass(this.state.activeTab); + }) } // Called when the user selects a method tab @@ -197,17 +245,28 @@ export default class extends React.Component{ return (
this.handleEnabledChange()}> @@ -245,7 +304,8 @@ export default class extends React.Component{ name="statusCode" placeholder="Default Status Code" type="text" - value={this.state.statusCode}/> + value={this.state.statusCode} + onChange={(e) => this.onFieldChange(e)}/>