|  | @@ -1,6 +1,163 @@
 | 
	
		
			
				|  |  |  var DomainStore = require('../stores').Domains;
 | 
	
		
			
				|  |  |  var React = require('react');
 | 
	
		
			
				|  |  | +var deepMerge = require('../util').deepMerge;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +var TextName = React.createClass({
 | 
	
		
			
				|  |  | +  getName: function() {
 | 
	
		
			
				|  |  | +    return {
 | 
	
		
			
				|  |  | +      name: this.refs.name.getDOMNode().value.trim()
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  clear: function() {
 | 
	
		
			
				|  |  | +    this.refs.name.getDOMNode().value = "";
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  render: function() {
 | 
	
		
			
				|  |  | +    return (
 | 
	
		
			
				|  |  | +      <td><input type="text" ref="name" defaultValue={this.props.record.name} /></td>
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +var SRVName = React.createClass({
 | 
	
		
			
				|  |  | +  getName: function() {
 | 
	
		
			
				|  |  | +    return {
 | 
	
		
			
				|  |  | +      data: {
 | 
	
		
			
				|  |  | +        service: this.refs.service.getDOMNode().value.trim(),
 | 
	
		
			
				|  |  | +        proto: this.refs.proto.getDOMNode().value
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  clear: function() {
 | 
	
		
			
				|  |  | +    this.refs.service.getDOMNode().value = "";
 | 
	
		
			
				|  |  | +    this.refs.proto.getDOMNode().value = "_udp";
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  render: function() {
 | 
	
		
			
				|  |  | +    var record = this.props.record;
 | 
	
		
			
				|  |  | +    var data = record && record.data || {};
 | 
	
		
			
				|  |  | +    var protos = ['_udp', '_tcp', '_tls'];
 | 
	
		
			
				|  |  | +    var options = protos.map(function(proto) {
 | 
	
		
			
				|  |  | +      return <option key={proto} value={proto}>{proto}</option>
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    return (
 | 
	
		
			
				|  |  | +      <td className="multi-input">
 | 
	
		
			
				|  |  | +        <div>
 | 
	
		
			
				|  |  | +          <label>Service</label>
 | 
	
		
			
				|  |  | +          <input type="text" ref="service" defaultValue={data.service} />
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +        <div>
 | 
	
		
			
				|  |  | +          <label>Proto</label>
 | 
	
		
			
				|  |  | +          <select ref="proto" defaultValue={data.proto}>{options}</select>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +      </td>
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +var TextValue = React.createClass({
 | 
	
		
			
				|  |  | +  getValue: function() {
 | 
	
		
			
				|  |  | +    return {
 | 
	
		
			
				|  |  | +      content: this.refs.value.getDOMNode().value.trim()
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  clear: function() {
 | 
	
		
			
				|  |  | +    this.refs.value.getDOMNode().value = "";
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  render: function() {
 | 
	
		
			
				|  |  | +    return (
 | 
	
		
			
				|  |  | +      <td><input type="text" ref="value" defaultValue={this.props.record.content} /></td>
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +var MXValue = React.createClass({
 | 
	
		
			
				|  |  | +  getValue: function() {
 | 
	
		
			
				|  |  | +    return {
 | 
	
		
			
				|  |  | +      content: this.refs.value.getDOMNode().value.trim(),
 | 
	
		
			
				|  |  | +      priority: this.refs.priority.getDOMNode().value.trim()
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  clear: function() {
 | 
	
		
			
				|  |  | +    this.refs.value.getDOMNode().value = "";
 | 
	
		
			
				|  |  | +    this.refs.priority.getDOMNode().value = "";
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  render: function() {
 | 
	
		
			
				|  |  | +    return (
 | 
	
		
			
				|  |  | +      <td className="multi-input">
 | 
	
		
			
				|  |  | +        <div>
 | 
	
		
			
				|  |  | +          <label>Domain</label>
 | 
	
		
			
				|  |  | +          <input type="text" ref="value" defaultValue={this.props.record.content} />
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +        <div>
 | 
	
		
			
				|  |  | +          <label>Priority</label>
 | 
	
		
			
				|  |  | +          <input type="number" ref="priority" minValue="0" maxValue="65535" defaultValue={this.props.record.priority} />
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +      </td>
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +var SRVValue = React.createClass({
 | 
	
		
			
				|  |  | +  getValue: function() {
 | 
	
		
			
				|  |  | +    return {
 | 
	
		
			
				|  |  | +      data: {
 | 
	
		
			
				|  |  | +        name: this.refs.name.getDOMNode().value.trim(),
 | 
	
		
			
				|  |  | +        priority: this.refs.priority.getDOMNode().value.trim(),
 | 
	
		
			
				|  |  | +        weight: this.refs.weight.getDOMNode().value.trim(),
 | 
	
		
			
				|  |  | +        port: this.refs.port.getDOMNode().value.trim(),
 | 
	
		
			
				|  |  | +        target: this.refs.target.getDOMNode().value.trim()
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  clear: function() {
 | 
	
		
			
				|  |  | +    this.refs.name.getDOMNode().value = "";
 | 
	
		
			
				|  |  | +    this.refs.priority.getDOMNode().value = "";
 | 
	
		
			
				|  |  | +    this.refs.weight.getDOMNode().value = "";
 | 
	
		
			
				|  |  | +    this.refs.port.getDOMNode().value = "";
 | 
	
		
			
				|  |  | +    this.refs.target.getDOMNode().value = "";
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  render: function() {
 | 
	
		
			
				|  |  | +    var record = this.props.record;
 | 
	
		
			
				|  |  | +    var data = record && record.data || {};
 | 
	
		
			
				|  |  | +    return (
 | 
	
		
			
				|  |  | +      <td className="multi-input">
 | 
	
		
			
				|  |  | +        <div>
 | 
	
		
			
				|  |  | +          <label>Name</label>
 | 
	
		
			
				|  |  | +          <input type="text" ref="name" defaultValue={data.name} />
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +        <div>
 | 
	
		
			
				|  |  | +          <label>Priority</label>
 | 
	
		
			
				|  |  | +          <input type="number" ref="priority" minValue="0" maxValue="65535" defaultValue={data.priority} />
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +        <div>
 | 
	
		
			
				|  |  | +          <label>Weight</label>
 | 
	
		
			
				|  |  | +          <input type="number" ref="weight" minValue="0" maxValue="65535" defaultValue={data.weight} />
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +        <div>
 | 
	
		
			
				|  |  | +          <label>Port</label>
 | 
	
		
			
				|  |  | +          <input type="number" ref="port" minValue="0" maxValue="65535" defaultValue={data.port} />
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +        <div>
 | 
	
		
			
				|  |  | +          <label>Target</label>
 | 
	
		
			
				|  |  | +          <input type="text" ref="target" defaultValue={data.target} />
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +      </td>
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +function getNameComponent(type) {
 | 
	
		
			
				|  |  | +  switch(type) {
 | 
	
		
			
				|  |  | +    case 'SRV':
 | 
	
		
			
				|  |  | +      return SRVName;
 | 
	
		
			
				|  |  | +    default:
 | 
	
		
			
				|  |  | +      return TextName;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +function getValueComponent(type) {
 | 
	
		
			
				|  |  | +  switch(type) {
 | 
	
		
			
				|  |  | +    case 'MX':
 | 
	
		
			
				|  |  | +      return MXValue;
 | 
	
		
			
				|  |  | +    case 'SRV':
 | 
	
		
			
				|  |  | +      return SRVValue;
 | 
	
		
			
				|  |  | +    default:
 | 
	
		
			
				|  |  | +      return TextValue;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  var CloudActive = React.createClass({
 | 
	
		
			
				|  |  |    render: function() {
 | 
	
		
			
				|  |  |      var record = this.props.record;
 | 
	
	
		
			
				|  | @@ -20,9 +177,12 @@ var CloudActive = React.createClass({
 | 
	
		
			
				|  |  |  });
 | 
	
		
			
				|  |  |  var RecordCreate = React.createClass({
 | 
	
		
			
				|  |  |    getInitialState: function() {
 | 
	
		
			
				|  |  | -    return {saving: false};
 | 
	
		
			
				|  |  | +    return {saving: false, type: 'A'};
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  types: ['A', 'AAAA', 'CNAME', 'LOC', 'MX', 'NS', 'SPF', 'SRV', 'TXT'],
 | 
	
		
			
				|  |  | +  changeType: function(event) {
 | 
	
		
			
				|  |  | +    this.setState({ type: event.target.value });
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  | -  types: ['A', 'AAAA', 'CNAME', 'LOC', 'NS', 'SPF', 'TXT'],
 | 
	
		
			
				|  |  |    finishSave: function(promise) {
 | 
	
		
			
				|  |  |      promise.then(function() {
 | 
	
		
			
				|  |  |        this.setState({saving: false});
 | 
	
	
		
			
				|  | @@ -30,18 +190,15 @@ var RecordCreate = React.createClass({
 | 
	
		
			
				|  |  |      }.bind(this));
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    reset: function() {
 | 
	
		
			
				|  |  | -    this.refs.type.getDOMNode().value = this.types[0];
 | 
	
		
			
				|  |  | -    this.refs.name.getDOMNode().value = "";
 | 
	
		
			
				|  |  | -    this.refs.value.getDOMNode().value = "";
 | 
	
		
			
				|  |  | +    this.refs.name.clear();
 | 
	
		
			
				|  |  | +    this.refs.value.clear();
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    commitAdd: function() {
 | 
	
		
			
				|  |  |      this.setState({saving: true});
 | 
	
		
			
				|  |  | -    var newRecord = {
 | 
	
		
			
				|  |  | +    var newRecord = deepMerge({
 | 
	
		
			
				|  |  |        type: this.refs.type.getDOMNode().value,
 | 
	
		
			
				|  |  | -      name: this.refs.name.getDOMNode().value.trim(),
 | 
	
		
			
				|  |  | -      content: this.refs.value.getDOMNode().value.trim(),
 | 
	
		
			
				|  |  |        ttl: 1 // automatic
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | +    }, this.refs.name.getName(), this.refs.value.getValue());
 | 
	
		
			
				|  |  |      this.finishSave(DomainStore.recordAdd(this.props.domain, newRecord));
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    render: function() {
 | 
	
	
		
			
				|  | @@ -49,15 +206,17 @@ var RecordCreate = React.createClass({
 | 
	
		
			
				|  |  |      var options = this.types.map(function(type) {
 | 
	
		
			
				|  |  |        return <option key={type} value={type}>{type}</option>
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  | +    var Name = getNameComponent(this.state.type);
 | 
	
		
			
				|  |  | +    var Value = getValueComponent(this.state.type);
 | 
	
		
			
				|  |  |      return (
 | 
	
		
			
				|  |  |        <tr className={className}>
 | 
	
		
			
				|  |  |          <td>
 | 
	
		
			
				|  |  | -          <select ref="type">
 | 
	
		
			
				|  |  | +          <select ref="type" onChange={this.changeType}>
 | 
	
		
			
				|  |  |              {options}
 | 
	
		
			
				|  |  |            </select>
 | 
	
		
			
				|  |  |          </td>
 | 
	
		
			
				|  |  | -        <td><input type="text" ref="name" /></td>
 | 
	
		
			
				|  |  | -        <td><input type="text" ref="value" /></td>
 | 
	
		
			
				|  |  | +        <Name ref="name" record={{}} />
 | 
	
		
			
				|  |  | +        <Value ref="value" record={{}} />
 | 
	
		
			
				|  |  |          <td></td>
 | 
	
		
			
				|  |  |          <td>
 | 
	
		
			
				|  |  |            <button className="btn btn-success" onClick={this.commitAdd}>Add</button>
 | 
	
	
		
			
				|  | @@ -90,13 +249,11 @@ var Record = React.createClass({
 | 
	
		
			
				|  |  |    commitEdit: function() {
 | 
	
		
			
				|  |  |      this.setState({saving: true});
 | 
	
		
			
				|  |  |      var record = this.props.record;
 | 
	
		
			
				|  |  | -    var newRecord = {
 | 
	
		
			
				|  |  | +    var newRecord = deepMerge({
 | 
	
		
			
				|  |  |        id: record.id.val(),
 | 
	
		
			
				|  |  |        type: record.type.val(),
 | 
	
		
			
				|  |  | -      name: this.refs.name.getDOMNode().value.trim(),
 | 
	
		
			
				|  |  | -      content: this.refs.value.getDOMNode().value.trim(),
 | 
	
		
			
				|  |  |        ttl: 1 // automatic
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | +    }, this.refs.name.getName(), this.refs.value.getValue());
 | 
	
		
			
				|  |  |      if(record.proxied.val()) {
 | 
	
		
			
				|  |  |        newRecord.proxied = record.proxied.val();
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -118,7 +275,6 @@ var Record = React.createClass({
 | 
	
		
			
				|  |  |    render: function() {
 | 
	
		
			
				|  |  |      var record = this.props.record;
 | 
	
		
			
				|  |  |      var className = this.state.saving ? 'saving' : '';
 | 
	
		
			
				|  |  | -    var editDisabled = ['MX', 'SRV'].indexOf(record.type.val()) >= 0;
 | 
	
		
			
				|  |  |      var displayName = record.name.val();
 | 
	
		
			
				|  |  |      var zoneName = '.'+record.zone_name.val();
 | 
	
		
			
				|  |  |      var limit = displayName.length - zoneName.length;
 | 
	
	
		
			
				|  | @@ -126,11 +282,13 @@ var Record = React.createClass({
 | 
	
		
			
				|  |  |        displayName = displayName.substring(0, limit);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      if(this.state.state === 'edit') {
 | 
	
		
			
				|  |  | +      var Name = getNameComponent(record.type.val());
 | 
	
		
			
				|  |  | +      var Value = getValueComponent(record.type.val());
 | 
	
		
			
				|  |  |        return (
 | 
	
		
			
				|  |  |          <tr className={className}>
 | 
	
		
			
				|  |  |            <td className="record-type"><span className={record.type.val()}>{record.type.val()}</span></td>
 | 
	
		
			
				|  |  | -          <td><input type="text" ref="name" defaultValue={displayName} /></td>
 | 
	
		
			
				|  |  | -          <td><input type="text" ref="value" defaultValue={record.content.val()} /></td>
 | 
	
		
			
				|  |  | +          <Name ref="name" record={record.val()} />
 | 
	
		
			
				|  |  | +          <Value ref="value" record={record.val()} />
 | 
	
		
			
				|  |  |            <td>
 | 
	
		
			
				|  |  |              <a onClick={this.cancelEdit}>Cancel</a>
 | 
	
		
			
				|  |  |            </td>
 | 
	
	
		
			
				|  | @@ -163,7 +321,7 @@ var Record = React.createClass({
 | 
	
		
			
				|  |  |            <td className="value">{record.content.val()}</td>
 | 
	
		
			
				|  |  |            <td><CloudActive record={record} onClick={this.toggleProxy} /></td>
 | 
	
		
			
				|  |  |            <td className="actions">
 | 
	
		
			
				|  |  | -            <button className="btn btn-primary" disabled={editDisabled} onClick={this.setEditing}>Edit</button>
 | 
	
		
			
				|  |  | +            <button className="btn btn-primary" onClick={this.setEditing}>Edit</button>
 | 
	
		
			
				|  |  |              <span> </span>
 | 
	
		
			
				|  |  |              <button className="btn btn-danger" onClick={this.setDeleting}>Delete</button>
 | 
	
		
			
				|  |  |            </td>
 |