From bb2d0ea22a2c86001ccc28d8acc2319ca7e32b71 Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Mon, 15 Jun 2026 05:51:36 -0600 Subject: [PATCH 1/2] Improve Save Template validation when no fields are selected (#1148) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Rationale Submitting the EHR "Save As Template" dialog with every field unchecked threw an uncaught `TypeError: Cannot read properties of undefined (reading 'length')`. The checkboxgroup's `getValue().fields` is `undefined` when nothing is selected, so reading `.length` crashed `onSubmit` — the user got a silent failure (the template was never saved) plus a console error, instead of any guidance. ## Related Pull Requests None. ## Changes - Guard the selected-field list before reading `.length`, so an empty selection no longer throws. - Evaluate the record-selector `'none'` case before the field check, so a section the user intends to save is distinguished from one explicitly excluded. - When no fields are selected, show a clear validation message ("At least one field is required and none are selected. Note: The field can be blank.") instead of the generic "No records selected" alert. --- ehr/resources/web/ehr/window/SaveTemplateWindow.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ehr/resources/web/ehr/window/SaveTemplateWindow.js b/ehr/resources/web/ehr/window/SaveTemplateWindow.js index 63d222e80..e5e1fc938 100644 --- a/ehr/resources/web/ehr/window/SaveTemplateWindow.js +++ b/ehr/resources/web/ehr/window/SaveTemplateWindow.js @@ -202,21 +202,25 @@ Ext4.define('EHR.window.SaveTemplateWindow', { var tn = this.down('#templateName').getValue(); var rows = []; + var noFieldsSelected = false; this.down('#theForm').items.each(function(tab){ var radioGroup = tab.down('#recordSelector'); var selections = radioGroup.getValue()[radioGroup.down('[name]').name]; + + if (selections == 'none') + return; + var fields = tab.down('#fieldSelector').getValue().fields; - if (!fields.length) + if (!fields || !fields.length){ + noFieldsSelected = true; return; + } if (!(fields instanceof Array)) // single elements aren't wrapped in an array fields = [fields]; - if (selections == 'none') - return; - var store = Ext4.StoreMgr.get(tab.storeId); var records = []; @@ -249,7 +253,7 @@ Ext4.define('EHR.window.SaveTemplateWindow', { if (!rows.length){ Ext4.Msg.hide(); - Ext4.Msg.alert('Error', "No records selected"); + Ext4.Msg.alert('Error', noFieldsSelected ? "At least one field is required and none are selected. Note: The field can be blank." : "No records selected"); return; } From 7898b18e82df94aae9b53bf90b68c23ab74e5117 Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Mon, 15 Jun 2026 05:53:55 -0600 Subject: [PATCH 2/2] Fall back to unaligned pedigree plot when kinship2 alignment fails (#1147) ## Rationale kinship2's QP-based alignment (align=TRUE) can fail with "constraints are inconsistent, no solution!" on deep or looped pedigrees, which aborts the entire Pedigree report so no image renders at all. ## Related Pull Requests None. ## Changes - Wrap the kinship2 `plot()` call in the Pedigree report in `tryCatch`, retrying once with `align=FALSE` when the alignment error is detected so the report still renders. Any other error is re-raised unchanged. --- .../reports/schemas/study/Pedigree/Pedigree.r | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ehr/resources/reports/schemas/study/Pedigree/Pedigree.r b/ehr/resources/reports/schemas/study/Pedigree/Pedigree.r index 24259fdfa..684a7d708 100644 --- a/ehr/resources/reports/schemas/study/Pedigree/Pedigree.r +++ b/ehr/resources/reports/schemas/study/Pedigree/Pedigree.r @@ -300,7 +300,19 @@ if ((nrow(labkey.data) == 0) | (all(is.na(labkey.data$dam)) & all(is.na(labkey.d png(filename="${imgout:png_pedigree}", width = plotWidth, height=plotHeight); par(xpd=TRUE); - plot(ptemp, align=T, width=15, symbolsize=symSize, cex=cexSize, col=fixedPed$colors, mar=c(4.1,3.5,4.1,3.8)) + # kinship2's QP-based alignment (align=TRUE) can fail with "constraints are inconsistent, + # no solution!" on deep/looped pedigrees. Fall back to the unaligned layout in that case so + # the report still renders rather than aborting. + tryCatch( + plot(ptemp, align=TRUE, width=15, symbolsize=symSize, cex=cexSize, col=fixedPed$colors, mar=c(4.1,3.5,4.1,3.8)), + error = function(e) { + # Only the QP alignment failure is recoverable by dropping alignment; re-raise anything else. + if (!grepl("constraints are inconsistent", conditionMessage(e), fixed = TRUE)) + stop(e) + message("Pedigree alignment failed (", conditionMessage(e), "); retrying with align=FALSE.") + plot(ptemp, align=FALSE, width=15, symbolsize=symSize, cex=cexSize, col=fixedPed$colors, mar=c(4.1,3.5,4.1,3.8)) + } + ) mtext("Unknown animals are marked with xxs ## or xxd ## where ## is a randomly generated unique number. This identifier is used only in this plot and is re-generated each time the plot is rendered.", side = 1, font = 3, cex = 0.95) leg.txt <- c("Male", "Female", "Deceased")