Skip to content

Commit

Permalink
Fix state when opening and closing schedule modal
Browse files Browse the repository at this point in the history
  • Loading branch information
desertaxle committed Feb 5, 2025
1 parent ec1d594 commit 172538d
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 33 deletions.
6 changes: 2 additions & 4 deletions src/components/DeploymentScheduleMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
<ScheduleFormModal
ref="scheduleFormModalRef"
v-bind="schedule"
:parameters="parameters"
:deployment-parameters="deployment.parameters"
:schedule-parameters="schedule.parameters"
:parameter-open-api-schema="deployment.parameterOpenApiSchema"
:enforce-parameter-schema="deployment.enforceParameterSchema"
@submit="updateSchedule"
/>

Expand Down Expand Up @@ -52,8 +52,6 @@
const scheduleFormModalRef = ref<ScheduleFormModalMethods | null>(null)
const parameters = computed(() => props.schedule.parameters ?? {})
const openEditModal = (): void => {
scheduleFormModalRef.value?.publicOpen?.()
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/DeploymentSchedulesFieldset.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
:active="null"
:schedule="null"
:job-variables="{}"
:parameters="{}"
:deployment-parameters="deployment.parameters"
:schedule-parameters="{}"
:parameter-open-api-schema="deployment.parameterOpenApiSchema"
@submit="createSchedule"
>
Expand Down
3 changes: 2 additions & 1 deletion src/components/ScheduleFieldset.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
:active="null"
:schedule="internalValue"
:job-variables="{}"
:parameters="{}"
:deployment-parameters="{}"
:schedule-parameters="{}"
:parameter-open-api-schema="{}"
@submit="updateSchedule"
>
Expand Down
103 changes: 76 additions & 27 deletions src/components/ScheduleFormModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<p-overflow-menu-item v-if="kind === 'none'" label="Use JSON input" @click="setKind('json')" />
</p-icon-button-menu>
</div>
<p-combobox v-model="selectedProperties" :options="propertyNames" empty-message="Select parameters to override for this schedule" />
<p-combobox v-if="kind !== 'json'" v-model="selectedProperties" :options="propertyNames" empty-message="Select parameters to override for this schedule" />
</template>
</SchemaInputV2>
</template>
Expand All @@ -59,15 +59,23 @@
import IntervalScheduleForm from '@/components/IntervalScheduleForm.vue'
import { useCan, useShowModal } from '@/compositions'
import { localization } from '@/localization'
import { CronSchedule, DeploymentScheduleCompatible, IntervalSchedule, Schedule, ScheduleType, getScheduleType, isCronSchedule, isIntervalSchedule } from '@/models'
import {
CronSchedule,
DeploymentScheduleCompatible,
IntervalSchedule,
Schedule,
ScheduleType,
getScheduleType,
isCronSchedule,
isIntervalSchedule
} from '@/models'
import { SchemaInputV2, SchemaV2, SchemaValuesV2 } from '@/schemas'
import { useSchemaValidation } from '@/schemas/compositions/useSchemaValidation'
import { isEmptyObject, omit, stringify } from '@/utilities'
import { ButtonGroupOption } from '@prefecthq/prefect-design'
import { useValidationObserver } from '@prefecthq/vue-compositions'
import merge from 'lodash.merge'
import { computed, ref, watch } from 'vue'
import { computed, reactive, ref, watch } from 'vue'
defineOptions({
inheritAttrs: false,
Expand All @@ -85,7 +93,8 @@
active: boolean | null,
schedule: Schedule | null,
jobVariables: Record<string, unknown> | undefined,
parameters: SchemaValuesV2,
deploymentParameters: SchemaValuesV2,
scheduleParameters?: SchemaValuesV2 | null,
parameterOpenApiSchema: SchemaV2,
}>()
Expand All @@ -94,41 +103,59 @@
const internalActive = ref<boolean>(props.active ?? true)
const { validate } = useValidationObserver()
const internalJobVariables = ref<string | undefined>(props.jobVariables ? stringify(props.jobVariables) : undefined)
const internalJobVariables = ref<string | undefined>(
props.jobVariables ? stringify(props.jobVariables) : undefined,
)
const emit = defineEmits<{
(event: 'submit', value: DeploymentScheduleCompatible): void,
}>()
// Parameters-related refs and compositions
const selectedProperties = ref<string[]>(Object.keys(props.parameters))
const properties = computed(() => props.parameterOpenApiSchema.properties ?? {})
const internalParameters = ref<SchemaValuesV2>(props.scheduleParameters ?? { })
const selectedProperties = ref<string[]>(Object.keys(internalParameters.value))
const properties = computed(
() => props.parameterOpenApiSchema.properties ?? {},
)
const propertyNames = computed(() => Object.keys(properties.value))
const propertiesToOmit = computed(() => propertyNames.value.filter(name => !selectedProperties.value.includes(name)))
const propertiesToOmit = computed(() => propertyNames.value.filter(
(name) => !selectedProperties.value.includes(name),
),
)
const internalSchema = computed(() => {
return { ...props.parameterOpenApiSchema, required: [], properties: omit(properties.value, propertiesToOmit.value) }
return {
...props.parameterOpenApiSchema,
required: [],
properties: omit(properties.value, propertiesToOmit.value),
}
})
const internalParameters = ref()
// Reset values to the initial values when the modal is opened
watch(showModal, () => {
if (showModal.value) {
internalParameters.value = {}
selectedProperties.value = []
internalParameters.value = props.scheduleParameters ?? { }
selectedProperties.value = Object.keys(internalParameters.value)
}
})
// When the properties to omit change, we need add/remove properties to stay in sync
watch(propertiesToOmit, () => {
const newParameters = omit(internalParameters.value, propertiesToOmit.value)
const partialDefaultParameters = omit(props.parameters, propertiesToOmit.value)
const partialDefaultParameters = omit(
props.deploymentParameters,
propertiesToOmit.value,
)
internalParameters.value = merge(partialDefaultParameters, newParameters)
})
const schemaHasParameters = computed(() => !isEmptyObject(props.parameterOpenApiSchema.properties))
const { errors, validate: validateParameters } = useSchemaValidation(internalSchema, internalParameters)
const schemaHasParameters = computed(
() => !isEmptyObject(props.parameterOpenApiSchema.properties),
)
const { errors, validate: validateParameters } = useSchemaValidation(
internalSchema,
internalParameters,
)
async function submit(schedule: Schedule | null): Promise<void> {
const valid = await validate()
Expand All @@ -147,10 +174,14 @@
if (!can.access.deploymentScheduleFlowRunInfraOverrides) {
jobVariables = undefined
} else {
jobVariables = internalJobVariables.value ? JSON.parse(internalJobVariables.value) : undefined
jobVariables = internalJobVariables.value
? JSON.parse(internalJobVariables.value)
: undefined
}
const parameters = isEmptyObject(internalParameters.value) ? undefined : internalParameters.value
const parameters = isEmptyObject(internalParameters.value)
? undefined
: internalParameters.value
const deploymentSchedule: DeploymentScheduleCompatible = {
active: internalActive.value,
Expand All @@ -166,9 +197,11 @@
const cronDisabled = ref<boolean>(false)
const intervalDisabled = ref<boolean>(false)
const disabled = computed(() => {
return scheduleForm.value === 'rrule' ||
return (
scheduleForm.value === 'rrule' ||
scheduleForm.value === 'cron' && cronDisabled.value ||
scheduleForm.value === 'interval' && intervalDisabled.value
)
})
const submitCurrentForm = async (): Promise<void> => {
Expand All @@ -187,16 +220,32 @@
await submit(schedule)
}
const cronSchedule = ref<CronSchedule | undefined>(isCronSchedule(props.schedule) ? props.schedule : undefined)
const intervalSchedule = ref<IntervalSchedule | undefined>(isIntervalSchedule(props.schedule) ? props.schedule : undefined)
const scheduleForm = ref<ScheduleType>(getScheduleType(props.schedule) ?? 'interval')
const scheduleFormOptions: ButtonGroupOption[] = [{ label: 'Interval', value: 'interval' }, { label: 'Cron', value: 'cron' }, { label: 'RRule', value: 'rrule' }]
const cronSchedule = ref<CronSchedule | undefined>(
isCronSchedule(props.schedule) ? props.schedule : undefined,
)
const intervalSchedule = ref<IntervalSchedule | undefined>(
isIntervalSchedule(props.schedule) ? props.schedule : undefined,
)
const scheduleForm = ref<ScheduleType>(
getScheduleType(props.schedule) ?? 'interval',
)
const scheduleFormOptions: ButtonGroupOption[] = [
{ label: 'Interval', value: 'interval' },
{ label: 'Cron', value: 'cron' },
{ label: 'RRule', value: 'rrule' },
]
const updateInternalState = (): void => {
cronSchedule.value = isCronSchedule(props.schedule) ? props.schedule : undefined
intervalSchedule.value = isIntervalSchedule(props.schedule) ? props.schedule : undefined
cronSchedule.value = isCronSchedule(props.schedule)
? props.schedule
: undefined
intervalSchedule.value = isIntervalSchedule(props.schedule)
? props.schedule
: undefined
internalActive.value = props.active ?? true
internalJobVariables.value = props.jobVariables ? stringify(props.jobVariables) : undefined
internalJobVariables.value = props.jobVariables
? stringify(props.jobVariables)
: undefined
}
watch(() => props.schedule, updateInternalState)
Expand Down

0 comments on commit 172538d

Please sign in to comment.