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

fix: [DHIS2-18028] User is able to add invalid related stages event #3795

Merged
Show file tree
Hide file tree
Changes from all 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 @@ -61,7 +61,7 @@ const getEventDetailsByLinkMode = ({
linkedEvent: {
...baseEventDetails,
scheduledAt: convertFn(clientRequestEvent.scheduledAt, dataElementTypes.DATE),
orgUnit: convertFn(clientRequestEvent.orgUnit, dataElementTypes.ORGANISATION_UNIT),
orgUnit: clientRequestEvent.orgUnit,
},
linkedEventId: baseEventDetails.event,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
// @flow
import React from 'react';
import i18n from '@dhis2/d2-i18n';
import {
SingleSelectField,
SingleSelectOption,
spacers,
} from '@dhis2/ui';
import { SingleSelectField, SingleSelectOption, spacers } from '@dhis2/ui';
import { withStyles } from '@material-ui/core';
import type { LinkToExistingProps } from './LinkToExisting.types';

Expand Down Expand Up @@ -58,13 +54,15 @@ export const LinkToExistingPlain = ({
error={saveAttempted && !!errorMessages.linkedEventId}
validationText={saveAttempted && errorMessages.linkedEventId}
>
{linkableEvents.map(event => (
<SingleSelectOption
key={event.id}
value={event.id}
label={event.label}
/>
))}
{linkableEvents
.map(event => (
<SingleSelectOption
key={event.id}
value={event.id}
label={event.label}
/>
))
}
</SingleSelectField>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
// @flow

import type { ErrorMessagesForRelatedStages, LinkableEvent } from '../RelatedStagesActions/RelatedStagesActions.types';
import type {
ErrorMessagesForRelatedStages,
RelatedStagesEvents,
} from '../RelatedStagesActions/RelatedStagesActions.types';
import type { RelatedStageDataValueStates } from '../WidgetRelatedStages.types';

export type LinkToExistingProps = {|
relatedStagesDataValues: RelatedStageDataValueStates,
setRelatedStagesDataValues: (RelatedStageDataValueStates) => void,
linkableEvents: Array<LinkableEvent>,
linkableEvents: Array<RelatedStagesEvents>,
errorMessages: ErrorMessagesForRelatedStages,
saveAttempted: boolean,
linkableStageLabel: string,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @flow
import React, { type ComponentType, useMemo } from 'react';
import i18n from '@dhis2/d2-i18n';
import { Radio, colors, spacers, spacersNum, IconInfo16, Button } from '@dhis2/ui';
import { Button, colors, IconInfo16, Radio, spacers, spacersNum } from '@dhis2/ui';
import { withStyles } from '@material-ui/core';
import { ConditionalTooltip } from 'capture-core/components/Tooltips/ConditionalTooltip';
import { actions as RelatedStagesActionTypes, mainOptionTranslatedTexts, relatedStageStatus } from '../constants';
Expand Down Expand Up @@ -53,6 +53,7 @@ export const RelatedStagesActionsPlain = ({
type,
relationshipName,
scheduledLabel,
events,
linkableEvents,
relatedStagesDataValues,
setRelatedStagesDataValues,
Expand All @@ -71,7 +72,7 @@ export const RelatedStagesActionsPlain = ({
linkMode: action,
}));
};
const canAddNewEventToStage = useCanAddNewEventToStage(programStage, linkableEvents);
const canAddNewEventToStage = useCanAddNewEventToStage(programStage, events);

if (!programStage) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ export type ErrorMessagesForRelatedStages = {|
linkedEventId?: ?string,
|}

export type LinkableEvent = {
export type RelatedStagesEvents = {
id: string,
label: string,
isLinkable: boolean,
status: string,
}

export type Props = {|
type: string,
relationshipName: string,
relatedStagesDataValues: RelatedStageDataValueStates,
linkableEvents: Array<LinkableEvent>,
events: Array<RelatedStagesEvents>,
linkableEvents: Array<RelatedStagesEvents>,
scheduledLabel: string,
saveAttempted: boolean,
errorMessages: ErrorMessagesForRelatedStages,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from 'react';
import { useRelatedStages } from './useRelatedStages';
import type { Props, RelatedStageDataValueStates } from './WidgetRelatedStages.types';
import type { ErrorMessagesForRelatedStages } from './RelatedStagesActions';
import { RelatedStagesActions } from './RelatedStagesActions';
import { relatedStageStatus } from './constants';
import { useStageLabels } from './hooks/useStageLabels';
import type { ErrorMessagesForRelatedStages } from './RelatedStagesActions';
import { relatedStageWidgetIsValid } from './relatedStageEventIsValid/relatedStageEventIsValid';
import { useAvailableRelatedStageEvents } from './hooks/useAvailableRelatedStageEvents';
import { useRelatedStageEvents } from './hooks/useRelatedStageEvents';

const WidgetRelatedStagesPlain = ({
programId,
Expand All @@ -21,7 +21,7 @@ const WidgetRelatedStagesPlain = ({
programId,
});
const { scheduledLabel, occurredLabel } = useStageLabels(programId, constraint?.programStage?.id);
const { linkableEvents, isLoading: isLoadingEvents } = useAvailableRelatedStageEvents({
const { events, linkableEvents, isLoading: isLoadingEvents } = useRelatedStageEvents({
stageId: constraint?.programStage?.id,
relationshipTypeId: selectedRelationshipType?.id,
scheduledLabel,
Expand Down Expand Up @@ -90,6 +90,7 @@ const WidgetRelatedStagesPlain = ({
relationshipName={selectedRelationshipType.displayName}
scheduledLabel={scheduledLabel}
type={currentRelatedStagesStatus}
events={events}
linkableEvents={linkableEvents}
relatedStagesDataValues={relatedStageDataValues}
setRelatedStagesDataValues={setRelatedStageDataValues}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import { useMemo } from 'react';
import { useSelector } from 'react-redux';
import { ProgramStage } from '../../../metaData';
import type { LinkableEvent } from '../RelatedStagesActions/RelatedStagesActions.types';
import type { RelatedStagesEvents } from '../RelatedStagesActions/RelatedStagesActions.types';

export const useCanAddNewEventToStage = (programStage: ?ProgramStage, existingRelatedEvents: LinkableEvent[]) => {
export const useCanAddNewEventToStage = (programStage: ?ProgramStage, existingRelatedEvents: RelatedStagesEvents[]) => {
const hiddenProgramStages = useSelector(({ rulesEffectsHiddenProgramStageDesc }) =>
rulesEffectsHiddenProgramStageDesc?.['enrollmentEvent-newEvent'],
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @flow
import { useMemo } from 'react';
import { convertDateObjectToDateFormatString } from '../../../utils/converters/date';
import type { LinkableEvent } from '../RelatedStagesActions/RelatedStagesActions.types';
import type { RelatedStagesEvents } from '../RelatedStagesActions/RelatedStagesActions.types';
import { useApiDataQuery } from '../../../utils/reactQueryHelpers';
import { handleAPIResponse, REQUESTED_ENTITIES } from '../../../utils/api';

Expand All @@ -15,12 +15,13 @@ type Props = {
}

type ReturnType = {
linkableEvents: Array<LinkableEvent>,
events: Array<RelatedStagesEvents>,
linkableEvents: Array<RelatedStagesEvents>,
isLoading: boolean,
isError: boolean,
}

export const useAvailableRelatedStageEvents = ({
export const useRelatedStageEvents = ({
stageId,
enrollmentId,
relationshipTypeId,
Expand All @@ -36,7 +37,7 @@ export const useAvailableRelatedStageEvents = ({
fields: 'event,occurredAt,scheduledAt,status,relationships',
},
}), [stageId, enrollmentId]);
const { data, isLoading, isError } = useApiDataQuery<Array<LinkableEvent>>(
const { data, isLoading, isError } = useApiDataQuery<Array<RelatedStagesEvents>>(
['availableRelatedStageEvents', stageId, enrollmentId, relationshipTypeId],
query,
{
Expand All @@ -45,19 +46,20 @@ export const useAvailableRelatedStageEvents = ({
staleTime: 0,
select: (response: any) => {
const events = handleAPIResponse(REQUESTED_ENTITIES.events, response);

if (events.length === 0) return [];

return events
.filter(event => !event.relationships ||
!event.relationships.some(relationship => relationship.relationshipType === relationshipTypeId))
.map((event) => {
const isLinkable = !event.relationships
?.some(relationship => relationship.relationshipType === relationshipTypeId);
const label = event.occurredAt
? `${occurredLabel}: ${convertDateObjectToDateFormatString(new Date(event.occurredAt))}`
: `${scheduledLabel}: ${convertDateObjectToDateFormatString(new Date(event.scheduledAt))}`;

return ({
id: event.event,
status: event.status,
isLinkable,
label,
});
});
Expand All @@ -66,7 +68,8 @@ export const useAvailableRelatedStageEvents = ({
);

return {
linkableEvents: data ?? [],
events: data ?? [],
linkableEvents: data?.filter(event => event.isLinkable) ?? [],
isLoading,
isError,
};
Expand Down
Loading