Explorar o código

project routing by query param

jusrhee %!s(int64=5) %!d(string=hai) anos
pai
achega
2cf12766c1

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

@@ -5,7 +5,7 @@ import styled from "styled-components";
 import api from "shared/api";
 import api from "shared/api";
 import { H } from "highlight.run";
 import { H } from "highlight.run";
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
-import { PorterUrl } from "shared/routing";
+import { PorterUrl, pushQueryParams, pushFiltered } from "shared/routing";
 import { ClusterType, ProjectType } from "shared/types";
 import { ClusterType, ProjectType } from "shared/types";
 
 
 import ConfirmOverlay from "components/ConfirmOverlay";
 import ConfirmOverlay from "components/ConfirmOverlay";
@@ -75,9 +75,9 @@ class Home extends Component<PropsType, StateType> {
           creating = res.data[i].status === "creating";
           creating = res.data[i].status === "creating";
         }
         }
         if (creating) {
         if (creating) {
-          this.props.history.push("dashboard?tab=provisioner");
+          pushFiltered(this.props, "/dashboard?tab=provisioner", ["project_id"]);
         } else if (this.state.ghRedirect) {
         } else if (this.state.ghRedirect) {
-          this.props.history.push("integrations");
+          pushFiltered(this.props, "/integrations", ["project_id"]);
           this.setState({ ghRedirect: false });
           this.setState({ ghRedirect: false });
         }
         }
       });
       });
@@ -97,15 +97,30 @@ 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) => {
   getProjects = (id?: number) => {
     let { user, setProjects } = this.context;
     let { user, setProjects } = this.context;
     let { currentProject } = this.props;
     let { currentProject } = this.props;
+    let queryString = window.location.search;
+    let urlParams = new URLSearchParams(queryString);
+    let projectId = urlParams.get("project_id");
+    if (!projectId && currentProject?.id) {
+      pushQueryParams(this.props, { project_id: currentProject.id.toString() });
+    }
+
     api
     api
       .getProjects("<token>", {}, { id: user.userId })
       .getProjects("<token>", {}, { id: user.userId })
       .then((res) => {
       .then((res) => {
         if (res.data) {
         if (res.data) {
           if (res.data.length === 0) {
           if (res.data.length === 0) {
-            this.props.history.push("new-project");
+            pushFiltered(this.props, "/new-project", ["project_id"]);
           } else if (res.data.length > 0 && !currentProject) {
           } else if (res.data.length > 0 && !currentProject) {
             setProjects(res.data);
             setProjects(res.data);
 
 
@@ -116,7 +131,7 @@ class Home extends Component<PropsType, StateType> {
                   foundProject = project;
                   foundProject = project;
                 }
                 }
               });
               });
-              this.context.setCurrentProject(foundProject);
+              this.setCurrentProject(foundProject);
             }
             }
             if (!foundProject) {
             if (!foundProject) {
               res.data.forEach((project: ProjectType, i: number) => {
               res.data.forEach((project: ProjectType, i: number) => {
@@ -127,7 +142,7 @@ class Home extends Component<PropsType, StateType> {
                   foundProject = project;
                   foundProject = project;
                 }
                 }
               });
               });
-              this.context.setCurrentProject(
+              this.setCurrentProject(
                 foundProject ? foundProject : res.data[0]
                 foundProject ? foundProject : res.data[0]
               );
               );
               this.initializeView();
               this.initializeView();
@@ -175,7 +190,7 @@ class Home extends Component<PropsType, StateType> {
         project_id: this.props.currentProject.id,
         project_id: this.props.currentProject.id,
       }
       }
     );
     );
-    return this.props.history.push("dashboard?tab=provisioner");
+    return pushFiltered(this.props, "/dashboard?tab=provisioner", ["project_id"]);
   };
   };
 
 
   checkDO = () => {
   checkDO = () => {
@@ -205,7 +220,7 @@ class Home extends Component<PropsType, StateType> {
             });
             });
           } else if (infras[0] === "docr") {
           } else if (infras[0] === "docr") {
             this.provisionDOCR(tgtIntegration.id, tier, () => {
             this.provisionDOCR(tgtIntegration.id, tier, () => {
-              this.props.history.push("dashboard?tab=provisioner");
+              pushFiltered(this.props, "/dashboard?tab=provisioner", ["project_id"]);
             });
             });
           } else {
           } else {
             this.provisionDOKS(tgtIntegration.id, region, clusterName);
             this.provisionDOKS(tgtIntegration.id, region, clusterName);
@@ -238,9 +253,8 @@ class Home extends Component<PropsType, StateType> {
     }
     }
 
 
     let provision = urlParams.get("provision");
     let provision = urlParams.get("provision");
-    let defaultProjectId = null;
+    let defaultProjectId = parseInt(urlParams.get("project_id"));
     if (provision === "do") {
     if (provision === "do") {
-      defaultProjectId = parseInt(urlParams.get("project_id"));
       this.setState({ handleDO: true });
       this.setState({ handleDO: true });
       this.checkDO();
       this.checkDO();
     }
     }
@@ -307,7 +321,7 @@ class Home extends Component<PropsType, StateType> {
     } else if (!currentCluster) {
     } else if (!currentCluster) {
       return <Loading />;
       return <Loading />;
     }
     }
-
+    console.log("current route", this.props.currentRoute);
     return (
     return (
       <DashboardWrapper>
       <DashboardWrapper>
         <ClusterDashboard
         <ClusterDashboard
@@ -378,10 +392,10 @@ class Home extends Component<PropsType, StateType> {
         if (res.data) {
         if (res.data) {
           setProjects(res.data);
           setProjects(res.data);
           if (res.data.length > 0) {
           if (res.data.length > 0) {
-            this.context.setCurrentProject(res.data[0]);
+            this.setCurrentProject(res.data[0]);
           } else {
           } else {
-            this.context.setCurrentProject(null);
-            this.props.history.push("new-project");
+            this.setCurrentProject(null);
+            pushFiltered(this.props, "/new-project", ["project_id"]);
           }
           }
           this.context.setCurrentModal(null, null);
           this.context.setCurrentModal(null, null);
         }
         }
@@ -460,7 +474,7 @@ class Home extends Component<PropsType, StateType> {
       })
       })
       .catch(console.log);
       .catch(console.log);
     setCurrentModal(null, null);
     setCurrentModal(null, null);
-    this.props.history.push("dashboard?tab=overview");
+    pushFiltered(this.props, "/dashboard", []);
   };
   };
 
 
   render() {
   render() {

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

@@ -4,8 +4,8 @@ import monojob from "assets/monojob.png";
 import monoweb from "assets/monoweb.png";
 import monoweb from "assets/monoweb.png";
 
 
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
-import { ChartType, ClusterType } from "shared/types";
-import { PorterUrl } from "shared/routing";
+import { ChartType, ClusterType, ProjectType } from "shared/types";
+import { PorterUrl, pushFiltered } from "shared/routing";
 
 
 import ChartList from "./chart/ChartList";
 import ChartList from "./chart/ChartList";
 import EnvGroupDashboard from "./env-groups/EnvGroupDashboard";
 import EnvGroupDashboard from "./env-groups/EnvGroupDashboard";
@@ -102,7 +102,7 @@ class ClusterDashboard extends Component<PropsType, StateType> {
     return (
     return (
       <>
       <>
         <ControlRow>
         <ControlRow>
-          <Button onClick={() => this.props.history.push("launch")}>
+          <Button onClick={() => pushFiltered(this.props, "/launch", ["project_id"])}>
             <i className="material-icons">add</i> Launch Template
             <i className="material-icons">add</i> Launch Template
           </Button>
           </Button>
           <SortFilterWrapper>
           <SortFilterWrapper>

+ 2 - 2
dashboard/src/main/home/dashboard/ClusterList.tsx

@@ -5,8 +5,8 @@ import { Context } from "shared/Context";
 import api from "shared/api";
 import api from "shared/api";
 import { ClusterType } from "shared/types";
 import { ClusterType } from "shared/types";
 import Helper from "components/values-form/Helper";
 import Helper from "components/values-form/Helper";
+import { pushFiltered } from "shared/routing";
 
 
-import Loading from "components/Loading";
 import { RouteComponentProps, withRouter } from "react-router";
 import { RouteComponentProps, withRouter } from "react-router";
 
 
 type PropsType = RouteComponentProps & {
 type PropsType = RouteComponentProps & {
@@ -63,7 +63,7 @@ class Templates extends Component<PropsType, StateType> {
         <TemplateBlock
         <TemplateBlock
           onClick={() => {
           onClick={() => {
             this.context.setCurrentCluster(cluster);
             this.context.setCurrentCluster(cluster);
-            this.props.history.push("applications");
+            pushFiltered(this.props, "applications", ["project_id"]);
           }}
           }}
           key={i}
           key={i}
         >
         >

+ 4 - 9
dashboard/src/main/home/dashboard/Dashboard.tsx

@@ -13,19 +13,13 @@ import TabRegion from "components/TabRegion";
 import Provisioner from "../provisioner/Provisioner";
 import Provisioner from "../provisioner/Provisioner";
 import FormDebugger from "components/values-form/FormDebugger";
 import FormDebugger from "components/values-form/FormDebugger";
 
 
-import { setSearchParam } from "shared/routing";
+import { pushQueryParams, pushFiltered } from "shared/routing";
 
 
 type PropsType = RouteComponentProps & {
 type PropsType = RouteComponentProps & {
   projectId: number | null;
   projectId: number | null;
   setRefreshClusters: (x: boolean) => void;
   setRefreshClusters: (x: boolean) => void;
 };
 };
 
 
-const tabOptions = [
-  { label: "Project Overview", value: "overview" },
-  { label: "Create a Cluster", value: "create-cluster" },
-  { label: "Provisioner Status", value: "provisioner" },
-];
-
 // TODO: rethink this list, should be coupled with tabOptions
 // TODO: rethink this list, should be coupled with tabOptions
 const tabOptionStrings = ["overview", "create-cluster", "provisioner"];
 const tabOptionStrings = ["overview", "create-cluster", "provisioner"];
 
 
@@ -60,6 +54,7 @@ class Dashboard extends Component<PropsType, StateType> {
   };
   };
 
 
   componentDidMount() {
   componentDidMount() {
+    console.log("href is", window.location.href);
     this.refreshInfras();
     this.refreshInfras();
     document.addEventListener("keydown", this.handleKeyDown);
     document.addEventListener("keydown", this.handleKeyDown);
     document.addEventListener("keyup", this.handleKeyUp);
     document.addEventListener("keyup", this.handleKeyUp);
@@ -101,7 +96,7 @@ class Dashboard extends Component<PropsType, StateType> {
   }
   }
 
 
   onShowProjectSettings = () => {
   onShowProjectSettings = () => {
-    this.props.history.push("project-settings");
+    pushFiltered(this.props, "project-settings", ["project_id"]);
   };
   };
 
 
   currentTab = () => new URLSearchParams(this.props.location.search).get("tab");
   currentTab = () => new URLSearchParams(this.props.location.search).get("tab");
@@ -125,7 +120,7 @@ class Dashboard extends Component<PropsType, StateType> {
   };
   };
 
 
   setCurrentTab = (x: string) => {
   setCurrentTab = (x: string) => {
-    this.props.history.push(setSearchParam(this.props.location, "tab", x));
+    pushQueryParams(this.props, { tab: x });
   };
   };
 
 
   render() {
   render() {

+ 4 - 5
dashboard/src/main/home/integrations/IntegrationCategories.tsx

@@ -7,6 +7,7 @@ import { integrationList } from "shared/common";
 import { RouteComponentProps, withRouter } from "react-router";
 import { RouteComponentProps, withRouter } from "react-router";
 import IntegrationList from "./IntegrationList";
 import IntegrationList from "./IntegrationList";
 import api from "shared/api";
 import api from "shared/api";
+import { pushFiltered } from "shared/routing";
 
 
 type PropsType = RouteComponentProps & {
 type PropsType = RouteComponentProps & {
   category: string;
   category: string;
@@ -129,7 +130,7 @@ class IntegrationCategories extends Component<PropsType, StateType> {
             <Flex>
             <Flex>
               <i
               <i
                 className="material-icons"
                 className="material-icons"
-                onClick={() => this.props.history.push("/integrations")}
+                onClick={() => pushFiltered(this.props, "/integrations", ["project_id"])}
               >
               >
                 keyboard_backspace
                 keyboard_backspace
               </i>
               </i>
@@ -141,9 +142,7 @@ class IntegrationCategories extends Component<PropsType, StateType> {
                 this.context.setCurrentModal("IntegrationsModal", {
                 this.context.setCurrentModal("IntegrationsModal", {
                   category: currentCategory,
                   category: currentCategory,
                   setCurrentIntegration: (x: string) =>
                   setCurrentIntegration: (x: string) =>
-                    this.props.history.push(
-                      `/integrations/${this.props.category}/create/${x}`
-                    ),
+                    pushFiltered(this.props, `/integrations/${this.props.category}/create/${x}`, ["project_id"]),
                 })
                 })
               }
               }
             >
             >
@@ -172,7 +171,7 @@ class IntegrationCategories extends Component<PropsType, StateType> {
             <Flex>
             <Flex>
               <i
               <i
                 className="material-icons"
                 className="material-icons"
-                onClick={() => this.props.history.push("/integrations")}
+                onClick={() => pushFiltered(this.props, "/integrations", ["project_id"])}
               >
               >
                 keyboard_backspace
                 keyboard_backspace
               </i>
               </i>

+ 6 - 5
dashboard/src/main/home/integrations/Integrations.tsx

@@ -3,6 +3,7 @@ import { Route, RouteComponentProps, Switch, withRouter } from "react-router";
 
 
 import { integrationList } from "shared/common";
 import { integrationList } from "shared/common";
 import styled from "styled-components";
 import styled from "styled-components";
+import { pushFiltered } from "shared/routing";
 
 
 import CreateIntegrationForm from "./create-integration/CreateIntegrationForm";
 import CreateIntegrationForm from "./create-integration/CreateIntegrationForm";
 import IntegrationCategories from "./IntegrationCategories";
 import IntegrationCategories from "./IntegrationCategories";
@@ -29,7 +30,7 @@ class Integrations extends Component<PropsType, StateType> {
           render={(rp) => {
           render={(rp) => {
             const { integration, category } = rp.match.params;
             const { integration, category } = rp.match.params;
             if (!IntegrationCategoryStrings.includes(category)) {
             if (!IntegrationCategoryStrings.includes(category)) {
-              this.props.history.push("/integrations");
+              pushFiltered(this.props, "/integrations", ["project_id"]);
             }
             }
             let icon =
             let icon =
               integrationList[integration] && integrationList[integration].icon;
               integrationList[integration] && integrationList[integration].icon;
@@ -40,7 +41,7 @@ class Integrations extends Component<PropsType, StateType> {
                     <i
                     <i
                       className="material-icons"
                       className="material-icons"
                       onClick={() =>
                       onClick={() =>
-                        this.props.history.push(`/integrations/${category}`)
+                        pushFiltered(this.props, `/integrations/${category}`, ["project_id"])
                       }
                       }
                     >
                     >
                       keyboard_backspace
                       keyboard_backspace
@@ -52,7 +53,7 @@ class Integrations extends Component<PropsType, StateType> {
                 <CreateIntegrationForm
                 <CreateIntegrationForm
                   integrationName={integration}
                   integrationName={integration}
                   closeForm={() => {
                   closeForm={() => {
-                    this.props.history.push(`/integrations/${category}`);
+                    pushFiltered(this.props, `/integrations/${category}`, ["project_id"]);
                   }}
                   }}
                 />
                 />
                 <Br />
                 <Br />
@@ -65,7 +66,7 @@ class Integrations extends Component<PropsType, StateType> {
           render={(rp) => {
           render={(rp) => {
             const currentCategory = rp.match.params.category;
             const currentCategory = rp.match.params.category;
             if (!IntegrationCategoryStrings.includes(currentCategory)) {
             if (!IntegrationCategoryStrings.includes(currentCategory)) {
-              this.props.history.push("/integrations");
+              pushFiltered(this.props, "/integrations", ["project_id"])
             }
             }
             return (
             return (
               <IntegrationCategories
               <IntegrationCategories
@@ -83,7 +84,7 @@ class Integrations extends Component<PropsType, StateType> {
             <IntegrationList
             <IntegrationList
               currentCategory={""}
               currentCategory={""}
               integrations={["kubernetes", "registry", "repo"]}
               integrations={["kubernetes", "registry", "repo"]}
-              setCurrent={(x) => this.props.history.push(`/integrations/${x}`)}
+              setCurrent={(x) => pushFiltered(this.props, `/integrations/${x}`, ["project_id"])}
               isCategory={true}
               isCategory={true}
               updateIntegrationList={() => {}}
               updateIntegrationList={() => {}}
             />
             />

+ 5 - 29
dashboard/src/main/home/launch/expanded-template/LaunchTemplate.tsx

@@ -4,6 +4,7 @@ import randomWords from "random-words";
 import _ from "lodash";
 import _ from "lodash";
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
 import api from "shared/api";
 import api from "shared/api";
+import { pushFiltered } from "shared/routing";
 import close from "assets/close.png";
 import close from "assets/close.png";
 import { RouteComponentProps, withRouter } from "react-router";
 import { RouteComponentProps, withRouter } from "react-router";
 
 
@@ -166,7 +167,7 @@ class LaunchTemplate extends Component<PropsType, StateType> {
           let dst =
           let dst =
             this.props.currentTemplate.name === "job" ? "jobs" : "applications";
             this.props.currentTemplate.name === "job" ? "jobs" : "applications";
           setTimeout(() => {
           setTimeout(() => {
-            this.props.history.push(dst);
+            pushFiltered(this.props, dst, ["project_id"]);
           }, 500);
           }, 500);
           window.analytics.track("Deployed Add-on", {
           window.analytics.track("Deployed Add-on", {
             name: this.props.currentTemplate.name,
             name: this.props.currentTemplate.name,
@@ -303,37 +304,12 @@ class LaunchTemplate extends Component<PropsType, StateType> {
               this.props.currentTemplate.name === "job"
               this.props.currentTemplate.name === "job"
                 ? "jobs"
                 ? "jobs"
                 : "applications";
                 : "applications";
-            this.props.history.push(dst);
+            pushFiltered(this.props, dst, ["project_id"]);
           }, 1000);
           }, 1000);
         });
         });
-        /*
-        try {
-          window.analytics.track("Deployed Application", {
-            name: this.props.currentTemplate.name,
-            namespace: this.state.selectedNamespace,
-            sourceType: this.state.sourceType,
-            values: values,
-          });
-        } catch (error) {
-          console.log(error);
-        }
-        */
       })
       })
       .catch((err) => {
       .catch((err) => {
         this.setState({ saveValuesStatus: "error" });
         this.setState({ saveValuesStatus: "error" });
-        /*
-        try {
-          window.analytics.track("Failed to Deploy Application", {
-            name: this.props.currentTemplate.name,
-            namespace: this.state.selectedNamespace,
-            sourceType: this.state.sourceType,
-            values: values,
-            error: err,
-          });
-        } catch (error) {
-          console.log(error);
-        }
-        */
       });
       });
   };
   };
 
 
@@ -584,7 +560,7 @@ class LaunchTemplate extends Component<PropsType, StateType> {
             Specify the container image you would like to connect to this
             Specify the container image you would like to connect to this
             template.
             template.
             <Highlight
             <Highlight
-              onClick={() => this.props.history.push("integrations/registry")}
+              onClick={() => pushFiltered(this.props, "integrations/registry", ["project_id"])}
             >
             >
               Manage Docker registries
               Manage Docker registries
             </Highlight>
             </Highlight>
@@ -610,7 +586,7 @@ class LaunchTemplate extends Component<PropsType, StateType> {
           <Subtitle>
           <Subtitle>
             Provide a repo folder to use as source.
             Provide a repo folder to use as source.
             <Highlight
             <Highlight
-              onClick={() => this.props.history.push("integrations/repo")}
+              onClick={() => pushFiltered(this.props, "/integrations/repo", ["project_id"])}
             >
             >
               Manage Git repos
               Manage Git repos
             </Highlight>
             </Highlight>

+ 3 - 2
dashboard/src/main/home/launch/launch-flow/LaunchFlow.tsx

@@ -6,6 +6,7 @@ import { RouteComponentProps, withRouter } from "react-router";
 
 
 import api from "shared/api";
 import api from "shared/api";
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
+import { pushFiltered } from "shared/routing";
 
 
 import hardcodedNames from "../hardcodedNameDict";
 import hardcodedNames from "../hardcodedNameDict";
 import SourcePage from "./SourcePage";
 import SourcePage from "./SourcePage";
@@ -163,7 +164,7 @@ class LaunchFlow extends Component<PropsType, StateType> {
           let dst =
           let dst =
             this.props.currentTemplate.name === "job" ? "jobs" : "applications";
             this.props.currentTemplate.name === "job" ? "jobs" : "applications";
           setTimeout(() => {
           setTimeout(() => {
-            this.props.history.push(dst);
+            pushFiltered(this.props, dst, ["project_id"]);
           }, 500);
           }, 500);
           window.analytics.track("Deployed Add-on", {
           window.analytics.track("Deployed Add-on", {
             name: this.props.currentTemplate.name,
             name: this.props.currentTemplate.name,
@@ -318,7 +319,7 @@ class LaunchFlow extends Component<PropsType, StateType> {
               this.props.currentTemplate.name === "job"
               this.props.currentTemplate.name === "job"
                 ? "jobs"
                 ? "jobs"
                 : "applications";
                 : "applications";
-            this.props.history.push(dst);
+            pushFiltered(this.props, dst, ["project_id"]);
           }, 1000);
           }, 1000);
         });
         });
       })
       })

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

@@ -5,6 +5,7 @@ import { Context } from "shared/Context";
 import { RouteComponentProps, withRouter } from "react-router";
 import { RouteComponentProps, withRouter } from "react-router";
 import close from "assets/close.png";
 import close from "assets/close.png";
 import { isAlphanumeric } from "shared/common";
 import { isAlphanumeric } from "shared/common";
+import { pushFiltered } from "shared/routing";
 
 
 import InputRow from "components/values-form/InputRow";
 import InputRow from "components/values-form/InputRow";
 import Helper from "components/values-form/Helper";
 import Helper from "components/values-form/Helper";
@@ -99,7 +100,7 @@ class SourcePage extends Component<PropsType, StateType> {
             Specify the container image you would like to connect to this
             Specify the container image you would like to connect to this
             template.
             template.
             <Highlight
             <Highlight
-              onClick={() => this.props.history.push("integrations/registry")}
+              onClick={() => pushFiltered(this.props, "integrations/registry", ["project_id"])}
             >
             >
               Manage Docker registries
               Manage Docker registries
             </Highlight>
             </Highlight>
@@ -145,7 +146,7 @@ class SourcePage extends Component<PropsType, StateType> {
         </CloseButton>
         </CloseButton>
         <Subtitle>
         <Subtitle>
           Provide a repo folder to use as source.
           Provide a repo folder to use as source.
-          <Highlight onClick={() => history.push("integrations/repo")}>
+          <Highlight onClick={() => pushFiltered(this.props, "/integrations/repo", ["project_id"])}>
             Manage Git repos
             Manage Git repos
           </Highlight>
           </Highlight>
           <Required>*</Required>
           <Required>*</Required>

+ 2 - 1
dashboard/src/main/home/modals/UpdateClusterModal.tsx

@@ -4,6 +4,7 @@ import close from "assets/close.png";
 
 
 import api from "shared/api";
 import api from "shared/api";
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
+import { pushFiltered } from "shared/routing";
 
 
 import SaveButton from "components/SaveButton";
 import SaveButton from "components/SaveButton";
 import InputRow from "components/values-form/InputRow";
 import InputRow from "components/values-form/InputRow";
@@ -51,7 +52,7 @@ class UpdateClusterModal extends Component<PropsType, StateType> {
           this.props.setRefreshClusters(true);
           this.props.setRefreshClusters(true);
           this.setState({ status: "successful", showDeleteOverlay: false });
           this.setState({ status: "successful", showDeleteOverlay: false });
           this.context.setCurrentModal(null, null);
           this.context.setCurrentModal(null, null);
-          this.props.history.push("dashboard?tab=overview");
+          pushFiltered(this.props, "dashboard?tab=overview", ["project_id"]);
           return;
           return;
         }
         }
 
 

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

@@ -5,7 +5,8 @@ import close from "assets/close.png";
 import { isAlphanumeric } from "shared/common";
 import { isAlphanumeric } from "shared/common";
 import api from "shared/api";
 import api from "shared/api";
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
-import { InfraType } from "shared/types";
+import { InfraType, ProjectType } from "shared/types";
+import { pushQueryParams, pushFiltered } from "shared/routing";
 
 
 import SelectRow from "components/values-form/SelectRow";
 import SelectRow from "components/values-form/SelectRow";
 import InputRow from "components/values-form/InputRow";
 import InputRow from "components/values-form/InputRow";
@@ -169,12 +170,21 @@ class AWSFormSection extends Component<PropsType, StateType> {
     this.props.handleError();
     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
   // Step 1: Create a project
   // TODO: promisify this function
   // TODO: promisify this function
   createProject = (callback?: any) => {
   createProject = (callback?: any) => {
     console.log("Creating project");
     console.log("Creating project");
     let { projectName, handleError } = this.props;
     let { projectName, handleError } = this.props;
-    let { user, setProjects, setCurrentProject, currentProject } = this.context;
+    let { user, setProjects, currentProject } = this.context;
 
 
     api
     api
       .createProject("<token>", { name: projectName }, {})
       .createProject("<token>", { name: projectName }, {})
@@ -192,7 +202,7 @@ class AWSFormSection extends Component<PropsType, StateType> {
           )
           )
           .then((res) => {
           .then((res) => {
             setProjects(res.data);
             setProjects(res.data);
-            setCurrentProject(proj, () => {
+            this.setCurrentProject(proj, () => {
               callback && callback();
               callback && callback();
             });
             });
           })
           })
@@ -261,7 +271,9 @@ class AWSFormSection extends Component<PropsType, StateType> {
           { id: currentProject.id }
           { id: currentProject.id }
         )
         )
       )
       )
-      .then(() => this.props.history.push("dashboard?tab=provisioner"))
+      .then(() => 
+        pushFiltered(this.props, "dashboard?tab=provisioner", ["project_id"])
+      )
       .catch(this.catchError);
       .catch(this.catchError);
   };
   };
 
 
@@ -278,7 +290,7 @@ class AWSFormSection extends Component<PropsType, StateType> {
       } else if (selectedInfras[0].value === "ecr") {
       } else if (selectedInfras[0].value === "ecr") {
         // Case: project exists, only provision ECR
         // Case: project exists, only provision ECR
         this.provisionECR().then(() =>
         this.provisionECR().then(() =>
-          this.props.history.push("dashboard?tab=provisioner")
+          pushFiltered(this.props, "dashboard?tab=provisioner", ["project_id"])
         );
         );
       } else {
       } else {
         // Case: project exists, only provision EKS
         // Case: project exists, only provision EKS
@@ -291,9 +303,9 @@ class AWSFormSection extends Component<PropsType, StateType> {
       } else if (selectedInfras[0].value === "ecr") {
       } else if (selectedInfras[0].value === "ecr") {
         // Case: project DNE, only provision ECR
         // Case: project DNE, only provision ECR
         this.createProject(() =>
         this.createProject(() =>
-          this.provisionECR().then(() => {
-            this.props.history.push("dashboard?tab=provisioner");
-          })
+          this.provisionECR().then(() => 
+            pushFiltered(this.props, "dashboard?tab=provisioner", ["project_id"])
+          )
         );
         );
       } else {
       } else {
         // Case: project DNE, only provision EKS
         // Case: project DNE, only provision EKS

+ 13 - 3
dashboard/src/main/home/provisioner/DOFormSection.tsx

@@ -5,7 +5,8 @@ import close from "assets/close.png";
 import { isAlphanumeric } from "shared/common";
 import { isAlphanumeric } from "shared/common";
 import api from "shared/api";
 import api from "shared/api";
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
-import { InfraType } from "shared/types";
+import { InfraType, ProjectType } from "shared/types";
+import { pushQueryParams } from "shared/routing";
 
 
 import InputRow from "components/values-form/InputRow";
 import InputRow from "components/values-form/InputRow";
 import CheckboxRow from "components/values-form/CheckboxRow";
 import CheckboxRow from "components/values-form/CheckboxRow";
@@ -131,11 +132,20 @@ export default class DOFormSection extends Component<PropsType, StateType> {
     return;
     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
   // Step 1: Create a project
   createProject = (callback?: any) => {
   createProject = (callback?: any) => {
     console.log("Creating project");
     console.log("Creating project");
     let { projectName } = this.props;
     let { projectName } = this.props;
-    let { user, setProjects, setCurrentProject } = this.context;
+    let { user, setProjects } = this.context;
 
 
     api
     api
       .createProject("<token>", { name: projectName }, {})
       .createProject("<token>", { name: projectName }, {})
@@ -152,7 +162,7 @@ export default class DOFormSection extends Component<PropsType, StateType> {
           }
           }
         );
         );
         setProjects(res_1.data);
         setProjects(res_1.data);
-        setCurrentProject(proj);
+        this.setCurrentProject(proj);
         callback && callback(proj.id);
         callback && callback(proj.id);
       })
       })
       .catch(this.catchError);
       .catch(this.catchError);

+ 13 - 3
dashboard/src/main/home/provisioner/ExistingClusterSection.tsx

@@ -5,6 +5,7 @@ import api from "shared/api";
 import { ProjectType } from "shared/types";
 import { ProjectType } from "shared/types";
 import { isAlphanumeric } from "shared/common";
 import { isAlphanumeric } from "shared/common";
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
+import { pushQueryParams, pushFiltered } from "shared/routing";
 
 
 import SaveButton from "components/SaveButton";
 import SaveButton from "components/SaveButton";
 import { RouteComponentProps, withRouter } from "react-router";
 import { RouteComponentProps, withRouter } from "react-router";
@@ -22,9 +23,18 @@ class ExistingClusterSection extends Component<PropsType, StateType> {
     buttonStatus: "",
     buttonStatus: "",
   };
   };
 
 
+  setCurrentProject = (project: ProjectType, callback?: any) => {
+    this.context.setCurrentProject(project, () => {
+      if (project) {
+        pushQueryParams(this.props, { project_id: project.id.toString() });
+      }
+      callback && callback();
+    });
+  }
+
   onCreateProject = () => {
   onCreateProject = () => {
     let { projectName } = this.props;
     let { projectName } = this.props;
-    let { user, setProjects, setCurrentProject } = this.context;
+    let { user, setProjects } = this.context;
 
 
     this.setState({ buttonStatus: "loading" });
     this.setState({ buttonStatus: "loading" });
     api
     api
@@ -45,8 +55,8 @@ class ExistingClusterSection extends Component<PropsType, StateType> {
             let proj = res.data.find((el: ProjectType) => {
             let proj = res.data.find((el: ProjectType) => {
               return el.name === projectName;
               return el.name === projectName;
             });
             });
-            setCurrentProject(proj);
-            this.props.history.push("dashboard?tab=overview");
+            this.setCurrentProject(proj);
+            pushFiltered(this.props, "dashboard?tab=overview", ["project_id"]);
           }
           }
         }
         }
       })
       })

+ 17 - 7
dashboard/src/main/home/provisioner/GCPFormSection.tsx

@@ -5,7 +5,8 @@ import close from "assets/close.png";
 import { isAlphanumeric } from "shared/common";
 import { isAlphanumeric } from "shared/common";
 import api from "shared/api";
 import api from "shared/api";
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
-import { InfraType } from "shared/types";
+import { InfraType, ProjectType } from "shared/types";
+import { pushQueryParams, pushFiltered } from "shared/routing";
 
 
 import UploadArea from "components/values-form/UploadArea";
 import UploadArea from "components/values-form/UploadArea";
 import SelectRow from "components/values-form/SelectRow";
 import SelectRow from "components/values-form/SelectRow";
@@ -162,11 +163,20 @@ class GCPFormSection extends Component<PropsType, StateType> {
     this.props.handleError();
     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
   // Step 1: Create a project
   createProject = (callback?: any) => {
   createProject = (callback?: any) => {
     console.log("Creating project");
     console.log("Creating project");
     let { projectName, handleError } = this.props;
     let { projectName, handleError } = this.props;
-    let { user, setProjects, setCurrentProject } = this.context;
+    let { user, setProjects } = this.context;
 
 
     api
     api
       .createProject("<token>", { name: projectName }, {})
       .createProject("<token>", { name: projectName }, {})
@@ -185,7 +195,7 @@ class GCPFormSection extends Component<PropsType, StateType> {
           )
           )
           .then((res) => {
           .then((res) => {
             setProjects(res.data);
             setProjects(res.data);
-            setCurrentProject(proj);
+            this.setCurrentProject(proj);
             callback && callback();
             callback && callback();
           })
           })
           .catch(this.catchError);
           .catch(this.catchError);
@@ -222,9 +232,9 @@ class GCPFormSection extends Component<PropsType, StateType> {
         },
         },
         { project_id: currentProject.id }
         { project_id: currentProject.id }
       )
       )
-      .then((res) => {
-        this.props.history.push("dashboard?tab=provisioner");
-      })
+      .then((res) =>
+        pushFiltered(this.props, "dashboard?tab=provisioner", ["project_id"])
+      )
       .catch(this.catchError);
       .catch(this.catchError);
   };
   };
 
 
@@ -252,7 +262,7 @@ class GCPFormSection extends Component<PropsType, StateType> {
           } else if (selectedInfras[0].value === "gcr") {
           } else if (selectedInfras[0].value === "gcr") {
             // Case: project exists, only provision GCR
             // Case: project exists, only provision GCR
             this.provisionGCR(id).then(() =>
             this.provisionGCR(id).then(() =>
-              this.props.history.push("dashboard?tab=provisioner")
+              pushFiltered(this.props, "dashboard?tab=provisioner", ["project_id"])
             );
             );
           } else {
           } else {
             // Case: project exists, only provision GKE
             // Case: project exists, only provision GKE

+ 2 - 1
dashboard/src/main/home/provisioner/ProvisionerSettings.tsx

@@ -12,6 +12,7 @@ import DOFormSection from "./DOFormSection";
 import SaveButton from "components/SaveButton";
 import SaveButton from "components/SaveButton";
 import ExistingClusterSection from "./ExistingClusterSection";
 import ExistingClusterSection from "./ExistingClusterSection";
 import { RouteComponentProps, withRouter } from "react-router";
 import { RouteComponentProps, withRouter } from "react-router";
+import { pushFiltered } from "shared/routing";
 
 
 type PropsType = RouteComponentProps & {
 type PropsType = RouteComponentProps & {
   isInNewProject?: boolean;
   isInNewProject?: boolean;
@@ -40,7 +41,7 @@ class NewProject extends Component<PropsType, StateType> {
     setCurrentError(
     setCurrentError(
       "Provisioning failed. Check your credentials and try again."
       "Provisioning failed. Check your credentials and try again."
     );
     );
-    this.props.history.push("dashboard?tab=overview");
+    pushFiltered(this.props, "dashboard?tab=overview", ["project_id"]);
   };
   };
 
 
   renderSelectedProvider = (override?: string) => {
   renderSelectedProvider = (override?: string) => {

+ 0 - 1
dashboard/src/main/home/sidebar/ClusterSection.tsx

@@ -85,7 +85,6 @@ class ClusterSection extends Component<PropsType, StateType> {
           ) {
           ) {
             this.setState({ clusters: [] });
             this.setState({ clusters: [] });
             setCurrentCluster(null);
             setCurrentCluster(null);
-            // this.props.history.push("dashboard?tab=overview");
           }
           }
         }
         }
       })
       })

+ 2 - 1
dashboard/src/main/home/sidebar/Drawer.tsx

@@ -5,6 +5,7 @@ import close from "assets/close.png";
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
 import { ClusterType } from "shared/types";
 import { ClusterType } from "shared/types";
 import { RouteComponentProps, withRouter } from "react-router";
 import { RouteComponentProps, withRouter } from "react-router";
+import { pushFiltered } from "shared/routing";
 
 
 type PropsType = RouteComponentProps & {
 type PropsType = RouteComponentProps & {
   toggleDrawer: () => void;
   toggleDrawer: () => void;
@@ -34,7 +35,7 @@ class Drawer extends Component<PropsType, StateType> {
             active={cluster.name === currentCluster.name}
             active={cluster.name === currentCluster.name}
             onClick={() => {
             onClick={() => {
               setCurrentCluster(cluster);
               setCurrentCluster(cluster);
-              this.props.history.push("applications");
+              pushFiltered(this.props, "/applications", ["project_id"]);
             }}
             }}
           >
           >
             <ClusterIcon>
             <ClusterIcon>

+ 15 - 8
dashboard/src/main/home/sidebar/ProjectSection.tsx

@@ -4,6 +4,7 @@ import gradient from "assets/gradient.png";
 
 
 import { Context } from "shared/Context";
 import { Context } from "shared/Context";
 import { ProjectType } from "shared/types";
 import { ProjectType } from "shared/types";
+import { pushQueryParams, pushFiltered } from "shared/routing";
 import { RouteComponentProps, withRouter } from "react-router";
 import { RouteComponentProps, withRouter } from "react-router";
 
 
 type PropsType = RouteComponentProps & {
 type PropsType = RouteComponentProps & {
@@ -43,9 +44,15 @@ class ProjectSection extends Component<PropsType, StateType> {
     }
     }
   };
   };
 
 
-  renderOptionList = () => {
-    let { setCurrentProject } = this.context;
+  setCurrentProject = (project: ProjectType) => {
+    this.context.setCurrentProject(project, () => {
+      if (project) {
+        pushQueryParams(this.props, { project_id: project.id.toString() });
+      }
+    });
+  }
 
 
+  renderOptionList = () => {
     return this.props.projects.map((project: ProjectType, i: number) => {
     return this.props.projects.map((project: ProjectType, i: number) => {
       return (
       return (
         <Option
         <Option
@@ -53,8 +60,8 @@ class ProjectSection extends Component<PropsType, StateType> {
           selected={project.name === this.props.currentProject.name}
           selected={project.name === this.props.currentProject.name}
           onClick={() => {
           onClick={() => {
             this.setState({ expanded: false });
             this.setState({ expanded: false });
-            setCurrentProject(project);
-            this.props.history.push("dashboard");
+            this.setCurrentProject(project);
+            pushFiltered(this.props, "/dashboard", ["project_id"]);
           }}
           }}
         >
         >
           <ProjectIcon>
           <ProjectIcon>
@@ -76,9 +83,9 @@ class ProjectSection extends Component<PropsType, StateType> {
             <Option
             <Option
               selected={false}
               selected={false}
               lastItem={true}
               lastItem={true}
-              onClick={() => {
-                this.props.history.push("new-project");
-              }}
+              onClick={() =>
+                pushFiltered(this.props, "new-project", ["project_id"])
+              }
             >
             >
               <ProjectIconAlt>+</ProjectIconAlt>
               <ProjectIconAlt>+</ProjectIconAlt>
               <ProjectLabel>Create a Project</ProjectLabel>
               <ProjectLabel>Create a Project</ProjectLabel>
@@ -114,7 +121,7 @@ class ProjectSection extends Component<PropsType, StateType> {
       );
       );
     }
     }
     return (
     return (
-      <InitializeButton onClick={() => this.props.history.push("new-project")}>
+      <InitializeButton onClick={() => pushFiltered(this.props, "new-project", ["project_id"])}>
         <Plus>+</Plus> Create a Project
         <Plus>+</Plus> Create a Project
       </InitializeButton>
       </InitializeButton>
     );
     );

+ 21 - 19
dashboard/src/main/home/sidebar/Sidebar.tsx

@@ -15,6 +15,7 @@ import ClusterSection from "./ClusterSection";
 import ProjectSectionContainer from "./ProjectSectionContainer";
 import ProjectSectionContainer from "./ProjectSectionContainer";
 import loading from "assets/loading.gif";
 import loading from "assets/loading.gif";
 import { RouteComponentProps, withRouter } from "react-router";
 import { RouteComponentProps, withRouter } from "react-router";
+import { pushFiltered } from "shared/routing";
 
 
 type PropsType = RouteComponentProps & {
 type PropsType = RouteComponentProps & {
   forceSidebar: boolean;
   forceSidebar: boolean;
@@ -105,27 +106,27 @@ class Sidebar extends Component<PropsType, StateType> {
         <>
         <>
           <NavButton
           <NavButton
             selected={currentView === "applications"}
             selected={currentView === "applications"}
-            onClick={() => {
-              this.props.history.push("/applications");
-            }}
+            onClick={() => 
+              pushFiltered(this.props, "/applications", ["project_id"])
+            }
           >
           >
             <Img src={monoweb} />
             <Img src={monoweb} />
             Applications
             Applications
           </NavButton>
           </NavButton>
           <NavButton
           <NavButton
             selected={currentView === "jobs"}
             selected={currentView === "jobs"}
-            onClick={() => {
-              this.props.history.push("/jobs");
-            }}
+            onClick={() => 
+              pushFiltered(this.props, "/jobs", ["project_id"])
+            }
           >
           >
             <Img src={monojob} />
             <Img src={monojob} />
             Jobs
             Jobs
           </NavButton>
           </NavButton>
           <NavButton
           <NavButton
             selected={currentView === "env-groups"}
             selected={currentView === "env-groups"}
-            onClick={() => {
-              this.props.history.push("/env-groups");
-            }}
+            onClick={() => 
+              pushFiltered(this.props, "/env-groups", ["project_id"])
+            }
           >
           >
             <Img src={sliders} />
             <Img src={sliders} />
             Env Groups
             Env Groups
@@ -136,7 +137,7 @@ class Sidebar extends Component<PropsType, StateType> {
   };
   };
 
 
   renderProjectContents = () => {
   renderProjectContents = () => {
-    let { currentView } = this.props;
+    let { currentView, history, location } = this.props;
     let { currentProject, setCurrentModal } = this.context;
     let { currentProject, setCurrentModal } = this.context;
     if (currentProject) {
     if (currentProject) {
       return (
       return (
@@ -145,7 +146,7 @@ class Sidebar extends Component<PropsType, StateType> {
           <NavButton
           <NavButton
             onClick={() =>
             onClick={() =>
               currentView !== "provisioner" &&
               currentView !== "provisioner" &&
-              this.props.history.push("/dashboard?tab=overview")
+                pushFiltered(this.props, "/dashboard", ["project_id"])
             }
             }
             selected={
             selected={
               currentView === "dashboard" || currentView === "provisioner"
               currentView === "dashboard" || currentView === "provisioner"
@@ -155,7 +156,9 @@ class Sidebar extends Component<PropsType, StateType> {
             Dashboard
             Dashboard
           </NavButton>
           </NavButton>
           <NavButton
           <NavButton
-            onClick={() => this.props.history.push("/launch")}
+            onClick={() => 
+              pushFiltered(this.props, "/launch", ["project_id"])
+            }
             selected={currentView === "launch"}
             selected={currentView === "launch"}
           >
           >
             <Img src={rocket} />
             <Img src={rocket} />
@@ -163,12 +166,9 @@ class Sidebar extends Component<PropsType, StateType> {
           </NavButton>
           </NavButton>
           <NavButton
           <NavButton
             selected={currentView === "integrations"}
             selected={currentView === "integrations"}
-            onClick={() => {
-              this.props.history.push("/integrations");
-            }}
-            // onClick={() => {
-            //   setCurrentModal("IntegrationsInstructionsModal", {});
-            // }}
+            onClick={() => 
+              pushFiltered(this.props, "/integrations", ["project_id"])
+            }
           >
           >
             <Img src={integrations} />
             <Img src={integrations} />
             Integrations
             Integrations
@@ -177,7 +177,9 @@ class Sidebar extends Component<PropsType, StateType> {
             return obj.user_id === this.context.user.userId;
             return obj.user_id === this.context.user.userId;
           })[0].kind === "admin" && (
           })[0].kind === "admin" && (
             <NavButton
             <NavButton
-              onClick={() => this.props.history.push("/project-settings")}
+              onClick={() => 
+                pushFiltered(this.props, "/project-settings", ["project_id"])
+              }
               selected={this.props.currentView === "project-settings"}
               selected={this.props.currentView === "project-settings"}
             >
             >
               <Img enlarge={true} src={settings} />
               <Img enlarge={true} src={settings} />

+ 1 - 0
dashboard/src/shared/Context.tsx

@@ -41,6 +41,7 @@ class ContextProvider extends Component {
     },
     },
     currentProject: null as ProjectType | null,
     currentProject: null as ProjectType | null,
     setCurrentProject: (currentProject: ProjectType, callback?: any) => {
     setCurrentProject: (currentProject: ProjectType, callback?: any) => {
+      console.log("certify", currentProject);
       if (currentProject) {
       if (currentProject) {
         localStorage.setItem("currentProject", currentProject.id.toString());
         localStorage.setItem("currentProject", currentProject.id.toString());
       } else {
       } else {

+ 27 - 7
dashboard/src/shared/routing.tsx

@@ -23,15 +23,35 @@ export const PorterUrls = [
   "jobs",
   "jobs",
 ];
 ];
 
 
-export const setSearchParam = (
-  location: Location<any>,
-  key: string,
-  value: string
+export const pushQueryParams = (
+  props: any,
+  params: any,
 ) => {
 ) => {
+  let { location, history } = props;
   const urlParams = new URLSearchParams(location.search);
   const urlParams = new URLSearchParams(location.search);
-  urlParams.set(key, value);
-  return {
+  Object.keys(params)?.forEach((key: string) => {
+    urlParams.set(key, params[key]);
+  });
+  history.push({
     pathname: location.pathname,
     pathname: location.pathname,
     search: urlParams.toString(),
     search: urlParams.toString(),
-  };
+  });
 };
 };
+
+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
+) => {
+  let { location, history } = props;
+  let urlParams = new URLSearchParams(location.search);
+  let newUrlParams = new URLSearchParams("");
+  keys?.forEach((key: string) => {
+    let value = urlParams.get(key);
+    value && newUrlParams.set(key, value);
+  });
+  history.push({
+    pathname,
+    search: newUrlParams.toString(),
+  });
+}