mirror of https://github.com/portainer/portainer
fix(app/edge-stack): edge stack create form validation (#343)
parent
3ca5ab180f
commit
b753371700
|
@ -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
|
||||
) {
|
||||
|
|
|
@ -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),
|
||||
})
|
||||
),
|
||||
|
|
|
@ -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) => ({
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue