Skip to content

Commit dffd95c

Browse files
Merge pull request #7020 from hotosm/feat/order-project-contribution
Enable sorting contributors list by mapped, validated, and combined tasks
2 parents 21bd7e2 + 32b0288 commit dffd95c

File tree

3 files changed

+54
-5
lines changed

3 files changed

+54
-5
lines changed

frontend/src/components/taskSelection/contributions.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,47 @@ export const MappingLevelIcon = ({ mappingLevel }) => {
4242
return null;
4343
};
4444

45+
const sortByLits = [
46+
{
47+
sortId: 'mapped',
48+
tooltipMessage: 'Sort by total number of mapped task',
49+
icon: <MappedIcon className="h1 w1 blue-grey" />,
50+
},
51+
{
52+
sortId: 'validated',
53+
tooltipMessage: 'Sort by total number of validated task',
54+
icon: <ValidatedIcon className="h1 w1 blue-grey" />,
55+
},
56+
{
57+
sortId: 'total',
58+
tooltipMessage: 'Sort by total number of mapped and validated (both combined) tasks',
59+
icon: <AsteriskIcon className="h1 w1 blue-grey" />,
60+
},
61+
];
62+
63+
const SortingHeader = ({ sortBy, setSortBy }: Object) => {
64+
return (
65+
<div className="flex justify-end items-center">
66+
{sortByLits?.map((sortByItem) => (
67+
<div
68+
key={sortByItem.sortId}
69+
className="w-20 fl tr dib truncate"
70+
title={sortByItem.tooltipMessage}
71+
>
72+
<button
73+
className={`bn dib pt2 mr4 pointer ph2 pv2 hover-bg-black-10 br3 ${
74+
sortBy === sortByItem?.sortId ? 'bg-black-10' : 'bg-transparent'
75+
}`}
76+
onClick={() => setSortBy(sortByItem?.sortId)}
77+
>
78+
{sortByItem?.icon}
79+
</button>
80+
</div>
81+
))}
82+
</div>
83+
);
84+
};
85+
4586
function Contributor({ user, activeUser, activeStatus, displayTasks }: Object) {
4687
const intl = useIntl();
4788
const checkActiveUserAndStatus = (status, username) =>
@@ -132,12 +173,14 @@ const Contributions = ({ project, tasks, contribsData, activeUser, activeStatus,
132173
};
133174
const [level, setLevel] = useState(mappingLevels[0]);
134175
const [userFilter, setUserFilter] = useState(defaultUserFilter);
176+
const [sortBy, setSortBy] = useState('total');
135177
const { percentMapped, percentValidated, percentBadImagery } = useComputeCompleteness(tasks);
136178

137179
const contributors = useFilterContributors(
138180
contribsData || [],
139181
level && level.value,
140182
userFilter && userFilter.value,
183+
sortBy,
141184
);
142185

143186
const displayTasks = (taskIds, status, user) => {
@@ -194,6 +237,7 @@ const Contributions = ({ project, tasks, contribsData, activeUser, activeStatus,
194237
delay={50}
195238
ready={contributors !== undefined}
196239
>
240+
<SortingHeader sortBy={sortBy} setSortBy={setSortBy} />
197241
{contributors.map((user, k) => (
198242
<Contributor
199243
user={user}

frontend/src/components/taskSelection/tests/contributions.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ describe('Contributions', () => {
3636
expect(screen.getAllByRole('link')[1].href).toBe('https://osmcha.org/?aoi=abc1234');
3737
// clicking on the number of tasks trigger selectTask
3838
await user.click(screen.getAllByText('5')[0]);
39-
expect(selectTask).toHaveBeenLastCalledWith([1, 3, 5, 7], 'ALL', 'test');
39+
expect(selectTask).toHaveBeenLastCalledWith([5, 36, 99, 115,142], 'MAPPED', 'test_1');
4040
await user.click(screen.getAllByText('5')[1]);
41-
expect(selectTask).toHaveBeenLastCalledWith([5, 36, 99, 115, 142], 'MAPPED', 'test_1');
41+
expect(selectTask).toHaveBeenLastCalledWith([1, 3, 5, 7], 'ALL', 'test');
4242
// filter ADVANCED users
4343
await selectEvent.select(container.querySelectorAll('input')[0], 'Advanced');
4444
expect(screen.queryByText('user_3')).not.toBeInTheDocument();
@@ -80,6 +80,6 @@ describe('Contributions', () => {
8080
);
8181
expect(container.querySelector('div.b--blue-dark')).toBeInTheDocument();
8282
await user.click(screen.getAllByText('5')[1]);
83-
expect(selectTask).toHaveBeenLastCalledWith([]);
83+
expect(selectTask).toHaveBeenLastCalledWith([1, 3, 5, 7], 'ALL', 'test');
8484
});
8585
});

frontend/src/hooks/UseFilterContributors.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
22

33
import { getPastMonths } from '../utils/date';
44

5-
export function useFilterContributors(contributors, level, username) {
5+
export function useFilterContributors(contributors, level, username, sortBy) {
66
const [filteredContributors, setFilter] = useState([]);
77

88
useEffect(() => {
@@ -19,7 +19,12 @@ export function useFilterContributors(contributors, level, username) {
1919
if (username) {
2020
users = users.filter((user) => user.username === username);
2121
}
22+
if (sortBy && users?.length) {
23+
users = [...users]?.sort((a, b) => b?.[sortBy] - a?.[sortBy]);
24+
}
25+
2226
setFilter(users);
23-
}, [contributors, level, username]);
27+
}, [contributors, level, username, sortBy]);
28+
2429
return filteredContributors;
2530
}

0 commit comments

Comments
 (0)