diff --git a/cypress/e2e/EnrollmentEditEventPage/EnrollmentEditEventPageForm.feature b/cypress/e2e/EnrollmentEditEventPage/EnrollmentEditEventPageForm.feature index 5eed4dc983..740965833b 100644 --- a/cypress/e2e/EnrollmentEditEventPage/EnrollmentEditEventPageForm.feature +++ b/cypress/e2e/EnrollmentEditEventPage/EnrollmentEditEventPageForm.feature @@ -58,11 +58,15 @@ And the user see the following text: 11 When the user clicks on the edit button And the user set the apgar score to 5 And the user clicks on the save button +Then you are redirected to the enrollment dashboard +And you open the Birth stage event Then the user see the following text: Enrollment: View Event And the user see the following text: 5 When the user clicks on the edit button And the user set the apgar score to 11 And the user clicks on the save button +Then you are redirected to the enrollment dashboard +And you open the Birth stage event Then the user see the following text: Enrollment: View Event And the user see the following text: 11 diff --git a/cypress/e2e/EnrollmentEditEventPage/EnrollmentEditEventPageForm/index.js b/cypress/e2e/EnrollmentEditEventPage/EnrollmentEditEventPageForm/index.js index 14bb38e5a9..7a94e65f41 100644 --- a/cypress/e2e/EnrollmentEditEventPage/EnrollmentEditEventPageForm/index.js +++ b/cypress/e2e/EnrollmentEditEventPage/EnrollmentEditEventPageForm/index.js @@ -168,3 +168,17 @@ Then('the user sees the enrollment status and recently edited event in Case outc changeEnrollmentAndEventsStatus(); }); +Then('you are redirected to the enrollment dashboard', () => { + cy.url().should('include', `${Cypress.config().baseUrl}/#/enrollment?`); +}); + +And('you open the Birth stage event', () => { + cy.get('[data-test="stage-content"]') + .eq(0) + .within(() => { + cy.get('[data-test="dhis2-uicore-datatablerow"]') + .eq(1) + .click(); + }); +}); + diff --git a/cypress/e2e/ViewPage/EditEventPageForm.feature b/cypress/e2e/ViewPage/EditEventPageForm.feature new file mode 100644 index 0000000000..f62e213d1c --- /dev/null +++ b/cypress/e2e/ViewPage/EditEventPageForm.feature @@ -0,0 +1,10 @@ +Feature: User interacts with a single event page view/edit form + +Scenario: The single event is edited and the changes are reflected in the working list +Given you open the main page with Ngelehun and antenatal care context +And you open the first event in the list +And you complete and save the event +Then you are redirected to the main page and the event status Completed is displayed in the list +And you open the first event in the list +And you incomplete and save the event +Then you are redirected to the main page and the event status Active is displayed in the list diff --git a/cypress/e2e/ViewPage/EditEventPageForm/index.js b/cypress/e2e/ViewPage/EditEventPageForm/index.js new file mode 100644 index 0000000000..e0f2b6d1c6 --- /dev/null +++ b/cypress/e2e/ViewPage/EditEventPageForm/index.js @@ -0,0 +1,40 @@ +import { Given, Then, defineStep as And } from '@badeball/cypress-cucumber-preprocessor'; +import '../../sharedSteps'; + +Given('you open the main page with Ngelehun and antenatal care context', () => { + cy.visit('#/?programId=lxAQ7Zs9VYR&orgUnitId=DiszpKrYNg8'); +}); + +And('you open the first event in the list', () => { + cy.get('[data-test="online-list-table"]').within(() => { + cy.get('[data-test="dhis2-uicore-tablebody"]') + .find('tr') + .eq(0) + .click(); + }); +}); + +And('you (incomplete)(complete) and save the event', () => { + cy.contains('Edit event') + .click(); + + cy.get('[data-test="dataentry-field-complete"]') + .find('input') + .click() + .blur(); + + cy.get('[data-test="dhis2-uicore-button"]') + .contains('Save') + .click(); +}); + +Then(/^you are redirected to the main page and the event status (.*) is displayed in the list/, (status) => { + cy.url().should('include', 'programId=lxAQ7Zs9VYR'); + cy.url().should('include', 'orgUnitId=DiszpKrYNg8'); + cy.get('[data-test="online-list-table"]').within(() => { + cy.get('[data-test="dhis2-uicore-tablebody"]') + .find('tr') + .eq(0) + .contains(status); + }); +}); diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.container.js b/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.container.js index 4142500c30..dccb301c52 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.container.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentEditEvent/EnrollmentEditEventPage.container.js @@ -189,6 +189,7 @@ const EnrollmentEditEventPageWithContextPlain = ({ const onSaveExternal = () => { const queryKey = [ReactQueryAppNamespace, 'changelog', CHANGELOG_ENTITY_TYPES.EVENT, eventId]; queryClient.removeQueries(queryKey); + history.push(`enrollment?${buildUrlQueryString({ enrollmentId })}`); }; const { teiDisplayName } = useTeiDisplayName(teiId, programId); diff --git a/src/core_modules/capture-core/components/Pages/ViewEvent/EventDetailsSection/EventDetailsSection.component.js b/src/core_modules/capture-core/components/Pages/ViewEvent/EventDetailsSection/EventDetailsSection.component.js index 04b053bf3b..593bf438dc 100644 --- a/src/core_modules/capture-core/components/Pages/ViewEvent/EventDetailsSection/EventDetailsSection.component.js +++ b/src/core_modules/capture-core/components/Pages/ViewEvent/EventDetailsSection/EventDetailsSection.component.js @@ -56,6 +56,7 @@ type Props = { onOpenEditEvent: (orgUnit: Object) => void, programStage: ProgramStage, eventAccess: { read: boolean, write: boolean }, + onBackToAllEvents: () => {}, classes: { container: string, headerContainer: string, @@ -75,6 +76,7 @@ const EventDetailsSectionPlain = (props: Props) => { showEditEvent, programStage, eventAccess, + onBackToAllEvents, ...passOnProps } = props; const orgUnitId = useSelector(({ viewEventPage }) => viewEventPage.loadedValues?.orgUnit?.id); const { orgUnit, error } = useCoreOrgUnit(orgUnitId); @@ -86,6 +88,7 @@ const EventDetailsSectionPlain = (props: Props) => { const onSaveExternal = () => { const queryKey = [ReactQueryAppNamespace, 'changelog', CHANGELOG_ENTITY_TYPES.EVENT, eventId]; queryClient.removeQueries(queryKey); + onBackToAllEvents(); }; if (error) { diff --git a/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/ViewEvent.component.js b/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/ViewEvent.component.js index de6353d5ea..ee5710e754 100644 --- a/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/ViewEvent.component.js +++ b/src/core_modules/capture-core/components/Pages/ViewEvent/ViewEventComponent/ViewEvent.component.js @@ -83,6 +83,7 @@ class ViewEventPlain extends Component { getAssignedUserSaveContext, onSaveAssignee, onSaveAssigneeError, + onBackToAllEvents, } = this.props; return ( @@ -98,6 +99,7 @@ class ViewEventPlain extends Component { export const openAddRelationship = () => actionCreator(actionTypes.VIEW_EVENT_OPEN_NEW_RELATIONSHIP)(); -export const updateEventContainer = (eventContainer: Object, orgUnit: OrgUnit) => - actionCreator(actionTypes.UPDATE_EVENT_CONTAINER)({ eventContainer, orgUnit }); - export const openViewEventPageFailed = (error: string) => actionCreator(actionTypes.OPEN_VIEW_EVENT_PAGE_FAILED)({ error }); diff --git a/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/EditEventDataEntry.container.js b/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/EditEventDataEntry.container.js index 7b004d1dc3..23f9599d56 100644 --- a/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/EditEventDataEntry.container.js +++ b/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/EditEventDataEntry.container.js @@ -91,13 +91,13 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props): any => ({ dispatch(startAsyncUpdateFieldForEditEvent(innerAction, onAsyncUpdateSuccess, onAsyncUpdateError)); }, - onSave: (orgUnit: OrgUnit) => (eventId: string, dataEntryId: string, formFoundation: RenderFoundation) => { + onSave: () => (eventId: string, dataEntryId: string, formFoundation: RenderFoundation) => { const { onSaveExternal } = props; window.scrollTo(0, 0); onSaveExternal && onSaveExternal(); - dispatch(requestSaveEditEventDataEntry(eventId, dataEntryId, formFoundation, orgUnit)); + dispatch(requestSaveEditEventDataEntry(eventId, dataEntryId, formFoundation)); }, - onSaveAndCompleteEnrollment: (orgUnit: OrgUnit) => ( + onSaveAndCompleteEnrollment: () => ( eventId: string, dataEntryId: string, formFoundation: RenderFoundation, @@ -113,7 +113,6 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props): any => ({ itemId: eventId, dataEntryId, formFoundation, - orgUnit, onSaveAndCompleteEnrollmentExternal, onSaveAndCompleteEnrollmentSuccessActionType, onSaveAndCompleteEnrollmentErrorActionType, @@ -139,14 +138,14 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props): any => ({ }, onCancelCreateNew: (itemId: string) => { const { dataEntryId, formFoundation, orgUnit, enrollmentId, programId, teiId, availableProgramStages } = props; - dispatch(requestSaveEditEventDataEntry(itemId, dataEntryId, formFoundation, orgUnit)); + dispatch(requestSaveEditEventDataEntry(itemId, dataEntryId, formFoundation)); dispatch(startCreateNewAfterCompleting({ enrollmentId, isCreateNew: false, orgUnitId: orgUnit.id, programId, teiId, availableProgramStages, })); }, onConfirmCreateNew: (itemId: string) => { const { dataEntryId, formFoundation, orgUnit, enrollmentId, programId, teiId, availableProgramStages } = props; - dispatch(requestSaveEditEventDataEntry(itemId, dataEntryId, formFoundation, orgUnit)); + dispatch(requestSaveEditEventDataEntry(itemId, dataEntryId, formFoundation)); dispatch(startCreateNewAfterCompleting({ enrollmentId, isCreateNew: true, orgUnitId: orgUnit.id, programId, teiId, availableProgramStages, })); diff --git a/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/editEventDataEntry.actions.js b/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/editEventDataEntry.actions.js index 4ef997bfb1..f067297cd2 100644 --- a/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/editEventDataEntry.actions.js +++ b/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/editEventDataEntry.actions.js @@ -1,11 +1,10 @@ // @flow - -import type { OrgUnit } from '@dhis2/rules-engine-javascript'; import { actionCreator } from '../../../actions/actions.utils'; import { effectMethods } from '../../../trackerOffline'; export const batchActionTypes = { START_SAVE_EDIT_EVENT_DATA_ENTRY_BATCH: 'StartSaveEditEventDataEntryBatchForViewSingleEvent', + SAVE_EDIT_EVENT_DATA_ENTRY_FAILED: 'SaveEditEventDataEntryBatchFailed', }; @@ -29,9 +28,11 @@ export const actionTypes = { export const cancelEditEventDataEntry = () => actionCreator(actionTypes.CANCEL_EDIT_EVENT_DATA_ENTRY)(); -export const requestSaveEditEventDataEntry = (itemId: string, dataEntryId: string, formFoundation: Object, orgUnit: OrgUnit) => - actionCreator(actionTypes.REQUEST_SAVE_EDIT_EVENT_DATA_ENTRY)({ itemId, dataEntryId, formFoundation, orgUnit }, { skipLogging: ['formFoundation'] }); - +export const requestSaveEditEventDataEntry = (itemId: string, dataEntryId: string, formFoundation: Object) => + actionCreator(actionTypes.REQUEST_SAVE_EDIT_EVENT_DATA_ENTRY)( + { itemId, dataEntryId, formFoundation }, + { skipLogging: ['formFoundation'] }, + ); export const startSaveEditEventDataEntry = ( eventId: string, @@ -92,7 +93,6 @@ export const requestSaveAndCompleteEnrollment = ({ itemId, dataEntryId, formFoundation, - orgUnit, onSaveAndCompleteEnrollmentExternal, onSaveAndCompleteEnrollmentSuccessActionType, onSaveAndCompleteEnrollmentErrorActionType, @@ -101,7 +101,6 @@ export const requestSaveAndCompleteEnrollment = ({ itemId: string, dataEntryId: string, formFoundation: Object, - orgUnit: OrgUnit, onSaveAndCompleteEnrollmentExternal?: (enrollmnet: ApiEnrollment) => void, onSaveAndCompleteEnrollmentSuccessActionType?: string, onSaveAndCompleteEnrollmentErrorActionType?: string, @@ -112,7 +111,6 @@ export const requestSaveAndCompleteEnrollment = ({ itemId, dataEntryId, formFoundation, - orgUnit, onSaveAndCompleteEnrollmentExternal, onSaveAndCompleteEnrollmentSuccessActionType, onSaveAndCompleteEnrollmentErrorActionType, diff --git a/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/editEventDataEntry.epics.js b/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/editEventDataEntry.epics.js index 1ab650c1a4..acd63ce69f 100644 --- a/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/editEventDataEntry.epics.js +++ b/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/editEventDataEntry.epics.js @@ -36,10 +36,6 @@ import { showEditEventDataEntry, } from '../../Pages/ViewEvent/EventDetailsSection/eventDetails.actions'; import { buildUrlQueryString } from '../../../utils/routing/buildUrlQueryString'; - -import { - updateEventContainer, -} from '../../Pages/ViewEvent/ViewEventComponent/viewEvent.actions'; import { newEventWidgetActionTypes } from '../../WidgetEnrollmentEventNew/Validated/validated.actions'; import { enrollmentEditEventActionTypes } from '../../Pages/EnrollmentEditEvent'; @@ -90,7 +86,6 @@ export const saveEditedEventEpic = (action$: InputObservable, store: ReduxStore) dataEntryId, itemId, formFoundation, - orgUnit, } = action.payload; const state = store.value; const dataEntryKey = getDataEntryKey(dataEntryId, itemId); @@ -149,13 +144,11 @@ export const saveEditedEventEpic = (action$: InputObservable, store: ReduxStore) if (program instanceof TrackerProgram) { return batchActions([ - updateEventContainer(eventContainer, orgUnit), updateEnrollmentEvent(eventId, serverData.events[0]), startSaveEditEventDataEntry(eventId, serverData, enrollmentSiteActionTypes.COMMIT_ENROLLMENT_EVENT, enrollmentSiteActionTypes.ROLLBACK_ENROLLMENT_EVENT), ], batchActionTypes.START_SAVE_EDIT_EVENT_DATA_ENTRY_BATCH); } return batchActions([ - updateEventContainer(eventContainer, orgUnit), startSaveEditEventDataEntry(eventId, serverData), ], batchActionTypes.START_SAVE_EDIT_EVENT_DATA_ENTRY_BATCH); })); @@ -195,20 +188,18 @@ export const saveEditedEventFailedEpic = (action$: InputObservable, store: Redux const meta = action.meta; const viewEventPage = state.viewEventPage; const eventContainer = viewEventPage.loadedValues.eventContainer; - const orgUnit = state.organisationUnits[eventContainer.event.orgUnitId]; if (eventContainer.event && eventContainer.event.attributeCategoryOptions) { eventContainer.event.attributeCategoryOptions = convertCategoryOptionsToServer(eventContainer.event.attributeCategoryOptions); } - let actions = [updateEventContainer(eventContainer, orgUnit)]; + let actions = []; if (meta.triggerAction === enrollmentSiteActionTypes.ROLLBACK_ENROLLMENT_EVENT) { - actions = [...actions, rollbackEnrollmentEvent(eventContainer.event.eventId)]; + actions = [rollbackEnrollmentEvent(eventContainer.event.eventId)]; + } else if (meta.triggerAction === enrollmentEditEventActionTypes.EVENT_SAVE_ENROLLMENT_COMPLETE_ERROR) { + actions = [rollbackEnrollmentAndEvents()]; } - if (meta.triggerAction === enrollmentEditEventActionTypes.EVENT_SAVE_ENROLLMENT_COMPLETE_ERROR) { - actions = [...actions, rollbackEnrollmentAndEvents()]; - } - return batchActions(actions); + return batchActions(actions, batchActionTypes.SAVE_EDIT_EVENT_DATA_ENTRY_FAILED); })); export const requestDeleteEventDataEntryEpic = (action$: InputObservable, store: ReduxStore, dependencies: any) => @@ -254,7 +245,6 @@ export const saveEventAndCompleteEnrollmentEpic = (action$: InputObservable, sto itemId, dataEntryId, formFoundation, - orgUnit, onSaveAndCompleteEnrollmentExternal, onSaveAndCompleteEnrollmentSuccessActionType, onSaveAndCompleteEnrollmentErrorActionType, @@ -283,18 +273,6 @@ export const saveEventAndCompleteEnrollmentEpic = (action$: InputObservable, sto mainDataServerValues.completedAt = getFormattedStringFromMomentUsingEuropeanGlyphs(moment()); } - const { eventContainer: prevEventContainer } = state.viewEventPage.loadedValues; - const eventContainer = { - ...prevEventContainer, - event: { - ...prevEventContainer.event, - ...dataEntryClientValues, - }, - values: { - ...formClientValues, - }, - }; - const editEvent = { ...mainDataServerValues, attributeOptionCombo: undefined, @@ -314,7 +292,6 @@ export const saveEventAndCompleteEnrollmentEpic = (action$: InputObservable, sto onSaveAndCompleteEnrollmentExternal && onSaveAndCompleteEnrollmentExternal(enrollmentWithAllEvents); return batchActions([ - updateEventContainer(eventContainer, orgUnit), startSaveEditEventDataEntry( eventId, serverData, diff --git a/src/core_modules/capture-core/components/WidgetEventEdit/ViewEventDataEntry/viewEventDataEntry.epics.js b/src/core_modules/capture-core/components/WidgetEventEdit/ViewEventDataEntry/viewEventDataEntry.epics.js index 4164776b80..c8d4fe056c 100644 --- a/src/core_modules/capture-core/components/WidgetEventEdit/ViewEventDataEntry/viewEventDataEntry.epics.js +++ b/src/core_modules/capture-core/components/WidgetEventEdit/ViewEventDataEntry/viewEventDataEntry.epics.js @@ -45,21 +45,18 @@ export const loadViewEventDataEntryEpic = (action$: InputObservable, store: Redu viewEventPageActionTypes.ORG_UNIT_RETRIEVED_ON_URL_UPDATE, viewEventPageActionTypes.ORG_UNIT_RETRIEVAL_FAILED_ON_URL_UPDATE, viewEventPageActionTypes.START_OPEN_EVENT_FOR_VIEW, - viewEventPageActionTypes.UPDATE_EVENT_CONTAINER, editEventDataEntryBatchActionTypes.START_SAVE_EDIT_EVENT_DATA_ENTRY_BATCH, ), filter(action => filterByInnerAction( action, editEventDataEntryBatchActionTypes.START_SAVE_EDIT_EVENT_DATA_ENTRY_BATCH, - viewEventPageActionTypes.UPDATE_EVENT_CONTAINER, ), ), map(action => mapToInnerAction( action, editEventDataEntryBatchActionTypes.START_SAVE_EDIT_EVENT_DATA_ENTRY_BATCH, - viewEventPageActionTypes.UPDATE_EVENT_CONTAINER, ), ), filter((action) => { diff --git a/src/core_modules/capture-core/reducers/descriptions/viewEvent.reducerDescription.js b/src/core_modules/capture-core/reducers/descriptions/viewEvent.reducerDescription.js index f82ba16563..4ff0449444 100644 --- a/src/core_modules/capture-core/reducers/descriptions/viewEvent.reducerDescription.js +++ b/src/core_modules/capture-core/reducers/descriptions/viewEvent.reducerDescription.js @@ -144,10 +144,6 @@ export const viewEventPageDesc = createReducerDescription({ [editEventDataEntryActionTypes.REQUEST_SAVE_EDIT_EVENT_DATA_ENTRY]: state => ({ ...state, saveInProgress: true, - eventDetailsSection: { - ...state.eventDetailsSection, - showEditEvent: false, - }, }), [editEventDataEntryActionTypes.SAVE_EDIT_EVENT_DATA_ENTRY_FAILED]: (state, action) => { if (action.meta.eventId !== state.eventId) {