Websocket clock server web interface written in ReactJS/TypeScript
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Alarm.js 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import * as React from 'react';
  2. import util from './utils';
  3. import Notif from './AlarmNotif';
  4. import './Alarm.css';
  5. /* An alarm component : represent an alarm in the Alarms table */
  6. class Alarm extends React.Component {
  7. constructor(props:{ name:string, // alarm name
  8. time:string, // alarm ring time
  9. on:bool, // on flag
  10. ringing:bool, // ringing flag
  11. snooze:bool, // snooze flag
  12. ws:WebSocket, // Clock.state.ws reference
  13. upd:function, // Clock.alrmUpdate() reference
  14. }) {
  15. super(props)
  16. this.time_input = null;
  17. this.state = { new_time:props.time, // time input value
  18. prev_new_time:props.time, // previous input value
  19. set_time:false, // if true show the time input
  20. }
  21. this.handleChangeSetTime = this.handleChangeSetTime.bind(this)
  22. this.set_time = this.set_time.bind(this)
  23. this.on = this.on.bind(this)
  24. this.off = this.off.bind(this)
  25. this.snooze = this.snooze.bind(this)
  26. this.Delete = this.Delete.bind(this)
  27. }
  28. render() {
  29. let alrm_state_btn = <></>;
  30. let alrm_class = 'Alrm';
  31. if(this.props.on) {
  32. alrm_state_btn = (
  33. <button
  34. onClick={this.off}
  35. >
  36. <abbr
  37. title="Turn OFF"
  38. >off</abbr>
  39. </button>
  40. );
  41. if(this.props.ringing) {
  42. alrm_state_btn = <>{alrm_state_btn}<button onClick={this.snooze}>snooze</button></>
  43. alrm_class += ' AlrmRinging';
  44. } else {
  45. alrm_class += ' AlrmOn';
  46. }
  47. } else {
  48. alrm_class += ' AlrmOff';
  49. alrm_state_btn = (
  50. <>
  51. <button
  52. onClick={this.on}
  53. >
  54. <abbr
  55. title="Turn ON"
  56. >on</abbr>
  57. </button>
  58. </>
  59. );
  60. }
  61. let snooze = this.props.snooze?<span className="snooze">Snooze</span>:<></>;
  62. let set_lbl = <abbr title="Set ringtime">Set</abbr>;
  63. let set_id = 'ringtime'+this.props.name;
  64. let time_disp = this.state.set_time ? (
  65. <form
  66. onSubmit={this.handleSubmitSetTime}
  67. className="AlrmSetTimeForm"
  68. >
  69. <input
  70. id={set_id}
  71. onChange={this.handleChangeSetTime}
  72. value={this.state.new_time}
  73. style={{width:"5em"}}
  74. ref={(input => {this.time_input = input;})}
  75. />
  76. <button
  77. onClick={this.set_time}
  78. >{set_lbl}</button>
  79. </form>
  80. ):(
  81. <span>
  82. {this.props.time}&nbsp;
  83. <button
  84. onClick={this.set_time}
  85. >{set_lbl}</button>
  86. </span>
  87. );
  88. return (
  89. <tr className={alrm_class}>
  90. <td className="AlrmName">{this.props.name}</td>
  91. <td>
  92. {time_disp}
  93. </td>
  94. <td className="AlrmStateBtn">
  95. {alrm_state_btn}
  96. {snooze}
  97. </td>
  98. <td>
  99. <button
  100. className="AlrmDeleteBtn"
  101. onClick={this.Delete}
  102. >
  103. <abbr title="Delete alarm">X</abbr>
  104. </button>
  105. </td>
  106. </tr>
  107. );
  108. }
  109. componentDidUpdate() {
  110. if(this.time_input !== null) {
  111. // Force focus on the edited alarm on each update
  112. this.time_input.focus()
  113. }
  114. }
  115. /* Time input form submit handler */
  116. set_time (evt) {
  117. evt.preventDefault()
  118. if(this.state.set_time) {
  119. this.props.ws.send('alarm set '+util.escape_arg(this.props.name)+' '+this.state.new_time.replace(/:/g, ' '))
  120. this.props.upd()
  121. }
  122. this.setState({new_time:this.props.time,
  123. set_time: !this.state.set_time})
  124. }
  125. /* Time input change event handler */
  126. handleChangeSetTime (evt) {
  127. let val = evt.target.value
  128. let prev = evt.target.value
  129. let prevdel = this.state.prev_new_time.length > val.length
  130. if(val.length > 0) {
  131. if(!val.match(/.*[0-9:]$/)) {
  132. val = val.substring(0, val.length-1)
  133. }
  134. if(!prevdel && (
  135. val.match(/^[0-9]{2}$/) ||
  136. val.match(/^[0-9]{1,2}:[0-9]{2}$/)
  137. )) {
  138. val += ':'
  139. prev = val
  140. }
  141. if(val.length > 8 || val.match(/[^0-9:]/) || val.match(/^.*:.*:.*:.*$/)) {
  142. prev = ''
  143. val = ''
  144. }
  145. }
  146. this.setState({new_time:val, prev_new_time:prev})
  147. }
  148. /* on button click handler */
  149. on (evt) {
  150. Notif.requestPermission()
  151. this.props.ws.send('alarm on '+util.escape_arg(this.props.name))
  152. this.props.upd()
  153. }
  154. /* off button click handler */
  155. off (evt) {
  156. this.props.ws.send('alarm off '+util.escape_arg(this.props.name))
  157. this.props.upd()
  158. }
  159. /* snooze button click handler */
  160. snooze (evt) {
  161. this.props.ws.send('alarm snooze '+util.escape_arg(this.props.name)+' 1')
  162. this.props.upd()
  163. }
  164. /* delete button click handler */
  165. Delete (evt) {
  166. var todel = true
  167. if(this.props.ringing || this.props.snooze || this.props.on) {
  168. todel = confirm('Do your really want to delete "'+this.props.name+'" ?')
  169. }
  170. if(todel) {
  171. this.props.ws.send('alarm del '+util.escape_arg(this.props.name))
  172. this.props.upd()
  173. }
  174. }
  175. }
  176. export default Alarm;