RecordList.jsx 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. var DomainStore = require('../stores').Domains;
  2. var React = require('react');
  3. var CloudActive = React.createClass({
  4. render: function() {
  5. var record = this.props.record;
  6. if(record.proxiable.val()) {
  7. var active = record.proxied.val();
  8. if(active) {
  9. return <button className='btn btn-warning' onClick={this.props.onClick}>On</button>
  10. }
  11. else {
  12. return <button className='btn btn-default' onClick={this.props.onClick}>Off</button>
  13. }
  14. }
  15. else {
  16. return <span></span>;
  17. }
  18. }
  19. });
  20. var RecordCreate = React.createClass({
  21. getInitialState: function() {
  22. return {saving: false};
  23. },
  24. types: ['A', 'AAAA', 'CNAME', 'LOC', 'NS', 'SPF', 'TXT'],
  25. finishSave: function(promise) {
  26. promise.then(function() {
  27. this.setState({saving: false});
  28. this.reset();
  29. }.bind(this));
  30. },
  31. reset: function() {
  32. this.refs.type.getDOMNode().value = this.types[0];
  33. this.refs.name.getDOMNode().value = "";
  34. this.refs.value.getDOMNode().value = "";
  35. },
  36. commitAdd: function() {
  37. this.setState({saving: true});
  38. var newRecord = {
  39. type: this.refs.type.getDOMNode().value,
  40. name: this.refs.name.getDOMNode().value.trim(),
  41. content: this.refs.value.getDOMNode().value.trim(),
  42. ttl: 1 // automatic
  43. };
  44. this.finishSave(DomainStore.recordAdd(this.props.domain, newRecord));
  45. },
  46. render: function() {
  47. var className = this.state.saving ? 'saving' : '';
  48. var options = this.types.map(function(type) {
  49. return <option key={type} value={type}>{type}</option>
  50. });
  51. return (
  52. <tr className={className}>
  53. <td>
  54. <select ref="type">
  55. {options}
  56. </select>
  57. </td>
  58. <td><input type="text" ref="name" /></td>
  59. <td><input type="text" ref="value" /></td>
  60. <td></td>
  61. <td>
  62. <button className="btn btn-success" onClick={this.commitAdd}>Add</button>
  63. </td>
  64. </tr>
  65. )
  66. }
  67. });
  68. var Record = React.createClass({
  69. getInitialState: function() {
  70. return {state: 'view', saving: false};
  71. },
  72. componentWillReceiveProps: function() {
  73. this.setState({state: 'view', saving: false});
  74. },
  75. setDeleting: function() {
  76. this.setState({state: 'delete'});
  77. },
  78. setEditing: function() {
  79. this.setState({state: 'edit'});
  80. },
  81. cancelEdit: function() {
  82. this.setState({state: 'view'});
  83. },
  84. commitDelete: function() {
  85. this.setState({saving: true});
  86. var record = this.props.record;
  87. DomainStore.recordDelete(record.zone_name.val(), record.id.val());
  88. },
  89. commitEdit: function() {
  90. this.setState({saving: true});
  91. var record = this.props.record;
  92. var newRecord = {
  93. id: record.id.val(),
  94. type: record.type.val(),
  95. name: this.refs.name.getDOMNode().value.trim(),
  96. content: this.refs.value.getDOMNode().value.trim(),
  97. ttl: 1 // automatic
  98. };
  99. if(record.proxied.val()) {
  100. newRecord.proxied = record.proxied.val();
  101. }
  102. DomainStore.recordEdit(record.zone_name.val(), newRecord);
  103. },
  104. toggleProxy: function() {
  105. this.setState({saving: true});
  106. var record = this.props.record;
  107. var newRecord = {
  108. id: record.id.val(),
  109. type: record.type.val(),
  110. name: record.name.val(),
  111. content: record.content.val(),
  112. proxied: !record.proxied.val(),
  113. ttl: 1
  114. };
  115. DomainStore.recordEdit(record.zone_name.val(), newRecord);
  116. },
  117. render: function() {
  118. var record = this.props.record;
  119. var className = this.state.saving ? 'saving' : '';
  120. var editDisabled = ['MX', 'SRV'].indexOf(record.type.val()) >= 0;
  121. var displayName = record.name.val();
  122. var zoneName = '.'+record.zone_name.val();
  123. var limit = displayName.length - zoneName.length;
  124. if(limit > 0 && displayName.substring(limit) === zoneName) {
  125. displayName = displayName.substring(0, limit);
  126. }
  127. if(this.state.state === 'edit') {
  128. return (
  129. <tr className={className}>
  130. <td className="record-type"><span className={record.type.val()}>{record.type.val()}</span></td>
  131. <td><input type="text" ref="name" defaultValue={displayName} /></td>
  132. <td><input type="text" ref="value" defaultValue={record.content.val()} /></td>
  133. <td>
  134. <a onClick={this.cancelEdit}>Cancel</a>
  135. </td>
  136. <td>
  137. <button className="btn btn-success" onClick={this.commitEdit}>Save</button>
  138. </td>
  139. </tr>
  140. );
  141. }
  142. else if(this.state.state === 'delete') {
  143. return (
  144. <tr className={className}>
  145. <td className="record-type"><span className={record.type.val()}>{record.type.val()}</span></td>
  146. <td><strong>{displayName}</strong></td>
  147. <td>{record.content.val()}</td>
  148. <td>
  149. <a onClick={this.cancelEdit}>Cancel</a>
  150. </td>
  151. <td>
  152. <button className="btn btn-danger" onClick={this.commitDelete}>Delete</button>
  153. </td>
  154. </tr>
  155. );
  156. }
  157. else {
  158. return (
  159. <tr className={className}>
  160. <td className="record-type"><span className={record.type.val()}>{record.type.val()}</span></td>
  161. <td><strong>{displayName}</strong></td>
  162. <td className="value">{record.content.val()}</td>
  163. <td><CloudActive record={record} onClick={this.toggleProxy} /></td>
  164. <td className="actions">
  165. <button className="btn btn-primary" disabled={editDisabled} onClick={this.setEditing}>Edit</button>
  166. <span> </span>
  167. <button className="btn btn-danger" onClick={this.setDeleting}>Delete</button>
  168. </td>
  169. </tr>
  170. );
  171. }
  172. }
  173. });
  174. var RecordList = React.createClass({
  175. render: function() {
  176. var records = this.props.records.map(function(record) {
  177. return <Record key={record.id.val()} record={record} />
  178. }.bind(this));
  179. var body;
  180. if(records.length === 0) {
  181. body = (
  182. <tbody>
  183. <tr>
  184. <td colSpan="5">Loading...</td>
  185. </tr>
  186. </tbody>
  187. );
  188. }
  189. else {
  190. body = (
  191. <tbody>
  192. {records}
  193. <RecordCreate domain={this.props.domain} />
  194. </tbody>
  195. );
  196. }
  197. return (
  198. <div id="records">
  199. <table className="table">
  200. <thead>
  201. <tr>
  202. <th className="type">Type</th>
  203. <th className="name">Name</th>
  204. <th className="value">Value</th>
  205. <th className="proxy">Proxy</th>
  206. <th className="actions">Actions</th>
  207. </tr>
  208. </thead>
  209. {body}
  210. </table>
  211. </div>
  212. );
  213. }
  214. });
  215. module.exports = RecordList;