FormDebugger.tsx 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. import React, { Component } from "react";
  2. import styled from "styled-components";
  3. import AceEditor from "react-ace";
  4. import FormWrapper from "components/values-form/FormWrapper";
  5. import CheckboxRow from "components/values-form/CheckboxRow";
  6. import InputRow from "components/values-form/InputRow";
  7. import yaml from "js-yaml";
  8. import "shared/ace-porter-theme";
  9. import "ace-builds/src-noconflict/mode-text";
  10. import Heading from "./Heading";
  11. import Helper from "./Helper";
  12. type PropsType = {
  13. goBack: () => void;
  14. };
  15. type StateType = {
  16. rawYaml: string;
  17. showBonusTabs: boolean;
  18. showStateDebugger: boolean;
  19. valuesToOverride: any;
  20. checkbox_a: boolean;
  21. input_a: string;
  22. isReadOnly: boolean;
  23. };
  24. const tabOptions = [
  25. { value: "a", label: "Bonus Tab A" },
  26. { value: "b", label: "Bonus Tab B" },
  27. ];
  28. export default class FormDebugger extends Component<PropsType, StateType> {
  29. state = {
  30. rawYaml: initYaml,
  31. showBonusTabs: false,
  32. showStateDebugger: true,
  33. valuesToOverride: {
  34. checkbox_a: {
  35. value: true,
  36. },
  37. } as any,
  38. checkbox_a: true,
  39. input_a: "",
  40. isReadOnly: false,
  41. };
  42. renderTabContents = (currentTab: string) => {
  43. return (
  44. <TabWrapper>
  45. {this.state.rawYaml.toString().slice(0, 300) || "No raw YAML inputted."}
  46. </TabWrapper>
  47. );
  48. };
  49. aceEditorRef = React.createRef<AceEditor>();
  50. render() {
  51. let formData = {};
  52. try {
  53. formData = yaml.load(this.state.rawYaml);
  54. } catch (err: any) {
  55. console.log("YAML parsing error.");
  56. }
  57. return (
  58. <StyledFormDebugger>
  59. <Button onClick={this.props.goBack}>
  60. <i className="material-icons">keyboard_backspace</i>
  61. Back
  62. </Button>
  63. <Heading>✨ Form.yaml Editor</Heading>
  64. <Helper>Write and test form.yaml free of consequence.</Helper>
  65. <EditorWrapper>
  66. <AceEditor
  67. ref={this.aceEditorRef}
  68. mode="yaml"
  69. value={this.state.rawYaml}
  70. theme="porter"
  71. onChange={(e: string) => this.setState({ rawYaml: e })}
  72. name="codeEditor"
  73. editorProps={{ $blockScrolling: true }}
  74. height="450px"
  75. width="100%"
  76. style={{
  77. borderRadius: "5px",
  78. border: "1px solid #ffffff22",
  79. marginTop: "27px",
  80. marginBottom: "27px",
  81. }}
  82. showPrintMargin={false}
  83. showGutter={true}
  84. highlightActiveLine={true}
  85. />
  86. </EditorWrapper>
  87. <CheckboxRow
  88. label="Show form state debugger"
  89. checked={this.state.showStateDebugger}
  90. toggle={() =>
  91. this.setState({ showStateDebugger: !this.state.showStateDebugger })
  92. }
  93. />
  94. <CheckboxRow
  95. label="Read-only"
  96. checked={this.state.isReadOnly}
  97. toggle={() =>
  98. this.setState({
  99. isReadOnly: !this.state.isReadOnly,
  100. })
  101. }
  102. />
  103. <CheckboxRow
  104. label="Include non-form dummy tabs"
  105. checked={this.state.showBonusTabs}
  106. toggle={() =>
  107. this.setState({ showBonusTabs: !this.state.showBonusTabs })
  108. }
  109. />
  110. <CheckboxRow
  111. label="checkbox_a"
  112. checked={this.state.checkbox_a}
  113. toggle={() =>
  114. this.setState({
  115. checkbox_a: !this.state.checkbox_a,
  116. // Override the form value for checkbox_a
  117. valuesToOverride: {
  118. ...this.state.valuesToOverride,
  119. checkbox_a: {
  120. value: !this.state.checkbox_a,
  121. },
  122. },
  123. })
  124. }
  125. />
  126. <InputRow
  127. type="string"
  128. value={this.state.input_a}
  129. setValue={(x: string) =>
  130. this.setState({
  131. input_a: x,
  132. // Override the form value for input_a
  133. valuesToOverride: {
  134. ...this.state.valuesToOverride,
  135. input_a: {
  136. value: x,
  137. },
  138. },
  139. })
  140. }
  141. label={"input_a"}
  142. placeholder="ex: override text"
  143. />
  144. <Heading>🎨 Rendered Form</Heading>
  145. <Br />
  146. <FormWrapper
  147. valuesToOverride={this.state.valuesToOverride}
  148. clearValuesToOverride={() =>
  149. this.setState({ valuesToOverride: null })
  150. }
  151. showStateDebugger={this.state.showStateDebugger}
  152. formData={formData}
  153. isReadOnly={this.state.isReadOnly}
  154. tabOptions={this.state.showBonusTabs ? tabOptions : []}
  155. renderTabContents={
  156. this.state.showBonusTabs ? this.renderTabContents : null
  157. }
  158. onSubmit={(values: any) => {
  159. alert("Check console output.");
  160. console.log("Raw submission values:");
  161. console.log(values);
  162. }}
  163. />
  164. </StyledFormDebugger>
  165. );
  166. }
  167. }
  168. const Br = styled.div`
  169. width: 100%;
  170. height: 12px;
  171. `;
  172. const TabWrapper = styled.div`
  173. background: #ffffff11;
  174. height: 200px;
  175. width: 100%;
  176. border-radius: 5px;
  177. display: flex;
  178. align-items: center;
  179. justify-content: center;
  180. font-size: 13px;
  181. overflow: auto;
  182. padding: 50px;
  183. `;
  184. const EditorWrapper = styled.div`
  185. .ace_editor,
  186. .ace_editor * {
  187. font-family: "Monaco", "Menlo", "Ubuntu Mono", "Droid Sans Mono", "Consolas",
  188. monospace !important;
  189. font-size: 12px !important;
  190. font-weight: 400 !important;
  191. letter-spacing: 0 !important;
  192. }
  193. `;
  194. const StyledFormDebugger = styled.div`
  195. position: relative;
  196. `;
  197. const Button = styled.div`
  198. display: flex;
  199. flex-direction: row;
  200. align-items: center;
  201. justify-content: space-between;
  202. font-size: 13px;
  203. cursor: pointer;
  204. font-family: "Work Sans", sans-serif;
  205. border-radius: 20px;
  206. color: white;
  207. height: 35px;
  208. margin-left: -2px;
  209. padding: 0px 8px;
  210. width: 85px;
  211. float: right;
  212. padding-bottom: 1px;
  213. font-weight: 500;
  214. padding-right: 15px;
  215. overflow: hidden;
  216. white-space: nowrap;
  217. text-overflow: ellipsis;
  218. cursor: pointer;
  219. border: 2px solid #969fbbaa;
  220. :hover {
  221. background: #ffffff11;
  222. }
  223. > i {
  224. color: white;
  225. width: 18px;
  226. height: 18px;
  227. color: #969fbbaa;
  228. font-weight: 600;
  229. font-size: 14px;
  230. border-radius: 20px;
  231. display: flex;
  232. align-items: center;
  233. margin-right: 5px;
  234. justify-content: center;
  235. }
  236. `;
  237. const initYaml = `name: Porter Example
  238. hasSource: true
  239. tabs:
  240. - name: main
  241. label: Main
  242. sections:
  243. - name: header
  244. contents:
  245. - type: heading
  246. label: 🍺 Porter Demo Form
  247. - type: subtitle
  248. name: command_description
  249. label: Basic form demonstrating some of the features of form.yaml
  250. - type: string-input
  251. placeholder: "ex: pilsner"
  252. label: Required Field A
  253. required: true
  254. variable: field_a
  255. - type: string-input
  256. placeholder: "ex: sapporo"
  257. required: true
  258. label: Required Field B
  259. variable: field_b
  260. - type: subtitle
  261. label: "Note: Hidden required fields aren't supported yet (global only)"
  262. - name: controlled-by-external
  263. show_if: checkbox_a
  264. contents:
  265. - type: heading
  266. label: Conditional Display (A)
  267. - type: subtitle
  268. label: This section can be externally controlled by the value of checkbox_a
  269. - type: string-input
  270. variable: input_a
  271. placeholder: "Override w/ input_a"
  272. - name: domain_name
  273. show_if: ingress.custom_domain
  274. contents:
  275. - type: array-input
  276. variable: ingress.hosts
  277. label: Domain Name
  278. - name: env
  279. label: Environment
  280. sections:
  281. - name: env_vars
  282. contents:
  283. - type: heading
  284. label: Environment Variables
  285. - type: subtitle
  286. label: Set environment variables for your secrets and environment-specific configuration.
  287. - type: env-key-value-array
  288. label:
  289. variable: container.env.normal
  290. - name: advanced
  291. label: Advanced
  292. sections:
  293. - name: advanced
  294. contents:
  295. - type: heading
  296. label: Some Header
  297. - type: subtitle
  298. label: Some helper text
  299. `;