Skip to content
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

Clean up Field types #8578

Merged
merged 19 commits into from
Feb 7, 2025
Merged

Clean up Field types #8578

merged 19 commits into from
Feb 7, 2025

Conversation

makelicious
Copy link
Collaborator

@makelicious makelicious commented Feb 5, 2025

Changes:

  • Create guards for each FieldType to use instead of casting
  • Remove "nominal"-style typing for field values. It might make a comeback*
  • Move FieldType related mappings to single file.
  • Ensure Pages are rendered with default form values (should fix the A component is changing an uncontrolled input of type text to be controlled)
    • Might not be a good idea. The point was that when new field is introduced, it is easy to keep in sync.
  • Rename optionValues to options (<select><option value=""></select> might trip SI otherwise)
  • Rename options to configuration

* Since country-config defines the configuration, we are left with union type when developing client or events backend. Only way to regain a bit of safety is to use guards.

Copy link

github-actions bot commented Feb 5, 2025

Oops! Looks like you forgot to update the changelog. When updating CHANGELOG.md, please consider the following:

  • Changelog is read by country implementors who might not always be familiar with all technical details of OpenCRVS. Keep language high-level, user friendly and avoid technical references to internals.
  • Answer "What's new?", "Why was the change made?" and "Why should I care?" for each change.
  • If it's a breaking change, include a migration guide answering "What do I need to do to upgrade?".

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input used string under the hood earlier.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input used string under the hood earlier.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input used string under the hood earlier.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input used string under the hood earlier.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose the license header in both makes this assumption.

Added linting since it is nicer to program with it.

@@ -88,43 +77,10 @@ const BaseField = z.object({

export type BaseField = z.infer<typeof BaseField>

export const FieldType = {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved under FieldType

case FieldType.CHECKBOX:
return checkboxToString(value as CheckboxFieldValue)
// @TODO: This should be a boolean?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this function used to be the display formatting function, so if checkbox was checked, then in the review view for instance, you saw the value as Yes or No. Should have been message descriptors tho

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, sorry the function comment threw me off a bit. But yea, checkbox value should be real boolean and not strings

Comment on lines 93 to 121
export function mapFieldTypeToElasticsearch(field: FieldConfig) {
switch (field.type) {
case FieldType.DATE:
// @TODO: This should be changed back to 'date'
// When we have proper validation of custom fields.
return { type: 'text' }
case FieldType.TEXT:
case FieldType.PARAGRAPH:
case FieldType.BULLET_LIST:
case FieldType.PAGE_HEADER:
return { type: 'text' }
case FieldType.DIVIDER:
case FieldType.RADIO_GROUP:
case FieldType.SELECT:
case FieldType.COUNTRY:
case FieldType.CHECKBOX:
case FieldType.LOCATION:
return { type: 'keyword' }
case FieldType.FILE:
return {
type: 'object',
properties: {
filename: { type: 'keyword' },
originalFilename: { type: 'keyword' },
type: { type: 'keyword' }
}
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep this somewhere closer to the indexing logic. Commons doesn't need to know about Elasticsearch being used

}

export function getInitialValues(fields: FieldConfig[]) {
return fields.reduce((initialValues: Record<string, FieldValue>, field) => {
export function setDefaultsForMissingFields(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be unused

case FieldType.CHECKBOX:
return checkboxToString(value as CheckboxFieldValue)
// @TODO: This should be a boolean?
return value === 'true' ? 'Yes' : 'No'
Copy link
Member

@rikukissa rikukissa Feb 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TRPCError: 
[
    {
        "received": "No",
        "code": "invalid_enum_value",
        "options": [
            "true",
            "false"
        ],
        "path": [
            "recommender.none"
        ],
        "message": "Invalid enum value. Expected 'true' | 'false', received 'No'"
    }
]

at Object.<anonymous> (/Users/riku/Code/OpenCRVS/opencrvs-core/packages/events/src/router/middleware/validate/index.ts:54:13)
at Generator.next (<anonymous>)
at fulfilled (/Users/riku/Code/OpenCRVS/opencrvs-core/packages/events/src/router/middleware/validate/index.ts:15:58)
at processTicksAndRejections (node:internal/process/task_queues:95:5)

Payload

{
  "json": {
    "eventId": "4a60fb38-80dd-49e4-a0a2-3ea372b8df72",
    "data": {
      "applicant.firstname": "Riku",
      "applicant.surname": "Rouvila",
      "applicant.dob": "2024-05-03",
      "applicant.image.label": "My driver's license",
      "recommender.none": "No",
      "recommender.firstname": "Pyry",
      "recommender.surname": "Rouvila",
      "recommender.id": "234234234",
      "applicant.image": {
        "filename": "7f879543-3320-4bea-b6a9-55100b48140e.png",
        "originalFilename": "Screenshot 2025-01-29 at 10.33.24.png",
        "type": "image/png"
      }
    },
    "transactionId": "f959db23-cd01-4879-9d90-dd7d645154b5"
  }
}

Comment on lines 176 to 179
const selectedCountry = countries.find(
(country) => country.value === value
)
case FieldType.COUNTRY:
return selectCountryFieldToString(value as SelectFieldValue, intl)
return selectedCountry ? intl.formatMessage(selectedCountry.label) : ''
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic should be inside the <Country /> registered input

fieldConfig.options,
intl

return selectedOption ? intl.formatMessage(selectedOption.label) : ''
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this correct? I'm guessing we do not want to store formatted values in the form data instead, right?

@makelicious makelicious requested a review from rikukissa February 6, 2025 14:01
Comment on lines +109 to +152
export function Output({
field,
value,
previousValue,
showPreviouslyMissingValuesAsChanged = true
}: {
field: FieldConfig
value?: FieldValue
previousValue?: FieldValue
showPreviouslyMissingValuesAsChanged: boolean
}) {
if (!value) {
if (previousValue) {
return <ValueOutput config={field} value={previousValue} />
}

return ''
}

if (previousValue && previousValue !== value) {
return (
<>
<Deleted>
<ValueOutput config={field} value={previousValue} />
</Deleted>
<br />
<ValueOutput config={field} value={value} />
</>
)
}
if (!previousValue && value && showPreviouslyMissingValuesAsChanged) {
return (
<>
<Deleted>
<ValueOutput config={field} value={'-'} />
</Deleted>
<br />
<ValueOutput config={field} value={value} />
</>
)
}

return <ValueOutput config={field} value={value} />
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function could almost inside components/Review/Output.tsx as it's only used in the Review page

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Goes over the file length limit :(

@makelicious makelicious added the 🚀 Ready to deploy Deployment automation should pick this PR up and start auto-deploying it label Feb 6, 2025
@makelicious makelicious added 🚀 Ready to deploy Deployment automation should pick this PR up and start auto-deploying it and removed 🚀 Ready to deploy Deployment automation should pick this PR up and start auto-deploying it labels Feb 7, 2025
@ocrvs-bot
Copy link
Collaborator

Your environment is deployed to https://ocrvs-8397-b.opencrvs.dev

@makelicious makelicious deployed to ocrvs-8397-b February 7, 2025 09:00 — with GitHub Actions Active
@makelicious
Copy link
Collaborator Author

on e2e, death 6.2. failed (the flaky one). Risking it all and merging

@makelicious makelicious merged commit f6786bf into develop Feb 7, 2025
73 of 74 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🚀 Ready to deploy Deployment automation should pick this PR up and start auto-deploying it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants