diff --git a/CHANGELOG.md b/CHANGELOG.md index a8bdf704ec..5c5bd7b301 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,59 @@ +## [100.53.1](https://github.com/dhis2/capture-app/compare/v100.53.0...v100.53.1) (2024-02-01) + + +### Bug Fixes + +* [DHIS2-16499] Handle different API response format ([#3517](https://github.com/dhis2/capture-app/issues/3517)) ([206d56c](https://github.com/dhis2/capture-app/commit/206d56c8c86f6cf3bdfc8792e87409c082237401)) + +# [100.53.0](https://github.com/dhis2/capture-app/compare/v100.52.0...v100.53.0) (2024-01-26) + + +### Features + +* [DHIS2-15475] Form Field Plugins ([#3502](https://github.com/dhis2/capture-app/issues/3502)) ([2ccb87b](https://github.com/dhis2/capture-app/commit/2ccb87bb775056c701dfaf9b4f9494b0008a57c3)) + +# [100.52.0](https://github.com/dhis2/capture-app/compare/v100.51.0...v100.52.0) (2024-01-25) + + +### Features + +* [DHIS2-16204] make opt-in to new dashboard the default ([#3508](https://github.com/dhis2/capture-app/issues/3508)) ([5407d7c](https://github.com/dhis2/capture-app/commit/5407d7c98257e16cd647438a7cfe693a5fcd2e0e)) + +# [100.51.0](https://github.com/dhis2/capture-app/compare/v100.50.7...v100.51.0) (2024-01-25) + + +### Features + +* [DHIS2-15480] widget assignee ([#3412](https://github.com/dhis2/capture-app/issues/3412)) ([d61efae](https://github.com/dhis2/capture-app/commit/d61efae8b24ffb34a84e765bc397de87ce76c125)) + +## [100.50.7](https://github.com/dhis2/capture-app/compare/v100.50.6...v100.50.7) (2024-01-23) + + +### Bug Fixes + +* [DHIS2-15888] multi text element in program rules ([#3482](https://github.com/dhis2/capture-app/issues/3482)) ([fd0776d](https://github.com/dhis2/capture-app/commit/fd0776d2261b761c9985db3f6bfb0fda4a2ad18c)) + +## [100.50.6](https://github.com/dhis2/capture-app/compare/v100.50.5...v100.50.6) (2024-01-21) + + +### Bug Fixes + +* [DHIS2-16352] Add spacing between event overview cards ([#3500](https://github.com/dhis2/capture-app/issues/3500)) ([2041d60](https://github.com/dhis2/capture-app/commit/2041d605454529b3bcd77fa3b53a4655ae1495cf)) + +## [100.50.5](https://github.com/dhis2/capture-app/compare/v100.50.4...v100.50.5) (2024-01-21) + + +### Bug Fixes + +* **translations:** sync translations from transifex (master) ([eca1ba4](https://github.com/dhis2/capture-app/commit/eca1ba418e672a58df08785b74430c60e8eb9bcb)) + +## [100.50.4](https://github.com/dhis2/capture-app/compare/v100.50.3...v100.50.4) (2024-01-14) + + +### Bug Fixes + +* **translations:** sync translations from transifex (master) ([ad60c3a](https://github.com/dhis2/capture-app/commit/ad60c3a4500176c8db08ceb05e074eedfcf5e2b3)) + ## [100.50.3](https://github.com/dhis2/capture-app/compare/v100.50.2...v100.50.3) (2023-12-24) diff --git a/cypress/e2e/EnrollmentAddEventPage/EnrollmentAddEventPageForm.feature b/cypress/e2e/EnrollmentAddEventPage/EnrollmentAddEventPageForm.feature index 966cd9083f..5964f07644 100644 --- a/cypress/e2e/EnrollmentAddEventPage/EnrollmentAddEventPageForm.feature +++ b/cypress/e2e/EnrollmentAddEventPage/EnrollmentAddEventPageForm.feature @@ -47,9 +47,8 @@ Feature: User interacts with the Enrollment New Event Workspace Then the input should throw an error with error-message Please provide a positive integer Scenario: User should be asked to create new event after completing a stage and choose to cancel - Given you open the main page with Ngelehun and Malaria focus investigation context - And you opt in to use the new enrollment Dashboard for Malaria focus investigation - Then you land on the enrollment new event page by having typed #/enrollmentEventNew?enrollmentId=zRfAPUpjoG3&orgUnitId=DiszpKrYNg8&programId=M3xtLkYBlKI&stageId=CWaAcQYKVpq&teiId=S3JjTA4QMNe + Given you land on the enrollment new event page by having typed #/enrollmentEventNew?enrollmentId=zRfAPUpjoG3&orgUnitId=DiszpKrYNg8&programId=M3xtLkYBlKI&stageId=CWaAcQYKVpq&teiId=S3JjTA4QMNe + And the data store is clean Then you see the following Enrollment: New Event And you see the widget header Foci investigation & classification And you type 2022-01-01 in the input number 0 diff --git a/cypress/e2e/EnrollmentAddEventPage/EnrollmentAddEventPageForm/index.js b/cypress/e2e/EnrollmentAddEventPage/EnrollmentAddEventPageForm/index.js index d4b2f403a9..4438466f15 100644 --- a/cypress/e2e/EnrollmentAddEventPage/EnrollmentAddEventPageForm/index.js +++ b/cypress/e2e/EnrollmentAddEventPage/EnrollmentAddEventPageForm/index.js @@ -1,5 +1,6 @@ import { Given, When, Then, defineStep as And } from '@badeball/cypress-cucumber-preprocessor'; import '../sharedSteps'; +import '../../sharedSteps'; const showAllEventsInProgramStage = () => { cy.get('[data-test="dhis2-uicore-tablefoot"]') @@ -16,16 +17,6 @@ Given('you open the main page with Ngelehun and Malaria focus investigation cont cy.visit('/#/?orgUnitId=DiszpKrYNg8&programId=M3xtLkYBlKI'); }); -When(/^you opt in to use the new enrollment Dashboard for (.*)$/, (program) => { - cy.get('[data-test="main-page-working-list"]').then(($wrapper) => { - if ($wrapper.find('[data-test="opt-in"]').length > 0) { - cy.contains('[data-test="dhis2-uicore-button"]', `Opt in for ${program}`).click(); - cy.contains('[data-test="dhis2-uicore-button"]', 'Yes, opt in').click(); - cy.contains('[data-test="dhis2-uicore-button"]', `Opt out for ${program}`); - } - }); -}); - Given(/^you land on the enrollment new event page by having typed (.*)$/, (url) => { cy.visit(url); }); diff --git a/cypress/e2e/EnrollmentPage/BreakingTheGlass.feature b/cypress/e2e/EnrollmentPage/BreakingTheGlass.feature index ac67d53256..a00ec363c1 100644 --- a/cypress/e2e/EnrollmentPage/BreakingTheGlass.feature +++ b/cypress/e2e/EnrollmentPage/BreakingTheGlass.feature @@ -4,13 +4,12 @@ Feature: Breaking the glass page @skip Scenario: User with search scope access tries to access an enrollment in a protected program Given the tei created by this test is cleared from the database - And you opt temporarily in on new enrollment dashboard in Child programme and WHO RMNCH Tracker + And the data store is clean And you create a new tei in Child programme from Ngelehun CHC And you change program to WHO RMNCH Tracker And you enroll the tei from Njandama MCHP And you log out And you log in as tracker2 user - And you opt temporarily in on new enrollment dashboard in Child programme and WHO RMNCH Tracker And you select the new tei And you change program to WHO RMNCH Tracker Then you see the breaking the glass page diff --git a/cypress/e2e/EnrollmentPage/BreakingTheGlass/index.js b/cypress/e2e/EnrollmentPage/BreakingTheGlass/index.js index 120dc0a0dc..d9fc185179 100644 --- a/cypress/e2e/EnrollmentPage/BreakingTheGlass/index.js +++ b/cypress/e2e/EnrollmentPage/BreakingTheGlass/index.js @@ -1,19 +1,18 @@ import { Given, When, Then, defineStep as And } from '@badeball/cypress-cucumber-preprocessor'; import '../sharedSteps'; +import '../../sharedSteps'; Given('the tei created by this test is cleared from the database', () => { cy.buildApiUrl('tracker', 'trackedEntities?filter=w75KJ2mc4zz:like:Breaking&filter=zDhUuAYrxNC:like:TheGlass&trackedEntityType=nEenWmSyUEp&page=1&pageSize=5&ouMode=ACCESSIBLE') .then(url => cy.request(url)) - .then(({ body }) => - body.instances.forEach(({ trackedEntity }) => - cy.buildApiUrl('trackedEntityInstances', trackedEntity) - .then(trackedEntityUrl => - cy.request('DELETE', trackedEntityUrl)), - )); -}); - -And('you opt temporarily in on new enrollment dashboard in Child programme and WHO RMNCH Tracker', () => { - cy.visit('/#/?newDashboard=IpHINAT79UW,WSGAb5XwJ3Y'); + .then(({ body }) => { + const apiTrackedEntities = body.trackedEntities || body.instances || []; + return apiTrackedEntities.forEach(({ trackedEntity }) => + cy + .buildApiUrl('trackedEntityInstances', trackedEntity) + .then(trackedEntityUrl => cy.request('DELETE', trackedEntityUrl)), + ); + }); }); And('you create a new tei in Child programme from Ngelehun CHC', () => { diff --git a/cypress/e2e/MainPage.feature b/cypress/e2e/MainPage.feature index 980d9fd1e2..cb10b479fb 100644 --- a/cypress/e2e/MainPage.feature +++ b/cypress/e2e/MainPage.feature @@ -35,13 +35,14 @@ Feature: User interacts with Main page Then the current url is /#/?orgUnitId=DiszpKrYNg8&programId=uy2gU8kT1jF&selectedTemplateId=uy2gU8kT1jF-default And the TEI working list is displayed - Scenario: The admin user can optin to use the new Enrollment Dashboard + Scenario: The admin user can optout from using the new Enrollment Dashboard Given you open the main page with Ngelehun and child programme context - And you see the opt in component for Child Programme - When you opt in to use the new enrollment Dashboard for Child Programme - Then you see the opt out component for Child Programme + And the data store is clean + And 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 + When you opt in to use the new enrollment Dashboard for Child Programme + Then you see the opt out component for Child Programme @v<41 Scenario: The icon is rendered as an svg diff --git a/cypress/e2e/NewPage.feature b/cypress/e2e/NewPage.feature index afbc13720c..7c814e0c4b 100644 --- a/cypress/e2e/NewPage.feature +++ b/cypress/e2e/NewPage.feature @@ -8,11 +8,12 @@ Feature: User creates a new entries from the registration page @v>=41 Scenario: New person in Tracker Program > Filling the Allergies with multiple options Given you are in the WHO RMNCH program registration page + And the data store is clean When you fill in multiple Allergies options Then you can see the multiple selections in the form And you fill the WHO RMNCH program registration form with its required unique values And you click the save person submit button - Then you are navigated to the WHO RMNCH program in Tracker Capture app + Then you see the enrollment event Edit page Scenario: Viewing the registration page with incomplete program categories selection Given you are in the main page with no selections made @@ -126,17 +127,19 @@ Feature: User creates a new entries from the registration page Scenario: New person > Submitting the form with unique name navigates you to the user dashboard Given you are in the Person registration page + And the data store is clean When you fill in a unique first name And you click the save person submit button - Then you are navigated to the Tracker Capture + Then you are navigated to the enrollment dashboard page without enrollment Scenario: New person > Submitting the form from the duplicates modal navigates you to the user dashboard Given you are in the Person registration page + And the data store is clean When you fill in the first name with value that has duplicates And you click the save person submit button And you see the possible duplicates modal And you submit the form again from the duplicates modal - Then you are navigated to the Tracker Capture + Then you are navigated to the enrollment dashboard page without enrollment Scenario: New person > Submitting the form shows a list with duplicates Given you are in the Person registration page @@ -171,17 +174,19 @@ Feature: User creates a new entries from the registration page Scenario: New person in Tracker Program > Submitting the form with unique values navigates you to the user dashboard Given you are in the WHO RMNCH program registration page + And the data store is clean When you fill the WHO RMNCH program registration form with its required unique values And you click the save person submit button - Then you are navigated to the WHO RMNCH program in Tracker Capture app + Then you see the enrollment event Edit page Scenario: New person in Tracker Program > Submitting the form from the duplicates modal navigates you to the user dashboard Given you are in the WHO RMNCH program registration page + And the data store is clean When you fill the WHO RMNCH program registration form with its required values And you click the save person submit button And you see the possible duplicates modal When you submit the form again from the duplicates modal - Then you are navigated to the WHO RMNCH program in Tracker Capture app + Then you see the enrollment event Edit page Scenario: New person in Tracker Program > Submitting the form shows a list with duplicates @@ -201,16 +206,11 @@ Feature: User creates a new entries from the registration page Then you see validation errors on the WHO RMNCH program registration page Scenario: Go to enrollment event when Open data entry form after enrollment is checked - Given you open the main page with Ngelehun and Malaria case diagnosis, treatment and investigation context - And you opt in to use the new enrollment Dashboard for Malaria case diagnosis, treatment and investigation - And you see the opt out component for Malaria case diagnosis, treatment and investigation - When you are in the Malaria case diagnosis, treatment and investigation program registration page + Given you are in the Malaria case diagnosis, treatment and investigation program registration page + And the data store is clean And you fill the Malaria case diagnosis registration form with values And you click the save malaria entity submit button Then you see the enrollment event Edit page - When you open the main page with Ngelehun and Malaria case diagnosis, treatment and investigation context - And you opt out to use the new enrollment Dashboard for Malaria case diagnosis, treatment and investigation - Then you see the opt in component for Malaria case diagnosis, treatment and investigation ## New enrollment of existing TEI diff --git a/cypress/e2e/NewPage/index.js b/cypress/e2e/NewPage/index.js index 901452f440..1bde1eb509 100644 --- a/cypress/e2e/NewPage/index.js +++ b/cypress/e2e/NewPage/index.js @@ -487,10 +487,6 @@ And('you fill in child programme first name with value that has duplicates', () .blur(); }); -Then('you are navigated to the WHO RMNCH program in Tracker Capture app', () => { - cy.url().should('include', 'dashboard?tei='); - cy.url().should('include', 'ou=DiszpKrYNg8&program=WSGAb5XwJ3Y'); -}); And('you fill the Child programme registration form with a first name with value that has duplicates', () => { cy.get('[data-test="capture-ui-input"]') diff --git a/cypress/e2e/SearchPage.feature b/cypress/e2e/SearchPage.feature index 0f98fdfdfc..1c4591802f 100644 --- a/cypress/e2e/SearchPage.feature +++ b/cypress/e2e/SearchPage.feature @@ -24,10 +24,11 @@ Feature: User interacts with Search page Scenario: Searching using unique identifier returns results Given you are on the default search page + And the data store is clean When you select the search domain WHO RMNCH Tracker And you fill in the unique identifier field with values that will return a tracked entity instance And you click find - Then you are navigated to the Tracker Capture + Then you are navigated to the enrollment dashboard page # Scenario: Searching using attributes in Tracker Program returns no results # Given you are on the default search page @@ -96,23 +97,25 @@ Feature: User interacts with Search page Scenario: Searching using attributes in Tracker Program navigates user to the dashboard view Given you are on the default search page + And the data store is clean When you select the search domain WHO RMNCH Tracker And you expand the attributes search area And you fill in the last name with values that will return results And you click search And you can see the first page of the results And you click the view dashboard button - Then you are navigated to the Tracker Capture + Then you are navigated to the enrollment dashboard page Scenario: Searching using attributes in TEType navigates user to dashboard view Given you are on the default search page + And the data store is clean When you select the search domain Person And you expand the attributes search area And you fill in the the form with first name value: Cla And you click search And you can see the first page of the results And you click the view dashboard button - Then you are navigated to the Tracker Capture without program + Then you are navigated to the enrollment dashboard page without enrollment Scenario: Searching using attributes in Tracker Program domain has disabled pagination Given you are on the default search page @@ -162,9 +165,10 @@ Feature: User interacts with Search page Scenario: Pressing enter should trigger search unique identifier returns results Given you are on the default search page + And the data store is clean When you select the search domain WHO RMNCH Tracker And you press enter after filling in the unique identifier field with values that will return a tracked entity instance - Then you are navigated to the Tracker Capture + Then you are navigated to the enrollment dashboard page Scenario: Pressing enter should trigger search attributes returns results Given you are in the search page with the Child Programme being preselected from the url diff --git a/cypress/e2e/SearchPage/index.js b/cypress/e2e/SearchPage/index.js index 644ff73111..322dc9d377 100644 --- a/cypress/e2e/SearchPage/index.js +++ b/cypress/e2e/SearchPage/index.js @@ -93,19 +93,6 @@ When('you fill in the unique identifier field with values that will return a tra .blur(); }); -Then('you are navigated to the Tracker Capture', () => { - cy.url() - .should('include', 'dhis-web-tracker-capture/') - .should('include', 'dashboard?tei=') - .should('include', 'program=WSGAb5XwJ3Y'); -}); - -Then('you are navigated to the Tracker Capture without program', () => { - cy.url() - .should('include', 'dhis-web-tracker-capture/') - .should('include', 'dashboard?tei=') - .should('include', 'tracked_entity_type=nEenWmSyUEp'); -}); When('you fill in the first name with values that will return no results', () => { cy.get('[data-test="form-attributes"]') diff --git a/cypress/e2e/WidgetsForEnrollmentPages/WidgetAssignee/index.js b/cypress/e2e/WidgetsForEnrollmentPages/WidgetAssignee/index.js new file mode 100644 index 0000000000..9f45c31e2f --- /dev/null +++ b/cypress/e2e/WidgetsForEnrollmentPages/WidgetAssignee/index.js @@ -0,0 +1,52 @@ +import { When, Then } from '@badeball/cypress-cucumber-preprocessor'; + +When('you assign the user Geetha in the view mode', () => { + cy.get('[data-test="widget-assignee"]').within(() => { + cy.get('[data-test="widget-assignee-assign"]').click(); + cy.get('[data-test="capture-ui-input"]').type('Geetha'); + cy.contains('Geetha Alwan').click(); + cy.get('[data-test="widget-assignee-save"]').click(); + }); +}); + +When('you assign the user Tracker demo User in the edit mode', () => { + cy + .get('[data-test="widget-enrollment-event"]') + .find('[data-test="dhis2-uicore-button"]') + .eq(1) + .click(); + + cy.get('[data-test="widget-assignee"]').within(() => { + cy.get('[data-test="widget-assignee-edit"]').click(); + cy.get('[data-test="dhis2-uicore-chip-remove"]').click(); + cy.get('[data-test="capture-ui-input"]').type('Tracker demo'); + cy.contains('Tracker demo User').click(); + cy.get('[data-test="widget-assignee-save"]').click(); + }); +}); + +When('you remove the assigned user', () => { + cy.get('[data-test="widget-assignee"]').within(() => { + cy.get('[data-test="widget-assignee-edit"]').click(); + cy.get('[data-test="dhis2-uicore-chip-remove"]').click(); + cy.get('[data-test="widget-assignee-save"]').click(); + }); +}); + +Then('the event has the user Geetha Alwan assigned', () => { + cy.get('[data-test="widget-assignee"]').within(() => { + cy.get('[data-test="widget-contents"]').contains('Geetha Alwan').should('exist'); + }); +}); + +Then('the event has the user Tracker demo User assigned', () => { + cy.get('[data-test="widget-assignee"]').within(() => { + cy.get('[data-test="widget-contents"]').contains('Tracker demo User').should('exist'); + }); +}); + +Then('the event has no assignd user', () => { + cy.get('[data-test="widget-assignee"]').within(() => { + cy.get('[data-test="widget-contents"]').contains('No one is assigned to this event').should('exist'); + }); +}); diff --git a/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEnrollmentEditEvent.feature b/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEnrollmentEditEvent.feature index c3add0d727..27dae1fd6a 100644 --- a/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEnrollmentEditEvent.feature +++ b/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEnrollmentEditEvent.feature @@ -102,4 +102,13 @@ Feature: The user interacts with the widgets on the enrollment edit event Given you land on the enrollment edit event page by having typed /#/enrollmentEventEdit?eventId=XGLkLlOXgmE&orgUnitId=DiszpKrYNg8 Then the enrollment widget should be loaded When you click edit mode - Then list should contain the new comment: new test comment \ No newline at end of file + Then list should contain the new comment: new test comment + + Scenario: You can assign a user to a event + Given you land on the enrollment edit event page by having typed /#/enrollmentEventEdit?eventId=veuwiLC2x0e&orgUnitId=g8upMTyEZGZ + When you assign the user Geetha in the view mode + Then the event has the user Geetha Alwan assigned + When you assign the user Tracker demo User in the edit mode + Then the event has the user Tracker demo User assigned + When you remove the assigned user + Then the event has no assignd user diff --git a/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEnrollmentEditEvent/index.js b/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEnrollmentEditEvent/index.js index 656f67c564..ff80131398 100644 --- a/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEnrollmentEditEvent/index.js +++ b/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEnrollmentEditEvent/index.js @@ -2,3 +2,5 @@ import '../sharedSteps'; import '../WidgetEnrollment'; import '../WidgetProfile'; import '../WidgetEventComment'; +import '../WidgetAssignee'; + diff --git a/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsDev/index.js b/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsDev/index.js index e1d79d283a..0b507921ea 100644 --- a/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsDev/index.js +++ b/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsDev/index.js @@ -36,25 +36,27 @@ Then('events should be retrieved from the api using the default query args', () .its('response.url') .should('include', 'page=1'); - cy.get('@result').its('response.body.instances').as('events'); + cy.get('@result').its('response.body').as('events'); }); Then('the list should display the events retrieved from the api', () => { cy.get('@events') - .then((events) => { + .then((body) => { + const apiEvents = body.events || body.instances || []; cy.get('[data-test="event-working-lists"]') .find('tr') - .should('have.length', events.length + 1); + .should('have.length', apiEvents.length + 1); }); cy.get('@events') - .then((teis) => { + .then((body) => { + const apiEvents = body.events || body.instances || []; cy.get('[data-test="event-working-lists"]') .find('tr') .each(($teiRow, index) => { const rowId = $teiRow.get(0).getAttribute('data-test'); if (index > 1) { - expect(rowId).to.equal(teis[index - 1].event); + expect(rowId).to.equal(apiEvents[index - 1].event); } }); }); @@ -87,7 +89,7 @@ Then('events assigned to anyone should be retrieved from the api', () => { .its('response.url') .should('include', 'page=1'); - cy.get('@result').its('response.body.instances').as('events'); + cy.get('@result').its('response.body').as('events'); }); When('you apply the assignee filter', () => { @@ -123,7 +125,7 @@ Then('active events that are assigned to anyone should be retrieved from the api .its('response.url') .should('include', 'page=1'); - cy.get('@result').its('response.body.instances').as('events'); + cy.get('@result').its('response.body').as('events'); }); When('you apply the current filter on the event working list', () => { @@ -152,7 +154,7 @@ Then('events where age is between 10 and 20 should be retrieved from the api', ( .its('response.url') .should('include', 'page=1'); - cy.get('@result').its('response.body.instances').as('events'); + cy.get('@result').its('response.body').as('events'); }); When('you click the next page button on the event working list', () => { @@ -172,7 +174,7 @@ Then('new events should be retrieved from the api', () => { .its('response.statusCode') .should('equal', 200); - cy.get('@result').its('response.body.instances').as('events'); + cy.get('@result').its('response.body').as('events'); }); When('you click the previous page button on the event working list', () => { @@ -216,7 +218,7 @@ Then('an event batch capped at 50 records should be retrieved from the api', () .its('response.url') .should('include', 'page=1'); - cy.get('@result').its('response.body.instances').as('events'); + cy.get('@result').its('response.body').as('events'); }); When('you click the report date column header', () => { @@ -248,5 +250,5 @@ Then('events should be retrieved from the api ordered ascendingly by report date .its('response.url') .should('include', 'page=1'); - cy.get('@resultAsc').its('response.body.instances').as('events'); + cy.get('@resultAsc').its('response.body').as('events'); }); diff --git a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsDev/index.js b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsDev/index.js index 56989dd920..5a0dd69651 100644 --- a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsDev/index.js +++ b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsDev/index.js @@ -42,7 +42,7 @@ Then('teis should be retrieved from the api using the default query args', () => .its('response.url') .should('include', 'page=1'); - cy.get('@result').its('response.body.instances').as('teis'); + cy.get('@result').its('response.body').as('teis'); }); Then('the first page of the default tei working list should be displayed', () => { @@ -89,7 +89,7 @@ Then('teis with an active enrollment should be retrieved from the api', () => { .its('response.url') .should('include', 'page=1'); - cy.get('@result').its('response.body.instances').as('teis'); + cy.get('@result').its('response.body').as('teis'); }); When('you apply the assignee filter', () => { @@ -118,7 +118,7 @@ Then('teis with active enrollments and unassigned events should be retrieved fro .its('response.url') .should('include', 'page=1'); - cy.get('@result').its('response.body.instances').as('teis'); + cy.get('@result').its('response.body').as('teis'); }); When('you apply the current filter on the tei working list', () => { @@ -143,25 +143,27 @@ Then('teis with a first name containing John should be retrieved from the api', .its('response.url') .should('include', 'page=1'); - cy.get('@result').its('response.body.instances').as('teis'); + cy.get('@result').its('response.body').as('teis'); }); Then('the list should display the teis retrieved from the api', () => { cy.get('@teis') - .then((teis) => { + .then((body) => { + const apiTrackedEntities = body.trackedEntities || body.instances || []; cy.get('[data-test="tei-working-lists"]') .find('tr') - .should('have.length', teis.length + 1); + .should('have.length', apiTrackedEntities.length + 1); }); cy.get('@teis') - .then((teis) => { + .then((body) => { + const apiTrackedEntities = body.trackedEntities || body.instances || []; cy.get('[data-test="tei-working-lists"]') .find('tr') .each(($teiRow, index) => { const rowId = $teiRow.get(0).getAttribute('data-test'); if (index > 1) { - expect(rowId).to.equal(teis[index - 1].trackedEntity); + expect(rowId).to.equal(apiTrackedEntities[index - 1].trackedEntity); } }); }); @@ -184,7 +186,7 @@ Then('new teis should be retrieved from the api', () => { .its('response.statusCode') .should('eq', 200); - cy.get('@result').its('response.body.instances').as('teis'); + cy.get('@result').its('response.body').as('teis'); }); @@ -222,7 +224,7 @@ Then('a tei batch capped at 50 records should be retrieved from the api', () => .its('response.url') .should('include', 'page=1'); - cy.get('@result').its('response.body.instances').as('teis'); + cy.get('@result').its('response.body').as('teis'); }); When('you click the first page button on the tei working list', () => { @@ -259,5 +261,5 @@ Then('teis should be retrieved from the api ordered ascendingly by first name', .its('response.url') .should('include', 'page=1'); - cy.get('@result').its('response.body.instances').as('teis'); + cy.get('@result').its('response.body').as('teis'); }); diff --git a/cypress/e2e/sharedSteps.js b/cypress/e2e/sharedSteps.js index 16967a0c21..6fa9febef3 100644 --- a/cypress/e2e/sharedSteps.js +++ b/cypress/e2e/sharedSteps.js @@ -155,12 +155,15 @@ Then(/^the user ?(.*) see the following text: (.*)$/, (not, message) => cy.contains(message).should(not ? 'not.exist' : 'exist'), ); -And('you navigated to the enrollment dashboard page', () => { - cy.url().should('include', 'enrollment?enrollmentId'); +And('you are navigated to the enrollment dashboard page', () => { + cy.url().should('include', 'enrollment?'); + cy.url().should('include', 'enrollmentId'); }); -And('you navigated to the enrollment dashboard page without enrollment', () => { - cy.url().should('include', 'enrollment?orgUnit'); +And('you are navigated to the enrollment dashboard page without enrollment', () => { + cy.url().should('include', 'enrollment?'); + cy.url().should('not.include', 'enrollmentId'); + cy.url().should('include', 'teiId'); }); Then('you should see no results found', () => { @@ -209,3 +212,9 @@ When(/^you opt out to use the new enrollment Dashboard for (.*)$/, (program) => Then(/^you see the opt in component for (.*)$/, (program) => { cy.contains('[data-test="dhis2-uicore-button"]', `Opt in for ${program}`); }); + +And('the data store is clean', () => { + cy.buildApiUrl('dataStore/capture/useNewDashboard') + .then(dataStoreUrl => + cy.request({ method: 'DELETE', url: dataStoreUrl, failOnStatusCode: false })); +}); diff --git a/docs/user/resources/images/user_assignment_edit.png b/docs/user/resources/images/user_assignment_edit.png index 6487dbb26f..0eafb0f8ba 100644 Binary files a/docs/user/resources/images/user_assignment_edit.png and b/docs/user/resources/images/user_assignment_edit.png differ diff --git a/docs/user/resources/images/user_assignment_edit_add.png b/docs/user/resources/images/user_assignment_edit_add.png index 1624262db5..cf74cb2bfa 100644 Binary files a/docs/user/resources/images/user_assignment_edit_add.png and b/docs/user/resources/images/user_assignment_edit_add.png differ diff --git a/docs/user/resources/images/user_assignment_edit_button.png b/docs/user/resources/images/user_assignment_edit_button.png index d650002481..4d1344c2e7 100644 Binary files a/docs/user/resources/images/user_assignment_edit_button.png and b/docs/user/resources/images/user_assignment_edit_button.png differ diff --git a/docs/user/resources/images/user_assignment_edit_enrollment.png b/docs/user/resources/images/user_assignment_edit_enrollment.png new file mode 100644 index 0000000000..d5357f3b00 Binary files /dev/null and b/docs/user/resources/images/user_assignment_edit_enrollment.png differ diff --git a/docs/user/resources/images/user_assignment_report_new.png b/docs/user/resources/images/user_assignment_report_new.png new file mode 100644 index 0000000000..02fa3d7ca4 Binary files /dev/null and b/docs/user/resources/images/user_assignment_report_new.png differ diff --git a/docs/user/resources/images/user_assignment_schedule_new_filled.png b/docs/user/resources/images/user_assignment_schedule_new_filled.png new file mode 100644 index 0000000000..c09c55a4a0 Binary files /dev/null and b/docs/user/resources/images/user_assignment_schedule_new_filled.png differ diff --git a/docs/user/using-the-capture-app.md b/docs/user/using-the-capture-app.md index 138568e172..ed4562e07b 100644 --- a/docs/user/using-the-capture-app.md +++ b/docs/user/using-the-capture-app.md @@ -566,11 +566,11 @@ You can set up your own views and save them for later use. The views can also be ![](resources/images/view_delete.png) -## User assignment { #capture_user_assignment } +## User assignment in events programs { #capture_user_assignment } Events can be assigned to users. This feature must be enabled per program. -### Assigning new events { #capture_user_assignment_new } +### Assigning user to new events { #capture_user_assignment_new } 1. Select an organisation unit and a program with user assignment enabled. @@ -592,13 +592,13 @@ Events can be assigned to users. This feature must be enabled per program. ![](resources/images/user_assignment_edit.png) -4. Click the edit button, or the **Assign** button if the event is not currently assigned to anyone. +4. Click the **Edit** button, or the **Assign** button if the event is not currently assigned to anyone. ![](resources/images/user_assignment_edit_button.png) ![](resources/images/user_assignment_edit_add.png) -5. Search for and select the user you would like to reassign the event to. The assignment is saved immediately. +5. Search for and select the user you would like to reassign the event to. Click the **Save** button. ### Assignee in the event list { #capture_user_assignment_event_list } @@ -1193,6 +1193,31 @@ Instead of reporting an event the user can select to schedule an event for later The suggested date for the first event of a program stage in an enrollment is always based on the enrollment date or the incident date (depending on the program configuration). The program stage configuration setting "scheduled days from start" will be added to the base date to cumpute the suggested date. +### Assigning user to new events +When reporting or scheduling an event, you can assign a user to it. This feature must be enabled per program stage in a tracker program by clicking the "Allow user assignment of events" check box. + +You will find the assignee section near the bottom of the data entry page. Search for and select the user you would like to assign the event to. The assignee will be preserved when you save the event. + +![](resources/images/user_assignment_report_new.png) + +![](resources/images/user_assignment_schedule_new_filled.png) + +### Change assignee +1. In View/Edit enrollment event page + +2. In the right column you will find the assignee widget. + + ![](resources/images/user_assignment_edit_enrollment.png) + +3. Click the **Edit** button, or the **Assign** button if the event is not currently assigned to anyone. + + ![](resources/images/user_assignment_edit_button.png) + + ![](resources/images/user_assignment_edit_add.png) + +4. Search for and select the user you would like to reassign the event to. Click the **Save** button. + + #### 1. **Default next scheduled date** If a program stage has a default next scheduled date configured, the suggested date is the most recent next scheduled date. Below is an example of how this can work. > diff --git a/flow-typed/npm/@dhis2/ui_vx.x.x.js b/flow-typed/npm/@dhis2/ui_vx.x.x.js index 118657154a..0ee51f1dfc 100644 --- a/flow-typed/npm/@dhis2/ui_vx.x.x.js +++ b/flow-typed/npm/@dhis2/ui_vx.x.x.js @@ -1,56 +1,67 @@ -// flow-typed signature: c6feccb0af432a25a3ab1270f8309035 -// flow-typed version: <>/@dhis2/ui_v^6.1/flow_v0.132.0 - -/** - * This is an autogenerated libdef stub for: - * - * '@dhis2/ui' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module '@dhis2/ui' { - declare module.exports: any; -} - /** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. + * Flowtype definitions for index + * Generated by Flowgen from a Typescript Definition + * Flowgen v1.21.0 */ -declare module '@dhis2/ui/build/cjs/lib' { - declare module.exports: any; -} - -declare module '@dhis2/ui/build/es/lib' { - declare module.exports: any; -} - -declare module '@dhis2/ui/d2.config' { - declare module.exports: any; -} - -declare module '@dhis2/ui/src' { - declare module.exports: any; -} -// Filename aliases -declare module '@dhis2/ui/build/cjs/lib.js' { - declare module.exports: $Exports<'@dhis2/ui/build/cjs/lib'>; -} -declare module '@dhis2/ui/build/es/lib.js' { - declare module.exports: $Exports<'@dhis2/ui/build/es/lib'>; -} -declare module '@dhis2/ui/d2.config.js' { - declare module.exports: $Exports<'@dhis2/ui/d2.config'>; -} -declare module '@dhis2/ui/src/index' { - declare module.exports: $Exports<'@dhis2/ui/src'>; -} -declare module '@dhis2/ui/src/index.js' { - declare module.exports: $Exports<'@dhis2/ui/src'>; -} + declare export * from "@dhis2/ui-constants"; + declare export * from "@dhis2/ui-icons"; + declare export * from "@dhis2/ui-forms"; + declare export * from "@dhis2-ui/alert"; + declare export * from "@dhis2-ui/button"; + declare export * from "@dhis2-ui/box"; + declare export * from "@dhis2-ui/calendar"; + declare export * from "@dhis2-ui/card"; + declare export * from "@dhis2-ui/center"; + declare export * from "@dhis2-ui/checkbox"; + declare export * from "@dhis2-ui/chip"; + declare export * from "@dhis2-ui/cover"; + declare export * from "@dhis2-ui/css"; + declare export * from "@dhis2-ui/divider"; + declare export * from "@dhis2-ui/field"; + declare export * from "@dhis2-ui/file-input"; + declare export * from "@dhis2-ui/header-bar"; + declare export * from "@dhis2-ui/help"; + declare export * from "@dhis2-ui/input"; + declare export * from "@dhis2-ui/intersection-detector"; + declare export * from "@dhis2-ui/label"; + declare export * from "@dhis2-ui/layer"; + declare export * from "@dhis2-ui/legend"; + declare export * from "@dhis2-ui/loader"; + declare export * from "@dhis2-ui/logo"; + declare export * from "@dhis2-ui/menu"; + declare export * from "@dhis2-ui/modal"; + declare export * from "@dhis2-ui/node"; + declare export * from "@dhis2-ui/notice-box"; + declare export * from "@dhis2-ui/organisation-unit-tree"; + declare export * from "@dhis2-ui/popover"; + declare export { Popper, PopperProps } from "@dhis2-ui/popper"; + declare export * from "@dhis2-ui/portal"; + declare export * from "@dhis2-ui/radio"; + declare export * from "@dhis2-ui/required"; + declare export { Pagination, PaginationProps } from "@dhis2-ui/pagination"; + declare export * from "@dhis2-ui/sharing-dialog"; + declare export { + SingleSelect, + SingleSelectField, + SingleSelectOption, + MultiSelect, + MultiSelectField, + MultiSelectOption, + SingleSelectProps, + SingleSelectFieldProps, + SingleSelectOptionProps, + MultiSelectProps, + MultiSelectFieldProps, + MultiSelectOptionProps, +} from "@dhis2-ui/select"; + declare export * from "@dhis2-ui/selector-bar"; + declare export * from "@dhis2-ui/switch"; + declare export * from "@dhis2-ui/table"; + declare export * from "@dhis2-ui/tab"; + declare export * from "@dhis2-ui/tag"; + declare export * from "@dhis2-ui/text-area"; + declare export * from "@dhis2-ui/tooltip"; + declare export * from "@dhis2-ui/transfer"; + declare export * from "@dhis2-ui/user-avatar"; + declare export * from "@dhis2-ui/segmented-control"; diff --git a/i18n/en.pot b/i18n/en.pot index 8aadf0a151..82e4ae8f8b 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -5,8 +5,8 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -"POT-Creation-Date: 2024-01-08T11:44:50.810Z\n" -"PO-Revision-Date: 2024-01-08T11:44:50.810Z\n" +"POT-Creation-Date: 2024-01-25T12:12:47.253Z\n" +"PO-Revision-Date: 2024-01-25T12:12:47.253Z\n" msgid "Choose one or more dates..." msgstr "Choose one or more dates..." @@ -71,9 +71,6 @@ msgstr "error encountered during field validation" msgid "error" msgstr "error" -msgid "Plugins are not yet available - Please contact your system administrator" -msgstr "Plugins are not yet available - Please contact your system administrator" - msgid "This value is validating" msgstr "This value is validating" @@ -802,18 +799,18 @@ msgstr "Program Stages could not be loaded" msgid "Stage" msgstr "Stage" -msgid "Enrollment{{escape}} View Event" -msgstr "Enrollment{{escape}} View Event" - -msgid "Enrollment{{escape}} Edit Event" -msgstr "Enrollment{{escape}} Edit Event" - msgid "The enrollment event data could not be found" msgstr "The enrollment event data could not be found" msgid "There are no feedback for this event" msgstr "There are no feedback for this event" +msgid "Enrollment{{escape}} View Event" +msgstr "Enrollment{{escape}} View Event" + +msgid "Enrollment{{escape}} Edit Event" +msgstr "Enrollment{{escape}} Edit Event" + msgid "Registered events" msgstr "Registered events" @@ -926,15 +923,6 @@ msgstr "" "Leaving this page will discard any selections you made for a new " "relationship" -msgid "No one is assigned to this event" -msgstr "No one is assigned to this event" - -msgid "Assign" -msgstr "Assign" - -msgid "Event assigned to {{name}}" -msgstr "Event assigned to {{name}}" - msgid "Feedbacks" msgstr "Feedbacks" @@ -1101,11 +1089,23 @@ msgstr "New {{trackedEntityName}} in {{programName}}" msgid "Search for a {{trackedEntityName}} in {{programName}}" msgstr "Search for a {{trackedEntityName}} in {{programName}}" -msgid "To work with the selected program," -msgstr "To work with the selected program," +msgid "Assigned to" +msgstr "Assigned to" + +msgid "You don't have access to edit this assignee" +msgstr "You don't have access to edit this assignee" + +msgid "Edit" +msgstr "Edit" + +msgid "No one is assigned to this event" +msgstr "No one is assigned to this event" + +msgid "You don't have access to assign an assignee" +msgstr "You don't have access to assign an assignee" -msgid "open the Tracker Capture app" -msgstr "open the Tracker Capture app" +msgid "Assign" +msgstr "Assign" msgid "This program is protected" msgstr "This program is protected" @@ -1182,9 +1182,6 @@ msgstr "Latitude" msgid "Longitude" msgstr "Longitude" -msgid "Edit" -msgstr "Edit" - msgid "Set coordinates" msgstr "Set coordinates" @@ -1578,6 +1575,9 @@ msgstr "Error deleting the enrollment event" msgid "Error editing the event, the changes made were not saved" msgstr "Error editing the event, the changes made were not saved" +msgid "Error updating the Assignee" +msgstr "Error updating the Assignee" + msgid "Set coordinate" msgstr "Set coordinate" diff --git a/i18n/es.po b/i18n/es.po index 67b54c1201..bdbd09c1ac 100644 --- a/i18n/es.po +++ b/i18n/es.po @@ -10,16 +10,16 @@ # Janeth Cruz, 2023 # Prabhjot Singh, 2023 # Christian Atavillos, 2023 -# Enzo Nicolas Rossi , 2023 # Gabriela Rodriguez , 2023 # Viktor Varland , 2023 +# Enzo Nicolas Rossi , 2024 # 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: Viktor Varland , 2023\n" +"Last-Translator: Enzo Nicolas Rossi , 2024\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" @@ -176,7 +176,7 @@ msgid "Complete event" msgstr "Completar el evento" msgid "{{ stageName }} - Basic info" -msgstr "" +msgstr "{{ stageName }} - Información básica" msgid "{{ stageName }} - Status" msgstr "" diff --git a/i18n/es_419.po b/i18n/es_419.po index 9e781ff26a..b9754779c5 100644 --- a/i18n/es_419.po +++ b/i18n/es_419.po @@ -1,14 +1,14 @@ # # Translators: -# Enzo Nicolas Rossi , 2023 # Jaime Bosque , 2023 +# Enzo Nicolas Rossi , 2024 # 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: Jaime Bosque , 2023\n" +"Last-Translator: Enzo Nicolas Rossi , 2024\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" @@ -1281,7 +1281,7 @@ msgid "Scheduled date cannot be changed for {{ eventStatus }} events" msgstr "" msgid "Event completed" -msgstr "" +msgstr "Evento completado" msgid "Back to all stages and events" msgstr "Volver a todas las etapas y eventos" @@ -1431,7 +1431,7 @@ msgid "Working list could not be loaded" msgstr "" msgid "Download as JSON" -msgstr "" +msgstr "Descargar como JSON" msgid "Download as CSV" msgstr "" @@ -1512,7 +1512,7 @@ msgid "Show All" msgstr "" msgid "An error has occured. See log for details" -msgstr "" +msgstr " Ha ocurrido un error. Ver el registro para más detalles." msgid "Scheduled{{ escape }} due {{ time }}" msgstr "" diff --git a/i18n/nb.po b/i18n/nb.po index 00e615f61b..16e7fc4490 100644 --- a/i18n/nb.po +++ b/i18n/nb.po @@ -1,14 +1,14 @@ # # Translators: # Caroline Hesthagen Holen , 2023 -# Karoline Tufte Lien , 2023 +# Karoline Tufte Lien , 2024 # 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: Karoline Tufte Lien , 2023\n" +"Last-Translator: Karoline Tufte Lien , 2024\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" @@ -756,7 +756,7 @@ msgstr "" "{{tetName}}." msgid "Enroll a new {{selectedTetName}} in this program." -msgstr "Registrer en ny {{teiDisplayName}} i dette programmet" +msgstr "Registrer en ny {{selectedTetName}} i dette programmet" msgid "{{programName}} is an event program and does not have enrollments." msgstr "{{programName}} er et hendelsesprogram og har ikke registreringer." @@ -837,7 +837,7 @@ msgid "Registered events" msgstr "Registrerte hendelser" msgid "Please select {{category}}." -msgstr "Velg {{kategori}}." +msgstr "Velg {{category}}." msgid "Or see all records accessible to you in {{program}} " msgstr "Eller se alle opptegnelser som er tilgjengelige for deg i {{program}}" diff --git a/package.json b/package.json index b407d2b323..920d59f046 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "capture-app", "homepage": ".", - "version": "100.50.3", + "version": "100.53.1", "cacheVersion": "7", "serverVersion": "38", "license": "BSD-3-Clause", @@ -10,7 +10,7 @@ "packages/rules-engine" ], "dependencies": { - "@dhis2/rules-engine-javascript": "100.50.3", + "@dhis2/rules-engine-javascript": "100.53.1", "@dhis2/app-runtime": "^3.9.3", "@dhis2/d2-i18n": "^1.1.0", "@dhis2/d2-icons": "^1.0.1", @@ -18,7 +18,7 @@ "@dhis2/d2-ui-org-unit-tree": "^7.3.3", "@dhis2/d2-ui-rich-text": "^7.4.0", "@dhis2/d2-ui-sharing-dialog": "^7.3.3", - "@dhis2/ui": "^8.13.8", + "@dhis2/ui": "^9.1.1", "@joakim_sm/react-infinite-calendar": "^2.4.2", "@material-ui/core": "3.9.4", "@material-ui/icons": "3", @@ -95,7 +95,7 @@ "@babel/preset-react": "^7.16.7", "@badeball/cypress-cucumber-preprocessor": "17.2.1", "@cypress/webpack-preprocessor": "^6.0.0", - "@dhis2/cli-app-scripts": "^9.0.1", + "@dhis2/cli-app-scripts": "^10.4.0", "@dhis2/cli-helpers-engine": "^3.2.1", "@dhis2/cli-style": "^10.4.1", "@dhis2/cli-utils-cypress": "^9.0.2", @@ -116,7 +116,7 @@ "eslint-friendly-formatter": "^3.0.0", "eslint-import-resolver-webpack": "^0.13.2", "eslint-plugin-flowtype": "^5.10.0", - "eslint-plugin-import": "2.25.4", + "eslint-plugin-import": "2.29.1", "eslint-plugin-jsx-a11y": "^5.1.1", "eslint-plugin-react": "^7.31.10", "eslint-plugin-react-hooks": "4.6.0", @@ -132,7 +132,11 @@ "wait-on": "^6.0.1" }, "resolutions": { + "@dhis2/cli-app-scripts": "^10.4.0", + "@dhis2/app-runtime": "^3.10.2", + "react-scripts": "4.0.3", "@babel/preset-react": "7.16.7", + "@dhis2/ui": "^9.1.1", "@js-temporal/polyfill": "0.4.3", "core-js": "2.5.7" }, diff --git a/packages/rules-engine/package.json b/packages/rules-engine/package.json index 56222b22a5..c4eac2494e 100644 --- a/packages/rules-engine/package.json +++ b/packages/rules-engine/package.json @@ -1,6 +1,6 @@ { "name": "@dhis2/rules-engine-javascript", - "version": "100.50.3", + "version": "100.53.1", "license": "BSD-3-Clause", "main": "./build/cjs/index.js", "scripts": { diff --git a/packages/rules-engine/src/commonUtils/normalizeRuleVariable.js b/packages/rules-engine/src/commonUtils/normalizeRuleVariable.js index 34f76e1bb5..6c10602fc7 100644 --- a/packages/rules-engine/src/commonUtils/normalizeRuleVariable.js +++ b/packages/rules-engine/src/commonUtils/normalizeRuleVariable.js @@ -39,6 +39,7 @@ export const normalizeRuleVariable = (data: any, valueType: string) => { [typeKeys.AGE]: convertString, [typeKeys.TEXT]: convertString, [typeKeys.LONG_TEXT]: convertString, + [typeKeys.MULTI_TEXT]: convertString, }; if (!data && data !== 0 && data !== false) { diff --git a/packages/rules-engine/src/constants/typeKeys.const.js b/packages/rules-engine/src/constants/typeKeys.const.js index 93bec23586..9280d683dc 100644 --- a/packages/rules-engine/src/constants/typeKeys.const.js +++ b/packages/rules-engine/src/constants/typeKeys.const.js @@ -1,6 +1,7 @@ // @flow export const typeKeys = { TEXT: 'TEXT', + MULTI_TEXT: 'MULTI_TEXT', LONG_TEXT: 'LONG_TEXT', LETTER: 'LETTER', PHONE_NUMBER: 'PHONE_NUMBER', diff --git a/packages/rules-engine/src/constants/typeToInterfaceFnName.const.js b/packages/rules-engine/src/constants/typeToInterfaceFnName.const.js index e8513c6858..f1fc9af926 100644 --- a/packages/rules-engine/src/constants/typeToInterfaceFnName.const.js +++ b/packages/rules-engine/src/constants/typeToInterfaceFnName.const.js @@ -3,6 +3,7 @@ import { typeKeys } from './typeKeys.const'; export const mapTypeToInterfaceFnName = { [typeKeys.TEXT]: 'convertText', + [typeKeys.MULTI_TEXT]: 'convertMultiText', [typeKeys.LONG_TEXT]: 'convertLongText', [typeKeys.LETTER]: 'convertLetter', [typeKeys.PHONE_NUMBER]: 'convertPhoneNumber', diff --git a/packages/rules-engine/src/d2Functions/getD2Functions.js b/packages/rules-engine/src/d2Functions/getD2Functions.js index e128bd871a..459238f447 100644 --- a/packages/rules-engine/src/d2Functions/getD2Functions.js +++ b/packages/rules-engine/src/d2Functions/getD2Functions.js @@ -296,4 +296,11 @@ export const getD2Functions = ({ return params[0]; }, }, + multiTextContains: { + parameters: 2, + execute: (params: any) => { + log.warn('multiTextContains not implemented yet'); + return params[0]; + }, + }, }); diff --git a/packages/rules-engine/src/d2Functions/getD2Functions.types.js b/packages/rules-engine/src/d2Functions/getD2Functions.types.js index 237127a052..4d2403997c 100644 --- a/packages/rules-engine/src/d2Functions/getD2Functions.types.js +++ b/packages/rules-engine/src/d2Functions/getD2Functions.types.js @@ -55,4 +55,5 @@ export type D2Functions = $ReadOnly<{| lastEventDate: D2FunctionConfig, addControlDigits: D2FunctionConfig, checkControlDigits: D2FunctionConfig, + multiTextContains: D2FunctionConfig, |}>; diff --git a/packages/rules-engine/src/helpers/OptionSetHelper.js b/packages/rules-engine/src/helpers/OptionSetHelper.js index 36cf148175..b84720da43 100644 --- a/packages/rules-engine/src/helpers/OptionSetHelper.js +++ b/packages/rules-engine/src/helpers/OptionSetHelper.js @@ -1,6 +1,19 @@ +// @flow +import { typeKeys } from '../constants'; +import type { Option } from '../services/VariableService'; + export class OptionSetHelper { - static getName(options, key) { + static getName(options: Array