Skip to content

Commit c63bef1

Browse files
committed
Obs functionality on bulk edit panel
1 parent d88ccb7 commit c63bef1

4 files changed

Lines changed: 147 additions & 21 deletions

File tree

ehr/resources/web/ehr/ehr_ext4_dataEntry.lib.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<script path="ehr/plugin/ResizableTextArea.js"/>
2222
<script path="ehr/plugin/RowEditor.js"/>
2323
<script path="ehr/plugin/CollapsibleDataEntryPanel.js"/>
24+
<script path="ehr/plugin/ClinicalObservationsBulkEdit.js"/>
2425

2526
<!--fields-->
2627
<script path="ehr/form/field/AnimalField.js"/>

ehr/resources/web/ehr/grid/ClinicalObservationGridPanel.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ Ext4.define('EHR.grid.ClinicalObservationGridPanel', {
1313
initComponent: function(){
1414
this.observationTypesStore = EHR.DataEntryUtils.getObservationTypesStore();
1515

16+
// Make the bulk edit panel for this grid offer the same category-dependent Observation/Score
17+
// editor as the grid's cell editor. formConfig is threaded unchanged to EHR.panel.BulkEditPanel,
18+
// which instantiates any plugins listed here.
19+
if (this.formConfig){
20+
this.formConfig.bulkEditPlugins = Ext4.Array.from(this.formConfig.bulkEditPlugins || []);
21+
if (!Ext4.Array.contains(this.formConfig.bulkEditPlugins, 'clinicalobservationsbulkedit')){
22+
this.formConfig.bulkEditPlugins.push('clinicalobservationsbulkedit');
23+
}
24+
}
25+
1626
this.callParent(arguments);
1727
},
1828

ehr/resources/web/ehr/panel/BulkEditPanel.js

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,20 @@ Ext4.define('EHR.panel.BulkEditPanel', {
4646

4747
this.callParent(arguments);
4848

49+
// Allow a form section to contribute panel plugins to its bulk edit panel via formConfig.bulkEditPlugins.
50+
// For example, the clinical observations grid uses this to make the Observation/Score editor depend on
51+
// the selected Category (see EHR.plugin.ClinicalObservationsBulkEdit), keeping this panel generic. This
52+
// runs after callParent because EHR.form.Panel resets this.plugins for collapsible forms. By this point
53+
// the panel's own plugins have already been constructed, so we construct ours explicitly and append them;
54+
// the component constructor then calls init() on every entry in this.plugins.
55+
var extraPlugins = this.formConfig && this.formConfig.bulkEditPlugins;
56+
if (extraPlugins){
57+
this.plugins = this.plugins || [];
58+
Ext4.Array.forEach(Ext4.Array.from(extraPlugins), function(p){
59+
this.plugins.push(this.constructPlugin(p));
60+
}, this);
61+
}
62+
4963
this.addEvents('bulkeditcomplete');
5064
},
5165

@@ -117,34 +131,38 @@ Ext4.define('EHR.panel.BulkEditPanel', {
117131

118132
item = Ext4.widget(item);
119133

120-
item.on('render', function(field){
121-
if (field.labelEl){
122-
Ext4.QuickTips.register({
123-
target: field.labelEl,
124-
text: 'Click to toggle'
125-
});
126-
127-
field.labelEl.on('click', function(){
128-
if (field.originalDisabled){
129-
Ext4.Msg.alert('Error', 'This field cannot be enabled');
130-
return;
131-
}
132-
133-
field.setDisabled(!field.isDisabled());
134-
Ext4.defer(field.focus, 100, field);
135-
}, this);
136-
}
137-
else {
138-
console.log(field);
139-
}
140-
}, this);
134+
this.addLabelToggle(item);
141135

142136
newItems.push(item);
143137
}, this);
144138

145139
return newItems;
146140
},
147141

142+
addLabelToggle: function(field){
143+
field.on('render', function(field){
144+
if (field.labelEl){
145+
Ext4.QuickTips.register({
146+
target: field.labelEl,
147+
text: 'Click to toggle'
148+
});
149+
150+
field.labelEl.on('click', function(){
151+
if (field.originalDisabled){
152+
Ext4.Msg.alert('Error', 'This field cannot be enabled');
153+
return;
154+
}
155+
156+
field.setDisabled(!field.isDisabled());
157+
Ext4.defer(field.focus, 100, field);
158+
}, this);
159+
}
160+
else {
161+
console.log(field);
162+
}
163+
}, this);
164+
},
165+
148166
onSubmit: function(){
149167
if (!this.suppressConfirmMsg){
150168
var values = this.getForm().getFieldValues();
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2026 LabKey Corporation
3+
*
4+
* Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
5+
*/
6+
/**
7+
* A plugin for EHR.panel.BulkEditPanel that makes the Observation/Score field's editor depend on the
8+
* selected Category, mirroring EHR.grid.plugin.ClinicalObservationsCellEditing so that the data type
9+
* and options offered in the bulk edit dialog match the clinical observations grid.
10+
*
11+
* It is attached to the bulk edit panel via the clinical observations grid's formConfig.bulkEditPlugins
12+
* (see EHR.grid.ClinicalObservationGridPanel), so the generic bulk edit panel stays free of any
13+
* observation-specific logic.
14+
*/
15+
Ext4.define('EHR.plugin.ClinicalObservationsBulkEdit', {
16+
extend: 'Ext.AbstractPlugin',
17+
alias: 'plugin.clinicalobservationsbulkedit',
18+
19+
init: function(panel){
20+
this.panel = panel;
21+
this.observationTypesStore = EHR.DataEntryUtils.getObservationTypesStore();
22+
panel.on('afterrender', this.setupObservationDependency, this, {single: true});
23+
24+
this.callParent(arguments);
25+
},
26+
27+
setupObservationDependency: function(){
28+
var panel = this.panel;
29+
var categoryField = panel.down('[name=category]');
30+
var observationField = panel.down('[name=observation]');
31+
if (!categoryField || !observationField){
32+
return;
33+
}
34+
35+
// Capture the base config of the original Observation/Score field so it can be rebuilt with a
36+
// category-specific editor (see reconfigureObservationField).
37+
this.observationFieldBaseCfg = {
38+
name: observationField.name,
39+
fieldLabel: observationField.fieldLabel,
40+
labelWidth: observationField.labelWidth,
41+
width: observationField.width
42+
};
43+
44+
categoryField.on('change', function(field, newValue){
45+
this.reconfigureObservationField(newValue);
46+
}, this);
47+
48+
// Initialize based on any pre-populated category value (e.g. when all selected records share a category)
49+
var initialCategory = categoryField.getValue();
50+
if (initialCategory){
51+
this.reconfigureObservationField(initialCategory);
52+
}
53+
},
54+
55+
reconfigureObservationField: function(category){
56+
var store = this.observationTypesStore;
57+
if (store.isLoading() || !store.getCount()){
58+
store.on('load', function(){
59+
this.reconfigureObservationField(category);
60+
}, this, {single: true});
61+
return;
62+
}
63+
64+
var panel = this.panel;
65+
var observationField = panel.down('[name=observation]');
66+
if (!observationField){
67+
return;
68+
}
69+
70+
var container = observationField.ownerCt;
71+
var index = container.items.indexOf(observationField);
72+
//preserve the user's enable/disable toggle state across category changes
73+
var wasDisabled = observationField.isDisabled();
74+
75+
//note: we proceed even if the category cannot be found, to support records saved under a no-longer-supported category
76+
var rec = category ? store.findRecord('value', category) : null;
77+
var editorConfig = rec && rec.get('editorconfig') ? Ext4.decode(rec.get('editorconfig')) : null;
78+
editorConfig = editorConfig || {
79+
xtype: 'textfield'
80+
};
81+
82+
var cfg = Ext4.apply({}, editorConfig);
83+
Ext4.apply(cfg, this.observationFieldBaseCfg);
84+
delete cfg.value;
85+
delete cfg.defaultValue;
86+
cfg.allowBlank = true;
87+
cfg.originalDisabled = false;
88+
cfg.disabled = wasDisabled;
89+
90+
cfg = EHR.DataEntryUtils.ensureLookupPlugin(cfg, false);
91+
92+
container.remove(observationField, true);
93+
var newField = Ext4.widget(cfg);
94+
panel.addLabelToggle(newField);
95+
container.insert(index, newField);
96+
}
97+
});

0 commit comments

Comments
 (0)