);
+
+ const { querySettings, handleTableFetch } = useQuerySettings();
+
// TODO: Display error in the notification system
const {
data: teamMembers, isLoading, isError,
- } = useTeamMembers(libraryId);
+ } = useTeamMembers(libraryId, querySettings);
- const rows = isError ? [] : (teamMembers || SKELETON_ROWS);
+ const rows = isError ? [] : (teamMembers?.results || SKELETON_ROWS);
+ const pageCount = teamMembers?.count ? Math.ceil(teamMembers.count / DEFAULT_PAGE_SIZE) : 1;
const navigate = useNavigate();
+ const adaptedFilterChoices = useMemo(
+ () => roles.map((role) => ({
+ name: role.name,
+ number: role.userCount,
+ value: role.role,
+ })),
+ [roles],
+ );
+
+ const fetchData = useMemo(() => debounce(handleTableFetch, 500), [handleTableFetch]);
+
+ useEffect(() => () => fetchData.cancel(), [fetchData]);
+
return (
{
) : null),
},
]}
- initialState={{
- pageSize: 10,
- }}
columns={
[
{
Header: intl.formatMessage(messages['library.authz.team.table.username']),
accessor: 'username',
Cell: NameCell,
+ disableSortBy: true,
},
{
Header: intl.formatMessage(messages['library.authz.team.table.email']),
accessor: 'email',
Cell: EmailCell,
+ disableFilters: true,
+ disableSortBy: true,
},
{
Header: intl.formatMessage(messages['library.authz.team.table.roles']),
@@ -107,10 +143,18 @@ const TeamTable = () => {
{roleLabels[role]}
))
)),
+ Filter: CheckboxFilter,
+ filter: 'includesValue',
+ filterChoices: Object.values(adaptedFilterChoices),
+ disableSortBy: true,
},
]
}
- />
+ >
+
+
+
+
);
};
diff --git a/src/authz-module/libraries-manager/components/TeamTable/messages.ts b/src/authz-module/libraries-manager/components/TeamTable/messages.ts
new file mode 100644
index 00000000..1bc30a2a
--- /dev/null
+++ b/src/authz-module/libraries-manager/components/TeamTable/messages.ts
@@ -0,0 +1,56 @@
+import { defineMessages } from '@edx/frontend-platform/i18n';
+
+const messages = defineMessages({
+ 'library.authz.team.table.username': {
+ id: 'library.authz.team.table.username',
+ defaultMessage: 'Username',
+ description: 'Libraries team management table username column header',
+ },
+ 'library.authz.team.table.username.current': {
+ id: 'library.authz.team.table.username.current',
+ defaultMessage: ' (Me)',
+ description: 'Libraries team management table indicative of current user',
+ },
+ 'library.authz.team.table.email': {
+ id: 'library.team.table.email',
+ defaultMessage: 'Email',
+ description: 'Libraries team management table email column header',
+ },
+ 'library.authz.team.table.roles': {
+ id: 'library.authz.team.table.roles',
+ defaultMessage: 'Roles',
+ description: 'Libraries team management table roles column header',
+ },
+ 'library.authz.team.table.action': {
+ id: 'library.authz.team.table.action',
+ defaultMessage: 'Action',
+ description: 'Libraries team management table action column header',
+ },
+ 'authz.libraries.team.table.edit.action': {
+ id: 'authz.libraries.team.table.edit.action',
+ defaultMessage: 'Edit',
+ description: 'Edit action',
+ },
+ 'authz.libraries.team.table.search': {
+ id: 'authz.libraries.team.table.search',
+ defaultMessage: 'Search by {firstField} or {secondField}',
+ description: 'Search placeholder for two specific fields',
+ },
+ 'authz.libraries.team.table.sort.name-a-z': {
+ id: 'authz.libraries.team.table.sort.name-a-z',
+ defaultMessage: 'Name A-Z',
+ description: 'Sort by name A-Z',
+ },
+ 'authz.libraries.team.table.sort.name-z-a': {
+ id: 'authz.libraries.team.table.sort.name-z-a',
+ defaultMessage: 'Name Z-A',
+ description: 'Sort by name Z-A',
+ },
+ 'authz.libraries.team.table.clearFilters': {
+ id: 'authz.libraries.team.table.clearFilters',
+ defaultMessage: 'Clear filters',
+ description: 'Button to clear all active filters in the table',
+ },
+});
+
+export default messages;
diff --git a/src/authz-module/libraries-manager/components/messages.ts b/src/authz-module/libraries-manager/components/messages.ts
index d36537e7..d73643a0 100644
--- a/src/authz-module/libraries-manager/components/messages.ts
+++ b/src/authz-module/libraries-manager/components/messages.ts
@@ -1,41 +1,16 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
- 'library.authz.team.table.username': {
- id: 'library.authz.team.table.username',
- defaultMessage: 'Username',
- description: 'Libraries team management table username column header',
- },
- 'library.authz.team.table.username.current': {
- id: 'library.authz.team.table.username.current',
- defaultMessage: ' (Me)',
- description: 'Libraries team management table indicative of current user',
- },
- 'library.authz.team.table.email': {
- id: 'library.team.table.email',
- defaultMessage: 'Email',
- description: 'Libraries team management table email column header',
- },
- 'library.authz.team.table.roles': {
- id: 'library.authz.team.table.roles',
- defaultMessage: 'Roles',
- description: 'Libraries team management table roles column header',
- },
- 'library.authz.team.table.action': {
- id: 'library.authz.team.table.action',
- defaultMessage: 'Action',
- description: 'Libraries team management table action column header',
- },
- 'authz.libraries.team.table.edit.action': {
- id: 'authz.libraries.team.table.edit.action',
- defaultMessage: 'Edit',
- description: 'Edit action',
- },
'libraries.authz.manage.assign.new.role.title': {
id: 'libraries.authz.manage.assign.new.role.title',
defaultMessage: 'Add New Role',
description: 'Libraries AuthZ assign a new role to a user button title',
},
+ 'library.authz.manage.role.select.label': {
+ id: 'library.authz.role.select.label',
+ defaultMessage: 'Roles',
+ description: 'Libraries team management label for roles select',
+ },
'libraries.authz.manage.cancel.button': {
id: 'libraries.authz.manage.cancel.button',
defaultMessage: 'Cancel',
diff --git a/src/authz-module/libraries-manager/context.test.tsx b/src/authz-module/libraries-manager/context.test.tsx
index 28f039d9..68199c9a 100644
--- a/src/authz-module/libraries-manager/context.test.tsx
+++ b/src/authz-module/libraries-manager/context.test.tsx
@@ -1,4 +1,5 @@
-import { screen } from '@testing-library/react';
+import { Component, ReactNode } from 'react';
+import { screen, renderHook } from '@testing-library/react';
import { useParams } from 'react-router-dom';
import { useValidateUserPermissions } from '@src/data/hooks';
import { renderWrapper } from '@src/setupTest';
@@ -18,16 +19,31 @@ jest.mock('@src/authz-module/data/hooks', () => ({
data: [
{
role: 'library_author',
- permissions: [
- 'view_library_team',
- 'edit_library',
- ],
+ permissions: ['view_library_team', 'edit_library'],
user_count: 12,
},
],
}),
}));
+class ErrorBoundary extends Component<{ children: ReactNode }, { hasError: boolean; error?: Error }> {
+ constructor(props: { children: ReactNode }) {
+ super(props);
+ this.state = { hasError: false };
+ }
+
+ static getDerivedStateFromError(error: Error) {
+ return { hasError: true, error };
+ }
+
+ render() {
+ if (this.state.hasError && this.state.error) {
+ throw this.state.error;
+ }
+ return this.props.children;
+ }
+}
+
const TestComponent = () => {
const context = useLibraryAuthZ();
return (
@@ -36,7 +52,9 @@ const TestComponent = () => {
{context.libraryId}
{context.canManageTeam ? 'true' : 'false'}
{Array.isArray(context.roles) ? context.roles.length : 'undefined'}
- {Array.isArray(context.permissions) ? context.permissions.length : 'undefined'}
+
+ {Array.isArray(context.permissions) ? context.permissions.length : 'undefined'}
+
{Array.isArray(context.resources) ? context.resources.length : 'undefined'}
);
@@ -137,21 +155,18 @@ describe('LibraryAuthZProvider', () => {
expect(() => {
renderWrapper(
-
-
- ,
+
+
+
+
+ ,
);
}).toThrow('MissingLibrary');
});
it('throws error when useLibraryAuthZ is used outside provider', () => {
- const BrokenComponent = () => {
- useLibraryAuthZ();
- return null;
- };
-
expect(() => {
- renderWrapper();
+ renderHook(() => useLibraryAuthZ());
}).toThrow('useLibraryAuthZ must be used within an LibraryAuthZProvider');
});
});
diff --git a/src/types.ts b/src/types.ts
index 3a7ebdd9..6b5e86b8 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -13,6 +13,7 @@ export interface TeamMember {
fullName: string;
email: string;
roles: string[];
+ createdAt: string;
}
export interface LibraryMetadata {