From fb09be725e7bfe3aea7dcca99efe6e365dacbd58 Mon Sep 17 00:00:00 2001 From: Robert Knight Date: Thu, 12 Dec 2024 12:54:05 +0000 Subject: [PATCH] Update group forms header and footer Align the header and footer of the group forms more closely with the mocks in https://www.figma.com/design/jon1U01LGSLcx7PWtZ9TPZ/Hypothesis---Group-Management?node-id=2942-1928&node-type=frame&t=NPDV4Y62CUMkfEpq-0. - Add "View group activity" link at the top of the page and remove the "Back to group overview" link from the bottom - Vertically align the page title with the Settings / Members tabs on the right - Add a divider below the title / tabs line, mirroring the one on the bottom of the form --- .../components/CreateEditGroupForm.tsx | 30 ++++------ .../components/EditGroupMembersForm.tsx | 4 +- .../components/GroupFormHeader.tsx | 58 +++++++++++++++---- .../components/forms/FormContainer.tsx | 5 -- .../test/CreateEditGroupForm-test.js | 7 +-- .../components/test/GroupFormHeader-test.js | 46 +++++++++++++++ 6 files changed, 110 insertions(+), 40 deletions(-) create mode 100644 h/static/scripts/group-forms/components/test/GroupFormHeader-test.js diff --git a/h/static/scripts/group-forms/components/CreateEditGroupForm.tsx b/h/static/scripts/group-forms/components/CreateEditGroupForm.tsx index 7a4da8ac250..0e8cf43ee66 100644 --- a/h/static/scripts/group-forms/components/CreateEditGroupForm.tsx +++ b/h/static/scripts/group-forms/components/CreateEditGroupForm.tsx @@ -235,10 +235,12 @@ export default function CreateEditGroupForm({ }; return ( - - {group && config.features.group_members && ( - - )} + +
)} -
+
+ + {/* These are in a child span to avoid a gap between them. */} + +  Required +
)} - - ); } diff --git a/h/static/scripts/group-forms/components/EditGroupMembersForm.tsx b/h/static/scripts/group-forms/components/EditGroupMembersForm.tsx index ecc2073361d..e736361a86b 100644 --- a/h/static/scripts/group-forms/components/EditGroupMembersForm.tsx +++ b/h/static/scripts/group-forms/components/EditGroupMembersForm.tsx @@ -380,8 +380,8 @@ export default function EditGroupMembersForm({ return ( <> - - + +
diff --git a/h/static/scripts/group-forms/components/GroupFormHeader.tsx b/h/static/scripts/group-forms/components/GroupFormHeader.tsx index 133fb10864d..3f8c63d4533 100644 --- a/h/static/scripts/group-forms/components/GroupFormHeader.tsx +++ b/h/static/scripts/group-forms/components/GroupFormHeader.tsx @@ -1,3 +1,4 @@ +import { Link } from '@hypothesis/frontend-shared'; import classnames from 'classnames'; import type { ComponentChildren } from 'preact'; import { Link as RouterLink, useRoute } from 'wouter-preact'; @@ -8,9 +9,10 @@ import { routes } from '../routes'; type TabLinkProps = { href: string; children: ComponentChildren; + testId?: string; }; -function TabLink({ children, href }: TabLinkProps) { +function TabLink({ children, href, testId }: TabLinkProps) { const [selected] = useRoute(href); return ( {children} @@ -27,22 +30,55 @@ function TabLink({ children, href }: TabLinkProps) { } export type GroupFormHeaderProps = { - group: Group; + group: Group | null; + title: string; + enableMembers?: boolean; }; -export default function GroupFormHeader({ group }: GroupFormHeaderProps) { +export default function GroupFormHeader({ + enableMembers = true, + group, + title, +}: GroupFormHeaderProps) { // This should be replaced with a proper URL generation function that handles // escaping etc. - const editLink = routes.groups.edit.replace(':pubid', group.pubid); - const editMembersLinks = routes.groups.editMembers.replace( - ':pubid', - group.pubid, - ); + const editLink = group + ? routes.groups.edit.replace(':pubid', group.pubid) + : null; + const editMembersLinks = group + ? routes.groups.editMembers.replace(':pubid', group.pubid) + : null; return ( -
- Settings - Members +
+ {group && ( +
+ + View group activity + +
+ )} +
+

+ {title} +

+
+ {enableMembers && editLink && ( + + Settings + + )} + {enableMembers && editMembersLinks && ( + + Members + + )} +
); } diff --git a/h/static/scripts/group-forms/components/forms/FormContainer.tsx b/h/static/scripts/group-forms/components/forms/FormContainer.tsx index a747c07e702..23988ee86bd 100644 --- a/h/static/scripts/group-forms/components/forms/FormContainer.tsx +++ b/h/static/scripts/group-forms/components/forms/FormContainer.tsx @@ -2,7 +2,6 @@ import classnames from 'classnames'; import type { ComponentChildren } from 'preact'; export type FormContainerProps = { - title: string; children: ComponentChildren; classes?: string; }; @@ -11,13 +10,9 @@ export type FormContainerProps = { export default function FormContainer({ children, classes, - title, }: FormContainerProps) { return (
-

- {title} -

{children}
); diff --git a/h/static/scripts/group-forms/components/test/CreateEditGroupForm-test.js b/h/static/scripts/group-forms/components/test/CreateEditGroupForm-test.js index 85c586979d8..0b32df6c54a 100644 --- a/h/static/scripts/group-forms/components/test/CreateEditGroupForm-test.js +++ b/h/static/scripts/group-forms/components/test/CreateEditGroupForm-test.js @@ -78,7 +78,7 @@ describe('CreateEditGroupForm', () => { const getElements = wrapper => { return { - header: wrapper.find('[data-testid="header"]'), + header: wrapper.find('GroupFormHeader'), nameField: wrapper.find('TextField[label="Name"]'), descriptionField: wrapper.find('TextField[label="Description"]'), submitButton: wrapper.find('button[data-testid="button"]'), @@ -111,7 +111,7 @@ describe('CreateEditGroupForm', () => { const { wrapper, elements } = createWrapper(); const { header, nameField, descriptionField, submitButton } = elements; - assert.equal(header.text(), heading); + assert.equal(header.prop('title'), heading); assert.equal(nameField.prop('value'), ''); assert.equal(descriptionField.prop('value'), ''); assert.equal(submitButton.text(), 'Create group'); @@ -245,12 +245,11 @@ describe('CreateEditGroupForm', () => { const { wrapper, elements } = createWrapper({ group }); const { header, nameField, descriptionField, submitButton } = elements; - assert.equal(header.text(), 'Edit group'); + assert.equal(header.prop('title'), 'Edit group'); assert.equal(nameField.prop('value'), group.name); assert.equal(descriptionField.prop('value'), group.description); assert.equal(getSelectedGroupType(wrapper), group.type); assert.equal(submitButton.text(), 'Save changes'); - assert.isTrue(wrapper.exists('[data-testid="back-link"]')); assert.isFalse(wrapper.exists('[data-testid="error-message"]')); await assertInLoadingState(wrapper, false); assert.isFalse(savedConfirmationShowing(wrapper)); diff --git a/h/static/scripts/group-forms/components/test/GroupFormHeader-test.js b/h/static/scripts/group-forms/components/test/GroupFormHeader-test.js new file mode 100644 index 00000000000..c0f1ad6a3bc --- /dev/null +++ b/h/static/scripts/group-forms/components/test/GroupFormHeader-test.js @@ -0,0 +1,46 @@ +import { mount } from '@hypothesis/frontend-testing'; + +import GroupFormHeader from '../GroupFormHeader'; + +describe('GroupFormHeader', () => { + const createHeader = (props = {}) => mount(); + + const group = { + pubid: 'abc123', + link: 'https://anno.co/groups/abc123', + }; + + const getLink = (wrapper, name) => wrapper.find(`a[data-testid="${name}"]`); + + it('renders title', () => { + const header = createHeader({ title: 'Create a new group' }); + assert.equal(header.find('h1').text(), 'Create a new group'); + }); + + it('does not show activity link or tabs if no group', () => { + const header = createHeader(); + assert.isFalse(getLink(header, 'activity-link').exists()); + assert.isFalse(getLink(header, 'settings-link').exists()); + assert.isFalse(getLink(header, 'members-link').exists()); + }); + + it('renders group activity link and tabs if there is a group', () => { + const header = createHeader({ group }); + + const activityLink = getLink(header, 'activity-link'); + assert.equal(activityLink.prop('href'), group.link); + + const settingsLink = getLink(header, 'settings-link'); + assert.equal(settingsLink.prop('href'), '/groups/abc123/edit'); + + const membersLink = getLink(header, 'members-link'); + assert.equal(membersLink.prop('href'), '/groups/abc123/edit/members'); + }); + + it('does not show tabs if the members flag is disabled', () => { + const header = createHeader({ group, enableMembers: false }); + assert.isTrue(getLink(header, 'activity-link').exists()); + assert.isFalse(getLink(header, 'settings-link').exists()); + assert.isFalse(getLink(header, 'members-link').exists()); + }); +});