FIX: Cast all numerical values in reports (#8087)

* FIX: Cast all numerical values in reports

The backend can return some numerical values in report as strings. That results in unexpected order of values when sorting report tables.

* Create `toNumber()` helper

The `typeof` and `parseFloat` seem to be the fastest path: https://jsperf.com/number-vs-typeof-vs-parsefloat#results
This commit is contained in:
Jarek Radosz 2019-09-12 15:17:34 +02:00 committed by GitHub
parent 73172f00d3
commit 1dcdcb5c31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 18 additions and 10 deletions

View File

@ -1,7 +1,11 @@
import { escapeExpression } from "discourse/lib/utilities"; import { escapeExpression } from "discourse/lib/utilities";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import round from "discourse/lib/round"; import round from "discourse/lib/round";
import { fillMissingDates, formatUsername } from "discourse/lib/utilities"; import {
fillMissingDates,
formatUsername,
toNumber
} from "discourse/lib/utilities";
import computed from "ember-addons/ember-computed-decorators"; import computed from "ember-addons/ember-computed-decorators";
import { number, durationTiny } from "discourse/lib/formatter"; import { number, durationTiny } from "discourse/lib/formatter";
import { renderAvatar } from "discourse/helpers/user-avatar"; import { renderAvatar } from "discourse/helpers/user-avatar";
@ -374,14 +378,14 @@ const Report = Discourse.Model.extend({
_secondsLabel(value) { _secondsLabel(value) {
return { return {
value, value: toNumber(value),
formatedValue: durationTiny(value) formatedValue: durationTiny(value)
}; };
}, },
_percentLabel(value) { _percentLabel(value) {
return { return {
value, value: toNumber(value),
formatedValue: value ? `${value}%` : "—" formatedValue: value ? `${value}%` : "—"
}; };
}, },
@ -394,14 +398,14 @@ const Report = Discourse.Model.extend({
const formatedValue = () => (formatNumbers ? number(value) : value); const formatedValue = () => (formatNumbers ? number(value) : value);
return { return {
value, value: toNumber(value),
formatedValue: value ? formatedValue() : "—" formatedValue: value ? formatedValue() : "—"
}; };
}, },
_bytesLabel(value) { _bytesLabel(value) {
return { return {
value, value: toNumber(value),
formatedValue: I18n.toHumanSize(value) formatedValue: I18n.toHumanSize(value)
}; };
}, },

View File

@ -599,8 +599,12 @@ export function clipboardData(e, canUpload) {
return { clipboard, types, canUpload, canPasteHtml }; return { clipboard, types, canUpload, canPasteHtml };
} }
export function toNumber(input) {
return typeof input === "number" ? input : parseFloat(input);
}
export function isNumeric(input) { export function isNumeric(input) {
return !isNaN(parseFloat(input)) && isFinite(input); return !isNaN(toNumber(input)) && isFinite(input);
} }
export function fillMissingDates(data, startDate, endDate) { export function fillMissingDates(data, startDate, endDate) {

View File

@ -7,7 +7,7 @@ let signups = {
yaxis: "Number of signups", yaxis: "Number of signups",
description: "New account registrations for this period", description: "New account registrations for this period",
data: [ data: [
{ x: "2018-06-16", y: 12 }, { x: "2018-06-16", y: "12" },
{ x: "2018-06-17", y: 16 }, { x: "2018-06-17", y: 16 },
{ x: "2018-06-18", y: 42 }, { x: "2018-06-18", y: 42 },
{ x: "2018-06-19", y: 38 }, { x: "2018-06-19", y: 38 },
@ -18,7 +18,7 @@ let signups = {
{ x: "2018-06-24", y: 17 }, { x: "2018-06-24", y: 17 },
{ x: "2018-06-25", y: 27 }, { x: "2018-06-25", y: 27 },
{ x: "2018-06-26", y: 32 }, { x: "2018-06-26", y: 32 },
{ x: "2018-06-27", y: 7 } { x: "2018-06-27", y: "7" }
], ],
start_date: "2018-06-16T00:00:00Z", start_date: "2018-06-16T00:00:00Z",
end_date: "2018-07-16T23:59:59Z", end_date: "2018-07-16T23:59:59Z",

View File

@ -398,7 +398,7 @@ QUnit.test("computed labels", assert => {
username: "joffrey", username: "joffrey",
user_id: 1, user_id: 1,
user_avatar: "/", user_avatar: "/",
flag_count: 1876, flag_count: "1876",
time_read: 287362, time_read: 287362,
note: "This is a long note", note: "This is a long note",
topic_id: 2, topic_id: 2,
@ -470,7 +470,7 @@ QUnit.test("computed labels", assert => {
assert.equal(flagCountLabel.type, "number"); assert.equal(flagCountLabel.type, "number");
let computedFlagCountLabel = flagCountLabel.compute(row); let computedFlagCountLabel = flagCountLabel.compute(row);
assert.equal(computedFlagCountLabel.formatedValue, "1.9k"); assert.equal(computedFlagCountLabel.formatedValue, "1.9k");
assert.equal(computedFlagCountLabel.value, 1876); assert.strictEqual(computedFlagCountLabel.value, 1876);
computedFlagCountLabel = flagCountLabel.compute(row, { computedFlagCountLabel = flagCountLabel.compute(row, {
formatNumbers: false formatNumbers: false
}); });