ValuesForm.tsx 9.6 KB

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