Skip to content

Commit bf60966

Browse files
committed
Resolves feedback: Refactors truncate function, rename number parser file, fixes changeset, improves notes template
1 parent 62b4c6c commit bf60966

File tree

9 files changed

+36
-25
lines changed

9 files changed

+36
-25
lines changed

.changeset/violet-chefs-dress.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
'@getodk/common': patch
66
---
77

8-
Support for default geopoint question type (`<input type="geopoint">`)
9-
Support for geopoint note
8+
- Support for geopoint questions with no appearance
9+
- Support for geopoint notes

packages/scenario/test/smoketests/child-vaccination.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ describe('ChildVaccinationTest.java', () => {
760760

761761
scenario.next('/data/not_single');
762762
scenario.next('/data/not_single/gps');
763-
scenario.answer('1.234 5.678 0 2.3');
763+
scenario.answer('1.234 5.678 0 2.3'); // an accuracy of 0m or greater than 5m makes a second geopoint question relevant
764764
scenario.next('/data/building_name');
765765
scenario.answer('Some building');
766766
scenario.next('/data/full_address1');

packages/web-forms/src/components/controls/GeopointFormattedValue.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const value = computed<GeopointValue>(() => {
2626
<template>
2727
<!-- TODO: translations -->
2828
<p class="geopoint-formatted-value">
29-
<span v-if="value?.accuracy != null">Accuracy: {{ truncateDecimals(value.accuracy) }} m</span>
29+
<span v-if="value?.accuracy != null">Accuracy: {{ truncateDecimals(value.accuracy, { decimals: 3 }) }} m</span>
3030
<span v-if="value?.latitude != null">Latitude: {{ value.latitude }}</span>
3131
<span v-if="value?.longitude != null">Longitude: {{ value.longitude }}</span>
3232
</p>

packages/web-forms/src/components/controls/Input/Geopoint/GeolocationRequestDialog.vue

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ interface GeolocationRequestDialogProps {
2323
2424
const props = defineProps<GeolocationRequestDialogProps>();
2525
26+
const accuracyTruncateOptions = { decimals: 3 };
27+
2628
const previousAccuracy = computed(() => {
2729
return new GeopointAccuracy(props.geopoint, props.options);
2830
});
@@ -164,14 +166,14 @@ onBeforeUnmount(cleanup);
164166
<div class="geopoint-information">
165167
<!-- TODO: translations -->
166168
<strong v-if="accuracy.value != null" class="geo-quality">
167-
{{ truncateDecimals(accuracy.value) }} m - {{ accuracy.label }}
169+
{{ truncateDecimals(accuracy.value, accuracyTruncateOptions) }} m - {{ accuracy.label }}
168170
</strong>
169171
<p v-if="options.accuracyThreshold > 0 && state.geopoint == null">
170172
Location will be saved at {{ options.accuracyThreshold }} m
171173
</p>
172174
<p>Time taken to capture location: <ElapsedTime /></p>
173175
<p v-if="previousAccuracy.value">
174-
Previous saved location at {{ truncateDecimals(previousAccuracy.value) }} m
176+
Previous saved location at {{ truncateDecimals(previousAccuracy.value, accuracyTruncateOptions) }} m
175177
</p>
176178
</div>
177179
</div>

packages/web-forms/src/components/controls/NoteControl.vue

+7-7
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,15 @@ const value = computed<NoteRenderableValue>(() => {
6969
<div class="note-control">
7070
<ControlText :question="question" />
7171

72-
<template v-if="question.valueType === 'geopoint'">
73-
<GeopointFormattedValue :question="question" />
74-
</template>
72+
<div v-if="value != null" class="note-value">
73+
<template v-if="question.valueType === 'geopoint'">
74+
<GeopointFormattedValue :question="question" />
75+
</template>
7576

76-
<template v-else-if="value != null">
77-
<div class="note-value">
77+
<template v-else>
7878
{{ value }}
79-
</div>
80-
</template>
79+
</template>
80+
</div>
8181
</div>
8282
</template>
8383

Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
1-
export const truncateDecimals = (num: number, decimals = 3): string => {
2-
if (
3-
typeof num !== 'number' ||
4-
Number.isNaN(num) ||
5-
typeof decimals !== 'number' ||
6-
Number.isNaN(decimals)
7-
) {
1+
interface TruncateDecimalsOptions {
2+
readonly decimals: number;
3+
}
4+
5+
export const truncateDecimals = (num: number, options: TruncateDecimalsOptions): string => {
6+
const { decimals } = options;
7+
8+
if (!Number.isFinite(decimals) || decimals < 0) {
9+
throw new Error(
10+
`Truncation failed: expected a finite, non-negative decimal option, got: ${decimals}`
11+
);
12+
}
13+
14+
if (!Number.isFinite(num)) {
815
return '';
916
}
1017

11-
if (Number.isInteger(num) || decimals <= 0) {
18+
if (Number.isInteger(num)) {
1219
return num.toString();
1320
}
1421

1522
const factor = Math.pow(10, decimals);
1623
const withDecimals = Math.floor(Math.abs(num) * factor) / factor;
17-
return (num < 0 ? -withDecimals : withDecimals).toString();
24+
const sign = Math.sign(num);
25+
26+
return String(withDecimals * sign);
1827
};

packages/xforms-engine/src/lib/NumberParsers.ts packages/xforms-engine/src/lib/number-parsers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export const parseToFloat = (value: string | null): number | null => {
1717
}
1818

1919
const parsed = Number(value);
20-
if (typeof value !== 'string' || value.trim() === '' || isNaN(parsed)) {
20+
if (typeof value !== 'string' || value.trim() === '' || Number.isNaN(parsed)) {
2121
throw new Error(`Expected a float, but got: ${value}`);
2222
}
2323

packages/xforms-engine/src/parse/body/control/InputControlDefinition.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { XFormDefinition } from '../../XFormDefinition.ts';
22
import type { InputAppearanceDefinition } from '../appearance/inputAppearanceParser.ts';
33
import { inputAppearanceParser } from '../appearance/inputAppearanceParser.ts';
44
import type { BodyElementParentContext } from '../BodyDefinition.ts';
5-
import { parseToFloat, parseToInteger } from '../../../lib/NumberParsers.ts';
5+
import { parseToFloat, parseToInteger } from '../../../lib/number-parsers.ts';
66
import { ControlDefinition } from './ControlDefinition.ts';
77

88
export class InputControlDefinition extends ControlDefinition<'input'> {

packages/xforms-engine/test/lib/NumberParsers.test.ts packages/xforms-engine/test/lib/number-parsers.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { assert, describe, expect, it } from 'vitest';
2-
import { parseToFloat, parseToInteger } from '../../src/lib/NumberParsers.ts';
2+
import { parseToFloat, parseToInteger } from '../../src/lib/number-parsers.ts';
33

44
describe('NumberParsers', () => {
55
interface SuccessTestCase {

0 commit comments

Comments
 (0)