edit.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /**
  2. * @author oldj
  3. * @blog https://oldj.net
  4. */
  5. 'use strict'
  6. import React from 'react'
  7. import MyFrame from './frame'
  8. import classnames from 'classnames'
  9. import Group from './group'
  10. import Agent from '../Agent'
  11. import makeId from '../../app/libs/make-id'
  12. import './edit.less'
  13. export default class EditPrompt extends React.Component {
  14. constructor (props) {
  15. super(props)
  16. this.state = {
  17. show: false,
  18. is_add: true,
  19. where: 'local',
  20. title: '',
  21. url: '',
  22. last_refresh: null,
  23. refresh_interval: 0,
  24. is_loading: false,
  25. include: []
  26. }
  27. this.current_hosts = null
  28. }
  29. tryToFocus () {
  30. let el = this.refs.body && this.refs.body.querySelector('input[type=text]')
  31. el && el.focus()
  32. }
  33. clear () {
  34. this.setState({
  35. where: 'local',
  36. title: '',
  37. url: '',
  38. last_refresh: null,
  39. refresh_interval: 0
  40. })
  41. }
  42. componentDidMount () {
  43. Agent.on('add_hosts', () => {
  44. this.setState({
  45. show: true,
  46. is_add: true
  47. })
  48. setTimeout(() => {
  49. this.tryToFocus()
  50. }, 100)
  51. })
  52. Agent.on('edit_hosts', (hosts) => {
  53. this.current_hosts = hosts
  54. let include = hosts.include || []
  55. include = Array.from(new Set(include))
  56. this.setState({
  57. id: hosts.id,
  58. show: true,
  59. is_add: false,
  60. where: hosts.where || 'local',
  61. title: hosts.title || '',
  62. url: hosts.url || '',
  63. last_refresh: hosts.last_refresh || null,
  64. refresh_interval: hosts.refresh_interval || 0,
  65. include
  66. })
  67. setTimeout(() => {
  68. this.tryToFocus()
  69. }, 100)
  70. })
  71. Agent.on('list_updated', list => {
  72. let hosts = list.find(i => i.id === this.state.id)
  73. if (hosts) {
  74. this.current_hosts = hosts
  75. this.setState({last_refresh: hosts.last_refresh})
  76. setTimeout(() => this.setState({is_loading: false}), 500)
  77. }
  78. })
  79. }
  80. onOK () {
  81. this.setState({
  82. title: (this.state.title || '').replace(/^\s+|\s+$/g, ''),
  83. url: (this.state.url || '').replace(/^\s+|\s+$/g, '')
  84. })
  85. if (this.state.title === '') {
  86. this.refs.title.focus()
  87. return false
  88. }
  89. if (this.state.where === 'remote' && this.state.url === '') {
  90. this.refs.url.focus()
  91. return false
  92. }
  93. let new_id = makeId()
  94. let data = Object.assign({}, this.current_hosts, this.state,
  95. this.state.is_add ? {
  96. id: new_id,
  97. content: `# ${this.state.title}`,
  98. on: false
  99. } : {})
  100. if (!data.id) data.id = new_id
  101. if (this.state.is_add) {
  102. this.props.justAdd(new_id)
  103. }
  104. delete data['is_add']
  105. Agent.emit('update_hosts', data)
  106. this.setState({
  107. show: false
  108. })
  109. this.clear()
  110. }
  111. onCancel () {
  112. this.setState({
  113. show: false
  114. })
  115. this.clear()
  116. }
  117. confirmDel () {
  118. let {lang} = this.props
  119. if (!confirm(lang.confirm_del)) return
  120. Agent.emit('del_hosts', this.current_hosts)
  121. this.setState({
  122. show: false
  123. })
  124. this.clear()
  125. }
  126. updateInclude (include) {
  127. this.setState({include})
  128. }
  129. getRefreshOptions () {
  130. let {lang} = this.props
  131. let k = [
  132. [0, `${lang.never}`],
  133. [1, `1 ${lang.hour}`],
  134. [24, `24 ${lang.hours}`],
  135. [168, `7 ${lang.days}`]
  136. ]
  137. if (Agent.IS_DEV) {
  138. k.splice(1, 0, [0.002778, `10s (for DEV)`]) // dev test only
  139. }
  140. return k.map(([v, n], idx) => {
  141. return (
  142. <option value={v} key={idx}>{n}</option>
  143. )
  144. })
  145. }
  146. getEditOperations () {
  147. if (this.state.is_add) return null
  148. let {lang} = this.props
  149. return (
  150. <div>
  151. <div className="ln">
  152. <a href="#" className="del"
  153. onClick={this.confirmDel.bind(this)}
  154. >
  155. <i className="iconfont icon-delete"/>
  156. <span>{lang.del_hosts}</span>
  157. </a>
  158. </div>
  159. </div>
  160. )
  161. }
  162. refresh () {
  163. if (this.state.is_loading) return
  164. Agent.emit('check_hosts_refresh', this.current_hosts)
  165. this.setState({
  166. is_loading: true
  167. })
  168. }
  169. renderGroup () {
  170. if (this.state.where !== 'group') return null
  171. return <Group
  172. list={this.props.list}
  173. include={this.state.include}
  174. updateInclude={this.updateInclude.bind(this)}
  175. />
  176. }
  177. renderRemoteInputs () {
  178. if (this.state.where !== 'remote') return null
  179. let {lang} = this.props
  180. return (
  181. <div className="remote-ipts">
  182. <div className="ln">
  183. <div className="title">{lang.url}</div>
  184. <div className="cnt">
  185. <input
  186. type="text"
  187. ref="url"
  188. value={this.state.url}
  189. placeholder="http://"
  190. onChange={(e) => this.setState({url: e.target.value})}
  191. onKeyDown={(e) => (e.keyCode === 13 && this.onOK()) ||
  192. (e.keyCode === 27 && this.onCancel())}
  193. />
  194. </div>
  195. </div>
  196. <div className="ln">
  197. <div className="title">{lang.auto_refresh}</div>
  198. <div className="cnt">
  199. <select
  200. value={this.state.refresh_interval}
  201. onChange={(e) => this.setState(
  202. {refresh_interval: parseFloat(e.target.value) || 0})}
  203. >
  204. {this.getRefreshOptions()}
  205. </select>
  206. <i
  207. className={classnames({
  208. iconfont: 1,
  209. 'icon-refresh': 1,
  210. 'invisible': !this.current_hosts ||
  211. this.state.url !== this.current_hosts.url,
  212. 'loading': this.state.is_loading
  213. })}
  214. title={lang.refresh}
  215. onClick={() => this.refresh()}
  216. />
  217. <span className="last-refresh">
  218. {lang.last_refresh}
  219. {this.state.last_refresh || 'N/A'}
  220. </span>
  221. </div>
  222. </div>
  223. </div>
  224. )
  225. }
  226. body () {
  227. let {lang} = this.props
  228. return (
  229. <div ref="body">
  230. <div className="ln">
  231. <input id="ipt-local" type="radio" name="where" value="local"
  232. checked={this.state.where === 'local'}
  233. onChange={(e) => this.setState({where: e.target.value})}
  234. />
  235. <label htmlFor="ipt-local">{lang.where_local}</label>
  236. <input id="ipt-remote" type="radio" name="where" value="remote"
  237. checked={this.state.where === 'remote'}
  238. onChange={(e) => this.setState({where: e.target.value})}
  239. />
  240. <label htmlFor="ipt-remote">{lang.where_remote}</label>
  241. <input id="ipt-group" type="radio" name="where" value="group"
  242. checked={this.state.where === 'group'}
  243. onChange={(e) => this.setState({where: e.target.value})}
  244. />
  245. <label htmlFor="ipt-group">{lang.where_group}</label>
  246. </div>
  247. <div className="ln">
  248. <div className="title">{lang.hosts_title}</div>
  249. <div className="cnt">
  250. <input
  251. type="text"
  252. ref="title"
  253. name="text"
  254. value={this.state.title}
  255. onChange={(e) => this.setState({title: e.target.value})}
  256. onKeyDown={(e) => (e.keyCode === 13 && this.onOK() ||
  257. e.keyCode === 27 && this.onCancel())}
  258. />
  259. </div>
  260. </div>
  261. {this.renderRemoteInputs()}
  262. {this.renderGroup()}
  263. {this.getEditOperations()}
  264. </div>
  265. )
  266. }
  267. render () {
  268. let {lang} = this.props
  269. return (
  270. <MyFrame
  271. show={this.state.show}
  272. head={lang[this.state.is_add ? 'add_hosts' : 'edit_hosts']}
  273. body={this.body()}
  274. onOK={() => this.onOK()}
  275. onCancel={() => this.onCancel()}
  276. lang={this.props.lang}
  277. />
  278. )
  279. }
  280. }