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

MPDX-8304 Next Action autoselected #1149

Merged
merged 7 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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 @@ -179,7 +179,7 @@ export const MassActionsEditTasksModal: React.FC<
(taskPhase && activitiesByPhase.get(taskPhase)) || []
}
label={t('Action')}
value={activityType || undefined}
value={activityType || null}
onChange={(activityType) =>
setFieldValue('activityType', activityType)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const TaskModalCompleteForm = ({
const { t } = useTranslation();
const { openTaskModal } = useTaskModal();
const { enqueueSnackbar } = useSnackbar();
const activityType = task.activityType || undefined;
const activityType = task.activityType || null;
const taskPhase = useMemo(() => getPhaseByActivityType(activityType), [task]);
const { phaseData, setPhaseId, activityTypes } = usePhaseData(taskPhase);

Expand Down Expand Up @@ -123,9 +123,7 @@ const TaskModalCompleteForm = ({
ResultEnum | DisplayResultEnum | null
>(task?.result || null);

const activityData = activityType
? activityTypes.get(activityType)
: undefined;
const activityData = activityType ? activityTypes.get(activityType) : null;
const [selectedSuggestedTags, setSelectedSuggestedTags] = useState<string[]>(
[],
);
Expand Down Expand Up @@ -357,7 +355,7 @@ const TaskModalCompleteForm = ({
setFieldValue={setFieldValue}
setResultSelected={setResultSelected}
phaseData={phaseData}
completedAction={activityType}
completedAction={activityType || null}
/>

<SuggestedContactStatus
Expand All @@ -375,7 +373,7 @@ const TaskModalCompleteForm = ({
<Grid item>
<ActivityTypeAutocomplete
options={nextActions}
value={nextAction || undefined}
value={nextAction || null}
label={t('Next Action')}
onChange={(nextAction) =>
setFieldValue('nextAction', nextAction)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('ActivityTypeAutocomplete', () => {
expect(getAllByRole('option')[0]).toHaveTextContent('None');
});

it('converts none values to undefined', async () => {
it('converts none values to null', async () => {
const onChange = jest.fn();

const { getByRole } = render(
Expand All @@ -61,7 +61,7 @@ describe('ActivityTypeAutocomplete', () => {
const input = getByRole('combobox', { name: 'Type' });
userEvent.click(input);
await waitFor(() => userEvent.click(getByRole('option', { name: 'None' })));
expect(onChange).toHaveBeenCalledWith(undefined);
expect(onChange).toHaveBeenCalledWith(null);
});

it('preserves none values', () => {
Expand Down Expand Up @@ -108,7 +108,7 @@ describe('ActivityTypeAutocomplete', () => {
<ActivityTypeAutocomplete
options={[]}
label="Type"
value={undefined}
value={null}
onChange={onChange}
/>,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { getLocalizedTaskType } from 'src/utils/functions/getLocalizedTaskType';
interface ActivityTypeProps {
options: ActivityTypeEnum[];
label: string;
value: ActivityTypeEnum | undefined;
onChange: (value: ActivityTypeEnum | undefined) => void;
value: ActivityTypeEnum | null;
onChange: (value: ActivityTypeEnum | null) => void;
// Set to true to make None an acceptable value. Otherwise, None will be converted to undefined.
preserveNone?: boolean;
activityTypes?: Map<ActivityTypeEnum, ActivityData>;
Expand Down Expand Up @@ -78,8 +78,8 @@ export const ActivityTypeAutocomplete: React.FC<ActivityTypeProps> = ({
onChange={(_, value) => {
onChange(
!preserveNone && value === ActivityTypeEnum.None
? undefined
: value || undefined,
? null
: value || null,
);
}}
onBlur={onBlur}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export interface ResultAutocompleteProps {
setResultSelected: SetResultSelected;
result?: ResultEnum | DisplayResultEnum | null;
phaseData: Phase | null;
completedAction: ActivityTypeEnum | null | undefined;
completedAction: ActivityTypeEnum | null;
}

export const ResultAutocomplete: React.FC<ResultAutocompleteProps> = ({
Expand Down
33 changes: 16 additions & 17 deletions src/components/Task/Modal/Form/LogForm/TaskModalLogForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ import { possiblePartnerStatus } from '../possiblePartnerStatus';
import { possibleResults } from '../possibleResults';

const taskSchema = yup.object({
taskPhase: yup.mixed<PhaseEnum>().required().default(undefined),
activityType: yup.mixed<ActivityTypeEnum>().required().default(undefined),
taskPhase: yup.mixed<PhaseEnum>().required(),
activityType: yup.mixed<ActivityTypeEnum>().required(),
subject: yup.string().required(),
contactIds: yup.array().of(yup.string()).default([]),
completedAt: nullableDateTime(),
Expand Down Expand Up @@ -112,9 +112,9 @@ const TaskModalLogForm = ({
DisplayResultEnum | ResultEnum | null
>(defaultValues?.result || null);

const [actionSelected, setActionSelected] = useState<
ActivityTypeEnum | undefined
>(defaultValues?.activityType || undefined);
const [actionSelected, setActionSelected] = useState<ActivityTypeEnum | null>(
defaultValues?.activityType || null,
);

const { enqueueSnackbar } = useSnackbar();
const { openTaskModal } = useTaskModal();
Expand All @@ -141,8 +141,7 @@ const TaskModalLogForm = ({
}, []);

const initialTask: Attributes = useMemo(() => {
let taskPhase: PhaseEnum | undefined =
defaultValues?.taskPhase ?? undefined;
let taskPhase: PhaseEnum | null = defaultValues?.taskPhase ?? null;
let taskSubject = defaultValues?.subject;

if (defaultValues?.activityType && activityTypes) {
Expand All @@ -160,8 +159,9 @@ const TaskModalLogForm = ({
}

return {
taskPhase: taskPhase,
activityType: defaultValues?.activityType ?? undefined,
// yup wants the initial values to match the schema
taskPhase: taskPhase as PhaseEnum,
activityType: (defaultValues?.activityType ?? null) as ActivityTypeEnum,
subject: taskSubject ?? '',
contactIds: defaultValues?.contactIds ?? [],
completedAt: DateTime.local(),
Expand Down Expand Up @@ -194,7 +194,8 @@ const TaskModalLogForm = ({
attributes.result = ResultEnum.Completed;
}
// Remove taskPhase from attributes as we don't save it on the DB
delete attributes.taskPhase;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { taskPhase, ...newAttributes } = attributes;
caleballdrin marked this conversation as resolved.
Show resolved Hide resolved

const updatingContactStatus =
changeContactStatus && !!suggestedPartnerStatus;
Expand All @@ -203,7 +204,7 @@ const TaskModalLogForm = ({
variables: {
accountListId,
attributes: {
...attributes,
...newAttributes,
completedAt: completedAt?.toISO(),
comment: comment?.trim(),
},
Expand Down Expand Up @@ -370,10 +371,8 @@ const TaskModalLogForm = ({
(taskPhase && activitiesByPhase.get(taskPhase)) || []
}
label={t('Action')}
value={activityType || undefined}
onChange={(
activityType: ActivityTypeEnum | undefined,
) => {
value={activityType || null}
onChange={(activityType: ActivityTypeEnum | null) => {
handleTaskActionChange({
activityType,
setFieldValue,
Expand Down Expand Up @@ -428,7 +427,7 @@ const TaskModalLogForm = ({
setFieldValue={setFieldValue}
setResultSelected={setResultSelected}
phaseData={phaseData}
completedAction={activityType}
completedAction={activityType || null}
/>
<SuggestedContactStatus
suggestedContactStatus={partnerStatus?.suggestedContactStatus}
Expand All @@ -451,7 +450,7 @@ const TaskModalLogForm = ({
<ActivityTypeAutocomplete
options={nextActions}
label={t('Next Action')}
value={nextAction || undefined}
value={nextAction || null}
onChange={(nextAction) =>
setFieldValue('nextAction', nextAction)
}
Expand Down
42 changes: 23 additions & 19 deletions src/components/Task/Modal/Form/TaskModalForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,22 +89,22 @@ const getTaskDetails = (
activityTypes: Map<ActivityTypeEnum, ActivityData>,
phaseTags: string[],
) => {
let taskPhase: PhaseEnum | undefined;
let taskPhase: PhaseEnum | null;
let taskSubject: string | undefined;
let filteredTags: ExtractSuggestedTags | undefined;
let additionalTags: ExtractSuggestedTags['additionalTags'] | undefined;
if (task) {
taskPhase = task?.taskPhase ?? undefined;
taskPhase = task?.taskPhase ?? null;
if (!taskPhase) {
taskPhase = task?.activityType
? activityTypes.get(task.activityType)?.phaseId || undefined
: undefined;
? activityTypes.get(task.activityType)?.phaseId || null
: null;
}
//go through tags and move some to selectedSuggestedTags and others to additionalTags
filteredTags = extractSuggestedTags(task.tagList, phaseTags);
additionalTags = filteredTags?.additionalTags;
} else {
taskPhase = defaultValues?.taskPhase || undefined;
taskPhase = defaultValues?.taskPhase || null;
taskSubject = defaultValues?.subject;
if (defaultValues?.activityType && activityTypes) {
const activityData = defaultValues.activityType
Expand All @@ -125,8 +125,8 @@ const getTaskDetails = (
};

const taskSchema = yup.object({
taskPhase: yup.mixed<PhaseEnum>().required().default(undefined),
activityType: yup.mixed<ActivityTypeEnum>().required().default(undefined),
taskPhase: yup.mixed<PhaseEnum>().required(),
activityType: yup.mixed<ActivityTypeEnum>().required(),
subject: yup.string().required(),
startAt: nullableDateTime(),
completedAt: nullableDateTime(),
Expand Down Expand Up @@ -175,9 +175,9 @@ const TaskModalForm = ({
DisplayResultEnum | ResultEnum | null
>(task?.result || defaultValues?.result || null);

const [actionSelected, setActionSelected] = useState<
ActivityTypeEnum | undefined
>(task?.activityType || defaultValues?.activityType || undefined);
const [actionSelected, setActionSelected] = useState<ActivityTypeEnum | null>(
task?.activityType || defaultValues?.activityType || null,
);

const { enqueueSnackbar } = useSnackbar();

Expand Down Expand Up @@ -227,8 +227,9 @@ const TaskModalForm = ({
);
if (task) {
return {
taskPhase,
activityType: task.activityType ?? undefined,
// yup wants the initial values to match the schema
taskPhase: taskPhase as PhaseEnum,
activityType: (task.activityType ?? null) as ActivityTypeEnum,
location: task.location ?? '',
subject: task.subject ?? '',
startAt: task.startAt ? DateTime.fromISO(task.startAt) : null,
Expand All @@ -249,8 +250,9 @@ const TaskModalForm = ({
};
} else {
return {
taskPhase: taskPhase,
activityType: defaultValues?.activityType ?? undefined,
// yup wants the initial values to match the schema
taskPhase: taskPhase as PhaseEnum,
activityType: (defaultValues?.activityType ?? null) as ActivityTypeEnum,
location: '',
subject: taskSubject ?? '',
startAt: DateTime.local(),
Expand Down Expand Up @@ -309,10 +311,12 @@ const TaskModalForm = ({
);
}

delete attributes.taskPhase;
// Remove taskPhase from attributes as we don't save it on the DB
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { taskPhase, ...newAttributes } = attributes;
caleballdrin marked this conversation as resolved.
Show resolved Hide resolved

const sharedAttributes = {
...attributes,
...newAttributes,
completedAt: completedAt?.toISO(),
startAt: startAt?.toISO(),
};
Expand Down Expand Up @@ -472,7 +476,7 @@ const TaskModalForm = ({
(taskPhase && activitiesByPhase.get(taskPhase)) || []
}
label={t('Action')}
value={activityType}
value={activityType || null}
onChange={(activityType) => {
handleTaskActionChange({
activityType,
Expand Down Expand Up @@ -585,7 +589,7 @@ const TaskModalForm = ({
setFieldValue={setFieldValue}
setResultSelected={setResultSelected}
phaseData={phaseData}
completedAction={activityType}
completedAction={activityType || null}
/>
)}

Expand All @@ -602,7 +606,7 @@ const TaskModalForm = ({
<ActivityTypeAutocomplete
options={nextActions}
label={t('Next Action')}
value={nextAction || undefined}
value={nextAction || null}
onChange={(nextAction) =>
setFieldValue('nextAction', nextAction)
}
Expand Down
27 changes: 16 additions & 11 deletions src/components/Task/Modal/Form/TaskModalHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export type SetResultSelected = React.Dispatch<
>;

type SetActionSelected = React.Dispatch<
React.SetStateAction<ActivityTypeEnum | undefined>
React.SetStateAction<ActivityTypeEnum | null>
>;

export type HandleTaskPhaseChangeProps = {
Expand All @@ -38,7 +38,7 @@ export type HandleTaskPhaseChangeProps = {
};

export type HandleTaskActionChangeProps = {
activityType: ActivityTypeEnum | undefined;
activityType: ActivityTypeEnum | null;
setFieldValue: SetFieldValue;
setActionSelected: SetActionSelected;
constants: Constants;
Expand Down Expand Up @@ -68,7 +68,7 @@ export const handleTaskPhaseChange = ({
setFieldValue('result', null);
setFieldValue('nextAction', null);
setResultSelected(null);
setActionSelected(undefined);
setActionSelected(null);
setPhaseId(phase);
setSelectedSuggestedTags([]);
};
Expand All @@ -81,7 +81,7 @@ export const handleTaskActionChange = ({
setFieldTouched,
}: HandleTaskActionChangeProps): void => {
setFieldValue('activityType', activityType);
setActionSelected(activityType || undefined);
setActionSelected(activityType || null);
const activity = constants?.activities?.find(
(activity) => activity.id === activityType,
);
Expand Down Expand Up @@ -121,21 +121,26 @@ export const handleResultChange = ({
setFieldValue('nextAction', defaultNextAction);
};

const findNextAction = (completedAction, nextActions) => {
const findNextAction = (
completedAction: ActivityTypeEnum | null | undefined,
nextActions: ActivityTypeEnum[],
): string | null => {
const actionsWithoutNone = nextActions.filter(
(action) => action !== ActivityTypeEnum.None,
);
return completedAction && nextActions.includes(completedAction)
? completedAction
: actionsWithoutNone.length === 1
? actionsWithoutNone[0]
: undefined;
if (completedAction && nextActions.includes(completedAction)) {
return completedAction;
} else if (actionsWithoutNone.length === 1) {
return actionsWithoutNone[0];
} else {
return null;
}
};

export const getDatabaseValueFromResult = (
phaseData: Phase | null,
displayResult?: DisplayResultEnum | ResultEnum,
activityType?: ActivityTypeEnum | undefined,
activityType?: ActivityTypeEnum | null,
): ResultEnum => {
if (!displayResult || !phaseData || !activityType) {
switch (displayResult) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/Task/Modal/Form/possibleNextActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
export const possibleNextActions = (
phaseData: Phase | null,
resultName: DisplayResultEnum | ResultEnum | null,
activity?: ActivityTypeEnum | undefined,
activity?: ActivityTypeEnum | null,
): ActivityTypeEnum[] => {
if (!phaseData || !resultName || !activity) {
return [];
Expand Down
Loading
Loading