ValuesWrapper.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import React, { Component } from 'react';
  2. import styled from 'styled-components';
  3. import { Section, FormElement } from '../../shared/types';
  4. import { Context } from '../../shared/Context';
  5. import SaveButton from '../SaveButton';
  6. type PropsType = {
  7. formTabs: any,
  8. onSubmit: (formValues: any) => void,
  9. disabled?: boolean,
  10. saveValuesStatus?: string | null,
  11. isInModal?: boolean,
  12. currentTab?: string, // For resetting state when flipping b/w tabs in ExpandedChart
  13. };
  14. type StateType = any;
  15. const providerMap: any = {
  16. 'gke': 'gcp',
  17. 'eks': 'aws',
  18. 'doks': 'do',
  19. };
  20. // Manages the consolidated state of all form tabs ("metastate")
  21. export default class ValuesWrapper extends Component<PropsType, StateType> {
  22. // No need to render, so OK to set as class variable outside of state
  23. requiredFields: string[] = [];
  24. updateFormState() {
  25. let metaState: any = {};
  26. this.props.formTabs.forEach((tab: any, i: number) => {
  27. // TODO: reconcile tab.name and tab.value
  28. if (tab.name || (tab.value && tab.value.includes('@'))) {
  29. tab.sections.forEach((section: Section, i: number) => {
  30. section.contents.forEach((item: FormElement, i: number) => {
  31. // If no name is assigned use values.yaml variable as identifier
  32. let key = item.name || item.variable;
  33. let def = (item.value && item.value[0]) || (item.settings && item.settings.default);
  34. // Handle add to list of required fields
  35. if (item.required) {
  36. key && this.requiredFields.push(key);
  37. }
  38. switch (item.type) {
  39. case 'checkbox':
  40. metaState[key] = def ? def : false;
  41. break;
  42. case 'string-input':
  43. metaState[key] = def ? def : '';
  44. break;
  45. case 'array-input':
  46. metaState[key] = def ? def : [];
  47. break;
  48. case 'number-input':
  49. metaState[key] = def.toString() ? def : '';
  50. break;
  51. case 'select':
  52. metaState[key] = def ? def : item.settings.options[0].value;
  53. break;
  54. case 'provider-select':
  55. def = providerMap[this.context.currentCluster.service];
  56. metaState[key] = def ? def : 'aws';
  57. break;
  58. case 'base-64':
  59. metaState[key] = def ? def : '';
  60. case 'base-64-password':
  61. metaState[key] = def ? def : '';
  62. default:
  63. }
  64. });
  65. });
  66. }
  67. });
  68. this.setState(metaState);
  69. }
  70. // Initialize corresponding state fields for form blocks
  71. componentDidMount() {
  72. this.updateFormState();
  73. }
  74. componentDidUpdate(prevProps: PropsType) {
  75. if (this.props.formTabs !== prevProps.formTabs ||
  76. this.props.currentTab !== prevProps.currentTab
  77. ) {
  78. this.updateFormState();
  79. }
  80. }
  81. // Checks if all required fields are set
  82. isDisabled = (): boolean => {
  83. let valueIndicators: any[] = [];
  84. this.requiredFields.forEach((field: string, i: number) => {
  85. valueIndicators.push(this.state[field] && true);
  86. });
  87. return valueIndicators.includes(false) || valueIndicators.includes('')
  88. }
  89. renderButton = () => {
  90. let { formTabs, currentTab } = this.props;
  91. let tab = formTabs.find((t: any) => t.name === currentTab || t.value === currentTab);
  92. if (tab && tab.context && tab.context.type === 'helm/values') {
  93. return (
  94. <SaveButton
  95. disabled={this.isDisabled() || this.props.disabled}
  96. text='Deploy'
  97. onClick={() => this.props.onSubmit(this.state)}
  98. status={this.isDisabled() ? 'Missing required fields' : this.props.saveValuesStatus}
  99. makeFlush={true}
  100. />
  101. );
  102. }
  103. }
  104. render() {
  105. let renderFunc: any = this.props.children;
  106. if (this.props.isInModal) {
  107. return (
  108. <StyledValuesWrapper>
  109. {renderFunc(this.state, (x: any) => this.setState(x))}
  110. {this.renderButton()}
  111. </StyledValuesWrapper>
  112. );
  113. }
  114. return (
  115. <PaddedWrapper>
  116. <StyledValuesWrapper>
  117. {renderFunc(this.state, (x: any) => this.setState(x))}
  118. {this.renderButton()}
  119. </StyledValuesWrapper>
  120. </PaddedWrapper>
  121. );
  122. }
  123. }
  124. ValuesWrapper.contextType = Context;
  125. const StyledValuesWrapper = styled.div`
  126. width: 100%;
  127. padding: 0;
  128. height: calc(100% - 65px);
  129. `;
  130. const PaddedWrapper = styled.div`
  131. padding-bottom: 65px;
  132. position: relative;
  133. `;