Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: [TECH-1657] standardize format of redux orgunits #3436

Merged
merged 13 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ Feature: The user interacts with the widgets on the enrollment add event page

Scenario: User can close the Enrollment Widget
Given you land on the enrollment add event page by having typed #/enrollmentEventNew?programId=IpHINAT79UW&orgUnitId=DiszpKrYNg8&teiId=EaOyKGOIGRp&enrollmentId=wBU0RAsYjKE&stageId=A03MvHHogjR
And the enrollment widget should be opened
When you click the enrollment widget toggle open close button
Then the enrollment widget should be closed

Scenario: User can close and reopen the Enrollment Widget
Given you land on the enrollment add event page by having typed #/enrollmentEventNew?programId=IpHINAT79UW&orgUnitId=DiszpKrYNg8&teiId=EaOyKGOIGRp&enrollmentId=wBU0RAsYjKE&stageId=A03MvHHogjR
And the enrollment widget should be opened
When you click the enrollment widget toggle open close button
Then the enrollment widget should be closed
When you click the enrollment widget toggle open close button
And you click the enrollment widget toggle open close button
Then the enrollment widget should be opened

Scenario: User can see the enrollment details
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,16 @@ Feature: The user interacts with the widgets on the enrollment dashboard

Scenario: User can close the Enrollment Widget
Given you land on the enrollment dashboard page by having typed #/enrollment?enrollmentId=wBU0RAsYjKE
And the enrollment widget should be opened
When you click the enrollment widget toggle open close button
Then the enrollment widget should be closed

Scenario: User can close and reopen the Enrollment Widget
Given you land on the enrollment dashboard page by having typed #/enrollment?enrollmentId=wBU0RAsYjKE
And the enrollment widget should be opened
When you click the enrollment widget toggle open close button
Then the enrollment widget should be closed
When you click the enrollment widget toggle open close button
And you click the enrollment widget toggle open close button
Then the enrollment widget should be opened

Scenario: User can see the enrollment details
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ Feature: The user interacts with the widgets on the enrollment edit event

Scenario: User can close the Enrollment Widget
Given you land on the enrollment edit event page by having typed /#/enrollmentEventEdit?eventId=XGLkLlOXgmE&orgUnitId=DiszpKrYNg8
And the enrollment widget should be opened
When you click the enrollment widget toggle open close button
Then the enrollment widget should be closed

Scenario: User can close and reopen the Enrollment Widget
Given you land on the enrollment edit event page by having typed /#/enrollmentEventEdit?eventId=XGLkLlOXgmE&orgUnitId=DiszpKrYNg8
And the enrollment widget should be opened
When you click the enrollment widget toggle open close button
Then the enrollment widget should be closed
When you click the enrollment widget toggle open close button
And you click the enrollment widget toggle open close button
Then the enrollment widget should be opened

Scenario: User can see the enrollment details
Expand Down
4 changes: 2 additions & 2 deletions packages/rules-engine/src/rulesEngine.types.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,12 @@ export type OrgUnitGroup = $ReadOnly<{|
code: string,
|}>;

export type OrgUnit = $ReadOnly<{|
export type OrgUnit = $ReadOnly<{
id: string,
name: string,
code: string,
groups: Array<OrgUnitGroup>,
|}>;
}>;

export type RulesEngineInput = {|
programRulesContainer: ProgramRulesContainer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { useSelector } from 'react-redux';
import { EnrollmentRegistrationEntryComponent } from './EnrollmentRegistrationEntry.component';
import type { OwnProps } from './EnrollmentRegistrationEntry.types';
import { useLifecycle } from './hooks';
import { useCurrentOrgUnitInfo } from '../../../hooks/useCurrentOrgUnitInfo';
import { useRulesEngineOrgUnit } from '../../../hooks';
import { useCurrentOrgUnitId } from '../../../hooks/useCurrentOrgUnitId';
import { useReduxOrgUnit } from '../../../redux/organisationUnits';
import { dataEntryHasChanges } from '../../DataEntry/common/dataEntryHasChanges';

export const EnrollmentRegistrationEntry: ComponentType<OwnProps> = ({
Expand All @@ -17,8 +17,8 @@ export const EnrollmentRegistrationEntry: ComponentType<OwnProps> = ({
onSave,
...passOnProps
}) => {
const orgUnitId = useCurrentOrgUnitInfo().id;
const { orgUnit, error } = useRulesEngineOrgUnit(orgUnitId);
const orgUnitId = useCurrentOrgUnitId();
const { orgUnit, error } = useReduxOrgUnit(orgUnitId);
const {
teiId,
ready,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { DataEntry } from './DataEntry/DataEntry.container';
import { EventsList } from './RecentlyAddedEventsList/RecentlyAddedEventsList.container';
import { useScopeTitleText } from '../../../../hooks/useScopeTitleText';
import { useCurrentProgramInfo } from '../../../../hooks/useCurrentProgramInfo';
import { useRulesEngineOrgUnit } from '../../../../hooks/useRulesEngineOrgUnit';
import { useReduxOrgUnit } from '../../../../redux/organisationUnits';
import { useLocationQuery } from '../../../../utils/routing';
import { useRulesEngine } from './useRulesEngine';
import type { PlainProps } from './NewEventDataEntryWrapper.types';
Expand Down Expand Up @@ -48,7 +48,7 @@ const NewEventDataEntryWrapperPlain = ({
}: PlainProps) => {
const { id: programId } = useCurrentProgramInfo();
const orgUnitId = useLocationQuery().orgUnitId;
const { orgUnit, error } = useRulesEngineOrgUnit(orgUnitId);
const { orgUnit, error } = useReduxOrgUnit(orgUnitId);
const rulesReady = useRulesEngine({ programId, orgUnit, formFoundation });
const titleText = useScopeTitleText(programId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { useHistory } from 'react-router-dom';
import { useScopeInfo } from '../../../hooks/useScopeInfo';
import { scopeTypes } from '../../../metaData';
import { TrackedEntityInstanceDataEntry } from '../TrackedEntityInstance';
import { useCurrentOrgUnitInfo } from '../../../hooks/useCurrentOrgUnitInfo';
import { useCurrentOrgUnitId } from '../../../hooks/useCurrentOrgUnitId';
import { useReduxOrgUnit } from '../../../redux/organisationUnits';
import type { Props, PlainProps } from './TeiRegistrationEntry.types';
import { DiscardDialog } from '../../Dialogs/DiscardDialog.component';
import { withSaveHandler } from '../../DataEntry';
Expand Down Expand Up @@ -54,7 +55,9 @@ const TeiRegistrationEntryPlain =
const [showWarning, setShowWarning] = useState(false);
const { scopeType } = useScopeInfo(selectedScopeId);
const { formId, formFoundation } = useMetadataForRegistrationForm({ selectedScopeId });
const orgUnit = useCurrentOrgUnitInfo();
const orgUnitId = useCurrentOrgUnitId();
const { orgUnit } = useReduxOrgUnit(orgUnitId); // Tony: [DHIS2-15814] Change this to new hook
const orgUnitName = orgUnit ? orgUnit.name : '';

const handleOnCancel = () => {
if (!isUserInteractionInProgress) {
Expand All @@ -68,9 +71,9 @@ const TeiRegistrationEntryPlain =
const url =
scopeType === scopeTypes.TRACKER_PROGRAM
?
buildUrlQueryString({ programId: selectedScopeId, orgUnitId: orgUnit.id })
buildUrlQueryString({ programId: selectedScopeId, orgUnitId })
:
buildUrlQueryString({ orgUnitId: orgUnit.id });
buildUrlQueryString({ orgUnitId });
return push(`/?${url}`);
};

Expand All @@ -79,9 +82,8 @@ const TeiRegistrationEntryPlain =
{
scopeType === scopeTypes.TRACKED_ENTITY_TYPE && formId &&
<>
{/* $FlowFixMe */}
<TrackedEntityInstanceDataEntry
orgUnit={orgUnit}
orgUnitId={orgUnitId}
formFoundation={formFoundation}
trackedEntityTypeId={selectedScopeId}
teiRegistrationMetadata={teiRegistrationMetadata}
Expand Down Expand Up @@ -114,7 +116,7 @@ const TeiRegistrationEntryPlain =
</Button>
</div>
<InfoIconText>
{translatedTextWithStylesForTei(trackedEntityName.toLowerCase(), orgUnit.name)}
{translatedTextWithStylesForTei(trackedEntityName.toLowerCase(), orgUnitName)}
</InfoIconText>

<DiscardDialog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useDispatch, useSelector } from 'react-redux';
import React, { useEffect, useMemo } from 'react';
import type { ComponentType } from 'react';
import { useScopeInfo } from '../../../hooks/useScopeInfo';
import { useCurrentOrgUnitInfo } from '../../../hooks/useCurrentOrgUnitInfo';
import { useCurrentOrgUnitId } from '../../../hooks/useCurrentOrgUnitId';
import { Enrollment, scopeTypes } from '../../../metaData';
import { startNewTeiDataEntryInitialisation } from './TeiRegistrationEntry.actions';
import type { OwnProps } from './TeiRegistrationEntry.types';
Expand All @@ -15,7 +15,7 @@ import { useMetadataForRegistrationForm } from '../common/TEIAndEnrollment/useMe
const useInitialiseTeiRegistration = (selectedScopeId, dataEntryId) => {
const dispatch = useDispatch();
const { scopeType, trackedEntityName } = useScopeInfo(selectedScopeId);
const { id: selectedOrgUnitId } = useCurrentOrgUnitInfo();
const selectedOrgUnitId = useCurrentOrgUnitId();
const { formId, formFoundation } = useMetadataForRegistrationForm({ selectedScopeId });
const formValues = useFormValuesFromSearchTerms();
const registrationFormReady = !!formId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class PreTeiDataEntryPure extends React.PureComponent<Object> {
}

type PreTeiDataEntryProps = {
orgUnit: Object,
orgUnitId: string,
trackedEntityTypeId: string,
onUpdateField: Function,
onStartAsyncUpdateField: Function,
Expand All @@ -52,17 +52,17 @@ type PreTeiDataEntryProps = {

export class PreTeiDataEntry extends React.Component<PreTeiDataEntryProps> {
getValidationContext = () => {
const { orgUnit, onGetUnsavedAttributeValues, trackedEntityTypeId } = this.props;
const { orgUnitId, onGetUnsavedAttributeValues, trackedEntityTypeId } = this.props;
return {
trackedEntityTypeId,
orgUnitId: orgUnit.id,
orgUnitId,
onGetUnsavedAttributeValues,
};
}

render() {
const {
orgUnit,
orgUnitId,
trackedEntityTypeId,
onUpdateField,
onStartAsyncUpdateField,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @flow
import { actionCreator } from '../../actions/actions.utils';
import type { ReduxOrgUnit } from '../../redux/organisationUnits';

export const lockedSelectorActionTypes = {
LOADING_START: 'LockedSelector.Loading',
Expand All @@ -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 });
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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(
Expand Down Expand Up @@ -76,4 +69,3 @@ export const validateSelectionsBasedOnUrlUpdateEpic = (action$: InputObservable)

return validSelectionsFromUrl();
}));

Original file line number Diff line number Diff line change
@@ -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',
Expand All @@ -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)();
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
})),
);
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
updateTeiDisplayName,
} from '../EnrollmentPage.actions';
import { useTrackerProgram } from '../../../../hooks/useTrackerProgram';
import { useRulesEngineOrgUnit } from '../../../../hooks/useRulesEngineOrgUnit';
import { useReduxOrgUnit } from '../../../../redux/organisationUnits';
import { EnrollmentPageDefaultComponent } from './EnrollmentPageDefault.component';
import {
useProgramMetadata,
Expand All @@ -33,7 +33,7 @@ export const EnrollmentPageDefault = () => {
const history = useHistory();
const dispatch = useDispatch();
const { enrollmentId, programId, teiId, orgUnitId } = useLocationQuery();
const { orgUnit, error } = useRulesEngineOrgUnit(orgUnitId);
const { orgUnit, error } = useReduxOrgUnit(orgUnitId);

const program = useTrackerProgram(programId);
const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useCommonEnrollmentDomainData, useRuleEffects } from '../../common/Enro
import type { Props } from './ProgramStageSelector.types';
import { useProgramFromIndexedDB } from '../../../../utils/cachedDataHooks/useProgramFromIndexedDB';
import { useLocationQuery, buildUrlQueryString } from '../../../../utils/routing';
import { useRulesEngineOrgUnit } from '../../../../hooks/useRulesEngineOrgUnit';
import { useReduxOrgUnit } from '../../../../redux/organisationUnits';
import { useTrackerProgram } from '../../../../hooks/useTrackerProgram';


Expand All @@ -24,7 +24,7 @@ export const ProgramStageSelector = ({ programId, orgUnitId, teiId, enrollmentId
isError: programError,
} = useProgramFromIndexedDB(programId);

const { orgUnit } = useRulesEngineOrgUnit(orgUnitId);
const { orgUnit } = useReduxOrgUnit(orgUnitId);
const programRules = useTrackerProgram(programId);

const ruleEffects = useRuleEffects({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { ViewEventSectionHeader } from '../Section/ViewEventSectionHeader.compon
import { EditEventDataEntry } from '../../../WidgetEventEdit/EditEventDataEntry/EditEventDataEntry.container';
import { ViewEventDataEntry } from '../../../WidgetEventEdit/ViewEventDataEntry/ViewEventDataEntry.container';
import type { ProgramStage } from '../../../../metaData';
import { useRulesEngineOrgUnit } from '../../../../hooks/useRulesEngineOrgUnit';
import { useReduxOrgUnit } from '../../../../redux/organisationUnits';
import { NoticeBox } from '../../../NoticeBox';

const getStyles = () => ({
Expand Down Expand Up @@ -60,7 +60,7 @@ const EventDetailsSectionPlain = (props: Props) => {
eventAccess,
...passOnProps } = props;
const orgUnitId = useSelector(({ viewEventPage }) => viewEventPage.loadedValues?.orgUnit?.id);
const { orgUnit, error } = useRulesEngineOrgUnit(orgUnitId);
const { orgUnit, error } = useReduxOrgUnit(orgUnitId);

if (error) {
return error.errorComponent;
Expand Down
Loading
Loading