Commit 9c48fa19 authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Add group type icons to groups menu

parent 35a67ebf
......@@ -161,7 +161,7 @@ function GroupList({ settings }: GroupListProps) {
<MenuItem
icon={PlusIcon}
href={newGroupLink}
label="New private group"
label="Create new group"
/>
)}
</Menu>
......
......@@ -2,11 +2,14 @@ import {
confirm,
CopyIcon,
ExternalIcon,
GlobeAltIcon,
GlobeAltLockIcon,
LeaveIcon,
LockIcon,
} from '@hypothesis/frontend-shared';
import classnames from 'classnames';
import type { Group } from '../../../types/api';
import type { Group, GroupType } from '../../../types/api';
import { orgName } from '../../helpers/group-list-item-common';
import { withServices } from '../../service-context';
import type { GroupsService } from '../../services/groups';
......@@ -15,6 +18,27 @@ import { useSidebarStore } from '../../store';
import { copyPlainText } from '../../util/copy-to-clipboard';
import MenuItem from '../MenuItem';
function GroupIcon({ type }: { type: GroupType }) {
const title =
type === 'open'
? 'Public group'
: type === 'restricted'
? 'Restricted group'
: 'Private group';
return (
<div
className="text-color-text-light"
title={title}
data-testid="group-icon"
>
{type === 'open' && <GlobeAltIcon />}
{type === 'restricted' && <GlobeAltLockIcon />}
{type === 'private' && <LockIcon />}
</div>
);
}
export type GroupListItemProps = {
group: Group;
......@@ -103,7 +127,12 @@ function GroupListItem({
isExpanded={hasActionMenu ? isExpanded : false}
isSelected={isSelected}
isSubmenuVisible={hasActionMenu ? isExpanded : undefined}
label={group.name}
label={
<div className="grow flex items-center justify-between gap-x-2">
{group.name}
<GroupIcon type={group.type} />
</div>
}
leftChannelContent={leftChannelContent}
onClick={isSelectable ? focusGroup : toggleSubmenu}
onToggleSubmenu={toggleSubmenu}
......
......@@ -151,23 +151,21 @@ describe('GroupList', () => {
expectNewGroupButton: false,
},
].forEach(({ userid, expectNewGroupButton }) => {
it('displays "New private group" button if user is logged in with first-party account', () => {
it('displays "Create new group" button if user is logged in with first-party account', () => {
fakeStore.profile.returns({ userid });
const wrapper = createGroupList();
const newGroupButton = wrapper.find(
'MenuItem[label="New private group"]',
);
const newGroupButton = wrapper.find('MenuItem[label="Create new group"]');
assert.equal(newGroupButton.length, expectNewGroupButton ? 1 : 0);
});
});
it('opens new window at correct URL when "New private group" is clicked', () => {
it('opens new window at correct URL when "Create new group" is clicked', () => {
fakeStore.getLink
.withArgs('groups.new')
.returns('https://example.com/groups/new');
fakeStore.profile.returns({ userid: 'jsmith@hypothes.is' });
const wrapper = createGroupList();
const newGroupButton = wrapper.find('MenuItem[label="New private group"]');
const newGroupButton = wrapper.find('MenuItem[label="Create new group"]');
assert.equal(newGroupButton.props().href, 'https://example.com/groups/new');
});
......
......@@ -377,4 +377,35 @@ describe('GroupListItem', () => {
assert.calledWith(fakeCopyPlainText, 'https://annotate.com/groups/groupid');
assert.calledWith(fakeToastMessenger.error, 'Unable to copy link');
});
[
{
type: 'private',
expectedIcon: 'LockIcon',
expectedTitle: 'Private group',
},
{
type: 'restricted',
expectedIcon: 'GlobeAltLockIcon',
expectedTitle: 'Restricted group',
},
{
type: 'open',
expectedIcon: 'GlobeAltIcon',
expectedTitle: 'Public group',
},
].forEach(({ type, expectedIcon, expectedTitle }) => {
it('shows the right icon for the group type', () => {
const wrapper = createGroupListItem({ ...fakeGroup, type });
const label = mount(wrapper.find('MenuItem').prop('label'));
const groupIcon = label.find('[data-testid="group-icon"]');
try {
assert.equal(groupIcon.prop('title'), expectedTitle);
assert.isTrue(groupIcon.exists(expectedIcon));
} finally {
label.unmount();
}
});
});
});
import {
CaretUpIcon,
MenuCollapseIcon,
MenuExpandIcon,
Slider,
} from '@hypothesis/frontend-shared';
......@@ -21,9 +21,7 @@ function SubmenuToggle({
isExpanded,
onToggleSubmenu,
}: SubmenuToggleProps) {
// FIXME: Use `MenuCollapseIcon` instead of `CaretUpIcon` once size
// disparities are addressed
const Icon = isExpanded ? CaretUpIcon : MenuExpandIcon;
const Icon = isExpanded ? MenuCollapseIcon : MenuExpandIcon;
return (
<div
data-testid="submenu-toggle"
......@@ -55,7 +53,7 @@ function SubmenuToggle({
onClick={onToggleSubmenu}
title={title}
>
<Icon className="w-3 h-3" />
<Icon className="w-3 h-3" viewBox="0 0 16 16" />
</div>
);
}
......
......@@ -244,6 +244,8 @@ export type Profile = {
user_info?: UserInfo;
};
export type GroupType = 'private' | 'restricted' | 'open';
export type Organization = {
name: string;
logo: string;
......@@ -261,7 +263,7 @@ export type Group = {
id: string;
/** Fully-qualified ID with authority. */
groupid?: string;
type: 'private' | 'open';
type: GroupType;
/**
* Note: This field is nullable in the API, but we assign a default organization in the client.
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment