Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(#249): Adds default geopoint question type #300

Draft
wants to merge 38 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5b292dc
Adds demo xml form for geopoint
latin-panda Feb 4, 2025
321d486
Adds watch for geolocation
latin-panda Feb 5, 2025
f919181
Adds buttons logic
latin-panda Feb 5, 2025
c94d612
Styles UI and DOM structure
latin-panda Feb 6, 2025
1e08674
Node Definition for Geo types
latin-panda Feb 6, 2025
a10f171
Revert "Node Definition for Geo types"
latin-panda Feb 6, 2025
889fe90
Fixes type check in webapp
latin-panda Feb 6, 2025
da8d36c
Fixes lint and type check in webapp
latin-panda Feb 7, 2025
44655b6
Adds nodeOptions to access attributes
latin-panda Feb 7, 2025
b330e74
Adds parser functions for nodeOptions
latin-panda Feb 7, 2025
03fba0d
Extract node option parsers to a file and test coverage
latin-panda Feb 8, 2025
f1446c1
Input node options is optional
latin-panda Feb 8, 2025
362612f
Implement accuracy threshold logic in client vue component
latin-panda Feb 8, 2025
cd351bb
Fixes GitHub lint
latin-panda Feb 8, 2025
1ea7869
Implements geolocation error case and improves quality assessment logic
latin-panda Feb 10, 2025
dca688a
Implements readonly
latin-panda Feb 10, 2025
1b57c73
Implements saving when control leaves the viewport as the user scrolls
latin-panda Feb 10, 2025
36ea1d1
Fixes vue component type check warning
latin-panda Feb 10, 2025
05e12f4
Implements autosave when form submits for geopoint
latin-panda Feb 10, 2025
001fdf8
Improving code style
latin-panda Feb 10, 2025
cf21460
Adding scenario tests for input type geopoint
latin-panda Feb 11, 2025
059d4d4
Fixing title and icons
latin-panda Feb 11, 2025
79a5432
codec
latin-panda Feb 12, 2025
c2dd023
Fixes codec to work with Note and Integrate codec to Geopoint Vue Com…
latin-panda Feb 14, 2025
8fa68af
Refactored UI to match redesigned UI for geopoint
latin-panda Feb 15, 2025
b6e965c
Refactored Geopoint codec to support string in encode
latin-panda Feb 15, 2025
d54bb0a
Simplified decode and properly registered geopoint note
latin-panda Feb 15, 2025
c3d09fc
format
latin-panda Feb 15, 2025
36c483d
Format constant for accuracy quality
latin-panda Feb 17, 2025
e97cb69
Fixes scenario's geopoint tests
latin-panda Feb 18, 2025
443eb5c
Fixes type check in web forms package
latin-panda Feb 18, 2025
f907cc8
Fixes scenario smoke test
latin-panda Feb 18, 2025
9bdff51
Tiny improvements in code
latin-panda Feb 18, 2025
eefb1e9
UIUX Feedback: fix margins and text indentation. Try again is hidden …
latin-panda Feb 19, 2025
c9ed78b
Codec feedback - minimum valuable solution
latin-panda Feb 19, 2025
a50983a
Codec feedback - extended solution with tuple type check
latin-panda Feb 19, 2025
aa8c1ab
Codec feedback - extended solution codec fix
latin-panda Feb 19, 2025
cecd173
Codec feedback - extended solution - geopoint class generates runtime…
latin-panda Feb 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions packages/common/src/fixtures/geopoint/1-geopoint.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0"?>
<h:html xmlns="http://www.w3.org/2002/xforms" xmlns:h="http://www.w3.org/1999/xhtml"
xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jr="http://openrosa.org/javarosa" xmlns:orx="http://openrosa.org/xforms"
xmlns:odk="http://www.opendatakit.org/xforms">
<h:head>
<h:title>Geopoint</h:title>
<model odk:xforms-version="1.0.0">
<itext>
<translation lang="English (en)">
<text id="/data/facility_gps:label">
<value>Collect the GPS coordinates of this facility.</value>
</text>
</translation>
<translation lang="French (fr)">
<text id="/data/facility_gps:label">
<value>Collectez les coordonnées GPS de cet établissement.</value>
</text>
</translation>
</itext>
<instance>
<data id="1_geopoint" version="2025020401">
<facility_gps/>
<meta>
<instanceID/>
</meta>
</data>
</instance>
<bind nodeset="/data/facility_gps" type="geopoint"/>
<bind nodeset="/data/meta/instanceID" type="string" readonly="true()" jr:preload="uid"/>
</model>
</h:head>
<h:body>
<input accuracyThreshold="5" unacceptableAccuracyThreshold="50" ref="/data/facility_gps">
<label ref="jr:itext('/data/facility_gps:label')"/>
</input>
</h:body>
</h:html>
7 changes: 6 additions & 1 deletion packages/common/src/fixtures/notes/2-all-possible-notes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<read_only_int />
<read_only_int_value>3</read_only_int_value>
<note_calc_decimal_from_int />
<geopoint-note>38.253094215699576 21.756382658677467 0 150</geopoint-note>
</group>
<meta>
<instanceID />
Expand All @@ -38,6 +39,7 @@
<bind nodeset="/data/group/note_calc_decimal_from_int" type="decimal"
calculate="/data/group/read_only_int_value + 1.5" readonly="true()" />
<bind nodeset="/data/meta/instanceID" type="string" readonly="true()" jr:preload="uid" />
<bind nodeset="/data/group/geopoint-note" type="geopoint" readonly="true()" />
</model>
</h:head>
<h:body>
Expand Down Expand Up @@ -76,6 +78,9 @@
<input ref="/data/group/note_calc_decimal_from_int">
<label>A note with decimal type calculated from int</label>
</input>
<input ref="/data/group/geopoint-note">
<label>A note with geopoint type</label>
</input>
</group>
</h:body>
</h:html>
</h:html>
76 changes: 73 additions & 3 deletions packages/scenario/test/bind-types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
t,
title,
} from '@getodk/common/test/fixtures/xform-dsl/index.ts';
import type { ValueType } from '@getodk/xforms-engine';
import type { InputValue, ValueType } from '@getodk/xforms-engine';
import { assert, beforeEach, describe, expect, expectTypeOf, it } from 'vitest';
import { intAnswer } from '../src/answer/ExpectedIntAnswer.ts';
import { InputNodeAnswer } from '../src/answer/InputNodeAnswer.ts';
Expand All @@ -37,12 +37,14 @@ describe('Data (<bind type>) type support', () => {
t('implicit-string-value', 'implicit string'),
t('int-value', '123'),
t('decimal-value', '45.67'),
t('geopoint-value', '38.25146813817506 21.758421137528785 0 0'),
)
),
bind('/root/string-value').type('string').relevant(modelNodeRelevanceExpression),
bind('/root/implicit-string-value').relevant(modelNodeRelevanceExpression),
bind('/root/int-value').type('int').relevant(modelNodeRelevanceExpression),
bind('/root/decimal-value').type('decimal').relevant(modelNodeRelevanceExpression)
bind('/root/decimal-value').type('decimal').relevant(modelNodeRelevanceExpression),
bind('/root/geopoint-value').type('geopoint').relevant(modelNodeRelevanceExpression)
)
),
body(
Expand Down Expand Up @@ -182,6 +184,33 @@ describe('Data (<bind type>) type support', () => {
expect(answer.value).toBe(null);
});
});

describe('type="geopoint"', () => {
let answer: ModelValueNodeAnswer<'geopoint'>;

beforeEach(() => {
answer = getTypedModelValueNodeAnswer('/root/geopoint-value', 'geopoint');
});

it('has a GeopointValue | null static type', () => {
expectTypeOf(answer.value).toEqualTypeOf<InputValue<'geopoint'>>();
});

it('has a GeopointValue populated value', () => {
expect(answer.value).toEqual({
accuracy: 0,
altitude: 0,
latitude: 38.25146813817506,
longitude: 21.758421137528785,
});
});

it('has an null as blank value', () => {
scenario.answer(modelNodeRelevancePath, 'no');
answer = getTypedModelValueNodeAnswer('/root/geopoint-value', 'geopoint');
expect(answer.value).toBeNull();
});
});
});

describe('inputs', () => {
Expand All @@ -202,12 +231,14 @@ describe('Data (<bind type>) type support', () => {
t('implicit-string-value', 'implicit string'),
t('int-value', '123'),
t('decimal-value', '45.67'),
t('geopoint-value', '38.25146813817506 21.758421137528785 1000 25'),
)
),
bind('/root/string-value').type('string').relevant(inputRelevanceExpression),
bind('/root/implicit-string-value').relevant(inputRelevanceExpression),
bind('/root/int-value').type('int').relevant(inputRelevanceExpression),
bind('/root/decimal-value').type('decimal').relevant(inputRelevanceExpression)
bind('/root/decimal-value').type('decimal').relevant(inputRelevanceExpression),
bind('/root/geopoint-value').type('geopoint').relevant(inputRelevanceExpression)
)
),
body(
Expand All @@ -216,6 +247,7 @@ describe('Data (<bind type>) type support', () => {
input('/root/implicit-string-value'),
input('/root/int-value'),
input('/root/decimal-value'),
input('/root/geopoint-value'),
)
);

Expand Down Expand Up @@ -480,6 +512,44 @@ describe('Data (<bind type>) type support', () => {
});
});
});

describe('type="geopoint"', () => {
let answer: InputNodeAnswer<'geopoint'>;

beforeEach(() => {
answer = getTypedInputNodeAnswer('/root/geopoint-value', 'geopoint');
});

it('has a GeopointValue | null static type', () => {
expectTypeOf(answer.value).toEqualTypeOf<InputValue<'geopoint'>>();
});

it('has a GeopointValue populated value', () => {
expect(answer.value).toEqual({
accuracy: 25,
altitude: 1000,
latitude: 38.25146813817506,
longitude: 21.758421137528785,
});
});

it('has an null as blank value', () => {
scenario.answer(inputRelevancePath, 'no');
answer = getTypedInputNodeAnswer('/root/geopoint-value', 'geopoint');
expect(answer.value).toBeNull();
});

it('sets a new value', () => {
scenario.answer('/root/geopoint-value', '-1.2936673 36.7260063 1500 10');
answer = getTypedInputNodeAnswer('/root/geopoint-value', 'geopoint');
expect(answer.value).toEqual({
accuracy: 10,
altitude: 1500,
latitude: -1.2936673,
longitude: 36.7260063,
});
});
});
});

describe('casting fractional values to int', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { computed, inject, provide, ref } from 'vue';
import ControlText from '../../ControlText.vue';
import ValidationMessage from '../../ValidationMessage.vue';
import InputDecimal from './InputDecimal.vue';
import InputGeopoint from './InputGeopoint.vue';
import InputInt from './InputInt.vue';
import InputNumbersAppearance from './InputNumbersAppearance.vue';
import InputText from './InputText.vue';
Expand Down Expand Up @@ -35,13 +36,19 @@ provide('isInvalid', isInvalid);
<template v-else-if="node.valueType === 'string' && node.appearances.numbers">
<InputNumbersAppearance :node="node" />
</template>
<template v-else-if="node.valueType === 'geopoint'">
<InputGeopoint :question="node" />
</template>
<template v-else>
<InputText :node="node" />
</template>

<i v-show="isInvalid && (doneAnswering || submitPressed)" class="icon-error" />
<i v-show="isInvalid && (doneAnswering || submitPressed) && node.valueType !== 'geopoint'" class="icon-error" />
</div>
<ValidationMessage :message="node.validationState.violation?.message.asString" :show-message="doneAnswering || submitPressed" />
<ValidationMessage
:message="node.validationState.violation?.message.asString"
:show-message="doneAnswering || submitPressed"
/>
</template>

<style scoped lang="scss">
Expand Down
Loading
Loading