-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add flattened passport structure for List items that is compati…
…ble with Calculate (#3249)
- Loading branch information
1 parent
9f0f1f6
commit 300de77
Showing
3 changed files
with
118 additions
and
1 deletion.
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
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 |
---|---|---|
|
@@ -33,6 +33,17 @@ const mockPayload = { | |
size: "Medium", | ||
}, | ||
], | ||
"mockFn.one.age": 10, | ||
"mockFn.one.cuteness": "Very", | ||
"mockFn.one.email": "[email protected]", | ||
"mockFn.one.name": "Richard Parker", | ||
"mockFn.one.size": "Medium", | ||
"mockFn.two.age": 10, | ||
"mockFn.two.cuteness": "Very", | ||
"mockFn.two.email": "[email protected]", | ||
"mockFn.two.name": "Richard Parker", | ||
"mockFn.two.size": "Medium", | ||
"mockFn.count": 2, | ||
}, | ||
}; | ||
|
||
|
@@ -355,6 +366,7 @@ describe("Form validation and error handling", () => { | |
test.todo("number fields use existing validation schemas"); | ||
test.todo("question fields use validation schema"); | ||
test.todo("unique constraints are enforced on question where this is set"); | ||
test.todo("optional fields can be empty when saving an item"); | ||
test.todo("an error displays if the minimum number of items is not met"); | ||
test.todo("an error displays if the maximum number of items is exceeded"); | ||
test.todo( | ||
|
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,87 @@ | ||
// Flattens nested object so we can output passport variables like `{listFn}.{itemIndexAsText}.{fieldFn}` | ||
// Adapted from https://gist.github.com/penguinboy/762197 | ||
export function flatten<T extends Record<string, any>>( | ||
object: T, | ||
path: string | null = null, | ||
separator = ".", | ||
): T { | ||
return Object.keys(object).reduce((acc: T, key: string): T => { | ||
const value = object[key]; | ||
|
||
// If the key is a whole number, convert to text before setting newPath | ||
// eg because Calculate/MathJS cannot automate passport variables with number segments | ||
if (/^-?\d+$/.test(key)) { | ||
key = convertNumberToText(parseInt(key) + 1); | ||
} | ||
|
||
const newPath = [path, key].filter(Boolean).join(separator); | ||
|
||
const isObject = [ | ||
typeof value === "object", | ||
value !== null, | ||
!(Array.isArray(value) && value.length === 0), | ||
].every(Boolean); | ||
|
||
return isObject | ||
? { ...acc, ...flatten(value, newPath, separator) } | ||
: { ...acc, [newPath]: value }; | ||
}, {} as T); | ||
} | ||
|
||
// Convert a whole number up to 99 to a spelled-out word (eg 34 => 'thirtyfour') | ||
// Adapted from https://stackoverflow.com/questions/5529934/javascript-numbers-to-words | ||
const ones = [ | ||
"", | ||
"one", | ||
"two", | ||
"three", | ||
"four", | ||
"five", | ||
"six", | ||
"seven", | ||
"eight", | ||
"nine", | ||
]; | ||
const tens = [ | ||
"", | ||
"", | ||
"twenty", | ||
"thirty", | ||
"forty", | ||
"fifty", | ||
"sixty", | ||
"seventy", | ||
"eighty", | ||
"ninety", | ||
]; | ||
const teens = [ | ||
"ten", | ||
"eleven", | ||
"twelve", | ||
"thirteen", | ||
"fourteen", | ||
"fifteen", | ||
"sixteen", | ||
"seventeen", | ||
"eighteen", | ||
"nineteen", | ||
]; | ||
|
||
function convertTens(num: number): string { | ||
if (num < 10) { | ||
return ones[num]; | ||
} else if (num >= 10 && num < 20) { | ||
return teens[num - 10]; | ||
} else { | ||
// format as compound string - eg "thirtyfour" instead of "thirty four" | ||
return tens[Math.floor(num / 10)] + ones[num % 10]; | ||
} | ||
} | ||
|
||
function convertNumberToText(num: number): string { | ||
if (num == 0) { | ||
return "zero"; | ||
} else { | ||
return convertTens(num); | ||
} | ||
} |