diff --git a/.gitignore b/.gitignore
index f02da370b..9f711bc21 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,6 +29,7 @@ public/**
out
.firebase
+.firebaseConfig.js
storybook-dist
diff --git a/package.json b/package.json
index 9e44a406a..f36c2760f 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
"@codemirror/legacy-modes": "^6.3.3",
"@jengaicons/react": "^1.3.0",
"@mdx-js/react": "^2.3.0",
- "@oshq/react-select": "^1.3.0",
+ "@oshq/react-select": "^1.3.2",
"@radix-ui/primitive": "^1.0.1",
"@radix-ui/react-alert-dialog": "1.0.4",
"@radix-ui/react-checkbox": "^1.0.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a6d305692..0846b6e63 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -18,8 +18,8 @@ dependencies:
specifier: ^2.3.0
version: 2.3.0(react@18.2.0)
'@oshq/react-select':
- specifier: ^1.3.0
- version: 1.3.0(@radix-ui/react-portal@1.0.4)(classnames@2.5.1)(framer-motion@10.17.8)(rc-virtual-list@3.11.3)(react@18.2.0)
+ specifier: ^1.3.2
+ version: 1.3.2(@radix-ui/react-portal@1.0.4)(classnames@2.5.1)(framer-motion@10.17.8)(rc-virtual-list@3.11.3)(react@18.2.0)
'@radix-ui/primitive':
specifier: ^1.0.1
version: 1.0.1
@@ -2607,8 +2607,8 @@ packages:
json-parse-even-better-errors: 2.3.1
dev: true
- /@oshq/react-select@1.3.0(@radix-ui/react-portal@1.0.4)(classnames@2.5.1)(framer-motion@10.17.8)(rc-virtual-list@3.11.3)(react@18.2.0):
- resolution: {integrity: sha512-Q9qZugOhG4Q8Cpt4U5lk4GuA8m2l4YED+fciVRVllsWy8H9If8zX6vo+pbSJhzd4YE5KwmjeKmt0Q7jHLS7Nzw==}
+ /@oshq/react-select@1.3.2(@radix-ui/react-portal@1.0.4)(classnames@2.5.1)(framer-motion@10.17.8)(rc-virtual-list@3.11.3)(react@18.2.0):
+ resolution: {integrity: sha512-G07uCRUqXMPM/0ZwMBaKHTIoA507D7pgbDOBEMETnGBfhLnk4rI6wcAioVxP5/IuletCyUZrARa7ixWuitgFow==}
peerDependencies:
'@radix-ui/react-portal': ^1.0.4
classnames: ^2.3.2
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+/$a+/new-project.tsx b/src/apps/console/routes/_a+/$a+/new-project.tsx
index 7d6656415..606513b55 100644
--- a/src/apps/console/routes/_a+/$a+/new-project.tsx
+++ b/src/apps/console/routes/_a+/$a+/new-project.tsx
@@ -5,7 +5,6 @@ import { getPagination, getSearch } from '~/console/server/utils/common';
import logger from '~/root/lib/client/helpers/log';
import { IRemixCtx } from '~/root/lib/types/common';
-
const _NewProject = () => {
return ;
};
diff --git a/src/apps/console/routes/_a+/new-team.tsx b/src/apps/console/routes/_a+/new-team.tsx
index 66c651f62..e0a7ef1f0 100644
--- a/src/apps/console/routes/_a+/new-team.tsx
+++ b/src/apps/console/routes/_a+/new-team.tsx
@@ -1,225 +1,34 @@
-import { ArrowRight, Plus, X } from '@jengaicons/react';
-import { useNavigate, useParams } from '@remix-run/react';
-import { Button, IconButton } from '~/components/atoms/button';
-import { TextInput } from '~/components/atoms/input';
+import { ArrowRight } from '@jengaicons/react';
+import { useNavigate } from '@remix-run/react';
+import { Button } from '~/components/atoms/button';
import { toast } from '~/components/molecule/toast';
import { useDataFromMatches } from '~/root/lib/client/hooks/use-custom-matches';
-import useForm, { dummyEvent } from '~/root/lib/client/hooks/use-form';
+import useForm from '~/root/lib/client/hooks/use-form';
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 { useEffect, useState } from 'react';
import { useConsoleApi } from '~/console/server/gql/api-provider';
-import RawWrapper, { TitleBox } from '~/console/components/raw-wrapper';
-import { FadeIn } from '~/console/page-components/util';
-import { IdSelector } from '~/console/components/id-selector';
-import ProgressWrapper from '~/console/components/progress-wrapper';
-import SelectPrimitive from '~/components/atoms/select-primitive';
-import DynamicPagination from '~/console/components/dynamic-pagination';
-import List from '~/console/components/list';
-import {
- ListBody,
- ListItem,
-} from '~/console/components/console-list-components';
-import { usePagination } from '~/components/molecule/pagination';
-import { ACCOUNT_ROLES } from '~/console/utils/commons';
-import { Github__Com___Kloudlite___Api___Apps___Iam___Types__Role as Role } from '~/root/src/generated/gql/server';
-import { titleCase } from '~/components/utils';
+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 InviteSection = () => {
- const { a: accountName } = useParams();
- const api = useConsoleApi();
- const [inviting, setInviting] = useState(false);
-
- const [inviteMembers, setInviteMembers] = useState<
- { userEmail: string; userRole: Role }[]
- >([]);
-
- const {
- values: valuesInvite,
- errors: errorsInvite,
- handleChange: handleChangeInvite,
- handleSubmit: handleSubmitInvite,
- resetValues: resetValuesInvite,
- } = useForm({
- initialValues: {
- userEmail: '',
- userRole: 'account_member',
- },
- validationSchema: Yup.object({
- userEmail: Yup.string()
- .required()
- .email()
- .test('is-valid', 'Email already exists.', (value) => {
- return !inviteMembers.find(
- (im) => im.userEmail.toLowerCase() === value.toLowerCase()
- );
- }),
- userRole: Yup.string().required().oneOf(Object.keys(ACCOUNT_ROLES)),
- }),
- onSubmit: async () => {
- setInviteMembers((prev) => [
- ...prev,
- {
- userEmail: valuesInvite.userEmail,
- userRole: valuesInvite.userRole as Role,
- },
- ]);
- resetValuesInvite();
- },
- });
-
- const { page, hasNext, hasPrevious, onNext, onPrev, setItems } =
- usePagination({
- items: inviteMembers,
- itemsPerPage: 5,
- });
-
- useEffect(() => {
- setItems(inviteMembers);
- }, [inviteMembers]);
-
- const removeMember = ({ item }: { item: (typeof inviteMembers)[number] }) => {
- setInviteMembers(inviteMembers.filter((im) => im !== item));
- };
-
- const sendInvitation = async () => {
- if (inviting) {
- return;
- }
-
- if (inviteMembers.length > 0) {
- try {
- setInviting(true);
- const { errors: e } = await api.inviteMembersForAccount({
- accountName: accountName!,
- invitations: inviteMembers,
- });
- if (e) {
- throw e[0];
- }
- toast.success('user invited');
- // navigate(`/onboarding/${accountName}/new-cloud-provider`);
- } catch (err) {
- handleError(err);
- } finally {
- setInviting(false);
- }
- } else {
- // navigate(`/onboarding/${accountName}/new-cloud-provider`);
- }
- };
- return (
-
-
-
0,
- noItemsMessage: '0 teammates to invite.',
- onNext,
- onPrev,
- headerClassName: 'bg-surface-basic-subdued',
- header: Team list
,
- }}
- className="rounded border border-border-default overflow-hidden min-h-[266px]"
- >
-
- {page.map((item) => {
- return (
- ,
- },
- {
- key: 2,
- render: () => ,
- },
- {
- key: 3,
- render: () => (
- }
- variant="plain"
- size="sm"
- onClick={() => {
- removeMember({ item });
- }}
- />
- ),
- },
- ]}
- />
- );
- })}
-
-
-
- );
-};
const NewAccount = () => {
const api = useConsoleApi();
const navigate = useNavigate();
const user = useDataFromMatches('user', {});
- const [isNameLoading, setIsNameLoading] = useState(false);
const { values, handleChange, errors, isLoading, handleSubmit } = useForm({
initialValues: {
name: '',
displayName: '',
+ isNameError: false,
},
validationSchema: Yup.object({
name: Yup.string().required(),
displayName: Yup.string().required(),
}),
onSubmit: async (v) => {
- if (isNameLoading) {
- toast.error('id is being checked, please wait');
- return;
- }
try {
const { errors: _errors } = await api.createAccount({
account: {
@@ -239,70 +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}
+ >
+
+
+
+
+ }
+ size="md"
+ loading={isLoading}
+ type="submit"
+ />
+
+
+
+
+
+
+
+
+
);
};
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
-
-
-
- )}
-
- {/* } */}
- {/* size="lg" */}
- {/* /> */}
- }
- onClick={() => {
- navigate(
- `/onboarding/${parseName(account)}/${parseName(
- cloudProvider
- )}/new-cluster`
- );
- }}
- />
-
-
- ),
- },
- {
- 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
+
+
+
+ )}
+
+ }
+ onClick={() => {
+ navigate(
+ `/onboarding/${parseName(account)}/${parseName(
+ cloudProvider
+ )}/new-cluster`
+ );
+ }}
+ />
+
+
+
+
+
+
+
);
};
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: (
-
- ),
- },
- {
- label: 'Validate Cloud Provider',
- active: false,
- completed: false,
- },
- {
- label: 'Setup First Cluster',
- active: false,
- completed: false,
- },
- ];
+ const { currentStep, jumpStep } = useMultiStepProgress({
+ defaultStep: 2,
+ totalSteps: 4,
+ });
return (
-
+ >
+ true}
+ jumpStep={jumpStep}
+ >
+
+
+
+
+ A cloud provider offers remote computing resources and services
+ over the internet.
+
+
+
+
+
+
+
+ }
+ />
+
+
+
+
+
+
+
+
);
};
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 = () => {
*/}
-
+
}
@@ -405,7 +404,7 @@ const AppCompute = () => {
(async () => {
const res = await submit();
if (res) {
- setPage('Application details');
+ setPage(1);
}
})();
}}
diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-detail.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-detail.tsx
index 56d3a481b..9b0ccc0b5 100644
--- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-detail.tsx
+++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/app-detail.tsx
@@ -1,10 +1,9 @@
import { ArrowRight } from '@jengaicons/react';
import { Button } from '~/components/atoms/button';
import { TextInput } from '~/components/atoms/input';
-import { IdSelector } from '~/console/components/id-selector';
import { useAppState } from '~/console/page-components/app-states';
import { keyconstants } from '~/console/server/r-utils/key-constants';
-import useForm, { dummyEvent } from '~/root/lib/client/hooks/use-form';
+import useForm from '~/root/lib/client/hooks/use-form';
import Yup from '~/root/lib/server/helpers/yup';
import { parseName } from '~/console/server/r-utils/common';
import { FadeIn } from '~/console/page-components/util';
@@ -41,8 +40,8 @@ const AppDetail = () => {
displayName: val.displayName,
};
});
- setPage('Compute');
- markPageAsCompleted('Application details');
+ setPage(2);
+ markPageAsCompleted(1);
},
});
@@ -55,7 +54,6 @@ const AppDetail = () => {
e.preventDefault();
}
}}
- className="py-3xl"
>
The application streamlines project management through intuitive task
@@ -82,14 +80,13 @@ const AppDetail = () => {
onChange={handleChange('description')}
/>
-
+
}
variant="primary"
- // onClick={next}
/>
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 (
-
+
{
-
+
}
variant="outline"
onClick={() => {
- setPage('Compute');
+ setPage(2);
}}
/>
@@ -72,8 +72,8 @@ const AppEnvironment = () => {
suffix={
}
variant="primary"
onClick={() => {
- setPage('Network');
- markPageAsCompleted('Environment');
+ setPage(4);
+ markPageAsCompleted(3);
}}
/>
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
-
+
}
variant="outline"
onClick={() => {
- setPage('Environment');
+ setPage(3);
}}
/>
@@ -259,9 +258,9 @@ const AppNetwork = () => {
suffix={
}
variant="primary"
onClick={() => {
- setPage('Review');
- markPageAsCompleted('Network');
- markPageAsCompleted('Review');
+ setPage(5);
+ markPageAsCompleted(4);
+ markPageAsCompleted(5);
}}
/>
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 = () => {
})}
)}
-
+
}
variant="outline"
onClick={() => {
- setPage('Network');
+ setPage(4);
}}
/>
diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/route.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/route.tsx
index 40a42a72f..2bcf367d0 100644
--- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/route.tsx
+++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-app/route.tsx
@@ -1,85 +1,61 @@
-import { useMapper } from '~/components/utils';
import {
AppContextProvider,
- createAppTabs,
useAppState,
} from '~/console/page-components/app-states';
-import ProgressWrapper from '~/console/components/progress-wrapper';
+import MultiStepProgress, {
+ useMultiStepProgress,
+} from '~/console/components/multi-step-progress';
+import MultiStepProgressWrapper from '~/console/components/multi-step-progress-wrapper';
+import { useEffect } from 'react';
import AppCompute from './app-compute';
import AppDetail from './app-detail';
import AppEnvironment from './app-environment';
import AppNetwork from './app-network';
import AppReview from './app-review';
-import { FadeIn } from '../../../../../../page-components/util';
const AppComp = () => {
const { setPage, page, isPageComplete } = useAppState();
- const isActive = (t: createAppTabs) => t === page;
- const progressItems: {
- label: createAppTabs;
- }[] = [
- {
- label: 'Application details',
- },
- {
- label: 'Compute',
- },
- {
- label: 'Environment',
- },
- {
- label: 'Network',
- },
- {
- label: 'Review',
- },
- ];
-
- const tab = () => {
- switch (page) {
- case 'Application details':
- return
;
- case 'Compute':
- return
;
- case 'Environment':
- return
;
- case 'Network':
- return
;
- case 'Review':
- return
;
- default:
- return (
-
- 404 | page not found
-
- );
- }
- };
-
- const items = useMapper(progressItems, (i) => {
- return {
- label: i.label,
- active: isActive(i.label),
- completed: isPageComplete(i.label),
- children: isActive(i.label) ? tab() : null,
- };
+ const { currentStep, jumpStep } = useMultiStepProgress({
+ defaultStep: page || 1,
+ totalSteps: 5,
});
- return (
-
{
- console.log(p);
+ useEffect(() => {
+ jumpStep(page);
+ }, [page]);
- if (isPageComplete(p.label as createAppTabs))
- setPage(p.label as createAppTabs);
- }}
+ return (
+
+ >
+ setPage(step)}
+ noJump={(step) => !isPageComplete(step)}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-managed-resource/_index.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-managed-resource/_index.tsx
index 0125b5ab6..515b96238 100644
--- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-managed-resource/_index.tsx
+++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-managed-resource/_index.tsx
@@ -10,17 +10,10 @@ import {
import { Button } from '~/components/atoms/button';
import Select from '~/components/atoms/select';
import { NameIdView } from '~/console/components/name-id-view';
-import ProgressWrapper from '~/console/components/progress-wrapper';
import { useConsoleApi } from '~/console/server/gql/api-provider';
import useForm, { dummyEvent } from '~/root/lib/client/hooks/use-form';
import Yup from '~/root/lib/server/helpers/yup';
-import {
- Dispatch,
- FormEventHandler,
- SetStateAction,
- useEffect,
- useState,
-} from 'react';
+import { FormEventHandler, useEffect, useState } from 'react';
import { IMSvTemplate } from '~/console/server/gql/queries/managed-templates-queries';
import { Switch } from '~/components/atoms/switch';
import { NumberInput, TextInput } from '~/components/atoms/input';
@@ -37,6 +30,10 @@ import {
} from '~/console/server/r-utils/common';
import { IProjectMSvs } from '~/console/server/gql/queries/project-managed-services-queries';
import { getManagedTemplate } from '~/console/utils/commons';
+import MultiStepProgressWrapper from '~/console/components/multi-step-progress-wrapper';
+import MultiStepProgress, {
+ useMultiStepProgress,
+} from '~/console/components/multi-step-progress';
import { ReviewComponent } from '../new-app/app-review';
import { IProjectContext } from '../../_layout';
@@ -57,11 +54,6 @@ export const loader = (ctx: IRemixCtx) => {
return defer({ promise });
};
-type steps = 'Select service' | 'Configure resource' | 'Review';
-
-const hasResource = (res: any) =>
- (!!res && res?.resource?.fields.length > 0) || !res;
-
const RenderField = ({
field,
value,
@@ -252,7 +244,7 @@ const TemplateView = ({
isLoading,
}: ITemplateView) => {
return (
-