From cc87a8a993001d5b4cea8493a84a6798f481cc5a Mon Sep 17 00:00:00 2001 From: Tony Valle <79843014+superskip@users.noreply.github.com> Date: Thu, 16 Nov 2023 17:24:35 +0100 Subject: [PATCH 01/18] fix: [DHIS2-15967] allow enrolling TEIs with mandatory TET attributes (#3455) --- .../EnrollmentRegistrationEntry.types.js | 11 +++++++---- .../hooks/useBuildEnrollmentPayload.js | 5 ++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types.js index d58a42aff2..3e4ea25e82 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/EnrollmentRegistrationEntry.types.js @@ -8,11 +8,17 @@ import type { ExistingUniqueValueDialogActionsComponent } from '../withErrorMess import type { InputAttribute } from './hooks/useFormValues'; import { RenderFoundation, ProgramStage } from '../../../metaData'; +type TrackedEntityAttributes = Array<{ + attribute: string, + value: any, +}>; + export type EnrollmentPayload = {| trackedEntity: string, trackedEntityType: string, orgUnit: string, geometry: any, + attributes: TrackedEntityAttributes, enrollments: [ {| occurredAt: string, @@ -23,10 +29,7 @@ export type EnrollmentPayload = {| events: Array<{ orgUnit: string, }>, - attributes: Array<{ - attribute: string, - value: any, - }>, + attributes: TrackedEntityAttributes, |} ] |} diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js index 95778162b0..d6ae0f8adf 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useBuildEnrollmentPayload.js @@ -156,13 +156,15 @@ export const useBuildEnrollmentPayload = ({ ? [firstStageDuringRegistrationEvent, ...autoGenerateEvents] : autoGenerateEvents; + const attributes = deriveAttributesFromFormValues(formServerValues); + const enrollment = { program: programId, status: 'ACTIVE', orgUnit: orgUnitId, occurredAt, enrolledAt, - attributes: deriveAttributesFromFormValues(formServerValues), + attributes, events: allEventsToBeCreated, }; @@ -177,6 +179,7 @@ export const useBuildEnrollmentPayload = ({ trackedEntity: teiId || generateUID(), orgUnit: orgUnitId, trackedEntityType: trackedEntityTypeId, + attributes, geometry, enrollments: [enrollment], }; From 45244cb3bc3922183d07b3a8c4a01fac775470f6 Mon Sep 17 00:00:00 2001 From: "@dhis2-bot" Date: Thu, 16 Nov 2023 16:30:17 +0000 Subject: [PATCH 02/18] chore(release): cut 100.44.6 [skip release] ## [100.44.6](https://github.com/dhis2/capture-app/compare/v100.44.5...v100.44.6) (2023-11-16) ### Bug Fixes * [DHIS2-15967] allow enrolling TEIs with mandatory TET attributes ([#3455](https://github.com/dhis2/capture-app/issues/3455)) ([cc87a8a](https://github.com/dhis2/capture-app/commit/cc87a8a993001d5b4cea8493a84a6798f481cc5a)) --- CHANGELOG.md | 7 +++++++ package.json | 4 ++-- packages/rules-engine/package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c27d4c0f1f..d3c8634b06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [100.44.6](https://github.com/dhis2/capture-app/compare/v100.44.5...v100.44.6) (2023-11-16) + + +### Bug Fixes + +* [DHIS2-15967] allow enrolling TEIs with mandatory TET attributes ([#3455](https://github.com/dhis2/capture-app/issues/3455)) ([cc87a8a](https://github.com/dhis2/capture-app/commit/cc87a8a993001d5b4cea8493a84a6798f481cc5a)) + ## [100.44.5](https://github.com/dhis2/capture-app/compare/v100.44.4...v100.44.5) (2023-11-10) diff --git a/package.json b/package.json index 894654968e..3ae9ef9cbb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "capture-app", "homepage": ".", - "version": "100.44.5", + "version": "100.44.6", "cacheVersion": "7", "serverVersion": "38", "license": "BSD-3-Clause", @@ -10,7 +10,7 @@ "packages/rules-engine" ], "dependencies": { - "@dhis2/rules-engine-javascript": "100.44.5", + "@dhis2/rules-engine-javascript": "100.44.6", "@dhis2/app-runtime": "^3.9.3", "@dhis2/d2-i18n": "^1.1.0", "@dhis2/d2-icons": "^1.0.1", diff --git a/packages/rules-engine/package.json b/packages/rules-engine/package.json index 461ab1c1fa..7df2edc3ad 100644 --- a/packages/rules-engine/package.json +++ b/packages/rules-engine/package.json @@ -1,6 +1,6 @@ { "name": "@dhis2/rules-engine-javascript", - "version": "100.44.5", + "version": "100.44.6", "license": "BSD-3-Clause", "main": "./build/cjs/index.js", "scripts": { From 46fb2270b21c4dec57f4447232608d8dd3cfb9af Mon Sep 17 00:00:00 2001 From: "@dhis2-bot" Date: Sun, 19 Nov 2023 02:38:07 +0100 Subject: [PATCH 03/18] fix(translations): sync translations from transifex (master) Automatically merged. --- i18n/cs.po | 111 ++++++++++++++++++++++++++------------------- i18n/uz_UZ_Cyrl.po | 10 ++-- 2 files changed, 69 insertions(+), 52 deletions(-) diff --git a/i18n/cs.po b/i18n/cs.po index 4e2e113dd9..171ec3d5b0 100644 --- a/i18n/cs.po +++ b/i18n/cs.po @@ -43,7 +43,7 @@ msgstr "" "mějte však na paměti, že se tím zavřou další verze." msgid "View {{programName}} dashboard" -msgstr "" +msgstr "Zobrazit {{programName}} ovládací panel" msgid "View dashboard" msgstr "Zobrazit ovládací panel" @@ -80,7 +80,7 @@ msgstr "chyba" msgid "" "Plugins are not yet available - Please contact your system administrator" -msgstr "" +msgstr "Pluginy zatím nejsou k dispozici – obraťte se na správce systému" msgid "This value is validating" msgstr "Tato hodnota se ověřuje" @@ -161,13 +161,13 @@ msgid "Complete event" msgstr "Dokončit událost" msgid "{{ stageName }} - Basic info" -msgstr "" +msgstr "{{ stageName }} - Základní informace" msgid "{{ stageName }} - Status" -msgstr "" +msgstr "{{ stageName }} - Stav" msgid "Please select {{categoryName}}" -msgstr "" +msgstr "Vyberte prosím {{categoryName}}" msgid "A future date is not allowed" msgstr "Budoucí datum není povoleno" @@ -185,10 +185,10 @@ msgid "Metadata error. see log for details" msgstr "Chyba metadat. viz log pro podrobnosti" msgid "{{ stageName }} - Details" -msgstr "" +msgstr "{{ stageName }} - Podrobnosti" msgid "{{ stageName }} - {{ sectionName }}" -msgstr "" +msgstr "{{ stageName }} - {{ sectionName }}" msgid "Assigned user" msgstr "Přiřazený uživatel" @@ -395,6 +395,8 @@ msgid "" "This event has unsaved changes. Leaving this page without saving will lose " "these changes. Are you sure you want to discard unsaved changes?" msgstr "" +"Tato událost obsahuje neuložené změny. Opuštěním této stránky bez uložení " +"tyto změny ztratíte. Opravdu chcete zahodit neuložené změny?" msgid "No events to display" msgstr "Žádné události k zobrazení" @@ -534,6 +536,9 @@ msgstr "začněte psát pro vyhledávání" msgid "suggestions could not be retrieved" msgstr "návrhy nelze načíst" +msgid "No results found" +msgstr "Nenalezeny žádné výsledky" + msgid "No items to display" msgstr "Žádné položky k zobrazení" @@ -607,13 +612,13 @@ msgid "Write comment" msgstr "Napsat komentář" msgid "was blanked out and hidden by your last action" -msgstr "" +msgstr "byla vymazána a skryta vaší poslední akcí" msgid "Notice" -msgstr "" +msgstr "Oznámení" msgid "Close the notice" -msgstr "" +msgstr "Zavřít oznámení" msgid "Use new Enrollment dashboard for {{programName}}" msgstr "Použít nový ovládací panel zápisu pro {{programName}}" @@ -629,18 +634,29 @@ msgid "" "functionality in Capture is ongoing and will be added in upcoming app " "releases." msgstr "" +"Kliknutím na přihlášení níže začnete používat nový ovládací panel registrace" +" v aplikaci Capture pro tento program Tracker. V současné době existuje " +"určitá funkce z aplikace Tracker Capture, která ještě nebyla přidána, včetně" +" funkcí vztahů a doporučení. Práce na zahrnutí této funkce sledování do " +"Capture pokračují a budou přidány v nadcházejících vydáních aplikace." msgid "" "The core team appreciates any feedback on this new functionality which is " "currently being beta tested, please report any issues and feedback in the " "DHIS2 JIRA project." msgstr "" +"Základní tým oceňuje jakoukoli zpětnou vazbu k této nové funkcionalitě, " +"která je v současné době beta testována, nahlaste prosím jakékoli problémy a" +" zpětnou vazbu v projektu DHIS2 JIRA." msgid "" "Click the button below to opt-in to the new enrollment dashboard " "functionality in the Capture app (beta) for this Tracker program for all " "users." msgstr "" +"Kliknutím na tlačítko níže se přihlásíte k nové funkci ovládacího panelu " +"registrace v aplikaci Capture (beta) pro tento program Tracker pro všechny " +"uživatele." msgid "Yes, opt in" msgstr "Ano, přihlásit se" @@ -662,6 +678,7 @@ msgstr "" msgid "" "An error occurred while fetching enrollments. Please enter a valid url." msgstr "" +"Při načítání registrací došlo k chybě. Zadejte prosím platnou adresu URL." msgid "Enrollment Dashboard" msgstr "Ovládací panel zápisu" @@ -704,19 +721,19 @@ msgstr "" "vyberte všechny kategorie." msgid "Invalid enrollment id {{enrollmentId}}." -msgstr "" +msgstr "Neplatné id zápisu {{enrollmentId}}." msgid "Choose an enrollment to view the dashboard." msgstr "Chcete-li zobrazit ovládací panel, vyberte zápis." msgid "There are no active enrollments." -msgstr "" +msgstr "Nejsou žádné aktivní zápisy." msgid "Add new enrollment for {{teiDisplayName}} in this program." -msgstr "" +msgstr "Přidejte nový zápis pro {{teiDisplayName}} v tomto programu." msgid "No access to program owner." -msgstr "" +msgstr "Žádný přístup k vlastníkovi programu." msgid "{{teiDisplayName}} is not enrolled in this program." msgstr "{{teiDisplayName}} není v tomto programu zapsán." @@ -783,7 +800,7 @@ msgid "Refer" msgstr "Odkazovat" msgid "You can't add any more {{ programStageName }} events" -msgstr "" +msgstr "Nemůžete přidat žádné další události {{ programStageName }}" msgid "Cancel without saving" msgstr "Zrušit bez uložení" @@ -847,7 +864,7 @@ msgid "New Enrollment in program{{escape}} {{programName}}" msgstr "Nový zápis do programu{{escape}} {{programName}}" msgid "Save {{trackedEntityTypeName}}" -msgstr "" +msgstr "Uložit {{trackedEntityTypeName}}" msgid "Save {{trackedEntityName}}" msgstr "Uložit {{trackedEntityName}}" @@ -956,14 +973,11 @@ msgid "Search by attributes" msgstr "Hledání podle atributů" msgid "Could not retrieve metadata. Please try again later." -msgstr "" +msgstr "Nepodařilo se načíst metadata. Prosím zkuste to znovu později." msgid "Possible duplicates found" msgstr "Byly nalezeny možné duplikáty" -msgid "No results found" -msgstr "Nenalezeny žádné výsledky" - msgid "An error occurred loading possible duplicates" msgstr "Při načítání možných duplikátů došlo k chybě" @@ -977,28 +991,28 @@ msgid "Add relationship" msgstr "Přidat vztah" msgid "No results found for " -msgstr "" +msgstr "Pro dotaz nebyly nalezeny žádné výsledky" msgid "Registering unit" msgstr "Registrační jednotka" msgid "Choose a registering unit" -msgstr "" +msgstr "Vyberte registrační jednotku" msgid "Clear selection" -msgstr "" +msgstr "Vymazat výběr" msgid "No programs available." msgstr "Nejsou k dispozici žádné programy." msgid "Search for a program" -msgstr "" +msgstr "Vyhledat program" msgid "Some programs are being filtered by the chosen registering unit" -msgstr "" +msgstr "Některé programy jsou filtrovány vybranou registrační jednotkou" msgid "Show all programs" -msgstr "" +msgstr "Zobrazit všechny programy" msgid "Choose a program" msgstr "Vyberte program" @@ -1074,7 +1088,7 @@ msgid "Cannot search in all programs" msgstr "Nelze vyhledávat ve všech programech" msgid "Missing search criteria" -msgstr "" +msgstr "Chybí kritéria vyhledávání" msgid "Results found" msgstr "Nalezeny výsledky" @@ -1113,20 +1127,22 @@ msgid "This program is protected" msgstr "Tento program je chráněn" msgid "Reason to check for enrollments" -msgstr "" +msgstr "Důvod ke kontrole zápisů" msgid "" "Describe the reason you are checking for enrollments in this protected " "program" -msgstr "" +msgstr "Popište důvod, proč kontrolujete zápisy v tomto chráněném programu" msgid "Check for enrollments" -msgstr "" +msgstr "Zkontrolujte zápisy" msgid "" "You must provide a reason to check for enrollments in this protected " "program. All activity will be logged." msgstr "" +"Pro kontrolu zápisů v tomto chráněném programu musíte uvést důvod. Veškerá " +"aktivita bude zaznamenána." msgid "Save comment" msgstr "Uložit komentář" @@ -1173,6 +1189,7 @@ msgstr "Označit pro další sledování" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +"Stávající data pro automaticky generované události nebudou aktualizována." msgid "Enrollment date" msgstr "Datum zápisu" @@ -1336,7 +1353,7 @@ msgid "New {{ eventName }} event" msgstr "Nová událost {{ eventName }}" msgid "To open this event, please wait until saving is complete" -msgstr "" +msgstr "Chcete-li otevřít tuto událost, počkejte na dokončení ukládání" msgid "Show {{ rest }} more" msgstr "Zobrazit {{rest}} více" @@ -1366,38 +1383,38 @@ msgid "Stages and Events" msgstr "Fáze a události" msgid "New TEI Relationship" -msgstr "" +msgstr "Nový vztah TEI" msgid "Missing implementation step" -msgstr "" +msgstr "Chybí krok implementace" msgid "Go back without saving relationship" -msgstr "" +msgstr "Vraťte se zpět bez uložení vztahu" msgid "New Relationship" -msgstr "" +msgstr "Nový vztah" msgid "Link to an existing {{tetName}}" -msgstr "" +msgstr "Odkaz na existující {{tetName}}" msgid "An error occurred while adding the relationship" -msgstr "" +msgstr "Při přidávání vztahu došlo k chybě" msgid "" "Something went wrong while loading relationships. Please try again later." -msgstr "" +msgstr "Při načítání vztahů se něco pokazilo. Prosím zkuste to znovu později." msgid "{{trackedEntityTypeName}} relationships" -msgstr "" +msgstr "{{trackedEntityTypeName}} vztahy" msgid "To open this relationship, please wait until saving is complete" -msgstr "" +msgstr "Chcete-li otevřít tento vztah, počkejte na dokončení ukládání" msgid "Type" -msgstr "" +msgstr "Typ" msgid "Created date" -msgstr "" +msgstr "Datum vytvoření" msgid "Program stage name" msgstr "Název fáze programu" @@ -1436,19 +1453,19 @@ msgid "Choose a program stage to filter by {{label}}" msgstr "Vyberte fázi programu, kterou chcete filtrovat podle {{label}}" msgid "Active enrollments" -msgstr "" +msgstr "Aktivní zápisy" msgid "Completed enrollments" -msgstr "" +msgstr "Dokončené zápisy" msgid "Cancelled enrollments" -msgstr "" +msgstr "Zrušené zápisy" msgid "Working list could not be updated" msgstr "Pracovní seznam nelze aktualizovat" msgid "an error occurred loading the working lists" -msgstr "" +msgstr "došlo k chybě při načítání pracovních seznamů" msgid "an error occurred loading Tracked entity instance lists" msgstr "došlo k chybě při načítání seznamů instancí trasovaných entit" @@ -1583,7 +1600,7 @@ msgid "Set area" msgstr "Nastavit oblast" msgid "Area on map saved" -msgstr "" +msgstr "Oblast na mapě byla uložena" msgid "Compatibility mode" msgstr "Režim kompatibility" diff --git a/i18n/uz_UZ_Cyrl.po b/i18n/uz_UZ_Cyrl.po index 5e07eebebb..7d62b3a5cd 100644 --- a/i18n/uz_UZ_Cyrl.po +++ b/i18n/uz_UZ_Cyrl.po @@ -512,7 +512,7 @@ msgid "Type to filter options" msgstr "" msgid "No match found" -msgstr "" +msgstr "Ҳеч нима топилмади" msgid "Search" msgstr "Излаш" @@ -538,6 +538,9 @@ msgstr "қидириш учун ёзишни бошланг" msgid "suggestions could not be retrieved" msgstr "таклифлар қабул қилинмади" +msgid "No results found" +msgstr "Ҳеч қандай натижа топилмади" + msgid "No items to display" msgstr "Кўрсатиладиган ахборот йўқ" @@ -554,7 +557,7 @@ msgid "Update" msgstr "Янгилаш" msgid "Reset filter" -msgstr "" +msgstr "Фильтрни қайта созлаш" msgid "Remove filter" msgstr "Фильтрни олиб ташлаш" @@ -967,9 +970,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "Бўлиши мумкин бўлган нусхалар топилди" -msgid "No results found" -msgstr "Ҳеч қандай натижа топилмади" - msgid "An error occurred loading possible duplicates" msgstr "Эҳтимолий нусхаларни юклашда хатолик юз берди" From 9d761f0af075d1d013e87574ac8cf7da3daa49e4 Mon Sep 17 00:00:00 2001 From: "@dhis2-bot" Date: Sun, 19 Nov 2023 01:49:09 +0000 Subject: [PATCH 04/18] chore(release): cut 100.44.7 [skip release] ## [100.44.7](https://github.com/dhis2/capture-app/compare/v100.44.6...v100.44.7) (2023-11-19) ### Bug Fixes * **translations:** sync translations from transifex (master) ([46fb227](https://github.com/dhis2/capture-app/commit/46fb2270b21c4dec57f4447232608d8dd3cfb9af)) --- CHANGELOG.md | 7 +++++++ package.json | 4 ++-- packages/rules-engine/package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3c8634b06..d1ac4613a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [100.44.7](https://github.com/dhis2/capture-app/compare/v100.44.6...v100.44.7) (2023-11-19) + + +### Bug Fixes + +* **translations:** sync translations from transifex (master) ([46fb227](https://github.com/dhis2/capture-app/commit/46fb2270b21c4dec57f4447232608d8dd3cfb9af)) + ## [100.44.6](https://github.com/dhis2/capture-app/compare/v100.44.5...v100.44.6) (2023-11-16) diff --git a/package.json b/package.json index 3ae9ef9cbb..b19003534a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "capture-app", "homepage": ".", - "version": "100.44.6", + "version": "100.44.7", "cacheVersion": "7", "serverVersion": "38", "license": "BSD-3-Clause", @@ -10,7 +10,7 @@ "packages/rules-engine" ], "dependencies": { - "@dhis2/rules-engine-javascript": "100.44.6", + "@dhis2/rules-engine-javascript": "100.44.7", "@dhis2/app-runtime": "^3.9.3", "@dhis2/d2-i18n": "^1.1.0", "@dhis2/d2-icons": "^1.0.1", diff --git a/packages/rules-engine/package.json b/packages/rules-engine/package.json index 7df2edc3ad..d6850c1d71 100644 --- a/packages/rules-engine/package.json +++ b/packages/rules-engine/package.json @@ -1,6 +1,6 @@ { "name": "@dhis2/rules-engine-javascript", - "version": "100.44.6", + "version": "100.44.7", "license": "BSD-3-Clause", "main": "./build/cjs/index.js", "scripts": { From 2f2e52c3103e9cb48e77766701a9a5fc9af6ad48 Mon Sep 17 00:00:00 2001 From: Jasmine Nguyen <89806888+jasminenguyennn@users.noreply.github.com> Date: Mon, 20 Nov 2023 10:43:59 +0000 Subject: [PATCH 05/18] feat: [DHIS2-13237] Enrollment coordinates in enrollment widget (#3141) Co-authored-by: Simona Domnisoru --- i18n/en.pot | 42 ++- .../useCommonEnrollmentDomainData.types.js | 1 + .../Actions/Actions.component.js | 26 +- .../Actions/Actions.container.js | 45 +-- .../AddLocation/AddLocation.component.js | 23 ++ .../Actions/AddLocation/addLocation.types.js | 6 + .../Actions/AddLocation/index.js | 2 + .../Coordinates/Coordinates.component.js | 256 ++++++++++++++++++ .../MapModal/Coordinates/Coordinates.types.js | 10 + .../MapModal/Coordinates/converters.js | 11 + .../Coordinates/coordinate.validator.js | 32 +++ .../MapModal/Coordinates/index.js | 3 + .../MapModal/MapModal.component.js | 27 ++ .../MapModal/MapModal.container.js | 32 +++ .../MapModal/MapModal.types.js | 18 ++ .../Polygon/ConditionalTooltip.component.js | 29 ++ .../Polygon/DeleteControl.component.js | 52 ++++ .../MapModal/Polygon/Polygon.component.js | 225 +++++++++++++++ .../MapModal/Polygon/Polygon.types.js | 24 ++ .../MapModal/Polygon/converters.js | 8 + .../MapModal/Polygon/index.js | 3 + .../WidgetEnrollment/MapModal/index.js | 3 + .../MiniMap/MiniMap.component.js | 80 ++++++ .../WidgetEnrollment/MiniMap/MiniMap.types.js | 13 + .../WidgetEnrollment/MiniMap/converters.js | 10 + .../WidgetEnrollment/MiniMap/index.js | 2 + .../WidgetEnrollment.component.js | 19 +- .../dataMutation/dataMutation.js | 67 +++++ .../WidgetEnrollment/hooks/useGeometry.js | 39 +++ .../WidgetEnrollment/hooks/useProgram.js | 4 +- 30 files changed, 1044 insertions(+), 68 deletions(-) create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/Actions/AddLocation/AddLocation.component.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/Actions/AddLocation/addLocation.types.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/Actions/AddLocation/index.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/Coordinates.component.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/Coordinates.types.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/converters.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/coordinate.validator.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/index.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/MapModal.component.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/MapModal.container.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/MapModal.types.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/ConditionalTooltip.component.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/DeleteControl.component.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/Polygon.component.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/Polygon.types.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/converters.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/index.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MapModal/index.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.component.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.types.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/converters.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/index.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/dataMutation/dataMutation.js create mode 100644 src/core_modules/capture-core/components/WidgetEnrollment/hooks/useGeometry.js diff --git a/i18n/en.pot b/i18n/en.pot index 5078cc26d8..0dd6fab89a 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -1176,6 +1176,33 @@ msgstr "Mark for follow-up" msgid "Existing dates for auto-generated events will not be updated." msgstr "Existing dates for auto-generated events will not be updated." +msgid "Latitude" +msgstr "Latitude" + +msgid "Longitude" +msgstr "Longitude" + +msgid "Edit" +msgstr "Edit" + +msgid "Set coordinates" +msgstr "Set coordinates" + +msgid "Coordinates" +msgstr "Coordinates" + +msgid "Delete polygon" +msgstr "Delete polygon" + +msgid "Close without saving" +msgstr "Close without saving" + +msgid "Finish drawing before saving" +msgstr "Finish drawing before saving" + +msgid "Set area" +msgstr "Set area" + msgid "Enrollment date" msgstr "Enrollment date" @@ -1200,6 +1227,12 @@ msgstr "Last updated {{date}}" msgid "Cancelled" msgstr "Cancelled" +msgid "Add coordinates" +msgstr "Add coordinates" + +msgid "Add area" +msgstr "Add area" + msgid "Comments about this enrollment" msgstr "Comments about this enrollment" @@ -1323,9 +1356,6 @@ msgstr "Profile widget could not be loaded. Please try again later" msgid "{{TETName}} profile" msgstr "{{TETName}} profile" -msgid "Edit" -msgstr "Edit" - msgid "tracked entity instance" msgstr "tracked entity instance" @@ -1572,12 +1602,6 @@ msgstr "To time" msgid "Page {{currentPage}}" msgstr "Page {{currentPage}}" -msgid "Delete polygon" -msgstr "Delete polygon" - -msgid "Set area" -msgstr "Set area" - msgid "Area on map saved" msgstr "Area on map saved" diff --git a/src/core_modules/capture-core/components/Pages/common/EnrollmentOverviewDomain/useCommonEnrollmentDomainData/useCommonEnrollmentDomainData.types.js b/src/core_modules/capture-core/components/Pages/common/EnrollmentOverviewDomain/useCommonEnrollmentDomainData/useCommonEnrollmentDomainData.types.js index 7ca431aa31..688e293955 100644 --- a/src/core_modules/capture-core/components/Pages/common/EnrollmentOverviewDomain/useCommonEnrollmentDomainData/useCommonEnrollmentDomainData.types.js +++ b/src/core_modules/capture-core/components/Pages/common/EnrollmentOverviewDomain/useCommonEnrollmentDomainData/useCommonEnrollmentDomainData.types.js @@ -39,6 +39,7 @@ export type EnrollmentData = {| scheduledAt: string, trackedEntity: string, trackedEntityType: string, + geometry?: ?{ type: string, coordinates: [number, number] | Array<[number, number]>} |}; export type AttributeValue = {| diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/Actions/Actions.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/Actions/Actions.component.js index 4d07c56a61..0c56de8cb1 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/Actions/Actions.component.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/Actions/Actions.component.js @@ -8,8 +8,10 @@ import { Complete } from './Complete'; import { Delete } from './Delete'; import { Followup } from './Followup'; import { AddNew } from './AddNew'; +import { AddLocation } from './AddLocation'; import type { PlainProps } from './actions.types'; import { LoadingMaskForButton } from '../../LoadingMasks'; +import { MapModal } from '../MapModal'; const styles = { actions: { @@ -35,13 +37,14 @@ export const ActionsPlain = ({ onlyEnrollOnce, classes, }: PlainProps) => { - const [open, setOpen] = useState(false); + const [isOpenActions, setOpenActions] = useState(false); + const [isOpenMap, setOpenMap] = useState(false); const handleOnUpdate = (arg) => { - setOpen(prev => !prev); + setOpenActions(false); onUpdate(arg); }; const handleOnDelete = (arg) => { - setOpen(prev => !prev); + setOpenActions(false); onDelete(arg); }; @@ -53,8 +56,8 @@ export const ActionsPlain = ({ small disabled={loading} className={classes.actions} - open={open} - onClick={() => setOpen(prev => !prev)} + open={isOpenActions} + onClick={() => setOpenActions(prev => !prev)} component={ loading ? null : ( @@ -72,6 +75,13 @@ export const ActionsPlain = ({ enrollment={enrollment} onUpdate={handleOnUpdate} /> + { + setOpenMap(true); + setOpenActions(false); + }} + /> + ) } @@ -94,6 +105,11 @@ export const ActionsPlain = ({ {i18n.t('We are processing your request.')} )} + {isOpenMap && } ); }; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/Actions/Actions.container.js b/src/core_modules/capture-core/components/WidgetEnrollment/Actions/Actions.container.js index 2ce98fcb38..1e3bab189e 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/Actions/Actions.container.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/Actions/Actions.container.js @@ -1,24 +1,8 @@ // @flow -import { useDataMutation } from '@dhis2/app-runtime'; import React from 'react'; import { ActionsComponent } from './Actions.component'; import type { Props } from './actions.types'; -import { processErrorReports } from '../processErrorReports'; - -const enrollmentUpdate = { - resource: 'tracker?async=false&importStrategy=UPDATE', - type: 'create', - data: enrollment => ({ - enrollments: [enrollment], - }), -}; -const enrollmentDelete = { - resource: 'tracker?async=false&importStrategy=DELETE', - type: 'create', - data: enrollment => ({ - enrollments: [enrollment], - }), -}; +import { useUpdateEnrollment, useDeleteEnrollment } from '../dataMutation/dataMutation'; export const Actions = ({ enrollment = {}, @@ -29,31 +13,8 @@ export const Actions = ({ onSuccess, ...passOnProps }: Props) => { - const [updateMutation, { loading: updateLoading }] = useDataMutation( - enrollmentUpdate, - { - onComplete: () => { - refetchEnrollment(); - refetchTEI(); - onSuccess && onSuccess(); - }, - onError: (e) => { - onError && onError(processErrorReports(e)); - }, - }, - ); - const [deleteMutation, { loading: deleteLoading }] = useDataMutation( - enrollmentDelete, - { - onComplete: () => { - onDelete(); - onSuccess && onSuccess(); - }, - onError: (e) => { - onError && onError(processErrorReports(e)); - }, - }, - ); + const { updateMutation, updateLoading } = useUpdateEnrollment(refetchEnrollment, refetchTEI, onError); + const { deleteMutation, deleteLoading } = useDeleteEnrollment(onDelete, onError); return ( { + const label = useGeometryLabel(enrollment); + + if (!label) { + return null; + } + + return ( + } + label={label} + onClick={() => setOpenMap(true)} + /> + ); +}; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/Actions/AddLocation/addLocation.types.js b/src/core_modules/capture-core/components/WidgetEnrollment/Actions/AddLocation/addLocation.types.js new file mode 100644 index 0000000000..d004713319 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/Actions/AddLocation/addLocation.types.js @@ -0,0 +1,6 @@ +// @flow + +export type Props = {| + enrollment: Object, + setOpenMap: (toogle: boolean) => void, +|}; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/Actions/AddLocation/index.js b/src/core_modules/capture-core/components/WidgetEnrollment/Actions/AddLocation/index.js new file mode 100644 index 0000000000..bdf4bdca7c --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/Actions/AddLocation/index.js @@ -0,0 +1,2 @@ +// @flow +export { AddLocation } from './AddLocation.component'; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/Coordinates.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/Coordinates.component.js new file mode 100644 index 0000000000..cd9940c11a --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/Coordinates.component.js @@ -0,0 +1,256 @@ +// @flow +import React, { useState, useMemo } from 'react'; +import classNames from 'classnames'; +import i18n from '@dhis2/d2-i18n'; +import { IconCross24, spacers, Modal, ModalTitle, ModalContent, ModalActions, Button, ButtonStrip } from '@dhis2/ui'; +import { ReactLeafletSearch } from 'react-leaflet-search-unpolyfilled'; +import { Map, TileLayer, Marker, withLeaflet } from 'react-leaflet'; +import { withStyles } from '@material-ui/core'; +import type { CoordinatesProps } from './Coordinates.types'; +import { CoordinateInput } from '../../../../../capture-ui/internal/CoordinateInput/CoordinateInput.component'; +import { isEqual } from '../../../../utils/valueEqualityChecker'; +import { isValidCoordinate } from './coordinate.validator'; +import { convertCoordinatesToServer } from './converters'; + +const styles = (theme: Theme) => ({ + modalContent: { + width: '100%', + }, + map: { + width: '100%', + height: 'calc(100vh - 380px)', + }, + inputWrapper: { + paddingTop: spacers.dp8, + display: 'flex', + }, + inputContent: { + flexGrow: 1, + }, + fieldButton: { + height: '42px !important', + width: 42, + borderRadius: '0 !important', + }, + errorContainer: { + backgroundColor: theme.palette.error.lighter, + color: theme.palette.error.main, + }, +}); + +const WrappedLeafletSearch = withLeaflet(ReactLeafletSearch); + +const CoordinatesPlain = ({ + classes, + center: initialCenter, + setOpen, + defaultValues, + onSetCoordinates, +}: CoordinatesProps) => { + const [position, setPosition] = useState(defaultValues); + const [center, setCenter] = useState(initialCenter); + const [tempLatitude, setTempLatitude] = useState(position?.[0]); + const [tempLongitude, setTempLongitude] = useState(position?.[1]); + const [isEditing, setEditing] = useState(!defaultValues); + const [isValid, setValid] = useState(true); + const hasErrors = useMemo(() => { + const changed = !isEqual(position, defaultValues); + return changed && !isValid; + }, [position, defaultValues, isValid]); + + const resetToDefaultValues = () => { + setCenter(initialCenter); + setPosition(defaultValues); + if (defaultValues) { + setTempLatitude(defaultValues[0]); + setTempLongitude(defaultValues[1]); + setEditing(false); + } else { + setTempLatitude(null); + setTempLongitude(null); + } + }; + + const onHandleMapClicked = (mapCoordinates) => { + if (isEditing) { + const { lat, lng } = mapCoordinates.latlng; + const newPosition: [number, number] = [lat, lng]; + setValid(true); + setPosition(newPosition); + setTempLatitude(lat); + setTempLongitude(lng); + } + }; + + const onSearch = (searchPosition: any) => { + setCenter(searchPosition); + setValid(true); + setTempLatitude(searchPosition[0]); + setTempLongitude(searchPosition[1]); + setPosition(searchPosition); + }; + + const renderMap = () => ( + { + if (ref?.leafletElement) { + ref.leafletElement.invalidateSize(); + } + }} + className={classes.map} + onClick={onHandleMapClicked} + > + + + {position && } + + ); + + const renderLatitude = () => ( + { + if (!latitude) { + return; + } + const longitude = tempLongitude || (position?.[1] ? position[1] : undefined); + if (!longitude) { + return; + } + if (!isValidCoordinate({ longitude: Number(longitude), latitude: Number(latitude) })) { + setPosition(null); + setValid(false); + return; + } + setValid(true); + const newPosition = [Number(latitude), longitude]; + setPosition(newPosition); + setCenter(newPosition); + }} + onChange={(latitude) => { + setTempLatitude(latitude); + }} + /> + ); + + const renderLongitude = () => ( + { + if (!longitude) { + return; + } + const latitude = tempLatitude || (position?.[1] ? position[0] : undefined); + if (!latitude) { + return; + } + if (!isValidCoordinate({ longitude: Number(longitude), latitude: Number(latitude) })) { + setPosition(null); + setValid(false); + return; + } + setValid(true); + const newPosition = [latitude, Number(longitude)]; + setPosition(newPosition); + setCenter(newPosition); + }} + onChange={(longitude) => { + setTempLongitude(longitude); + }} + /> + ); + + const renderFieldButton = () => ( +
+ {!isEditing ? ( + + ) : ( +
+ ); + + const renderActions = () => ( + + + + + ); + + return ( + + {i18n.t('Coordinates')} + + {renderMap()} +
+
+
{renderLatitude()}
+
{renderLongitude()}
+ {renderFieldButton()} +
+ {hasErrors && ( +
{i18n.t('Please provide valid coordinates')}
+ )} +
+
+ {renderActions()} +
+ ); +}; +export const Coordinates = withStyles(styles)(CoordinatesPlain); diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/Coordinates.types.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/Coordinates.types.js new file mode 100644 index 0000000000..56e3c5f689 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/Coordinates.types.js @@ -0,0 +1,10 @@ +// @flow + +export type CoordinatesProps = { + center: ?[number, number], + setOpen: (open: boolean) => void, + onSetCoordinates: (coordinates: ?[number, number] | ?Array<[number, number]>) => void, + defaultValues?: ?[number, number], + ...CssClasses, +} + diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/converters.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/converters.js new file mode 100644 index 0000000000..357a034be3 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/converters.js @@ -0,0 +1,11 @@ +// @flow + +export const convertCoordinatesToServer = (coordinates?: Array | null): ?[number, number] => { + if (!coordinates || !coordinates[0]) { + return null; + } + + const lng: number = coordinates[0][1]; + const lat: number = coordinates[0][0]; + return [lng, lat]; +}; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/coordinate.validator.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/coordinate.validator.js new file mode 100644 index 0000000000..1d37df3233 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/coordinate.validator.js @@ -0,0 +1,32 @@ +// @flow + +type Location = { + longitude: number, + latitude: number, +}; + +function isNumValid(num) { + if (typeof num === 'number') { + return true; + } else if (typeof num === 'string') { + return num.match(/[^0-9.,-]+/) === null; + } + + return false; +} + +export const isValidCoordinate = (value: Location) => { + if (!value) { + return false; + } + + const { longitude, latitude } = value; + if (!isNumValid(latitude) || !isNumValid(longitude)) { + return false; + } + + const ld = parseInt(longitude, 10); + const lt = parseInt(latitude, 10); + + return ld >= -180 && ld <= 180 && lt >= -90 && lt <= 90; +}; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/index.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/index.js new file mode 100644 index 0000000000..8d4c2efc14 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Coordinates/index.js @@ -0,0 +1,3 @@ +// @flow +export { Coordinates } from './Coordinates.component'; + diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/MapModal.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/MapModal.component.js new file mode 100644 index 0000000000..355490f756 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/MapModal.component.js @@ -0,0 +1,27 @@ +// @flow +import React from 'react'; +import { dataElementTypes } from '../../../metaData'; +import type { MapModalComponentProps } from './MapModal.types'; +import { Coordinates } from './Coordinates'; +import { Polygon } from './Polygon'; + +export const MapModal = ({ type, center, setOpen, onSetCoordinates, defaultValues }: MapModalComponentProps) => ( + <> + {type === dataElementTypes.COORDINATE && ( + + )} + {type === dataElementTypes.POLYGON && ( + + )} + +); diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/MapModal.container.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/MapModal.container.js new file mode 100644 index 0000000000..b39d141b1d --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/MapModal.container.js @@ -0,0 +1,32 @@ +// @flow +import React, { useCallback } from 'react'; +import { useGeometry } from '../hooks/useGeometry'; +import type { MapModalProps } from './MapModal.types'; +import { MapModal as MapModalComponent } from './MapModal.component'; + +const DEFAULT_CENTER = [51.505, -0.09]; + +export const MapModal = ({ + enrollment, + onUpdate, + setOpenMap, + defaultValues, + center, +}: MapModalProps) => { + const { geometryType, dataElementType } = useGeometry(enrollment); + + const onSetCoordinates = useCallback((coordinates) => { + const geometry = coordinates ? { type: geometryType, coordinates } : null; + onUpdate({ ...enrollment, geometry }); + }, [enrollment, geometryType, onUpdate]); + + return ( + + ); +}; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/MapModal.types.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/MapModal.types.js new file mode 100644 index 0000000000..80a273420b --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/MapModal.types.js @@ -0,0 +1,18 @@ +// @flow +import { dataElementTypes } from '../../../metaData'; + +export type MapModalComponentProps = { + center: ?[number, number], + type: typeof dataElementTypes.COORDINATE | typeof dataElementTypes.POLYGON, + defaultValues?: ?Array> | ?[number, number], + setOpen: (open: boolean) => void, + onSetCoordinates: (coordinates: ?[number, number] | ?Array<[number, number]>) => void, +} + +export type MapModalProps = {| + center?: ?[number, number], + enrollment: Object, + onUpdate: (arg: Object) => void, + setOpenMap: (toggle: boolean) => void, + defaultValues?: ?Array> | ?[number, number], +|}; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/ConditionalTooltip.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/ConditionalTooltip.component.js new file mode 100644 index 0000000000..1250a792d2 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/ConditionalTooltip.component.js @@ -0,0 +1,29 @@ +// @flow +import React from 'react'; +import { Tooltip } from '@dhis2/ui'; + +type Props = { + enabled: boolean, + children: any, +}; + +export const ConditionalTooltip = (props: Props) => { + const { enabled, children, ...passOnProps } = props; + + return enabled ? + ( + { ({ onMouseOver, onMouseOut, ref }) => ( + { + if (btnRef) { + btnRef.onpointerenter = onMouseOver; + btnRef.onpointerleave = onMouseOut; + ref.current = btnRef; + } + }} + > + {children} + + )} + ) : children; +}; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/DeleteControl.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/DeleteControl.component.js new file mode 100644 index 0000000000..3dd18b0e96 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/DeleteControl.component.js @@ -0,0 +1,52 @@ +// @flow +import React, { useEffect, useState, useCallback } from 'react'; +import ReactDOM from 'react-dom'; +import i18n from '@dhis2/d2-i18n'; +import classNames from 'classnames'; +import L, { Control } from 'leaflet'; +import { withLeaflet } from 'react-leaflet'; + +type Props = { + onClick: () => void, + disabled?: ?boolean, + leaflet: typeof Control, +}; + +const DeleteControlPlain = ({ onClick, disabled, leaflet }: Props) => { + const [leafletElement, setLeafletElement] = useState(); + const onHandleClick = useCallback(() => !disabled && onClick(), [disabled, onClick]); + + useEffect(() => { + const deleteControl = L.control({ position: 'topright' }); + const text = i18n.t('Delete polygon'); + const jsx = ( +
+ {/* eslint-disable-next-line */} + +
+ ); + + deleteControl.onAdd = () => { + const div = L.DomUtil.create('div', ''); + ReactDOM.render(jsx, div); + return div; + }; + setLeafletElement(deleteControl); + }, [onHandleClick, disabled]); + + useEffect(() => { + leafletElement && leafletElement.addTo(leaflet.map); + }, [leafletElement, leaflet.map]); + + useEffect(() => () => leafletElement && leafletElement.remove(), [leafletElement]); + + return null; +}; + +export const DeleteControl = withLeaflet(DeleteControlPlain); diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/Polygon.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/Polygon.component.js new file mode 100644 index 0000000000..d1c2eeefe1 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/Polygon.component.js @@ -0,0 +1,225 @@ +// @flow +import React, { useState, useRef } from 'react'; +import i18n from '@dhis2/d2-i18n'; +import { Modal, ModalTitle, ModalContent, ModalActions, Button, ButtonStrip } from '@dhis2/ui'; +import { ReactLeafletSearch } from 'react-leaflet-search-unpolyfilled'; +import { Map, TileLayer, FeatureGroup, withLeaflet } from 'react-leaflet'; +import { EditControl } from 'react-leaflet-draw'; +import L from 'leaflet'; +import { withStyles } from '@material-ui/core'; +import type { PolygonProps, FeatureCollection } from './Polygon.types'; +import { convertPolygonToServer } from './converters'; +import { DeleteControl } from './DeleteControl.component'; +import { ConditionalTooltip } from './ConditionalTooltip.component'; + +const styles = () => ({ + modalContent: { + width: '100%', + }, + map: { + width: '100%', + height: 'calc(100vh - 380px)', + }, + setAreaButton: { + marginLeft: '5px', + }, +}); + +const coordsToFeatureCollection = (inputCoordinates: any): ?FeatureCollection => { + if (!inputCoordinates) { + return null; + } + const list = inputCoordinates[0].length > 2 ? inputCoordinates[0] : inputCoordinates.map(c => [c[1], c[0]]); + + return { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'Polygon', + coordinates: [list], + }, + }, + ], + }; +}; + +const drawing = { + STARTED: 'STARTED', + FINISHED: 'FINISHED', +}; + +const WrappedLeafletSearch = withLeaflet(ReactLeafletSearch); + +const PolygonPlain = ({ + classes, + center: initialCenter, + setOpen, + defaultValues, + onSetCoordinates, +}: PolygonProps) => { + const [polygonArea, setPolygonArea] = useState(defaultValues); + const [center, setCenter] = useState(initialCenter); + const [drawingState, setDrawingState] = useState(undefined); + const prevDrawingState = useRef(undefined); + + const resetToDefaultValues = () => { + setCenter(initialCenter); + setPolygonArea(defaultValues); + }; + + const onMapPolygonCreated = (e: any) => { + const polygonCoordinates = e.layer.toGeoJSON().geometry.coordinates[0].map(c => [c[1], c[0]]); + setPolygonArea(polygonCoordinates); + setDrawingState(drawing.FINISHED); + prevDrawingState.current = drawing.FINISHED; + }; + + const onMapPolygonDelete = () => { + setPolygonArea(null); + setDrawingState(drawing.FINISHED); + prevDrawingState.current = drawing.FINISHED; + }; + + const onSearch = (searchPosition: any) => { + setCenter(searchPosition); + }; + + const getFeatureCollection = () => (Array.isArray(polygonArea) ? coordsToFeatureCollection(polygonArea) : null); + + const renderMap = () => ( + { + if (ref?.leafletElement) { + ref.leafletElement.invalidateSize(); + if (ref.contextValue && polygonArea) { + const { map } = ref.contextValue; + map?.fitBounds(polygonArea); + } + } + }} + className={classes.map} + > + + + { + onFeatureGroupReady(reactFGref, getFeatureCollection()); + }} + > + setDrawingState(drawing.STARTED)} + onDrawStop={() => setDrawingState(prevDrawingState.current)} + draw={{ + rectangle: false, + polyline: false, + circle: false, + marker: false, + circlemarker: false, + }} + edit={{ + remove: false, + edit: false, + }} + /> + + + + ); + + const onFeatureGroupReady = (reactFGref: any, featureCollection: ?FeatureCollection) => { + if (!reactFGref) { + return; + } + if (featureCollection) { + const leafletGeoJSON = new L.GeoJSON(featureCollection); + const leafletFG = reactFGref.leafletElement; + leafletFG.clearLayers(); + + leafletGeoJSON.eachLayer((layer) => { + leafletFG.addLayer(layer); + }); + } else { + const leafletFG = reactFGref.leafletElement; + leafletFG.clearLayers(); + } + }; + + const renderActions = () => ( + + {!drawingState && ( + + )} + {drawingState && ( + <> + + + + + + )} + + ); + + return ( + + {i18n.t('Area')} + {renderMap()} + {renderActions()} + + ); +}; + +export const Polygon = withStyles(styles)(PolygonPlain); diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/Polygon.types.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/Polygon.types.js new file mode 100644 index 0000000000..024be1b432 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/Polygon.types.js @@ -0,0 +1,24 @@ +// @flow + +type Feature = { + type: string, + properties: Object, + geometry: { + type: string, + coordinates: Array | number>>, + }, +} + +export type FeatureCollection = { + type: string, + features: Array, +}; + +export type PolygonProps = { + center: ?[number, number], + setOpen: (open: boolean) => void, + onSetCoordinates: (coordinates: ?[number, number] | ?Array<[number, number]>) => void, + defaultValues?: ?Array>, + ...CssClasses, +} + diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/converters.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/converters.js new file mode 100644 index 0000000000..15556ee8c2 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/converters.js @@ -0,0 +1,8 @@ +// @flow + +export const convertPolygonToServer = (coordinates?: Array> | null): ?Array<[number, number]> => { + if (!coordinates) { + return null; + } + return Array<[number, number]>(coordinates.map(c => (c ? [c[1], c[0]] : null))); +}; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/index.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/index.js new file mode 100644 index 0000000000..04659c427b --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/Polygon/index.js @@ -0,0 +1,3 @@ +// @flow +export { Polygon } from './Polygon.component'; + diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/index.js b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/index.js new file mode 100644 index 0000000000..41266d1ca4 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MapModal/index.js @@ -0,0 +1,3 @@ +// @flow +export { MapModal } from './MapModal.container'; + diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.component.js new file mode 100644 index 0000000000..a8d3304847 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.component.js @@ -0,0 +1,80 @@ +// @flow +import React, { useState } from 'react'; +import { Map, TileLayer, Marker, Polygon } from 'react-leaflet'; +import { withStyles } from '@material-ui/core'; +import { dataElementTypes } from '../../../metaData'; +import { MapModal } from '../MapModal'; +import type { MiniMapProps } from './MiniMap.types'; +import { convertToClientCoordinates } from './converters'; +import { useUpdateEnrollment } from '../dataMutation/dataMutation'; + +const styles = () => ({ + mapContainer: { + width: 150, + height: 120, + }, + map: { + width: '100%', + height: '100%', + }, +}); + +const MiniMapPlain = ({ + coordinates, + geometryType, + enrollment, + refetchEnrollment, + refetchTEI, + onError, + classes, +}: MiniMapProps) => { + const [isOpenMap, setOpenMap] = useState(false); + const { updateMutation } = useUpdateEnrollment(refetchEnrollment, refetchTEI, onError); + const clientValues = convertToClientCoordinates(coordinates, geometryType); + const center = geometryType === dataElementTypes.COORDINATE ? clientValues : clientValues[0]; + const onMapReady = (mapRef) => { + if (mapRef?.contextValue && geometryType === dataElementTypes.POLYGON) { + const { map } = mapRef.contextValue; + map?.fitBounds(clientValues); + } + }; + + return ( + <> +
+ { + onMapReady(mapRef); + }} + center={center} + className={classes.map} + zoom={11} + zoomControl={false} + attributionControl={false} + key="minimap" + onClick={() => { + setOpenMap(true); + }} + > + + {geometryType === dataElementTypes.COORDINATE && } + {geometryType === dataElementTypes.POLYGON && } + +
+ {isOpenMap && ( + + )} + + ); +}; + +export const MiniMap = withStyles(styles)(MiniMapPlain); diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.types.js b/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.types.js new file mode 100644 index 0000000000..b905c28783 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.types.js @@ -0,0 +1,13 @@ +// @flow +import type { QueryRefetchFunction } from '@dhis2/app-runtime'; +import { dataElementTypes } from '../../../metaData'; + +export type MiniMapProps = { + coordinates: Array>, + enrollment: any, + refetchEnrollment: QueryRefetchFunction, + refetchTEI: QueryRefetchFunction, + onError?: (message: string) => void, + geometryType: typeof dataElementTypes.COORDINATE | typeof dataElementTypes.POLYGON, + ...CssClasses +} diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/converters.js b/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/converters.js new file mode 100644 index 0000000000..498738ef13 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/converters.js @@ -0,0 +1,10 @@ +// @flow +import { dataElementTypes } from '../../../metaData'; + +export const convertToClientCoordinates = (coordinates: any[], type: $Values) => { + if (type === dataElementTypes.COORDINATE) { + return [coordinates[1], coordinates[0]]; + } + + return coordinates[0].map(coord => [coord[1], coord[0]]); +}; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/index.js b/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/index.js new file mode 100644 index 0000000000..c1e7fa0e6f --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/index.js @@ -0,0 +1,2 @@ +// @flow +export { MiniMap } from './MiniMap.component'; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/WidgetEnrollment.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/WidgetEnrollment.component.js index d9d400d044..018a6e7798 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/WidgetEnrollment.component.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/WidgetEnrollment.component.js @@ -4,7 +4,6 @@ import moment from 'moment'; import { IconClock16, IconDimensionOrgUnit16, - IconLocation16, colors, Tag, spacersNum, @@ -16,12 +15,11 @@ import { LoadingMaskElementCenter } from '../LoadingMasks'; import { Widget } from '../Widget'; import type { PlainProps } from './enrollment.types'; import { Status } from './Status'; -import { convertValue as convertValueServerToClient } from '../../converters/serverToClient'; -import { convertValue as convertValueClientToView } from '../../converters/clientToView'; import { dataElementTypes } from '../../metaData'; import { useOrgUnitName } from '../../metadataRetrieval/orgUnitName'; import { Date } from './Date'; import { Actions } from './Actions'; +import { MiniMap } from './MiniMap'; const styles = { enrollment: { @@ -152,13 +150,14 @@ export const WidgetEnrollmentPlain = ({ {enrollment.geometry && (
- - - - {convertValueClientToView( - convertValueServerToClient(enrollment.geometry.coordinates, geometryType), - geometryType, - )} +
)} ({ + enrollments: [enrollment], + }), +}; + +const enrollmentDelete = { + resource: 'tracker?async=false&importStrategy=DELETE', + type: 'create', + data: enrollment => ({ + enrollments: [enrollment], + }), +}; + +const processErrorReports = (error) => { + // $FlowFixMe[prop-missing] + const errorReports = error?.details?.validationReport?.errorReports; + return errorReports?.length > 0 + ? errorReports.reduce((acc, errorReport) => `${acc} ${errorReport.message}`, '') + : error.message; +}; + + +export const useUpdateEnrollment = ( + refetchEnrollment: QueryRefetchFunction, + refetchTEI: QueryRefetchFunction, + onError?: ?(message: string) => void, +) => { + const [updateMutation, { loading: updateLoading }] = useDataMutation( + enrollmentUpdate, + { + onComplete: () => { + refetchEnrollment(); + refetchTEI(); + }, + onError: (e) => { + onError && onError(processErrorReports(e)); + }, + }, + ); + return { + updateMutation, updateLoading, + }; +}; + +export const useDeleteEnrollment = ( + onDelete: () => void, + onError?: ?(message: string) => void, +) => { + const [deleteMutation, { loading: deleteLoading }] = useDataMutation( + enrollmentDelete, + { + onComplete: onDelete, + onError: (e) => { + onError && onError(processErrorReports(e)); + }, + }, + ); + return { deleteMutation, deleteLoading }; +}; + diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/hooks/useGeometry.js b/src/core_modules/capture-core/components/WidgetEnrollment/hooks/useGeometry.js new file mode 100644 index 0000000000..3569c211db --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetEnrollment/hooks/useGeometry.js @@ -0,0 +1,39 @@ +// @flow +import i18n from '@dhis2/d2-i18n'; +import { dataElementTypes } from '../../../metaData'; +import { useProgram } from './useProgram'; + +export const useGeometry = (enrollment: { program: string }) => { + const { + program: { featureType }, + } = useProgram(enrollment.program); + + if (featureType === 'POINT') { + return { + geometryType: 'Point', + dataElementType: dataElementTypes.COORDINATE, + }; + } + + return { + geometryType: 'Polygon', + dataElementType: dataElementTypes.POLYGON, + }; +}; + +export const useGeometryLabel = (enrollment: { program: string, geometry: { type: string } }) => { + const { + program: { featureType }, + error, + } = useProgram(enrollment.program); + + if (error || !featureType || !['POINT', 'POLYGON'].includes(featureType) || enrollment.geometry?.type) { + return undefined; + } + + if (featureType === 'POINT') { + return i18n.t('Add coordinates'); + } + + return i18n.t('Add area'); +}; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/hooks/useProgram.js b/src/core_modules/capture-core/components/WidgetEnrollment/hooks/useProgram.js index 4d643cb140..de41c3692e 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/hooks/useProgram.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/hooks/useProgram.js @@ -10,7 +10,7 @@ export const useProgram = (programId: string) => { resource: `programs/${programId}`, params: { fields: [ - 'displayIncidentDate,displayIncidentDateLabel,displayEnrollmentDateLabel,onlyEnrollOnce,trackedEntityType[displayName],programStages[autoGenerateEvent],access', + 'displayIncidentDate,displayIncidentDateLabel,displayEnrollmentDateLabel,onlyEnrollOnce,trackedEntityType[displayName],programStages[autoGenerateEvent],access,featureType', ], }, }, @@ -18,5 +18,5 @@ export const useProgram = (programId: string) => { [programId], ), ); - return { error, program: !loading && data?.program }; + return { error, loading, program: data?.program }; }; From 05d268e7b022f643d1e7ff919d41280f061a3ddc Mon Sep 17 00:00:00 2001 From: "@dhis2-bot" Date: Mon, 20 Nov 2023 10:49:34 +0000 Subject: [PATCH 06/18] chore(release): cut 100.45.0 [skip release] # [100.45.0](https://github.com/dhis2/capture-app/compare/v100.44.7...v100.45.0) (2023-11-20) ### Features * [DHIS2-13237] Enrollment coordinates in enrollment widget ([#3141](https://github.com/dhis2/capture-app/issues/3141)) ([2f2e52c](https://github.com/dhis2/capture-app/commit/2f2e52c3103e9cb48e77766701a9a5fc9af6ad48)) --- CHANGELOG.md | 7 +++++++ package.json | 4 ++-- packages/rules-engine/package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1ac4613a7..a096db949f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [100.45.0](https://github.com/dhis2/capture-app/compare/v100.44.7...v100.45.0) (2023-11-20) + + +### Features + +* [DHIS2-13237] Enrollment coordinates in enrollment widget ([#3141](https://github.com/dhis2/capture-app/issues/3141)) ([2f2e52c](https://github.com/dhis2/capture-app/commit/2f2e52c3103e9cb48e77766701a9a5fc9af6ad48)) + ## [100.44.7](https://github.com/dhis2/capture-app/compare/v100.44.6...v100.44.7) (2023-11-19) diff --git a/package.json b/package.json index b19003534a..05175c3689 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "capture-app", "homepage": ".", - "version": "100.44.7", + "version": "100.45.0", "cacheVersion": "7", "serverVersion": "38", "license": "BSD-3-Clause", @@ -10,7 +10,7 @@ "packages/rules-engine" ], "dependencies": { - "@dhis2/rules-engine-javascript": "100.44.7", + "@dhis2/rules-engine-javascript": "100.45.0", "@dhis2/app-runtime": "^3.9.3", "@dhis2/d2-i18n": "^1.1.0", "@dhis2/d2-icons": "^1.0.1", diff --git a/packages/rules-engine/package.json b/packages/rules-engine/package.json index d6850c1d71..dc15c3fc58 100644 --- a/packages/rules-engine/package.json +++ b/packages/rules-engine/package.json @@ -1,6 +1,6 @@ { "name": "@dhis2/rules-engine-javascript", - "version": "100.44.7", + "version": "100.45.0", "license": "BSD-3-Clause", "main": "./build/cjs/index.js", "scripts": { From 8f28703ae8b56cfee283ec1ce0ec2b13dfd91e30 Mon Sep 17 00:00:00 2001 From: "@dhis2-bot" Date: Sun, 26 Nov 2023 02:37:35 +0100 Subject: [PATCH 07/18] fix(translations): sync translations from transifex (master) Automatically merged. --- i18n/uz_UZ_Cyrl.po | 77 +++++++++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/i18n/uz_UZ_Cyrl.po b/i18n/uz_UZ_Cyrl.po index 7d62b3a5cd..620b5591f9 100644 --- a/i18n/uz_UZ_Cyrl.po +++ b/i18n/uz_UZ_Cyrl.po @@ -177,6 +177,7 @@ msgstr "" msgid "Saving a {{trackedEntityName}} in {{programName}} in {{orgUnitName}}." msgstr "" +"Сақланмоқда {{trackedEntityName}} да {{programName}} да {{orgUnitName}}." msgid "Cancel" msgstr "Бекор қилиш" @@ -212,7 +213,7 @@ msgid "Assignee" msgstr "Ваколат берилган шахс" msgid "Saving to {{programName}} in {{orgUnitName}}" -msgstr "" +msgstr "Сақланади {{programName}} да {{orgUnitName}}" msgid "" "This is not an event program or the metadata is corrupt. See log for " @@ -250,7 +251,7 @@ msgid "Finish" msgstr "Тугатиш" msgid "Save without completing" -msgstr "" +msgstr "Тугалланмасдан сақлаш" msgid "Complete" msgstr "Тўлдириш" @@ -673,36 +674,38 @@ msgid "" msgstr "" msgid "Enrollment Dashboard" -msgstr "" +msgstr "Қайд этиш панели" msgid "No indicator output for this enrollment yet" -msgstr "" +msgstr "Ушбу қайд этишда индикатор ахбороти мавжуд эмас" msgid "No feedback for this enrollment yet" -msgstr "" +msgstr "Ушбу қайд этишда қайта алоқа ахбороти мавжуд эмас" msgid "Quick actions" -msgstr "" +msgstr "Тезкор харакатлар" msgid "New Event" -msgstr "" +msgstr "Янги Ҳодиса/Ҳолат" msgid "Schedule an event" -msgstr "" +msgstr "Ҳодиса/Ҳолатни режалаш" msgid "Make referral" msgstr "Йўналиш яратинг" msgid "No available program stages" -msgstr "" +msgstr "Дастур босқичлари мавжуд эмас" msgid "Program stage not found" -msgstr "" +msgstr "Дастур босқичлари топилмади" msgid "" "Choose a program to add new or see existing enrollments for " "{{teiDisplayName}}" msgstr "" +" {{teiDisplayName}} учун янги рўйхатга ёки мавжуд рўйхатга олишларини кўриш " +"учун дастурни танланг." msgid "" "{{programName}} has categories. Choose all categories to view dashboard." @@ -713,7 +716,7 @@ msgid "Invalid enrollment id {{enrollmentId}}." msgstr "" msgid "Choose an enrollment to view the dashboard." -msgstr "" +msgstr "бошқарув панелини кўриш учун рўйхатдан ўтишни танланг." msgid "There are no active enrollments." msgstr "" @@ -751,19 +754,19 @@ msgid "View working list in this program." msgstr "Ушбу дастурдаги ишчи рўйхатни кўриб чиқиш" msgid "Page is missing required values from URL" -msgstr "" +msgstr "URL саҳифасида керакли қийматлар йўқ" msgid "Program is not valid" -msgstr "" +msgstr "Дастур яроқли эмас" msgid "Org unit is not valid with current program" -msgstr "" +msgstr "Жорий дастур учун ташкилий бирлик яроқли эмас" msgid "There was an error opening the Page" -msgstr "" +msgstr "Саҳифани очишда хатолик мавжуд" msgid "Enrollment{{escape}} New Event" -msgstr "" +msgstr "Рўйхатга олишда {{escape}} Янги Ҳодиса/Ҳолат" msgid "There was an error loading the page" msgstr "" @@ -1174,6 +1177,33 @@ msgstr "Кузатув учун белгиланг" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Кенглик" + +msgid "Longitude" +msgstr "" + +msgid "Edit" +msgstr "Таҳрирлаш" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "Координаталар" + +msgid "Delete polygon" +msgstr "Полигон (кўпбурчак) ни ўчириб ташлаш" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "Ҳудудни белгиланг" + msgid "Enrollment date" msgstr "Қайд этилган сана" @@ -1199,6 +1229,12 @@ msgstr " {{date}}да охирги марта янгиланган" msgid "Cancelled" msgstr "Бекор қилинди" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1322,9 +1358,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "Таҳрирлаш" - msgid "tracked entity instance" msgstr "кузатилаётган объект намунаси" @@ -1572,12 +1605,6 @@ msgstr "Шу вақтгача" msgid "Page {{currentPage}}" msgstr "{{currentPage}} саҳифаси" -msgid "Delete polygon" -msgstr "Полигон (кўпбурчак) ни ўчириб ташлаш" - -msgid "Set area" -msgstr "Ҳудудни белгиланг" - msgid "Area on map saved" msgstr "" From fad338ddac06ca6d984ef40a5be3a562f1611197 Mon Sep 17 00:00:00 2001 From: "@dhis2-bot" Date: Sun, 26 Nov 2023 01:44:31 +0000 Subject: [PATCH 08/18] chore(release): cut 100.45.1 [skip release] ## [100.45.1](https://github.com/dhis2/capture-app/compare/v100.45.0...v100.45.1) (2023-11-26) ### Bug Fixes * **translations:** sync translations from transifex (master) ([8f28703](https://github.com/dhis2/capture-app/commit/8f28703ae8b56cfee283ec1ce0ec2b13dfd91e30)) --- CHANGELOG.md | 7 +++++++ package.json | 4 ++-- packages/rules-engine/package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a096db949f..364f1d18d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [100.45.1](https://github.com/dhis2/capture-app/compare/v100.45.0...v100.45.1) (2023-11-26) + + +### Bug Fixes + +* **translations:** sync translations from transifex (master) ([8f28703](https://github.com/dhis2/capture-app/commit/8f28703ae8b56cfee283ec1ce0ec2b13dfd91e30)) + # [100.45.0](https://github.com/dhis2/capture-app/compare/v100.44.7...v100.45.0) (2023-11-20) diff --git a/package.json b/package.json index 05175c3689..70d4742f93 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "capture-app", "homepage": ".", - "version": "100.45.0", + "version": "100.45.1", "cacheVersion": "7", "serverVersion": "38", "license": "BSD-3-Clause", @@ -10,7 +10,7 @@ "packages/rules-engine" ], "dependencies": { - "@dhis2/rules-engine-javascript": "100.45.0", + "@dhis2/rules-engine-javascript": "100.45.1", "@dhis2/app-runtime": "^3.9.3", "@dhis2/d2-i18n": "^1.1.0", "@dhis2/d2-icons": "^1.0.1", diff --git a/packages/rules-engine/package.json b/packages/rules-engine/package.json index dc15c3fc58..017039b19c 100644 --- a/packages/rules-engine/package.json +++ b/packages/rules-engine/package.json @@ -1,6 +1,6 @@ { "name": "@dhis2/rules-engine-javascript", - "version": "100.45.0", + "version": "100.45.1", "license": "BSD-3-Clause", "main": "./build/cjs/index.js", "scripts": { From 2dbca1efe36ed0e166d4aea803505c30c79cb35d Mon Sep 17 00:00:00 2001 From: eirikhaugstulen Date: Wed, 29 Nov 2023 13:26:44 +0100 Subject: [PATCH 09/18] fix: [DHIS2-15693] Rules not triggered on program update (#3472) --- .../EnrollmentRegistrationEntry/hooks/useLifecycle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useLifecycle.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useLifecycle.js index 4a84d7ccb7..a9b0eda796 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useLifecycle.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useLifecycle.js @@ -45,7 +45,7 @@ export const useLifecycle = ( }); useEffect(() => { dataEntryReadyRef.current = false; - }, [teiId]); + }, [teiId, selectedScopeId]); useEffect(() => { if ( From 9e60cf78c7205423b2f0aa9ccb30909dd2e049fa Mon Sep 17 00:00:00 2001 From: "@dhis2-bot" Date: Wed, 29 Nov 2023 12:33:21 +0000 Subject: [PATCH 10/18] chore(release): cut 100.45.2 [skip release] ## [100.45.2](https://github.com/dhis2/capture-app/compare/v100.45.1...v100.45.2) (2023-11-29) ### Bug Fixes * [DHIS2-15693] Rules not triggered on program update ([#3472](https://github.com/dhis2/capture-app/issues/3472)) ([2dbca1e](https://github.com/dhis2/capture-app/commit/2dbca1efe36ed0e166d4aea803505c30c79cb35d)) --- CHANGELOG.md | 7 +++++++ package.json | 4 ++-- packages/rules-engine/package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 364f1d18d5..a28036713d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [100.45.2](https://github.com/dhis2/capture-app/compare/v100.45.1...v100.45.2) (2023-11-29) + + +### Bug Fixes + +* [DHIS2-15693] Rules not triggered on program update ([#3472](https://github.com/dhis2/capture-app/issues/3472)) ([2dbca1e](https://github.com/dhis2/capture-app/commit/2dbca1efe36ed0e166d4aea803505c30c79cb35d)) + ## [100.45.1](https://github.com/dhis2/capture-app/compare/v100.45.0...v100.45.1) (2023-11-26) diff --git a/package.json b/package.json index 70d4742f93..a3a3e55966 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "capture-app", "homepage": ".", - "version": "100.45.1", + "version": "100.45.2", "cacheVersion": "7", "serverVersion": "38", "license": "BSD-3-Clause", @@ -10,7 +10,7 @@ "packages/rules-engine" ], "dependencies": { - "@dhis2/rules-engine-javascript": "100.45.1", + "@dhis2/rules-engine-javascript": "100.45.2", "@dhis2/app-runtime": "^3.9.3", "@dhis2/d2-i18n": "^1.1.0", "@dhis2/d2-icons": "^1.0.1", diff --git a/packages/rules-engine/package.json b/packages/rules-engine/package.json index 017039b19c..360a957889 100644 --- a/packages/rules-engine/package.json +++ b/packages/rules-engine/package.json @@ -1,6 +1,6 @@ { "name": "@dhis2/rules-engine-javascript", - "version": "100.45.1", + "version": "100.45.2", "license": "BSD-3-Clause", "main": "./build/cjs/index.js", "scripts": { From 2404fca8085965e699ae518cfe816f2f3d38dea7 Mon Sep 17 00:00:00 2001 From: eirikhaugstulen Date: Thu, 30 Nov 2023 13:20:00 +0100 Subject: [PATCH 11/18] feat: [DHIS2-14275] Support custom icons (#3473) --- cypress/e2e/MainPage.feature | 12 ++++++++++++ cypress/e2e/MainPage/index.js | 12 ++++++++++++ .../capture-core-utils/featuresSupport/support.js | 2 ++ .../NonBundledDhis2Icon.component.js | 11 +++++++++-- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/cypress/e2e/MainPage.feature b/cypress/e2e/MainPage.feature index 70a5430db6..980d9fd1e2 100644 --- a/cypress/e2e/MainPage.feature +++ b/cypress/e2e/MainPage.feature @@ -42,3 +42,15 @@ Feature: User interacts with Main page Then you see the opt out component for Child Programme When you opt out to use the new enrollment Dashboard for Child Programme Then you see the opt in component for Child Programme + + @v<41 + Scenario: The icon is rendered as an svg + Given you are in the main page with no selections made + When you select Child Programme + Then the icon is rendered as an svg + + @v>=41 + Scenario: The icon is rendered as a custom icon + Given you are in the main page with no selections made + When you select Child Programme + Then the icon is rendered as a custom icon diff --git a/cypress/e2e/MainPage/index.js b/cypress/e2e/MainPage/index.js index f004659122..6090ac6fb5 100644 --- a/cypress/e2e/MainPage/index.js +++ b/cypress/e2e/MainPage/index.js @@ -20,6 +20,18 @@ And('you can load the view with the name Events assigned to me', () => { }); }); +Then('the icon is rendered as a custom icon', () => { + cy.get('[alt="child_program_positive"]') + .invoke('attr', 'src') + .should('match', /\/icons\/child_program_positive\/icon$/); +}); + +Then('the icon is rendered as an svg', () => { + cy.get('[alt="child_program_positive"]') + .invoke('attr', 'src') + .should('match', /\/icons\/child_program_positive\/icon.svg$/); +}); + Then('the TEI working list is displayed', () => { cy.get('[data-test="tei-working-lists"]').within(() => { cy.contains('Rows per page').should('exist'); diff --git a/src/core_modules/capture-core-utils/featuresSupport/support.js b/src/core_modules/capture-core-utils/featuresSupport/support.js index 0b31bf6dd9..207c929c21 100644 --- a/src/core_modules/capture-core-utils/featuresSupport/support.js +++ b/src/core_modules/capture-core-utils/featuresSupport/support.js @@ -2,12 +2,14 @@ export const FEATURES = Object.freeze({ programStageWorkingList: 'programStageWorkingList', storeProgramStageWorkingList: 'storeProgramStageWorkingList', + customIcons: 'customIcons', }); // The first minor version that supports the feature const MINOR_VERSION_SUPPORT = Object.freeze({ [FEATURES.programStageWorkingList]: 39, [FEATURES.storeProgramStageWorkingList]: 40, + [FEATURES.customIcons]: 41, }); export const hasAPISupportForFeature = (minorVersion: string, featureName: string) => diff --git a/src/core_modules/capture-core/components/NonBundledDhis2Icon/NonBundledDhis2Icon.component.js b/src/core_modules/capture-core/components/NonBundledDhis2Icon/NonBundledDhis2Icon.component.js index b16ac14c1e..c6dc0002eb 100644 --- a/src/core_modules/capture-core/components/NonBundledDhis2Icon/NonBundledDhis2Icon.component.js +++ b/src/core_modules/capture-core/components/NonBundledDhis2Icon/NonBundledDhis2Icon.component.js @@ -1,13 +1,20 @@ // @flow import React from 'react'; import { useConfig } from '@dhis2/app-runtime'; -import { buildUrl } from 'capture-core-utils'; +import { buildUrl, FEATURES, useFeature } from 'capture-core-utils'; import { NonBundledIcon } from 'capture-ui'; import type { Props } from './nonBundledDhis2Icon.types'; export const NonBundledDhis2Icon = ({ name, alternativeText = name, ...passOnProps }: Props) => { + const supportCustomIcons = useFeature(FEATURES.customIcons); const { baseUrl, apiVersion } = useConfig(); - const source = name && buildUrl(baseUrl, `api/${apiVersion}/icons/${name}/icon.svg`); + let source; + + if (name) { + source = buildUrl(baseUrl, `api/${apiVersion}/icons/${name}/icon`); + // Append .svg to source if supportCustomIcons is false (feature flag v41) + source = supportCustomIcons ? source : `${source}.svg`; + } return ( Date: Thu, 30 Nov 2023 12:31:48 +0000 Subject: [PATCH 12/18] chore(release): cut 100.46.0 [skip release] # [100.46.0](https://github.com/dhis2/capture-app/compare/v100.45.2...v100.46.0) (2023-11-30) ### Features * [DHIS2-14275] Support custom icons ([#3473](https://github.com/dhis2/capture-app/issues/3473)) ([2404fca](https://github.com/dhis2/capture-app/commit/2404fca8085965e699ae518cfe816f2f3d38dea7)) --- CHANGELOG.md | 7 +++++++ package.json | 4 ++-- packages/rules-engine/package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a28036713d..97013b7aa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [100.46.0](https://github.com/dhis2/capture-app/compare/v100.45.2...v100.46.0) (2023-11-30) + + +### Features + +* [DHIS2-14275] Support custom icons ([#3473](https://github.com/dhis2/capture-app/issues/3473)) ([2404fca](https://github.com/dhis2/capture-app/commit/2404fca8085965e699ae518cfe816f2f3d38dea7)) + ## [100.45.2](https://github.com/dhis2/capture-app/compare/v100.45.1...v100.45.2) (2023-11-29) diff --git a/package.json b/package.json index a3a3e55966..cd12b9b935 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "capture-app", "homepage": ".", - "version": "100.45.2", + "version": "100.46.0", "cacheVersion": "7", "serverVersion": "38", "license": "BSD-3-Clause", @@ -10,7 +10,7 @@ "packages/rules-engine" ], "dependencies": { - "@dhis2/rules-engine-javascript": "100.45.2", + "@dhis2/rules-engine-javascript": "100.46.0", "@dhis2/app-runtime": "^3.9.3", "@dhis2/d2-i18n": "^1.1.0", "@dhis2/d2-icons": "^1.0.1", diff --git a/packages/rules-engine/package.json b/packages/rules-engine/package.json index 360a957889..b53e6943e0 100644 --- a/packages/rules-engine/package.json +++ b/packages/rules-engine/package.json @@ -1,6 +1,6 @@ { "name": "@dhis2/rules-engine-javascript", - "version": "100.45.2", + "version": "100.46.0", "license": "BSD-3-Clause", "main": "./build/cjs/index.js", "scripts": { From a24bb2723f06cd4a3ca87bbbb22977b097377b3c Mon Sep 17 00:00:00 2001 From: Tony Valle <79843014+superskip@users.noreply.github.com> Date: Thu, 30 Nov 2023 13:46:51 +0100 Subject: [PATCH 13/18] fix: [DHIS2-15686] fix program rule variables for edit profile mode (#3463) --- .../WidgetProfile/DataEntry/ProgramRules/rulesContainer.js | 3 ++- .../components/WidgetProfile/DataEntry/hooks/useEvents.js | 6 +++--- .../WidgetProfile/DataEntry/hooks/useLifecycle.js | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/core_modules/capture-core/components/WidgetProfile/DataEntry/ProgramRules/rulesContainer.js b/src/core_modules/capture-core/components/WidgetProfile/DataEntry/ProgramRules/rulesContainer.js index bb75e2a61d..554648322a 100644 --- a/src/core_modules/capture-core/components/WidgetProfile/DataEntry/ProgramRules/rulesContainer.js +++ b/src/core_modules/capture-core/components/WidgetProfile/DataEntry/ProgramRules/rulesContainer.js @@ -1,12 +1,13 @@ // @flow import type { ProgramRulesContainer } from '@dhis2/rules-engine-javascript'; -import { getTrackedEntityAttributeId, getProgramId, getProgramRuleActions, getProgramStageId } from '../helpers'; +import { getTrackedEntityAttributeId, getDataElementId, getProgramId, getProgramRuleActions, getProgramStageId } from '../helpers'; import { getRulesAndVariablesFromProgramIndicators } from '../../../../metaDataMemoryStoreBuilders/programs/getRulesAndVariablesFromIndicators'; const addProgramVariables = (program, programRuleVariables) => { program.programRuleVariables = programRuleVariables.map(programRulesVariable => ({ ...programRulesVariable, programId: getProgramId(programRulesVariable), + dataElementId: getDataElementId(programRulesVariable), trackedEntityAttributeId: getTrackedEntityAttributeId(programRulesVariable), })); }; diff --git a/src/core_modules/capture-core/components/WidgetProfile/DataEntry/hooks/useEvents.js b/src/core_modules/capture-core/components/WidgetProfile/DataEntry/hooks/useEvents.js index 0c900af9a4..6e606a08d4 100644 --- a/src/core_modules/capture-core/components/WidgetProfile/DataEntry/hooks/useEvents.js +++ b/src/core_modules/capture-core/components/WidgetProfile/DataEntry/hooks/useEvents.js @@ -10,7 +10,7 @@ const getClientFormattedDataValuesAsObject = (dataValues, elementsById) => dataValues.reduce((acc, { dataElement: id, value }) => { const dataElement = elementsById[id]; if (dataElement) { - acc[id] = convertValue(value, elementsById[id].type); + acc[id] = convertValue(value, dataElement.valueType); } return acc; }, {}); @@ -39,8 +39,8 @@ export const useEvents = (enrollment: any, elementsById: Array) => { enrollmentId: event.enrollment, enrollmentStatus: event.enrollmentStatus, status: event.status, - eventDate: convertDate(event.eventDate), - dueDate: convertDate(event.dueDate), + occurredAt: convertDate(event.occurredAt), + scheduledAt: convertDate(event.scheduledAt), ...getClientFormattedDataValuesAsObject(event.dataValues, elementsById), })), [elementsById, enrollment, orgUnitNames], diff --git a/src/core_modules/capture-core/components/WidgetProfile/DataEntry/hooks/useLifecycle.js b/src/core_modules/capture-core/components/WidgetProfile/DataEntry/hooks/useLifecycle.js index ce75b815f8..c60464a921 100644 --- a/src/core_modules/capture-core/components/WidgetProfile/DataEntry/hooks/useLifecycle.js +++ b/src/core_modules/capture-core/components/WidgetProfile/DataEntry/hooks/useLifecycle.js @@ -49,7 +49,7 @@ export const useLifecycle = ({ const state = useSelector(stateArg => stateArg); const enrollment = useSelector(({ enrollmentDomain }) => enrollmentDomain?.enrollment); const dataElements: DataElements = useDataElements(programAPI); - const otherEvents = useEvents(enrollment, programAPI); + const otherEvents = useEvents(enrollment, dataElements); const orgUnit: ?OrgUnit = useOrganisationUnit(orgUnitId).orgUnit; const rulesContainer: ProgramRulesContainer = useRulesContainer(programAPI); const formFoundation: RenderFoundation = useFormFoundation(programAPI); From 47a95b2989880af8264f63409b57b9bf7043776e Mon Sep 17 00:00:00 2001 From: "@dhis2-bot" Date: Thu, 30 Nov 2023 13:02:09 +0000 Subject: [PATCH 14/18] chore(release): cut 100.46.1 [skip release] ## [100.46.1](https://github.com/dhis2/capture-app/compare/v100.46.0...v100.46.1) (2023-11-30) ### Bug Fixes * [DHIS2-15686] fix program rule variables for edit profile mode ([#3463](https://github.com/dhis2/capture-app/issues/3463)) ([a24bb27](https://github.com/dhis2/capture-app/commit/a24bb2723f06cd4a3ca87bbbb22977b097377b3c)) --- CHANGELOG.md | 7 +++++++ package.json | 4 ++-- packages/rules-engine/package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97013b7aa0..7b603a0b17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [100.46.1](https://github.com/dhis2/capture-app/compare/v100.46.0...v100.46.1) (2023-11-30) + + +### Bug Fixes + +* [DHIS2-15686] fix program rule variables for edit profile mode ([#3463](https://github.com/dhis2/capture-app/issues/3463)) ([a24bb27](https://github.com/dhis2/capture-app/commit/a24bb2723f06cd4a3ca87bbbb22977b097377b3c)) + # [100.46.0](https://github.com/dhis2/capture-app/compare/v100.45.2...v100.46.0) (2023-11-30) diff --git a/package.json b/package.json index cd12b9b935..4648cadedc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "capture-app", "homepage": ".", - "version": "100.46.0", + "version": "100.46.1", "cacheVersion": "7", "serverVersion": "38", "license": "BSD-3-Clause", @@ -10,7 +10,7 @@ "packages/rules-engine" ], "dependencies": { - "@dhis2/rules-engine-javascript": "100.46.0", + "@dhis2/rules-engine-javascript": "100.46.1", "@dhis2/app-runtime": "^3.9.3", "@dhis2/d2-i18n": "^1.1.0", "@dhis2/d2-icons": "^1.0.1", diff --git a/packages/rules-engine/package.json b/packages/rules-engine/package.json index b53e6943e0..ff1415cd4f 100644 --- a/packages/rules-engine/package.json +++ b/packages/rules-engine/package.json @@ -1,6 +1,6 @@ { "name": "@dhis2/rules-engine-javascript", - "version": "100.46.0", + "version": "100.46.1", "license": "BSD-3-Clause", "main": "./build/cjs/index.js", "scripts": { From 620b00832da7c4951d6e905b40317dd0acca0aa6 Mon Sep 17 00:00:00 2001 From: eirikhaugstulen Date: Fri, 1 Dec 2023 08:07:29 +0100 Subject: [PATCH 15/18] feat: [DHIS2-16123] Add inheritable TEAs to Relationships (#3464) --- .../hooks/useFormValues.js | 10 ++- .../TeiRegistrationEntry.container.js | 40 +++++++++-- .../TeiRegistrationEntry.types.js | 2 + .../hooks/useFormValuesFromSearchTerms.js | 31 +++++--- .../SingleOrgUnitSelectField.component.js | 6 +- .../components/Pages/New/NewPage.types.js | 3 +- .../RegistrationDataEntry.types.js | 4 +- .../DataEntryEnrollment.component.js | 2 + .../Enrollment/dataEntryEnrollment.types.js | 2 + .../RegisterTeiDataEntry.component.js | 8 ++- .../DataEntryTrackedEntityInstance.js | 2 + .../dataEntryTrackedEntityInstance.types.js | 2 + .../RegisterTei/RegisterTei.component.js | 2 + .../RegisterTei/RegisterTei.container.js | 12 ++++ .../RegisterTei/RegisterTei.types.js | 4 ++ ...kedEntityRelationshipsWrapper.component.js | 1 + .../useInheritedAttributeValues.js | 70 +++++++++++++++++++ .../metaData/DataElement/DataElement.js | 9 +++ .../factory/enrollment/DataElementFactory.js | 1 + .../TrackedEntityType/DataElementFactory.js | 1 + .../storeTrackedEntityAttributes.js | 2 +- .../storageControllers/cache.types.js | 1 + .../query/useApiDataQuery.js | 2 +- 23 files changed, 189 insertions(+), 28 deletions(-) create mode 100644 src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/useInheritedAttributeValues.js diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useFormValues.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useFormValues.js index 1431a10e23..679d973ecb 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useFormValues.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/useFormValues.js @@ -8,6 +8,7 @@ import type { RenderFoundation } from '../../../../metaData'; import { convertClientToForm, convertServerToClient } from '../../../../converters'; import { subValueGetterByElementType } from './getSubValueForTei'; import type { QuerySingleResource } from '../../../../utils/api/api.types'; +import { dataElementTypes } from '../../../../metaData'; type InputProgramData = { attributes: Array<{ @@ -32,7 +33,7 @@ export type InputAttribute = { displayName: string, lastUpdated: string, value: string, - valueType: string, + valueType: $Keys, }; type InputForm = { @@ -50,7 +51,7 @@ type StaticPatternValues = { const useClientAttributesWithSubvalues = (program: InputProgramData, attributes: Array) => { const dataEngine = useDataEngine(); - const [listAttributes, setListAttributes] = useState([]); + const [listAttributes, setListAttributes] = useState(null); const getListAttributes = useCallback(async () => { if (program && attributes) { @@ -139,8 +140,6 @@ export const useFormValues = ({ program, trackedEntityInstanceAttributes, orgUni const formValuesReadyRef = useRef(false); const [formValues, setFormValues] = useState({}); const [clientValues, setClientValues] = useState({}); - const areAttributesWithSubvaluesReady = - (teiId && clientAttributesWithSubvalues.length > 0) || (!teiId && clientAttributesWithSubvalues.length === 0); useEffect(() => { formValuesReadyRef.current = false; @@ -152,7 +151,7 @@ export const useFormValues = ({ program, trackedEntityInstanceAttributes, orgUni formFoundation && Object.entries(formFoundation).length > 0 && formValuesReadyRef.current === false && - areAttributesWithSubvaluesReady + !!clientAttributesWithSubvalues ) { const staticPatternValues = { orgUnitCode: orgUnit.code }; const querySingleResource = makeQuerySingleResource(dataEngine.query.bind(dataEngine)); @@ -172,7 +171,6 @@ export const useFormValues = ({ program, trackedEntityInstanceAttributes, orgUni clientAttributesWithSubvalues, formValuesReadyRef, orgUnit, - areAttributesWithSubvaluesReady, searchTerms, dataEngine, ]); diff --git a/src/core_modules/capture-core/components/DataEntries/TeiRegistrationEntry/TeiRegistrationEntry.container.js b/src/core_modules/capture-core/components/DataEntries/TeiRegistrationEntry/TeiRegistrationEntry.container.js index 4c3b8badab..7d017181b9 100644 --- a/src/core_modules/capture-core/components/DataEntries/TeiRegistrationEntry/TeiRegistrationEntry.container.js +++ b/src/core_modules/capture-core/components/DataEntries/TeiRegistrationEntry/TeiRegistrationEntry.container.js @@ -11,19 +11,37 @@ import { useFormValuesFromSearchTerms } from './hooks/useFormValuesFromSearchTer import { dataEntryHasChanges } from '../../DataEntry/common/dataEntryHasChanges'; import { useMetadataForRegistrationForm } from '../common/TEIAndEnrollment/useMetadataForRegistrationForm'; import { useBuildTeiPayload } from './hooks/useBuildTeiPayload'; +import type { InputAttribute } from '../EnrollmentRegistrationEntry/hooks/useFormValues'; -const useInitialiseTeiRegistration = (selectedScopeId, dataEntryId, orgUnitId) => { +type Props = { + selectedScopeId: string, + dataEntryId: string, + orgUnitId: string, + inheritedAttributes: ?Array, +} +const useInitialiseTeiRegistration = ({ + selectedScopeId, + dataEntryId, + orgUnitId, + inheritedAttributes, +}: Props) => { const dispatch = useDispatch(); const { scopeType, trackedEntityName } = useScopeInfo(selectedScopeId); const { formId, formFoundation } = useMetadataForRegistrationForm({ selectedScopeId }); - const formValues = useFormValuesFromSearchTerms(); + const formValues = useFormValuesFromSearchTerms({ inheritedAttributes }); const registrationFormReady = !!formId; useEffect(() => { if (registrationFormReady && scopeType === scopeTypes.TRACKED_ENTITY_TYPE) { dispatch( startNewTeiDataEntryInitialisation( - { selectedOrgUnitId: orgUnitId, selectedScopeId, dataEntryId, formFoundation, formValues }, + { + selectedOrgUnitId: orgUnitId, + selectedScopeId, + dataEntryId, + formFoundation, + formValues, + }, )); } }, [ @@ -43,8 +61,20 @@ const useInitialiseTeiRegistration = (selectedScopeId, dataEntryId, orgUnitId) = }; -export const TeiRegistrationEntry: ComponentType = ({ selectedScopeId, id, orgUnitId, onSave, ...rest }) => { - const { trackedEntityName } = useInitialiseTeiRegistration(selectedScopeId, id, orgUnitId); +export const TeiRegistrationEntry: ComponentType = ({ + selectedScopeId, + id, + orgUnitId, + onSave, + inheritedAttributes, + ...rest +}) => { + const { trackedEntityName } = useInitialiseTeiRegistration({ + selectedScopeId, + dataEntryId: id, + orgUnitId, + inheritedAttributes, + }); const ready = useSelector(({ dataEntries }) => (!!dataEntries[id])); const dataEntry = useSelector(({ dataEntries }) => (dataEntries[id])); const { diff --git a/src/core_modules/capture-core/components/DataEntries/TeiRegistrationEntry/TeiRegistrationEntry.types.js b/src/core_modules/capture-core/components/DataEntries/TeiRegistrationEntry/TeiRegistrationEntry.types.js index 43afd9adc8..33f32eabf8 100644 --- a/src/core_modules/capture-core/components/DataEntries/TeiRegistrationEntry/TeiRegistrationEntry.types.js +++ b/src/core_modules/capture-core/components/DataEntries/TeiRegistrationEntry/TeiRegistrationEntry.types.js @@ -6,6 +6,7 @@ import type { ExistingUniqueValueDialogActionsComponent } from '../withErrorMess import type { TeiPayload, } from '../../Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/dataEntryTrackedEntityInstance.types'; +import type { InputAttribute } from '../EnrollmentRegistrationEntry/hooks/useFormValues'; export type OwnProps = $ReadOnly<{| id: string, @@ -16,6 +17,7 @@ export type OwnProps = $ReadOnly<{| onSave: (TeiPayload) => void, duplicatesReviewPageSize: number, isSavingInProgress?: boolean, + inheritedAttributes?: Array, renderDuplicatesCardActions?: RenderCustomCardActions, renderDuplicatesDialogActions?: (onCancel: () => void, onSave: (TeiPayload) => void) => Node, ExistingUniqueValueDialogActions: ExistingUniqueValueDialogActionsComponent, diff --git a/src/core_modules/capture-core/components/DataEntries/TeiRegistrationEntry/hooks/useFormValuesFromSearchTerms.js b/src/core_modules/capture-core/components/DataEntries/TeiRegistrationEntry/hooks/useFormValuesFromSearchTerms.js index 87bdf7fa98..42c6fbff54 100644 --- a/src/core_modules/capture-core/components/DataEntries/TeiRegistrationEntry/hooks/useFormValuesFromSearchTerms.js +++ b/src/core_modules/capture-core/components/DataEntries/TeiRegistrationEntry/hooks/useFormValuesFromSearchTerms.js @@ -1,19 +1,32 @@ // @flow -import { useEffect, useState } from 'react'; +import { useMemo } from 'react'; import { useSelector } from 'react-redux'; import { convertClientToForm } from '../../../../converters'; +import type { InputAttribute } from '../../EnrollmentRegistrationEntry/hooks/useFormValues'; +type Props = { + inheritedAttributes: ?Array, +}; -export const useFormValuesFromSearchTerms = () => { +export const useFormValuesFromSearchTerms = ({ inheritedAttributes }: Props) => { const searchTerms = useSelector(({ searchDomain }) => searchDomain.currentSearchInfo.currentSearchTerms); - const [formValues, setFormValues] = useState(); - useEffect(() => { + + return useMemo(() => { + if (inheritedAttributes) { + return inheritedAttributes + ?.reduce((acc, item) => { + acc[item.attribute] = convertClientToForm(item.value, item.valueType); + return acc; + }, {}); + } if (searchTerms) { - const searchFormValues = searchTerms - ?.reduce((acc, item) => ({ ...acc, [item.id]: convertClientToForm(item.value, item.type) }), {}); - setFormValues(searchFormValues); + return searchTerms + ?.reduce((acc, item) => { + acc[item.id] = convertClientToForm(item.value, item.type); + return acc; + }, {}); } - }, [searchTerms]); - return formValues; + return null; + }, [inheritedAttributes, searchTerms]); }; diff --git a/src/core_modules/capture-core/components/FormFields/New/Fields/OrgUnitField/SingleOrgUnitSelectField.component.js b/src/core_modules/capture-core/components/FormFields/New/Fields/OrgUnitField/SingleOrgUnitSelectField.component.js index 6c252f087b..7946993a79 100644 --- a/src/core_modules/capture-core/components/FormFields/New/Fields/OrgUnitField/SingleOrgUnitSelectField.component.js +++ b/src/core_modules/capture-core/components/FormFields/New/Fields/OrgUnitField/SingleOrgUnitSelectField.component.js @@ -13,7 +13,7 @@ const getStyles = () => ({ type OrgUnitValue = { id: string, - name: string, + displayName: string, path: string, } @@ -44,7 +44,7 @@ class SingleOrgUnitSelectFieldPlain extends React.Component { const { classes } = this.props; return (
- {selectedOrgUnit.name} + {selectedOrgUnit.displayName}
); } @@ -52,7 +52,7 @@ class SingleOrgUnitSelectFieldPlain extends React.Component { onSelectOrgUnit = (orgUnit: Object) => { this.props.onBlur({ id: orgUnit.id, - name: orgUnit.displayName, + displayName: orgUnit.displayName, path: orgUnit.path, }); } diff --git a/src/core_modules/capture-core/components/Pages/New/NewPage.types.js b/src/core_modules/capture-core/components/Pages/New/NewPage.types.js index 899367152f..f9357422d7 100644 --- a/src/core_modules/capture-core/components/Pages/New/NewPage.types.js +++ b/src/core_modules/capture-core/components/Pages/New/NewPage.types.js @@ -1,5 +1,6 @@ // @flow import { typeof newPageStatuses } from './NewPage.constants'; +import { dataElementTypes } from '../../../metaData'; type ProgramCategories = Array<{|name: string, id: string|}> @@ -10,7 +11,7 @@ type InputAttribute = { displayName: string, lastUpdated: string, value: string, - valueType: string, + valueType: $Keys, }; export type ContainerProps = $ReadOnly<{| diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.types.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.types.js index 79a07ea96e..22e908fb66 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.types.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.types.js @@ -1,5 +1,7 @@ // @flow +import { dataElementTypes } from '../../../../metaData'; + type InputAttribute = { attribute: string, code: string, @@ -7,7 +9,7 @@ type InputAttribute = { displayName: string, lastUpdated: string, value: string, - valueType: string, + valueType: $Keys, }; export type OwnProps = $ReadOnly<{| diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js index 2dbf0c7a20..25b215eed7 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/DataEntryEnrollment.component.js @@ -12,6 +12,7 @@ const NewEnrollmentRelationshipPlain = theme, onSave, programId, + inheritedAttributes, orgUnitId, duplicatesReviewPageSize, renderDuplicatesDialogActions, @@ -35,6 +36,7 @@ const NewEnrollmentRelationshipPlain = renderDuplicatesDialogActions={renderDuplicatesDialogActions} renderDuplicatesCardActions={renderDuplicatesCardActions} ExistingUniqueValueDialogActions={ExistingUniqueValueDialogActions} + trackedEntityInstanceAttributes={inheritedAttributes} /> ); }; diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/dataEntryEnrollment.types.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/dataEntryEnrollment.types.js index de3f6cee6f..3b32b17d35 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/dataEntryEnrollment.types.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/Enrollment/dataEntryEnrollment.types.js @@ -6,11 +6,13 @@ import type { SaveForEnrollmentAndTeiRegistration, ExistingUniqueValueDialogActionsComponent, } from '../../../../../../DataEntries'; +import type { InputAttribute } from '../../../../../../DataEntries/EnrollmentRegistrationEntry/hooks/useFormValues'; export type Props = {| theme: Theme, programId: string, orgUnitId: string, + inheritedAttributes: Array, enrollmentMetadata?: Enrollment, onSave: SaveForEnrollmentAndTeiRegistration, duplicatesReviewPageSize: number, diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/RegisterTeiDataEntry.component.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/RegisterTeiDataEntry.component.js index 292a1d1530..940aa904fd 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/RegisterTeiDataEntry.component.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/RegisterTeiDataEntry.component.js @@ -12,7 +12,13 @@ type Props = { export class RegisterTeiDataEntryComponent extends React.Component { render() { - const { showDataEntry, programId, onSaveWithoutEnrollment, onSaveWithEnrollment, ...passOnProps } = this.props; + const { + showDataEntry, + programId, + onSaveWithoutEnrollment, + onSaveWithEnrollment, + ...passOnProps + } = this.props; if (!showDataEntry) { return null; diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/DataEntryTrackedEntityInstance.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/DataEntryTrackedEntityInstance.js index c455e3616d..20579fc2db 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/DataEntryTrackedEntityInstance.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/DataEntryTrackedEntityInstance.js @@ -14,6 +14,7 @@ const RelationshipTrackedEntityInstancePlain = theme, onSave, trackedEntityTypeId, + inheritedAttributes, duplicatesReviewPageSize, renderDuplicatesDialogActions, renderDuplicatesCardActions, @@ -36,6 +37,7 @@ const RelationshipTrackedEntityInstancePlain = orgUnitId={orgUnitId} teiRegistrationMetadata={teiRegistrationMetadata} selectedScopeId={teiRegistrationMetadata.form.id} + inheritedAttributes={inheritedAttributes} saveButtonText={i18n.t('Save new {{trackedEntityTypeName}} and link', { trackedEntityTypeName: trackedEntityTypeNameLC, interpolation: { escapeValue: false }, })} diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/dataEntryTrackedEntityInstance.types.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/dataEntryTrackedEntityInstance.types.js index b4f9617052..4fcec10567 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/dataEntryTrackedEntityInstance.types.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/DataEntry/TrackedEntityInstance/dataEntryTrackedEntityInstance.types.js @@ -5,6 +5,7 @@ import type { RenderCustomCardActions } from '../../../../../../CardList'; import type { ExistingUniqueValueDialogActionsComponent, } from '../../../../../../DataEntries'; +import type { InputAttribute } from '../../../../../../DataEntries/EnrollmentRegistrationEntry/hooks/useFormValues'; export type TeiPayload = {| trackedEntity: string, @@ -23,6 +24,7 @@ export type Props = {| trackedEntityTypeId: string, onSave: TeiPayload => void, teiRegistrationMetadata?: TeiRegistration, + inheritedAttributes: Array, duplicatesReviewPageSize: number, renderDuplicatesCardActions?: RenderCustomCardActions, renderDuplicatesDialogActions?: (onCancel: () => void, onSave: (TeiPayload) => void) => Node, diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegisterTei.component.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegisterTei.component.js index 9a9a7070af..c22abb0c0e 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegisterTei.component.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegisterTei.component.js @@ -64,6 +64,7 @@ const RegisterTeiPlain = ({ trackedEntityName, trackedEntityTypeId, selectedScopeId, + inheritedAttributes, classes, }: ComponentProps) => { const { resultsPageSize } = useContext(ResultsPageSizeContext); @@ -110,6 +111,7 @@ const RegisterTeiPlain = ({ renderDuplicatesDialogActions={renderDuplicatesDialogActions} renderDuplicatesCardActions={renderDuplicatesCardActions} ExistingUniqueValueDialogActions={ExistingUniqueValueDialogActions} + inheritedAttributes={inheritedAttributes} /> { @@ -16,6 +18,15 @@ export const RegisterTei = ({ const error = useSelector(({ newRelationshipRegisterTei }) => (newRelationshipRegisterTei.error)); const selectedScopeId = suggestedProgramId || trackedEntityTypeId; const { trackedEntityName } = useScopeInfo(selectedScopeId); + const { inheritedAttributes, isLoading: isLoadingAttributes } = useInheritedAttributeValues({ + teiId, + trackedEntityTypeId, + programId: suggestedProgramId, + }); + + if (isLoadingAttributes) { + return null; + } return ( ); }; diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegisterTei.types.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegisterTei.types.js index 0de2b570ba..dea706722b 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegisterTei.types.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegisterTei.types.js @@ -1,4 +1,6 @@ // @flow +import type { InputAttribute } from '../../../../DataEntries/EnrollmentRegistrationEntry/hooks/useFormValues'; + export type SharedProps = {| onLink: (teiId: string, values: Object) => void, onGetUnsavedAttributeValues?: ?Function, @@ -7,6 +9,7 @@ export type SharedProps = {| export type ContainerProps = {| suggestedProgramId: string, + teiId: string, onSave: (teiPayload: Object) => void, ...SharedProps, |}; @@ -16,6 +19,7 @@ export type ComponentProps = {| error: string, dataEntryId: string, trackedEntityName: ?string, + inheritedAttributes: Array, onSaveWithEnrollment: () => void, onSaveWithoutEnrollment: () => void, ...SharedProps, diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/TrackedEntityRelationshipsWrapper/TrackedEntityRelationshipsWrapper.component.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/TrackedEntityRelationshipsWrapper/TrackedEntityRelationshipsWrapper.component.js index df27fb1125..135dafe53f 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/TrackedEntityRelationshipsWrapper/TrackedEntityRelationshipsWrapper.component.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/TrackedEntityRelationshipsWrapper/TrackedEntityRelationshipsWrapper.component.js @@ -76,6 +76,7 @@ export const TrackedEntityRelationshipsWrapper = ({ suggestedProgramId={suggestedProgramId} onLink={onLinkToTrackedEntityFromSearch} onSave={onLinkToTrackedEntityFromRegistration} + teiId={teiId} onGetUnsavedAttributeValues={() => console.log('get unsaved')} trackedEntityTypeId={selectedTrackedEntityTypeId} /> diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/useInheritedAttributeValues.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/useInheritedAttributeValues.js new file mode 100644 index 0000000000..8c526525dd --- /dev/null +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/useInheritedAttributeValues.js @@ -0,0 +1,70 @@ +// @flow +import { useMemo } from 'react'; +import { useSelector } from 'react-redux'; +import type { InputAttribute } from '../../../DataEntries/EnrollmentRegistrationEntry/hooks/useFormValues'; +import { useApiDataQuery } from '../../../../utils/reactQueryHelpers'; +import { + getProgramFromProgramIdThrowIfNotFound, + getTrackedEntityTypeThrowIfNotFound, + TrackerProgram, +} from '../../../../metaData'; + +type Props = { + teiId: string, + trackedEntityTypeId: string, +}; + +type Return = { + inheritedAttributes: Array, + isLoading: boolean, +}; +export const useInheritedAttributeValues = ({ teiId, trackedEntityTypeId }: Props): Return => { + const programId = useSelector(({ newRelationshipRegisterTei }) => newRelationshipRegisterTei.programId); + const inheritedAttributeIds = useMemo(() => { + const attributeIds = new Set(); + + if (programId) { + const program = getProgramFromProgramIdThrowIfNotFound(programId); + if (program instanceof TrackerProgram) { + program.attributes.forEach((attribute) => { + if (attribute.inherit) { + attributeIds.add(attribute.id); + } + }); + } + return attributeIds; + } + + const trackedEntityType = getTrackedEntityTypeThrowIfNotFound(trackedEntityTypeId); + trackedEntityType.attributes.forEach((attribute) => { + if (attribute.inherit) { + attributeIds.add(attribute.id); + } + }); + return attributeIds; + }, [programId, trackedEntityTypeId]); + + + const { data, isLoading } = useApiDataQuery( + ['inheritedAttributeValues', teiId, programId], + { + resource: 'tracker/trackedEntities', + id: teiId, + params: { + fields: ['attributes'], + program: programId, + }, + }, { + enabled: !!teiId, + select: (response) => { + const attributes = response.attributes || []; + return attributes + .filter(attribute => inheritedAttributeIds.has(attribute.attribute)); + }, + }); + + return { + inheritedAttributes: data ?? [], + isLoading, + }; +}; diff --git a/src/core_modules/capture-core/metaData/DataElement/DataElement.js b/src/core_modules/capture-core/metaData/DataElement/DataElement.js index 5555d4842e..78fe1d959a 100644 --- a/src/core_modules/capture-core/metaData/DataElement/DataElement.js +++ b/src/core_modules/capture-core/metaData/DataElement/DataElement.js @@ -35,6 +35,7 @@ export class DataElement { _displayInReports: boolean; _icon: Icon | void; _unique: ?Unique; + _inherit: boolean; _searchable: ?boolean; _url: ?string; _attributeValues: Array @@ -157,6 +158,14 @@ export class DataElement { return this._unique; } + get inherit(): boolean { + return this._inherit; + } + + set inherit(value: boolean) { + this._inherit = value; + } + set searchable(searchable: boolean) { this._searchable = searchable; } diff --git a/src/core_modules/capture-core/metaDataMemoryStoreBuilders/programs/factory/enrollment/DataElementFactory.js b/src/core_modules/capture-core/metaDataMemoryStoreBuilders/programs/factory/enrollment/DataElementFactory.js index 18e56e1869..27d1222735 100644 --- a/src/core_modules/capture-core/metaDataMemoryStoreBuilders/programs/factory/enrollment/DataElementFactory.js +++ b/src/core_modules/capture-core/metaDataMemoryStoreBuilders/programs/factory/enrollment/DataElementFactory.js @@ -164,6 +164,7 @@ export class DataElementFactory { dataElement.compulsory = cachedProgramTrackedEntityAttribute.mandatory; dataElement.code = cachedTrackedEntityAttribute.code; dataElement.attributeValues = cachedTrackedEntityAttribute.attributeValues; + dataElement.inherit = cachedTrackedEntityAttribute.inherit; dataElement.name = this._getAttributeTranslation( cachedTrackedEntityAttribute.translations, diff --git a/src/core_modules/capture-core/metaDataMemoryStoreBuilders/trackedEntityTypes/factory/TrackedEntityType/DataElementFactory.js b/src/core_modules/capture-core/metaDataMemoryStoreBuilders/trackedEntityTypes/factory/TrackedEntityType/DataElementFactory.js index bc27da80ed..723d148d3c 100644 --- a/src/core_modules/capture-core/metaDataMemoryStoreBuilders/trackedEntityTypes/factory/TrackedEntityType/DataElementFactory.js +++ b/src/core_modules/capture-core/metaDataMemoryStoreBuilders/trackedEntityTypes/factory/TrackedEntityType/DataElementFactory.js @@ -112,6 +112,7 @@ export class DataElementFactory { cachedAttribute.translations, DataElementFactory.translationPropertyNames.DESCRIPTION) || cachedAttribute.description; o.displayInForms = true; + o.inherit = cachedAttribute.inherit; o.displayInReports = cachedTrackedEntityTypeAttribute.displayInList; o.disabled = false; o.type = cachedAttribute.valueType; diff --git a/src/core_modules/capture-core/metaDataStoreLoaders/trackedEntityAttributes/quickStoreOperations/storeTrackedEntityAttributes.js b/src/core_modules/capture-core/metaDataStoreLoaders/trackedEntityAttributes/quickStoreOperations/storeTrackedEntityAttributes.js index 8624bb577e..7658ff4a8b 100644 --- a/src/core_modules/capture-core/metaDataStoreLoaders/trackedEntityAttributes/quickStoreOperations/storeTrackedEntityAttributes.js +++ b/src/core_modules/capture-core/metaDataStoreLoaders/trackedEntityAttributes/quickStoreOperations/storeTrackedEntityAttributes.js @@ -7,7 +7,7 @@ export const storeTrackedEntityAttributes = (ids: Array) => { resource: 'trackedEntityAttributes', params: { fields: 'id,displayName,displayShortName,displayFormName,description,valueType,optionSetValue,unique,orgunitScope,' + - 'pattern,code,attributeValues,translations[property,locale,value],optionSet[id]', + 'pattern,code,attributeValues,inherit,translations[property,locale,value],optionSet[id]', filter: `id:in:[${ids.join(',')}]`, pageSize: ids.length, }, diff --git a/src/core_modules/capture-core/storageControllers/cache.types.js b/src/core_modules/capture-core/storageControllers/cache.types.js index 49ce4a64ca..01ba461309 100644 --- a/src/core_modules/capture-core/storageControllers/cache.types.js +++ b/src/core_modules/capture-core/storageControllers/cache.types.js @@ -26,6 +26,7 @@ export type CachedTrackedEntityAttribute = { translations: Array, valueType: string, optionSetValue: boolean, + inherit: boolean, optionSet: { id: string }, unique: ?boolean, orgunitScope: ?boolean, diff --git a/src/core_modules/capture-core/utils/reactQueryHelpers/query/useApiDataQuery.js b/src/core_modules/capture-core/utils/reactQueryHelpers/query/useApiDataQuery.js index 8505d4aaff..44b0ba996f 100644 --- a/src/core_modules/capture-core/utils/reactQueryHelpers/query/useApiDataQuery.js +++ b/src/core_modules/capture-core/utils/reactQueryHelpers/query/useApiDataQuery.js @@ -6,7 +6,7 @@ import type { Result } from './useMetadataQuery.types'; import { ReactQueryAppNamespace } from '../reactQueryHelpers.const'; export const useApiDataQuery = ( - queryKey: Array, + queryKey: Array, queryObject: ResourceQuery, queryOptions: UseQueryOptions, ): Result => { From e20fb8c551aefb0546c5973dd87940d56e3018be Mon Sep 17 00:00:00 2001 From: "@dhis2-bot" Date: Sun, 3 Dec 2023 02:37:54 +0100 Subject: [PATCH 16/18] fix(translations): sync translations from transifex (master) Automatically merged. --- i18n/ar.po | 56 ++++-- i18n/cs.po | 42 +++- i18n/es.po | 52 +++-- i18n/es_419.po | 131 ++++++++++--- i18n/fr.po | 54 ++++-- i18n/id.po | 54 ++++-- i18n/km.po | 133 ++++++++++--- i18n/lo.po | 54 ++++-- i18n/nb.po | 52 +++-- i18n/nl.po | 48 +++-- i18n/or.po | 468 ++++++++++++++++++++++++++++++--------------- i18n/prs.po | 48 +++-- i18n/ps.po | 46 +++-- i18n/pt.po | 48 +++-- i18n/pt_BR.po | 42 +++- i18n/ru.po | 48 +++-- i18n/sv.po | 46 +++-- i18n/tg.po | 46 +++-- i18n/uk.po | 46 +++-- i18n/ur.po | 52 +++-- i18n/uz_UZ_Cyrl.po | 4 +- i18n/uz_UZ_Latn.po | 48 +++-- i18n/vi.po | 52 +++-- i18n/zh.po | 48 +++-- i18n/zh_CN.po | 46 +++-- 25 files changed, 1291 insertions(+), 473 deletions(-) diff --git a/i18n/ar.po b/i18n/ar.po index e1e1024ca7..f2f9d46408 100644 --- a/i18n/ar.po +++ b/i18n/ar.po @@ -1,16 +1,16 @@ # # Translators: # KRG HIS , 2020 -# Viktor Varland , 2023 -# Hamza Assada <7amza.it@gmail.com>, 2023 # Philip Larsen Donnelly, 2023 +# Hamza Assada <7amza.it@gmail.com>, 2023 +# Viktor Varland , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Philip Larsen Donnelly, 2023\n" +"Last-Translator: Viktor Varland , 2023\n" "Language-Team: Arabic (https://app.transifex.com/hisp-uio/teams/100509/ar/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -533,6 +533,9 @@ msgstr "ابدأ الكتابة للبحث" msgid "suggestions could not be retrieved" msgstr "تعذر استرداد الاقتراحات" +msgid "No results found" +msgstr "لم يتم العثور على أي نتائج" + msgid "No items to display" msgstr "لا توجد عناصر للعرض" @@ -951,9 +954,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "إحتمال وجود تكرار" -msgid "No results found" -msgstr "لم يتم العثور على أي نتائج" - msgid "An error occurred loading possible duplicates" msgstr "" @@ -1154,6 +1154,33 @@ msgstr "اشر من أجل الملحق" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "خط العرض" + +msgid "Longitude" +msgstr "خط الطول" + +msgid "Edit" +msgstr "تعديل" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "الإحداثيات" + +msgid "Delete polygon" +msgstr "حذف المضلع" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "عين المساحة" + msgid "Enrollment date" msgstr "تاريخ التسجيل" @@ -1178,6 +1205,12 @@ msgstr "" msgid "Cancelled" msgstr "الملغية" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1300,9 +1333,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "تعديل" - msgid "tracked entity instance" msgstr "نموذج الكيان المتتبع" @@ -1368,7 +1398,7 @@ msgid "To open this relationship, please wait until saving is complete" msgstr "" msgid "Type" -msgstr "" +msgstr "النوع" msgid "Created date" msgstr "" @@ -1550,12 +1580,6 @@ msgstr "إلى وقت" msgid "Page {{currentPage}}" msgstr "صفحة {{currentPage}}" -msgid "Delete polygon" -msgstr "حذف المضلع" - -msgid "Set area" -msgstr "عين المساحة" - msgid "Area on map saved" msgstr "" diff --git a/i18n/cs.po b/i18n/cs.po index 171ec3d5b0..eb1fcb93e4 100644 --- a/i18n/cs.po +++ b/i18n/cs.po @@ -1191,6 +1191,33 @@ msgid "Existing dates for auto-generated events will not be updated." msgstr "" "Stávající data pro automaticky generované události nebudou aktualizována." +msgid "Latitude" +msgstr "Zeměpisná šířka" + +msgid "Longitude" +msgstr "Zeměpisná délka" + +msgid "Edit" +msgstr "Upravit" + +msgid "Set coordinates" +msgstr "Nastavit souřadnice" + +msgid "Coordinates" +msgstr "Souřadnice" + +msgid "Delete polygon" +msgstr "Smazat polygon" + +msgid "Close without saving" +msgstr "Zavřít bez uložení" + +msgid "Finish drawing before saving" +msgstr "Před uložením dokončete kreslení" + +msgid "Set area" +msgstr "Nastavit oblast" + msgid "Enrollment date" msgstr "Datum zápisu" @@ -1215,6 +1242,12 @@ msgstr "Poslední aktualizace {{date}}" msgid "Cancelled" msgstr "Zrušeno" +msgid "Add coordinates" +msgstr "Přidat souřadnice" + +msgid "Add area" +msgstr "Přidat oblast" + msgid "Comments about this enrollment" msgstr "Komentáře k tomuto zápisu" @@ -1343,9 +1376,6 @@ msgstr "Widget profilu nelze načíst. Prosím zkuste to znovu později" msgid "{{TETName}} profile" msgstr "profil {{TETName}}" -msgid "Edit" -msgstr "Upravit" - msgid "tracked entity instance" msgstr "sledovaná instance entity" @@ -1593,12 +1623,6 @@ msgstr "Na čas" msgid "Page {{currentPage}}" msgstr "Stránka {{currentPage}}" -msgid "Delete polygon" -msgstr "Smazat polygon" - -msgid "Set area" -msgstr "Nastavit oblast" - msgid "Area on map saved" msgstr "Oblast na mapě byla uložena" diff --git a/i18n/es.po b/i18n/es.po index a009f61377..67b54c1201 100644 --- a/i18n/es.po +++ b/i18n/es.po @@ -6,20 +6,20 @@ # Philip Larsen Donnelly, 2022 # Marta Vila , 2022 # Pablo Pajuelo Cabezas , 2022 -# Viktor Varland , 2023 # Alison Andrade , 2023 # Janeth Cruz, 2023 # Prabhjot Singh, 2023 # Christian Atavillos, 2023 # Enzo Nicolas Rossi , 2023 # Gabriela Rodriguez , 2023 +# Viktor Varland , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Gabriela Rodriguez , 2023\n" +"Last-Translator: Viktor Varland , 2023\n" "Language-Team: Spanish (https://app.transifex.com/hisp-uio/teams/100509/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -557,6 +557,9 @@ msgstr "Empiece a escribir para buscar" msgid "suggestions could not be retrieved" msgstr "No se pudieron recuperar las sugerencias" +msgid "No results found" +msgstr "No results found" + msgid "No items to display" msgstr "No hay elementos para mostrar" @@ -1004,9 +1007,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "Posibles duplicados encontrados" -msgid "No results found" -msgstr "No results found" - msgid "An error occurred loading possible duplicates" msgstr "Se produjo un error al cargar posibles duplicados" @@ -1226,6 +1226,33 @@ msgstr "Marcar para seguimiento" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Latitud" + +msgid "Longitude" +msgstr "Longitud" + +msgid "Edit" +msgstr "Editar" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "Coordenadas" + +msgid "Delete polygon" +msgstr "Eliminar polígono" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "Establecer área" + msgid "Enrollment date" msgstr "Fecha de inscripción" @@ -1252,6 +1279,12 @@ msgstr "Última actualización {{date}}" msgid "Cancelled" msgstr "Cancelar" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "Comentarios sobre esta inscripción" @@ -1388,9 +1421,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "Perfil de {{TETName}} " -msgid "Edit" -msgstr "Editar" - msgid "tracked entity instance" msgstr "instancia de entidad rastreada" @@ -1642,12 +1672,6 @@ msgstr "Hasta la hora" msgid "Page {{currentPage}}" msgstr "Página {{currentPage}}" -msgid "Delete polygon" -msgstr "Eliminar polígono" - -msgid "Set area" -msgstr "Establecer área" - msgid "Area on map saved" msgstr "Área en el mapa guardada" diff --git a/i18n/es_419.po b/i18n/es_419.po index 42247a9fcb..9e781ff26a 100644 --- a/i18n/es_419.po +++ b/i18n/es_419.po @@ -1,14 +1,14 @@ # # Translators: -# Jaime Bosque , 2023 # Enzo Nicolas Rossi , 2023 +# Jaime Bosque , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2023-09-04T07:07:59.195Z\n" +"POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Enzo Nicolas Rossi , 2023\n" +"Last-Translator: Jaime Bosque , 2023\n" "Language-Team: Spanish (Latin America) (https://app.transifex.com/hisp-uio/teams/100509/es_419/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -160,6 +160,15 @@ msgstr "Coordenadas" msgid "Enrollment" msgstr "Inscripción" +msgid "Complete event" +msgstr "Evento completo" + +msgid "{{ stageName }} - Basic info" +msgstr "" + +msgid "{{ stageName }} - Status" +msgstr "" + msgid "Please select {{categoryName}}" msgstr "" @@ -182,15 +191,18 @@ msgstr "" "Error de metadatos. Un administrador deberá ver el registro de auditoría " "para más detalles" +msgid "{{ stageName }} - Details" +msgstr "" + +msgid "{{ stageName }} - {{ sectionName }}" +msgstr "" + msgid "Assigned user" msgstr "Usuario asignado" msgid "Search for user" msgstr "Buscar usuario" -msgid "Complete event" -msgstr "Evento completo" - msgid "Basic info" msgstr " " @@ -532,6 +544,9 @@ msgstr "Empiece a escribir para buscar" msgid "suggestions could not be retrieved" msgstr "no se pudieron cargar las sugerencias" +msgid "No results found" +msgstr "" + msgid "No items to display" msgstr "No hay elementos para mostrar" @@ -947,10 +962,19 @@ msgstr "" msgid "Organisation unit could not be loaded" msgstr "" -msgid "Possible duplicates found" +msgid "Selected program" msgstr "" -msgid "No results found" +msgid "Search {{uniqueAttrName}}" +msgstr "" + +msgid "Search by attributes" +msgstr "" + +msgid "Could not retrieve metadata. Please try again later." +msgstr "" + +msgid "Possible duplicates found" msgstr "" msgid "An error occurred loading possible duplicates" @@ -1011,9 +1035,6 @@ msgstr "" msgid "Search by {{name}}" msgstr "" -msgid "Search by attributes" -msgstr "" - msgid "all programs" msgstr "" @@ -1065,12 +1086,6 @@ msgstr "" msgid "Results found" msgstr "" -msgid "Selected program" -msgstr "" - -msgid "Search {{uniqueAttrName}}" -msgstr "" - msgid "Saved lists in this program" msgstr "" @@ -1160,6 +1175,33 @@ msgstr "" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Latitud" + +msgid "Longitude" +msgstr "Longitud" + +msgid "Edit" +msgstr "" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "" + +msgid "Delete polygon" +msgstr "" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "" + msgid "Enrollment date" msgstr "Fecha de inscripción" @@ -1184,6 +1226,12 @@ msgstr "" msgid "Cancelled" msgstr "Cancelar" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1306,9 +1354,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "Perfil de {{TETName}} " -msgid "Edit" -msgstr "" - msgid "tracked entity instance" msgstr "" @@ -1345,13 +1390,47 @@ msgstr "" msgid "Stages and Events" msgstr "" -msgid "Working list could not be loaded" +msgid "New TEI Relationship" msgstr "" -msgid "Download as JSON" +msgid "Missing implementation step" +msgstr "" + +msgid "Go back without saving relationship" +msgstr "" + +msgid "New Relationship" msgstr "" -msgid "Download as XML" +msgid "Link to an existing {{tetName}}" +msgstr "" + +msgid "An error occurred while adding the relationship" +msgstr "" + +msgid "" +"Something went wrong while loading relationships. Please try again later." +msgstr "" + +msgid "{{trackedEntityTypeName}} relationships" +msgstr "" + +msgid "To open this relationship, please wait until saving is complete" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Created date" +msgstr "" + +msgid "Program stage name" +msgstr "" + +msgid "Working list could not be loaded" +msgstr "" + +msgid "Download as JSON" msgstr "" msgid "Download as CSV" @@ -1522,12 +1601,6 @@ msgstr "" msgid "Page {{currentPage}}" msgstr "" -msgid "Delete polygon" -msgstr "" - -msgid "Set area" -msgstr "" - msgid "Area on map saved" msgstr "" diff --git a/i18n/fr.po b/i18n/fr.po index 9e40ff42d3..4c1f686a40 100644 --- a/i18n/fr.po +++ b/i18n/fr.po @@ -1,21 +1,21 @@ # # Translators: # Edem Kossi , 2022 -# Philip Larsen Donnelly, 2022 # Karoline Tufte Lien , 2022 # tx_e2f_fr r25 , 2022 # Bram Piot , 2022 # Yao Selom SAKA (HISP WCA) , 2023 # Yayra Gomado , 2023 -# Viktor Varland , 2023 # Gabriela Rodriguez , 2023 +# Viktor Varland , 2023 +# Philip Larsen Donnelly, 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Gabriela Rodriguez , 2023\n" +"Last-Translator: Philip Larsen Donnelly, 2023\n" "Language-Team: French (https://app.transifex.com/hisp-uio/teams/100509/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -557,6 +557,9 @@ msgstr "commencer à saisir pour effectuer une recherche" msgid "suggestions could not be retrieved" msgstr "les suggestions n'ont pas pu être récupérées" +msgid "No results found" +msgstr "Aucun résultat trouvé" + msgid "No items to display" msgstr "Aucun élément à afficher" @@ -995,9 +998,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "Doublons éventuellement détectés" -msgid "No results found" -msgstr "Aucun résultat trouvé" - msgid "An error occurred loading possible duplicates" msgstr "Une erreur s'est produite lors du chargement des doublons possibles" @@ -1213,6 +1213,33 @@ msgstr "Marquer pour suivi" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Latitude" + +msgid "Longitude" +msgstr "Longitude" + +msgid "Edit" +msgstr "Modifier" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "Coordonnées" + +msgid "Delete polygon" +msgstr "Supprimer polygone" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "Définir l'aire" + msgid "Enrollment date" msgstr "Date d'enrôlement" @@ -1238,6 +1265,12 @@ msgstr "Dernière mise à jour {{date}}" msgid "Cancelled" msgstr "Annulé" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "Commentaires sur cette inscription" @@ -1374,9 +1407,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "Profil {{Nom de la TET}}" -msgid "Edit" -msgstr "Modifier" - msgid "tracked entity instance" msgstr "instance d'entité suivie" @@ -1629,12 +1659,6 @@ msgstr "À" msgid "Page {{currentPage}}" msgstr "Page {{page en cours}}" -msgid "Delete polygon" -msgstr "Supprimer polygone" - -msgid "Set area" -msgstr "Définir l'aire" - msgid "Area on map saved" msgstr "" diff --git a/i18n/id.po b/i18n/id.po index b22da534fd..065b73ed4c 100644 --- a/i18n/id.po +++ b/i18n/id.po @@ -3,19 +3,19 @@ # Carwoto Sa'an , 2021 # Yusuf Setiawan , 2021 # Guardian Sanjaya , 2022 -# Untoro Dwi Raharjo , 2023 # Philip Larsen Donnelly, 2023 # Raja Fathurrahim, 2023 # Farida Sibuea , 2023 -# Viktor Varland , 2023 # Aprisa Chrysantina , 2023 +# Viktor Varland , 2023 +# Untoro Dwi Raharjo , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Aprisa Chrysantina , 2023\n" +"Last-Translator: Untoro Dwi Raharjo , 2023\n" "Language-Team: Indonesian (https://app.transifex.com/hisp-uio/teams/100509/id/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -544,6 +544,9 @@ msgstr "mulai mengetik untuk mencari" msgid "suggestions could not be retrieved" msgstr "saran tidak dapat diambil" +msgid "No results found" +msgstr "Tidak ada hasil ditemukan" + msgid "No items to display" msgstr "Tidak ada item untuk ditampilkan" @@ -972,9 +975,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "Kemungkinan duplikat ditemukan" -msgid "No results found" -msgstr "Tidak ada hasil ditemukan" - msgid "An error occurred loading possible duplicates" msgstr "Terjadi kesalahan saat memuat kemungkinan duplikat" @@ -1181,6 +1181,33 @@ msgstr "Tandai untuk follow up" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Garis lintang" + +msgid "Longitude" +msgstr "Garis bujur" + +msgid "Edit" +msgstr "Sunting" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "Koordinat" + +msgid "Delete polygon" +msgstr "Hapus poligon" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "Setel luas" + msgid "Enrollment date" msgstr "Tanggal pendaftaran" @@ -1205,6 +1232,12 @@ msgstr "Terakhir diperbarui {{date}}" msgid "Cancelled" msgstr "Dibatalkan" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "Komentar tentang pendaftaran ini" @@ -1327,9 +1360,6 @@ msgstr "Widget profil tidak dapat dimuat. Silakan coba lagi nanti" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "Sunting" - msgid "tracked entity instance" msgstr "contoh entitas yang dilacak" @@ -1577,12 +1607,6 @@ msgstr "Ke waktu" msgid "Page {{currentPage}}" msgstr "Halaman {{Halaman saat ini}}" -msgid "Delete polygon" -msgstr "Hapus poligon" - -msgid "Set area" -msgstr "Setel luas" - msgid "Area on map saved" msgstr "" diff --git a/i18n/km.po b/i18n/km.po index a36bcf4e1a..cdd9ea090a 100644 --- a/i18n/km.po +++ b/i18n/km.po @@ -1,15 +1,15 @@ # # Translators: # Philip Larsen Donnelly, 2022 -# Viktor Varland , 2022 # channara rin, 2023 +# Viktor Varland , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2023-09-04T07:07:59.195Z\n" +"POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: channara rin, 2023\n" +"Last-Translator: Viktor Varland , 2023\n" "Language-Team: Khmer (https://app.transifex.com/hisp-uio/teams/100509/km/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -153,6 +153,15 @@ msgstr "" msgid "Enrollment" msgstr "" +msgid "Complete event" +msgstr "" + +msgid "{{ stageName }} - Basic info" +msgstr "" + +msgid "{{ stageName }} - Status" +msgstr "" + msgid "Please select {{categoryName}}" msgstr "" @@ -171,13 +180,16 @@ msgstr "បោះបង់" msgid "Metadata error. see log for details" msgstr "" -msgid "Assigned user" +msgid "{{ stageName }} - Details" msgstr "" -msgid "Search for user" +msgid "{{ stageName }} - {{ sectionName }}" msgstr "" -msgid "Complete event" +msgid "Assigned user" +msgstr "" + +msgid "Search for user" msgstr "" msgid "Basic info" @@ -510,6 +522,9 @@ msgstr "" msgid "suggestions could not be retrieved" msgstr "" +msgid "No results found" +msgstr "មិនមានលទ្ធផលបង្ហាញ" + msgid "No items to display" msgstr "" @@ -913,11 +928,20 @@ msgstr "" msgid "Organisation unit could not be loaded" msgstr "" -msgid "Possible duplicates found" +msgid "Selected program" msgstr "" -msgid "No results found" -msgstr "មិនមានលទ្ធផលបង្ហាញ" +msgid "Search {{uniqueAttrName}}" +msgstr "" + +msgid "Search by attributes" +msgstr "" + +msgid "Could not retrieve metadata. Please try again later." +msgstr "" + +msgid "Possible duplicates found" +msgstr "" msgid "An error occurred loading possible duplicates" msgstr "" @@ -977,9 +1001,6 @@ msgstr "" msgid "Search by {{name}}" msgstr "" -msgid "Search by attributes" -msgstr "" - msgid "all programs" msgstr "" @@ -1031,12 +1052,6 @@ msgstr "" msgid "Results found" msgstr "" -msgid "Selected program" -msgstr "" - -msgid "Search {{uniqueAttrName}}" -msgstr "" - msgid "Saved lists in this program" msgstr "" @@ -1126,6 +1141,33 @@ msgstr "" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "រយៈទទឹង" + +msgid "Longitude" +msgstr "រយៈបណ្តោយ" + +msgid "Edit" +msgstr "កែសម្រួល​" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "" + +msgid "Delete polygon" +msgstr "" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "" + msgid "Enrollment date" msgstr "ថ្ងៃខែឆ្នាំចុះឈ្មោះ" @@ -1150,6 +1192,12 @@ msgstr "" msgid "Cancelled" msgstr "បានលុបចោល" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1272,9 +1320,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "កែសម្រួល​" - msgid "tracked entity instance" msgstr "" @@ -1311,13 +1356,47 @@ msgstr "" msgid "Stages and Events" msgstr "" -msgid "Working list could not be loaded" +msgid "New TEI Relationship" msgstr "" -msgid "Download as JSON" +msgid "Missing implementation step" +msgstr "" + +msgid "Go back without saving relationship" +msgstr "" + +msgid "New Relationship" msgstr "" -msgid "Download as XML" +msgid "Link to an existing {{tetName}}" +msgstr "" + +msgid "An error occurred while adding the relationship" +msgstr "" + +msgid "" +"Something went wrong while loading relationships. Please try again later." +msgstr "" + +msgid "{{trackedEntityTypeName}} relationships" +msgstr "" + +msgid "To open this relationship, please wait until saving is complete" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Created date" +msgstr "" + +msgid "Program stage name" +msgstr "" + +msgid "Working list could not be loaded" +msgstr "" + +msgid "Download as JSON" msgstr "" msgid "Download as CSV" @@ -1488,12 +1567,6 @@ msgstr "" msgid "Page {{currentPage}}" msgstr "" -msgid "Delete polygon" -msgstr "" - -msgid "Set area" -msgstr "" - msgid "Area on map saved" msgstr "" diff --git a/i18n/lo.po b/i18n/lo.po index 0521d1c02a..21bbeecd37 100644 --- a/i18n/lo.po +++ b/i18n/lo.po @@ -1,16 +1,16 @@ # # Translators: -# Thuy Nguyen , 2022 # Saysamone Sibounma, 2023 -# Viktor Varland , 2023 # Philip Larsen Donnelly, 2023 +# Viktor Varland , 2023 +# Thuy Nguyen , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Philip Larsen Donnelly, 2023\n" +"Last-Translator: Thuy Nguyen , 2023\n" "Language-Team: Lao (https://app.transifex.com/hisp-uio/teams/100509/lo/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -523,6 +523,9 @@ msgstr "" msgid "suggestions could not be retrieved" msgstr "" +msgid "No results found" +msgstr "" + msgid "No items to display" msgstr "" @@ -941,9 +944,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "" -msgid "No results found" -msgstr "" - msgid "An error occurred loading possible duplicates" msgstr "" @@ -1142,6 +1142,33 @@ msgstr "ໝາຍໄວ້ເພື່ອຕິດຕາມ" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "ເສັ້ນຂະໜານ" + +msgid "Longitude" +msgstr "ເສັ້ນແວງ" + +msgid "Edit" +msgstr "ແກ້ໄຂ" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "Coordinates" + +msgid "Delete polygon" +msgstr "" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "" + msgid "Enrollment date" msgstr "ວັນທີ່ລົງທະບຽນ" @@ -1166,6 +1193,12 @@ msgstr "" msgid "Cancelled" msgstr "ຍົກເລີກແລ້ວ" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1288,9 +1321,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "ແກ້ໄຂ" - msgid "tracked entity instance" msgstr "" @@ -1538,12 +1568,6 @@ msgstr "" msgid "Page {{currentPage}}" msgstr "" -msgid "Delete polygon" -msgstr "" - -msgid "Set area" -msgstr "" - msgid "Area on map saved" msgstr "" diff --git a/i18n/nb.po b/i18n/nb.po index e562d46e97..00e615f61b 100644 --- a/i18n/nb.po +++ b/i18n/nb.po @@ -1,14 +1,14 @@ # # Translators: -# Karoline Tufte Lien , 2023 # Caroline Hesthagen Holen , 2023 +# Karoline Tufte Lien , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Caroline Hesthagen Holen , 2023\n" +"Last-Translator: Karoline Tufte Lien , 2023\n" "Language-Team: Norwegian Bokmål (https://app.transifex.com/hisp-uio/teams/100509/nb/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -540,6 +540,9 @@ msgstr "begynn å skrive for å søke" msgid "suggestions could not be retrieved" msgstr "forslag kunne ikke hentes" +msgid "No results found" +msgstr "Ingen resultater funnet" + msgid "No items to display" msgstr "Ingen elementer å vise" @@ -983,9 +986,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "Mulige duplikater funnet" -msgid "No results found" -msgstr "Ingen resultater funnet" - msgid "An error occurred loading possible duplicates" msgstr "En feil oppsto ved lasting av mulige duplikater" @@ -1199,6 +1199,33 @@ msgstr "" "Eksisterende datoer for automatisk genererte hendelser vil ikke bli " "oppdatert." +msgid "Latitude" +msgstr "Breddegrad" + +msgid "Longitude" +msgstr "Lengdegrad" + +msgid "Edit" +msgstr "Rediger" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "Koordinater" + +msgid "Delete polygon" +msgstr "Slett polygon" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "Sett område" + msgid "Enrollment date" msgstr "Registreringsdato" @@ -1223,6 +1250,12 @@ msgstr "Sist oppdatert {{date}}" msgid "Cancelled" msgstr "Kansellert" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "Kommentarer om denne registreringen" @@ -1351,9 +1384,6 @@ msgstr "Profil -widgeten kunne ikke lastes inn. Prøv igjen senere" msgid "{{TETName}} profile" msgstr "{{TETName}} profil" -msgid "Edit" -msgstr "Rediger" - msgid "tracked entity instance" msgstr "Sporet enhetforekomst" @@ -1601,12 +1631,6 @@ msgstr "Til klokkeslett" msgid "Page {{currentPage}}" msgstr "Side {{currentPage}}" -msgid "Delete polygon" -msgstr "Slett polygon" - -msgid "Set area" -msgstr "Sett område" - msgid "Area on map saved" msgstr "Området på kartet er lagret" diff --git a/i18n/nl.po b/i18n/nl.po index 4a2d38b67b..bc73cff5d8 100644 --- a/i18n/nl.po +++ b/i18n/nl.po @@ -546,6 +546,9 @@ msgstr "begin met typen om te zoeken" msgid "suggestions could not be retrieved" msgstr "suggesties konden niet worden opgehaald" +msgid "No results found" +msgstr "Geen resultaten gevonden" + msgid "No items to display" msgstr "Geen items om weer te geven" @@ -1000,9 +1003,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "Mogelijke duplicaten gevonden" -msgid "No results found" -msgstr "Geen resultaten gevonden" - msgid "An error occurred loading possible duplicates" msgstr "Er is een fout opgetreden bij het laden van mogelijke duplicaten" @@ -1220,6 +1220,33 @@ msgstr "Markeer voor vervolg" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Breedtegraad" + +msgid "Longitude" +msgstr "Lengtegraad" + +msgid "Edit" +msgstr "Bewerk" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "" + +msgid "Delete polygon" +msgstr "Polygoon verwijderen" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "Gebied instellen" + msgid "Enrollment date" msgstr "Inschrijvingsdatum" @@ -1245,6 +1272,12 @@ msgstr "Laatst bijgewerkt {{datum}}" msgid "Cancelled" msgstr "Geannuleerd" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "Opmerkingen over deze inschrijving" @@ -1378,9 +1411,6 @@ msgstr "Profielwidget kan niet worden geladen. Probeer het later opnieuw" msgid "{{TETName}} profile" msgstr "{{TETNaam}} profiel" -msgid "Edit" -msgstr "Bewerk" - msgid "tracked entity instance" msgstr "gevolgd entiteitsexemplaar" @@ -1633,12 +1663,6 @@ msgstr "Timen" msgid "Page {{currentPage}}" msgstr "Pagina {{huidigePagina}}" -msgid "Delete polygon" -msgstr "Polygoon verwijderen" - -msgid "Set area" -msgstr "Gebied instellen" - msgid "Area on map saved" msgstr "Gebied op kaart opgeslagen" diff --git a/i18n/or.po b/i18n/or.po index 3e1d979be6..572b2755bf 100644 --- a/i18n/or.po +++ b/i18n/or.po @@ -1,14 +1,14 @@ # # Translators: -# SubhamJena , 2022 +# SubhamJena , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2022-08-17T08:14:13.865Z\n" +"POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: SubhamJena , 2022\n" -"Language-Team: Odia (https://www.transifex.com/hisp-uio/teams/100509/or/)\n" +"Last-Translator: SubhamJena , 2023\n" +"Language-Team: Odia (https://app.transifex.com/hisp-uio/teams/100509/or/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -36,6 +36,27 @@ msgid "" "again, but be aware that this will close other versions." msgstr "" +msgid "View {{programName}} dashboard" +msgstr "" + +msgid "View dashboard" +msgstr "" + +msgid "View active enrollment" +msgstr "" + +msgid "Re-enroll" +msgstr "" + +msgid "in" +msgstr "" + +msgid "Enrolled" +msgstr "" + +msgid "Previously enrolled" +msgstr "" + msgid "Organisation unit" msgstr "" @@ -45,10 +66,14 @@ msgstr "" msgid "Last updated" msgstr "" -msgid "Enrolled" +msgid "error encountered during field validation" msgstr "" -msgid "Previously enrolled" +msgid "error" +msgstr "" + +msgid "" +"Plugins are not yet available - Please contact your system administrator" msgstr "" msgid "This value is validating" @@ -87,7 +112,7 @@ msgstr "" msgid "Please provide a valid time" msgstr "" -msgid "Please provide a valid percentage" +msgid "Please provide an integer between 0 and 100" msgstr "" msgid "Please provide a valid url" @@ -126,6 +151,18 @@ msgstr "" msgid "Enrollment" msgstr "" +msgid "Complete event" +msgstr "" + +msgid "{{ stageName }} - Basic info" +msgstr "" + +msgid "{{ stageName }} - Status" +msgstr "" + +msgid "Please select {{categoryName}}" +msgstr "" + msgid "A future date is not allowed" msgstr "" @@ -141,13 +178,16 @@ msgstr "" msgid "Metadata error. see log for details" msgstr "" -msgid "Assigned user" +msgid "{{ stageName }} - Details" msgstr "" -msgid "Search for user" +msgid "{{ stageName }} - {{ sectionName }}" msgstr "" -msgid "Complete event" +msgid "Assigned user" +msgstr "" + +msgid "Search for user" msgstr "" msgid "Basic info" @@ -232,7 +272,7 @@ msgstr "" msgid "Go back to event without saving relationship" msgstr "" -msgid "Unsaved changes" +msgid "Discard unsaved changes?" msgstr "" msgid "" @@ -240,10 +280,10 @@ msgid "" "relationship" msgstr "" -msgid "Yes, discard" +msgid "Yes, discard changes" msgstr "" -msgid "No, stay here" +msgid "No, cancel" msgstr "" msgid "New event" @@ -264,9 +304,6 @@ msgstr "" msgid "enrollment" msgstr "" -msgid "in" -msgstr "" - msgid "Enroll in a program by selecting a program from the top bar." msgstr "" @@ -295,9 +332,6 @@ msgstr "" msgid "Registered person" msgstr "" -msgid "Leaving this page will discard the changes you made to this event." -msgstr "" - msgid "validation failed" msgstr "" @@ -313,10 +347,13 @@ msgstr "" msgid "Warnings" msgstr "" -msgid "Warnings found" +msgid "Generate new event" msgstr "" -msgid "Abort" +msgid "Do you want to create another event?" +msgstr "" + +msgid "Yes, create new event" msgstr "" msgid "Back to form" @@ -340,7 +377,9 @@ msgstr "" msgid "Operations running" msgstr "" -msgid "Sort" +msgid "" +"This event has unsaved changes. Leaving this page without saving will lose " +"these changes. Are you sure you want to discard unsaved changes?" msgstr "" msgid "No events to display" @@ -451,6 +490,12 @@ msgstr "" msgid "Select image" msgstr "" +msgid "Type to filter options" +msgstr "" + +msgid "No match found" +msgstr "" + msgid "Search" msgstr "" @@ -475,6 +520,9 @@ msgstr "" msgid "suggestions could not be retrieved" msgstr "" +msgid "No results found" +msgstr "" + msgid "No items to display" msgstr "" @@ -493,6 +541,9 @@ msgstr "" msgid "Reset filter" msgstr "" +msgid "Remove filter" +msgstr "" + msgid "{{fromDate}} to {{toDate}}" msgstr "" @@ -511,6 +562,9 @@ msgstr "" msgid "More filters" msgstr "" +msgid "Stage filters" +msgstr "" + msgid "Rows per page" msgstr "" @@ -535,19 +589,46 @@ msgstr "" msgid "Add comment" msgstr "" -msgid "You dont have access to write comments" +msgid "You don't have access to write comments" msgstr "" msgid "Write comment" msgstr "" +msgid "was blanked out and hidden by your last action" +msgstr "" + +msgid "Notice" +msgstr "" + +msgid "Close the notice" +msgstr "" + msgid "Use new Enrollment dashboard for {{programName}}" msgstr "" msgid "Opt in for {{programName}}" msgstr "" -msgid "No, cancel" +msgid "" +"By clicking opt-in below, you will start using the new enrollment dashboard " +"in the Capture app for this Tracker program. At the moment, there is certain" +" functionality from Tracker Capture that has not yet been added, including " +"relationship and referral functionality. The work on including this Tracker " +"functionality in Capture is ongoing and will be added in upcoming app " +"releases." +msgstr "" + +msgid "" +"The core team appreciates any feedback on this new functionality which is " +"currently being beta tested, please report any issues and feedback in the " +"DHIS2 JIRA project." +msgstr "" + +msgid "" +"Click the button below to opt-in to the new enrollment dashboard " +"functionality in the Capture app (beta) for this Tracker program for all " +"users." msgstr "" msgid "Yes, opt in" @@ -566,7 +647,8 @@ msgid "" "There is an error while opening this enrollment. Please enter a valid url." msgstr "" -msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" +msgid "" +"An error occurred while fetching enrollments. Please enter a valid url." msgstr "" msgid "Enrollment Dashboard" @@ -605,9 +687,21 @@ msgid "" "{{programName}} has categories. Choose all categories to view dashboard." msgstr "" +msgid "Invalid enrollment id {{enrollmentId}}." +msgstr "" + msgid "Choose an enrollment to view the dashboard." msgstr "" +msgid "There are no active enrollments." +msgstr "" + +msgid "Add new enrollment for {{teiDisplayName}} in this program." +msgstr "" + +msgid "No access to program owner." +msgstr "" + msgid "{{teiDisplayName}} is not enrolled in this program." msgstr "" @@ -670,7 +764,7 @@ msgstr "" msgid "Refer" msgstr "" -msgid "You can’t add any more events in this program" +msgid "You can't add any more {{ programStageName }} events" msgstr "" msgid "Cancel without saving" @@ -682,7 +776,7 @@ msgstr "" msgid "Program Stages could not be loaded" msgstr "" -msgid "stage" +msgid "Stage" msgstr "" msgid "Enrollment{{escape}} View Event" @@ -721,9 +815,6 @@ msgstr "" msgid "Save as new" msgstr "" -msgid "View dashboard" -msgstr "" - msgid "View enrollment" msgstr "" @@ -737,7 +828,10 @@ msgstr "" msgid "New Enrollment in program{{escape}} {{programName}}" msgstr "" -msgid "Save new" +msgid "Save {{trackedEntityTypeName}}" +msgstr "" + +msgid "Save {{trackedEntityName}}" msgstr "" msgid "Save new {{trackedEntityTypeName}} and link" @@ -785,213 +879,220 @@ msgstr "" msgid "Register" msgstr "" -msgid "" -"Fill in at least {{minAttributesRequiredToSearch}} attributes to search" +msgid "Back" msgstr "" -msgid "Search {{name}}" +msgid "events" msgstr "" -msgid "Search by {{name}}" +msgid "event" msgstr "" -msgid "Search by attributes" +msgid "You don't have access to edit this event" msgstr "" -msgid "Fill in these fields to search{{escape}} {{ searchableAttributes }}" +msgid "Edit event" +msgstr "" + +msgid "Event details" msgstr "" msgid "" -"Fill in at least {{minAttributesRequiredToSearch}} of these fields to " -"search{{escape}} {{searchableAttributes}}" +"Leaving this page will discard any selections you made for a new " +"relationship" msgstr "" -msgid "Fill in this field to search{{escape}} {{searchableAttributes}}" +msgid "No one is assigned to this event" msgstr "" -msgid "Back" +msgid "Assign" msgstr "" -msgid "Search for {{titleText}}" +msgid "Event assigned to {{name}}" msgstr "" -msgid "Search for" +msgid "Feedbacks" msgstr "" -msgid "" -"You can also choose a program from the top bar and search in that program" +msgid "Show all events" msgstr "" -msgid "No results found" +msgid "Event could not be loaded. Are you sure it exists?" msgstr "" -msgid "" -"You can change your search terms and search again to find what you are " -"looking for." +msgid "Event could not be loaded" msgstr "" -msgid "Register a user" +msgid "Organisation unit could not be loaded" msgstr "" -msgid "Back to search" +msgid "Selected program" msgstr "" -msgid "An error has occurred" +msgid "Search {{uniqueAttrName}}" msgstr "" -msgid "" -"There is a problem with this search, please change the search terms or try " -"again later. For more details open the Console tab of the Developer tools" +msgid "Search by attributes" msgstr "" -msgid "Too many results" +msgid "Could not retrieve metadata. Please try again later." msgstr "" -msgid "" -"This search returned too many results to show. Try changing search terms or " -"searching by more attributes to narrow down the results." +msgid "Possible duplicates found" msgstr "" -msgid "Cannot search in all programs" +msgid "An error occurred loading possible duplicates" msgstr "" -msgid "Choose a type to start searching" +msgid "You don't have access to delete this relationship" msgstr "" -msgid "View active enrollment" +msgid "You don't have access to create any relationships" msgstr "" -msgid "Re-enroll" +msgid "Add relationship" msgstr "" -msgid "all programs" +msgid "No results found for " msgstr "" -msgid "If none of search results match, you can create new " +msgid "Registering unit" msgstr "" -msgid "Create new" +msgid "Choose a registering unit" msgstr "" -msgid "" -"Not finding the results you were looking for? Try to search all programs " -"that use type " +msgid "Clear selection" msgstr "" -msgid "Search in all programs" +msgid "No programs available." msgstr "" -msgid "events" +msgid "Search for a program" msgstr "" -msgid "event" +msgid "Some programs are being filtered by the chosen registering unit" msgstr "" -msgid "You dont have access to edit this event" +msgid "Show all programs" msgstr "" -msgid "Edit event" +msgid "Choose a program" msgstr "" -msgid "Event details" +msgid "Search for {{titleText}}" +msgstr "" + +msgid "Search for" msgstr "" msgid "" -"Leaving this page will discard any selections you made for a new " -"relationship" +"You can also choose a program from the top bar and search in that program" msgstr "" -msgid "No one is assigned to this event" +msgid "Choose a type to start searching" msgstr "" -msgid "Assign" +msgid "Search {{name}}" msgstr "" -msgid "Event assigned to {{name}}" +msgid "Search by {{name}}" msgstr "" -msgid "Feedbacks" +msgid "all programs" msgstr "" -msgid "Show all events" +msgid "" +"Not finding the results you were looking for? Try to search all programs " +"that use type " msgstr "" -msgid "Event could not be loaded. Are you sure it exists?" +msgid "Search in all programs" msgstr "" -msgid "Event could not be loaded" +msgid "If none of search results match, you can create a new " msgstr "" -msgid "Organisation unit could not be loaded" +msgid "Create new" msgstr "" -msgid "Possible duplicates found" +msgid "Fill in these fields to search{{escape}} {{ searchableAttributes }}" msgstr "" -msgid "An error occurred loading possible duplicates" +msgid "" +"Fill in at least {{minAttributesRequiredToSearch}} of these fields to " +"search{{escape}} {{searchableAttributes}}" msgstr "" -msgid "You dont have access to delete this relationship" +msgid "Fill in this field to search{{escape}} {{searchableAttributes}}" msgstr "" -msgid "You dont have access to create any relationships" +msgid "" +"You can change your search terms and search again to find what you are " +"looking for." msgstr "" -msgid "Add relationship" +msgid "Back to search" msgstr "" -msgid "Selected registering unit" +msgid "An error has occurred" msgstr "" -msgid "Start Again" +msgid "Too many results" msgstr "" -msgid "Are you sure? All unsaved data will be lost." +msgid "Cannot search in all programs" msgstr "" -msgid "Accept" +msgid "Missing search criteria" msgstr "" -msgid "Registering Organisation Unit" +msgid "Results found" msgstr "" -msgid "Select" +msgid "Saved lists in this program" msgstr "" -msgid "No programs available." +msgid "Saved lists offer quick access to your most used views in a program." msgstr "" -msgid "Selected program" +msgid "" +"There are no saved lists in this program yet, create one using the button " +"below." msgstr "" -msgid "Select program" +msgid "Create saved list" msgstr "" -msgid "Selected" +msgid "New {{trackedEntityName}} in {{programName}}" msgstr "" -msgid "Results found" +msgid "Search for a {{trackedEntityName}} in {{programName}}" msgstr "" -msgid "Search {{uniqueAttrName}}" +msgid "To work with the selected program," msgstr "" -msgid "Fill in at least {{minAttributesRequired}} attributes to search" +msgid "open the Tracker Capture app" msgstr "" -msgid "New {{trackedEntityName}} in {{programName}}" +msgid "This program is protected" msgstr "" -msgid "Search for a {{trackedEntityName}} in {{programName}}" +msgid "Reason to check for enrollments" msgstr "" -msgid "Clear selections" +msgid "" +"Describe the reason you are checking for enrollments in this protected " +"program" msgstr "" -msgid "To work with the selected program," +msgid "Check for enrollments" msgstr "" -msgid "open the Tracker Capture app" +msgid "" +"You must provide a reason to check for enrollments in this protected " +"program. All activity will be logged." msgstr "" msgid "Save comment" @@ -1003,10 +1104,10 @@ msgstr "" msgid "We are processing your request." msgstr "" -msgid "Add new" +msgid "Only one enrollment per {{tetName}} is allowed in this program" msgstr "" -msgid "Only one enrollment per {{tetName}} is allowed in this program" +msgid "Add new" msgstr "" msgid "Reactivate" @@ -1035,6 +1136,36 @@ msgstr "" msgid "Mark for follow-up" msgstr "" +msgid "Existing dates for auto-generated events will not be updated." +msgstr "" + +msgid "Latitude" +msgstr "ଅକ୍ଷାଂଶ" + +msgid "Longitude" +msgstr "ଦ୍ରାଘିମା" + +msgid "Edit" +msgstr "" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "" + +msgid "Delete polygon" +msgstr "" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "" + msgid "Enrollment date" msgstr "" @@ -1059,6 +1190,12 @@ msgstr "" msgid "Cancelled" msgstr "" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1101,40 +1238,34 @@ msgstr "" msgid "Yes, delete event" msgstr "" +msgid "Go to “Schedule” tab to reschedule this event" +msgstr "" + +msgid "Scheduled date cannot be changed for {{ eventStatus }} events" +msgstr "" + msgid "Event completed" msgstr "" msgid "Back to all stages and events" msgstr "" -msgid "You don't have access to edit this event" +msgid "Schedule date info" msgstr "" -msgid "Schedule date info" +msgid "Scheduled automatically for {{suggestedScheduleDate}}" msgstr "" msgid "" -"This date is the suggested scheduled date based on the intervals defined, \n" -" it can be adjusted if needed." +"The scheduled date matches the suggested date, but can be changed if needed." msgstr "" -msgid "This date is {{count}} days {{position}} the suggested date." -msgid_plural "This date is {{count}} days {{position}} the suggested date." -msgstr[0] "" -msgstr[1] "" - msgid "after" msgstr "" msgid "before" msgstr "" -msgid "There are {{count}} scheduled event in {{orgUnitName}} on this day." -msgid_plural "" -"There are {{count}} scheduled event in {{orgUnitName}} on this day." -msgstr[0] "" -msgstr[1] "" - msgid "" "Scheduling an event in {{stageName}} for {{programName}} in {{orgUnitName}}" msgstr "" @@ -1178,9 +1309,6 @@ msgstr "" msgid "Try again or contact your system administrator for support" msgstr "" -msgid "tracked entity instance" -msgstr "" - msgid "Fix errors in the form to continue." msgstr "" @@ -1190,13 +1318,13 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" +msgid "tracked entity instance" msgstr "" msgid "New {{ eventName }} event" msgstr "" -msgid "This event is not yet preserved and cannot be edited" +msgid "To open this event, please wait until saving is complete" msgstr "" msgid "Show {{ rest }} more" @@ -1214,9 +1342,6 @@ msgstr "" msgid "Events could not be retrieved. Please try again later." msgstr "" -msgid "Registering unit" -msgstr "" - msgid "{{ totalEvents }} events" msgstr "" @@ -1229,13 +1354,47 @@ msgstr "" msgid "Stages and Events" msgstr "" -msgid "Working list could not be loaded" +msgid "New TEI Relationship" msgstr "" -msgid "Download as JSON" +msgid "Missing implementation step" +msgstr "" + +msgid "Go back without saving relationship" +msgstr "" + +msgid "New Relationship" +msgstr "" + +msgid "Link to an existing {{tetName}}" +msgstr "" + +msgid "An error occurred while adding the relationship" +msgstr "" + +msgid "" +"Something went wrong while loading relationships. Please try again later." +msgstr "" + +msgid "{{trackedEntityTypeName}} relationships" +msgstr "" + +msgid "To open this relationship, please wait until saving is complete" +msgstr "" + +msgid "Type" msgstr "" -msgid "Download as XML" +msgid "Created date" +msgstr "" + +msgid "Program stage name" +msgstr "" + +msgid "Working list could not be loaded" +msgstr "" + +msgid "Download as JSON" msgstr "" msgid "Download as CSV" @@ -1250,9 +1409,6 @@ msgstr "" msgid "an error occurred loading working lists" msgstr "" -msgid "Enrollment status" -msgstr "" - msgid "Assigned to" msgstr "" @@ -1262,9 +1418,27 @@ msgstr "" msgid "Inactive" msgstr "" +msgid "Enrollment status" +msgstr "" + +msgid "Choose a program stage to filter by {{label}}" +msgstr "" + +msgid "Active enrollments" +msgstr "" + +msgid "Completed enrollments" +msgstr "" + +msgid "Cancelled enrollments" +msgstr "" + msgid "Working list could not be updated" msgstr "" +msgid "an error occurred loading the working lists" +msgstr "" + msgid "an error occurred loading Tracked entity instance lists" msgstr "" @@ -1319,6 +1493,9 @@ msgstr "" msgid "Skipped" msgstr "" +msgid "Visited" +msgstr "" + msgid "{{trackedEntityName}} in program{{escape}} {{programName}}" msgstr "" @@ -1367,9 +1544,6 @@ msgstr "" msgid "Set coordinate" msgstr "" -msgid "Page {{currentPage}}" -msgstr "" - msgid "Date" msgstr "" @@ -1388,16 +1562,10 @@ msgstr "" msgid "To time" msgstr "" -msgid "error encountered during field validation" -msgstr "" - -msgid "error" -msgstr "" - -msgid "Delete polygon" +msgid "Page {{currentPage}}" msgstr "" -msgid "Set area" +msgid "Area on map saved" msgstr "" msgid "Compatibility mode" diff --git a/i18n/prs.po b/i18n/prs.po index 4ae583ebe5..f7a6858ec0 100644 --- a/i18n/prs.po +++ b/i18n/prs.po @@ -520,6 +520,9 @@ msgstr "" msgid "suggestions could not be retrieved" msgstr "" +msgid "No results found" +msgstr "هیج نتیجه ی یافت نشد" + msgid "No items to display" msgstr "" @@ -938,9 +941,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "" -msgid "No results found" -msgstr "هیج نتیجه ی یافت نشد" - msgid "An error occurred loading possible duplicates" msgstr "" @@ -1139,6 +1139,33 @@ msgstr "نشانی برای پیگیری" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "عرض البلد" + +msgid "Longitude" +msgstr "طول البلد" + +msgid "Edit" +msgstr "تجدید" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "ځانګړتیاوې" + +msgid "Delete polygon" +msgstr "" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "" + msgid "Enrollment date" msgstr "تاریخ شمولیت" @@ -1163,6 +1190,12 @@ msgstr "" msgid "Cancelled" msgstr "" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1285,9 +1318,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "تجدید" - msgid "tracked entity instance" msgstr "" @@ -1535,12 +1565,6 @@ msgstr "" msgid "Page {{currentPage}}" msgstr "" -msgid "Delete polygon" -msgstr "" - -msgid "Set area" -msgstr "" - msgid "Area on map saved" msgstr "" diff --git a/i18n/ps.po b/i18n/ps.po index 51a9bdd72a..6e904c62e5 100644 --- a/i18n/ps.po +++ b/i18n/ps.po @@ -1,14 +1,14 @@ # # Translators: -# Viktor Varland , 2023 # Philip Larsen Donnelly, 2023 +# Viktor Varland , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Philip Larsen Donnelly, 2023\n" +"Last-Translator: Viktor Varland , 2023\n" "Language-Team: Pashto (https://app.transifex.com/hisp-uio/teams/100509/ps/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1140,6 +1140,33 @@ msgstr "د تعقيب لپاره يې په نښه کړئ" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "لېټېټيوډ" + +msgid "Longitude" +msgstr "لانګېټيوډ" + +msgid "Edit" +msgstr "درست یې کړئ" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "مختصات" + +msgid "Delete polygon" +msgstr "" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "" + msgid "Enrollment date" msgstr "د نوم ثبتونې نېټه" @@ -1164,6 +1191,12 @@ msgstr "" msgid "Cancelled" msgstr "لغوه شوی" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1286,9 +1319,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "درست یې کړئ" - msgid "tracked entity instance" msgstr "" @@ -1536,12 +1566,6 @@ msgstr "" msgid "Page {{currentPage}}" msgstr "" -msgid "Delete polygon" -msgstr "" - -msgid "Set area" -msgstr "" - msgid "Area on map saved" msgstr "" diff --git a/i18n/pt.po b/i18n/pt.po index cea52926b0..102c4482d0 100644 --- a/i18n/pt.po +++ b/i18n/pt.po @@ -547,6 +547,9 @@ msgstr "comece a digitar para pesquisar" msgid "suggestions could not be retrieved" msgstr "sugestões não puderam ser recuperadas" +msgid "No results found" +msgstr "Nenhum resultado encontrado" + msgid "No items to display" msgstr "Nenhum item para exibir" @@ -991,9 +994,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "Possíveis duplicatas encontradas" -msgid "No results found" -msgstr "Nenhum resultado encontrado" - msgid "An error occurred loading possible duplicates" msgstr "Ocorreu um erro ao carregar possíveis duplicatas" @@ -1211,6 +1211,33 @@ msgstr "Marcar para acompanhamento" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Latitude" + +msgid "Longitude" +msgstr "Longitude" + +msgid "Edit" +msgstr "Editar" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "Coordenadas" + +msgid "Delete polygon" +msgstr "Excluir polígono" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "Definir área" + msgid "Enrollment date" msgstr "Data de inscrição" @@ -1237,6 +1264,12 @@ msgstr "Última atualização em {{date}}" msgid "Cancelled" msgstr "Cancelado" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "Comentários sobre esta inscrição" @@ -1371,9 +1404,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "{{TETName}} perfil" -msgid "Edit" -msgstr "Editar" - msgid "tracked entity instance" msgstr "instância de entidade rastreada" @@ -1625,12 +1655,6 @@ msgstr "Para o tempo" msgid "Page {{currentPage}}" msgstr "Página {{currentPage}}" -msgid "Delete polygon" -msgstr "Excluir polígono" - -msgid "Set area" -msgstr "Definir área" - msgid "Area on map saved" msgstr "Área no mapa gravada" diff --git a/i18n/pt_BR.po b/i18n/pt_BR.po index cca4b80e6f..fa227d2a98 100644 --- a/i18n/pt_BR.po +++ b/i18n/pt_BR.po @@ -1141,6 +1141,33 @@ msgstr "" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Latitude" + +msgid "Longitude" +msgstr "Longitude" + +msgid "Edit" +msgstr "Editar" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "Coordenadas" + +msgid "Delete polygon" +msgstr "" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "" + msgid "Enrollment date" msgstr "" @@ -1165,6 +1192,12 @@ msgstr "" msgid "Cancelled" msgstr "" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1287,9 +1320,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "Editar" - msgid "tracked entity instance" msgstr "" @@ -1537,12 +1567,6 @@ msgstr "" msgid "Page {{currentPage}}" msgstr "" -msgid "Delete polygon" -msgstr "" - -msgid "Set area" -msgstr "" - msgid "Area on map saved" msgstr "" diff --git a/i18n/ru.po b/i18n/ru.po index 3ba772b823..95c94ed984 100644 --- a/i18n/ru.po +++ b/i18n/ru.po @@ -543,6 +543,9 @@ msgstr "Начинайте вводить для поиска" msgid "suggestions could not be retrieved" msgstr "Подсказка не может быть найдена" +msgid "No results found" +msgstr "Результаты не найдены" + msgid "No items to display" msgstr "Нет элементов для отображения" @@ -964,9 +967,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "Найдены возможные дубликаты" -msgid "No results found" -msgstr "Результаты не найдены" - msgid "An error occurred loading possible duplicates" msgstr "" @@ -1165,6 +1165,33 @@ msgstr "Отметить для последующего наблюдения" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Широта" + +msgid "Longitude" +msgstr "Долгота" + +msgid "Edit" +msgstr "Редактировать" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "Координаты" + +msgid "Delete polygon" +msgstr "Удалить полигон" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "Установить площадь" + msgid "Enrollment date" msgstr "Дата зачисления" @@ -1189,6 +1216,12 @@ msgstr "" msgid "Cancelled" msgstr "Отмененный" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1311,9 +1344,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "Редактировать" - msgid "tracked entity instance" msgstr "Элемент отслеживаемого объекта" @@ -1561,12 +1591,6 @@ msgstr "ко времени" msgid "Page {{currentPage}}" msgstr "Страница {{currentPage}}" -msgid "Delete polygon" -msgstr "Удалить полигон" - -msgid "Set area" -msgstr "Установить площадь" - msgid "Area on map saved" msgstr "" diff --git a/i18n/sv.po b/i18n/sv.po index 12f88faefd..980919e391 100644 --- a/i18n/sv.po +++ b/i18n/sv.po @@ -1,15 +1,15 @@ # # Translators: -# Viktor Varland , 2023 # Jason Pickering , 2023 # Philip Larsen Donnelly, 2023 +# Viktor Varland , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Philip Larsen Donnelly, 2023\n" +"Last-Translator: Viktor Varland , 2023\n" "Language-Team: Swedish (https://app.transifex.com/hisp-uio/teams/100509/sv/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1141,6 +1141,33 @@ msgstr "" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Latitud" + +msgid "Longitude" +msgstr "Longitud" + +msgid "Edit" +msgstr "Redigera" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "koordinater" + +msgid "Delete polygon" +msgstr "" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "" + msgid "Enrollment date" msgstr "inskrivning datum" @@ -1165,6 +1192,12 @@ msgstr "" msgid "Cancelled" msgstr "Avbruten" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1287,9 +1320,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "Redigera" - msgid "tracked entity instance" msgstr "" @@ -1537,12 +1567,6 @@ msgstr "" msgid "Page {{currentPage}}" msgstr "" -msgid "Delete polygon" -msgstr "" - -msgid "Set area" -msgstr "" - msgid "Area on map saved" msgstr "" diff --git a/i18n/tg.po b/i18n/tg.po index e231a3fb60..76ef7fdb4d 100644 --- a/i18n/tg.po +++ b/i18n/tg.po @@ -1,14 +1,14 @@ # # Translators: -# Viktor Varland , 2023 # Philip Larsen Donnelly, 2023 +# Viktor Varland , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Philip Larsen Donnelly, 2023\n" +"Last-Translator: Viktor Varland , 2023\n" "Language-Team: Tajik (https://app.transifex.com/hisp-uio/teams/100509/tg/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1140,6 +1140,33 @@ msgstr "" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Тӯл" + +msgid "Longitude" +msgstr "Арз" + +msgid "Edit" +msgstr "Таҳрир" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "Координатаҳо" + +msgid "Delete polygon" +msgstr "" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "" + msgid "Enrollment date" msgstr "Санаи номнавис" @@ -1164,6 +1191,12 @@ msgstr "" msgid "Cancelled" msgstr "" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1286,9 +1319,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "Таҳрир" - msgid "tracked entity instance" msgstr "" @@ -1536,12 +1566,6 @@ msgstr "" msgid "Page {{currentPage}}" msgstr "" -msgid "Delete polygon" -msgstr "" - -msgid "Set area" -msgstr "" - msgid "Area on map saved" msgstr "" diff --git a/i18n/uk.po b/i18n/uk.po index 0697b82144..610b8d9f56 100644 --- a/i18n/uk.po +++ b/i18n/uk.po @@ -2,16 +2,16 @@ # Translators: # Wanda , 2021 # Nadiia , 2023 -# Viktor Varland , 2023 # Éva Tamási, 2023 # Philip Larsen Donnelly, 2023 +# Viktor Varland , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Philip Larsen Donnelly, 2023\n" +"Last-Translator: Viktor Varland , 2023\n" "Language-Team: Ukrainian (https://app.transifex.com/hisp-uio/teams/100509/uk/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1143,6 +1143,33 @@ msgstr "Позначте для подальших дій" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Широта" + +msgid "Longitude" +msgstr "Довгота" + +msgid "Edit" +msgstr "Редагувати" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "" + +msgid "Delete polygon" +msgstr "" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "" + msgid "Enrollment date" msgstr "Дата реєстрації" @@ -1167,6 +1194,12 @@ msgstr "" msgid "Cancelled" msgstr "Скасовано" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1289,9 +1322,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "Редагувати" - msgid "tracked entity instance" msgstr "" @@ -1539,12 +1569,6 @@ msgstr "" msgid "Page {{currentPage}}" msgstr "" -msgid "Delete polygon" -msgstr "" - -msgid "Set area" -msgstr "" - msgid "Area on map saved" msgstr "" diff --git a/i18n/ur.po b/i18n/ur.po index c87c2e613a..458326829b 100644 --- a/i18n/ur.po +++ b/i18n/ur.po @@ -1,14 +1,14 @@ # # Translators: -# Viktor Varland , 2023 # Philip Larsen Donnelly, 2023 +# Viktor Varland , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Philip Larsen Donnelly, 2023\n" +"Last-Translator: Viktor Varland , 2023\n" "Language-Team: Urdu (https://app.transifex.com/hisp-uio/teams/100509/ur/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -521,6 +521,9 @@ msgstr "" msgid "suggestions could not be retrieved" msgstr "" +msgid "No results found" +msgstr "کوئی نتیجہ نہیں ملا" + msgid "No items to display" msgstr "" @@ -939,9 +942,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "" -msgid "No results found" -msgstr "کوئی نتیجہ نہیں ملا" - msgid "An error occurred loading possible duplicates" msgstr "" @@ -1140,6 +1140,33 @@ msgstr "اپ کے لئے نشان زد کریں" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "طول" + +msgid "Longitude" +msgstr "لمبائی" + +msgid "Edit" +msgstr "ترمیم" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "سماج" + +msgid "Delete polygon" +msgstr "" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "" + msgid "Enrollment date" msgstr "اندراج کی تاریخ" @@ -1164,6 +1191,12 @@ msgstr "" msgid "Cancelled" msgstr "منسوخ" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1286,9 +1319,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "ترمیم" - msgid "tracked entity instance" msgstr "" @@ -1536,12 +1566,6 @@ msgstr "" msgid "Page {{currentPage}}" msgstr "" -msgid "Delete polygon" -msgstr "" - -msgid "Set area" -msgstr "" - msgid "Area on map saved" msgstr "" diff --git a/i18n/uz_UZ_Cyrl.po b/i18n/uz_UZ_Cyrl.po index 620b5591f9..0b7928980e 100644 --- a/i18n/uz_UZ_Cyrl.po +++ b/i18n/uz_UZ_Cyrl.po @@ -294,7 +294,7 @@ msgstr "" " қилинади." msgid "Yes, discard changes" -msgstr "" +msgstr "Ҳа, ўзгартиришлар бекор қилинсин" msgid "No, cancel" msgstr "Йўқ, бекор қилинг" @@ -1181,7 +1181,7 @@ msgid "Latitude" msgstr "Кенглик" msgid "Longitude" -msgstr "" +msgstr "Узунлик" msgid "Edit" msgstr "Таҳрирлаш" diff --git a/i18n/uz_UZ_Latn.po b/i18n/uz_UZ_Latn.po index 944b63b094..7e11d32a5a 100644 --- a/i18n/uz_UZ_Latn.po +++ b/i18n/uz_UZ_Latn.po @@ -541,6 +541,9 @@ msgstr "qidirish uchun yozishni boshlang" msgid "suggestions could not be retrieved" msgstr "takliflar qabul qilinmadi" +msgid "No results found" +msgstr "Hech qanday natija topilmadi" + msgid "No items to display" msgstr "Koʼrsatiladigan axborot yoʼq" @@ -963,9 +966,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "Boʼlishi mumkin boʼlgan nusxalar topildi" -msgid "No results found" -msgstr "Hech qanday natija topilmadi" - msgid "An error occurred loading possible duplicates" msgstr "" @@ -1168,6 +1168,33 @@ msgstr "Kuzatuv uchun belgilang" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Kenglik" + +msgid "Longitude" +msgstr "Kenglik" + +msgid "Edit" +msgstr "Tahrirlash" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "Координаталар" + +msgid "Delete polygon" +msgstr "Poligon (koʼpburchak) ni oʼchirib tashlash" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "Hududni belgilang" + msgid "Enrollment date" msgstr "Qayd qilingan sana" @@ -1192,6 +1219,12 @@ msgstr "" msgid "Cancelled" msgstr "Bekor qilindi" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1314,9 +1347,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "Tahrirlash" - msgid "tracked entity instance" msgstr "kuzatilayotgan obʼekt namunasi" @@ -1565,12 +1595,6 @@ msgstr "Shu vaqtgacha" msgid "Page {{currentPage}}" msgstr "{{currentPage}} sahifasi" -msgid "Delete polygon" -msgstr "Poligon (koʼpburchak) ni oʼchirib tashlash" - -msgid "Set area" -msgstr "Hududni belgilang" - msgid "Area on map saved" msgstr "" diff --git a/i18n/vi.po b/i18n/vi.po index a2b56bfc1e..ac142f4ea7 100644 --- a/i18n/vi.po +++ b/i18n/vi.po @@ -2,15 +2,15 @@ # Translators: # Mai Nguyen , 2022 # Thuy Nguyen , 2023 -# Viktor Varland , 2023 # Philip Larsen Donnelly, 2023 +# Viktor Varland , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Philip Larsen Donnelly, 2023\n" +"Last-Translator: Viktor Varland , 2023\n" "Language-Team: Vietnamese (https://app.transifex.com/hisp-uio/teams/100509/vi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -537,6 +537,9 @@ msgstr "bắt đầu nhập để tìm kiếm" msgid "suggestions could not be retrieved" msgstr "đề xuất không thể được truy xuất" +msgid "No results found" +msgstr "Không tìm thấy kết quả nào" + msgid "No items to display" msgstr "Không có mục để hiển thị" @@ -957,9 +960,6 @@ msgstr "" msgid "Possible duplicates found" msgstr "Có thể tìm thấy các bản sao" -msgid "No results found" -msgstr "Không tìm thấy kết quả nào" - msgid "An error occurred loading possible duplicates" msgstr "" @@ -1164,6 +1164,33 @@ msgstr "Đánh dấu để theo-dõi" msgid "Existing dates for auto-generated events will not be updated." msgstr "" +msgid "Latitude" +msgstr "Vĩ độ" + +msgid "Longitude" +msgstr "Kinh độ" + +msgid "Edit" +msgstr "Chỉnh sửa" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "Toạ độ" + +msgid "Delete polygon" +msgstr "Xóa đa giác" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "Đặt khu vực" + msgid "Enrollment date" msgstr "Ngày ghi vào" @@ -1188,6 +1215,12 @@ msgstr "" msgid "Cancelled" msgstr "Đã hủy" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "" @@ -1310,9 +1343,6 @@ msgstr "" msgid "{{TETName}} profile" msgstr "" -msgid "Edit" -msgstr "Chỉnh sửa" - msgid "tracked entity instance" msgstr "thực thể được theo dõi" @@ -1560,12 +1590,6 @@ msgstr "Đến " msgid "Page {{currentPage}}" msgstr "Trang {{currentPage}}" -msgid "Delete polygon" -msgstr "Xóa đa giác" - -msgid "Set area" -msgstr "Đặt khu vực" - msgid "Area on map saved" msgstr "" diff --git a/i18n/zh.po b/i18n/zh.po index 78121cdf22..5723afede3 100644 --- a/i18n/zh.po +++ b/i18n/zh.po @@ -1,16 +1,16 @@ # # Translators: # Philip Larsen Donnelly, 2022 -# Viktor Varland , 2023 -# 晓东 林 <13981924470@126.com>, 2023 # easylin , 2023 +# 晓东 林 <13981924470@126.com>, 2023 +# Viktor Varland , 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: easylin , 2023\n" +"Last-Translator: Viktor Varland , 2023\n" "Language-Team: Chinese (https://app.transifex.com/hisp-uio/teams/100509/zh/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1149,6 +1149,33 @@ msgstr "后续标记" msgid "Existing dates for auto-generated events will not be updated." msgstr "自动生成的事件的现有日期将不会更新。" +msgid "Latitude" +msgstr "维度" + +msgid "Longitude" +msgstr "经度" + +msgid "Edit" +msgstr "编辑" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "坐标" + +msgid "Delete polygon" +msgstr "删除多边形" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "设置区域" + msgid "Enrollment date" msgstr "报名日期" @@ -1173,6 +1200,12 @@ msgstr "最近更新的{{date}}" msgid "Cancelled" msgstr "已取消" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "关于本次报名的评论" @@ -1295,9 +1328,6 @@ msgstr "无法加载个人资料窗口小部件。请稍后再试" msgid "{{TETName}} profile" msgstr "{{TETName}} 基本信息" -msgid "Edit" -msgstr "编辑" - msgid "tracked entity instance" msgstr "跟踪的实体实例" @@ -1545,12 +1575,6 @@ msgstr "到时间" msgid "Page {{currentPage}}" msgstr "第{{currentPage}}页" -msgid "Delete polygon" -msgstr "删除多边形" - -msgid "Set area" -msgstr "设置区域" - msgid "Area on map saved" msgstr "地图上的区域已保存" diff --git a/i18n/zh_CN.po b/i18n/zh_CN.po index 215b2766d8..6ebfc4ee69 100644 --- a/i18n/zh_CN.po +++ b/i18n/zh_CN.po @@ -1,14 +1,14 @@ # # Translators: -# 晓东 林 <13981924470@126.com>, 2023 # easylin , 2023 +# 晓东 林 <13981924470@126.com>, 2023 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" "POT-Creation-Date: 2023-09-12T06:24:49.265Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: easylin , 2023\n" +"Last-Translator: 晓东 林 <13981924470@126.com>, 2023\n" "Language-Team: Chinese (China) (https://app.transifex.com/hisp-uio/teams/100509/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1147,6 +1147,33 @@ msgstr "后续标记" msgid "Existing dates for auto-generated events will not be updated." msgstr "自动生成的事件的现有日期将不会更新。" +msgid "Latitude" +msgstr "纬度" + +msgid "Longitude" +msgstr "经度" + +msgid "Edit" +msgstr "编辑" + +msgid "Set coordinates" +msgstr "" + +msgid "Coordinates" +msgstr "坐标" + +msgid "Delete polygon" +msgstr "删除多边形" + +msgid "Close without saving" +msgstr "" + +msgid "Finish drawing before saving" +msgstr "" + +msgid "Set area" +msgstr "设置区域" + msgid "Enrollment date" msgstr "报名日期" @@ -1171,6 +1198,12 @@ msgstr "最近更新的{{date}}" msgid "Cancelled" msgstr "已取消" +msgid "Add coordinates" +msgstr "" + +msgid "Add area" +msgstr "" + msgid "Comments about this enrollment" msgstr "关于本次报名的评论" @@ -1293,9 +1326,6 @@ msgstr "无法加载个人资料窗口小部件。请稍后再试" msgid "{{TETName}} profile" msgstr "{{TETName}}个人资料" -msgid "Edit" -msgstr "编辑" - msgid "tracked entity instance" msgstr "跟踪的实体实例" @@ -1543,12 +1573,6 @@ msgstr "到时间" msgid "Page {{currentPage}}" msgstr "第{{currentPage}}页" -msgid "Delete polygon" -msgstr "删除多边形" - -msgid "Set area" -msgstr "设置区域" - msgid "Area on map saved" msgstr "地图上的区域已保存" From efa835efd46051243ac0b457d6b403b2a15d0da4 Mon Sep 17 00:00:00 2001 From: "@dhis2-bot" Date: Sun, 3 Dec 2023 01:43:17 +0000 Subject: [PATCH 17/18] chore(release): cut 100.47.0 [skip release] # [100.47.0](https://github.com/dhis2/capture-app/compare/v100.46.1...v100.47.0) (2023-12-03) ### Bug Fixes * **translations:** sync translations from transifex (master) ([e20fb8c](https://github.com/dhis2/capture-app/commit/e20fb8c551aefb0546c5973dd87940d56e3018be)) ### Features * [DHIS2-16123] Add inheritable TEAs to Relationships ([#3464](https://github.com/dhis2/capture-app/issues/3464)) ([620b008](https://github.com/dhis2/capture-app/commit/620b00832da7c4951d6e905b40317dd0acca0aa6)) --- CHANGELOG.md | 12 ++++++++++++ package.json | 4 ++-- packages/rules-engine/package.json | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b603a0b17..e6878dc55d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# [100.47.0](https://github.com/dhis2/capture-app/compare/v100.46.1...v100.47.0) (2023-12-03) + + +### Bug Fixes + +* **translations:** sync translations from transifex (master) ([e20fb8c](https://github.com/dhis2/capture-app/commit/e20fb8c551aefb0546c5973dd87940d56e3018be)) + + +### Features + +* [DHIS2-16123] Add inheritable TEAs to Relationships ([#3464](https://github.com/dhis2/capture-app/issues/3464)) ([620b008](https://github.com/dhis2/capture-app/commit/620b00832da7c4951d6e905b40317dd0acca0aa6)) + ## [100.46.1](https://github.com/dhis2/capture-app/compare/v100.46.0...v100.46.1) (2023-11-30) diff --git a/package.json b/package.json index 4648cadedc..a510d227de 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "capture-app", "homepage": ".", - "version": "100.46.1", + "version": "100.47.0", "cacheVersion": "7", "serverVersion": "38", "license": "BSD-3-Clause", @@ -10,7 +10,7 @@ "packages/rules-engine" ], "dependencies": { - "@dhis2/rules-engine-javascript": "100.46.1", + "@dhis2/rules-engine-javascript": "100.47.0", "@dhis2/app-runtime": "^3.9.3", "@dhis2/d2-i18n": "^1.1.0", "@dhis2/d2-icons": "^1.0.1", diff --git a/packages/rules-engine/package.json b/packages/rules-engine/package.json index ff1415cd4f..a894110539 100644 --- a/packages/rules-engine/package.json +++ b/packages/rules-engine/package.json @@ -1,6 +1,6 @@ { "name": "@dhis2/rules-engine-javascript", - "version": "100.46.1", + "version": "100.47.0", "license": "BSD-3-Clause", "main": "./build/cjs/index.js", "scripts": { From a47e429fc7148cf7c86c0b7865e87147cdbe1cfa Mon Sep 17 00:00:00 2001 From: Simona Domnisoru Date: Mon, 4 Dec 2023 08:32:29 +0100 Subject: [PATCH 18/18] test: [TECH-887] improve rules engine unit test coverage (#3462) --- packages/rules-engine/src/RulesEngine.js | 2 +- .../src/helpers/previousValueCheck.js | 2 +- .../rulesEffectsProcessor.js | 27 +- .../helpers/structureEvents.js | 6 +- ...eRuleEffectsForTrackerProgram.test.js.snap | 2 +- ...icableRuleEffectsForTrackerProgram.test.js | 150 +- ...licableRulesEffectsForEventProgram.test.js | 68 +- .../__tests__/postProcessRulesEffects.test.js | 211 ++ .../ruleEffectsForEventProgram.test.js | 2854 +++++++++++++++-- .../rulesEffectsForTrackerProgram.test.js | 889 ++++- .../rules/__tests__/rulesEngine.test.js | 717 +++++ 11 files changed, 4522 insertions(+), 406 deletions(-) create mode 100644 src/core_modules/capture-core/rules/__tests__/postProcessRulesEffects.test.js create mode 100644 src/core_modules/capture-core/rules/__tests__/rulesEngine.test.js diff --git a/packages/rules-engine/src/RulesEngine.js b/packages/rules-engine/src/RulesEngine.js index bbd6f279d1..d634f5d558 100644 --- a/packages/rules-engine/src/RulesEngine.js +++ b/packages/rules-engine/src/RulesEngine.js @@ -1,6 +1,6 @@ // @flow import log from 'loglevel'; -import { VariableService } from './services/VariableService/VariableService'; +import { VariableService } from './services/VariableService'; import { ValueProcessor } from './processors/ValueProcessor'; import { executeExpression } from './services/expressionService'; import { getD2Functions } from './d2Functions'; diff --git a/packages/rules-engine/src/helpers/previousValueCheck.js b/packages/rules-engine/src/helpers/previousValueCheck.js index 628900c6be..5745315d04 100644 --- a/packages/rules-engine/src/helpers/previousValueCheck.js +++ b/packages/rules-engine/src/helpers/previousValueCheck.js @@ -59,7 +59,7 @@ export const getOutputEffectsWithPreviousValueCheck = ({ onProcessValue: (value: any, type: $Values) => any, }) => outputEffects.reduce((acc, outputEffect) => { - if (formValues && outputEffect.targetDataType) { + if (formValues && Object.keys(formValues).length !== 0 && outputEffect.targetDataType) { const formValue = formValues[outputEffect.id]; const rawValue = mapByTargetDataTypes[outputEffect.targetDataType]({ dataElementId, diff --git a/packages/rules-engine/src/processors/rulesEffectsProcessor/rulesEffectsProcessor.js b/packages/rules-engine/src/processors/rulesEffectsProcessor/rulesEffectsProcessor.js index 15951dbc57..72cbd2f20f 100644 --- a/packages/rules-engine/src/processors/rulesEffectsProcessor/rulesEffectsProcessor.js +++ b/packages/rules-engine/src/processors/rulesEffectsProcessor/rulesEffectsProcessor.js @@ -296,26 +296,23 @@ export function getRulesEffectsProcessor( formValues, onProcessValue, }: { - effects: ?Array, + effects: Array, dataElements: ?DataElements, trackedEntityAttributes: ?TrackedEntityAttributes, formValues?: ?{ [key: string]: any }, onProcessValue: (value: any, type: $Values) => any, }): OutputEffects { - if (effects) { - return effects - .filter(({ action }) => mapActionsToProcessor[action]) - .flatMap(effect => mapActionsToProcessor[effect.action]( - effect, - dataElements, - trackedEntityAttributes, - formValues, - onProcessValue, - )) - // when mapActionsToProcessor function returns `null` we filter those value out. - .filter(keepTruthyValues => keepTruthyValues); - } - return []; + return effects + .filter(({ action }) => mapActionsToProcessor[action]) + .flatMap(effect => mapActionsToProcessor[effect.action]( + effect, + dataElements, + trackedEntityAttributes, + formValues, + onProcessValue, + )) + // when mapActionsToProcessor function returns `null` we filter those value out. + .filter(keepTruthyValues => keepTruthyValues); } return processRulesEffects; diff --git a/packages/rules-engine/src/services/VariableService/helpers/structureEvents.js b/packages/rules-engine/src/services/VariableService/helpers/structureEvents.js index e0e1422616..7c4fcab7f8 100644 --- a/packages/rules-engine/src/services/VariableService/helpers/structureEvents.js +++ b/packages/rules-engine/src/services/VariableService/helpers/structureEvents.js @@ -38,9 +38,9 @@ export const getStructureEvents = (compareDates: CompareDates) => { event.eventId !== currentEvent.eventId, ); - const events = [...otherEventsFiltered, currentEvent] - .sort(compareEvents); + const events = Object.keys(currentEvent).length !== 0 ? otherEventsFiltered.concat(currentEvent) : otherEventsFiltered; + const sortedEvents = events.sort(compareEvents); - return createEventsContainer(events); + return createEventsContainer(sortedEvents); }; }; diff --git a/src/core_modules/capture-core/rules/__tests__/__snapshots__/getApplicableRuleEffectsForTrackerProgram.test.js.snap b/src/core_modules/capture-core/rules/__tests__/__snapshots__/getApplicableRuleEffectsForTrackerProgram.test.js.snap index 2c73fac45b..f2fb347ece 100644 --- a/src/core_modules/capture-core/rules/__tests__/__snapshots__/getApplicableRuleEffectsForTrackerProgram.test.js.snap +++ b/src/core_modules/capture-core/rules/__tests__/__snapshots__/getApplicableRuleEffectsForTrackerProgram.test.js.snap @@ -125,7 +125,7 @@ Object { "trackedEntityAttributes": Object { "lZGmxYbs96q": Object { "id": "lZGmxYbs96q", - "optionSetId": undefined, + "optionSetId": "optionSet", "valueType": "DATE", }, "lZGmxYbs97q": Object { diff --git a/src/core_modules/capture-core/rules/__tests__/getApplicableRuleEffectsForTrackerProgram.test.js b/src/core_modules/capture-core/rules/__tests__/getApplicableRuleEffectsForTrackerProgram.test.js index 0ad48833c4..23e05892ba 100644 --- a/src/core_modules/capture-core/rules/__tests__/getApplicableRuleEffectsForTrackerProgram.test.js +++ b/src/core_modules/capture-core/rules/__tests__/getApplicableRuleEffectsForTrackerProgram.test.js @@ -1,3 +1,4 @@ +import { variableSourceTypes } from '@dhis2/rules-engine-javascript'; import { TrackerProgram, ProgramStage, @@ -10,24 +11,27 @@ import { } from '../../metaData'; import { getApplicableRuleEffectsForTrackerProgram } from '..'; -const mockGetProgramRuleEffects = jest.fn().mockImplementation(() => [{ - id: 'effectId', - type: 'DISPLAYTEXT', - message: 'display effect', -}]); +const mockGetProgramRuleEffects = jest.fn().mockImplementation(() => [ + { + id: 'effectId', + type: 'DISPLAYTEXT', + message: 'display effect', + }, +]); const mockOptionSet = new OptionSet('optionSet1', [new Option('option1', 'opt1')]); jest.mock('@dhis2/rules-engine-javascript/build/cjs/RulesEngine', () => ({ - RulesEngine: jest.fn().mockImplementation(() => - ({ getProgramRuleEffects: (...args) => mockGetProgramRuleEffects(...args) })), + RulesEngine: jest + .fn() + .mockImplementation(() => ({ getProgramRuleEffects: (...args) => mockGetProgramRuleEffects(...args) })), })); jest.mock('../../metaDataMemoryStores/constants/constants.store', () => ({ - constantsStore: ({ get: () => [{ id: 'constantId1', value: '1' }] }), + constantsStore: { get: () => [{ id: 'constantId1', value: '1' }] }, })); jest.mock('../../metaDataMemoryStores/optionSets/optionSets.store', () => ({ - optionSetStore: ({ get: () => [mockOptionSet] }), + optionSetStore: { get: () => [mockOptionSet] }, })); describe('getApplicableRuleEffectsForTrackerProgram', () => { @@ -46,20 +50,22 @@ describe('getApplicableRuleEffectsForTrackerProgram', () => { trackedEntityInstanceId: 'vCGpQAWG17I', }; - const otherEvents = [{ - da1Id: 'otherEventText', - dueDate: '2021-05-31T09:51:38.134', - enrollmentId: 'vVtmDlsu3me', - enrollmentStatus: 'ACTIVE', - eventDate: '2021-05-31T00:00:00.000', - eventId: 'BxGzDJK3JqN', - orgUnitId: 'DiszpKrYNg8', - orgUnitName: 'Ngelehun CHC', - programId: 'IpHINAT79UW', - programStageId: 'A03MvHHogjR', - status: 'ACTIVE', - trackedEntityInstanceId: 'vCGpQAWG17I', - }]; + const otherEvents = [ + { + da1Id: 'otherEventText', + dueDate: '2021-05-31T09:51:38.134', + enrollmentId: 'vVtmDlsu3me', + enrollmentStatus: 'ACTIVE', + eventDate: '2021-05-31T00:00:00.000', + eventId: 'BxGzDJK3JqN', + orgUnitId: 'DiszpKrYNg8', + orgUnitName: 'Ngelehun CHC', + programId: 'IpHINAT79UW', + programStageId: 'A03MvHHogjR', + status: 'ACTIVE', + trackedEntityInstanceId: 'vCGpQAWG17I', + }, + ]; const orgUnit = { id: 'DiszpKrYNg8', code: 'Ngelehun CHC' }; @@ -72,16 +78,18 @@ describe('getApplicableRuleEffectsForTrackerProgram', () => { const programStage = new ProgramStage((stage) => { stage.id = 'st1Id'; stage.name = 'stage1'; - stage.programRules = [{ - id: 'rule1Id', - name: 'rule1', - displayName: 'rule1', - priority: 1, - condition: 'true', - programId: 'IpHINAT79UW', - programStageId: 'st1Id', - programRuleActions: [], - }]; + stage.programRules = [ + { + id: 'rule1Id', + name: 'rule1', + displayName: 'rule1', + priority: 1, + condition: 'true', + programId: 'IpHINAT79UW', + programStageId: 'st1Id', + programRuleActions: [], + }, + ]; stage.stageForm = new RenderFoundation((foundation) => { const section = new Section((initSection) => { @@ -115,6 +123,7 @@ describe('getApplicableRuleEffectsForTrackerProgram', () => { element3.id = 'lZGmxYbs96q'; element3.name = 'SomeDate'; element3.type = dataElementTypes.DATE; + element3.optionSet = { id: 'optionSet', name: 'optionSet', code: 'optionSet' }; }), new DataElement((element4) => { element4.id = 'w75KJ2mc4zz'; @@ -129,7 +138,7 @@ describe('getApplicableRuleEffectsForTrackerProgram', () => { displayName: 'Test', id: 'PUQZWgmQ0jx', programId: 'IpHINAT79UW', - programRuleVariableSourceType: 'DATAELEMENT_NEWEST_EVENT_PROGRAM', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, useNameForOptionSet: true, }, { @@ -137,7 +146,7 @@ describe('getApplicableRuleEffectsForTrackerProgram', () => { displayName: 'apgarcomment', id: 'aKpfPKSRQnv', programId: 'IpHINAT79UW', - programRuleVariableSourceType: 'DATAELEMENT_NEWEST_EVENT_PROGRAM', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, useNameForOptionSet: true, }, { @@ -145,23 +154,27 @@ describe('getApplicableRuleEffectsForTrackerProgram', () => { displayName: 'apgarscore', id: 'g2GooOydipB', programId: 'IpHINAT79UW', - programRuleVariableSourceType: 'DATAELEMENT_NEWEST_EVENT_PROGRAM', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, useNameForOptionSet: true, }, ]; - initProgram.programRules = [{ - condition: 'true', - displayName: 'TestRule', - id: 'JJDQxgHuuL2', - programId: 'IpHINAT79UW', - programRuleActions: [{ - data: '#{Test}', - id: 'CQaifjkoFEU', - location: 'feedback', - programRuleActionType: 'DISPLAYTEXT', - }], - }]; + initProgram.programRules = [ + { + condition: 'true', + displayName: 'TestRule', + id: 'JJDQxgHuuL2', + programId: 'IpHINAT79UW', + programRuleActions: [ + { + data: '#{Test}', + id: 'CQaifjkoFEU', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + ], + }, + ]; }); const attributeValues = { @@ -210,16 +223,51 @@ describe('getApplicableRuleEffectsForTrackerProgram', () => { }); test('Flat result', () => { + const effects = getApplicableRuleEffectsForTrackerProgram( + { + program, + stage: programStage, + orgUnit, + currentEvent, + otherEvents, + attributeValues, + enrollmentData, + }, + true, + ); + + expect(Array.isArray(effects)).toBe(true); + }); + + test('RulesEngine called without programRules', () => { + const effects = getApplicableRuleEffectsForTrackerProgram({ + program: new TrackerProgram((initProgram) => { + initProgram.programRules = []; + }), + stage: new ProgramStage((stage) => { + stage.programRules = []; + }), + orgUnit, + currentEvent, + otherEvents, + attributeValues, + enrollmentData, + }); + + expect(effects).toStrictEqual([]); + }); + + test('currentEvent without a programStageId', () => { const effects = getApplicableRuleEffectsForTrackerProgram({ program, stage: programStage, orgUnit, - currentEvent, + currentEvent: {}, otherEvents, attributeValues, enrollmentData, - }, true); + }); - expect(Array.isArray(effects)).toBe(true); + expect(effects.DISPLAYTEXT).toBeDefined(); }); }); diff --git a/src/core_modules/capture-core/rules/__tests__/getApplicableRulesEffectsForEventProgram.test.js b/src/core_modules/capture-core/rules/__tests__/getApplicableRulesEffectsForEventProgram.test.js index 0fd9ac1510..7efadd5453 100644 --- a/src/core_modules/capture-core/rules/__tests__/getApplicableRulesEffectsForEventProgram.test.js +++ b/src/core_modules/capture-core/rules/__tests__/getApplicableRulesEffectsForEventProgram.test.js @@ -1,3 +1,4 @@ +import { variableSourceTypes } from '@dhis2/rules-engine-javascript'; import { EventProgram, ProgramStage, @@ -10,24 +11,27 @@ import { } from '../../metaData'; import { getApplicableRuleEffectsForEventProgram } from '..'; -const mockGetProgramRuleEffects = jest.fn().mockImplementation(() => [{ - id: 'effectId', - type: 'DISPLAYTEXT', - message: 'display effect', -}]); +const mockGetProgramRuleEffects = jest.fn().mockImplementation(() => [ + { + id: 'effectId', + type: 'DISPLAYTEXT', + message: 'display effect', + }, +]); const mockOptionSet = new OptionSet('optionSet1', [new Option('option1', 'opt1')]); jest.mock('@dhis2/rules-engine-javascript/build/cjs/RulesEngine', () => ({ - RulesEngine: jest.fn().mockImplementation(() => - ({ getProgramRuleEffects: (...args) => mockGetProgramRuleEffects(...args) })), + RulesEngine: jest + .fn() + .mockImplementation(() => ({ getProgramRuleEffects: (...args) => mockGetProgramRuleEffects(...args) })), })); jest.mock('../../metaDataMemoryStores/constants/constants.store', () => ({ - constantsStore: ({ get: () => [{ id: 'constantId1', value: '1' }] }), + constantsStore: { get: () => [{ id: 'constantId1', value: '1' }] }, })); jest.mock('../../metaDataMemoryStores/optionSets/optionSets.store', () => ({ - optionSetStore: ({ get: () => [mockOptionSet] }), + optionSetStore: { get: () => [mockOptionSet] }, })); describe('getApplicableRuleEffectsForEventProgram', () => { @@ -75,7 +79,7 @@ describe('getApplicableRuleEffectsForEventProgram', () => { displayName: 'Test', id: 'PUQZWgmQ0jx', programId: 'IpHINAT79UW', - programRuleVariableSourceType: 'DATAELEMENT_NEWEST_EVENT_PROGRAM', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, useNameForOptionSet: true, }, { @@ -83,7 +87,7 @@ describe('getApplicableRuleEffectsForEventProgram', () => { displayName: 'apgarcomment', id: 'aKpfPKSRQnv', programId: 'IpHINAT79UW', - programRuleVariableSourceType: 'DATAELEMENT_NEWEST_EVENT_PROGRAM', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, useNameForOptionSet: true, }, { @@ -91,23 +95,27 @@ describe('getApplicableRuleEffectsForEventProgram', () => { displayName: 'apgarscore', id: 'g2GooOydipB', programId: 'IpHINAT79UW', - programRuleVariableSourceType: 'DATAELEMENT_NEWEST_EVENT_PROGRAM', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, useNameForOptionSet: true, }, ]; - initProgram.programRules = [{ - condition: 'true', - displayName: 'TestRule', - id: 'JJDQxgHuuL2', - programId: 'IpHINAT79UW', - programRuleActions: [{ - data: '#{Test}', - id: 'CQaifjkoFEU', - location: 'feedback', - programRuleActionType: 'DISPLAYTEXT', - }], - }]; + initProgram.programRules = [ + { + condition: 'true', + displayName: 'TestRule', + id: 'JJDQxgHuuL2', + programId: 'IpHINAT79UW', + programRuleActions: [ + { + data: '#{Test}', + id: 'CQaifjkoFEU', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + ], + }, + ]; }); test('RulesEngine called with computed arguments from getApplicableRuleEffectsForEventProgram', () => { @@ -139,4 +147,16 @@ describe('getApplicableRuleEffectsForEventProgram', () => { expect(effects.DISPLAYTEXT).toBeDefined(); }); + + test('RulesEngine called without programRules', () => { + const effects = getApplicableRuleEffectsForEventProgram({ + program: new EventProgram((initProgram) => { + initProgram.programRules = []; + }), + orgUnit, + currentEvent, + }); + + expect(effects).toStrictEqual([]); + }); }); diff --git a/src/core_modules/capture-core/rules/__tests__/postProcessRulesEffects.test.js b/src/core_modules/capture-core/rules/__tests__/postProcessRulesEffects.test.js new file mode 100644 index 0000000000..6792dc777f --- /dev/null +++ b/src/core_modules/capture-core/rules/__tests__/postProcessRulesEffects.test.js @@ -0,0 +1,211 @@ +import { postProcessRulesEffects } from '../index'; +import { RenderFoundation, Section, DataElement, dataElementTypes } from '../../metaData'; + +test('Post process rules effects', () => { + // given + const rulesEffects = [ + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Eeb7Ixr4Pv6', message: 'd2:floor((5+5) / 2) = 5' }, + }, + { type: 'HIDEPROGRAMSTAGE', id: 'PUZaKR0Jh2k' }, + { id: 'SWfdBhglX0fk', type: 'HIDESECTION' }, + { id: 'w75KJ2mc4zz', type: 'ASSIGN', value: 'true' }, + { id: 'wasdJ2mc4zz', type: 'ASSIGN', value: 'true' }, + { + id: 'w75KJ2mc4zz', + message: ' true', + type: 'ERRORONCOMPLETE', + }, + { + id: 'w75KJ2mc4zz', + message: ' true', + type: 'WARNINGONCOMPLETE', + }, + { + id: 'w75KJ2mc4zz', + type: 'SETMANDATORYFIELD', + }, + { + content: undefined, + id: 'zDhUuAYrxNC', + targetDataType: 'trackedEntityAttribute', + type: 'HIDEFIELD', + hadValue: true, + name: undefined, + }, + { + content: undefined, + id: 'unknown', + type: 'HIDEFIELD', + }, + { + displayKeyValuePair: { + id: 'khy8GmlwpgZ', + key: "d2:weeksBetween('2020-01-28', V{unknown} ) = ", + value: '', + }, + id: 'feedback', + type: 'DISPLAYKEYVALUEPAIR', + }, + ]; + + const foundation = new RenderFoundation(() => {}); + const section1 = new Section((initSection) => { + initSection.id = 's1Id'; + initSection.name = 'section1'; + const dataElement1 = new DataElement((o) => { + o.id = 'w75KJ2mc4zz'; + o.name = 'dataElement1'; + o.type = dataElementTypes.TEXT; + o.optionSet = { + id: 'optionSet', + name: 'optionSet', + code: 'optionSet', + options: [{ option: { value: false } }], + }; + }); + + const dataElement2 = new DataElement((o) => { + o.id = 'wasdJ2mc4zz'; + o.name = 'dataElement1'; + o.type = dataElementTypes.NUMBER; + o.compulsory = true; + }); + initSection.addElement(dataElement1); + initSection.addElement(dataElement2); + }); + + const section2 = new Section((initSection) => { + initSection.id = 'SWfdBhglX0fk'; + initSection.name = 'section2'; + const dataElement = new DataElement((o) => { + o.id = 'da1Id'; + o.name = 'dataElement1'; + o.type = dataElementTypes.TEXT; + }); + + initSection.addElement(dataElement); + }); + + foundation.addSection(section1); + foundation.addSection(section2); + + // when + const processedRulesEffects = postProcessRulesEffects(rulesEffects, foundation); + + // then + expect(processedRulesEffects).toEqual([ + { + displayText: { + id: 'Eeb7Ixr4Pv6', + message: 'd2:floor((5+5) / 2) = 5', + }, + id: 'feedback', + type: 'DISPLAYTEXT', + }, + { + id: 'PUZaKR0Jh2k', + type: 'HIDEPROGRAMSTAGE', + }, + { + id: 'w75KJ2mc4zz', + message: ' true', + type: 'ERRORONCOMPLETE', + }, + { + id: 'w75KJ2mc4zz', + message: ' true', + type: 'WARNINGONCOMPLETE', + }, + { + id: 'w75KJ2mc4zz', + type: 'SETMANDATORYFIELD', + }, + { + displayKeyValuePair: { + id: 'khy8GmlwpgZ', + key: "d2:weeksBetween('2020-01-28', V{unknown} ) = ", + value: '', + }, + id: 'feedback', + type: 'DISPLAYKEYVALUEPAIR', + }, + { + content: undefined, + id: 'unknown', + type: 'HIDEFIELD', + }, + { + id: 'da1Id', + type: 'HIDEFIELD', + }, + { + id: 'unknown', + type: 'ASSIGN', + value: null, + }, + { + id: 'w75KJ2mc4zz', + type: 'ASSIGN', + value: null, + }, + { + id: 'wasdJ2mc4zz', + type: 'ASSIGN', + value: 'true', + }, + ]); +}); + +test('the rules effects are not defined', () => { + // given + + const foundation = new RenderFoundation(() => {}); + const section1 = new Section((initSection) => { + initSection.id = 's1Id'; + initSection.name = 'section1'; + const dataElement1 = new DataElement((o) => { + o.id = 'da1Id'; + o.name = 'dataElement1'; + o.type = dataElementTypes.TEXT; + }); + + initSection.addElement(dataElement1); + }); + + foundation.addSection(section1); + + // when + const processedRulesEffects = postProcessRulesEffects(undefined, foundation); + + // then + expect(processedRulesEffects).toEqual([]); +}); + +test('HIDESECTION effect sectionId do not match the formFoundation sectionId', () => { + // given + const rulesEffects = [{ id: 'SWfdBhglX0fk', type: 'HIDESECTION' }]; + + const foundation = new RenderFoundation(() => {}); + const section1 = new Section((initSection) => { + initSection.id = 's1Id'; + initSection.name = 'section1'; + const dataElement1 = new DataElement((o) => { + o.id = 'da1Id'; + o.name = 'dataElement1'; + o.type = dataElementTypes.TEXT; + }); + + initSection.addElement(dataElement1); + }); + + foundation.addSection(section1); + + // when + const processedRulesEffects = postProcessRulesEffects(rulesEffects, foundation); + + // then + expect(processedRulesEffects).toEqual([]); +}); diff --git a/src/core_modules/capture-core/rules/__tests__/ruleEffectsForEventProgram.test.js b/src/core_modules/capture-core/rules/__tests__/ruleEffectsForEventProgram.test.js index 8fd6054d3c..215b2a8ea0 100644 --- a/src/core_modules/capture-core/rules/__tests__/ruleEffectsForEventProgram.test.js +++ b/src/core_modules/capture-core/rules/__tests__/ruleEffectsForEventProgram.test.js @@ -1,19 +1,95 @@ -import { rulesEngineEffectTargetDataTypes } from '@dhis2/rules-engine-javascript'; +import { rulesEngineEffectTargetDataTypes, variableSourceTypes } from '@dhis2/rules-engine-javascript'; import { rulesEngine } from '../rulesEngine'; +import { systemSettingsStore } from '../../metaDataMemoryStores'; describe('Event Event rules engine', () => { // these variables are shared between each test - const constants = [{ id: 'Gfd3ppDfq8E', displayName: 'Commodity ordering overhead', value: 5 }, { id: 'bCqvfPR02Im', displayName: 'Pi', value: 3.14 }]; - const dataElementsInProgram = { sWoqcoByYmD: { id: 'sWoqcoByYmD', valueType: 'BOOLEAN' }, Ok9OQpitjQr: { id: 'Ok9OQpitjQr', valueType: 'BOOLEAN' }, vANAXwtLwcT: { id: 'vANAXwtLwcT', valueType: 'NUMBER' } }; - const programRules = [{ id: 'GC4gpdoSD4r', condition: '#{hemoglobin} < 9', description: 'Show warning if hemoglobin is dangerously low', displayName: 'Hemoglobin warning', programId: 'lxAQ7Zs9VYR', programRuleActions: [{ id: 'suS9GnraCx1', content: 'Hemoglobin value lower than normal', displayContent: 'Hemoglobin value lower than normal', dataElementId: 'vANAXwtLwcT', programRuleActionType: 'SHOWWARNING' }] }, { id: 'dahuKlP7jR2', condition: '#{hemoglobin} > 99', description: 'Show error for hemoglobin value higher than 99', displayName: 'Show error for high hemoglobin value', programId: 'lxAQ7Zs9VYR', programRuleActions: [{ id: 'UUwZWS8uirn', content: 'The hemoglobin value cannot be above 99', displayContent: 'The hemoglobin value cannot be above 99', dataElementId: 'vANAXwtLwcT', programRuleActionType: 'SHOWERROR' }] }, { id: 'xOe5qCzRS0Y', condition: '!#{womanSmoking} ', description: 'Hide smoking cessation councelling dataelement unless patient is smoking', displayName: 'Hide smoking cessation councelling', programId: 'lxAQ7Zs9VYR', programRuleActions: [{ id: 'hwgyO59SSxu', dataElementId: 'Ok9OQpitjQr', programRuleActionType: 'HIDEFIELD' }] }]; - const programRuleVariables = [{ id: 'Z92dJO9gIje', dataElementId: 'sWoqcoByYmD', displayName: 'womanSmoking', programId: 'lxAQ7Zs9VYR', programRuleVariableSourceType: 'DATAELEMENT_NEWEST_EVENT_PROGRAM', useNameForOptionSet: true }, { id: 'omrL0gtPpDL', dataElementId: 'vANAXwtLwcT', displayName: 'hemoglobin', programId: 'lxAQ7Zs9VYR', programRuleVariableSourceType: 'DATAELEMENT_NEWEST_EVENT_PROGRAM', useNameForOptionSet: true }]; + const constants = [ + { id: 'Gfd3ppDfq8E', displayName: 'Commodity ordering overhead', value: 5 }, + { id: 'bCqvfPR02Im', displayName: 'Pi', value: 3.14 }, + ]; + const dataElementsInProgram = { + sWoqcoByYmD: { id: 'sWoqcoByYmD', valueType: 'BOOLEAN' }, + Ok9OQpitjQr: { id: 'Ok9OQpitjQr', valueType: 'BOOLEAN' }, + vANAXwtLwcT: { id: 'vANAXwtLwcT', valueType: 'NUMBER' }, + }; + const programRules = [ + { + id: 'GC4gpdoSD4r', + condition: '#{hemoglobin} < 9', + description: 'Show warning if hemoglobin is dangerously low', + displayName: 'Hemoglobin warning', + programId: 'lxAQ7Zs9VYR', + programRuleActions: [ + { + id: 'suS9GnraCx1', + content: 'Hemoglobin value lower than normal', + displayContent: 'Hemoglobin value lower than normal', + dataElementId: 'vANAXwtLwcT', + programRuleActionType: 'SHOWWARNING', + }, + ], + }, + { + id: 'dahuKlP7jR2', + condition: '#{hemoglobin} > 99', + description: 'Show error for hemoglobin value higher than 99', + displayName: 'Show error for high hemoglobin value', + programId: 'lxAQ7Zs9VYR', + programRuleActions: [ + { + id: 'UUwZWS8uirn', + content: 'The hemoglobin value cannot be above 99', + displayContent: 'The hemoglobin value cannot be above 99', + dataElementId: 'vANAXwtLwcT', + programRuleActionType: 'SHOWERROR', + }, + ], + }, + { + id: 'xOe5qCzRS0Y', + condition: '!#{womanSmoking} ', + description: 'Hide smoking cessation councelling dataelement unless patient is smoking', + displayName: 'Hide smoking cessation councelling', + programId: 'lxAQ7Zs9VYR', + programRuleActions: [ + { id: 'hwgyO59SSxu', dataElementId: 'Ok9OQpitjQr', programRuleActionType: 'HIDEFIELD' }, + ], + }, + ]; + const programRuleVariables = [ + { + id: 'Z92dJO9gIje', + dataElementId: 'sWoqcoByYmD', + displayName: 'womanSmoking', + programId: 'lxAQ7Zs9VYR', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, + useNameForOptionSet: true, + }, + { + id: 'omrL0gtPpDL', + dataElementId: 'vANAXwtLwcT', + displayName: 'hemoglobin', + programId: 'lxAQ7Zs9VYR', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, + useNameForOptionSet: true, + }, + ]; const orgUnit = { id: 'DiszpKrYNg8', name: 'Ngelehun CHC' }; const optionSets = {}; describe.each([ [ { vANAXwtLwcT: 0 }, - [{ id: 'vANAXwtLwcT', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, message: 'Hemoglobin value lower than normal ', type: 'SHOWWARNING' }, { id: 'Ok9OQpitjQr', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, type: 'HIDEFIELD' }], + [ + { + id: 'vANAXwtLwcT', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + message: 'Hemoglobin value lower than normal ', + type: 'SHOWWARNING', + }, + { id: 'Ok9OQpitjQr', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, type: 'HIDEFIELD' }, + ], ], [ { vANAXwtLwcT: 9 }, @@ -25,7 +101,15 @@ describe('Event Event rules engine', () => { ], [ { vANAXwtLwcT: 100 }, - [{ id: 'vANAXwtLwcT', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, message: 'The hemoglobin value cannot be above 99 ', type: 'SHOWERROR' }, { id: 'Ok9OQpitjQr', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, type: 'HIDEFIELD' }], + [ + { + id: 'vANAXwtLwcT', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + message: 'The hemoglobin value cannot be above 99 ', + type: 'SHOWERROR', + }, + { id: 'Ok9OQpitjQr', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, type: 'HIDEFIELD' }, + ], ], ])('where value needs to >= 9 and <= 99', (currentEvent, expected) => { test(`and given value(s): ${JSON.stringify(currentEvent)}`, () => { @@ -44,11 +128,26 @@ describe('Event Event rules engine', () => { describe.each([ [ { sWoqcoByYmD: true }, - [{ id: 'vANAXwtLwcT', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, message: 'Hemoglobin value lower than normal ', type: 'SHOWWARNING' }], + [ + { + id: 'vANAXwtLwcT', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + message: 'Hemoglobin value lower than normal ', + type: 'SHOWWARNING', + }, + ], ], [ { sWoqcoByYmD: false }, - [{ id: 'vANAXwtLwcT', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, message: 'Hemoglobin value lower than normal ', type: 'SHOWWARNING' }, { id: 'Ok9OQpitjQr', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, type: 'HIDEFIELD' }], + [ + { + id: 'vANAXwtLwcT', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + message: 'Hemoglobin value lower than normal ', + type: 'SHOWWARNING', + }, + { id: 'Ok9OQpitjQr', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, type: 'HIDEFIELD' }, + ], ], ])('where field is hidden regarding a boolean value', (currentEvent, expected) => { test(`and given value(s): ${JSON.stringify(currentEvent)}`, () => { @@ -67,25 +166,138 @@ describe('Event Event rules engine', () => { describe('Event rules engine', () => { // these variables are shared between each test - const constants = [{ id: 'Gfd3ppDfq8E', displayName: 'Commodity ordering overhead', value: 5 }, { id: 'bCqvfPR02Im', displayName: 'Pi', value: 3.14 }]; - const dataElementsInProgram = { oZg33kd9taw: { id: 'oZg33kd9taw', valueType: 'TEXT', optionSetId: 'pC3N9N77UmT' }, SWfdB5lX0fk: { id: 'SWfdB5lX0fk', valueType: 'BOOLEAN', optionSetId: undefined }, qrur9Dvnyt5: { id: 'qrur9Dvnyt5', valueType: 'INTEGER', optionSetId: undefined }, GieVkTxp4HH: { id: 'GieVkTxp4HH', valueType: 'NUMBER', optionSetId: undefined }, vV9UWAZohSf: { id: 'vV9UWAZohSf', valueType: 'INTEGER_POSITIVE', optionSetId: undefined }, eMyVanycQSC: { id: 'eMyVanycQSC', valueType: 'DATE', optionSetId: undefined }, K6uUAvq500H: { id: 'K6uUAvq500H', valueType: 'TEXT', optionSetId: 'eUZ79clX7y1' }, msodh3rEMJa: { id: 'msodh3rEMJa', valueType: 'DATE', optionSetId: undefined }, S33cRBsnXPo: { id: 'S33cRBsnXPo', valueType: 'ORGANISATION_UNIT', optionSetId: undefined }, fWIAEtYVEGk: { id: 'fWIAEtYVEGk', valueType: 'TEXT', optionSetId: 'iDFPKpFTiVw' }, ulD2zW0TIy2: { id: 'ulD2zW0TIy2', valueType: 'FILE_RESOURCE' } }; - const programRules = [{ id: 'fd3wL1quxGb', condition: "#{gender} == 'Male'", description: 'Hide pregnant if gender is male', displayName: 'Hide pregnant if gender is male', programId: 'eBAyeGv0exc', programRuleActions: [{ id: 'IrmpncBsypT', dataElementId: 'SWfdB5lX0fk', programRuleActionType: 'HIDEFIELD', programStageSectionId: 'd7ZILSbPgYh' }] }, { id: 'x7PaHGvgWY2', condition: 'true', description: 'Body Mass Index. Weight in kg / height in m square.', displayName: 'BMI', programId: 'eBAyeGv0exc', programRuleActions: [{ id: 'x7PaHGvgWY2', content: 'BMI', displayContent: 'BMI', data: '#{Zj7UnCAulEk.vV9UWAZohSf}/((#{Zj7UnCAulEk.GieVkTxp4HH}/100)*(#{Zj7UnCAulEk.GieVkTxp4HH}/100))', programRuleActionType: 'DISPLAYKEYVALUEPAIR', location: 'indicators' }] }]; - const programRuleVariables = [{ id: 'RycV5uDi66i', dataElementId: 'qrur9Dvnyt5', displayName: 'age', programId: 'eBAyeGv0exc', programRuleVariableSourceType: 'DATAELEMENT_NEWEST_EVENT_PROGRAM', useNameForOptionSet: true }, { id: 'zINGRka3g9N', dataElementId: 'oZg33kd9taw', displayName: 'gender', programId: 'eBAyeGv0exc', programRuleVariableSourceType: 'DATAELEMENT_NEWEST_EVENT_PROGRAM', useNameForOptionSet: true }, { id: 'Zj7UnCAulEk.vV9UWAZohSf', displayName: 'Zj7UnCAulEk.vV9UWAZohSf', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', dataElementId: 'vV9UWAZohSf', programId: 'eBAyeGv0exc' }, { id: 'Zj7UnCAulEk.GieVkTxp4HH', displayName: 'Zj7UnCAulEk.GieVkTxp4HH', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', dataElementId: 'GieVkTxp4HH', programId: 'eBAyeGv0exc' }, { id: 'Zj7UnCAulEk.GieVkTxp4HH', displayName: 'Zj7UnCAulEk.GieVkTxp4HH', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', dataElementId: 'GieVkTxp4HH', programId: 'eBAyeGv0exc' }]; + const constants = [ + { id: 'Gfd3ppDfq8E', displayName: 'Commodity ordering overhead', value: 5 }, + { id: 'bCqvfPR02Im', displayName: 'Pi', value: 3.14 }, + ]; + const dataElementsInProgram = { + oZg33kd9taw: { id: 'oZg33kd9taw', valueType: 'TEXT', optionSetId: 'pC3N9N77UmT' }, + SWfdB5lX0fk: { id: 'SWfdB5lX0fk', valueType: 'TRUE_ONLY', optionSetId: undefined }, + qrur9Dvnyt5: { id: 'qrur9Dvnyt5', valueType: 'INTEGER', optionSetId: undefined }, + GieVkTxp4HH: { id: 'GieVkTxp4HH', valueType: 'NUMBER', optionSetId: undefined }, + vV9UWAZohSf: { id: 'vV9UWAZohSf', valueType: 'INTEGER_POSITIVE', optionSetId: undefined }, + eMyVanycQSC: { id: 'eMyVanycQSC', valueType: 'DATE', optionSetId: undefined }, + K6uUAvq500H: { id: 'K6uUAvq500H', valueType: 'TEXT', optionSetId: 'eUZ79clX7y1' }, + msodh3rEMJa: { id: 'msodh3rEMJa', valueType: 'DATE', optionSetId: undefined }, + S33cRBsnXPo: { id: 'S33cRBsnXPo', valueType: 'ORGANISATION_UNIT', optionSetId: undefined }, + fWIAEtYVEGk: { id: 'fWIAEtYVEGk', valueType: 'TEXT', optionSetId: 'iDFPKpFTiVw' }, + ulD2zW0TIy2: { id: 'ulD2zW0TIy2', valueType: 'FILE_RESOURCE' }, + }; + const programRules = [ + { + id: 'fd3wL1quxGb', + condition: "#{gender} == 'Male'", + description: 'Hide pregnant if gender is male', + displayName: 'Hide pregnant if gender is male', + programId: 'eBAyeGv0exc', + programRuleActions: [ + { + id: 'IrmpncBsypT', + dataElementId: 'SWfdB5lX0fk', + programRuleActionType: 'HIDEFIELD', + programStageSectionId: 'd7ZILSbPgYh', + }, + ], + }, + { + id: 'x7PaHGvgWY2', + condition: 'true', + description: 'Body Mass Index. Weight in kg / height in m square.', + displayName: 'BMI', + programId: 'eBAyeGv0exc', + programRuleActions: [ + { + id: 'x7PaHGvgWY2', + content: 'BMI', + displayContent: 'BMI', + data: '#{Zj7UnCAulEk.vV9UWAZohSf}/((#{Zj7UnCAulEk.GieVkTxp4HH}/100)*(#{Zj7UnCAulEk.GieVkTxp4HH}/100))', + programRuleActionType: 'DISPLAYKEYVALUEPAIR', + location: 'indicators', + }, + ], + }, + ]; + const programRuleVariables = [ + { + id: 'RycV5uDi66i', + dataElementId: 'qrur9Dvnyt5', + displayName: 'age', + programId: 'eBAyeGv0exc', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, + useNameForOptionSet: true, + }, + { + id: 'zINGRka3g9N', + dataElementId: 'oZg33kd9taw', + displayName: 'gender', + programId: 'eBAyeGv0exc', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, + useNameForOptionSet: true, + }, + { + id: 'Zj7UnCAulEk.vV9UWAZohSf', + displayName: 'Zj7UnCAulEk.vV9UWAZohSf', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + dataElementId: 'vV9UWAZohSf', + programId: 'eBAyeGv0exc', + }, + { + id: 'Zj7UnCAulEk.GieVkTxp4HH', + displayName: 'Zj7UnCAulEk.GieVkTxp4HH', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + dataElementId: 'GieVkTxp4HH', + programId: 'eBAyeGv0exc', + }, + { + id: 'Zj7UnCAulEk.GieVkTxp4HH', + displayName: 'Zj7UnCAulEk.GieVkTxp4HH', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + dataElementId: 'GieVkTxp4HH', + programId: 'eBAyeGv0exc', + }, + ]; const orgUnit = { id: 'DiszpKrYNg8', name: 'Ngelehun CHC' }; - const optionSets = { pC3N9N77UmT: { id: 'pC3N9N77UmT', displayName: 'Gender', version: 0, valueType: 'TEXT', options: [{ id: 'rBvjJYbMCVx', displayName: 'Male', code: 'Male', translations: [] }, { id: 'Mnp3oXrpAbK', displayName: 'Female', code: 'Female', translations: [] }] } }; + const optionSets = { + pC3N9N77UmT: { + id: 'pC3N9N77UmT', + displayName: 'Gender', + version: 0, + valueType: 'TEXT', + options: undefined, + }, + }; describe.each([ [ { oZg33kd9taw: 'Female', SWfdB5lX0fk: null }, - [{ displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, id: 'indicators', type: 'DISPLAYKEYVALUEPAIR' }], + [ + { + displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, + id: 'indicators', + type: 'DISPLAYKEYVALUEPAIR', + }, + ], ], [ { oZg33kd9taw: 'Male', SWfdB5lX0fk: null }, - [{ id: 'SWfdB5lX0fk', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, type: 'HIDEFIELD' }, { displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, id: 'indicators', type: 'DISPLAYKEYVALUEPAIR' }], + [ + { id: 'SWfdB5lX0fk', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, type: 'HIDEFIELD' }, + { + displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, + id: 'indicators', + type: 'DISPLAYKEYVALUEPAIR', + }, + ], ], [ { oZg33kd9taw: null, SWfdB5lX0fk: null }, - [{ displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, id: 'indicators', type: 'DISPLAYKEYVALUEPAIR' }], + [ + { + displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, + id: 'indicators', + type: 'DISPLAYKEYVALUEPAIR', + }, + ], ], ])('where field is hidden regarding the gender of the event', (currentEvent, expected) => { test(`and given value(s): ${JSON.stringify(currentEvent)}`, () => { @@ -104,35 +316,83 @@ describe('Event rules engine', () => { describe.each([ [ { qrur9Dvnyt5: null, GieVkTxp4HH: null, vV9UWAZohSf: null }, - [{ displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, id: 'indicators', type: 'DISPLAYKEYVALUEPAIR' }], + [ + { + displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, + id: 'indicators', + type: 'DISPLAYKEYVALUEPAIR', + }, + ], ], [ { qrur9Dvnyt5: null, GieVkTxp4HH: null, vV9UWAZohSf: 85 }, - [{ displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, id: 'indicators', type: 'DISPLAYKEYVALUEPAIR' }], + [ + { + displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, + id: 'indicators', + type: 'DISPLAYKEYVALUEPAIR', + }, + ], ], [ { qrur9Dvnyt5: null, GieVkTxp4HH: 180, vV9UWAZohSf: null }, - [{ displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '0' }, id: 'indicators', type: 'DISPLAYKEYVALUEPAIR' }], + [ + { + displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '0' }, + id: 'indicators', + type: 'DISPLAYKEYVALUEPAIR', + }, + ], ], [ { qrur9Dvnyt5: null, GieVkTxp4HH: 180, vV9UWAZohSf: 85 }, - [{ displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '26.234567901234566' }, id: 'indicators', type: 'DISPLAYKEYVALUEPAIR' }], + [ + { + displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '26.234567901234566' }, + id: 'indicators', + type: 'DISPLAYKEYVALUEPAIR', + }, + ], ], [ { qrur9Dvnyt5: 40, GieVkTxp4HH: null, vV9UWAZohSf: null }, - [{ displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, id: 'indicators', type: 'DISPLAYKEYVALUEPAIR' }], + [ + { + displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, + id: 'indicators', + type: 'DISPLAYKEYVALUEPAIR', + }, + ], ], [ { qrur9Dvnyt5: 40, GieVkTxp4HH: null, vV9UWAZohSf: 85 }, - [{ displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, id: 'indicators', type: 'DISPLAYKEYVALUEPAIR' }], + [ + { + displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '' }, + id: 'indicators', + type: 'DISPLAYKEYVALUEPAIR', + }, + ], ], [ { qrur9Dvnyt5: 40, GieVkTxp4HH: 180, vV9UWAZohSf: null }, - [{ displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '0' }, id: 'indicators', type: 'DISPLAYKEYVALUEPAIR' }], + [ + { + displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '0' }, + id: 'indicators', + type: 'DISPLAYKEYVALUEPAIR', + }, + ], ], [ { qrur9Dvnyt5: 40, GieVkTxp4HH: 180, vV9UWAZohSf: 85 }, - [{ displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '26.234567901234566' }, id: 'indicators', type: 'DISPLAYKEYVALUEPAIR' }], + [ + { + displayKeyValuePair: { id: 'x7PaHGvgWY2', key: 'BMI', value: '26.234567901234566' }, + id: 'indicators', + type: 'DISPLAYKEYVALUEPAIR', + }, + ], ], ])('where BMI is calculated', (currentEvent, expected) => { test(`and given value(s): ${JSON.stringify(currentEvent)}`, () => { @@ -151,14 +411,503 @@ describe('Event rules engine', () => { describe('Event rules engine', () => { // these variables are shared between each test - const constants = [{ id: 'Gfd3ppDfq8E', displayName: 'Commodity ordering overhead', value: 5 }, { id: 'bCqvfPR02Im', displayName: 'Pi', value: 3.14 }]; - const dataElementsInProgram = { dyfYIsTFTjG: { id: 'dyfYIsTFTjG', valueType: 'TEXT' }, XOaXLWuhKzV: { id: 'XOaXLWuhKzV', valueType: 'TEXT', optionSetId: 'WDUwjiW2rGH' }, AtFlciXnstG: { id: 'AtFlciXnstG', valueType: 'INTEGER_ZERO_OR_POSITIVE' }, JGnHr6WI3AY: { id: 'JGnHr6WI3AY', valueType: 'TEXT', optionSetId: 'L6eMZDJkCwX' }, s3eoonJ8OJb: { id: 's3eoonJ8OJb', valueType: 'DATE' }, gktroFPckdr: { id: 'gktroFPckdr', valueType: 'TEXT', optionSetId: 'UYDsNdpo2BU' }, QQLXTXVidW2: { id: 'QQLXTXVidW2', valueType: 'TEXT', optionSetId: 'L6eMZDJkCwX' }, ovY6E8BSdto: { id: 'ovY6E8BSdto', valueType: 'TEXT', optionSetId: 'dsgBmIZ0Yrq' }, Z5z8vFQy0w0: { id: 'Z5z8vFQy0w0', valueType: 'TEXT' }, TzqawmlPkI5: { id: 'TzqawmlPkI5', valueType: 'TEXT', optionSetId: 'L6eMZDJkCwX' }, f8j4XDEozvj: { id: 'f8j4XDEozvj', valueType: 'TEXT', optionSetId: 'xD9QOIvNAjw' }, jBBkFuPKctq: { id: 'jBBkFuPKctq', valueType: 'TEXT', optionSetId: 'T9zjyaIkRqH' }, A4Fg6jgWauf: { id: 'A4Fg6jgWauf', valueType: 'TEXT', optionSetId: 'w1vUkxq8IOl' }, CUbZcLm9LyN: { id: 'CUbZcLm9LyN', valueType: 'TEXT', optionSetId: 'L6eMZDJkCwX' }, p8htbyJHydl: { id: 'p8htbyJHydl', valueType: 'TEXT', optionSetId: 'L6eMZDJkCwX' }, SbXES4EPgqP: { id: 'SbXES4EPgqP', valueType: 'NUMBER' }, bOYWVEBaWy6: { id: 'bOYWVEBaWy6', valueType: 'TEXT', optionSetId: 'qI4cs9ocBwn' }, PFXeJV8d7ja: { id: 'PFXeJV8d7ja', valueType: 'DATE' } }; - const programRules = [{ id: 'DOz4wl8ErDD', condition: 'true', description: 'Hide Irrelevant Test Result Options', displayName: 'Hide Test Result Options', programId: 'PNClHaZARtz', programRuleActions: [{ id: 'XuM1JizlcF1', dataElementId: 'ovY6E8BSdto', programRuleActionType: 'HIDEOPTION', optionId: 'MkeWrqeqZXL' }, { id: 'FRfTFXSwKDU', dataElementId: 'ovY6E8BSdto', programRuleActionType: 'HIDEOPTION', optionId: 'fPV0gQ8ds6D' }] }, { id: 'DtfaG1TgyZk', condition: "(d2:hasValue( #{LAB_TEST} ) && #{LAB_TEST} == 'No') ||\n(d2:hasValue( #{LAB_TEST} ) && #{LAB_TEST} == 'Yes' && #{TEST_RESULT} == 'Inconclusive')", description: "Automation: Assign 'Probable Case' to Case Classification", displayName: "Assign 'Probable Case' to Case Classification", programId: 'PNClHaZARtz', programRuleActions: [{ id: 'NPvy6sF6axT', data: "'Probable Case'", dataElementId: 'Z5z8vFQy0w0', programRuleActionType: 'ASSIGN' }], priority: 4 }, { id: 'E9ghdhg6ABQ', condition: "#{SYMPTOMS} != 'Yes'", description: 'Hide Onset of Symptoms Date if no symptoms', displayName: 'Hide Onset of Symptoms Date', programId: 'PNClHaZARtz', programRuleActions: [{ id: 'VcnnsBPtzlW', dataElementId: 's3eoonJ8OJb', programRuleActionType: 'HIDEFIELD' }] }, { id: 'FnSVDp8v0H9', condition: 'true', description: 'Hide Irrelevant Unknown Options', displayName: 'Hide Unknown Options', programId: 'PNClHaZARtz', programRuleActions: [{ id: 'UqDEcMuF5DF', dataElementId: 'JGnHr6WI3AY', programRuleActionType: 'HIDEOPTION', optionId: 'pqxvAQU1z9W' }, { id: 'GrFjkYTT07o', dataElementId: 'p8htbyJHydl', programRuleActionType: 'HIDEOPTION', optionId: 'pqxvAQU1z9W' }, { id: 'HlyTQaTz00f', dataElementId: 'CUbZcLm9LyN', programRuleActionType: 'HIDEOPTION', optionId: 'pqxvAQU1z9W' }] }, { id: 'L8bP6GifQXL', condition: "!d2:hasValue( #{INFECTION_SOURCE} ) || #{INFECTION_SOURCE} == 'IMPORTED_CASE' || #{INFECTION_SOURCE} == 'EXPOSURE_UNKNOWN'", description: 'Hide Case Type for Imported Cases', displayName: 'Hide Case Type', programId: 'PNClHaZARtz', programRuleActions: [{ id: 'k05Owr8pwIn', dataElementId: 'A4Fg6jgWauf', programRuleActionType: 'HIDEFIELD' }] }, { id: 'MLS5vZLguQM', condition: "#{INFECTION_SOURCE} != 'LOCAL_TRANSMISSION'", description: "Hide 'Specify Local Infection Source' unless Local Transmission is selected", displayName: "Hide 'Specify Local Infection Source'", programId: 'PNClHaZARtz', programRuleActions: [{ id: 'ho7xRPUB0Gl', dataElementId: 'jBBkFuPKctq', programRuleActionType: 'HIDEFIELD' }] }, { id: 'NXWk8sq70OV', condition: "#{TRAVEL_HISTORY} == 'No'", description: "Hide 'Imported Case' if not traveled", displayName: "Hide 'Imported Case'", programId: 'PNClHaZARtz', programRuleActions: [{ id: 'fJIgmDK53Vp', dataElementId: 'f8j4XDEozvj', programRuleActionType: 'HIDEOPTION', optionId: 'PMGTqmVIF4T' }] }, { id: 'NZaVqr7dPfQ', condition: '!d2:hasValue( #{ONSET_DATE} ) && !d2:hasValue(V{event_date})', description: 'Automation: Assign Empty date if no Onset date and no event date is available', displayName: 'Assign Empty Date', programId: 'PNClHaZARtz', programRuleActions: [{ id: 'q060xuOwQx3', data: "''", dataElementId: 'PFXeJV8d7ja', programRuleActionType: 'ASSIGN' }], priority: 3 }, { id: 'QrJx9LI9KRo', condition: "d2:hasValue( #{LAB_TEST} ) && #{LAB_TEST} == 'Yes' && !d2:hasValue( #{TEST_RESULT} )", description: 'Automation: Assign Empty Value to Class Classification', displayName: 'Assign Empty Value to Class Classification', programId: 'PNClHaZARtz', programRuleActions: [{ id: 'rFaZAbOgMSz', data: "''", dataElementId: 'Z5z8vFQy0w0', programRuleActionType: 'ASSIGN' }], priority: 2 }, { id: 'R6oEX1xlQma', condition: 'true', description: 'Hide irrelevant Outcome Options', displayName: 'Hide Outcome Options', programId: 'PNClHaZARtz', programRuleActions: [{ id: 'Ov7qHXf0Q2s', dataElementId: 'bOYWVEBaWy6', programRuleActionType: 'HIDEOPTION', optionId: 'dUeRcF2cApV' }, { id: 'V95rgvUlqY0', dataElementId: 'bOYWVEBaWy6', programRuleActionType: 'HIDEOPTION', optionId: 'bYt4why1tL3' }, { id: 'eZUUOjykbLv', dataElementId: 'bOYWVEBaWy6', programRuleActionType: 'HIDEOPTION', optionId: 'xBoo6HyaYcd' }, { id: 'Zcs7rz5VEF7', dataElementId: 'bOYWVEBaWy6', programRuleActionType: 'HIDEOPTION', optionId: 'RCT079wdeKT' }] }, { id: 'dZsTiQEUg5L', condition: '!d2:hasValue( #{ONSET_DATE} ) && d2:hasValue(V{event_date})', description: 'Automation: Assign Event date if no Onset date is available', displayName: 'Assign Event Date', programId: 'PNClHaZARtz', programRuleActions: [{ id: 'sQKFBORp5P1', data: 'V{event_date}', dataElementId: 'PFXeJV8d7ja', programRuleActionType: 'ASSIGN' }], priority: 2 }, { id: 'kVBrxwODyTj', condition: '!d2:hasValue( #{LAB_TEST} )', description: 'Hide Case Classification Field until Lab Test question is answered', displayName: 'Hide Case Classification Field', programId: 'PNClHaZARtz', programRuleActions: [{ id: 'ZT8AexxBPl0', dataElementId: 'Z5z8vFQy0w0', programRuleActionType: 'HIDEFIELD' }] }, { id: 'q2QbEfeDlI9', condition: "!d2:hasValue( #{HOSPITALISED} ) || #{HOSPITALISED} == 'No'", description: 'Hide ICU field unless Hospitalised', displayName: 'Hide ICU field', programId: 'PNClHaZARtz', programRuleActions: [{ id: 'wwvxLCpuOCx', dataElementId: 'p8htbyJHydl', programRuleActionType: 'HIDEFIELD' }] }, { id: 'rZUpiMuJIKH', condition: "d2:hasValue( #{LAB_TEST} ) && #{LAB_TEST} == 'Yes' && #{TEST_RESULT} == 'Positive'", description: "Automation: Assign 'Laboratory Confirmed Case' to Case Classification", displayName: "Assign 'Laboratory Confirmed Case' to Case Classification", programId: 'PNClHaZARtz', programRuleActions: [{ id: 'hcamYSDn00P', data: "'Laboratory Confirmed Case'", dataElementId: 'Z5z8vFQy0w0', programRuleActionType: 'ASSIGN' }], priority: 3 }, { id: 'sEQsGGAQSJT', condition: "(d2:hasValue( #{LAB_TEST} ) && #{LAB_TEST} == 'Unknown') ||\n(d2:hasValue( #{LAB_TEST} ) && #{LAB_TEST} == 'Yes' && (#{TEST_RESULT} == 'Negative' || #{TEST_RESULT} == 'Unknown'))", description: "Automation: Assign Suspected Case' to Case Classification", displayName: "Assign 'Suspected Case' to Case Classification", programId: 'PNClHaZARtz', programRuleActions: [{ id: 'zxb2XDboGAF', data: "'Suspected Case'", dataElementId: 'Z5z8vFQy0w0', programRuleActionType: 'ASSIGN' }], priority: 1 }, { id: 'sKCZMuWwOKA', condition: 'd2:hasValue( #{ONSET_DATE} )', description: 'Automation: Assign Symptoms Onset Date if available', displayName: 'Assign Onset Date', programId: 'PNClHaZARtz', programRuleActions: [{ id: 'lJOYxhjupxz', data: '#{ONSET_DATE}', dataElementId: 'PFXeJV8d7ja', programRuleActionType: 'ASSIGN' }], priority: 1 }, { id: 'vj5GWKIrhKh', condition: "#{LAB_TEST} != 'Yes'", description: 'Hide Test Result Field until Lab Test question is answered with yes', displayName: 'Hide Test Result Field', programId: 'PNClHaZARtz', programRuleActions: [{ id: 'VxxxIX2598r', dataElementId: 'ovY6E8BSdto', programRuleActionType: 'HIDEFIELD' }] }]; - const programRuleVariables = [{ id: 'DoRHHfNPccb', dataElementId: 'f8j4XDEozvj', displayName: 'INFECTION_SOURCE', programId: 'PNClHaZARtz', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', useNameForOptionSet: false }, { id: 'EnpvdmYrwLb', dataElementId: 'TzqawmlPkI5', displayName: 'TRAVEL_HISTORY', programId: 'PNClHaZARtz', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', useNameForOptionSet: true }, { id: 'JPIyrAmJapV', dataElementId: 'CUbZcLm9LyN', displayName: 'HOSPITALISED', programId: 'PNClHaZARtz', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', useNameForOptionSet: true }, { id: 'LAaPMTz69L7', displayName: 'CASE_CLASSIFICATION', programId: 'PNClHaZARtz', programRuleVariableSourceType: 'CALCULATED_VALUE', useNameForOptionSet: true, valueType: 'TEXT' }, { id: 'MpixycZvu0m', dataElementId: 'ovY6E8BSdto', displayName: 'TEST_RESULT', programId: 'PNClHaZARtz', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', useNameForOptionSet: true }, { id: 'XcPYCpTOPwB', dataElementId: 'QQLXTXVidW2', displayName: 'LAB_TEST', programId: 'PNClHaZARtz', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', useNameForOptionSet: true }, { id: 'cZSslcAEupI', dataElementId: 's3eoonJ8OJb', displayName: 'ONSET_DATE', programId: 'PNClHaZARtz', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', useNameForOptionSet: true }, { id: 'eSq3nc1t2F6', dataElementId: 'dyfYIsTFTjG', displayName: 'PATIENT_ID', programId: 'PNClHaZARtz', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', useNameForOptionSet: true }, { id: 'lY0yJGU1D4e', dataElementId: 'JGnHr6WI3AY', displayName: 'SYMPTOMS', programId: 'PNClHaZARtz', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', useNameForOptionSet: false }]; + const constants = [ + { id: 'Gfd3ppDfq8E', displayName: 'Commodity ordering overhead', value: 5 }, + { id: 'bCqvfPR02Im', displayName: 'Pi', value: 3.14 }, + ]; + const dataElementsInProgram = { + dyfYIsTFTjG: { id: 'dyfYIsTFTjG', valueType: 'TEXT' }, + XOaXLWuhKzV: { id: 'XOaXLWuhKzV', valueType: 'TEXT', optionSetId: 'WDUwjiW2rGH' }, + AtFlciXnstG: { id: 'AtFlciXnstG', valueType: 'INTEGER_ZERO_OR_POSITIVE' }, + JGnHr6WI3AY: { id: 'JGnHr6WI3AY', valueType: 'TEXT', optionSetId: 'L6eMZDJkCwX' }, + s3eoonJ8OJb: { id: 's3eoonJ8OJb', valueType: 'DATE' }, + gktroFPckdr: { id: 'gktroFPckdr', valueType: 'TEXT', optionSetId: 'UYDsNdpo2BU' }, + QQLXTXVidW2: { id: 'QQLXTXVidW2', valueType: 'TEXT', optionSetId: 'L6eMZDJkCwX' }, + ovY6E8BSdto: { id: 'ovY6E8BSdto', valueType: 'TEXT', optionSetId: 'dsgBmIZ0Yrq' }, + Z5z8vFQy0w0: { id: 'Z5z8vFQy0w0', valueType: 'TEXT' }, + TzqawmlPkI5: { id: 'TzqawmlPkI5', valueType: 'TEXT', optionSetId: 'L6eMZDJkCwX' }, + f8j4XDEozvj: { id: 'f8j4XDEozvj', valueType: 'TEXT', optionSetId: 'xD9QOIvNAjw' }, + jBBkFuPKctq: { id: 'jBBkFuPKctq', valueType: 'TEXT', optionSetId: 'T9zjyaIkRqH' }, + A4Fg6jgWauf: { id: 'A4Fg6jgWauf', valueType: 'TEXT', optionSetId: 'w1vUkxq8IOl' }, + CUbZcLm9LyN: { id: 'CUbZcLm9LyN', valueType: 'TEXT', optionSetId: 'L6eMZDJkCwX' }, + p8htbyJHydl: { id: 'p8htbyJHydl', valueType: 'TEXT', optionSetId: 'L6eMZDJkCwX' }, + SbXES4EPgqP: { id: 'SbXES4EPgqP', valueType: 'NUMBER' }, + bOYWVEBaWy6: { id: 'bOYWVEBaWy6', valueType: 'TEXT', optionSetId: 'qI4cs9ocBwn' }, + PFXeJV8d7ja: { id: 'PFXeJV8d7ja', valueType: 'DATE' }, + }; + const programRules = [ + { + id: 'DOz4wl8ErDD', + condition: 'true', + description: 'Hide Irrelevant Test Result Options', + displayName: 'Hide Test Result Options', + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'XuM1JizlcF1', + dataElementId: 'ovY6E8BSdto', + programRuleActionType: 'HIDEOPTION', + optionId: 'MkeWrqeqZXL', + }, + { + id: 'FRfTFXSwKDU', + dataElementId: 'ovY6E8BSdto', + programRuleActionType: 'HIDEOPTION', + optionId: 'fPV0gQ8ds6D', + }, + ], + }, + { + id: 'DtfaG1TgyZk', + condition: + "(d2:hasValue( #{LAB_TEST} ) && #{LAB_TEST} == 'No') ||\n(d2:hasValue( #{LAB_TEST} ) && #{LAB_TEST} == 'Yes' && #{TEST_RESULT} == 'Inconclusive')", + description: "Automation: Assign 'Probable Case' to Case Classification", + displayName: "Assign 'Probable Case' to Case Classification", + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'NPvy6sF6axT', + data: "'Probable Case'", + dataElementId: 'Z5z8vFQy0w0', + programRuleActionType: 'ASSIGN', + }, + ], + priority: 4, + }, + { + id: 'E9ghdhg6ABQ', + condition: "#{SYMPTOMS} != 'Yes'", + description: 'Hide Onset of Symptoms Date if no symptoms', + displayName: 'Hide Onset of Symptoms Date', + programId: 'PNClHaZARtz', + programRuleActions: [ + { id: 'VcnnsBPtzlW', dataElementId: 's3eoonJ8OJb', programRuleActionType: 'HIDEFIELD' }, + ], + }, + { + id: 'FnSVDp8v0H9', + condition: 'true', + description: 'Hide Irrelevant Unknown Options', + displayName: 'Hide Unknown Options', + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'UqDEcMuF5DF', + dataElementId: 'JGnHr6WI3AY', + programRuleActionType: 'HIDEOPTION', + optionId: 'pqxvAQU1z9W', + }, + { + id: 'GrFjkYTT07o', + dataElementId: 'p8htbyJHydl', + programRuleActionType: 'HIDEOPTION', + optionId: 'pqxvAQU1z9W', + }, + { + id: 'HlyTQaTz00f', + dataElementId: 'CUbZcLm9LyN', + programRuleActionType: 'HIDEOPTION', + optionId: 'pqxvAQU1z9W', + }, + ], + }, + { + id: 'L8bP6GifQXL', + condition: + "!d2:hasValue( #{INFECTION_SOURCE} ) || #{INFECTION_SOURCE} == 'IMPORTED_CASE' || #{INFECTION_SOURCE} == 'EXPOSURE_UNKNOWN'", + description: 'Hide Case Type for Imported Cases', + displayName: 'Hide Case Type', + programId: 'PNClHaZARtz', + programRuleActions: [ + { id: 'k05Owr8pwIn', dataElementId: 'A4Fg6jgWauf', programRuleActionType: 'HIDEFIELD' }, + ], + }, + { + id: 'MLS5vZLguQM', + condition: "#{INFECTION_SOURCE} != 'LOCAL_TRANSMISSION'", + description: "Hide 'Specify Local Infection Source' unless Local Transmission is selected", + displayName: "Hide 'Specify Local Infection Source'", + programId: 'PNClHaZARtz', + programRuleActions: [ + { id: 'ho7xRPUB0Gl', dataElementId: 'jBBkFuPKctq', programRuleActionType: 'HIDEFIELD' }, + ], + }, + { + id: 'NXWk8sq70OV', + condition: "#{TRAVEL_HISTORY} == 'No'", + description: "Hide 'Imported Case' if not traveled", + displayName: "Hide 'Imported Case'", + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'fJIgmDK53Vp', + dataElementId: 'f8j4XDEozvj', + programRuleActionType: 'HIDEOPTION', + optionId: 'PMGTqmVIF4T', + }, + ], + }, + { + id: 'NZaVqr7dPfQ', + condition: '!d2:hasValue( #{ONSET_DATE} ) && !d2:hasValue(V{event_date})', + description: 'Automation: Assign Empty date if no Onset date and no event date is available', + displayName: 'Assign Empty Date', + programId: 'PNClHaZARtz', + programRuleActions: [ + { id: 'q060xuOwQx3', data: "''", dataElementId: 'PFXeJV8d7ja', programRuleActionType: 'ASSIGN' }, + ], + priority: 3, + }, + { + id: 'QrJx9LI9KRo', + condition: "d2:hasValue( #{LAB_TEST} ) && #{LAB_TEST} == 'Yes' && !d2:hasValue( #{TEST_RESULT} )", + description: 'Automation: Assign Empty Value to Class Classification', + displayName: 'Assign Empty Value to Class Classification', + programId: 'PNClHaZARtz', + programRuleActions: [ + { id: 'rFaZAbOgMSz', data: "''", dataElementId: 'Z5z8vFQy0w0', programRuleActionType: 'ASSIGN' }, + ], + priority: 2, + }, + { + id: 'R6oEX1xlQma', + condition: 'true', + description: 'Hide irrelevant Outcome Options', + displayName: 'Hide Outcome Options', + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'Ov7qHXf0Q2s', + dataElementId: 'bOYWVEBaWy6', + programRuleActionType: 'HIDEOPTION', + optionId: 'dUeRcF2cApV', + }, + { + id: 'V95rgvUlqY0', + dataElementId: 'bOYWVEBaWy6', + programRuleActionType: 'HIDEOPTION', + optionId: 'bYt4why1tL3', + }, + { + id: 'eZUUOjykbLv', + dataElementId: 'bOYWVEBaWy6', + programRuleActionType: 'HIDEOPTION', + optionId: 'xBoo6HyaYcd', + }, + { + id: 'Zcs7rz5VEF7', + dataElementId: 'bOYWVEBaWy6', + programRuleActionType: 'HIDEOPTION', + optionId: 'RCT079wdeKT', + }, + ], + }, + { + id: 'dZsTiQEUg5L', + condition: '!d2:hasValue( #{ONSET_DATE} ) && d2:hasValue(V{event_date})', + description: 'Automation: Assign Event date if no Onset date is available', + displayName: 'Assign Event Date', + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'sQKFBORp5P1', + data: 'V{event_date}', + dataElementId: 'PFXeJV8d7ja', + programRuleActionType: 'ASSIGN', + }, + ], + priority: 2, + }, + { + id: 'kVBrxwODyTj', + condition: '!d2:hasValue( #{LAB_TEST} )', + description: 'Hide Case Classification Field until Lab Test question is answered', + displayName: 'Hide Case Classification Field', + programId: 'PNClHaZARtz', + programRuleActions: [ + { id: 'ZT8AexxBPl0', dataElementId: 'Z5z8vFQy0w0', programRuleActionType: 'HIDEFIELD' }, + ], + }, + { + id: 'q2QbEfeDlI9', + condition: "!d2:hasValue( #{HOSPITALISED} ) || #{HOSPITALISED} == 'No'", + description: 'Hide ICU field unless Hospitalised', + displayName: 'Hide ICU field', + programId: 'PNClHaZARtz', + programRuleActions: [ + { id: 'wwvxLCpuOCx', dataElementId: 'p8htbyJHydl', programRuleActionType: 'HIDEFIELD' }, + ], + }, + { + id: 'rZUpiMuJIKH', + condition: "d2:hasValue( #{LAB_TEST} ) && #{LAB_TEST} == 'Yes' && #{TEST_RESULT} == 'Positive'", + description: "Automation: Assign 'Laboratory Confirmed Case' to Case Classification", + displayName: "Assign 'Laboratory Confirmed Case' to Case Classification", + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'hcamYSDn00P', + data: "'Laboratory Confirmed Case'", + dataElementId: 'Z5z8vFQy0w0', + programRuleActionType: 'ASSIGN', + }, + ], + priority: 3, + }, + { + id: 'sEQsGGAQSJT', + condition: + "(d2:hasValue( #{LAB_TEST} ) && #{LAB_TEST} == 'Unknown') ||\n(d2:hasValue( #{LAB_TEST} ) && #{LAB_TEST} == 'Yes' && (#{TEST_RESULT} == 'Negative' || #{TEST_RESULT} == 'Unknown'))", + description: "Automation: Assign Suspected Case' to Case Classification", + displayName: "Assign 'Suspected Case' to Case Classification", + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'zxb2XDboGAF', + data: "'Suspected Case'", + dataElementId: 'Z5z8vFQy0w0', + programRuleActionType: 'ASSIGN', + }, + ], + priority: 1, + }, + { + id: 'sKCZMuWwOKA', + condition: 'd2:hasValue( #{ONSET_DATE} )', + description: 'Automation: Assign Symptoms Onset Date if available', + displayName: 'Assign Onset Date', + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'lJOYxhjupxz', + data: '#{ONSET_DATE}', + dataElementId: 'PFXeJV8d7ja', + programRuleActionType: 'ASSIGN', + }, + ], + priority: 1, + }, + { + id: 'vj5GWKIrhKh', + condition: "#{LAB_TEST} != 'Yes'", + description: 'Hide Test Result Field until Lab Test question is answered with yes', + displayName: 'Hide Test Result Field', + programId: 'PNClHaZARtz', + programRuleActions: [ + { id: 'VxxxIX2598r', dataElementId: 'ovY6E8BSdto', programRuleActionType: 'HIDEFIELD' }, + ], + }, + ]; + const programRuleVariables = [ + { + id: 'DoRHHfNPccb', + dataElementId: 'f8j4XDEozvj', + displayName: 'INFECTION_SOURCE', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: false, + }, + { + id: 'EnpvdmYrwLb', + dataElementId: 'TzqawmlPkI5', + displayName: 'TRAVEL_HISTORY', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: true, + }, + { + id: 'JPIyrAmJapV', + dataElementId: 'CUbZcLm9LyN', + displayName: 'HOSPITALISED', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: true, + }, + { + id: 'LAaPMTz69L7', + displayName: 'CASE_CLASSIFICATION', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.CALCULATED_VALUE, + useNameForOptionSet: true, + valueType: 'TEXT', + }, + { + id: 'MpixycZvu0m', + dataElementId: 'ovY6E8BSdto', + displayName: 'TEST_RESULT', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: true, + }, + { + id: 'XcPYCpTOPwB', + dataElementId: 'QQLXTXVidW2', + displayName: 'LAB_TEST', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: true, + }, + { + id: 'cZSslcAEupI', + dataElementId: 's3eoonJ8OJb', + displayName: 'ONSET_DATE', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: true, + }, + { + id: 'eSq3nc1t2F6', + dataElementId: 'dyfYIsTFTjG', + displayName: 'PATIENT_ID', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: true, + }, + { + id: 'lY0yJGU1D4e', + dataElementId: 'JGnHr6WI3AY', + displayName: 'SYMPTOMS', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: false, + }, + ]; const orgUnit = { id: 'DiszpKrYNg8', name: 'Ngelehun CHC' }; const optionSets = { - L6eMZDJkCwX: { id: 'L6eMZDJkCwX', displayName: 'Yes/No/Unknown', version: 3, valueType: 'TEXT', options: [{ id: 'x9yVKkv9koc', displayName: 'Yes', code: 'Yes', translations: [{ property: 'NAME', locale: 'uz@Latn', value: 'Ha' }, { property: 'NAME', locale: 'fr', value: 'Oui' }, { property: 'NAME', locale: 'pt', value: 'Sim' }, { property: 'NAME', locale: 'uz@Cyrl', value: 'Ҳа' }, { property: 'NAME', locale: 'es', value: 'Sí' }, { property: 'NAME', locale: 'nb', value: 'Ja' }, { property: 'NAME', locale: 'ru', value: 'да' }] }, { id: 'R98tI2c6rF5', displayName: 'No', code: 'No', translations: [{ property: 'NAME', locale: 'nb', value: 'Nei' }, { property: 'NAME', locale: 'es', value: 'No' }, { property: 'NAME', locale: 'uz@Latn', value: 'Yo`q' }, { property: 'NAME', locale: 'ru', value: 'нет' }, { property: 'NAME', locale: 'pt', value: 'Não' }, { property: 'NAME', locale: 'fr', value: 'Non' }, { property: 'NAME', locale: 'uz@Cyrl', value: 'Йўқ' }] }, { id: 'pqxvAQU1z9W', displayName: 'Unknown', code: 'Unknown', translations: [{ property: 'NAME', locale: 'es', value: 'DEsconocido' }, { property: 'NAME', locale: 'nb', value: 'Ukjent' }, { property: 'NAME', locale: 'uz@Cyrl', value: 'Ноаниқ' }, { property: 'NAME', locale: 'fr', value: 'Inconnu' }, { property: 'NAME', locale: 'uz@Latn', value: 'Noaniq' }, { property: 'NAME', locale: 'pt', value: 'Desconhecido' }, { property: 'NAME', locale: 'ru', value: 'Неизвестно' }] }] }, - dsgBmIZ0Yrq: { id: 'dsgBmIZ0Yrq', displayName: 'Test Result', version: 6, valueType: 'TEXT', options: [{ id: 'B44lkxTWbGO', displayName: 'Inconclusive', code: 'Inconclusive', translations: [{ property: 'NAME', locale: 'fr', value: 'Non concluant' }, { property: 'NAME', locale: 'pt', value: 'Inconclusivo' }, { property: 'NAME', locale: 'nb', value: 'Mangelfull' }, { property: 'NAME', locale: 'es', value: 'No concluyente' }, { property: 'NAME', locale: 'ru', value: 'Неокончательный' }] }, { id: 'ljClr1z2aE7', displayName: 'Negative', code: 'Negative', translations: [{ property: 'NAME', locale: 'fr', value: 'Négatif' }, { property: 'NAME', locale: 'nb', value: 'Negativ' }, { property: 'NAME', locale: 'es', value: 'Negativo' }, { property: 'NAME', locale: 'uz@Latn', value: 'Manfiy' }, { property: 'NAME', locale: 'pt', value: 'Negativo' }, { property: 'NAME', locale: 'ru', value: 'Отрицательный' }, { property: 'NAME', locale: 'uz@Cyrl', value: 'Манфий' }] }, { id: 'LKbwTJwocOk', displayName: 'Positive', code: 'Positive', translations: [{ property: 'NAME', locale: 'ru', value: 'Положительный' }, { property: 'NAME', locale: 'es', value: 'Positivo' }, { property: 'NAME', locale: 'uz@Latn', value: 'Musbat' }, { property: 'NAME', locale: 'uz@Cyrl', value: 'Мусбат' }, { property: 'NAME', locale: 'nb', value: 'Positiv' }, { property: 'NAME', locale: 'fr', value: 'Positif' }, { property: 'NAME', locale: 'pt', value: 'Positivo' }] }, { id: 'MkeWrqeqZXL', displayName: 'Not performed', code: 'Not performed', translations: [{ property: 'NAME', locale: 'ru', value: 'Не выполнен' }, { property: 'NAME', locale: 'pt', value: 'Não realizado' }, { property: 'NAME', locale: 'nb', value: 'Ikke utført' }, { property: 'NAME', locale: 'fr', value: 'Non réalisé' }, { property: 'NAME', locale: 'es', value: 'No realizado' }] }, { id: 'fPV0gQ8ds6D', displayName: 'Invalid', code: 'Invalid', translations: [{ property: 'NAME', locale: 'es', value: 'Inválido' }, { property: 'NAME', locale: 'fr', value: 'Invalide' }, { property: 'NAME', locale: 'pt', value: 'Inválido' }, { property: 'NAME', locale: 'nb', value: 'Ugyldig' }, { property: 'NAME', locale: 'ru', value: 'Недействительный' }] }, { id: 'YV3jCZlvwZe', displayName: 'Unknown', code: 'Unknown', translations: [{ property: 'NAME', locale: 'es', value: 'DEsconocido' }, { property: 'NAME', locale: 'nb', value: 'Ukjent' }, { property: 'NAME', locale: 'uz@Cyrl', value: 'Ноаниқ' }, { property: 'NAME', locale: 'fr', value: 'Inconnu' }, { property: 'NAME', locale: 'uz@Latn', value: 'Noaniq' }, { property: 'NAME', locale: 'pt', value: 'Desconhecido' }, { property: 'NAME', locale: 'ru', value: 'Неизвестно' }] }] }, + L6eMZDJkCwX: { + id: 'L6eMZDJkCwX', + displayName: 'Yes/No/Unknown', + version: 3, + valueType: 'TEXT', + options: [ + { + id: 'x9yVKkv9koc', + displayName: 'Yes', + code: 'Yes', + translations: [ + { property: 'NAME', locale: 'uz@Latn', value: 'Ha' }, + { property: 'NAME', locale: 'fr', value: 'Oui' }, + { property: 'NAME', locale: 'pt', value: 'Sim' }, + { property: 'NAME', locale: 'uz@Cyrl', value: 'Ҳа' }, + { property: 'NAME', locale: 'es', value: 'Sí' }, + { property: 'NAME', locale: 'nb', value: 'Ja' }, + { property: 'NAME', locale: 'ru', value: 'да' }, + ], + }, + { + id: 'R98tI2c6rF5', + displayName: 'No', + code: 'No', + translations: [ + { property: 'NAME', locale: 'nb', value: 'Nei' }, + { property: 'NAME', locale: 'es', value: 'No' }, + { property: 'NAME', locale: 'uz@Latn', value: 'Yo`q' }, + { property: 'NAME', locale: 'ru', value: 'нет' }, + { property: 'NAME', locale: 'pt', value: 'Não' }, + { property: 'NAME', locale: 'fr', value: 'Non' }, + { property: 'NAME', locale: 'uz@Cyrl', value: 'Йўқ' }, + ], + }, + { + id: 'pqxvAQU1z9W', + code: 'Unknown', + translations: [ + { property: 'NAME', locale: 'es', value: 'DEsconocido' }, + { property: 'NAME', locale: 'nb', value: 'Ukjent' }, + { property: 'NAME', locale: 'uz@Cyrl', value: 'Ноаниқ' }, + { property: 'NAME', locale: 'fr', value: 'Inconnu' }, + { property: 'NAME', locale: 'uz@Latn', value: 'Noaniq' }, + { property: 'NAME', locale: 'pt', value: 'Desconhecido' }, + { property: 'NAME', locale: 'ru', value: 'Неизвестно' }, + ], + }, + ], + }, + dsgBmIZ0Yrq: { + id: 'dsgBmIZ0Yrq', + displayName: 'Test Result', + version: 6, + valueType: 'TEXT', + options: [ + { + id: 'B44lkxTWbGO', + code: 'Inconclusive', + translations: [ + { property: 'NAME', locale: 'fr', value: 'Non concluant' }, + { property: 'NAME', locale: 'pt', value: 'Inconclusivo' }, + { property: 'NAME', locale: 'nb', value: 'Mangelfull' }, + { property: 'NAME', locale: 'es', value: 'No concluyente' }, + { property: 'NAME', locale: 'ru', value: 'Неокончательный' }, + ], + }, + { + id: 'ljClr1z2aE7', + displayName: 'Negative', + code: 'Negative', + translations: [ + { property: 'NAME', locale: 'fr', value: 'Négatif' }, + { property: 'NAME', locale: 'nb', value: 'Negativ' }, + { property: 'NAME', locale: 'es', value: 'Negativo' }, + { property: 'NAME', locale: 'uz@Latn', value: 'Manfiy' }, + { property: 'NAME', locale: 'pt', value: 'Negativo' }, + { property: 'NAME', locale: 'ru', value: 'Отрицательный' }, + { property: 'NAME', locale: 'uz@Cyrl', value: 'Манфий' }, + ], + }, + { + id: 'LKbwTJwocOk', + displayName: 'Positive', + code: 'Positive', + translations: [ + { property: 'NAME', locale: 'ru', value: 'Положительный' }, + { property: 'NAME', locale: 'es', value: 'Positivo' }, + { property: 'NAME', locale: 'uz@Latn', value: 'Musbat' }, + { property: 'NAME', locale: 'uz@Cyrl', value: 'Мусбат' }, + { property: 'NAME', locale: 'nb', value: 'Positiv' }, + { property: 'NAME', locale: 'fr', value: 'Positif' }, + { property: 'NAME', locale: 'pt', value: 'Positivo' }, + ], + }, + { + id: 'MkeWrqeqZXL', + displayName: 'Not performed', + code: 'Not performed', + translations: [ + { property: 'NAME', locale: 'ru', value: 'Не выполнен' }, + { property: 'NAME', locale: 'pt', value: 'Não realizado' }, + { property: 'NAME', locale: 'nb', value: 'Ikke utført' }, + { property: 'NAME', locale: 'fr', value: 'Non réalisé' }, + { property: 'NAME', locale: 'es', value: 'No realizado' }, + ], + }, + { + id: 'fPV0gQ8ds6D', + displayName: 'Invalid', + code: 'Invalid', + translations: [ + { property: 'NAME', locale: 'es', value: 'Inválido' }, + { property: 'NAME', locale: 'fr', value: 'Invalide' }, + { property: 'NAME', locale: 'pt', value: 'Inválido' }, + { property: 'NAME', locale: 'nb', value: 'Ugyldig' }, + { property: 'NAME', locale: 'ru', value: 'Недействительный' }, + ], + }, + { + id: 'YV3jCZlvwZe', + displayName: 'Unknown', + code: 'Unknown', + translations: [ + { property: 'NAME', locale: 'es', value: 'DEsconocido' }, + { property: 'NAME', locale: 'nb', value: 'Ukjent' }, + { property: 'NAME', locale: 'uz@Cyrl', value: 'Ноаниқ' }, + { property: 'NAME', locale: 'fr', value: 'Inconnu' }, + { property: 'NAME', locale: 'uz@Latn', value: 'Noaniq' }, + { property: 'NAME', locale: 'pt', value: 'Desconhecido' }, + { property: 'NAME', locale: 'ru', value: 'Неизвестно' }, + ], + }, + ], + }, }; // NOTE: in this test we dont use toMatchSnapshot instead we test again hardcoded values. Since the effects are plenty @@ -167,18 +916,68 @@ describe('Event rules engine', () => { [ { JGnHr6WI3AY: 'Yes' }, [ - { type: 'ASSIGN', id: 'PFXeJV8d7ja', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'MkeWrqeqZXL' }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'fPV0gQ8ds6D' }, - { type: 'HIDEOPTION', id: 'JGnHr6WI3AY', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'CUbZcLm9LyN', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, + { + type: 'ASSIGN', + id: 'PFXeJV8d7ja', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'MkeWrqeqZXL', + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'fPV0gQ8ds6D', + }, + { + type: 'HIDEOPTION', + id: 'JGnHr6WI3AY', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'p8htbyJHydl', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'CUbZcLm9LyN', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, { type: 'HIDEFIELD', id: 'A4Fg6jgWauf', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'jBBkFuPKctq', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'dUeRcF2cApV' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'bYt4why1tL3' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'xBoo6HyaYcd' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'RCT079wdeKT' }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'dUeRcF2cApV', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'bYt4why1tL3', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'xBoo6HyaYcd', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'RCT079wdeKT', + }, { type: 'HIDEFIELD', id: 'Z5z8vFQy0w0', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, @@ -187,40 +986,150 @@ describe('Event rules engine', () => { [ { QQLXTXVidW2: 'Yes' }, [ - { type: 'ASSIGN', id: 'Z5z8vFQy0w0', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'ASSIGN', id: 'PFXeJV8d7ja', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'MkeWrqeqZXL' }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'fPV0gQ8ds6D' }, + { + type: 'ASSIGN', + id: 'Z5z8vFQy0w0', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'ASSIGN', + id: 'PFXeJV8d7ja', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'MkeWrqeqZXL', + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'fPV0gQ8ds6D', + }, { type: 'HIDEFIELD', id: 's3eoonJ8OJb', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'JGnHr6WI3AY', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'CUbZcLm9LyN', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, + { + type: 'HIDEOPTION', + id: 'JGnHr6WI3AY', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'p8htbyJHydl', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'CUbZcLm9LyN', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, { type: 'HIDEFIELD', id: 'A4Fg6jgWauf', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'jBBkFuPKctq', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'dUeRcF2cApV' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'bYt4why1tL3' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'xBoo6HyaYcd' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'RCT079wdeKT' }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'dUeRcF2cApV', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'bYt4why1tL3', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'xBoo6HyaYcd', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'RCT079wdeKT', + }, { type: 'HIDEFIELD', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, ], ], [ { QQLXTXVidW2: 'No' }, [ - { type: 'ASSIGN', id: 'PFXeJV8d7ja', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'ASSIGN', id: 'Z5z8vFQy0w0', value: 'Probable Case', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'MkeWrqeqZXL' }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'fPV0gQ8ds6D' }, + { + type: 'ASSIGN', + id: 'PFXeJV8d7ja', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'ASSIGN', + id: 'Z5z8vFQy0w0', + value: 'Probable Case', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'MkeWrqeqZXL', + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'fPV0gQ8ds6D', + }, { type: 'HIDEFIELD', id: 's3eoonJ8OJb', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'JGnHr6WI3AY', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'CUbZcLm9LyN', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, + { + type: 'HIDEOPTION', + id: 'JGnHr6WI3AY', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'p8htbyJHydl', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'CUbZcLm9LyN', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, { type: 'HIDEFIELD', id: 'A4Fg6jgWauf', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'jBBkFuPKctq', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'dUeRcF2cApV' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'bYt4why1tL3' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'xBoo6HyaYcd' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'RCT079wdeKT' }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'dUeRcF2cApV', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'bYt4why1tL3', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'xBoo6HyaYcd', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'RCT079wdeKT', + }, { type: 'HIDEFIELD', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, ], @@ -228,20 +1137,75 @@ describe('Event rules engine', () => { [ { QQLXTXVidW2: 'Unknown' }, [ - { type: 'ASSIGN', id: 'Z5z8vFQy0w0', value: 'Suspected Case', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'ASSIGN', id: 'PFXeJV8d7ja', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'MkeWrqeqZXL' }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'fPV0gQ8ds6D' }, + { + type: 'ASSIGN', + id: 'Z5z8vFQy0w0', + value: 'Suspected Case', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'ASSIGN', + id: 'PFXeJV8d7ja', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'MkeWrqeqZXL', + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'fPV0gQ8ds6D', + }, { type: 'HIDEFIELD', id: 's3eoonJ8OJb', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'JGnHr6WI3AY', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'CUbZcLm9LyN', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, + { + type: 'HIDEOPTION', + id: 'JGnHr6WI3AY', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'p8htbyJHydl', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'CUbZcLm9LyN', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, { type: 'HIDEFIELD', id: 'A4Fg6jgWauf', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'jBBkFuPKctq', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'dUeRcF2cApV' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'bYt4why1tL3' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'xBoo6HyaYcd' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'RCT079wdeKT' }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'dUeRcF2cApV', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'bYt4why1tL3', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'xBoo6HyaYcd', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'RCT079wdeKT', + }, { type: 'HIDEFIELD', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, ], @@ -249,19 +1213,69 @@ describe('Event rules engine', () => { [ { CUbZcLm9LyN: 'Yes' }, [ - { type: 'ASSIGN', id: 'PFXeJV8d7ja', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'MkeWrqeqZXL' }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'fPV0gQ8ds6D' }, + { + type: 'ASSIGN', + id: 'PFXeJV8d7ja', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'MkeWrqeqZXL', + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'fPV0gQ8ds6D', + }, { type: 'HIDEFIELD', id: 's3eoonJ8OJb', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'JGnHr6WI3AY', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'CUbZcLm9LyN', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, + { + type: 'HIDEOPTION', + id: 'JGnHr6WI3AY', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'p8htbyJHydl', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'CUbZcLm9LyN', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, { type: 'HIDEFIELD', id: 'A4Fg6jgWauf', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'jBBkFuPKctq', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'dUeRcF2cApV' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'bYt4why1tL3' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'xBoo6HyaYcd' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'RCT079wdeKT' }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'dUeRcF2cApV', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'bYt4why1tL3', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'xBoo6HyaYcd', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'RCT079wdeKT', + }, { type: 'HIDEFIELD', id: 'Z5z8vFQy0w0', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, ], @@ -269,80 +1283,300 @@ describe('Event rules engine', () => { [ { QQLXTXVidW2: 'Yes', ovY6E8BSdto: 'Inconclusive' }, [ - { type: 'ASSIGN', id: 'PFXeJV8d7ja', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'ASSIGN', id: 'Z5z8vFQy0w0', value: 'Probable Case', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'MkeWrqeqZXL' }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'fPV0gQ8ds6D' }, + { + type: 'ASSIGN', + id: 'PFXeJV8d7ja', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'ASSIGN', + id: 'Z5z8vFQy0w0', + value: 'Probable Case', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'MkeWrqeqZXL', + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'fPV0gQ8ds6D', + }, { type: 'HIDEFIELD', id: 's3eoonJ8OJb', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'JGnHr6WI3AY', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'CUbZcLm9LyN', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, + { + type: 'HIDEOPTION', + id: 'JGnHr6WI3AY', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'p8htbyJHydl', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'CUbZcLm9LyN', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, { type: 'HIDEFIELD', id: 'A4Fg6jgWauf', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'jBBkFuPKctq', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'dUeRcF2cApV' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'bYt4why1tL3' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'xBoo6HyaYcd' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'RCT079wdeKT' }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'dUeRcF2cApV', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'bYt4why1tL3', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'xBoo6HyaYcd', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'RCT079wdeKT', + }, { type: 'HIDEFIELD', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, ], ], [ { QQLXTXVidW2: 'Yes', ovY6E8BSdto: 'Positive' }, [ - { type: 'ASSIGN', id: 'PFXeJV8d7ja', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'ASSIGN', id: 'Z5z8vFQy0w0', value: 'Laboratory Confirmed Case', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'MkeWrqeqZXL' }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'fPV0gQ8ds6D' }, + { + type: 'ASSIGN', + id: 'PFXeJV8d7ja', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'ASSIGN', + id: 'Z5z8vFQy0w0', + value: 'Laboratory Confirmed Case', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'MkeWrqeqZXL', + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'fPV0gQ8ds6D', + }, { type: 'HIDEFIELD', id: 's3eoonJ8OJb', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'JGnHr6WI3AY', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'CUbZcLm9LyN', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, + { + type: 'HIDEOPTION', + id: 'JGnHr6WI3AY', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'p8htbyJHydl', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'CUbZcLm9LyN', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, { type: 'HIDEFIELD', id: 'A4Fg6jgWauf', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'jBBkFuPKctq', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'dUeRcF2cApV' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'bYt4why1tL3' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'xBoo6HyaYcd' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'RCT079wdeKT' }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'dUeRcF2cApV', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'bYt4why1tL3', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'xBoo6HyaYcd', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'RCT079wdeKT', + }, { type: 'HIDEFIELD', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, ], ], [ { QQLXTXVidW2: 'Yes', ovY6E8BSdto: 'Negative' }, [ - { type: 'ASSIGN', id: 'Z5z8vFQy0w0', value: 'Suspected Case', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'ASSIGN', id: 'PFXeJV8d7ja', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'MkeWrqeqZXL' }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'fPV0gQ8ds6D' }, + { + type: 'ASSIGN', + id: 'Z5z8vFQy0w0', + value: 'Suspected Case', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'ASSIGN', + id: 'PFXeJV8d7ja', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'MkeWrqeqZXL', + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'fPV0gQ8ds6D', + }, { type: 'HIDEFIELD', id: 's3eoonJ8OJb', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'JGnHr6WI3AY', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'CUbZcLm9LyN', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, + { + type: 'HIDEOPTION', + id: 'JGnHr6WI3AY', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'p8htbyJHydl', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'CUbZcLm9LyN', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, { type: 'HIDEFIELD', id: 'A4Fg6jgWauf', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'jBBkFuPKctq', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'dUeRcF2cApV' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'bYt4why1tL3' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'xBoo6HyaYcd' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'RCT079wdeKT' }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'dUeRcF2cApV', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'bYt4why1tL3', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'xBoo6HyaYcd', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'RCT079wdeKT', + }, { type: 'HIDEFIELD', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, ], ], [ { QQLXTXVidW2: 'Yes', ovY6E8BSdto: 'Unknown' }, [ - { type: 'ASSIGN', id: 'Z5z8vFQy0w0', value: 'Suspected Case', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'ASSIGN', id: 'PFXeJV8d7ja', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'MkeWrqeqZXL' }, - { type: 'HIDEOPTION', id: 'ovY6E8BSdto', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'fPV0gQ8ds6D' }, + { + type: 'ASSIGN', + id: 'Z5z8vFQy0w0', + value: 'Suspected Case', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'ASSIGN', + id: 'PFXeJV8d7ja', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'MkeWrqeqZXL', + }, + { + type: 'HIDEOPTION', + id: 'ovY6E8BSdto', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'fPV0gQ8ds6D', + }, { type: 'HIDEFIELD', id: 's3eoonJ8OJb', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'JGnHr6WI3AY', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, - { type: 'HIDEOPTION', id: 'CUbZcLm9LyN', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'pqxvAQU1z9W' }, + { + type: 'HIDEOPTION', + id: 'JGnHr6WI3AY', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'p8htbyJHydl', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, + { + type: 'HIDEOPTION', + id: 'CUbZcLm9LyN', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'pqxvAQU1z9W', + }, { type: 'HIDEFIELD', id: 'A4Fg6jgWauf', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, { type: 'HIDEFIELD', id: 'jBBkFuPKctq', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'dUeRcF2cApV' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'bYt4why1tL3' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'xBoo6HyaYcd' }, - { type: 'HIDEOPTION', id: 'bOYWVEBaWy6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, optionId: 'RCT079wdeKT' }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'dUeRcF2cApV', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'bYt4why1tL3', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'xBoo6HyaYcd', + }, + { + type: 'HIDEOPTION', + id: 'bOYWVEBaWy6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + optionId: 'RCT079wdeKT', + }, { type: 'HIDEFIELD', id: 'p8htbyJHydl', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, ], ], @@ -361,15 +1595,261 @@ describe('Event rules engine', () => { }); }); - describe('Event rules engine effects with functions and effects', () => { // these variables are shared between each test - const constants = [{ id: 'Gfd3ppDfq8E', displayName: 'Commodity ordering overhead', value: 5 }, { id: 'bCqvfPR02Im', displayName: 'Pi', value: 3.14 }]; - const dataElementsInProgram = { oZg33kd9taw: { id: 'oZg33kd9taw', valueType: 'TEXT', optionSetId: 'pC3N9N77UmT' }, SWfdB5lX0fk: { id: 'SWfdB5lX0fk', valueType: 'BOOLEAN' }, qrur9Dvnyt5: { id: 'qrur9Dvnyt5', valueType: 'INTEGER' }, GieVkTxp4HH: { id: 'GieVkTxp4HH', valueType: 'NUMBER' }, vV9UWAZohSf: { id: 'vV9UWAZohSf', valueType: 'INTEGER_POSITIVE' }, eMyVanycQSC: { id: 'eMyVanycQSC', valueType: 'DATE' }, K6uUAvq500H: { id: 'K6uUAvq500H', valueType: 'TEXT', optionSetId: 'eUZ79clX7y1' }, msodh3rEMJa: { id: 'msodh3rEMJa', valueType: 'DATE' }, S33cRBsnXPo: { id: 'S33cRBsnXPo', valueType: 'ORGANISATION_UNIT' }, fWIAEtYVEGk: { id: 'fWIAEtYVEGk', valueType: 'TEXT', optionSetId: 'iDFPKpFTiVw' }, ulD2zW0TIy2: { id: 'ulD2zW0TIy2', valueType: 'FILE_RESOURCE' } }; - const programRules = [{ id: 'CTzRoPyvf8v', condition: 'true', displayName: 'Testing the functions!', programId: 'eBAyeGv0exc', programRuleActions: [{ id: 'isP0uvT24jf', displayContent: "d2:yearsBetween( '2010-01-28', V{event_date}) =", data: "d2:yearsBetween( '2010-01-28', V{event_date})", programRuleActionType: 'DISPLAYTEXT' }, { id: 'vQCRnX6w9pM', displayContent: 'd2:oizp( -10000000 ) =', data: 'd2:oizp( -10000000 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'SYAL0GIDnxI', displayContent: 'display age = ', data: 'd2:hasValue(#{age}) && #{age}', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'Xa0tKyNk5YE', displayContent: 'org_unit = ', data: 'V{orgunit_code}', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'JXssEpbJdO2', displayContent: 'd2:right(#{age}, 3) = ', data: 'd2:hasValue(#{age}) && d2:right(#{age}, 3)', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'o0LLNIYsliy', displayContent: "d2:monthsBetween( '2020-01-28', V{event_date}) = ", data: "d2:monthsBetween( '2020-01-28', V{event_date})", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'k07KnI11Sf4', displayContent: 'd2:left(#{age}, 3) = ', data: 'd2:hasValue(#{age}) && d2:left(#{age}, 3)', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'OITs4nPfMQ3', displayContent: "d2:split('these-are-testing-values', '-', 2) = ", data: "d2:split('these-are-testing-values', '-', 2)", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'EzkFLDtAxCR', displayContent: 'd2:modulus( 12 , 100 ) = ', data: 'd2:modulus( 12 , 100 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'RCYEyOly0Mi', displayContent: "d2:countIfValue( #{gender}, 'Male' ) = ", data: "d2:countIfValue( #{gender}, 'Male' )", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'bRnjbxIwIRd', displayContent: 'd2:round( 12.5 ) = ', data: 'd2:round( 12.5 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'BuEcHNoD98P', displayContent: 'd2:ceil(11.3) = ', data: 'd2:ceil(11.3)', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'Foc3PhzoAVr', displayContent: 'd2:count(#{age}) = ', data: 'd2:count(#{age})', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'QpeF2WDjwIV', displayContent: "d2:addDays( '2020-01-12', 5 ) = ", data: "d2:addDays( '2020-01-12', 5 )", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'WJTjezLR4cJ', displayContent: "d2:weeksBetween('2020-01-28', V{event_date} ) = ", data: "d2:weeksBetween('2020-01-28', V{event_date} )", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'YnE4dNJVF2P', displayContent: 'd2:zing( -2 ) = ', data: 'd2:zing( -2 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'bZsv2cUkbB7', displayContent: 'd2:floor( 11.5 ) =', data: 'd2:floor( 11.5 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'J8RxAbHlnO3', displayContent: 'd2:oizp( 10000000 ) = ', data: 'd2:oizp( 10000000 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'NT1wojA2RdT', displayContent: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking') = ", data: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking')", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'NUGe7EUVouK', displayContent: "d2:substring('hello dhis 2', 6, 10) = ", data: "d2:substring('hello dhis 2', 6, 10)", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'Ma6nCIGrBrd', displayContent: "d2:length( 'dhis2 rocks' ) = ", data: "d2:length( 'dhis2 rocks' )", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'RRSDsxWiUMc', displayContent: 'd2:round( 0 ) = ', data: 'd2:round( 0 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'QUe0Pks4ckc', displayContent: 'd2:countIfValue( #{age}, 1 ) = ', data: 'd2:countIfValue( #{age}, 1 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'sHaE1YI0ur2', displayContent: 'd2:zing( 1000 ) = ', data: 'd2:zing( 1000 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'EojHcBMpW7q', displayContent: 'd2:hasValue( #{age} ) = ', data: 'd2:hasValue( #{age} )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }] }]; - const programRuleVariables = [{ id: 'RycV5uDi66i', dataElementId: 'qrur9Dvnyt5', displayName: 'age', programId: 'eBAyeGv0exc', programRuleVariableSourceType: 'DATAELEMENT_NEWEST_EVENT_PROGRAM', useNameForOptionSet: true }, { id: 'zINGRka3g9N', dataElementId: 'oZg33kd9taw', displayName: 'gender', programId: 'eBAyeGv0exc', programRuleVariableSourceType: 'DATAELEMENT_NEWEST_EVENT_PROGRAM', useNameForOptionSet: true }, { id: 'Zj7UnCAulEk.vV9UWAZohSf', displayName: 'Zj7UnCAulEk.vV9UWAZohSf', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', dataElementId: 'vV9UWAZohSf', programId: 'eBAyeGv0exc' }, { id: 'Zj7UnCAulEk.GieVkTxp4HH', displayName: 'Zj7UnCAulEk.GieVkTxp4HH', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', dataElementId: 'GieVkTxp4HH', programId: 'eBAyeGv0exc' }, { id: 'Zj7UnCAulEk.GieVkTxp4HH', displayName: 'Zj7UnCAulEk.GieVkTxp4HH', programRuleVariableSourceType: 'DATAELEMENT_CURRENT_EVENT', dataElementId: 'GieVkTxp4HH', programId: 'eBAyeGv0exc' }]; + const constants = [ + { id: 'Gfd3ppDfq8E', displayName: 'Commodity ordering overhead', value: 5 }, + { id: 'bCqvfPR02Im', displayName: 'Pi', value: 3.14 }, + ]; + const dataElementsInProgram = { + oZg33kd9taw: { id: 'oZg33kd9taw', valueType: 'TEXT', optionSetId: 'pC3N9N77UmT' }, + SWfdB5lX0fk: { id: 'SWfdB5lX0fk', valueType: 'BOOLEAN' }, + qrur9Dvnyt5: { id: 'qrur9Dvnyt5', valueType: 'INTEGER' }, + GieVkTxp4HH: { id: 'GieVkTxp4HH', valueType: 'NUMBER' }, + vV9UWAZohSf: { id: 'vV9UWAZohSf', valueType: 'INTEGER_POSITIVE' }, + eMyVanycQSC: { id: 'eMyVanycQSC', valueType: 'DATE' }, + K6uUAvq500H: { id: 'K6uUAvq500H', valueType: 'TEXT', optionSetId: 'eUZ79clX7y1' }, + msodh3rEMJa: { id: 'msodh3rEMJa', valueType: 'DATE' }, + S33cRBsnXPo: { id: 'S33cRBsnXPo', valueType: 'ORGANISATION_UNIT' }, + fWIAEtYVEGk: { id: 'fWIAEtYVEGk', valueType: 'TEXT', optionSetId: 'iDFPKpFTiVw' }, + ulD2zW0TIy2: { id: 'ulD2zW0TIy2', valueType: 'FILE_RESOURCE' }, + }; + const programRules = [ + { + id: 'CTzRoPyvf8v', + condition: 'true', + displayName: 'Testing the functions!', + programId: 'eBAyeGv0exc', + programRuleActions: [ + { + id: 'isP0uvT24jf', + displayContent: "d2:yearsBetween( '2010-01-28', V{event_date}) =", + data: "d2:yearsBetween( '2010-01-28', V{event_date})", + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'vQCRnX6w9pM', + displayContent: 'd2:oizp( -10000000 ) =', + data: 'd2:oizp( -10000000 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'SYAL0GIDnxI', + displayContent: 'display age = ', + data: 'd2:hasValue(#{age}) && #{age}', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'Xa0tKyNk5YE', + displayContent: 'org_unit = ', + data: 'V{orgunit_code}', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'JXssEpbJdO2', + displayContent: 'd2:right(#{age}, 3) = ', + data: 'd2:hasValue(#{age}) && d2:right(#{age}, 3)', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'o0LLNIYsliy', + displayContent: "d2:monthsBetween( '2020-01-28', V{event_date}) = ", + data: "d2:monthsBetween( '2020-01-28', V{event_date})", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'k07KnI11Sf4', + displayContent: 'd2:left(#{age}, 3) = ', + data: 'd2:hasValue(#{age}) && d2:left(#{age}, 3)', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'OITs4nPfMQ3', + displayContent: "d2:split('these-are-testing-values', '-', 2) = ", + data: "d2:split('these-are-testing-values', '-', 2)", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'EzkFLDtAxCR', + displayContent: 'd2:modulus( 12 , 100 ) = ', + data: 'd2:modulus( 12 , 100 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'RCYEyOly0Mi', + displayContent: "d2:countIfValue( #{gender}, 'Male' ) = ", + data: "d2:countIfValue( #{gender}, 'Male' )", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'bRnjbxIwIRd', + displayContent: 'd2:round( 12.5 ) = ', + data: 'd2:round( 12.5 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'BuEcHNoD98P', + displayContent: 'd2:ceil(11.3) = ', + data: 'd2:ceil(11.3)', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'Foc3PhzoAVr', + displayContent: 'd2:count(#{age}) = ', + data: 'd2:count(#{age})', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'QpeF2WDjwIV', + displayContent: "d2:addDays( '2020-01-12', 5 ) = ", + data: "d2:addDays( '2020-01-12', 5 )", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'WJTjezLR4cJ', + displayContent: "d2:weeksBetween('2020-01-28', V{event_date} ) = ", + data: "d2:weeksBetween('2020-01-28', V{event_date} )", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'YnE4dNJVF2P', + displayContent: 'd2:zing( -2 ) = ', + data: 'd2:zing( -2 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'bZsv2cUkbB7', + displayContent: 'd2:floor( 11.5 ) =', + data: 'd2:floor( 11.5 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'J8RxAbHlnO3', + displayContent: 'd2:oizp( 10000000 ) = ', + data: 'd2:oizp( 10000000 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'NT1wojA2RdT', + displayContent: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking') = ", + data: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'NUGe7EUVouK', + displayContent: "d2:substring('hello dhis 2', 6, 10) = ", + data: "d2:substring('hello dhis 2', 6, 10)", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'Ma6nCIGrBrd', + displayContent: "d2:length( 'dhis2 rocks' ) = ", + data: "d2:length( 'dhis2 rocks' )", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'RRSDsxWiUMc', + displayContent: 'd2:round( 0 ) = ', + data: 'd2:round( 0 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'QUe0Pks4ckc', + displayContent: 'd2:countIfValue( #{age}, 1 ) = ', + data: 'd2:countIfValue( #{age}, 1 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'sHaE1YI0ur2', + displayContent: 'd2:zing( 1000 ) = ', + data: 'd2:zing( 1000 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'EojHcBMpW7q', + displayContent: 'd2:hasValue( #{age} ) = ', + data: 'd2:hasValue( #{age} )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + ], + }, + ]; + const programRuleVariables = [ + { + id: 'RycV5uDi66i', + dataElementId: 'qrur9Dvnyt5', + displayName: 'age', + programId: 'eBAyeGv0exc', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, + useNameForOptionSet: true, + }, + { + id: 'zINGRka3g9N', + dataElementId: 'oZg33kd9taw', + displayName: 'gender', + programId: 'eBAyeGv0exc', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, + useNameForOptionSet: true, + }, + { + id: 'Zj7UnCAulEk.vV9UWAZohSf', + displayName: 'Zj7UnCAulEk.vV9UWAZohSf', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_PREVIOUS_EVENT, + dataElementId: 'vV9UWAZohSf', + programId: 'eBAyeGv0exc', + }, + { + id: 'Zj7UnCAulEk.GieVkTxp4HH', + displayName: 'Zj7UnCAulEk.GieVkTxp4HH', + programRuleVariableSourceType: variableSourceTypes.TEI_ATTRIBUTE, + dataElementId: 'GieVkTxp4HH', + programId: 'eBAyeGv0exc', + }, + { + id: 'Zj7UnCAulEk.GieVkTxp4HH', + displayName: 'Zj7UnCAulEk.GieVkTxp4HH', + programRuleVariableSourceType: 'UNKNOWN', + dataElementId: 'GieVkTxp4HH', + programId: 'eBAyeGv0exc', + }, + ]; const orgUnit = { id: 'DiszpKrYNg8', name: 'Ngelehun CHC', code: 'OU_559' }; - const optionSets = { pC3N9N77UmT: { id: 'pC3N9N77UmT', displayName: 'Gender', version: 0, valueType: 'TEXT', options: [{ id: 'rBvjJYbMCVx', displayName: 'Male', code: 'Male', translations: [] }, { id: 'Mnp3oXrpAbK', displayName: 'Female', code: 'Female', translations: [] }] } }; + const optionSets = { + pC3N9N77UmT: { + id: 'pC3N9N77UmT', + displayName: 'Gender', + version: 0, + valueType: 'TEXT', + options: [ + { id: 'rBvjJYbMCVx', displayName: 'Male', code: 'Male', translations: [] }, + { id: 'Mnp3oXrpAbK', displayName: 'Female', code: 'Female', translations: [] }, + ], + }, + }; // NOTE: in this test we dont use toMatchSnapshot instead we test again hardcoded values. Since the effects are plenty // here each time this way we can avoid mistakes in comparing snapshots @@ -377,95 +1857,410 @@ describe('Event rules engine effects with functions and effects', () => { [ {}, [ - { type: 'DISPLAYTEXT', displayText: { id: 'isP0uvT24jf', message: "d2:yearsBetween( '2010-01-28', V{event_date}) = " } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'vQCRnX6w9pM', message: 'd2:oizp( -10000000 ) = 0' } }, + { + type: 'DISPLAYTEXT', + displayText: { id: 'isP0uvT24jf', message: "d2:yearsBetween( '2010-01-28', V{event_date}) = " }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'vQCRnX6w9pM', message: 'd2:oizp( -10000000 ) = 0' }, + }, { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'SYAL0GIDnxI', message: 'display age = ' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'Xa0tKyNk5YE', message: 'org_unit = OU_559' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'JXssEpbJdO2', message: 'd2:right(#{age}, 3) = ' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'o0LLNIYsliy', message: "d2:monthsBetween( '2020-01-28', V{event_date}) = " } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'k07KnI11Sf4', message: 'd2:left(#{age}, 3) = ' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'OITs4nPfMQ3', message: "d2:split('these-are-testing-values', '-', 2) = testing" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'EzkFLDtAxCR', message: 'd2:modulus( 12 , 100 ) = 12' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'RCYEyOly0Mi', message: "d2:countIfValue( #{gender}, 'Male' ) = 0" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'bRnjbxIwIRd', message: 'd2:round( 12.5 ) = 13' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'BuEcHNoD98P', message: 'd2:ceil(11.3) = 12' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'Foc3PhzoAVr', message: 'd2:count(#{age}) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'QpeF2WDjwIV', message: "d2:addDays( '2020-01-12', 5 ) = 2020-01-17" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'WJTjezLR4cJ', message: "d2:weeksBetween('2020-01-28', V{event_date} ) = " } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'YnE4dNJVF2P', message: 'd2:zing( -2 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'bZsv2cUkbB7', message: 'd2:floor( 11.5 ) = 11' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'J8RxAbHlnO3', message: 'd2:oizp( 10000000 ) = 1' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'NT1wojA2RdT', message: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking') = dhis2isrocking" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'NUGe7EUVouK', message: "d2:substring('hello dhis 2', 6, 10) = dhis" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'Ma6nCIGrBrd', message: "d2:length( 'dhis2 rocks' ) = 11" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'RRSDsxWiUMc', message: 'd2:round( 0 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'QUe0Pks4ckc', message: 'd2:countIfValue( #{age}, 1 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'sHaE1YI0ur2', message: 'd2:zing( 1000 ) = 1000' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'EojHcBMpW7q', message: 'd2:hasValue( #{age} ) = ' } }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Xa0tKyNk5YE', message: 'org_unit = OU_559' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'JXssEpbJdO2', message: 'd2:right(#{age}, 3) = ' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'o0LLNIYsliy', message: "d2:monthsBetween( '2020-01-28', V{event_date}) = " }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'k07KnI11Sf4', message: 'd2:left(#{age}, 3) = ' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'OITs4nPfMQ3', + message: "d2:split('these-are-testing-values', '-', 2) = testing", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'EzkFLDtAxCR', message: 'd2:modulus( 12 , 100 ) = 12' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'RCYEyOly0Mi', message: "d2:countIfValue( #{gender}, 'Male' ) = 0" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'bRnjbxIwIRd', message: 'd2:round( 12.5 ) = 13' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'BuEcHNoD98P', message: 'd2:ceil(11.3) = 12' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Foc3PhzoAVr', message: 'd2:count(#{age}) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'QpeF2WDjwIV', message: "d2:addDays( '2020-01-12', 5 ) = 2020-01-17" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'WJTjezLR4cJ', message: "d2:weeksBetween('2020-01-28', V{event_date} ) = " }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'YnE4dNJVF2P', message: 'd2:zing( -2 ) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'bZsv2cUkbB7', message: 'd2:floor( 11.5 ) = 11' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'J8RxAbHlnO3', message: 'd2:oizp( 10000000 ) = 1' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'NT1wojA2RdT', + message: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking') = dhis2isrocking", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'NUGe7EUVouK', message: "d2:substring('hello dhis 2', 6, 10) = dhis" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Ma6nCIGrBrd', message: "d2:length( 'dhis2 rocks' ) = 11" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'RRSDsxWiUMc', message: 'd2:round( 0 ) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'QUe0Pks4ckc', message: 'd2:countIfValue( #{age}, 1 ) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'sHaE1YI0ur2', message: 'd2:zing( 1000 ) = 1000' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'EojHcBMpW7q', message: 'd2:hasValue( #{age} ) = ' }, + }, ], ], [ { - oZg33kd9taw: 'Male', qrur9Dvnyt5: 0, occurredAt: '2020-04-30T22:00:00.000Z', + oZg33kd9taw: 'Male', + qrur9Dvnyt5: 0, + occurredAt: '2020-04-30T22:00:00.000Z', }, [ - { type: 'DISPLAYTEXT', displayText: { id: 'isP0uvT24jf', message: "d2:yearsBetween( '2010-01-28', V{event_date}) = 10" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'vQCRnX6w9pM', message: 'd2:oizp( -10000000 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'SYAL0GIDnxI', message: 'display age = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'Xa0tKyNk5YE', message: 'org_unit = OU_559' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'JXssEpbJdO2', message: 'd2:right(#{age}, 3) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'o0LLNIYsliy', message: "d2:monthsBetween( '2020-01-28', V{event_date}) = 3" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'k07KnI11Sf4', message: 'd2:left(#{age}, 3) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'OITs4nPfMQ3', message: "d2:split('these-are-testing-values', '-', 2) = testing" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'EzkFLDtAxCR', message: 'd2:modulus( 12 , 100 ) = 12' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'RCYEyOly0Mi', message: "d2:countIfValue( #{gender}, 'Male' ) = 1" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'bRnjbxIwIRd', message: 'd2:round( 12.5 ) = 13' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'BuEcHNoD98P', message: 'd2:ceil(11.3) = 12' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'Foc3PhzoAVr', message: 'd2:count(#{age}) = 1' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'QpeF2WDjwIV', message: "d2:addDays( '2020-01-12', 5 ) = 2020-01-17" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'WJTjezLR4cJ', message: "d2:weeksBetween('2020-01-28', V{event_date} ) = 13" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'YnE4dNJVF2P', message: 'd2:zing( -2 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'bZsv2cUkbB7', message: 'd2:floor( 11.5 ) = 11' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'J8RxAbHlnO3', message: 'd2:oizp( 10000000 ) = 1' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'NT1wojA2RdT', message: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking') = dhis2isrocking" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'NUGe7EUVouK', message: "d2:substring('hello dhis 2', 6, 10) = dhis" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'Ma6nCIGrBrd', message: "d2:length( 'dhis2 rocks' ) = 11" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'RRSDsxWiUMc', message: 'd2:round( 0 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'QUe0Pks4ckc', message: 'd2:countIfValue( #{age}, 1 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'sHaE1YI0ur2', message: 'd2:zing( 1000 ) = 1000' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'EojHcBMpW7q', message: 'd2:hasValue( #{age} ) = true' } }, + { + type: 'DISPLAYTEXT', + displayText: { id: 'isP0uvT24jf', message: "d2:yearsBetween( '2010-01-28', V{event_date}) = 10" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'vQCRnX6w9pM', message: 'd2:oizp( -10000000 ) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'SYAL0GIDnxI', message: 'display age = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Xa0tKyNk5YE', message: 'org_unit = OU_559' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'JXssEpbJdO2', message: 'd2:right(#{age}, 3) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'o0LLNIYsliy', message: "d2:monthsBetween( '2020-01-28', V{event_date}) = 3" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'k07KnI11Sf4', message: 'd2:left(#{age}, 3) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'OITs4nPfMQ3', + message: "d2:split('these-are-testing-values', '-', 2) = testing", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'EzkFLDtAxCR', message: 'd2:modulus( 12 , 100 ) = 12' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'RCYEyOly0Mi', message: "d2:countIfValue( #{gender}, 'Male' ) = 1" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'bRnjbxIwIRd', message: 'd2:round( 12.5 ) = 13' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'BuEcHNoD98P', message: 'd2:ceil(11.3) = 12' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Foc3PhzoAVr', message: 'd2:count(#{age}) = 1' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'QpeF2WDjwIV', message: "d2:addDays( '2020-01-12', 5 ) = 2020-01-17" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'WJTjezLR4cJ', message: "d2:weeksBetween('2020-01-28', V{event_date} ) = 13" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'YnE4dNJVF2P', message: 'd2:zing( -2 ) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'bZsv2cUkbB7', message: 'd2:floor( 11.5 ) = 11' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'J8RxAbHlnO3', message: 'd2:oizp( 10000000 ) = 1' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'NT1wojA2RdT', + message: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking') = dhis2isrocking", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'NUGe7EUVouK', message: "d2:substring('hello dhis 2', 6, 10) = dhis" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Ma6nCIGrBrd', message: "d2:length( 'dhis2 rocks' ) = 11" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'RRSDsxWiUMc', message: 'd2:round( 0 ) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'QUe0Pks4ckc', message: 'd2:countIfValue( #{age}, 1 ) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'sHaE1YI0ur2', message: 'd2:zing( 1000 ) = 1000' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'EojHcBMpW7q', message: 'd2:hasValue( #{age} ) = true' }, + }, ], ], [ { - oZg33kd9taw: 'Male', qrur9Dvnyt5: 1000000000, occurredAt: '2020-04-30T22:00:00.000Z', + oZg33kd9taw: 'Male', + qrur9Dvnyt5: 1000000000, + occurredAt: '2020-04-30T22:00:00.000Z', }, [ - { type: 'DISPLAYTEXT', displayText: { id: 'isP0uvT24jf', message: "d2:yearsBetween( '2010-01-28', V{event_date}) = 10" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'vQCRnX6w9pM', message: 'd2:oizp( -10000000 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'SYAL0GIDnxI', message: 'display age = 1000000000' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'Xa0tKyNk5YE', message: 'org_unit = OU_559' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'JXssEpbJdO2', message: 'd2:right(#{age}, 3) = 000' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'o0LLNIYsliy', message: "d2:monthsBetween( '2020-01-28', V{event_date}) = 3" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'k07KnI11Sf4', message: 'd2:left(#{age}, 3) = 100' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'OITs4nPfMQ3', message: "d2:split('these-are-testing-values', '-', 2) = testing" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'EzkFLDtAxCR', message: 'd2:modulus( 12 , 100 ) = 12' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'RCYEyOly0Mi', message: "d2:countIfValue( #{gender}, 'Male' ) = 1" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'bRnjbxIwIRd', message: 'd2:round( 12.5 ) = 13' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'BuEcHNoD98P', message: 'd2:ceil(11.3) = 12' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'Foc3PhzoAVr', message: 'd2:count(#{age}) = 1' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'QpeF2WDjwIV', message: "d2:addDays( '2020-01-12', 5 ) = 2020-01-17" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'WJTjezLR4cJ', message: "d2:weeksBetween('2020-01-28', V{event_date} ) = 13" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'YnE4dNJVF2P', message: 'd2:zing( -2 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'bZsv2cUkbB7', message: 'd2:floor( 11.5 ) = 11' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'J8RxAbHlnO3', message: 'd2:oizp( 10000000 ) = 1' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'NT1wojA2RdT', message: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking') = dhis2isrocking" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'NUGe7EUVouK', message: "d2:substring('hello dhis 2', 6, 10) = dhis" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'Ma6nCIGrBrd', message: "d2:length( 'dhis2 rocks' ) = 11" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'RRSDsxWiUMc', message: 'd2:round( 0 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'QUe0Pks4ckc', message: 'd2:countIfValue( #{age}, 1 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'sHaE1YI0ur2', message: 'd2:zing( 1000 ) = 1000' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'EojHcBMpW7q', message: 'd2:hasValue( #{age} ) = true' } }, + { + type: 'DISPLAYTEXT', + displayText: { id: 'isP0uvT24jf', message: "d2:yearsBetween( '2010-01-28', V{event_date}) = 10" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'vQCRnX6w9pM', message: 'd2:oizp( -10000000 ) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'SYAL0GIDnxI', message: 'display age = 1000000000' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Xa0tKyNk5YE', message: 'org_unit = OU_559' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'JXssEpbJdO2', message: 'd2:right(#{age}, 3) = 000' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'o0LLNIYsliy', message: "d2:monthsBetween( '2020-01-28', V{event_date}) = 3" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'k07KnI11Sf4', message: 'd2:left(#{age}, 3) = 100' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'OITs4nPfMQ3', + message: "d2:split('these-are-testing-values', '-', 2) = testing", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'EzkFLDtAxCR', message: 'd2:modulus( 12 , 100 ) = 12' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'RCYEyOly0Mi', message: "d2:countIfValue( #{gender}, 'Male' ) = 1" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'bRnjbxIwIRd', message: 'd2:round( 12.5 ) = 13' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'BuEcHNoD98P', message: 'd2:ceil(11.3) = 12' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Foc3PhzoAVr', message: 'd2:count(#{age}) = 1' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'QpeF2WDjwIV', message: "d2:addDays( '2020-01-12', 5 ) = 2020-01-17" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'WJTjezLR4cJ', message: "d2:weeksBetween('2020-01-28', V{event_date} ) = 13" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'YnE4dNJVF2P', message: 'd2:zing( -2 ) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'bZsv2cUkbB7', message: 'd2:floor( 11.5 ) = 11' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'J8RxAbHlnO3', message: 'd2:oizp( 10000000 ) = 1' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'NT1wojA2RdT', + message: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking') = dhis2isrocking", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'NUGe7EUVouK', message: "d2:substring('hello dhis 2', 6, 10) = dhis" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Ma6nCIGrBrd', message: "d2:length( 'dhis2 rocks' ) = 11" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'RRSDsxWiUMc', message: 'd2:round( 0 ) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'QUe0Pks4ckc', message: 'd2:countIfValue( #{age}, 1 ) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'sHaE1YI0ur2', message: 'd2:zing( 1000 ) = 1000' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'EojHcBMpW7q', message: 'd2:hasValue( #{age} ) = true' }, + }, ], ], ])('where functions take place', (currentEvent, expected) => { @@ -485,8 +2280,71 @@ describe('Event rules engine effects with functions and effects', () => { describe('Event rules engine effects with functions and effects', () => { // these variables are shared between each test const constants = []; - const dataElementsInProgram = { oZg33kd9taw: { id: 'oZg33kd9taw', valueType: 'TEXT', optionSetId: 'pC3N9N77UmT' }, SWfdB5lX0fk: { id: 'SWfdB5lX0fk', valueType: 'BOOLEAN' }, qrur9Dvnyt5: { id: 'qrur9Dvnyt5', valueType: 'INTEGER' }, GieVkTxp4HH: { id: 'GieVkTxp4HH', valueType: 'NUMBER' }, vV9UWAZohSf: { id: 'vV9UWAZohSf', valueType: 'INTEGER_POSITIVE' }, eMyVanycQSC: { id: 'eMyVanycQSC', valueType: 'DATE' }, K6uUAvq500H: { id: 'K6uUAvq500H', valueType: 'TEXT', optionSetId: 'eUZ79clX7y1' }, msodh3rEMJa: { id: 'msodh3rEMJa', valueType: 'DATE' }, S33cRBsnXPo: { id: 'S33cRBsnXPo', valueType: 'ORGANISATION_UNIT' }, fWIAEtYVEGk: { id: 'fWIAEtYVEGk', valueType: 'TEXT', optionSetId: 'iDFPKpFTiVw' }, ulD2zW0TIy2: { id: 'ulD2zW0TIy2', valueType: 'FILE_RESOURCE' } }; - const programRules = [{ id: 'cq1dwUY4lVU', condition: 'true', displayName: 'testing the z-scores', programId: 'eBAyeGv0exc', programRuleActions: [{ id: 'I6pDcSm2m0g', displayContent: "d2:zScoreWFA( 20, 15, 'M' ) = ", data: "d2:zScoreWFA( 20, 15, 'M' )", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'No0T9TgN1Px', displayContent: "d2:zScoreWFH( 100, 20, 'M' ) = ", data: "d2:zScoreWFH( 100, 20, 'M' )", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'n1GUxR8fShY', displayContent: "d2:zScoreHFA( 15, 20, 'F' ) =", data: "d2:zScoreHFA( 15, 20, 'F' ) ", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'QJlZHo0GoVK', displayContent: "d2:zScoreWFH( 100, 20, 'F' ) = ", data: "d2:zScoreWFH( 100, 20, 'F' ) ", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'ItuKGBUuJgK', displayContent: "d2:zScoreWFA( 20, 15, 'F' ) = ", data: "d2:zScoreWFA( 20, 15, 'F' )", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, { id: 'uhyaCDzzivm', displayContent: "d2:zScoreHFA( 15, 20, 'M' ) =", data: "d2:zScoreHFA( 15, 20, 'M' )", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }] }]; + const dataElementsInProgram = { + oZg33kd9taw: { id: 'oZg33kd9taw', valueType: 'TEXT', optionSetId: 'pC3N9N77UmT' }, + SWfdB5lX0fk: { id: 'SWfdB5lX0fk', valueType: 'BOOLEAN' }, + qrur9Dvnyt5: { id: 'qrur9Dvnyt5', valueType: 'INTEGER' }, + GieVkTxp4HH: { id: 'GieVkTxp4HH', valueType: 'NUMBER' }, + vV9UWAZohSf: { id: 'vV9UWAZohSf', valueType: 'INTEGER_POSITIVE' }, + eMyVanycQSC: { id: 'eMyVanycQSC', valueType: 'DATE' }, + K6uUAvq500H: { id: 'K6uUAvq500H', valueType: 'TEXT', optionSetId: 'eUZ79clX7y1' }, + msodh3rEMJa: { id: 'msodh3rEMJa', valueType: 'DATE' }, + S33cRBsnXPo: { id: 'S33cRBsnXPo', valueType: 'ORGANISATION_UNIT' }, + fWIAEtYVEGk: { id: 'fWIAEtYVEGk', valueType: 'TEXT', optionSetId: 'iDFPKpFTiVw' }, + ulD2zW0TIy2: { id: 'ulD2zW0TIy2', valueType: 'FILE_RESOURCE' }, + }; + const programRules = [ + { + id: 'cq1dwUY4lVU', + condition: 'true', + displayName: 'testing the z-scores', + programId: 'eBAyeGv0exc', + programRuleActions: [ + { + id: 'I6pDcSm2m0g', + displayContent: "d2:zScoreWFA( 20, 15, 'M' ) = ", + data: "d2:zScoreWFA( 20, 15, 'M' )", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'No0T9TgN1Px', + displayContent: "d2:zScoreWFH( 100, 20, 'M' ) = ", + data: "d2:zScoreWFH( 100, 20, 'M' )", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'n1GUxR8fShY', + displayContent: "d2:zScoreHFA( 15, 20, 'F' ) =", + data: "d2:zScoreHFA( 15, 20, 'F' ) ", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'QJlZHo0GoVK', + displayContent: "d2:zScoreWFH( 100, 20, 'F' ) = ", + data: "d2:zScoreWFH( 100, 20, 'F' ) ", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'ItuKGBUuJgK', + displayContent: "d2:zScoreWFA( 20, 15, 'F' ) = ", + data: "d2:zScoreWFA( 20, 15, 'F' )", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'uhyaCDzzivm', + displayContent: "d2:zScoreHFA( 15, 20, 'M' ) =", + data: "d2:zScoreHFA( 15, 20, 'M' )", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + ], + }, + ]; const programRuleVariables = []; const orgUnit = { id: 'DiszpKrYNg8', name: 'Ngelehun CHC' }; const optionSets = {}; @@ -505,12 +2363,36 @@ describe('Event rules engine effects with functions and effects', () => { // then expect(rulesEffects).toEqual([ - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'I6pDcSm2m0g', message: "d2:zScoreWFA( 20, 15, 'M' ) = 2.47" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'No0T9TgN1Px', message: "d2:zScoreWFH( 100, 20, 'M' ) = 3.5" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'n1GUxR8fShY', message: "d2:zScoreHFA( 15, 20, 'F' ) = -3.5" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'QJlZHo0GoVK', message: "d2:zScoreWFH( 100, 20, 'F' ) = 2.84" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'ItuKGBUuJgK', message: "d2:zScoreWFA( 20, 15, 'F' ) = 2.65" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'uhyaCDzzivm', message: "d2:zScoreHFA( 15, 20, 'M' ) = -3.5" } }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'I6pDcSm2m0g', message: "d2:zScoreWFA( 20, 15, 'M' ) = 2.47" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'No0T9TgN1Px', message: "d2:zScoreWFH( 100, 20, 'M' ) = 3.5" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'n1GUxR8fShY', message: "d2:zScoreHFA( 15, 20, 'F' ) = -3.5" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'QJlZHo0GoVK', message: "d2:zScoreWFH( 100, 20, 'F' ) = 2.84" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'ItuKGBUuJgK', message: "d2:zScoreWFA( 20, 15, 'F' ) = 2.65" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'uhyaCDzzivm', message: "d2:zScoreHFA( 15, 20, 'M' ) = -3.5" }, + }, ]); }); }); @@ -519,7 +2401,11 @@ describe('Event rules engine effects with functions and effects', () => { describe('Event rules engine', () => { // these variables are shared between each test const constants = []; - const dataElementsInProgram = { oZg33kd9taw: { id: 'oZg33kd9taw', valueType: 'BOOLEAN' }, SWfdB5lX0fk: { id: 'SWfdB5lX0fk', valueType: 'TRUE_ONLY' }, qrur9Dvnyt5: { id: 'qrur9Dvnyt5', valueType: 'NUMBER' } }; + const dataElementsInProgram = { + oZg33kd9taw: { id: 'oZg33kd9taw', valueType: 'BOOLEAN' }, + SWfdB5lX0fk: { id: 'SWfdB5lX0fk', valueType: 'TRUE_ONLY' }, + qrur9Dvnyt5: { id: 'qrur9Dvnyt5', valueType: 'NUMBER' }, + }; const programRuleVariables = []; const orgUnit = { id: 'DiszpKrYNg8', name: 'Ngelehun CHC' }; const optionSets = {}; @@ -527,50 +2413,110 @@ describe('Event rules engine', () => { describe.each([ [ - [{ - id: 'cq1dwUY4lVU', - condition: 'true', - displayName: 'testing assign actions', - programId: 'eBAyeGv0exc', - programRuleActions: [ - { id: 'lJOYxhjupxz', data: 'true', dataElementId: 'oZg33kd9taw', programRuleActionType: 'ASSIGN' }, - { id: 'lJOYxhjupx1', data: 'true', dataElementId: 'SWfdB5lX0fk', programRuleActionType: 'ASSIGN' }, - { id: 'lJOYxhjupx2', data: '6', dataElementId: 'qrur9Dvnyt5', programRuleActionType: 'ASSIGN' }, - ], - }], [ - { type: 'ASSIGN', id: 'oZg33kd9taw', value: 'true', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'ASSIGN', id: 'SWfdB5lX0fk', value: 'true', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'ASSIGN', id: 'qrur9Dvnyt5', value: '6', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, + { + id: 'cq1dwUY4lVU', + condition: 'true', + displayName: 'testing assign actions', + programId: 'eBAyeGv0exc', + programRuleActions: [ + { + id: 'lJOYxhjupxz', + data: 'true', + dataElementId: 'oZg33kd9taw', + programRuleActionType: 'ASSIGN', + }, + { + id: 'lJOYxhjupx1', + data: 'true', + dataElementId: 'SWfdB5lX0fk', + programRuleActionType: 'ASSIGN', + }, + { id: 'lJOYxhjupx2', data: '6', dataElementId: 'qrur9Dvnyt5', programRuleActionType: 'ASSIGN' }, + ], + }, ], - ], [ - [{ - id: 'cq1dwUY4lVU', - condition: 'true', - displayName: 'testing assign actions', - programId: 'eBAyeGv0exc', - programRuleActions: [ - { id: 'lJOYxhjupxz', data: '', dataElementId: 'oZg33kd9taw', programRuleActionType: 'ASSIGN' }, - { id: 'lJOYxhjupx1', data: '', dataElementId: 'SWfdB5lX0fk', programRuleActionType: 'ASSIGN' }, - { id: 'lJOYxhjupx2', data: '', dataElementId: 'qrur9Dvnyt5', programRuleActionType: 'ASSIGN' }, - ], - }], [ - { type: 'ASSIGN', id: 'oZg33kd9taw', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'ASSIGN', id: 'SWfdB5lX0fk', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, - { type: 'ASSIGN', id: 'qrur9Dvnyt5', value: null, targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }, + { + type: 'ASSIGN', + id: 'oZg33kd9taw', + value: 'true', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'ASSIGN', + id: 'SWfdB5lX0fk', + value: 'true', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'ASSIGN', + id: 'qrur9Dvnyt5', + value: '6', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + ], + ], + [ + [ + { + id: 'cq1dwUY4lVU', + condition: 'true', + displayName: 'testing assign actions', + programId: 'eBAyeGv0exc', + programRuleActions: [ + { id: 'lJOYxhjupxz', data: '', dataElementId: 'oZg33kd9taw', programRuleActionType: 'ASSIGN' }, + { id: 'lJOYxhjupx1', data: '', dataElementId: 'SWfdB5lX0fk', programRuleActionType: 'ASSIGN' }, + { id: 'lJOYxhjupx2', data: '', dataElementId: 'qrur9Dvnyt5', programRuleActionType: 'ASSIGN' }, + ], + }, + ], + [ + { + type: 'ASSIGN', + id: 'oZg33kd9taw', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'ASSIGN', + id: 'SWfdB5lX0fk', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + { + type: 'ASSIGN', + id: 'qrur9Dvnyt5', + value: null, + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, + ], + ], + [ + [ + { + id: 'cq1dwUY4lVU', + condition: 'true', + displayName: 'testing assign actions', + programId: 'eBAyeGv0exc', + programRuleActions: [ + { + id: 'lJOYxhjupxz', + data: 'false', + dataElementId: 'oZg33kd9taw', + programRuleActionType: 'ASSIGN', + }, + ], + }, + ], + [ + { + type: 'ASSIGN', + id: 'oZg33kd9taw', + value: 'false', + targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT, + }, ], - ], [ - [{ - id: 'cq1dwUY4lVU', - condition: 'true', - displayName: 'testing assign actions', - programId: 'eBAyeGv0exc', - programRuleActions: [ - { id: 'lJOYxhjupxz', data: 'false', dataElementId: 'oZg33kd9taw', programRuleActionType: 'ASSIGN' }, - ], - }], - [{ type: 'ASSIGN', id: 'oZg33kd9taw', value: 'false', targetDataType: rulesEngineEffectTargetDataTypes.DATA_ELEMENT }], ], ])('where assign actions are triggered', (programRules, expected) => { test(`with given value(s): ${JSON.stringify(programRules)}`, () => { @@ -586,3 +2532,393 @@ describe('Event rules engine', () => { }); }); }); + +describe('Assign effects', () => { + // these variables are shared between each test + const constants = []; + const dataElementsInProgram = { + qrur9Dvnyt5: { id: 'qrur9Dvnyt5', valueType: 'NUMBER' }, + hrur9Dvnyt5: { id: 'hrur9Dvnyt5', valueType: 'TRUE_ONLY' }, + g67r9Dvnyt5: { id: 'g67r9Dvnyt5', valueType: 'TRUE_ONLY' }, + sfer9Dvnyt5: { id: 'sfer9Dvnyt5', valueType: 'LONG_TEXT' }, + oZg33kd9taw: { id: 'oZg33kd9taw', valueType: 'BOOLEAN' }, + hjrr9Dvnyt5: { id: 'hjrr9Dvnyt5', valueType: 'LETTER' }, + lowr9Dvnyt5: { id: 'lowr9Dvnyt5', valueType: 'PHONE_NUMBER' }, + kht29Dvnyt5: { id: 'kht29Dvnyt5', valueType: 'EMAIL' }, + hyrt9Dvnyt5: { id: 'hyrt9Dvnyt5', valueType: 'DATE' }, + loir9Dvnyt5: { id: 'loir9Dvnyt5', valueType: 'DATETIME' }, + sldkjfjfjfe: { id: 'sldkjfjfjfe', valueType: 'TIME' }, + kyt49Dvnyt5: { id: 'kyt49Dvnyt5', valueType: 'PERCENTAGE' }, + kiyu9Dvnyt5: { id: 'kiyu9Dvnyt5', valueType: 'INTEGER' }, + frt59Dvnyt5: { id: 'frt59Dvnyt5', valueType: 'INTEGER_POSITIVE' }, + jhty9Dvnyt5: { id: 'jhty9Dvnyt5', valueType: 'INTEGER_NEGATIVE' }, + jhrr9Dvnyt5: { id: 'jhrr9Dvnyt5', valueType: 'INTEGER_ZERO_OR_POSITIVE' }, + plor9Dvnyt5: { id: 'plor9Dvnyt5', valueType: 'USERNAME' }, + frg39Dvnyt5: { id: 'frg39Dvnyt5', valueType: 'COORDINATE' }, + kjyu9Dvnyt5: { id: 'kjyu9Dvnyt5', valueType: 'ORGANISATION_UNIT' }, + kjfr9Dvnyt5: { id: 'kjfr9Dvnyt5', valueType: 'AGE' }, + lqwr9Dvnyt5: { id: 'lqwr9Dvnyt5', valueType: 'URL' }, + mjus9Dvnyt5: { id: 'mjus9Dvnyt5', valueType: 'FILE_RESOURCE' }, + fgrr9Dvnyt5: { id: 'fgrr9Dvnyt5', valueType: 'IMAGE' }, + oZ3fhkd9taw: { id: 'oZ3fhkd9taw', valueType: 'UNKNOWN' }, + }; + const orgUnit = { id: 'DiszpKrYNg8', name: 'Ngelehun CHC' }; + const optionSets = {}; + const currentEvent = {}; + + test('Assign effect corner cases', () => { + const programRules = [ + { + id: 'cq1dwUY4lVU', + condition: 'true', + displayName: 'testing assign actions', + programId: 'eBAyeGv0exc', + programRuleActions: [ + { + id: 'lJOYxhjupx2', + data: "'string'", + dataElementId: 'qrur9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { id: 'lJOYxkjupx2', data: "'10'", dataElementId: 'qrur9Dvnyt5', programRuleActionType: 'ASSIGN' }, + { + id: 'lJhYxhjupxz', + data: "'string'", + dataElementId: 'oZg33kd9taw', + programRuleActionType: 'ASSIGN', + }, + { + id: 'lJfYxhjupxz', + data: "'string'", + dataElementId: 'oZ3fhkd9taw', + programRuleActionType: 'ASSIGN', + }, + { + id: 'sdfsd34567h', + data: 'value', + dataElementId: 'hrur9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'g67rgyvnyt5', + data: null, + dataElementId: 'g67r9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'fsafYxhjux2', + data: "'LONG_TEXT'", + dataElementId: 'sfer9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'o8rr9Dvnyt5', + data: "'LETTER'", + dataElementId: 'hjrr9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'lsdjlks4ffs', + data: '34535353', + dataElementId: 'lowr9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'hsjd7574jfj', + data: 'test@test.com', + dataElementId: 'kht29Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'sdf57549jco', + data: '11-11-2013', + dataElementId: 'hyrt9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'gtir9Dvnyt5', + data: '2021-05-31', + dataElementId: 'loir9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 's678jfjfjfe', + data: '11:11', + dataElementId: 'sldkjfjfjfe', + programRuleActionType: 'ASSIGN', + }, + { + id: 'sdhsfjks35f', + data: '30', + dataElementId: 'kyt49Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'kjosfjks35f', + data: '30', + dataElementId: 'kiyu9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'kjyofjks35f', + data: '30', + dataElementId: 'frt59Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'jhkj9Dvnyt5', + data: '-30', + dataElementId: 'jhty9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'hjyur9Dvnyt5', + data: '-30', + dataElementId: 'jhrr9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'lopr9Dvnyt5', + data: 'username', + dataElementId: 'plor9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'kjy39Dvnyt5', + data: "'12,4343'", + dataElementId: 'frg39Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'loiu9Dvnyt5', + data: 'ORGANISATION_UNIT', + dataElementId: 'kjyu9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'kjfr9Dvnyt5', + data: 'Invalid date', + dataElementId: 'kjfr9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'hywr9Dvnyt5', + data: 'urlPath', + dataElementId: 'lqwr9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'gt769Dvnyt5', + data: 'FILE_RESOURCE', + dataElementId: 'mjus9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + { + id: 'gt659Dvnyt5', + data: 'IMAGE', + dataElementId: 'fgrr9Dvnyt5', + programRuleActionType: 'ASSIGN', + }, + ], + }, + ]; + const programRuleVariables = []; + systemSettingsStore.set({ dateFormat: 'YYYY-MM-DD' }); + // when + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + currentEvent, + dataElements: dataElementsInProgram, + selectedOrgUnit: orgUnit, + optionSets, + }); + + // then + expect(rulesEffects).toEqual([ + { type: 'ASSIGN', id: 'qrur9Dvnyt5', value: null, targetDataType: 'dataElement' }, + { type: 'ASSIGN', id: 'qrur9Dvnyt5', value: '10', targetDataType: 'dataElement' }, + { type: 'ASSIGN', id: 'oZg33kd9taw', value: 'false', targetDataType: 'dataElement' }, + { type: 'ASSIGN', id: 'oZ3fhkd9taw', value: '', targetDataType: 'dataElement' }, + { + id: 'hrur9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: 'false', + }, + { + id: 'g67r9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: null, + }, + { + id: 'sfer9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: 'LONG_TEXT', + }, + { + id: 'hjrr9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: 'LETTER', + }, + { + id: 'lowr9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: 34535353, + }, + { + id: 'kht29Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: false, + }, + { + id: 'hyrt9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: '2013-01-01', + }, + { + id: 'loir9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: { + date: 'Invalid date', + time: 'Invalid date', + }, + }, + { + id: 'sldkjfjfjfe', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: false, + }, + { + id: 'kyt49Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: '30', + }, + { + id: 'kiyu9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: '30', + }, + { + id: 'frt59Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: '30', + }, + { + id: 'jhty9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: '-30', + }, + { + id: 'jhrr9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: '-30', + }, + { + id: 'plor9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: '', + }, + { + id: 'frg39Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: { + latitude: 2, + longitude: 434, + }, + }, + { + id: 'kjyu9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: '', + }, + { + id: 'kjfr9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: { + date: 'Invalid date', + days: 'NaN', + months: 'NaN', + years: 'NaN', + }, + }, + { + id: 'lqwr9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: false, + }, + { + id: 'mjus9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: '', + }, + { + id: 'fgrr9Dvnyt5', + targetDataType: 'dataElement', + type: 'ASSIGN', + value: '', + }, + ]); + }); + + test('Assign effect with the program rule variable id found in the content key', () => { + const programRules = [ + { + id: 'cq1dwUY4lVU', + condition: 'true', + displayName: 'testing assign actions', + programId: 'eBAyeGv0exc', + programRuleActions: [ + { + id: 'lJOYxhjupx2', + data: 'rowExpresion', + dataElementId: 'qrur9Dvnyt5', + programRuleActionType: 'ASSIGN', + content: 'Hemoglobin value lower than normal RycV5uDi66i', + }, + ], + }, + ]; + const programRuleVariables = [ + { + id: 'RycV5uDi66i', + dataElementId: 'qrur9Dvnyt5', + displayName: 'age', + programId: 'eBAyeGv0exc', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, + useNameForOptionSet: true, + }, + ]; + // when + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + currentEvent, + dataElements: dataElementsInProgram, + selectedOrgUnit: orgUnit, + optionSets, + }); + + // then + expect(rulesEffects).toEqual([ + { type: 'ASSIGN', id: 'qrur9Dvnyt5', value: 'false', targetDataType: 'dataElement' }, + ]); + }); +}); diff --git a/src/core_modules/capture-core/rules/__tests__/rulesEffectsForTrackerProgram.test.js b/src/core_modules/capture-core/rules/__tests__/rulesEffectsForTrackerProgram.test.js index bbd2514ae8..213c6c5abf 100644 --- a/src/core_modules/capture-core/rules/__tests__/rulesEffectsForTrackerProgram.test.js +++ b/src/core_modules/capture-core/rules/__tests__/rulesEffectsForTrackerProgram.test.js @@ -1,78 +1,865 @@ +import { variableSourceTypes } from '@dhis2/rules-engine-javascript'; import { rulesEngine } from '../rulesEngine'; test('expressions with d2Functions in tracker program', () => { // given const constants = []; - const trackedEntityAttributes = { w75KJ2mc4zz: { id: 'w75KJ2mc4zz', valueType: 'TEXT' }, zDhUuAYrxNC: { id: 'zDhUuAYrxNC', valueType: 'TEXT' }, cejWyOfXge6: { id: 'cejWyOfXge6', valueType: 'TEXT', optionSetId: 'pC3N9N77UmT' }, lZGmxYbs97q: { id: 'lZGmxYbs97q', valueType: 'NUMBER' } }; - const programRules = [{ - id: 'g82J3xsNer9', - condition: 'true', - displayName: 'Testing the functions!', - programId: 'IpHINAT79UW', - programRuleActions: [ - { id: 'Eeb7Ixr4Pvx', displayContent: "d2:left('dhis', 3) = ", data: "d2:left('dhis', 3)", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'lbIGJYVI57u', displayContent: 'd2:zing( -2 ) = ', data: 'd2:zing( -2 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'kwKhYpVRDyj', displayContent: "d2:monthsBetween( '2020-01-28', V{enrollment_date}) = ", data: "d2:monthsBetween( '2020-01-28', V{enrollment_date})", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'AFkfzcDf4Fs', displayContent: "d2:inOrgUnitGroup('CHC') = ", data: "d2:inOrgUnitGroup('CHC')", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'wmAQnxbs7V8', displayContent: 'd2:round( 12.5 ) = ', data: 'd2:round( 12.5 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'tFGwyDBQk3b', displayContent: 'd2:round( 0 ) = ', data: 'd2:round( 0 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'NSQV537qvyu', displayContent: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking') = ", data: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking')", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'M7vYMD5uNwD', displayContent: 'd2:ceil(11.3) = ', data: 'd2:ceil(11.3)', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'cgdUEJkqq0J', displayContent: "d2:yearsBetween( '2010-01-28', V{enrollment_date}) = ", data: "d2:yearsBetween( '2010-01-28', V{enrollment_date})", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'xZpYbFPXWG2', displayContent: 'd2:zing( 1000 ) = ', data: 'd2:zing( 1000 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'IGpzruAKVzk', displayContent: "d2:split('these-are-testing-values', '-', 2) = ", data: "d2:split('these-are-testing-values', '-', 2)", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'NLsawa3P5hc', displayContent: "d2:substring('hello dhis 2', 6, 10) = ", data: "d2:substring('hello dhis 2', 6, 10)", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'i0OgulFyVPQ', displayContent: 'd2:oizp( -10000000 ) = ', data: 'd2:oizp( -10000000 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'PqzKFmEMmuz', displayContent: "d2:right('dhis', 3) = ", data: "d2:right('dhis', 3)", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'xIUDr1lRV6N', displayContent: "d2:addDays( '2018-04-20', 100 ) = ", data: "d2:addDays( '2018-04-20', 100 )", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'RXmprywJ0Rb', displayContent: 'd2:floor( 11.5 ) = ', data: 'd2:floor( 11.5 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'cZQngI2IC1a', displayContent: "d2:length( 'dhis2 rocks' ) = ", data: "d2:length( 'dhis2 rocks' )", location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'qSe8GmlwpgZ', displayContent: "d2:weeksBetween('2020-01-28', V{enrollment_date} ) = ", data: "d2:weeksBetween('2020-01-28', V{enrollment_date} )", location: 'feedback', programRuleActionType: 'DISPLAYKEYVALUEPAIR' }, - { id: 'Tx4gHcLselM', displayContent: 'd2:oizp( 10000000 ) = ', data: 'd2:oizp( 10000000 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'f3MrrcCf1z2', displayContent: 'd2:modulus( 12 , 100 ) = ', data: 'd2:modulus( 12 , 100 )', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'Eeb7Ixr4Pv6', displayContent: 'd2:floor((5+5) / 2) = ', data: 'd2:floor((5+5) / 2)', location: 'feedback', programRuleActionType: 'DISPLAYTEXT' }, - { id: 'nKNmayYigcy', programStageId: 'PUZaKR0Jh2k', programRuleActionType: 'HIDEPROGRAMSTAGE' }, - ], - }]; - const programRulesVariables = []; + const trackedEntityAttributes = { + w75KJ2mc4zz: { id: 'w75KJ2mc4zz', valueType: 'TEXT' }, + zDhUuAYrxNC: { id: 'zDhUuAYrxNC', valueType: 'TEXT' }, + cejWyOfXge6: { id: 'cejWyOfXge6', valueType: 'TEXT', optionSetId: 'pC3N9N77UmT' }, + lZGmxYbs97q: { id: 'lZGmxYbs97q', valueType: 'NUMBER' }, + Z5z8vFQy0w0: { id: 'Z5z8vFQy0w0', valueType: 'URL' }, + TzqawmlPkI5: { id: 'TzqawmlPkI5', valueType: 'AGE' }, + f8j4XDEozvj: { id: 'f8j4XDEozvj', valueType: 'FILE_RESOURCE' }, + jBBkFuPKctq: { id: 'jBBkFuPKctq', valueType: 'ORGANISATION_UNIT' }, + A4Fg6jgWauf: { id: 'A4Fg6jgWauf', valueType: 'IMAGE' }, + CUbZcLm9LyN: { id: 'CUbZcLm9LyN', valueType: 'USERNAME' }, + p8htbyJHydl: { id: 'p8htbyJHydl', valueType: 'COORDINATE' }, + }; + const programRules = [ + { + id: 'g82J3xsNer9', + condition: 'true', + displayName: 'Testing the functions!', + programId: 'IpHINAT79UW', + programRuleActions: [ + { + id: 'Eeb7Ixr4Pvx', + displayContent: "d2:left('dhis', 3) = ", + data: "d2:left('dhis', 3)", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'lbIGJYVI57u', + displayContent: 'd2:zing( -2 ) = ', + data: 'd2:zing( -2 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'kwKhYpVRDyj', + displayContent: "d2:monthsBetween( '2020-01-28', V{enrollment_date}) = ", + data: "d2:monthsBetween( '2020-01-28', V{enrollment_date})", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'polhYpVRDyj', + displayContent: "d2:daysBetween( '2020-01-28', V{enrollment_date}) = ", + data: "d2:daysBetween( '2020-01-28', V{enrollment_date})", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'FkeGdlkYAVr', + displayContent: "d2:validatePattern('d2:daysBetween( '2020-01-28', V{enrollment_date})', 108)", + data: "d2:validatePattern(d2:daysBetween( '2020-01-28', V{enrollment_date}), 108)", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'Foc3PhzoAVr', + displayContent: 'd2:count(#{undefinedVariable}) = ', + data: 'd2:count(#{unknow})', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'FjkwPhzoAVr', + displayContent: "d2:countIfValue(#{undefinedVariable}, 'Male') = ", + data: "d2:countIfValue(#{undefinedVariable}, 'Male') = ", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'TkgrHcLselM', + displayContent: 'd2:countIfZeroPos(100) = ', + data: 'd2:countIfZeroPos(100)', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'Foc3PhzoAVr', + displayContent: 'd2:hasValue(#{undefinedVariable})', + data: 'd2:hasValue(#{undefinedVariable})', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'FoljdkeoAVr', + displayContent: "d2:validatePattern('Male', 'a')", + data: "d2:validatePattern('Male','a')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'FoljdlkYAVr', + displayContent: "d2:validatePattern('Male', 'Male')", + data: "d2:validatePattern('Male','Male')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'kpljdlkYAVr', + displayContent: 'd2:validatePattern()', + data: 'd2:validatePattern()', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'FoljdjkRAVr', + displayContent: "d2:hasUserRole('admin')", + data: "d2:hasUserRole('admin')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'FoljdkLRAVr', + displayContent: "d2:extractDataMatrixValue('batch number', 3)", + data: "d2:extractDataMatrixValue('batch number', 3)", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'FollkyLRAVr', + displayContent: "d2:extractDataMatrixValue('batch number', 'unknow')", + data: "d2:extractDataMatrixValue('batch number', 'unknow')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'lkEUdkLRAVr', + displayContent: "d2:extractDataMatrixValue('gtin', ']d2')", + data: "d2:extractDataMatrixValue('gtin', ']d2')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'FlkodkLRAVr', + displayContent: "d2:extractDataMatrixValue('batch number', ']d2')", + data: "d2:extractDataMatrixValue('batch number', ']d2')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'kuYodkLRAVr', + displayContent: "d2:extractDataMatrixValue('production date', ']Q3unknown')", + data: "d2:extractDataMatrixValue('production date', ']Q3unknown')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'kuYookLRAVr', + displayContent: "d2:extractDataMatrixValue('lot number', ']Q3703')", + data: "d2:extractDataMatrixValue('lot number', ']Q3703')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'lkyodkLRAVr', + displayContent: "d2:extractDataMatrixValue('best before date', ']Q3369')", + data: "d2:extractDataMatrixValue('best before date', ']Q3369')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'lkpyodkLRAVr', + displayContent: "d2:extractDataMatrixValue('expiration date', ']Q3369')", + data: "d2:extractDataMatrixValue('expiration date', ']Q3369')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'lkyohgyRAVr', + displayContent: "d2:extractDataMatrixValue('serial number', ']Q3369')", + data: "d2:extractDataMatrixValue('serial number', ']Q3369')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'lkyolktRAVr', + displayContent: "d2:extractDataMatrixValue('unknow key', ']d2')", + data: "d2:extractDataMatrixValue('unknow key', ']d2')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'FolpqkLRAVr', + displayContent: 'd2:lastEventDate(V{event_id})', + data: 'd2:lastEventDate(V{event_id})', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'FolkokLRAVr', + displayContent: 'd2:lastEventDate(V{enrollment_date})', + data: 'd2:lastEventDate(V{enrollment_date})', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'FolkwkLRAVr', + displayContent: 'd2:lastEventDate(#{undefinedVariable})', + data: 'd2:lastEventDate(#{undefinedVariable})', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'llokowfRAVr', + displayContent: "d2:addControlDigits('2')", + data: "d2:addControlDigits('2')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'lloksfegwAVr', + displayContent: "d2:addControlDigits('7')", + data: "d2:addControlDigits('7')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'lkyksfegwAVr', + displayContent: "d2:addControlDigits('9')", + data: "d2:addControlDigits('9')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'llolkyfRAVr', + displayContent: "d2:addControlDigits('12345678912')", + data: "d2:addControlDigits('12345678912')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'FollowfRAVr', + displayContent: 'd2:checkControlDigits(1)', + data: 'd2:checkControlDigits(1)', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'AFkfzcDf4Fs', + displayContent: "d2:inOrgUnitGroup('CHC') = ", + data: "d2:inOrgUnitGroup('CHC')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'wmAQnxbs7V8', + displayContent: 'd2:round( 12.5, 1 ) = ', + data: 'd2:round( 12.5, 1 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'tFGwyDBQk3b', + displayContent: 'd2:round( 0 ) = ', + data: 'd2:round( 0 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'NSQV537qvyu', + displayContent: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking') = ", + data: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking')", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'M7vYMD5uNwD', + displayContent: 'd2:ceil(11.3) = ', + data: 'd2:ceil(11.3)', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'cgdUEJkqq0J', + displayContent: "d2:yearsBetween( '2010-01-28', V{enrollment_date}) = ", + data: "d2:yearsBetween( '2010-01-28', V{enrollment_date})", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'xZpYbFPXWG2', + displayContent: 'd2:zing( 1000 ) = ', + data: 'd2:zing( 1000 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'IGpzruAKVzk', + displayContent: "d2:split('these-are-testing-values', '-', 2) = ", + data: "d2:split('these-are-testing-values', '-', 2)", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'NLsawa3P5hc', + displayContent: "d2:substring('hello dhis 2', -1, 10) = ", + data: "d2:substring('hello dhis 2', -1, 10)", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'i0OgulFyVPQ', + displayContent: 'd2:oizp( -10000000 ) = ', + data: 'd2:oizp( -10000000 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'PqzKFmEMmuz', + displayContent: "d2:right('dhis', 3) = ", + data: "d2:right('dhis', 3)", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'xIUDr1lRV6N', + displayContent: "d2:addDays( '2018-04-20', 100 ) = ", + data: "d2:addDays( '2018-04-20', 100 )", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'RXmprywJ0Rb', + displayContent: 'd2:floor( 11.5 ) = ', + data: 'd2:floor( 11.5 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'cZQngI2IC1a', + displayContent: "d2:length( 'dhis2 rocks' ) = ", + data: "d2:length( 'dhis2 rocks' )", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'qSe8GmlwpgZ', + displayContent: "d2:weeksBetween('2020-01-28', V{enrollment_date} ) = ", + data: "d2:weeksBetween('2020-01-28', V{enrollment_date} )", + location: 'feedback', + programRuleActionType: 'DISPLAYKEYVALUEPAIR', + }, + { + id: 'Tx4gHcLselM', + displayContent: 'd2:oizp( 10000000 ) = ', + data: 'd2:oizp( 10000000 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'f3MrrcCf1z2', + displayContent: 'd2:modulus( 12 , 100 ) = ', + data: 'd2:modulus( 12 , 100 )', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'Eeb7Ixr4Pv6', + displayContent: 'd2:floor((5+5) / 2) = ', + data: 'd2:floor((5+5) / 2)', + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { id: 'nKNmayYigcy', programStageId: 'PUZaKR0Jh2k', programRuleActionType: 'HIDEPROGRAMSTAGE' }, + { + id: 'nKNmayYigcy', + programStageSectionId: 'SWfdBhglX0fk', + programRuleActionType: 'HIDESECTION', + }, + { + id: 'lJOYxhjupxz', + data: 'true', + trackedEntityAttributeId: 'w75KJ2mc4zz', + programRuleActionType: 'ASSIGN', + }, + { + id: 'lJOdxhjupxz', + data: 'true', + trackedEntityAttributeId: 'w75KJ2mc4zz', + programRuleActionType: 'ERRORONCOMPLETE', + }, + { + id: 'ljlYxhjupxz', + data: 'true', + trackedEntityAttributeId: 'w75KJ2mc4zz', + programRuleActionType: 'WARNINGONCOMPLETE', + }, + { + id: 'lljoxhjupxz', + data: 'true', + trackedEntityAttributeId: 'w75KJ2mc4zz', + programRuleActionType: 'SETMANDATORYFIELD', + }, + { + id: 'lgjoxhjupxz', + data: 'true', + optionGroupId: 'w75KJ2mc4zz', + programRuleActionType: 'HIDEOPTIONGROUP', + }, + { + id: 'lljljhjupxz', + data: 'true', + optionGroupId: 'w75KJ2mc4zz', + programRuleActionType: 'SHOWOPTIONGROUP', + }, + { id: 'hwgyO59SSxu', trackedEntityAttributeId: 'zDhUuAYrxNC', programRuleActionType: 'HIDEFIELD' }, + { id: 'khygyO59Sxu', trackedEntityAttributeId: 'unknown', programRuleActionType: 'HIDEFIELD' }, + { id: 'khtgyO5SSxu', trackedEntityAttributeId: 'Z5z8vFQy0w0', programRuleActionType: 'HIDEFIELD' }, + { id: 'hwgyOgy4Sxu', trackedEntityAttributeId: 'TzqawmlPkI5', programRuleActionType: 'HIDEFIELD' }, + { id: 'hwgyloeSSxu', trackedEntityAttributeId: 'f8j4XDEozvj', programRuleActionType: 'HIDEFIELD' }, + { id: 'lkoeO59SSxu', trackedEntityAttributeId: 'jBBkFuPKctq', programRuleActionType: 'HIDEFIELD' }, + { id: 'poe4O59SSxu', trackedEntityAttributeId: 'A4Fg6jgWauf', programRuleActionType: 'HIDEFIELD' }, + { id: 'gtyyO59SSxu', trackedEntityAttributeId: 'CUbZcLm9LyN', programRuleActionType: 'HIDEFIELD' }, + { id: 'kopyO59SSxu', trackedEntityAttributeId: 'p8htbyJHydl', programRuleActionType: 'HIDEFIELD' }, + { id: 'dsfsdfsw4rh', dataElementId: 'unknown', programRuleActionType: 'HIDEFIELD' }, + { + id: 'khy8GmlwpgZ', + displayContent: "d2:weeksBetween('2020-01-28', V{unknown} ) = ", + data: "d2:weeksBetween('2020-01-28', V{unknown} )", + location: 'feedback', + programRuleActionType: 'DISPLAYKEYVALUEPAIR', + }, + ], + }, + ]; + const programRuleVariables = [ + { + id: 'DoRHHfNPccb', + trackedEntityAttributeId: 'w75KJ2mc4zz', + displayName: 'INFECTION_SOURCE', + programId: 'IpHINAT79UW', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: false, + }, + { + id: 'lokHHfNPccb', + trackedEntityAttributeId: 'w75KJ2mc4zz', + displayName: 'INFECTION_SOURCE', + programId: 'IpHINAT79UW', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: false, + }, + { + id: 'Zj7UnCAulEk', + displayName: 'Zj7UnCAulEk', + programRuleVariableSourceType: variableSourceTypes.TEI_ATTRIBUTE, + trackedEntityAttributeId: 'w75KJ2mc4zz', + programId: 'IpHINAT79UW', + }, + ]; const optionSets = {}; - const teiValues = {}; + const teiValues = { + zDhUuAYrxNC: 'value', + Z5z8vFQy0w0: 'https://www.google.com/', + TzqawmlPkI5: '30', + f8j4XDEozvj: 'FILE_RESOURCE', + jBBkFuPKctq: 'ORGANISATION_UNIT', + A4Fg6jgWauf: 'IMAGE', + CUbZcLm9LyN: 'USERNAME', + p8htbyJHydl: { latitude: '12.4353', longitude: '67.34534' }, + }; const orgUnit = { id: 'DiszpKrYNg8', name: 'Ngelehun CHC' }; - const enrollmentData = { enrolledAt: '2020-05-14T22:00:00.000Z' }; + const enrollmentData = { enrolledAt: '2020-05-14T10:00:00.000Z' }; + const currentEvent = { + occurredAt: '2020-07-14T10:00:00.000Z', + da1Id: 'currentEventText', + dueDate: '2021-05-31T09:51:38.134', + enrollmentId: 'vVtmDlsu3me', + enrollmentStatus: 'ACTIVE', + eventDate: '2021-05-31T00:00:00.000', + eventId: 'BxGzDJK3JqN', + orgUnitId: 'DiszpKrYNg8', + orgUnitName: 'Ngelehun CHC', + programId: 'IpHINAT79UW', + programStageId: 'A03MvHHogjR', + status: 'ACTIVE', + trackedEntityInstanceId: 'vCGpQAWG17I', + }; // when const rulesEffects = rulesEngine.getProgramRuleEffects({ - programRulesContainer: { programRulesVariables, programRules, constants }, + programRulesContainer: { programRuleVariables, programRules, constants }, trackedEntityAttributes, selectedEntity: teiValues, selectedEnrollment: enrollmentData, selectedOrgUnit: orgUnit, optionSets, + currentEvent, }); // then expect(rulesEffects).toEqual([ - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'Eeb7Ixr4Pvx', message: "d2:left('dhis', 3) = dhi" } }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Eeb7Ixr4Pvx', message: "d2:left('dhis', 3) = dhi" }, + }, { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'lbIGJYVI57u', message: 'd2:zing( -2 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'kwKhYpVRDyj', message: "d2:monthsBetween( '2020-01-28', V{enrollment_date}) = 3" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'AFkfzcDf4Fs', message: "d2:inOrgUnitGroup('CHC') = " } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'wmAQnxbs7V8', message: 'd2:round( 12.5 ) = 13' } }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'kwKhYpVRDyj', message: "d2:monthsBetween( '2020-01-28', V{enrollment_date}) = 3" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'polhYpVRDyj', message: "d2:daysBetween( '2020-01-28', V{enrollment_date}) = 107" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'FkeGdlkYAVr', + message: "d2:validatePattern('d2:daysBetween( '2020-01-28', V{enrollment_date})', 108) ", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Foc3PhzoAVr', message: 'd2:count(#{undefinedVariable}) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'FjkwPhzoAVr', message: "d2:countIfValue(#{undefinedVariable}, 'Male') = " }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'TkgrHcLselM', message: 'd2:countIfZeroPos(100) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Foc3PhzoAVr', message: 'd2:hasValue(#{undefinedVariable}) ' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'FoljdkeoAVr', message: "d2:validatePattern('Male', 'a') " }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'FoljdlkYAVr', message: "d2:validatePattern('Male', 'Male') true" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'kpljdlkYAVr', message: 'd2:validatePattern() ' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'FoljdjkRAVr', message: "d2:hasUserRole('admin') " }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'FoljdkLRAVr', + message: "d2:extractDataMatrixValue('batch number', 3) Incomplete DataMatrix input", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'FollkyLRAVr', + message: + "d2:extractDataMatrixValue('batch number', 'unknow') Unsupported GS1 identifier: {gs1Identifier}", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'lkEUdkLRAVr', + message: "d2:extractDataMatrixValue('gtin', ']d2') ", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'FlkodkLRAVr', + message: "d2:extractDataMatrixValue('batch number', ']d2') ", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'kuYodkLRAVr', + message: "d2:extractDataMatrixValue('production date', ']Q3unknown') ", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'kuYookLRAVr', + message: "d2:extractDataMatrixValue('lot number', ']Q3703') ", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'lkyodkLRAVr', + message: "d2:extractDataMatrixValue('best before date', ']Q3369') ", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'lkpyodkLRAVr', + message: "d2:extractDataMatrixValue('expiration date', ']Q3369') ", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'lkyohgyRAVr', + message: "d2:extractDataMatrixValue('serial number', ']Q3369') ", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'lkyolktRAVr', + message: "d2:extractDataMatrixValue('unknow key', ']d2') ", + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'FolpqkLRAVr', message: 'd2:lastEventDate(V{event_id}) 2020-07-14' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'FolkokLRAVr', message: 'd2:lastEventDate(V{enrollment_date}) ' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'FolkwkLRAVr', message: 'd2:lastEventDate(#{undefinedVariable}) ' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'llokowfRAVr', message: "d2:addControlDigits('2') 261" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'lloksfegwAVr', message: "d2:addControlDigits('7') 709" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'lkyksfegwAVr', message: "d2:addControlDigits('9') 950" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'llolkyfRAVr', message: "d2:addControlDigits('12345678912') 1234567891200" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'FollowfRAVr', message: 'd2:checkControlDigits(1) 1' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'AFkfzcDf4Fs', message: "d2:inOrgUnitGroup('CHC') = " }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'wmAQnxbs7V8', message: 'd2:round( 12.5, 1 ) = 12.5' }, + }, { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'tFGwyDBQk3b', message: 'd2:round( 0 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'NSQV537qvyu', message: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking') = dhis2isrocking" } }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { + id: 'NSQV537qvyu', + message: "d2:concatenate( 'dh', 'is', 2, 'is', 'rocking') = dhis2isrocking", + }, + }, { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'M7vYMD5uNwD', message: 'd2:ceil(11.3) = 12' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'cgdUEJkqq0J', message: "d2:yearsBetween( '2010-01-28', V{enrollment_date}) = 10" } }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'cgdUEJkqq0J', message: "d2:yearsBetween( '2010-01-28', V{enrollment_date}) = 10" }, + }, { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'xZpYbFPXWG2', message: 'd2:zing( 1000 ) = 1000' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'IGpzruAKVzk', message: "d2:split('these-are-testing-values', '-', 2) = testing" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'NLsawa3P5hc', message: "d2:substring('hello dhis 2', 6, 10) = dhis" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'i0OgulFyVPQ', message: 'd2:oizp( -10000000 ) = 0' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'PqzKFmEMmuz', message: "d2:right('dhis', 3) = his" } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'xIUDr1lRV6N', message: "d2:addDays( '2018-04-20', 100 ) = 2018-07-29" } }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'IGpzruAKVzk', message: "d2:split('these-are-testing-values', '-', 2) = testing" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'NLsawa3P5hc', message: "d2:substring('hello dhis 2', -1, 10) = " }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'i0OgulFyVPQ', message: 'd2:oizp( -10000000 ) = 0' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'PqzKFmEMmuz', message: "d2:right('dhis', 3) = his" }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'xIUDr1lRV6N', message: "d2:addDays( '2018-04-20', 100 ) = 2018-07-29" }, + }, { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'RXmprywJ0Rb', message: 'd2:floor( 11.5 ) = 11' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'cZQngI2IC1a', message: "d2:length( 'dhis2 rocks' ) = 11" } }, - { type: 'DISPLAYKEYVALUEPAIR', id: 'feedback', displayKeyValuePair: { id: 'qSe8GmlwpgZ', key: "d2:weeksBetween('2020-01-28', V{enrollment_date} ) = ", value: '15' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'Tx4gHcLselM', message: 'd2:oizp( 10000000 ) = 1' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'f3MrrcCf1z2', message: 'd2:modulus( 12 , 100 ) = 12' } }, - { type: 'DISPLAYTEXT', id: 'feedback', displayText: { id: 'Eeb7Ixr4Pv6', message: 'd2:floor((5+5) / 2) = 5' } }, // check double parentheses + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'cZQngI2IC1a', message: "d2:length( 'dhis2 rocks' ) = 11" }, + }, + { + type: 'DISPLAYKEYVALUEPAIR', + id: 'feedback', + displayKeyValuePair: { + id: 'qSe8GmlwpgZ', + key: "d2:weeksBetween('2020-01-28', V{enrollment_date} ) = ", + value: '15', + }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Tx4gHcLselM', message: 'd2:oizp( 10000000 ) = 1' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'f3MrrcCf1z2', message: 'd2:modulus( 12 , 100 ) = 12' }, + }, + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Eeb7Ixr4Pv6', message: 'd2:floor((5+5) / 2) = 5' }, + }, { type: 'HIDEPROGRAMSTAGE', id: 'PUZaKR0Jh2k' }, + { id: 'SWfdBhglX0fk', type: 'HIDESECTION' }, + { id: 'w75KJ2mc4zz', targetDataType: 'trackedEntityAttribute', type: 'ASSIGN', value: 'true' }, + { + id: 'w75KJ2mc4zz', + message: ' true', + targetDataType: 'trackedEntityAttribute', + type: 'ERRORONCOMPLETE', + }, + { + id: 'w75KJ2mc4zz', + message: ' true', + targetDataType: 'trackedEntityAttribute', + type: 'WARNINGONCOMPLETE', + }, + { + id: 'w75KJ2mc4zz', + targetDataType: 'trackedEntityAttribute', + type: 'SETMANDATORYFIELD', + }, + { + content: undefined, + id: 'zDhUuAYrxNC', + targetDataType: 'trackedEntityAttribute', + type: 'HIDEFIELD', + hadValue: true, + name: undefined, + }, + { + content: undefined, + id: 'unknown', + targetDataType: 'trackedEntityAttribute', + type: 'HIDEFIELD', + }, + { + content: undefined, + id: 'Z5z8vFQy0w0', + targetDataType: 'trackedEntityAttribute', + type: 'HIDEFIELD', + hadValue: true, + name: undefined, + }, + { + content: undefined, + id: 'TzqawmlPkI5', + targetDataType: 'trackedEntityAttribute', + type: 'HIDEFIELD', + hadValue: true, + name: undefined, + }, + { + content: undefined, + id: 'f8j4XDEozvj', + targetDataType: 'trackedEntityAttribute', + type: 'HIDEFIELD', + }, + { + content: undefined, + id: 'jBBkFuPKctq', + targetDataType: 'trackedEntityAttribute', + type: 'HIDEFIELD', + }, + { + content: undefined, + id: 'A4Fg6jgWauf', + targetDataType: 'trackedEntityAttribute', + type: 'HIDEFIELD', + }, + { + content: undefined, + id: 'CUbZcLm9LyN', + targetDataType: 'trackedEntityAttribute', + type: 'HIDEFIELD', + hadValue: true, + name: undefined, + }, + { + content: undefined, + id: 'p8htbyJHydl', + targetDataType: 'trackedEntityAttribute', + type: 'HIDEFIELD', + hadValue: true, + name: undefined, + }, + { + content: undefined, + id: 'unknown', + targetDataType: 'dataElement', + type: 'HIDEFIELD', + }, + { + displayKeyValuePair: { + id: 'khy8GmlwpgZ', + key: "d2:weeksBetween('2020-01-28', V{unknown} ) = ", + value: '', + }, + id: 'feedback', + type: 'DISPLAYKEYVALUEPAIR', + }, ]); }); diff --git a/src/core_modules/capture-core/rules/__tests__/rulesEngine.test.js b/src/core_modules/capture-core/rules/__tests__/rulesEngine.test.js new file mode 100644 index 0000000000..4a0f04e813 --- /dev/null +++ b/src/core_modules/capture-core/rules/__tests__/rulesEngine.test.js @@ -0,0 +1,717 @@ +import { variableSourceTypes } from '@dhis2/rules-engine-javascript'; +import { rulesEngine } from '../rulesEngine'; + +describe('Rules engine', () => { + const constants = []; + const dataElementsInProgram = {}; + const programRuleVariables = []; + const orgUnit = { id: 'DiszpKrYNg8', name: 'Ngelehun CHC' }; + const optionSets = {}; + const currentEvent = {}; + + test('Rules engine without programRules', () => { + // when + const programRules = undefined; + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + currentEvent, + dataElements: dataElementsInProgram, + selectedOrgUnit: orgUnit, + optionSets, + }); + + // then + expect(rulesEffects).toEqual([]); + }); + + test('Program rule without an condition', () => { + // when + const programRules = [ + { + id: 'GC4gpdoSD4r', + condition: undefined, + description: 'Show warning if hemoglobin is dangerously low', + displayName: 'Hemoglobin warning', + programId: 'lxAQ7Zs9VYR', + programRuleActions: [ + { + id: 'suS9GnraCx1', + content: 'Hemoglobin value lower than normal', + displayContent: 'Hemoglobin value lower than normal', + dataElementId: 'vANAXwtLwcT', + programRuleActionType: 'SHOWWARNING', + }, + ], + }, + ]; + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + currentEvent, + dataElements: dataElementsInProgram, + selectedOrgUnit: orgUnit, + optionSets, + }); + + // then + expect(rulesEffects).toEqual([]); + }); + + test('Program rule condition error handeling', () => { + const programRules = [ + { + id: 'GC4gpdoSD4r', + condition: 'i am a condition with error', + description: 'Show warning if hemoglobin is dangerously low', + displayName: 'Hemoglobin warning', + programId: 'lxAQ7Zs9VYR', + programRuleActions: [ + { + id: 'suS9GnraCx1', + content: 'Hemoglobin value lower than normal', + displayContent: 'Hemoglobin value lower than normal', + dataElementId: 'vANAXwtLwcT', + programRuleActionType: 'SHOWWARNING', + }, + ], + }, + ]; + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + currentEvent, + dataElements: dataElementsInProgram, + selectedOrgUnit: orgUnit, + optionSets, + }); + + // then + expect(rulesEffects).toEqual([]); + }); + + test('user roles', () => { + rulesEngine.setSelectedUserRoles(['ADMIN']); + expect(rulesEngine.userRoles).toEqual(['ADMIN']); + }); + + test('SHOW_WARNING program rule effect with a general target', () => { + const programRules = [ + { + id: 'GC4gpdoSD4r', + condition: 'true', + description: 'Show warning if hemoglobin is dangerously low', + displayName: 'Hemoglobin warning', + programId: 'lxAQ7Zs9VYR', + programRuleActions: [ + { + id: 'SWfdB5lX0fk', + content: 'Hemoglobin value lower than normal', + displayContent: 'Hemoglobin value lower than normal', + programRuleActionType: 'SHOWWARNING', + }, + ], + }, + ]; + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + currentEvent, + dataElements: dataElementsInProgram, + selectedOrgUnit: orgUnit, + optionSets, + }); + + // then + expect(rulesEffects).toEqual([ + { + id: 'general', + type: 'SHOWWARNING', + warning: { + id: 'SWfdB5lX0fk', + message: 'Hemoglobin value lower than normal ', + }, + }, + ]); + }); + + test('SHOW_ERROR program rule effect with a general target', () => { + const programRules = [ + { + id: 'GC4gpdoSD4r', + condition: 'true', + description: 'Show error if hemoglobin is dangerously low', + displayName: 'Hemoglobin error', + programId: 'lxAQ7Zs9VYR', + programRuleActions: [ + { + id: 'SWfdB5lX0fk', + content: 'Hemoglobin value lower than normal', + displayContent: 'Hemoglobin value lower than normal', + programRuleActionType: 'SHOWERROR', + }, + ], + }, + ]; + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + currentEvent, + dataElements: dataElementsInProgram, + selectedOrgUnit: orgUnit, + optionSets, + }); + + // then + expect(rulesEffects).toEqual([ + { + id: 'general', + type: 'SHOWERROR', + error: { + id: 'SWfdB5lX0fk', + message: 'Hemoglobin value lower than normal ', + }, + }, + ]); + }); + + test('HIDE_PROGRAM_STAGE program rule effect corner case. The action does not have a program stage id', () => { + const programRules = [ + { + id: 'GC4gpdoSD4r', + condition: 'true', + description: 'Show warning if hemoglobin is dangerously low', + displayName: 'Hemoglobin warning', + programId: 'lxAQ7Zs9VYR', + programRuleActions: [ + { + id: 'nKNmayYigcy', + programRuleActionType: 'HIDEPROGRAMSTAGE', + }, + ], + }, + ]; + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + currentEvent, + dataElements: dataElementsInProgram, + selectedOrgUnit: orgUnit, + optionSets, + }); + + // then + expect(rulesEffects).toEqual([]); + }); + + test('HIDE_SECTION program rule effect corner case. The action does not have a program stage section id', () => { + const programRules = [ + { + id: 'GC4gpdoSD4r', + condition: 'true', + description: 'Show warning if hemoglobin is dangerously low', + displayName: 'Hemoglobin warning', + programId: 'lxAQ7Zs9VYR', + programRuleActions: [ + { + id: 'nKNmayYigcy', + programRuleActionType: 'HIDESECTION', + }, + ], + }, + ]; + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + currentEvent, + dataElements: dataElementsInProgram, + selectedOrgUnit: orgUnit, + optionSets, + }); + + // then + expect(rulesEffects).toEqual([]); + }); +}); + +describe('Program Rule Variables corner cases', () => { + const constants = []; + const orgUnit = { id: 'DiszpKrYNg8', name: 'Ngelehun CHC' }; + const optionSets = {}; + + test('without currentEvent and without otherEvents', () => { + // given + const programRules = [ + { + id: 'g82J3xsNer9', + condition: 'true', + displayName: 'Testing the variables source type', + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'Eeb7Ixr4Pvx', + displayContent: "d2:left('dhis', 3) = ", + data: "d2:left('dhis', 3)", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'ElktIxr4Pvx', + displayContent: "d2:left('dhis', 3) = ", + data: "d2:left('dhis', 3)", + content: 'event_status', + programRuleActionType: 'ASSIGN', + }, + ], + }, + ]; + const dataElementsInProgram = { + f8j4XDEozvj: { id: 'f8j4XDEozvj', valueType: 'INTEGER', optionSetId: undefined }, + }; + const currentEvent = undefined; + const programRuleVariables = [ + { + id: 'DoRHHfNPccb', + dataElementId: 'f8j4XDEozvj', + displayName: 'INFECTION_SOURCE', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: false, + }, + { + id: 'lokHHfNPccb', + dataElementId: 'f8j4XDEozvj', + displayName: 'INFECTION_SOURCE', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_PREVIOUS_EVENT, + useNameForOptionSet: false, + }, + { + id: 'DolgHfNPccb', + dataElementId: 'f8j4XDEozvj', + displayName: 'INFECTION_SOURCE', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM, + useNameForOptionSet: false, + }, + ]; + + // when + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + selectedOrgUnit: orgUnit, + optionSets, + currentEvent, + dataElements: dataElementsInProgram, + }); + + // then + expect(rulesEffects).toEqual([ + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Eeb7Ixr4Pvx', message: "d2:left('dhis', 3) = dhi" }, + }, + ]); + }); + + test('without currentEvent and with otherEvents', () => { + // given + const programRules = [ + { + id: 'g82J3xsNer9', + condition: 'true', + displayName: 'Testing the variables source type', + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'Eeb7Ixr4Pvx', + displayContent: "d2:left('dhis', 3) = ", + data: "d2:left('dhis', 3)", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'ElktIxr4Pvx', + displayContent: "d2:left('dhis', 3) = ", + data: "d2:left('dhis', 3)", + content: 'event_status', + programRuleActionType: 'ASSIGN', + }, + ], + }, + ]; + const dataElementsInProgram = { + f8j4XDEozvj: { id: 'f8j4XDEozvj', valueType: 'INTEGER', optionSetId: undefined }, + }; + const currentEvent = undefined; + const otherEvents = [ + { + da1Id: 'otherEventText', + dueDate: '2021-05-31T09:51:38.134', + enrollmentId: 'vVtmDlsu3me', + enrollmentStatus: 'ACTIVE', + eventDate: '2021-05-31T00:00:00.000', + eventId: 'BxGzDJK3JqN', + orgUnitId: 'DiszpKrYNg8', + orgUnitName: 'Ngelehun CHC', + programId: 'IpHINAT79UW', + programStageId: 'A03MvHHogjR', + status: 'ACTIVE', + trackedEntityInstanceId: 'vCGpQAWG17I', + occurredAt: '2021-05-31T00:00:00.000', + }, + ]; + const programRuleVariables = [ + { + id: 'lokHHfNPccb', + dataElementId: 'f8j4XDEozvj', + displayName: 'INFECTION_SOURCE', + programId: 'PNClHaZARtz', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_PREVIOUS_EVENT, + useNameForOptionSet: false, + }, + ]; + + // when + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + selectedOrgUnit: orgUnit, + optionSets, + currentEvent, + dataElements: dataElementsInProgram, + otherEvents, + }); + + // then + expect(rulesEffects).toEqual([ + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Eeb7Ixr4Pvx', message: "d2:left('dhis', 3) = dhi" }, + }, + ]); + }); + + test('with currentEvent and with otherEvents', () => { + // given + const programRules = [ + { + id: 'g82J3xsNer9', + condition: 'true', + displayName: 'Testing the variables source type', + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'Eeb7Ixr4Pvx', + displayContent: "d2:left('dhis', 3) = ", + data: "d2:left('dhis', 3)", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'ElktIxr4Pvx', + displayContent: "d2:left('dhis', 3) = ", + data: "d2:left('dhis', 3)", + content: 'event_status', + programRuleActionType: 'ASSIGN', + }, + ], + }, + ]; + const dataElementsInProgram = { + f8j4XDEozvj: { id: 'f8j4XDEozvj', valueType: 'INTEGER', optionSetId: undefined }, + GieVkTxp4HH: { id: 'GieVkTxp4HH', valueType: 'NUMBER', optionSetId: undefined }, + }; + const currentEvent = { + occurredAt: '2020-07-14T22:00:00.000Z', + da1Id: 'currentEventText', + dueDate: '2021-05-31T09:51:38.134', + enrollmentId: 'vVtmDlsu3me', + enrollmentStatus: 'ACTIVE', + eventDate: '2021-05-31T00:00:00.000', + eventId: 'BlgrDJK3JqN', + orgUnitId: 'DiszpKrYNg8', + orgUnitName: 'Ngelehun CHC', + programId: 'IpHINAT79UW', + programStageId: 'A03MvHHogjR', + status: 'ACTIVE', + trackedEntityInstanceId: 'vCsfsAWG17I', + }; + const otherEvents = [ + { + da1Id: 'otherEventText', + dueDate: '2021-05-31T09:51:38.134', + enrollmentId: 'vVtmDlsu3me', + enrollmentStatus: 'ACTIVE', + eventDate: '2021-05-31T00:00:00.000', + eventId: 'BxGzDJK3JqN', + orgUnitId: 'DiszpKrYNg8', + orgUnitName: 'Ngelehun CHC', + programId: 'IpHINAT79UW', + programStageId: 'A03MvHHogjR', + status: 'ACTIVE', + trackedEntityInstanceId: 'vCGpQAWG17I', + occurredAt: '2021-05-31T00:00:00.000', + }, + ]; + const programRuleVariables = [ + { + id: 'lokHHfNPccb', + dataElementId: 'f8j4XDEozvj', + displayName: 'INFECTION_SOURCE', + programId: 'IpHINAT79UW', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_PREVIOUS_EVENT, + useNameForOptionSet: false, + }, + { + id: 'ZghUnCAulEk.GieVkTxp4HH', + displayName: 'ZghUnCAulEk.GieVkTxp4HH', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM_STAGE, + programStageId: 'A03MvHHogjR', + dataElementId: 'GieVkTxp4HH', + programId: 'IpHINAT79UW', + }, + { + id: 'Zj7UnsdhlEk.GieVkTxp4HH', + displayName: 'Zj7UnsdhlEk.GieVkTxp4HH', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM_STAGE, + dataElementId: 'GieVkTxp4HH', + programId: 'IpHINAT79UW', + }, + { + id: 'Zj7luCAulEk.GieVkTxp4HH', + displayName: 'Zj7luCAulEk.GieVkTxp4HH', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM_STAGE, + programStageId: 'AsdfMvHHgjR', + dataElementId: 'GieVkTxp4HH', + programId: 'IpHINAT79UW', + }, + ]; + + // when + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + selectedOrgUnit: orgUnit, + optionSets, + currentEvent, + dataElements: dataElementsInProgram, + otherEvents, + }); + + // then + expect(rulesEffects).toEqual([ + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Eeb7Ixr4Pvx', message: "d2:left('dhis', 3) = dhi" }, + }, + ]); + }); + + test('currentEvent without occurredAt date', () => { + // given + const programRules = [ + { + id: 'g82J3xsNer9', + condition: 'true', + displayName: 'Testing the variables source type', + programId: 'PNClHaZARtz', + programRuleActions: [ + { + id: 'Eeb7Ixr4Pvx', + displayContent: "d2:left('dhis', 3) = ", + data: "d2:left('dhis', 3)", + location: 'feedback', + programRuleActionType: 'DISPLAYTEXT', + }, + { + id: 'ElktIxr4Pvx', + displayContent: "d2:left('dhis', 3) = ", + data: "d2:left('dhis', 3)", + content: 'event_status', + programRuleActionType: 'ASSIGN', + }, + ], + }, + ]; + const dataElementsInProgram = { + f8j4XDEozvj: { id: 'f8j4XDEozvj', valueType: 'INTEGER', optionSetId: undefined }, + GieVkTxp4HH: { id: 'GieVkTxp4HH', valueType: 'NUMBER', optionSetId: undefined }, + }; + const currentEvent = { + da1Id: 'currentEventText', + dueDate: '2021-05-31T09:51:38.134', + enrollmentId: 'vVtmDlsu3me', + enrollmentStatus: 'ACTIVE', + eventDate: '2021-05-31T00:00:00.000', + eventId: 'BlgrDJK3JqN', + orgUnitId: 'DiszpKrYNg8', + orgUnitName: 'Ngelehun CHC', + programId: 'IpHINAT79UW', + programStageId: 'A03MvHHogjR', + status: 'ACTIVE', + trackedEntityInstanceId: 'vCsfsAWG17I', + }; + const otherEvents = [ + { + da1Id: 'otherEventText', + dueDate: '2021-05-31T09:51:38.134', + enrollmentId: 'vVtmDlsu3me', + enrollmentStatus: 'ACTIVE', + eventDate: '2021-05-31T00:00:00.000', + eventId: 'BxGzDJK3JqN', + orgUnitId: 'DiszpKrYNg8', + orgUnitName: 'Ngelehun CHC', + programId: 'IpHINAT79UW', + programStageId: 'A03MvHHogjR', + status: 'ACTIVE', + trackedEntityInstanceId: 'vCGpQAWG17I', + occurredAt: '2021-05-31T00:00:00.000', + }, + ]; + const programRuleVariables = [ + { + id: 'lokHHfNPccb', + dataElementId: 'f8j4XDEozvj', + displayName: 'INFECTION_SOURCE', + programId: 'IpHINAT79UW', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_PREVIOUS_EVENT, + useNameForOptionSet: false, + }, + { + id: 'ZghUnCAulEk.GieVkTxp4HH', + displayName: 'ZghUnCAulEk.GieVkTxp4HH', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM_STAGE, + programStageId: 'A03MvHHogjR', + dataElementId: 'GieVkTxp4HH', + programId: 'IpHINAT79UW', + }, + { + id: 'Zj7UnsdhlEk.GieVkTxp4HH', + displayName: 'Zj7UnsdhlEk.GieVkTxp4HH', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM_STAGE, + dataElementId: 'GieVkTxp4HH', + programId: 'IpHINAT79UW', + }, + { + id: 'Zj7luCAulEk.GieVkTxp4HH', + displayName: 'Zj7luCAulEk.GieVkTxp4HH', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_NEWEST_EVENT_PROGRAM_STAGE, + programStageId: 'AsdfMvHHgjR', + dataElementId: 'GieVkTxp4HH', + programId: 'IpHINAT79UW', + }, + ]; + + // when + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + selectedOrgUnit: orgUnit, + optionSets, + currentEvent, + dataElements: dataElementsInProgram, + otherEvents, + }); + + // then + expect(rulesEffects).toEqual([ + { + type: 'DISPLAYTEXT', + id: 'feedback', + displayText: { id: 'Eeb7Ixr4Pvx', message: "d2:left('dhis', 3) = dhi" }, + }, + ]); + }); + + test('programRuleVariable with a value type not supported', () => { + // given + const trackedEntityAttributes = { + w75KJ2mc4zz: { id: 'w75KJ2mc4zz', valueType: 'UNKNOWN' }, + }; + const programRules = []; + const currentEvent = {}; + const programRuleVariables = [ + { + id: 'DoRHHfNPccb', + displayName: 'INFECTION_SOURCE', + trackedEntityAttributeId: 'w75KJ2mc4zz', + programId: 'IpHINAT79UW', + programRuleVariableSourceType: variableSourceTypes.TEI_ATTRIBUTE, + useNameForOptionSet: false, + }, + ]; + + // when + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + selectedOrgUnit: orgUnit, + optionSets, + currentEvent, + trackedEntityAttributes, + }); + + // then + expect(rulesEffects).toEqual([]); + }); + + test('HIDEFIELD effect when the form values are empty', () => { + // given + const programRules = [ + { + id: 'g82J3xsNer9', + condition: 'true', + displayName: 'Testing the variables source type', + programId: 'PNClHaZARtz', + programRuleActions: [ + { id: 'hwgyO59SSxu', trackedEntityAttributeId: 'zDhUuAYrxNC', programRuleActionType: 'HIDEFIELD' }, + ], + }, + ]; + const trackedEntityAttributes = { + zDhUuAYrxNC: { id: 'zDhUuAYrxNC', valueType: 'TEXT' }, + }; + const programRuleVariables = [ + { + id: 'DoRHHfNPccb', + trackedEntityAttributeId: 'w75KJ2mc4zz', + displayName: 'INFECTION_SOURCE', + programId: 'IpHINAT79UW', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: false, + }, + { + id: 'lokHHfNPccb', + trackedEntityAttributeId: 'w75KJ2mc4zz', + displayName: 'INFECTION_SOURCE', + programId: 'IpHINAT79UW', + programRuleVariableSourceType: variableSourceTypes.DATAELEMENT_CURRENT_EVENT, + useNameForOptionSet: false, + }, + { + id: 'Zj7UnCAulEk', + displayName: 'Zj7UnCAulEk', + programRuleVariableSourceType: variableSourceTypes.TEI_ATTRIBUTE, + trackedEntityAttributeId: 'w75KJ2mc4zz', + programId: 'IpHINAT79UW', + }, + ]; + const teiValues = {}; + const enrollmentData = { enrolledAt: '2020-05-14T22:00:00.000Z' }; + const currentEvent = undefined; + + // when + const rulesEffects = rulesEngine.getProgramRuleEffects({ + programRulesContainer: { programRuleVariables, programRules, constants }, + trackedEntityAttributes, + selectedEntity: teiValues, + selectedEnrollment: enrollmentData, + selectedOrgUnit: orgUnit, + optionSets, + currentEvent, + }); + + // then + expect(rulesEffects).toEqual([ + { + content: undefined, + id: 'zDhUuAYrxNC', + targetDataType: 'trackedEntityAttribute', + type: 'HIDEFIELD', + }, + ]); + }); +});