ContentPlugin.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. import * as React from 'react'
  15. import styled from 'styled-components'
  16. import configLoader from '../../utils/Config'
  17. import LabelDictionary from '../../utils/LabelDictionary'
  18. import FieldInput from '../../components/ui/FieldInput/FieldInput'
  19. import type { Field } from '../../@types/Field'
  20. import { Endpoint, Validation } from '../../@types/Endpoint'
  21. import { ThemeProps } from '../../components/Theme'
  22. export const Wrapper = styled.div<any>`
  23. display: flex;
  24. flex-direction: column;
  25. min-height: 0;
  26. `
  27. export const Fields = styled.div<any>`
  28. display: flex;
  29. margin-top: 32px;
  30. padding: 0 32px;
  31. flex-direction: column;
  32. overflow: auto;
  33. `
  34. export const FieldStyled = styled(FieldInput)`
  35. min-width: ${props => (props.useTextArea ? '100%' : '224px')};
  36. max-width: ${ThemeProps.inputSizes.large.width}px;
  37. margin-bottom: 16px;
  38. `
  39. export const Row = styled.div<any>`
  40. display: flex;
  41. flex-shrink: 0;
  42. justify-content: space-between;
  43. `
  44. type Props = {
  45. connectionInfoSchema: Field[],
  46. validation: Validation | null,
  47. invalidFields: string[],
  48. getFieldValue: (field: Field | null) => any,
  49. handleFieldChange: (field: Field | null, value: any) => void,
  50. disabled: boolean,
  51. cancelButtonText: string,
  52. validating: boolean,
  53. onRef: (contentPlugin: any) => void,
  54. handleFieldsChange: (items: { field: Field, value: any }[]) => void,
  55. originalConnectionInfo: Endpoint['connection_info'],
  56. onResizeUpdate: (scrollOffset: number) => void,
  57. scrollableRef: (ref: HTMLElement) => void,
  58. highlightRequired: () => void
  59. handleValidateClick: () => void
  60. handleCancelClick: () => void
  61. }
  62. class ContentPlugin extends React.Component<Props> {
  63. componentDidMount() {
  64. this.props.onRef(this)
  65. }
  66. componentWillUnmount() {
  67. this.props.onRef(undefined)
  68. }
  69. findInvalidFields = () => {
  70. const invalidFields = this.props.connectionInfoSchema.filter(field => {
  71. if (field.required) {
  72. const value = this.props.getFieldValue(field)
  73. return !value || value.length === 0
  74. }
  75. return false
  76. }).map(f => f.name)
  77. return invalidFields
  78. }
  79. renderFields() {
  80. const rows: JSX.Element[] = []
  81. let lastField: JSX.Element
  82. let i = 0
  83. this.props.connectionInfoSchema.forEach((field, schemaIndex) => {
  84. const isPassword = Boolean(configLoader.config.passwordFields.find(fn => field.name === fn))
  85. || field.name.indexOf('password') > -1
  86. const currentField = (
  87. <FieldStyled
  88. {...field}
  89. label={field.title || LabelDictionary.get(field.name)}
  90. width={ThemeProps.inputSizes.large.width}
  91. disabled={this.props.disabled}
  92. password={isPassword}
  93. highlight={this.props.invalidFields.findIndex(fn => fn === field.name) > -1}
  94. value={this.props.getFieldValue(field)}
  95. onChange={value => { this.props.handleFieldChange(field, value) }}
  96. />
  97. )
  98. const pushRow = (field1: React.ReactNode, field2?: React.ReactNode) => {
  99. rows.push((
  100. <Row key={field.name}>
  101. {field1}
  102. {field2}
  103. </Row>
  104. ))
  105. }
  106. if (field.useTextArea) {
  107. pushRow(currentField)
  108. i -= 1
  109. } else if (i % 2 !== 0) {
  110. pushRow(lastField, currentField)
  111. } else if (schemaIndex === this.props.connectionInfoSchema.length - 1) {
  112. pushRow(currentField)
  113. if (field.useTextArea) {
  114. i -= 1
  115. }
  116. } else {
  117. lastField = currentField
  118. }
  119. i += 1
  120. })
  121. return (
  122. <Fields>
  123. {rows}
  124. </Fields>
  125. )
  126. }
  127. render() {
  128. return (
  129. <Wrapper>
  130. {this.renderFields()}
  131. </Wrapper>
  132. )
  133. }
  134. }
  135. export default ContentPlugin