From cc53c42ad1c00a364b8f4959d9ed158be6cb6fb0 Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt Date: Wed, 15 Nov 2023 11:11:13 -0500 Subject: [PATCH 1/3] fixed: go to irrelevant error when first non-readonly (e.g. dn) question in form is not relevant, #720 --- public/js/src/module/controller-webform-oc.js | 111 +++++++++--------- 1 file changed, 55 insertions(+), 56 deletions(-) diff --git a/public/js/src/module/controller-webform-oc.js b/public/js/src/module/controller-webform-oc.js index 47c66f72..0aca15d3 100644 --- a/public/js/src/module/controller-webform-oc.js +++ b/public/js/src/module/controller-webform-oc.js @@ -170,62 +170,6 @@ function init(formEl, data, loadErrors = []) { // set form eventhandlers before initializing form _setFormEventHandlers(); - const handleGoToIrrelevant = (e) => { - let err; - // In OC hidden go_to fields should show loadError - // regular questions: - if (!e.target.classList.contains('or-appearance-dn')) { - err = t('alert.goto.irrelevant'); - } - // Discrepancy notes - else { - err = `${t('alert.goto.irrelevant')} `; - const goToErrorLink = settings.goToErrorUrl - ? `${settings.goToErrorUrl}` - : ''; - if (settings.interface === 'queries') { - err += goToErrorLink - ? t('alert.goto.msg2', { - miniform: goToErrorLink, - // switch off escaping - interpolation: { - escapeValue: false, - }, - }) - : t('alert.goto.msg1'); - } - } - // For goto targets that are discrepancy notes and are relevant but their linked question is not, - // the goto-irrelevant event will be fired twice. We can safely remove the eventlistener after the first - // event is caught (for all cases). - form.view.html.removeEventListener( - events.GoToIrrelevant().type, - handleGoToIrrelevant - ); - goToHiddenErrors = [err]; - loadErrors.push(err); - }; - - const handleGoToInvisible = () => { - form.view.html.removeEventListener( - events.GoToInvisible().type, - handleGoToInvisible - ); - if (settings.interface === 'sdv') { - loadErrors.push(`${t('alert.goto.invisible')} `); - } - }; - - // listen for "goto-irrelevant" event and add error - form.view.html.addEventListener( - events.GoToIrrelevant().type, - handleGoToIrrelevant - ); - form.view.html.addEventListener( - events.GoToInvisible().type, - handleGoToInvisible - ); - loadErrors = loadErrors.concat(form.init()); // Determine whether UI language should be attempted to be switched. @@ -293,6 +237,61 @@ function init(formEl, data, loadErrors = []) { // this is placed in between form.init() and form.goTo(). $('.main-loader').remove(); if (settings.goTo && location.hash) { + const handleGoToIrrelevant = (e) => { + let err; + // In OC hidden go_to fields should show loadError + // regular questions: + if (!e.target.classList.contains('or-appearance-dn')) { + err = t('alert.goto.irrelevant'); + } + // Discrepancy notes + else { + err = `${t('alert.goto.irrelevant')} `; + const goToErrorLink = settings.goToErrorUrl + ? `${settings.goToErrorUrl}` + : ''; + if (settings.interface === 'queries') { + err += goToErrorLink + ? t('alert.goto.msg2', { + miniform: goToErrorLink, + // switch off escaping + interpolation: { + escapeValue: false, + }, + }) + : t('alert.goto.msg1'); + } + } + // For goto targets that are discrepancy notes and are relevant but their linked question is not, + // the goto-irrelevant event will be fired twice. We can safely remove the eventlistener after the first + // event is caught (for all cases). + form.view.html.removeEventListener( + events.GoToIrrelevant().type, + handleGoToIrrelevant + ); + goToHiddenErrors = [err]; + loadErrors.push(err); + }; + + const handleGoToInvisible = () => { + form.view.html.removeEventListener( + events.GoToInvisible().type, + handleGoToInvisible + ); + if (settings.interface === 'sdv') { + loadErrors.push(`${t('alert.goto.invisible')} `); + } + }; + + form.view.html.addEventListener( + events.GoToIrrelevant().type, + handleGoToIrrelevant + ); + form.view.html.addEventListener( + events.GoToInvisible().type, + handleGoToInvisible + ); + // form.goTo returns an array of 1 error if it has error. We're using our special // knowledge of Enketo Core to replace this error goToErrors = form.goTo( From 8e44738da2c6a156457c74b0836b146b103841ef Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt Date: Wed, 15 Nov 2023 13:22:49 -0500 Subject: [PATCH 2/3] fixed: dn comments are not HTML encoded, #718 --- widget/discrepancy-note/dn-widget.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/widget/discrepancy-note/dn-widget.js b/widget/discrepancy-note/dn-widget.js index 9854020a..fd9d2d31 100644 --- a/widget/discrepancy-note/dn-widget.js +++ b/widget/discrepancy-note/dn-widget.js @@ -1585,6 +1585,20 @@ class Comment extends Widget { } } + _encodeHtml(str) { + return str.replace( + /[&<>'"]/g, + (tag) => + ({ + '&': '&', + '<': '<', + '>': '>', + "'": ''', + '"': '"', + }[tag]) + ); + } + _getHistoryRow(item, options = {}) { const types = { comment: ' ', @@ -1638,7 +1652,9 @@ class Comment extends Widget { types[item.type] } - ${msg} + ${this._encodeHtml( + msg + )} ${ assignee From 20f4b0d78747bf7a769fcb197ac4b2349a6d0e9b Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt Date: Thu, 30 Nov 2023 15:24:13 -0500 Subject: [PATCH 3/3] fixed: loading to the wrong page if the first page contains no dn widget, #720 temporary duplicate fix that can be reverted later, --- public/js/src/module/page.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/public/js/src/module/page.js b/public/js/src/module/page.js index 59ea69bf..46a2ceeb 100644 --- a/public/js/src/module/page.js +++ b/public/js/src/module/page.js @@ -6,6 +6,31 @@ import reasons from './reasons'; import settings from './settings'; import gui from './gui'; +// Contains fix for https://github.com/OpenClinica/enketo-express-oc/issues/720 +// This function should be removed once PR https://github.com/enketo/enketo/pull/1286 is merged +// and published +pageModule.flipToPageContaining = function ($e) { + const e = $e[0]; + const closestPage = e.closest('[role="page"]'); + + if (closestPage) { + this._flipTo(closestPage); + } else if (e.closest('.question')) { + // If $e is a comment question, and it is not inside a group, there will be no closestPage. + const referer = e.querySelector('[data-for]'); + const ancestor = e.closest('.or-repeat, form.or'); + if (referer && ancestor) { + const linkedQuestion = ancestor.querySelector( + `[name="${referer.dataset.for}"]` + ); + if (linkedQuestion) { + this._flipTo(linkedQuestion.closest('[role="page"]')); + } + } + } + this.$toc.parent().find('.pages-toc__overlay').click(); +}; + /* * The only thing we want to change in this function for OC, * is to NOT flip to the next page when a repeat is the same as a page and