diff --git a/src/core_modules/capture-core/components/LockedSelector/LockedSelector.actions.js b/src/core_modules/capture-core/components/LockedSelector/LockedSelector.actions.js index a91ec8b952..5426d31572 100644 --- a/src/core_modules/capture-core/components/LockedSelector/LockedSelector.actions.js +++ b/src/core_modules/capture-core/components/LockedSelector/LockedSelector.actions.js @@ -1,5 +1,6 @@ // @flow import { actionCreator } from '../../actions/actions.utils'; +import type { ReduxOrgUnit } from '../../redux/organisationUnits'; export const lockedSelectorActionTypes = { LOADING_START: 'LockedSelector.Loading', @@ -17,7 +18,7 @@ export const lockedSelectorActionTypes = { export const updateSelectionsFromUrl = (data: Object) => actionCreator(lockedSelectorActionTypes.FROM_URL_UPDATE)(data); export const validSelectionsFromUrl = () => actionCreator(lockedSelectorActionTypes.FROM_URL_CURRENT_SELECTIONS_VALID)(); export const invalidSelectionsFromUrl = (error: string) => actionCreator(lockedSelectorActionTypes.FROM_URL_CURRENT_SELECTIONS_INVALID)({ error }); -export const setCurrentOrgUnitBasedOnUrl = (orgUnit: Object) => actionCreator(lockedSelectorActionTypes.FETCH_ORG_UNIT_SUCCESS)(orgUnit); +export const setCurrentOrgUnitBasedOnUrl = (orgUnit: ReduxOrgUnit) => actionCreator(lockedSelectorActionTypes.FETCH_ORG_UNIT_SUCCESS)(orgUnit); export const startLoading = () => actionCreator(lockedSelectorActionTypes.LOADING_START)(); export const completeUrlUpdate = () => actionCreator(lockedSelectorActionTypes.FROM_URL_UPDATE_COMPLETE)(); export const errorRetrievingOrgUnitBasedOnUrl = (error: string) => actionCreator(lockedSelectorActionTypes.FETCH_ORG_UNIT_ERROR)({ error }); diff --git a/src/core_modules/capture-core/components/LockedSelector/LockedSelector.epics.js b/src/core_modules/capture-core/components/LockedSelector/LockedSelector.epics.js index ba5a8d7032..360cbd6508 100644 --- a/src/core_modules/capture-core/components/LockedSelector/LockedSelector.epics.js +++ b/src/core_modules/capture-core/components/LockedSelector/LockedSelector.epics.js @@ -1,8 +1,8 @@ // @flow import i18n from '@dhis2/d2-i18n'; import { ofType } from 'redux-observable'; -import { catchError, filter, flatMap, map, startWith, switchMap } from 'rxjs/operators'; -import { from, of } from 'rxjs'; +import { filter, map, concatMap } from 'rxjs/operators'; +import { of } from 'rxjs'; import { lockedSelectorActionTypes, invalidSelectionsFromUrl, @@ -16,32 +16,25 @@ import { import { programCollection } from '../../metaDataMemoryStores'; import { getLocationPathname, pageFetchesOrgUnitUsingTheOldWay } from '../../utils/url'; import { getLocationQuery } from '../../utils/routing'; +import { getOrgUnit } from '../../redux/organisationUnits'; -const orgUnitsQuery = id => ({ resource: 'organisationUnits', id }); - -export const getOrgUnitDataBasedOnUrlUpdateEpic = ( - action$: InputObservable, - store: ReduxStore, - { querySingleResource }: ApiUtils) => +export const getOrgUnitDataBasedOnUrlUpdateEpic = (action$: InputObservable, store: ReduxStore) => action$.pipe( ofType(lockedSelectorActionTypes.FROM_URL_UPDATE), filter(action => action.payload.nextProps.orgUnitId), - switchMap((action) => { + concatMap((action) => { const { organisationUnits } = store.value; const { orgUnitId } = action.payload.nextProps; if (organisationUnits[orgUnitId]) { return of(completeUrlUpdate()); } - return from(querySingleResource(orgUnitsQuery(action.payload.nextProps.orgUnitId))) - .pipe( - flatMap(response => - of(setCurrentOrgUnitBasedOnUrl({ id: response.id, name: response.displayName, code: response.code }))), - catchError(() => - of(errorRetrievingOrgUnitBasedOnUrl(i18n.t('Could not get organisation unit')))), - startWith(startLoading()), - ); - }, - )); + return of(startLoading(), getOrgUnit({ + orgUnitId, + onSuccess: setCurrentOrgUnitBasedOnUrl, + onError: () => errorRetrievingOrgUnitBasedOnUrl(i18n.t('Could not get organisation unit')), + })); + }), + ); export const setOrgUnitDataEmptyBasedOnUrlUpdateEpic = (action$: InputObservable) => action$.pipe( @@ -76,4 +69,3 @@ export const validateSelectionsBasedOnUrlUpdateEpic = (action$: InputObservable) return validSelectionsFromUrl(); })); - diff --git a/src/core_modules/capture-core/components/OrgUnitFetcher/OrgUnitFetcher.actions.js b/src/core_modules/capture-core/components/OrgUnitFetcher/OrgUnitFetcher.actions.js index 260ad0c4ae..4c36fd473d 100644 --- a/src/core_modules/capture-core/components/OrgUnitFetcher/OrgUnitFetcher.actions.js +++ b/src/core_modules/capture-core/components/OrgUnitFetcher/OrgUnitFetcher.actions.js @@ -1,6 +1,7 @@ // @flow import { actionCreator } from '../../actions/actions.utils'; +import type { ReduxOrgUnit } from '../../redux/organisationUnits'; export const actionTypes = { FETCH_ORG_UNIT: 'OrgUnitFetcher.FetchOrgUnit', @@ -11,6 +12,6 @@ export const actionTypes = { export const fetchOrgUnit = (orgUnitId: string) => actionCreator(actionTypes.FETCH_ORG_UNIT)({ orgUnitId }); -export const setCurrentOrgUnit = (orgUnit: Object) => actionCreator(actionTypes.FETCH_ORG_UNIT_SUCCESS)(orgUnit); +export const setCurrentOrgUnit = (orgUnit: ReduxOrgUnit) => actionCreator(actionTypes.FETCH_ORG_UNIT_SUCCESS)(orgUnit); export const errorRetrievingOrgUnit = () => actionCreator(actionTypes.FETCH_ORG_UNIT_FAILURE)(); diff --git a/src/core_modules/capture-core/components/OrgUnitFetcher/OrgUnitFetcher.component.js b/src/core_modules/capture-core/components/OrgUnitFetcher/OrgUnitFetcher.component.js index 51f7bb0d70..199c96f6ce 100644 --- a/src/core_modules/capture-core/components/OrgUnitFetcher/OrgUnitFetcher.component.js +++ b/src/core_modules/capture-core/components/OrgUnitFetcher/OrgUnitFetcher.component.js @@ -6,13 +6,7 @@ import { fetchOrgUnit } from './OrgUnitFetcher.actions'; export const OrgUnitFetcher = (({ orgUnitId, children, error }: Object) => { const dispatch = useDispatch(); - const { orgUnit } = useSelector( - ({ - organisationUnits, - }) => ({ - orgUnit: organisationUnits[orgUnitId], - }), - ); + const orgUnit = useSelector(({ organisationUnits }) => organisationUnits[orgUnitId]); useEffect(() => { if (!orgUnit && orgUnitId) { diff --git a/src/core_modules/capture-core/components/OrgUnitFetcher/OrgUnitFetcher.epics.js b/src/core_modules/capture-core/components/OrgUnitFetcher/OrgUnitFetcher.epics.js index 1c36e942d1..d50ed49f73 100644 --- a/src/core_modules/capture-core/components/OrgUnitFetcher/OrgUnitFetcher.epics.js +++ b/src/core_modules/capture-core/components/OrgUnitFetcher/OrgUnitFetcher.epics.js @@ -1,17 +1,14 @@ // @flow import { ofType } from 'redux-observable'; -import { catchError, map, switchMap } from 'rxjs/operators'; -import { from, of } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { getOrgUnit } from '../../redux/organisationUnits'; import { actionTypes, setCurrentOrgUnit, errorRetrievingOrgUnit } from './OrgUnitFetcher.actions'; - -const orgUnitsQuery = id => ({ resource: `organisationUnits/${id}` }); - -export const orgUnitFetcherEpic = (action$: InputObservable, _: ReduxStore, { querySingleResource }: ApiUtils, -) => action$.pipe( +export const orgUnitFetcherEpic = (action$: InputObservable) => action$.pipe( ofType(actionTypes.FETCH_ORG_UNIT), - switchMap(({ payload: { orgUnitId } }) => from(querySingleResource(orgUnitsQuery(orgUnitId))) - .pipe(map(({ id, displayName: name }) => setCurrentOrgUnit({ id, name })))) - , - catchError(() => of(errorRetrievingOrgUnit())), + map(({ payload: { orgUnitId } }) => getOrgUnit({ + orgUnitId, + onSuccess: orgUnit => setCurrentOrgUnit(orgUnit), + onError: errorRetrievingOrgUnit, + })), ); diff --git a/src/core_modules/capture-core/components/Pages/ViewEvent/epics/viewEvent.epics.js b/src/core_modules/capture-core/components/Pages/ViewEvent/epics/viewEvent.epics.js index 91c84cced6..254a6cf3bc 100644 --- a/src/core_modules/capture-core/components/Pages/ViewEvent/epics/viewEvent.epics.js +++ b/src/core_modules/capture-core/components/Pages/ViewEvent/epics/viewEvent.epics.js @@ -4,8 +4,7 @@ import { ofType } from 'redux-observable'; import { map, switchMap } from 'rxjs/operators'; import i18n from '@dhis2/d2-i18n'; import { errorCreator } from 'capture-core-utils'; -import { getRulesEngineOrgUnit } from 'capture-core/rules/getRulesEngineOrgUnit'; -import { getAssociatedOrgUnitGroups } from 'capture-core/MetaDataStoreUtils/getAssociatedOrgUnitGroups'; +import { getOrgUnit } from 'capture-core/redux/organisationUnits'; import { isSelectionsEqual } from '../../../App/isSelectionsEqual'; import { getErrorMessageAndDetails } from '../../../../utils/errors/getErrorMessageAndDetails'; @@ -39,18 +38,24 @@ export const getEventOpeningFromEventListEpic = ( action$.pipe( ofType(eventWorkingListsActionTypes.VIEW_EVENT_PAGE_OPEN), switchMap(({ payload: { eventId } }) => getEvent(eventId, absoluteApiPath, querySingleResource) - .then(eventContainer => - (eventContainer - ? Promise.all( - [eventContainer, getRulesEngineOrgUnit(eventContainer.event.orgUnitId, querySingleResource)], - ) - : [])) - .then(([eventContainer, orgUnit]) => { + .then((eventContainer) => { if (!eventContainer) { return openViewEventPageFailed( i18n.t('Event could not be loaded. Are you sure it exists?')); } - return startOpenEventForView(eventContainer, orgUnit); + return getOrgUnit({ + orgUnitId: eventContainer.event.orgUnitId, + onSuccess: orgUnit => startOpenEventForView(eventContainer, orgUnit), + onError: (error) => { + const { message, details } = getErrorMessageAndDetails(error); + log.error( + errorCreator( + message || + i18n.t('Organisation unit could not be loaded'))(details)); + return openViewEventPageFailed( + i18n.t('Could not get organisation unit')); + }, + }); }) .catch((error) => { const { message, details } = getErrorMessageAndDetails(error); @@ -95,28 +100,22 @@ export const getEventFromUrlEpic = ( }); })); -export const getOrgUnitOnUrlUpdateEpic = (action$: InputObservable, _: ReduxStore, { querySingleResource }: ApiUtils) => +export const getOrgUnitOnUrlUpdateEpic = (action$: InputObservable) => action$.pipe( ofType(viewEventActionTypes.EVENT_FROM_URL_RETRIEVED), - switchMap((action) => { + map((action) => { const eventContainer = action.payload.eventContainer; - // change from organisationUnitGroups -> groups - return Promise.all( - [ - querySingleResource({ resource: `organisationUnits/${eventContainer.event.orgUnitId}` }), - getAssociatedOrgUnitGroups(eventContainer.event.orgUnitId), - ]) - .then(([orgUnit, groups]) => { - orgUnit.groups = groups; - return orgUnitRetrievedOnUrlUpdate(orgUnit, eventContainer); - }) - .catch((error) => { + return getOrgUnit({ + orgUnitId: eventContainer.event.orgUnitId, + onSuccess: orgUnit => orgUnitRetrievedOnUrlUpdate(orgUnit, eventContainer), + onError: (error) => { const { message, details } = getErrorMessageAndDetails(error); log.error(errorCreator( message || i18n.t('Organisation unit could not be loaded'))(details)); return orgUnitCouldNotBeRetrievedOnUrlUpdate(eventContainer); - }); + }, + }); })); export const openViewPageLocationChangeEpic = (action$: InputObservable, _: ReduxStore, { history }: ApiUtils) => diff --git a/src/core_modules/capture-core/components/ScopeSelector/QuickSelector/actions/QuickSelector.actions.js b/src/core_modules/capture-core/components/ScopeSelector/QuickSelector/actions/QuickSelector.actions.js index 184bda91b2..214f58bb4b 100644 --- a/src/core_modules/capture-core/components/ScopeSelector/QuickSelector/actions/QuickSelector.actions.js +++ b/src/core_modules/capture-core/components/ScopeSelector/QuickSelector/actions/QuickSelector.actions.js @@ -3,7 +3,6 @@ import { actionCreator } from '../../../../actions/actions.utils'; export const actionTypes = { SET_ORG_UNIT_ID: 'setOrgUnitId', - STORE_ORG_UNIT_OBJECT: 'storeOrgUnitObject', SET_PROGRAM_ID: 'setProgramId', SET_CATEGORY_ID: 'setCategoryId', RESET_CATEGORY_SELECTIONS: 'resetCategorySelections', @@ -15,9 +14,6 @@ export const actionTypes = { export const setOrgUnitId = (orgUnitId: string) => actionCreator(actionTypes.SET_ORG_UNIT_ID)(orgUnitId); -export const storeOrgUnitObject = - (orgUnitObject: Object) => actionCreator(actionTypes.STORE_ORG_UNIT_OBJECT)(orgUnitObject); - export const setProgramId = (programId: string) => actionCreator(actionTypes.SET_PROGRAM_ID)(programId); diff --git a/src/core_modules/capture-core/reducers/descriptions/organisationUnits.reducerDescription.js b/src/core_modules/capture-core/reducers/descriptions/organisationUnits.reducerDescription.js index 6610eb8e40..33b4677d52 100644 --- a/src/core_modules/capture-core/reducers/descriptions/organisationUnits.reducerDescription.js +++ b/src/core_modules/capture-core/reducers/descriptions/organisationUnits.reducerDescription.js @@ -1,32 +1,14 @@ // @flow import { createReducerDescription } from '../../trackerRedux/trackerReducer'; -import { actionTypes as viewEventActionTypes } from '../../components/Pages/ViewEvent/ViewEventComponent/viewEvent.actions'; -import { actionTypes as setOrgUnitActionTypes } from '../../components/ScopeSelector/QuickSelector/actions/QuickSelector.actions'; -import { lockedSelectorActionTypes } from '../../components/LockedSelector/LockedSelector.actions'; import { actionTypes as initActionTypes } from '../../init/init.actions'; -import { actionTypes as orgUnitFetcherActionTypes } from '../../components/OrgUnitFetcher/OrgUnitFetcher.actions'; +import { actionTypes as reduxOrgunitActionTypes } from '../../redux/organisationUnits/organisationUnits.actions'; +import type { ReduxOrgUnit } from '../../redux/organisationUnits'; export const organisationUnitDesc = createReducerDescription({ - [viewEventActionTypes.ORG_UNIT_RETRIEVED_ON_URL_UPDATE]: (state, action) => { - const newState = { ...state }; - const orgUnit = action.payload.orgUnit; - newState[orgUnit.id] = orgUnit; - return newState; - }, - [setOrgUnitActionTypes.STORE_ORG_UNIT_OBJECT]: (state, action) => { - const newState = { ...state }; - const orgUnit = action.payload; - newState[orgUnit.id] = orgUnit; - return newState; - }, - - [lockedSelectorActionTypes.FETCH_ORG_UNIT_SUCCESS]: (state, action) => ({ + [reduxOrgunitActionTypes.ORG_UNIT_FETCHED]: (state: ReduxState, action: { payload: ReduxOrgUnit }) => ({ ...state, [action.payload.id]: action.payload, }), - [orgUnitFetcherActionTypes.FETCH_ORG_UNIT_SUCCESS]: (state, action) => ({ - ...state, [action.payload.id]: action.payload, - }), }, 'organisationUnits'); export const organisationUnitRootsDesc = createReducerDescription({ diff --git a/src/core_modules/capture-core/rules/getRulesEngineOrgUnit.js b/src/core_modules/capture-core/rules/getRulesEngineOrgUnit.js deleted file mode 100644 index d195283079..0000000000 --- a/src/core_modules/capture-core/rules/getRulesEngineOrgUnit.js +++ /dev/null @@ -1,20 +0,0 @@ -// @flow -import { getAssociatedOrgUnitGroups } from 'capture-core/MetaDataStoreUtils/getAssociatedOrgUnitGroups'; -import type { QuerySingleResource } from '../utils/api/api.types'; - -export async function getRulesEngineOrgUnit(orgUnitId: string, querySingleResource: QuerySingleResource) { - return Promise.all([ - querySingleResource({ - resource: `organisationUnits/${orgUnitId}`, - params: { - fields: 'displayName,code', - }, - }), - getAssociatedOrgUnitGroups(orgUnitId), - ]).then(([orgUnit, groups]) => ({ - id: orgUnitId, - name: orgUnit.displayName, - code: orgUnit.code, - groups, - })); -}