Skip to content

Commit

Permalink
Add placeholder transform unit and percentage definitions (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
petechd authored Jun 17, 2022
1 parent d86ac99 commit 3849374
Show file tree
Hide file tree
Showing 10 changed files with 644 additions and 9 deletions.
2 changes: 2 additions & 0 deletions app/error_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"The referenced answer cannot be used to set the minimum of answer"
)
ANSWER_TYPE_FOR_OPTION_LABEL_FROM_VALUE_INVALID = "The answer type for option label from value is not of type ['Radio','Checkbox','Dropdown']"
ANSWER_TYPE_FOR_TRANSFORM_TYPE_INVALID = "Expected the answer type for '{transform}' transform to be type '{expected_type}' but got type '{answer_type}'"
ANSWER_UNIT_AND_TRANSFORM_UNIT_MISMATCH = "The answer unit and transform unit mismatch, '{answer_unit}' not '{transform_unit}'"
ANSWER_REFERENCE_CANNOT_BE_USED_ON_MAX = (
"The referenced answer cannot be used to set the maximum of answer"
)
Expand Down
82 changes: 73 additions & 9 deletions app/validators/placeholders/placeholder_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def validate_option_label_from_value_placeholder(self, answer_id):

# if answer id doesn't exist, no further validation is done
if not answer_id_exists:
return
return None

if not any(
x.value == answers[answer_id]["answer"]["type"] for x in AnswerOptionType
Expand All @@ -108,7 +108,61 @@ def validate_option_label_from_value_placeholder(self, answer_id):
identifier=answer_id,
)

def validate_placeholder_transforms(self, transforms):
def validate_answer_type_for_transform(
self, argument, argument_name, transform_type
):
if not (
transform_type in ["format_unit", "format_percentage"]
and argument_name == "value"
and argument.get("value", {}).get("source") == "answers"
):
return None

answer_id = argument["value"]["identifier"]
answer_type = self.questionnaire_schema.answers_with_context[answer_id][
"answer"
]["type"]

if answer_type.lower() in transform_type:
return None

expected_type = transform_type.split("_")[1].title()
self.add_error(
error_messages.ANSWER_TYPE_FOR_TRANSFORM_TYPE_INVALID.format(
transform=transform_type,
expected_type=expected_type,
answer_type=answer_type,
),
identifier=answer_id,
)

def validate_answer_and_transform_unit_match(self, *, arguments, transform_type):
if transform_type != "format_unit":
return None

value = arguments["value"]
answer_id = value.get("identifier")
unit = arguments["unit"]

if self.errors or (
unit
== self.questionnaire_schema.answers_with_context[answer_id]["answer"][
"unit"
]
):
return None

self.add_error(
error_messages.ANSWER_UNIT_AND_TRANSFORM_UNIT_MISMATCH.format(
answer_unit=self.questionnaire_schema.answers_with_context[answer_id][
"answer"
]["unit"],
transform_unit=unit,
),
identifier=answer_id,
)

def _validate_placeholder_previous_transforms(self, transforms):
# First transform can't reference a previous transform
first_transform = transforms[0]
for argument_name in first_transform.get("arguments"):
Expand All @@ -118,11 +172,6 @@ def validate_placeholder_transforms(self, transforms):
and argument.get("source") == "previous_transform"
):
self.add_error(self.FIRST_TRANSFORM_CONTAINS_PREVIOUS_TRANSFORM_REF)
if (
first_transform["transform"] == "option_label_from_value"
and argument_name == "answer_id"
):
self.validate_option_label_from_value_placeholder(argument)

# Previous transform must be referenced in all subsequent transforms
for transform in transforms[1:]:
Expand All @@ -135,11 +184,26 @@ def validate_placeholder_transforms(self, transforms):
):
previous_transform_used = True

if not previous_transform_used:
self.add_error(self.NO_PREVIOUS_TRANSFORM_REF_IN_CHAIN)

def validate_placeholder_transforms(self, transforms):
self._validate_placeholder_previous_transforms(transforms)

for transform in transforms:
for argument_name in transform.get("arguments"):
argument = transform["arguments"][argument_name]
if (
transform["transform"] == "option_label_from_value"
and argument_name == "answer_id"
):
self.validate_option_label_from_value_placeholder(argument)

if not previous_transform_used:
self.add_error(self.NO_PREVIOUS_TRANSFORM_REF_IN_CHAIN)
self.validate_answer_type_for_transform(
transform.get("arguments"), argument_name, transform["transform"]
)

self.validate_answer_and_transform_unit_match(
arguments=transform.get("arguments"),
transform_type=transform["transform"],
)
6 changes: 6 additions & 0 deletions schemas/string_interpolation/definitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@
{
"$ref": "https://eq.ons.gov.uk/string_interpolation/transforms/format_number.json#/format_number"
},
{
"$ref": "https://eq.ons.gov.uk/string_interpolation/transforms/format_percentage.json#/format_percentage"
},
{
"$ref": "https://eq.ons.gov.uk/string_interpolation/transforms/format_unit.json#/format_unit"
},
{
"$ref": "https://eq.ons.gov.uk/string_interpolation/transforms/format_currency.json#/format_currency"
},
Expand Down
25 changes: 25 additions & 0 deletions schemas/string_interpolation/transforms/format_percentage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$id": "https://eq.ons.gov.uk/string_interpolation/transforms/format_percentage.json",
"$schema": "http://json-schema.org/draft-07/schema",
"format_percentage": {
"type": "object",
"properties": {
"transform": {
"type": "string",
"enum": ["format_percentage"]
},
"arguments": {
"type": "object",
"properties": {
"value": {
"$ref": "https://eq.ons.gov.uk/string_interpolation/definitions.json#/placeholder_value_sources"
}
},
"additionalProperties": false,
"required": ["value"]
}
},
"additionalProperties": false,
"required": ["transform", "arguments"]
}
}
34 changes: 34 additions & 0 deletions schemas/string_interpolation/transforms/format_unit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"$id": "https://eq.ons.gov.uk/string_interpolation/transforms/format_unit.json",
"$schema": "http://json-schema.org/draft-07/schema",
"format_unit": {
"type": "object",
"properties": {
"transform": {
"type": "string",
"enum": ["format_unit"]
},
"arguments": {
"type": "object",
"properties": {
"value": {
"$ref": "https://eq.ons.gov.uk/string_interpolation/definitions.json#/placeholder_value_sources"
},
"unit_length": {
"description": "The formatting length. e.g. 1h (narrow) / 1 hr (short) / 1 hour (long)",
"default": "short",
"type": "string",
"enum": ["short", "narrow", "long"]
},
"unit": {
"$ref": "https://eq.ons.gov.uk/lists/units.json#/unit"
}
},
"additionalProperties": false,
"required": ["value", "unit"]
}
},
"additionalProperties": false,
"required": ["transform", "arguments"]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
{
"mime_type": "application/json/ons/eq",
"language": "en",
"schema_version": "0.0.1",
"data_version": "0.0.3",
"survey_id": "0",
"title": "Placeholder Test",
"theme": "default",
"description": "A questionnaire to test placeholders",
"navigation": {
"visible": true
},
"metadata": [
{
"name": "user_id",
"type": "string"
},
{
"name": "period_id",
"type": "string"
},
{
"name": "ru_name",
"type": "string"
},
{
"name": "trad_as",
"type": "string",
"optional": true
}
],
"questionnaire_flow": {
"type": "Linear",
"options": {
"summary": {
"collapsible": false
}
}
},
"sections": [
{
"id": "percentage-section",
"title": "Percentage Input",
"groups": [
{
"id": "[percentage-group",
"blocks": [
{
"type": "Question",
"id": "average-distance-block",
"question": {
"answers": [
{
"id": "average-distance",
"mandatory": false,
"unit": "mile",
"type": "Unit",
"unit_length": "long",
"label": "Average commuting distance",
"default": 0
}
],
"id": "average-distance-question",
"title": "What is the average commuting distance of an employee (in miles) ?",
"type": "General"
}
},
{
"id": "average-distance-interstitial",
"content": {
"title": "Average commuting distance interstitial",
"contents": [
{
"description": {
"text": "The average commuting distance of an employee is <em>{answer_distance}</em>",
"placeholders": [
{
"placeholder": "answer_distance",
"transforms": [
{
"transform": "format_unit",
"arguments": {
"value": {
"source": "answers",
"identifier": "average-distance"
},
"unit": "meter",
"unit_length": "long"
}
}
]
}
]
}
}
]
},
"type": "Interstitial"
}
]
}
]
}
]
}
Loading

0 comments on commit 3849374

Please sign in to comment.