ソースを参照

tie project query param set to context setter

jusrhee 5 年 前
コミット
8c32ad31e7

+ 6 - 10
dashboard/src/App.tsx

@@ -1,18 +1,14 @@
 import React, { Component } from "react";
+import { BrowserRouter } from "react-router-dom";
 
-import { ContextProvider } from "./shared/Context";
-import Main from "./main/Main";
+import MainWrapper from "./main/MainWrapper";
 
-type PropsType = {};
-
-type StateType = {};
-
-export default class App extends Component<PropsType, StateType> {
+export default class App extends Component {
   render() {
     return (
-      <ContextProvider>
-        <Main />
-      </ContextProvider>
+      <BrowserRouter>
+        <MainWrapper />
+      </BrowserRouter>
     );
   }
 }

+ 1 - 1
dashboard/src/main/Main.tsx

@@ -210,7 +210,7 @@ export default class Main extends Component<PropsType, StateType> {
     return (
       <StyledMain>
         <GlobalStyle />
-        <BrowserRouter>{this.renderMain()}</BrowserRouter>
+        {this.renderMain()}
         <CurrentError currentError={this.context.currentError} />
       </StyledMain>
     );

+ 23 - 0
dashboard/src/main/MainWrapper.tsx

@@ -0,0 +1,23 @@
+import React, { Component } from "react";
+import { BrowserRouter } from "react-router-dom";
+
+import { ContextProvider } from "../shared/Context";
+import Main from "./Main";
+import { RouteComponentProps, withRouter } from "react-router";
+
+type PropsType = RouteComponentProps & {};
+
+type StateType = {};
+
+class MainWrapper extends Component<PropsType, StateType> {
+  render() {
+    let { history, location } = this.props;
+    return (
+      <ContextProvider history={history} location={location}>
+        <Main />
+      </ContextProvider>
+    );
+  }
+}
+
+export default withRouter(MainWrapper);

+ 15 - 19
dashboard/src/main/home/Home.tsx

@@ -75,7 +75,9 @@ class Home extends Component<PropsType, StateType> {
           creating = res.data[i].status === "creating";
         }
         if (creating) {
-          pushFiltered(this.props, "/dashboard?tab=provisioner", ["project_id"]);
+          pushFiltered(this.props, "/dashboard?tab=provisioner", [
+            "project_id",
+          ]);
         } else if (this.state.ghRedirect) {
           pushFiltered(this.props, "/integrations", ["project_id"]);
           this.setState({ ghRedirect: false });
@@ -97,16 +99,8 @@ class Home extends Component<PropsType, StateType> {
       });
   };
 
-  setCurrentProject = (project: ProjectType) => {
-    this.context.setCurrentProject(project, () => {
-      if (project) {
-        pushQueryParams(this.props, { project_id: project.id.toString() });
-      }
-    });
-  }
-
   getProjects = (id?: number) => {
-    let { user, setProjects } = this.context;
+    let { user, setProjects, setCurrentProject } = this.context;
     let { currentProject } = this.props;
     let queryString = window.location.search;
     let urlParams = new URLSearchParams(queryString);
@@ -131,7 +125,7 @@ class Home extends Component<PropsType, StateType> {
                   foundProject = project;
                 }
               });
-              this.setCurrentProject(foundProject);
+              setCurrentProject(foundProject || res.data[0]);
             }
             if (!foundProject) {
               res.data.forEach((project: ProjectType, i: number) => {
@@ -142,9 +136,7 @@ class Home extends Component<PropsType, StateType> {
                   foundProject = project;
                 }
               });
-              this.setCurrentProject(
-                foundProject ? foundProject : res.data[0]
-              );
+              setCurrentProject(foundProject || res.data[0]);
               this.initializeView();
             }
           }
@@ -190,7 +182,9 @@ class Home extends Component<PropsType, StateType> {
         project_id: this.props.currentProject.id,
       }
     );
-    return pushFiltered(this.props, "/dashboard?tab=provisioner", ["project_id"]);
+    return pushFiltered(this.props, "/dashboard?tab=provisioner", [
+      "project_id",
+    ]);
   };
 
   checkDO = () => {
@@ -220,7 +214,9 @@ class Home extends Component<PropsType, StateType> {
             });
           } else if (infras[0] === "docr") {
             this.provisionDOCR(tgtIntegration.id, tier, () => {
-              pushFiltered(this.props, "/dashboard?tab=provisioner", ["project_id"]);
+              pushFiltered(this.props, "/dashboard?tab=provisioner", [
+                "project_id",
+              ]);
             });
           } else {
             this.provisionDOKS(tgtIntegration.id, region, clusterName);
@@ -385,16 +381,16 @@ class Home extends Component<PropsType, StateType> {
   };
 
   projectOverlayCall = () => {
-    let { user, setProjects } = this.context;
+    let { user, setProjects, setCurrentProject } = this.context;
     api
       .getProjects("<token>", {}, { id: user.userId })
       .then((res) => {
         if (res.data) {
           setProjects(res.data);
           if (res.data.length > 0) {
-            this.setCurrentProject(res.data[0]);
+            setCurrentProject(res.data[0]);
           } else {
-            this.setCurrentProject(null);
+            setCurrentProject(null);
             pushFiltered(this.props, "/new-project", ["project_id"]);
           }
           this.context.setCurrentModal(null, null);

+ 3 - 1
dashboard/src/main/home/cluster-dashboard/ClusterDashboard.tsx

@@ -102,7 +102,9 @@ class ClusterDashboard extends Component<PropsType, StateType> {
     return (
       <>
         <ControlRow>
-          <Button onClick={() => pushFiltered(this.props, "/launch", ["project_id"])}>
+          <Button
+            onClick={() => pushFiltered(this.props, "/launch", ["project_id"])}
+          >
             <i className="material-icons">add</i> Launch Template
           </Button>
           <SortFilterWrapper>

+ 9 - 7
dashboard/src/main/home/cluster-dashboard/expanded-chart/ExpandedJobChart.tsx

@@ -181,8 +181,8 @@ export default class ExpandedJobChart extends Component<PropsType, StateType> {
   };
 
   setupCronJobWebsocket = (chart: ChartType) => {
-    let releaseName = chart.name
-    let releaseNamespace = chart.namespace
+    let releaseName = chart.name;
+    let releaseNamespace = chart.namespace;
 
     let { currentCluster, currentProject } = this.context;
     let protocol = process.env.NODE_ENV == "production" ? "wss" : "ws";
@@ -204,9 +204,11 @@ export default class ExpandedJobChart extends Component<PropsType, StateType> {
         this.state.imageIsPlaceholder
       ) {
         // filter job belonging to chart
-        let relNameAnn = event.Object?.metadata?.annotations["meta.helm.sh/release-name"]
-        let relNamespaceAnn = event.Object?.metadata?.annotations["meta.helm.sh/release-namespace"]
-        
+        let relNameAnn =
+          event.Object?.metadata?.annotations["meta.helm.sh/release-name"];
+        let relNamespaceAnn =
+          event.Object?.metadata?.annotations["meta.helm.sh/release-namespace"];
+
         if (
           relNameAnn &&
           relNamespaceAnn &&
@@ -217,7 +219,7 @@ export default class ExpandedJobChart extends Component<PropsType, StateType> {
           let newestImage =
             event.Object?.spec?.jobTemplate?.spec?.template?.spec?.containers[0]
               ?.image;
-          console.log("newest image", newestImage)
+          console.log("newest image", newestImage);
           if (
             newestImage &&
             newestImage !== "porterdev/hello-porter-job" &&
@@ -366,7 +368,7 @@ export default class ExpandedJobChart extends Component<PropsType, StateType> {
       newestImage !== "public.ecr.aws/o1j4x7p4/hello-porter-job" &&
       newestImage !== "public.ecr.aws/o1j4x7p4/hello-porter-job:latest"
     ) {
-      console.log("set to false on sorting")
+      console.log("set to false on sorting");
       this.setState({ jobs, newestImage, imageIsPlaceholder: false });
     } else {
       this.setState({ jobs });

+ 11 - 3
dashboard/src/main/home/integrations/IntegrationCategories.tsx

@@ -130,7 +130,9 @@ class IntegrationCategories extends Component<PropsType, StateType> {
             <Flex>
               <i
                 className="material-icons"
-                onClick={() => pushFiltered(this.props, "/integrations", ["project_id"])}
+                onClick={() =>
+                  pushFiltered(this.props, "/integrations", ["project_id"])
+                }
               >
                 keyboard_backspace
               </i>
@@ -142,7 +144,11 @@ class IntegrationCategories extends Component<PropsType, StateType> {
                 this.context.setCurrentModal("IntegrationsModal", {
                   category: currentCategory,
                   setCurrentIntegration: (x: string) =>
-                    pushFiltered(this.props, `/integrations/${this.props.category}/create/${x}`, ["project_id"]),
+                    pushFiltered(
+                      this.props,
+                      `/integrations/${this.props.category}/create/${x}`,
+                      ["project_id"]
+                    ),
                 })
               }
             >
@@ -171,7 +177,9 @@ class IntegrationCategories extends Component<PropsType, StateType> {
             <Flex>
               <i
                 className="material-icons"
-                onClick={() => pushFiltered(this.props, "/integrations", ["project_id"])}
+                onClick={() =>
+                  pushFiltered(this.props, "/integrations", ["project_id"])
+                }
               >
                 keyboard_backspace
               </i>

+ 10 - 4
dashboard/src/main/home/integrations/Integrations.tsx

@@ -41,7 +41,9 @@ class Integrations extends Component<PropsType, StateType> {
                     <i
                       className="material-icons"
                       onClick={() =>
-                        pushFiltered(this.props, `/integrations/${category}`, ["project_id"])
+                        pushFiltered(this.props, `/integrations/${category}`, [
+                          "project_id",
+                        ])
                       }
                     >
                       keyboard_backspace
@@ -53,7 +55,9 @@ class Integrations extends Component<PropsType, StateType> {
                 <CreateIntegrationForm
                   integrationName={integration}
                   closeForm={() => {
-                    pushFiltered(this.props, `/integrations/${category}`, ["project_id"]);
+                    pushFiltered(this.props, `/integrations/${category}`, [
+                      "project_id",
+                    ]);
                   }}
                 />
                 <Br />
@@ -66,7 +70,7 @@ class Integrations extends Component<PropsType, StateType> {
           render={(rp) => {
             const currentCategory = rp.match.params.category;
             if (!IntegrationCategoryStrings.includes(currentCategory)) {
-              pushFiltered(this.props, "/integrations", ["project_id"])
+              pushFiltered(this.props, "/integrations", ["project_id"]);
             }
             return (
               <IntegrationCategories
@@ -84,7 +88,9 @@ class Integrations extends Component<PropsType, StateType> {
             <IntegrationList
               currentCategory={""}
               integrations={["kubernetes", "registry", "repo"]}
-              setCurrent={(x) => pushFiltered(this.props, `/integrations/${x}`, ["project_id"])}
+              setCurrent={(x) =>
+                pushFiltered(this.props, `/integrations/${x}`, ["project_id"])
+              }
               isCategory={true}
               updateIntegrationList={() => {}}
             />

+ 8 - 2
dashboard/src/main/home/launch/expanded-template/LaunchTemplate.tsx

@@ -560,7 +560,11 @@ class LaunchTemplate extends Component<PropsType, StateType> {
             Specify the container image you would like to connect to this
             template.
             <Highlight
-              onClick={() => pushFiltered(this.props, "integrations/registry", ["project_id"])}
+              onClick={() =>
+                pushFiltered(this.props, "integrations/registry", [
+                  "project_id",
+                ])
+              }
             >
               Manage Docker registries
             </Highlight>
@@ -586,7 +590,9 @@ class LaunchTemplate extends Component<PropsType, StateType> {
           <Subtitle>
             Provide a repo folder to use as source.
             <Highlight
-              onClick={() => pushFiltered(this.props, "/integrations/repo", ["project_id"])}
+              onClick={() =>
+                pushFiltered(this.props, "/integrations/repo", ["project_id"])
+              }
             >
               Manage Git repos
             </Highlight>

+ 10 - 2
dashboard/src/main/home/launch/launch-flow/SourcePage.tsx

@@ -100,7 +100,11 @@ class SourcePage extends Component<PropsType, StateType> {
             Specify the container image you would like to connect to this
             template.
             <Highlight
-              onClick={() => pushFiltered(this.props, "integrations/registry", ["project_id"])}
+              onClick={() =>
+                pushFiltered(this.props, "integrations/registry", [
+                  "project_id",
+                ])
+              }
             >
               Manage Docker registries
             </Highlight>
@@ -146,7 +150,11 @@ class SourcePage extends Component<PropsType, StateType> {
         </CloseButton>
         <Subtitle>
           Provide a repo folder to use as source.
-          <Highlight onClick={() => pushFiltered(this.props, "/integrations/repo", ["project_id"])}>
+          <Highlight
+            onClick={() =>
+              pushFiltered(this.props, "/integrations/repo", ["project_id"])
+            }
+          >
             Manage Git repos
           </Highlight>
           <Required>*</Required>

+ 8 - 16
dashboard/src/main/home/provisioner/AWSFormSection.tsx

@@ -170,21 +170,11 @@ class AWSFormSection extends Component<PropsType, StateType> {
     this.props.handleError();
   };
 
-  setCurrentProject = (project: ProjectType, callback?: any) => {
-    this.context.setCurrentProject(project, () => {
-      if (project) {
-        pushQueryParams(this.props, { project_id: project.id.toString() });
-      }
-      callback && callback();
-    });
-  }
-
   // Step 1: Create a project
   // TODO: promisify this function
   createProject = (callback?: any) => {
-    console.log("Creating project");
-    let { projectName, handleError } = this.props;
-    let { user, setProjects, currentProject } = this.context;
+    let { projectName } = this.props;
+    let { user, setProjects, setCurrentProject } = this.context;
 
     api
       .createProject("<token>", { name: projectName }, {})
@@ -202,7 +192,7 @@ class AWSFormSection extends Component<PropsType, StateType> {
           )
           .then((res) => {
             setProjects(res.data);
-            this.setCurrentProject(proj, () => {
+            setCurrentProject(proj, () => {
               callback && callback();
             });
           })
@@ -271,7 +261,7 @@ class AWSFormSection extends Component<PropsType, StateType> {
           { id: currentProject.id }
         )
       )
-      .then(() => 
+      .then(() =>
         pushFiltered(this.props, "dashboard?tab=provisioner", ["project_id"])
       )
       .catch(this.catchError);
@@ -303,8 +293,10 @@ class AWSFormSection extends Component<PropsType, StateType> {
       } else if (selectedInfras[0].value === "ecr") {
         // Case: project DNE, only provision ECR
         this.createProject(() =>
-          this.provisionECR().then(() => 
-            pushFiltered(this.props, "dashboard?tab=provisioner", ["project_id"])
+          this.provisionECR().then(() =>
+            pushFiltered(this.props, "dashboard?tab=provisioner", [
+              "project_id",
+            ])
           )
         );
       } else {

+ 2 - 12
dashboard/src/main/home/provisioner/DOFormSection.tsx

@@ -132,20 +132,10 @@ export default class DOFormSection extends Component<PropsType, StateType> {
     return;
   };
 
-  setCurrentProject = (project: ProjectType, callback?: any) => {
-    this.context.setCurrentProject(project, () => {
-      if (project) {
-        pushQueryParams(this.props, { project_id: project.id.toString() });
-      }
-      callback && callback();
-    });
-  }
-
   // Step 1: Create a project
   createProject = (callback?: any) => {
-    console.log("Creating project");
     let { projectName } = this.props;
-    let { user, setProjects } = this.context;
+    let { user, setProjects, setCurrentProject } = this.context;
 
     api
       .createProject("<token>", { name: projectName }, {})
@@ -162,7 +152,7 @@ export default class DOFormSection extends Component<PropsType, StateType> {
           }
         );
         setProjects(res_1.data);
-        this.setCurrentProject(proj);
+        setCurrentProject(proj);
         callback && callback(proj.id);
       })
       .catch(this.catchError);

+ 2 - 11
dashboard/src/main/home/provisioner/ExistingClusterSection.tsx

@@ -23,18 +23,9 @@ class ExistingClusterSection extends Component<PropsType, StateType> {
     buttonStatus: "",
   };
 
-  setCurrentProject = (project: ProjectType, callback?: any) => {
-    this.context.setCurrentProject(project, () => {
-      if (project) {
-        pushQueryParams(this.props, { project_id: project.id.toString() });
-      }
-      callback && callback();
-    });
-  }
-
   onCreateProject = () => {
     let { projectName } = this.props;
-    let { user, setProjects } = this.context;
+    let { user, setProjects, setCurrentProject } = this.context;
 
     this.setState({ buttonStatus: "loading" });
     api
@@ -55,7 +46,7 @@ class ExistingClusterSection extends Component<PropsType, StateType> {
             let proj = res.data.find((el: ProjectType) => {
               return el.name === projectName;
             });
-            this.setCurrentProject(proj);
+            setCurrentProject(proj);
             pushFiltered(this.props, "dashboard?tab=overview", ["project_id"]);
           }
         }

+ 6 - 14
dashboard/src/main/home/provisioner/GCPFormSection.tsx

@@ -163,20 +163,10 @@ class GCPFormSection extends Component<PropsType, StateType> {
     this.props.handleError();
   };
 
-  setCurrentProject = (project: ProjectType, callback?: any) => {
-    this.context.setCurrentProject(project, () => {
-      if (project) {
-        pushQueryParams(this.props, { project_id: project.id.toString() });
-      }
-      callback && callback();
-    });
-  }
-
   // Step 1: Create a project
   createProject = (callback?: any) => {
-    console.log("Creating project");
-    let { projectName, handleError } = this.props;
-    let { user, setProjects } = this.context;
+    let { projectName } = this.props;
+    let { user, setProjects, setCurrentProject } = this.context;
 
     api
       .createProject("<token>", { name: projectName }, {})
@@ -195,7 +185,7 @@ class GCPFormSection extends Component<PropsType, StateType> {
           )
           .then((res) => {
             setProjects(res.data);
-            this.setCurrentProject(proj);
+            setCurrentProject(proj);
             callback && callback();
           })
           .catch(this.catchError);
@@ -262,7 +252,9 @@ class GCPFormSection extends Component<PropsType, StateType> {
           } else if (selectedInfras[0].value === "gcr") {
             // Case: project exists, only provision GCR
             this.provisionGCR(id).then(() =>
-              pushFiltered(this.props, "dashboard?tab=provisioner", ["project_id"])
+              pushFiltered(this.props, "dashboard?tab=provisioner", [
+                "project_id",
+              ])
             );
           } else {
             // Case: project exists, only provision GKE

+ 5 - 10
dashboard/src/main/home/sidebar/ProjectSection.tsx

@@ -44,15 +44,8 @@ class ProjectSection extends Component<PropsType, StateType> {
     }
   };
 
-  setCurrentProject = (project: ProjectType) => {
-    this.context.setCurrentProject(project, () => {
-      if (project) {
-        pushQueryParams(this.props, { project_id: project.id.toString() });
-      }
-    });
-  }
-
   renderOptionList = () => {
+    let { setCurrentProject } = this.context;
     return this.props.projects.map((project: ProjectType, i: number) => {
       return (
         <Option
@@ -60,7 +53,7 @@ class ProjectSection extends Component<PropsType, StateType> {
           selected={project.name === this.props.currentProject.name}
           onClick={() => {
             this.setState({ expanded: false });
-            this.setCurrentProject(project);
+            setCurrentProject(project);
             pushFiltered(this.props, "/dashboard", ["project_id"]);
           }}
         >
@@ -121,7 +114,9 @@ class ProjectSection extends Component<PropsType, StateType> {
       );
     }
     return (
-      <InitializeButton onClick={() => pushFiltered(this.props, "new-project", ["project_id"])}>
+      <InitializeButton
+        onClick={() => pushFiltered(this.props, "new-project", ["project_id"])}
+      >
         <Plus>+</Plus> Create a Project
       </InitializeButton>
     );

+ 7 - 11
dashboard/src/main/home/sidebar/Sidebar.tsx

@@ -106,7 +106,7 @@ class Sidebar extends Component<PropsType, StateType> {
         <>
           <NavButton
             selected={currentView === "applications"}
-            onClick={() => 
+            onClick={() =>
               pushFiltered(this.props, "/applications", ["project_id"])
             }
           >
@@ -115,16 +115,14 @@ class Sidebar extends Component<PropsType, StateType> {
           </NavButton>
           <NavButton
             selected={currentView === "jobs"}
-            onClick={() => 
-              pushFiltered(this.props, "/jobs", ["project_id"])
-            }
+            onClick={() => pushFiltered(this.props, "/jobs", ["project_id"])}
           >
             <Img src={monojob} />
             Jobs
           </NavButton>
           <NavButton
             selected={currentView === "env-groups"}
-            onClick={() => 
+            onClick={() =>
               pushFiltered(this.props, "/env-groups", ["project_id"])
             }
           >
@@ -146,7 +144,7 @@ class Sidebar extends Component<PropsType, StateType> {
           <NavButton
             onClick={() =>
               currentView !== "provisioner" &&
-                pushFiltered(this.props, "/dashboard", ["project_id"])
+              pushFiltered(this.props, "/dashboard", ["project_id"])
             }
             selected={
               currentView === "dashboard" || currentView === "provisioner"
@@ -156,9 +154,7 @@ class Sidebar extends Component<PropsType, StateType> {
             Dashboard
           </NavButton>
           <NavButton
-            onClick={() => 
-              pushFiltered(this.props, "/launch", ["project_id"])
-            }
+            onClick={() => pushFiltered(this.props, "/launch", ["project_id"])}
             selected={currentView === "launch"}
           >
             <Img src={rocket} />
@@ -166,7 +162,7 @@ class Sidebar extends Component<PropsType, StateType> {
           </NavButton>
           <NavButton
             selected={currentView === "integrations"}
-            onClick={() => 
+            onClick={() =>
               pushFiltered(this.props, "/integrations", ["project_id"])
             }
           >
@@ -177,7 +173,7 @@ class Sidebar extends Component<PropsType, StateType> {
             return obj.user_id === this.context.user.userId;
           })[0].kind === "admin" && (
             <NavButton
-              onClick={() => 
+              onClick={() =>
                 pushFiltered(this.props, "/project-settings", ["project_id"])
               }
               selected={this.props.currentView === "project-settings"}

+ 10 - 2
dashboard/src/shared/Context.tsx

@@ -1,12 +1,20 @@
 import React, { Component } from "react";
 
 import { ProjectType, ClusterType, CapabilityType } from "shared/types";
+import { pushQueryParams } from "shared/routing";
 
 const Context = React.createContext({});
 
 const { Provider } = Context;
 const ContextConsumer = Context.Consumer;
 
+type PropsType = {
+  history: any;
+  location: any;
+};
+
+type StateType = any;
+
 /**
  * Component managing a universal (application-wide) data store.
  *
@@ -18,7 +26,7 @@ const ContextConsumer = Context.Consumer;
  *    components consuming Context)
  * 4) As a rule of thumb, Context should not be used for UI-related state
  */
-class ContextProvider extends Component {
+class ContextProvider extends Component<PropsType, StateType> {
   state = {
     currentModal: null as string | null,
     currentModalData: null as any,
@@ -41,7 +49,7 @@ class ContextProvider extends Component {
     },
     currentProject: null as ProjectType | null,
     setCurrentProject: (currentProject: ProjectType, callback?: any) => {
-      console.log("certify", currentProject);
+      pushQueryParams(this.props, { project_id: currentProject.id.toString() });
       if (currentProject) {
         localStorage.setItem("currentProject", currentProject.id.toString());
       } else {

+ 3 - 6
dashboard/src/shared/routing.tsx

@@ -23,10 +23,7 @@ export const PorterUrls = [
   "jobs",
 ];
 
-export const pushQueryParams = (
-  props: any,
-  params: any,
-) => {
+export const pushQueryParams = (props: any, params: any) => {
   let { location, history } = props;
   const urlParams = new URLSearchParams(location.search);
   Object.keys(params)?.forEach((key: string) => {
@@ -41,7 +38,7 @@ export const pushQueryParams = (
 export const pushFiltered = (
   props: any, // Props for retrieving history and location
   pathname: string, // Path to redirect to
-  keys: string[], // Query params to preserve during redirect
+  keys: string[] // Query params to preserve during redirect
 ) => {
   let { location, history } = props;
   let urlParams = new URLSearchParams(location.search);
@@ -54,4 +51,4 @@ export const pushFiltered = (
     pathname,
     search: newUrlParams.toString(),
   });
-}
+};