ContentPlugin.jsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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 ToggleButtonBar from '../../../components/atoms/ToggleButtonBar'
  18. import type { Field } from '../../../types/Field'
  19. import { Wrapper, Fields, FieldStyled, Row } from '../default/ContentPlugin'
  20. const ToggleButtonBarStyled = styled(ToggleButtonBar)`
  21. margin-top: 16px;
  22. `
  23. type Props = {
  24. connectionInfoSchema: Field[],
  25. validation: { valid: boolean, validation: { message: string } },
  26. invalidFields: string[],
  27. getFieldValue: (field: ?Field) => any,
  28. handleFieldChange: (field: Field, value: any) => void,
  29. disabled: boolean,
  30. cancelButtonText: string,
  31. validating: boolean,
  32. onRef: (contentPlugin: any) => void,
  33. onResizeUpdate: (scrollOfset: number) => void,
  34. scrollableRef: (ref: HTMLElement) => void,
  35. }
  36. type State = {
  37. useAdvancedOptions: boolean,
  38. }
  39. class ContentPlugin extends React.Component<Props, State> {
  40. constructor() {
  41. super()
  42. this.state = {
  43. useAdvancedOptions: false,
  44. }
  45. }
  46. componentDidMount() {
  47. this.props.onRef(this)
  48. }
  49. componentDidUpdate(prevProps: Props, prevState: State) {
  50. if (prevState.useAdvancedOptions !== this.state.useAdvancedOptions) {
  51. this.props.onResizeUpdate(0)
  52. }
  53. }
  54. componentWillUnmount() {
  55. this.props.onRef(undefined)
  56. }
  57. handleAdvancedOptionsToggle(useAdvancedOptions: boolean) {
  58. this.setState({ useAdvancedOptions })
  59. }
  60. findInvalidFields = () => {
  61. const apiVersion = this.props.getFieldValue(this.props.connectionInfoSchema.find(n => n.name === 'identity_api_version'))
  62. const invalidFields = this.props.connectionInfoSchema.filter(field => {
  63. let required
  64. if (typeof field.required === 'function') {
  65. required = field.required(apiVersion)
  66. } else {
  67. required = field.required
  68. }
  69. if (required) {
  70. let value = this.props.getFieldValue(field)
  71. return !value
  72. }
  73. return false
  74. }).map(f => f.name)
  75. return invalidFields
  76. }
  77. filterSimpleAdvanced(): Field[] {
  78. const apiVersion = this.props.getFieldValue(this.props.connectionInfoSchema.find(n => n.name === 'identity_api_version'))
  79. const extraAdvancedFields = ['description', 'glance_api_version', 'identity_api_version']
  80. return this.props.connectionInfoSchema.filter(field => {
  81. if (this.state.useAdvancedOptions) {
  82. return true
  83. }
  84. let required
  85. if (typeof field.required === 'function') {
  86. required = field.required(apiVersion)
  87. } else {
  88. required = field.required
  89. }
  90. return required || extraAdvancedFields.find(fieldName => field.name === fieldName)
  91. })
  92. }
  93. renderSimpleAdvancedToggle() {
  94. return (
  95. <ToggleButtonBarStyled
  96. items={[{ label: 'Simple', value: 'simple' }, { label: 'Advanced', value: 'advanced' }]}
  97. selectedValue={this.state.useAdvancedOptions ? 'advanced' : 'simple'}
  98. onChange={item => { this.handleAdvancedOptionsToggle(item.value === 'advanced') }}
  99. />
  100. )
  101. }
  102. renderFields() {
  103. const rows = []
  104. let lastField
  105. let apiVersion = this.props.getFieldValue(this.props.connectionInfoSchema.find(n => n.name === 'identity_api_version'))
  106. let fields = this.filterSimpleAdvanced()
  107. fields.forEach((field, i) => {
  108. const currentField = (
  109. <FieldStyled
  110. {...field}
  111. required={typeof field.required === 'function' ? field.required(apiVersion) : field.required}
  112. large
  113. disabled={this.props.disabled}
  114. password={field.name === 'password'}
  115. highlight={this.props.invalidFields.findIndex(fn => fn === field.name) > -1}
  116. value={this.props.getFieldValue(field)}
  117. onChange={value => { this.props.handleFieldChange(field, value) }}
  118. />
  119. )
  120. if (i % 2 !== 0) {
  121. rows.push((
  122. <Row key={field.name}>
  123. {lastField}
  124. {currentField}
  125. </Row>
  126. ))
  127. } else if (i === this.props.connectionInfoSchema.length - 1) {
  128. rows.push((
  129. <Row key={field.name}>
  130. {currentField}
  131. </Row>
  132. ))
  133. }
  134. lastField = currentField
  135. })
  136. return (
  137. <Fields innerRef={ref => { this.props.scrollableRef(ref) }}>
  138. {rows}
  139. </Fields>
  140. )
  141. }
  142. render() {
  143. return (
  144. <Wrapper>
  145. {this.renderSimpleAdvancedToggle()}
  146. {this.renderFields()}
  147. </Wrapper>
  148. )
  149. }
  150. }
  151. export default ContentPlugin