@adaptabletools/adaptable
Version:
Powerful AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
160 lines (159 loc) • 8.62 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import * as React from 'react';
import { CheckBox } from '../../../components/CheckBox';
import FormLayout, { FormRow } from '../../../components/FormLayout';
import Radio from '../../../components/Radio';
import AdaptableInput from '../../Components/AdaptableInput';
import { useOnePageAdaptableWizardContext } from '../../Wizard/OnePageAdaptableWizard';
import { Box } from '../../../components/Flex';
import { Card } from '../../../components/Card';
import { SingleSelect } from '../../../components/NewSelect';
import ObjectFactory from '../../../Utilities/ObjectFactory';
import { buildCronExpression, buildRunAtIso, inferPresetFromCron, isScheduleValid as validateSchedule, parseOneOffDateFromRunAt, parseTimeFromSchedule, } from '../../../Utilities/Helpers/Scheduling/ScheduleHelper';
export const isScheduleValid = (holder) => {
if (!holder?.Schedule) {
return 'Schedule is not specified';
}
return validateSchedule(holder.Schedule);
};
const daysMap = [
{ label: 'Monday', value: 'Monday' },
{ label: 'Tuesday', value: 'Tuesday' },
{ label: 'Wednesday', value: 'Wednesday' },
{ label: 'Thursday', value: 'Thursday' },
{ label: 'Friday', value: 'Friday' },
{ label: 'Saturday', value: 'Saturday' },
{ label: 'Sunday', value: 'Sunday' },
];
const PRESET_OPTIONS = [
{ value: 'daily', label: 'Every Day' },
{ value: 'weekdays', label: 'Weekdays (Mon–Fri)' },
{ value: 'selectedDays', label: 'Selected Days' },
{ value: 'monthly', label: 'Monthly' },
{ value: 'custom', label: 'Custom Cron' },
];
const DEFAULT_SELECTED_DAYS = ['Monday'];
function buildScheduleFromUiState(params) {
if (params.isOneOff) {
const date = params.oneOffDate || new Date().toISOString().slice(0, 10);
return {
IsOneOff: true,
RunAt: buildRunAtIso(date, params.hour, params.minute),
};
}
return {
IsOneOff: false,
CronExpression: buildCronExpression(params.preset, params.hour, params.minute, {
days: params.selectedDays,
dayOfMonth: params.dayOfMonth,
customExpression: params.customCron,
}),
};
}
export const ScheduleBuilderWizard = (props) => {
const { data } = useOnePageAdaptableWizardContext();
const schedule = data?.Schedule ?? ObjectFactory.CreateDefaultSchedule();
const isOneOff = schedule.IsOneOff;
const { hour: initialHour, minute: initialMinute } = parseTimeFromSchedule(schedule);
const inferred = inferPresetFromCron(schedule.CronExpression);
const [hour, setHour] = React.useState(initialHour);
const [minute, setMinute] = React.useState(initialMinute);
const [preset, setPreset] = React.useState(inferred.preset);
const [selectedDays, setSelectedDays] = React.useState(inferred.days);
const [dayOfMonth, setDayOfMonth] = React.useState(inferred.dayOfMonth);
const [customCron, setCustomCron] = React.useState(schedule.CronExpression ?? '');
const [oneOffDate, setOneOffDate] = React.useState(parseOneOffDateFromRunAt(schedule.RunAt));
React.useEffect(() => {
const { hour: h, minute: m } = parseTimeFromSchedule(schedule);
const inf = inferPresetFromCron(schedule.CronExpression);
setHour(h);
setMinute(m);
setPreset(inf.preset);
setSelectedDays(inf.days);
setDayOfMonth(inf.dayOfMonth);
setCustomCron(schedule.CronExpression ?? '');
setOneOffDate(parseOneOffDateFromRunAt(schedule.RunAt));
}, [schedule.IsOneOff, schedule.RunAt, schedule.CronExpression]);
const commit = React.useCallback((overrides) => {
const next = buildScheduleFromUiState({
isOneOff,
oneOffDate,
hour,
minute,
preset,
selectedDays,
dayOfMonth,
customCron,
...overrides,
});
props.onChange({ ...data, Schedule: next });
}, [
isOneOff,
oneOffDate,
hour,
minute,
preset,
selectedDays,
dayOfMonth,
customCron,
data,
props,
]);
const handleFrequencyChange = (oneOff) => {
if (oneOff) {
commit({
isOneOff: true,
oneOffDate: oneOffDate || new Date().toISOString().slice(0, 10),
});
}
else {
commit({ isOneOff: false });
}
};
const handleTimeChange = (event) => {
const [h, m] = (event.target.value || '09:00')
.split(':')
.map((item) => parseInt(item, 10));
setHour(h);
setMinute(m);
commit({ hour: h, minute: m });
};
const handleOneOffDateChange = (event) => {
const value = event.target.value;
setOneOffDate(value);
commit({ oneOffDate: value });
};
const handlePresetChange = (value) => {
setPreset(value);
const days = value === 'selectedDays' && selectedDays.length === 0
? DEFAULT_SELECTED_DAYS
: selectedDays;
if (value === 'selectedDays' && selectedDays.length === 0) {
setSelectedDays(days);
}
commit({ preset: value, selectedDays: days });
};
const handleDayChange = (checked, day) => {
const next = checked
? [...selectedDays, day]
: selectedDays.filter((d) => d !== day);
if (next.length === 0) {
return;
}
setSelectedDays(next);
setPreset('selectedDays');
commit({ selectedDays: next, preset: 'selectedDays' });
};
const handleDayOfMonthChange = (event) => {
const dom = parseInt(event.target.value, 10) || 1;
setDayOfMonth(dom);
commit({ dayOfMonth: dom });
};
const handleCustomCronChange = (event) => {
const value = event.target.value;
setCustomCron(value);
commit({ customCron: value, preset: 'custom' });
};
const timeValue = `${`${hour}`.padStart(2, '0')}:${`${minute}`.padStart(2, '0')}`;
return (_jsx(Box, { "data-name": "schedule-setup", children: _jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Schedule" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Configure when this should run" })] }), _jsx(Card.Body, { children: _jsxs(FormLayout, { children: [_jsxs(FormRow, { label: "Frequency", children: [_jsx(Radio, { "data-name": "frequency-recurring", className: "twa:mr-2", value: "recurring", checked: !isOneOff, onChange: (checked) => checked && handleFrequencyChange(false), children: "Recurring" }), _jsx(Radio, { "data-name": "frequency-one-off", checked: isOneOff, value: "oneoff", onChange: (checked) => checked && handleFrequencyChange(true), children: "One-off" })] }), isOneOff ? (_jsx(FormRow, { label: "Date", children: _jsx(AdaptableInput, { "data-name": "one-off-date", className: "twa:w-[300px]", type: "date", placeholder: "Date", onChange: handleOneOffDateChange, value: oneOffDate }) })) : (_jsxs(_Fragment, { children: [_jsx(FormRow, { label: "Pattern", children: _jsx(Box, { className: "twa:max-w-[300px]", children: _jsx(SingleSelect, { className: "twa:w-full", "data-name": "recurrence-preset", items: PRESET_OPTIONS, value: preset, placeholder: "Select pattern", onValueChange: handlePresetChange }) }) }), preset === 'selectedDays' && (_jsx(FormRow, { label: "Days", children: daysMap.map((day) => (_jsx(CheckBox, { "data-name": `day-${day.value}`, className: "twa:ml-2 twa:w-1/3", value: day.value, checked: selectedDays.includes(day.value), onChange: (checked) => handleDayChange(checked, day.value), children: day.label }, day.value))) })), preset === 'monthly' && (_jsx(FormRow, { label: "Day of month", children: _jsx(AdaptableInput, { "data-name": "day-of-month", className: "twa:w-[120px]", type: "number", min: 1, max: 31, value: dayOfMonth, onChange: handleDayOfMonthChange }) })), preset === 'custom' && (_jsx(FormRow, { label: "Cron expression", children: _jsx(AdaptableInput, { "data-name": "custom-cron", className: "twa:w-[300px]", placeholder: "minute hour day month weekday", value: customCron, onChange: handleCustomCronChange }) }))] })), (isOneOff || preset !== 'custom') && (_jsx(FormRow, { label: "Time", children: _jsx(AdaptableInput, { "data-name": "time", className: "twa:w-[300px]", value: timeValue, type: "time", onChange: handleTimeChange }) }))] }) })] }) }));
};