Skip to content

Commit 5335f70

Browse files
committed
feat: add tost for error feedback
1 parent 74bfbcd commit 5335f70

6 files changed

Lines changed: 60 additions & 23 deletions

File tree

src/authz-module/components/RoleCard/index.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ describe('RoleCard', () => {
2020
title: 'Admin',
2121
objectName: 'Test Library',
2222
description: 'Can manage everything',
23-
showDelete: true,
23+
handleDelete: jest.fn(),
2424
userCounter: 2,
2525
permissions: [
2626
{
@@ -71,8 +71,8 @@ describe('RoleCard', () => {
7171
expect(screen.getByTestId('manage-icon')).toBeInTheDocument();
7272
});
7373

74-
it('does not show delete button when showDelete is false', () => {
75-
renderWrapper(<RoleCard {...defaultProps} showDelete={false} />);
74+
it('does not show delete button when handleDelete is not passed', () => {
75+
renderWrapper(<RoleCard {...defaultProps} handleDelete={undefined} />);
7676
expect(screen.queryByRole('button', { name: /delete role action/i })).not.toBeInTheDocument();
7777
});
7878

src/authz-module/data/hooks.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ export const useAssignTeamMembersRole = () => {
8888
});
8989
};
9090

91-
9291
/**
9392
* React Query hook to remove roles for a specific team member within a scope.
9493
*

src/authz-module/libraries-manager/LibrariesUserManager.test.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { renderWrapper } from '@src/setupTest';
44
import LibrariesUserManager from './LibrariesUserManager';
55
import { useLibraryAuthZ } from './context';
66
import { useLibrary, useTeamMembers } from '../data/hooks';
7+
import { ToastManagerProvider } from './ToastManagerContext';
78

89
jest.mock('react-router-dom', () => ({
910
...jest.requireActual('react-router-dom'),
@@ -17,6 +18,11 @@ jest.mock('./context', () => ({
1718
jest.mock('../data/hooks', () => ({
1819
useLibrary: jest.fn(),
1920
useTeamMembers: jest.fn(),
21+
useRevokeUserRoles: jest.fn(() => ({
22+
isPending: false,
23+
mutation: jest.fn(),
24+
25+
})),
2026
}));
2127
jest.mock('../components/RoleCard', () => ({
2228
__esModule: true,
@@ -75,7 +81,7 @@ describe('LibrariesUserManager', () => {
7581
});
7682

7783
it('renders the user roles correctly', () => {
78-
renderWrapper(<LibrariesUserManager />);
84+
renderWrapper(<ToastManagerProvider><LibrariesUserManager /></ToastManagerProvider>);
7985

8086
// Breadcrumb check
8187
expect(screen.getByText('Manage Access')).toBeInTheDocument();

src/authz-module/libraries-manager/LibrariesUserManager.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import { useEffect, useMemo, useState } from 'react';
22
import { useNavigate, useParams } from 'react-router-dom';
33
import { useIntl } from '@edx/frontend-platform/i18n';
4+
import { logError } from '@edx/frontend-platform/logging';
45
import { Container, Skeleton } from '@openedx/paragon';
56
import { ROUTES } from '@src/authz-module/constants';
67
import { Role } from 'types';
7-
import { useToastManager } from 'authz-module/libraries-manager/ToastManagerContext';
8+
import { useToastManager } from '@src/authz-module/libraries-manager/ToastManagerContext';
89
import AuthZLayout from '../components/AuthZLayout';
910
import { useLibraryAuthZ } from './context';
1011
import RoleCard from '../components/RoleCard';
1112
import { AssignNewRoleTrigger } from './components/AssignNewRoleModal';
13+
import ConfirmDeletionModal from './components/ConfirmDeletionModal';
1214
import { useLibrary, useRevokeUserRoles, useTeamMembers } from '../data/hooks';
1315
import { buildPermissionsByRoleMatrix } from './utils';
1416

1517
import messages from './messages';
16-
import ConfirmDeletionModal from './components/ConfirmDeletionModal';
1718

1819
const LibrariesUserManager = () => {
1920
const intl = useIntl();
@@ -22,6 +23,15 @@ const LibrariesUserManager = () => {
2223
const {
2324
libraryId, permissions, roles, resources, canManageTeam,
2425
} = useLibraryAuthZ();
26+
const teamMembersPath = `/authz/${ROUTES.LIBRARIES_TEAM_PATH.replace(':libraryId', libraryId)}`;
27+
28+
useEffect(() => {
29+
if (!canManageTeam) {
30+
navigate(teamMembersPath);
31+
}
32+
// eslint-disable-next-line react-hooks/exhaustive-deps
33+
}, [canManageTeam]);
34+
2535
const { data: library } = useLibrary(libraryId);
2636
const { mutate: revokeUserRoles, isPending: isRevokingUserRole } = useRevokeUserRoles();
2737
const rootBreadcrumb = intl.formatMessage(messages['library.authz.breadcrumb.root']) || '';
@@ -39,11 +49,9 @@ const LibrariesUserManager = () => {
3949
const [showConfirmDeletionModal, setShowConfirmDeletionModal] = useState(false);
4050
const { handleShowToast, handleDiscardToast } = useToastManager();
4151

42-
const { data: teamMember, isLoading: isLoadingTeamMember } = useTeamMembers(libraryId, querySettings);
52+
const { data: teamMember, isLoading: isLoadingTeamMember, isFetching: isFetchingMember } = useTeamMembers(libraryId, querySettings);
4353
const user = teamMember?.results?.find(member => member.username === username);
4454

45-
const teamMembersPath = `/authz/${ROUTES.LIBRARIES_TEAM_PATH.replace(':libraryId', libraryId)}`;
46-
4755
const userRoles = useMemo(() => {
4856
const assignedRoles = roles.filter(role => user?.roles.includes(role.role))
4957
.map(role => ({
@@ -55,6 +63,15 @@ const LibrariesUserManager = () => {
5563
return assignedRoles;
5664
}, [roles, user?.roles, permissions, resources, intl]);
5765

66+
useEffect(() => {
67+
if (!isFetchingMember) {
68+
if (!isLoadingTeamMember && !user?.username) {
69+
navigate(teamMembersPath);
70+
}
71+
}
72+
// eslint-disable-next-line react-hooks/exhaustive-deps
73+
}, [isFetchingMember, isLoadingTeamMember, user?.username]);
74+
5875
const handleCloseConfirmDeletionModal = () => {
5976
setRoleToDelete(null);
6077
setShowConfirmDeletionModal(false);
@@ -90,10 +107,10 @@ const LibrariesUserManager = () => {
90107
handleCloseConfirmDeletionModal();
91108
},
92109
onError: (error) => {
93-
// eslint-disable-next-line no-console
94-
console.error('Failed to revoke user role:', error);
110+
logError(error);
111+
// eslint-disable-next-line react/no-unstable-nested-components
112+
handleShowToast(intl.formatMessage(messages['library.authz.team.default.error.toast.message'], { b: chunk => <b>{chunk}</b>, br: () => <br /> }));
95113
handleCloseConfirmDeletionModal();
96-
// Could add error toast here if needed
97114
},
98115
});
99116
};

src/authz-module/libraries-manager/components/messages.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,26 @@ const messages = defineMessages({
66
defaultMessage: 'Add New Role',
77
description: 'Libraries AuthZ assign a new role to a user button title',
88
},
9+
'libraries.authz.manage.cancel.button': {
10+
id: 'libraries.authz.manage.cancel.button',
11+
defaultMessage: 'Cancel',
12+
description: 'Libraries AuthZ cancel button title',
13+
},
14+
'libraries.authz.manage.saving.button': {
15+
id: 'libraries.authz.manage.saving.button',
16+
defaultMessage: 'Saving...',
17+
description: 'Libraries AuthZ saving button title',
18+
},
19+
'libraries.authz.manage.save.button': {
20+
id: 'libraries.authz.manage.save.button',
21+
defaultMessage: 'Save',
22+
description: 'Libraries AuthZ save button title',
23+
},
24+
'libraries.authz.manage.assign.role.success': {
25+
id: 'libraries.authz.manage.assign.role.success',
26+
defaultMessage: 'Role added successfully.',
27+
description: 'Libraries AuthZ assign role success message',
28+
},
929
'library.authz.team.remove.user.modal.title': {
1030
id: 'library.authz.team.remove.user.modal.title',
1131
defaultMessage: 'Remove role?',
@@ -31,11 +51,6 @@ const messages = defineMessages({
3151
defaultMessage: 'Roles',
3252
description: 'Libraries team management label for roles select',
3353
},
34-
'libraries.authz.manage.cancel.button': {
35-
id: 'libraries.authz.manage.cancel.button',
36-
defaultMessage: 'Cancel',
37-
description: 'Libraries AuthZ cancel button title',
38-
},
3954
'libraries.authz.manage.removing.button': {
4055
id: 'libraries.authz.manage.removing.button',
4156
defaultMessage: 'Removing...',
@@ -46,11 +61,6 @@ const messages = defineMessages({
4661
defaultMessage: 'Remove',
4762
description: 'Libraries AuthZ remove button title',
4863
},
49-
'libraries.authz.manage.assign.role.success': {
50-
id: 'libraries.authz.manage.assign.role.success',
51-
defaultMessage: 'Role added successfully.',
52-
description: 'Libraries AuthZ assign role success message',
53-
},
5464
});
5565

5666
export default messages;

src/authz-module/libraries-manager/messages.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ const messages = defineMessages({
3131
defaultMessage: 'The {role} role has been successfully removed.{rolesCount, plural, =0 { The user no longer has access to this library and has been removed from the member list.} other {}}',
3232
description: 'Libraries team management remove user toast success',
3333
},
34+
'library.authz.team.default.error.toast.message': {
35+
id: 'library.authz.team.default.error.toast.message',
36+
defaultMessage: '<b>Something went wrong on our end</b> <br></br> Please try again later.',
37+
description: 'Libraries team management remove user toast success',
38+
},
3439
});
3540

3641
export default messages;

0 commit comments

Comments
 (0)