ValuesWrapper.tsx 5.2 KB

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