1
0
Fork 0

Refactor command form

This commit is contained in:
Gregory Eremin 2017-11-04 20:38:21 +01:00
parent 730aaa071a
commit 9bd7b91e83
1 changed files with 106 additions and 105 deletions

View File

@ -1,141 +1,83 @@
import React, { Component } from 'react'; import React, { Component } from 'react'
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom'
import Nav from '../blocks/nav.js'; import Nav from '../blocks/nav.js'
import Output from '../blocks/output.js'; import Output from '../blocks/output.js'
import { api, httpPOST } from '../http.js'; import { api, httpPOST } from '../http.js'
import './command.css'; import './command.css'
export default class Command extends Component { export default class Command extends Component {
constructor(props) { constructor(props) {
super(props); super(props)
this.state = { this.state = {
form: this.defaultForm(props.commands[props.cmd]), form: this.defaultForm(props.commands[props.cmd]),
jobID: null, jobID: null,
error: null, error: null,
}; }
} }
componentWillReceiveProps(props) { componentWillReceiveProps(props) {
this.setState({form: this.defaultForm(props.commands[props.cmd])}); let form = this.defaultForm(props.commands[props.cmd])
this.setState({form: form})
} }
defaultForm(cmd) { defaultForm(cmd) {
if (!cmd || Object.keys(cmd).length === 0) { if (!cmd || Object.keys(cmd).length === 0) {
return {}; return {}
} }
var form = { return {
command: cmd.name, command: cmd.name,
args: "", args: "",
flags: {} flags: cmd.flags.reduce((list = {}, flag) => {
list[flag.name] = flag.default
return list
})
} }
cmd.flags.forEach((flag) => {
form.flags[flag.name] = flag.default;
});
return form;
} }
render() { render() {
let cmd = this.props.commands[this.props.cmd];
if (!cmd) {
return null;
}
return ( return (
<div className="container"> <div className="container">
<Nav commands={this.props.commands} active={this.props.cmd} <Nav commands={this.props.commands} active={this.props.cmd}
query={this.props.query} onQueryChange={this.props.onQueryChange} /> query={this.props.query} onQueryChange={this.props.onQueryChange} />
<main> <main>
<form method="post" action="/api/exec" onSubmit={this.submitHandler.bind(this)} ref="form"> {this.renderForm()}
<div className="command">
<div className="name">{cmd.name}</div>
<div className="descr">{cmd.description}</div>
<input type="hidden" name="command" defaultValue={cmd.name} />
</div>
<ul className="fields">
<li>
<div className="descr">Command arguments</div>
<input type="text" name="args" placeholder={cmd.args_placeholder}
onChange={this.changeHandler.bind(this)} />
</li>
{cmd.flags.map((flag) => { return this.input(flag); })}
</ul>
<input type="submit" value="Execute" id="submit-button"/>
<Link to={"/cmd/"+ cmd.name +"/jobs"} className="history">History</Link>
</form>
{this.renderError()} {this.renderError()}
<Output cmd={cmd} jobID={this.state.jobID} key={this.state.jobID} /> <Output jobID={this.state.jobID} />
</main> </main>
</div> </div>
); )
} }
renderError() { renderForm() {
if (this.state.error === null) { let cmd = this.props.commands[this.props.cmd]
return null; if (!cmd) {
return null
} }
return ( return (
<div className="error">{this.state.error}</div> <form method="post" action="/api/exec" onSubmit={this.submitHandler.bind(this)} ref="form">
); <div className="command">
<div className="name">{cmd.name}</div>
<div className="descr">{cmd.description}</div>
<input type="hidden" name="command" defaultValue={cmd.name} />
</div>
<ul className="fields">
<li>
<div className="descr">Command arguments</div>
<input type="text" name="args" placeholder={cmd.args_placeholder}
onChange={this.changeHandler.bind(this)} />
</li>
{cmd.flags.map(this.renderFlag.bind(this))}
</ul>
<input type="submit" value="Execute" id="submit-button"/>
<Link to={"/cmd/"+ cmd.name +"/jobs"} className="history">History</Link>
</form>
)
} }
submitHandler(event) { renderFlag(flag) {
event.preventDefault();
let f = this.state.form;
var args = [];
args.push(["command", f.command]);
args.push(["args", f.args]);
for (let name of Object.keys(f.flags)) {
args.push(["flags[" + name + "]", f.flags[name]]);
}
let formQuery = args.map((pair) => {
return pair[0] + "=" + encodeURIComponent(pair[1]);
}).join("&");
httpPOST(api("/exec"), formQuery,
(response) => {
let details = JSON.parse(response);
this.setState({jobID: details.id, error: null});
},
(error) => {
this.setState({jobID: null, error: error});
},
);
}
changeHandler(event) {
if (event.target.id.indexOf("flag-") === 0) {
var val = event.target.value;
if (event.target.type === "checkbox") {
val = JSON.stringify(event.target.checked);
}
var flags = this.state.form.flags;
let name = event.target.id.substring(5);
flags[name] = val;
this.setState({
form: {
command: this.state.form.command,
args: this.state.form.args,
flags: flags
}
});
} else if (event.target.name === "args") {
this.setState({
form: {
command: this.state.form.command,
args: event.target.value,
flags: this.state.form.flags
}
});
}
}
input(flag) {
let flagName = (name) => "flags[" + name + "]" let flagName = (name) => "flags[" + name + "]"
if (flag.type === "bool") { if (flag.type === "bool") {
return ( return (
@ -148,17 +90,17 @@ export default class Command extends Component {
</li> </li>
) )
} else { } else {
var inputType = "string"; var inputType = "string"
let numericTypes = [ let numericTypes = [
"int", "int8", "int16", "int32", "int64", "int", "int8", "int16", "int32", "int64",
"uint", "uint8", "uint16", "uint32", "uint64" "uint", "uint8", "uint16", "uint32", "uint64"
]; ]
if (numericTypes.includes(flag.type)) { if (numericTypes.includes(flag.type)) {
inputType = "number"; inputType = "number"
} }
return ( return (
<li key={flag.name}> <li key={flag.name}>
<label htmlFor={"flags-"+flag.name}>{flag.name}</label> <label htmlFor={"flag-"+flag.name}>{flag.name}</label>
<span className="descr">{flag.description}</span> <span className="descr">{flag.description}</span>
<input type={inputType} name={flagName(flag.name)} id={"flag-"+flag.name} <input type={inputType} name={flagName(flag.name)} id={"flag-"+flag.name}
defaultValue={flag.default} defaultValue={flag.default}
@ -167,4 +109,63 @@ export default class Command extends Component {
) )
} }
} }
renderError() {
if (this.state.error === null) {
return null
}
return (
<div className="error">{this.state.error}</div>
)
}
submitHandler(event) {
event.preventDefault()
httpPOST(api("/exec"), formQuery(this.state.form),
(response) => {
let details = JSON.parse(response)
this.setState({jobID: details.id, error: null})
},
(error) => {
this.setState({jobID: null, error: error})
},
)
}
changeHandler(event) {
let field = event.target
let form = this.state.form
if (field.id.indexOf("flag-") === 0) {
var val = field.value
if (field.type === "checkbox") {
val = JSON.stringify(field.checked)
}
let name = field.id.substring(5)
form.flags[name] = val
this.setState({
form: {
command: form.command,
args: form.args,
flags: form.flags
}
})
} else if (field.name === "args") {
this.setState({
form: {
command: form.command,
args: field.value,
flags: form.flags
}
})
}
}
}
function formQuery(form) {
var args = Object.keys(form.flags).map((name) => ["flags[" + name + "]", form.flags[name]])
args.push(["command", form.command])
args.push(["args", form.args])
return args.map((pair) => pair[0] + "=" + encodeURIComponent(pair[1]))
} }