ValuesForm.tsx 10 KB

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