ValuesForm.tsx 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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. secretOption={true}
  102. />
  103. );
  104. case "key-value-array":
  105. return (
  106. <KeyValueArray
  107. key={i}
  108. namespace={this.props.namespace}
  109. clusterId={this.props.clusterId}
  110. values={this.props.metaState[key]}
  111. setValues={(x: any) => {
  112. this.props.setMetaState({ [key]: x });
  113. // Need to pull env vars out of form.yaml for createGHA build env vars
  114. if (
  115. this.props.handleEnvChange &&
  116. key === "container.env.normal"
  117. ) {
  118. this.props.handleEnvChange(x);
  119. }
  120. }}
  121. label={item.label}
  122. disabled={this.props.disabled}
  123. />
  124. );
  125. case "array-input":
  126. return (
  127. <InputArray
  128. key={i}
  129. values={this.props.metaState[key]}
  130. setValues={(x: string[]) => {
  131. this.props.setMetaState({ [key]: x });
  132. }}
  133. label={item.label}
  134. disabled={this.props.disabled}
  135. />
  136. );
  137. case "string-input":
  138. return (
  139. <InputRow
  140. key={i}
  141. isRequired={item.required}
  142. type="text"
  143. value={this.getInputValue(item)}
  144. setValue={(x: string) => {
  145. if (item.settings && item.settings.unit && x !== "") {
  146. x = x + item.settings.unit;
  147. }
  148. this.props.setMetaState({ [key]: x });
  149. }}
  150. label={item.label}
  151. unit={item.settings ? item.settings.unit : null}
  152. disabled={this.props.disabled}
  153. />
  154. );
  155. case "string-input-password":
  156. return (
  157. <InputRow
  158. key={i}
  159. isRequired={item.required}
  160. type="password"
  161. value={this.getInputValue(item)}
  162. setValue={(x: string) => {
  163. if (item.settings && item.settings.unit && x !== "") {
  164. x = x + item.settings.unit;
  165. }
  166. this.props.setMetaState({ [key]: x });
  167. }}
  168. label={item.label}
  169. unit={item.settings ? item.settings.unit : null}
  170. disabled={this.props.disabled}
  171. />
  172. );
  173. case "number-input":
  174. return (
  175. <InputRow
  176. key={i}
  177. isRequired={item.required}
  178. type="number"
  179. value={this.getInputValue(item)}
  180. setValue={(x: number) => {
  181. let val: string | number = x;
  182. if (Number.isNaN(x)) {
  183. val = "";
  184. }
  185. // Convert to string if unit is set
  186. if (item.settings && item.settings.unit) {
  187. val = x.toString();
  188. val = val + item.settings.unit;
  189. }
  190. this.props.setMetaState({ [key]: val });
  191. }}
  192. label={item.label}
  193. unit={item.settings ? item.settings.unit : null}
  194. disabled={this.props.disabled}
  195. />
  196. );
  197. case "select":
  198. return (
  199. <SelectRow
  200. key={i}
  201. value={this.props.metaState[key]}
  202. setActiveValue={(val) => this.props.setMetaState({ [key]: val })}
  203. options={item.settings.options}
  204. dropdownLabel=""
  205. label={item.label}
  206. />
  207. );
  208. case "provider-select":
  209. return (
  210. <SelectRow
  211. key={i}
  212. value={this.props.metaState[key]}
  213. setActiveValue={(val) => this.props.setMetaState({ [key]: val })}
  214. options={[
  215. { value: "aws", label: "Amazon Web Services (AWS)" },
  216. { value: "gcp", label: "Google Cloud Platform (GCP)" },
  217. { value: "do", label: "DigitalOcean" },
  218. ]}
  219. dropdownLabel=""
  220. label={item.label}
  221. />
  222. );
  223. case "velero-create-backup":
  224. return <VeleroForm />;
  225. case "base-64":
  226. return (
  227. <Base64InputRow
  228. key={i}
  229. isRequired={item.required}
  230. type="text"
  231. value={this.getInputValue(item)}
  232. setValue={(x: string) => {
  233. if (item.settings && item.settings.unit && x !== "") {
  234. x = x + item.settings.unit;
  235. }
  236. this.props.setMetaState({ [key]: btoa(x) });
  237. }}
  238. label={item.label}
  239. unit={item.settings ? item.settings.unit : null}
  240. disabled={this.props.disabled}
  241. />
  242. );
  243. case "base-64-password":
  244. return (
  245. <Base64InputRow
  246. key={i}
  247. isRequired={item.required}
  248. type="password"
  249. value={this.getInputValue(item)}
  250. setValue={(x: string) => {
  251. if (item.settings && item.settings.unit && x !== "") {
  252. x = x + item.settings.unit;
  253. }
  254. this.props.setMetaState({ [key]: btoa(x) });
  255. }}
  256. label={item.label}
  257. unit={item.settings ? item.settings.unit : null}
  258. disabled={this.props.disabled}
  259. />
  260. );
  261. default:
  262. }
  263. });
  264. };
  265. renderFormContents = () => {
  266. if (this.props.metaState) {
  267. return this.props.sections.map((section: Section, i: number) => {
  268. // Hide collapsible section if deciding field is false
  269. if (section.show_if) {
  270. if (!this.props.metaState[section.show_if]) {
  271. return null;
  272. }
  273. }
  274. return <div key={i}>{this.renderSection(section)}</div>;
  275. });
  276. }
  277. };
  278. render() {
  279. return (
  280. <StyledValuesForm>
  281. <DarkMatter />
  282. {this.renderFormContents()}
  283. </StyledValuesForm>
  284. );
  285. }
  286. }
  287. ValuesForm.contextType = Context;
  288. const ResourceList = styled.div`
  289. margin-bottom: 15px;
  290. margin-top: 20px;
  291. border-radius: 5px;
  292. overflow: hidden;
  293. `;
  294. const DarkMatter = styled.div`
  295. margin-top: 0px;
  296. `;
  297. const StyledValuesForm = styled.div`
  298. width: 100%;
  299. height: 100%;
  300. background: #ffffff11;
  301. color: #ffffff;
  302. padding: 0px 35px 25px;
  303. position: relative;
  304. border-radius: 5px;
  305. font-size: 13px;
  306. overflow: auto;
  307. `;