jnfrati 4 лет назад
Родитель
Сommit
30a7b3c2df

+ 12 - 0
dashboard/src/main/home/onboarding/Onboarding.tsx

@@ -1,21 +1,33 @@
 import React, { useContext, useEffect } from "react";
+import { useLocation } from "react-router";
 import { Context } from "shared/Context";
+import { useRouting } from "shared/routing";
 import styled from "styled-components";
 import { OnboardingState } from "./OnboardingState";
 import Routes from "./Routes";
+import StepHandler from "./StepHandler";
 
 const Onboarding = () => {
   const context = useContext(Context);
+  const location = useLocation();
+  const { pushFiltered } = useRouting();
 
   useEffect(() => {
     OnboardingState.actions.initFromGlobalContext(context);
   }, [context]);
 
   useEffect(() => {
+    OnboardingState.actions.restoreState();
     return () => {
       OnboardingState.actions.clearState();
     };
   }, []);
+
+  useEffect(() => {
+    if (StepHandler.currentStep.url !== location.pathname) {
+      pushFiltered(StepHandler.currentStep.url, []);
+    }
+  }, [location.pathname]);
   return (
     <StyledOnboarding>
       <Routes />

+ 3 - 1
dashboard/src/main/home/onboarding/OnboardingState.ts

@@ -1,7 +1,7 @@
 import { ContextProps } from "shared/types";
 import { proxy } from "valtio";
 import { devtools } from "valtio/utils";
-import { SupportedProviders } from "./components/ProviderSelector";
+import StepHandler from "./StepHandler";
 import { State as ConnectRegistryState } from "./steps/ConnectRegistry/ConnectRegistryState";
 
 export type OnboardingStateType = {
@@ -75,6 +75,7 @@ const actions = {
     console.log(json);
     localStorage.setItem("onboarding", json);
   },
+  restoreState: () => {},
 };
 
 const initialState: OnboardingStateType = {
@@ -85,6 +86,7 @@ const initialState: OnboardingStateType = {
   selectedProvider: null,
   actions,
   connectRegistry_state: ConnectRegistryState,
+  stepHandler_state: StepHandler,
 };
 
 export const OnboardingState = proxy<OnboardingStateType>(initialState);

+ 3 - 3
dashboard/src/main/home/onboarding/Routes.tsx

@@ -1,5 +1,5 @@
-import React from "react";
-import { Route, Switch } from "react-router";
+import React, { useEffect } from "react";
+import { Route, Switch, useHistory, useLocation } from "react-router";
 import ConnectRegistry from "./steps/ConnectRegistry/ConnectRegistry";
 import ConnectSource from "./steps/ConnectSource";
 import { NewProjectFC } from "./steps/NewProject";
@@ -12,7 +12,7 @@ export const Routes = () => {
         <Route path={`/onboarding/new-project`}>
           <NewProjectFC />
         </Route>
-        <Route path={`/onboarding/integrations`}>
+        <Route path={`/onboarding/source`}>
           <ConnectSource />
         </Route>
         <Route path={`/onboarding/registry`}>

+ 89 - 0
dashboard/src/main/home/onboarding/StateHandler.ts

@@ -0,0 +1,89 @@
+import { proxy } from "valtio";
+
+type AWSRegistryConfig = {
+  provider: "aws";
+  credentials: {
+    id: string;
+  };
+  settings: {
+    registry_name: string;
+    region: string;
+  };
+};
+
+type GCPRegistryConfig = {
+  provider: "gcp";
+  credentials: {
+    id: string;
+  };
+  settings: {
+    registry_name: string;
+    gcr_url: string;
+  };
+};
+
+type AWSProvisionerConfig = {
+  skip: false;
+  provider: "aws";
+  credentials: {
+    id: string;
+  };
+  settings: {
+    cluster_name: string;
+    aws_region: string;
+    aws_machine_type: string;
+  };
+};
+
+type GCPProvisionerConfig = {
+  skip: false;
+  provider: "gcp";
+  credentials: {
+    id: string;
+  };
+  settings: {
+    gcp_region: string;
+    cluster_name: string;
+  };
+};
+
+type SkipProvisionConfig = {
+  skip: true;
+};
+
+type OnboardingState = {
+  project: {
+    id: number;
+    name: string;
+  } | null;
+  connected_source: {
+    source: "github" | "docker";
+  } | null;
+  connected_registry: GCPRegistryConfig | AWSRegistryConfig | null;
+  provision_resources:
+    | GCPProvisionerConfig
+    | AWSProvisionerConfig
+    | SkipProvisionConfig
+    | null;
+  restoreState: (state: OnboardingState) => void;
+  clearState: () => void;
+};
+
+export const State = proxy<OnboardingState>({
+  project: null,
+  connected_source: null,
+  connected_registry: null,
+  provision_resources: null,
+  restoreState: (prevState) => {
+    State.project = prevState.project;
+    State.connected_source = prevState.connected_source;
+    State.connected_registry = prevState.connected_registry;
+    State.provision_resources = prevState.provision_resources;
+  },
+  clearState: () => {
+    State.project = null;
+    State.connected_source = null;
+    State.connected_registry = null;
+    State.provision_resources = null;
+  },
+});

+ 83 - 0
dashboard/src/main/home/onboarding/StepHandler.ts

@@ -0,0 +1,83 @@
+import { proxy } from "valtio";
+import { StepKey, Steps } from "./types";
+
+type Step = {
+  previous?: StepKey;
+  url: string;
+  next?: StepKey;
+  final?: true;
+};
+
+export type FlowType = {
+  initial: StepKey;
+  steps: {
+    [key in Steps]: Step;
+  };
+};
+
+const flow: FlowType = {
+  initial: "new_project",
+  steps: {
+    new_project: {
+      url: "/onboarding/new-project",
+      next: "connect_source",
+    },
+    connect_source: {
+      previous: "new_project",
+      url: "/onboarding/source",
+      next: "connect_registry",
+    },
+    connect_registry: {
+      previous: "connect_source",
+      url: "/onboarding/registry",
+      next: "provision_resources",
+    },
+    provision_resources: {
+      previous: "connect_registry",
+      url: "/onboarding/provision",
+      final: true,
+    },
+  },
+};
+
+type StepHandlerType = {
+  flow: FlowType;
+  currentStepName: StepKey;
+  currentStep: Step;
+  actions: {
+    nextStep: () => { redirectUrl: string };
+    clearState: () => void;
+    restoreState: (prevState: StepHandlerType) => void;
+  };
+};
+
+export const StepHandler: StepHandlerType = proxy({
+  flow,
+  currentStepName: flow.initial,
+  currentStep: flow.steps[flow.initial],
+  actions: {
+    nextStep: () => {
+      const cs = StepHandler.currentStep;
+      if (cs.final) {
+        return {
+          redirectUrl: "/dashboard?tab=provisioner",
+        };
+      }
+      const nextStepName = cs.next;
+      const nextStep = flow.steps[nextStepName];
+      StepHandler.currentStep = nextStep;
+      StepHandler.currentStepName = nextStepName;
+      return {
+        redirectUrl: nextStep.url,
+      };
+    },
+    clearState: () => {
+      StepHandler.currentStepName = flow.initial;
+      StepHandler.currentStep = flow.steps[flow.initial];
+    },
+    restoreState: (prevState) => {
+      StepHandler.currentStepName = prevState.currentStepName;
+      StepHandler.currentStep = prevState.currentStep;
+    },
+  },
+});

+ 1 - 2
dashboard/src/main/home/onboarding/components/ProviderSelector.tsx

@@ -1,13 +1,12 @@
 import React from "react";
 import { integrationList } from "shared/common";
 import styled from "styled-components";
+import { SupportedProviders } from "../types";
 
 export type ProviderSelectorProps = {
   selectProvider: (provider: SupportedProviders) => void;
 };
 
-export type SupportedProviders = "aws" | "gcp" | "do";
-
 const providers: SupportedProviders[] = ["aws", "gcp", "do"];
 
 const ProviderSelector: React.FC<ProviderSelectorProps> = ({

+ 1 - 3
dashboard/src/main/home/onboarding/steps/ConnectRegistry/ConnectRegistryState.ts

@@ -1,7 +1,5 @@
 import { proxy } from "valtio";
-import { devtools } from "valtio/utils";
-
-import { SupportedProviders } from "../../components/ProviderSelector";
+import { SupportedProviders } from "../../types";
 
 type AllowedSteps = "credentials" | "settings" | "test_connection" | null;
 

+ 10 - 0
dashboard/src/main/home/onboarding/types.ts

@@ -0,0 +1,10 @@
+export type SupportedProviders = "aws" | "gcp" | "do";
+
+export enum Steps {
+  NEW_PROJECT = "new_project",
+  CONNECT_SOURCE = "connect_source",
+  CONNECT_REGISTRY = "connect_registry",
+  PROVISION_RESOURCES = "provision_resources",
+}
+
+export type StepKey = `${Steps}`;