index.jsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. Copyright (C) 2017 Cloudbase Solutions SRL
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. // @flow
  15. import React from 'react'
  16. import styled from 'styled-components'
  17. import { observer } from 'mobx-react'
  18. import Switch from '../../atoms/Switch'
  19. import TextInput from '../../atoms/TextInput'
  20. import Dropdown from '../../molecules/Dropdown'
  21. import InfoIcon from '../../atoms/InfoIcon'
  22. import PropertiesTable from '../../molecules/PropertiesTable'
  23. import StyleProps from '../../styleUtils/StyleProps'
  24. import LabelDictionary from '../../../utils/LabelDictionary'
  25. const getDirection = props => {
  26. if (props.type === 'strict-boolean' || props.type === 'boolean') {
  27. return 'row'
  28. }
  29. return 'column'
  30. }
  31. const Wrapper = styled.div`
  32. display: flex;
  33. flex-direction: ${props => getDirection(props)};
  34. ${props => getDirection(props) === 'row' ? '' : 'justify-content: center;'}
  35. `
  36. const Label = styled.div`
  37. font-weight: ${StyleProps.fontWeights.medium};
  38. ${props => getDirection(props) === 'column' ? 'margin-bottom: 8px;' : ''}
  39. `
  40. const LabelText = styled.span`
  41. margin-right: 24px;
  42. `
  43. type PropertyType = { name: string, type: string }
  44. type Props = {
  45. type: 'replica' | 'migration',
  46. name: string,
  47. value: any,
  48. onChange: (value: any) => void,
  49. valueCallback: (prop: PropertyType, value: any) => void,
  50. className?: string,
  51. properties: PropertyType[],
  52. enum: string[],
  53. required: boolean,
  54. }
  55. @observer
  56. class WizardOptionsField extends React.Component<Props> {
  57. renderSwitch(propss: { triState: boolean }) {
  58. return (
  59. <Switch
  60. width="112px"
  61. justifyContent="flex-end"
  62. triState={propss.triState}
  63. checked={this.props.value}
  64. onChange={checked => { this.props.onChange(checked) }}
  65. style={{ marginTop: '-8px' }}
  66. leftLabel
  67. />
  68. )
  69. }
  70. renderTextInput() {
  71. return (
  72. <TextInput
  73. width="320px"
  74. required={this.props.required}
  75. value={this.props.value}
  76. onChange={e => { this.props.onChange(e.target.value) }}
  77. placeholder={LabelDictionary.get(this.props.name)}
  78. />
  79. )
  80. }
  81. renderObjectTable() {
  82. if (!this.props.properties) {
  83. return null
  84. }
  85. return (
  86. <PropertiesTable
  87. properties={this.props.properties}
  88. valueCallback={this.props.valueCallback}
  89. onChange={this.props.onChange}
  90. />
  91. )
  92. }
  93. renderEnumDropdown() {
  94. let items = this.props.enum.map(e => {
  95. return {
  96. label: typeof e === 'string' ? LabelDictionary.get(e) : e.name,
  97. value: typeof e === 'string' ? e : e.id,
  98. }
  99. })
  100. items = [
  101. { label: 'Choose a value', value: null },
  102. ...items,
  103. ]
  104. let selectedItem = items.find(i => i.value === this.props.value)
  105. return (
  106. <Dropdown
  107. width={320}
  108. data-test-id={`dropdown-${this.props.name}`}
  109. noSelectionMessage="Choose a value"
  110. selectedItem={selectedItem}
  111. items={items}
  112. onChange={item => this.props.onChange(item.value)}
  113. />
  114. )
  115. }
  116. renderField() {
  117. let field = null
  118. switch (this.props.type) {
  119. case 'strict-boolean':
  120. field = this.renderSwitch({ triState: false })
  121. break
  122. case 'boolean':
  123. field = this.renderSwitch({ triState: true })
  124. break
  125. case 'string':
  126. if (this.props.enum) {
  127. field = this.renderEnumDropdown()
  128. } else {
  129. field = this.renderTextInput()
  130. }
  131. break
  132. case 'object':
  133. field = this.renderObjectTable()
  134. break
  135. default:
  136. }
  137. return field
  138. }
  139. renderLabel() {
  140. let description = LabelDictionary.getDescription(this.props.name)
  141. let infoIcon = null
  142. if (description) {
  143. infoIcon = <InfoIcon text={description} marginLeft={-20} />
  144. }
  145. return (
  146. <Label>
  147. <LabelText>{LabelDictionary.get(this.props.name)}</LabelText>
  148. {infoIcon}
  149. </Label>
  150. )
  151. }
  152. render() {
  153. let field = this.renderField()
  154. if (!field) {
  155. return null
  156. }
  157. return (
  158. <Wrapper type={this.props.type} className={this.props.className}>
  159. {this.renderLabel()}
  160. {field}
  161. </Wrapper>
  162. )
  163. }
  164. }
  165. export default WizardOptionsField