diff --git a/packages/grafana-data/src/datetime/durationutil.test.ts b/packages/grafana-data/src/datetime/durationutil.test.ts index 6f67957bf12..c5b861191a2 100644 --- a/packages/grafana-data/src/datetime/durationutil.test.ts +++ b/packages/grafana-data/src/datetime/durationutil.test.ts @@ -18,12 +18,12 @@ describe('Duration util', () => { describe('parseDuration', () => { it('parses a duration string', () => { const durationString = '3M 5d 20m'; - expect(parseDuration(durationString)).toEqual({ months: '3', days: '5', minutes: '20' }); + expect(parseDuration(durationString)).toEqual({ months: 3, days: 5, minutes: 20 }); }); it('strips out non valid durations', () => { const durationString = '3M 6v 5b 4m'; - expect(parseDuration(durationString)).toEqual({ months: '3', minutes: '4' }); + expect(parseDuration(durationString)).toEqual({ months: 3, minutes: 4 }); }); }); diff --git a/packages/grafana-data/src/datetime/durationutil.ts b/packages/grafana-data/src/datetime/durationutil.ts index 3a012bd7a1d..73185a2c29b 100644 --- a/packages/grafana-data/src/datetime/durationutil.ts +++ b/packages/grafana-data/src/datetime/durationutil.ts @@ -35,19 +35,25 @@ export function intervalToAbbreviatedDurationString(interval: Interval, includeS /** * parseDuration parses duration string into datefns Duration object * - * @param duration - string to convert. For example '2m', '5h 20s' + * @param durationString - string to convert. For example '2m', '5h 20s' * * @public */ -export function parseDuration(duration: string): Duration { - return duration.split(' ').reduce((acc, value) => { +export function parseDuration(durationString: string): Duration { + return durationString.split(' ').reduce((acc, value) => { const match = value.match(/(\d+)(.+)/); - if (match === null || match.length !== 3) { + + const rawLength = match?.[1]; + const unit = match?.[2]; + + if (!(rawLength && unit)) { return acc; } - const key = Object.entries(durationMap).find(([_, abbreviations]) => abbreviations?.includes(match[2]))?.[0]; - return !key ? acc : { ...acc, [key]: match[1] }; + const mapping = Object.entries(durationMap).find(([_, abbreviations]) => abbreviations?.includes(match[2])); + const length = parseInt(rawLength, 10); + + return mapping ? { ...acc, [mapping[0]]: length } : acc; }, {}); } diff --git a/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.test.tsx b/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.test.tsx index 011c0acbbeb..5e07c0d23ec 100644 --- a/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.test.tsx +++ b/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.test.tsx @@ -35,5 +35,16 @@ describe('RefreshPicker', () => { ]); }); }); + + it('should format durations with multiple units', () => { + const intervals = ['10s', '1m 30s']; + + const result = intervalsToOptions({ intervals }); + expect(result).toEqual([ + { value: '', label: 'Off', ariaLabel: 'Turn off auto refresh' }, + { value: '10s', label: '10s', ariaLabel: '10 seconds' }, + { value: '1m 30s', label: '1m 30s', ariaLabel: '1 minute 30 seconds' }, + ]); + }); }); }); diff --git a/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx b/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx index 6486f69eb83..c212194bb57 100644 --- a/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx +++ b/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx @@ -102,12 +102,7 @@ export function intervalsToOptions({ intervals = defaultIntervals }: { intervals > { const intervalsOrDefault = intervals || defaultIntervals; const options = intervalsOrDefault.map((interval) => { - const duration: { [key: string]: string | number } = parseDuration(interval); - - const key = Object.keys(duration)[0]; - const value = duration[key]; - duration[key] = Number(value); - + const duration = parseDuration(interval); const ariaLabel = formatDuration(duration); return {