diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/app+/$app+/settings+/compute/route.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/app+/$app+/settings+/compute/route.tsx
index 221b13789..6cf949c8e 100644
--- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/app+/$app+/settings+/compute/route.tsx
+++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/app+/$app+/settings+/compute/route.tsx
@@ -13,11 +13,10 @@ import ExtendedFilledTab from '~/console/components/extended-filled-tab';
import Wrapper from '~/console/components/wrapper';
import { useUnsavedChanges } from '~/root/lib/client/hooks/use-unsaved-changes';
import { Button } from '~/components/atoms/button';
+import useCustomSwr from '~/lib/client/hooks/use-custom-swr';
+import { useConsoleApi } from '~/console/server/gql/api-provider';
+import { parseNodes } from '~/console/server/r-utils/common';
import { plans } from '../../../../new-app/datas';
-import useCustomSwr from "~/lib/client/hooks/use-custom-swr";
-import {useConsoleApi} from "~/console/server/gql/api-provider";
-import {useMapper} from "~/components/utils";
-import {parseNodes} from "~/console/server/r-utils/common";
const valueRender = ({
label,
@@ -41,15 +40,13 @@ const valueRender = ({
};
const SettingCompute = () => {
- const { app, setApp, getContainer, activeContIndex, getRepoMapper } = useAppState();
+ const { app, setApp, getContainer, activeContIndex, getRepoMapper } =
+ useAppState();
const { setPerformAction, hasChanges, loading } = useUnsavedChanges();
- const api = useConsoleApi()
-
- const [selectedRepo, setSelectedRepo] = useState("");
- const [imageDigests, setImageDigests] = useState<{ tags: string[], digest: string }[]>([])
- const [accountName, setAccountName] = useState("")
+ const api = useConsoleApi();
+ const [accountName, setAccountName] = useState('');
const {
data,
@@ -66,8 +63,8 @@ const SettingCompute = () => {
cpuMode: app.metadata?.annotations?.[keyconstants.cpuMode] || 'shared',
memPerCpu: app.metadata?.annotations?.[keyconstants.memPerCpu] || 1,
- repoName: '',
- repoImageTag: '',
+ repoName: app.metadata?.annotations?.[keyconstants.repoName] || '',
+ repoImageTag: app.metadata?.annotations?.[keyconstants.imageTag] || '',
repoImageUrl: '',
cpu: parseValue(
@@ -111,6 +108,8 @@ const SettingCompute = () => {
...(s.metadata?.annotations || {}),
[keyconstants.cpuMode]: val.cpuMode,
[keyconstants.selectedPlan]: val.selectedPlan,
+ [keyconstants.repoName]: val.repoName,
+ [keyconstants.imageTag]: val.repoImageTag,
},
},
spec: {
@@ -161,22 +160,18 @@ const SettingCompute = () => {
// accName: val.accountName
// }));
- const repos = getRepoMapper(data)
-
-
- useEffect(() => {
- (async () => {
- const {data} = await api.listDigest({repoName: selectedRepo})
-
- const digests = data.edges.map(item => ({
- digest: item.node.digest,
- tags: item.node.tags,
- }))
-
- setImageDigests(digests);
- })()
+ const repos = getRepoMapper(data);
- }, [selectedRepo])
+ const {
+ data: digestData,
+ isLoading: digestLoading,
+ error: digestError,
+ } = useCustomSwr(
+ () => `/digests_${values.repoName}`,
+ async () => {
+ return api.listDigest({ repoName: values.repoName });
+ }
+ );
useEffect(() => {
submit();
@@ -213,14 +208,14 @@ const SettingCompute = () => {
>
- }
- size="lg"
- value={values.imageUrl}
- onChange={handleChange('imageUrl')}
- error={!!errors.imageUrl}
- message={errors.imageUrl}
+ label={
+
+ }
+ size="lg"
+ value={values.imageUrl}
+ onChange={handleChange('imageUrl')}
+ error={!!errors.imageUrl}
+ message={errors.imageUrl}
/>
{/*
{
// onChange={handleChange('pullSecret')}
/> */}
-
- OR
-
+ OR
{/*
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 30de2d47e..029bcabe2 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
@@ -1,429 +1,420 @@
-import {ArrowLeft, ArrowRight} from '@jengaicons/react';
-import {Button} from '~/components/atoms/button';
-import {NumberInput, TextInput} from '~/components/atoms/input';
+import { ArrowLeft, ArrowRight } from '@jengaicons/react';
+import { Button } from '~/components/atoms/button';
+import { NumberInput, TextInput } from '~/components/atoms/input';
import Slider from '~/components/atoms/slider';
-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 { 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 Yup from '~/root/lib/server/helpers/yup';
-import {InfoLabel} from '~/console/components/commons';
-import {FadeIn, parseValue} from '~/console/page-components/util';
+import { InfoLabel } from '~/console/components/commons';
+import { FadeIn, parseValue } from '~/console/page-components/util';
import Select from '~/components/atoms/select';
import ExtendedFilledTab from '~/console/components/extended-filled-tab';
-import {plans} from './datas';
-import {ExtractNodeType, parseName, parseNodes} from "~/console/server/r-utils/common";
-import {IRepos} from "~/console/server/gql/queries/repo-queries";
-import useCustomSwr from "~/lib/client/hooks/use-custom-swr";
-import {useConsoleApi} from "~/console/server/gql/api-provider";
-import {IDigests} from "~/console/server/gql/queries/tags-queries";
-import {useAppend, useMapper} from "~/components/utils";
-import {IDialogBase} from "~/console/components/types.d";
-import {useEffect, useRef, useState} from "react";
-
+import { parseNodes } from '~/console/server/r-utils/common';
+import useCustomSwr from '~/lib/client/hooks/use-custom-swr';
+import { useConsoleApi } from '~/console/server/gql/api-provider';
+import { useMapper } from '~/components/utils';
+import { useState } from 'react';
+import { plans } from './datas';
const valueRender = ({
- label,
- isShared,
- memoryPerCpu,
- }: {
- label: string;
- isShared: boolean;
- memoryPerCpu: number;
+ label,
+ isShared,
+ memoryPerCpu,
+}: {
+ label: string;
+ isShared: boolean;
+ memoryPerCpu: number;
}) => {
- return (
-
+ return (
+
{label}-{isShared ? 'Shared' : 'Dedicated'}
-
+
{memoryPerCpu}GB/vCPU
-
- );
-};
-
-type ISelectedRepo = {
- label: string;
- value: string;
- service: ExtractNodeType
;
+
+ );
};
-type ISelectedImage = {
- label: string;
- value: string;
- service: ExtractNodeType
;
-};
-
-type IDialog = IDialogBase>;
-
-
const AppCompute = () => {
- const {app, setApp, setPage, markPageAsCompleted, activeContIndex} =
- useAppState();
- const api = useConsoleApi()
-
- const [selectedRepo, setSelectedRepo] = useState("");
- const [imageDigests, setImageDigests] = useState<{ tags: string[], digest: string }[]>([])
- const [accountName, setAccountName] = useState("")
- const [showImageUrl, setShowImageUrl] = useState(true)
-
- const {
- data,
- isLoading: repoLoading,
- error: repoLoadingError,
- } = useCustomSwr('/repos', async () => {
- return api.listRepo({});
- });
-
-
- const {values, errors, handleChange, isLoading, submit} = useForm({
- initialValues: {
- imageUrl: app.spec.containers[activeContIndex]?.image || '',
- pullSecret: 'TODO',
- cpuMode: app.metadata?.annotations?.[keyconstants.cpuMode] || 'shared',
- memPerCpu: app.metadata?.annotations?.[keyconstants.memPerCpu] || '1',
-
- cpu: parseValue(
- app.spec.containers[activeContIndex]?.resourceCpu?.max,
- 250
- ),
-
- repoName: '',
- repoImageTag: '',
- repoImageUrl: '',
-
- selectedPlan:
- app.metadata?.annotations[keyconstants.selectedPlan] || 'shared-1',
- selectionMode:
- app.metadata?.annotations[keyconstants.selectionModeKey] || 'quick',
- manualCpuMin: parseValue(
- app.spec.containers[activeContIndex].resourceCpu?.min,
- 0
- ),
- manualCpuMax: parseValue(
- app.spec.containers[activeContIndex].resourceCpu?.max,
- 0
- ),
- manualMemMin: parseValue(
- app.spec.containers[activeContIndex].resourceMemory?.min,
- 0
- ),
- manualMemMax: parseValue(
- app.spec.containers[activeContIndex].resourceMemory?.max,
- 0
- ),
+ const { app, setApp, setPage, markPageAsCompleted, activeContIndex } =
+ useAppState();
+ const api = useConsoleApi();
+
+ const [accountName, setAccountName] = useState('');
+ const [showImageUrl, setShowImageUrl] = useState(true);
+
+ const {
+ data,
+ isLoading: repoLoading,
+ error: repoLoadingError,
+ } = useCustomSwr('/repos', async () => {
+ return api.listRepo({});
+ });
+
+ const { values, errors, handleChange, isLoading, submit } = useForm({
+ initialValues: {
+ imageUrl: app.spec.containers[activeContIndex]?.image || '',
+ pullSecret: 'TODO',
+ cpuMode: app.metadata?.annotations?.[keyconstants.cpuMode] || 'shared',
+ memPerCpu: app.metadata?.annotations?.[keyconstants.memPerCpu] || '1',
+
+ cpu: parseValue(
+ app.spec.containers[activeContIndex]?.resourceCpu?.max,
+ 250
+ ),
+
+ repoName: app.metadata?.annotations?.[keyconstants.repoName] || '',
+ repoImageTag: app.metadata?.annotations?.[keyconstants.imageTag] || '',
+ repoImageUrl: '',
+
+ selectedPlan:
+ app.metadata?.annotations[keyconstants.selectedPlan] || 'shared-1',
+ selectionMode:
+ app.metadata?.annotations[keyconstants.selectionModeKey] || 'quick',
+ manualCpuMin: parseValue(
+ app.spec.containers[activeContIndex].resourceCpu?.min,
+ 0
+ ),
+ manualCpuMax: parseValue(
+ app.spec.containers[activeContIndex].resourceCpu?.max,
+ 0
+ ),
+ manualMemMin: parseValue(
+ app.spec.containers[activeContIndex].resourceMemory?.min,
+ 0
+ ),
+ manualMemMax: parseValue(
+ app.spec.containers[activeContIndex].resourceMemory?.max,
+ 0
+ ),
+ },
+ validationSchema: Yup.object({
+ // imageUrl: Yup.string().required(),
+ pullSecret: Yup.string(),
+ cpuMode: Yup.string().required(),
+ selectedPlan: Yup.string().required(),
+ // cpu: Yup.number().required().min(100).max(8000),
+ }),
+ onSubmit: (val) => {
+ setApp((s) => ({
+ ...s,
+ metadata: {
+ ...s.metadata!,
+ annotations: {
+ ...(s.metadata?.annotations || {}),
+ [keyconstants.cpuMode]: val.cpuMode,
+ [keyconstants.memPerCpu]: val.memPerCpu,
+ [keyconstants.selectionModeKey]: val.selectionMode,
+ [keyconstants.selectedPlan]: val.selectedPlan,
+ [keyconstants.repoName]: val.repoName,
+ [keyconstants.imageTag]: val.repoImageTag,
+ },
},
- validationSchema: Yup.object({
- // imageUrl: Yup.string().required(),
- pullSecret: Yup.string(),
- cpuMode: Yup.string().required(),
- selectedPlan: Yup.string().required(),
- // cpu: Yup.number().required().min(100).max(8000),
- }),
- onSubmit: (val) => {
- setApp((s) => ({
- ...s,
- metadata: {
- ...s.metadata!,
- annotations: {
- ...(s.metadata?.annotations || {}),
- [keyconstants.cpuMode]: val.cpuMode,
- [keyconstants.memPerCpu]: val.memPerCpu,
- [keyconstants.selectionModeKey]: val.selectionMode,
- [keyconstants.selectedPlan]: val.selectedPlan,
+ spec: {
+ ...s.spec,
+ containers: [
+ {
+ ...(s.spec.containers?.[0] || {}),
+ image: val.imageUrl === '' ? val.repoImageUrl : val.imageUrl,
+ name: 'container-0',
+ resourceCpu:
+ val.selectionMode === 'quick'
+ ? {
+ max: `${val.cpu}m`,
+ min: `${val.cpu}m`,
+ }
+ : {
+ max: `${val.manualCpuMax}m`,
+ min: `${val.manualCpuMin}m`,
},
- },
- spec: {
- ...s.spec,
- containers: [
- {
- ...(s.spec.containers?.[0] || {}),
- image: val.imageUrl == '' ? val.repoImageUrl : val.imageUrl,
- name: 'container-0',
- repoName: val.repoName,
- // repoImage: val.repoImage,
- resourceCpu:
- val.selectionMode === 'quick'
- ? {
- max: `${val.cpu}m`,
- min: `${val.cpu}m`,
- }
- : {
- max: `${val.manualCpuMax}m`,
- min: `${val.manualCpuMin}m`,
- },
- resourceMemory:
- val.selectionMode === 'quick'
- ? {
- max: `${(
- (values.cpu || 1) * parseValue(values.memPerCpu, 4)
- ).toFixed(2)}Mi`,
- min: `${val.cpu}Mi`,
- }
- : {
- max: `${val.manualMemMax}Mi`,
- min: `${val.manualMemMin}Mi`,
- },
- },
- ],
- },
- }));
+ resourceMemory:
+ val.selectionMode === 'quick'
+ ? {
+ max: `${(
+ (values.cpu || 1) * parseValue(values.memPerCpu, 4)
+ ).toFixed(2)}Mi`,
+ min: `${val.cpu}Mi`,
+ }
+ : {
+ max: `${val.manualMemMax}Mi`,
+ min: `${val.manualMemMin}Mi`,
+ },
+ },
+ ],
},
- });
-
- const repos = useMapper(parseNodes(data), (val) => ({
- label: val.name,
- value: val.name,
- accName: val.accountName
- }));
+ }));
+ },
+ });
+
+ const repos = useMapper(parseNodes(data), (val) => ({
+ label: val.name,
+ value: val.name,
+ accName: val.accountName,
+ }));
+
+ const {
+ data: digestData,
+ isLoading: digestLoading,
+ error: digestError,
+ } = useCustomSwr(
+ () => `/digests_${values.repoName}`,
+ async () => {
+ return api.listDigest({ repoName: values.repoName });
+ }
+ );
+
+ return (
+ {
+ e.preventDefault();
-
- useEffect(() => {
(async () => {
- const {data} = await api.listDigest({repoName: selectedRepo})
-
- const digests = data.edges.map(item => ({
- digest: item.node.digest,
- tags: item.node.tags,
- }))
-
- setImageDigests(digests);
- })()
-
- }, [selectedRepo])
-
- return (
- {
- e.preventDefault();
-
- (async () => {
- const res = await submit();
- if (res) {
- setPage(3);
- markPageAsCompleted(2);
- }
- })();
+ const res = await submit();
+ if (res) {
+ setPage(3);
+ markPageAsCompleted(2);
+ }
+ })();
+ }}
+ >
+
+ Compute refers to the processing power and resources used for data
+ manipulation and calculations in a system.
+
+
+ {showImageUrl && (
+
+ }
+ size="lg"
+ value={values.imageUrl}
+ onChange={(e) => {
+ handleChange('imageUrl')(
+ dummyEvent(e.target.value.toLowerCase())
+ );
+ handleChange('repoName')(dummyEvent(''));
+ handleChange('repoImageTag')(dummyEvent(''));
}}
- >
-
- Compute refers to the processing power and resources used for data
- manipulation and calculations in a system.
-
-
- { showImageUrl && (
-
- }
- size="lg"
- value={values.imageUrl}
- onChange={(e) => {
- handleChange('imageUrl')(dummyEvent(e.target.value.toLowerCase()))
- handleChange('repoName')(dummyEvent(''));
- handleChange('repoImageTag')(dummyEvent(''));
- }}
- error={!!errors.imageUrl}
- message={errors.imageUrl}
- />
- )}
-
-
{
- setShowImageUrl(!showImageUrl)
- // handleChange('imageUrl')(dummyEvent(''));
- // handleChange('repoName')(dummyEvent(''));
- // handleChange('repoImageTag')(dummyEvent(''));
- }}
- className={"bodyMd text-border-focus underline underline-offset-2"}>
- { showImageUrl ? "Advanced options" : "Normal options"}
-
-
- {!showImageUrl && (
-
{
- handleChange('repoName')(dummyEvent(val.value));
- handleChange('imageUrl')(dummyEvent(''));
- setSelectedRepo(val.value)
- setAccountName(val.accName)
- }}
- options={async () => [...repos]}
- error={!!errors.repos || !!repoLoadingError}
- message={repoLoadingError ? 'Error fetching apps.' : errors.app}
- loading={repoLoading}
- />
- )}
-
- {!showImageUrl && (
- {
- handleChange('repoImageTag')(dummyEvent(val.value));
- handleChange('repoImageUrl')(dummyEvent(`registry.kloudlite.io/${accountName}/${values.repoName}:${val.value}`))
- }}
- options={async () => [...new Set(imageDigests.map(item => item.tags).flat())].map(item => ({
- label: item,
- value: item,
- }))}
- error={!!errors.repoImageTag}
- message={errors.repoImageTag}
- />
- )}
+ error={!!errors.imageUrl}
+ message={errors.imageUrl}
+ />
+ )}
+
+
-
-
-
-
- {
- handleChange('selectionMode')(dummyEvent(e));
- }}
- items={[
- {label: 'Quick', value: 'quick'},
- {
- label: 'Manual',
- value: 'manual',
- },
- ]}
- />
-
+
+
+
+
+
+ {
+ handleChange('selectionMode')(dummyEvent(e));
+ }}
+ items={[
+ { label: 'Quick', value: 'quick' },
+ {
+ label: 'Manual',
+ value: 'manual',
+ },
+ ]}
+ />
+
+
+ {values.selectionMode === 'quick' ? (
+
+
[
+ ...Object.entries(plans).map(([_, vs]) => ({
+ label: vs.label,
+ options: vs.options.map((op) => ({
+ ...op,
+ render: () => (
+
+
{op.label}
+
{op.memoryPerCpu}GB/vCPU
+
+ ),
+ })),
+ })),
+ ]}
+ valueRender={valueRender}
+ onChange={(v) => {
+ handleChange('selectedPlan')(dummyEvent(v.value));
+ handleChange('memPerCpu')(dummyEvent(v.memoryPerCpu));
+ handleChange('cpuMode')(
+ dummyEvent(v.isShared ? 'shared' : 'dedicated')
+ );
+ }}
+ />
+
+
+
+ Select CPU
- {values.selectionMode === 'quick' ? (
-
-
[
- ...Object.entries(plans).map(([_, vs]) => ({
- label: vs.label,
- options: vs.options.map((op) => ({
- ...op,
- render: () => (
-
-
{op.label}
-
{op.memoryPerCpu}GB/vCPU
-
- ),
- })),
- })),
- ]}
- valueRender={valueRender}
- onChange={(v) => {
- handleChange('selectedPlan')(dummyEvent(v.value));
- handleChange('memPerCpu')(dummyEvent(v.memoryPerCpu));
- handleChange('cpuMode')(
- dummyEvent(v.isShared ? 'shared' : 'dedicated')
- );
- }}
- />
-
-
-
- Select CPU
-
-
- {((values.cpu || 1) / 1000).toFixed(2)}vCPU &{' '}
- {(
- ((values.cpu || 1) * parseValue(values.memPerCpu, 4)) /
- 1000
- ).toFixed(2)}
- GB Memory
-
-
-
{
- handleChange('cpu')(dummyEvent(value));
- }}
- />
-
-
- ) : (
-
-
-
-
-
+
+ {((values.cpu || 1) / 1000).toFixed(2)}vCPU &{' '}
+ {(
+ ((values.cpu || 1) * parseValue(values.memPerCpu, 4)) /
+ 1000
+ ).toFixed(2)}
+ GB Memory
+
+
+
{
+ handleChange('cpu')(dummyEvent(value));
+ }}
+ />
+
+
+ ) : (
+
+
+
+
+
1000m = 1VCPU
- }
- />
-
-
-
+ }
+ />
+
+
+
1000m = 1VCPU
- }
- size="lg"
- suffix="m"
- />
-
-
-
-
-
- )}
+ }
+ size="lg"
+ suffix="m"
+ />
+
+
+
+
+
+ )}
+
- {/*
+ {/*
Select plan
@@ -522,33 +513,33 @@ const AppCompute = () => {
*/}
-
-
-
- );
+
+
}
+ variant="outline"
+ onClick={() => {
+ (async () => {
+ const res = await submit();
+ if (res) {
+ setPage(1);
+ }
+ })();
+ }}
+ />
+
+
|
+
+
}
+ variant="primary"
+ />
+
+
+ );
};
// const ContainerRepoLayout = () => {
@@ -568,4 +559,4 @@ const AppCompute = () => {
// };
export default AppCompute;
-// export default NewContainerRepo
\ No newline at end of file
+// export default NewContainerRepo
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 be67e0a45..ffd257ccb 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
@@ -16,24 +16,28 @@ interface IReviewComponent {
title: string;
children: ReactNode;
onEdit: () => void;
+ canEdit?: boolean;
}
export const ReviewComponent = ({
title = '',
children,
onEdit,
+ canEdit = true,
}: IReviewComponent) => {
return (
{title}
-
-
-
+ {canEdit && (
+
+
+
+ )}
{children}
@@ -83,7 +87,7 @@ const AppReview = () => {
An assessment of the work, product, or performance.
-
{}}>
+ { }}>
{app.displayName}
@@ -92,7 +96,7 @@ const AppReview = () => {
-
{}}>
+ { }}>
@@ -127,7 +131,7 @@ const AppReview = () => {
-
{}}>
+ { }}>
@@ -147,7 +151,7 @@ const AppReview = () => {
-
{}}>
+ { }}>
Ports exposed from the app
diff --git a/src/apps/console/server/r-utils/key-constants.js b/src/apps/console/server/r-utils/key-constants.js
index ebb602a1f..8c7a6a488 100644
--- a/src/apps/console/server/r-utils/key-constants.js
+++ b/src/apps/console/server/r-utils/key-constants.js
@@ -8,4 +8,6 @@ export const keyconstants = {
selectedPlan: 'kloudlite.io/ui-selected-plan',
memPerCpu: 'kloudlite.io/ui-mem-per-cpu',
nodeType: 'kloudlite.io/ui-node-type',
+ repoName: 'kloudlite.io/ui-repoName',
+ imageTag: 'kloudlite.io/ui-imageTag',
};