Skip to content

Commit

Permalink
Merge pull request #1151 from CruGlobal/8240-deselect-removed-ids
Browse files Browse the repository at this point in the history
[MPDX-8240] Deselect removed ids
  • Loading branch information
canac authored Oct 25, 2024
2 parents 6c3cb0b + 6e9c8e4 commit ada0000
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 105 deletions.
11 changes: 10 additions & 1 deletion pages/accountLists/[accountListId]/tasks/Tasks.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import userEvent from '@testing-library/user-event';
import { VirtuosoMockContext } from 'react-virtuoso';
import TestRouter from '__tests__/util/TestRouter';
import { GqlMockedProvider } from '__tests__/util/graphqlMocking';
import { GetTaskIdsForMassSelectionQuery } from 'src/hooks/GetIdsForMassSelection.generated';
import useTaskModal from 'src/hooks/useTaskModal';
import { dispatch } from 'src/lib/analytics';
import theme from 'src/theme';
Expand Down Expand Up @@ -141,7 +142,10 @@ describe('tasks page', () => {
it('should dispatch one analytics event per task', async () => {
const { getAllByTestId, getByRole, findByRole } = render(
<MocksProviders>
<GqlMockedProvider<{ Tasks: TasksQuery }>
<GqlMockedProvider<{
Tasks: TasksQuery;
GetTaskIdsForMassSelection: GetTaskIdsForMassSelectionQuery;
}>
mocks={{
Tasks: {
tasks: {
Expand All @@ -154,6 +158,11 @@ describe('tasks page', () => {
pageInfo: { hasNextPage: false },
},
},
GetTaskIdsForMassSelection: {
tasks: {
nodes: [{ id: '1' }, { id: '2' }, { id: '3' }],
},
},
}}
>
<Tasks />
Expand Down
23 changes: 12 additions & 11 deletions pages/accountLists/[accountListId]/tasks/[[...contactId]].page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,18 +184,19 @@ const TasksPage: React.FC = () => {

//#region Mass Actions

const taskCount = data?.tasks.totalCount ?? 0;
const { data: allTasks } = useGetTaskIdsForMassSelectionQuery({
variables: {
accountListId,
first: taskCount,
tasksFilter,
},
skip: taskCount === 0,
});
const { data: allTasks, previousData: allTasksPrevious } =
useGetTaskIdsForMassSelectionQuery({
variables: {
accountListId,
tasksFilter,
},
});
// When the next batch of task ids is loading, use the previous batch of task ids in the
// meantime to avoid throwing out the selected task ids.
const allTaskIds = useMemo(
() => allTasks?.tasks.nodes.map((task) => task.id) ?? [],
[allTasks],
() =>
(allTasks ?? allTasksPrevious)?.tasks.nodes.map((task) => task.id) ?? [],
[allTasks, allTasksPrevious],
);

const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,19 @@ export const ContactTasksTab: React.FC<ContactTasksTabProps> = ({
[starredFilter, searchTerm],
);
const taskCount = data?.tasks.totalCount ?? 0;
const { data: allTasks } = useGetTaskIdsForMassSelectionQuery({
variables: {
accountListId,
first: taskCount,
tasksFilter,
},
skip: taskCount === 0,
});
const { data: allTasks, previousData: allTasksPrevious } =
useGetTaskIdsForMassSelectionQuery({
variables: {
accountListId,
tasksFilter,
},
});
// When the next batch of task ids is loading, use the previous batch of task ids in the
// meantime to avoid throwing out the selected task ids.
const allTaskIds = useMemo(
() => allTasks?.tasks.nodes.map((task) => task.id) ?? [],
[allTasks],
() =>
(allTasks ?? allTasksPrevious)?.tasks.nodes.map((task) => task.id) ?? [],
[allTasks, allTasksPrevious],
);
//#region Mass Actions
const {
Expand Down
25 changes: 14 additions & 11 deletions src/components/Contacts/ContactsContext/ContactsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -186,18 +186,21 @@ export const ContactsProvider: React.FC<ContactsContextProps> = ({

//#region Mass Actions

const contactCount = data?.contacts.totalCount ?? 0;
const { data: allContacts } = useGetIdsForMassSelectionQuery({
variables: {
accountListId,
first: contactCount,
contactsFilters,
},
skip: contactCount === 0,
});
const { data: allContacts, previousData: allContactsPrevious } =
useGetIdsForMassSelectionQuery({
variables: {
accountListId,
contactsFilters,
},
});
// When the next batch of contact ids is loading, use the previous batch of contact ids in the
// meantime to avoid throwing out the selected contact ids.
const allContactIds = useMemo(
() => allContacts?.contacts.nodes.map((contact) => contact.id) ?? [],
[allContacts],
() =>
(allContacts ?? allContactsPrevious)?.contacts.nodes.map(
(contact) => contact.id,
) ?? [],
[allContacts, allContactsPrevious],
);

const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,26 +88,28 @@ export const PartnerGivingAnalysisReport = forwardRef<
? Object.keys(activeFilters).length > 0
: false;

const { data, loading } = useGetPartnerGivingAnalysisReportQuery({
variables: {
input: {
accountListId,
// Page 1 is the first page for the API
page: page + 1,
pageSize: limit,
sortField: orderBy ?? '',
sortDirection:
order === 'asc'
? SortDirection.Ascending
: SortDirection.Descending,
contactFilters,
const { data, previousData, loading } =
useGetPartnerGivingAnalysisReportQuery({
variables: {
input: {
accountListId,
// Page 1 is the first page for the API
page: page + 1,
pageSize: limit,
sortField: orderBy ?? '',
sortDirection:
order === 'asc'
? SortDirection.Ascending
: SortDirection.Descending,
contactFilters,
},
},
},
});
});
const contacts = data?.partnerGivingAnalysisReport.contacts ?? [];

const contactCount = data?.partnerGivingAnalysisReport?.totalContacts ?? 0;
const { data: allContacts } =
const contactCount =
(data ?? previousData)?.partnerGivingAnalysisReport?.totalContacts ?? 0;
const { data: allContacts, previousData: allContactsPrevious } =
useGetPartnerGivingAnalysisIdsForMassSelectionQuery({
variables: {
input: {
Expand All @@ -121,12 +123,15 @@ export const PartnerGivingAnalysisReport = forwardRef<
},
skip: contactCount === 0,
});
// When the next batch of contact ids is loading, use the previous batch of contact ids in the
// meantime to avoid throwing out the selected contact ids.
const allContactIds = useMemo(
() =>
allContacts?.partnerGivingAnalysisReport?.contacts.map(
(contact) => contact.id,
) ?? [],
[allContacts],
(
allContacts ?? allContactsPrevious
)?.partnerGivingAnalysisReport?.contacts.map((contact) => contact.id) ??
[],
[allContacts, allContactsPrevious],
);

const {
Expand Down
39 changes: 23 additions & 16 deletions src/components/Tool/Appeal/AppealsContext/AppealsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,38 +173,45 @@ export const AppealsProvider: React.FC<AppealsContextProps> = ({
},
skip: !accountListId,
});
const { data } = contactsQueryResult;

//#region Mass Actions

const contactCount = data?.contacts.totalCount ?? 0;
const { data: allContacts } = useGetIdsForMassSelectionQuery({
variables: {
accountListId,
first: contactCount,
contactsFilters,
},
skip: contactCount === 0,
});
const { data: allContacts, previousData: allContactsPrevious } =
useGetIdsForMassSelectionQuery({
variables: {
accountListId,
contactsFilters,
},
});
// In the flows view, we need the total count of all contacts in every column, but the API
// filters out contacts excluded from an appeal. We have to load excluded contacts also and
// manually merge them with the other contacts.
const { data: allExcludedContacts } = useGetIdsForMassSelectionQuery({
const {
data: allExcludedContacts,
previousData: allExcludedContactsPrevious,
} = useGetIdsForMassSelectionQuery({
variables: {
accountListId,
first: contactCount,
contactsFilters: { ...contactsFilters, appealStatus: 'excluded' },
},
// Skip this query when there is an appealStatus filter from the list view
skip: contactCount === 0 || !!contactsFilters.appealStatus,
skip: !!contactsFilters.appealStatus,
});
// When the next batch of contact ids is loading, use the previous batch of contact ids in the
// meantime to avoid throwing out the selected contact ids.
const allContactIds = useMemo(
() =>
[
...(allContacts?.contacts.nodes ?? []),
...(allExcludedContacts?.contacts.nodes ?? []),
...((allContacts ?? allContactsPrevious)?.contacts.nodes ?? []),
...((allExcludedContacts ?? allExcludedContactsPrevious)?.contacts
.nodes ?? []),
].map((contact) => contact.id),
[allContacts, allExcludedContacts],
[
allContacts,
allContactsPrevious,
allExcludedContacts,
allExcludedContactsPrevious,
],
);

const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,21 @@ export const ContactFlowColumn: React.FC<Props> = ({
skip: !accountListId || !appealStatus,
});

const contactCount = data?.contacts.totalCount ?? 0;
const { data: allContacts } = useGetIdsForMassSelectionQuery({
variables: {
accountListId,
first: contactCount,
contactsFilters,
},
skip: contactCount === 0,
});

const { data: allContacts, previousData: allContactsPrevious } =
useGetIdsForMassSelectionQuery({
variables: {
accountListId,
contactsFilters,
},
});
// When the next batch of contact ids is loading, use the previous batch of contact ids in the
// meantime to avoid throwing out the selected contact ids.
const allContactIds = useMemo(
() => allContacts?.contacts.nodes.map((contact) => contact.id) ?? [],
[allContacts],
() =>
(allContacts ?? allContactsPrevious)?.contacts.nodes.map(
(contact) => contact.id,
) ?? [],
[allContacts, allContactsPrevious],
);

const { data: excludedContacts } = useExcludedAppealContactsQuery({
Expand Down
6 changes: 2 additions & 4 deletions src/hooks/GetIdsForMassSelection.graphql
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
query GetIdsForMassSelection(
$accountListId: ID!
$first: Int!
$contactsFilters: ContactFilterSetInput
) {
contacts(
accountListId: $accountListId
first: $first
contactsFilter: $contactsFilters
first: 20000 # Maximum allowed by the API
) {
nodes {
id
Expand All @@ -16,13 +15,12 @@ query GetIdsForMassSelection(

query GetTaskIdsForMassSelection(
$accountListId: ID!
$first: Int!
$tasksFilter: TaskFilterSetInput
) {
tasks(
accountListId: $accountListId
first: $first
tasksFilter: $tasksFilter
first: 1000 # Maximum allowed by the API
) {
nodes {
id
Expand Down
16 changes: 15 additions & 1 deletion src/hooks/useMassSelection.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { renderHook } from '@testing-library/react';
import { ListHeaderCheckBoxState } from 'src/components/Shared/Header/ListHeader';
import { useMassSelection } from './useMassSelection';
import { UseMassSelectionResult, useMassSelection } from './useMassSelection';

const defaultIdsList = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'];

Expand Down Expand Up @@ -117,4 +117,18 @@ describe('useMassSelection', () => {
expect(result.current.ids).toEqual(['1', '2', '3', '7', '8', '9', '10']);
});
});

it('deselects removed ids', () => {
const { result, rerender } = renderHook<
UseMassSelectionResult,
{ ids: string[] }
>(({ ids }) => useMassSelection(ids), {
initialProps: { ids: defaultIdsList },
});

result.current.selectMultipleIds(['1', '2', '3']);

rerender({ ids: ['2', '3', '4'] });
expect(result.current.ids).toEqual(['2', '3']);
});
});
Loading

0 comments on commit ada0000

Please sign in to comment.