Skip to content

(feat) O3-3367 Add support for person attributes#423

Open
CynthiaKamau wants to merge 3 commits intomainfrom
O3-3367
Open

(feat) O3-3367 Add support for person attributes#423
CynthiaKamau wants to merge 3 commits intomainfrom
O3-3367

Conversation

@CynthiaKamau
Copy link
Contributor

@CynthiaKamau CynthiaKamau commented Nov 19, 2024

Requirements

  • This PR has a title that briefly describes the work done including the ticket number. If there is a ticket, make sure your PR title includes a conventional commit label. See existing PR titles for inspiration.
  • My work conforms to the OpenMRS 3.0 Styleguide and design documentation.
  • My work includes tests or is validated by existing tests.

Summary

Add support for person attributes

Schema :

{
  "name": "New person attributes  form ",
  "pages": [
    {
      "label": "newPage ",
      "sections": [
        {
          "label": "New section",
          "isExpanded": "true",
          "questions": [
            {
              "label": "Person attribute (String)",
              "type": "personAttribute",
              "required": false,
              "id": "bloodTyping",
              "questionOptions": {
                "rendering": "text",
                "attributeType": "8d871d18-c2cc-11de-8d13-0010c6dffd0f"
              }
            },
            {
              "label": "Person attribute (location drop down)",
              "type": "personAttribute",
              "required": false,
              "id": "bloodTyping1",
              "questionOptions": {
                "rendering": "ui-select-extended",
                "attributeType": "8d87236c-c2cc-11de-8d13-0010c6dffd0f"
              },
              "validators": []
            },
            {
              "label": "Person attribute (concept select drop down)",
              "type": "personAttribute",
              "required": false,
              "id": "bloodTyping2",
              "questionOptions": {
                "rendering": "ui-select-extended",
                "concept": "5272AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "attributeType": "8d871f2a-c2cc-11de-8d13-0010c6dffd0f"
              },
              "validators": []
            }
          ]
        }
      ]
    }
  ],
  "processor": "EncounterFormProcessor",
  "encounterType": "dd528487-82a5-4082-9c72-ed246bd49591",
  "referencedForms": [],
  "description": "Form that keeps HIV patient data",
  "version": "2.0",
  "uuid": "9478f8b6-0875-4127-b557-f8d844d1bd69"
}

Screenshots

Screen.Recording.2024-11-21.at.13.54.06.mov

Related Issue

Other

@CynthiaKamau CynthiaKamau marked this pull request as draft November 19, 2024 10:41
@github-actions
Copy link

github-actions bot commented Nov 19, 2024

Size Change: -265 kB (-17.25%) 👏

Total Size: 1.27 MB

Filename Size Change
dist/524.js 0 B -265 kB (removed) 🏆
ℹ️ View Unchanged
Filename Size Change
dist/148.js 267 kB 0 B
dist/151.js 382 kB 0 B
dist/225.js 2.58 kB 0 B
dist/260.js 114 kB 0 B
dist/277.js 11.9 kB 0 B
dist/300.js 645 B 0 B
dist/335.js 968 B 0 B
dist/353.js 3.02 kB 0 B
dist/41.js 3.37 kB 0 B
dist/422.js 3.05 kB 0 B
dist/499.js 2.51 kB 0 B
dist/540.js 2.63 kB 0 B
dist/55.js 758 B 0 B
dist/606.js 2.24 kB 0 B
dist/635.js 14.4 kB 0 B
dist/658.js 1.85 kB 0 B
dist/727.js 87.2 kB 0 B
dist/979.js 6.87 kB 0 B
dist/99.js 691 B 0 B
dist/993.js 3.09 kB 0 B
dist/main.js 358 kB +169 B (+0.05%)
dist/openmrs-esm-form-engine-lib.js 3.8 kB +1 B (+0.03%)

compressed-size-action

@CynthiaKamau CynthiaKamau force-pushed the O3-3367 branch 2 times, most recently from be9d967 to 48be05c Compare November 21, 2024 11:22
@CynthiaKamau CynthiaKamau marked this pull request as ready for review November 21, 2024 11:25
@CynthiaKamau CynthiaKamau force-pushed the O3-3367 branch 2 times, most recently from 7b25040 to ebf119f Compare November 21, 2024 11:42
@CynthiaKamau CynthiaKamau marked this pull request as draft November 21, 2024 11:48
@CynthiaKamau CynthiaKamau marked this pull request as ready for review November 22, 2024 07:43
@ibacher
Copy link
Member

ibacher commented Nov 22, 2024

So the immediate thing I see here is that we're embedding "format" in the form. I don't really love when we duplicate metadata like this in forms. Just load the format from the backend definition of the attribute type, so we don't face weird issues where changing an attribute type causes forms to break.

@CynthiaKamau CynthiaKamau force-pushed the O3-3367 branch 4 times, most recently from 8ac443b to e0f7bcc Compare November 27, 2024 09:15
Copy link
Member

@samuelmale samuelmale left a comment

Choose a reason for hiding this comment

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

Nice work @CynthiaKamau! Any chance we can have some integrational test cases covering all supported rendering types?

export const PersonAttributesAdapter: FormFieldValueAdapter = {
transformFieldValue: function (field: FormField, value: any, context: FormContextProps) {
clearSubmission(field);
if (field.meta?.previousValue?.value === value || isEmpty(value)) {
Copy link
Member

Choose a reason for hiding this comment

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

What happens if the user tries to delete an attribute in edit mode?

 if (field.meta?.previousValue && isEmpty(value)) {
   // should we void the attribute?
}

import { clearSubmission } from '../utils/common-utils';
import { isEmpty } from '../validators/form-validator';

export const PersonAttributesAdapter: FormFieldValueAdapter = {
Copy link
Member

Choose a reason for hiding this comment

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

Are you planning on adding some test coverage for this adapter?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes i will

Comment on lines +9 to +15
async fetchData(searchTerm: string, config?: Record<string, any>, uuid?: string): Promise<any[]> {
const rep = 'v=custom:(uuid,display)';
const url = `${restBaseUrl}/location?${rep}`;
const { data } = await openmrsFetch(searchTerm ? `${url}&q=${searchTerm}` : url);

return data?.results;
}
Copy link
Member

Choose a reason for hiding this comment

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

This data source seems to just load locations (not tied down to the "attribute" model). Anything stopping you from reusing the existing location DS`?

Copy link
Member

Choose a reason for hiding this comment

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

^^^^ This

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment on lines +9 to +15
async fetchData(searchTerm: string, config?: Record<string, any>, uuid?: string): Promise<any[]> {
const rep = 'v=custom:(uuid,display)';
const url = `${restBaseUrl}/location?${rep}`;
const { data } = await openmrsFetch(searchTerm ? `${url}&q=${searchTerm}` : url);

return data?.results;
}
Copy link
Member

Choose a reason for hiding this comment

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

^^^^ This


fetchData(searchTerm: string, config?: Record<string, any>): Promise<any[]> {
const apiUrl = this.url.replace('conceptUuid', config.referencedValue || config.concept);
const apiUrl = this.url.replace('conceptUuid', config.concept || config.referencedValue);
Copy link
Member

Choose a reason for hiding this comment

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

Why the inversion here?

if (patientUuid) {
openmrsFetch(`${restBaseUrl}/patient/${patientUuid}?v=custom:(attributes)`)
.then((response) => {
setPersonAttributes(response?.data?.attributes);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
setPersonAttributes(response?.data?.attributes);
setPersonAttributes(response.data?.attributes);

Copy link
Member

Choose a reason for hiding this comment

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

Is there some reason we're not using SWR here?

...controlTemplates.map((template) => ({
name: template.name,
component: templateToComponentMap.find((component) => component.name === template.name).baseControlComponent,
component: templateToComponentMap.find((component) => component.name === template.name)?.baseControlComponent,
Copy link
Member

Choose a reason for hiding this comment

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

Don't really understand why we need the ? here?

Comment on lines -189 to +203

transformers.push(...inbuiltFormTransformers.map((inbuiltTransformer) => inbuiltTransformer.component));

const inbuiltTransformersPromises = inbuiltFormTransformers.map(async (inbuiltTransformer) => {
const transformer = inbuiltTransformer.component;
if (transformer instanceof Promise) {
return await transformer;
}
return transformer;
});
const resolvedInbuiltTransformers = await Promise.all(inbuiltTransformersPromises);
transformers.push(...resolvedInbuiltTransformers);
transformers.forEach((transformer) => {
const inbuiltTransformer = inbuiltFormTransformers.find((t) => t.component === transformer);
registryCache.formSchemaTransformers[inbuiltTransformer.name] = transformer;
if (inbuiltTransformer) {
registryCache.formSchemaTransformers[inbuiltTransformer.name] = transformer;
}
Copy link
Member

Choose a reason for hiding this comment

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

Could we refactor this? The code is way more complicated than it needs to be and has way more iterations than it needs to. For example:

transformers = transformers.concat(inbuildFormTransformers.map((transformer) => transformer.component ? ({...transformer, component: Promise.resolve(transformer.component)}) : null).filter(Boolean).map(async (transformer) => {
  const theTransformer = await transformer.component;
  registryCache.formSchemaTransformers[transformer.name] = theTransformer;
  return theTransformer;
}));

@CynthiaKamau CynthiaKamau force-pushed the O3-3367 branch 2 times, most recently from e967865 to cb6a495 Compare December 16, 2024 12:12
@CynthiaKamau CynthiaKamau force-pushed the O3-3367 branch 2 times, most recently from a920aa0 to 6776aac Compare January 15, 2025 11:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants