@openmrs/esm-form-engine-lib 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  import {
2
+ type AttachmentFieldValue,
2
3
  type FormField,
3
4
  type FormProcessorContextProps,
4
5
  type OpenmrsEncounter,
@@ -7,7 +8,7 @@ import {
7
8
  type PatientProgram,
8
9
  type PatientProgramPayload,
9
10
  } from '../../types';
10
- import { saveAttachment, savePatientIdentifier, saveProgramEnrollment } from '../../api';
11
+ import { createAttachment, savePatientIdentifier, saveProgramEnrollment } from '../../api';
11
12
  import { hasRendering, hasSubmission } from '../../utils/common-utils';
12
13
  import dayjs from 'dayjs';
13
14
  import { assignedObsIds, constructObs, voidObs } from '../../adapters/obs-adapter';
@@ -144,19 +145,17 @@ export function savePatientPrograms(patientPrograms: PatientProgramPayload[]) {
144
145
  export function saveAttachments(fields: FormField[], encounter: OpenmrsEncounter, abortController: AbortController) {
145
146
  const complexFields = fields?.filter((field) => field?.questionOptions.rendering === 'file' && hasSubmission(field));
146
147
 
147
- if (!complexFields?.length) return [];
148
+ if (!complexFields?.length) {
149
+ return [];
150
+ }
148
151
 
149
- return complexFields.map((field) => {
152
+ const allPromises = complexFields.flatMap((field) => {
150
153
  const patientUuid = typeof encounter?.patient === 'string' ? encounter?.patient : encounter?.patient?.uuid;
151
- return saveAttachment(
152
- patientUuid,
153
- field,
154
- field?.questionOptions.concept,
155
- new Date().toISOString(),
156
- encounter?.uuid,
157
- abortController,
158
- );
154
+ const attachments = (field.meta.submission.newValue as AttachmentFieldValue[]) ?? [];
155
+ return attachments.map((attachment) => createAttachment(patientUuid, encounter.uuid, attachment));
159
156
  });
157
+
158
+ return Promise.all(allPromises);
160
159
  }
161
160
 
162
161
  export function getMutableSessionProps(context: FormContextProps) {
@@ -199,11 +198,14 @@ function processObsField(obsForSubmission: OpenmrsObs[], field: FormField) {
199
198
 
200
199
  if (field.type === 'obsGroup') {
201
200
  processObsGroup(obsForSubmission, field);
202
- } else if (hasSubmission(field)) {
203
- // For non-group obs with a submission
201
+ return;
202
+ }
203
+
204
+ // new attachments will be processed later
205
+ if (!hasRendering(field, 'file')) {
204
206
  addObsToList(obsForSubmission, field.meta.submission.newValue);
205
- addObsToList(obsForSubmission, field.meta.submission.voidedValue);
206
207
  }
208
+ addObsToList(obsForSubmission, field.meta.submission.voidedValue);
207
209
  }
208
210
 
209
211
  function processObsGroup(obsForSubmission: OpenmrsObs[], groupField: FormField) {
@@ -257,7 +259,7 @@ function hasSubmittableObs(field: FormField) {
257
259
  type,
258
260
  } = field;
259
261
 
260
- if (isTransient || !['obs', 'obsGroup'].includes(type) || hasRendering(field, 'file') || field.meta.groupId) {
262
+ if (isTransient || !['obs', 'obsGroup'].includes(type) || field.meta.groupId) {
261
263
  return false;
262
264
  }
263
265
  if ((field.isHidden || field.isParentHidden) && field.meta.initialValue?.omrsObject) {
@@ -16,6 +16,7 @@ import { getControlTemplate } from './inbuilt-components/control-templates';
16
16
  import { inbuiltPostSubmissionActions } from './inbuilt-components/InbuiltPostSubmissionActions';
17
17
  import { inbuiltFormTransformers } from './inbuilt-components/inbuiltTransformers';
18
18
  import { inbuiltFieldValueAdapters } from './inbuilt-components/inbuiltFieldValueAdapters';
19
+ import { hasRendering } from '../utils/common-utils';
19
20
 
20
21
  /**
21
22
  * @internal
@@ -143,7 +144,7 @@ export async function getRegisteredControl(renderType: string) {
143
144
  */
144
145
  export function getFieldControlWithFallback(question: FormField) {
145
146
  // Check if the question has a missing concept
146
- if (hasMissingConcept(question)) {
147
+ if (hasMissingConcept(question) && !hasRendering(question, 'file')) {
147
148
  // If so, render a disabled text input
148
149
  question.disabled = true;
149
150
  question.isDisabled = true;
@@ -1,4 +1,4 @@
1
- import { type OpenmrsResource } from '@openmrs/esm-framework';
1
+ import { type UploadedFile, type OpenmrsResource } from '@openmrs/esm-framework';
2
2
 
3
3
  export interface OpenmrsEncounter {
4
4
  uuid?: string;
@@ -108,14 +108,14 @@ export interface OpenmrsFormResource extends OpenmrsResource {
108
108
  valueReference?: string;
109
109
  }
110
110
 
111
- export interface Attachment {
112
- id: string;
113
- src: string;
114
- title: string;
115
- description: string;
116
- dateTime: string;
117
- bytesMimeType: string;
118
- bytesContentFamily: string;
111
+ export interface Attachment extends UploadedFile {
112
+ uuid?: string;
113
+ voided?: boolean;
114
+ }
115
+
116
+ export interface AttachmentFieldValue extends Attachment {
117
+ formFieldNamespace: string;
118
+ formFieldPath: string;
119
119
  }
120
120
 
121
121
  export interface AttachmentResponse {
@@ -118,8 +118,8 @@ export interface PostSubmissionAction {
118
118
  ): void;
119
119
  }
120
120
 
121
- export interface FormFieldInputProps {
122
- value: any;
121
+ export interface FormFieldInputProps<TValue = any> {
122
+ value: TValue;
123
123
  field: FormField;
124
124
  errors: ValidationResult[];
125
125
  warnings: ValidationResult[];
@@ -128,7 +128,7 @@ export interface FormFieldInputProps {
128
128
  *
129
129
  * @param value - The new value of the field.
130
130
  */
131
- setFieldValue: (value: any) => void;
131
+ setFieldValue: (value: TValue) => void;
132
132
  }
133
133
 
134
134
  /**
@@ -1,34 +0,0 @@
1
- import React from 'react';
2
- import Webcam from 'react-webcam';
3
- import { Button } from '@carbon/react';
4
- import { Camera as CameraIcon } from '@carbon/react/icons';
5
-
6
- import styles from './camera.scss';
7
-
8
- interface CameraProps {
9
- handleImages: (state: any) => void;
10
- }
11
-
12
- const Camera: React.FC<CameraProps> = ({ handleImages }) => {
13
- const webcamRef = React.useRef(null);
14
-
15
- const capture = React.useCallback(() => {
16
- const imageSrc = webcamRef.current.getScreenshot();
17
- handleImages(imageSrc);
18
- }, [webcamRef]);
19
-
20
- const videoConstraints = {
21
- facingMode: 'user',
22
- };
23
-
24
- return (
25
- <div>
26
- <Webcam audio={false} ref={webcamRef} screenshotFormat="image/png" videoConstraints={videoConstraints} />
27
- <div className={styles.captureButton}>
28
- <Button onClick={capture} type="button" hasIconOnly renderIcon={() => <CameraIcon size={24} />}></Button>
29
- </div>
30
- </div>
31
- );
32
- };
33
-
34
- export default Camera;
@@ -1,3 +0,0 @@
1
- .captureButton {
2
- margin: 0.5rem 0;
3
- }