UNPKG

react-cron-jobs

Version:
577 lines (515 loc) 20.2 kB
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import './style.scss'; const CronBuilder = require('cron-builder'); class CronJob extends Component { constructor(props) { super(props); this.state = { // Display the date time pickers inputs // according to the schedule frequency selected. operationCronDict: { showMinutePicker: false, showHourPicker: false, showDayPicker: false, showWeekPicker: false, showMonthPicker: false, }, // Maintain the user selected time values in state. minuteSelectedList: [], hourSelectedList: [], daySelectedList: [], weekSelectedList: [], monthSelectedList: [], }; // Initializing refs for all the select // components. This is needed to highlight // selected values in date time picker select boxes // for a given cron expression. this.frequencyRef = undefined; this.minuteRef = undefined; this.hourRef = undefined; this.dayRef = undefined; this.weekRef = undefined; this.monthRef = undefined; this.yearRef = undefined; } componentWillReceiveProps(nextProps) { if (this.props.frequency !== nextProps.frequency) { // If cronstring is received as props, // display the crontab with date and timepickers // highlighted with selected values. if (nextProps.cronString !== undefined && nextProps.cronString !== '') { // cron string will be in the following format: // < * * * * * >. // Here the first star represents minute values // second represents hour values. // third represents day values. // fourth represents month values. // fifth represents week values. // Example cron expressions: // schedule job daily at 12 PM: 0 0 * * * // schedule job every sunday at 9 AM and 6PM : 0 9,18 * * 0 const cronString = nextProps.cronString; // Get the values from cron expression and populate them // in state const cronValues = cronString && cronString.split(' '); this.setState({ selectedFrequency: nextProps.frequency, minuteSelectedList: cronValues && cronValues[0].split(',') || [], hourSelectedList: cronValues && cronValues[1].split(',') || [], daySelectedList: cronValues && cronValues[2].split(',') || [], monthSelectedList: cronValues && cronValues[3].split(',') || [], weekSelectedList: cronValues && cronValues[4].split(',') || [] }, () => { // Show the date time pickers as per the schedule frequency // selected. console.log('selected frq', this.state.selectedFrequency); this.updateCronSelection(this.state.selectedFrequency); }); // When no cron expression is provided to the component, // Use schedule frequency as 'day' by default. } else { this.updateCronSelection('day'); this.prepareCronExpression(); } } } componentDidUpdate() { // When cron expression is received as props // we render the date time pickers according to the schedule // frequency received and highlight the values in the select box // as per the cron expression if (this.state.selectedFrequency) { const selectedOptionObj = this.frequencyOptionsList.find((row) => { return row.value === this.state.selectedFrequency; }); if (this.frequencyRef) { this.frequencyRef[selectedOptionObj.index].selected = true; } } // Hightlight the selected values in select box this.highlightValueSelection(this.state.minuteSelectedList, this.minuteRef, this.minuteOptionsList); this.highlightValueSelection(this.state.hourSelectedList, this.hourRef, this.hourOptionsList); this.highlightValueSelection(this.state.daySelectedList, this.dayRef, this.dayOptionsList); this.highlightValueSelection(this.state.monthSelectedList, this.monthRef, this.monthOptionsList); this.highlightValueSelection(this.state.weekSelectedList, this.weekRef, this.weekOptionsList); } // This is an option list used by // frequency select box frequencyOptionsList = [ // We have to get this list as props and use whatever frequency values we need // as per the requirements. Currently we only need the following { label: 'Minute', value: 'minute', index: 0 }, { label: 'Hour', value: 'hour', index: 1 }, { label: 'Day', value: 'day', index: 2 }, { label: 'Week', value: 'week', index: 3 }, { label: 'Month', value: 'month', index: 4 }, { label: 'Year', value: 'year', index: 5 } ] // This is an options list used by // minute picker select box. minuteOptionsList = [ { label: '0', value: 0, index: 0 }, { label: '5', value: 5, index: 1 }, { label: '10', value: 10, index: 2 }, { label: '15', value: 15, index: 3 }, { label: '20', value: 20, index: 4 }, { label: '25', value: 25, index: 5 }, { label: '30', value: 30, index: 6 }, { label: '35', value: 35, index: 7 }, { label: '40', value: 40, index: 8 }, { label: '45', value: 45, index: 9 }, { label: '50', value: 50, index: 10 }, { label: '55', value: 55, index: 11 } ]; // This is an options list used by // hour picker select box. hourOptionsList = [ { label: '0', value: 0, index: 0 }, { label: '1', value: 1, index: 1 }, { label: '2', value: 2, index: 2 }, { label: '3', value: 3, index: 3 }, { label: '4', value: 4, index: 4 }, { label: '5', value: 5, index: 5 }, { label: '6', value: 6, index: 6 }, { label: '7', value: 7, index: 7 }, { label: '8', value: 8, index: 8 }, { label: '9', value: 9, index: 9 }, { label: '10', value: 10, index: 10 }, { label: '11', value: 11, index: 11 }, { label: '12', value: 12, index: 12 }, { label: '13', value: 13, index: 13 }, { label: '14', value: 14, index: 14 }, { label: '15', value: 15, index: 15 }, { label: '16', value: 16, index: 16 }, { label: '17', value: 17, index: 17 }, { label: '18', value: 18, index: 18 }, { label: '19', value: 19, index: 19 }, { label: '20', value: 20, index: 20 }, { label: '21', value: 21, index: 21 }, { label: '22', value: 22, index: 22 }, { label: '23', value: 23, index: 23 } ]; // This is an options list used by // day picker select box. dayOptionsList = [ { label: '1st', value: 1, index: 0 }, { label: '2nd', value: 2, index: 1 }, { label: '3rd', value: 3, index: 2 }, { label: '4th', value: 4, index: 3 }, { label: '5th', value: 5, index: 4 }, { label: '6th', value: 6, index: 5 }, { label: '7th', value: 7, index: 6 }, { label: '8th', value: 8, index: 7 }, { label: '9th', value: 9, index: 8 }, { label: '10th', value: 10, index: 9 }, { label: '11th', value: 11, index: 10 }, { label: '12th', value: 12, index: 11 }, { label: '13th', value: 13, index: 12 }, { label: '14th', value: 14, index: 13 }, { label: '15th', value: 15, index: 14 }, { label: '16th', value: 16, index: 15 }, { label: '17th', value: 17, index: 16 }, { label: '18th', value: 18, index: 17 }, { label: '19th', value: 19, index: 18 }, { label: '20th', value: 20, index: 20 }, { label: '21st', value: 21, index: 21 }, { label: '22nd', value: 22, index: 22 }, { label: '23rd', value: 23, index: 23 }, { label: '24th', value: 24, index: 24 }, { label: '25th', value: 25, index: 25 }, { label: '26th', value: 26, index: 26 }, { label: '27th', value: 27, index: 27 }, { label: '28th', value: 28, index: 28 }, { label: '29th', value: 29, index: 29 }, { label: '30th', value: 30, index: 30 }, { label: '31th', value: 31, index: 31 }, ] // This is an options list used by // week picker select box. weekOptionsList = [ { label: 'Sunday', value: 1, index: 0 }, { label: 'Monday', value: 2, index: 1 }, { label: 'Tuesday', value: 3, index: 2 }, { label: 'Wednesday', value: 4, index: 3 }, { label: 'Thursday', value: 5, index: 4 }, { label: 'Friday', value: 6, index: 5 }, { label: 'Saturday', value: 7, index: 6 } ] // This is an options list used by // month picker select box. monthOptionsList = [ { label: 'January', value: 1, index: 0 }, { label: 'Febrauary', value: 2, index: 1 }, { label: 'March', value: 3, index: 2 }, { label: 'April', value: 4, index: 3 }, { label: 'May', value: 5, index: 4 }, { label: 'June', value: 6, index: 5 }, { label: 'July', value: 7, index: 6 }, { label: 'August', value: 8, index: 7 }, { label: 'September', value: 9, index: 8 }, { label: 'October', value: 10, index: 9 }, { label: 'November', value: 11, index: 10 }, { label: 'December', value: 12, index: 11 }, ]; // This function highlights the options in a select box // based on the values in the selectedList. The following // are the arguments received by this function: // selectedList: List of values that are to be highlighted in select box. // refObject : Reference to the select box whose options are to be highlighted. // optionsList : All the options of select box. highlightValueSelection = (selectedList, refObject, optionsList) => { selectedList && selectedList.map((value) => { const optionObj = optionsList.find((obj) => { return obj.value.toString() === value; }); if (refObject && optionObj !== undefined) { refObject[optionObj.index].selected = true; } }); } // This function returns an option tag using the 'label' and 'value' // keys present in the object('item') passed as argument getOption = function (item, keyPrefix) { return <option key={keyPrefix + item.label} value={item.value}>{item.label}</option>; }; // Display the minute picker select box renderMinutePicker = () => { return ( <div className="time-picker-container form-control-wrapper"> <select className="form-control" id="minute" name="minute" ref={select => { this.minuteRef = select; }} onChange={(e) => { this.updateScheduleConfiguration(e.target.options, 'minute'); }} multiple > {this.minuteOptionsList.map((item) => { return this.getOption(item, 'minute'); })} </select> </div> ); } // Display the hour picker select box renderHourPicker = () => { return ( <div className="time-picker-container"> <div className="supporting-words"> at </div> <div className="form-control-wrapper"> <select className="form-control" id="hour" name="hour" ref={select => { this.hourRef = select; }} onChange={(e) => { this.updateScheduleConfiguration(e.target.options, 'hour'); }} multiple > {this.hourOptionsList.map((item) => { return this.getOption(item, 'hour'); })} </select> </div> </div> ); } // Display the day picker select box renderDayPicker = () => { return ( <div className="time-picker-container"> <div className="supporting-words"> on the </div> <div className="form-control-wrapper"> <select className="form-control" id="day" name="day" ref={select => { this.dayRef = select; }} onChange={(e) => { this.updateScheduleConfiguration(e.target.options, 'day'); }} multiple > {this.dayOptionsList.map((item) => { return this.getOption(item, 'day'); })} </select> </div> </div> ); } // Display the week picker select box renderWeekPicker = () => { return ( <div className="time-picker-container"> <div className="supporting-words"> on </div> <div className="form-control-wrapper"> <select className="form-control" id="week" name="week" ref={select => { this.weekRef = select; }} onChange={(e) => { this.updateScheduleConfiguration(e.target.options, 'week'); }} multiple > {this.weekOptionsList.map((item) => { return this.getOption(item, 'week'); })} </select> </div> </div> ); } // Display the month picker select box renderMonthPicker = () => { return ( <div className="time-picker-container"> <div className="supporting-words"> of </div> <div className="form-control-wrapper"> <select className="form-control" id="month" name="month" ref={select => { this.monthRef = select; }} onChange={(e) => { this.updateScheduleConfiguration(e.target.options, 'month'); }} multiple > {this.monthOptionsList.map((item) => { return this.getOption(item, 'month'); })} </select> </div> </div> ); } // This function takes care of displaying // appropriate date / time pickers as per the // schedule frequency selected. displayDateTimePicker = ( selectedFrequency, displayMinuteFlag, displayHourFlag, displayDayFlag, displayWeekFlag, displayMonthFlag) => { const operationCronDictCopy = {}; operationCronDictCopy.showMinutePicker = displayMinuteFlag; operationCronDictCopy.showHourPicker = displayHourFlag; operationCronDictCopy.showDayPicker = displayDayFlag; operationCronDictCopy.showWeekPicker = displayWeekFlag; operationCronDictCopy.showMonthPicker = displayMonthFlag; operationCronDictCopy.selectedFrequency = selectedFrequency; this.setState({ operationCronDict: operationCronDictCopy }); } // This function generates the cron expression using the CronBuilder // class and its methods (cron builder npm pacakge). prepareCronExpression = () => { const cronExp = new CronBuilder(); this.state.minuteSelectedList.length && cronExp.set('minute', this.state.minuteSelectedList); this.state.hourSelectedList.length && cronExp.set('hour', this.state.hourSelectedList); this.state.daySelectedList.length && cronExp.set('dayOfTheMonth', this.state.daySelectedList); this.state.weekSelectedList.length && cronExp.set('dayOfTheWeek', this.state.weekSelectedList); this.state.monthSelectedList.length && cronExp.set('month', this.state.monthSelectedList); const cronInfoObj = {}; cronInfoObj.cronString = cronExp.build(); cronInfoObj.scheduleFrequency = this.state.selectedFrequency; this.props.getCronInfo(cronInfoObj, this.props.jobName); } // This function updates the selected values list in the state updateSelectedValues = (selectedValuesList, unitOfTime) => { switch (unitOfTime) { case 'minute': this.setState({ minuteSelectedList: selectedValuesList }, () => { this.prepareCronExpression(); }); break; case 'hour': this.setState({ hourSelectedList: selectedValuesList }, () => { this.prepareCronExpression(); }); break; case 'day': this.setState({ daySelectedList: selectedValuesList }, () => { this.prepareCronExpression(); }); break; case 'week': this.setState({ weekSelectedList: selectedValuesList }, () => { this.prepareCronExpression(); }); break; case 'month': this.setState({ monthSelectedList: selectedValuesList }, () => { this.prepareCronExpression(); }); break; default: return null; } } // This function is called when any changes are done on // any of the select boxes of date time picker UI. This function // takes two arguments: // options : List containing DOM objects of all options // unitOfTime : The date / time picker select box which is updated in UI updateScheduleConfiguration = (options, unitOfTime) => { let selectedValuesList = []; // get the latest selected values from all the options in select. selectedValuesList = [...options].filter(o => o.selected).map(o => o.value); // update the selectedvalues list in the state this.updateSelectedValues(selectedValuesList, unitOfTime); } // This function decides which date / time picker should be displayed // based on schedule frequency selected. updateCronSelection = (selectedFrequency) => { switch (selectedFrequency) { case 'minute': this.displayDateTimePicker(selectedFrequency, false, false, false, false, false); break; case 'hour': this.displayDateTimePicker(selectedFrequency, true, false, false, false, false); break; case 'day': this.displayDateTimePicker(selectedFrequency, true, true, false, false, false); break; case 'week': this.displayDateTimePicker(selectedFrequency, true, true, false, true, false); break; case 'month': this.displayDateTimePicker(selectedFrequency, true, true, true, false, false); break; case 'year': this.displayDateTimePicker(selectedFrequency, true, true, true, false, true); break; default: return null; } } // This is called when scheduled frequency is updated. // Here we reset selected values and re render the date // time pickers as per schedule selected. handleCronSelection = (selectedFrequency) => { this.minuteRef = undefined; this.hourRef = undefined; this.dayRef = undefined; this.weekRef = undefined; this.monthRef = undefined; this.yearRef = undefined; // reset selected values when the scheduled // frequency is updated. this.setState({ minuteSelectedList: [], hourSelectedList: [], daySelectedList: [], weekSelectedList: [], monthSelectedList: [], operationCronDict: {}, selectedFrequency: selectedFrequency }, () => { this.updateCronSelection(selectedFrequency); }); } render() { return ( <div className="cron-tab-container"> <div className="supporting-words"> Every </div> <div className="form-control-wrapper"> <select className="form-control cron-select" name="cronSelect" ref={select => { this.frequencyRef = select; }} onChange={(e) => { this.handleCronSelection(e.target.value); }} > {this.frequencyOptionsList.map((item) => { return this.getOption(item, 'frequency'); })} </select> </div> <div>{this.state.operationCronDict.showDayPicker && this.renderDayPicker()}</div> <div>{this.state.operationCronDict.showMonthPicker && this.renderMonthPicker()}</div> <div>{this.state.operationCronDict.showWeekPicker && this.renderWeekPicker()}</div> <div> {this.state.operationCronDict.showHourPicker && this.renderHourPicker()} </div> <div> {(this.state.operationCronDict.selectedFrequency !== 'hour' && this.state.operationCronDict.selectedFrequency !== 'minute') && ':'} </div> <div>{this.state.operationCronDict.showMinutePicker && this.renderMinutePicker()}</div> <div> {this.state.operationCronDict.selectedFrequency === 'hour' && 'past the hour'} </div> </div> ); } } CronJob.propTypes = { // Use this callback function to receive the cron expression // for the schedule configured. getCronString: PropTypes.func, // Pass this prop to get the name of the job in the above callback // function passed as props jobName: PropTypes.string, // Use this to configure defaults or load CronJob UI for //particular configuration frequency: PropTypes.string, cronString: PropTypes.string }; export default CronJob;