Browse Source

Add get metadata function and use metadata to add/delete env groups

jnfrati 4 năm trước cách đây
mục cha
commit
d847221477

+ 57 - 5
dashboard/src/components/porter-form/PorterFormContextProvider.tsx

@@ -1,6 +1,7 @@
 import React, { createContext, useContext, useReducer } from "react";
 import {
   GetFinalVariablesFunction,
+  GetMetadataFunction,
   PorterFormAction,
   PorterFormData,
   PorterFormState,
@@ -15,16 +16,17 @@ import {
   ShowIfOr,
 } from "../../shared/types";
 import { getFinalVariablesForStringInput } from "./field-components/Input";
-import { getFinalVariablesForKeyValueArray } from "./field-components/KeyValueArray";
+import {
+  getFinalVariablesForKeyValueArray,
+  getMetadata as getMetadataForKeyValueArray,
+} from "./field-components/KeyValueArray";
 import { Context } from "../../shared/Context";
 import { getFinalVariablesForArrayInput } from "./field-components/ArrayInput";
 import { getFinalVariablesForCheckbox } from "./field-components/Checkbox";
 import { getFinalVariablesForSelect } from "./field-components/Select";
-import api from "shared/api";
 
-interface Props {
+export interface BaseProps {
   rawFormData: PorterFormData;
-  onSubmit: (vars: PorterFormVariableList, cb?: () => void) => void;
   initialVariables?: PorterFormVariableList;
   overrideVariables?: PorterFormVariableList;
   includeHiddenFields?: boolean;
@@ -32,6 +34,21 @@ interface Props {
   doDebug?: boolean;
 }
 
+export interface PropsWithMetadata extends BaseProps {
+  onSubmit: (
+    data: { vars: PorterFormVariableList; metadata: PorterFormVariableList },
+    cb?: () => void
+  ) => void;
+  includeMetadata: true;
+}
+
+export interface PropsWithoutMetadata extends BaseProps {
+  onSubmit: (vars: PorterFormVariableList, cb?: () => void) => void;
+  includeMetadata: false;
+}
+
+export type Props = PropsWithMetadata | PropsWithoutMetadata;
+
 interface ContextProps {
   formData: PorterFormData;
   formState: PorterFormState;
@@ -43,7 +60,7 @@ interface ContextProps {
 }
 
 export const PorterFormContext = createContext<ContextProps | undefined>(
-  undefined!
+  undefined
 );
 const { Provider } = PorterFormContext;
 
@@ -453,6 +470,41 @@ export const PorterFormContextProvider: React.FC<Props> = (props) => {
         })
       )
     );
+
+    if (props.includeMetadata) {
+      const metadataFunctions: Record<string, GetMetadataFunction> = {
+        "key-value-array": getMetadataForKeyValueArray,
+      };
+      const metadataList: PorterFormVariableList[] = [];
+      data?.tabs?.map((tab) =>
+        tab.sections?.map((section) =>
+          section.contents?.map((field) => {
+            if (metadataFunctions[field?.type]) {
+              metadataList.push(
+                metadataFunctions[field?.type](
+                  state.variables,
+                  field,
+                  state.components[field.id]?.state,
+                  context
+                )
+              );
+            }
+          })
+        )
+      );
+
+      if (props.doDebug)
+        console.log({
+          values: Object.assign.apply({}, varList),
+          metadata: Object.assign.apply({}, metadataList),
+        });
+
+      return {
+        values: Object.assign.apply({}, varList),
+        metadata: Object.assign.apply({}, metadataList),
+      };
+    }
+
     if (props.doDebug) console.log(Object.assign.apply({}, varList));
 
     return Object.assign.apply({}, varList);

+ 5 - 2
dashboard/src/components/porter-form/PorterFormWrapper.tsx

@@ -8,7 +8,7 @@ type PropsType = {
   formData: any;
   valuesToOverride?: any;
   isReadOnly?: boolean;
-  onSubmit?: (values: any) => void;
+  onSubmit?: (values: any, cb?: () => void) => void;
   renderTabContents?: (currentTab: string, submitValues?: any) => any;
   leftTabOptions?: { value: string; label: string }[];
   rightTabOptions?: { value: string; label: string }[];
@@ -22,9 +22,10 @@ type PropsType = {
   includeHiddenFields?: boolean;
   hideBottomSpacer?: boolean;
   redirectTabAfterSave?: string;
+  includeMetadata?: boolean;
 };
 
-const PorterFormWrapper: React.FunctionComponent<PropsType> = ({
+const PorterFormWrapper: React.FC<PropsType> = ({
   formData,
   valuesToOverride,
   isReadOnly,
@@ -42,6 +43,7 @@ const PorterFormWrapper: React.FunctionComponent<PropsType> = ({
   includeHiddenFields,
   hideBottomSpacer,
   redirectTabAfterSave,
+  includeMetadata,
 }) => {
   const hashCode = (s: string) => {
     return s?.split("").reduce(function (a, b) {
@@ -79,6 +81,7 @@ const PorterFormWrapper: React.FunctionComponent<PropsType> = ({
         isReadOnly={isReadOnly}
         onSubmit={onSubmit}
         includeHiddenFields={includeHiddenFields}
+        includeMetadata={includeMetadata}
       >
         <PorterForm
           showStateDebugger={showStateDebugger}

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

@@ -1,6 +1,7 @@
 import React, { useContext, useEffect, useState } from "react";
 import {
   GetFinalVariablesFunction,
+  GetMetadataFunction,
   KeyValueArrayField,
   KeyValueArrayFieldState,
   PopulatedEnvGroup,
@@ -13,7 +14,7 @@ import Modal from "../../../main/home/modals/Modal";
 import LoadEnvGroupModal from "../../../main/home/modals/LoadEnvGroupModal";
 import EnvEditorModal from "../../../main/home/modals/EnvEditorModal";
 import { hasSetValue } from "../utils";
-import _, { omit } from "lodash";
+import _, { differenceBy, omit } from "lodash";
 import Helper from "components/form-components/Helper";
 import Heading from "components/form-components/Heading";
 import Loading from "components/Loading";
@@ -565,6 +566,31 @@ export const getFinalVariablesForKeyValueArray: GetFinalVariablesFunction = (
   }
 };
 
+type KeyValueArrayMetadata = {
+  added: { name: string }[];
+  deleted: { name: string }[];
+};
+
+export const getMetadata: GetMetadataFunction<KeyValueArrayMetadata> = (
+  vars,
+  props: KeyValueArrayField,
+  state: KeyValueArrayFieldState
+) => {
+  const originalSyncedEnvGroups: { name: string }[] =
+    props.value[0]?.synced || [];
+  const currSynced = state.synced_env_groups || [];
+
+  let obj: KeyValueArrayMetadata = {
+    added: [],
+    deleted: [],
+  };
+
+  obj.added = differenceBy(currSynced, originalSyncedEnvGroups, "name");
+  obj.deleted = differenceBy(originalSyncedEnvGroups, currSynced, "name");
+
+  return obj;
+};
+
 export default KeyValueArray;
 
 const ExpandableEnvGroup: React.FC<{

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

@@ -301,3 +301,10 @@ export type GetFinalVariablesFunction = (
   state: PorterFormFieldFieldState,
   context: Partial<ContextProps>
 ) => PorterFormVariableList;
+
+export type GetMetadataFunction<T = unknown> = (
+  vars: PorterFormVariableList,
+  props: FormField,
+  state: PorterFormFieldFieldState,
+  context: Partial<ContextProps>
+) => T;

+ 6 - 23
dashboard/src/main/home/cluster-dashboard/expanded-chart/ExpandedChart.tsx

@@ -221,7 +221,9 @@ const ExpandedChart: React.FC<Props> = (props) => {
     }
   };
 
-  const onSubmit = async (rawValues: any) => {
+  const onSubmit = async (props: any) => {
+    const rawValues = props.values;
+
     // console.log("raw", rawValues);
     // Convert dotted keys to nested objects
     let values: any = {};
@@ -244,29 +246,9 @@ const ExpandedChart: React.FC<Props> = (props) => {
       ...values,
     });
 
-    const oldSyncedEnvGroups =
-      props.currentChart.config?.container?.env?.synced || [];
-    const newSyncedEnvGroups = values?.container?.env?.synced || [];
-
-    const deletedEnvGroups = onlyInLeft<{
-      keys: Array<any>;
-      name: string;
-      version: number;
-    }>(
-      oldSyncedEnvGroups,
-      newSyncedEnvGroups,
-      (oldVal, newVal) => oldVal.name === newVal.name
-    );
+    const deletedEnvGroups = props?.metadata?.deleted || [];
 
-    const addedEnvGroups = onlyInLeft<{
-      keys: Array<any>;
-      name: string;
-      version: number;
-    }>(
-      newSyncedEnvGroups,
-      oldSyncedEnvGroups,
-      (oldVal, newVal) => oldVal.name === newVal.name
-    );
+    const addedEnvGroups = props?.metadata?.added || [];
 
     const addApplicationToEnvGroupPromises = addedEnvGroups.map(
       (envGroup: any) => {
@@ -869,6 +851,7 @@ const ExpandedChart: React.FC<Props> = (props) => {
                       !isAuthorized("application", "", ["get", "update"])
                     }
                     onSubmit={onSubmit}
+                    includeMetadata
                     rightTabOptions={rightTabOptions}
                     leftTabOptions={leftTabOptions}
                     color={isPreview ? "#f5cb42" : null}

+ 8 - 6
dashboard/src/main/home/cluster-dashboard/expanded-chart/ExpandedJobChart.tsx

@@ -94,10 +94,11 @@ export const ExpandedJobChartFC: React.FC<{
 
   const leftTabOptions = [{ label: "Jobs", value: "jobs" }];
 
-  const processValuesToUpdateChart = (newConfig?: any) => (
-    currentChart: ChartType
-  ) => {
-    // return "";
+  const processValuesToUpdateChart = (props?: {
+    values: any;
+    metadata: any;
+  }) => (currentChart: ChartType) => {
+    const newConfig = props.values;
     let conf: string;
     let values = currentChart.config;
 
@@ -117,7 +118,7 @@ export const ExpandedJobChartFC: React.FC<{
       conf = yaml.dump(values, { forceQuotes: true });
     }
 
-    return conf;
+    return { yaml: conf, metadata: props.metadata };
   };
 
   const handleDeleteChart = async () => {
@@ -250,7 +251,7 @@ export const ExpandedJobChartFC: React.FC<{
     }
 
     if (currentTab === "build-settings") {
-      return <BuildSettingsTab chart={chart} />;
+      return <BuildSettingsTab chart={chart} isPreviousVersion={disableForm} />;
     }
 
     if (
@@ -357,6 +358,7 @@ export const ExpandedJobChartFC: React.FC<{
               onSubmit={(formValues) =>
                 updateChart(processValuesToUpdateChart(formValues))
               }
+              includeMetadata
               leftTabOptions={leftTabOptions}
               rightTabOptions={rightTabOptions}
               saveValuesStatus={saveStatus}

+ 8 - 25
dashboard/src/shared/hooks/useChart.ts

@@ -125,34 +125,17 @@ export const useChart = (oldChart: ChartType, closeChart: () => void) => {
    */
   const updateChart = async (
     processValues:
-      | ((chart: ChartType) => string)
-      | ((chart: ChartType, oldChart?: ChartType) => string)
+      | ((chart: ChartType) => { yaml: string; metadata: any })
+      | ((
+          chart: ChartType,
+          oldChart?: ChartType
+        ) => { yaml: string; metadata: any })
   ) => {
     setSaveStatus("loading");
-    const values = processValues(chart, oldChart);
+    const { yaml: values, metadata } = processValues(chart, oldChart);
 
-    const oldSyncedEnvGroups = oldChart.config?.container?.env?.synced || [];
-    const newSyncedEnvGroups = chart.config?.container?.env?.synced || [];
-
-    const deletedEnvGroups = onlyInLeft<{
-      keys: Array<any>;
-      name: string;
-      version: number;
-    }>(
-      oldSyncedEnvGroups,
-      newSyncedEnvGroups,
-      (oldVal, newVal) => oldVal.name === newVal.name
-    );
-
-    const addedEnvGroups = onlyInLeft<{
-      keys: Array<any>;
-      name: string;
-      version: number;
-    }>(
-      newSyncedEnvGroups,
-      oldSyncedEnvGroups,
-      (oldVal, newVal) => oldVal.name === newVal.name
-    );
+    const addedEnvGroups = metadata?.added || [];
+    const deletedEnvGroups = metadata?.deleted || [];
 
     const addApplicationToEnvGroupPromises = addedEnvGroups.map(
       (envGroup: any) => {