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

feat: Add filtering and sorting on userTag screens (GSoC) #2398

Merged
Merged
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
66e1af2
add people to tag functaionality
meetulr Oct 25, 2024
edb8360
minor change
meetulr Oct 25, 2024
689ad90
more translations
meetulr Oct 25, 2024
abaf86e
minor change
meetulr Oct 26, 2024
7b7b6bf
add a variable for page size
meetulr Oct 26, 2024
72b6fd3
add tag actions
meetulr Oct 26, 2024
3b97043
add tests
meetulr Oct 26, 2024
6c13484
translations
meetulr Oct 26, 2024
76f5fbe
change to infinite scroll
meetulr Oct 27, 2024
d022c8d
add subtags infinite scroll
meetulr Oct 27, 2024
27227a9
Merge branch 'tagActions' into changeToInfiniteScroll
meetulr Oct 27, 2024
d11a6ee
extract common variables to utils
meetulr Oct 27, 2024
01b4b65
minor correction
meetulr Oct 27, 2024
c882dd6
Merge branch 'tagActions' into changeToInfiniteScroll
meetulr Oct 27, 2024
ba59202
more design adjustments
meetulr Oct 27, 2024
a59da70
add tests
meetulr Oct 27, 2024
f773005
add scrollbar for infinite scroll
meetulr Oct 27, 2024
e42b8fe
extract infinite scroll loader
meetulr Oct 27, 2024
ab3310a
minor adjustment
meetulr Oct 27, 2024
b223e21
refactoring
meetulr Oct 27, 2024
1b4b913
Merge branch 'develop' of https://github.com/PalisadoesFoundation/tal…
meetulr Oct 27, 2024
a8bca91
exclude ManageTag from countline check
meetulr Oct 27, 2024
58af286
fix linting
meetulr Oct 27, 2024
59f5e03
fix linting
meetulr Oct 27, 2024
879ef42
fix linting
meetulr Oct 27, 2024
6a79d51
make coderabbit suggested changes
meetulr Oct 28, 2024
9bc25d7
more changes
meetulr Oct 28, 2024
926f766
more changes
meetulr Oct 28, 2024
d3e91ac
minor correction
meetulr Oct 28, 2024
2a49ea0
add error component for tagNode subtags query
meetulr Oct 28, 2024
052aead
fix translation
meetulr Oct 28, 2024
d8d657a
fix translation
meetulr Oct 28, 2024
e9a86f8
Merge branch 'tagActions' into refactoringAndDesignAdjustments
meetulr Oct 28, 2024
4ae2507
remove unused css classes
meetulr Oct 28, 2024
ffbdffc
refactor ManageTag file to reduce its size
meetulr Oct 30, 2024
f4c7814
update pull-request check
meetulr Oct 30, 2024
95a1138
minor adjustments
meetulr Oct 30, 2024
4efe79e
minor correction
meetulr Oct 30, 2024
bbab01c
Merge branch 'develop' of https://github.com/PalisadoesFoundation/tal…
meetulr Oct 30, 2024
6f65f9f
minor change
meetulr Oct 30, 2024
eb5b7ea
correction
meetulr Oct 30, 2024
ee1cf2d
minor changes
meetulr Oct 30, 2024
5ac6cbe
minor change
meetulr Oct 30, 2024
9626c68
coderabbitai changes
meetulr Oct 30, 2024
9be6fa8
more changes
meetulr Oct 30, 2024
63febd0
fix dataGrid classes
meetulr Oct 30, 2024
cec740b
remove getUserTagAncestors query
meetulr Nov 1, 2024
b96e7e4
add search and sort
meetulr Nov 1, 2024
12793a1
add tests
meetulr Nov 1, 2024
cc56edf
error toast on no seletion tag/user
meetulr Nov 1, 2024
3742f1d
minor correction
meetulr Nov 1, 2024
ae1afea
fix test
meetulr Nov 1, 2024
7feb527
merge with upstream/develop
meetulr Nov 1, 2024
ba50762
minor change
meetulr Nov 2, 2024
cbe81df
add useEffect
meetulr Nov 2, 2024
23fea57
exclude TagActionsMocks from countlines check
meetulr Nov 2, 2024
3d801ca
coderabbitai suggested changes
meetulr Nov 2, 2024
5085b7f
show sort order
meetulr Nov 2, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- name: Count number of lines
run: |
chmod +x ./.github/workflows/countline.py
./.github/workflows/countline.py --lines 600 --exclude_files src/screens/LoginPage/LoginPage.tsx src/GraphQl/Queries/Queries.ts src/screens/OrgList/OrgList.tsx src/GraphQl/Mutations/mutations.ts src/components/EventListCard/EventListCardModals.tsx
./.github/workflows/countline.py --lines 600 --exclude_files src/screens/LoginPage/LoginPage.tsx src/GraphQl/Queries/Queries.ts src/screens/OrgList/OrgList.tsx src/GraphQl/Mutations/mutations.ts src/components/EventListCard/EventListCardModals.tsx src/components/TagActions/TagActionsMocks.ts

- name: Get changed TypeScript files
id: changed-files
Expand Down
3 changes: 2 additions & 1 deletion public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@
"noTagsFound": "No tags found",
"removeUserTag": "Delete Tag",
"removeUserTagMessage": "Do you want to delete this tag?",
"addChildTag": "Add a Sub Tag"
"addChildTag": "Add a Sub Tag",
"enterTagName": "Enter Tag Name"
},
"manageTag": {
"title": "Tag Details",
Expand Down
3 changes: 2 additions & 1 deletion public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@
"noTagsFound": "Aucune étiquette trouvée",
"removeUserTag": "Supprimer l'Étiquette",
"removeUserTagMessage": "Voulez-vous supprimer cette étiquette ?",
"addChildTag": "Ajouter une Sous-Étiquette"
"addChildTag": "Ajouter une Sous-Étiquette",
"enterTagName": "Entrez le nom du étiquette"
meetulr marked this conversation as resolved.
Show resolved Hide resolved
},
"manageTag": {
"title": "Détails de l'étiquette",
Expand Down
3 changes: 2 additions & 1 deletion public/locales/hi/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@
"noTagsFound": "कोई टैग नहीं मिला",
"removeUserTag": "टैग हटाएँ",
"removeUserTagMessage": "क्या आप इस टैग को हटाना चाहते हैं?",
"addChildTag": "उप-टैग जोड़ें"
"addChildTag": "उप-टैग जोड़ें",
"enterTagName": "टैग का नाम दर्ज करें"
},
"manageTag": {
"title": "टैग विवरण",
Expand Down
3 changes: 2 additions & 1 deletion public/locales/sp/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@
"noTagsFound": "No se encontraron etiquetas",
"removeUserTag": "Eliminar Etiqueta",
"removeUserTagMessage": "¿Desea eliminar esta etiqueta?",
"addChildTag": "Agregar una Sub Etiqueta"
"addChildTag": "Agregar una Sub Etiqueta",
"enterTagName": "Ingrese el nombre de la etiqueta"
},
"manageTag": {
"title": "Detalles de la Etiqueta",
Expand Down
3 changes: 2 additions & 1 deletion public/locales/zh/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@
"noTagsFound": "未找到标签",
"removeUserTag": "删除标签",
"removeUserTagMessage": "您确定要删除此标签吗?",
"addChildTag": "添加子标签"
"addChildTag": "添加子标签",
"enterTagName": "输入标签名称"
},
"manageTag": {
"title": "标签详情",
Expand Down
18 changes: 17 additions & 1 deletion src/GraphQl/Queries/OrganizationQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,35 @@ export const ORGANIZATION_USER_TAGS_LIST = gql`
$before: String
$first: PositiveInt
$last: PositiveInt
$where: UserTagWhereInput
$sortedBy: UserTagSortedByInput
) {
organizations(id: $id) {
userTags(after: $after, before: $before, first: $first, last: $last) {
userTags(
after: $after
before: $before
first: $first
last: $last
where: $where
sortedBy: $sortedBy
) {
edges {
node {
_id
name
parentTag {
_id
}
usersAssignedTo(first: $first, last: $last) {
totalCount
}
childTags(first: $first, last: $last) {
totalCount
}
ancestorTags {
_id
name
}
}
cursor
}
Expand Down
45 changes: 28 additions & 17 deletions src/GraphQl/Queries/userTagQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export const USER_TAGS_ASSIGNED_MEMBERS = gql`
$before: String
$first: PositiveInt
$last: PositiveInt
$where: UserTagUsersAssignedToWhereInput
$sortedBy: UserTagUsersAssignedToSortedByInput
) {
getAssignedUsers: getUserTag(id: $id) {
name
Expand All @@ -22,6 +24,8 @@ export const USER_TAGS_ASSIGNED_MEMBERS = gql`
before: $before
first: $first
last: $last
where: $where
sortedBy: $sortedBy
) {
edges {
node {
Expand All @@ -38,6 +42,10 @@ export const USER_TAGS_ASSIGNED_MEMBERS = gql`
}
totalCount
}
ancestorTags {
_id
name
}
}
}
`;
Expand All @@ -56,10 +64,19 @@ export const USER_TAG_SUB_TAGS = gql`
$before: String
$first: PositiveInt
$last: PositiveInt
$where: UserTagWhereInput
$sortedBy: UserTagSortedByInput
) {
getChildTags: getUserTag(id: $id) {
name
childTags(after: $after, before: $before, first: $first, last: $last) {
childTags(
after: $after
before: $before
first: $first
last: $last
where: $where
sortedBy: $sortedBy
) {
edges {
node {
_id
Expand All @@ -70,6 +87,10 @@ export const USER_TAG_SUB_TAGS = gql`
childTags(first: $first, last: $last) {
totalCount
}
ancestorTags {
_id
name
}
}
}
pageInfo {
Expand All @@ -80,6 +101,10 @@ export const USER_TAG_SUB_TAGS = gql`
}
totalCount
}
ancestorTags {
_id
name
}
}
}
`;
Expand All @@ -98,6 +123,7 @@ export const USER_TAGS_MEMBERS_TO_ASSIGN_TO = gql`
$before: String
$first: PositiveInt
$last: PositiveInt
$where: UserTagUsersToAssignToWhereInput
meetulr marked this conversation as resolved.
Show resolved Hide resolved
) {
getUsersToAssignTo: getUserTag(id: $id) {
name
Expand All @@ -106,6 +132,7 @@ export const USER_TAGS_MEMBERS_TO_ASSIGN_TO = gql`
before: $before
first: $first
last: $last
where: $where
) {
edges {
node {
Expand All @@ -125,19 +152,3 @@ export const USER_TAGS_MEMBERS_TO_ASSIGN_TO = gql`
}
}
`;

/**
* GraphQL query to retrieve the ancestor tags of a certain tag.
*
* @param id - The ID of the current tag.
* @returns The list of ancestor tags.
*/

export const USER_TAG_ANCESTORS = gql`
query GetUserTagAncestors($id: ID!) {
getUserTagAncestors(id: $id) {
_id
name
}
}
`;
9 changes: 8 additions & 1 deletion src/components/AddPeopleToTag/AddPeopleToTag.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
}

.scrollContainer {
max-height: 100px;
height: 100px;
overflow-y: auto;
margin-bottom: 1rem;
}
Expand All @@ -45,3 +45,10 @@
.removeFilterIcon {
cursor: pointer;
}

.loadingDiv {
min-height: 300px;
display: flex;
justify-content: center;
align-items: center;
}
117 changes: 111 additions & 6 deletions src/components/AddPeopleToTag/AddPeopleToTag.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { store } from 'state/store';
import userEvent from '@testing-library/user-event';
import { StaticMockLink } from 'utils/StaticMockLink';
import { toast } from 'react-toastify';
import type { ApolloLink } from '@apollo/client';
import { InMemoryCache, type ApolloLink } from '@apollo/client';
import type { InterfaceAddPeopleToTagProps } from './AddPeopleToTag';
import AddPeopleToTag from './AddPeopleToTag';
import i18n from 'utils/i18nForTest';
Expand Down Expand Up @@ -63,12 +63,39 @@ const props: InterfaceAddPeopleToTagProps = {
>,
};

const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
getUserTag: {
merge(existing = {}, incoming) {
const merged = {
...existing,
...incoming,
usersToAssignTo: {
...existing.usersToAssignTo,
...incoming.usersToAssignTo,
edges: [
...(existing.usersToAssignTo?.edges || []),
...(incoming.usersToAssignTo?.edges || []),
],
},
};

return merged;
},
},
},
},
},
});

const renderAddPeopleToTagModal = (
props: InterfaceAddPeopleToTagProps,
link: ApolloLink,
): RenderResult => {
return render(
<MockedProvider addTypename={false} link={link}>
<MockedProvider cache={cache} addTypename={false} link={link}>
<MemoryRouter initialEntries={['/orgtags/123/manageTag/1']}>
<Provider store={store}>
<I18nextProvider i18n={i18n}>
Expand All @@ -91,7 +118,7 @@ describe('Organisation Tags Page', () => {
...jest.requireActual('react-router-dom'),
useParams: () => ({ orgId: 'orgId' }),
}));
// cache.reset();
cache.reset();
});

afterEach(() => {
Expand Down Expand Up @@ -147,6 +174,72 @@ describe('Organisation Tags Page', () => {
userEvent.click(screen.getAllByTestId('deselectMemberBtn')[0]);
});

test('searchs for tags where the firstName matches the provided firstName search input', async () => {
renderAddPeopleToTagModal(props, link);

await wait();

await waitFor(() => {
expect(
screen.getByPlaceholderText(translations.firstName),
).toBeInTheDocument();
});
const input = screen.getByPlaceholderText(translations.firstName);
fireEvent.change(input, { target: { value: 'usersToAssignTo' } });

// should render the two users from the mock data
// where firstName starts with "usersToAssignTo"
await waitFor(() => {
const members = screen.getAllByTestId('memberName');
expect(members.length).toEqual(2);
});

await waitFor(() => {
expect(screen.getAllByTestId('memberName')[0]).toHaveTextContent(
'usersToAssignTo user1',
);
});

await waitFor(() => {
expect(screen.getAllByTestId('memberName')[1]).toHaveTextContent(
'usersToAssignTo user2',
);
});
});

test('searchs for tags where the lastName matches the provided lastName search input', async () => {
renderAddPeopleToTagModal(props, link);

await wait();

await waitFor(() => {
expect(
screen.getByPlaceholderText(translations.lastName),
).toBeInTheDocument();
});
const input = screen.getByPlaceholderText(translations.lastName);
fireEvent.change(input, { target: { value: 'userToAssignTo' } });

// should render the two users from the mock data
// where lastName starts with "usersToAssignTo"
await waitFor(() => {
const members = screen.getAllByTestId('memberName');
expect(members.length).toEqual(2);
});

await waitFor(() => {
expect(screen.getAllByTestId('memberName')[0]).toHaveTextContent(
'first userToAssignTo',
);
});

await waitFor(() => {
expect(screen.getAllByTestId('memberName')[1]).toHaveTextContent(
'second userToAssignTo',
);
});
});
meetulr marked this conversation as resolved.
Show resolved Hide resolved

test('Renders more members with infinite scroll', async () => {
const { getByText } = renderAddPeopleToTagModal(props, link);

Expand All @@ -157,13 +250,15 @@ describe('Organisation Tags Page', () => {
});

// Find the infinite scroll div by test ID or another selector
const scrollableDiv = screen.getByTestId('scrollableDiv');
const addPeopleToTagScrollableDiv = screen.getByTestId(
'addPeopleToTagScrollableDiv',
);

const initialMemberDataLength = screen.getAllByTestId('memberName').length;

// Set scroll position to the bottom
fireEvent.scroll(scrollableDiv, {
target: { scrollY: scrollableDiv.scrollHeight },
fireEvent.scroll(addPeopleToTagScrollableDiv, {
target: { scrollY: addPeopleToTagScrollableDiv.scrollHeight },
meetulr marked this conversation as resolved.
Show resolved Hide resolved
});

await waitFor(() => {
Expand All @@ -179,6 +274,16 @@ describe('Organisation Tags Page', () => {

await wait();

// gives error if no user is selected
await waitFor(() => {
expect(screen.getByTestId('assignPeopleBtn')).toBeInTheDocument();
});
userEvent.click(screen.getByTestId('assignPeopleBtn'));

await waitFor(() => {
expect(toast.error).toHaveBeenCalledWith(translations.noOneSelected);
});
meetulr marked this conversation as resolved.
Show resolved Hide resolved

await waitFor(() => {
expect(screen.getAllByTestId('selectMemberBtn')[0]).toBeInTheDocument();
});
Expand Down
Loading
Loading