Просмотр исходного кода

Implement injected props for porter form

jnfrati 3 лет назад
Родитель
Сommit
a82378ae65

+ 6 - 0
dashboard/src/components/porter-form/PorterForm.tsx

@@ -4,6 +4,7 @@ import {
   CheckboxField,
   CronField,
   FormField,
+  InjectedProps,
   InputField,
   KeyValueArrayField,
   ResourceListField,
@@ -49,6 +50,7 @@ interface Props {
   hideSpacer?: boolean;
   // The tab to redirect to after saving the form
   redirectTabAfterSave?: string;
+  injectedProps?: InjectedProps;
 }
 
 const PorterForm: React.FC<Props> = (props) => {
@@ -63,10 +65,14 @@ const PorterForm: React.FC<Props> = (props) => {
   const { currentTab, setCurrentTab } = props;
 
   const renderSectionField = (field: FormField): JSX.Element => {
+    const injected = props.injectedProps?.[field.type];
+
     const bundledProps = {
       ...field,
       isReadOnly,
+      injectedValues: injected ?? {},
     };
+
     switch (field.type) {
       case "heading":
         return <Heading>{field.label}</Heading>;

+ 4 - 1
dashboard/src/components/porter-form/PorterFormWrapper.tsx

@@ -1,7 +1,7 @@
 import React, { useState } from "react";
 
 import PorterForm from "./PorterForm";
-import { PorterFormData } from "./types";
+import { InjectedProps, PorterFormData } from "./types";
 import { PorterFormContextProvider } from "./PorterFormContextProvider";
 
 type PropsType = {
@@ -23,6 +23,7 @@ type PropsType = {
   hideBottomSpacer?: boolean;
   redirectTabAfterSave?: string;
   includeMetadata?: boolean;
+  injectedProps?: InjectedProps;
 };
 
 const PorterFormWrapper: React.FC<PropsType> = ({
@@ -44,6 +45,7 @@ const PorterFormWrapper: React.FC<PropsType> = ({
   hideBottomSpacer,
   redirectTabAfterSave,
   includeMetadata,
+  injectedProps,
 }) => {
   const hashCode = (s: string) => {
     return s?.split("").reduce(function (a, b) {
@@ -99,6 +101,7 @@ const PorterFormWrapper: React.FC<PropsType> = ({
           isLaunch={isLaunch}
           hideSpacer={hideBottomSpacer}
           redirectTabAfterSave={redirectTabAfterSave}
+          injectedProps={injectedProps}
         />
       </PorterFormContextProvider>
     </React.Fragment>

+ 23 - 1
dashboard/src/components/porter-form/field-components/KeyValueArray.tsx

@@ -4,6 +4,7 @@ import {
   GetMetadataFunction,
   KeyValueArrayField,
   KeyValueArrayFieldState,
+  PartialEnvGroup,
   PopulatedEnvGroup,
 } from "../types";
 import sliders from "../../../assets/sliders.svg";
@@ -63,7 +64,27 @@ const KeyValueArray: React.FC<Props> = (props) => {
     if (hasSetValue(props) && !Array.isArray(state?.synced_env_groups)) {
       const values = props.value[0];
       // console.log(values);
-      const envGroups = values?.synced || [];
+      const envGroups: PartialEnvGroup[] = values?.synced || [];
+
+      if (Array.isArray(props.injectedProps?.availableSyncEnvGroups)) {
+        const availableEnvGroups = props.injectedProps.availableSyncEnvGroups;
+
+        const populatedEnvGroups = envGroups
+          .map((envGroup) => {
+            return availableEnvGroups.find(
+              (availableEnvGroup) => availableEnvGroup.name === envGroup.name
+            );
+          })
+          .filter(Boolean);
+
+        setState(() => ({
+          synced_env_groups: Array.isArray(populatedEnvGroups)
+            ? populatedEnvGroups
+            : [],
+        }));
+        return;
+      }
+
       const promises = Promise.all(
         envGroups.map(async (envGroup: any) => {
           const res = await api.getEnvGroup(
@@ -90,6 +111,7 @@ const KeyValueArray: React.FC<Props> = (props) => {
       });
     }
   }, [
+    props.injectedProps,
     props.value[0],
     variables?.clusterId,
     variables?.namespace,

+ 20 - 0
dashboard/src/components/porter-form/types.ts

@@ -9,6 +9,7 @@ import { ContextProps } from "../../shared/types";
 
 export interface GenericField {
   id: string;
+  injectedProps: unknown;
 }
 
 export interface GenericInputField extends GenericField {
@@ -88,6 +89,9 @@ export interface KeyValueArrayField extends GenericInputField {
     };
     type: "env" | "normal";
   };
+  injectedProps: {
+    availableSyncEnvGroups: PopulatedEnvGroup[];
+  };
 }
 
 export interface ArrayInputField extends GenericInputField {
@@ -308,3 +312,19 @@ export type GetMetadataFunction<T = unknown> = (
   state: PorterFormFieldFieldState,
   context: Partial<ContextProps>
 ) => T;
+
+type EnforceKeys<
+  Key extends string,
+  T extends Partial<Record<Key, unknown>>
+> = {
+  [K in keyof T as K extends Key ? K : never]: T[K];
+};
+
+export type InjectedProps = Partial<
+  EnforceKeys<
+    FormField["type"],
+    {
+      "key-value-array": KeyValueArrayField["injectedProps"];
+    }
+  >
+>;

+ 33 - 18
dashboard/src/main/home/cluster-dashboard/stacks/launch/NewApp.tsx

@@ -19,7 +19,9 @@ import { hardcodedIcons } from "shared/hardcodedNameDict";
 const DEFAULT_STACK_SOURCE_CONFIG_INDEX = 0;
 
 const NewApp = () => {
-  const { addAppResource, newStack } = useContext(StacksLaunchContext);
+  const { addAppResource, newStack, namespace } = useContext(
+    StacksLaunchContext
+  );
   const { currentCluster } = useContext(Context);
 
   const params = useParams<{
@@ -72,7 +74,11 @@ const NewApp = () => {
   }, [params]);
 
   if (isLoading) {
-    return <Wrapper><Loading /></Wrapper>;
+    return (
+      <Wrapper>
+        <Loading />
+      </Wrapper>
+    );
   }
 
   if (hasError) {
@@ -185,17 +191,20 @@ const NewApp = () => {
       <TitleSection>
         <DynamicLink to={`/stacks/launch/overview`}>
           <BackButton>
-            <i className="material-icons">
-              keyboard_backspace
-            </i>
+            <i className="material-icons">keyboard_backspace</i>
           </BackButton>
         </DynamicLink>
         <Polymer>
-        <Icon src={hardcodedIcons[template.metadata.name]} />
+          <Icon src={hardcodedIcons[template.metadata.name]} />
         </Polymer>
-        Add {template.metadata.name.charAt(0).toUpperCase() + template.metadata.name.slice(1)} to Stack
+        Add{" "}
+        {template.metadata.name.charAt(0).toUpperCase() +
+          template.metadata.name.slice(1)}{" "}
+        to Stack
       </TitleSection>
-      <Heading>Application Name <Required>*</Required></Heading>
+      <Heading>
+        Application Name <Required>*</Required>
+      </Heading>
       <InputRow
         type="string"
         value={appName}
@@ -205,15 +214,21 @@ const NewApp = () => {
       />
 
       <div style={{ position: "relative" }}>
-      <Heading>Application Settings</Heading>
-      <Helper>Configure settings for this application.</Helper>
-      <PorterFormWrapper
-        formData={template.form}
-        onSubmit={handleSubmit}
-        isLaunch
-        saveValuesStatus={saveButtonStatus}
-        saveButtonText="Add Application"
-      />
+        <Heading>Application Settings</Heading>
+        <Helper>Configure settings for this application.</Helper>
+        <PorterFormWrapper
+          formData={template.form}
+          onSubmit={handleSubmit}
+          isLaunch
+          saveValuesStatus={saveButtonStatus}
+          saveButtonText="Add Application"
+          valuesToOverride={{ namespace }}
+          injectedProps={{
+            "key-value-array": {
+              availableSyncEnvGroups: [],
+            },
+          }}
+        />
       </div>
     </StyledLaunchFlow>
   );
@@ -283,4 +298,4 @@ const StyledLaunchFlow = styled.div`
   margin-top: ${(props: { disableMarginTop?: boolean }) =>
     props.disableMarginTop ? "inherit" : "calc(50vh - 380px)"};
   padding-bottom: 150px;
-`;
+`;

+ 8 - 0
dashboard/src/main/home/modals/LoadEnvGroupModal.tsx

@@ -32,6 +32,7 @@ type PropsType = {
   syncedEnvGroups?: PopulatedEnvGroup[];
   setSyncedEnvGroups?: (values: PopulatedEnvGroup) => void;
   normalEnvVarsOnly?: boolean;
+  availableEnvGroups?: PopulatedEnvGroup[];
 };
 
 type StateType = {
@@ -114,6 +115,13 @@ export default class LoadEnvGroupModal extends Component<PropsType, StateType> {
   };
 
   componentDidMount() {
+    if (Array.isArray(this.props.availableEnvGroups)) {
+      this.setState({
+        envGroups: this.props.availableEnvGroups,
+        loading: false,
+      });
+      return;
+    }
     this.updateEnvGroups();
   }