Skip to content

Commit

Permalink
Merge pull request #840 from aehrc/issue/833
Browse files Browse the repository at this point in the history
Issue/833
  • Loading branch information
fongsean authored Jun 5, 2024
2 parents 41bf74b + 0304d3e commit e4aa555
Show file tree
Hide file tree
Showing 20 changed files with 196 additions and 104 deletions.
6 changes: 5 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
lib
dist
coverage
build
*.md
*.stories.*
*.stories.*
*.cjs
*.js
*.config.*
2 changes: 1 addition & 1 deletion apps/smart-forms-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"dependencies": {
"@aehrc/sdc-assemble": "^1.2.0",
"@aehrc/sdc-populate": "^2.2.0",
"@aehrc/smart-forms-renderer": "^0.34.0",
"@aehrc/smart-forms-renderer": "^0.34.2",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@fontsource/material-icons": "^5.0.16",
Expand Down
2 changes: 1 addition & 1 deletion documentation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"typecheck": "tsc"
},
"dependencies": {
"@aehrc/smart-forms-renderer": "^0.34.0",
"@aehrc/smart-forms-renderer": "^0.34.2",
"@docusaurus/core": "3.3.2",
"@docusaurus/preset-classic": "3.3.2",
"@docusaurus/theme-live-codeblock": "^3.3.2",
Expand Down
4 changes: 2 additions & 2 deletions documentation/src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
}

/* Custom CSS for code blocks */
code, pre {
code,
pre {
font-size: 0.875em; /* Adjust the font size as needed */
}

6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,9 @@ function createReferenceContextTuple(
referenceContext,
Promise.resolve(
createWarningIssue(
`Reference Context ${referenceContext.part[0]?.valueString ?? ''} does not contain a reference`
`Reference Context ${
referenceContext.part[0]?.valueString ?? ''
} does not contain a reference`
)
),
null
Expand All @@ -259,7 +261,9 @@ function createResourceContextTuple(
resourceContext,
Promise.resolve(
createWarningIssue(
`${resourceContextName} bundle entry ${bundleEntry.fullUrl ?? ''} does not contain a request`
`${resourceContextName} bundle entry ${
bundleEntry.fullUrl ?? ''
} does not contain a request`
)
),
null
Expand Down
2 changes: 1 addition & 1 deletion packages/smart-forms-renderer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aehrc/smart-forms-renderer",
"version": "0.34.0",
"version": "0.34.2",
"description": "FHIR Structured Data Captured (SDC) rendering engine for Smart Forms",
"main": "lib/index.js",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@
*/

import React from 'react';
import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
import type {
QuestionnaireItem,
QuestionnaireItemAnswerOption,
QuestionnaireResponseItem
} from 'fhir/r4';
import { findInAnswerOptions, getChoiceControlType, getQrChoiceValue } from '../../../utils/choice';
import { createEmptyQrItem } from '../../../utils/qrItem';
import type {
Expand Down Expand Up @@ -68,15 +72,25 @@ function ChoiceRadioAnswerOptionItem(props: ChoiceRadioAnswerOptionItemProps) {
});

// Event handlers
function handleChange(newValue: string) {
if (options.length === 0) {
function handleChange(newValue: QuestionnaireItemAnswerOption | string | null) {
// No options present or newValue is type null
if (options.length === 0 || newValue === null) {
onQrItemChange(createEmptyQrItem(qItem));
return;
}

const qrAnswer = findInAnswerOptions(options, newValue);
// newValue is type string
if (typeof newValue === 'string') {
const qrAnswer = findInAnswerOptions(options, newValue);
onQrItemChange(
qrAnswer ? { ...createEmptyQrItem(qItem), answer: [qrAnswer] } : createEmptyQrItem(qItem)
);
return;
}

// newValue is type QuestionnaireItemAnswerOption
onQrItemChange(
qrAnswer ? { ...createEmptyQrItem(qItem), answer: [qrAnswer] } : createEmptyQrItem(qItem)
newValue ? { ...createEmptyQrItem(qItem), answer: [newValue] } : createEmptyQrItem(qItem)
);
}

Expand Down Expand Up @@ -117,7 +131,6 @@ function ChoiceRadioAnswerOptionItem(props: ChoiceRadioAnswerOptionItemProps) {
calcExpUpdated={calcExpUpdated}
onFocusLinkId={() => onFocusLinkId(qItem.linkId)}
onSelectChange={handleChange}
onClear={handleClear}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,71 +16,62 @@
*/

import React, { Fragment } from 'react';
import InputAdornment from '@mui/material/InputAdornment';
import MenuItem from '@mui/material/MenuItem';
import Select from '@mui/material/Select';
import type { QuestionnaireItem, QuestionnaireItemAnswerOption } from 'fhir/r4';
import useRenderingExtensions from '../../../hooks/useRenderingExtensions';
import type { PropsWithIsTabledAttribute } from '../../../interfaces/renderProps.interface';
import { TEXT_FIELD_WIDTH } from '../Textfield.styles';
import { StandardTextField, TEXT_FIELD_WIDTH } from '../Textfield.styles';
import FadingCheckIcon from '../ItemParts/FadingCheckIcon';
import Autocomplete from '@mui/material/Autocomplete';
import { getAnswerOptionLabel } from '../../../utils/openChoice';
import { compareAnswerOptionValue } from '../../../utils/choice';

interface ChoiceSelectAnswerOptionFieldsProps extends PropsWithIsTabledAttribute {
qItem: QuestionnaireItem;
options: QuestionnaireItemAnswerOption[];
valueSelect: string;
valueSelect: QuestionnaireItemAnswerOption | null;
readOnly: boolean;
calcExpUpdated: boolean;
onSelectChange: (newValue: string) => void;
onSelectChange: (newValue: QuestionnaireItemAnswerOption | null) => void;
}

function ChoiceSelectAnswerOptionFields(props: ChoiceSelectAnswerOptionFieldsProps) {
const { qItem, options, valueSelect, readOnly, calcExpUpdated, isTabled, onSelectChange } = props;

const { displayUnit, displayPrompt, entryFormat } = useRenderingExtensions(qItem);

// TODO use calcExpUpdated as updated feedback

return (
<Select
<Autocomplete
id={qItem.id}
name={qItem.text}
value={valueSelect}
disabled={readOnly}
fullWidth
placeholder={entryFormat}
label={displayPrompt}
endAdornment={<InputAdornment position="end">{displayUnit}</InputAdornment>}
sx={{ maxWidth: !isTabled ? TEXT_FIELD_WIDTH : 3000, minWidth: 160 }}
value={valueSelect ?? null}
options={options}
getOptionLabel={(option) => getAnswerOptionLabel(option)}
isOptionEqualToValue={(option, value) => compareAnswerOptionValue(option, value)}
onChange={(_, newValue) => onSelectChange(newValue)}
openOnFocus
autoHighlight
sx={{ maxWidth: !isTabled ? TEXT_FIELD_WIDTH : 3000, minWidth: 160, flexGrow: 1 }}
size="small"
onChange={(e) => onSelectChange(e.target.value)}>
{options.map((option, index) => {
if (option['valueCoding']) {
return (
<MenuItem key={option.valueCoding.code} value={option.valueCoding.code}>
{option.valueCoding.display ?? option.valueCoding.code}
</MenuItem>
);
}

if (option['valueString']) {
return (
<MenuItem key={option.valueString} value={option.valueString}>
{option.valueString}
</MenuItem>
);
}

if (option['valueInteger']) {
return (
<MenuItem key={option.valueInteger} value={option.valueInteger.toString()}>
{option.valueInteger}
</MenuItem>
);
}

return <Fragment key={index} />;
})}
</Select>
disabled={readOnly}
renderInput={(params) => (
<StandardTextField
isTabled={isTabled}
label={displayPrompt}
placeholder={entryFormat}
{...params}
InputProps={{
...params.InputProps,
endAdornment: (
<>
{params.InputProps.endAdornment}
<FadingCheckIcon fadeIn={calcExpUpdated} disabled={readOnly} />
{displayUnit}
</>
)
}}
data-test="q-item-choice-dropdown-answer-value-set-field"
/>
)}
/>
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@

import React from 'react';

import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
import type {
QuestionnaireItem,
QuestionnaireItemAnswerOption,
QuestionnaireResponseItem
} from 'fhir/r4';
import { findInAnswerOptions, getQrChoiceValue } from '../../../utils/choice';
import { createEmptyQrItem } from '../../../utils/qrItem';
import type {
Expand Down Expand Up @@ -66,23 +70,28 @@ function ChoiceSelectAnswerOptionItem(props: ChoiceSelectAnswerOptionItemProps)
}
});

// Event handlers
function handleChange(newValue: string) {
if (options.length === 0) {
function handleChange(newValue: QuestionnaireItemAnswerOption | string | null) {
// No options present or newValue is type null
if (options.length === 0 || newValue === null) {
onQrItemChange(createEmptyQrItem(qItem));
return;
}

const qrAnswer = findInAnswerOptions(options, newValue);
// newValue is type string
if (typeof newValue === 'string') {
const qrAnswer = findInAnswerOptions(options, newValue);
onQrItemChange(
qrAnswer ? { ...createEmptyQrItem(qItem), answer: [qrAnswer] } : createEmptyQrItem(qItem)
);
return;
}

// newValue is type QuestionnaireItemAnswerOption
onQrItemChange(
qrAnswer ? { ...createEmptyQrItem(qItem), answer: [qrAnswer] } : createEmptyQrItem(qItem)
newValue ? { ...createEmptyQrItem(qItem), answer: [newValue] } : createEmptyQrItem(qItem)
);
}

function handleClear() {
onQrItemChange(createEmptyQrItem(qItem));
}

return (
<ChoiceSelectAnswerOptionView
qItem={qItem}
Expand All @@ -94,7 +103,6 @@ function ChoiceSelectAnswerOptionItem(props: ChoiceSelectAnswerOptionItemProps)
isTabled={isTabled}
onFocusLinkId={() => onFocusLinkId(qItem.linkId)}
onSelectChange={handleChange}
onClear={handleClear}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
* limitations under the License.
*/

import React from 'react';
import React, { useMemo } from 'react';
import { FullWidthFormComponentBox } from '../../Box.styles';
import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
import type {
PropsWithIsRepeatedAttribute,
PropsWithIsTabledAttribute
} from '../../../interfaces/renderProps.interface';
import type { QuestionnaireItem, QuestionnaireItemAnswerOption } from 'fhir/r4';
import { findInAnswerOptions } from '../../../utils/choice';
import ChoiceSelectAnswerOptionFields from './ChoiceSelectAnswerOptionFields';

interface ChoiceSelectAnswerOptionViewProps
Expand All @@ -33,9 +34,8 @@ interface ChoiceSelectAnswerOptionViewProps
valueChoice: string | null;
readOnly: boolean;
calcExpUpdated: boolean;
onSelectChange: (linkId: string) => void;
onSelectChange: (newValue: QuestionnaireItemAnswerOption | null) => void;
onFocusLinkId: () => void;
onClear: () => void;
}

function ChoiceSelectAnswerOptionView(props: ChoiceSelectAnswerOptionViewProps) {
Expand All @@ -48,16 +48,20 @@ function ChoiceSelectAnswerOptionView(props: ChoiceSelectAnswerOptionViewProps)
readOnly,
calcExpUpdated,
onFocusLinkId,
onSelectChange,
onClear
onSelectChange
} = props;

const valueSelect: QuestionnaireItemAnswerOption | null = useMemo(
() => findInAnswerOptions(options, valueChoice ?? '') ?? null,
[options, valueChoice]
);

if (isRepeated) {
return (
<ChoiceSelectAnswerOptionFields
qItem={qItem}
options={options}
valueSelect={valueChoice ?? ''}
valueSelect={valueSelect}
readOnly={readOnly}
calcExpUpdated={calcExpUpdated}
isTabled={isTabled}
Expand All @@ -75,7 +79,7 @@ function ChoiceSelectAnswerOptionView(props: ChoiceSelectAnswerOptionViewProps)
<ChoiceSelectAnswerOptionFields
qItem={qItem}
options={options}
valueSelect={valueChoice ?? ''}
valueSelect={valueSelect}
readOnly={readOnly}
calcExpUpdated={calcExpUpdated}
isTabled={isTabled}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ function GroupItemSwitcher(props: GroupItemSwitcherProps) {
<GridGroup
qItem={qItem}
qrItem={qrItem ?? null}
groupCardElevation={groupCardElevation + 1}
groupCardElevation={groupCardElevation}
parentIsReadOnly={parentIsReadOnly}
onQrItemChange={onQrItemChange}
/>
Expand Down
Loading

0 comments on commit e4aa555

Please sign in to comment.