PorterForm.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import React, { useContext, useState } from "react";
  2. import { Section, FormField, StringInputField, CheckboxField } from "./types";
  3. import TabRegion, { TabOption } from "../TabRegion";
  4. import Heading from "../values-form/Heading";
  5. import Helper from "../values-form/Helper";
  6. import StringInput from "./field-components/StringInput";
  7. import { PorterFormContext } from "./PorterFormContextProvider";
  8. import Checkbox from "./field-components/Checkbox";
  9. import styled from "styled-components";
  10. import SaveButton from "../SaveButton";
  11. interface Props {
  12. leftTabOptions?: TabOption[];
  13. rightTabOptions?: TabOption[];
  14. renderTabContents?: (
  15. currentTab: string,
  16. submitValues?: any
  17. ) => React.ReactElement;
  18. saveButtonText?: string;
  19. }
  20. const PorterForm: React.FC<Props> = (props) => {
  21. const { formData, isReadOnly } = useContext(PorterFormContext);
  22. const [currentTab, setCurrentTab] = useState(
  23. formData.tabs.length > 0 ? formData.tabs[0].name : ""
  24. );
  25. const renderSectionField = (field: FormField): JSX.Element => {
  26. const bundledProps = {
  27. ...field,
  28. isReadOnly,
  29. };
  30. switch (field.type) {
  31. case "heading":
  32. return <Heading>{field.label}</Heading>;
  33. case "subtitle":
  34. return <Helper>{field.label}</Helper>;
  35. case "string-input":
  36. return <StringInput {...(bundledProps as StringInputField)} />;
  37. case "checkbox":
  38. return <Checkbox {...(bundledProps as CheckboxField)} />;
  39. }
  40. return <p>Not Implemented: {(field as any).type}</p>;
  41. };
  42. const renderSection = (section: Section): JSX.Element => {
  43. return (
  44. <>
  45. {section.contents.map((field, i) => {
  46. return (
  47. <React.Fragment key={field.id}>
  48. {renderSectionField(field)}
  49. </React.Fragment>
  50. );
  51. })}
  52. </>
  53. );
  54. };
  55. const getTabOptions = (): TabOption[] => {
  56. return (props.leftTabOptions || [])
  57. .concat(
  58. formData.tabs.map((tab) => {
  59. return { label: tab.label, value: tab.name };
  60. })
  61. )
  62. .concat(props.rightTabOptions || []);
  63. };
  64. const renderTab = (name: string): JSX.Element => {
  65. const tab = formData.tabs.filter((tab) => tab.name == name)[0];
  66. if (!tab) {
  67. // tab is external
  68. return props.renderTabContents ? props.renderTabContents(name) : <></>;
  69. }
  70. return (
  71. <>
  72. {tab.sections.map((section) => {
  73. return (
  74. <React.Fragment key={section.name}>
  75. {renderSection(section)}
  76. </React.Fragment>
  77. );
  78. })}
  79. </>
  80. );
  81. };
  82. return (
  83. <>
  84. <TabRegion
  85. options={getTabOptions()}
  86. currentTab={currentTab}
  87. setCurrentTab={setCurrentTab}
  88. >
  89. <StyledPorterForm>{renderTab(currentTab)}</StyledPorterForm>
  90. </TabRegion>
  91. <SaveButton
  92. text={props.saveButtonText || "Deploy"}
  93. onClick={() => {}}
  94. makeFlush
  95. />
  96. <Spacer />
  97. </>
  98. );
  99. };
  100. export default PorterForm;
  101. const Spacer = styled.div`
  102. height: 50px;
  103. `;
  104. const StyledPorterForm = styled.div`
  105. width: 100%;
  106. height: 100%;
  107. background: #ffffff11;
  108. color: #ffffff;
  109. padding: 0px 35px 25px;
  110. position: relative;
  111. border-radius: 5px;
  112. font-size: 13px;
  113. overflow: auto;
  114. `;