Skip to content

Commit e725dfe

Browse files
authored
Merge pull request #1315 from CruGlobal/MPDX-8388-suggested-tags-autocomplete
MPDX-8388 - Suggested task tags show up in tags autocomplete
2 parents f18df0d + cb150ee commit e725dfe

File tree

3 files changed

+115
-4
lines changed

3 files changed

+115
-4
lines changed

src/components/Task/Modal/Form/Inputs/TagsAutocomplete/TagsAutocomplete.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ interface TagsAutocompleteProps {
1313
value: string[];
1414
onChange: (tagList: string[]) => void;
1515
label?: string;
16+
selectedSuggestedTags?: string[];
1617
}
1718

1819
export const TagsAutocomplete: React.FC<TagsAutocompleteProps> = ({
@@ -21,6 +22,7 @@ export const TagsAutocomplete: React.FC<TagsAutocompleteProps> = ({
2122
value,
2223
onChange,
2324
label,
25+
selectedSuggestedTags,
2426
}) => {
2527
const { t } = useTranslation();
2628

@@ -32,7 +34,11 @@ export const TagsAutocomplete: React.FC<TagsAutocompleteProps> = ({
3234
});
3335
// Because of the @skip and @include directives, only contactTagList or taskTagList will be populated, but not both
3436
const options =
35-
data?.accountList.contactTagList ?? data?.accountList.taskTagList ?? [];
37+
data?.accountList.contactTagList ??
38+
data?.accountList?.taskTagList?.filter(
39+
(tag) => !selectedSuggestedTags?.includes(tag),
40+
) ??
41+
[];
3642

3743
return (
3844
<Autocomplete

src/components/Task/Modal/Form/TaskModalForm.test.tsx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,66 @@ describe('TaskModalForm', () => {
199199
});
200200
}, 10000);
201201

202+
it('should toggle suggested tags and additional tags', async () => {
203+
const { findByRole, getByRole, queryByRole } = render(
204+
<LocalizationProvider dateAdapter={AdapterLuxon}>
205+
<SnackbarProvider>
206+
<GqlMockedProvider<{
207+
AssigneeOptions: AssigneeOptionsQuery;
208+
ContactOptions: ContactOptionsQuery;
209+
TagOptions: TagOptionsQuery;
210+
}>
211+
mocks={{
212+
AssigneeOptions: {
213+
accountListUsers: {
214+
nodes: [
215+
{
216+
user: { id: 'user-1', firstName: 'User', lastName: '1' },
217+
},
218+
{
219+
user: { id: 'user-2', firstName: 'User', lastName: '2' },
220+
},
221+
],
222+
},
223+
},
224+
ContactOptions: {
225+
contacts: {
226+
nodes: [
227+
{ id: 'contact-1', name: 'Contact 1' },
228+
{ id: 'contact-2', name: 'Contact 2' },
229+
],
230+
},
231+
},
232+
TagOptions: {
233+
accountList: {
234+
taskTagList: ['tag-1', 'tag-2'],
235+
},
236+
},
237+
}}
238+
onCall={mutationSpy}
239+
>
240+
<TaskModalForm accountListId={accountListId} onClose={onClose} />
241+
</GqlMockedProvider>
242+
</SnackbarProvider>
243+
</LocalizationProvider>,
244+
);
245+
246+
userEvent.click(getByRole('combobox', { name: 'Task Type' }));
247+
userEvent.click(await findByRole('option', { name: 'Appointment' }));
248+
249+
expect(getByRole('combobox', { name: 'Tags' })).toBeInTheDocument();
250+
251+
userEvent.click(getByRole('combobox', { name: 'Tags' }));
252+
userEvent.click(await findByRole('option', { name: 'tag-1' }));
253+
254+
expect(getByRole('button', { name: 'tag-1' })).toBeInTheDocument();
255+
256+
userEvent.click(getByRole('combobox', { name: 'Tags' }));
257+
await waitFor(() =>
258+
expect(queryByRole('option', { name: 'tag-1' })).not.toBeInTheDocument(),
259+
);
260+
});
261+
202262
it('persisted', async () => {
203263
const {
204264
getByRole,

src/components/Task/Modal/Form/TaskModalForm.tsx

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, {
22
ReactElement,
3+
useCallback,
34
useEffect,
45
useMemo,
56
useRef,
@@ -391,6 +392,39 @@ const TaskModalForm = ({
391392
setTimeout(() => activityRef?.current?.focus(), 50);
392393
};
393394

395+
const handleChangeAutocomplete = useCallback(
396+
(autoCompleteTagList: string[], tagList: string[]) => {
397+
const suggested = autoCompleteTagList.filter((tag) =>
398+
phaseTags.some(
399+
(phaseTag) => phaseTag.toLowerCase() === tag.toLowerCase(),
400+
),
401+
);
402+
403+
if (suggested.length) {
404+
setSelectedSuggestedTags([
405+
...selectedSuggestedTags,
406+
...suggested.filter(
407+
(tag) =>
408+
!selectedSuggestedTags
409+
.map((t) => t.toLowerCase())
410+
.includes(tag.toLowerCase()),
411+
),
412+
]);
413+
}
414+
415+
const removedTag = tagList.find(
416+
(tag) => !autoCompleteTagList.includes(tag),
417+
);
418+
419+
if (removedTag && selectedSuggestedTags.includes(removedTag)) {
420+
setSelectedSuggestedTags((prev) =>
421+
prev.filter((tag) => tag !== removedTag),
422+
);
423+
}
424+
},
425+
[phaseTags, setSelectedSuggestedTags, selectedSuggestedTags],
426+
);
427+
394428
return (
395429
<Formik
396430
initialValues={initialTask}
@@ -620,15 +654,26 @@ const TaskModalForm = ({
620654
<PhaseTags
621655
tags={phaseTags}
622656
selectedTags={selectedSuggestedTags}
623-
setSelectedTags={setSelectedSuggestedTags}
657+
setSelectedTags={(tags) => {
658+
setSelectedSuggestedTags(tags);
659+
// Remove any deselected suggested tags from tagList as well
660+
setFieldValue(
661+
'tagList',
662+
tagList.filter((tag) => tags.includes(tag)),
663+
);
664+
}}
624665
/>
625666
)}
626667
<Grid item xs={12}>
627668
<TagsAutocomplete
628669
accountListId={accountListId}
670+
selectedSuggestedTags={selectedSuggestedTags}
629671
type={TagTypeEnum.Tag}
630-
value={tagList ?? []}
631-
onChange={(tagList) => setFieldValue('tagList', tagList)}
672+
value={tagList || []}
673+
onChange={(autoCompleteTagList) => {
674+
setFieldValue('tagList', autoCompleteTagList);
675+
handleChangeAutocomplete(autoCompleteTagList, tagList);
676+
}}
632677
label={
633678
phaseTags?.length && initialTask.completedAt
634679
? t('Additional Tags')

0 commit comments

Comments
 (0)