Drop the custom-cron schedule option from automations

Remove the "Custom (Cron)" schedule field — too technical for the editor.
The remaining presets (minutes/hours/days/weeks/months) cover the need and
still build the cron string under the hood.

Removed at the root: the ScheduleField.Custom enum case, the custom-cron
input and select option, the schedule_custom_cron type field and its
schedule-summary handling, the backend validation (Rule::in and the
schedule_custom_cron rule), the i18n keys, and the custom round-trip test
case. Existing automations keep firing — the scheduler runs off the stored
cron string, not schedule_field.
This commit is contained in:
Paulo Castellano 2026-06-13 10:06:38 -03:00
parent 31b6544c57
commit 37a7a64ff0
9 changed files with 11 additions and 40 deletions

View file

@ -121,7 +121,7 @@ private function dataRulesForNodeType(?string $type): array
NodeType::Trigger->value => [
'trigger_type' => ['required', Rule::in(array_column(TriggerType::cases(), 'value'))],
'cron' => ['required_if:nodes.*.data.trigger_type,'.TriggerType::Schedule->value, 'string'],
'schedule_field' => ['sometimes', Rule::in(['minutes', 'hours', 'days', 'weeks', 'months', 'custom'])],
'schedule_field' => ['sometimes', Rule::in(['minutes', 'hours', 'days', 'weeks', 'months'])],
'schedule_minutes_interval' => ['sometimes', 'integer', 'min:1', 'max:59'],
'schedule_hours_interval' => ['sometimes', 'integer', 'min:1', 'max:23'],
'schedule_days_interval' => ['sometimes', 'integer', 'min:1', 'max:31'],
@ -130,7 +130,6 @@ private function dataRulesForNodeType(?string $type): array
'schedule_weekdays' => ['sometimes', 'array'],
'schedule_weekdays.*' => ['integer', 'min:0', 'max:6'],
'schedule_day_of_month' => ['sometimes', 'integer', 'min:1', 'max:31'],
'schedule_custom_cron' => ['sometimes', 'nullable', 'string'],
'schedule_timezone' => ['sometimes', 'string', 'timezone'],
],
NodeType::FetchRss->value => [

View file

@ -241,7 +241,6 @@
'days' => 'Days',
'weeks' => 'Weeks',
'months' => 'Months',
'custom' => 'Custom (Cron)',
],
'minutes_interval' => 'Minutes between triggers',
'hours_interval' => 'Hours between triggers',
@ -250,8 +249,6 @@
'minute' => 'Trigger at minute',
'weekdays' => 'Trigger on weekdays',
'day_of_month' => 'Day of month',
'custom_cron' => 'Cron expression',
'custom_cron_hint' => 'Format: minute hour day month weekday',
'timezone_hint' => 'All times in :tz',
'weekday_names' => [
'sun' => 'Sun',

View file

@ -241,7 +241,6 @@
'days' => 'Días',
'weeks' => 'Semanas',
'months' => 'Meses',
'custom' => 'Personalizado (Cron)',
],
'minutes_interval' => 'Minutos entre disparos',
'hours_interval' => 'Horas entre disparos',
@ -250,8 +249,6 @@
'minute' => 'Disparar al minuto',
'weekdays' => 'Disparar en días',
'day_of_month' => 'Día del mes',
'custom_cron' => 'Expresión cron',
'custom_cron_hint' => 'Formato: minuto hora día mes día-de-semana',
'timezone_hint' => 'Todos los horarios en :tz',
'weekday_names' => [
'sun' => 'Dom',

View file

@ -241,7 +241,6 @@
'days' => 'Dias',
'weeks' => 'Semanas',
'months' => 'Meses',
'custom' => 'Personalizado (Cron)',
],
'minutes_interval' => 'Minutos entre disparos',
'hours_interval' => 'Horas entre disparos',
@ -250,8 +249,6 @@
'minute' => 'Disparar no minuto',
'weekdays' => 'Disparar nos dias',
'day_of_month' => 'Dia do mês',
'custom_cron' => 'Expressão cron',
'custom_cron_hint' => 'Formato: minuto hora dia mês dia-da-semana',
'timezone_hint' => 'Todos os horários em :tz',
'weekday_names' => [
'sun' => 'Dom',

View file

@ -1,6 +1,13 @@
<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import {
generateScheduleCron,
humanSchedule as scheduleSummary,
normalizeScheduleData,
timezoneAbbr as getTimezoneAbbr,
userTimezone as getUserTimezone,
} from '@/components/automations/schedule-summary';
import InputError from '@/components/InputError.vue';
import { Input } from '@/components/ui/input';
import {
@ -10,15 +17,8 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import {
generateScheduleCron,
humanSchedule as scheduleSummary,
normalizeScheduleData,
timezoneAbbr as getTimezoneAbbr,
userTimezone as getUserTimezone,
} from '@/components/automations/schedule-summary';
import { ScheduleField } from '@/types/automation/schedule-field';
import type { ScheduleData } from '@/types/automation/schedule-data';
import { ScheduleField } from '@/types/automation/schedule-field';
import { TriggerType, type TriggerTypeValue } from '@/types/automation/trigger-type';
const props = defineProps<{
@ -132,7 +132,6 @@ watch(local, (val) => emit('update', val), { deep: true });
<SelectItem :value="ScheduleField.Days">{{ $t('automations.config.trigger.schedule.fields.days') }}</SelectItem>
<SelectItem :value="ScheduleField.Weeks">{{ $t('automations.config.trigger.schedule.fields.weeks') }}</SelectItem>
<SelectItem :value="ScheduleField.Months">{{ $t('automations.config.trigger.schedule.fields.months') }}</SelectItem>
<SelectItem :value="ScheduleField.Custom">{{ $t('automations.config.trigger.schedule.fields.custom') }}</SelectItem>
</SelectContent>
</Select>
</div>
@ -266,17 +265,8 @@ watch(local, (val) => emit('update', val), { deep: true });
</div>
</template>
<template v-if="local.schedule_field === ScheduleField.Custom">
<div>
<label class="mb-1 block text-sm font-medium">{{ $t('automations.config.trigger.schedule.custom_cron') }}</label>
<Input v-model="local.schedule_custom_cron" placeholder="0 9 * * 1,3,5" />
<InputError :message="errors?.cron" class="mt-1" />
<p class="mt-1 text-xs text-foreground/50">{{ $t('automations.config.trigger.schedule.custom_cron_hint') }}</p>
</div>
</template>
<p class="rounded-md bg-muted px-3 py-2 text-xs text-foreground/70">{{ humanSchedule }}</p>
<p v-if="local.schedule_field !== ScheduleField.Custom" class="text-xs text-foreground/50">{{ $t('automations.config.trigger.schedule.timezone_hint', { tz: timezoneAbbr }) }}</p>
<p class="text-xs text-foreground/50">{{ $t('automations.config.trigger.schedule.timezone_hint', { tz: timezoneAbbr }) }}</p>
</template>
</div>
</template>

View file

@ -1,8 +1,8 @@
import { trans, transChoice } from 'laravel-vue-i18n';
import dayjs from '@/dayjs';
import { ScheduleField } from '@/types/automation/schedule-field';
import type { ScheduleData } from '@/types/automation/schedule-data';
import { ScheduleField } from '@/types/automation/schedule-field';
import { TriggerType } from '@/types/automation/trigger-type';
const pad2 = (n: number) => String(n).padStart(2, '0');
@ -81,7 +81,6 @@ export const normalizeScheduleData = (data: ScheduleData): ScheduleData => {
schedule_minute: data.schedule_minute ?? inferred.schedule_minute ?? 0,
schedule_weekdays: data.schedule_weekdays ?? inferred.schedule_weekdays ?? [1],
schedule_day_of_month: data.schedule_day_of_month ?? inferred.schedule_day_of_month ?? 1,
schedule_custom_cron: data.schedule_custom_cron ?? '0 9 * * 1,3,5',
};
};
@ -110,8 +109,6 @@ export const generateScheduleCron = (data: ScheduleData): string => {
const d = num(data, 'schedule_day_of_month', 1, 1, 31);
return `${minute} ${hour} ${d} * *`;
}
case ScheduleField.Custom:
return (data.schedule_custom_cron ?? '').trim() || '0 9 * * *';
}
return '0 9 * * *';
};
@ -143,8 +140,6 @@ export const humanSchedule = (data: ScheduleData): string => {
const d = num(data, 'schedule_day_of_month', 1, 1, 31);
return trans(summaryKey('monthly'), { day: String(d), time });
}
case ScheduleField.Custom:
return (data.schedule_custom_cron ?? '').trim() || '0 9 * * *';
}
return '';
};

View file

@ -23,6 +23,5 @@ export interface ScheduleData {
schedule_minute?: number;
schedule_weekdays?: number[];
schedule_day_of_month?: number;
schedule_custom_cron?: string;
schedule_timezone?: string;
}

View file

@ -4,7 +4,6 @@ export const ScheduleField = {
Days: 'days',
Weeks: 'weeks',
Months: 'months',
Custom: 'custom',
} as const;
export type ScheduleFieldValue = (typeof ScheduleField)[keyof typeof ScheduleField];

View file

@ -87,7 +87,6 @@
'daily at time' => [['schedule_field' => 'days', 'schedule_days_interval' => 2, 'schedule_hour' => 8, 'schedule_minute' => 45]],
'weekly on weekdays' => [['schedule_field' => 'weeks', 'schedule_weekdays' => [1, 3, 5], 'schedule_hour' => 14, 'schedule_minute' => 0]],
'monthly on day-of-month' => [['schedule_field' => 'months', 'schedule_day_of_month' => 15, 'schedule_hour' => 9, 'schedule_minute' => 0]],
'custom cron' => [['schedule_field' => 'custom', 'schedule_custom_cron' => '0 9 * * 1,3,5']],
'timezone' => [['schedule_timezone' => 'America/Sao_Paulo']],
'all fields together' => [[
'schedule_field' => 'weeks',
@ -98,7 +97,6 @@
'schedule_minute' => 30,
'schedule_weekdays' => [0, 6],
'schedule_day_of_month' => 28,
'schedule_custom_cron' => '*/5 * * * *',
'schedule_timezone' => 'Europe/Lisbon',
]],
]);