diff --git a/i18n/en.pot b/i18n/en.pot index b89585a062..8a2d42e9be 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: 2026-06-10T13:04:43.537Z\n" -"PO-Revision-Date: 2026-06-10T13:04:43.537Z\n" +"POT-Creation-Date: 2026-06-19T18:35:22.256Z\n" +"PO-Revision-Date: 2026-06-19T18:35:22.257Z\n" msgid "The application could not be loaded." msgstr "The application could not be loaded." @@ -123,17 +123,43 @@ msgstr "Show less" msgid "Show more" msgstr "Show more" +msgid "This value is validating" +msgstr "This value is validating" + +msgid "Async field update failed" +msgstr "Async field update failed" + msgid "error encountered during field validation" msgstr "error encountered during field validation" msgid "error" msgstr "error" -msgid "This value is validating" -msgstr "This value is validating" +msgid "{{programStageName}} completed" +msgstr "{{programStageName}} completed" -msgid "Async field update failed" -msgstr "Async field update failed" +msgid "Would you like to complete the enrollment and all active events as well?" +msgstr "Would you like to complete the enrollment and all active events as well?" + +msgid "{{count}} event in {{programStageName}}" +msgid_plural "{{count}} event in {{programStageName}}" +msgstr[0] "{{count}} event in {{programStageName}}" +msgstr[1] "{{count}} events in {{programStageName}}" + +msgid "Yes, complete enrollment and events" +msgstr "Yes, complete enrollment and events" + +msgid "Complete enrollment only" +msgstr "Complete enrollment only" + +msgid "No, cancel" +msgstr "No, cancel" + +msgid "Would you like to complete the enrollment?" +msgstr "Would you like to complete the enrollment?" + +msgid "Complete enrollment" +msgstr "Complete enrollment" msgid "Area" msgstr "Area" @@ -306,9 +332,6 @@ msgstr "" msgid "Yes, discard changes" msgstr "Yes, discard changes" -msgid "No, cancel" -msgstr "No, cancel" - msgid "You don't have access to create an event in the current selections" msgstr "You don't have access to create an event in the current selections" @@ -330,29 +353,6 @@ msgstr "Enroll in a program by selecting a program from the top bar." msgid "An error has occurred. See log for details" msgstr "An error has occurred. See log for details" -msgid "{{programStageName}} completed" -msgstr "{{programStageName}} completed" - -msgid "Would you like to complete the enrollment and all active events as well?" -msgstr "Would you like to complete the enrollment and all active events as well?" - -msgid "{{count}} event in {{programStageName}}" -msgid_plural "{{count}} event in {{programStageName}}" -msgstr[0] "{{count}} event in {{programStageName}}" -msgstr[1] "{{count}} events in {{programStageName}}" - -msgid "Yes, complete enrollment and events" -msgstr "Yes, complete enrollment and events" - -msgid "Complete enrollment only" -msgstr "Complete enrollment only" - -msgid "Would you like to complete the enrollment?" -msgstr "Would you like to complete the enrollment?" - -msgid "Complete enrollment" -msgstr "Complete enrollment" - msgid "A duplicate exists (but there were some errors, see log for details" msgstr "A duplicate exists (but there were some errors, see log for details" @@ -479,18 +479,6 @@ msgstr "To" msgid "Period" msgstr "Period" -msgid "Please provide zero or a positive integer" -msgstr "Please provide zero or a positive integer" - -msgid "Please specify the number of days" -msgstr "Please specify the number of days" - -msgid "Days in the past" -msgstr "Days in the past" - -msgid "Days in the future" -msgstr "Days in the future" - msgid "This week" msgstr "This week" @@ -515,6 +503,18 @@ msgstr "Absolute range" msgid "Relative range" msgstr "Relative range" +msgid "Please provide zero or a positive integer" +msgstr "Please provide zero or a positive integer" + +msgid "Please specify the number of days" +msgstr "Please specify the number of days" + +msgid "Days in the past" +msgstr "Days in the past" + +msgid "Days in the future" +msgstr "Days in the future" + msgid "Please specify a date" msgstr "Please specify a date" @@ -649,9 +649,6 @@ msgid_plural "Please enter at least {{minCharactersToSearch}} character to filte msgstr[0] "Please enter at least {{minCharactersToSearch}} character to filter" msgstr[1] "Please enter at least {{minCharactersToSearch}} characters to filter" -msgid "Locked to{{escape}} {{buttonText}}" -msgstr "Locked to{{escape}} {{buttonText}}" - msgid "{{fromDate}} to {{toDate}}" msgstr "{{fromDate}} to {{toDate}}" @@ -679,6 +676,9 @@ msgstr "after or equal to" msgid "before or equal to" msgstr "before or equal to" +msgid "Locked to{{escape}} {{buttonText}}" +msgstr "Locked to{{escape}} {{buttonText}}" + msgid "More filters" msgstr "More filters" @@ -712,6 +712,92 @@ msgstr "Notice" msgid "Close the notice" msgstr "Close the notice" +msgid "tracked entity instance" +msgstr "tracked entity instance" + +msgid "Enter details now is not available when creating a relationship" +msgstr "Enter details now is not available when creating a relationship" + +msgid "Save new {{trackedEntityTypeName}} and link" +msgstr "Save new {{trackedEntityTypeName}} and link" + +msgid "Link" +msgstr "Link" + +msgid "Save as new {{trackedEntityName}}" +msgstr "Save as new {{trackedEntityName}}" + +msgid "Some programs are being filtered." +msgstr "Some programs are being filtered." + +msgid "Show all" +msgstr "Show all" + +msgid "Program" +msgstr "Program" + +msgid "Registration" +msgstr "Registration" + +msgid "Organisation Unit" +msgstr "Organisation Unit" + +msgid "All accessible" +msgstr "All accessible" + +msgid "Selected" +msgstr "Selected" + +msgid "Please select an organisation unit." +msgstr "Please select an organisation unit." + +msgid "Organisation unit scope" +msgstr "Organisation unit scope" + +msgid "Selected program" +msgstr "Selected program" + +msgid "Search {{uniqueAttrName}}" +msgstr "Search {{uniqueAttrName}}" + +msgid "Search by attributes" +msgstr "Search by attributes" + +msgid "Search {{attributeName}}" +msgstr "Search {{attributeName}}" + +msgid "Fill in at least {{count}} attribute to search" +msgid_plural "Fill in at least {{count}} attribute to search" +msgstr[0] "Fill in at least {{count}} attribute to search" +msgstr[1] "Fill in at least {{count}} attributes to search" + +msgid "Missing search criteria" +msgstr "Missing search criteria" + +msgid "Please fill in {{uniqueTEAName}} to search" +msgstr "Please fill in {{uniqueTEAName}} to search" + +msgid "Back to search" +msgstr "Back to search" + +msgid "Search form is missing. See log for details" +msgstr "Search form is missing. See log for details" + +msgid "Could not retrieve metadata. Please try again later." +msgstr "Could not retrieve metadata. Please try again later." + +msgid "Choose an organisation unit to start reporting" +msgstr "Choose an organisation unit to start reporting" + +msgid "The enrollment event data could not be found" +msgstr "The enrollment event data could not be found" + +msgid "Loading" +msgstr "Loading" + +msgid "An error occurred while loading the form" +msgstr "An error occurred while loading the form" + msgid "Quick actions" msgstr "Quick actions" @@ -724,6 +810,18 @@ msgstr "Make referral" msgid "No available program stages" msgstr "No available program stages" +msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" +msgstr "Enrollment with id \"{{enrollmentId}}\" does not exist" + +msgid "Tracked entity instance with id \"{{teiId}}\" does not exist" +msgstr "Tracked entity instance with id \"{{teiId}}\" does not exist" + +msgid "Program with id \"{{programId}}\" does not exist" +msgstr "Program with id \"{{programId}}\" does not exist" + +msgid "An error occurred while fetching enrollments. Please enter a valid url." +msgstr "An error occurred while fetching enrollments. Please enter a valid url." + msgid "Invalid enrollment id {{enrollmentId}}." msgstr "Invalid enrollment id {{enrollmentId}}." @@ -778,18 +876,6 @@ msgstr "Create a new event in this program." msgid "View working list in this program." msgstr "View working list in this program." -msgid "Enrollment with id \"{{enrollmentId}}\" does not exist" -msgstr "Enrollment with id \"{{enrollmentId}}\" does not exist" - -msgid "Tracked entity instance with id \"{{teiId}}\" does not exist" -msgstr "Tracked entity instance with id \"{{teiId}}\" does not exist" - -msgid "Program with id \"{{programId}}\" does not exist" -msgstr "Program with id \"{{programId}}\" does not exist" - -msgid "An error occurred while fetching enrollments. Please enter a valid url." -msgstr "An error occurred while fetching enrollments. Please enter a valid url." - msgid "An error has occurred" msgstr "An error has occurred" @@ -885,9 +971,6 @@ msgstr "" "You don't have access to create a {{trackedEntityName}} in the current " "selections" -msgid "Choose an organisation unit to start reporting" -msgstr "Choose an organisation unit to start reporting" - msgid "Choose the {{missingCategories}} to start reporting" msgstr "Choose the {{missingCategories}} to start reporting" @@ -909,32 +992,8 @@ msgstr "Save {{trackedEntityTypeName}}" msgid "Save {{trackedEntityName}}" msgstr "Save {{trackedEntityName}}" -msgid "Enter details now is not available when creating a relationship" -msgstr "Enter details now is not available when creating a relationship" - -msgid "Save new {{trackedEntityTypeName}} and link" -msgstr "Save new {{trackedEntityTypeName}} and link" - -msgid "Link" -msgstr "Link" - -msgid "Save as new {{trackedEntityName}}" -msgstr "Save as new {{trackedEntityName}}" - -msgid "Some programs are being filtered." -msgstr "Some programs are being filtered." - -msgid "Show all" -msgstr "Show all" - -msgid "Program" -msgstr "Program" - -msgid "Organisation Unit" -msgstr "Organisation Unit" - -msgid "Registration" -msgstr "Registration" +msgid "Register" +msgstr "Register" msgid "Search results" msgstr "Search results" @@ -954,9 +1013,6 @@ msgstr "Link to an existing {{trackedEntityType}}" msgid "Create new {{trackedEntityType}}" msgstr "Create new {{trackedEntityType}}" -msgid "Register" -msgstr "Register" - msgid "Back" msgstr "Back" @@ -966,6 +1022,15 @@ msgstr "events" msgid "event" msgstr "event" +msgid "Event could not be loaded. Are you sure it exists?" +msgstr "Event could not be loaded. Are you sure it exists?" + +msgid "Event could not be loaded" +msgstr "Event could not be loaded" + +msgid "Organisation unit could not be loaded" +msgstr "Organisation unit could not be loaded" + msgid "View changelog" msgstr "View changelog" @@ -991,79 +1056,14 @@ msgstr "This event doesn't have any relationships" msgid "Warnings" msgstr "Warnings" -msgid "Event could not be loaded. Are you sure it exists?" -msgstr "Event could not be loaded. Are you sure it exists?" +msgid "First Page" +msgstr "First Page" -msgid "Event could not be loaded" -msgstr "Event could not be loaded" +msgid "Previous Page" +msgstr "Previous Page" -msgid "Organisation unit could not be loaded" -msgstr "Organisation unit could not be loaded" - -msgid "tracked entity instance" -msgstr "tracked entity instance" - -msgid "All accessible" -msgstr "All accessible" - -msgid "Selected" -msgstr "Selected" - -msgid "Please select an organisation unit." -msgstr "Please select an organisation unit." - -msgid "Organisation unit scope" -msgstr "Organisation unit scope" - -msgid "Selected program" -msgstr "Selected program" - -msgid "Search {{uniqueAttrName}}" -msgstr "Search {{uniqueAttrName}}" - -msgid "Search by attributes" -msgstr "Search by attributes" - -msgid "Search {{attributeName}}" -msgstr "Search {{attributeName}}" - -msgid "Fill in at least {{count}} attribute to search" -msgid_plural "Fill in at least {{count}} attribute to search" -msgstr[0] "Fill in at least {{count}} attribute to search" -msgstr[1] "Fill in at least {{count}} attributes to search" - -msgid "Missing search criteria" -msgstr "Missing search criteria" - -msgid "Please fill in {{uniqueTEAName}} to search" -msgstr "Please fill in {{uniqueTEAName}} to search" - -msgid "Back to search" -msgstr "Back to search" - -msgid "Search form is missing. See log for details" -msgstr "Search form is missing. See log for details" - -msgid "Could not retrieve metadata. Please try again later." -msgstr "Could not retrieve metadata. Please try again later." - -msgid "The enrollment event data could not be found" -msgstr "The enrollment event data could not be found" - -msgid "Loading" -msgstr "Loading" - -msgid "An error occurred while loading the form" -msgstr "An error occurred while loading the form" - -msgid "First Page" -msgstr "First Page" - -msgid "Previous Page" -msgstr "Previous Page" - -msgid "Next Page" -msgstr "Next Page" +msgid "Next Page" +msgstr "Next Page" msgid "Possible duplicates found" msgstr "Possible duplicates found" @@ -1371,15 +1371,24 @@ msgstr "Remove mark for follow-up" msgid "Mark for follow-up" msgstr "Mark for follow-up" +msgid "An error occurred while transferring ownership" +msgstr "An error occurred while transferring ownership" + msgid "Transfer" msgstr "Transfer" -msgid "An error occurred while transferring ownership" -msgstr "An error occurred while transferring ownership" +msgid "Cancelled" +msgstr "Cancelled" msgid "Existing dates for auto-generated events will not be updated." msgstr "Existing dates for auto-generated events will not be updated." +msgid "Add coordinates" +msgstr "Add coordinates" + +msgid "Add area" +msgstr "Add area" + msgid "Latitude" msgstr "Latitude" @@ -1421,6 +1430,9 @@ msgstr "" "You will lose access to the enrollment when transferring ownership to " "{{organisationUnit}}." +msgid "organisation unit" +msgstr "organisation unit" + msgid "Transfer Ownership" msgstr "Transfer Ownership" @@ -1431,6 +1443,16 @@ msgstr "" "Choose the organisation unit to which enrollment ownership should be " "transferred." +msgid "Cannot transfer to this {{orgUnitLabel}}" +msgstr "Cannot transfer to this {{orgUnitLabel}}" + +msgid "" +"The enrollment date is outside the selected {{orgUnitLabel}}'s opening and " +"closing dates." +msgstr "" +"The enrollment date is outside the selected {{orgUnitLabel}}'s opening and " +"closing dates." + msgid "Enrollment date" msgstr "Enrollment date" @@ -1449,15 +1471,6 @@ msgstr "Started at{{escape}}" msgid "Owned by{{escape}}" msgstr "Owned by{{escape}}" -msgid "Cancelled" -msgstr "Cancelled" - -msgid "Add coordinates" -msgstr "Add coordinates" - -msgid "Add area" -msgstr "Add area" - msgid "Program stage not found" msgstr "Program stage not found" @@ -1617,6 +1630,9 @@ msgstr "{{trackedEntityName}} profile" msgid "Profile" msgstr "Profile" +msgid "Fix errors in the form to continue." +msgstr "Fix errors in the form to continue." + msgid "There is a problem with this form" msgstr "There is a problem with this form" @@ -1629,9 +1645,6 @@ msgstr "There was a problem saving changes" msgid "Try again or contact your system administrator for support" msgstr "Try again or contact your system administrator for support" -msgid "Fix errors in the form to continue." -msgstr "Fix errors in the form to continue." - msgid "You do not have access to delete this {{trackedEntityTypeName}}" msgstr "You do not have access to delete this {{trackedEntityTypeName}}" @@ -1668,12 +1681,36 @@ msgstr "No attributes configured" msgid "{{trackedEntityTypeName}} profile" msgstr "{{trackedEntityTypeName}} profile" +msgid "Enter details now" +msgstr "Enter details now" + +msgid "Link to an existing event" +msgstr "Link to an existing event" + +msgid "The event was successfully linked" +msgstr "The event was successfully linked" + +msgid "An error occurred while linking the event" +msgstr "An error occurred while linking the event" + +msgid "Scheduled date" +msgstr "Scheduled date" + +msgid "Report date" +msgstr "Report date" + msgid "Choose a {{linkableStageLabel}} event" msgstr "Choose a {{linkableStageLabel}} event" msgid "Select an event" msgstr "Select an event" +msgid "Please enter a date" +msgstr "Please enter a date" + +msgid "Please select a valid event" +msgstr "Please select a valid event" + msgid "{{ linkableStageLabel }} can only have one event" msgstr "{{ linkableStageLabel }} can only have one event" @@ -1692,29 +1729,104 @@ msgstr "Enter details" msgid "Linked event" msgstr "Linked event" -msgid "Enter details now" -msgstr "Enter details now" +msgid "Changelog" +msgstr "Changelog" -msgid "Link to an existing event" -msgstr "Link to an existing event" +msgid "No changes to display" +msgstr "No changes to display" -msgid "The event was successfully linked" -msgstr "The event was successfully linked" +msgid "Data item" +msgstr "Data item" -msgid "An error occurred while linking the event" -msgstr "An error occurred while linking the event" +msgid "Updated" +msgstr "Updated" -msgid "Scheduled date" -msgstr "Scheduled date" +msgid "Created" +msgstr "Created" -msgid "Report date" -msgstr "Report date" +msgid "Deleted" +msgstr "Deleted" -msgid "Please enter a date" -msgstr "Please enter a date" +msgid "Sort by date" +msgstr "Sort by date" -msgid "Please select a valid event" -msgstr "Please select a valid event" +msgid "User" +msgstr "User" + +msgid "Sort by username" +msgstr "Sort by username" + +msgid "Sort by data item" +msgstr "Sort by data item" + +msgid "Change" +msgstr "Change" + +msgid "Value" +msgstr "Value" + +msgid "File" +msgstr "File" + +msgid "Image" +msgstr "Image" + +msgid "Delete relationship" +msgstr "Delete relationship" + +msgid "Deleting the relationship is permanent and cannot be undone." +msgstr "Deleting the relationship is permanent and cannot be undone." + +msgid "Are you sure you want to delete this relationship?" +msgstr "Are you sure you want to delete this relationship?" + +msgid "Yes, delete relationship" +msgstr "Yes, delete relationship" + +msgid "An error occurred while deleting the relationship." +msgstr "An error occurred while deleting the relationship." + +msgid "Show {{ rest }} more" +msgstr "Show {{ rest }} more" + +msgid "To open this relationship, please wait until saving is complete" +msgstr "To open this relationship, please wait until saving is complete" + +msgid "This enrollment doesn't have any relationships" +msgstr "This enrollment doesn't have any relationships" + +msgid "Type" +msgstr "Type" + +msgid "Created date" +msgstr "Created date" + +msgid "Program stage name" +msgstr "Program stage name" + +msgid "New {{trackedEntityTypeName}} relationship" +msgstr "New {{trackedEntityTypeName}} relationship" + +msgid "An error occurred while adding the relationship" +msgstr "An error occurred while adding the relationship" + +msgid "Missing implementation step" +msgstr "Missing implementation step" + +msgid "Go back without saving relationship" +msgstr "Go back without saving relationship" + +msgid "New Relationship" +msgstr "New Relationship" + +msgid "Link to an existing {{tetName}}" +msgstr "Link to an existing {{tetName}}" + +msgid "Something went wrong while loading relationships. Please try again later." +msgstr "Something went wrong while loading relationships. Please try again later." + +msgid "{{trackedEntityTypeName}} relationships" +msgstr "{{trackedEntityTypeName}} relationships" msgid "This stage can only have one event" msgstr "This stage can only have one event" @@ -1743,9 +1855,6 @@ msgstr "Skip" msgid "To open this event, please wait until saving is complete" msgstr "To open this event, please wait until saving is complete" -msgid "Show {{ rest }} more" -msgstr "Show {{ rest }} more" - msgid "Go to full {{ eventName }}" msgstr "Go to full {{ eventName }}" @@ -1809,6 +1918,9 @@ msgstr "You do not have access to remove the link between these events" msgid "You do not have access to remove the link and delete the linked event" msgstr "You do not have access to remove the link and delete the linked event" +msgid "Scheduled" +msgstr "Scheduled" + msgid "An error occurred while loading the widget." msgstr "An error occurred while loading the widget." @@ -1819,114 +1931,15 @@ msgstr "" "This {{stageName}} event is linked to a {{linkedStageName}} event. Review " "the linked event details before entering data below" -msgid "Scheduled" -msgstr "Scheduled" - -msgid "Changelog" -msgstr "Changelog" - -msgid "No changes to display" -msgstr "No changes to display" - -msgid "Data item" -msgstr "Data item" - -msgid "Updated" -msgstr "Updated" - -msgid "Created" -msgstr "Created" - -msgid "Deleted" -msgstr "Deleted" - -msgid "Sort by date" -msgstr "Sort by date" - -msgid "User" -msgstr "User" - -msgid "Sort by username" -msgstr "Sort by username" - -msgid "Sort by data item" -msgstr "Sort by data item" - -msgid "Change" -msgstr "Change" - -msgid "Value" -msgstr "Value" - -msgid "File" -msgstr "File" - -msgid "Image" -msgstr "Image" - -msgid "New {{trackedEntityTypeName}} relationship" -msgstr "New {{trackedEntityTypeName}} relationship" - -msgid "Missing implementation step" -msgstr "Missing implementation step" - -msgid "Go back without saving relationship" -msgstr "Go back without saving relationship" - -msgid "New Relationship" -msgstr "New Relationship" - -msgid "Link to an existing {{tetName}}" -msgstr "Link to an existing {{tetName}}" - -msgid "An error occurred while adding the relationship" -msgstr "An error occurred while adding the relationship" - -msgid "Something went wrong while loading relationships. Please try again later." -msgstr "Something went wrong while loading relationships. Please try again later." - -msgid "{{trackedEntityTypeName}} relationships" -msgstr "{{trackedEntityTypeName}} relationships" - -msgid "Delete relationship" -msgstr "Delete relationship" - -msgid "Deleting the relationship is permanent and cannot be undone." -msgstr "Deleting the relationship is permanent and cannot be undone." - -msgid "Are you sure you want to delete this relationship?" -msgstr "Are you sure you want to delete this relationship?" - -msgid "Yes, delete relationship" -msgstr "Yes, delete relationship" - -msgid "An error occurred while deleting the relationship." -msgstr "An error occurred while deleting the relationship." - -msgid "To open this relationship, please wait until saving is complete" -msgstr "To open this relationship, please wait until saving is complete" - -msgid "This enrollment doesn't have any relationships" -msgstr "This enrollment doesn't have any relationships" - -msgid "Type" -msgstr "Type" - -msgid "Created date" -msgstr "Created date" - -msgid "Program stage name" -msgstr "Program stage name" - msgid "Working list could not be loaded" msgstr "Working list could not be loaded" -msgid "Download data..." -msgstr "Download data..." - msgid "an error occurred loading working lists" msgstr "an error occurred loading working lists" +msgid "Download data..." +msgstr "Download data..." + msgid "You do not have access to complete events" msgstr "You do not have access to complete events" @@ -1972,6 +1985,12 @@ msgstr "This cannot be undone." msgid "Are you sure you want to delete the selected events?" msgstr "Are you sure you want to delete the selected events?" +msgid "Working list could not be updated" +msgstr "Working list could not be updated" + +msgid "an error occurred loading the working lists" +msgstr "an error occurred loading the working lists" + msgid "Owner organisation unit" msgstr "Owner organisation unit" @@ -2112,12 +2131,6 @@ msgstr "Are you sure you want to delete?" msgid "An error occurred while deleting the records" msgstr "An error occurred while deleting the records" -msgid "Working list could not be updated" -msgstr "Working list could not be updated" - -msgid "an error occurred loading the working lists" -msgstr "an error occurred loading the working lists" - msgid "Update view" msgstr "Update view" @@ -2298,6 +2311,19 @@ msgstr "Please enter a valid time" msgid "Please enter a time" msgstr "Please enter a time" +msgid "" +"Date must be within the {{orgUnitLabel}}'s opening and closing dates " +"({{opening}} – {{closed}})" +msgstr "" +"Date must be within the {{orgUnitLabel}}'s opening and closing dates " +"({{opening}} – {{closed}})" + +msgid "Date cannot be before the {{orgUnitLabel}}'s opening date ({{opening}})" +msgstr "Date cannot be before the {{orgUnitLabel}}'s opening date ({{opening}})" + +msgid "Date cannot be after the {{orgUnitLabel}}'s closing date ({{closed}})" +msgstr "Date cannot be after the {{orgUnitLabel}}'s closing date ({{closed}})" + msgid "" "The following attribute type is not supported for searching and has been " "hidden" diff --git a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentDataEntry.component.tsx b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentDataEntry.component.tsx index 81802aa393..eab277cd72 100644 --- a/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentDataEntry.component.tsx +++ b/src/core_modules/capture-core/components/DataEntries/Enrollment/EnrollmentDataEntry.component.tsx @@ -4,6 +4,11 @@ import i18n from '@dhis2/d2-i18n'; import moment from 'moment'; import { type OrgUnit } from '@dhis2/rules-engine-javascript'; import { convertDateObjectToDateFormatString } from 'capture-core/utils/converters/date'; +import { + getOrgUnitOpeningCalendarMin, + getOrgUnitClosingCalendarMax, +} from 'capture-core/utils/orgUnits/getOrgUnitCalendarBounds'; +import { getOrgUnitLabel } from 'capture-core/utils/orgUnits/getOrgUnitLabel'; import { isLangRtl } from '../../../utils/rtl'; import { DataEntry, @@ -118,14 +123,14 @@ const getEnrollmentDateSettings = () => { required: true, calendarWidth: props.formHorizontal ? 250 : 350, popupAnchorPosition: getCalendarAnchorPosition(props.formHorizontal), - calendarMax: !props.enrollmentMetadata.allowFutureEnrollmentDate ? - convertDateObjectToDateFormatString(moment()) : - undefined, + calendarMax: getOrgUnitClosingCalendarMax(props.orgUnit, !props.enrollmentMetadata.allowFutureEnrollmentDate), + calendarMin: getOrgUnitOpeningCalendarMin(props.orgUnit), calendarType: systemSettingsStore.get().calendar, dateFormat: systemSettingsStore.get().dateFormat, }), getPropName: () => 'enrolledAt', - getValidatorContainers: getEnrollmentDateValidatorContainer, + getValidatorContainers: (props: any) => + getEnrollmentDateValidatorContainer(props?.orgUnit, getOrgUnitLabel(props?.programId)), getPassOnFieldData: () => true, getMeta: () => ({ placement: placements.TOP, diff --git a/src/core_modules/capture-core/components/DataEntries/Enrollment/fieldValidators/enrollmentDate.validatorContainersGetter.ts b/src/core_modules/capture-core/components/DataEntries/Enrollment/fieldValidators/enrollmentDate.validatorContainersGetter.ts index 90cd7edda6..1bc1279fd4 100644 --- a/src/core_modules/capture-core/components/DataEntries/Enrollment/fieldValidators/enrollmentDate.validatorContainersGetter.ts +++ b/src/core_modules/capture-core/components/DataEntries/Enrollment/fieldValidators/enrollmentDate.validatorContainersGetter.ts @@ -1,6 +1,11 @@ import i18n from '@dhis2/d2-i18n'; import { hasValue } from 'capture-core-utils/validators/form'; -import { isValidDate, isValidNonFutureDate } from '../../../../utils/validation/validators/form'; +import { + isValidDate, + isValidNonFutureDate, + getWithinOrgUnitDateRangeValidator, +} from '../../../../utils/validation/validators/form'; +import type { OrgUnitDateRange } from '../../../../utils/orgUnits/getOrgUnitCalendarBounds'; const isValidEnrollmentDate = (value: string, internalComponentError?: {error?: string, errorCode?: string}) => { if (!value) { @@ -10,7 +15,7 @@ const isValidEnrollmentDate = (value: string, internalComponentError?: {error?: return isValidDate(value, internalComponentError); }; -export const getEnrollmentDateValidatorContainer = () => { +export const getEnrollmentDateValidatorContainer = (orgUnit?: OrgUnitDateRange | null, orgUnitLabel?: string | null) => { const validatorContainers = [ { validator: hasValue, @@ -24,6 +29,12 @@ export const getEnrollmentDateValidatorContainer = () => { { validator: isValidNonFutureDate, errorMessage: i18n.t('A date in the future is not allowed'), }, + { + // The message is built by the validator itself (it interpolates the org unit's + // opening/closing dates and label), so the static fallback is intentionally empty. + validator: getWithinOrgUnitDateRangeValidator(orgUnit, orgUnitLabel), + errorMessage: '', + }, ]; return validatorContainers; }; diff --git a/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.component.tsx b/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.component.tsx index a60123b6fe..3156959bc1 100644 --- a/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.component.tsx +++ b/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.component.tsx @@ -4,6 +4,10 @@ import type { ReduxAction } from 'capture-core-utils/types'; import i18n from '@dhis2/d2-i18n'; import { type OrgUnit } from '@dhis2/rules-engine-javascript'; import { isLangRtl } from '../../../../../utils/rtl'; +import { + getOrgUnitOpeningCalendarMin, + getOrgUnitClosingCalendarMax, +} from '../../../../../utils/orgUnits/getOrgUnitCalendarBounds'; import { DataEntry as DataEntryContainer } from '../../../../DataEntry/DataEntry.container'; import { withCancelButton } from '../../../../DataEntry/withCancelButton'; import { withDataEntryField } from '../../../../DataEntry/dataEntryField/withDataEntryField'; @@ -175,6 +179,8 @@ const buildReportDateSettingsFn = () => { calendarWidth: props.formHorizontal ? 250 : 350, orientation: getOrientation(props.formHorizontal), popupAnchorPosition: getCalendarAnchorPosition(props.formHorizontal), + calendarMax: getOrgUnitClosingCalendarMax(props.orgUnit), + calendarMin: getOrgUnitOpeningCalendarMin(props.orgUnit), calendarType: systemSettingsStore.get().calendar, dateFormat: systemSettingsStore.get().dateFormat, }), @@ -521,6 +527,7 @@ type Props = { programName: string, orgUnitId: string, orgUnit: OrgUnit, + orgUnitWithDates?: OrgUnit, orgUnitName: string, stageName: string, onUpdateDataEntryField: (orgUnit: OrgUnit) => (innerAction: ReduxAction) => void, @@ -650,6 +657,7 @@ class NewEventDataEntry extends Component> onStartAsyncUpdateField, programName, // eslint-disable-line orgUnit, + orgUnitWithDates, orgUnitName, // eslint-disable-line classes, onSave, @@ -671,7 +679,7 @@ class NewEventDataEntry extends Component> fieldOptions={this.fieldOptions} dataEntrySections={this.dataEntrySections} relationshipsRef={this.setRelationshipsInstance} - orgUnit={orgUnit} + orgUnit={orgUnitWithDates ?? orgUnit} // @ts-expect-error - keeping original functionality as before ts rewrite orgUnitId={orgUnit?.id} {...passOnProps} diff --git a/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.container.ts b/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.container.tsx similarity index 82% rename from src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.container.ts rename to src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.container.tsx index 6248331077..b93fa80427 100644 --- a/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.container.ts +++ b/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.container.tsx @@ -1,5 +1,6 @@ +import React from 'react'; import { v4 as uuid } from 'uuid'; -import { connect } from 'react-redux'; +import { connect, useSelector } from 'react-redux'; import i18n from '@dhis2/d2-i18n'; import { batchActions } from 'redux-batched-actions'; import type { OrgUnit } from '@dhis2/rules-engine-javascript'; @@ -24,6 +25,7 @@ import { } from './dataEntry.selectors'; import type { RenderFoundation } from '../../../../../metaData'; import { withLoadingIndicator, withErrorMessageHandler } from '../../../../../HOC'; +import { useOrgUnitWithDates } from '../../../../../metadataRetrieval/coreOrgUnit'; import { newEventSaveTypes } from './newEventSaveTypes'; const makeMapStateToProps = () => { @@ -32,8 +34,8 @@ const makeMapStateToProps = () => { const mapStateToProps = (state: any, props: any) => ({ recentlyAddedRelationshipId: state.newEventPage.recentlyAddedRelationshipId, ready: !state.activePage.isDataEntryLoading, - error: !props.formFoundation ? - i18n.t('This is not an event program or the metadata is corrupt. See log for details.') : null, + error: props.formFoundation ? + null : i18n.t('This is not an event program or the metadata is corrupt. See log for details.'), programName: programNameSelector(state), orgUnit: state.dataEntriesFieldsValue['singleEvent-newEvent']?.orgUnit, orgUnitName: state.dataEntriesFieldsValue['singleEvent-newEvent']?.orgUnit?.name, @@ -110,6 +112,17 @@ const mapDispatchToProps = (dispatch: any) => ({ }, }); -export const DataEntry = connect(makeMapStateToProps, mapDispatchToProps)( +const ConnectedDataEntry = connect(makeMapStateToProps, mapDispatchToProps)( withLoadingIndicator()(withErrorMessageHandler()(DataEntryComponent)), ); + +// The org unit is selected within the form (and lives in redux), so we enrich the field value +// here — not in the parent wrapper — with its opening/closing dates, allowing the occurred-date +// field to enforce the org unit's open/close range. The bare `orgUnit` (save/rules) is untouched. +export const DataEntry = (props: any) => { + const orgUnitFieldValue = useSelector( + (state: any) => state.dataEntriesFieldsValue['singleEvent-newEvent']?.orgUnit, + ); + const orgUnitWithDates = useOrgUnitWithDates(orgUnitFieldValue); + return ; +}; diff --git a/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/fieldValidators/eventDate.validatorContainersGetter.ts b/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/fieldValidators/eventDate.validatorContainersGetter.ts index 769cad5481..61ee55490c 100644 --- a/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/fieldValidators/eventDate.validatorContainersGetter.ts +++ b/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/fieldValidators/eventDate.validatorContainersGetter.ts @@ -1,8 +1,13 @@ import { hasValue } from 'capture-core-utils/validators/form'; import i18n from '@dhis2/d2-i18n'; -import { isValidDate, isValidPeriod } from '../../../../../../utils/validation/validators/form'; +import { + isValidDate, + isValidPeriod, + getWithinOrgUnitDateRangeValidator, +} from '../../../../../../utils/validation/validators/form'; import { convertFormToClient } from '../../../../../../converters'; import { dataElementTypes } from '../../../../../../metaData'; +import { getOrgUnitLabel } from '../../../../../../utils/orgUnits/getOrgUnitLabel'; const preValidateDate = ( value?: string, @@ -47,4 +52,10 @@ export const getEventDateValidatorContainers = (props?: any) => [ validator: (value: string) => validateNotExpired(value, props), errorMessage: '', }, + { + // The message is built by the validator itself (it interpolates the org unit's + // opening/closing dates and label), so the static fallback is intentionally empty. + validator: getWithinOrgUnitDateRangeValidator(props?.orgUnit, getOrgUnitLabel(props?.programId)), + errorMessage: '', + }, ]; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/TransferModal/TransferModal.component.tsx b/src/core_modules/capture-core/components/WidgetEnrollment/TransferModal/TransferModal.component.tsx index 0ed8c66bc4..59e19942ec 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/TransferModal/TransferModal.component.tsx +++ b/src/core_modules/capture-core/components/WidgetEnrollment/TransferModal/TransferModal.component.tsx @@ -6,12 +6,16 @@ import { ModalActions, ButtonStrip, Button, + NoticeBox, } from '@dhis2/ui'; import i18n from '@dhis2/d2-i18n'; +import { isIsoDateWithinOrgUnitRange } from 'capture-core/utils/validation/validators/form'; +import { getOrgUnitLabel } from 'capture-core/utils/orgUnits/getOrgUnitLabel'; import type { TransferModalProps } from './TransferModal.types'; import { OrgUnitField } from './OrgUnitField'; import { useTransferValidation } from './hooks/useTransferValidation'; import { InfoBoxes } from './InfoBoxes'; +import { useCoreOrgUnit } from '../../../metadataRetrieval/coreOrgUnit'; export const TransferModal = ({ enrollment, @@ -31,6 +35,12 @@ export const TransferModal = ({ ownerOrgUnitId, }); + // The enrollment date must fall within the destination org unit's opening/closing range + const { orgUnit: destinationOrgUnit } = useCoreOrgUnit(selectedOrgUnit?.id ?? ''); + const enrollmentDateOutsideRange = !!selectedOrgUnit + && !isIsoDateWithinOrgUnitRange(enrollment.enrolledAt, destinationOrgUnit); + const orgUnitLabel = getOrgUnitLabel(enrollment.program) || i18n.t('organisation unit'); + const handleOnUpdateOwnership = async () => { if (!selectedOrgUnit) return; await onUpdateOwnership({ @@ -65,6 +75,22 @@ export const TransferModal = ({ programAccessLevel={programAccessLevel} orgUnitScopes={orgUnitScopes} /> + + {enrollmentDateOutsideRange && ( + + {i18n.t( + "The enrollment date is outside the selected {{orgUnitLabel}}'s opening and closing dates.", + { orgUnitLabel, interpolation: { escapeValue: false } }, + )} + + )} @@ -76,7 +102,7 @@ export const TransferModal = ({