index.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. var React = require('react');
  2. var ReactDOM = require('react-dom');
  3. var Remarkable = require('remarkable');
  4. var Button = require('react-bootstrap').Button;
  5. var ButtonToolbar = require('react-bootstrap').ButtonToolbar;
  6. var FormControl = require('react-bootstrap').FormControl;
  7. var FormGroup = require('react-bootstrap').FormGroup;
  8. var Panel = require('react-bootstrap').Panel;
  9. var DatePicker = require('react-bootstrap-date-picker');
  10. var dateFormat = require('dateformat');
  11. var $ = require('jquery');
  12. const API_URL = "https://todo.tankernn.eu/php/api.php";
  13. const priorityNames = {1: "danger", 2: "warning", 3: "primary", 4: "success"};
  14. function dateToString(date) {
  15. return dateFormat(date, "yyyy-mm-dd");
  16. }
  17. var TodoForm = React.createClass({
  18. getInitialState: function() {
  19. return {title: '', text: '', deadline: new Date().toISOString(), priority: 1};
  20. },
  21. handleTitleChange: function(e) {
  22. this.setState({title: e.target.value});
  23. },
  24. handleDateChange: function(dateString) {
  25. this.setState({deadline: dateString});
  26. },
  27. handlePriorityChange: function(e) {
  28. this.setState({priority: e.target.value});
  29. },
  30. handleTextChange: function(e) {
  31. this.setState({text: e.target.value});
  32. },
  33. handleSubmit: function(e) {
  34. e.preventDefault();
  35. var title = this.state.title.trim();
  36. var text = this.state.text.trim();
  37. var priority = this.state.priority;
  38. var deadline = dateToString(this.state.deadline);
  39. console.log(deadline);
  40. if (!title || !text || !deadline) {
  41. return;
  42. }
  43. this.props.onCommentSubmit({a: 'add', title: title, text: text, deadline: deadline, priority: priority});
  44. this.setState(this.getInitialState());
  45. },
  46. render: function() {
  47. return (
  48. <form className="form-inline" name="todoForm" onSubmit={this.handleSubmit}>
  49. <FormControl
  50. type="text"
  51. placeholder="Title"
  52. value={this.state.title}
  53. onChange={this.handleTitleChange}
  54. />
  55. <FormControl componentClass="select" value={this.state.priority} onChange={this.handlePriorityChange}>
  56. <option value="1">First priority</option>
  57. <option value="2">Second priority</option>
  58. <option value="3">Not very important</option>
  59. <option value="4">Only if you are bored</option>
  60. </FormControl>
  61. <DatePicker
  62. value={this.state.deadline}
  63. onChange={this.handleDateChange}
  64. />
  65. <br />
  66. <FormControl
  67. componentClass="textarea"
  68. value={this.state.text}
  69. onChange={this.handleTextChange} />
  70. <br />
  71. <Button bsStyle="primary" type="submit">Add</Button>
  72. </form>
  73. );
  74. }
  75. });
  76. var Item = React.createClass({
  77. rawMarkup: function() {
  78. var md = new Remarkable();
  79. var rawMarkup = md.render(this.props.children.toString());
  80. return { __html: rawMarkup };
  81. },
  82. handleEditClick: function() {
  83. console.log("I wanna edit.");
  84. },
  85. handleDeleteClick: function() {
  86. console.log("Deleting " + this.props.id);
  87. this.props.handleDeleteClick(this.props.id);
  88. },
  89. render: function() {
  90. var md = new Remarkable();
  91. var daysLeft = Math.ceil((new Date(this.props.deadline) - new Date()) / (1000 * 60 * 60 * 24));
  92. if (daysLeft > 1) {
  93. daysLeft += " days left.";
  94. } else if (daysLeft == 1) {
  95. daysLeft = "One day left.";
  96. } else if (daysLeft == 0) {
  97. daysLeft = "Today!";
  98. } else {
  99. daysLeft = "Should have been done " + Math.abs(daysLeft) + " day(s) ago."
  100. }
  101. return (
  102. <Panel
  103. header={<header><span className="deadline">{daysLeft}</span><h3>{this.props.title}</h3></header>}
  104. footer={
  105. <ButtonToolbar>
  106. <Button bsStyle="primary" onClick={this.handleEditClick}>Edit</Button>
  107. <Button bsStyle="danger" onClick={this.handleDeleteClick}>Delete</Button>
  108. </ButtonToolbar>
  109. }
  110. bsStyle={priorityNames[this.props.priority]}
  111. >
  112. <span dangerouslySetInnerHTML={this.rawMarkup()} />
  113. </Panel>
  114. );
  115. }
  116. });
  117. var TodoList = React.createClass({
  118. render: function() {
  119. console.log(this.props.list);
  120. var onDeleteClick = this.props.onDeleteClick;
  121. var itemList = this.props.list.map(function(item) {
  122. return (
  123. <Item handleDeleteClick={onDeleteClick} priority={item.priority} title={item.title} id={item.id} key={item.id} deadline={item.deadline}>
  124. {item.description}
  125. </Item>
  126. );
  127. });
  128. return (
  129. <div className="list">
  130. {itemList}
  131. </div>
  132. );
  133. }
  134. });
  135. var App = React.createClass({
  136. getInitialState: function() {
  137. return {list: [], result: 0};
  138. },
  139. updateList: function() {
  140. $.ajax({
  141. url: this.props.url,
  142. dataType: 'json',
  143. type: 'GET',
  144. success: function(data) {
  145. this.setState({list: data.list, result: data.result});
  146. }.bind(this),
  147. error: function(xhr, status, err) {
  148. console.error(this.props.url, status, err.toString());
  149. }.bind(this)
  150. });
  151. },
  152. componentDidMount: function() {
  153. this.updateList();
  154. },
  155. handleCommentSubmit: function(comment) {
  156. $.ajax({
  157. url: this.props.url,
  158. dataType: 'json',
  159. cache: false,
  160. type: 'POST',
  161. data: comment,
  162. success: function(data) {
  163. if (data.result != 0) {
  164. console.log("Error in API: " + data.result);
  165. }
  166. if (data.hasOwnProperty("message")) {
  167. console.log("API message: " + data.message);
  168. }
  169. this.setState({list: data.list, result: data.result});
  170. }.bind(this),
  171. error: function(xhr, status, err) {
  172. console.error(this.props.url, status, err.toString());
  173. this.setState({result: 1});
  174. }.bind(this)
  175. });
  176. },
  177. handleDelete: function(id) {
  178. $.ajax({
  179. url: this.props.url,
  180. dataType: 'json',
  181. cache: false,
  182. type: 'POST',
  183. data: {a: 'rm', id: id},
  184. success: function(data) {
  185. this.setState({list: data.list, result: data.result});
  186. }.bind(this),
  187. error: function(xhr, status, err) {
  188. console.error(this.props.url, status, err.toString());
  189. }.bind(this)
  190. });
  191. },
  192. render: function() {
  193. return (
  194. <main>
  195. <h1>Tankernn TODO list</h1>
  196. <TodoForm onCommentSubmit={this.handleCommentSubmit} />
  197. <TodoList onDeleteClick={this.handleDelete} list={this.state.list} />
  198. </main>
  199. );
  200. }
  201. });
  202. ReactDOM.render(<App url={API_URL} />, document.getElementById('content'));