|
@@ -0,0 +1,214 @@
|
|
|
+var cloudflare = require('../cloudflare');
|
|
|
+var React = require('react');
|
|
|
+
|
|
|
+var CloudActive = React.createClass({
|
|
|
+ render: function() {
|
|
|
+ var record = this.props.record;
|
|
|
+ if(record.type === 'A' || record.type === 'AAAA' || record.type === 'CNAME') {
|
|
|
+ var active = record.service_mode === '1';
|
|
|
+ if(active) {
|
|
|
+ return <button className='btn btn-warning' onClick={this.props.onClick}>On</button>
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return <button className='btn btn-default' onClick={this.props.onClick}>Off</button>
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return <span></span>;
|
|
|
+ }
|
|
|
+ }
|
|
|
+});
|
|
|
+var RecordCreate = React.createClass({
|
|
|
+ getInitialState: function() {
|
|
|
+ return {saving: false};
|
|
|
+ },
|
|
|
+ types: ['A', 'AAAA', 'CNAME'],
|
|
|
+ finishSave: function(promise) {
|
|
|
+ promise.then(this.props.onEdit).then(function() {
|
|
|
+ this.setState({saving: false});
|
|
|
+ this.reset();
|
|
|
+ }.bind(this));
|
|
|
+ },
|
|
|
+ reset: function() {
|
|
|
+ this.refs.type.getDOMNode().value = this.types[0];
|
|
|
+ this.refs.name.getDOMNode().value = "";
|
|
|
+ this.refs.value.getDOMNode().value = "";
|
|
|
+ },
|
|
|
+ commitAdd: function() {
|
|
|
+ this.setState({saving: true});
|
|
|
+ var newRecord = {
|
|
|
+ type: this.refs.type.getDOMNode().value,
|
|
|
+ name: this.refs.name.getDOMNode().value.trim(),
|
|
|
+ content: this.refs.value.getDOMNode().value.trim()
|
|
|
+ };
|
|
|
+ this.finishSave(cloudflare.record_add(this.props.domain, newRecord));
|
|
|
+ },
|
|
|
+ render: function() {
|
|
|
+ var className = this.state.saving ? 'saving' : '';
|
|
|
+ var options = this.types.map(function(type) {
|
|
|
+ return <option key={type} value={type}>{type}</option>
|
|
|
+ });
|
|
|
+ return (
|
|
|
+ <tr className={className}>
|
|
|
+ <td>
|
|
|
+ <select ref="type">
|
|
|
+ {options}
|
|
|
+ </select>
|
|
|
+ </td>
|
|
|
+ <td><input type="text" ref="name" /></td>
|
|
|
+ <td><input type="text" ref="value" /></td>
|
|
|
+ <td></td>
|
|
|
+ <td>
|
|
|
+ <button className="btn btn-success" onClick={this.commitAdd}>Add</button>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ )
|
|
|
+ }
|
|
|
+});
|
|
|
+var Record = React.createClass({
|
|
|
+ getInitialState: function() {
|
|
|
+ return {state: 'view', saving: false};
|
|
|
+ },
|
|
|
+ setDeleting: function() {
|
|
|
+ this.setState({state: 'delete'});
|
|
|
+ },
|
|
|
+ setEditing: function() {
|
|
|
+ this.setState({state: 'edit'});
|
|
|
+ },
|
|
|
+ cancelEdit: function() {
|
|
|
+ this.setState({state: 'view'});
|
|
|
+ },
|
|
|
+ finishSave: function(promise) {
|
|
|
+ promise.then(this.props.onEdit).then(function() {
|
|
|
+ this.setState({state: 'view', saving: false});
|
|
|
+ }.bind(this));
|
|
|
+ },
|
|
|
+ commitDelete: function() {
|
|
|
+ this.setState({saving: true});
|
|
|
+ var record = this.props.record;
|
|
|
+ this.finishSave(cloudflare.record_delete(record.zone_name, record.rec_id));
|
|
|
+ },
|
|
|
+ commitEdit: function() {
|
|
|
+ this.setState({saving: true});
|
|
|
+ var record = this.props.record;
|
|
|
+ var newRecord = {
|
|
|
+ id: record.rec_id,
|
|
|
+ type: record.type,
|
|
|
+ name: this.refs.name.getDOMNode().value.trim(),
|
|
|
+ content: this.refs.value.getDOMNode().value.trim()
|
|
|
+ };
|
|
|
+ if(record.service_mode) {
|
|
|
+ newRecord.service_mode = record.service_mode;
|
|
|
+ }
|
|
|
+ this.finishSave(cloudflare.record_edit(record.zone_name, newRecord));
|
|
|
+ },
|
|
|
+ toggleProxy: function() {
|
|
|
+ this.setState({saving: true});
|
|
|
+ var record = this.props.record;
|
|
|
+ var newRecord = {
|
|
|
+ id: record.rec_id,
|
|
|
+ type: record.type,
|
|
|
+ name: record.name,
|
|
|
+ content: record.content,
|
|
|
+ service_mode: record.service_mode === "1" ? "0" : "1"
|
|
|
+ };
|
|
|
+ this.finishSave(cloudflare.record_edit(record.zone_name, newRecord));
|
|
|
+ },
|
|
|
+ render: function() {
|
|
|
+ var record = this.props.record;
|
|
|
+ var className = this.state.saving ? 'saving' : '';
|
|
|
+ if(this.state.state === 'edit') {
|
|
|
+ return (
|
|
|
+ <tr className={className}>
|
|
|
+ <td className="record-type"><span className={record.type}>{record.type}</span></td>
|
|
|
+ <td><input type="text" ref="name" defaultValue={record.display_name} /></td>
|
|
|
+ <td><input type="text" ref="value" defaultValue={record.display_content} /></td>
|
|
|
+ <td>
|
|
|
+ <a onClick={this.cancelEdit}>Cancel</a>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <button className="btn btn-success" onClick={this.commitEdit}>Save</button>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ );
|
|
|
+ }
|
|
|
+ else if(this.state.state === 'delete') {
|
|
|
+ return (
|
|
|
+ <tr className={className}>
|
|
|
+ <td className="record-type"><span className={record.type}>{record.type}</span></td>
|
|
|
+ <td><strong>{record.display_name}</strong></td>
|
|
|
+ <td>{record.display_content}</td>
|
|
|
+ <td>
|
|
|
+ <a onClick={this.cancelEdit}>Cancel</a>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <button className="btn btn-danger" onClick={this.commitDelete}>Delete</button>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ );
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return (
|
|
|
+ <tr className={className}>
|
|
|
+ <td className="record-type"><span className={record.type}>{record.type}</span></td>
|
|
|
+ <td><strong>{record.display_name}</strong></td>
|
|
|
+ <td className="value">{record.display_content}</td>
|
|
|
+ <td><CloudActive record={record} onClick={this.toggleProxy} /></td>
|
|
|
+ <td className="actions">
|
|
|
+ <button className="btn btn-primary" onClick={this.setEditing}>Edit</button>
|
|
|
+ <span> </span>
|
|
|
+ <button className="btn btn-danger" onClick={this.setDeleting}>Delete</button>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+});
|
|
|
+var RecordList = React.createClass({
|
|
|
+ getInitialState: function() {
|
|
|
+ return {records: []};
|
|
|
+ },
|
|
|
+ componentDidMount: function() {
|
|
|
+ this.reload();
|
|
|
+ },
|
|
|
+ componentWillReceiveProps: function(nextProps) {
|
|
|
+ if(nextProps.domain != this.props.domain) {
|
|
|
+ this.setState({records: []});
|
|
|
+ this.reload(nextProps);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ reload: function(props) {
|
|
|
+ if(!props) {
|
|
|
+ props = this.props;
|
|
|
+ }
|
|
|
+ return cloudflare.records(props.domain).then(function(data) {
|
|
|
+ this.setState({records: data.response.recs.objs});
|
|
|
+ }.bind(this));
|
|
|
+ },
|
|
|
+ render: function() {
|
|
|
+ var records = this.state.records.map(function(record) {
|
|
|
+ return <Record key={record.rec_id} record={record} onEdit={this.reload} />
|
|
|
+ }.bind(this));
|
|
|
+ return (
|
|
|
+ <div id="records">
|
|
|
+ <table className="table">
|
|
|
+ <thead>
|
|
|
+ <tr>
|
|
|
+ <th className="type">Type</th>
|
|
|
+ <th className="name">Name</th>
|
|
|
+ <th className="value">Value</th>
|
|
|
+ <th className="proxy">Proxy</th>
|
|
|
+ <th className="actions">Actions</th>
|
|
|
+ </tr>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ <RecordCreate domain={this.props.domain} onEdit={this.reload} />
|
|
|
+ {records}
|
|
|
+ </tbody>
|
|
|
+ </table>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+module.exports = RecordList;
|