-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
web-forms (ui): Basic presentation of form load failures
Where a “form load failure” is any Promise rejection produced by the engine’s `initializeForm` entrypoint. This is intentionally broad, and what I think is a relatively minimal first pass that might be useful to users (and to us). “Relatively” minimal because I took the opportunity to lay a bit of groundwork for a few things either cued for near term work, or ripe for near term improvement. Notable among those: - Establish a more intentional approach to use of test fixtures in the `web-forms` package. This includes a dedicated fixtures directory (alongside those already used by `scenario`), and a narrower “test helper” (ugh) to access those. That access point also includes some additional breadcrumbs for ways we might improve fixture access in the future. - `FormLoadFailure` begins laying a bit of groundwork for the incoming, much more comprehensive overhaul of error messaging. - Actually tests a few different form load failure conditions. I believe these will be useful for catching potential regressions in that overhaul, as well in other future work around those specific failure modes. UI/UX/presentation design note: I had a brief discussion with @alyblenkin about this being a minimal first step. We agreed that this seems like a reasonable first pass, and agreed there’s more to do in near-future iterations. Things which are currently lacking from a UX perspective, blocked by work with a larger scope: - Better messaging of specific errors. We’ll be cataloguing known cases as part of #202, which will give us a much clearer picture of how to address this. - Any kind of direct prompt for user action. Deferred for the same reasons. - Ability to close the dialog or go back. Deferred because this would expand scope to navigation more generally, which we should look at more holistically.
- Loading branch information
1 parent
6d86e7a
commit 17b819e
Showing
10 changed files
with
426 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
packages/common/src/fixtures/test-web-forms/simple-dag-cycle.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?xml version="1.0"?> | ||
<h:html xmlns="http://www.w3.org/2002/xforms" xmlns:h="http://www.w3.org/1999/xhtml" | ||
xmlns:jr="http://openrosa.org/javarosa" xmlns:odk="http://www.opendatakit.org/xforms" | ||
xmlns:orx="http://openrosa.org/xforms"> | ||
<h:head> | ||
<h:title>Form design problem: computation cycle</h:title> | ||
<model> | ||
<instance> | ||
<data id="simple-dag-cycle"> | ||
<group> | ||
<a>1</a> | ||
</group> | ||
</data> | ||
</instance> | ||
<bind nodeset="/data/group/a" type="int" calculate="../a + 1" /> | ||
</model> | ||
</h:head> | ||
<h:body> | ||
<group ref="/data/group"> | ||
<repeat nodeset="/data/group"> | ||
<input ref="/data/group/a" /> | ||
</repeat> | ||
</group> | ||
</h:body> | ||
</h:html> |
33 changes: 33 additions & 0 deletions
33
packages/common/src/fixtures/test-web-forms/xpath-syntax-error.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?xml version="1.0"?> | ||
<h:html xmlns="http://www.w3.org/2002/xforms" | ||
xmlns:ev="http://www.w3.org/2001/xml-events" | ||
xmlns:h="http://www.w3.org/1999/xhtml" | ||
xmlns:jr="http://openrosa.org/javarosa" | ||
xmlns:orx="http://openrosa.org/xforms/" | ||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"> | ||
<h:head> | ||
<h:title>Form design problem: syntax error</h:title> | ||
<model> | ||
<instance> | ||
<root id="form-design-problem-syntax-error"> | ||
<first-question>1</first-question> | ||
<second-question /> | ||
<meta> | ||
<instanceID /> | ||
</meta> | ||
</root> | ||
</instance> | ||
<bind nodeset="/root/first-question" /> | ||
<bind nodeset="/root/second-question" calculate="/root/first-question ? 2" /> | ||
<bind nodeset="/root/meta/instanceID" type="string" /> | ||
</model> | ||
</h:head> | ||
<h:body> | ||
<input ref="/root/first-question"> | ||
<label>1. Default value is 1</label> | ||
</input> | ||
<input ref="/root/second-question"> | ||
<label>2. Fails to calculate (expression has invalid token: `?`)</label> | ||
</input> | ||
</h:body> | ||
</h:html> |
29 changes: 29 additions & 0 deletions
29
packages/common/src/fixtures/test-web-forms/xpath-unknown-function.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<?xml version="1.0"?> | ||
<h:html xmlns="http://www.w3.org/2002/xforms" | ||
xmlns:ev="http://www.w3.org/2001/xml-events" | ||
xmlns:h="http://www.w3.org/1999/xhtml" | ||
xmlns:jr="http://openrosa.org/javarosa" | ||
xmlns:orx="http://openrosa.org/xforms/" | ||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"> | ||
<h:head> | ||
<h:title>Form design problem: unknown XPath function</h:title> | ||
<model> | ||
<instance> | ||
<root id="xpath-unknown-function"> | ||
<first-question /> | ||
<second-question /> | ||
<meta> | ||
<instanceID /> | ||
</meta> | ||
</root> | ||
</instance> | ||
<bind nodeset="/root/first-question" calculate="nope(1)" /> | ||
<bind nodeset="/root/meta/instanceID" type="string" /> | ||
</model> | ||
</h:head> | ||
<h:body> | ||
<input ref="/root/first-question"> | ||
<label>Calculate calls an XPath function `nope`, which does not exist!</label> | ||
</input> | ||
</h:body> | ||
</h:html> |
11 changes: 11 additions & 0 deletions
11
packages/common/src/lib/runtime-types/shared-type-predicates.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export type UnknownObject = Readonly<Record<PropertyKey, unknown>>; | ||
|
||
/** | ||
* Checks whether a value's type is `'object'`, and the value is not `null`. | ||
* This is useful as a precondition for more specific type-narrowing predicate | ||
* and/or assertion functions, allowing inspection of arbitrary properties on | ||
* {@link value} without verbose/error prone inline type assertions. | ||
*/ | ||
export const isUnknownObject = (value: unknown): value is UnknownObject => { | ||
return typeof value === 'object' && value != null; | ||
}; |
82 changes: 82 additions & 0 deletions
82
packages/web-forms/src/components/Form/FormLoadFailureDialog.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
<script setup lang="ts"> | ||
import Dialog from 'primevue/dialog'; | ||
import Message from 'primevue/message'; | ||
import { computed } from 'vue'; | ||
import type { InitializeFormFailure } from '../../lib/error/FormLoadFailure.ts'; | ||
/** | ||
* @todo translations | ||
*/ | ||
const FORM_LOAD_ERROR_TEXT = { | ||
DIALOG_TITLE: 'An error occurred while loading this form', | ||
DETAILS_SUMMARY_LABEL: 'Technical error details', | ||
}; | ||
interface FormLoadErrorProps { | ||
readonly error: InitializeFormFailure; | ||
} | ||
const props = defineProps<FormLoadErrorProps>(); | ||
interface FormLoadErrorDetail { | ||
readonly stack: string | null; | ||
readonly unknownCauseDetail: string | null; | ||
} | ||
const detail = computed((): FormLoadErrorDetail | null => { | ||
const { stack = null, unknownCauseDetail } = props.error; | ||
if (stack == null && unknownCauseDetail == null) { | ||
return null; | ||
} | ||
return { | ||
stack, | ||
unknownCauseDetail, | ||
}; | ||
}); | ||
</script> | ||
|
||
<template> | ||
<Dialog | ||
class="form-load-failure-dialog" | ||
:visible="detail != null" | ||
:header="FORM_LOAD_ERROR_TEXT.DIALOG_TITLE" | ||
:closable="false" | ||
:draggable="false" | ||
:keep-in-viewport="true" | ||
> | ||
<Message severity="error" class="content" :closable="false"> | ||
{{ error.message }} | ||
</Message> | ||
|
||
<details v-if="detail != null" class="initialize-form-failure-details"> | ||
<summary>{{ FORM_LOAD_ERROR_TEXT.DETAILS_SUMMARY_LABEL }}</summary> | ||
|
||
<pre v-if="detail.unknownCauseDetail != null">{{ | ||
detail.unknownCauseDetail | ||
}}</pre> | ||
|
||
<pre v-if="detail.stack != null">{{ | ||
detail.stack | ||
}}</pre> | ||
</details> | ||
</Dialog> | ||
</template> | ||
|
||
<style scoped> | ||
.form-load-failure-dialog .content { | ||
margin-top: 0; | ||
} | ||
.initialize-form-failure-details { | ||
display: block; | ||
position: relative; | ||
width: max(100dvw - 6rem, 40rem); | ||
overflow: auto; | ||
} | ||
.initialize-form-failure-details summary { | ||
cursor: pointer; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.