-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#81 (1) JsonForms skeleton #148
Changes from 16 commits
6f10d4e
fcf3235
9f08a99
4f1589b
da17e98
a591fa3
05ca3dd
ef2a1c5
321321b
1bc7b7d
193c4ea
2e87ff5
88f376a
5a4d2b1
6e2db90
d1c8ac4
88dfe68
3493e00
66b9a2b
d2fbe0d
6d870ec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ interface ButtonProps { | |
label: string; | ||
width?: string; | ||
height?: string; | ||
color?: 'primary' | 'secondary' | undefined; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You'll notice this isn't used in this PR -- I'm using it for the Arrays to create the "Add item" button -- in next PR |
||
sx?: SxProps; | ||
} | ||
|
||
|
@@ -18,6 +19,7 @@ export const IconButton: React.FC<ButtonProps> = ({ | |
label, | ||
width, | ||
height, | ||
color, | ||
sx, | ||
}) => ( | ||
<Tooltip title={disabled ? '' : label}> | ||
|
@@ -27,6 +29,7 @@ export const IconButton: React.FC<ButtonProps> = ({ | |
onClick={onClick} | ||
aria-label={label} | ||
size="small" | ||
color={color} | ||
> | ||
{icon} | ||
</MuiIconButton> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import React from 'react'; | ||
import { rankWith, ControlProps, isDateControl } from '@jsonforms/core'; | ||
import { withJsonFormsControlProps } from '@jsonforms/react'; | ||
import { FormLabel, Box } from '@mui/material'; | ||
import { BaseDatePickerInput } from '@openmsupply-client/common'; | ||
|
||
export const dateTester = rankWith(5, isDateControl); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as a new user to this - what is a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tester -- function that returns a number based on whether or not a predicate is true (In this case it will return 5 if
I thought since we're generally going to have testers coupled to components in a one-to-one manner, it made sense to keep each tester with its associated component. I did make a more generic tester for matching custom fields (in uiSchema) to components, but it wasn't being used in here. I might include it in a later PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh, right. thanks - wasn't clear to me from the name alone! |
||
|
||
const UIComponent = (props: ControlProps) => { | ||
const { data, handleChange, label, path } = props; | ||
|
||
return ( | ||
<Box | ||
display="flex" | ||
alignItems="center" | ||
gap={2} | ||
justifyContent="space-around" | ||
style={{ minWidth: 300 }} | ||
marginTop={1} | ||
> | ||
<Box flex={1} style={{ textAlign: 'end' }} flexBasis="40%"> | ||
<FormLabel sx={{ fontWeight: 'bold' }}>{label}:</FormLabel> | ||
</Box> | ||
<Box flex={1} flexBasis="60%"> | ||
<BaseDatePickerInput | ||
value={data} | ||
onChange={e => handleChange(path, e)} | ||
inputFormat="dd/MM/yyyy" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The hard-coded format : can it be intl based? can it be configurable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is actually just copied straight from So yeah, we should localise them both at some point. |
||
/> | ||
</Box> | ||
</Box> | ||
); | ||
}; | ||
|
||
export const Date = withJsonFormsControlProps(UIComponent); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import React from 'react'; | ||
import { rankWith, uiTypeIs, LayoutProps, GroupLayout } from '@jsonforms/core'; | ||
import { withJsonFormsLayoutProps } from '@jsonforms/react'; | ||
import { MaterialLayoutRenderer } from '@jsonforms/material-renderers'; | ||
import { Box, Typography } from '@mui/material'; | ||
|
||
export const groupTester = rankWith(4, uiTypeIs('Group')); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, these things aren't making sense. what is |
||
|
||
const UIComponent = (props: LayoutProps) => { | ||
const { uischema, schema, visible, renderers, path } = props; | ||
|
||
const layoutProps = { | ||
elements: (uischema as GroupLayout).elements, | ||
schema: schema, | ||
path: path, | ||
direction: 'column' as 'column' | 'row', | ||
visible: visible, | ||
uischema: uischema, | ||
renderers: renderers, | ||
}; | ||
return ( | ||
<Box | ||
sx={{ | ||
maxWidth: 500, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the maxWidth is fairly specific, just wondering if that will cause problems later. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've moved these values into a "styleConstants" file so we can update them easily if we need to. Also -- if we need a wider "Group" in future, we can always make "width" a new property in uiSchema which the component can use, or have an alternative component "WideGroup". (for one that spans 2 columns, perhaps?) |
||
paddingLeft: 2, | ||
paddingRight: 2, | ||
marginBottom: 2, | ||
}} | ||
> | ||
<Typography width="40%" fontSize="1.2em" textAlign="right"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we may have to use ems throughout 🤔 Could the font size here come from the theme? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, have re-styled the "subtitle" variant in theme with this fontSize -- didn't look like it was being used elsewhere. Would like to organise the typography a bit better overall at some point: msupply-foundation/openmsupply-client#1149 |
||
<strong>{(uischema as GroupLayout).label}</strong> | ||
</Typography> | ||
<MaterialLayoutRenderer {...layoutProps} /> | ||
</Box> | ||
); | ||
}; | ||
|
||
export const Group = withJsonFormsLayoutProps(UIComponent); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import React from 'react'; | ||
import { | ||
LayoutProps, | ||
rankWith, | ||
UISchemaElement, | ||
uiTypeIs, | ||
} from '@jsonforms/core'; | ||
import { withJsonFormsLayoutProps } from '@jsonforms/react'; | ||
import { SxProps, Typography } from '@mui/material'; | ||
import { RegexUtils } from '@common/utils'; | ||
|
||
export const labelTester = rankWith(3, uiTypeIs('Label')); | ||
|
||
type LabelVariant = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p'; | ||
|
||
type LayoutPropsExtended = LayoutProps & { | ||
uischema: UISchemaElement & { | ||
sx?: SxProps; | ||
text?: string; | ||
variant?: LabelVariant; | ||
}; | ||
}; | ||
|
||
const variants: { [key in LabelVariant]: SxProps } = { | ||
h1: { fontSize: '1.8em', fontWeight: 'bold', textAlign: 'center' }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wider discussion: these should really come from the theme There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I'd like to standardise h1, h2, etc, but I don't want to go overwriting theme values for those just yet as it'll probably have significant flow-on effects. To do though: msupply-foundation/openmsupply-client#1149 |
||
h2: { fontSize: '1.4em', fontWeight: 'bold', textAlign: 'center' }, | ||
h3: { | ||
fontWeight: 'bold', | ||
textAlign: 'right', | ||
width: '40%', | ||
height: '1.5em', // This shouldn't be necessary 🤷♂️ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove then? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It shouldn't be necessary -- but it is. That's that weird quirk I showed you the other day where changing the % width affected the height for no apparent reason. |
||
marginTop: '1em', | ||
}, | ||
h4: {}, | ||
h5: {}, | ||
h6: {}, | ||
p: {}, | ||
}; | ||
|
||
const UIComponent = (props: LayoutPropsExtended) => { | ||
const { | ||
uischema: { variant = 'p', sx, text }, | ||
data, | ||
} = props; | ||
const variantStyles = variants[variant]; | ||
return ( | ||
<Typography sx={{ ...variantStyles, ...sx } as SxProps}> | ||
{RegexUtils.stringSubstitution(text ?? '', data)} | ||
</Typography> | ||
CarlosNZ marked this conversation as resolved.
Show resolved
Hide resolved
|
||
); | ||
}; | ||
|
||
export const Label = withJsonFormsLayoutProps(UIComponent); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import React from 'react'; | ||
import { rankWith, isEnumControl, ControlProps } from '@jsonforms/core'; | ||
import { withJsonFormsControlProps } from '@jsonforms/react'; | ||
import { FormLabel, Box } from '@mui/material'; | ||
import { Select } from '@openmsupply-client/common'; | ||
|
||
export const selectTester = rankWith(4, isEnumControl); | ||
|
||
const UIComponent = (props: ControlProps) => { | ||
const { data, handleChange, label, schema, path } = props; | ||
|
||
const options = schema.enum | ||
? schema.enum.map((option: string) => ({ | ||
label: option, | ||
value: option, | ||
})) | ||
: []; | ||
|
||
return ( | ||
<Box | ||
display="flex" | ||
alignItems="center" | ||
gap={2} | ||
justifyContent="space-around" | ||
style={{ minWidth: 300 }} | ||
marginTop={0.5} | ||
> | ||
<Box flex={1} style={{ textAlign: 'end' }} flexBasis="40%"> | ||
<FormLabel sx={{ fontWeight: 'bold' }}>{label}:</FormLabel> | ||
</Box> | ||
<Box flex={1} flexBasis="60%"> | ||
<Select | ||
sx={{ minWidth: 100 }} | ||
options={options} | ||
value={data} | ||
onChange={e => handleChange(path, e.target.value)} | ||
/> | ||
</Box> | ||
</Box> | ||
); | ||
}; | ||
|
||
export const Selector = withJsonFormsControlProps(UIComponent); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export * from './Group'; | ||
export * from './Label'; | ||
export * from './Text'; | ||
export * from './Select'; | ||
export * from './Date'; | ||
// export * from './Array'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import React from 'react'; | ||
import { ControlProps, rankWith, schemaTypeIs } from '@jsonforms/core'; | ||
import { withJsonFormsControlProps } from '@jsonforms/react'; | ||
import { DetailInputWithLabelRow } from '@openmsupply-client/common'; | ||
|
||
export const stringTester = rankWith(3, schemaTypeIs('string')); | ||
|
||
const UIComponent = (props: ControlProps) => { | ||
const { data, handleChange, label, path } = props; | ||
return ( | ||
<DetailInputWithLabelRow | ||
label={label} | ||
inputProps={{ | ||
value: data, | ||
sx: { margin: 0.5, width: '100%' }, | ||
disabled: false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isn't this the default value for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes -- I think I put that in there as a reminder that I needed to update it with a dynamic value based on whether it's editable or now. I'll remove for now. |
||
onChange: e => handleChange(path, e.target.value), | ||
}} | ||
/> | ||
); | ||
}; | ||
|
||
export const TextField = withJsonFormsControlProps(UIComponent); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './useJsonForms'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
{ | ||
"Patient": { | ||
"id": "123", | ||
"gender": "Male", | ||
"firstName": "Carl", | ||
"lastName": "Smith", | ||
"healthCenter": { | ||
"id": "999", | ||
"name": "My Health Center" | ||
}, | ||
"addresses": [ | ||
{ | ||
"key": "primary", | ||
"address1": "111 Address Street", | ||
"address2": "Auckland", | ||
"country": "NZ" | ||
}, | ||
{ | ||
"key": "secondary", | ||
"address1": "222 Address", | ||
"address2": "address2", | ||
"country": "NZ" | ||
} | ||
], | ||
"contactDetails": [ | ||
{ | ||
"key": "primary", | ||
"address1": "111 Contact Street", | ||
"address2": "Auckland", | ||
"country": "NZ" | ||
}, | ||
{ | ||
"key": "secondary", | ||
"address1": "222 Contact", | ||
"mobile": "+023456", | ||
"email": "email", | ||
"website": "website" | ||
} | ||
], | ||
"socioEconomics": { | ||
"education": "education", | ||
"occupation": "occupation", | ||
"literate": "literate" | ||
}, | ||
"testingArray": [{ "field1": "ONE", "field2": "TWO" }], | ||
"family": { | ||
"maritalStatus": "single", | ||
"nextOfKin": { | ||
"id": "nextOfKinId", | ||
"firstName": "namekin", | ||
"lastName": "lastNameKin", | ||
"addresses": [], | ||
"contactDetails": [ | ||
{ | ||
"key": "primary", | ||
"address1": "NOK contact", | ||
"address2": "Auckland", | ||
"country": "New Zealand" | ||
} | ||
], | ||
"socioEconomics": {} | ||
}, | ||
"caregiver": { | ||
"id": "cargiverId", | ||
"firstName": "caregiver", | ||
"lastName": "caregiverLastName", | ||
"addresses": [], | ||
"contactDetails": [], | ||
"socioEconomics": {} | ||
}, | ||
"mother": { | ||
"id": "motherId", | ||
"firstName": "Jenny", | ||
"lastName": "Shaw", | ||
"addresses": [], | ||
"contactDetails": [], | ||
"socioEconomics": {} | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need the icons, I'll try and remove in next PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please! the icons packages is huge and we have deliberately created only the icons we need in order to avoid it