ConfigModal.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. import React, { PureComponent } from 'react';
  2. import { PageHeader, Button, Descriptions, Modal, Card, Icon, Row, Col, Form, Popconfirm, Input, Space, Divider } from 'antd';
  3. import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
  4. import styles from './ConfigModal.less'
  5. export default class ConfigModal extends PureComponent {
  6. formRef = React.createRef();
  7. state = {
  8. }
  9. setFormValues(config) {
  10. if (config) {
  11. this.formRef.current.setFieldsValue({
  12. ...(config.config || {}),
  13. envsArr: Object.keys(config.config.envs || {}).map(key => ({ key, value: config.config.envs[key] })),
  14. mountsArr: Object.keys(config.config.mounts || {}).map(key => ({ key, value: config.config.mounts[key] })),
  15. ingressAnnotaionsArr: Object.keys(config.config.ingressAnnotaions || {}).map(key => ({ key, value: config.config.ingressAnnotaions[key] })),
  16. hostPathArr: Object.keys(config.config.hostPath || {}).map(key => ({ key, value: config.config.hostPath[key] })),
  17. });
  18. }
  19. }
  20. componentDidMount() {
  21. this.setFormValues(this.props.config);
  22. }
  23. componentWillReceiveProps(props) {
  24. if (props.config != this.props.config)
  25. this.setFormValues(props.config);
  26. }
  27. onOk() {
  28. this.formRef.current.validateFields().then(values => {
  29. this.props.onOk({
  30. ...this.props.config,
  31. config: {
  32. ...values,
  33. envs: (values.envsArr || []).reduce((obj, item) => {
  34. obj[item.key] = item.value;
  35. return obj;
  36. }, {}),
  37. mounts: (values.mountsArr || []).reduce((obj, item) => {
  38. obj[item.key] = item.value;
  39. return obj;
  40. }, {}),
  41. hostPath: (values.hostPathArr || []).reduce((obj, item) => {
  42. obj[item.key] = item.value;
  43. return obj;
  44. }, {}),
  45. ingressAnnotaions: (values.ingressAnnotaionsArr || []).reduce((obj, item) => {
  46. obj[item.key] = item.value;
  47. return obj;
  48. }, {}),
  49. }
  50. })
  51. });
  52. }
  53. render() {
  54. return (
  55. <Modal
  56. visible={this.props.visible}
  57. forceRender
  58. onCancel={() => this.props.onCancel()}
  59. title={"更新配置"}
  60. okText="确认"
  61. cancelText="取消"
  62. onOk={this.onOk.bind(this)}
  63. className={styles.modal}
  64. width="80%"
  65. >
  66. <Form
  67. ref={this.formRef}
  68. labelCol={{ span: 4 }}
  69. wrapperCol={{ span: 20 }}
  70. labelAlign="right"
  71. >
  72. <Form.Item
  73. name="hostPrefix"
  74. label="域名前缀"
  75. tooltip="有域名前缀时会根据端口对服务进行暴露,生成域名规则为{域名前缀}-{端口}.{主域名}"
  76. >
  77. <Input placeholder="域名前缀"></Input>
  78. </Form.Item >
  79. <Form.Item
  80. name="servicePort"
  81. label="服务端口"
  82. tooltip="服务端口,多个用英文逗号隔开"
  83. >
  84. <Input placeholder='服务端口,多个用英文逗号隔开'></Input>
  85. </Form.Item >
  86. <Form.Item
  87. name="replicas"
  88. label="实例数"
  89. tooltip="服务部署的实例数目,即pod数量,默认为1"
  90. >
  91. <Input placeholder="实例数"></Input>
  92. </Form.Item >
  93. <Form.Item
  94. name="runArgs"
  95. label="运行参数"
  96. tooltip="服务运行参数"
  97. >
  98. <Input placeholder="运行参数"></Input>
  99. </Form.Item>
  100. <Form.Item
  101. name="runCommands"
  102. label="运行命令"
  103. tooltip="服务运行命令"
  104. >
  105. <Input placeholder="运行命令"></Input>
  106. </Form.Item >
  107. <Divider plain>环境变量配置</Divider>
  108. <div className={styles.list}>
  109. <Form.List name="envsArr" label="key-value">
  110. {(fields, {add, remove}) => (
  111. <>
  112. {fields.map(field => (
  113. <div key={`env-${field.fieldKey}`} field={field} className={styles.field}>
  114. <Form.Item
  115. {...field}
  116. key={`env-key-${field.fieldKey}`}
  117. label="key"
  118. name={[field.name, 'key']}
  119. fieldKey={[field.fieldKey, 'key']}
  120. rules={[{ required: true, message: 'key不能为空' }]}
  121. >
  122. <Input placeholder="环境变量key" />
  123. </Form.Item>
  124. <Form.Item
  125. {...field}
  126. key={`env-value-${field.fieldKey}`}
  127. label="value"
  128. name={[field.name, 'value']}
  129. fieldKey={[field.fieldKey, 'value']}
  130. rules={[{ required: true, message: 'value不能为空' }]}
  131. >
  132. <Input placeholder="环境变量value" />
  133. </Form.Item>
  134. <MinusCircleOutlined style={{fontSize: 18, marginLeft: 10}} onClick={() => remove(field.name)} />
  135. </div>
  136. ))}
  137. <Form.Item className={styles.addBtn}>
  138. <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
  139. 添加
  140. </Button>
  141. </Form.Item>
  142. </>
  143. )}
  144. </Form.List>
  145. </div>
  146. <Divider plain>挂载文件配置</Divider>
  147. <div className={styles.list}>
  148. <Form.List name="mountsArr">
  149. {(fields, {add, remove}) => (
  150. <>
  151. {fields.map(field => (
  152. <div key={`mount-${field.fieldKey}`} className={styles.field}>
  153. <Form.Item
  154. {...field}
  155. key={`mount-key-${field.fieldKey}`}
  156. label="文件路径"
  157. name={[field.name, 'key']}
  158. fieldKey={[field.fieldKey, 'key']}
  159. rules={[{ required: true, message: '文件路径不能为空' }]}
  160. >
  161. <Input placeholder="文件路径" />
  162. </Form.Item>
  163. <Form.Item
  164. {...field}
  165. label="文件内容"
  166. key={`mount-value-${field.fieldKey}`}
  167. style={{alignItems: 'center'}}
  168. name={[field.name, 'value']}
  169. fieldKey={[field.fieldKey, 'value']}
  170. >
  171. <Input.TextArea placeholder="文件内容" />
  172. </Form.Item>
  173. <MinusCircleOutlined style={{fontSize: 18, marginLeft: 10}} onClick={() => remove(field.name)} />
  174. </div>
  175. ))}
  176. <Form.Item className={styles.addBtn} >
  177. <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
  178. 添加
  179. </Button>
  180. </Form.Item>
  181. </>
  182. )}
  183. </Form.List>
  184. </div>
  185. <Divider plain>节点文件挂载</Divider>
  186. <div className={styles.list}>
  187. <Form.List name="hostPathArr">
  188. {(fields, {add, remove}) => (
  189. <>
  190. {fields.map(field => (
  191. <div key={`hostPath-${field.fieldKey}`} className={styles.field}>
  192. <Form.Item
  193. {...field}
  194. key={`hostPath-key-${field.fieldKey}`}
  195. name={[field.name, 'key']}
  196. label="节点路径"
  197. fieldKey={[field.fieldKey, 'key']}
  198. rules={[{ required: true, message: '节点文件路径不能为空' }]}
  199. >
  200. <Input placeholder="节点文件路径" />
  201. </Form.Item>
  202. <Form.Item
  203. {...field}
  204. key={`hostPath-value-${field.fieldKey}`}
  205. name={[field.name, 'value']}
  206. label="挂载路径"
  207. fieldKey={[field.fieldKey, 'value']}
  208. rules={[{ required: true, message: '挂载文件路径不能为空' }]}
  209. >
  210. <Input placeholder="挂载文件路径" />
  211. </Form.Item>
  212. <MinusCircleOutlined style={{fontSize: 18, marginLeft: 10}} onClick={() => remove(field.name)} />
  213. </div>
  214. ))}
  215. <Form.Item className={styles.addBtn} >
  216. <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
  217. 添加
  218. </Button>
  219. </Form.Item>
  220. </>
  221. )}
  222. </Form.List>
  223. </div>
  224. <Divider plain>ingress控制器annotations</Divider>
  225. <div className={styles.list}>
  226. <Form.List name="ingressAnnotationsArr">
  227. {(fields, {add, remove}) => (
  228. <>
  229. {fields.map(field => (
  230. <div key={`ingress-${field.fieldKey}`} className={styles.field}>
  231. <Form.Item
  232. {...field}
  233. label="key"
  234. key={`ingress-key-${field.fieldKey}`}
  235. name={[field.name, 'key']}
  236. fieldKey={[field.fieldKey, 'key']}
  237. rules={[{ required: true, message: 'annotationKey不能为空' }]}
  238. >
  239. <Input placeholder="annotationKey" />
  240. </Form.Item>
  241. <Form.Item
  242. {...field}
  243. key={`ingress-value-${field.fieldKey}`}
  244. name={[field.name, 'value']}
  245. label="value"
  246. fieldKey={[field.fieldKey, 'value']}
  247. rules={[{ required: true, message: 'annotationValue不能为空' }]}
  248. >
  249. <Input placeholder="annotationValue" />
  250. </Form.Item>
  251. <MinusCircleOutlined style={{fontSize: 18, marginLeft: 10}} onClick={() => remove(field.name)} />
  252. </div>
  253. ))}
  254. <Form.Item className={styles.addBtn} >
  255. <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
  256. 添加
  257. </Button>
  258. </Form.Item>
  259. </>
  260. )}
  261. </Form.List>
  262. </div>
  263. </Form>
  264. </Modal>
  265. )
  266. }
  267. }