Skip to content

Commit 5a55041

Browse files
feat: integrating api for permissions assignments on audit user page table
1 parent ef7bf9b commit 5a55041

14 files changed

Lines changed: 151 additions & 179 deletions

File tree

src/authz-module/audit-user/CustomCells.tsx

Lines changed: 0 additions & 44 deletions
This file was deleted.

src/authz-module/audit-user/index.tsx

Lines changed: 10 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -11,98 +11,12 @@ import { useNavigate, useParams } from 'react-router-dom';
1111
import { useUserAccount } from '@src/data/hooks';
1212
import baseMessages from '@src/authz-module/messages';
1313
import AddRoleButton from '@src/authz-module/components/AddRoleButton';
14-
import { RoleCell } from '@src/authz-module/components/TableCells';
14+
import {
15+
OrgCell, RoleCell, ScopeCell, PermissionsCell, ViewAllPermissionsCell, ActionsCell,
16+
} from '@src/authz-module/components/TableCells';
1517
import { useQuerySettings } from '@src/authz-module/hooks/useQuerySettings';
1618
import { useUserAssignedRoles } from '@src/authz-module/data/hooks';
1719
import messages from './messages';
18-
import { ViewAllPermissionsCell, ActionsCell, PermissionsCell } from './CustomCells';
19-
20-
const dummyData = [
21-
{
22-
role: 'Course Admin',
23-
organization: 'edX',
24-
scope: 'Course: Demo Course',
25-
permissions: ['View', 'Edit', 'Delete'],
26-
},
27-
{
28-
role: 'Course Auditor',
29-
organization: 'edX',
30-
scope: 'Course: Demo Course 2',
31-
permissions: ['View', 'Edit'],
32-
},
33-
{
34-
role: 'Super Admin',
35-
organization: 'edX',
36-
scope: 'Course: Demo Course',
37-
permissions: ['View', 'Edit', 'Delete'],
38-
},
39-
{
40-
role: 'Course Auditor',
41-
organization: 'edX',
42-
scope: 'Course: Demo Course 2',
43-
permissions: ['View', 'Edit'],
44-
},
45-
{
46-
role: 'Global Staff',
47-
organization: 'edX',
48-
scope: 'Course: Demo Course',
49-
permissions: ['View', 'Edit', 'Delete'],
50-
},
51-
{
52-
role: 'Course Auditor',
53-
organization: 'edX',
54-
scope: 'Course: Demo Course 2',
55-
permissions: ['View', 'Edit'],
56-
},
57-
{
58-
role: 'Course Admin',
59-
organization: 'edX',
60-
scope: 'Course: Demo Course',
61-
permissions: ['View', 'Edit', 'Delete'],
62-
},
63-
{
64-
role: 'Course Auditor',
65-
organization: 'edX',
66-
scope: 'Course: Demo Course 2',
67-
permissions: ['View', 'Edit'],
68-
},
69-
{
70-
role: 'Course Admin',
71-
organization: 'edX',
72-
scope: 'Course: Demo Course',
73-
permissions: ['View', 'Edit', 'Delete'],
74-
},
75-
{
76-
role: 'Course Auditor',
77-
organization: 'edX',
78-
scope: 'Course: Demo Course 2',
79-
permissions: ['View', 'Edit'],
80-
},
81-
{
82-
role: 'Course Admin',
83-
organization: 'edX',
84-
scope: 'Course: Demo Course',
85-
permissions: ['View', 'Edit', 'Delete'],
86-
},
87-
{
88-
role: 'Course Auditor',
89-
organization: 'edX',
90-
scope: 'Course: Demo Course 2',
91-
permissions: ['View', 'Edit'],
92-
},
93-
{
94-
role: 'Course Admin',
95-
organization: 'edX',
96-
scope: 'Course: Demo Course',
97-
permissions: ['View', 'Edit', 'Delete'],
98-
},
99-
{
100-
role: 'Course Auditor',
101-
organization: 'edX',
102-
scope: 'Course: Demo Course 2',
103-
permissions: ['View', 'Edit'],
104-
},
105-
];
10620

10721
const AuditUserPage = () => {
10822
const { formatMessage } = useIntl();
@@ -111,7 +25,7 @@ const AuditUserPage = () => {
11125
const { isLoading: isLoadingUser, data: user } = useUserAccount(username ?? '');
11226
const { querySettings, handleTableFetch } = useQuerySettings();
11327
// TODO: use actual assigned roles data when API is ready, currently using dummy data for development purpose
114-
const { data: _userAssignedRoles } = useUserAssignedRoles(username ?? '', querySettings);
28+
const { data: { results: userAssignments } = { results: [] } } = useUserAssignedRoles(username ?? '', querySettings);
11529
const authzHomePath = '/authz';
11630
if (!user && !isLoadingUser) {
11731
navigate(authzHomePath);
@@ -142,11 +56,13 @@ const AuditUserPage = () => {
14256
},
14357
{
14458
Header: formatMessage(messages['authz.user.table.organization.column.header']),
145-
accessor: 'organization',
59+
accessor: 'org',
60+
Cell: OrgCell,
14661
},
14762
{
14863
Header: formatMessage(messages['authz.user.table.scope.column.header']),
14964
accessor: 'scope',
65+
Cell: ScopeCell,
15066
disableFilters: true,
15167
},
15268
{
@@ -156,7 +72,7 @@ const AuditUserPage = () => {
15672
disableSortBy: true,
15773
},
15874
];
159-
const pageCount = dummyData?.length ? Math.ceil(dummyData.length / TABLE_DEFAULT_PAGE_SIZE) : 1;
75+
const pageCount = userAssignments?.length ? Math.ceil(userAssignments.length / TABLE_DEFAULT_PAGE_SIZE) : 1;
16076

16177
const fetchData = useMemo(() => debounce(handleTableFetch, 500), [handleTableFetch]);
16278

@@ -182,9 +98,9 @@ const AuditUserPage = () => {
18298
<DataTable
18399
isPaginated
184100
manualPagination
185-
data={dummyData}
101+
data={userAssignments}
186102
fetchData={fetchData}
187-
itemCount={dummyData?.length || 0}
103+
itemCount={userAssignments?.length || 0}
188104
pageCount={pageCount}
189105
initialState={{ pageSize: TABLE_DEFAULT_PAGE_SIZE }}
190106
additionalColumns={additionalColumns}

src/authz-module/audit-user/messages.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,6 @@ const messages = defineMessages(
2727
defaultMessage: 'Actions',
2828
description: 'Header for the actions column in the user table',
2929
},
30-
'authz.user.table.view_all_permissions.link.text': {
31-
id: 'authz.user.table.view_all_permissions.link.text',
32-
defaultMessage: 'View all permissions',
33-
description: 'Text for the link to view all permissions in the user table',
34-
},
35-
'authz.user.table.delete.action.alt': {
36-
id: 'authz.user.table.delete.action.alt',
37-
defaultMessage: 'Delete role action',
38-
description: 'Alt description for delete button',
39-
},
40-
'authz.user.table.permissions.available.count': {
41-
id: 'authz.user.table.permissions.available.count',
42-
defaultMessage: '{count, plural, one {# permission available} other {# permissions available}}',
43-
description: 'Text showing the number of permissions available, with proper pluralization',
44-
},
4530
},
4631
);
4732

src/authz-module/audit-user/utils.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,93 @@
1-
import { TableCellValue, TeamMember } from '@src/types';
1+
import { useIntl } from '@edx/frontend-platform/i18n';
2+
import { TableCellValue, UserRole } from '@src/types';
3+
import { DJANGO_MANAGED_ROLES, MAP_ROLE_KEY_TO_LABEL } from '@src/authz-module/constants';
4+
import { IconButton } from '@openedx/paragon';
5+
import { Delete, ExpandMore } from '@openedx/paragon/icons';
6+
import messages from './messages';
7+
import ViewMoreLink from './ViewMoreLink';
28

3-
type CellProps = TableCellValue<TeamMember>;
4-
type ExtendedCellProps = CellProps & {
9+
type CellProps = TableCellValue<UserRole>;
10+
type CellPropsWithValue = CellProps & {
511
value: string;
12+
};
13+
type ExtendedCellProps = CellPropsWithValue & {
614
cell: {
715
getCellProps: (props?: Record<string, string>) => Record<string, string>;
816
};
917
};
1018

1119
const RoleCell = ({ value, cell }: ExtendedCellProps) => (
12-
<td {...cell.getCellProps({ 'data-role': value })}>
13-
{value}
20+
<td {...cell.getCellProps({ 'data-role': MAP_ROLE_KEY_TO_LABEL[value] || '' })}>
21+
{MAP_ROLE_KEY_TO_LABEL[value] || ''}
1422
</td>
1523
);
1624

25+
const OrgCell = ({ value, row }: CellPropsWithValue) => {
26+
const { formatMessage } = useIntl();
27+
return (
28+
<td>
29+
{DJANGO_MANAGED_ROLES.includes(row.original.role) ? formatMessage(messages['authz.user.table.org.all.organizations.label']) : value}
30+
</td>
31+
);
32+
};
33+
34+
const ScopeCell = ({ value, row }: CellPropsWithValue) => {
35+
const { formatMessage } = useIntl();
36+
const isDjangoRole = DJANGO_MANAGED_ROLES.includes(row.original.role);
37+
return (
38+
<td>
39+
{isDjangoRole ? formatMessage(messages['authz.user.table.scope.global.label']) : value}
40+
</td>
41+
);
42+
};
43+
44+
const PermissionsCell = ({ row }: CellProps) => {
45+
const { formatMessage } = useIntl();
46+
const { role, permissionCount: count } = row.original;
47+
const isDjangoRole = DJANGO_MANAGED_ROLES.includes(role);
48+
return (
49+
<span>
50+
{ isDjangoRole
51+
? formatMessage(
52+
messages['authz.user.table.permissions.access.label'],
53+
{ accessType: role === 'django.superuser' ? 'total' : 'partial' },
54+
)
55+
: formatMessage(messages['authz.user.table.permissions.available.count'], { count })}
56+
</span>
57+
);
58+
};
59+
60+
const ActionsCell = ({ row }: CellProps) => {
61+
const { formatMessage } = useIntl();
62+
const handleDelete = () => {
63+
// TODO: Implement delete functionality
64+
// eslint-disable-next-line no-console
65+
console.log('Delete clicked for row:', row);
66+
};
67+
68+
return (
69+
<IconButton variant="danger" onClick={handleDelete} alt={formatMessage(messages['authz.user.table.delete.action.alt'])} src={Delete} />
70+
);
71+
};
72+
73+
const ViewAllPermissionsCell = ({ row }: CellProps) => {
74+
const { formatMessage } = useIntl();
75+
return (
76+
<ViewMoreLink
77+
label={formatMessage(messages['authz.user.table.view_all_permissions.link.text'])}
78+
// TODO: Implement view more functionality
79+
// eslint-disable-next-line no-console
80+
onClick={() => console.log('View more clicked for row:', row)}
81+
iconSrc={ExpandMore}
82+
/>
83+
);
84+
};
85+
1786
export {
1887
RoleCell,
88+
OrgCell,
89+
ScopeCell,
90+
PermissionsCell,
91+
ActionsCell,
92+
ViewAllPermissionsCell,
1993
};

src/authz-module/components/TableFooter/TableFooter.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ import messages from '../messages';
66
const Footer = () => {
77
const { formatMessage } = useIntl();
88
const {
9-
pageCount, gotoPage, state, itemCount,
9+
pageCount, gotoPage, state, itemCount, rows,
1010
// @ts-ignore-next-line - Paragon's DataTableContext is not typed
1111
} = useContext<DataTableContext>(DataTableContext);
12-
const { pageIndex, pageSize } = state;
13-
12+
const { pageIndex } = state;
1413
return (
1514
<TableFooter>
1615
<span>
17-
{formatMessage(messages['authz.table.footer.items.showing.text'], { pageSize, itemCount })}
16+
{formatMessage(messages['authz.table.footer.items.showing.text'], { pageSize: rows.length, itemCount })}
1817
</span>
1918
<Pagination
2019
variant="reduced"

src/authz-module/components/messages.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,38 @@ const messages = defineMessages({
1313
},
1414
'authz.table.footer.items.showing.text': {
1515
id: 'authz.table.footer.items.showing.text',
16-
defaultMessage: 'Showing {pageSize} of {itemCount} users.',
17-
description: 'Message displayed when the user reaches the applied filters limit',
16+
defaultMessage: 'Showing {pageSize} of {itemCount}.',
17+
description: 'Text in the table footer indicating how many items are being shown out of the total count.',
18+
},
19+
'authz.user.table.org.all.organizations.label': {
20+
id: 'authz.user.table.org.all.organizations.label',
21+
defaultMessage: 'All Organizations',
22+
description: 'Label for the "All Organizations" message on the user assignments table when a user has a django managed role assigned.',
23+
},
24+
'authz.user.table.scope.global.label': {
25+
id: 'authz.user.table.scope.global.label',
26+
defaultMessage: 'Global',
27+
description: 'Label for the "Global" scope in the user assignments table when a user has a django managed role assigned.',
28+
},
29+
'authz.user.table.permissions.access.label': {
30+
id: 'authz.user.table.permissions.access.label',
31+
defaultMessage: '{accessType, select, total {Total Access} partial {Partial Access} other {No Access}}',
32+
description: 'Label for the permissions access level in the user assignments table, can be Total or Partial.',
33+
},
34+
'authz.user.table.permissions.available.count': {
35+
id: 'authz.user.table.permissions.available.count',
36+
defaultMessage: '{count, plural, one {# permission available} other {# permissions available}}',
37+
description: 'Text showing the number of permissions available, with proper pluralization',
38+
},
39+
'authz.user.table.delete.action.alt': {
40+
id: 'authz.user.table.delete.action.alt',
41+
defaultMessage: 'Delete role action',
42+
description: 'Alt description for delete button',
43+
},
44+
'authz.user.table.view_all_permissions.link.text': {
45+
id: 'authz.user.table.view_all_permissions.link.text',
46+
defaultMessage: 'View all permissions',
47+
description: 'Text for the link to view all permissions in the user table',
1848
},
1949
});
2050

src/authz-module/constants.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,18 @@ export enum RoleOperationErrorStatus {
119119
}
120120

121121
export const TABLE_DEFAULT_PAGE_SIZE = 10;
122+
123+
export const MAP_ROLE_KEY_TO_LABEL: Record<string, string> = {
124+
library_admin: 'Library Admin',
125+
library_author: 'Library Author',
126+
library_contributor: 'Library Contributor',
127+
library_user: 'Library User',
128+
course_admin: 'Course Admin',
129+
course_staff: 'Course Staff',
130+
course_editor: 'Course Editor',
131+
course_auditor: 'Course Auditor',
132+
'django.superuser': 'Super Admin',
133+
'django.globalstaff': 'Global Staff',
134+
};
135+
136+
export const DJANGO_MANAGED_ROLES = ['django.superuser', 'django.globalstaff'];

0 commit comments

Comments
 (0)