Skip to content

Commit 5a35b81

Browse files
Allowed users to change rendering type when editing a question
1 parent 710f21d commit 5a35b81

File tree

2 files changed

+47
-10
lines changed

2 files changed

+47
-10
lines changed
Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
1-
import type { FormField } from '@openmrs/esm-form-engine-lib';
2-
import { allowedPropertiesMapping, allowedQuestionOptionsMapping } from '@constants';
1+
import type { FormField, RenderType } from '@openmrs/esm-form-engine-lib';
2+
import { allowedPropertiesMapping, allowedQuestionOptionsMapping, allowedRenderingOptionsMapping } from '@constants';
33

44
/**
55
* Cleans the given questionOptions object by retaining only allowed keys for the new type.
6+
* It combines allowed keys from both the question type and the rendering type.
67
*/
7-
function cleanQuestionOptionsForType(options: any, newType: string): any {
8-
const allowedOpts = allowedQuestionOptionsMapping[newType] || [];
9-
const cleanedOpts = Object.fromEntries(Object.entries(options).filter(([optKey]) => allowedOpts.includes(optKey)));
8+
function cleanQuestionOptionsForType(options: any, questionType: string, rendering: RenderType): any {
9+
const allowedByType = allowedQuestionOptionsMapping[questionType] || [];
10+
const allowedByRendering = allowedRenderingOptionsMapping[rendering] || [];
11+
const allowedOpts = new Set(['rendering', ...allowedByType, ...allowedByRendering]);
12+
const cleanedOpts = Object.fromEntries(Object.entries(options).filter(([key]) => allowedOpts.has(key)));
1013
cleanedOpts.rendering = options.rendering;
1114
return cleanedOpts;
1215
}
1316

1417
/**
1518
* Cleans the given form field by retaining only allowed top‑level properties for the new type.
16-
* Also cleans nested questionOptions using the nested mapping.
19+
* Also cleans nested questionOptions using the combined mappings for question type and rendering type.
1720
*/
1821
export function cleanFormFieldForType(field: FormField, newType: string): FormField {
1922
const allowedKeys = allowedPropertiesMapping[newType] || [];
@@ -27,9 +30,12 @@ export function cleanFormFieldForType(field: FormField, newType: string): FormFi
2730

2831
// If questionOptions is allowed and exists, clean it using the nested mapping.
2932
if (cleaned.questionOptions && typeof cleaned.questionOptions === 'object') {
30-
cleaned.questionOptions = cleanQuestionOptionsForType(cleaned.questionOptions, newType);
33+
cleaned.questionOptions = cleanQuestionOptionsForType(
34+
cleaned.questionOptions,
35+
newType,
36+
cleaned.questionOptions.rendering as RenderType,
37+
);
3138
}
32-
3339
cleaned.type = newType;
3440
return cleaned as FormField;
3541
}

src/constants.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,45 @@ export const allowedPropertiesMapping: Record<string, string[]> = Object.fromEnt
9090
Mapping of allowed keys for the nested questionOptions object per question type.
9191
*/
9292
export const allowedQuestionOptionsMapping: Record<string, string[]> = {
93-
control: ['rendering', 'minLength', 'maxLength'],
93+
control: ['rendering'],
9494
encounterDatetime: ['rendering'],
9595
encounterLocation: ['rendering'],
9696
encounterProvider: ['rendering'],
97-
encounterRole: ['rendering', 'isSearchable'],
97+
encounterRole: ['rendering'],
9898
obs: ['rendering', 'concept', 'answers'],
9999
obsGroup: ['rendering', 'concept'],
100100
patientIdentifier: ['rendering', 'identifierType', 'minLength', 'maxLength'],
101101
testOrder: ['rendering'],
102102
programState: ['rendering', 'programUuid', 'workflowUuid', 'answers'],
103103
};
104+
105+
/**
106+
Mapping of allowed keys for questionOptions based on the rendering type.
107+
*/
108+
export const allowedRenderingOptionsMapping: Record<RenderType, string[]> = {
109+
checkbox: ['rendering', 'concept', 'answers'],
110+
'checkbox-searchable': ['rendering', 'concept'],
111+
'content-switcher': ['rendering', 'concept'],
112+
date: ['rendering'],
113+
datetime: ['rendering'],
114+
drug: ['rendering', 'concept'],
115+
'encounter-location': ['rendering', 'concept'],
116+
'encounter-provider': ['rendering', 'concept'],
117+
'encounter-role': ['rendering', 'concept', 'isSearchable'],
118+
'fixed-value': ['rendering', 'concept'],
119+
file: ['rendering', 'concept'],
120+
group: ['rendering', 'concept'],
121+
number: ['rendering', 'concept', 'min', 'max'],
122+
problem: ['rendering', 'concept'],
123+
radio: ['rendering', 'concept', 'answers'],
124+
repeating: ['rendering', 'concept'],
125+
select: ['rendering', 'concept', 'answers'],
126+
text: ['rendering', 'concept', 'minLength', 'maxLength'],
127+
textarea: ['rendering', 'concept', 'rows'],
128+
toggle: ['rendering', 'concept', 'toggleOptions'],
129+
'ui-select-extended': ['rendering', 'concept', 'isSearchable'],
130+
'workspace-launcher': ['rendering', 'concept'],
131+
markdown: ['rendering', 'concept'],
132+
'extension-widget': ['rendering', 'concept'],
133+
'select-concept-answers': ['rendering', 'concept', 'answers'],
134+
};

0 commit comments

Comments
 (0)