diff --git a/CHANGELOG.md b/CHANGELOG.md index 89d693d458..4ec9917046 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,123 @@ +## [101.14.4](https://github.com/dhis2/capture-app/compare/v101.14.3...v101.14.4) (2024-10-29) + + +### Bug Fixes + +* [DHIS2-18228] Image Deleted on Update ([#3857](https://github.com/dhis2/capture-app/issues/3857)) ([4656864](https://github.com/dhis2/capture-app/commit/46568640482a3d6a610533573b1132c160329296)) + +## [101.14.3](https://github.com/dhis2/capture-app/compare/v101.14.2...v101.14.3) (2024-10-29) + + +### Bug Fixes + +* [DHIS2-17843] Disable delete enrollment button when user does not have authority ([#3859](https://github.com/dhis2/capture-app/issues/3859)) ([edee6d3](https://github.com/dhis2/capture-app/commit/edee6d350fb2672a3470ef4c282460b34fa726eb)) + +## [101.14.2](https://github.com/dhis2/capture-app/compare/v101.14.1...v101.14.2) (2024-10-27) + + +### Bug Fixes + +* **translations:** sync translations from transifex (master) ([57a7b83](https://github.com/dhis2/capture-app/commit/57a7b8300c841d043da84735ed32dfce0b64e25b)) + +## [101.14.1](https://github.com/dhis2/capture-app/compare/v101.14.0...v101.14.1) (2024-10-22) + + +### Bug Fixes + +* [DHIS2-16010] app crashes on invalid programid ([#3765](https://github.com/dhis2/capture-app/issues/3765)) ([9133a63](https://github.com/dhis2/capture-app/commit/9133a63e138517c633a192b5d51f39a43c57e327)) + +# [101.14.0](https://github.com/dhis2/capture-app/compare/v101.13.0...v101.14.0) (2024-10-21) + + +### Features + +* [DHIS2-17792] Org unit context in forms ([#3828](https://github.com/dhis2/capture-app/issues/3828)) ([c8ccf63](https://github.com/dhis2/capture-app/commit/c8ccf63e0cde97a190cec6248dc25a4a4d747646)) + +# [101.13.0](https://github.com/dhis2/capture-app/compare/v101.12.2...v101.13.0) (2024-10-21) + + +### Features + +* [DHIS2-16992] Fixed size for changelog modal and columns ([#3834](https://github.com/dhis2/capture-app/issues/3834)) ([3b021cf](https://github.com/dhis2/capture-app/commit/3b021cf5569338db5038d8ed231a810a0fa909f3)) +* [DHIS2-17991] Show orgUnit selector in Enter details now ([#3824](https://github.com/dhis2/capture-app/issues/3824)) ([bf2f1ca](https://github.com/dhis2/capture-app/commit/bf2f1cabebe4ddf100cb8054be0a4af2fbec3965)) + +## [101.12.2](https://github.com/dhis2/capture-app/compare/v101.12.1...v101.12.2) (2024-10-20) + + +### Bug Fixes + +* **translations:** sync translations from transifex (master) ([9bf7696](https://github.com/dhis2/capture-app/commit/9bf7696de59baf42dd8f8ee1869f4696f83c007a)) + +## [101.12.1](https://github.com/dhis2/capture-app/compare/v101.12.0...v101.12.1) (2024-10-16) + + +### Bug Fixes + +* [DHIS2-17978] use title instead of alt on missing icons ([#3847](https://github.com/dhis2/capture-app/issues/3847)) ([b5940f2](https://github.com/dhis2/capture-app/commit/b5940f21204cf26afce6c28ba88b50c09728265f)) + +# [101.12.0](https://github.com/dhis2/capture-app/compare/v101.11.2...v101.12.0) (2024-10-15) + + +### Features + +* [DHIS2-17956] Display name for org unit in changelog ([#3826](https://github.com/dhis2/capture-app/issues/3826)) ([5299f37](https://github.com/dhis2/capture-app/commit/5299f37d33448616c0074ec6568a82c9c96f65cb)) + +## [101.11.2](https://github.com/dhis2/capture-app/compare/v101.11.1...v101.11.2) (2024-10-15) + + +### Bug Fixes + +* [DHIS2-18056] use linkedEntityFormFoundation instead of the searchFormFoundation ([#3835](https://github.com/dhis2/capture-app/issues/3835)) ([cbfe70b](https://github.com/dhis2/capture-app/commit/cbfe70b850554678c7a8bad40e0874ea227fe65c)) + +## [101.11.1](https://github.com/dhis2/capture-app/compare/v101.11.0...v101.11.1) (2024-10-15) + + +### Bug Fixes + +* [DHIS2-16993] Text and long text DEs are missing arrows in changelog when deleted ([#3827](https://github.com/dhis2/capture-app/issues/3827)) ([5e6dfa6](https://github.com/dhis2/capture-app/commit/5e6dfa6bb4b82a68305741bd4bb672a5a1af8f5f)) + +# [101.11.0](https://github.com/dhis2/capture-app/compare/v101.10.2...v101.11.0) (2024-10-14) + + +### Features + +* [DHIS2-17970] Auto-select orgUnit if there is only one available ([#3798](https://github.com/dhis2/capture-app/issues/3798)) ([de06f8b](https://github.com/dhis2/capture-app/commit/de06f8b1b5480ba7315ca648784ef414f8473e06)) + +## [101.10.2](https://github.com/dhis2/capture-app/compare/v101.10.1...v101.10.2) (2024-10-14) + + +### Bug Fixes + +* [DHIS2-18215] selected working list not persisted on navigate ([#3838](https://github.com/dhis2/capture-app/issues/3838)) ([599b2c1](https://github.com/dhis2/capture-app/commit/599b2c1e29c94fd0258844aadb7eef20e03024eb)) + +## [101.10.1](https://github.com/dhis2/capture-app/compare/v101.10.0...v101.10.1) (2024-10-14) + + +### Bug Fixes + +* [DHIS2-18028] User is able to add invalid related stages event ([#3795](https://github.com/dhis2/capture-app/issues/3795)) ([301585e](https://github.com/dhis2/capture-app/commit/301585ed17379900db642a05e0157d52107f96a2)) + +# [101.10.0](https://github.com/dhis2/capture-app/compare/v101.9.1...v101.10.0) (2024-10-14) + + +### Features + +* [DHIS2-17771] Org unit context in tables and lists ([#3813](https://github.com/dhis2/capture-app/issues/3813)) ([b1a720a](https://github.com/dhis2/capture-app/commit/b1a720afc58b281ec7fc50e5af39ac19f4ec0cf4)) + +## [101.9.1](https://github.com/dhis2/capture-app/compare/v101.9.0...v101.9.1) (2024-10-13) + + +### Bug Fixes + +* **translations:** sync translations from transifex (master) ([2603f34](https://github.com/dhis2/capture-app/commit/2603f342d3e34e1f4ac631797c60b93e2aa3606a)) + +# [101.9.0](https://github.com/dhis2/capture-app/compare/v101.8.0...v101.9.0) (2024-10-09) + + +### Features + +* [DHIS2-15238] show and filter on assigned user in program stage WL ([#3821](https://github.com/dhis2/capture-app/issues/3821)) ([e032d50](https://github.com/dhis2/capture-app/commit/e032d5004de91ee30fff89a53e273faf52bea234)) + # [101.8.0](https://github.com/dhis2/capture-app/compare/v101.7.4...v101.8.0) (2024-10-08) diff --git a/cypress/e2e/EnrollmentAddEventPage/EnrollmentAddEventPageForm/EnrollmentAddEventPageForm.feature b/cypress/e2e/EnrollmentAddEventPage/EnrollmentAddEventPageForm/EnrollmentAddEventPageForm.feature index 47bacdbe8a..869b837615 100644 --- a/cypress/e2e/EnrollmentAddEventPage/EnrollmentAddEventPageForm/EnrollmentAddEventPageForm.feature +++ b/cypress/e2e/EnrollmentAddEventPage/EnrollmentAddEventPageForm/EnrollmentAddEventPageForm.feature @@ -50,7 +50,6 @@ Feature: User interacts with the Enrollment New Event Workspace Scenario: User should be asked to create new event after completing a stage and choose to cancel 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/EnrollmentPage/BreakingTheGlass/BreakingTheGlass.feature b/cypress/e2e/EnrollmentPage/BreakingTheGlass/BreakingTheGlass.feature index 8f20612a24..40ed7aac7c 100644 --- a/cypress/e2e/EnrollmentPage/BreakingTheGlass/BreakingTheGlass.feature +++ b/cypress/e2e/EnrollmentPage/BreakingTheGlass/BreakingTheGlass.feature @@ -4,7 +4,6 @@ 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 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 diff --git a/cypress/e2e/MainPage/MainPage.feature b/cypress/e2e/MainPage/MainPage.feature index cb10b479fb..8f29db3697 100644 --- a/cypress/e2e/MainPage/MainPage.feature +++ b/cypress/e2e/MainPage/MainPage.feature @@ -35,15 +35,6 @@ 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 optout from using the new Enrollment Dashboard - Given you open the main page with Ngelehun and child programme context - 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 Given you are in the main page with no selections made diff --git a/cypress/e2e/MainPage/MainPage.js b/cypress/e2e/MainPage/MainPage.js index a420c317b5..01a56c2777 100644 --- a/cypress/e2e/MainPage/MainPage.js +++ b/cypress/e2e/MainPage/MainPage.js @@ -1,4 +1,4 @@ -import { Given, Then, defineStep as And } from '@badeball/cypress-cucumber-preprocessor'; +import { defineStep as And, Given, Then } from '@badeball/cypress-cucumber-preprocessor'; Given('you are in the search page with Ngelehun and MNCH PNC context', () => { cy.visit('/#/search?orgUnitId=DiszpKrYNg8&programId=uy2gU8kT1jF'); @@ -20,13 +20,13 @@ 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"]') + cy.get('[title="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"]') + cy.get('[title="child_program_positive"]') .invoke('attr', 'src') .should('match', /\/icons\/child_program_positive\/icon.svg$/); }); diff --git a/cypress/e2e/NewPage/NewPage.feature b/cypress/e2e/NewPage/NewPage.feature index 49e3d27f99..29b5ffc199 100644 --- a/cypress/e2e/NewPage/NewPage.feature +++ b/cypress/e2e/NewPage/NewPage.feature @@ -7,7 +7,6 @@ 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 @@ -103,14 +102,12 @@ 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 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 @@ -152,7 +149,6 @@ 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 see the enrollment event Edit page @@ -166,7 +162,6 @@ Feature: User creates a new entries from the registration 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 @@ -192,10 +187,12 @@ Feature: User creates a new entries from the registration page Scenario: Go to enrollment event when Open data entry form after enrollment is checked 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 + # Cleanup + And you delete the recently added malaria entity + ## New enrollment of existing TEI diff --git a/cypress/e2e/NewPage/NewPage.js b/cypress/e2e/NewPage/NewPage.js index de6efe53e2..9ef6ab3440 100644 --- a/cypress/e2e/NewPage/NewPage.js +++ b/cypress/e2e/NewPage/NewPage.js @@ -1,4 +1,4 @@ -import { Given, When, Then, defineStep as And } from '@badeball/cypress-cucumber-preprocessor'; +import { defineStep as And, Given, Then, When } from '@badeball/cypress-cucumber-preprocessor'; import moment from 'moment'; import { getCurrentYear } from '../../support/date'; @@ -17,7 +17,7 @@ And('there should be informative message explaining you need to select an organi }); And('you select tracked entity type person', () => { - cy.get('[data-test="dhis2-uicore-select"') + cy.get('[data-test="dhis2-uicore-select"]') .click(); cy.get('[data-test="dhis2-uicore-singleselectoption"]') .contains('Person') @@ -645,6 +645,17 @@ And('you delete the recently added tracked entity', () => { cy.url().should('include', 'selectedTemplateId=IpHINAT79UW'); }); +And('you delete the recently added malaria entity', () => { + cy.get('[data-test="widget-profile-overflow-menu"]') + .click(); + cy.contains('Delete Malaria Entity') + .click(); + cy.get('[data-test="widget-profile-delete-modal"]').within(() => { + cy.contains('Yes, delete Malaria Entity') + .click(); + }); +}); + And(/^you select (.*) from the available tracked entity types/, (selection) => { cy.get('[data-test="dhis2-uicore-select-input"]') .click(); diff --git a/cypress/e2e/ScopeSelector/ScopeSelector.feature b/cypress/e2e/ScopeSelector/ScopeSelector.feature index a53da4790d..ec80a5d2b0 100644 --- a/cypress/e2e/ScopeSelector/ScopeSelector.feature +++ b/cypress/e2e/ScopeSelector/ScopeSelector.feature @@ -28,8 +28,6 @@ Feature: User uses the ScopeSelector to navigate When you select both org unit and program Malaria case registration Then you should see the table - # DHIS2-16010 - App crashes on invalid program id - @skip Scenario: Main page > Url with invalid program id Given you land on a main page with an invalid program id Then you should see error message diff --git a/cypress/e2e/SearchPage/SearchPage.feature b/cypress/e2e/SearchPage/SearchPage.feature index b1a2a58741..afc2f9e035 100644 --- a/cypress/e2e/SearchPage/SearchPage.feature +++ b/cypress/e2e/SearchPage/SearchPage.feature @@ -24,7 +24,6 @@ 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 @@ -97,7 +96,6 @@ 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 @@ -108,7 +106,6 @@ Feature: User interacts with Search 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 @@ -165,7 +162,6 @@ 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 enrollment dashboard page diff --git a/cypress/e2e/WidgetsForEnrollmentPages/WidgetEnrollment/index.js b/cypress/e2e/WidgetsForEnrollmentPages/WidgetEnrollment/index.js index ca5bef0b08..fb01545e49 100644 --- a/cypress/e2e/WidgetsForEnrollmentPages/WidgetEnrollment/index.js +++ b/cypress/e2e/WidgetsForEnrollmentPages/WidgetEnrollment/index.js @@ -66,7 +66,7 @@ Then('the user sees the enrollment organisation unit', () => { cy.get('[data-test="widget-enrollment"]').within(() => { cy.get('[data-test="widget-enrollment-icon-orgunit"]').should('exist'); cy.get('[data-test="widget-enrollment-orgunit"]') - .contains('Started at: Ngelehun CHC') + .contains('Started at:Ngelehun CHC') .should('exist'); }); }); @@ -77,7 +77,7 @@ Then('the user sees the owner organisation unit', () => { 'exist', ); cy.get('[data-test="widget-enrollment-owner-orgunit"]') - .contains('Owned by: Ngelehun CHC') + .contains('Owned by:Ngelehun CHC') .should('exist'); }); }); @@ -232,7 +232,7 @@ Then(/^the user successfully transfers the enrollment/, () => { cy.get('[data-test="widget-enrollment"]').within(() => { cy.get('[data-test="widget-enrollment-owner-orgunit"]') - .contains('Owned by: Njandama MCHP') + .contains('Owned by:Njandama MCHP') .should('exist'); }); }); @@ -246,7 +246,7 @@ Then(/^the user types in (.*)/, (orgunit) => { Given(/^the enrollment owner organisation unit is (.*)/, (orgunit) => { cy.get('[data-test="widget-enrollment"]').within(() => { cy.get('[data-test="widget-enrollment-owner-orgunit"]') - .contains(`Owned by: ${orgunit}`) + .contains(`Owned by:${orgunit}`) .should('exist'); }); }); diff --git a/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsDev/EventWorkingListsDev.js b/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsDev/EventWorkingListsDev.js index 0b507921ea..c633a34430 100644 --- a/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsDev/EventWorkingListsDev.js +++ b/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsDev/EventWorkingListsDev.js @@ -1,5 +1,5 @@ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'; -import '../../sharedSteps'; +import '../sharedSteps'; beforeEach(() => { // Disable cache for chromium browsers to force the api to be called diff --git a/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsUser/EventWorkingListsUser.js b/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsUser/EventWorkingListsUser.js index c5cb9fc63b..b1a6158642 100644 --- a/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsUser/EventWorkingListsUser.js +++ b/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsUser/EventWorkingListsUser.js @@ -1,6 +1,6 @@ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'; import { v4 as uuid } from 'uuid'; -import '../../sharedSteps'; +import '../sharedSteps'; import { getCurrentYear, combineDataAndYear } from '../../../../support/date'; Given('you open the main page with Ngelehun and malaria case context', () => { diff --git a/cypress/e2e/WorkingLists/EventWorkingLists/sharedSteps.js b/cypress/e2e/WorkingLists/EventWorkingLists/sharedSteps.js new file mode 100644 index 0000000000..f2fdb84848 --- /dev/null +++ b/cypress/e2e/WorkingLists/EventWorkingLists/sharedSteps.js @@ -0,0 +1,18 @@ +import { When, Then } from '@badeball/cypress-cucumber-preprocessor'; +import '../sharedSteps'; + +When('you set the assignee filter to anyone', () => { + cy.get('[data-test="event-working-lists"]') + .contains('Assigned to') + .click(); + + cy.get('[data-test="list-view-filter-contents"]') + .contains('Anyone') + .click(); +}); + +Then('the assigned to filter button should show that the anyone filter is in effect', () => { + cy.get('[data-test="event-working-lists"]') + .contains('Assigned to: Anyone') + .should('exist'); +}); diff --git a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsDev/TeiWorkingListsDev.feature b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsDev/TeiWorkingListsDev.feature index 1e0857292e..981ef03ca1 100644 --- a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsDev/TeiWorkingListsDev.feature +++ b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsDev/TeiWorkingListsDev.feature @@ -27,10 +27,10 @@ Scenario: Show only teis with active enrollments and unassinged events using the Given you open the main page with Ngelehun and Malaria focus investigation context When you set the enrollment status filter to active And you apply the enrollment status filter -And you set the assginee filter to none +And you set the assginee filter to None And you apply the assignee filter Then the enrollment status filter button should show that the active filter is in effect -And the assignee filter button should show that unassigned filter is in effect +And the assignee filter button should show that None filter is in effect And teis with active enrollments and unassigned events should be retrieved from the api And the list should display the teis retrieved from the api And for a tracker program the page navigation should show that you are on the first page diff --git a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsDev/TeiWorkingListsDev.js b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsDev/TeiWorkingListsDev.js index 5a0dd69651..050be8508b 100644 --- a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsDev/TeiWorkingListsDev.js +++ b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsDev/TeiWorkingListsDev.js @@ -1,5 +1,5 @@ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'; -import '../../sharedSteps'; +import '../sharedSteps'; beforeEach(() => { // Disable cache for chromium browsers to force the api to be called diff --git a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser/TeiWorkingListsUser.feature b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser/TeiWorkingListsUser.feature index a80e857fcd..db142862ee 100644 --- a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser/TeiWorkingListsUser.feature +++ b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser/TeiWorkingListsUser.feature @@ -8,277 +8,316 @@ Feature: User interacts with tei working lists When you change the sharing settings Then you see the new sharing settings -Scenario: User opens the default working list for a tracker program -Given you open the main page with Ngelehun and child programe context -Then the default working list should be displayed -And rows per page should be set to 15 -And for a tracker program the page navigation should show that you are on the first page - -Scenario: Show only teis with completed enrollments using the predefined working list -Given you open the main page with Ngelehun and child programe context -When you select the working list called completed enrollments -Then the enrollment status filter button should show that the completed filter is in effect -And the list should display teis with a completed enrollment -And rows per page should be set to 15 -And for a tracker program the page navigation should show that you are on the first page - -Scenario: Show only teis with completed enrollments using the filter -Given you open the main page with Ngelehun and child programe context -When you set the enrollment status filter to completed -And you apply the current filter -Then the enrollment status filter button should show that the completed filter is in effect -And the list should display teis with a completed enrollment -And rows per page should be set to 15 -And for a tracker program the page navigation should show that you are on the first page - -# DHIS2-13960: /trackedEntities filter by assignee results are not consistent -@skip -Scenario: Show only teis with active enrollments and unassinged events using the filter -Given you open the main page with Ngelehun and Malaria focus investigation context -When you set the enrollment status filter to active -And you apply the current filter -And you set the assginee filter to none -And you apply the current filter -Then the enrollment status filter button should show that the active filter is in effect -And the assignee filter button should show that unassigned filter is in effect -And the list should display teis with an active enrollment and unassinged events -And rows per page should be set to 15 -And for a tracker program the page navigation should show that you are on the first page - -Scenario: Show only teis with first name containig John using the filter -Given you open the main page with Ngelehun and child programe context -When you set the first name filter to John -And you apply the current filter -Then the first name filter button should show that the filter is in effect -And the list should display teis with John as the first name -And rows per page should be set to 15 -And for a tracker program the page navigation should show that you are on the first page - -Scenario: Show the registering unit column -Given you open the main page with Ngelehun and child programe context -When you open the column selector -And you select the organisation unit and save from the column selector -Then the organisation unit should display in the list - -Scenario: Show next page -Given you open the main page with Ngelehun and child programe context -When you click the next page button -Then the list should display data for the second page -And the pagination for the tei working list should show the second page - -Scenario: Show next page then previous page -Given you open the main page with Ngelehun and child programe context -When you click the next page button -Then the list should display data for the second page -And the pagination for the tei working list should show the second page -When you click the previous page button -Then the default working list should be displayed -And for a tracker program the page navigation should show that you are on the first page - -Scenario: Show next page then first page -Given you open the main page with Ngelehun and child programe context -When you click the next page button -Then the list should display data for the second page -And the pagination for the tei working list should show the second page -When you click the first page button -Then the default working list should be displayed -And for a tracker program the page navigation should show that you are on the first page - -Scenario: Show 10 rows per page -Given you open the main page with Ngelehun and child programe context -When you change rows per page to 10 -Then the list should display 10 rows of data -And for a tracker program the page navigation should show that you are on the first page - -Scenario: Show teis ordered ascendingly by first name -Given you open the main page with Ngelehun and child programe context -When you click the first name column header -Then the sort arrow should indicate ascending order -And the list should display data ordered ascendingly by first name -And for a tracker program the page navigation should show that you are on the first page - -Scenario: The TEI custom working lists is loaded -Given you open the main page with Ngelehun and Malaria focus investigation context -Then you see the custom TEI working lists -And you can load the view with the name Events assigned to me - - - -Scenario: The user creates, updates and deletes a TEI custom working list -Given you open the main page with Ngelehun and Malaria case diagnosis context -And you set the enrollment status filter to completed -And you apply the current filter -And you set the enrollment date to a relative range -And you apply the current filter -When you save the list with the name My custom list -Then the new My custom list is created -And the enrollment status filter button should show that the completed filter is in effect -When you set the enrollment status filter to active -And you apply the current filter -When you update the list with the name My custom list -Then the enrollment status filter button should show that the active filter is in effect -And you delete the name My custom list -Then the My custom list is deleted - -Scenario: The user can delete a TEI working list right immediately after creating it. -Given you open the main page with Ngelehun and Malaria case diagnosis context -And you set the enrollment status filter to completed -And you apply the current filter -And you set the enrollment date to a relative range -And you apply the current filter -When you save the list with the name My custom list -Then the new My custom list is created -When you delete the name My custom list -Then the My custom list is deleted - -Scenario: The user can open and select a program stage filter -Given you open the main page with Ngelehun and Malaria focus investigation context -When you open the program stage filters from the more filters dropdown menu -When you select the Foci response program stage -And you apply the current filter -And you open the column selector -And you select a data element columns and save from the column selector -Then you see data elements specific filters and columns - -Scenario: While in a program stage working list, the user can filter by both TEA and data elements -Given you open the main page with Ngelehun, WHO RMNCH Tracker and First antenatal care visit context -When you set the enrollment status filter to active -And you apply the current filter -And you set the event status filter to completed -And you apply the current filter -And you set the first name filter to Urzula -And you apply the current filter -And you set the WHOMCH Smoking filter to No -And you apply the current filter -Then the list should display 1 row of data - -Scenario: While in a program stage working list, the user can sort by both TEA and data elements -Given you open the main page with Ngelehun, WHO RMNCH Tracker and First antenatal care visit context -And you set the first name filter to u -And you apply the current filter -When you click the last name column header -Then the sort arrow should indicate ascending order -And the list should display data ordered ascendingly by last name -When you click the WHOMCH Hemoglobin value column header -Then the sort arrow should indicate descending order -And the list should display data ordered descending by WHOMCH Hemoglobin - -Scenario: The user can remove the program stage filter -Given you open the main page with Ngelehun and WHO RMNCH Tracker context -When you open the program stage filters from the more filters dropdown menu -And you select the First antenatal care visit program stage -And you apply the current filter -Then you see program stage working list events -When you remove the program stage filter -Then you don't see program stage working list events - -Scenario: The user can filter the events by scheduledAt date -Given you open the main page with Ngelehun and WHO RMNCH Tracker context -When you open the program stage filters from the more filters dropdown menu -And you select the First antenatal care visit program stage -And you apply the current filter -Then you see scheduledAt filter -And you open the column selector -When you select a scheduledAt column and save from the column selector -And you select the events scheduled today -And you apply the current filter -Then you see the selected option in the scheduledAt filter - -Scenario: The program stage working list configureation is kept when navigating -Given you open the main page with Ngelehun and WHO RMNCH Tracker context and configure a program stage working list -When you open an enrollment event from the working list -And you go back using the browser button -Then the program stage working list is loaded - -Scenario: The program stage working list without a orgUnit selected redirects to a tracker event -Given you open the main page with all accesible records in the WHO RMNCH Tracker context and configure a program stage working list -When you open an enrollment event from the working list -Then the tracker event URL contains the orgUnitId - -Scenario: The user can open a program stage list without events -Given you open the main page with Ngelehun and WHO RMNCH Tracker context and configure a program stage working list -And you set the event visit date to Today -And you apply the current filter -Then the working list is empty - -@v>=40 -Scenario: The user creates, updates and deletes a Program stage custom working list -Given you open the main page with Ngelehun and Malaria case diagnosis and Household investigation context -And you set the enrollment status filter to completed -And you apply the current filter -And you set the enrollment date to a relative range -And you apply the current filter -When you save the list with the name Custom Program stage list -Then the new Custom Program stage list is created -And the enrollment status filter button should show that the completed filter is in effect -When you set the enrollment status filter to active -And you apply the current filter -When you update the list with the name Custom Program stage list -Then the enrollment status filter button should show that the active filter is in effect -And you delete the name Custom Program stage list -Then the Custom Program stage list is deleted - -@v>=40 -Scenario: The user can delete a Program stage working list right immediately after creating it. -Given you open the main page with Ngelehun and Malaria case diagnosis and Household investigation context -When you save the list with the name Custom Program stage list -Then the new Custom Program stage list is created -And you delete the name Custom Program stage list -Then the Custom Program stage list is deleted - -# For the program stage WL scenarios I need to create/delete my own because there are no program stage working lists in the demo database. -@v>=40 -Scenario: The Program stage custom working can be shared -Given you open the main page with Ngelehun and Malaria case diagnosis and Household investigation context -And you save the list with the name Custom Program stage list -When you change the sharing settings -Then you see the new sharing settings - -@v>=40 -Scenario: The Program stage working list configuration is kept when changing the org unit -Given you open the main page with Ngelehun and Malaria case diagnosis and Household investigation context -And you save the list with the name Custom Program stage list -Then the new Custom Program stage list is created -And you set the event status filter to completed -And you apply the current filter -And you change the org unit -Then the working list configuration was kept -And you delete the name Custom Program stage list -And the Custom Program stage list is deleted - -@v>=40 -Scenario: The user can save a program stage working list, based on a TEI working list configuration -Given you open a clean main page with Ngelehun and Malaria focus investigation context -Then you see the custom TEI working lists -And you can load the view with the name Ongoing foci responses -And you open the program stage filters from the more filters dropdown menu -And you select the Foci response program stage -And you apply the current filter -Then you are redirect to the default templete -When you save the list with the name Custom Program stage list -Then the new Custom Program stage list is created -And the TEI working list initial configuration was kept -And you delete the name Custom Program stage list -Then the Custom Program stage list is deleted - -@v>=40 -Scenario: The user can download the tracked entity working list -Given you open the main page with Ngelehun and child programe context -And you open the menu and click the "Download data..." button -Then the download dialog opens -Then the CSV button exists -Then the JSON button exists - -@v<40 -Scenario: The user can download the tracked entity working list -Given you open the main page with Ngelehun and child programe context -And you open the menu and click the "Download data..." button -Then the download dialog opens -Then the JSON button exists - -Scenario: The user cannot download the tracked entity working list when no orgUnit is selected -Given you open the main page with child programe context -And the user clicks the element containing the text: Or see all records accessible to you in Child Programme -And you open the menu -Then the "Download data..." button is hidden + Scenario: User opens the default working list for a tracker program + Given you open the main page with Ngelehun and child programe context + Then the default working list should be displayed + And rows per page should be set to 15 + And for a tracker program the page navigation should show that you are on the first page + + Scenario: Show only teis with completed enrollments using the predefined working list + Given you open the main page with Ngelehun and child programe context + When you select the working list called completed enrollments + Then the enrollment status filter button should show that the completed filter is in effect + And the list should display teis with a completed enrollment + And rows per page should be set to 15 + And for a tracker program the page navigation should show that you are on the first page + + Scenario: Show only teis with completed enrollments using the filter + Given you open the main page with Ngelehun and child programe context + When you set the enrollment status filter to completed + And you apply the current filter + Then the enrollment status filter button should show that the completed filter is in effect + And the list should display teis with a completed enrollment + And rows per page should be set to 15 + And for a tracker program the page navigation should show that you are on the first page + + # DHIS2-13960: /trackedEntities filter by assignee results are not consistent + @skip + Scenario: Show only teis with active enrollments and unassinged events using the filter + Given you open the main page with Ngelehun and Malaria focus investigation context + When you set the enrollment status filter to active + And you apply the current filter + And you set the assginee filter to None + And you apply the current filter + Then the enrollment status filter button should show that the active filter is in effect + And the assignee filter button should show that None filter is in effect + And the list should display teis with an active enrollment and unassinged events + And rows per page should be set to 15 + And for a tracker program the page navigation should show that you are on the first page + + Scenario: Show only teis with first name containig John using the filter + Given you open the main page with Ngelehun and child programe context + When you set the first name filter to John + And you apply the current filter + Then the first name filter button should show that the filter is in effect + And the list should display teis with John as the first name + And rows per page should be set to 15 + And for a tracker program the page navigation should show that you are on the first page + + Scenario: Show the registering unit column + Given you open the main page with Ngelehun and child programe context + When you open the column selector + And you select the organisation unit and save from the column selector + Then the organisation unit should display in the list + + Scenario: Show next page + Given you open the main page with Ngelehun and child programe context + When you click the next page button + Then the list should display data for the second page + And the pagination for the tei working list should show the second page + + Scenario: Show next page then previous page + Given you open the main page with Ngelehun and child programe context + When you click the next page button + Then the list should display data for the second page + And the pagination for the tei working list should show the second page + When you click the previous page button + Then the default working list should be displayed + And for a tracker program the page navigation should show that you are on the first page + + Scenario: Show next page then first page + Given you open the main page with Ngelehun and child programe context + When you click the next page button + Then the list should display data for the second page + And the pagination for the tei working list should show the second page + When you click the first page button + Then the default working list should be displayed + And for a tracker program the page navigation should show that you are on the first page + + Scenario: Show 10 rows per page + Given you open the main page with Ngelehun and child programe context + When you change rows per page to 10 + Then the list should display 10 rows of data + And for a tracker program the page navigation should show that you are on the first page + + Scenario: Show teis ordered ascendingly by first name + Given you open the main page with Ngelehun and child programe context + When you click the first name column header + Then the sort arrow should indicate ascending order + And the list should display data ordered ascendingly by first name + And for a tracker program the page navigation should show that you are on the first page + + Scenario: The TEI custom working lists is loaded + Given you open the main page with Ngelehun and Malaria focus investigation context + Then you see the custom TEI working lists + And you can load the view with the name Events assigned to me + + Scenario: The user creates, updates and deletes a TEI custom working list + Given you open the main page with Ngelehun and Malaria case diagnosis context + And you set the enrollment status filter to completed + And you apply the current filter + And you set the enrollment date to a relative range + And you apply the current filter + When you save the list with the name My custom list + Then the new My custom list is created + And the enrollment status filter button should show that the completed filter is in effect + When you set the enrollment status filter to active + And you apply the current filter + When you update the list with the name My custom list + Then the enrollment status filter button should show that the active filter is in effect + And you delete the name My custom list + Then the My custom list is deleted + + Scenario: The user is navigated back to the selected working list after closing a TEI + Given you open the main page with Ngelehun and child programe context + And you select the working list called completed enrollments + When you open a tei from the working list + And you deselect the tracked entity from the context selector + Then the working list called completed enrollments should be selected + + Scenario: The user can delete a TEI working list right immediately after creating it. + Given you open the main page with Ngelehun and Malaria case diagnosis context + And you set the enrollment status filter to completed + And you apply the current filter + And you set the enrollment date to a relative range + And you apply the current filter + When you save the list with the name My custom list + Then the new My custom list is created + When you delete the name My custom list + Then the My custom list is deleted + + Scenario: The user can open and select a program stage filter + Given you open the main page with Ngelehun and Malaria focus investigation context + When you open the program stage filters from the more filters dropdown menu + When you select the Foci response program stage + And you apply the current filter + And you open the column selector + And you select a data element columns and save from the column selector + Then you see data elements specific filters and columns + + Scenario: While in a program stage working list, the user can filter by both TEA and data elements + Given you open the main page with Ngelehun, WHO RMNCH Tracker and First antenatal care visit context + When you set the enrollment status filter to active + And you apply the current filter + And you set the event status filter to completed + And you apply the current filter + And you set the first name filter to Urzula + And you apply the current filter + And you set the WHOMCH Smoking filter to No + And you apply the current filter + Then the list should display 1 row of data + + Scenario: While in a program stage working list, the user can sort by both TEA and data elements + Given you open the main page with Ngelehun, WHO RMNCH Tracker and First antenatal care visit context + And you set the first name filter to u + And you apply the current filter + When you click the last name column header + Then the sort arrow should indicate ascending order + And the list should display data ordered ascendingly by last name + When you click the WHOMCH Hemoglobin value column header + Then the sort arrow should indicate descending order + And the list should display data ordered descending by WHOMCH Hemoglobin + + Scenario: The user can remove the program stage filter + Given you open the main page with Ngelehun and WHO RMNCH Tracker context + When you open the program stage filters from the more filters dropdown menu + And you select the First antenatal care visit program stage + And you apply the current filter + Then you see program stage working list events + When you remove the program stage filter + Then you don't see program stage working list events + + Scenario: The user can filter the events by scheduledAt date + Given you open the main page with Ngelehun and WHO RMNCH Tracker context + When you open the program stage filters from the more filters dropdown menu + And you select the First antenatal care visit program stage + And you apply the current filter + Then you see scheduledAt filter + And you open the column selector + When you select a scheduledAt column and save from the column selector + And you select the events scheduled today + And you apply the current filter + Then you see the selected option in the scheduledAt filter + + Scenario: The program stage working list configureation is kept when navigating + Given you open the main page with Ngelehun and WHO RMNCH Tracker context and configure a program stage working list + When you open an enrollment event from the working list + And you go back using the browser button + Then the program stage working list is loaded + + Scenario: The program stage working list without a orgUnit selected redirects to a tracker event + Given you open the main page with all accesible records in the WHO RMNCH Tracker context and configure a program stage working list + When you open an enrollment event from the working list + Then the tracker event URL contains the orgUnitId + + Scenario: The user can open a program stage list without events + Given you open the main page with Ngelehun and WHO RMNCH Tracker context and configure a program stage working list + And you set the event visit date to Today + And you apply the current filter + Then the working list is empty + + Scenario: The user can filter the Foci response assigned events + Given you open the main page with Ngelehun and Malaria focus investigation context + When you open the program stage filters from the more filters dropdown menu + And you select the Foci response program stage + And you apply the current filter + And you set the assginee filter to Anyone + And you apply the current filter + Then the assignee filter button should show that Anyone filter is in effect + And the assignee column is displayed + + Scenario: The assigned user data is kept when switching between working list types + Given you open the main page with Ngelehun and Malaria focus investigation context + And you filter by assigned Foci investigation & classification events + And the assignee filter button should show that Anyone filter is in effect + When you remove the program stage filter + Then you don't see program stage working list events + And the assignee filter button should show that Anyone filter is in effect + When you set the assginee filter to None + And you apply the current filter + Then the assignee filter button should show that None filter is in effect + When you open the program stage filters from the more filters dropdown menu + And you select the Foci response program stage + And you apply the current filter + Then the assignee filter button should show that None filter is in effect + + @v>=40 + Scenario: The user can create and delete a program stage working list for Foci investigation & classification assigned events + Given you open the main page with Ngelehun and Malaria focus investigation context + And you filter by assigned Foci investigation & classification events + When you save the list with the name Custom Program stage list + Then the new Custom Program stage list is created + And you delete the name Custom Program stage list + Then the Custom Program stage list is deleted + + @v>=40 + Scenario: The user creates, updates and deletes a Program stage custom working list + Given you open the main page with Ngelehun and Malaria case diagnosis and Household investigation context + And you set the enrollment status filter to completed + And you apply the current filter + And you set the enrollment date to a relative range + And you apply the current filter + When you save the list with the name Custom Program stage list + Then the new Custom Program stage list is created + And the enrollment status filter button should show that the completed filter is in effect + When you set the enrollment status filter to active + And you apply the current filter + When you update the list with the name Custom Program stage list + Then the enrollment status filter button should show that the active filter is in effect + And you delete the name Custom Program stage list + Then the Custom Program stage list is deleted + + @v>=40 + Scenario: The user can delete a Program stage working list right immediately after creating it. + Given you open the main page with Ngelehun and Malaria case diagnosis and Household investigation context + When you save the list with the name Custom Program stage list + Then the new Custom Program stage list is created + And you delete the name Custom Program stage list + Then the Custom Program stage list is deleted + + # For the program stage WL scenarios I need to create/delete my own because there are no program stage working lists in the demo database. + @v>=40 + Scenario: The Program stage custom working can be shared + Given you open the main page with Ngelehun and Malaria case diagnosis and Household investigation context + And you save the list with the name Custom Program stage list + When you change the sharing settings + Then you see the new sharing settings + + @v>=40 + Scenario: The Program stage working list configuration is kept when changing the org unit + Given you open the main page with Ngelehun and Malaria case diagnosis and Household investigation context + And you save the list with the name Custom Program stage list + Then the new Custom Program stage list is created + And you set the event status filter to completed + And you apply the current filter + And you change the org unit + Then the working list configuration was kept + And you delete the name Custom Program stage list + And the Custom Program stage list is deleted + + @v>=40 + Scenario: The user can save a program stage working list, based on a TEI working list configuration + Given you open a clean main page with Ngelehun and Malaria focus investigation context + Then you see the custom TEI working lists + And you can load the view with the name Ongoing foci responses + And you open the program stage filters from the more filters dropdown menu + And you select the Foci response program stage + And you apply the current filter + Then you are redirect to the default templete + When you save the list with the name Custom Program stage list + Then the new Custom Program stage list is created + And the TEI working list initial configuration was kept + And you delete the name Custom Program stage list + Then the Custom Program stage list is deleted + + @v>=40 + Scenario: The user can download the tracked entity working list + Given you open the main page with Ngelehun and child programe context + And you open the menu and click the "Download data..." button + Then the download dialog opens + Then the CSV button exists + Then the JSON button exists + + @v<40 + Scenario: The user can download the tracked entity working list + Given you open the main page with Ngelehun and child programe context + And you open the menu and click the "Download data..." button + Then the download dialog opens + Then the JSON button exists + + Scenario: The user cannot download the tracked entity working list when no orgUnit is selected + Given you open the main page with child programe context + And the user clicks the element containing the text: Or see all records accessible to you in Child Programme + And you open the menu + Then the "Download data..." button is hidden diff --git a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser/TeiWorkingListsUser.js b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser/TeiWorkingListsUser.js index 9026a15f3d..0ea736c26a 100644 --- a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser/TeiWorkingListsUser.js +++ b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser/TeiWorkingListsUser.js @@ -1,6 +1,6 @@ -import { Given, When, Then, defineStep as And } from '@badeball/cypress-cucumber-preprocessor'; +import { defineStep as And, Given, Then, When } from '@badeball/cypress-cucumber-preprocessor'; import { v4 as uuid } from 'uuid'; -import '../../sharedSteps'; +import '../sharedSteps'; const cleanUpIfApplicable = (programId) => { cy.buildApiUrl(`programStageWorkingLists?filter=program.id:eq:${programId}&fields=id,displayName`) @@ -198,22 +198,6 @@ When('you set the WHOMCH Smoking filter to No', () => { .click(); }); -When('you set the assginee filter to none', () => { - cy.get('[data-test="tei-working-lists"]') - .contains('Assigned to') - .click(); - - cy.get('[data-test="list-view-filter-contents"]') - .contains('None') - .click(); -}); - -Then('the assignee filter button should show that unassigned filter is in effect', () => { - cy.get('[data-test="tei-working-lists"]') - .contains('Assigned to: None') - .should('exist'); -}); - Then('the list should display teis with an active enrollment and unassinged events', () => { const ids = [ 'ZDA984904', @@ -627,7 +611,7 @@ When('you select a data element columns and save from the column selector', () = }); Then('you see data elements specific filters and columns', () => { - cy.get('[data-test="filter-button-container-DX4LVYeP7bw"]') + cy.get('[data-test="filter-button-container-assignee"]') .should('exist'); cy.get('[data-test="tei-working-lists"]') .should('exist'); @@ -670,6 +654,25 @@ When('you remove the program stage filter', () => { .click(); }); +When('you open a tei from the working list', () => { + cy.get('[data-test="tei-working-lists"]') + .contains('Filona') + .click(); +}); + +When('you deselect the tracked entity from the context selector', () => { + cy.get('[data-test="person-selector-container-clear-icon"]') + .click(); +}); + +// the working list called completed enrollments should be selected +Then('the working list called completed enrollments should be selected', () => { + cy.get('[data-test="workinglist-template-selector-chip"]') + .contains('Completed enrollments') + .parent() + .should('have.class', 'selected'); +}); + Then('you see scheduledAt filter', () => { cy.get('[data-test="tei-working-lists"]') .contains('Appointment date') @@ -866,3 +869,46 @@ Then('the working list is empty', () => { .contains('No items to display') .click(); }); + +Then('the assignee column is displayed', () => { + cy.get('[data-test="dhis2-uicore-tablehead"]') + .contains('Assigned to') + .should('exist'); + + cy.get('[data-test="dhis2-uicore-tablebody"]') + .contains('Tracker demo User (tracker)') + .should('exist'); + + cy.get('[data-test="tei-working-lists"]') + .find('tr') + .should('have.length', 2); +}); + +And('you filter by assigned Foci investigation & classification events', () => { + cy.get('[data-test="tei-working-lists"]') + .within(() => { + cy.contains('More filters') + .click(); + }); + + cy.get('[data-test="more-filters-menu"]') + .within(() => cy.contains('Program stage').click()); + + cy.get('[data-test="list-view-filter-contents"]') + .contains('Foci investigation & classification') + .click(); + + cy.get('[data-test="list-view-filter-apply-button"]') + .click(); + + cy.get('[data-test="tei-working-lists"]') + .contains('Assigned to') + .click(); + + cy.get('[data-test="list-view-filter-contents"]') + .contains('Anyone') + .click(); + + cy.get('[data-test="list-view-filter-apply-button"]') + .click(); +}); diff --git a/cypress/e2e/WorkingLists/TeiWorkingLists/sharedSteps.js b/cypress/e2e/WorkingLists/TeiWorkingLists/sharedSteps.js new file mode 100644 index 0000000000..190c14624b --- /dev/null +++ b/cypress/e2e/WorkingLists/TeiWorkingLists/sharedSteps.js @@ -0,0 +1,18 @@ +import { When, Then } from '@badeball/cypress-cucumber-preprocessor'; +import '../sharedSteps'; + +When(/^you set the assginee filter to (.*)$/, (assignedUser) => { + cy.get('[data-test="tei-working-lists"]') + .contains('Assigned to') + .click(); + + cy.get('[data-test="list-view-filter-contents"]') + .contains(assignedUser) + .click(); +}); + +Then(/^the assignee filter button should show that (.*) filter is in effect/, (assignedUser) => { + cy.get('[data-test="tei-working-lists"]') + .contains(`Assigned to: ${assignedUser}`) + .should('exist'); +}); diff --git a/cypress/e2e/WorkingLists/sharedSteps.js b/cypress/e2e/WorkingLists/sharedSteps.js index c28bdb5ccb..dbe0bb9928 100644 --- a/cypress/e2e/WorkingLists/sharedSteps.js +++ b/cypress/e2e/WorkingLists/sharedSteps.js @@ -12,22 +12,6 @@ Then('for a tracker program the page navigation should show that you are on the .should('exist'); }); -Then('the assigned to filter button should show that the anyone filter is in effect', () => { - cy.get('[data-test="event-working-lists"]') - .contains('Assigned to: Anyone') - .should('exist'); -}); - -When('you set the assignee filter to anyone', () => { - cy.get('[data-test="event-working-lists"]') - .contains('Assigned to') - .click(); - - cy.get('[data-test="list-view-filter-contents"]') - .contains('Anyone') - .click(); -}); - When('you set the status filter to active', () => { cy.get('[data-test="event-working-lists"]') .contains('Status') @@ -98,16 +82,6 @@ When('you set the enrollment status filter to active', () => { .click(); }); -When('you set the assginee filter to none', () => { - cy.get('[data-test="tei-working-lists"]') - .contains('Assigned to') - .click(); - - cy.get('[data-test="list-view-filter-contents"]') - .contains('None') - .click(); -}); - When(/^you set the first name filter to (.*)$/, (name) => { cy.get('[data-test="tei-working-lists"]') .contains('First name') @@ -147,12 +121,6 @@ Then('rows per page should be set to 15', () => { .should('exist'); }); -Then('the assignee filter button should show that unassigned filter is in effect', () => { - cy.get('[data-test="tei-working-lists"]') - .contains('Assigned to: None') - .should('exist'); -}); - When('you change rows per page to 10', () => { cy.get('div[data-test="rows-per-page-selector"]') .click() diff --git a/cypress/support/step_definitions/common/baseSteps.js b/cypress/support/step_definitions/common/baseSteps.js index 42c19ad164..a4db6e4a30 100644 --- a/cypress/support/step_definitions/common/baseSteps.js +++ b/cypress/support/step_definitions/common/baseSteps.js @@ -181,33 +181,3 @@ When(/^the user selects the org unit (.*)$/, (orgUnit) => { cy.contains(orgUnit) .click(); }); - -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="dhis2-uicore-button"]').length > 0) { - cy.contains('[data-test="dhis2-uicore-button"]', `Opt in for ${program}`).click(); - cy.contains('[data-test="opt-in-button"]', 'Yes, opt in').click(); - cy.contains('[data-test="opt-out-button"]', `Opt out for ${program}`); - } - }); -}); - -Then(/^you see the opt out component for (.*)$/, (program) => { - cy.contains('[data-test="opt-out-button"]', `Opt out for ${program}`); -}); - -When(/^you opt out to use the new enrollment Dashboard for (.*)$/, (program) => { - cy.intercept('PUT', '**/dataStore/capture/useNewDashboard').as('optOutEnrollmentDashboard'); - cy.contains('[data-test="opt-out-button"]', `Opt out for ${program}`).click(); - cy.wait('@optOutEnrollmentDashboard', { timeout: 30000 }); -}); - -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/developer/configure-a-capture-plugin.mdx b/docs/developer/configure-a-capture-plugin.mdx index dbf597972a..7f7ab36e39 100644 --- a/docs/developer/configure-a-capture-plugin.mdx +++ b/docs/developer/configure-a-capture-plugin.mdx @@ -1,5 +1,4 @@ import Logo from './resources/tracker-plugin-configurator-logo.png' -import TPCFormFieldDemoImg from './resources/tpc-form-field-demo.png' # Configuration @@ -11,7 +10,7 @@ This application is called __Tracker Plugin Configurator__ and is available in t The app is also installable from the App Management app in your DHIS2 instance. -Tracker Plugin Configurator +Tracker Plugin Configurator ### How to use the Tracker Plugin Configurator @@ -25,5 +24,5 @@ The app is also installable from the App Management app in your DHIS2 instance.
-Form Field Plugin +![Form field plugin](resources/tpc-form-field-demo.png) diff --git a/docs/developer/develop-a-capture-plugin.md b/docs/developer/develop-a-capture-plugin.md index 1205c186b5..6f109ce37f 100644 --- a/docs/developer/develop-a-capture-plugin.md +++ b/docs/developer/develop-a-capture-plugin.md @@ -5,7 +5,7 @@ description: Learn how to develop a plugin for the DHIS2 Capture app. id: develop-a-capture-plugin --- -To develop your own capture plugin, you need to follow these steps: +Developing a capture plugin is almost the same as developing a regular DHIS2 custom app. However, there are some differences in how you structure your plugin and how you configure it to work with the DHIS2 Capture app. These are outlined in the few steps below. ## Step 1: Create a new DHIS2 custom app @@ -52,6 +52,6 @@ To build your plugin, you can use the provided build script from `d2-app-scripts Run `yarn build` or (`d2-app-scripts build`) to build a production version of your plugin. After building your plugin, you can deploy it to your DHIS2 instance. -You can do this by uploading the ZIP file to the _App management_ app in your DHIS2 instance, or publishing it to the app hub. +You can do this by uploading the ZIP file to the _App management_ app in your DHIS2 instance, or publishing it to the App Hub. -See [Configuring a Capture plugin](/docs/capture-plugins/developer/configure-a-capture-plugin) for more information on how to configure your plugin in the DHIS2 Capture app. +See [Configuring a Capture plugin](configure-a-capture-plugin) for more information on how to configure your plugin in the DHIS2 Capture app. diff --git a/docs/developer/enrollment-plugins/manual-setup.mdx b/docs/developer/enrollment-plugins/manual-setup.mdx index bae6afbe0f..36c4443d5a 100644 --- a/docs/developer/enrollment-plugins/manual-setup.mdx +++ b/docs/developer/enrollment-plugins/manual-setup.mdx @@ -19,7 +19,7 @@ When booting the capture application, we will look in the dataStore for these ke We assume that you will already have these three keys under the `capture` namespace in the datastore. If you do not have them, please create them before proceeding. | Page | Key | -|-----------------------|-----------------------------| +| --------------------- | --------------------------- | | Enrollment Dashboard | `enrollmentOverviewLayout` | | Enrollment Add Event | `enrollmentEventNewLayout` | | Enrollment Edit Event | `enrollmentEventEditLayout` | @@ -37,10 +37,8 @@ You can also have different layouts for the three different enrollment pages. label={'Enrollment Dashboard'} default > - - {`{ +```json +{ "IpHINAT79UW": { "title": "Child Programme dashboard", "leftColumn": [ @@ -94,17 +92,15 @@ You can also have different layouts for the three different enrollment pages. } ] } -}`} - +} +``` - - {`{ +```json +{ "IpHINAT79UW": { "title": "Child Programme: Add Event", "leftColumn": [ @@ -150,17 +146,15 @@ You can also have different layouts for the three different enrollment pages. } ] } -}`} - +} +``` - - {`{ +```json +{ "IpHINAT79UW": { "title": "Child Programme: Edit Event", "leftColumn": [ @@ -215,7 +209,7 @@ You can also have different layouts for the three different enrollment pages. ] } }`} - +``` @@ -268,11 +262,8 @@ You can also extend the configurations to render your own custom plugins. You ca You would place this inside either the `leftColumn` or `rightColumn` array. - -{`"leftColumn": [ +```json title="capture/enrollmentEventEditLayout" +"leftColumn": [ { "type": "component", "name": "EditEventWorkspace" @@ -284,6 +275,5 @@ You would place this inside either the `leftColumn` or `rightColumn` array. } // highlight-end ], -`} - +``` diff --git a/docs/developer/form-field-plugins/developer-details.md b/docs/developer/form-field-plugins/developer-details.md index 86b30531d9..cce32947ce 100644 --- a/docs/developer/form-field-plugins/developer-details.md +++ b/docs/developer/form-field-plugins/developer-details.md @@ -4,11 +4,9 @@ sidebar_label: Developer details id: developer-details --- -Here are some details for developers who want to develop a form field plugin for the DHIS2 Capture app. - A form field plugin runs in a sandboxed environment, meaning it can only read and write data that it's been configured to have access to. -If the plugin is given access to a field, we provide any relevant values, metadata, and rules engine output for that field. -We also provide some context about the application state, mainly if the plugin is in view or edit mode, or if the form has been attempted submitted. +If the plugin is given access to a field, all relevant values, metadata, and rules engine output for that field is provided. +Also the context about the application state is provided, mainly if the plugin is in view or edit mode, or if the form has been attempted to be submitted. If a plugin tries to update a field that it has not been given access to, an appropriate error message will be displayed in the console. diff --git a/docs/developer/getting-started.md b/docs/developer/getting-started.md index 6fcd7ead9f..e25b294434 100644 --- a/docs/developer/getting-started.md +++ b/docs/developer/getting-started.md @@ -6,6 +6,10 @@ The plugin framework is currently an experimental feature and is subject to chan We are working on improving both the technology and the way you use it. We will provide more documentation and examples as we progress. ::: +:::info Supported versions +The plugin framework is supported in **DHIS2 version 40.5 and later**. +::: + ## What are plugins? Plugins are a way to extend the functionality of our core applications within the DHIS2 ecosystem. These plugins will act and feel like native widgets / components, and allow you to write custom code that will be injected into the core applications, diff --git a/docs/user/using-the-capture-app.md b/docs/user/using-the-capture-app.md index 1d64b1a4e2..fab4c41175 100644 --- a/docs/user/using-the-capture-app.md +++ b/docs/user/using-the-capture-app.md @@ -594,7 +594,7 @@ Events can be assigned to users. This feature must be enabled per program. 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 } +### Assignee in the event list In the event list you will be able to view the assignee per event. Moreover, you can sort and filter the list by the assignee. @@ -804,7 +804,7 @@ You can show data elements from a single stage in a working list. Select the "Pr ![](resources/images/program_stage_working_list.png) -The tracker program stage list can be [filtered](#filter-the-list), [sorted](#sort-the-list), [modified](#modify-the-list-layout), [saved](#capture_view_save), [updated](#capture_view_update), [deleted](#capture_view_delete) and [shared](#capture_view_share) in the same way as other working lists. +The tracker program stage list can be [filtered](#filter-the-list), [sorted](#sort-the-list), [modified](#modify-the-list-layout), [saved](#capture_view_save), [updated](#capture_view_update), [deleted](#capture_view_delete) and [shared](#capture_view_share) in the same way as other working lists. Additionally, the program stage list can be [filtered by assignee](#assignee-in-the-event-list), just like an event program list. ## Implementer / administrator info { #implementer_info } @@ -821,20 +821,6 @@ For performance reasons the Capture app caches metadata in the client browser. W ## Enrollment dashboard -### Enabling the enrollment dashboard - -#### Opt in - -Enable the enrollment dashboard for a Tracker program for all the users. The dialog is visible for users with program write access. - -![](resources/images/enrollment-dash-opt-in.png) - -#### Opt out - -Disable the enrollment dashboard for a Tracker program for all the users. - -![](resources/images/enrollment-dash-opt-out.png) - ### Reaching the enrollment dashboard via url You reach the enrollment dashboard either by typing in the address bar of your browser or using the user interface of the capture app. diff --git a/i18n/ar_IQ.po b/i18n/ar_IQ.po index cbeeaaf0e3..13422d6d58 100644 --- a/i18n/ar_IQ.po +++ b/i18n/ar_IQ.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: KRG HIS , 2024\n" "Language-Team: Arabic (Iraq) (https://app.transifex.com/hisp-uio/teams/100509/ar_IQ/)\n" @@ -602,15 +602,6 @@ msgstr "البرنامج غير موجود" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "متصل" - -msgid "Offline" -msgstr "غير متصل" - -msgid "Syncing" -msgstr "تزامن" - msgid "Add note" msgstr "" @@ -1251,12 +1242,6 @@ msgstr "" msgid "Follow-up" msgstr "" -msgid "Started at {{orgUnitName}}" -msgstr "" - -msgid "Owned by {{ownerOrgUnit}}" -msgstr "" - msgid "Cancelled" msgstr "تم الإلغاء" @@ -1482,6 +1467,23 @@ msgstr "" msgid "New {{ eventName }} event" msgstr "" +msgid "An error occurred while deleting the event" +msgstr "" + +msgid "" +"Deleting an event is permanent and cannot be undone. Are you sure you want " +"to delete this event?" +msgstr "" + +msgid "An error occurred when updating event status" +msgstr "" + +msgid "Unskip" +msgstr "" + +msgid "Skip" +msgstr "" + msgid "To open this event, please wait until saving is complete" msgstr "" diff --git a/i18n/ckb.po b/i18n/ckb.po index 1a33d92772..851ae43bd0 100644 --- a/i18n/ckb.po +++ b/i18n/ckb.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Philip Larsen Donnelly, 2024\n" "Language-Team: Central Kurdish (https://app.transifex.com/hisp-uio/teams/100509/ckb/)\n" @@ -607,15 +607,6 @@ msgstr "پرۆگرامەکە بوونی نیە" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "ئۆنڵاین" - -msgid "Offline" -msgstr "ئۆفڵاین" - -msgid "Syncing" -msgstr "هاوتاکردن" - msgid "Add note" msgstr "" @@ -1254,12 +1245,6 @@ msgstr "" msgid "Follow-up" msgstr "" -msgid "Started at {{orgUnitName}}" -msgstr "" - -msgid "Owned by {{ownerOrgUnit}}" -msgstr "" - msgid "Cancelled" msgstr "" @@ -1477,6 +1462,23 @@ msgstr "" msgid "New {{ eventName }} event" msgstr "" +msgid "An error occurred while deleting the event" +msgstr "" + +msgid "" +"Deleting an event is permanent and cannot be undone. Are you sure you want " +"to delete this event?" +msgstr "" + +msgid "An error occurred when updating event status" +msgstr "" + +msgid "Unskip" +msgstr "" + +msgid "Skip" +msgstr "" + msgid "To open this event, please wait until saving is complete" msgstr "" diff --git a/i18n/cs.po b/i18n/cs.po index 040d421b6b..496af4cba9 100644 --- a/i18n/cs.po +++ b/i18n/cs.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Jiří Podhorecký , 2024\n" "Language-Team: Czech (https://app.transifex.com/hisp-uio/teams/100509/cs/)\n" @@ -625,53 +625,6 @@ msgstr "Oznámení" msgid "Close the notice" msgstr "Zavřít oznámení" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "Použít nový ovládací panel zápisu pro {{programName}}" - -msgid "Opt in for {{programName}}" -msgstr "Přihlásit se do {{programName}}" - -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 "" -"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" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "Přestat používat nový ovládací panel zápisu pro {{programName}}" - -msgid "Opt out for {{programName}}" -msgstr "Odhlásit se z {{programName}}" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "Zápis s ID \"{{enrollmentId}}\" neexistuje" @@ -766,9 +719,6 @@ msgstr "Zobrazit pracovní seznam v tomto programu." msgid "Page is missing required values from URL" msgstr "Na stránce chybí požadované hodnoty z adresy URL" -msgid "Program is not valid" -msgstr "Program není platný" - msgid "Org unit is not valid with current program" msgstr "Organizační jednotka není platná pro aktuální program" @@ -1285,6 +1235,12 @@ msgstr "Widget pro zápis nelze načíst. Prosím zkuste to znovu později" msgid "Follow-up" msgstr "Následovat" +msgid "Started at{{escape}}" +msgstr "" + +msgid "Owned by{{escape}}" +msgstr "" + msgid "Cancelled" msgstr "Zrušeno" @@ -1489,13 +1445,6 @@ msgstr "{{ linkableStageLabel }} nemá žádné propojitelné události" msgid "Ambiguous relationships, contact system administrator" msgstr "Nejednoznačné vztahy, kontaktujte správce systému" -msgid "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." -msgstr "" -"V dalším kroku po vyplnění této stránky {{currentStageLabel}} zadejte údaje " -"{{linkableStageLabel}}." - msgid "Enter details now" msgstr "Zadejte nyní podrobnosti" @@ -1580,6 +1529,9 @@ msgstr "Seznam změn" msgid "No changes to display" msgstr "" +msgid "Updated" +msgstr "Aktualizováno" + msgid "Created" msgstr "Vytvořeno" @@ -1598,6 +1550,9 @@ msgstr "Datová položka" msgid "Change" msgstr "" +msgid "Value" +msgstr "" + msgid "New {{trackedEntityTypeName}} relationship" msgstr "" diff --git a/i18n/en.pot b/i18n/en.pot index d299bcedcf..5fb403e3d7 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-09-02T11:08:16.281Z\n" -"PO-Revision-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-25T18:18:11.518Z\n" +"PO-Revision-Date: 2024-10-25T18:18:11.518Z\n" msgid "Choose one or more dates..." msgstr "Choose one or more dates..." @@ -616,54 +616,6 @@ msgstr "Notice" msgid "Close the notice" msgstr "Close the notice" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "Use new Enrollment dashboard for {{programName}}" - -msgid "Opt in for {{programName}}" -msgstr "Opt in for {{programName}}" - -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 "" -"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." - -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 "" -"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." - -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 "" -"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." - -msgid "Yes, opt in" -msgstr "Yes, opt in" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "Stop using new Enrollment dashboard for {{programName}}" - -msgid "Opt out for {{programName}}" -msgstr "Opt out for {{programName}}" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "Enrollment with id \"{{enrollmentId}}\" does not exist" @@ -753,9 +705,6 @@ msgstr "View working list in this program." msgid "Page is missing required values from URL" msgstr "Page is missing required values from URL" -msgid "Program is not valid" -msgstr "Program is not valid" - msgid "Org unit is not valid with current program" msgstr "Org unit is not valid with current program" @@ -1184,6 +1133,9 @@ msgstr "Mark as cancelled" msgid "Mark incomplete" msgstr "Mark incomplete" +msgid "You do not have access to delete this enrollment" +msgstr "You do not have access to delete this enrollment" + msgid "Delete enrollment" msgstr "Delete enrollment" @@ -1272,6 +1224,12 @@ msgstr "Enrollment widget could not be loaded. Please try again later" msgid "Follow-up" msgstr "Follow-up" +msgid "Started at{{escape}}" +msgstr "Started at{{escape}}" + +msgid "Owned by{{escape}}" +msgstr "Owned by{{escape}}" + msgid "Cancelled" msgstr "Cancelled" @@ -1462,13 +1420,6 @@ msgstr "{{ linkableStageLabel }} has no linkable events" msgid "Ambiguous relationships, contact system administrator" msgstr "Ambiguous relationships, contact system administrator" -msgid "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." -msgstr "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." - msgid "Enter details now" msgstr "Enter details now" @@ -1553,6 +1504,9 @@ msgstr "Changelog" msgid "No changes to display" msgstr "No changes to display" +msgid "Updated" +msgstr "Updated" + msgid "Created" msgstr "Created" @@ -1571,6 +1525,9 @@ msgstr "Data item" msgid "Change" msgstr "Change" +msgid "Value" +msgstr "Value" + msgid "New {{trackedEntityTypeName}} relationship" msgstr "New {{trackedEntityTypeName}} relationship" diff --git a/i18n/es.po b/i18n/es.po index f102174f36..62ee25e726 100644 --- a/i18n/es.po +++ b/i18n/es.po @@ -14,13 +14,14 @@ # Viktor Varland , 2024 # Marta Vila , 2024 # Juan M Alcantara Acosta , 2024 +# Manuel Silva , 2024 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Juan M Alcantara Acosta , 2024\n" +"Last-Translator: Manuel Silva , 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" @@ -646,54 +647,6 @@ msgstr "Aviso" msgid "Close the notice" msgstr "cerrar el aviso" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "Usar el nuevo panel de inscripción para {{programName}}" - -msgid "Opt in for {{programName}}" -msgstr "Utilizar el nuevo capture para {{programName}}" - -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 "" -"Al hacer clic en registrarse a continuación, comenzará a utilizar el nuevo " -"panel de inscripción en la aplicación Capture para este programa. Por el " -"momento, hay ciertas funciones de la Tracker Capture que aún no se han " -"agregado, incluida la función de relación y referencia. El trabajo para " -"incluir esta funcionalidad Tracker en Capture está en curso y se agregará en" -" próximos lanzamientos de la aplicación." - -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 "" -"El equipo de desarrollo agradece cualquier comentario sobre esta nueva " -"funcionalidad que actualmente se está probando en versión beta. Informe " -"cualquier problema y comentario en el proyecto de JIRA de DHIS2" - -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 "" -"Haga clic en el botón de abajo para optar por la nueva funcionalidad del " -"panel de inscripción en la aplicación Capture (beta) para este programa " -"Tracker para todos los usuarios." - -msgid "Yes, opt in" -msgstr "Sí, aceptar" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "Deje de usar el nuevo panel de inscripción para {{programName}}" - -msgid "Opt out for {{programName}}" -msgstr "Salir de la prueba del nuevo Capture {{programName}}" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "La inscripción con el ID \"{{enrollmentId}}\" no existe" @@ -791,9 +744,6 @@ msgstr "Ver lista de trabajo en este programa." msgid "Page is missing required values from URL" msgstr "A la página le faltan los valores obligatorios de la URL" -msgid "Program is not valid" -msgstr "El programa no es válido" - msgid "Org unit is not valid with current program" msgstr "La unidad organizativa no es válida con el programa actual" @@ -1324,6 +1274,12 @@ msgstr "" msgid "Follow-up" msgstr "Seguimiento" +msgid "Started at{{escape}}" +msgstr "" + +msgid "Owned by{{escape}}" +msgstr "" + msgid "Cancelled" msgstr "Cancelar" @@ -1537,13 +1493,6 @@ msgid "Ambiguous relationships, contact system administrator" msgstr "" "Relaciones ambiguas, póngase en contacto con el administrador del sistema" -msgid "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." -msgstr "" -"Introduzca los detalles de {{linkableStageLabel}} en el siguiente paso " -"después de completar este {{currentStageLabel}}." - msgid "Enter details now" msgstr "Introducir datos ahora" @@ -1631,6 +1580,9 @@ msgstr "Registro de cambios" msgid "No changes to display" msgstr "No hay cambios para mostrar" +msgid "Updated" +msgstr "Actualizado" + msgid "Created" msgstr "Creado" @@ -1649,6 +1601,9 @@ msgstr "Elemento de datos" msgid "Change" msgstr "Cambio" +msgid "Value" +msgstr "" + msgid "New {{trackedEntityTypeName}} relationship" msgstr "Nueva relación de {{trackedEntityTypeName}}" diff --git a/i18n/es_419.po b/i18n/es_419.po index 1007032b9c..c94ef95e6a 100644 --- a/i18n/es_419.po +++ b/i18n/es_419.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Jaime Bosque , 2024\n" "Language-Team: Spanish (Latin America) (https://app.transifex.com/hisp-uio/teams/100509/es_419/)\n" @@ -617,15 +617,6 @@ msgstr "El programa no existe" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "En línea" - -msgid "Offline" -msgstr "Offline" - -msgid "Syncing" -msgstr "Sincronizando" - msgid "Add note" msgstr "Añadir nota" @@ -644,54 +635,6 @@ msgstr "Aviso" msgid "Close the notice" msgstr "cerrar el aviso" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "Usar el nuevo panel de inscripción para {{programName}}" - -msgid "Opt in for {{programName}}" -msgstr "Opt in para el programa {{programName}}" - -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 "" -"Al hacer clic en registrarse, comenzará a utilizar el nuevo panel de " -"inscripción en Capture para este programa. Por el momento, hay ciertas " -"funciones de la Tracker Capture que aún no se han agregado, incluida la " -"función de relación y referencia. El trabajo para incluir esta funcionalidad" -" Tracker en Capture está en curso y se agregará en próximos lanzamientos de " -"la aplicación." - -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 "" -"El equipo de desarrollo agradece cualquier comentario sobre esta nueva " -"funcionalidad que actualmente se está probando en versión beta. Informe " -"cualquier problema y comentario en el proyecto de JIRA de DHIS2." - -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 "" -"Haga clic en el botón de abajo para optar por la nueva funcionalidad del " -"panel de inscripción en la aplicación Capture (beta) para este programa " -"Tracker para todos los usuarios." - -msgid "Yes, opt in" -msgstr "Sí, opt in" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "Deje de usar el nuevo panel de inscripción para {{programName}}" - -msgid "Opt out for {{programName}}" -msgstr "Dejar de probar la nueva app con el programa \"{{programName}}\"" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "La inscripción con id \"{{enrollmentId}}\" no existe" @@ -789,9 +732,6 @@ msgstr "Ver lista de trabajo en este programa." msgid "Page is missing required values from URL" msgstr "A la página le faltan los valores obligatorios de la URL" -msgid "Program is not valid" -msgstr "El programa no es válido" - msgid "Org unit is not valid with current program" msgstr "La unidad organizativa no es válida con el programa actual" @@ -1293,10 +1233,10 @@ msgstr "" msgid "Follow-up" msgstr "" -msgid "Started at {{orgUnitName}}" +msgid "Started at{{escape}}" msgstr "" -msgid "Owned by {{ownerOrgUnit}}" +msgid "Owned by{{escape}}" msgstr "" msgid "Cancelled" @@ -1489,11 +1429,6 @@ msgstr "" msgid "Ambiguous relationships, contact system administrator" msgstr "" -msgid "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." -msgstr "" - msgid "Enter details now" msgstr "" @@ -1577,6 +1512,9 @@ msgstr "" msgid "No changes to display" msgstr "" +msgid "Updated" +msgstr "" + msgid "Created" msgstr "" @@ -1595,6 +1533,9 @@ msgstr "" msgid "Change" msgstr "" +msgid "Value" +msgstr "" + msgid "New {{trackedEntityTypeName}} relationship" msgstr "" diff --git a/i18n/fr.po b/i18n/fr.po index f74f7e4d77..3effbc2fc8 100644 --- a/i18n/fr.po +++ b/i18n/fr.po @@ -10,13 +10,14 @@ # Viktor Varland , 2024 # Yayra Gomado , 2024 # Bram Piot , 2024 +# Jason Pickering , 2024 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Bram Piot , 2024\n" +"Last-Translator: Jason Pickering , 2024\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" @@ -644,45 +645,6 @@ msgstr "" msgid "Close the notice" msgstr "" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "" -"Utiliser un nouveau tableau de bord d'inscription pour {{programName}}" - -msgid "Opt in for {{programName}}" -msgstr "Choisir {{programName}}" - -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" -msgstr "Oui, choisir" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "" -"Ne plus utiliser le tableau de bord des nouvelles inscriptions pour " -"{{programName}}" - -msgid "Opt out for {{programName}}" -msgstr "Ne pas chosir {{programName}}" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "L'inscription avec id \"{{enrollmentId}}\" n'existe pas" @@ -778,9 +740,6 @@ msgstr "Afficher la liste de travail dans ce programme." msgid "Page is missing required values from URL" msgstr "Des valeurs obligatoires ne figurent pas dans l'URL de la page" -msgid "Program is not valid" -msgstr "Le programme n'est pas valide" - msgid "Org unit is not valid with current program" msgstr "L'unité d'organisation n'est pas valide avec le programme actuel" @@ -1295,6 +1254,12 @@ msgstr "" msgid "Follow-up" msgstr "Suivi" +msgid "Started at{{escape}}" +msgstr "" + +msgid "Owned by{{escape}}" +msgstr "" + msgid "Cancelled" msgstr "Annulé" @@ -1504,11 +1469,6 @@ msgstr "" msgid "Ambiguous relationships, contact system administrator" msgstr "" -msgid "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." -msgstr "" - msgid "Enter details now" msgstr "Saisir les détails maintenant" @@ -1593,6 +1553,9 @@ msgstr "" msgid "No changes to display" msgstr "" +msgid "Updated" +msgstr "Mis-à-jour" + msgid "Created" msgstr "Créé" @@ -1611,6 +1574,9 @@ msgstr "Item de données" msgid "Change" msgstr "Modifier" +msgid "Value" +msgstr "" + msgid "New {{trackedEntityTypeName}} relationship" msgstr "" diff --git a/i18n/id.po b/i18n/id.po index 7c64de57cb..1cf72fa6a2 100644 --- a/i18n/id.po +++ b/i18n/id.po @@ -8,15 +8,15 @@ # ratih syabrina, 2024 # Yusuf Setiawan , 2024 # Guardian Sanjaya , 2024 -# Viktor Varland , 2024 # Aprisa Chrysantina , 2024 +# Viktor Varland , 2024 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Aprisa Chrysantina , 2024\n" +"Last-Translator: Viktor Varland , 2024\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" @@ -630,42 +630,6 @@ msgstr "" msgid "Close the notice" msgstr "" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "Gunakan dasbor pendaftaran baru pada {{programName}}" - -msgid "Opt in for {{programName}}" -msgstr "" - -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" -msgstr "" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "Berhenti menggunakan dasbor pendafataran baru pada {{programName}}" - -msgid "Opt out for {{programName}}" -msgstr "" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "Pendaftaran dengan id \"{{enrollmentId}}\" tidak tersedia" @@ -758,9 +722,6 @@ msgstr "Lihat daftar kerja dalam program ini." msgid "Page is missing required values from URL" msgstr "Halaman kehilangan nilai yang diutuhkan dari URL" -msgid "Program is not valid" -msgstr "Program tidak valid" - msgid "Org unit is not valid with current program" msgstr "" @@ -1263,6 +1224,12 @@ msgstr "Widget pendaftaran tidak dapat dimuat. Silakan coba lagi nanti" msgid "Follow-up" msgstr "Mengikuti" +msgid "Started at{{escape}}" +msgstr "" + +msgid "Owned by{{escape}}" +msgstr "" + msgid "Cancelled" msgstr "Dibatalkan" @@ -1449,11 +1416,6 @@ msgstr "" msgid "Ambiguous relationships, contact system administrator" msgstr "" -msgid "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." -msgstr "" - msgid "Enter details now" msgstr "" @@ -1535,6 +1497,9 @@ msgstr "" msgid "No changes to display" msgstr "" +msgid "Updated" +msgstr "Diperbarui" + msgid "Created" msgstr "Dibuat" @@ -1553,6 +1518,9 @@ msgstr "Data item" msgid "Change" msgstr "" +msgid "Value" +msgstr "Nilai" + msgid "New {{trackedEntityTypeName}} relationship" msgstr "" diff --git a/i18n/km.po b/i18n/km.po index 04fa91cdc5..ec9c3dac3e 100644 --- a/i18n/km.po +++ b/i18n/km.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Viktor Varland , 2024\n" "Language-Team: Khmer (https://app.transifex.com/hisp-uio/teams/100509/km/)\n" @@ -589,15 +589,6 @@ msgstr "" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "លើបណ្ដាញអិនធឺរណែត" - -msgid "Offline" -msgstr "ក្រៅ​បណ្ដាញអិនធឺរណែត" - -msgid "Syncing" -msgstr "" - msgid "Add note" msgstr "បន្ថែមការកត់ចំណាំ" @@ -1233,12 +1224,6 @@ msgstr "" msgid "Follow-up" msgstr "តាមដាន" -msgid "Started at {{orgUnitName}}" -msgstr "" - -msgid "Owned by {{ownerOrgUnit}}" -msgstr "" - msgid "Cancelled" msgstr "បានលុបចោល" @@ -1454,6 +1439,23 @@ msgstr "" msgid "New {{ eventName }} event" msgstr "" +msgid "An error occurred while deleting the event" +msgstr "" + +msgid "" +"Deleting an event is permanent and cannot be undone. Are you sure you want " +"to delete this event?" +msgstr "" + +msgid "An error occurred when updating event status" +msgstr "" + +msgid "Unskip" +msgstr "" + +msgid "Skip" +msgstr "" + msgid "To open this event, please wait until saving is complete" msgstr "" diff --git a/i18n/lo.po b/i18n/lo.po index 24d7ea4464..4decb60044 100644 --- a/i18n/lo.po +++ b/i18n/lo.po @@ -1,18 +1,18 @@ # # Translators: # Philip Larsen Donnelly, 2022 -# Saysamone Sibounma, 2023 # Somkhit Bouavong , 2024 # Thuy Nguyen , 2024 # Viktor Varland , 2024 # Namwan Chanthavisouk, 2024 +# Saysamone Sibounma, 2024 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Namwan Chanthavisouk, 2024\n" +"Last-Translator: Saysamone Sibounma, 2024\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" @@ -623,51 +623,6 @@ msgstr "ການແຈ້ງເຕືອນ" msgid "Close the notice" msgstr "ປິດການແຈ້ງເຕືອນ" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "ໃຊ້ກະດານຂ່າວລົງທະບຽນໃໝ່ເພື່ອ {{programName}}" - -msgid "Opt in for {{programName}}" -msgstr "ຕົວເລືອກໃນ {{programName}}" - -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 "" -"ໂດຍການຄລິກເລືອກເຂົ້າທາງລຸ່ມນີ້, ທ່ານຈະເລີ່ມໃຊ້ກະດານຂ່າວລົງທະບຽນໃໝ່ໃນແອັບ " -"Capture ສຳລັບໂປແກຣມຕິດຕາມນີ້. ເຊິ່ງໃນປັດຈຸບັນໜ້າທີ່ຫຼັກຈາກການຕິດຕາມ Capture " -"ແມ່ນຍັງບໍ່ໄດ້ເພີ່ມເຂົ້າເທື່ອ, ລວມທັງເຊື່ອມໂຍງ ແລະ ການສົ່ງຕໍ່. " -"ການເຮັດວຽກກ່ຽວກັບໜ້າທີ່ຫຼັກຈາກການຕິດຕາມນີ້ໃນ Capture ແມ່ນກໍາລັງດໍາເນີນຢູ່ " -"ແລະ ຈະຖືກເພີ່ມເຂົ້າໃນແອັບໃໝ່." - -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 "" -"ທີມງານເຮົາຂໍຂອບໃຈສຳລັບຄໍາຕິຊົມກ່ຽວກັບຫນ້າທີ່ໃຫມ່ນີ້ທີ່ກໍາລັງຖືກທົດສອບຢູ່ໃນເບຕ້າ," -" ກະລຸນາລາຍງານບັນຫາ ແລະ ຄໍາຕິຊົມໃນໂຄງການ 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 "" -"ຄລິກທີ່ປຸ່ມຂ້າງລຸ່ມເພື່ອເລືອກເຂົ້າໃຊ້ໜ້າທີ່ການລົງທະບຽນໃໝ່ຂອງກະດານຂ່າວໃນແອັບ " -"Capture (ເບຕ້າ) ສຳລັບໂປແກຣມການຕິດຕາມນີ້ສຳລັບຜູ້ໃຊ້ທັງໝົດ." - -msgid "Yes, opt in" -msgstr "ຕົກລົງ, ເລືອກເຂົ້າ" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "ຢຸດໃຊ້ກະດານຂ່າວການລົງທະບຽນໃໝ່ໃນ {{programName}}" - -msgid "Opt out for {{programName}}" -msgstr "ເລືອກອອກສຳລັບ {{programName}}" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "ລົງທະບຽນດ້ວຍໄອດີ \" {{enrollmentId}} \" ແມ່ນບໍ່ພົບ" @@ -758,9 +713,6 @@ msgstr "ເບິ່ງລາຍຊື່ເຮັດວຽກຢູ່ໃນໂ msgid "Page is missing required values from URL" msgstr "ບໍ່ພົບໜ້ານີ້ ຕ້ອງການຄ່າຈາກ URL" -msgid "Program is not valid" -msgstr "ໂປຣແກຼມບໍ່ຖືກຕ້ອງ" - msgid "Org unit is not valid with current program" msgstr "ຫົວໜ່ວຍການຈັດຕັ້ງບໍ່ຖືກຕ້ອງກັບໂປແກຼມນີ້" @@ -1266,6 +1218,12 @@ msgstr "ບໍ່ສາມາດໂຫຼດລາຍການການລົງ msgid "Follow-up" msgstr "ຕິດຕາມ" +msgid "Started at{{escape}}" +msgstr "" + +msgid "Owned by{{escape}}" +msgstr "" + msgid "Cancelled" msgstr "ຍົກເລີກແລ້ວ" @@ -1459,13 +1417,6 @@ msgstr "{{ linkableStageLabel }} ບໍ່ມີເຫດການທີ່ສ msgid "Ambiguous relationships, contact system administrator" msgstr "ການເຊື່ອມໂຍງບໍ່ຊັດເຈນ, ຕິດຕໍ່ຜູ້ດູແລລະບົບ" -msgid "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." -msgstr "" -"ໃສ່ລາຍລະອຽດ {{linkableStageLabel}} ໃນຂັ້ນຕອນຕໍ່ໄປຫຼັງຈາກເຮັດສໍາເລັດ " -"{{currentStageLabel}} ນີ້." - msgid "Enter details now" msgstr "ປ້ອນລາຍລະອຽດ" @@ -1549,6 +1500,9 @@ msgstr "ບັນທຶກການປ່ຽນແປງ" msgid "No changes to display" msgstr "ບໍ່ມີການປ່ຽນແປງທີ່ຈະສະແດງ" +msgid "Updated" +msgstr "" + msgid "Created" msgstr "ສ້າງແລ້ວ" @@ -1567,6 +1521,9 @@ msgstr "ລາຍການຂໍ້ມູນ" msgid "Change" msgstr "ປ່ຽນ" +msgid "Value" +msgstr "ຄ່າ" + msgid "New {{trackedEntityTypeName}} relationship" msgstr "ຄວາມສໍາພັນໃໝ່ {{trackedEntityTypeName}} " diff --git a/i18n/nb.po b/i18n/nb.po index 7f32ad1482..6b566e538a 100644 --- a/i18n/nb.po +++ b/i18n/nb.po @@ -1,15 +1,15 @@ # # Translators: # Karoline Tufte Lien , 2024 -# Caroline Hesthagen Holen , 2024 # Merethe Wollan Blisten, 2024 +# Caroline Hesthagen Holen , 2024 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Merethe Wollan Blisten, 2024\n" +"Last-Translator: Caroline Hesthagen Holen , 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" @@ -626,54 +626,6 @@ msgstr "Merknad" msgid "Close the notice" msgstr "Lukk merknaden" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "Bruk nytt registreringsdashbord for {{programName}}" - -msgid "Opt in for {{programName}}" -msgstr "Meld på for {{programName}}" - -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 "" -"Ved å klikke på \"meld på\" nedenfor, vil du begynne å bruke det nye " -"registreringsdashbordet i Capture-appen for dette Tracker-programmet. For " -"øyeblikket er det noe funksjonalitet fra Tracker Capture som ennå ikke er " -"lagt til, inkludert relasjons- og henvisningsfunksjonalitet. Arbeidet med å " -"inkludere denne Tracker-funksjonaliteten i Capture pågår og vil bli lagt til" -" i kommende apputgivelser." - -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 "" -"Kjerneteamet setter pris på all tilbakemelding på denne nye funksjonaliteten" -" som for øyeblikket blir betatestet, vennligst rapporter eventuelle " -"problemer og tilbakemeldinger i DHIS2 JIRA-prosjektet." - -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 "" -"Klikk på knappen nedenfor for å melde deg på den nye funksjonen for " -"registreringsdashbord i Capture-appen (beta) for dette Tracker-programmet " -"for alle brukere." - -msgid "Yes, opt in" -msgstr "Ja, meld på" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "Slutt å bruke nytt registreringsdashbord for {{programName}}" - -msgid "Opt out for {{programName}}" -msgstr "Meld ut for {{programName}}" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "Registrering med ID-en \"{{enrollmentId}}\" eksisterer ikke" @@ -769,9 +721,6 @@ msgstr "Se arbeidsliste i dette programmet." msgid "Page is missing required values from URL" msgstr "Siden mangler nødvendige verdier fra URL" -msgid "Program is not valid" -msgstr "Programmet er ikke gyldig" - msgid "Org unit is not valid with current program" msgstr "Organisasjonsenheten er ikke gyldig med gjeldende program" @@ -1290,6 +1239,12 @@ msgstr "Registreringsmodulen kunne ikke lastes inn. Prøv igjen senere" msgid "Follow-up" msgstr "Oppfølging" +msgid "Started at{{escape}}" +msgstr "" + +msgid "Owned by{{escape}}" +msgstr "" + msgid "Cancelled" msgstr "Kansellert" @@ -1492,13 +1447,6 @@ msgstr "{{ linkableStageLabel }} har ingen hendelser som kan kobles til" msgid "Ambiguous relationships, contact system administrator" msgstr "Uklare relasjoner, kontakt din systemadministrator" -msgid "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." -msgstr "" -"Skriv inn {{linkableStageLabel}}detaljer i neste trinn etter du har fullført" -" dette {{currentStageLabel}}." - msgid "Enter details now" msgstr "Skriv inn detaljer " @@ -1584,6 +1532,9 @@ msgstr "Endringslogg" msgid "No changes to display" msgstr "Ingen endringer å vise" +msgid "Updated" +msgstr "Oppdatert" + msgid "Created" msgstr "Opprettet" @@ -1602,6 +1553,9 @@ msgstr "Datapunkt" msgid "Change" msgstr "Endre" +msgid "Value" +msgstr "Verdi" + msgid "New {{trackedEntityTypeName}} relationship" msgstr "Ny {{trackedEntityTypeName}} relasjon" diff --git a/i18n/nl.po b/i18n/nl.po index 98e3e09bf6..9f88c8b400 100644 --- a/i18n/nl.po +++ b/i18n/nl.po @@ -3,15 +3,15 @@ # Cherise Beek , 2021 # Yury Rogachev , 2021 # Philip Larsen Donnelly, 2024 -# Rica, 2024 # Charel van den Elsen, 2024 +# Rica, 2024 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Charel van den Elsen, 2024\n" +"Last-Translator: Rica, 2024\n" "Language-Team: Dutch (https://app.transifex.com/hisp-uio/teams/100509/nl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -632,57 +632,6 @@ msgstr "" msgid "Close the notice" msgstr "" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "Gebruik nieuw inschrijvingsdashboard voor {{programName}}" - -msgid "Opt in for {{programName}}" -msgstr "Aanmelden voor {{programName}}" - -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 "" -"Door hieronder op opt-in te klikken, gaat u het nieuwe " -"inschrijvingsdashboard in de Capture-app voor dit Tracker-programma " -"gebruiken. Op dit moment is er bepaalde functionaliteit van Tracker Capture " -"die nog niet is toegevoegd, waaronder relatie- en " -"verwijzingsfunctionaliteit. Het werk om deze Tracker-functionaliteit in " -"Capture op te nemen is aan de gang en zal worden toegevoegd in aankomende " -"app-releases." - -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 "" -"Het kernteam stelt alle feedback op prijs over deze nieuwe functionaliteit " -"die momenteel in bèta wordt getest. Meld eventuele problemen en feedback in " -"het DHIS2 JIRA-project." - -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 "" -"Klik op de onderstaande knop om u aan te melden voor de nieuwe " -"functionaliteit van het inschrijvingsdashboard in de Capture-app (bèta) voor" -" dit Tracker-programma voor alle gebruikers." - -msgid "Yes, opt in" -msgstr "Ja, opt-in" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "" -"Stop met het gebruik van het nieuwe inschrijvingsdashboard voor " -"{{programName}}" - -msgid "Opt out for {{programName}}" -msgstr "Afmelden voor {{programName}}" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "" @@ -781,9 +730,6 @@ msgstr "Bekijk werklijst in dit programma." msgid "Page is missing required values from URL" msgstr "Pagina mist vereiste waarden van URL" -msgid "Program is not valid" -msgstr "Programma is niet geldig" - msgid "Org unit is not valid with current program" msgstr "Organisatie-eenheid is niet geldig met het huidige programma" @@ -1301,6 +1247,12 @@ msgstr "" msgid "Follow-up" msgstr "Opvolgen" +msgid "Started at{{escape}}" +msgstr "" + +msgid "Owned by{{escape}}" +msgstr "" + msgid "Cancelled" msgstr "Geannuleerd" @@ -1504,11 +1456,6 @@ msgstr "" msgid "Ambiguous relationships, contact system administrator" msgstr "" -msgid "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." -msgstr "" - msgid "Enter details now" msgstr "" @@ -1592,6 +1539,9 @@ msgstr "" msgid "No changes to display" msgstr "" +msgid "Updated" +msgstr "" + msgid "Created" msgstr "Gemaakt" @@ -1610,6 +1560,9 @@ msgstr "Gegevensitem" msgid "Change" msgstr "" +msgid "Value" +msgstr "Waarde" + msgid "New {{trackedEntityTypeName}} relationship" msgstr "" diff --git a/i18n/prs.po b/i18n/prs.po index 89f3234f12..9b6cbf8306 100644 --- a/i18n/prs.po +++ b/i18n/prs.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Philip Larsen Donnelly, 2024\n" "Language-Team: Persian (Afghanistan) (https://app.transifex.com/hisp-uio/teams/100509/fa_AF/)\n" @@ -588,15 +588,6 @@ msgstr "" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "آنلاین" - -msgid "Offline" -msgstr "آفلاین" - -msgid "Syncing" -msgstr "" - msgid "Add note" msgstr "افزودن یاداشت" @@ -1233,12 +1224,6 @@ msgstr "" msgid "Follow-up" msgstr "تعقیب کردن" -msgid "Started at {{orgUnitName}}" -msgstr "" - -msgid "Owned by {{ownerOrgUnit}}" -msgstr "" - msgid "Cancelled" msgstr "" diff --git a/i18n/ps.po b/i18n/ps.po index 31f1707af2..38518df9a7 100644 --- a/i18n/ps.po +++ b/i18n/ps.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Viktor Varland , 2024\n" "Language-Team: Pashto (https://app.transifex.com/hisp-uio/teams/100509/ps/)\n" @@ -589,15 +589,6 @@ msgstr "" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "په لیکه کې دی" - -msgid "Offline" -msgstr "په لیکه کې نشته" - -msgid "Syncing" -msgstr "" - msgid "Add note" msgstr "نوټ ور اضافه کړئ" @@ -1234,12 +1225,6 @@ msgstr "" msgid "Follow-up" msgstr "" -msgid "Started at {{orgUnitName}}" -msgstr "" - -msgid "Owned by {{ownerOrgUnit}}" -msgstr "" - msgid "Cancelled" msgstr "لغوه شوی" diff --git a/i18n/pt.po b/i18n/pt.po index 7531dccfa4..0f02ab2cdc 100644 --- a/i18n/pt.po +++ b/i18n/pt.po @@ -7,13 +7,14 @@ # Sheila André , 2024 # Ge Joao , 2024 # Viktor Varland , 2024 +# Juan M Alcantara Acosta , 2024 # msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" -"Last-Translator: Viktor Varland , 2024\n" +"Last-Translator: Juan M Alcantara Acosta , 2024\n" "Language-Team: Portuguese (https://app.transifex.com/hisp-uio/teams/100509/pt/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -616,15 +617,6 @@ msgstr "Programa não existe" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "Ligado" - -msgid "Offline" -msgstr "Desligado" - -msgid "Syncing" -msgstr "Sincronizando" - msgid "Add note" msgstr "Adicionar uma nota" @@ -643,54 +635,6 @@ msgstr "Aviso" msgid "Close the notice" msgstr "Fechar o aviso" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "Use o novo painel de inscrição para {{programName}}" - -msgid "Opt in for {{programName}}" -msgstr "Opte por {{programName}}" - -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 "" -"Ao clicar em aceitar abaixo, começará a usar o novo painel de registro no " -"aplicativo Capture para este programa Rastreador. No momento, há certas " -"funcionalidades do Tracker Capture que ainda não foram adicionadas, " -"incluindo funcionalidade de relacionamento e referência. O trabalho para " -"incluir essa funcionalidade do Rastreador no Capture está em andamento e " -"será adicionado nas próximas versões do aplicativo." - -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 "" -"A equipe principal agradece qualquer feedback sobre esta nova funcionalidade" -" que está sendo testada na versão beta. Relate quaisquer problemas e " -"comentários no projeto 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 "" -"Clique no botão abaixo para aceitar a nova funcionalidade do painel de " -"registro no aplicativo Capture (beta) para este programa Rastreador para " -"todos os utilizadores." - -msgid "Yes, opt in" -msgstr "Sim, aceite" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "Pare de usar o novo painel de inscrição para {{programName}}" - -msgid "Opt out for {{programName}}" -msgstr "Desativar {{programName}}" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "" @@ -1594,7 +1538,7 @@ msgid "Scheduled" msgstr "Agendado" msgid "Changelog" -msgstr "" +msgstr "Registo de mudanças" msgid "No changes to display" msgstr "" diff --git a/i18n/pt_BR.po b/i18n/pt_BR.po index 00cd51c882..f33904fb18 100644 --- a/i18n/pt_BR.po +++ b/i18n/pt_BR.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Thiago Rocha, 2024\n" "Language-Team: Portuguese (Brazil) (https://app.transifex.com/hisp-uio/teams/100509/pt_BR/)\n" @@ -592,15 +592,6 @@ msgstr "" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "Ligado" - -msgid "Offline" -msgstr "Desligado" - -msgid "Syncing" -msgstr "" - msgid "Add note" msgstr "Adicionar uma nota" @@ -1238,12 +1229,6 @@ msgstr "" msgid "Follow-up" msgstr "Seguimento" -msgid "Started at {{orgUnitName}}" -msgstr "" - -msgid "Owned by {{ownerOrgUnit}}" -msgstr "" - msgid "Cancelled" msgstr "Cancelado" diff --git a/i18n/ro.po b/i18n/ro.po index 5c64022113..ee6543821a 100644 --- a/i18n/ro.po +++ b/i18n/ro.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Valeriu Plesca , 2024\n" "Language-Team: Romanian (https://app.transifex.com/hisp-uio/teams/100509/ro/)\n" @@ -603,15 +603,6 @@ msgstr "Programul nu există" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "Online" - -msgid "Offline" -msgstr "Offline" - -msgid "Syncing" -msgstr "Sincronizare" - msgid "Add note" msgstr "" @@ -630,42 +621,6 @@ msgstr "" msgid "Close the notice" msgstr "" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "" - -msgid "Opt in for {{programName}}" -msgstr "" - -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" -msgstr "" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "" - -msgid "Opt out for {{programName}}" -msgstr "Renunțare la {{programName}}" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "" diff --git a/i18n/ru.po b/i18n/ru.po index 01896cce66..68ea9d95c7 100644 --- a/i18n/ru.po +++ b/i18n/ru.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Philip Larsen Donnelly, 2024\n" "Language-Team: Russian (https://app.transifex.com/hisp-uio/teams/100509/ru/)\n" @@ -615,15 +615,6 @@ msgid "Selected program is invalid for selected organisation unit" msgstr "" "Выбранная программа недействительна для выбранной организационной единицы" -msgid "Online" -msgstr "Онлайн" - -msgid "Offline" -msgstr "Оффлайн" - -msgid "Syncing" -msgstr "Синхронизация" - msgid "Add note" msgstr "Добавить заметку" @@ -642,55 +633,6 @@ msgstr "Заметка" msgid "Close the notice" msgstr "Закрыть заметку" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "" -"Использовать новую регистрационную панель для программы{{programName}}" - -msgid "Opt in for {{programName}}" -msgstr "Применить для программы {{programName}}" - -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 "" -"Нажав \"применить\" ниже, вы получите доступ к новой панель регистрации в " -"приложении Capture для данной программы. На данный момент некоторые функции " -"из приложения Tracker Capture еще не добавлены, в том числе функции " -"\"Связи\" и \"Направления\". Эти функции будут включены в приложение Capture" -" в ближайших релизах." - -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 "" -"Команда DHIS2 будет признательна за любые отзывы касательно данного " -"функционала, проходящего в данный момент бета-тестирование. Пожалуйста, " -"сообщайте о любых проблемах и делитесь отзывами в проекте 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 "" -"Нажмите на кнопку ниже, чтобы дать доступ всем пользователям данной " -"программы к новой панели регистрации в приложении Capture (бета-версия)." - -msgid "Yes, opt in" -msgstr "Да, получить доступ" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "" -"Перестать использовать новую панель регистрации для программы " -"{{programName}}" - -msgid "Opt out for {{programName}}" -msgstr "Отменить доступ для программы {{programName}}" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "" "Регистрационная запись с идентификатором \"{{enrollmentId}}\" не существует" diff --git a/i18n/sv.po b/i18n/sv.po index 62edd96eb5..e771dc9cec 100644 --- a/i18n/sv.po +++ b/i18n/sv.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Viktor Varland , 2024\n" "Language-Team: Swedish (https://app.transifex.com/hisp-uio/teams/100509/sv/)\n" @@ -591,15 +591,6 @@ msgstr "" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "Uppkopplad" - -msgid "Offline" -msgstr "Off-line" - -msgid "Syncing" -msgstr "" - msgid "Add note" msgstr "Lägg till anteckning" @@ -1236,12 +1227,6 @@ msgstr "" msgid "Follow-up" msgstr "" -msgid "Started at {{orgUnitName}}" -msgstr "" - -msgid "Owned by {{ownerOrgUnit}}" -msgstr "" - msgid "Cancelled" msgstr "Avbruten" @@ -1459,6 +1444,23 @@ msgstr "" msgid "New {{ eventName }} event" msgstr "" +msgid "An error occurred while deleting the event" +msgstr "" + +msgid "" +"Deleting an event is permanent and cannot be undone. Are you sure you want " +"to delete this event?" +msgstr "" + +msgid "An error occurred when updating event status" +msgstr "" + +msgid "Unskip" +msgstr "" + +msgid "Skip" +msgstr "" + msgid "To open this event, please wait until saving is complete" msgstr "" diff --git a/i18n/tet.po b/i18n/tet.po index 719938fd39..d268e14ea8 100644 --- a/i18n/tet.po +++ b/i18n/tet.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Philip Larsen Donnelly, 2024\n" "Language-Team: Tetum (Tetun) (https://app.transifex.com/hisp-uio/teams/100509/tet/)\n" @@ -588,15 +588,6 @@ msgstr "" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "Online" - -msgid "Offline" -msgstr "Offline" - -msgid "Syncing" -msgstr "" - msgid "Add note" msgstr "" @@ -1232,12 +1223,6 @@ msgstr "" msgid "Follow-up" msgstr "Segimentu" -msgid "Started at {{orgUnitName}}" -msgstr "" - -msgid "Owned by {{ownerOrgUnit}}" -msgstr "" - msgid "Cancelled" msgstr "" @@ -1453,6 +1438,23 @@ msgstr "" msgid "New {{ eventName }} event" msgstr "" +msgid "An error occurred while deleting the event" +msgstr "" + +msgid "" +"Deleting an event is permanent and cannot be undone. Are you sure you want " +"to delete this event?" +msgstr "" + +msgid "An error occurred when updating event status" +msgstr "" + +msgid "Unskip" +msgstr "" + +msgid "Skip" +msgstr "" + msgid "To open this event, please wait until saving is complete" msgstr "" diff --git a/i18n/tg.po b/i18n/tg.po index 1346766a62..02c2ea6da5 100644 --- a/i18n/tg.po +++ b/i18n/tg.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Viktor Varland , 2024\n" "Language-Team: Tajik (https://app.transifex.com/hisp-uio/teams/100509/tg/)\n" @@ -589,15 +589,6 @@ msgstr "" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "Онлайн" - -msgid "Offline" -msgstr "Офлайн" - -msgid "Syncing" -msgstr "" - msgid "Add note" msgstr "" @@ -1234,12 +1225,6 @@ msgstr "" msgid "Follow-up" msgstr "Пайгирӣ кардан" -msgid "Started at {{orgUnitName}}" -msgstr "" - -msgid "Owned by {{ownerOrgUnit}}" -msgstr "" - msgid "Cancelled" msgstr "" @@ -1457,6 +1442,23 @@ msgstr "" msgid "New {{ eventName }} event" msgstr "" +msgid "An error occurred while deleting the event" +msgstr "" + +msgid "" +"Deleting an event is permanent and cannot be undone. Are you sure you want " +"to delete this event?" +msgstr "" + +msgid "An error occurred when updating event status" +msgstr "" + +msgid "Unskip" +msgstr "" + +msgid "Skip" +msgstr "" + msgid "To open this event, please wait until saving is complete" msgstr "" diff --git a/i18n/uk.po b/i18n/uk.po index c51bff2210..b294680692 100644 --- a/i18n/uk.po +++ b/i18n/uk.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Viktor Varland , 2024\n" "Language-Team: Ukrainian (https://app.transifex.com/hisp-uio/teams/100509/uk/)\n" @@ -594,15 +594,6 @@ msgstr "" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "Онлайн" - -msgid "Offline" -msgstr "Офлайн" - -msgid "Syncing" -msgstr "" - msgid "Add note" msgstr "Додати нотатку" @@ -1241,12 +1232,6 @@ msgstr "" msgid "Follow-up" msgstr "Подальші дії" -msgid "Started at {{orgUnitName}}" -msgstr "" - -msgid "Owned by {{ownerOrgUnit}}" -msgstr "" - msgid "Cancelled" msgstr "Скасовано" diff --git a/i18n/ur.po b/i18n/ur.po index ce4b3021c3..9a1900631a 100644 --- a/i18n/ur.po +++ b/i18n/ur.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Viktor Varland , 2024\n" "Language-Team: Urdu (https://app.transifex.com/hisp-uio/teams/100509/ur/)\n" @@ -589,15 +589,6 @@ msgstr "" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "آن لائن" - -msgid "Offline" -msgstr "آف لائن" - -msgid "Syncing" -msgstr "" - msgid "Add note" msgstr "نوٹ شامل" @@ -1234,12 +1225,6 @@ msgstr "" msgid "Follow-up" msgstr "" -msgid "Started at {{orgUnitName}}" -msgstr "" - -msgid "Owned by {{ownerOrgUnit}}" -msgstr "" - msgid "Cancelled" msgstr "منسوخ" diff --git a/i18n/uz_UZ_Cyrl.po b/i18n/uz_UZ_Cyrl.po index 32a8d2e932..6ad437c602 100644 --- a/i18n/uz_UZ_Cyrl.po +++ b/i18n/uz_UZ_Cyrl.po @@ -606,15 +606,6 @@ msgstr "Дастур мавжуд эмас" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "Онлайн" - -msgid "Offline" -msgstr "Оффлайн" - -msgid "Syncing" -msgstr "Синхронлашмоқда" - msgid "Add note" msgstr "Изоҳ қолдириш" diff --git a/i18n/uz_UZ_Latn.po b/i18n/uz_UZ_Latn.po index 0379eb17c6..720b8be8e6 100644 --- a/i18n/uz_UZ_Latn.po +++ b/i18n/uz_UZ_Latn.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-08-10T10:42:21.141Z\n" +"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: Yury Rogachev , 2024\n" "Language-Team: Uzbek (Latin) (https://app.transifex.com/hisp-uio/teams/100509/uz@Latn/)\n" @@ -607,15 +607,6 @@ msgstr "Dastur mavjud emas" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "Onlayn" - -msgid "Offline" -msgstr "Offlayn" - -msgid "Syncing" -msgstr "Sinxronlashmoqda" - msgid "Add note" msgstr "Izoh qoldirish" @@ -1258,12 +1249,6 @@ msgstr "" msgid "Follow-up" msgstr "Kuzatish" -msgid "Started at {{orgUnitName}}" -msgstr "" - -msgid "Owned by {{ownerOrgUnit}}" -msgstr "" - msgid "Cancelled" msgstr "Bekor qilindi" diff --git a/i18n/zh.po b/i18n/zh.po index dcd850bd86..d18eb1bd0d 100644 --- a/i18n/zh.po +++ b/i18n/zh.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: easylin , 2024\n" "Language-Team: Chinese (https://app.transifex.com/hisp-uio/teams/100509/zh/)\n" @@ -610,44 +610,6 @@ msgstr "注意" msgid "Close the notice" msgstr "关闭通知" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "为 {{programName}} 使用新的注册仪表板" - -msgid "Opt in for {{programName}}" -msgstr "选择加入 {{programName}}" - -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 "" -"通过单击下面的选择加入,您将开始使用 Capture 应用程序中的新注册仪表板来执行此跟踪项目。目前,Tracker Capture " -"的某些功能尚未添加,包括关系和推荐功能。在 Capture 中包含此 Tracker 功能的工作正在进行中,并将添加到即将发布的应用程序中。" - -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 "核心团队感谢对目前正在 Beta 测试的这个新功能的任何反馈,请报告 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 "单击下面的按钮,为所有用户选择加入此 Tracker 程序的 Capture 应用程序(测试版)中的新注册仪表板功能。" - -msgid "Yes, opt in" -msgstr "是的,选择加入" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "停止为 {{programName}} 使用新的注册信息中心" - -msgid "Opt out for {{programName}}" -msgstr "选择退出 {{programName}}" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "ID为“ {{enrollmentId}}”的报名不存在" @@ -736,9 +698,6 @@ msgstr "查看此项目中的工作清单。" msgid "Page is missing required values from URL" msgstr "页面缺少 URL 中的必需值" -msgid "Program is not valid" -msgstr "项目无效" - msgid "Org unit is not valid with current program" msgstr "机构对当前项目无效" @@ -1232,6 +1191,12 @@ msgstr "无法加载报名的小部件。请稍后再试" msgid "Follow-up" msgstr "后续" +msgid "Started at{{escape}}" +msgstr "" + +msgid "Owned by{{escape}}" +msgstr "" + msgid "Cancelled" msgstr "已取消" @@ -1420,11 +1385,6 @@ msgstr "{{ linkableStageLabel }} 没有可链接的事件" msgid "Ambiguous relationships, contact system administrator" msgstr "关系不明确,请联系系统管理员" -msgid "" -"Enter {{linkableStageLabel}} details in the next step after completing this " -"{{currentStageLabel}}." -msgstr "完成此{{currentStageLabel}}后,在下一步中输入{{linkableStageLabel}}详细信息。" - msgid "Enter details now" msgstr "立即输入详细信息" @@ -1506,6 +1466,9 @@ msgstr "变更日志" msgid "No changes to display" msgstr "没有显示任何变化" +msgid "Updated" +msgstr "更新" + msgid "Created" msgstr "已创建" @@ -1524,6 +1487,9 @@ msgstr "数据条目" msgid "Change" msgstr "改变" +msgid "Value" +msgstr "价值" + msgid "New {{trackedEntityTypeName}} relationship" msgstr "新的 {{trackedEntityTypeName}} 关系" diff --git a/i18n/zh_CN.po b/i18n/zh_CN.po index d370cc02a6..3f3a8e6b43 100644 --- a/i18n/zh_CN.po +++ b/i18n/zh_CN.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2024-09-02T11:08:16.281Z\n" +"POT-Creation-Date: 2024-10-14T14:53:34.553Z\n" "PO-Revision-Date: 2019-06-27 07:31+0000\n" "Last-Translator: 晓东 林 <13981924470@126.com>, 2024\n" "Language-Team: Chinese (China) (https://app.transifex.com/hisp-uio/teams/100509/zh_CN/)\n" @@ -591,15 +591,6 @@ msgstr "项目不存在" msgid "Selected program is invalid for selected organisation unit" msgstr "" -msgid "Online" -msgstr "在线" - -msgid "Offline" -msgstr "离线" - -msgid "Syncing" -msgstr "同步" - msgid "Add note" msgstr "添加笔记" @@ -618,44 +609,6 @@ msgstr "注意" msgid "Close the notice" msgstr "关闭通知" -msgid "Use new Enrollment dashboard for {{programName}}" -msgstr "为 {{programName}} 使用新的注册仪表板" - -msgid "Opt in for {{programName}}" -msgstr "选择加入 {{programName}}" - -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 "" -"通过单击下面的选择加入,您将开始使用 Capture 应用程序中的新注册仪表板来执行此跟踪程序。目前,Tracker Capture " -"的某些功能尚未添加,包括关系和推荐功能。在 Capture 中包含此 Tracker 功能的工作正在进行中,并将添加到即将发布的应用程序中。" - -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 "核心团队感谢对目前正在 Beta 测试的这个新功能的任何反馈,请报告 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 "单击下面的按钮,为所有用户选择加入此 Tracker 程序的 Capture 应用程序(测试版)中的新注册仪表板功能。" - -msgid "Yes, opt in" -msgstr "是的,选择加入" - -msgid "Stop using new Enrollment dashboard for {{programName}}" -msgstr "停止为 {{programName}} 使用新的注册仪表板" - -msgid "Opt out for {{programName}}" -msgstr "选择退出 {{programName}}" - msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" msgstr "ID为“ {{enrollmentId}}”的报名不存在" diff --git a/package.json b/package.json index 6083bbc62d..c658afe3a5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "capture-app", "homepage": ".", - "version": "101.8.0", + "version": "101.14.4", "cacheVersion": "7", "serverVersion": "38", "license": "BSD-3-Clause", @@ -10,6 +10,7 @@ "packages/rules-engine" ], "dependencies": { + "@dhis2/rules-engine-javascript": "101.14.4", "@dhis2/app-runtime": "^3.9.3", "@dhis2/d2-i18n": "^1.1.0", "@dhis2/d2-icons": "^1.0.1", @@ -17,7 +18,6 @@ "@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/rules-engine-javascript": "101.8.0", "@dhis2/ui": "^9.10.1", "@joakim_sm/react-infinite-calendar": "^2.4.2", "@material-ui/core": "3.9.4", diff --git a/packages/rules-engine/package.json b/packages/rules-engine/package.json index a3ef56b41b..33aba0adb7 100644 --- a/packages/rules-engine/package.json +++ b/packages/rules-engine/package.json @@ -1,6 +1,6 @@ { "name": "@dhis2/rules-engine-javascript", - "version": "101.8.0", + "version": "101.14.4", "license": "BSD-3-Clause", "main": "./build/cjs/index.js", "scripts": { diff --git a/packages/rules-engine/src/services/VariableService/variableService.types.js b/packages/rules-engine/src/services/VariableService/variableService.types.js index 9640354c46..2977933c29 100644 --- a/packages/rules-engine/src/services/VariableService/variableService.types.js +++ b/packages/rules-engine/src/services/VariableService/variableService.types.js @@ -27,6 +27,7 @@ type EventMain = { +status?: $Values, +occurredAt?: string, +scheduledAt?: string, + +createdAt?: string, }; export type EventValues = { diff --git a/src/core_modules/capture-core/HOC/withErrorMessageHandler.js b/src/core_modules/capture-core/HOC/withErrorMessageHandler.js index 7fc48e201d..8e6f4dcbda 100644 --- a/src/core_modules/capture-core/HOC/withErrorMessageHandler.js +++ b/src/core_modules/capture-core/HOC/withErrorMessageHandler.js @@ -1,11 +1,11 @@ // @flow import * as React from 'react'; import { withStyles } from '@material-ui/core/styles'; +import { NoticeBox } from '@dhis2/ui'; -const getStyles = (theme: Theme) => ({ +const getStyles = () => ({ errorContainer: { margin: 20, - color: theme.palette.error.main, }, }); @@ -23,12 +23,13 @@ export const withErrorMessageHandler = () => if (error) { return ( -
- {error} -
+
{error}
+ ); } diff --git a/src/core_modules/capture-core/actions/navigateToEnrollmentOverview/navigateToEnrollmentOverview.constants.js b/src/core_modules/capture-core/actions/navigateToEnrollmentOverview/navigateToEnrollmentOverview.constants.js deleted file mode 100644 index 435c2824ac..0000000000 --- a/src/core_modules/capture-core/actions/navigateToEnrollmentOverview/navigateToEnrollmentOverview.constants.js +++ /dev/null @@ -1,6 +0,0 @@ -// @flow - -export const scopeHierarchyTypes = { - PROGRAM: 'PROGRAM', - TRACKED_ENTITY_TYPE: 'TRACKED_ENTITY_TYPE', -}; diff --git a/src/core_modules/capture-core/actions/navigateToEnrollmentOverview/navigateToEnrollmentOverview.epics.js b/src/core_modules/capture-core/actions/navigateToEnrollmentOverview/navigateToEnrollmentOverview.epics.js index 32f7d066e2..8b413b70a4 100644 --- a/src/core_modules/capture-core/actions/navigateToEnrollmentOverview/navigateToEnrollmentOverview.epics.js +++ b/src/core_modules/capture-core/actions/navigateToEnrollmentOverview/navigateToEnrollmentOverview.epics.js @@ -4,58 +4,22 @@ import { ofType } from 'redux-observable'; import { switchMap } from 'rxjs/operators'; import { EMPTY } from 'rxjs'; import { actionTypes as NavigateToEnrollmentOverviewActionTypes } from './navigateToEnrollmentOverview.actions'; -import { buildUrlQueryString, getLocationQuery, shouldUseNewDashboard } from '../../utils/routing'; -import { scopeHierarchyTypes } from './navigateToEnrollmentOverview.constants'; +import { buildUrlQueryString } from '../../utils/routing'; -// TODO This will be removed when the link between capture and tracker capture is not relevant -const redirectToTracker = ({ teiId, orgUnitId, dependencies }) => { - const baseUrl = dependencies.absoluteApiPath; - const { search, pathname } = dependencies.history.location; - const { programId: queryProgramId, trackedEntityTypeId: queryTrackedEntityTypeId } = getLocationQuery(); - - const instanceBaseUrl = baseUrl.split('/api')[0]; - const scopeHierarchy = queryProgramId ? scopeHierarchyTypes.PROGRAM : scopeHierarchyTypes.TRACKED_ENTITY_TYPE; - const selectedScopeId = queryTrackedEntityTypeId || queryProgramId; - const scopeSearchParam = `${scopeHierarchy.toLowerCase()}=${selectedScopeId}`; - const base64Url = btoa(`/dhis-web-capture/#${pathname}${search}`); - setTimeout(() => { - window.location.href = `${instanceBaseUrl}/dhis-web-tracker-capture/#/dashboard?tei=${teiId}&ou=${orgUnitId}&${scopeSearchParam}&returnUrl=${base64Url}`; - }, 50); -}; - -const redirectToEnrollmentDashboard = ({ dependencies, teiId, programId, orgUnitId, enrollmentId }) => { - dependencies.history.push( - `/enrollment?${buildUrlQueryString({ - teiId, - programId, - orgUnitId, - enrollmentId, - })}`, - ); -}; - -export const navigateToEnrollmentOverviewEpic = (action$: InputObservable, store: ReduxStore, dependencies: any) => +export const navigateToEnrollmentOverviewEpic = (action$: InputObservable, store: ReduxStore, { history }: ApiUtils) => action$.pipe( ofType(NavigateToEnrollmentOverviewActionTypes.NAVIGATE_TO_ENROLLMENT_OVERVIEW), switchMap((action) => { const { teiId, programId, orgUnitId } = action.payload; const enrollmentId = programId && (action.payload?.enrollmentId || 'AUTO'); - const { dataStore, userDataStore } = store.value.useNewDashboard; - - if (dataStore || userDataStore) { - const shouldRedirectToEnrollmentDashboard = shouldUseNewDashboard({ - userDataStore, - dataStore, - programId, + history.push( + `/enrollment?${buildUrlQueryString({ teiId, - }); - if (shouldRedirectToEnrollmentDashboard) { - redirectToEnrollmentDashboard({ dependencies, teiId, programId, orgUnitId, enrollmentId }); - return EMPTY; - } - } - - redirectToTracker({ dependencies, store, teiId, orgUnitId }); + programId, + orgUnitId, + enrollmentId, + })}`, + ); return EMPTY; }), ); diff --git a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/getSubValueForTei.js b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/getSubValueForTei.js index b8df8130ed..eab8d88a89 100644 --- a/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/getSubValueForTei.js +++ b/src/core_modules/capture-core/components/DataEntries/EnrollmentRegistrationEntry/hooks/getSubValueForTei.js @@ -1,6 +1,8 @@ // @flow import type { QuerySingleResource } from 'capture-core/utils/api'; import { dataElementTypes } from '../../../../metaData'; +import { getOrgUnitNames } from '../../../../metadataRetrieval/orgUnitName'; + const getImageOrFileResourceSubvalue = async (key: string, querySingleResource: QuerySingleResource) => { const { id, displayName: name } = await querySingleResource({ resource: 'fileResources', id: key }); @@ -11,14 +13,8 @@ const getImageOrFileResourceSubvalue = async (key: string, querySingleResource: }; const getOrganisationUnitSubvalue = async (key: string, querySingleResource: QuerySingleResource) => { - const organisationUnit = await querySingleResource({ - resource: 'organisationUnits', - id: key, - params: { - fields: 'id,name', - }, - }); - return { ...organisationUnit }; + const organisationUnit = await getOrgUnitNames([key], querySingleResource); + return organisationUnit[key]; }; export const subValueGetterByElementType = { diff --git a/src/core_modules/capture-core/components/DataStore/DataStore.actions.js b/src/core_modules/capture-core/components/DataStore/DataStore.actions.js deleted file mode 100644 index a06c83561d..0000000000 --- a/src/core_modules/capture-core/components/DataStore/DataStore.actions.js +++ /dev/null @@ -1,6 +0,0 @@ -// @flow -import { actionCreator } from '../../actions/actions.utils'; -import { type UseNewDashboard, actionTypes as dataStoreActionTypes } from './DataStore.types'; - -export const saveDataStore = ({ dataStore, userDataStore }: UseNewDashboard) => - actionCreator(dataStoreActionTypes.SAVE_DATA_STORE)({ dataStore, userDataStore }); diff --git a/src/core_modules/capture-core/components/DataStore/DataStore.epics.js b/src/core_modules/capture-core/components/DataStore/DataStore.epics.js deleted file mode 100644 index 71c1cee90c..0000000000 --- a/src/core_modules/capture-core/components/DataStore/DataStore.epics.js +++ /dev/null @@ -1,61 +0,0 @@ -// @flow -import { ofType } from 'redux-observable'; -import { flatMap, catchError } from 'rxjs/operators'; -import { EMPTY } from 'rxjs'; -import { saveDataStore } from './DataStore.actions'; -import { type UseNewDashboard } from './DataStore.types'; -import { appStartActionTypes } from '../../../../components/AppStart'; -import { programCollection } from '../../metaDataMemoryStores'; - -const setNewDashboardByDefault = (key: string, dataStoreValues) => { - if (!dataStoreValues) { - return {}; - } - const programs = [...programCollection.keys()]; - const valuesWithDefault = programs.reduce((acc, program) => { - const dataStoreValue = dataStoreValues[program]; - acc[program] = dataStoreValue === undefined ? true : dataStoreValue; - return acc; - }, {}); - - return { [key]: valuesWithDefault }; -}; - -const getDataStoreFromApi = async querySingleResource => - querySingleResource({ - resource: 'dataStore/capture/useNewDashboard', - }); - -const getUserDataStoreFromApi = async querySingleResource => - querySingleResource({ - resource: 'userDataStore/capture/useNewDashboard', - }); - -export const fetchDataStoreEpic = (action$: InputObservable, _: ReduxStore, { querySingleResource }: ApiUtils) => - action$.pipe( - ofType(appStartActionTypes.APP_LOAD_SUCESS), - flatMap(async () => { - const apiDataStore: ?UseNewDashboard = await getDataStoreFromApi(querySingleResource) - .catch((error) => { - if (error.details.httpStatusCode === 404) { - return {}; - } - return undefined; - }); - - return saveDataStore(setNewDashboardByDefault('dataStore', apiDataStore)); - }), - catchError(() => EMPTY), - ); - -export const fetchUserDataStoreEpic = (action$: InputObservable, _: ReduxStore, { querySingleResource }: ApiUtils) => - action$.pipe( - ofType(appStartActionTypes.APP_LOAD_SUCESS), - flatMap(async () => { - const apiUserDataStore: UseNewDashboard = await getUserDataStoreFromApi(querySingleResource); - // $FlowFixMe - return saveDataStore(setNewDashboardByDefault('userDataStore', apiUserDataStore)); - }), - catchError(() => EMPTY), - ); - diff --git a/src/core_modules/capture-core/components/DataStore/DataStore.types.js b/src/core_modules/capture-core/components/DataStore/DataStore.types.js deleted file mode 100644 index ffa2641abb..0000000000 --- a/src/core_modules/capture-core/components/DataStore/DataStore.types.js +++ /dev/null @@ -1,9 +0,0 @@ -// @flow - -export const actionTypes = { - SAVE_DATA_STORE: 'useNewDashboard.SaveDataStore', -}; - -export type UseNewDashboard = {| - [key: string]: string, -|} diff --git a/src/core_modules/capture-core/components/DataStore/index.js b/src/core_modules/capture-core/components/DataStore/index.js deleted file mode 100644 index e6359f21f1..0000000000 --- a/src/core_modules/capture-core/components/DataStore/index.js +++ /dev/null @@ -1 +0,0 @@ -export { saveDataStore } from './DataStore.actions'; 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..48c8bb1a99 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 @@ -1,14 +1,21 @@ // @flow import * as React from 'react'; import { withStyles } from '@material-ui/core'; -import { Chip } from '@dhis2/ui'; +import { Chip, colors } from '@dhis2/ui'; import { OrgUnitField } from './OrgUnitField.component'; +import { TooltipOrgUnit } from '../../../../Tooltips/TooltipOrgUnit/TooltipOrgUnit.component'; const getStyles = () => ({ selectedOrgUnitContainer: { display: 'flex', alignItems: 'center', }, + chip: { + cursor: 'text !important', + '&:hover': { + backgroundColor: `${colors.grey200} !important`, + }, + }, }); type OrgUnitValue = { @@ -27,9 +34,7 @@ type Props = { disabled?: ?boolean, classes: { selectedOrgUnitContainer: string, - clearSelectedOrgUnitButton: string, - clearSelectedOrgUnitButtonDisabled: string, - selectedOrgUnitText: string, + chip: string, } } @@ -44,7 +49,12 @@ class SingleOrgUnitSelectFieldPlain extends React.Component { const { classes } = this.props; return (
- {selectedOrgUnit.name} + + +
); } diff --git a/src/core_modules/capture-core/components/MetadataAutoSelectInitializer/hooks/useMetadataAutoSelect.js b/src/core_modules/capture-core/components/MetadataAutoSelectInitializer/hooks/useMetadataAutoSelect.js index 90be846e65..e85322f939 100644 --- a/src/core_modules/capture-core/components/MetadataAutoSelectInitializer/hooks/useMetadataAutoSelect.js +++ b/src/core_modules/capture-core/components/MetadataAutoSelectInitializer/hooks/useMetadataAutoSelect.js @@ -1,9 +1,10 @@ // @flow import { useCallback, useEffect, useState } from 'react'; import { useHistory } from 'react-router-dom'; -import { useApiMetadataQuery, useIndexedDBQuery } from '../../../utils/reactQueryHelpers'; +import { useIndexedDBQuery } from '../../../utils/reactQueryHelpers'; import { getUserStorageController, userStores } from '../../../storageControllers'; import { buildUrlQueryString, useLocationQuery } from '../../../utils/routing'; +import { useOrgUnitAutoSelect } from '../../../dataQueries'; const getAllPrograms = () => { const userStorageController = getUserStorageController(); @@ -28,21 +29,8 @@ export const useMetadataAutoSelect = () => { }, ); - const { data: searchOrgUnits, isLoading: loadingOrgUnits } = useApiMetadataQuery( - ['searchOrgUnitsForAutoSelect'], - { - resource: 'organisationUnits', - params: { - fields: 'id', - withinUserSearchHierarchy: true, - pageSize: 2, - }, - }, - { - enabled: Object.keys(urlParams).length === 0 && !mounted, - select: ({ organisationUnits }) => organisationUnits, - }, - ); + const queryOptions = { enabled: Object.keys(urlParams).length === 0 && !mounted }; + const { isLoading: loadingOrgUnits, data: searchOrgUnits } = useOrgUnitAutoSelect(queryOptions); const updateUrlIfApplicable = useCallback(() => { const paramsToAdd = { diff --git a/src/core_modules/capture-core/components/OptInOut/OptIn/OptIn.component.js b/src/core_modules/capture-core/components/OptInOut/OptIn/OptIn.component.js deleted file mode 100644 index 81a541bf82..0000000000 --- a/src/core_modules/capture-core/components/OptInOut/OptIn/OptIn.component.js +++ /dev/null @@ -1,71 +0,0 @@ -// @flow -import React, { useState, type ComponentType } from 'react'; -import { NoticeBox, Button, Modal, ModalTitle, ModalContent, ModalActions, ButtonStrip } from '@dhis2/ui'; -import i18n from '@dhis2/d2-i18n'; -import { withStyles } from '@material-ui/core'; -import type { PlainProps } from './optIn.types'; - -const styles = { - container: { - width: '80%', - margin: '0 auto', - }, -}; - -export const OptInPlain = ({ classes, programName, handleOptIn, loading }: PlainProps) => { - const [toggle, setToggle] = useState(false); - - const title = i18n.t('Use new Enrollment dashboard for {{programName}}', { - programName, - interpolation: { escapeValue: false }, - }); - const button = i18n.t('Opt in for {{programName}}', { - programName, - interpolation: { escapeValue: false }, - }); - - const modalContent = i18n.t('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.'); - - const modalContentFeedback = i18n.t('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.'); - - return ( -
- -

- {i18n.t('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.')} -

- -
-
- {toggle && ( - setToggle(false)} dataTest="opt-in-modal"> - {title} - -

{modalContent}

-

{modalContentFeedback}

-
- - - - - - -
- )} -
- ); -}; - -export const OptIn: ComponentType<$Diff> = withStyles(styles)(OptInPlain); diff --git a/src/core_modules/capture-core/components/OptInOut/OptIn/OptIn.container.js b/src/core_modules/capture-core/components/OptInOut/OptIn/OptIn.container.js deleted file mode 100644 index 7bea988d28..0000000000 --- a/src/core_modules/capture-core/components/OptInOut/OptIn/OptIn.container.js +++ /dev/null @@ -1,57 +0,0 @@ -// @flow -import React, { useCallback } from 'react'; -import { useDataMutation } from '@dhis2/app-runtime'; -import { useSelector, useDispatch } from 'react-redux'; -import { OptIn as OptInComponent } from './OptIn.component'; -import type { Props } from './optIn.types'; -import { useTrackerProgram } from '../../../hooks/useTrackerProgram'; -import { saveDataStore } from '../../DataStore'; - -const dataStoreUpdate = { - resource: 'dataStore/capture/useNewDashboard', - type: 'update', - data: ({ data }) => data, -}; - -const dataStoreCreate = { - resource: 'dataStore/capture/useNewDashboard', - type: 'create', - data: ({ data }) => data, -}; - -export const OptIn = ({ programId }: Props) => { - const dispatch = useDispatch(); - const program = useTrackerProgram(programId); - const newDashboard = useSelector(({ useNewDashboard }) => useNewDashboard); - const { dataStore } = newDashboard; - const showOptIn = program?.access?.write && !dataStore?.[programId]; - - const [updateMutation, { loading: loadingUpdate }] = useDataMutation(dataStoreUpdate, { - onComplete: () => { - dispatch(saveDataStore({ dataStore: { ...dataStore, [programId]: true } })); - }, - }); - const [createMutation, { loading: loadingCreate }] = useDataMutation(dataStoreCreate, { - onComplete: () => { - dispatch(saveDataStore({ dataStore: { ...dataStore, [programId]: true } })); - }, - }); - - const handleOptIn = useCallback(() => { - if (dataStore) { - const data = { ...dataStore, [programId]: true }; - updateMutation({ data }); - } else { - const data = { [programId]: true }; - createMutation({ data }); - } - }, [programId, updateMutation, createMutation, dataStore]); - - return showOptIn ? ( - - ) : null; -}; diff --git a/src/core_modules/capture-core/components/OptInOut/OptIn/index.js b/src/core_modules/capture-core/components/OptInOut/OptIn/index.js deleted file mode 100644 index 3d26d28715..0000000000 --- a/src/core_modules/capture-core/components/OptInOut/OptIn/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// @flow -export { OptIn } from './OptIn.container'; diff --git a/src/core_modules/capture-core/components/OptInOut/OptIn/optIn.types.js b/src/core_modules/capture-core/components/OptInOut/OptIn/optIn.types.js deleted file mode 100644 index e105d399ce..0000000000 --- a/src/core_modules/capture-core/components/OptInOut/OptIn/optIn.types.js +++ /dev/null @@ -1,12 +0,0 @@ -// @flow - -export type Props = {| - programId: string, -|}; - -export type PlainProps = {| - handleOptIn: () => void, - programName: string, - loading: boolean, - ...CssClasses -|}; diff --git a/src/core_modules/capture-core/components/OptInOut/OptOut/OptOut.component.js b/src/core_modules/capture-core/components/OptInOut/OptOut/OptOut.component.js deleted file mode 100644 index 3639694228..0000000000 --- a/src/core_modules/capture-core/components/OptInOut/OptOut/OptOut.component.js +++ /dev/null @@ -1,44 +0,0 @@ -// @flow -import React, { type ComponentType } from 'react'; -import { NoticeBox, Button } from '@dhis2/ui'; -import i18n from '@dhis2/d2-i18n'; -import { withStyles } from '@material-ui/core'; -import type { PlainProps } from './optOut.types'; - -const styles = { - container: { - width: '80%', - margin: '0 auto', - }, -}; - -export const OptOutPlain = ({ classes, programName, handleOptOut, loading }: PlainProps) => { - const title = i18n.t('Stop using new Enrollment dashboard for {{programName}}', { - programName, - interpolation: { escapeValue: false }, - }); - const button = i18n.t('Opt out for {{programName}}', { - programName, - interpolation: { escapeValue: false }, - }); - - return ( -
-
- -

- {i18n.t( - 'This program uses the new enrollment dashboard functionality ' + - 'in the Capture app (beta). Click this button to opt-out and direct ' + - 'all users to the Tracker capture app for this program.', - )} -

- -
-
- ); -}; - -export const OptOut: ComponentType<$Diff> = withStyles(styles)(OptOutPlain); diff --git a/src/core_modules/capture-core/components/OptInOut/OptOut/OptOut.container.js b/src/core_modules/capture-core/components/OptInOut/OptOut/OptOut.container.js deleted file mode 100644 index c9ba767866..0000000000 --- a/src/core_modules/capture-core/components/OptInOut/OptOut/OptOut.container.js +++ /dev/null @@ -1,36 +0,0 @@ -// @flow -import React, { useCallback } from 'react'; -import { useDataMutation } from '@dhis2/app-runtime'; -import { useSelector, useDispatch } from 'react-redux'; -import { OptOut as OptOutComponent } from './OptOut.component'; -import type { Props } from './optOut.types'; -import { useTrackerProgram } from '../../../hooks/useTrackerProgram'; -import { saveDataStore } from '../../DataStore'; - -const dataStoreUpdate = { - resource: 'dataStore/capture/useNewDashboard', - type: 'update', - data: ({ data }) => data, -}; - -export const OptOut = ({ programId }: Props) => { - const dispatch = useDispatch(); - const program = useTrackerProgram(programId); - const newDashboard = useSelector(({ useNewDashboard }) => useNewDashboard); - const { dataStore } = newDashboard; - - const [updateMutation, { loading: loadingUpdate }] = useDataMutation(dataStoreUpdate, { - onComplete: () => { - dispatch(saveDataStore({ dataStore: { ...dataStore, [programId]: false } })); - }, - }); - const handleOptOut = useCallback(() => { - const data = { ...dataStore, [programId]: false }; - updateMutation({ data }); - }, [programId, updateMutation, dataStore]); - const showOptOut = program?.access?.write && dataStore?.[programId]; - - return showOptOut ? ( - - ) : null; -}; diff --git a/src/core_modules/capture-core/components/OptInOut/OptOut/index.js b/src/core_modules/capture-core/components/OptInOut/OptOut/index.js deleted file mode 100644 index b89207bf49..0000000000 --- a/src/core_modules/capture-core/components/OptInOut/OptOut/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// @flow -export { OptOut } from './OptOut.container'; diff --git a/src/core_modules/capture-core/components/OptInOut/OptOut/optOut.types.js b/src/core_modules/capture-core/components/OptInOut/OptOut/optOut.types.js deleted file mode 100644 index 3f4a4c244e..0000000000 --- a/src/core_modules/capture-core/components/OptInOut/OptOut/optOut.types.js +++ /dev/null @@ -1,12 +0,0 @@ -// @flow - -export type Props = {| - programId: string, -|}; - -export type PlainProps = {| - handleOptOut: () => void, - programName: string, - loading: boolean, - ...CssClasses, -|}; diff --git a/src/core_modules/capture-core/components/OptInOut/index.js b/src/core_modules/capture-core/components/OptInOut/index.js deleted file mode 100644 index cc2949649c..0000000000 --- a/src/core_modules/capture-core/components/OptInOut/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -export { OptIn } from './OptIn'; -export { OptOut } from './OptOut'; diff --git a/src/core_modules/capture-core/components/Pages/Enrollment/EnrollmentPage.component.js b/src/core_modules/capture-core/components/Pages/Enrollment/EnrollmentPage.component.js index 9de818c2b2..baf588711b 100644 --- a/src/core_modules/capture-core/components/Pages/Enrollment/EnrollmentPage.component.js +++ b/src/core_modules/capture-core/components/Pages/Enrollment/EnrollmentPage.component.js @@ -9,7 +9,7 @@ import { LoadingMaskForPage } from '../../LoadingMasks/LoadingMaskForPage.compon import { withErrorMessageHandler } from '../../../HOC'; import { MissingMessage } from './MissingMessage.component'; import { EnrollmentPageDefault } from './EnrollmentPageDefault'; -import { TopBar } from './TopBar.container'; + const getStyles = ({ typography }) => ({ loadingMask: { @@ -22,36 +22,19 @@ const getStyles = ({ typography }) => ({ const EnrollmentPagePlain = ({ classes, - programId, - orgUnitId, - enrollmentId, - trackedEntityName, - teiDisplayName, enrollmentPageStatus, - enrollmentsAsOptions, }) => ( - <> - - -
- {enrollmentPageStatus === enrollmentPageStatuses.MISSING_SELECTIONS && } +
+ {enrollmentPageStatus === enrollmentPageStatuses.MISSING_SELECTIONS && } - {enrollmentPageStatus === enrollmentPageStatuses.DEFAULT && } + {enrollmentPageStatus === enrollmentPageStatuses.DEFAULT && } - {enrollmentPageStatus === enrollmentPageStatuses.LOADING && ( -
- -
- )} -
- + {enrollmentPageStatus === enrollmentPageStatuses.LOADING && ( +
+ +
+ )} +
); export const EnrollmentPageComponent: ComponentType<$Diff> = compose( diff --git a/src/core_modules/capture-core/components/Pages/Enrollment/EnrollmentPage.container.js b/src/core_modules/capture-core/components/Pages/Enrollment/EnrollmentPage.container.js index bacc367ac1..9de18b5331 100644 --- a/src/core_modules/capture-core/components/Pages/Enrollment/EnrollmentPage.container.js +++ b/src/core_modules/capture-core/components/Pages/Enrollment/EnrollmentPage.container.js @@ -24,6 +24,7 @@ import { useSetEnrollmentId, } from '../../ScopeSelector'; import { useLocationQuery } from '../../../utils/routing'; +import { TopBar } from './TopBar.container'; const useComponentLifecycle = () => { const dispatch = useDispatch(); @@ -114,15 +115,26 @@ export const EnrollmentPage: ComponentType<{||}> = () => { useSelector(({ activePage }) => activePage.selectionsError && activePage.selectionsError.error); return ( - + <> + + + + ); }; diff --git a/src/core_modules/capture-core/components/Pages/Enrollment/TopBar.container.js b/src/core_modules/capture-core/components/Pages/Enrollment/TopBar.container.js index 47477a965d..c258a96dc3 100644 --- a/src/core_modules/capture-core/components/Pages/Enrollment/TopBar.container.js +++ b/src/core_modules/capture-core/components/Pages/Enrollment/TopBar.container.js @@ -52,19 +52,21 @@ export const TopBar = ({ onResetOrgUnitId={() => resetOrgUnitId()} onStartAgain={() => reset()} > - resetTeiId('/')} - options={[ - { - label: teiDisplayName, - value: 'alwaysPreselected', - }, - ]} - selectedValue="alwaysPreselected" - title={trackedEntityName} - displayOnly - /> + {trackedEntityName ? ( + resetTeiId('/')} + options={[ + { + label: teiDisplayName, + value: 'alwaysPreselected', + }, + ]} + selectedValue="alwaysPreselected" + title={trackedEntityName} + displayOnly + /> + ) : <>} {enrollmentsAsOptions?.length > 0 ? ( { + const history = useHistory(); const { teiId, programId, orgUnitId, enrollmentId } = useLocationQuery(); const { valid: validIds, loading, error: validatedIdsError } = useValidatedIDsFromCache({ programId, orgUnitId }); const { @@ -63,6 +65,12 @@ const EnrollmentAddEventPagePlain = ({ classes }: Props) => { return EnrollmentAddEventPageStatuses.DEFAULT; }, [enrollmentId, isLoading, loading, pageIsInvalid, programId, teiId, validIds]); + useEffect(() => { + if (pageStatus === EnrollmentAddEventPageStatuses.PROGRAM_INVALID) { + history.push(`/enrollment?${buildUrlQueryString({ orgUnitId, teiId, enrollmentId })}`); + } + }, [pageStatus, orgUnitId, teiId, enrollmentId, history]); + if (pageStatus === EnrollmentAddEventPageStatuses.LOADING) { return ; } @@ -89,10 +97,6 @@ const EnrollmentAddEventPagePlain = ({ classes }: Props) => { i18n.t('Page is missing required values from URL') )} - {pageStatus === EnrollmentAddEventPageStatuses.PROGRAM_INVALID && ( - i18n.t('Program is not valid') - )} - {pageStatus === EnrollmentAddEventPageStatuses.ORG_UNIT_INVALID && ( i18n.t('Org unit is not valid with current program') )} diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container.js index fb3656915b..88b39abb5d 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container.js @@ -109,9 +109,9 @@ export const EnrollmentAddEventPageDefault = ({ const dataEntryHasChanges = useSelector(state => getDataEntryHasChanges(state, widgetReducerName)); const { program } = useProgramInfo(programId); - const selectedProgramStage = [...program.stages.values()].find(item => item.id === stageId); + const selectedProgramStage = [...program?.stages.values() ?? []].find(item => item.id === stageId); const outputEffects = useWidgetDataFromStore(widgetReducerName); - const hideWidgets = useHideWidgetByRuleLocations(program.programRules.concat(selectedProgramStage?.programRules ?? [])); + const hideWidgets = useHideWidgetByRuleLocations(program?.programRules.concat(selectedProgramStage?.programRules ?? [])); // $FlowFixMe const trackedEntityName = program?.trackedEntityType?.name; diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.types.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.types.js index d900462c76..a8929f2b14 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.types.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.types.js @@ -7,7 +7,7 @@ import type { import { Program } from '../../../../metaData'; export type Props = {| - program: Program, + program: ?Program, stageId: string, orgUnitId: string, teiId: string, diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.component.js b/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.component.js index 03b56579de..d2acb94e3b 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.component.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.component.js @@ -60,7 +60,7 @@ export const EnrollmentEditEventPageComponent = ({ mode={mode} programStage={programStage} enrollmentId={enrollmentId} - programId={program.id} + programId={program?.id} enrollmentsAsOptions={enrollmentsAsOptions} trackedEntityName={trackedEntityName} teiDisplayName={teiDisplayName} diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.container.js b/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.container.js index 9ba1bfcdd8..995fca5429 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.container.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.container.js @@ -132,8 +132,8 @@ const EnrollmentEditEventPageWithContextPlain = ({ }, [dispatch]); const { program } = useProgramInfo(programId); - const programStage = [...program.stages?.values()].find(item => item.id === stageId); - const hideWidgets = useHideWidgetByRuleLocations(program.programRules.concat(programStage?.programRules)); + const programStage = [...program?.stages?.values() ?? []].find(item => item.id === stageId); + const hideWidgets = useHideWidgetByRuleLocations(program?.programRules.concat(programStage?.programRules)); const onDeleteTrackedEntitySuccess = useCallback(() => { history.push(`/?${buildUrlQueryString({ orgUnitId, programId })}`); diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.types.js b/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.types.js index e164d9fc02..7f48be3b24 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.types.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.types.js @@ -17,7 +17,7 @@ export type PlainProps = {| enrollmentId: string, eventId: string, stageId: string, - program: Program, + program: ?Program, trackedEntityTypeId: string, mode: string, orgUnitId: string, diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/TopBar.container.js b/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/TopBar.container.js index 1798a80a16..e613228db2 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/TopBar.container.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/TopBar.container.js @@ -21,7 +21,7 @@ import { TopBarActions } from '../../TopBarActions'; type Props = {| programStage: ?ProgramStage, enrollmentId: string, - programId: string, + programId: ?string, mode: string, orgUnitId: string, trackedEntityName: string, diff --git a/src/core_modules/capture-core/components/Pages/MainPage/MainPage.component.js b/src/core_modules/capture-core/components/Pages/MainPage/MainPage.component.js index 2d29de6e9b..5c9952f28d 100644 --- a/src/core_modules/capture-core/components/Pages/MainPage/MainPage.component.js +++ b/src/core_modules/capture-core/components/Pages/MainPage/MainPage.component.js @@ -3,13 +3,13 @@ import React, { useMemo } from 'react'; import { compose } from 'redux'; import { colors, spacers } from '@dhis2/ui'; import { withStyles } from '@material-ui/core/styles'; +import type { ComponentType } from 'react'; +import type { Props, ContainerProps } from './mainPage.types'; import { WorkingListsType } from './WorkingListsType'; -import type { Props, PlainProps } from './mainPage.types'; import { MainPageStatuses } from './MainPage.constants'; import { WithoutOrgUnitSelectedMessage } from './WithoutOrgUnitSelectedMessage/WithoutOrgUnitSelectedMessage'; import { WithoutCategorySelectedMessage } from './WithoutCategorySelectedMessage/WithoutCategorySelectedMessage'; import { withErrorMessageHandler, withLoadingIndicator } from '../../../HOC'; -import { TopBar } from './TopBar.container'; import { SearchBox } from '../../SearchBox'; import { TemplateSelector } from '../../TemplateSelector'; import { @@ -41,79 +41,66 @@ const getStyles = () => ({ }, }); -const useShowMainPage = ({ programId, orgUnitId, trackedEntityTypeId, displayFrontPageList, selectedTemplateId }) => - useMemo(() => { - const noProgramSelected = !programId; - const noOrgUnitSelected = !orgUnitId; - const isEventProgram = !trackedEntityTypeId; - - return noProgramSelected || noOrgUnitSelected || isEventProgram || displayFrontPageList || selectedTemplateId; - }, [programId, orgUnitId, trackedEntityTypeId, displayFrontPageList, selectedTemplateId]); - -const MainPageBody = compose( - withErrorMessageHandler(), - withStyles(getStyles), -)(({ MainPageStatus, setShowAccessible, programId, showMainPage, classes, ...passOnProps }: PlainProps) => ( - <> - {showMainPage ? ( - <> - {MainPageStatus === MainPageStatuses.WITHOUT_ORG_UNIT_SELECTED && ( - - )} - {MainPageStatus === MainPageStatuses.CATEGORY_OPTION_INVALID_FOR_ORG_UNIT && ( - - )} - {MainPageStatus === MainPageStatuses.WITHOUT_PROGRAM_CATEGORY_SELECTED && ( - - )} - {MainPageStatus === MainPageStatuses.SHOW_WORKING_LIST && ( -
- -
- )} - - ) : ( -
-
- -
-
- -
-
- )} - -)); - -const MainPage = ({ +const MainPagePlain = ({ programId, orgUnitId, trackedEntityTypeId, displayFrontPageList, selectedTemplateId, - selectedCategories, - ...passOnProps + MainPageStatus, + setShowAccessible, + classes, + onChangeTemplate, }: Props) => { - const showMainPage = useShowMainPage({ - programId, - orgUnitId, - trackedEntityTypeId, - displayFrontPageList, - selectedTemplateId, - }); + const showMainPage = useMemo(() => { + const noProgramSelected = !programId; + const noOrgUnitSelected = !orgUnitId; + const isEventProgram = !trackedEntityTypeId; + return noProgramSelected || noOrgUnitSelected || isEventProgram || displayFrontPageList || selectedTemplateId; + }, [programId, orgUnitId, trackedEntityTypeId, displayFrontPageList, selectedTemplateId]); return ( <> - - + {showMainPage ? ( + <> + {MainPageStatus === MainPageStatuses.WITHOUT_ORG_UNIT_SELECTED && ( + + )} + {MainPageStatus === MainPageStatuses.CATEGORY_OPTION_INVALID_FOR_ORG_UNIT && ( + + )} + {MainPageStatus === MainPageStatuses.WITHOUT_PROGRAM_CATEGORY_SELECTED && ( + + )} + {MainPageStatus === MainPageStatuses.SHOW_WORKING_LIST && ( +
+ +
+ )} + + ) : ( +
+
+ +
+
+ +
+
+ )} ); }; -export const MainPageComponent = withLoadingIndicator()(MainPage); + +export const MainPageComponent: ComponentType = + compose( + withLoadingIndicator(), + withErrorMessageHandler(), + withStyles(getStyles), + )(MainPagePlain); diff --git a/src/core_modules/capture-core/components/Pages/MainPage/MainPage.container.js b/src/core_modules/capture-core/components/Pages/MainPage/MainPage.container.js index 52a10ab4e4..3dc90d8bd5 100644 --- a/src/core_modules/capture-core/components/Pages/MainPage/MainPage.container.js +++ b/src/core_modules/capture-core/components/Pages/MainPage/MainPage.container.js @@ -1,7 +1,7 @@ // @flow -import React, { useEffect, useMemo, useCallback } from 'react'; +import React, { useCallback, useEffect, useMemo } from 'react'; // $FlowFixMe -import { connect, useSelector, shallowEqual, useDispatch } from 'react-redux'; +import { connect, shallowEqual, useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; import { programCollection } from 'capture-core/metaDataMemoryStores/programCollection/programCollection'; import { MainPageComponent } from './MainPage.component'; @@ -11,6 +11,7 @@ import { buildUrlQueryString, useLocationQuery } from '../../../utils/routing'; import { MainPageStatuses } from './MainPage.constants'; import { OrgUnitFetcher } from '../../OrgUnitFetcher'; import { useCategoryOptionIsValidForOrgUnit } from '../../../hooks/useCategoryComboIsValidForOrgUnit'; +import { TopBar } from './TopBar.container'; const mapStateToProps = (state: ReduxState) => ({ error: state.activePage.selectionsError && state.activePage.selectionsError.error, // TODO: Should probably remove this @@ -68,9 +69,11 @@ const useMainPageStatus = ({ const useSelectorMainPage = () => useSelector( - ({ currentSelections, activePage }) => ({ + ({ currentSelections, activePage, workingListsTemplates, workingListsContext }) => ({ categories: currentSelections.categories, selectedCategories: currentSelections.categoriesMeta, + reduxSelectedTemplateId: workingListsTemplates.teiList?.selectedTemplateId, + workingListProgramId: workingListsContext.teiList?.programIdView, ready: !activePage.isLoading && !activePage.lockedSelectorLoads, error: activePage.selectionsError && activePage.selectionsError.error, }), @@ -103,6 +106,8 @@ const MainPageContainer = () => { const { categories, selectedCategories, + reduxSelectedTemplateId, + workingListProgramId, error, ready, } = useSelectorMainPage(); @@ -131,7 +136,18 @@ const MainPageContainer = () => { }, [showAllAccessible, dispatch]); useEffect(() => { - if (programId && trackedEntityTypeId && displayFrontPageList && selectedTemplateId === undefined) { + if (programId && trackedEntityTypeId && selectedTemplateId === undefined) { + if (reduxSelectedTemplateId && workingListProgramId === programId) { + handleChangeTemplateUrl({ + programId, + orgUnitId, + selectedTemplateId: reduxSelectedTemplateId, + showAllAccessible, + history, + }); + return; + } + if (!displayFrontPageList) return; handleChangeTemplateUrl({ programId, orgUnitId, @@ -148,10 +164,13 @@ const MainPageContainer = () => { trackedEntityTypeId, displayFrontPageList, history, + reduxSelectedTemplateId, + workingListProgramId, ]); return ( + { error={error} ready={ready} displayFrontPageList={displayFrontPageList} - selectedCategories={selectedCategories} /> ); diff --git a/src/core_modules/capture-core/components/Pages/MainPage/WithoutCategorySelectedMessage/WithoutCategorySelectedMessage.js b/src/core_modules/capture-core/components/Pages/MainPage/WithoutCategorySelectedMessage/WithoutCategorySelectedMessage.js index d30ef8e3dd..fd23dceaa9 100644 --- a/src/core_modules/capture-core/components/Pages/MainPage/WithoutCategorySelectedMessage/WithoutCategorySelectedMessage.js +++ b/src/core_modules/capture-core/components/Pages/MainPage/WithoutCategorySelectedMessage/WithoutCategorySelectedMessage.js @@ -32,7 +32,7 @@ const WithoutCategorySelectedMessagePlain = ({ programId, classes }) => { categories: currentSelections.categories, }), shallowEqual); - if (!program.categoryCombination) { + if (!program?.categoryCombination) { log.error(errorCreator(errorMessages.MISSING_CATEGORY)({ programId })); throw Error(i18n.t(errorMessages.GENERIC_ERROR)); } diff --git a/src/core_modules/capture-core/components/Pages/MainPage/WithoutOrgUnitSelectedMessage/WithoutOrgUnitSelectedMessage.js b/src/core_modules/capture-core/components/Pages/MainPage/WithoutOrgUnitSelectedMessage/WithoutOrgUnitSelectedMessage.js index f791f50b93..cb2379c151 100644 --- a/src/core_modules/capture-core/components/Pages/MainPage/WithoutOrgUnitSelectedMessage/WithoutOrgUnitSelectedMessage.js +++ b/src/core_modules/capture-core/components/Pages/MainPage/WithoutOrgUnitSelectedMessage/WithoutOrgUnitSelectedMessage.js @@ -39,16 +39,15 @@ type Props = {| |} const WithoutOrgUnitSelectedMessagePlain = ({ programId, setShowAccessible, classes }: Props) => { - // TODO - this hook breaks the app when the program is not found const { program, programType } = useProgramInfo(programId); const IncompleteSelectionMessage = useMemo(() => (programType === programTypes.TRACKER_PROGRAM ? ( i18n.t('Or see all records accessible to you in {{program}} ', { - program: program.name, + program: program?.name, interpolation: { escapeValue: false }, }) ) : i18n.t('Or see all events accessible to you in {{program}}', - { program: program.name, interpolation: { escapeValue: false } })), - [program.name, programType]); + { program: program?.name, interpolation: { escapeValue: false } })), + [program?.name, programType]); return (
{ @@ -15,14 +14,12 @@ export const WorkingListsType = ({ programId, orgUnitId, selectedTemplateId, onC if (programType === programTypes.TRACKER_PROGRAM) { return ( <> - - ); } diff --git a/src/core_modules/capture-core/components/Pages/MainPage/mainPage.types.js b/src/core_modules/capture-core/components/Pages/MainPage/mainPage.types.js index 25cff6c98e..bac702d632 100644 --- a/src/core_modules/capture-core/components/Pages/MainPage/mainPage.types.js +++ b/src/core_modules/capture-core/components/Pages/MainPage/mainPage.types.js @@ -1,27 +1,21 @@ // @flow -type PassOnProps = $ReadOnly<{| +export type ContainerProps = $ReadOnly<{| programId: string, orgUnitId: string, selectedTemplateId?: string, + trackedEntityTypeId?: string, + displayFrontPageList?: boolean, onChangeTemplate?: (selectedTemplateId?: string) => void, -|}>; - -export type PlainProps = $ReadOnly<{| - ...PassOnProps, setShowAccessible: () => void, MainPageStatus: boolean, selectedTemplateId: string, - showMainPage: boolean, - ...CssClasses, -|}>; - -export type Props = $ReadOnly<{| - ...PassOnProps, - ...PlainProps, error: boolean, ready: boolean, - trackedEntityTypeId?: string, - displayFrontPageList?: boolean, - selectedCategories: ?{ [categoryId: string]: { writeAccess: boolean } }, +|} +>; + +export type Props = $ReadOnly<{| + ...ContainerProps, + ...CssClasses |}>; diff --git a/src/core_modules/capture-core/components/Pages/New/NewPage.component.js b/src/core_modules/capture-core/components/Pages/New/NewPage.component.js index a7b070193b..35939b44f6 100644 --- a/src/core_modules/capture-core/components/Pages/New/NewPage.component.js +++ b/src/core_modules/capture-core/components/Pages/New/NewPage.component.js @@ -7,7 +7,7 @@ import withStyles from '@material-ui/core/styles/withStyles'; import { OrgUnitFetcher } from 'capture-core/components/OrgUnitFetcher'; import i18n from '@dhis2/d2-i18n'; import { Button } from '@dhis2/ui'; -import { TopBar } from './TopBar.container'; + import type { ContainerProps, Props } from './NewPage.types'; import { withErrorMessageHandler, withLoadingIndicator } from '../../../HOC'; import { NEW_TEI_DATA_ENTRY_ID, newPageStatuses } from './NewPage.constants'; @@ -36,11 +36,7 @@ const NewPagePlain = ({ categoryOptionIsInvalidForOrgUnit, missingCategoriesInProgramSelection, orgUnitSelectionIncomplete, - isUserInteractionInProgress, - programId, - teiId, trackedEntityName, - teiDisplayName, trackedEntityInstanceAttributes, }: Props) => { const { scopeType } = useScopeInfo(currentScopeId); @@ -72,16 +68,7 @@ const NewPagePlain = ({ ]); const orgUnitId = useSelector(({ currentSelections }) => currentSelections.orgUnitId); - return (<> - + return (
{ !writeAccess ? @@ -154,7 +141,7 @@ const NewPagePlain = ({ }
- ); + ); }; export const NewPageComponent: ComponentType = diff --git a/src/core_modules/capture-core/components/Pages/New/NewPage.container.js b/src/core_modules/capture-core/components/Pages/New/NewPage.container.js index 8ea87c19e2..4286ee2c70 100644 --- a/src/core_modules/capture-core/components/Pages/New/NewPage.container.js +++ b/src/core_modules/capture-core/components/Pages/New/NewPage.container.js @@ -9,7 +9,7 @@ import { showDefaultViewOnNewPage, showMessageToSelectProgramCategoryOnNewPage, showMessageThatCategoryOptionIsInvalidForOrgUnit, } from './NewPage.actions'; -import { typeof newPageStatuses } from './NewPage.constants'; +import { newPageStatuses } from './NewPage.constants'; import { buildUrlQueryString, useLocationQuery } from '../../../utils/routing'; import { getScopeFromScopeId, TrackerProgram, TrackedEntityType } from '../../../metaData'; import { useMissingCategoriesInProgramSelection } from '../../../hooks/useMissingCategoriesInProgramSelection'; @@ -18,6 +18,7 @@ import { useTrackedEntityInstances } from './hooks'; import { deriveTeiName } from '../common/EnrollmentOverviewDomain/useTeiDisplayName'; import { programCollection } from '../../../metaDataMemoryStores/programCollection/programCollection'; import { useCategoryOptionIsValidForOrgUnit } from '../../../hooks/useCategoryComboIsValidForOrgUnit'; +import { TopBar } from './TopBar.container'; const useUserWriteAccess = (scopeId) => { const scope = getScopeFromScopeId(scopeId); @@ -89,7 +90,7 @@ export const NewPage: ComponentType<{||}> = () => { ({ currentSelections }) => !currentSelections.orgUnitId && !currentSelections.complete, ); - const newPageStatus: $Keys = + const newPageStatus: $Keys = useSelector(({ newPage }) => newPage.newPageStatus); const handleMainPageNavigation = () => { @@ -108,26 +109,34 @@ export const NewPage: ComponentType<{||}> = () => { ); return ( - ); + <> + + + + ); }; 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 438b61a88f..9004f99945 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 @@ -29,7 +29,6 @@ export type ContainerProps = $ReadOnly<{| writeAccess: boolean, error: boolean, ready: boolean, - isUserInteractionInProgress: boolean, programId?: string, teiId?: string, trackedEntityName?: string, diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js index d14df1119e..4ee21bd46c 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/RegistrationDataEntry.epics.js @@ -12,7 +12,7 @@ import { getTrackerProgramThrowIfNotFound } from '../../../../metaData'; import { navigateToEnrollmentOverview, } from '../../../../actions/navigateToEnrollmentOverview/navigateToEnrollmentOverview.actions'; -import { buildUrlQueryString, shouldUseNewDashboard } from '../../../../utils/routing'; +import { buildUrlQueryString } from '../../../../utils/routing'; import { getStageWithOpenAfterEnrollment, PAGES, @@ -54,15 +54,11 @@ export const startSavingNewTrackedEntityInstanceWithEnrollmentEpic: Epic = ( ofType(registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_START), map((action) => { const { currentSelections: { programId } } = store.value; - const { dataStore, userDataStore } = store.value.useNewDashboard; const { enrollmentPayload, uid } = action.payload; const { stages, useFirstStageDuringRegistration } = getTrackerProgramThrowIfNotFound(programId); - - const shouldRedirect = shouldUseNewDashboard({ userDataStore, dataStore, programId }); const { stageWithOpenAfterEnrollment, redirectTo } = getStageWithOpenAfterEnrollment( stages, useFirstStageDuringRegistration, - shouldRedirect, ); const eventIndex = enrollmentPayload.enrollments[0]?.events.findIndex( diff --git a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getStageWithOpenAfterEnrollment.js b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getStageWithOpenAfterEnrollment.js index 23d9d1a610..3688d29b4c 100644 --- a/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getStageWithOpenAfterEnrollment.js +++ b/src/core_modules/capture-core/components/Pages/New/RegistrationDataEntry/helpers/getStageWithOpenAfterEnrollment.js @@ -13,13 +13,12 @@ export const PAGES = { export const getStageWithOpenAfterEnrollment = ( stages: Map, useFirstStageDuringRegistration: boolean, - shouldRedirect: boolean, ) => { const stagesArray = [...stages.values()]; const [firstStageWithOpenAfterEnrollment] = stagesArray.filter(({ openAfterEnrollment }) => openAfterEnrollment); const redirectTo = (() => { - if (shouldRedirect && firstStageWithOpenAfterEnrollment) { + if (firstStageWithOpenAfterEnrollment) { // event will be created during first stage registration if ( useFirstStageDuringRegistration diff --git a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegistrationSection/RegUnitSelector/RegUnitSelector.component.js b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegistrationSection/RegUnitSelector/RegUnitSelector.component.js index ea39476d43..fc4f52cfa5 100644 --- a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegistrationSection/RegUnitSelector/RegUnitSelector.component.js +++ b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegistrationSection/RegUnitSelector/RegUnitSelector.component.js @@ -47,7 +47,7 @@ class RegUnitSelectorPlain extends React.Component { return; } - onUpdateSelectedOrgUnit(orgUnit, program.organisationUnits ? !program.organisationUnits[orgUnit.id] : false); + onUpdateSelectedOrgUnit(orgUnit, program?.organisationUnits ? !program.organisationUnits[orgUnit.id] : false); } render() { diff --git a/src/core_modules/capture-core/components/Pages/NewRelationship/TeiRelationship/SearchResults/TeiRelationshipSearchResults.component.js b/src/core_modules/capture-core/components/Pages/NewRelationship/TeiRelationship/SearchResults/TeiRelationshipSearchResults.component.js index 3cced06ccf..461424f302 100644 --- a/src/core_modules/capture-core/components/Pages/NewRelationship/TeiRelationship/SearchResults/TeiRelationshipSearchResults.component.js +++ b/src/core_modules/capture-core/components/Pages/NewRelationship/TeiRelationship/SearchResults/TeiRelationshipSearchResults.component.js @@ -10,7 +10,11 @@ import { makeAttributesSelector } from './teiRelationshipSearchResults.selectors import { CardList } from '../../../../CardList'; import type { CurrentSearchTerms } from '../../../../SearchBox'; import { SearchResultsHeader } from '../../../../SearchResultsHeader'; -import { type SearchGroup } from '../../../../../metaData'; +import { + type SearchGroup, + getTrackerProgramThrowIfNotFound, + getTrackedEntityTypeThrowIfNotFound, +} from '../../../../../metaData'; import { ResultsPageSizeContext } from '../../../shared-contexts'; import type { ListItem } from '../../../../CardList/CardList.types'; import { convertClientValuesToServer } from '../../../../../converters/helpers/clientToServer'; @@ -25,7 +29,8 @@ type Props = {| currentPage: number, searchGroup: SearchGroup, searchValues: any, - selectedProgramId: string, + selectedProgramId?: string, + selectedTrackedEntityTypeId: string, teis: Array, trackedEntityTypeName: string, ...CssClasses @@ -60,6 +65,15 @@ const getStyles = (theme: Theme) => ({ }, }); +const getLinkedEntityFormFoundation = (selectedProgramId, selectedTrackedEntityTypeId) => { + if (selectedProgramId) { + const program = getTrackerProgramThrowIfNotFound(selectedProgramId); + return program.enrollment.enrollmentForm; + } + const trackedEntityType = getTrackedEntityTypeThrowIfNotFound(selectedTrackedEntityTypeId); + return trackedEntityType.teiRegistration.form; +}; + const CardListButton = ({ handleOnClick, teiId }) => (
diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js index 061f7a5fe4..07832fe83f 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/Validated/getConvertedRelatedStageEvent/getConvertedRelatedStageEvent.js @@ -47,7 +47,6 @@ const getEventDetailsByLinkMode = ({ }), ); } - return ({ linkedEvent: { ...baseEventDetails, @@ -56,23 +55,34 @@ const getEventDetailsByLinkMode = ({ }, linkedEventId: baseEventDetails.event, }); - } else if (linkMode === RelatedStageModes.ENTER_DATA) { + } + + if (linkMode === RelatedStageModes.ENTER_DATA) { + const { orgUnit: linkedEventOrgUnit } = relatedStageDataValues; + if (!linkedEventOrgUnit) { + throw new Error( + errorCreator('Missing required data for creating related stage event')({ + linkedEventOrgUnit, + }), + ); + } return ({ linkedEvent: { ...baseEventDetails, scheduledAt: convertFn(clientRequestEvent.scheduledAt, dataElementTypes.DATE), - orgUnit: convertFn(clientRequestEvent.orgUnit, dataElementTypes.ORGANISATION_UNIT), + orgUnit: convertFn(linkedEventOrgUnit, dataElementTypes.ORGANISATION_UNIT), }, linkedEventId: baseEventDetails.event, }); - } else if (linkMode === RelatedStageModes.LINK_EXISTING_RESPONSE) { + } + + if (linkMode === RelatedStageModes.LINK_EXISTING_RESPONSE) { const { linkedEventId } = relatedStageDataValues; return { linkedEvent: null, linkedEventId, }; } - log.error(errorCreator(`Referral mode ${linkMode} is not supported`)()); return { linkedEvent: null, diff --git a/src/core_modules/capture-core/components/WidgetEventEdit/DataEntry/epics/editEventDataEntry.epics.js b/src/core_modules/capture-core/components/WidgetEventEdit/DataEntry/epics/editEventDataEntry.epics.js index 69d7a4ab24..05515b4bcc 100644 --- a/src/core_modules/capture-core/components/WidgetEventEdit/DataEntry/epics/editEventDataEntry.epics.js +++ b/src/core_modules/capture-core/components/WidgetEventEdit/DataEntry/epics/editEventDataEntry.epics.js @@ -65,14 +65,21 @@ const runRulesForEditSingleEvent = ({ if (program instanceof TrackerProgram) { const { enrollment, attributeValues } = state.enrollmentDomain; + const { apiOtherEvents, apiCurrentEventOriginal } = enrollment.events.reduce((acc, apiEvent) => { + if (apiEvent.event === currentEvent.eventId) { + acc.apiCurrentEventOriginal = apiEvent; + } else { + acc.apiOtherEvents.push(apiEvent); + } + return acc; + }, { apiOtherEvents: [] }); + effects = getApplicableRuleEffectsForTrackerProgram({ program, stage, orgUnit, - currentEvent, - otherEvents: prepareEnrollmentEventsForRulesEngine( - enrollment?.events.filter(enrollmentEvent => enrollmentEvent.event !== currentEvent.eventId), - ), + currentEvent: { ...currentEvent, createdAt: apiCurrentEventOriginal.createdAt }, + otherEvents: prepareEnrollmentEventsForRulesEngine(apiOtherEvents), enrollmentData: getEnrollmentForRulesEngine(enrollment), attributeValues: getAttributeValuesForRulesEngine(attributeValues, program.attributes), }); diff --git a/src/core_modules/capture-core/components/WidgetEventEdit/WidgetEventEdit.container.js b/src/core_modules/capture-core/components/WidgetEventEdit/WidgetEventEdit.container.js index f953852223..b39bb89c7c 100644 --- a/src/core_modules/capture-core/components/WidgetEventEdit/WidgetEventEdit.container.js +++ b/src/core_modules/capture-core/components/WidgetEventEdit/WidgetEventEdit.container.js @@ -32,7 +32,7 @@ import { EventChangelogWrapper } from './EventChangelogWrapper'; import { FEATURES, useFeature } from '../../../capture-core-utils'; import { inMemoryFileStore } from '../DataEntry/file/inMemoryFileStore'; import { eventStatuses } from './constants/status.const'; -import { useAuthorities } from './hooks'; +import { useAuthorities } from '../../utils/authority/useAuthorities'; const styles = { header: { @@ -101,8 +101,8 @@ export const WidgetEventEditPlain = ({ const loadedValues = useSelector(({ viewEventPage }) => viewEventPage.loadedValues); const eventAccess = getProgramEventAccess(programId, stageId); - const { canEditCompletedEvent } = useAuthorities(); - const blockEntryForm = stage.blockEntryForm && !canEditCompletedEvent && eventStatus === eventStatuses.COMPLETED; + const { hasAuthority } = useAuthorities({ authorities: ['F_UNCOMPLETE_EVENT'] }); + const blockEntryForm = stage.blockEntryForm && !hasAuthority && eventStatus === eventStatuses.COMPLETED; const disableEdit = !eventAccess?.write || blockEntryForm; const tooltipContent = blockEntryForm ? diff --git a/src/core_modules/capture-core/components/WidgetEventEdit/hooks/index.js b/src/core_modules/capture-core/components/WidgetEventEdit/hooks/index.js deleted file mode 100644 index edcfc4f241..0000000000 --- a/src/core_modules/capture-core/components/WidgetEventEdit/hooks/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// @flow -export { useAuthorities } from './useAuthorities'; diff --git a/src/core_modules/capture-core/components/WidgetProfile/OverflowMenu/OverflowMenu.container.js b/src/core_modules/capture-core/components/WidgetProfile/OverflowMenu/OverflowMenu.container.js index f2b4fca631..031f7fd462 100644 --- a/src/core_modules/capture-core/components/WidgetProfile/OverflowMenu/OverflowMenu.container.js +++ b/src/core_modules/capture-core/components/WidgetProfile/OverflowMenu/OverflowMenu.container.js @@ -1,8 +1,8 @@ // @flow import React from 'react'; +import { useAuthorities } from 'capture-core/utils/authority/useAuthorities'; import type { Props } from './OverflowMenu.types'; import { OverflowMenuComponent } from './OverflowMenu.component'; -import { useAuthorities } from './hooks'; export const OverflowMenu = ({ trackedEntityTypeName, @@ -13,13 +13,13 @@ export const OverflowMenu = ({ teiId, programAPI, }: Props) => { - const { canCascadeDeleteTei } = useAuthorities(); + const { hasAuthority } = useAuthorities({ authorities: ['F_TEI_CASCADE_DELETE'] }); return ( { - const queryKey = ['authorities']; - const queryFn = { - resource: 'me.json', - params: { - fields: 'authorities', - }, - }; - const queryOptions = { - select: ({ authorities }) => - authorities && - authorities.some(authority => authority === auth.ALL || authority === auth.F_TEI_CASCADE_DELETE), - }; - const { data } = useApiMetadataQuery(queryKey, queryFn, queryOptions); - - return { - canCascadeDeleteTei: Boolean(data), - }; -}; diff --git a/src/core_modules/capture-core/components/WidgetProfile/hooks/getSubValueForTei.js b/src/core_modules/capture-core/components/WidgetProfile/hooks/getSubValueForTei.js index af3c5de5ec..18891f0578 100644 --- a/src/core_modules/capture-core/components/WidgetProfile/hooks/getSubValueForTei.js +++ b/src/core_modules/capture-core/components/WidgetProfile/hooks/getSubValueForTei.js @@ -2,6 +2,7 @@ import type { QuerySingleResource } from 'capture-core/utils/api'; import { dataElementTypes } from '../../../metaData'; import { FEATURES, hasAPISupportForFeature } from '../../../../capture-core-utils'; +import { getOrgUnitNames } from '../../../metadataRetrieval/orgUnitName'; type Attribute = { id: string, @@ -59,22 +60,9 @@ const getImageResourceSubvalue = async ({ attribute, minorServerVersion }: SubVa }; }; -const getOrganisationUnitSubvalue = async ({ attribute, querySingleResource }: SubValueFunctionParams) => { - const organisationUnit = await querySingleResource({ - resource: 'organisationUnits', - id: attribute.value, - params: { - fields: 'id,name,ancestors[displayName]', - }, - }); - - const orgUnitClientValue = { - id: organisationUnit.id, - name: organisationUnit.name, - ancestors: organisationUnit.ancestors.map(ancestor => ancestor.displayName), - }; - - return orgUnitClientValue; +const getOrganisationUnitSubvalue = async ({ attribute: { value }, querySingleResource }: SubValueFunctionParams) => { + const organisationUnits = await getOrgUnitNames([value], querySingleResource); + return organisationUnits[value]; }; export const subValueGetterByElementType = { diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/EnterDataInOrgUnit/EnterData.component.js b/src/core_modules/capture-core/components/WidgetRelatedStages/EnterDataInOrgUnit/EnterData.component.js new file mode 100644 index 0000000000..47ff354bed --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/EnterDataInOrgUnit/EnterData.component.js @@ -0,0 +1,114 @@ +// @flow +import React from 'react'; +import i18n from '@dhis2/d2-i18n'; +import type { ComponentType } from 'react'; +import { withStyles } from '@material-ui/core'; +import { colors, spacers, spacersNum, IconInfo16 } from '@dhis2/ui'; +import { OrgUnitSelectorForRelatedStages } from '../FormComponents'; +import type { ErrorMessagesForRelatedStages } from '../RelatedStagesActions'; +import type { RelatedStageDataValueStates } from '../WidgetRelatedStages.types'; + +const styles = { + wrapper: { + padding: `${spacers.dp16} 0`, + maxWidth: '55.75rem', + }, + fieldWrapper: { + display: 'flex', + flexWrap: 'wrap', + alignItems: 'start', + justifyContent: 'space-between', + padding: `${spacers.dp8} ${spacers.dp16}`, + }, + fieldLabel: { + color: colors.grey900, + paddingTop: spacersNum.dp12, + paddingRight: spacersNum.dp16, + flexBasis: '200px', + }, + fieldContent: { + flexBasis: '150px', + flexGrow: 1, + }, + alternateColor: { + backgroundColor: colors.grey100, + }, + infoBox: { + margin: '8px 8px', + display: 'flex', + fontSize: '14px', + gap: '5px', + background: colors.grey100, + padding: '12px 8px', + border: `1px solid ${colors.grey600}`, + }, +}; + +type Props = { + linkableStageLabel: string, + relatedStagesDataValues: RelatedStageDataValueStates, + setRelatedStagesDataValues: (() => Object) => void, + currentStageLabel: string, + saveAttempted: boolean, + errorMessages: ErrorMessagesForRelatedStages, + ...CssClasses +} + +export const EnterDataInOrgUnitPlain = ({ + linkableStageLabel, + relatedStagesDataValues, + setRelatedStagesDataValues, + saveAttempted, + errorMessages, + currentStageLabel, + classes, +}: Props) => { + const onSelectOrgUnit = (e: { id: string, displayName: string, path: string }) => { + const orgUnit = { + id: e.id, + name: e.displayName, + path: e.path, + }; + + setRelatedStagesDataValues(prevValues => ({ + ...prevValues, + orgUnit, + })); + }; + + const onDeselectOrgUnit = () => { + setRelatedStagesDataValues(prevValues => ({ + ...prevValues, + orgUnit: null, + })); + }; + + return ( +
+
+ +
+
+ + {i18n.t( + relatedStagesDataValues?.orgUnit?.name + ? 'Enter {{linkableStageLabel}} details for {{orgUnitLabel}} in the next step after completing this {{currentStageLabel}}.' + : 'Select organisation unit and enter {{linkableStageLabel}} details in the next step after completing this {{currentStageLabel}}.', + { + linkableStageLabel, + currentStageLabel, + orgUnitLabel: relatedStagesDataValues?.orgUnit?.name, + }, + )} +
+
+ ); +}; + +export const EnterDataInOrgUnit: ComponentType<$Diff> = withStyles(styles)(EnterDataInOrgUnitPlain); diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/EnterDataInOrgUnit/index.js b/src/core_modules/capture-core/components/WidgetRelatedStages/EnterDataInOrgUnit/index.js new file mode 100644 index 0000000000..0d5a3fe03e --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/EnterDataInOrgUnit/index.js @@ -0,0 +1,2 @@ +// @flow +export { EnterDataInOrgUnit } from './EnterData.component'; diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.js b/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.js index 85bf2dae37..a53c05eb3f 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.js @@ -1,11 +1,7 @@ // @flow import React from 'react'; import i18n from '@dhis2/d2-i18n'; -import { - SingleSelectField, - SingleSelectOption, - spacers, -} from '@dhis2/ui'; +import { SingleSelectField, SingleSelectOption, spacers } from '@dhis2/ui'; import { withStyles } from '@material-ui/core'; import type { LinkToExistingProps } from './LinkToExisting.types'; @@ -58,17 +54,18 @@ export const LinkToExistingPlain = ({ error={saveAttempted && !!errorMessages.linkedEventId} validationText={saveAttempted && errorMessages.linkedEventId} > - {linkableEvents.map(event => ( - - ))} + {linkableEvents + .map(event => ( + + )) + } ); }; -export const LinkToExisting = - withStyles(styles)(LinkToExistingPlain); +export const LinkToExisting = withStyles(styles)(LinkToExistingPlain); diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.types.js b/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.types.js index 386160b8e2..afa25ce233 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.types.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.types.js @@ -1,12 +1,15 @@ // @flow -import type { ErrorMessagesForRelatedStages, LinkableEvent } from '../RelatedStagesActions/RelatedStagesActions.types'; +import type { + ErrorMessagesForRelatedStages, + RelatedStagesEvents, +} from '../RelatedStagesActions/RelatedStagesActions.types'; import type { RelatedStageDataValueStates } from '../WidgetRelatedStages.types'; export type LinkToExistingProps = {| relatedStagesDataValues: RelatedStageDataValueStates, setRelatedStagesDataValues: (RelatedStageDataValueStates) => void, - linkableEvents: Array, + linkableEvents: Array, errorMessages: ErrorMessagesForRelatedStages, saveAttempted: boolean, linkableStageLabel: string, diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js index 5bd127a887..38bbb6e24b 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.component.js @@ -1,7 +1,7 @@ // @flow import React, { type ComponentType, useMemo } from 'react'; import i18n from '@dhis2/d2-i18n'; -import { Radio, colors, spacers, spacersNum, IconInfo16, Button } from '@dhis2/ui'; +import { Button, colors, Radio, spacers, spacersNum } from '@dhis2/ui'; import { withStyles } from '@material-ui/core'; import { ConditionalTooltip } from 'capture-core/components/Tooltips/ConditionalTooltip'; import { actions as RelatedStagesActionTypes, mainOptionTranslatedTexts, relatedStageStatus } from '../constants'; @@ -11,6 +11,7 @@ import { ScheduleInOrgUnit } from '../ScheduleInOrgUnit'; import { useProgramStageInfo } from '../../../metaDataMemoryStores/programCollection/helpers'; import type { Props } from './RelatedStagesActions.types'; import { LinkToExisting } from '../LinkToExisting'; +import { EnterDataInOrgUnit } from '../EnterDataInOrgUnit/EnterData.component'; const styles = () => ({ wrapper: { @@ -37,15 +38,6 @@ const styles = () => ({ clearSelections: { padding: spacers.dp8, }, - infoBox: { - margin: '8px 8px', - display: 'flex', - fontSize: '14px', - gap: '5px', - background: colors.grey100, - padding: '12px 8px', - border: `1px solid ${colors.grey600}`, - }, }); export const RelatedStagesActionsPlain = ({ @@ -53,6 +45,7 @@ export const RelatedStagesActionsPlain = ({ type, relationshipName, scheduledLabel, + events, linkableEvents, relatedStagesDataValues, setRelatedStagesDataValues, @@ -71,7 +64,7 @@ export const RelatedStagesActionsPlain = ({ linkMode: action, })); }; - const canAddNewEventToStage = useCanAddNewEventToStage(programStage, linkableEvents); + const canAddNewEventToStage = useCanAddNewEventToStage(programStage, events); if (!programStage) { return null; @@ -170,16 +163,14 @@ export const RelatedStagesActionsPlain = ({ )} {selectedAction === RelatedStagesActionTypes.ENTER_DATA && ( -
- - {i18n.t( - 'Enter {{linkableStageLabel}} details in the next step after completing this {{currentStageLabel}}.', - { - linkableStageLabel: programStage.stageForm.name, - currentStageLabel, - }, - )} -
+ )} {selectedAction === RelatedStagesActionTypes.LINK_EXISTING_RESPONSE && ( diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js index ea381b6374..a99f2d0758 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/RelatedStagesActions/RelatedStagesActions.types.js @@ -17,16 +17,19 @@ export type ErrorMessagesForRelatedStages = {| linkedEventId?: ?string, |} -export type LinkableEvent = { +export type RelatedStagesEvents = { id: string, label: string, + isLinkable: boolean, + status: string, } export type Props = {| type: string, relationshipName: string, relatedStagesDataValues: RelatedStageDataValueStates, - linkableEvents: Array, + events: Array, + linkableEvents: Array, scheduledLabel: string, saveAttempted: boolean, errorMessages: ErrorMessagesForRelatedStages, diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/ScheduleInOrgUnit.container.js b/src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/ScheduleInOrgUnit.component.js similarity index 100% rename from src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/ScheduleInOrgUnit.container.js rename to src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/ScheduleInOrgUnit.component.js diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/index.js b/src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/index.js index 2e1a21bf88..c547d9d70d 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/index.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/ScheduleInOrgUnit/index.js @@ -1,2 +1,2 @@ // @flow -export { ScheduleInOrgUnit } from './ScheduleInOrgUnit.container'; +export { ScheduleInOrgUnit } from './ScheduleInOrgUnit.component'; diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.component.js b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.component.js index 3050b4d3e9..722515d992 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.component.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/WidgetRelatedStages.component.js @@ -1,13 +1,14 @@ // @flow import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from 'react'; import { useRelatedStages } from './useRelatedStages'; +import { useOrgUnitAutoSelect } from '../../dataQueries'; import type { Props, RelatedStageDataValueStates } from './WidgetRelatedStages.types'; +import type { ErrorMessagesForRelatedStages } from './RelatedStagesActions'; import { RelatedStagesActions } from './RelatedStagesActions'; import { relatedStageStatus } from './constants'; import { useStageLabels } from './hooks/useStageLabels'; -import type { ErrorMessagesForRelatedStages } from './RelatedStagesActions'; import { relatedStageWidgetIsValid } from './relatedStageEventIsValid/relatedStageEventIsValid'; -import { useAvailableRelatedStageEvents } from './hooks/useAvailableRelatedStageEvents'; +import { useRelatedStageEvents } from './hooks/useRelatedStageEvents'; const WidgetRelatedStagesPlain = ({ programId, @@ -21,7 +22,7 @@ const WidgetRelatedStagesPlain = ({ programId, }); const { scheduledLabel, occurredLabel } = useStageLabels(programId, constraint?.programStage?.id); - const { linkableEvents, isLoading: isLoadingEvents } = useAvailableRelatedStageEvents({ + const { events, linkableEvents, isLoading: isLoadingEvents } = useRelatedStageEvents({ stageId: constraint?.programStage?.id, relationshipTypeId: selectedRelationshipType?.id, scheduledLabel, @@ -36,6 +37,15 @@ const WidgetRelatedStagesPlain = ({ orgUnit: undefined, linkedEventId: undefined, }); + const { isLoading: orgUnitLoading, data } = useOrgUnitAutoSelect(); + useEffect(() => { + if (!orgUnitLoading && data?.length === 1) { + setRelatedStageDataValues(prev => ({ + ...prev, + orgUnit: data[0], + })); + } + }, [data, orgUnitLoading, setRelatedStageDataValues]); const addErrorMessage = (message: ErrorMessagesForRelatedStages) => { setErrorMessages((prevMessages: Object) => ({ @@ -81,7 +91,7 @@ const WidgetRelatedStagesPlain = ({ } }, [formIsValid, relatedStageDataValues]); - if (!currentRelatedStagesStatus || !selectedRelationshipType || isLoadingEvents) { + if (!currentRelatedStagesStatus || !selectedRelationshipType || isLoadingEvents || orgUnitLoading) { return null; } @@ -90,6 +100,7 @@ const WidgetRelatedStagesPlain = ({ relationshipName={selectedRelationshipType.displayName} scheduledLabel={scheduledLabel} type={currentRelatedStagesStatus} + events={events} linkableEvents={linkableEvents} relatedStagesDataValues={relatedStageDataValues} setRelatedStagesDataValues={setRelatedStageDataValues} @@ -103,8 +114,8 @@ const WidgetRelatedStagesPlain = ({ ); }; -export const WidgetRelatedStages = forwardRef(WidgetRelatedStagesPlain); + formIsValidOnSave: Function, + getLinkedStageValues: Function + |}>(WidgetRelatedStagesPlain); diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useCanAddNewEventToStage.js b/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useCanAddNewEventToStage.js index e78e53a554..a95321b927 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useCanAddNewEventToStage.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useCanAddNewEventToStage.js @@ -2,9 +2,9 @@ import { useMemo } from 'react'; import { useSelector } from 'react-redux'; import { ProgramStage } from '../../../metaData'; -import type { LinkableEvent } from '../RelatedStagesActions/RelatedStagesActions.types'; +import type { RelatedStagesEvents } from '../RelatedStagesActions/RelatedStagesActions.types'; -export const useCanAddNewEventToStage = (programStage: ?ProgramStage, existingRelatedEvents: LinkableEvent[]) => { +export const useCanAddNewEventToStage = (programStage: ?ProgramStage, existingRelatedEvents: RelatedStagesEvents[]) => { const hiddenProgramStages = useSelector(({ rulesEffectsHiddenProgramStageDesc }) => rulesEffectsHiddenProgramStageDesc?.['enrollmentEvent-newEvent'], ); diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useAvailableRelatedStageEvents.js b/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useRelatedStageEvents.js similarity index 74% rename from src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useAvailableRelatedStageEvents.js rename to src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useRelatedStageEvents.js index b273b3f66f..8a5e8a7c17 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useAvailableRelatedStageEvents.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/hooks/useRelatedStageEvents.js @@ -1,7 +1,7 @@ // @flow import { useMemo } from 'react'; import { convertDateObjectToDateFormatString } from '../../../utils/converters/date'; -import type { LinkableEvent } from '../RelatedStagesActions/RelatedStagesActions.types'; +import type { RelatedStagesEvents } from '../RelatedStagesActions/RelatedStagesActions.types'; import { useApiDataQuery } from '../../../utils/reactQueryHelpers'; import { handleAPIResponse, REQUESTED_ENTITIES } from '../../../utils/api'; @@ -15,12 +15,13 @@ type Props = { } type ReturnType = { - linkableEvents: Array, + events: Array, + linkableEvents: Array, isLoading: boolean, isError: boolean, } -export const useAvailableRelatedStageEvents = ({ +export const useRelatedStageEvents = ({ stageId, enrollmentId, relationshipTypeId, @@ -36,7 +37,7 @@ export const useAvailableRelatedStageEvents = ({ fields: 'event,occurredAt,scheduledAt,status,relationships', }, }), [stageId, enrollmentId]); - const { data, isLoading, isError } = useApiDataQuery>( + const { data, isLoading, isError } = useApiDataQuery>( ['availableRelatedStageEvents', stageId, enrollmentId, relationshipTypeId], query, { @@ -45,19 +46,20 @@ export const useAvailableRelatedStageEvents = ({ staleTime: 0, select: (response: any) => { const events = handleAPIResponse(REQUESTED_ENTITIES.events, response); - if (events.length === 0) return []; return events - .filter(event => !event.relationships || - !event.relationships.some(relationship => relationship.relationshipType === relationshipTypeId)) .map((event) => { + const isLinkable = !event.relationships + ?.some(relationship => relationship.relationshipType === relationshipTypeId); const label = event.occurredAt ? `${occurredLabel}: ${convertDateObjectToDateFormatString(new Date(event.occurredAt))}` : `${scheduledLabel}: ${convertDateObjectToDateFormatString(new Date(event.scheduledAt))}`; return ({ id: event.event, + status: event.status, + isLinkable, label, }); }); @@ -66,7 +68,8 @@ export const useAvailableRelatedStageEvents = ({ ); return { - linkableEvents: data ?? [], + events: data ?? [], + linkableEvents: data?.filter(event => event.isLinkable) ?? [], isLoading, isError, }; diff --git a/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js b/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js index 07ad6a17a8..b02e1f5ae5 100644 --- a/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js +++ b/src/core_modules/capture-core/components/WidgetRelatedStages/relatedStageEventIsValid/ValidationFunctions.js @@ -44,6 +44,23 @@ const scheduleInOrgUnit = (props) => { return scheduledAtIsValid && orgUnitIsValid; }; +const enterData = (props) => { + const { orgUnit, setErrorMessages } = props ?? {}; + const orgUnitIsValid = isValidOrgUnit(orgUnit); + + if (!orgUnitIsValid) { + setErrorMessages({ + orgUnit: i18n.t('Please provide a valid organisation unit'), + }); + } else { + setErrorMessages({ + orgUnit: null, + }); + } + + return orgUnitIsValid; +}; + const linkToExistingResponse = (props) => { const { linkedEventId, setErrorMessages } = props ?? {}; const linkedEventIdIsValid = !!linkedEventId; @@ -64,7 +81,7 @@ const linkToExistingResponse = (props) => { export const ValidationFunctionsByLinkMode: { [key: string]: (props: ?Props) => boolean } = { [RelatedStageModes.SCHEDULE_IN_ORG]: props => scheduleInOrgUnit(props), - [RelatedStageModes.ENTER_DATA]: () => true, + [RelatedStageModes.ENTER_DATA]: props => enterData(props), [RelatedStageModes.LINK_EXISTING_RESPONSE]: props => linkToExistingResponse(props), }; diff --git a/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/helpers.js b/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/helpers.js index d4f2d6b2a6..74ae039f19 100644 --- a/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/helpers.js +++ b/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/helpers.js @@ -8,7 +8,7 @@ import type { StageDataElement } from '../../../../types/common.types'; import { Notes } from '../Notes.component'; import type { QuerySingleResource } from '../../../../../../utils/api/api.types'; import { isEventOverdue } from '../../../../../../utils/isEventOverdue'; -import { getCachedOrgUnitName } from '../../../../../../metadataRetrieval/orgUnitName'; +import { TooltipOrgUnit } from '../../../../../Tooltips/TooltipOrgUnit/TooltipOrgUnit.component'; const getEventStatus = (event: ApiEnrollmentEvent) => { const today = moment().startOf('day'); @@ -58,7 +58,7 @@ const convertStatusForView = (event: ApiEnrollmentEvent) => { }; }; -const convertOrgUnitForView = (event: ApiEnrollmentEvent) => getCachedOrgUnitName(event.orgUnit); +const convertOrgUnitForView = (event: ApiEnrollmentEvent) => ; const convertNoteForView = (event: ApiEnrollmentEvent) => ; diff --git a/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/useEventList.js b/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/useEventList.js index 2199216154..f160eb00e3 100644 --- a/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/useEventList.js +++ b/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/hooks/useEventList.js @@ -22,7 +22,7 @@ import { } from '../../../../../../metaDataMemoryStoreBuilders/common/helpers/dataElement/unsupportedMultiText'; import { useOrgUnitNames } from '../../../../../../metadataRetrieval/orgUnitName'; -const baseKeys = [{ id: 'status' }, { id: 'occurredAt' }, { id: 'assignedUser' }, { id: 'orgUnitName' }, { id: 'scheduledAt' }, { id: 'notes' }]; +const baseKeys = [{ id: 'status' }, { id: 'occurredAt' }, { id: 'assignedUser' }, { id: 'orgUnit' }, { id: 'scheduledAt' }, { id: 'notes' }]; const basedFieldTypes = [ { type: dataElementTypes.STATUS, resolveValue: convertStatusForView }, { type: dataElementTypes.DATE }, diff --git a/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/getEventDataWithSubValue.js b/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/getEventDataWithSubValue.js index a5493d19fd..d0aa4cc038 100644 --- a/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/getEventDataWithSubValue.js +++ b/src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/getEventDataWithSubValue.js @@ -2,6 +2,7 @@ import { featureAvailable, FEATURES } from 'capture-core-utils'; import { dataElementTypes } from '../../../../metaData'; import type { QuerySingleResource } from '../../../../utils/api/api.types'; +import { getOrgUnitNames } from '../../../../metadataRetrieval/orgUnitName'; const getFileResourceSubvalue = async (keys: Object, querySingleResource: QuerySingleResource, eventId: string, absoluteApiPath: string) => { const promises = Object.keys(keys) @@ -57,19 +58,9 @@ const getImageSubvalue = (keys: Object, querySingleResource: QuerySingleResource ); const getOrganisationUnitSubvalue = async (keys: Object, querySingleResource: QuerySingleResource) => { - const ids = Object.values(keys) - .join(','); - - const { organisationUnits = [] } = await querySingleResource({ - resource: 'organisationUnits', - params: { filter: `id:in:[${ids}]` }, - }); - - return organisationUnits - .reduce((acc, { id, displayName: name }) => { - acc[id] = { id, name }; - return acc; - }, {}); + const ids = Object.values(keys).map(value => String(value)); + const orgUnitNames = await getOrgUnitNames(ids, querySingleResource); + return orgUnitNames; }; const subValueGetterByElementType = { diff --git a/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/FlatListOrgUnitField/FlatListOrgUnitField.js b/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/FlatListOrgUnitField/FlatListOrgUnitField.js deleted file mode 100644 index aaf3ffdf3c..0000000000 --- a/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/FlatListOrgUnitField/FlatListOrgUnitField.js +++ /dev/null @@ -1,19 +0,0 @@ -// @flow -import React from 'react'; -import { useOrgUnitNameWithAncestors } from '../../../metadataRetrieval/orgUnitName'; - -type Props = { - orgUnitId: string, -} - -export const FlatListOrgUnitField = ({ - orgUnitId, -}: Props) => { - const { displayName } = useOrgUnitNameWithAncestors(orgUnitId); - - return ( - - {displayName} - - ); -}; diff --git a/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/FlatListOrgUnitField/index.js b/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/FlatListOrgUnitField/index.js deleted file mode 100644 index cf8e8c20b7..0000000000 --- a/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/FlatListOrgUnitField/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow - -export { FlatListOrgUnitField } from './FlatListOrgUnitField'; diff --git a/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/utils/getDataEntryDetails.js b/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/utils/getDataEntryDetails.js index 3e42d171de..a76d895a77 100644 --- a/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/utils/getDataEntryDetails.js +++ b/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/utils/getDataEntryDetails.js @@ -5,7 +5,7 @@ import i18n from '@dhis2/d2-i18n'; import { dataElementTypes, type RenderFoundation } from '../../../metaData'; import { convertClientToView, convertServerToClient } from '../../../converters'; import type { LinkedEvent } from '../WidgetTwoEventWorkspace.types'; -import { FlatListOrgUnitField } from '../FlatListOrgUnitField'; +import { TooltipOrgUnit } from '../../Tooltips/TooltipOrgUnit'; const convertFn = pipe(convertServerToClient, convertClientToView); @@ -37,7 +37,7 @@ const DataEntryFieldsToInclude = { type: dataElementTypes.ORGANISATION_UNIT, placement: Placements.TOP, label: i18n.t('Organisation unit'), - convertFn: orgUnitId => , + convertFn: orgUnitId => , }, status: { apiKey: 'status', diff --git a/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/utils/getSubValueForDataValue.js b/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/utils/getSubValueForDataValue.js index 5de5037e21..2a54bc5f8c 100644 --- a/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/utils/getSubValueForDataValue.js +++ b/src/core_modules/capture-core/components/WidgetTwoEventWorkspace/utils/getSubValueForDataValue.js @@ -2,6 +2,7 @@ import { dataElementTypes } from '../../../metaData'; import type { QuerySingleResource } from '../../../utils/api'; import { featureAvailable, FEATURES } from '../../../../capture-core-utils'; +import { getOrgUnitNames } from '../../../metadataRetrieval/orgUnitName'; type SubValueFunctionProps = { dataElement: Object, @@ -44,15 +45,9 @@ const getImageSubvalue = async ({ dataElement, querySingleResource, eventId, abs }; }; -const getOrganisationUnitSubvalue = async ({ dataElement, querySingleResource }: SubValueFunctionProps) => { - const organisationUnit = await querySingleResource({ - resource: 'organisationUnits', - id: dataElement.value, - params: { - fields: 'id,name', - }, - }); - return { ...organisationUnit }; +const getOrganisationUnitSubvalue = async ({ dataElement: { value }, querySingleResource }: SubValueFunctionProps) => { + const organisationUnits = await getOrgUnitNames([value], querySingleResource); + return organisationUnits[value]; }; export const subValueGetterByElementType = { diff --git a/src/core_modules/capture-core/components/WidgetsChangelog/common/Changelog/Changelog.component.js b/src/core_modules/capture-core/components/WidgetsChangelog/common/Changelog/Changelog.component.js index 9f853a80e1..d43b9a0620 100644 --- a/src/core_modules/capture-core/components/WidgetsChangelog/common/Changelog/Changelog.component.js +++ b/src/core_modules/capture-core/components/WidgetsChangelog/common/Changelog/Changelog.component.js @@ -34,7 +34,9 @@ export const ChangelogComponent = ({ - + ( + + {label} + +); + + +export const ChangelogChangeCell = ({ changeType }: Object) => { + const config = changeTypeConfigs[changeType]; + + if (!config) { + log.error(errorCreator('Changelog component not found')({ changeType })); + return null; + } + + return ( + + ); +}; + diff --git a/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogChangeCell.js b/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogCells/ChangelogValueCell.js similarity index 60% rename from src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogChangeCell.js rename to src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogCells/ChangelogValueCell.js index e5dbef266a..246c7c2651 100644 --- a/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogChangeCell.js +++ b/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogCells/ChangelogValueCell.js @@ -1,11 +1,10 @@ // @flow import React from 'react'; import log from 'loglevel'; -import { colors, IconArrowRight16, spacers, Tag } from '@dhis2/ui'; -import i18n from '@dhis2/d2-i18n'; +import { colors, IconArrowRight16, spacers } from '@dhis2/ui'; import { withStyles } from '@material-ui/core/styles'; -import { CHANGE_TYPES } from '../Changelog/Changelog.constants'; -import { errorCreator } from '../../../../../capture-core-utils'; +import { CHANGE_TYPES } from '../../Changelog/Changelog.constants'; +import { errorCreator } from '../../../../../../capture-core-utils'; type Props = { changeType: $Values, @@ -15,14 +14,16 @@ type Props = { container: string, previousValue: string, currentValue: string, + updatePreviousValue: string, + updateCurrentValue: string, + updateArrow: string, } } const styles = { container: { - display: 'flex', alignItems: 'center', - gap: spacers.dp4, + display: 'flex', }, previousValue: { color: colors.grey700, @@ -30,19 +31,31 @@ const styles = { currentValue: { color: colors.grey900, }, + updatePreviousValue: { + color: colors.grey700, + maxWidth: '45%', + }, + updateCurrentValue: { + color: colors.grey900, + maxWidth: '45%', + }, + updateArrow: { + display: 'inline-flex', + alignItems: 'center', + margin: `${spacers.dp4}`, + }, }; const Updated = ({ previousValue, currentValue, classes }) => (
- {previousValue} - - {currentValue} + {previousValue} + + {currentValue}
); const Created = ({ currentValue, classes }) => (
- {i18n.t('Created')} {currentValue}
); @@ -50,8 +63,6 @@ const Created = ({ currentValue, classes }) => ( const Deleted = ({ previousValue, classes }) => (
{previousValue} - - {i18n.t('Deleted')}
); @@ -61,7 +72,7 @@ const ChangelogComponentsByType = { [CHANGE_TYPES.DELETED]: Deleted, }; -const ChangelogChangeCellPlain = ({ changeType, currentValue, previousValue, classes }: Props) => { +const ChangelogValueCellPlain = ({ changeType, currentValue, previousValue, classes }: Props) => { const ChangelogComponent = ChangelogComponentsByType[changeType]; if (!ChangelogComponent) { @@ -78,4 +89,4 @@ const ChangelogChangeCellPlain = ({ changeType, currentValue, previousValue, cla ); }; -export const ChangelogChangeCell = withStyles(styles)(ChangelogChangeCellPlain); +export const ChangelogValueCell = withStyles(styles)(ChangelogValueCellPlain); diff --git a/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogCells/index.js b/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogCells/index.js new file mode 100644 index 0000000000..d5f9ff3167 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogCells/index.js @@ -0,0 +1,4 @@ +// @flow + +export { ChangelogChangeCell } from './ChangelogChangeCell'; +export { ChangelogValueCell } from './ChangelogValueCell'; diff --git a/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogTableHeader.js b/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogTableHeader.js index 9c3ebd671a..26dc592540 100644 --- a/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogTableHeader.js +++ b/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogTableHeader.js @@ -9,27 +9,30 @@ type Props = { setSortDirection: SetSortDirection, }; -export const ChangelogTableHeader = ({ - sortDirection, - setSortDirection, -}: Props) => ( +export const ChangelogTableHeader = ({ sortDirection, setSortDirection }: Props) => ( setSortDirection(direction)} sortDirection={sortDirection} + fixed + top="0" + width="140px" > {i18n.t('Date')} - + {i18n.t('User')} - + {i18n.t('Data item')} - + {i18n.t('Change')} + + {i18n.t('Value')} + ); diff --git a/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogTableRow.js b/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogTableRow.js index 31c9a1ddbb..e93571cbf2 100644 --- a/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogTableRow.js +++ b/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/ChangelogTableRow.js @@ -1,29 +1,35 @@ // @flow import React from 'react'; import { DataTableCell, DataTableRow } from '@dhis2/ui'; -import { ChangelogChangeCell } from './ChangelogChangeCell'; -import type { ChangelogRecord } from '../Changelog/Changelog.types'; +import { withStyles } from '@material-ui/core/styles'; +import { ChangelogChangeCell, ChangelogValueCell } from './ChangelogCells'; -type Props = {| - record: ChangelogRecord, -|} +type Props = { + record: { + date: string, + user: string, + dataItemLabel: string, + changeType: string, + }, + classes: { + dataItemColumn: string, + valueColumn: string, + }, +}; -export const ChangelogTableRow = ({ record }: Props) => ( - - - {record.date} - - - {record.user} - - - {record.dataItemLabel} - +const styles = { + dataItemColumn: { wordWrap: 'break-word', hyphens: 'auto' }, + valueColumn: { wordWrap: 'break-word' }, +}; - - - +const ChangelogTableRowPlain = ({ record, classes }: Props) => ( + + {record.date} + {record.user} + {record.dataItemLabel} + + ); + +export const ChangelogTableRow = withStyles(styles)(ChangelogTableRowPlain); diff --git a/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/index.js b/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/index.js index 6f2fa32294..f18acb8934 100644 --- a/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/index.js +++ b/src/core_modules/capture-core/components/WidgetsChangelog/common/ChangelogTable/index.js @@ -1,6 +1,5 @@ // @flow export { ChangelogTableHeader } from './ChangelogTableHeader'; -export { ChangelogChangeCell } from './ChangelogChangeCell'; export { ChangelogTableRow } from './ChangelogTableRow'; diff --git a/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/TeiWorkingListsSetup.component.js b/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/TeiWorkingListsSetup.component.js index f2dfe2809b..b59d0233cd 100644 --- a/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/TeiWorkingListsSetup.component.js +++ b/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/TeiWorkingListsSetup.component.js @@ -61,7 +61,7 @@ export const TeiWorkingListsSetup = ({ const prevTemplateId = useRef(currentTemplateId); const defaultColumns = useDefaultColumnConfig(program, orgUnitId, programStageId); const columns = useColumns(customColumnOrder, defaultColumns); - const filtersOnly = useFiltersOnly(program); + const filtersOnly = useFiltersOnly(program, programStageId); const programStageFiltersOnly = useProgramStageFilters(program, programStageId); const staticTemplates = useStaticTemplates( storedTemplates?.find(storedTemplate => storedTemplate.isDefault && storedTemplate.isAltered), diff --git a/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/hooks/useDefaultColumnConfig.js b/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/hooks/useDefaultColumnConfig.js index 3f6b926761..f15ade1d0e 100644 --- a/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/hooks/useDefaultColumnConfig.js +++ b/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/hooks/useDefaultColumnConfig.js @@ -36,13 +36,13 @@ const getProgramStageMainConfig = (programStage): Array => [ { id: ADDITIONAL_FILTERS.status, - visible: false, + visible: true, type: dataElementTypes.TEXT, header: i18n.t(ADDITIONAL_FILTERS_LABELS.status), }, { id: ADDITIONAL_FILTERS.occurredAt, - visible: false, + visible: true, type: dataElementTypes.DATE, header: programStage.stageForm.getLabel('occurredAt') || i18n.t(ADDITIONAL_FILTERS_LABELS.occurredAt), }, @@ -50,7 +50,7 @@ const getProgramStageMainConfig = (programStage): Array => ? [ { id: ADDITIONAL_FILTERS.scheduledAt, - visible: false, + visible: true, type: dataElementTypes.DATE, header: programStage.stageForm.getLabel('scheduledAt') || @@ -58,6 +58,16 @@ const getProgramStageMainConfig = (programStage): Array => }, ] : []), + ...(programStage.enableUserAssignment + ? [ + { + id: ADDITIONAL_FILTERS.assignedUser, + visible: true, + type: dataElementTypes.ASSIGNEE, + header: i18n.t(ADDITIONAL_FILTERS_LABELS.assignee), + }, + ] + : []), ].map(field => ({ ...field, mainProperty: true, diff --git a/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/hooks/useFiltersOnly.js b/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/hooks/useFiltersOnly.js index 155d6b9775..76c4ef14db 100644 --- a/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/hooks/useFiltersOnly.js +++ b/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/hooks/useFiltersOnly.js @@ -4,12 +4,13 @@ import i18n from '@dhis2/d2-i18n'; import { dataElementTypes, type TrackerProgram } from '../../../../../metaData'; import { MAIN_FILTERS } from '../../constants'; -export const useFiltersOnly = ({ - enrollment: { enrollmentDateLabel, incidentDateLabel, showIncidentDate }, - stages, -}: TrackerProgram) => +export const useFiltersOnly = ( + { enrollment: { enrollmentDateLabel, incidentDateLabel, showIncidentDate }, stages }: TrackerProgram, + programStageId?: string, +) => useMemo(() => { - const enableUserAssignment = Array.from(stages.values()).find(stage => stage.enableUserAssignment); + const enableUserAssignment = + !programStageId && Array.from(stages.values()).find(stage => stage.enableUserAssignment); return [ { id: MAIN_FILTERS.PROGRAM_STATUS, @@ -80,9 +81,15 @@ export const useFiltersOnly = ({ id: MAIN_FILTERS.ASSIGNEE, type: dataElementTypes.ASSIGNEE, header: i18n.t('Assigned to'), - transformRecordsFilter: (rawFilter: Object) => rawFilter, + transformRecordsFilter: (rawFilter: Object) => { + const { assignedUser, assignedUserMode } = rawFilter; + return { + assignedUserMode, + ...(assignedUser && { assignedUser }), + }; + }, }, ] : []), ]; - }, [enrollmentDateLabel, incidentDateLabel, showIncidentDate, stages]); + }, [enrollmentDateLabel, incidentDateLabel, showIncidentDate, stages, programStageId]); diff --git a/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/hooks/useProgramStageFilters.js b/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/hooks/useProgramStageFilters.js index d17f1be4b1..108f76bc0e 100644 --- a/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/hooks/useProgramStageFilters.js +++ b/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/Setup/hooks/useProgramStageFilters.js @@ -2,7 +2,7 @@ import { useMemo } from 'react'; import i18n from '@dhis2/d2-i18n'; import { statusTypes, translatedStatusTypes } from 'capture-core/events/statusTypes'; -import { type TrackerProgram, type ProgramStage } from '../../../../../metaData'; +import { type TrackerProgram, type ProgramStage, dataElementTypes } from '../../../../../metaData'; import { ADDITIONAL_FILTERS, ADDITIONAL_FILTERS_LABELS } from '../../helpers'; const useProgramStageData = (programStageId, stages) => @@ -13,12 +13,14 @@ const useProgramStageData = (programStageId, stages) => hideDueDate: programStage.hideDueDate, occurredAtLabel: programStage.stageForm.getLabel('occurredAt'), scheduledAtLabel: programStage.stageForm.getLabel('scheduledAt'), + enableUserAssignment: programStage.enableUserAssignment, }; } return { occurredAtLabel: i18n.t(ADDITIONAL_FILTERS_LABELS.occurredAt), scheduledAtLabel: i18n.t(ADDITIONAL_FILTERS_LABELS.scheduledAt), hideDueDate: undefined, + enableUserAssignment: false, }; }, [programStageId, stages]); @@ -33,7 +35,10 @@ const useProgramStageDropdowOptions = stages => ); export const useProgramStageFilters = ({ stages }: TrackerProgram, programStageId?: string) => { - const { hideDueDate, occurredAtLabel, scheduledAtLabel } = useProgramStageData(programStageId, stages); + const { hideDueDate, occurredAtLabel, scheduledAtLabel, enableUserAssignment } = useProgramStageData( + programStageId, + stages, + ); const options: Array<{ text: string, value: string }> = useProgramStageDropdowOptions(stages); return useMemo(() => { @@ -117,6 +122,22 @@ export const useProgramStageFilters = ({ stages }: TrackerProgram, programStageI }, ] : []), + ...(enableUserAssignment + ? [ + { + id: ADDITIONAL_FILTERS.assignedUser, + type: dataElementTypes.ASSIGNEE, + header: ADDITIONAL_FILTERS_LABELS.assignee, + transformRecordsFilter: (rawFilter: Object) => { + const { assignedUser, assignedUserMode } = rawFilter; + return { + assignedUserMode, + ...(assignedUser && { assignedUser }), + }; + }, + }, + ] + : []), ]; - }, [programStageId, occurredAtLabel, scheduledAtLabel, hideDueDate, options]); + }, [programStageId, occurredAtLabel, scheduledAtLabel, hideDueDate, options, enableUserAssignment]); }; diff --git a/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/helpers/eventFilters/additionalFiltersConvertor.js b/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/helpers/eventFilters/additionalFiltersConvertor.js index 72350fbdf3..ac209da460 100644 --- a/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/helpers/eventFilters/additionalFiltersConvertor.js +++ b/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/helpers/eventFilters/additionalFiltersConvertor.js @@ -4,6 +4,7 @@ export const ADDITIONAL_FILTERS = { occurredAt: 'eventOccurredAt', scheduledAt: 'scheduledAt', status: 'status', + assignedUser: 'assignee', }; export const ADDITIONAL_FILTERS_LABELS = { @@ -11,10 +12,12 @@ export const ADDITIONAL_FILTERS_LABELS = { occurredAt: 'Report date', scheduledAt: 'Scheduled date', status: 'Event status', + assignee: 'Assigned to', }; export const ADDITIONAL_FILTERS_API_NAME = { [ADDITIONAL_FILTERS.occurredAt]: 'occurredAt', + [ADDITIONAL_FILTERS.assignedUser]: 'assignedUser', }; export const getFilterApiName = (clientFilter: string) => ADDITIONAL_FILTERS_API_NAME[clientFilter] || clientFilter; diff --git a/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/helpers/templates/buildArgumentsForTemplate.js b/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/helpers/templates/buildArgumentsForTemplate.js index 9d16721c2e..8f8014a1a1 100644 --- a/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/helpers/templates/buildArgumentsForTemplate.js +++ b/src/core_modules/capture-core/components/WorkingLists/TeiWorkingLists/helpers/templates/buildArgumentsForTemplate.js @@ -9,6 +9,51 @@ import type { TeiWorkingListsColumnConfigs, ApiTrackerQueryCriteria } from '../. import type { FiltersData } from '../../../WorkingListsBase'; import { getOrderQueryArgs } from '../../epics'; +const buildArguments = ({ + filters, + programStageFiltersOnly, + columns, + programStageId, + mainFiltersConverted, +}: { + filters?: FiltersData, + programStageFiltersOnly: Array<{ id: string, type: string }>, + columns: TeiWorkingListsColumnConfigs, + programStageId?: string, + mainFiltersConverted: Object, +}) => { + if (!programStageId) { + return { + assignedUserMode: mainFiltersConverted.assignedUserMode, + assignedUsers: mainFiltersConverted.assignedUsers, + attributesColumns: columns, + dataFilters: [], + status: undefined, + eventOccurredAt: undefined, + scheduledAt: undefined, + }; + } + + const additionalFiltersConverted = convertMainFilters({ + filters, + mainFilters: programStageFiltersOnly, + }); + const { status, eventOccurredAt, scheduledAt } = additionalFiltersConverted; + return { + status, + eventOccurredAt, + scheduledAt, + assignedUserMode: additionalFiltersConverted.assignedUserMode, + assignedUsers: additionalFiltersConverted.assignedUsers, + attributesColumns: columns.filter(column => !column.additionalColumn), + dataFilters: convertToEventFilterQuery({ + filters, + mainFilters: programStageFiltersOnly, + dataElementsValueFilters: columns.filter(column => column.additionalColumn), + }), + }; +}; + export const buildArgumentsForTemplate = ({ filters, filtersOnly, @@ -28,25 +73,20 @@ export const buildArgumentsForTemplate = ({ programId: string, programStageId?: string, }) => { - const { programStatus, occurredAt, enrolledAt, assignedUserMode, assignedUsers, followUp } = convertMainFilters({ + const mainFiltersConverted = convertMainFilters({ filters, mainFilters: filtersOnly, }); - const { status, eventOccurredAt, scheduledAt } = convertMainFilters({ - filters, - mainFilters: programStageFiltersOnly, - }); - const attributeValueFilters = convertToTEIFilterAttributes({ - filters, - attributeValueFilters: programStageId ? columns.filter(column => !column.additionalColumn) : columns, - }); - const dataFilters = programStageId - ? convertToEventFilterQuery({ + const { programStatus, occurredAt, enrolledAt, followUp } = mainFiltersConverted; + const { assignedUserMode, assignedUsers, attributesColumns, dataFilters, status, eventOccurredAt, scheduledAt } = + buildArguments({ filters, - mainFilters: programStageFiltersOnly, - dataElementsValueFilters: columns.filter(column => column.additionalColumn), - }) - : []; + programStageFiltersOnly, + columns, + programStageId, + mainFiltersConverted, + }); + const attributeValueFilters = convertToTEIFilterAttributes({ filters, attributeValueFilters: attributesColumns }); const visibleColumnIds: Array = columns.filter(({ visible }) => visible).map(({ id }) => id); const criteria: ApiTrackerQueryCriteria = { programStatus, diff --git a/src/core_modules/capture-core/converters/clientToList.js b/src/core_modules/capture-core/converters/clientToList.js index a5f39b4105..e72b837179 100644 --- a/src/core_modules/capture-core/converters/clientToList.js +++ b/src/core_modules/capture-core/converters/clientToList.js @@ -8,6 +8,7 @@ import { dataElementTypes, type DataElement } from '../metaData'; import { convertMomentToDateFormatString } from '../utils/converters/date'; import { stringifyNumber } from './common/stringifyNumber'; import { MinimalCoordinates } from '../components/MinimalCoordinates'; +import { TooltipOrgUnit } from '../components/Tooltips/TooltipOrgUnit'; function convertDateForListDisplay(rawValue: string): string { const momentDate = moment(rawValue); @@ -86,10 +87,14 @@ function convertStatusForDisplay(clientValue: Object) { ); } -function convertOrgUnitForDisplay(rawValue: string | Object) { - return (typeof rawValue === 'string' ? rawValue : rawValue.name); +function convertOrgUnitForDisplay(clientValue: string | {id: string}) { + const orgUnitId = typeof clientValue === 'string' ? clientValue : clientValue.id; + return ( + + ); } + const valueConvertersForType = { [dataElementTypes.NUMBER]: stringifyNumber, [dataElementTypes.INTEGER]: stringifyNumber, diff --git a/src/core_modules/capture-core/converters/clientToView.js b/src/core_modules/capture-core/converters/clientToView.js index 115bcbeb69..2849a02b01 100644 --- a/src/core_modules/capture-core/converters/clientToView.js +++ b/src/core_modules/capture-core/converters/clientToView.js @@ -34,11 +34,6 @@ type ImageClientValue = { previewUrl: string, }; -type OrgUnitClientValue = { - name: string, - ancestors?: Array, - tooltip?: string, -}; function convertFileForDisplay(clientValue: FileClientValue) { return ( @@ -57,16 +52,13 @@ function convertImageForDisplay(clientValue: ImageClientValue) { return ; } -function convertOrgUnitForDisplay(clientValue: OrgUnitClientValue) { +function convertOrgUnitForDisplay(clientValue: { id: string }) { return ( - + ); } + const valueConvertersForType = { [dataElementTypes.NUMBER]: stringifyNumber, [dataElementTypes.INTEGER]: stringifyNumber, diff --git a/src/core_modules/capture-core/dataQueries/index.js b/src/core_modules/capture-core/dataQueries/index.js index 913bca576a..c77469ff0c 100644 --- a/src/core_modules/capture-core/dataQueries/index.js +++ b/src/core_modules/capture-core/dataQueries/index.js @@ -1 +1,2 @@ export { useOrganisationUnit } from './useOrganisationUnit'; +export { useOrgUnitAutoSelect } from './useOrgUnitsForAutoSelect'; diff --git a/src/core_modules/capture-core/dataQueries/useOrgUnitsForAutoSelect.js b/src/core_modules/capture-core/dataQueries/useOrgUnitsForAutoSelect.js new file mode 100644 index 0000000000..a2e57ed10a --- /dev/null +++ b/src/core_modules/capture-core/dataQueries/useOrgUnitsForAutoSelect.js @@ -0,0 +1,26 @@ +// @flow +import { useApiMetadataQuery } from '../utils/reactQueryHelpers'; + +export const useOrgUnitAutoSelect = (customQueryOptions: Object) => { + const queryKey = ['organisationUnits']; + const queryFn = { + resource: 'organisationUnits', + params: { + fields: ['id, displayName~rename(name), path'], + withinUserHierarchy: true, + pageSize: 2, + }, + }; + const defaultQueryOptions = { + select: ({ organisationUnits }) => organisationUnits, + }; + + const queryOptions = { ...defaultQueryOptions, ...customQueryOptions }; + + const { data, isLoading } = useApiMetadataQuery(queryKey, queryFn, queryOptions); + + return { + isLoading, + data, + }; +}; diff --git a/src/core_modules/capture-core/events/getSubValues.js b/src/core_modules/capture-core/events/getSubValues.js index 19b36daf2a..7d61eb702a 100644 --- a/src/core_modules/capture-core/events/getSubValues.js +++ b/src/core_modules/capture-core/events/getSubValues.js @@ -37,19 +37,23 @@ const subValueGetterByElementType = { return null; }), [dataElementTypes.IMAGE]: ({ + value, eventId, metaElementId, absoluteApiPath, }: { + value: any, eventId: string, metaElementId: string, absoluteApiPath: string, }) => (featureAvailable(FEATURES.trackerImageEndpoint) ? { + value, url: `${absoluteApiPath}/tracker/events/${eventId}/dataValues/${metaElementId}/image`, previewUrl: `${absoluteApiPath}/tracker/events/${eventId}/dataValues/${metaElementId}/image?dimension=small`, } : { + value, url: `${absoluteApiPath}/events/files?dataElementUid=${metaElementId}&eventUid=${eventId}`, previewUrl: `${absoluteApiPath}/events/files?dataElementUid=${metaElementId}&eventUid=${eventId}&dimension=SMALL`, } @@ -67,11 +71,13 @@ const subValueGetterByElementType = { }) => { const ouIds = value.split('/'); const id = ouIds[ouIds.length - 1]; - return querySingleResource({ resource: 'organisationUnits', + return querySingleResource({ + resource: 'organisationUnits', id, params: { fields: 'id,code,displayName,path', - } }) + }, + }) .then(res => ({ id: res.id, code: res.code, diff --git a/src/core_modules/capture-core/hooks/useProgramInfo/useProgramInfo.js b/src/core_modules/capture-core/hooks/useProgramInfo/useProgramInfo.js index dc2437ed04..2b2a4ddbbb 100644 --- a/src/core_modules/capture-core/hooks/useProgramInfo/useProgramInfo.js +++ b/src/core_modules/capture-core/hooks/useProgramInfo/useProgramInfo.js @@ -4,9 +4,16 @@ import { getProgramFromProgramIdThrowIfNotFound, TrackerProgram } from '../../me import { programTypes } from './programTypes.const'; export const useProgramInfo = (programId: string) => useMemo(() => { - const program = getProgramFromProgramIdThrowIfNotFound(programId); - return { - program, - programType: program instanceof TrackerProgram ? programTypes.TRACKER_PROGRAM : programTypes.EVENT_PROGRAM, - }; + try { + const program = getProgramFromProgramIdThrowIfNotFound(programId); + return { + program, + programType: program instanceof TrackerProgram ? programTypes.TRACKER_PROGRAM : programTypes.EVENT_PROGRAM, + }; + } catch (error) { + return { + program: undefined, + programType: undefined, + }; + } }, [programId]); diff --git a/src/core_modules/capture-core/metaData/helpers/getProgramEventAccess.js b/src/core_modules/capture-core/metaData/helpers/getProgramEventAccess.js index 8fad80830f..3fddd73db8 100644 --- a/src/core_modules/capture-core/metaData/helpers/getProgramEventAccess.js +++ b/src/core_modules/capture-core/metaData/helpers/getProgramEventAccess.js @@ -14,7 +14,7 @@ export function getProgramEventAccess( if (program instanceof EventProgram) { stage = program.stage; } else if (programStageId) { - stage = program.getStage(programStageId); + stage = program?.getStage(programStageId); } if (!stage) { log.error(errorCreator('stage not found')({ programId, programStageId })); diff --git a/src/core_modules/capture-core/metadataRetrieval/orgUnitName/index.js b/src/core_modules/capture-core/metadataRetrieval/orgUnitName/index.js index 21e8b84212..204c983009 100644 --- a/src/core_modules/capture-core/metadataRetrieval/orgUnitName/index.js +++ b/src/core_modules/capture-core/metadataRetrieval/orgUnitName/index.js @@ -3,5 +3,4 @@ export { useOrgUnitNameWithAncestors, useOrgUnitNames, getOrgUnitNames, - getCachedOrgUnitName, } from './orgUnitName'; diff --git a/src/core_modules/capture-core/metadataRetrieval/orgUnitName/orgUnitName.js b/src/core_modules/capture-core/metadataRetrieval/orgUnitName/orgUnitName.js index 56d222c119..c86c4d7c14 100644 --- a/src/core_modules/capture-core/metadataRetrieval/orgUnitName/orgUnitName.js +++ b/src/core_modules/capture-core/metadataRetrieval/orgUnitName/orgUnitName.js @@ -209,5 +209,3 @@ export const useOrgUnitNameWithAncestors = (orgUnitId: ?string): { return { error }; }; - -export const getCachedOrgUnitName = (orgUnitId: string): ?string => displayNameCache[orgUnitId]?.displayName; diff --git a/src/core_modules/capture-core/reducers/descriptions/useNewDashboard.reducerDescription.js b/src/core_modules/capture-core/reducers/descriptions/useNewDashboard.reducerDescription.js deleted file mode 100644 index a2bd768063..0000000000 --- a/src/core_modules/capture-core/reducers/descriptions/useNewDashboard.reducerDescription.js +++ /dev/null @@ -1,17 +0,0 @@ -// @flow -import { createReducerDescription } from '../../trackerRedux/trackerReducer'; -import { actionTypes as dataStoreActionTypes } from '../../components/DataStore/DataStore.types'; - -export const useNewDashboardDesc = createReducerDescription({ - [dataStoreActionTypes.SAVE_DATA_STORE]: (state, action) => { - const newState = { ...state }; - const { dataStore, userDataStore } = action.payload; - newState.dataStore = dataStore; - newState.userDataStore = userDataStore; - - return newState; - }, -}, 'useNewDashboard', { - dataStore: undefined, - userDataStore: undefined, -}); diff --git a/src/core_modules/capture-core/components/WidgetEventEdit/hooks/useAuthorities.js b/src/core_modules/capture-core/utils/authority/useAuthorities.js similarity index 54% rename from src/core_modules/capture-core/components/WidgetEventEdit/hooks/useAuthorities.js rename to src/core_modules/capture-core/utils/authority/useAuthorities.js index 78de4ab612..0bea301f9e 100644 --- a/src/core_modules/capture-core/components/WidgetEventEdit/hooks/useAuthorities.js +++ b/src/core_modules/capture-core/utils/authority/useAuthorities.js @@ -2,11 +2,10 @@ import { useApiMetadataQuery } from 'capture-core/utils/reactQueryHelpers'; const auth = Object.freeze({ - F_UNCOMPLETE_EVENT: 'F_UNCOMPLETE_EVENT', ALL: 'ALL', }); -export const useAuthorities = () => { +export const useAuthorities = ({ authorities }: { authorities: Array }) => { const queryKey = ['authorities']; const queryFn = { resource: 'me.json', @@ -15,13 +14,15 @@ export const useAuthorities = () => { }, }; const queryOptions = { - select: ({ authorities }) => - authorities && - authorities.some(authority => authority === auth.ALL || authority === auth.F_UNCOMPLETE_EVENT), + select: ({ authorities: userAuthorities }) => + userAuthorities && + authorities.some( + authority => userAuthorities.includes(auth.ALL) || userAuthorities.includes(authority), + ), }; const { data } = useApiMetadataQuery(queryKey, queryFn, queryOptions); return { - canEditCompletedEvent: Boolean(data), + hasAuthority: Boolean(data), }; }; diff --git a/src/core_modules/capture-core/utils/routing/index.js b/src/core_modules/capture-core/utils/routing/index.js index 3b533bc3cd..3131c7c491 100644 --- a/src/core_modules/capture-core/utils/routing/index.js +++ b/src/core_modules/capture-core/utils/routing/index.js @@ -2,4 +2,3 @@ export { useLocationQuery } from './useLocationQuery'; export { getLocationQuery } from './getLocationQuery'; export { buildUrlQueryString } from './buildUrlQueryString'; -export { shouldUseNewDashboard } from './newDashboard'; diff --git a/src/core_modules/capture-core/utils/routing/newDashboard.js b/src/core_modules/capture-core/utils/routing/newDashboard.js deleted file mode 100644 index c81265f93e..0000000000 --- a/src/core_modules/capture-core/utils/routing/newDashboard.js +++ /dev/null @@ -1,16 +0,0 @@ -// @flow - -export const shouldUseNewDashboard = ({ - userDataStore, - dataStore, - programId, - teiId, -}: { - userDataStore: any, - dataStore: any, - programId: ?string, - teiId?: ?string, -}): boolean => - Boolean(!programId && teiId) || // Check for when a TEI is created/searched without being enrolled in any program. In this case the URL has the enrollmentId set to 'AUTO'. - userDataStore?.[programId] || - (userDataStore?.[programId] !== false && dataStore?.[programId]); diff --git a/src/core_modules/capture-ui/NonBundledIcon/NonBundledIcon.component.js b/src/core_modules/capture-ui/NonBundledIcon/NonBundledIcon.component.js index dda968e42f..b906adcebb 100644 --- a/src/core_modules/capture-ui/NonBundledIcon/NonBundledIcon.component.js +++ b/src/core_modules/capture-ui/NonBundledIcon/NonBundledIcon.component.js @@ -27,7 +27,9 @@ export const NonBundledIcon = ({ {alternativeText} ) } diff --git a/src/epics/trackerCapture.epics.js b/src/epics/trackerCapture.epics.js index f0bdf3bc7e..48836ddc46 100644 --- a/src/epics/trackerCapture.epics.js +++ b/src/epics/trackerCapture.epics.js @@ -35,11 +35,6 @@ import { deleteTemplateEpic, } from 'capture-core/components/WorkingLists/EventWorkingLists'; -import { - fetchDataStoreEpic, - fetchUserDataStoreEpic, -} from 'capture-core/components/DataStore/DataStore.epics'; - import { getEventFromUrlEpic, } from 'capture-core/components/Pages/ViewEvent/epics/editEvent.epics'; @@ -245,8 +240,6 @@ export const epics = combineEpics( resetProgramAfterSettingOrgUnitIfApplicableEpic, calculateSelectionsCompletenessEpic, triggerLoadCoreEpic, - fetchDataStoreEpic, - fetchUserDataStoreEpic, loadAppEpic, initEventListEpic, initTeiViewEpic, diff --git a/src/reducers/descriptions/trackerCapture.reducerDescriptions.js b/src/reducers/descriptions/trackerCapture.reducerDescriptions.js index 6f6ad63d84..ac35a29082 100644 --- a/src/reducers/descriptions/trackerCapture.reducerDescriptions.js +++ b/src/reducers/descriptions/trackerCapture.reducerDescriptions.js @@ -40,7 +40,6 @@ import { workingListsListRecordsDesc, } from 'capture-core/reducers/descriptions/workingLists'; import { mainPageDesc } from 'capture-core/reducers/descriptions/mainPage.reducerDescription'; -import { useNewDashboardDesc } from 'capture-core/reducers/descriptions/useNewDashboard.reducerDescription'; import { newEventPageDesc } from 'capture-core/reducers/descriptions/newEvent.reducerDescription'; import { editEventPageDesc } from 'capture-core/reducers/descriptions/editEvent.reducerDescription'; import { viewEventPageDesc } from 'capture-core/reducers/descriptions/viewEvent.reducerDescription'; @@ -129,7 +128,6 @@ export const reducerDescriptions = [ searchDomainDesc, teiSearchDesc, trackedEntityInstanceDesc, - useNewDashboardDesc, viewEventPageDesc, workingListsDesc, workingListsMetaDesc,