diff --git a/src/apps/console/components/multi-step-progress.tsx b/src/apps/console/components/multi-step-progress.tsx index 62d488885..a23b9280a 100644 --- a/src/apps/console/components/multi-step-progress.tsx +++ b/src/apps/console/components/multi-step-progress.tsx @@ -1,41 +1,42 @@ import { Check } from '@jengaicons/react'; -import React, { - Children, - ReactElement, - ReactNode, - useRef, - useState, -} from 'react'; +import React, { Children, ReactElement, ReactNode, useState } from 'react'; import { cn } from '~/components/utils'; interface IUseMultiStepProgress { defaultStep: number; totalSteps: number; + onChange?: (step: number) => void; } export const useMultiStepProgress = ({ defaultStep = 1, totalSteps = 1, + onChange, }: IUseMultiStepProgress) => { const [currentIndex, setCurrentIndex] = useState(defaultStep); const nextStep = () => { if (currentIndex < totalSteps) { + onChange?.(currentIndex + 1); setCurrentIndex((prev) => prev + 1); } }; const prevStep = () => { if (currentIndex > 1) { + onChange?.(currentIndex - 1); setCurrentIndex((prev) => prev - 1); } }; const jumpStep = (step: number) => { + onChange?.(step); setCurrentIndex(step); }; const reset = () => { + onChange?.(1); setCurrentIndex(1); }; + return { currentStep: currentIndex, nextStep, prevStep, reset, jumpStep }; }; @@ -45,9 +46,10 @@ type IProgressTrackerItem = { label: ReactNode; children?: ReactNode; onClick?: () => void; - hasBorder: boolean; index: number; - noJump?: boolean; + noJump?: (step: number) => boolean; + editable?: boolean; + step: number; }; function ProgressTrackerItem( @@ -59,17 +61,19 @@ function ProgressTrackerItem( completed = false, label, onClick, - hasBorder, index, noJump, + editable, + step, } = props; - return (
@@ -78,12 +82,17 @@ function ProgressTrackerItem( aria-label={`step-${index}`} onClick={onClick} className={cn( - 'border-2 border-surface-basic-default headingXs box-content w-3xl h-3xl rounded-full flex items-center justify-center absolute left-0 -ml-[12px]', - completed - ? 'bg-surface-primary-default text-text-on-primary' - : 'bg-surface-primary-selected', - active && !completed ? 'text-text-primary' : 'text-text-disabled', - onClick && !noJump ? 'cursor-pointer' : 'cursor-default' + 'border-2 border-surface-basic-default headingXs box-content w-3xl h-3xl rounded-full flex items-center justify-center absolute left-0 ', + onClick && !noJump?.(step) ? 'cursor-pointer' : 'cursor-default', + { + 'bg-surface-primary-default text-text-on-primary': + !!completed && !!editable, + 'bg-icon-disabled text-text-on-primary': !!completed && !editable, + 'bg-surface-basic-active text-text-disabled': + !completed && !active, + 'bg-surface-primary-selected text-text-default': + active && !completed, + } )} > {completed ? : index} @@ -91,8 +100,11 @@ function ProgressTrackerItem( @@ -109,8 +121,15 @@ interface IStep { label: ReactNode; step: number; className?: string; + completed?: boolean; } -const Step = ({ children, step, className, label: _label }: IStep) => { +const Step = ({ + children, + step, + className, + label: _label, + completed: _completed, +}: IStep) => { return (
{children} @@ -122,13 +141,15 @@ interface IMultiStepProgress { children: ReactElement | ReactElement[]; currentStep: number; jumpStep: (step: number) => void; - noJump?: boolean; + noJump?: (step: number) => boolean; + editable?: boolean; } const Root = ({ children, currentStep, jumpStep, noJump, + editable = true, }: IMultiStepProgress) => { let child = children; // @ts-ignore @@ -138,26 +159,26 @@ const Root = ({ } return ( -
+
{Children.map(child, (ch, index) => { return ( !(index + 1 < currentStep))} + editable={editable} + completed={currentStep > ch.props.step} onClick={() => { - if (index + 1 < currentStep) { - if (!noJump) { - jumpStep(index + 1); - } + if (noJump ? !noJump?.(ch.props.step) : index + 1 < currentStep) { + jumpStep(index + 1); } }} > {currentStep === ch.props.step ? ( -
{ch.props.children}
+
{ch.props.children}
) : null}
); diff --git a/src/apps/console/page-components/app-states.tsx b/src/apps/console/page-components/app-states.tsx index 6a7d8c7ed..ff15fce76 100644 --- a/src/apps/console/page-components/app-states.tsx +++ b/src/apps/console/page-components/app-states.tsx @@ -28,14 +28,6 @@ type ISetContainer = (fn: ((val: T) => T) | T, index?: number) => void; const CreateAppContext = createContext(null); -export type createAppTabs = - | 'Environment' - | 'Application details' - | 'Compute' - | 'Network' - | 'Review' - | NonNullableString; - export type createAppEnvPage = | 'environment_variables' | 'config_mounts' @@ -47,7 +39,7 @@ interface IappState { }; activeContIndex: number; envPage: createAppEnvPage; - page: createAppTabs; + page: number; app: AppIn; } @@ -99,7 +91,7 @@ export const useAppState = () => { }); }; - const setPage: ISetState = (fn) => { + const setPage: ISetState = (fn) => { if (typeof fn === 'function') { setState((s) => ({ ...s, page: fn(s.page) })); } else { @@ -117,7 +109,7 @@ export const useAppState = () => { useEffect(() => { if (!page) { - setPage('Application details'); + setPage(1); } if (!envPage) { setEnvPage('environment_variables'); @@ -159,7 +151,7 @@ export const useAppState = () => { } }; - const isPageComplete = (page: createAppTabs) => { + const isPageComplete = (page: number) => { if (completePages) return completePages[page]; setState((s) => { @@ -171,7 +163,7 @@ export const useAppState = () => { return false; }; - const markPageAsCompleted = (page: createAppTabs) => { + const markPageAsCompleted = (page: number) => { setState((s) => { return { ...s, @@ -185,7 +177,7 @@ export const useAppState = () => { const resetState = (iApp?: AppIn) => { setState({ - page: 'Application details', + page: 1, app: iApp || defaultApp, completePages: {}, envPage: 'environment_variables', diff --git a/src/apps/console/page-components/new-cluster.tsx b/src/apps/console/page-components/new-cluster.tsx index 24d60f3ee..08cd39979 100644 --- a/src/apps/console/page-components/new-cluster.tsx +++ b/src/apps/console/page-components/new-cluster.tsx @@ -65,6 +65,7 @@ export const NewCluster = ({ providerSecrets, cloudProvider }: props) => { })); const { a: accountName } = useParams(); + const rootUrl = `/${accountName}/infra/clusters`; const { currentStep, jumpStep, nextStep } = useMultiStepProgress({ defaultStep: isOnboarding ? 4 : 1, @@ -151,7 +152,7 @@ export const NewCluster = ({ providerSecrets, cloudProvider }: props) => { throw e[0]; } toast.success('Cluster created successfully'); - navigate(`/${accountName}/infra/clusters`); + navigate(rootUrl); } catch (err) { handleError(err); } @@ -173,7 +174,7 @@ export const NewCluster = ({ providerSecrets, cloudProvider }: props) => { const getView = () => { return ( -
+
{ : { backButton: { content: 'Back to clusters', - to: `/${accountName}/infra/clusters`, + to: rootUrl, }, })} > isOnboarding || !(step < currentStep)} currentStep={currentStep} jumpStep={jumpStep} + editable={!isOnboarding} > {!isOnboarding ? ( <> @@ -328,7 +330,7 @@ export const NewCluster = ({ providerSecrets, cloudProvider }: props) => { jumpStep(1); }} > -
+
Cluster name diff --git a/src/apps/console/page-components/new-project.tsx b/src/apps/console/page-components/new-project.tsx index d7d69c391..34717d7c6 100644 --- a/src/apps/console/page-components/new-project.tsx +++ b/src/apps/console/page-components/new-project.tsx @@ -28,6 +28,7 @@ const NewProject = () => { const params = useParams(); const { a: accountName } = params; + const rootUrl = `/${accountName}/projects`; const { currentStep, jumpStep, nextStep } = useMultiStepProgress({ defaultStep: 1, @@ -68,7 +69,7 @@ const NewProject = () => { throw e[0]; } toast.success('project created successfully'); - navigate(`/${accountName}/projects`); + navigate(rootUrl); } catch (err) { handleError(err); } @@ -102,7 +103,7 @@ const NewProject = () => { subTitle="Simplify Collaboration and Enhance Productivity with Kloudlite teams" backButton={{ content: 'Back to projects', - to: `/${accountName}/projects`, + to: rootUrl, }} > diff --git a/src/apps/console/routes/_a+/new-team.tsx b/src/apps/console/routes/_a+/new-team.tsx index 09d99b4b5..e0a7ef1f0 100644 --- a/src/apps/console/routes/_a+/new-team.tsx +++ b/src/apps/console/routes/_a+/new-team.tsx @@ -8,8 +8,11 @@ import { UserMe } from '~/root/lib/server/gql/saved-queries'; import Yup from '~/root/lib/server/helpers/yup'; import { handleError } from '~/root/lib/utils/common'; import { useConsoleApi } from '~/console/server/gql/api-provider'; -import ProgressWrapper from '~/console/components/progress-wrapper'; import { NameIdView } from '~/console/components/name-id-view'; +import MultiStepProgressWrapper from '~/console/components/multi-step-progress-wrapper'; +import MultiStepProgress, { + useMultiStepProgress, +} from '~/console/components/multi-step-progress'; const NewAccount = () => { const api = useConsoleApi(); @@ -45,61 +48,53 @@ const NewAccount = () => { }, }); - const progressItems = [ - { - label: 'Create Team', - active: true, - completed: false, - children: ( -
- -
-
- - ), - }, - { - label: 'Add your Cloud Provider', - active: false, - completed: false, - }, - { - label: 'Validate Cloud Provider', - active: false, - completed: false, - }, - { - label: 'Setup First Cluster', - active: false, - completed: false, - }, - ]; + const { currentStep, jumpStep } = useMultiStepProgress({ + defaultStep: 1, + totalSteps: 4, + }); return ( - + > + true} + jumpStep={jumpStep} + > + +
+ +
+
+
+
+ + + +
+ + ); }; diff --git a/src/apps/console/routes/_a+/onboarding+/$a+/$cloudprovider+/validate-cp.tsx b/src/apps/console/routes/_a+/onboarding+/$a+/$cloudprovider+/validate-cp.tsx index 2655de7c1..0e54073f8 100644 --- a/src/apps/console/routes/_a+/onboarding+/$a+/$cloudprovider+/validate-cp.tsx +++ b/src/apps/console/routes/_a+/onboarding+/$a+/$cloudprovider+/validate-cp.tsx @@ -19,6 +19,10 @@ import { LoadingPlaceHolder } from '~/console/components/loading'; import CodeView from '~/console/components/code-view'; import { asyncPopupWindow } from '~/console/utils/commons'; import ProgressWrapper from '~/console/components/progress-wrapper'; +import MultiStepProgressWrapper from '~/console/components/multi-step-progress-wrapper'; +import MultiStepProgress, { + useMultiStepProgress, +} from '~/console/components/multi-step-progress'; import { IAccountContext } from '../../../../_main+/$account+/_layout'; export const loader = async (ctx: IRemixCtx) => { @@ -45,7 +49,6 @@ export const loader = async (ctx: IRemixCtx) => { const Validator = ({ cloudProvider }: { cloudProvider: any }) => { const { account } = useOutletContext(); - const [showUnsavedChanges, setShowUnsavedChanges] = useState(false); const navigate = useNavigate(); const api = useConsoleApi(); @@ -73,126 +76,114 @@ const Validator = ({ cloudProvider }: { cloudProvider: any }) => { } ); - const progressItems = [ - { - label: 'Create Team', - active: false, - completed: true, - }, - { - label: 'Invite your Team Members', - active: false, - completed: true, - }, - { - label: 'Add your Cloud Provider', - active: false, - completed: true, - }, - { - label: 'Validate Cloud Provider', - active: true, - completed: false, - children: ( -
-
- Validate your cloud provider's credentials -
- {il ? ( -
- -
- ) : data?.result ? ( -
- }> - Your Credential is valid - -
- ) : ( -
-
- Account ID - - {cloudProvider.aws?.awsAccountId} - -
-
- - - - visit the link above or - - to create AWS cloudformation stack - -
-
- )} -
- {/*
-
- ), - }, - { - label: 'Setup First Cluster', - active: false, - completed: false, - }, - ]; + const { currentStep, jumpStep } = useMultiStepProgress({ + defaultStep: 3, + totalSteps: 4, + }); return ( - + > + true} + jumpStep={jumpStep} + > + + + +
+
+ Validate your cloud provider's credentials +
+ {il ? ( +
+ +
+ ) : data?.result ? ( +
+ }> + Your Credential is valid + +
+ ) : ( +
+
+ Account ID + + {cloudProvider.aws?.awsAccountId} + +
+
+ + + + visit the link above or + + to create AWS cloudformation stack + +
+
+ )} +
+
+
+
+ +
+ + ); }; diff --git a/src/apps/console/routes/_a+/onboarding+/$a+/new-cloud-provider.tsx b/src/apps/console/routes/_a+/onboarding+/$a+/new-cloud-provider.tsx index 2ed12a137..5d599a4b9 100644 --- a/src/apps/console/routes/_a+/onboarding+/$a+/new-cloud-provider.tsx +++ b/src/apps/console/routes/_a+/onboarding+/$a+/new-cloud-provider.tsx @@ -10,8 +10,11 @@ import { handleError } from '~/root/lib/utils/common'; import { useState } from 'react'; import { useConsoleApi } from '~/console/server/gql/api-provider'; import { validateCloudProvider } from '~/console/server/r-utils/common'; -import ProgressWrapper from '~/console/components/progress-wrapper'; import { NameIdView } from '~/console/components/name-id-view'; +import MultiStepProgressWrapper from '~/console/components/multi-step-progress-wrapper'; +import MultiStepProgress, { + useMultiStepProgress, +} from '~/console/components/multi-step-progress'; const NewCloudProvider = () => { const { a: accountName } = useParams(); @@ -80,92 +83,89 @@ const NewCloudProvider = () => { }, }); - const progressItems = [ - { - label: 'Create Team', - active: false, - completed: true, - }, - { - label: 'Add your Cloud Provider', - active: true, - completed: false, - children: ( -
-
- A cloud provider offers remote computing resources and services over - the internet. -
-
- -
- { + handleChange('provider')(dummyEvent(value)); + }} + options={async () => providers} + /> + + {values.provider.value === 'aws' && ( + + )} +
+
+
+
+
+ + + + + + ); }; diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-compute.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-compute.tsx index 8d775f13c..cf71f78d3 100644 --- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-compute.tsx +++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-compute.tsx @@ -134,12 +134,11 @@ const AppCompute = () => { (async () => { const res = await submit(); if (res) { - setPage('Environment'); - markPageAsCompleted('Compute'); + setPage(3); + markPageAsCompleted(2); } })(); }} - className="py-3xl" >
Compute refers to the processing power and resources used for data @@ -396,7 +395,7 @@ const AppCompute = () => {
*/} -
+
diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-environment.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-environment.tsx index 7bf68b801..502627173 100644 --- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-environment.tsx +++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-environment.tsx @@ -33,7 +33,7 @@ const AppEnvironment = () => { ]; return ( - +
{ -
+
diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-network.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-network.tsx index 27d547c4f..ef0ad5eed 100644 --- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-network.tsx +++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-network.tsx @@ -234,21 +234,20 @@ export const ExposedPorts = () => { const AppNetwork = () => { const { setPage, markPageAsCompleted } = useAppState(); - console.log('networkd'); return ( - +
Expose service ports that need to be exposed from container
-
+
diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-review.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-review.tsx index 9fca4b87e..be67e0a45 100644 --- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-review.tsx +++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-review.tsx @@ -171,13 +171,13 @@ const AppReview = () => { })}
)} -
+