diff --git a/app/react/portainer/environments/update-schedules/CreateView/CreateView.tsx b/app/react/portainer/environments/update-schedules/CreateView/CreateView.tsx index 1557af374..53fad79c3 100644 --- a/app/react/portainer/environments/update-schedules/CreateView/CreateView.tsx +++ b/app/react/portainer/environments/update-schedules/CreateView/CreateView.tsx @@ -5,6 +5,7 @@ import { useRouter } from '@uirouter/react'; import { notifySuccess } from '@/portainer/services/notifications'; import { withLimitToBE } from '@/react/hooks/useLimitToBE'; +import { useEdgeGroups } from '@/react/edge/edge-groups/queries/useEdgeGroups'; import { PageHeader } from '@@/PageHeader'; import { Widget } from '@@/Widget'; @@ -36,7 +37,7 @@ function CreateView() { }), [] ); - + const edgeGroupsQuery = useEdgeGroups(); const schedulesQuery = useList(); const createMutation = useCreateMutation(); @@ -75,7 +76,9 @@ function CreateView() { initialValues={initialValues} onSubmit={handleSubmit} validateOnMount - validationSchema={() => validation(schedules)} + validationSchema={() => + validation(schedules, edgeGroupsQuery.data) + } > {({ isValid, setFieldValue, values, handleBlur, errors }) => ( diff --git a/app/react/portainer/environments/update-schedules/ItemView/ItemView.tsx b/app/react/portainer/environments/update-schedules/ItemView/ItemView.tsx index 774de45f5..17e0cf809 100644 --- a/app/react/portainer/environments/update-schedules/ItemView/ItemView.tsx +++ b/app/react/portainer/environments/update-schedules/ItemView/ItemView.tsx @@ -5,6 +5,8 @@ import { object, SchemaOf } from 'yup'; import { notifySuccess } from '@/portainer/services/notifications'; import { withLimitToBE } from '@/react/hooks/useLimitToBE'; +import { useEdgeGroups } from '@/react/edge/edge-groups/queries/useEdgeGroups'; +import { EdgeGroup } from '@/react/edge/edge-groups/types'; import { PageHeader } from '@@/PageHeader'; import { Widget } from '@@/Widget'; @@ -32,6 +34,7 @@ function ItemView() { } = useCurrentStateAndParams(); const id = parseInt(idParam, 10); + const edgeGroupsQuery = useEdgeGroups(); if (!idParam || Number.isNaN(id)) { throw new Error('id is a required path param'); @@ -113,7 +116,12 @@ function ItemView() { }} validateOnMount validationSchema={() => - updateValidation(item.id, schedules, isScheduleActive) + updateValidation( + item.id, + schedules, + edgeGroupsQuery.data, + isScheduleActive + ) } > {({ isValid, setFieldValue, values, handleBlur, errors }) => ( @@ -171,9 +179,10 @@ function ItemView() { function updateValidation( itemId: EdgeUpdateSchedule['id'], schedules: EdgeUpdateSchedule[], + edgeGroups: Array | undefined, isScheduleActive: boolean ): SchemaOf<{ name: string } | FormValues> { return !isScheduleActive - ? validation(schedules, itemId) + ? validation(schedules, edgeGroups, itemId) : object({ name: nameValidation(schedules, itemId) }); } diff --git a/app/react/portainer/environments/update-schedules/common/validation.ts b/app/react/portainer/environments/update-schedules/common/validation.ts index ed8bcf93c..0186dc29c 100644 --- a/app/react/portainer/environments/update-schedules/common/validation.ts +++ b/app/react/portainer/environments/update-schedules/common/validation.ts @@ -1,6 +1,7 @@ -import { array, object, SchemaOf, string } from 'yup'; +import { array, object, SchemaOf, string, number } from 'yup'; import { parseIsoDate } from '@/portainer/filters/filters'; +import { EdgeGroup } from '@/react/edge/edge-groups/types'; import { EdgeUpdateSchedule, ScheduleType } from '../types'; @@ -10,10 +11,24 @@ import { FormValues } from './types'; export function validation( schedules: EdgeUpdateSchedule[], + edgeGroups: Array | undefined, currentId?: EdgeUpdateSchedule['id'] ): SchemaOf { return object({ - groupIds: array().min(1, 'At least one group is required'), + groupIds: array() + .of(number().default(0)) + .min(1, 'At least one group is required') + .test( + 'At least one group must have endpoints', + (groupIds) => + !!( + groupIds && + edgeGroups && + groupIds?.flatMap( + (id) => edgeGroups?.find((group) => group.Id === id)?.Endpoints + ).length > 0 + ) + ), name: nameValidation(schedules, currentId), type: typeValidation(), scheduledTime: string() @@ -28,5 +43,6 @@ export function validation( // rollback otherwise: (schema) => schema.required('No rollback options available'), }), + registryId: number().default(0), }); }