mirror of
https://github.com/portainer/portainer.git
synced 2025-07-21 14:29:40 +02:00
fix(app/edge-stack): edge stack create form validation (#343)
This commit is contained in:
parent
3ca5ab180f
commit
b753371700
6 changed files with 38 additions and 43 deletions
|
@ -29,13 +29,16 @@ export function CreateForm() {
|
||||||
const [webhookId] = useState(() => createWebhookId());
|
const [webhookId] = useState(() => createWebhookId());
|
||||||
|
|
||||||
const [templateParams, setTemplateParams] = useTemplateParams();
|
const [templateParams, setTemplateParams] = useTemplateParams();
|
||||||
const templateQuery = useTemplate(templateParams.type, templateParams.id);
|
const templateQuery = useTemplate(
|
||||||
|
templateParams.templateType,
|
||||||
|
templateParams.templateId
|
||||||
|
);
|
||||||
|
|
||||||
const validation = useValidation(templateQuery);
|
const validation = useValidation(templateQuery);
|
||||||
const mutation = useCreate({
|
const mutation = useCreate({
|
||||||
webhookId,
|
webhookId,
|
||||||
template: templateQuery.customTemplate || templateQuery.appTemplate,
|
template: templateQuery.customTemplate || templateQuery.appTemplate,
|
||||||
templateType: templateParams.type,
|
templateType: templateParams.templateType,
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialValues = useInitialValues(templateQuery, templateParams);
|
const initialValues = useInitialValues(templateQuery, templateParams);
|
||||||
|
@ -53,6 +56,7 @@ export function CreateForm() {
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
onSubmit={mutation.onSubmit}
|
onSubmit={mutation.onSubmit}
|
||||||
validationSchema={validation}
|
validationSchema={validation}
|
||||||
|
validateOnMount
|
||||||
>
|
>
|
||||||
<InnerForm
|
<InnerForm
|
||||||
webhookId={webhookId}
|
webhookId={webhookId}
|
||||||
|
@ -118,8 +122,8 @@ function useInitialValues(
|
||||||
customTemplate: CustomTemplate | undefined;
|
customTemplate: CustomTemplate | undefined;
|
||||||
},
|
},
|
||||||
templateParams: {
|
templateParams: {
|
||||||
id: number | undefined;
|
templateId: number | undefined;
|
||||||
type: 'app' | 'custom' | undefined;
|
templateType: 'app' | 'custom' | undefined;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const template = templateQuery.customTemplate || templateQuery.appTemplate;
|
const template = templateQuery.customTemplate || templateQuery.appTemplate;
|
||||||
|
@ -139,7 +143,7 @@ function useInitialValues(
|
||||||
staggerConfig:
|
staggerConfig:
|
||||||
templateQuery.customTemplate?.EdgeSettings?.StaggerConfig ??
|
templateQuery.customTemplate?.EdgeSettings?.StaggerConfig ??
|
||||||
getDefaultStaggerConfig(),
|
getDefaultStaggerConfig(),
|
||||||
method: templateParams.id ? 'template' : 'editor',
|
method: templateParams.templateId ? 'template' : 'editor',
|
||||||
git: toGitFormModel(
|
git: toGitFormModel(
|
||||||
templateQuery.customTemplate?.GitConfig,
|
templateQuery.customTemplate?.GitConfig,
|
||||||
parseAutoUpdateResponse()
|
parseAutoUpdateResponse()
|
||||||
|
@ -149,19 +153,19 @@ function useInitialValues(
|
||||||
getDefaultRelativePathModel(),
|
getDefaultRelativePathModel(),
|
||||||
enableWebhook: false,
|
enableWebhook: false,
|
||||||
fileContent: '',
|
fileContent: '',
|
||||||
templateValues: getTemplateValues(templateParams.type, template),
|
templateValues: getTemplateValues(templateParams.templateType, template),
|
||||||
useManifestNamespaces: false,
|
useManifestNamespaces: false,
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
templateQuery.customTemplate,
|
templateQuery.customTemplate,
|
||||||
templateParams.id,
|
templateParams.templateId,
|
||||||
templateParams.type,
|
templateParams.templateType,
|
||||||
template,
|
template,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
templateParams.id &&
|
templateParams.templateId &&
|
||||||
!templateQuery.customTemplate &&
|
!templateQuery.customTemplate &&
|
||||||
!templateQuery.appTemplate
|
!templateQuery.appTemplate
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -17,7 +17,11 @@ import { useCurrentUser } from '@/react/hooks/useUser';
|
||||||
import { relativePathValidation } from '@/react/portainer/gitops/RelativePathFieldset/validation';
|
import { relativePathValidation } from '@/react/portainer/gitops/RelativePathFieldset/validation';
|
||||||
import { CustomTemplate } from '@/react/portainer/templates/custom-templates/types';
|
import { CustomTemplate } from '@/react/portainer/templates/custom-templates/types';
|
||||||
import { TemplateViewModel } from '@/react/portainer/templates/app-templates/view-model';
|
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 { EnvironmentType } from '@/react/portainer/environments/types';
|
||||||
|
|
||||||
import { envVarValidation } from '@@/form-components/EnvironmentVariablesFieldset';
|
import { envVarValidation } from '@@/form-components/EnvironmentVariablesFieldset';
|
||||||
|
@ -133,7 +137,10 @@ export function useValidation({
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
}) as SchemaOf<GitFormModel>,
|
}) as SchemaOf<GitFormModel>,
|
||||||
relativePath: relativePathValidation(),
|
relativePath: mixed().when('method', {
|
||||||
|
is: 'repository',
|
||||||
|
then: () => relativePathValidation(),
|
||||||
|
}) as SchemaOf<RelativePathModel>,
|
||||||
useManifestNamespaces: boolean().default(false),
|
useManifestNamespaces: boolean().default(false),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
|
|
@ -28,8 +28,8 @@ const buildMethods = [editor, upload, git, edgeStackTemplate] as const;
|
||||||
interface Props {
|
interface Props {
|
||||||
webhookId: string;
|
webhookId: string;
|
||||||
onChangeTemplate: (change: {
|
onChangeTemplate: (change: {
|
||||||
type: 'app' | 'custom' | undefined;
|
templateType: 'app' | 'custom' | undefined;
|
||||||
id: number | undefined;
|
templateId: number | undefined;
|
||||||
}) => void;
|
}) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,8 +76,8 @@ export function DockerComposeForm({ webhookId, onChangeTemplate }: Props) {
|
||||||
values.templateValues
|
values.templateValues
|
||||||
);
|
);
|
||||||
onChangeTemplate({
|
onChangeTemplate({
|
||||||
id: templateValues.templateId,
|
templateId: templateValues.templateId,
|
||||||
type: templateValues.type,
|
templateType: templateValues.type,
|
||||||
});
|
});
|
||||||
setValues((values) => ({
|
setValues((values) => ({
|
||||||
...values,
|
...values,
|
||||||
|
@ -145,6 +145,7 @@ export function DockerComposeForm({ webhookId, onChangeTemplate }: Props) {
|
||||||
<FormSection title="Advanced configurations">
|
<FormSection title="Advanced configurations">
|
||||||
<RelativePathFieldset
|
<RelativePathFieldset
|
||||||
values={values.relativePath}
|
values={values.relativePath}
|
||||||
|
errors={errors.relativePath}
|
||||||
gitModel={values.git}
|
gitModel={values.git}
|
||||||
onChange={(relativePath) =>
|
onChange={(relativePath) =>
|
||||||
setValues((values) => ({
|
setValues((values) => ({
|
||||||
|
|
|
@ -29,11 +29,11 @@ export function InnerForm({
|
||||||
webhookId: string;
|
webhookId: string;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
onChangeTemplate: ({
|
onChangeTemplate: ({
|
||||||
type,
|
templateType,
|
||||||
id,
|
templateId,
|
||||||
}: {
|
}: {
|
||||||
type: 'app' | 'custom' | undefined;
|
templateType: 'app' | 'custom' | undefined;
|
||||||
id: number | undefined;
|
templateId: number | undefined;
|
||||||
}) => void;
|
}) => void;
|
||||||
}) {
|
}) {
|
||||||
const { values, setFieldValue, errors, setValues, setFieldError, isValid } =
|
const { values, setFieldValue, errors, setValues, setFieldError, isValid } =
|
||||||
|
@ -128,6 +128,7 @@ export function InnerForm({
|
||||||
<StaggerFieldset
|
<StaggerFieldset
|
||||||
isEdit={false}
|
isEdit={false}
|
||||||
values={values.staggerConfig}
|
values={values.staggerConfig}
|
||||||
|
errors={errors.staggerConfig}
|
||||||
onChange={(newStaggerValues) =>
|
onChange={(newStaggerValues) =>
|
||||||
setFieldValue('staggerConfig', newStaggerValues)
|
setFieldValue('staggerConfig', newStaggerValues)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
import { useParamsState } from '@/react/hooks/useParamState';
|
import { useParamsState } from '@/react/hooks/useParamState';
|
||||||
|
|
||||||
export function useTemplateParams() {
|
export function useTemplateParams() {
|
||||||
const [{ id, type }, setTemplateParams] = useParamsState(
|
const [{ templateId, templateType }, setTemplateParams] = useParamsState(
|
||||||
['templateId', 'templateType'],
|
|
||||||
(params) => ({
|
(params) => ({
|
||||||
id: parseTemplateId(params.templateId),
|
templateId: parseTemplateId(params.templateId),
|
||||||
type: parseTemplateType(params.templateType),
|
templateType: parseTemplateType(params.templateType),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
return [{ id, type }, setTemplateParams] as const;
|
return [{ templateId, templateType }, setTemplateParams] as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseTemplateId(param?: string) {
|
function parseTemplateId(param?: string) {
|
||||||
|
|
|
@ -22,32 +22,15 @@ export function useParamState<T>(
|
||||||
|
|
||||||
/** Use this when you need to use/update multiple params at once. */
|
/** Use this when you need to use/update multiple params at once. */
|
||||||
export function useParamsState<T extends Record<string, unknown>>(
|
export function useParamsState<T extends Record<string, unknown>>(
|
||||||
params: string[],
|
|
||||||
parseParams: (params: Record<string, string | undefined>) => T
|
parseParams: (params: Record<string, string | undefined>) => T
|
||||||
) {
|
) {
|
||||||
const { params: stateParams } = useCurrentStateAndParams();
|
const { params: stateParams } = useCurrentStateAndParams();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const state = parseParams(
|
const state = parseParams(stateParams);
|
||||||
params.reduce(
|
|
||||||
(acc, param) => {
|
|
||||||
acc[param] = stateParams[param];
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{} as Record<string, string | undefined>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
function setState(newState: Partial<T>) {
|
function setState(newState: Partial<T>) {
|
||||||
const newStateParams = Object.entries(newState).reduce(
|
router.stateService.go('.', newState, { reload: false });
|
||||||
(acc, [key, value]) => {
|
|
||||||
acc[key] = value;
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{} as Record<string, unknown>
|
|
||||||
);
|
|
||||||
|
|
||||||
router.stateService.go('.', newStateParams, { reload: false });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [state, setState] as const;
|
return [state, setState] as const;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue