fix(app/edge-stack): edge stack create form validation (#343)

pull/12512/head
LP B 2025-01-24 17:02:52 +01:00 committed by GitHub
parent 3ca5ab180f
commit b753371700
6 changed files with 38 additions and 43 deletions

View File

@ -29,13 +29,16 @@ export function CreateForm() {
const [webhookId] = useState(() => createWebhookId());
const [templateParams, setTemplateParams] = useTemplateParams();
const templateQuery = useTemplate(templateParams.type, templateParams.id);
const templateQuery = useTemplate(
templateParams.templateType,
templateParams.templateId
);
const validation = useValidation(templateQuery);
const mutation = useCreate({
webhookId,
template: templateQuery.customTemplate || templateQuery.appTemplate,
templateType: templateParams.type,
templateType: templateParams.templateType,
});
const initialValues = useInitialValues(templateQuery, templateParams);
@ -53,6 +56,7 @@ export function CreateForm() {
initialValues={initialValues}
onSubmit={mutation.onSubmit}
validationSchema={validation}
validateOnMount
>
<InnerForm
webhookId={webhookId}
@ -118,8 +122,8 @@ function useInitialValues(
customTemplate: CustomTemplate | undefined;
},
templateParams: {
id: number | undefined;
type: 'app' | 'custom' | undefined;
templateId: number | undefined;
templateType: 'app' | 'custom' | undefined;
}
) {
const template = templateQuery.customTemplate || templateQuery.appTemplate;
@ -139,7 +143,7 @@ function useInitialValues(
staggerConfig:
templateQuery.customTemplate?.EdgeSettings?.StaggerConfig ??
getDefaultStaggerConfig(),
method: templateParams.id ? 'template' : 'editor',
method: templateParams.templateId ? 'template' : 'editor',
git: toGitFormModel(
templateQuery.customTemplate?.GitConfig,
parseAutoUpdateResponse()
@ -149,19 +153,19 @@ function useInitialValues(
getDefaultRelativePathModel(),
enableWebhook: false,
fileContent: '',
templateValues: getTemplateValues(templateParams.type, template),
templateValues: getTemplateValues(templateParams.templateType, template),
useManifestNamespaces: false,
}),
[
templateQuery.customTemplate,
templateParams.id,
templateParams.type,
templateParams.templateId,
templateParams.templateType,
template,
]
);
if (
templateParams.id &&
templateParams.templateId &&
!templateQuery.customTemplate &&
!templateQuery.appTemplate
) {

View File

@ -17,7 +17,11 @@ import { useCurrentUser } from '@/react/hooks/useUser';
import { relativePathValidation } from '@/react/portainer/gitops/RelativePathFieldset/validation';
import { CustomTemplate } from '@/react/portainer/templates/custom-templates/types';
import { TemplateViewModel } from '@/react/portainer/templates/app-templates/view-model';
import { DeployMethod, GitFormModel } from '@/react/portainer/gitops/types';
import {
DeployMethod,
GitFormModel,
RelativePathModel,
} from '@/react/portainer/gitops/types';
import { EnvironmentType } from '@/react/portainer/environments/types';
import { envVarValidation } from '@@/form-components/EnvironmentVariablesFieldset';
@ -133,7 +137,10 @@ export function useValidation({
);
},
}) as SchemaOf<GitFormModel>,
relativePath: relativePathValidation(),
relativePath: mixed().when('method', {
is: 'repository',
then: () => relativePathValidation(),
}) as SchemaOf<RelativePathModel>,
useManifestNamespaces: boolean().default(false),
})
),

View File

@ -28,8 +28,8 @@ const buildMethods = [editor, upload, git, edgeStackTemplate] as const;
interface Props {
webhookId: string;
onChangeTemplate: (change: {
type: 'app' | 'custom' | undefined;
id: number | undefined;
templateType: 'app' | 'custom' | undefined;
templateId: number | undefined;
}) => void;
}
@ -76,8 +76,8 @@ export function DockerComposeForm({ webhookId, onChangeTemplate }: Props) {
values.templateValues
);
onChangeTemplate({
id: templateValues.templateId,
type: templateValues.type,
templateId: templateValues.templateId,
templateType: templateValues.type,
});
setValues((values) => ({
...values,
@ -145,6 +145,7 @@ export function DockerComposeForm({ webhookId, onChangeTemplate }: Props) {
<FormSection title="Advanced configurations">
<RelativePathFieldset
values={values.relativePath}
errors={errors.relativePath}
gitModel={values.git}
onChange={(relativePath) =>
setValues((values) => ({

View File

@ -29,11 +29,11 @@ export function InnerForm({
webhookId: string;
isLoading: boolean;
onChangeTemplate: ({
type,
id,
templateType,
templateId,
}: {
type: 'app' | 'custom' | undefined;
id: number | undefined;
templateType: 'app' | 'custom' | undefined;
templateId: number | undefined;
}) => void;
}) {
const { values, setFieldValue, errors, setValues, setFieldError, isValid } =
@ -128,6 +128,7 @@ export function InnerForm({
<StaggerFieldset
isEdit={false}
values={values.staggerConfig}
errors={errors.staggerConfig}
onChange={(newStaggerValues) =>
setFieldValue('staggerConfig', newStaggerValues)
}

View File

@ -1,15 +1,14 @@
import { useParamsState } from '@/react/hooks/useParamState';
export function useTemplateParams() {
const [{ id, type }, setTemplateParams] = useParamsState(
['templateId', 'templateType'],
const [{ templateId, templateType }, setTemplateParams] = useParamsState(
(params) => ({
id: parseTemplateId(params.templateId),
type: parseTemplateType(params.templateType),
templateId: parseTemplateId(params.templateId),
templateType: parseTemplateType(params.templateType),
})
);
return [{ id, type }, setTemplateParams] as const;
return [{ templateId, templateType }, setTemplateParams] as const;
}
function parseTemplateId(param?: string) {

View File

@ -22,32 +22,15 @@ export function useParamState<T>(
/** Use this when you need to use/update multiple params at once. */
export function useParamsState<T extends Record<string, unknown>>(
params: string[],
parseParams: (params: Record<string, string | undefined>) => T
) {
const { params: stateParams } = useCurrentStateAndParams();
const router = useRouter();
const state = parseParams(
params.reduce(
(acc, param) => {
acc[param] = stateParams[param];
return acc;
},
{} as Record<string, string | undefined>
)
);
const state = parseParams(stateParams);
function setState(newState: Partial<T>) {
const newStateParams = Object.entries(newState).reduce(
(acc, [key, value]) => {
acc[key] = value;
return acc;
},
{} as Record<string, unknown>
);
router.stateService.go('.', newStateParams, { reload: false });
router.stateService.go('.', newState, { reload: false });
}
return [state, setState] as const;