ValuesForm.tsx 10.0 KB

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