ValuesForm.tsx 9.7 KB

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