index.tsx 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*
  2. * <<
  3. * Davinci
  4. * ==
  5. * Copyright (C) 2016 - 2017 EDP
  6. * ==
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. * >>
  19. */
  20. import React, { PureComponent, GetDerivedStateFromProps } from 'react'
  21. import classnames from 'classnames'
  22. import { ListFormLayout, List, ListItem } from 'app/components/ListFormLayout'
  23. import ReferenceForm from './ReferenceForm'
  24. import { Modal, Button, message } from 'antd'
  25. import FormType from 'antd/lib/form/Form'
  26. import { IDataParamSource } from '../Dropbox'
  27. import { IReference, IReferenceLine } from './types'
  28. import { ReferenceType } from './constants'
  29. import { uuid } from 'app/utils/util'
  30. import { getDefaultReferenceLineData } from './util'
  31. import styles from './Reference.less'
  32. interface IReferenceProps {
  33. references: IReference[]
  34. metrics: IDataParamSource[]
  35. visible: boolean
  36. onSave: (mergedReferences: IReference[]) => void
  37. onCancel: () => void
  38. }
  39. interface IReferenceStates {
  40. prevReferences: IReference[]
  41. editingReferences: IReference[]
  42. selected: IReference
  43. }
  44. class Reference extends PureComponent<IReferenceProps, IReferenceStates> {
  45. public state: IReferenceStates = {
  46. prevReferences: [],
  47. editingReferences: [],
  48. selected: null
  49. }
  50. private referenceForm: FormType
  51. private refHandles = {
  52. referenceForm: (ref) => {
  53. this.referenceForm = ref
  54. }
  55. }
  56. public static getDerivedStateFromProps: GetDerivedStateFromProps<
  57. IReferenceProps,
  58. IReferenceStates
  59. > = (props, state) => {
  60. const { references } = props
  61. if (references && references !== state.prevReferences) {
  62. let editingReferences = []
  63. let selected = null
  64. try {
  65. editingReferences = JSON.parse(JSON.stringify(references))
  66. if (editingReferences.length) {
  67. selected = editingReferences[0]
  68. }
  69. } catch (error) {
  70. message.error('参考线配置解析失败')
  71. throw error
  72. }
  73. return {
  74. prevReferences: references,
  75. editingReferences,
  76. selected
  77. }
  78. }
  79. return null
  80. }
  81. private getDefaultReference = (): IReferenceLine => {
  82. return {
  83. key: uuid(8, 16),
  84. name: '新建参考线',
  85. type: ReferenceType.Line,
  86. ...getDefaultReferenceLineData()
  87. }
  88. }
  89. private addReference = () => {
  90. const { selected } = this.state
  91. const reference = this.getDefaultReference()
  92. if (selected) {
  93. this.getFormValues((mergedReferences) => {
  94. this.setState({
  95. editingReferences: [...mergedReferences, reference],
  96. selected: reference
  97. })
  98. })
  99. } else {
  100. this.setState({
  101. editingReferences: [reference],
  102. selected: reference
  103. })
  104. }
  105. }
  106. private selectReference = (key: string) => {
  107. this.getFormValues((mergedReferences) => {
  108. this.setState({
  109. editingReferences: mergedReferences,
  110. selected: mergedReferences.find((ref) => ref.key === key)
  111. })
  112. })
  113. }
  114. private changeReferenceName = (key: string, name: string) => {
  115. this.setState({
  116. editingReferences: this.state.editingReferences.map((ref) => {
  117. if (ref.key === key) {
  118. ref.name = name
  119. }
  120. return ref
  121. })
  122. })
  123. }
  124. private deleteReference = (key: string) => {
  125. const { editingReferences, selected } = this.state
  126. let reselected: IReference = null
  127. if (editingReferences.length > 1) {
  128. if (key === selected.key) {
  129. const delIndex = editingReferences.findIndex((ref) => ref.key === key)
  130. reselected =
  131. delIndex === editingReferences.length - 1
  132. ? editingReferences[delIndex - 1]
  133. : editingReferences[delIndex + 1]
  134. } else {
  135. reselected = selected
  136. }
  137. }
  138. this.setState({
  139. editingReferences: editingReferences.filter((ref) => ref.key !== key),
  140. selected: reselected
  141. })
  142. }
  143. private getFormValues = (
  144. resolve: (mergedReferences: IReference[]) => void
  145. ) => {
  146. this.referenceForm.props.form.validateFieldsAndScroll((err, values) => {
  147. if (err) {
  148. return
  149. }
  150. const { editingReferences, selected } = this.state
  151. const mergedReferences = editingReferences.map((ref) =>
  152. ref.key === selected.key
  153. ? {
  154. ...selected,
  155. ...values
  156. }
  157. : ref
  158. )
  159. resolve(mergedReferences)
  160. })
  161. }
  162. private save = () => {
  163. const { onSave } = this.props
  164. const { editingReferences } = this.state
  165. if (editingReferences.length) {
  166. this.getFormValues((mergedReferences) => {
  167. onSave(mergedReferences)
  168. })
  169. } else {
  170. onSave([])
  171. }
  172. }
  173. private reset = () => {
  174. this.setState({
  175. prevReferences: [],
  176. editingReferences: [],
  177. selected: null
  178. })
  179. }
  180. public render() {
  181. const { visible, metrics, onCancel } = this.props
  182. const { editingReferences, selected } = this.state
  183. const listItems = editingReferences.map(({ key, name }) => {
  184. const listItemClass = classnames({
  185. [styles.listItem]: true,
  186. [styles.selected]: selected.key === key
  187. })
  188. return (
  189. <ListItem
  190. key={key}
  191. id={key}
  192. name={name}
  193. className={listItemClass}
  194. onClick={this.selectReference}
  195. onChange={this.changeReferenceName}
  196. onDelete={this.deleteReference}
  197. />
  198. )
  199. })
  200. return (
  201. <Modal
  202. wrapClassName="ant-modal-large ant-modal-center"
  203. title="参考线配置"
  204. visible={visible}
  205. maskClosable={false}
  206. onOk={this.save}
  207. okText="保存"
  208. okButtonProps={{size: 'large'}}
  209. onCancel={onCancel}
  210. cancelButtonProps={{size: 'large'}}
  211. afterClose={this.reset}
  212. >
  213. <ListFormLayout
  214. type="horizontal"
  215. initialSize={200}
  216. minSize={200}
  217. maxSize={480}
  218. className={styles.configPanel}
  219. >
  220. <List
  221. title="参考线列表"
  222. className={styles.list}
  223. onAddItem={this.addReference}
  224. >
  225. {listItems}
  226. </List>
  227. {selected && (
  228. <ReferenceForm
  229. reference={selected}
  230. metrics={metrics}
  231. wrappedComponentRef={this.refHandles.referenceForm}
  232. />
  233. )}
  234. </ListFormLayout>
  235. </Modal>
  236. )
  237. }
  238. }
  239. export default Reference