Skip to content

Commit

Permalink
Allow more customization of consent form from Python script
Browse files Browse the repository at this point in the history
  • Loading branch information
vloothuis committed Dec 20, 2023
1 parent b5ab47a commit f739b96
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 26 deletions.
47 changes: 41 additions & 6 deletions src/framework/processing/py/port/api/props.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataclasses import dataclass
from typing import TypedDict
from typing import Optional, TypedDict

import pandas as pd

Expand All @@ -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):
Expand All @@ -31,6 +33,7 @@ class PropsUIHeader:
Attributes:
title: title of the page
"""

title: Translatable

def toDict(self):
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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 = []
Expand All @@ -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


Expand All @@ -125,6 +155,7 @@ class PropsUIPromptFileInput:
description: text with an explanation
extensions: accepted mime types, example: "application/zip, text/plain"
"""

description: Translatable
extensions: str

Expand All @@ -143,6 +174,7 @@ class RadioItem(TypedDict):
id: id of radio button
value: text to be displayed
"""

id: int
value: str

Expand All @@ -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]
Expand All @@ -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
Expand All @@ -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"
Expand Down
3 changes: 3 additions & 0 deletions src/framework/types/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
}
Expand Down
25 changes: 5 additions & 20 deletions src/framework/visualisation/react/ui/prompts/consent_form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const ConsentForm = (props: Props): JSX.Element => {
const [waiting, setWaiting] = React.useState<boolean>(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}`])
Expand Down Expand Up @@ -151,13 +151,14 @@ export const ConsentForm = (props: Props): JSX.Element => {

return (
<>
<BodyLarge text={description} />
<BodyLarge text={Translator.translate(props.description ?? description, locale)} />
<div className='flex flex-col gap-8'>
{tablesIn.current.map((table) => renderTable(table))}
<div>
<BodyLarge margin='' text={donateQuestion} />
<BodyLarge margin='' text={Translator.translate(props.donateQuestion ?? donateQuestionLabel, locale)} />
<div className='flex flex-row gap-4 mt-4 mb-4'>
<PrimaryButton label={donateButton} onClick={handleDonate} color='bg-success text-white' spinning={waiting} />
<PrimaryButton label={Translator.translate(props.donateButton ?? donateButtonLabel, locale)}
onClick={handleDonate} color='bg-success text-white' spinning={waiting} />
<LabelButton label={cancelButton} onClick={handleCancel} color='text-grey1' />
</div>
</div>
Expand All @@ -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?')
Expand Down

0 comments on commit f739b96

Please sign in to comment.