ValuesForm.tsx 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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 CheckboxRow from "./CheckboxRow";
  6. import InputRow from "./InputRow";
  7. import Base64InputRow from "./Base64InputRow";
  8. import SelectRow from "./SelectRow";
  9. import Helper from "./Helper";
  10. import Heading from "./Heading";
  11. import ExpandableResource from "../ExpandableResource";
  12. import VeleroForm from "../forms/VeleroForm";
  13. import InputArray from "./InputArray";
  14. import KeyValueArray from "./KeyValueArray";
  15. type PropsType = {
  16. sections?: Section[];
  17. metaState?: any;
  18. setMetaState?: any;
  19. handleEnvChange?: (x: any) => void;
  20. };
  21. type StateType = any;
  22. // Requires an internal representation unlike other values components because metaState value underdetermines input order
  23. export default class ValuesForm extends Component<PropsType, StateType> {
  24. getInputValue = (item: FormElement) => {
  25. let key = item.name || item.variable;
  26. let value = this.props.metaState[key];
  27. if (item.settings && item.settings.unit && value && value.includes) {
  28. value = value.split(item.settings.unit)[0];
  29. }
  30. return value;
  31. };
  32. renderSection = (section: Section) => {
  33. return section.contents.map((item: FormElement, i: number) => {
  34. // If no name is assigned use values.yaml variable as identifier
  35. let key = item.name || item.variable;
  36. switch (item.type) {
  37. case "heading":
  38. return <Heading key={i}>{item.label}</Heading>;
  39. case "subtitle":
  40. return <Helper key={i}>{item.label}</Helper>;
  41. case "resource-list":
  42. if (Array.isArray(item.value)) {
  43. return (
  44. <ResourceList key={i}>
  45. {item.value.map((resource: any, i: number) => {
  46. return (
  47. <ExpandableResource
  48. key={i}
  49. resource={resource}
  50. isLast={i === item.value.length - 1}
  51. roundAllCorners={true}
  52. />
  53. );
  54. })}
  55. </ResourceList>
  56. );
  57. }
  58. case "checkbox":
  59. return (
  60. <CheckboxRow
  61. key={i}
  62. checked={this.props.metaState[key]}
  63. toggle={() =>
  64. this.props.setMetaState({ [key]: !this.props.metaState[key] })
  65. }
  66. label={item.label}
  67. />
  68. );
  69. case "key-value-array":
  70. return (
  71. <KeyValueArray
  72. key={i}
  73. values={this.props.metaState[key]}
  74. setValues={(x: any) => {
  75. this.props.setMetaState({ [key]: x });
  76. // Need to pull env vars out of form.yaml for createGHA build env vars
  77. if (
  78. this.props.handleEnvChange &&
  79. key === "container.env.normal"
  80. ) {
  81. this.props.handleEnvChange(x);
  82. }
  83. }}
  84. label={item.label}
  85. />
  86. );
  87. case "array-input":
  88. return (
  89. <InputArray
  90. key={i}
  91. values={this.props.metaState[key]}
  92. setValues={(x: string[]) => {
  93. this.props.setMetaState({ [key]: x });
  94. }}
  95. label={item.label}
  96. />
  97. );
  98. case "string-input":
  99. return (
  100. <InputRow
  101. key={i}
  102. isRequired={item.required}
  103. type="text"
  104. value={this.getInputValue(item)}
  105. setValue={(x: string) => {
  106. if (item.settings && item.settings.unit && x !== "") {
  107. x = x + item.settings.unit;
  108. }
  109. this.props.setMetaState({ [key]: x });
  110. }}
  111. label={item.label}
  112. unit={item.settings ? item.settings.unit : null}
  113. />
  114. );
  115. case "string-input-password":
  116. return (
  117. <InputRow
  118. key={i}
  119. isRequired={item.required}
  120. type="password"
  121. value={this.getInputValue(item)}
  122. setValue={(x: string) => {
  123. console.log("string input", x);
  124. if (item.settings && item.settings.unit && x !== "") {
  125. x = x + item.settings.unit;
  126. }
  127. this.props.setMetaState({ [key]: x });
  128. }}
  129. label={item.label}
  130. unit={item.settings ? item.settings.unit : null}
  131. />
  132. );
  133. case "number-input":
  134. return (
  135. <InputRow
  136. key={i}
  137. isRequired={item.required}
  138. type="number"
  139. value={this.getInputValue(item)}
  140. setValue={(x: number) => {
  141. let val: string | number = x;
  142. if (Number.isNaN(x)) {
  143. val = "";
  144. }
  145. // Convert to string if unit is set
  146. if (item.settings && item.settings.unit) {
  147. val = x.toString();
  148. val = val + item.settings.unit;
  149. }
  150. this.props.setMetaState({ [key]: val });
  151. }}
  152. label={item.label}
  153. unit={item.settings ? item.settings.unit : null}
  154. />
  155. );
  156. case "select":
  157. return (
  158. <SelectRow
  159. key={i}
  160. value={this.props.metaState[key]}
  161. setActiveValue={(val) => this.props.setMetaState({ [key]: val })}
  162. options={item.settings.options}
  163. dropdownLabel=""
  164. label={item.label}
  165. />
  166. );
  167. case "provider-select":
  168. return (
  169. <SelectRow
  170. key={i}
  171. value={this.props.metaState[key]}
  172. setActiveValue={(val) => this.props.setMetaState({ [key]: val })}
  173. options={[
  174. { value: "aws", label: "Amazon Web Services (AWS)" },
  175. { value: "gcp", label: "Google Cloud Platform (GCP)" },
  176. { value: "do", label: "DigitalOcean" },
  177. ]}
  178. dropdownLabel=""
  179. label={item.label}
  180. />
  181. );
  182. case "velero-create-backup":
  183. return <VeleroForm />;
  184. case "base-64":
  185. return (
  186. <Base64InputRow
  187. key={i}
  188. isRequired={item.required}
  189. type="text"
  190. value={this.getInputValue(item)}
  191. setValue={(x: string) => {
  192. if (item.settings && item.settings.unit && x !== "") {
  193. x = x + item.settings.unit;
  194. }
  195. this.props.setMetaState({ [key]: btoa(x) });
  196. }}
  197. label={item.label}
  198. unit={item.settings ? item.settings.unit : null}
  199. />
  200. );
  201. case "base-64-password":
  202. return (
  203. <Base64InputRow
  204. key={i}
  205. isRequired={item.required}
  206. type="password"
  207. value={this.getInputValue(item)}
  208. setValue={(x: string) => {
  209. if (item.settings && item.settings.unit && x !== "") {
  210. x = x + item.settings.unit;
  211. }
  212. this.props.setMetaState({ [key]: btoa(x) });
  213. }}
  214. label={item.label}
  215. unit={item.settings ? item.settings.unit : null}
  216. />
  217. );
  218. default:
  219. }
  220. });
  221. };
  222. renderFormContents = () => {
  223. if (this.props.metaState) {
  224. return this.props.sections.map((section: Section, i: number) => {
  225. // Hide collapsible section if deciding field is false
  226. if (section.show_if) {
  227. if (!this.props.metaState[section.show_if]) {
  228. return null;
  229. }
  230. }
  231. return <div key={i}>{this.renderSection(section)}</div>;
  232. });
  233. }
  234. };
  235. render() {
  236. return (
  237. <StyledValuesForm>
  238. <DarkMatter />
  239. {this.renderFormContents()}
  240. </StyledValuesForm>
  241. );
  242. }
  243. }
  244. ValuesForm.contextType = Context;
  245. const ResourceList = styled.div`
  246. margin-bottom: 15px;
  247. margin-top: 20px;
  248. border-radius: 5px;
  249. overflow: hidden;
  250. `;
  251. const DarkMatter = styled.div`
  252. margin-top: 0px;
  253. `;
  254. const StyledValuesForm = styled.div`
  255. width: 100%;
  256. height: 100%;
  257. background: #ffffff11;
  258. color: #ffffff;
  259. padding: 0px 35px 25px;
  260. position: relative;
  261. border-radius: 5px;
  262. font-size: 13px;
  263. overflow: auto;
  264. `;