diff --git a/src/dashboard/Data/Jobs/EditScheduledJobModal.react.js b/src/dashboard/Data/Jobs/EditScheduledJobModal.react.js index 2cee584e37..d431c9f685 100644 --- a/src/dashboard/Data/Jobs/EditScheduledJobModal.react.js +++ b/src/dashboard/Data/Jobs/EditScheduledJobModal.react.js @@ -42,8 +42,8 @@ function parseInitialState(job) { repeatType = 'Every day'; } else { repeatType = 'On an interval'; - if (job.repeatMinutes > 60) { - intervalCount = (job.repeatMinutes / 60) | 0; + if (job.repeatMinutes >= 60 && job.repeatMinutes % 60 === 0) { + intervalCount = job.repeatMinutes / 60; intervalUnit = 'hour'; } else { intervalCount = job.repeatMinutes; diff --git a/src/dashboard/Data/Jobs/Jobs.react.js b/src/dashboard/Data/Jobs/Jobs.react.js index 7288f6433b..2cb8a76df3 100644 --- a/src/dashboard/Data/Jobs/Jobs.react.js +++ b/src/dashboard/Data/Jobs/Jobs.react.js @@ -66,10 +66,12 @@ function scheduleString(data) { if (data.repeatMinutes) { if (data.repeatMinutes === 1440) { schedule += 'Every day, '; - } else if (data.repeatMinutes > 60) { - schedule += 'Each day, every ' + ((data.repeatMinutes / 60) | 0) + ' hours, '; + } else if (data.repeatMinutes >= 60 && data.repeatMinutes % 60 === 0) { + const hours = data.repeatMinutes / 60; + schedule += 'Each day, every ' + hours + (hours === 1 ? ' hour, ' : ' hours, '); } else { - schedule += 'Each day, every ' + data.repeatMinutes + ' minutes, '; + const mins = data.repeatMinutes; + schedule += 'Each day, every ' + mins + (mins === 1 ? ' minute, ' : ' minutes, '); } if (data.timeOfDay) { schedule += 'after ' + data.timeOfDay.substr(0, 5) + ', '; diff --git a/src/lib/stores/JobsStore.js b/src/lib/stores/JobsStore.js index 020b1af0d2..224774ea37 100644 --- a/src/lib/stores/JobsStore.js +++ b/src/lib/stores/JobsStore.js @@ -12,6 +12,22 @@ import { registerStore } from 'lib/stores/StoreManager'; export const ActionTypes = keyMirror(['FETCH', 'CREATE', 'EDIT', 'DELETE']); +// Scheduled jobs store their interval as an "HH:MM" string in `schedule.intervalRun` +// (e.g. "01:00" for every hour, "00:15" for every 15 minutes). Convert it back into a +// total number of minutes so the rest of the dashboard can treat `repeatMinutes` as a +// number. Returns null when there is no interval set. +function intervalRunToMinutes(intervalRun) { + if (intervalRun === null || intervalRun === undefined || intervalRun === '') { + return null; + } + if (typeof intervalRun === 'number') { + return intervalRun || null; + } + const [hours, minutes] = String(intervalRun).split(':'); + const total = (parseInt(hours, 10) || 0) * 60 + (parseInt(minutes, 10) || 0); + return total || null; +} + // Jobs state should be an Immutable Map with the following fields: // - lastFetch: the last time all data was fetched from the server // - jobs: An Immutable Map of schedule ids to Maps of job details @@ -41,7 +57,7 @@ function JobsStore(state, action) { job.startAfter || job.startAt ), - repeatMinutes: job.schedule && (job.schedule.intervalRun || (job.schedule.dailyRun ? 1440 : null)), + repeatMinutes: job.schedule && (intervalRunToMinutes(job.schedule.intervalRun) || (job.schedule.dailyRun ? 1440 : null)), timeOfDay: (job.schedule && (job.schedule.dailyRun || job.schedule.timeOfDay)) || null, params: job.parameter ? JSON.stringify(job.parameter) : null, }));