Skip to content

Commit

Permalink
Merge pull request #5 from pughlab/drafts-bugfixes
Browse files Browse the repository at this point in the history
Drafts are now autosaved only if a valid patient ID has been input. D…
  • Loading branch information
suluxan authored Feb 8, 2024
2 parents 58912db + 22b9685 commit ab015e8
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 11 deletions.
28 changes: 26 additions & 2 deletions ui/src/components/form/FormGenerator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,23 @@ function transformData(data: any, re: RegExp) {
})
}

function formatDraftDate(date: Date) {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
const ampm = date.toLocaleString('en-US', { timeZoneName: 'short' }).split(' ')[2]
const timeZone = date.toLocaleString('en-US', { timeZoneName: 'short' }).split(' ')[3]

return `${year}-${month}-${day} ${hours}:${minutes}:${seconds} ${ampm} ${timeZone}`
}

export function FormGenerator({ formMetadata, root }) {

// State and context variables
const [lastDraftUpdate, setLastDraftUpdate] = useState("")
const [lastSubmissionUpdate, setLastSubmissionUpdate] = useState(`Submissions-${new Date().toUTCString()}`)
const [draftModified, setDraftModified] = useState(false)

Expand Down Expand Up @@ -339,10 +353,12 @@ export function FormGenerator({ formMetadata, root }) {
// sets the interval for saving drafts
useEffect(() => {
const seconds = 10 // save the drafts every ten seconds (10 * 1000 milliseconds)
const draftSaveInterval = draftModified
const validPatient = !!patientIdentifier.submitter_donor_id && !!patientIdentifier.program_id
const draftSaveInterval = draftModified && validPatient
? setInterval(() => {
saveDraft()
setDraftModified(false)
setLastDraftUpdate(formatDraftDate(new Date()))
}, seconds * 1000)
: null

Expand Down Expand Up @@ -407,6 +423,7 @@ export function FormGenerator({ formMetadata, root }) {
onCompleted: () => {
setDraftModified(false)
updateDraftID(null)
setLastDraftUpdate("")
}
})

Expand Down Expand Up @@ -517,6 +534,7 @@ export function FormGenerator({ formMetadata, root }) {
// final render
return (
<div key={formMetadata.form_name} style={{ paddingLeft: "60px", paddingRight: "60px" }}>
{ lastDraftUpdate !== "" ? <><span style={{float: 'right'}}>Last autosaved at: {lastDraftUpdate}</span><br/></> : <></> }
<Form
size="small"
onSubmit={(event) => {
Expand Down Expand Up @@ -552,7 +570,7 @@ export function FormGenerator({ formMetadata, root }) {
}
</Form.Group>
<SubmissionTable
key={`Submissions-${lastSubmissionUpdate.toUTCString()}`}
key={`Submissions-${lastSubmissionUpdate}`}
formID={formMetadata.form_id}
formIDKeys={renderedFormIDFields.map((field) => field.name)}
headers={tableHeaders}
Expand All @@ -566,6 +584,7 @@ export function FormGenerator({ formMetadata, root }) {
const isDisabled = field.conditionals === null
? false
: doesFieldNotMeetAllConditions(field.conditionals, state.fields)
const isReadonly = field.readonly ?? false
const errorMessage = isDisabled ? null : state.errorMessages[field.name]

switch (String(field.component).toLowerCase()) {
Expand All @@ -578,6 +597,7 @@ export function FormGenerator({ formMetadata, root }) {
label={labels[field.name]}
value={state.fields[field.name]}
isDisabled={isDisabled}
isReadonly={isReadonly}
errorMessage={errorMessage}
validator={state.validators[field.name]}
updateErrorMessage={updateErrorMessages}
Expand All @@ -591,6 +611,7 @@ export function FormGenerator({ formMetadata, root }) {
label={labels[field.name]}
value={state.fields[field.name]}
isDisabled={isDisabled}
isReadonly={isReadonly}
validator={state.validators[field.name]}
errorMessage={errorMessage}
updateErrorMessage={updateErrorMessages}
Expand All @@ -604,6 +625,7 @@ export function FormGenerator({ formMetadata, root }) {
label={labels[field.name]}
value={state.fields[field.name]}
isDisabled={isDisabled}
isReadonly={isReadonly}
validator={state.validators[field.name]}
errorMessage={errorMessage}
updateErrorMessage={updateErrorMessages}
Expand All @@ -621,6 +643,7 @@ export function FormGenerator({ formMetadata, root }) {
study={patientIdentifier.study}
label={labels[field.name]}
isDisabled={isDisabled}
isReadonly={isReadonly}
errorMessage={errorMessage}
options={state.options[field.name]}
validator={state.validators[field.name]}
Expand All @@ -635,6 +658,7 @@ export function FormGenerator({ formMetadata, root }) {
study={patientIdentifier.study}
label={labels[field.name]}
isDisabled={isDisabled}
isReadonly={isReadonly}
errorMessage={errorMessage}
options={state.options[field.name]}
validator={state.validators[field.name]}
Expand Down
6 changes: 4 additions & 2 deletions ui/src/components/form/fields/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "react-datepicker/dist/react-datepicker.css"
import { fieldIsRequired } from "../utils"


export function DateInputField({ field, study, label, value, comparingDate = null, isDisabled, errorMessage, validator, updateErrorMessage, updateValue }) {
export function DateInputField({ field, study, label, value, comparingDate = null, isDisabled, isReadonly, errorMessage, validator, updateErrorMessage, updateValue }) {
// calculate time difference in years between the current value and a given date
const otherDate = comparingDate ?? new Date()
const difference = dayjs(otherDate).diff(dayjs(value), 'years')
Expand Down Expand Up @@ -56,12 +56,13 @@ export function DateInputField({ field, study, label, value, comparingDate = nul
showMonthYearPicker
showFullMonthYearPicker
showFourColumnMonthYearPicker
readOnly={isReadonly}
/>
</Form.Field>
)
}

export function InputField({ field, study, label, value, isDisabled, errorMessage, validator, updateErrorMessage, updateValue }) {
export function InputField({ field, study, label, value, isDisabled, isReadonly, errorMessage, validator, updateErrorMessage, updateValue }) {
return (
<Form.Field disabled={isDisabled} error={errorMessage !== null}>
<div>
Expand All @@ -83,6 +84,7 @@ export function InputField({ field, study, label, value, isDisabled, errorMessag
name={field.name}
value={value ?? ''}
type={field.type}
readOnly={isReadonly}
placeholder={field.placeholder}
onChange={(e) => {
let newValue = ["number", "integer"].includes(field.type.toLowerCase())
Expand Down
10 changes: 5 additions & 5 deletions ui/src/components/form/fields/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { Form, Icon, Popup } from "semantic-ui-react";
import * as R from "remeda";
import { constructDropdown, fieldIsRequired } from '../utils'

export function SmallSelectField({ field, study, label, isDisabled, errorMessage, options, validator, value, updateErrorMessage, updateValue }) {
export function SmallSelectField({ field, study, label, isDisabled, isReadonly, errorMessage, options, validator, value, updateErrorMessage, updateValue }) {
const processedOptions = constructDropdown(options)
return (
<Form.Field disabled={isDisabled} error={errorMessage !== null}>
<Form.Field disabled={isDisabled} readOnly={isReadonly} error={errorMessage !== null}>
<div>
<Popup
trigger={<span style={fieldIsRequired(field, study) && !isDisabled ? { color: 'red' } : { display: 'none' }}>* </span>}
Expand All @@ -22,7 +22,7 @@ export function SmallSelectField({ field, study, label, isDisabled, errorMessage
inverted
/>
</div>
<Form.Group widths={options.length}>
<Form.Group widths={options.length !== 1 ? options.length : "equal"}>
{R.map(processedOptions, (option) => {
const isActive = value === option.value;
return (
Expand Down Expand Up @@ -57,12 +57,12 @@ export function SmallSelectField({ field, study, label, isDisabled, errorMessage
)
}

export function LargeSelectField({ field, study, label, isDisabled, errorMessage, options, validator, value, updateErrorMessage, updateValue }) {
export function LargeSelectField({ field, study, label, isDisabled, isReadonly, errorMessage, options, validator, value, updateErrorMessage, updateValue }) {
const processedOptions = useMemo(() => {
return constructDropdown(options)
}, [options])
return (
<Form.Field disabled={isDisabled} error={errorMessage !== null}>
<Form.Field disabled={isDisabled} readOnly={isReadonly} error={errorMessage !== null}>
<div>
<Popup
trigger={<span style={fieldIsRequired(field, study) && !isDisabled ? { color: 'red' } : { display: 'none' }}>* </span>}
Expand Down
3 changes: 2 additions & 1 deletion ui/src/components/form/fields/textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ export function TextAreaField({
study,
label,
isDisabled,
isReadonly,
validator,
value,
errorMessage,
updateErrorMessage,
updateValue
}) {
return (
<Form.Field disabled={isDisabled} error={errorMessage !== null}>
<Form.Field disabled={isDisabled} readOnly={isReadonly} error={errorMessage !== null}>
<div>
<Popup
trigger={<span style={fieldIsRequired(field, study) && !isDisabled ? { color: 'red' } : { display: 'none' }}>* </span>}
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/form/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const doesFieldNotMeetAllConditions = (conditionals, gfs) => {
else {
Array.isArray(conditionals[key]) ?
check.push(conditionals[key].includes(gfs[key])) :
check.push(conditionals[key] === gfs[key]);
check.push(conditionals[key] === gfs[key] || conditionals[key] === Boolean(gfs[key]));
}
});

Expand Down

0 comments on commit ab015e8

Please sign in to comment.