From f3dc36f9cd2c9b92bbf6be9a791dac54130aac33 Mon Sep 17 00:00:00 2001 From: henrikmv Date: Thu, 21 May 2026 21:39:16 +0200 Subject: [PATCH 01/13] fix: add removeEnrollmentNote action and epic for handling note removal --- i18n/en.pot | 7 +++++-- .../WidgetEnrollmentNote.actions.ts | 4 ++++ .../WidgetEnrollmentNote.epics.ts | 13 +++++++++++-- .../components/WidgetEnrollmentNote/index.ts | 1 + .../enrollmentDomain.reducerDescription.ts | 8 ++++++++ .../feedback.reducerDescriptionGetter.ts | 3 +++ src/epics/trackerCapture.epics.ts | 6 +++++- 7 files changed, 37 insertions(+), 5 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index f2a0f92a71..8f9a698c0e 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-05-19T07:38:15.345Z\n" -"PO-Revision-Date: 2026-05-19T07:38:15.345Z\n" +"POT-Creation-Date: 2026-05-21T19:39:17.481Z\n" +"PO-Revision-Date: 2026-05-21T19:39:17.481Z\n" msgid "The application could not be loaded." msgstr "The application could not be loaded." @@ -2234,6 +2234,9 @@ msgstr "Error editing the event, the changes made were not saved" msgid "Error updating the Assignee" msgstr "Error updating the Assignee" +msgid "Could not save note" +msgstr "Could not save note" + msgid "There was an error fetching metadata" msgstr "There was an error fetching metadata" diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions.ts b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions.ts index 619f3bffc9..fe7fc851c4 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions.ts +++ b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions.ts @@ -7,6 +7,7 @@ export const actionTypes = { START_ADD_NOTE_FOR_ENROLLMENT: 'StartAddNoteForEnrollment', NOTE_ADDED_FOR_ENROLLMENT: 'NoteAddedForEnrollment', ADD_ENROLLMENT_NOTE: 'AddEnrollmentNote', + REMOVE_ENROLLMENT_NOTE: 'RemoveEnrollmentNote', ADD_NOTE_FAILED_FOR_ENROLLMENT: 'AddNoteFailedForEnrollment', }; @@ -40,3 +41,6 @@ export const startAddNoteForEnrollment = ( export const addEnrollmentNote = (enrollmentUid: string, note: Record) => actionCreator(actionTypes.ADD_ENROLLMENT_NOTE)({ enrollmentUid, note }); + +export const removeEnrollmentNote = (enrollmentUid: string, noteClientId: string) => + actionCreator(actionTypes.REMOVE_ENROLLMENT_NOTE)({ enrollmentUid, noteClientId }); diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics.ts b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics.ts index 99eaf0c22f..78459ac115 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics.ts +++ b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics.ts @@ -1,11 +1,11 @@ import { batchActions } from 'redux-batched-actions'; import { ofType } from 'redux-observable'; import { featureAvailable, FEATURES } from 'capture-core-utils'; -import { switchMap } from 'rxjs/operators'; +import { map, switchMap } from 'rxjs/operators'; import uuid from 'd2-utilizr/lib/uuid'; import moment from 'moment'; import type { ReduxStore, ApiUtils, EpicAction } from 'capture-core-utils/types/global'; -import { actionTypes, batchActionTypes, startAddNoteForEnrollment, addEnrollmentNote } +import { actionTypes, batchActionTypes, startAddNoteForEnrollment, addEnrollmentNote, removeEnrollmentNote } from './WidgetEnrollmentNote.actions'; import type { ClientNote, SaveContext } from './WidgetEnrollmentNote.types'; @@ -65,3 +65,12 @@ export const addNoteForEnrollmentEpic = ( ], batchActionTypes.ADD_NOTE_BATCH_FOR_ENROLLMENT); }); })); + +export const removeNoteForEnrollmentEpic = ( + action$: EpicAction, +) => + action$.pipe( + ofType(actionTypes.ADD_NOTE_FAILED_FOR_ENROLLMENT), + map((action: { meta: { context: SaveContext } }) => + removeEnrollmentNote(action.meta.context.enrollmentId, action.meta.context.noteClientId), + )); diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentNote/index.ts b/src/core_modules/capture-core/components/WidgetEnrollmentNote/index.ts index 2076d9af43..f06eb07149 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentNote/index.ts +++ b/src/core_modules/capture-core/components/WidgetEnrollmentNote/index.ts @@ -1 +1,2 @@ export { WidgetEnrollmentNote } from './WidgetEnrollmentNote.component'; +export { actionTypes as enrollmentNoteActionTypes } from './WidgetEnrollmentNote.actions'; diff --git a/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts b/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts index 42f057dbe8..9f51aa3f4d 100644 --- a/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts +++ b/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts @@ -260,6 +260,14 @@ export const enrollmentDomainDesc = createReducerDescription( notes: [...state.enrollment.notes, note], }, }), + [enrollmentNoteActionTypes.REMOVE_ENROLLMENT_NOTE]: + (state, { payload: { noteClientId } }) => ({ + ...state, + enrollment: { + ...state.enrollment, + notes: state.enrollment.notes.filter((n: any) => n?.createdBy?.uid !== noteClientId), + }, + }), [editEventActionTypes.REQUEST_DELETE_EVENT_DATA_ENTRY]: (state, { payload: { eventId } }) => { const events = state.enrollment.events?.map((event) => { if (event.event === eventId) { diff --git a/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts b/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts index db5e60028a..782ae3362e 100644 --- a/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts +++ b/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts @@ -27,6 +27,7 @@ import { registrationFormActionTypes } from '../../components/Pages/New/Registra import { enrollmentSiteActionTypes } from '../../components/Pages/common/EnrollmentOverviewDomain'; import { enrollmentEditEventActionTypes } from '../../components/Pages/EnrollmentEditEvent'; import { actionTypes as viewEventActionTypes } from '../../components/Pages/ViewEvent/ViewEventComponent/viewEvent.actions'; +import { enrollmentNoteActionTypes } from '../../components/WidgetEnrollmentNote'; const alertVariants = { info: 'info', @@ -150,4 +151,6 @@ export const getFeedbackDesc = (appUpdaters: Updaters) => createReducerDescripti addErrorFeedback(state, { message: i18n.t('Error updating the Assignee') }), [enrollmentEditEventActionTypes.ASSIGNEE_SAVE_FAILED]: state => addErrorFeedback(state, { message: i18n.t('Error updating the Assignee') }), + [enrollmentNoteActionTypes.ADD_NOTE_FAILED_FOR_ENROLLMENT]: state => + addErrorFeedback(state, { message: i18n.t('Could not save note') }), }, 'feedbacks', []); diff --git a/src/epics/trackerCapture.epics.ts b/src/epics/trackerCapture.epics.ts index 0b03a2f174..e3786155d4 100644 --- a/src/epics/trackerCapture.epics.ts +++ b/src/epics/trackerCapture.epics.ts @@ -128,7 +128,10 @@ import { saveNoteForViewEventFailedEpic, } from 'capture-core/components/Pages/ViewEvent/Notes/viewEventNotes.epics'; -import { addNoteForEnrollmentEpic } from 'capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics'; +import { + addNoteForEnrollmentEpic, + removeNoteForEnrollmentEpic, +} from 'capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics'; import { openNewRelationshipRegisterTeiEpic, loadSearchGroupDuplicatesForReviewEpic, @@ -373,6 +376,7 @@ export const epics = (combineEpics as any)( updateEventFailedEpic, addNoteForNewEnrollmentEventEpic, addNoteForEnrollmentEpic, + removeNoteForEnrollmentEpic, navigateToEnrollmentOverviewEpic, scheduleEnrollmentEventEpic, orgUnitFetcherEpic, From 257878062dfb5d3a56563dd7ed56e4e018001f0e Mon Sep 17 00:00:00 2001 From: henrikmv Date: Tue, 26 May 2026 13:27:13 +0200 Subject: [PATCH 02/13] fix: add similar error handling for all three note types --- .../components/FeedbackBar/FeedbackBar.component.tsx | 2 +- .../components/WidgetEventNote/WidgetEventNote.epics.ts | 1 + .../components/WidgetEventNote/WidgetEventNote.types.ts | 1 + .../capture-core/components/WidgetEventNote/index.ts | 1 + .../descriptions/feedback.reducerDescriptionGetter.ts | 6 ++++++ 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.tsx b/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.tsx index d478dccaa7..e4266241ff 100644 --- a/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.tsx +++ b/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.tsx @@ -33,7 +33,7 @@ const FeedbackBarComponentPlain = ({ feedback, onClose }: Props) => { <> {isAlertBarOpen && ( - + {message} )} diff --git a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts index e2c191e142..f8c815df8b 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts @@ -67,6 +67,7 @@ export const addNoteForEventEpic = ( }, storedBy: userName, storedAt: fromClientDate(moment().toISOString()).getServerZonedISOString(), + clientId, }; const formNote: FormNote = { ...clientNote, diff --git a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts index 87957e6627..0f64c2c579 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts @@ -12,6 +12,7 @@ export type ClientNote = { }; storedBy: string; storedAt: string; + clientId: string; }; export type FormNote = ClientNote & { diff --git a/src/core_modules/capture-core/components/WidgetEventNote/index.ts b/src/core_modules/capture-core/components/WidgetEventNote/index.ts index df498109aa..009fe50208 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/index.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/index.ts @@ -1,2 +1,3 @@ export { WidgetEventNote } from './WidgetEventNote.component'; export { addNoteForEventEpic, removeNoteForEventEpic } from './WidgetEventNote.epics'; +export { actionTypes as eventNoteActionTypes } from './WidgetEventNote.actions'; diff --git a/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts b/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts index 782ae3362e..ba786db52e 100644 --- a/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts +++ b/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts @@ -28,6 +28,8 @@ import { enrollmentSiteActionTypes } from '../../components/Pages/common/Enrollm import { enrollmentEditEventActionTypes } from '../../components/Pages/EnrollmentEditEvent'; import { actionTypes as viewEventActionTypes } from '../../components/Pages/ViewEvent/ViewEventComponent/viewEvent.actions'; import { enrollmentNoteActionTypes } from '../../components/WidgetEnrollmentNote'; +import { eventNoteActionTypes } from '../../components/WidgetEventNote'; +import { actionTypes as viewEventNotesActionTypes } from '../../components/Pages/ViewEvent/Notes/viewEventNotes.actions'; const alertVariants = { info: 'info', @@ -153,4 +155,8 @@ export const getFeedbackDesc = (appUpdaters: Updaters) => createReducerDescripti addErrorFeedback(state, { message: i18n.t('Error updating the Assignee') }), [enrollmentNoteActionTypes.ADD_NOTE_FAILED_FOR_ENROLLMENT]: state => addErrorFeedback(state, { message: i18n.t('Could not save note') }), + [eventNoteActionTypes.ADD_NOTE_FAILED_FOR_EVENT]: state => + addErrorFeedback(state, { message: i18n.t('Could not save note') }), + [viewEventNotesActionTypes.SAVE_EVENT_NOTE_FAILED]: state => + addErrorFeedback(state, { message: i18n.t('Could not save note') }), }, 'feedbacks', []); From 4a45e6689e7398f0736b1f2164fff47a39af3b41 Mon Sep 17 00:00:00 2001 From: henrikmv Date: Wed, 27 May 2026 12:48:42 +0200 Subject: [PATCH 03/13] fix: lint --- .../WidgetEventNote/WidgetEventNote.epics.ts | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts index 02b0318984..d2c59ed35b 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts @@ -53,32 +53,32 @@ export const addNoteForEventEpic = ( const serverData = createServerData(eventId, payload.note, useNewEndpoint); - const clientNote: ClientNote = { - value: payload.note, - lastUpdatedBy: { - firstName, - surname, - uid: clientId, - }, - storedBy: username, - storedAt: fromClientDate(moment().toISOString()).getServerZonedISOString(), - clientId, - }; - const formNote: FormNote = { - ...clientNote, - storedAt: clientNote.storedAt, - createdBy: { - firstName, - surname, - uid: clientId, - }, - }; - const saveContext: SaveContext = { - dataEntryId: payload.dataEntryId, - itemId: payload.itemId, - eventId, - noteClientId: clientId, - }; + const clientNote: ClientNote = { + value: payload.note, + lastUpdatedBy: { + firstName, + surname, + uid: clientId, + }, + storedBy: username, + storedAt: fromClientDate(moment().toISOString()).getServerZonedISOString(), + clientId, + }; + const formNote: FormNote = { + ...clientNote, + storedAt: clientNote.storedAt, + createdBy: { + firstName, + surname, + uid: clientId, + }, + }; + const saveContext: SaveContext = { + dataEntryId: payload.dataEntryId, + itemId: payload.itemId, + eventId, + noteClientId: clientId, + }; return batchActions([ startAddNoteForEvent(eventId, serverData, state.currentSelections, saveContext), From c1a8218debc18504c443ad1d76561969eaeb58d3 Mon Sep 17 00:00:00 2001 From: henrikmv Date: Thu, 28 May 2026 09:31:14 +0200 Subject: [PATCH 04/13] fix: include context in error messages for enrollment and event note failures --- i18n/en.pot | 11 +++++++---- .../descriptions/feedback.reducerDescriptionGetter.ts | 6 +++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index bd016c6d37..4b49716d22 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-05-26T07:35:44.230Z\n" -"PO-Revision-Date: 2026-05-26T07:35:44.230Z\n" +"POT-Creation-Date: 2026-05-28T07:31:16.181Z\n" +"PO-Revision-Date: 2026-05-28T07:31:16.181Z\n" msgid "The application could not be loaded." msgstr "The application could not be loaded." @@ -2234,8 +2234,11 @@ msgstr "Error editing the event, the changes made were not saved" msgid "Error updating the Assignee" msgstr "Error updating the Assignee" -msgid "Could not save note" -msgstr "Could not save note" +msgid "Could not save enrollment note" +msgstr "Could not save enrollment note" + +msgid "Could not save event note" +msgstr "Could not save event note" msgid "There was an error fetching metadata" msgstr "There was an error fetching metadata" diff --git a/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts b/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts index ba786db52e..05e1db06d8 100644 --- a/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts +++ b/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts @@ -154,9 +154,9 @@ export const getFeedbackDesc = (appUpdaters: Updaters) => createReducerDescripti [enrollmentEditEventActionTypes.ASSIGNEE_SAVE_FAILED]: state => addErrorFeedback(state, { message: i18n.t('Error updating the Assignee') }), [enrollmentNoteActionTypes.ADD_NOTE_FAILED_FOR_ENROLLMENT]: state => - addErrorFeedback(state, { message: i18n.t('Could not save note') }), + addErrorFeedback(state, { message: i18n.t('Could not save enrollment note') }), [eventNoteActionTypes.ADD_NOTE_FAILED_FOR_EVENT]: state => - addErrorFeedback(state, { message: i18n.t('Could not save note') }), + addErrorFeedback(state, { message: i18n.t('Could not save event note') }), [viewEventNotesActionTypes.SAVE_EVENT_NOTE_FAILED]: state => - addErrorFeedback(state, { message: i18n.t('Could not save note') }), + addErrorFeedback(state, { message: i18n.t('Could not save event note') }), }, 'feedbacks', []); From 789725c4a06a6952ba3f5e16a1317eac78142b8e Mon Sep 17 00:00:00 2001 From: henrikmv Date: Thu, 28 May 2026 10:43:28 +0200 Subject: [PATCH 05/13] fix: remove unused action types and improve note structure in WidgetEnrollmentNote and WidgetEventNote components --- .../WidgetEnrollmentNote.actions.ts | 1 - .../WidgetEnrollmentNote.epics.ts | 1 + .../WidgetEnrollmentNote.types.ts | 1 + .../WidgetEventNote.actions.ts | 1 - .../WidgetEventNote/WidgetEventNote.epics.ts | 25 +++++-------------- .../WidgetEventNote/WidgetEventNote.types.ts | 11 +++----- .../enrollmentDomain.reducerDescription.ts | 2 +- 7 files changed, 13 insertions(+), 29 deletions(-) diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions.ts b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions.ts index fe7fc851c4..7ade3abd34 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions.ts +++ b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions.ts @@ -13,7 +13,6 @@ export const actionTypes = { export const batchActionTypes = { ADD_NOTE_BATCH_FOR_ENROLLMENT: 'AddNoteBatchForEnrollment', - REMOVE_NOTE_BATCH_FOR_ENROLLMENT: 'RemoveNoteBatchForEnrollment', }; export const requestAddNoteForEnrollment = (enrollmentId: string, note: string) => diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics.ts b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics.ts index e267e4ddb3..9b4a5b0272 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics.ts +++ b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics.ts @@ -47,6 +47,7 @@ export const addNoteForEnrollmentEpic = ( }, storedBy: username, storedAt: fromClientDate(moment().toISOString()).getServerZonedISOString(), + clientId, }; const saveContext: SaveContext = { diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.types.ts b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.types.ts index 4f3470de6e..4cc1e94307 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.types.ts +++ b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.types.ts @@ -7,6 +7,7 @@ export type ClientNote = { }; storedBy: string; storedAt: string; + clientId: string; }; export type SaveContext = { diff --git a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.actions.ts b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.actions.ts index 3e91ecc142..7e62d9c502 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.actions.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.actions.ts @@ -11,7 +11,6 @@ export const actionTypes = { export const batchActionTypes = { ADD_NOTE_BATCH_FOR_EVENT: 'AddNoteBatchForEvent', - REMOVE_NOTE_BATCH_FOR_EVENT: 'RemoveNoteBatchForEvent', }; export const requestAddNoteForEvent = (itemId: string, dataEntryId: string, note: string) => diff --git a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts index d2c59ed35b..10270e551c 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts @@ -7,12 +7,7 @@ import moment from 'moment'; import type { ReduxStore, ApiUtils, EpicAction } from 'capture-core-utils/types'; import { CurrentUser } from '../../utils/userInfo/CurrentUser'; import { actionTypes, batchActionTypes, startAddNoteForEvent } from './WidgetEventNote.actions'; -import type { ClientNote, FormNote, SaveContext } from './WidgetEventNote.types'; - -import { - addEventNote, - removeEventNote, -} from '../Pages/ViewEvent/ViewEventComponent/editEvent.actions'; +import type { FormNote, SaveContext } from './WidgetEventNote.types'; import { addNote, @@ -53,25 +48,21 @@ export const addNoteForEventEpic = ( const serverData = createServerData(eventId, payload.note, useNewEndpoint); - const clientNote: ClientNote = { + const formNote: FormNote = { value: payload.note, lastUpdatedBy: { firstName, surname, uid: clientId, }, - storedBy: username, - storedAt: fromClientDate(moment().toISOString()).getServerZonedISOString(), - clientId, - }; - const formNote: FormNote = { - ...clientNote, - storedAt: clientNote.storedAt, createdBy: { firstName, surname, uid: clientId, }, + storedBy: username, + storedAt: fromClientDate(moment().toISOString()).getServerZonedISOString(), + clientId, }; const saveContext: SaveContext = { dataEntryId: payload.dataEntryId, @@ -83,7 +74,6 @@ export const addNoteForEventEpic = ( return batchActions([ startAddNoteForEvent(eventId, serverData, state.currentSelections, saveContext), addNote(payload.dataEntryId, payload.itemId, formNote), - addEventNote(eventId, clientNote), ], batchActionTypes.ADD_NOTE_BATCH_FOR_EVENT); })); @@ -92,8 +82,5 @@ export const removeNoteForEventEpic = (action$: EpicAction { const context = action.meta.context; - return batchActions([ - removeNote(context.dataEntryId, context.itemId, context.noteClientId), - removeEventNote(context.eventId, context.noteClientId), - ], batchActionTypes.REMOVE_NOTE_BATCH_FOR_EVENT); + return removeNote(context.dataEntryId, context.itemId, context.noteClientId); })); diff --git a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts index 0f64c2c579..38067097e2 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts @@ -3,24 +3,21 @@ export type Props = { dataEntryId: string; }; -export type ClientNote = { +export type FormNote = { value: string; lastUpdatedBy: { firstName: string; surname: string; uid: string; }; - storedBy: string; - storedAt: string; - clientId: string; -}; - -export type FormNote = ClientNote & { createdBy: { firstName: string; surname: string; uid: string; }; + storedBy: string; + storedAt: string; + clientId: string; }; export type SaveContext = { diff --git a/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts b/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts index 9f51aa3f4d..5dff8b459c 100644 --- a/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts +++ b/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts @@ -265,7 +265,7 @@ export const enrollmentDomainDesc = createReducerDescription( ...state, enrollment: { ...state.enrollment, - notes: state.enrollment.notes.filter((n: any) => n?.createdBy?.uid !== noteClientId), + notes: state.enrollment.notes.filter((n: any) => n?.clientId !== noteClientId), }, }), [editEventActionTypes.REQUEST_DELETE_EVENT_DATA_ENTRY]: (state, { payload: { eventId } }) => { From 2f819d0db6df37fd758fdfda24cd380b8e915da8 Mon Sep 17 00:00:00 2001 From: henrikmv Date: Thu, 28 May 2026 10:55:54 +0200 Subject: [PATCH 06/13] fix: update clientId assignment --- .../components/Pages/ViewEvent/Notes/viewEventNotes.epics.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core_modules/capture-core/components/Pages/ViewEvent/Notes/viewEventNotes.epics.ts b/src/core_modules/capture-core/components/Pages/ViewEvent/Notes/viewEventNotes.epics.ts index 2b0fc3a0e7..6d37b8299b 100644 --- a/src/core_modules/capture-core/components/Pages/ViewEvent/Notes/viewEventNotes.epics.ts +++ b/src/core_modules/capture-core/components/Pages/ViewEvent/Notes/viewEventNotes.epics.ts @@ -67,7 +67,7 @@ export const addNoteForViewEventEpic = (action$: any, store: any, { fromClientDa }, storedBy: username, storedAt: fromClientDate(moment().toISOString()).getServerZonedISOString(), - clientId: uuid(), + clientId, }; return batchActions([ startSaveEventNote(eventId, serverData, state.currentSelections, clientNote.clientId), From 96407cc28036d54b3dd21a06806999fde44ba138 Mon Sep 17 00:00:00 2001 From: henrikmv Date: Thu, 28 May 2026 11:22:31 +0200 Subject: [PATCH 07/13] fix: remove unused event note actions --- .../ViewEventComponent/editEvent.actions.ts | 8 -------- .../ViewEventComponent/viewEvent.actions.ts | 8 -------- .../descriptions/events.reducerDescription.ts | 16 ---------------- 3 files changed, 32 deletions(-) diff --git a/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/editEvent.actions.ts b/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/editEvent.actions.ts index 87177c8eaa..8e4ef15909 100644 --- a/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/editEvent.actions.ts +++ b/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/editEvent.actions.ts @@ -6,8 +6,6 @@ export const actionTypes = { EVENT_FROM_URL_RETRIEVED: 'EventFromUrlRetrievedForEditEvent', EVENT_FROM_URL_COULD_NOT_BE_RETRIEVED: 'EventFromUrlCouldNotBeRetrievedForEditEvent', ORG_UNIT_RETRIEVAL_FAILED_ON_URL_UPDATE: 'OrgUnitRetrievalFailedForEditEventOnUrlUpdate', - ADD_EVENT_NOTE: 'AddEventNote', - REMOVE_EVENT_NOTE: 'RemoveEventNote', }; export const eventFromUrlCouldNotBeRetrieved = (message: string) => @@ -18,9 +16,3 @@ export const eventFromUrlRetrieved = (eventContainer: any, orgUnit: OrgUnit, pre export const orgUnitCouldNotBeRetrievedOnUrlUpdate = (eventContainer: any) => actionCreator(actionTypes.ORG_UNIT_RETRIEVAL_FAILED_ON_URL_UPDATE)({ eventContainer }); - -export const addEventNote = (eventId: string, note: any) => - actionCreator(actionTypes.ADD_EVENT_NOTE)({ eventId, note }); - -export const removeEventNote = (eventId: string, noteClientId: string) => - actionCreator(actionTypes.REMOVE_EVENT_NOTE)({ eventId, noteClientId }); diff --git a/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/viewEvent.actions.ts b/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/viewEvent.actions.ts index a24712b319..88af3a7479 100644 --- a/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/viewEvent.actions.ts +++ b/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/viewEvent.actions.ts @@ -8,8 +8,6 @@ export const actionTypes = { ORG_UNIT_RETRIEVED_ON_URL_UPDATE: 'OrgUnitRetrievedForViewEventOnUrlUpdate', ORG_UNIT_RETRIEVAL_FAILED_ON_URL_UPDATE: 'OrgUnitRetrievalFailedForViewEventOnUrlUpdate', START_OPEN_EVENT_FOR_VIEW: 'StartOpenEventForView', - ADD_EVENT_NOTE: 'AddEventNoteForViewEvent', - REMOVE_EVENT_NOTE: 'RemoveEventNoteForViewEvent', UPDATE_WORKING_LIST_ON_BACK_TO_MAIN_PAGE: 'UpdateWorkingListOnBackToMainPageForViewEvent', NO_WORKING_LIST_UPDATE_NEEDED_ON_BACK_TO_MAIN_PAGE: 'NoWorkingListUpdateNeededOnBackToMainPageForViewEvent', START_GO_BACK_TO_MAIN_PAGE: 'StartGoBackToMainPageForViewEvent', @@ -49,12 +47,6 @@ export const orgUnitCouldNotBeRetrievedOnUrlUpdate = (eventContainer: any) => export const startOpenEventForView = (eventContainer: any, orgUnit: any) => actionCreator(actionTypes.START_OPEN_EVENT_FOR_VIEW)({ eventContainer, orgUnit }); -export const addEventNote = (eventId: string, note: any) => - actionCreator(actionTypes.ADD_EVENT_NOTE)({ eventId, note }); - -export const removeEventNote = (eventId: string, noteClientId: string) => - actionCreator(actionTypes.REMOVE_EVENT_NOTE)({ eventId, noteClientId }); - export const startGoBackToMainPage = (orgUnitId: string | null) => actionCreator(actionTypes.START_GO_BACK_TO_MAIN_PAGE)({ orgUnitId }); diff --git a/src/core_modules/capture-core/reducers/descriptions/events.reducerDescription.ts b/src/core_modules/capture-core/reducers/descriptions/events.reducerDescription.ts index 24cc4d1cdb..88cf5bea3f 100644 --- a/src/core_modules/capture-core/reducers/descriptions/events.reducerDescription.ts +++ b/src/core_modules/capture-core/reducers/descriptions/events.reducerDescription.ts @@ -48,22 +48,6 @@ export const eventsDesc = createReducerDescription({ }; return newState; }, - [viewEventActionTypes.ADD_EVENT_NOTE]: (state, action) => { - const newState = { ...state }; - const payload = action.payload; - if (newState[payload.eventId]) { - newState[payload.eventId].notes = [...state[payload.eventId].notes, payload.note]; - } - return newState; - }, - [viewEventActionTypes.REMOVE_EVENT_NOTE]: (state, action) => { - const newState = { ...state }; - const payload = action.payload; - if (newState[payload.eventId]) { - newState[payload.eventId].notes = state[payload.eventId].notes.filter(n => n.clientId !== payload.noteClientId); - } - return newState; - }, }, 'events', {}); export const eventsValuesDesc = createReducerDescription({ From 5c0722ab393cc69389158e216da416ebb3a1ed00 Mon Sep 17 00:00:00 2001 From: henrikmv Date: Thu, 28 May 2026 11:36:19 +0200 Subject: [PATCH 08/13] fix: remove lastUpdatedBy field --- .../components/WidgetEventNote/WidgetEventNote.epics.ts | 5 ----- .../components/WidgetEventNote/WidgetEventNote.types.ts | 5 ----- .../descriptions/enrollmentDomain.reducerDescription.ts | 3 +-- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts index 10270e551c..e37d3a81ae 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts @@ -50,11 +50,6 @@ export const addNoteForEventEpic = ( const formNote: FormNote = { value: payload.note, - lastUpdatedBy: { - firstName, - surname, - uid: clientId, - }, createdBy: { firstName, surname, diff --git a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts index 38067097e2..9331e9347e 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts @@ -5,11 +5,6 @@ export type Props = { export type FormNote = { value: string; - lastUpdatedBy: { - firstName: string; - surname: string; - uid: string; - }; createdBy: { firstName: string; surname: string; diff --git a/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts b/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts index 5dff8b459c..ea63dd09ef 100644 --- a/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts +++ b/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts @@ -1,7 +1,6 @@ import { createReducerDescription } from '../../trackerRedux'; import { enrollmentSiteActionTypes } from '../../components/Pages/common/EnrollmentOverviewDomain'; -import { actionTypes as enrollmentNoteActionTypes } - from '../../components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions'; +import { enrollmentNoteActionTypes } from '../../components/WidgetEnrollmentNote'; import { actionTypes as editEventActionTypes } from '../../components/WidgetEventEdit/EditEventDataEntry/editEventDataEntry.actions'; import { newEventWidgetActionTypes } from '../../components/WidgetEnrollmentEventNew/Validated/validated.actions'; From 27913f7707cc9197e11367c5896da9e9975c5384 Mon Sep 17 00:00:00 2001 From: henrikmv Date: Thu, 28 May 2026 14:35:12 +0200 Subject: [PATCH 09/13] fix: add unique id to feedback messages and refactor error feedback handling --- .../FeedbackBar/FeedbackBar.component.tsx | 4 +- .../FeedbackBar/FeedbackBar.types.ts | 1 + .../feedback.reducerDescriptionGetter.ts | 156 +++++++----------- 3 files changed, 66 insertions(+), 95 deletions(-) diff --git a/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.tsx b/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.tsx index e4266241ff..bbf92a312c 100644 --- a/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.tsx +++ b/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.tsx @@ -24,7 +24,7 @@ const FeedbackBarComponentPlain = ({ feedback, onClose }: Props) => { return null; } - const { message, displayType, variant } = feedback; + const { id, message, displayType, variant } = feedback; const isAlertBarOpen = typeof message === 'string' && !displayType; const isDialogOpen = typeof message === 'object' && displayType === 'dialog'; const alertVariant = getAlertVariant(variant); @@ -33,7 +33,7 @@ const FeedbackBarComponentPlain = ({ feedback, onClose }: Props) => { <> {isAlertBarOpen && ( - + {message} )} diff --git a/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.types.ts b/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.types.ts index f7acaada51..55a54cb07d 100644 --- a/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.types.ts +++ b/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.types.ts @@ -1,6 +1,7 @@ import { ReactNode } from 'react'; export type Feedback = { + id: string; message: string | { title: string; content: string }; action?: ReactNode; displayType?: 'alert' | 'dialog'; diff --git a/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts b/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts index 05e1db06d8..e5e4cd7d09 100644 --- a/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts +++ b/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts @@ -3,6 +3,7 @@ import log from 'loglevel'; import i18n from '@dhis2/d2-i18n'; import isString from 'd2-utilizr/lib/isString'; import isObject from 'd2-utilizr/lib/isObject'; +import uuid from 'd2-utilizr/lib/uuid'; import { errorCreator } from 'capture-core-utils'; import { createReducerDescription } from '../../trackerRedux/trackerReducer'; import { actionTypes as feedbackActionTypes } from '../../components/FeedbackBar/actions/feedback.actions'; @@ -44,31 +45,19 @@ type ErrorFeedbackInput = { action?: ReactNode, }; -function addErrorFeedback( - state: any, - { message, variant = alertVariants.critical as keyof typeof alertVariants, action }: ErrorFeedbackInput, -) { - return [ - ...state, - { - message, - action, - feedbackType: 'ERROR', - variant, - }, - ]; -} +const getErrorFeedback = ({ + message, + variant = 'critical', + action, +}: ErrorFeedbackInput) => ({ + id: uuid(), + message, + action, + feedbackType: 'ERROR' as const, + variant, +}); -function getErrorFeedback( - { message, variant = alertVariants.critical as keyof typeof alertVariants, action }: ErrorFeedbackInput, -) { - return { - message, - action, - feedbackType: 'ERROR', - variant, - }; -} +const addErrorFeedback = (input: ErrorFeedbackInput) => [getErrorFeedback(input)]; export const getFeedbackDesc = (appUpdaters: Updaters) => createReducerDescription({ ...appUpdaters, @@ -77,86 +66,67 @@ export const getFeedbackDesc = (appUpdaters: Updaters) => createReducerDescripti newState.shift(); return newState; }, - [dataEntryActionTypes.COMPLETE_EVENT_ERROR]: (state, action) => - addErrorFeedback(state, { + [dataEntryActionTypes.COMPLETE_EVENT_ERROR]: (_state, action) => + addErrorFeedback({ message: action.payload.error, action: action.payload.action, }), - [enrollmentActionTypes.ENROLLMENT_LOAD_FAILED]: (state, action) => - addErrorFeedback(state, action.payload), - [workingListsCommonActionTypes.LIST_VIEW_INIT_ERROR]: (state, action) => - addErrorFeedback(state, action.payload.errorMessage), - [newEventDataEntryActionTypes.SAVE_FAILED_FOR_NEW_EVENT_AFTER_RETURNED_TO_MAIN_PAGE]: (state, action) => { + [enrollmentActionTypes.ENROLLMENT_LOAD_FAILED]: (_state, action) => + addErrorFeedback(action.payload), + [workingListsCommonActionTypes.LIST_VIEW_INIT_ERROR]: (_state, action) => + addErrorFeedback(action.payload.errorMessage), + [newEventDataEntryActionTypes.SAVE_FAILED_FOR_NEW_EVENT_AFTER_RETURNED_TO_MAIN_PAGE]: (_state, action) => { const error = action.payload; const errorMessage = isString(error) ? error : error.message; const errorObject = isObject(error) ? error : null; log.error(errorCreator(errorMessage || 'Error saving event')(errorObject)); - const newState = [ - ...state, - getErrorFeedback({ message: i18n.t('Could not save event') }), - ]; - return newState; + return addErrorFeedback({ message: i18n.t('Could not save event') }); }, - [workingListsCommonActionTypes.LIST_UPDATE_ERROR]: (state, action) => [ - ...state, - getErrorFeedback({ message: action.payload.errorMessage }), - ], - [eventWorkingListsActionTypes.EVENT_DELETE_ERROR]: state => [ - ...state, - getErrorFeedback({ message: i18n.t('Could not delete event') }), - ], - - [workingListsCommonActionTypes.TEMPLATE_UPDATE_ERROR]: state => [ - ...state, - getErrorFeedback({ message: i18n.t('Could not save working list') }), - ], - [workingListsCommonActionTypes.TEMPLATE_ADD_ERROR]: state => [ - ...state, - getErrorFeedback({ message: i18n.t('Could not add working list') }), - ], - [workingListsCommonActionTypes.TEMPLATE_DELETE_ERROR]: state => [ - ...state, - getErrorFeedback({ message: i18n.t('Could not delete working list') }), - ], - [asyncHandlerActionTypes.ASYNC_UPDATE_FIELD_FAILED]: (state, { payload }) => - addErrorFeedback(state, { message: payload.message }), - [newEventDataEntryActionTypes.SAVE_FAILED_FOR_NEW_EVENT_ADD_ANOTHER]: (state, action) => { + [workingListsCommonActionTypes.LIST_UPDATE_ERROR]: (_state, action) => + addErrorFeedback({ message: action.payload.errorMessage }), + [eventWorkingListsActionTypes.EVENT_DELETE_ERROR]: () => + addErrorFeedback({ message: i18n.t('Could not delete event') }), + [workingListsCommonActionTypes.TEMPLATE_UPDATE_ERROR]: () => + addErrorFeedback({ message: i18n.t('Could not save working list') }), + [workingListsCommonActionTypes.TEMPLATE_ADD_ERROR]: () => + addErrorFeedback({ message: i18n.t('Could not add working list') }), + [workingListsCommonActionTypes.TEMPLATE_DELETE_ERROR]: () => + addErrorFeedback({ message: i18n.t('Could not delete working list') }), + [asyncHandlerActionTypes.ASYNC_UPDATE_FIELD_FAILED]: (_state, { payload }) => + addErrorFeedback({ message: payload.message }), + [newEventDataEntryActionTypes.SAVE_FAILED_FOR_NEW_EVENT_ADD_ANOTHER]: (_state, action) => { const error = action.payload; const errorMessage = isString(error) ? error : error.message; const errorObject = isObject(error) ? error : null; log.error(errorCreator(errorMessage || 'Error saving event')(errorObject)); - const newState = [ - ...state, - getErrorFeedback({ message: i18n.t('Could not save event') }), - ]; - return newState; + return addErrorFeedback({ message: i18n.t('Could not save event') }); }, - [dataEntryActionTypes.DATA_ENTRY_RELATIONSHIP_ALREADY_EXISTS]: (state, action) => - addErrorFeedback(state, { message: action.payload.message }), - [viewEventNewRelationshipActionTypes.EVENT_RELATIONSHIP_ALREADY_EXISTS]: (state, action) => - addErrorFeedback(state, { message: action.payload.message }), - [registrationSectionActionTypes.ORG_UNIT_SEARCH_FAILED]: state => - addErrorFeedback(state, { message: i18n.t('Organisation unit search failed.') }), - [registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_SAVE_FAILED]: state => - addErrorFeedback(state, { message: i18n.t('Error saving tracked entity instance') }), - [registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_FAILED]: state => - addErrorFeedback(state, { message: i18n.t('Error saving enrollment') }), - [enrollmentSiteActionTypes.SAVE_FAILED]: state => - addErrorFeedback(state, { message: i18n.t('Error saving the enrollment event') }), - [editEventActionTypes.DELETE_EVENT_DATA_ENTRY_FAILED]: state => - addErrorFeedback(state, { message: i18n.t('Error deleting the enrollment event') }), - [editEventDataEntryAction.SAVE_EDIT_EVENT_DATA_ENTRY_FAILED]: state => - addErrorFeedback(state, { message: i18n.t('Error editing the event, the changes made were not saved') }), - [enrollmentSiteActionTypes.ERROR_ENROLLMENT]: (state, action) => - addErrorFeedback(state, { message: i18n.t(action.payload.message) }), - [viewEventActionTypes.ASSIGNEE_SAVE_FAILED]: state => - addErrorFeedback(state, { message: i18n.t('Error updating the Assignee') }), - [enrollmentEditEventActionTypes.ASSIGNEE_SAVE_FAILED]: state => - addErrorFeedback(state, { message: i18n.t('Error updating the Assignee') }), - [enrollmentNoteActionTypes.ADD_NOTE_FAILED_FOR_ENROLLMENT]: state => - addErrorFeedback(state, { message: i18n.t('Could not save enrollment note') }), - [eventNoteActionTypes.ADD_NOTE_FAILED_FOR_EVENT]: state => - addErrorFeedback(state, { message: i18n.t('Could not save event note') }), - [viewEventNotesActionTypes.SAVE_EVENT_NOTE_FAILED]: state => - addErrorFeedback(state, { message: i18n.t('Could not save event note') }), + [dataEntryActionTypes.DATA_ENTRY_RELATIONSHIP_ALREADY_EXISTS]: (_state, action) => + addErrorFeedback({ message: action.payload.message }), + [viewEventNewRelationshipActionTypes.EVENT_RELATIONSHIP_ALREADY_EXISTS]: (_state, action) => + addErrorFeedback({ message: action.payload.message }), + [registrationSectionActionTypes.ORG_UNIT_SEARCH_FAILED]: () => + addErrorFeedback({ message: i18n.t('Organisation unit search failed.') }), + [registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_SAVE_FAILED]: () => + addErrorFeedback({ message: i18n.t('Error saving tracked entity instance') }), + [registrationFormActionTypes.NEW_TRACKED_ENTITY_INSTANCE_WITH_ENROLLMENT_SAVE_FAILED]: () => + addErrorFeedback({ message: i18n.t('Error saving enrollment') }), + [enrollmentSiteActionTypes.SAVE_FAILED]: () => + addErrorFeedback({ message: i18n.t('Error saving the enrollment event') }), + [editEventActionTypes.DELETE_EVENT_DATA_ENTRY_FAILED]: () => + addErrorFeedback({ message: i18n.t('Error deleting the enrollment event') }), + [editEventDataEntryAction.SAVE_EDIT_EVENT_DATA_ENTRY_FAILED]: () => + addErrorFeedback({ message: i18n.t('Error editing the event, the changes made were not saved') }), + [enrollmentSiteActionTypes.ERROR_ENROLLMENT]: (_state, action) => + addErrorFeedback({ message: i18n.t(action.payload.message) }), + [viewEventActionTypes.ASSIGNEE_SAVE_FAILED]: () => + addErrorFeedback({ message: i18n.t('Error updating the Assignee') }), + [enrollmentEditEventActionTypes.ASSIGNEE_SAVE_FAILED]: () => + addErrorFeedback({ message: i18n.t('Error updating the Assignee') }), + [enrollmentNoteActionTypes.ADD_NOTE_FAILED_FOR_ENROLLMENT]: () => + addErrorFeedback({ message: i18n.t('Could not save enrollment note') }), + [eventNoteActionTypes.ADD_NOTE_FAILED_FOR_EVENT]: () => + addErrorFeedback({ message: i18n.t('Could not save event note') }), + [viewEventNotesActionTypes.SAVE_EVENT_NOTE_FAILED]: () => + addErrorFeedback({ message: i18n.t('Could not save event note') }), }, 'feedbacks', []); From 73f842cbe1619172f2f9b610c9c69bfd29b35433 Mon Sep 17 00:00:00 2001 From: henrikmv Date: Thu, 28 May 2026 15:23:59 +0200 Subject: [PATCH 10/13] fix: revert changes not for this pr --- i18n/en.pot | 10 ++----- .../ViewEvent/Notes/viewEventNotes.epics.ts | 2 +- .../ViewEventComponent/editEvent.actions.ts | 8 ++++++ .../ViewEventComponent/viewEvent.actions.ts | 8 ++++++ .../WidgetEnrollmentNote.actions.ts | 5 +--- .../WidgetEnrollmentNote.epics.ts | 12 +-------- .../WidgetEnrollmentNote.types.ts | 1 - .../components/WidgetEnrollmentNote/index.ts | 1 - .../WidgetEventNote.actions.ts | 1 + .../WidgetEventNote/WidgetEventNote.epics.ts | 27 +++++++++++++++---- .../WidgetEventNote/WidgetEventNote.types.ts | 13 ++++++--- .../components/WidgetEventNote/index.ts | 1 - .../enrollmentDomain.reducerDescription.ts | 11 ++------ .../descriptions/events.reducerDescription.ts | 16 +++++++++++ .../feedback.reducerDescriptionGetter.ts | 9 ------- src/epics/trackerCapture.epics.ts | 6 +---- 16 files changed, 73 insertions(+), 58 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index 4b49716d22..7984e77390 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-05-28T07:31:16.181Z\n" -"PO-Revision-Date: 2026-05-28T07:31:16.181Z\n" +"POT-Creation-Date: 2026-05-28T13:24:01.386Z\n" +"PO-Revision-Date: 2026-05-28T13:24:01.386Z\n" msgid "The application could not be loaded." msgstr "The application could not be loaded." @@ -2234,12 +2234,6 @@ msgstr "Error editing the event, the changes made were not saved" msgid "Error updating the Assignee" msgstr "Error updating the Assignee" -msgid "Could not save enrollment note" -msgstr "Could not save enrollment note" - -msgid "Could not save event note" -msgstr "Could not save event note" - msgid "There was an error fetching metadata" msgstr "There was an error fetching metadata" diff --git a/src/core_modules/capture-core/components/Pages/ViewEvent/Notes/viewEventNotes.epics.ts b/src/core_modules/capture-core/components/Pages/ViewEvent/Notes/viewEventNotes.epics.ts index 6d37b8299b..2b0fc3a0e7 100644 --- a/src/core_modules/capture-core/components/Pages/ViewEvent/Notes/viewEventNotes.epics.ts +++ b/src/core_modules/capture-core/components/Pages/ViewEvent/Notes/viewEventNotes.epics.ts @@ -67,7 +67,7 @@ export const addNoteForViewEventEpic = (action$: any, store: any, { fromClientDa }, storedBy: username, storedAt: fromClientDate(moment().toISOString()).getServerZonedISOString(), - clientId, + clientId: uuid(), }; return batchActions([ startSaveEventNote(eventId, serverData, state.currentSelections, clientNote.clientId), diff --git a/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/editEvent.actions.ts b/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/editEvent.actions.ts index 8e4ef15909..87177c8eaa 100644 --- a/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/editEvent.actions.ts +++ b/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/editEvent.actions.ts @@ -6,6 +6,8 @@ export const actionTypes = { EVENT_FROM_URL_RETRIEVED: 'EventFromUrlRetrievedForEditEvent', EVENT_FROM_URL_COULD_NOT_BE_RETRIEVED: 'EventFromUrlCouldNotBeRetrievedForEditEvent', ORG_UNIT_RETRIEVAL_FAILED_ON_URL_UPDATE: 'OrgUnitRetrievalFailedForEditEventOnUrlUpdate', + ADD_EVENT_NOTE: 'AddEventNote', + REMOVE_EVENT_NOTE: 'RemoveEventNote', }; export const eventFromUrlCouldNotBeRetrieved = (message: string) => @@ -16,3 +18,9 @@ export const eventFromUrlRetrieved = (eventContainer: any, orgUnit: OrgUnit, pre export const orgUnitCouldNotBeRetrievedOnUrlUpdate = (eventContainer: any) => actionCreator(actionTypes.ORG_UNIT_RETRIEVAL_FAILED_ON_URL_UPDATE)({ eventContainer }); + +export const addEventNote = (eventId: string, note: any) => + actionCreator(actionTypes.ADD_EVENT_NOTE)({ eventId, note }); + +export const removeEventNote = (eventId: string, noteClientId: string) => + actionCreator(actionTypes.REMOVE_EVENT_NOTE)({ eventId, noteClientId }); diff --git a/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/viewEvent.actions.ts b/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/viewEvent.actions.ts index 88af3a7479..a24712b319 100644 --- a/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/viewEvent.actions.ts +++ b/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/viewEvent.actions.ts @@ -8,6 +8,8 @@ export const actionTypes = { ORG_UNIT_RETRIEVED_ON_URL_UPDATE: 'OrgUnitRetrievedForViewEventOnUrlUpdate', ORG_UNIT_RETRIEVAL_FAILED_ON_URL_UPDATE: 'OrgUnitRetrievalFailedForViewEventOnUrlUpdate', START_OPEN_EVENT_FOR_VIEW: 'StartOpenEventForView', + ADD_EVENT_NOTE: 'AddEventNoteForViewEvent', + REMOVE_EVENT_NOTE: 'RemoveEventNoteForViewEvent', UPDATE_WORKING_LIST_ON_BACK_TO_MAIN_PAGE: 'UpdateWorkingListOnBackToMainPageForViewEvent', NO_WORKING_LIST_UPDATE_NEEDED_ON_BACK_TO_MAIN_PAGE: 'NoWorkingListUpdateNeededOnBackToMainPageForViewEvent', START_GO_BACK_TO_MAIN_PAGE: 'StartGoBackToMainPageForViewEvent', @@ -47,6 +49,12 @@ export const orgUnitCouldNotBeRetrievedOnUrlUpdate = (eventContainer: any) => export const startOpenEventForView = (eventContainer: any, orgUnit: any) => actionCreator(actionTypes.START_OPEN_EVENT_FOR_VIEW)({ eventContainer, orgUnit }); +export const addEventNote = (eventId: string, note: any) => + actionCreator(actionTypes.ADD_EVENT_NOTE)({ eventId, note }); + +export const removeEventNote = (eventId: string, noteClientId: string) => + actionCreator(actionTypes.REMOVE_EVENT_NOTE)({ eventId, noteClientId }); + export const startGoBackToMainPage = (orgUnitId: string | null) => actionCreator(actionTypes.START_GO_BACK_TO_MAIN_PAGE)({ orgUnitId }); diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions.ts b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions.ts index 7ade3abd34..619f3bffc9 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions.ts +++ b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions.ts @@ -7,12 +7,12 @@ export const actionTypes = { START_ADD_NOTE_FOR_ENROLLMENT: 'StartAddNoteForEnrollment', NOTE_ADDED_FOR_ENROLLMENT: 'NoteAddedForEnrollment', ADD_ENROLLMENT_NOTE: 'AddEnrollmentNote', - REMOVE_ENROLLMENT_NOTE: 'RemoveEnrollmentNote', ADD_NOTE_FAILED_FOR_ENROLLMENT: 'AddNoteFailedForEnrollment', }; export const batchActionTypes = { ADD_NOTE_BATCH_FOR_ENROLLMENT: 'AddNoteBatchForEnrollment', + REMOVE_NOTE_BATCH_FOR_ENROLLMENT: 'RemoveNoteBatchForEnrollment', }; export const requestAddNoteForEnrollment = (enrollmentId: string, note: string) => @@ -40,6 +40,3 @@ export const startAddNoteForEnrollment = ( export const addEnrollmentNote = (enrollmentUid: string, note: Record) => actionCreator(actionTypes.ADD_ENROLLMENT_NOTE)({ enrollmentUid, note }); - -export const removeEnrollmentNote = (enrollmentUid: string, noteClientId: string) => - actionCreator(actionTypes.REMOVE_ENROLLMENT_NOTE)({ enrollmentUid, noteClientId }); diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics.ts b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics.ts index 9b4a5b0272..609f3a200e 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics.ts +++ b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics.ts @@ -6,7 +6,7 @@ import uuid from 'd2-utilizr/lib/uuid'; import moment from 'moment'; import type { ReduxStore, ApiUtils, EpicAction } from 'capture-core-utils/types/global'; import { CurrentUser } from '../../utils/userInfo/CurrentUser'; -import { actionTypes, batchActionTypes, startAddNoteForEnrollment, addEnrollmentNote, removeEnrollmentNote } +import { actionTypes, batchActionTypes, startAddNoteForEnrollment, addEnrollmentNote } from './WidgetEnrollmentNote.actions'; import type { ClientNote, SaveContext } from './WidgetEnrollmentNote.types'; @@ -47,7 +47,6 @@ export const addNoteForEnrollmentEpic = ( }, storedBy: username, storedAt: fromClientDate(moment().toISOString()).getServerZonedISOString(), - clientId, }; const saveContext: SaveContext = { @@ -60,12 +59,3 @@ export const addNoteForEnrollmentEpic = ( addEnrollmentNote(enrollmentId, clientNote), ], batchActionTypes.ADD_NOTE_BATCH_FOR_ENROLLMENT); })); - -export const removeNoteForEnrollmentEpic = ( - action$: EpicAction, -) => - action$.pipe( - ofType(actionTypes.ADD_NOTE_FAILED_FOR_ENROLLMENT), - map((action: { meta: { context: SaveContext } }) => - removeEnrollmentNote(action.meta.context.enrollmentId, action.meta.context.noteClientId), - )); diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.types.ts b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.types.ts index 4cc1e94307..4f3470de6e 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.types.ts +++ b/src/core_modules/capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.types.ts @@ -7,7 +7,6 @@ export type ClientNote = { }; storedBy: string; storedAt: string; - clientId: string; }; export type SaveContext = { diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentNote/index.ts b/src/core_modules/capture-core/components/WidgetEnrollmentNote/index.ts index f06eb07149..2076d9af43 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentNote/index.ts +++ b/src/core_modules/capture-core/components/WidgetEnrollmentNote/index.ts @@ -1,2 +1 @@ export { WidgetEnrollmentNote } from './WidgetEnrollmentNote.component'; -export { actionTypes as enrollmentNoteActionTypes } from './WidgetEnrollmentNote.actions'; diff --git a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.actions.ts b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.actions.ts index 7e62d9c502..3e91ecc142 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.actions.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.actions.ts @@ -11,6 +11,7 @@ export const actionTypes = { export const batchActionTypes = { ADD_NOTE_BATCH_FOR_EVENT: 'AddNoteBatchForEvent', + REMOVE_NOTE_BATCH_FOR_EVENT: 'RemoveNoteBatchForEvent', }; export const requestAddNoteForEvent = (itemId: string, dataEntryId: string, note: string) => diff --git a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts index e37d3a81ae..9fca9c4e59 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.epics.ts @@ -7,7 +7,12 @@ import moment from 'moment'; import type { ReduxStore, ApiUtils, EpicAction } from 'capture-core-utils/types'; import { CurrentUser } from '../../utils/userInfo/CurrentUser'; import { actionTypes, batchActionTypes, startAddNoteForEvent } from './WidgetEventNote.actions'; -import type { FormNote, SaveContext } from './WidgetEventNote.types'; +import type { ClientNote, FormNote, SaveContext } from './WidgetEventNote.types'; + +import { + addEventNote, + removeEventNote, +} from '../Pages/ViewEvent/ViewEventComponent/editEvent.actions'; import { addNote, @@ -48,16 +53,24 @@ export const addNoteForEventEpic = ( const serverData = createServerData(eventId, payload.note, useNewEndpoint); - const formNote: FormNote = { + const clientNote: ClientNote = { value: payload.note, - createdBy: { + lastUpdatedBy: { firstName, surname, uid: clientId, }, storedBy: username, storedAt: fromClientDate(moment().toISOString()).getServerZonedISOString(), - clientId, + }; + const formNote: FormNote = { + ...clientNote, + storedAt: clientNote.storedAt, + createdBy: { + firstName, + surname, + uid: clientId, + }, }; const saveContext: SaveContext = { dataEntryId: payload.dataEntryId, @@ -69,6 +82,7 @@ export const addNoteForEventEpic = ( return batchActions([ startAddNoteForEvent(eventId, serverData, state.currentSelections, saveContext), addNote(payload.dataEntryId, payload.itemId, formNote), + addEventNote(eventId, clientNote), ], batchActionTypes.ADD_NOTE_BATCH_FOR_EVENT); })); @@ -77,5 +91,8 @@ export const removeNoteForEventEpic = (action$: EpicAction { const context = action.meta.context; - return removeNote(context.dataEntryId, context.itemId, context.noteClientId); + return batchActions([ + removeNote(context.dataEntryId, context.itemId, context.noteClientId), + removeEventNote(context.eventId, context.noteClientId), + ], batchActionTypes.REMOVE_NOTE_BATCH_FOR_EVENT); })); diff --git a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts index 9331e9347e..87957e6627 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/WidgetEventNote.types.ts @@ -3,16 +3,23 @@ export type Props = { dataEntryId: string; }; -export type FormNote = { +export type ClientNote = { value: string; - createdBy: { + lastUpdatedBy: { firstName: string; surname: string; uid: string; }; storedBy: string; storedAt: string; - clientId: string; +}; + +export type FormNote = ClientNote & { + createdBy: { + firstName: string; + surname: string; + uid: string; + }; }; export type SaveContext = { diff --git a/src/core_modules/capture-core/components/WidgetEventNote/index.ts b/src/core_modules/capture-core/components/WidgetEventNote/index.ts index 009fe50208..df498109aa 100644 --- a/src/core_modules/capture-core/components/WidgetEventNote/index.ts +++ b/src/core_modules/capture-core/components/WidgetEventNote/index.ts @@ -1,3 +1,2 @@ export { WidgetEventNote } from './WidgetEventNote.component'; export { addNoteForEventEpic, removeNoteForEventEpic } from './WidgetEventNote.epics'; -export { actionTypes as eventNoteActionTypes } from './WidgetEventNote.actions'; diff --git a/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts b/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts index ea63dd09ef..42f057dbe8 100644 --- a/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts +++ b/src/core_modules/capture-core/reducers/descriptions/enrollmentDomain.reducerDescription.ts @@ -1,6 +1,7 @@ import { createReducerDescription } from '../../trackerRedux'; import { enrollmentSiteActionTypes } from '../../components/Pages/common/EnrollmentOverviewDomain'; -import { enrollmentNoteActionTypes } from '../../components/WidgetEnrollmentNote'; +import { actionTypes as enrollmentNoteActionTypes } + from '../../components/WidgetEnrollmentNote/WidgetEnrollmentNote.actions'; import { actionTypes as editEventActionTypes } from '../../components/WidgetEventEdit/EditEventDataEntry/editEventDataEntry.actions'; import { newEventWidgetActionTypes } from '../../components/WidgetEnrollmentEventNew/Validated/validated.actions'; @@ -259,14 +260,6 @@ export const enrollmentDomainDesc = createReducerDescription( notes: [...state.enrollment.notes, note], }, }), - [enrollmentNoteActionTypes.REMOVE_ENROLLMENT_NOTE]: - (state, { payload: { noteClientId } }) => ({ - ...state, - enrollment: { - ...state.enrollment, - notes: state.enrollment.notes.filter((n: any) => n?.clientId !== noteClientId), - }, - }), [editEventActionTypes.REQUEST_DELETE_EVENT_DATA_ENTRY]: (state, { payload: { eventId } }) => { const events = state.enrollment.events?.map((event) => { if (event.event === eventId) { diff --git a/src/core_modules/capture-core/reducers/descriptions/events.reducerDescription.ts b/src/core_modules/capture-core/reducers/descriptions/events.reducerDescription.ts index 88cf5bea3f..24cc4d1cdb 100644 --- a/src/core_modules/capture-core/reducers/descriptions/events.reducerDescription.ts +++ b/src/core_modules/capture-core/reducers/descriptions/events.reducerDescription.ts @@ -48,6 +48,22 @@ export const eventsDesc = createReducerDescription({ }; return newState; }, + [viewEventActionTypes.ADD_EVENT_NOTE]: (state, action) => { + const newState = { ...state }; + const payload = action.payload; + if (newState[payload.eventId]) { + newState[payload.eventId].notes = [...state[payload.eventId].notes, payload.note]; + } + return newState; + }, + [viewEventActionTypes.REMOVE_EVENT_NOTE]: (state, action) => { + const newState = { ...state }; + const payload = action.payload; + if (newState[payload.eventId]) { + newState[payload.eventId].notes = state[payload.eventId].notes.filter(n => n.clientId !== payload.noteClientId); + } + return newState; + }, }, 'events', {}); export const eventsValuesDesc = createReducerDescription({ diff --git a/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts b/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts index e5e4cd7d09..781369f79d 100644 --- a/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts +++ b/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts @@ -28,9 +28,6 @@ import { registrationFormActionTypes } from '../../components/Pages/New/Registra import { enrollmentSiteActionTypes } from '../../components/Pages/common/EnrollmentOverviewDomain'; import { enrollmentEditEventActionTypes } from '../../components/Pages/EnrollmentEditEvent'; import { actionTypes as viewEventActionTypes } from '../../components/Pages/ViewEvent/ViewEventComponent/viewEvent.actions'; -import { enrollmentNoteActionTypes } from '../../components/WidgetEnrollmentNote'; -import { eventNoteActionTypes } from '../../components/WidgetEventNote'; -import { actionTypes as viewEventNotesActionTypes } from '../../components/Pages/ViewEvent/Notes/viewEventNotes.actions'; const alertVariants = { info: 'info', @@ -123,10 +120,4 @@ export const getFeedbackDesc = (appUpdaters: Updaters) => createReducerDescripti addErrorFeedback({ message: i18n.t('Error updating the Assignee') }), [enrollmentEditEventActionTypes.ASSIGNEE_SAVE_FAILED]: () => addErrorFeedback({ message: i18n.t('Error updating the Assignee') }), - [enrollmentNoteActionTypes.ADD_NOTE_FAILED_FOR_ENROLLMENT]: () => - addErrorFeedback({ message: i18n.t('Could not save enrollment note') }), - [eventNoteActionTypes.ADD_NOTE_FAILED_FOR_EVENT]: () => - addErrorFeedback({ message: i18n.t('Could not save event note') }), - [viewEventNotesActionTypes.SAVE_EVENT_NOTE_FAILED]: () => - addErrorFeedback({ message: i18n.t('Could not save event note') }), }, 'feedbacks', []); diff --git a/src/epics/trackerCapture.epics.ts b/src/epics/trackerCapture.epics.ts index e3786155d4..0b03a2f174 100644 --- a/src/epics/trackerCapture.epics.ts +++ b/src/epics/trackerCapture.epics.ts @@ -128,10 +128,7 @@ import { saveNoteForViewEventFailedEpic, } from 'capture-core/components/Pages/ViewEvent/Notes/viewEventNotes.epics'; -import { - addNoteForEnrollmentEpic, - removeNoteForEnrollmentEpic, -} from 'capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics'; +import { addNoteForEnrollmentEpic } from 'capture-core/components/WidgetEnrollmentNote/WidgetEnrollmentNote.epics'; import { openNewRelationshipRegisterTeiEpic, loadSearchGroupDuplicatesForReviewEpic, @@ -376,7 +373,6 @@ export const epics = (combineEpics as any)( updateEventFailedEpic, addNoteForNewEnrollmentEventEpic, addNoteForEnrollmentEpic, - removeNoteForEnrollmentEpic, navigateToEnrollmentOverviewEpic, scheduleEnrollmentEventEpic, orgUnitFetcherEpic, From b02ad2a65c0e096e8954fc732990c7e6d2ccc7d4 Mon Sep 17 00:00:00 2001 From: henrikmv Date: Thu, 28 May 2026 15:26:40 +0200 Subject: [PATCH 11/13] fix: revert pot --- i18n/en.pot | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index 7984e77390..58ea419d37 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-05-28T13:24:01.386Z\n" -"PO-Revision-Date: 2026-05-28T13:24:01.386Z\n" +"POT-Creation-Date: 2026-05-26T07:35:44.230Z\n" +"PO-Revision-Date: 2026-05-26T07:35:44.230Z\n" msgid "The application could not be loaded." msgstr "The application could not be loaded." From 7b1de787f53d1f62349aece97007a1348079bd43 Mon Sep 17 00:00:00 2001 From: henrikmv Date: Fri, 29 May 2026 11:18:48 +0200 Subject: [PATCH 12/13] fix: update error feedback handling to include message object for LIST_VIEW_INIT_ERROR --- .../reducers/descriptions/feedback.reducerDescriptionGetter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts b/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts index 781369f79d..2c82710d92 100644 --- a/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts +++ b/src/core_modules/capture-core/reducers/descriptions/feedback.reducerDescriptionGetter.ts @@ -71,7 +71,7 @@ export const getFeedbackDesc = (appUpdaters: Updaters) => createReducerDescripti [enrollmentActionTypes.ENROLLMENT_LOAD_FAILED]: (_state, action) => addErrorFeedback(action.payload), [workingListsCommonActionTypes.LIST_VIEW_INIT_ERROR]: (_state, action) => - addErrorFeedback(action.payload.errorMessage), + addErrorFeedback({ message: action.payload.errorMessage }), [newEventDataEntryActionTypes.SAVE_FAILED_FOR_NEW_EVENT_AFTER_RETURNED_TO_MAIN_PAGE]: (_state, action) => { const error = action.payload; const errorMessage = isString(error) ? error : error.message; From 59b2791e7fd827ab467337a6b4ddef7f460e0cb1 Mon Sep 17 00:00:00 2001 From: henrikmv Date: Fri, 29 May 2026 12:52:41 +0200 Subject: [PATCH 13/13] fix: (review) align getFeedbackDesc --- .../feedback.reducerDescription.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/reducers/descriptions/feedback.reducerDescription.ts b/src/reducers/descriptions/feedback.reducerDescription.ts index 27151d3ff0..c0b728c3ec 100644 --- a/src/reducers/descriptions/feedback.reducerDescription.ts +++ b/src/reducers/descriptions/feedback.reducerDescription.ts @@ -1,4 +1,5 @@ import i18n from '@dhis2/d2-i18n'; +import uuid from 'd2-utilizr/lib/uuid'; import { getFeedbackDesc } from 'capture-core/reducers/descriptions/feedback.reducerDescriptionGetter'; import { getMainStorageController } from 'capture-core/storageControllers'; import { appStartActionTypes } from '../../components/AppStart'; @@ -7,17 +8,16 @@ export const feedbackDesc = getFeedbackDesc({ [appStartActionTypes.APP_LOAD_SUCESS]: (state) => { const storageController = getMainStorageController(); if (storageController.Adapters[0] !== storageController.adapterType) { - return [ - ...state, { - message: { - title: i18n.t('Compatibility mode'), - // eslint-disable-next-line max-len - content: i18n.t('This app is currently running in compatibility mode due to browser restrictions. For better performance, use another browser or exit private mode if this is currently in use.'), - }, - feedbackType: 'ERROR', - displayType: 'dialog', + return [{ + id: uuid(), + message: { + title: i18n.t('Compatibility mode'), + // eslint-disable-next-line max-len + content: i18n.t('This app is currently running in compatibility mode due to browser restrictions. For better performance, use another browser or exit private mode if this is currently in use.'), }, - ]; + feedbackType: 'ERROR', + displayType: 'dialog', + }]; } return state; },