Skip to content
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 @@ -13,6 +13,7 @@
value: string[];
onChange: (tagList: string[]) => void;
label?: string;
selectedSuggestedTags?: string[];
}

export const TagsAutocomplete: React.FC<TagsAutocompleteProps> = ({
Expand All @@ -21,18 +22,23 @@
value,
onChange,
label,
selectedSuggestedTags,
}) => {
const { t } = useTranslation();

const { data, loading } = useTagOptionsQuery({
variables: {
accountListId,
contact: type === TagTypeEnum.Contact,
},
});
// Because of the @skip and @include directives, only contactTagList or taskTagList will be populated, but not both
const options =
data?.accountList.contactTagList ?? data?.accountList.taskTagList ?? [];
data?.accountList.contactTagList ??
data?.accountList?.taskTagList?.filter(
(tag) => !selectedSuggestedTags?.includes(tag),
) ??
[];

Check warning on line 41 in src/components/Task/Modal/Form/Inputs/TagsAutocomplete/TagsAutocomplete.tsx

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ New issue: Complex Method

TagsAutocomplete:React.FC<TagsAutocompleteProps> has a cyclomatic complexity of 10, threshold = 10. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

return (
<Autocomplete
Expand Down
60 changes: 60 additions & 0 deletions src/components/Task/Modal/Form/TaskModalForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,66 @@ describe('TaskModalForm', () => {
});
}, 10000);

it('should toggle suggested tags and additional tags', async () => {
const { findByRole, getByRole, queryByRole } = render(
<LocalizationProvider dateAdapter={AdapterLuxon}>
<SnackbarProvider>
<GqlMockedProvider<{
AssigneeOptions: AssigneeOptionsQuery;
ContactOptions: ContactOptionsQuery;
TagOptions: TagOptionsQuery;
}>
mocks={{
AssigneeOptions: {
accountListUsers: {
nodes: [
{
user: { id: 'user-1', firstName: 'User', lastName: '1' },
},
{
user: { id: 'user-2', firstName: 'User', lastName: '2' },
},
],
},
},
ContactOptions: {
contacts: {
nodes: [
{ id: 'contact-1', name: 'Contact 1' },
{ id: 'contact-2', name: 'Contact 2' },
],
},
},
TagOptions: {
accountList: {
taskTagList: ['tag-1', 'tag-2'],
},
},
}}
onCall={mutationSpy}
>
<TaskModalForm accountListId={accountListId} onClose={onClose} />
</GqlMockedProvider>
</SnackbarProvider>
</LocalizationProvider>,
);

userEvent.click(getByRole('combobox', { name: 'Task Type' }));
userEvent.click(await findByRole('option', { name: 'Appointment' }));

expect(getByRole('combobox', { name: 'Tags' })).toBeInTheDocument();

userEvent.click(getByRole('combobox', { name: 'Tags' }));
userEvent.click(await findByRole('option', { name: 'tag-1' }));

expect(getByRole('button', { name: 'tag-1' })).toBeInTheDocument();

userEvent.click(getByRole('combobox', { name: 'Tags' }));
await waitFor(() =>
expect(queryByRole('option', { name: 'tag-1' })).not.toBeInTheDocument(),
);
});

it('persisted', async () => {
const {
getByRole,
Expand Down
51 changes: 48 additions & 3 deletions src/components/Task/Modal/Form/TaskModalForm.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, {
ReactElement,
useCallback,
useEffect,
useMemo,
useRef,
Expand Down Expand Up @@ -391,6 +392,39 @@
setTimeout(() => activityRef?.current?.focus(), 50);
};

const handleChangeAutocomplete = useCallback(
(autoCompleteTagList: string[], tagList: string[]) => {
const suggested = autoCompleteTagList.filter((tag) =>
phaseTags.some(
(phaseTag) => phaseTag.toLowerCase() === tag.toLowerCase(),
),
);

if (suggested.length) {
setSelectedSuggestedTags([

Check warning on line 404 in src/components/Task/Modal/Form/TaskModalForm.tsx

View check run for this annotation

Codecov / codecov/patch

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

Added line #L404 was not covered by tests
...selectedSuggestedTags,
...suggested.filter(
(tag) =>
!selectedSuggestedTags
.map((t) => t.toLowerCase())

Check warning on line 409 in src/components/Task/Modal/Form/TaskModalForm.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/Task/Modal/Form/TaskModalForm.tsx#L408-L409

Added lines #L408 - L409 were not covered by tests
.includes(tag.toLowerCase()),
),
]);
}

const removedTag = tagList.find(
(tag) => !autoCompleteTagList.includes(tag),

Check warning on line 416 in src/components/Task/Modal/Form/TaskModalForm.tsx

View check run for this annotation

Codecov / codecov/patch

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

Added line #L416 was not covered by tests
);

if (removedTag && selectedSuggestedTags.includes(removedTag)) {
setSelectedSuggestedTags((prev) =>
prev.filter((tag) => tag !== removedTag),

Check warning on line 421 in src/components/Task/Modal/Form/TaskModalForm.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/Task/Modal/Form/TaskModalForm.tsx#L420-L421

Added lines #L420 - L421 were not covered by tests
);
}
},
[phaseTags, setSelectedSuggestedTags, selectedSuggestedTags],
);

return (
<Formik
initialValues={initialTask}
Expand Down Expand Up @@ -620,15 +654,26 @@
<PhaseTags
tags={phaseTags}
selectedTags={selectedSuggestedTags}
setSelectedTags={setSelectedSuggestedTags}
setSelectedTags={(tags) => {
setSelectedSuggestedTags(tags);

Check warning on line 658 in src/components/Task/Modal/Form/TaskModalForm.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/Task/Modal/Form/TaskModalForm.tsx#L657-L658

Added lines #L657 - L658 were not covered by tests
// Remove any deselected suggested tags from tagList as well
setFieldValue(

Check warning on line 660 in src/components/Task/Modal/Form/TaskModalForm.tsx

View check run for this annotation

Codecov / codecov/patch

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

Added line #L660 was not covered by tests
'tagList',
tagList.filter((tag) => tags.includes(tag)),

Check warning on line 662 in src/components/Task/Modal/Form/TaskModalForm.tsx

View check run for this annotation

Codecov / codecov/patch

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

Added line #L662 was not covered by tests
);
}}
/>
)}
<Grid item xs={12}>
<TagsAutocomplete
accountListId={accountListId}
selectedSuggestedTags={selectedSuggestedTags}
type={TagTypeEnum.Tag}
value={tagList ?? []}
onChange={(tagList) => setFieldValue('tagList', tagList)}
value={tagList || []}
onChange={(autoCompleteTagList) => {
setFieldValue('tagList', autoCompleteTagList);
handleChangeAutocomplete(autoCompleteTagList, tagList);
}}

Check warning on line 676 in src/components/Task/Modal/Form/TaskModalForm.tsx

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

TaskModalForm increases in cyclomatic complexity from 88 to 92, threshold = 10. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
label={
phaseTags?.length && initialTask.completedAt
? t('Additional Tags')
Expand Down
Loading