Skip to content

Commit

Permalink
Remove member count and user search from group settings UI
Browse files Browse the repository at this point in the history
We decided to remove these features for the moment because we plan to introduce
pagination first, which would require implementing the sorting/counting logic
server-side. To simplify the initial implementation of pagination, these
features won't be included.
  • Loading branch information
robertknight committed Nov 28, 2024
1 parent 1633fc7 commit 0d82af0
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 98 deletions.
54 changes: 3 additions & 51 deletions h/static/scripts/group-forms/components/EditGroupMembersForm.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { DataTable, Input, Scroll } from '@hypothesis/frontend-shared';
import { useContext, useEffect, useMemo, useState } from 'preact/hooks';
import { DataTable, Scroll } from '@hypothesis/frontend-shared';
import { useContext, useEffect, useState } from 'preact/hooks';

import { Config } from '../config';
import type { APIConfig, Group } from '../config';
import ErrorNotice from './ErrorNotice';
import FormContainer from './forms/FormContainer';
import type { GroupMembersResponse } from '../utils/api';
import { callAPI } from '../utils/api';
import { pluralize } from '../utils/pluralize';
import GroupFormHeader from './GroupFormHeader';

type MemberRow = {
Expand Down Expand Up @@ -66,8 +65,6 @@ export default function EditGroupMembersForm({
},
];

const [filter, setFilter] = useState('');

const renderRow = (user: MemberRow, field: keyof MemberRow) => {
switch (field) {
case 'username':
Expand All @@ -86,62 +83,17 @@ export default function EditGroupMembersForm({
}
};

const memberText = pluralize(members?.length ?? 0, 'member', 'members');

const filteredMembers = useMemo(() => {
if (!filter || !members) {
return members;
}

const normalizedFilter = filter.toLowerCase();

// nb. We can get away with lower-casing name and filter to do
// case-insensitive search because of the character set restrictions on
// usernames. This would be incorrect for Unicode text.
return members.filter(m =>
m.username.toLowerCase().includes(normalizedFilter),
);
}, [filter, members]);

let emptyMessage;
if (members !== null && members.length > 0 && filter) {
emptyMessage = (
<div data-testid="no-filter-match">
No members match the filter {'"'}
<b>{filter}</b>
{'"'}
</div>
);
}

return (
<FormContainer title="Edit group members">
<GroupFormHeader group={group} />
<hr />
<div className="flex py-3 items-center">
{/* Input has `w-full` style. Wrap in container to stop it stretching to full width of row. */}
<div>
<Input
aria-label="Search members"
data-testid="search-input"
placeholder="Search…"
onInput={e => setFilter((e.target as HTMLInputElement).value)}
/>
</div>
<div className="grow" />
<div data-testid="member-count">
{members?.length ?? '...'} {memberText}
</div>
</div>
<ErrorNotice message={errorMessage} />
<div className="w-full">
<Scroll>
<DataTable
title="Group members"
rows={filteredMembers ?? []}
rows={members ?? []}
columns={columns}
renderItem={renderRow}
emptyMessage={emptyMessage}
/>
</Scroll>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,6 @@ describe('EditGroupMembersForm', () => {
return wrapper.find('[data-testid="username"]').map(node => node.text());
};

const enterFilterValue = (wrapper, value) => {
const filter = wrapper.find('input[data-testid="search-input"]');
filter.getDOMNode().value = value;
filter.simulate('input');
};

it('fetches and displays members', async () => {
const wrapper = createForm();
assert.calledWith(
Expand All @@ -88,20 +82,6 @@ describe('EditGroupMembersForm', () => {
assert.deepEqual(users, ['bob', 'johnsmith']);
});

it('displays member count', async () => {
fakeCallAPI.withArgs('/api/groups/1234/members').resolves([
{
username: 'bob',
},
]);
const wrapper = createForm();
const memberCount = wrapper.find('[data-testid="member-count"]');
assert.equal(memberCount.text(), '... members');

await waitForTable(wrapper);
assert.equal(memberCount.text(), '1 member');
});

it('displays error if member fetch fails', async () => {
fakeCallAPI
.withArgs('/api/groups/1234/members')
Expand All @@ -123,31 +103,4 @@ describe('EditGroupMembersForm', () => {
// Unmount while fetching. This should abort the request.
wrapper.unmount();
});

it('filters members', async () => {
const wrapper = createForm();
await waitForTable(wrapper);

// Filter should remove non-matching users
enterFilterValue(wrapper, 'john');
const users = getRenderedUsers(wrapper);
assert.deepEqual(users, ['johnsmith']);

// Filter should match anywhere in username
enterFilterValue(wrapper, 'smith');
const users2 = getRenderedUsers(wrapper);
assert.deepEqual(users2, ['johnsmith']);

// Filter should be case-insensitive
enterFilterValue(wrapper, 'BOB');
const users3 = getRenderedUsers(wrapper);
assert.deepEqual(users3, ['bob']);
});

it('displays message if filter does not match any members', async () => {
const wrapper = createForm();
await waitForTable(wrapper);
enterFilterValue(wrapper, 'no-match');
assert.isTrue(wrapper.exists('[data-testid="no-filter-match"]'));
});
});

0 comments on commit 0d82af0

Please sign in to comment.