import { Rocket } from 'lucide-react'; import { Form, Formik } from 'formik'; import { array, lazy, number, object, string } from 'yup'; import { useRouter } from '@uirouter/react'; import _ from 'lodash'; import { TemplateViewModel } from '@/react/portainer/templates/app-templates/view-model'; import { EnvironmentType } from '@/react/portainer/environments/types'; import { notifySuccess } from '@/portainer/services/notifications'; import { Widget } from '@@/Widget'; import { FallbackImage } from '@@/FallbackImage'; import { Icon } from '@@/Icon'; import { FormActions } from '@@/form-components/FormActions'; import { Button } from '@@/buttons'; import { EdgeGroupsSelector } from '../../edge-stacks/components/EdgeGroupsSelector'; import { NameField, nameValidation, } from '../../edge-stacks/CreateView/NameField'; import { EdgeGroup } from '../../edge-groups/types'; import { DeploymentType, EdgeStack } from '../../edge-stacks/types'; import { useEdgeStacks } from '../../edge-stacks/queries/useEdgeStacks'; import { useEdgeGroups } from '../../edge-groups/queries/useEdgeGroups'; import { useCreateEdgeStack } from '../../edge-stacks/queries/useCreateEdgeStack/useCreateEdgeStack'; import { EnvVarsFieldset } from './EnvVarsFieldset'; export function DeployFormWidget({ template, unselect, }: { template: TemplateViewModel; unselect: () => void; }) { return (
} /> } title={template.Title} />
); } interface FormValues { name: string; edgeGroupIds: Array; envVars: Record; } function DeployForm({ template, unselect, }: { template: TemplateViewModel; unselect: () => void; }) { const router = useRouter(); const mutation = useCreateEdgeStack(); const edgeStacksQuery = useEdgeStacks(); const edgeGroupsQuery = useEdgeGroups({ select: (groups) => Object.fromEntries(groups.map((g) => [g.Id, g.EndpointTypes])), }); const initialValues: FormValues = { edgeGroupIds: [], name: template.Name || '', envVars: Object.fromEntries(template.Env?.map((env) => [env.name, env.value])) || {}, }; if (!edgeStacksQuery.data || !edgeGroupsQuery.data) { return null; } return ( validation(edgeStacksQuery.data, edgeGroupsQuery.data) } validateOnMount > {({ values, errors, setFieldValue, isValid }) => (
setFieldValue('name', v)} errors={errors.name} /> setFieldValue('edgeGroupIds', value)} required /> setFieldValue('envVars', values)} /> )}
); function handleSubmit(values: FormValues) { return mutation.mutate( { method: 'git', payload: { name: values.name, edgeGroups: values.edgeGroupIds, deploymentType: DeploymentType.Compose, envVars: Object.entries(values.envVars).map(([name, value]) => ({ name, value, })), git: { RepositoryURL: template.Repository.url, ComposeFilePathInRepository: template.Repository.stackfile, }, }, }, { onSuccess() { notifySuccess('Success', 'Edge Stack created'); router.stateService.go('edge.stacks'); }, } ); } } function validation( stacks: EdgeStack[], edgeGroupsType: Record> ) { return lazy((values: FormValues) => { const types = getTypes(values.edgeGroupIds); return object({ name: nameValidation( stacks, types?.includes(EnvironmentType.EdgeAgentOnDocker) ), edgeGroupIds: array(number().required().default(0)) .min(1, 'At least one group is required') .test( 'same-type', 'Groups should be of the same type', (value) => _.uniq(getTypes(value)).length === 1 ), envVars: array() .transform((_, orig) => Object.values(orig)) .of(string().required('Required')), }); }); function getTypes(value: number[] | undefined) { return value?.flatMap((g) => edgeGroupsType[g]); } }