Skip to content

Commit cec6521

Browse files
committed
Pr feedback plus option to include space
1 parent f9bdea5 commit cec6521

5 files changed

Lines changed: 443 additions & 34 deletions

File tree

src/plugins/data/common/field_formats/converters/duration.test.ts

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,69 @@ describe('Duration Format', () => {
139139
],
140140
});
141141

142+
testCase({
143+
inputFormat: 'nanoseconds',
144+
outputFormat: 'dynamic',
145+
outputPrecision: 2,
146+
showSuffix: true,
147+
fixtures: [
148+
{
149+
input: 1988,
150+
output: '0.00 Milliseconds',
151+
},
152+
{
153+
input: 658,
154+
output: '0.00 Milliseconds',
155+
},
156+
{
157+
input: 3857,
158+
output: '0.00 Milliseconds',
159+
},
160+
],
161+
});
162+
163+
testCase({
164+
inputFormat: 'microseconds',
165+
outputFormat: 'dynamic',
166+
outputPrecision: 2,
167+
showSuffix: true,
168+
fixtures: [
169+
{
170+
input: 1988,
171+
output: '1.99 Milliseconds',
172+
},
173+
{
174+
input: 658,
175+
output: '0.66 Milliseconds',
176+
},
177+
{
178+
input: 3857,
179+
output: '3.86 Milliseconds',
180+
},
181+
],
182+
});
183+
184+
testCase({
185+
inputFormat: 'microseconds',
186+
outputFormat: 'dynamic',
187+
outputPrecision: 1,
188+
showSuffix: true,
189+
fixtures: [
190+
{
191+
input: 1988,
192+
output: '2.0 Milliseconds',
193+
},
194+
{
195+
input: 658,
196+
output: '0.7 Milliseconds',
197+
},
198+
{
199+
input: 3857,
200+
output: '3.9 Milliseconds',
201+
},
202+
],
203+
});
204+
142205
testCase({
143206
inputFormat: 'seconds',
144207
outputFormat: 'dynamic',
@@ -167,6 +230,14 @@ describe('Duration Format', () => {
167230
showSuffix: true,
168231
useShortSuffix: true,
169232
fixtures: [
233+
{
234+
input: -123,
235+
output: '-123 ms',
236+
},
237+
{
238+
input: 1,
239+
output: '1 ms',
240+
},
170241
{
171242
input: 600,
172243
output: '600 ms',
@@ -177,12 +248,51 @@ describe('Duration Format', () => {
177248
},
178249
{
179250
input: 3000,
180-
output: '3 sec',
251+
output: '3 s',
181252
},
182253
{
183254
input: 300000,
184255
output: '5 min',
185256
},
257+
{
258+
input: 30000000,
259+
output: '8 h',
260+
},
261+
{
262+
input: 90000000,
263+
output: '1 d',
264+
},
265+
{
266+
input: 9000000000,
267+
output: '3 mon',
268+
},
269+
{
270+
input: 99999999999,
271+
output: '3 y',
272+
},
273+
],
274+
});
275+
276+
testCase({
277+
inputFormat: 'milliseconds',
278+
outputFormat: 'dynamic',
279+
outputPrecision: 0,
280+
showSuffix: true,
281+
useShortSuffix: true,
282+
includeSpaceWithSuffix: false,
283+
fixtures: [
284+
{
285+
input: -123,
286+
output: '-123ms',
287+
},
288+
{
289+
input: 1,
290+
output: '1ms',
291+
},
292+
{
293+
input: 600,
294+
output: '600ms',
295+
},
186296
],
187297
});
188298

@@ -192,13 +302,15 @@ describe('Duration Format', () => {
192302
outputPrecision,
193303
showSuffix,
194304
useShortSuffix,
305+
includeSpaceWithSuffix,
195306
fixtures,
196307
}: {
197308
inputFormat: string;
198309
outputFormat: string;
199310
outputPrecision: number | undefined;
200311
showSuffix: boolean | undefined;
201312
useShortSuffix?: boolean;
313+
includeSpaceWithSuffix?: boolean;
202314
fixtures: any[];
203315
}) {
204316
fixtures.forEach((fixture: Record<string, any>) => {
@@ -209,7 +321,14 @@ describe('Duration Format', () => {
209321
outputPrecision ? `, ${outputPrecision} decimals` : ''
210322
}`, () => {
211323
const duration = new DurationFormat(
212-
{ inputFormat, outputFormat, outputPrecision, showSuffix, useShortSuffix },
324+
{
325+
inputFormat,
326+
outputFormat,
327+
outputPrecision,
328+
showSuffix,
329+
useShortSuffix,
330+
includeSpaceWithSuffix,
331+
},
213332
jest.fn()
214333
);
215334
expect(duration.convert(input)).toBe(output);

src/plugins/data/common/field_formats/converters/duration.ts

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ const outputFormats = [
110110
defaultMessage: 'Seconds',
111111
}),
112112
shortText: i18n.translate('data.fieldFormats.duration.outputFormats.asSeconds.short', {
113-
defaultMessage: 'sec',
113+
defaultMessage: 's',
114114
}),
115115
method: 'asSeconds',
116116
},
@@ -128,7 +128,7 @@ const outputFormats = [
128128
defaultMessage: 'Hours',
129129
}),
130130
shortText: i18n.translate('data.fieldFormats.duration.outputFormats.asHours.short', {
131-
defaultMessage: 'hr',
131+
defaultMessage: 'h',
132132
}),
133133
method: 'asHours',
134134
},
@@ -164,7 +164,7 @@ const outputFormats = [
164164
defaultMessage: 'Years',
165165
}),
166166
shortText: i18n.translate('data.fieldFormats.duration.outputFormats.asYears.short', {
167-
defaultMessage: 'Yr',
167+
defaultMessage: 'y',
168168
}),
169169
method: 'asYears',
170170
},
@@ -188,16 +188,23 @@ function formatInputDynamically(
188188
val: number,
189189
inputFormat: string,
190190
outputPrecision: number,
191-
showSuffix: boolean,
192-
useShortSuffix: boolean
191+
useShortSuffix: boolean,
192+
includeSpace: string
193193
) {
194194
const ratio = ratioToSeconds[inputFormat] || 1;
195195
const kind = (inputFormat in ratioToSeconds
196196
? 'seconds'
197197
: inputFormat) as unitOfTime.DurationConstructor;
198198
const valueInDuration = moment.duration(val * ratio, kind);
199199

200-
return formatDuration(valueInDuration, outputPrecision, showSuffix, useShortSuffix);
200+
return formatDuration(
201+
val,
202+
valueInDuration,
203+
inputFormat,
204+
outputPrecision,
205+
useShortSuffix,
206+
includeSpace
207+
);
201208
}
202209

203210
export class DurationFormat extends FieldFormat {
@@ -223,6 +230,7 @@ export class DurationFormat extends FieldFormat {
223230
inputFormat: DEFAULT_INPUT_FORMAT.kind,
224231
outputFormat: DEFAULT_OUTPUT_FORMAT.method,
225232
outputPrecision: DEFAULT_OUTPUT_PRECISION,
233+
includeSpaceWithSuffix: true,
226234
};
227235
}
228236

@@ -232,41 +240,46 @@ export class DurationFormat extends FieldFormat {
232240
const outputPrecision = this.param('outputPrecision');
233241
const showSuffix = Boolean(this.param('showSuffix'));
234242
const useShortSuffix = Boolean(this.param('useShortSuffix'));
243+
const includeSpaceWithSuffix = this.param('includeSpaceWithSuffix');
244+
245+
// explicitly checking for false
246+
const includeSpace = includeSpaceWithSuffix ? ' ' : '';
247+
235248
const human = this.isHuman();
236249
const dyanmic = this.isDynamic();
250+
237251
const prefix =
238252
val < 0 && human
239253
? i18n.translate('data.fieldFormats.duration.negativeLabel', {
240254
defaultMessage: 'minus',
241255
}) + ' '
242256
: '';
257+
243258
const duration = parseInputAsDuration(val, inputFormat) as Record<keyof Duration, Function>;
244259
const formatted = dyanmic
245-
? formatInputDynamically(val, inputFormat, outputPrecision, showSuffix, useShortSuffix)
260+
? formatInputDynamically(val, inputFormat, outputPrecision, useShortSuffix, includeSpace)
246261
: duration[outputFormat]();
247262
const precise = human || dyanmic ? formatted : formatted.toFixed(outputPrecision);
248263
const type = outputFormats.find(({ method }) => method === outputFormat);
249264

250265
const unitText = useShortSuffix ? type?.shortText : type?.text;
251266

252-
const suffix = showSuffix && unitText ? ` ${unitText}` : '';
267+
const suffix = showSuffix && unitText ? `${includeSpace}${unitText}` : '';
253268

254269
return dyanmic ? precise : prefix + precise + suffix;
255270
};
256271
}
257272

258273
function formatDuration(
274+
val: number,
259275
duration: moment.Duration,
276+
inputFormat: string,
260277
outputPrecision: number,
261-
showSuffix: boolean,
262-
useShortSuffix: boolean
278+
useShortSuffix: boolean,
279+
includeSpace: string
263280
) {
264-
const parts = [];
265-
// const duration = moment.duration(period);
266-
267281
// return nothing when the duration is falsy or not correctly parsed (P0D)
268282
if (!duration || duration.toISOString() === 'P0D') return;
269-
270283
const units = [
271284
{ unit: duration.years(), nextUnitRate: 12, method: 'asYears' },
272285
{ unit: duration.months(), nextUnitRate: 4, method: 'asMonths' },
@@ -278,27 +291,32 @@ function formatDuration(
278291
{ unit: duration.milliseconds(), nextUnitRate: 1000, method: 'asMilliseconds' },
279292
];
280293

294+
const getUnitText = (method: string) => {
295+
const type = outputFormats.find(({ method: methodT }) => method === methodT);
296+
return useShortSuffix ? type?.shortText : type?.text;
297+
};
298+
281299
for (let i = 0; i < units.length; i++) {
282300
const unitValue = units[i].unit;
283301
if (unitValue >= 1) {
284-
const type = outputFormats.find(({ method }) => method === units[i].method);
285-
const unitText = showSuffix ? (useShortSuffix ? type?.shortText : type?.text) : '';
302+
const unitText = getUnitText(units[i].method);
286303

287304
const value = Math.floor(unitValue);
288305
if (units?.[i + 1]) {
289306
const decimalPointValue = Math.floor(units[i + 1].unit);
290-
parts.push(
307+
return (
291308
(value + decimalPointValue / units[i].nextUnitRate).toFixed(outputPrecision) +
292-
' ' +
293-
unitText
309+
includeSpace +
310+
unitText
294311
);
295-
return parts.join(', ');
296312
} else {
297-
parts.push(value + ' ' + unitText);
298-
return parts.join(', ');
313+
return unitValue.toFixed(outputPrecision) + includeSpace + unitText;
299314
}
300315
}
301316
}
302317

303-
return 0;
318+
const unitValue = units[units.length - 1].unit;
319+
const unitText = getUnitText(units[units.length - 1].method);
320+
321+
return unitValue.toFixed(outputPrecision) + includeSpace + unitText;
304322
}

0 commit comments

Comments
 (0)