From f739b969103fad354fadbf726f1da124715e3ffd Mon Sep 17 00:00:00 2001 From: Jeroen Date: Wed, 20 Dec 2023 21:08:10 +0100 Subject: [PATCH] Allow more customization of consent form from Python script --- src/framework/processing/py/port/api/props.py | 47 ++++++++++++++++--- src/framework/types/prompts.ts | 3 ++ .../react/ui/prompts/consent_form.tsx | 25 ++-------- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/framework/processing/py/port/api/props.py b/src/framework/processing/py/port/api/props.py index b1644bee..435c31c3 100644 --- a/src/framework/processing/py/port/api/props.py +++ b/src/framework/processing/py/port/api/props.py @@ -1,5 +1,5 @@ from dataclasses import dataclass -from typing import TypedDict +from typing import Optional, TypedDict import pandas as pd @@ -11,13 +11,15 @@ class Translations(TypedDict): en: English string to display nl: Dutch string to display """ + en: str nl: str @dataclass class Translatable: - """Wrapper class for Translations""" + """Wrapper class for Translations""" + translations: Translations def toDict(self): @@ -31,6 +33,7 @@ class PropsUIHeader: Attributes: title: title of the page """ + title: Translatable def toDict(self): @@ -40,18 +43,36 @@ def toDict(self): return dict +@dataclass +class PropsUIFooter: + """Page footer + + Attributes: + progressPercentage: float indicating the progress in the flow + """ + + progressPercentage: float + + def toDict(self): + dict = {} + dict["__type__"] = "PropsUIFooter" + dict["progressPercentage"] = self.progressPercentage + return dict + + @dataclass class PropsUIPromptConfirm: """Retry submitting a file page - Prompt the user if they want to submit a new file. - This can be used in case a file could not be processed. + Prompt the user if they want to submit a new file. + This can be used in case a file could not be processed. Attributes: text: message to display ok: message to display if the user wants to try again cancel: message to display if the user wants to continue regardless """ + text: Translatable ok: Translatable cancel: Translatable @@ -67,13 +88,14 @@ def toDict(self): @dataclass class PropsUIPromptConsentFormTable: - """Table to be shown to the participant prior to donation + """Table to be shown to the participant prior to donation Attributes: id: a unique string to itentify the table after donation title: title of the table data_frame: table to be shown """ + id: str title: Translatable data_frame: pd.DataFrame @@ -86,16 +108,21 @@ def toDict(self): dict["data_frame"] = self.data_frame.to_json() return dict + @dataclass class PropsUIPromptConsentForm: - """Tables to be shown to the participant prior to donation + """Tables to be shown to the participant prior to donation Attributes: tables: a list of tables meta_tables: a list of optional tables, for example for logging data """ + tables: list[PropsUIPromptConsentFormTable] meta_tables: list[PropsUIPromptConsentFormTable] + description: Optional[Translatable] = None + donate_question: Optional[Translatable] = None + donate_button: Optional[Translatable] = None def translate_tables(self): output = [] @@ -114,6 +141,9 @@ def toDict(self): dict["__type__"] = "PropsUIPromptConsentForm" dict["tables"] = self.translate_tables() dict["metaTables"] = self.translate_meta_tables() + dict["description"] = self.description and self.description.toDict() + dict["donateQuestion"] = self.donate_question and self.donate_question.toDict() + dict["donateButton"] = self.donate_button and self.donate_button.toDict() return dict @@ -125,6 +155,7 @@ class PropsUIPromptFileInput: description: text with an explanation extensions: accepted mime types, example: "application/zip, text/plain" """ + description: Translatable extensions: str @@ -143,6 +174,7 @@ class RadioItem(TypedDict): id: id of radio button value: text to be displayed """ + id: int value: str @@ -158,6 +190,7 @@ class PropsUIPromptRadioInput: description: short description of the radio group items: a list of radio buttons """ + title: Translatable description: Translatable items: list[RadioItem] @@ -180,6 +213,7 @@ class PropsUIPageDonation: header: page header body: main body of the page, see the individual classes for an explanation """ + platform: str header: PropsUIHeader body: PropsUIPromptRadioInput | PropsUIPromptConsentForm | PropsUIPromptFileInput | PropsUIPromptConfirm @@ -195,6 +229,7 @@ def toDict(self): class PropsUIPageEnd: """An ending page to show the user they are done""" + def toDict(self): dict = {} dict["__type__"] = "PropsUIPageEnd" diff --git a/src/framework/types/prompts.ts b/src/framework/types/prompts.ts index fc6cd0cb..d730da42 100644 --- a/src/framework/types/prompts.ts +++ b/src/framework/types/prompts.ts @@ -43,6 +43,9 @@ export function isPropsUIPromptRadioInput (arg: any): arg is PropsUIPromptRadioI } export interface PropsUIPromptConsentForm { __type__: 'PropsUIPromptConsentForm' + description?: Text + donateQuestion?: Text + donateButton?: Text tables: PropsUIPromptConsentFormTable[] metaTables: PropsUIPromptConsentFormTable[] } diff --git a/src/framework/visualisation/react/ui/prompts/consent_form.tsx b/src/framework/visualisation/react/ui/prompts/consent_form.tsx index 5e1da87e..03d98354 100644 --- a/src/framework/visualisation/react/ui/prompts/consent_form.tsx +++ b/src/framework/visualisation/react/ui/prompts/consent_form.tsx @@ -24,7 +24,7 @@ export const ConsentForm = (props: Props): JSX.Element => { const [waiting, setWaiting] = React.useState(false) const { locale, resolve } = props - const { description, donateQuestion, donateButton, cancelButton } = prepareCopy(props) + const cancelButton = Translator.translate(cancelButtonLabel, props.locale) function rowCell (dataFrame: any, column: string, row: number): PropsUITableCell { const text = String(dataFrame[column][`${row}`]) @@ -151,13 +151,14 @@ export const ConsentForm = (props: Props): JSX.Element => { return ( <> - +
{tablesIn.current.map((table) => renderTable(table))}
- +
- +
@@ -166,22 +167,6 @@ export const ConsentForm = (props: Props): JSX.Element => { ) } -interface Copy { - description: string - donateQuestion: string - donateButton: string - cancelButton: string -} - -function prepareCopy ({ locale }: Props): Copy { - return { - description: Translator.translate(description, locale), - donateQuestion: Translator.translate(donateQuestionLabel, locale), - donateButton: Translator.translate(donateButtonLabel, locale), - cancelButton: Translator.translate(cancelButtonLabel, locale) - } -} - const donateQuestionLabel = new TextBundle() .add('en', 'Do you want to donate the above data?') .add('nl', 'Wilt u de bovenstaande gegevens doneren?')