diff --git a/src/components/Admin/__snapshots__/Admin.test.jsx.snap b/src/components/Admin/__snapshots__/Admin.test.jsx.snap index 93e82b2841..f7f4b78f98 100644 --- a/src/components/Admin/__snapshots__/Admin.test.jsx.snap +++ b/src/components/Admin/__snapshots__/Admin.test.jsx.snap @@ -1621,7 +1621,7 @@ exports[` renders correctly with dashboard analytics data renders # cou > Filter by course @@ -1630,7 +1630,7 @@ exports[` renders correctly with dashboard analytics data renders # cou > renders correctly with dashboard analytics data renders # cou > Filter by start date @@ -1688,7 +1688,7 @@ exports[` renders correctly with dashboard analytics data renders # cou renders correctly with dashboard analytics data renders # cou > renders correctly with dashboard analytics data renders # cou className="form-control" data-hj-suppress={true} disabled={false} - id="pgn-searchfield-input-19" + id="pgn-searchfield-input-22" name="searchfield-input" onBlur={[Function]} onChange={[Function]} @@ -1811,7 +1811,7 @@ exports[` renders correctly with dashboard analytics data renders # cou > renders correctly with dashboard analytics data renders # cou renders correctly with dashboard analytics data renders # of > Filter by course @@ -3175,7 +3175,7 @@ exports[` renders correctly with dashboard analytics data renders # of > renders correctly with dashboard analytics data renders # of > Filter by start date @@ -3233,7 +3233,7 @@ exports[` renders correctly with dashboard analytics data renders # of renders correctly with dashboard analytics data renders # of > renders correctly with dashboard analytics data renders # of className="form-control" data-hj-suppress={true} disabled={false} - id="pgn-searchfield-input-54" + id="pgn-searchfield-input-62" name="searchfield-input" onBlur={[Function]} onChange={[Function]} @@ -3356,7 +3356,7 @@ exports[` renders correctly with dashboard analytics data renders # of > renders correctly with dashboard analytics data renders # of renders correctly with dashboard analytics data renders # of > Filter by course @@ -4720,7 +4720,7 @@ exports[` renders correctly with dashboard analytics data renders # of > renders correctly with dashboard analytics data renders # of > Filter by start date @@ -4778,7 +4778,7 @@ exports[` renders correctly with dashboard analytics data renders # of renders correctly with dashboard analytics data renders # of > renders correctly with dashboard analytics data renders # of className="form-control" data-hj-suppress={true} disabled={false} - id="pgn-searchfield-input-61" + id="pgn-searchfield-input-70" name="searchfield-input" onBlur={[Function]} onChange={[Function]} @@ -4901,7 +4901,7 @@ exports[` renders correctly with dashboard analytics data renders # of > renders correctly with dashboard analytics data renders # of renders correctly with dashboard analytics data renders colla > Filter by course @@ -6265,7 +6265,7 @@ exports[` renders correctly with dashboard analytics data renders colla > renders correctly with dashboard analytics data renders colla > Filter by start date @@ -6323,7 +6323,7 @@ exports[` renders correctly with dashboard analytics data renders colla renders correctly with dashboard analytics data renders colla > renders correctly with dashboard analytics data renders colla className="form-control" data-hj-suppress={true} disabled={false} - id="pgn-searchfield-input-68" + id="pgn-searchfield-input-78" name="searchfield-input" onBlur={[Function]} onChange={[Function]} @@ -6446,7 +6446,7 @@ exports[` renders correctly with dashboard analytics data renders colla > renders correctly with dashboard analytics data renders colla renders correctly with dashboard analytics data renders full > Filter by course @@ -7810,7 +7810,7 @@ exports[` renders correctly with dashboard analytics data renders full > renders correctly with dashboard analytics data renders full > Filter by start date @@ -7868,7 +7868,7 @@ exports[` renders correctly with dashboard analytics data renders full renders correctly with dashboard analytics data renders full > renders correctly with dashboard analytics data renders full className="form-control" data-hj-suppress={true} disabled={false} - id="pgn-searchfield-input-5" + id="pgn-searchfield-input-6" name="searchfield-input" onBlur={[Function]} onChange={[Function]} @@ -7991,7 +7991,7 @@ exports[` renders correctly with dashboard analytics data renders full > renders correctly with dashboard analytics data renders full renders correctly with dashboard analytics data renders inact > Filter by course @@ -9355,7 +9355,7 @@ exports[` renders correctly with dashboard analytics data renders inact > renders correctly with dashboard analytics data renders inact > Filter by start date @@ -9413,7 +9413,7 @@ exports[` renders correctly with dashboard analytics data renders inact renders correctly with dashboard analytics data renders inact > renders correctly with dashboard analytics data renders inact className="form-control" data-hj-suppress={true} disabled={false} - id="pgn-searchfield-input-47" + id="pgn-searchfield-input-54" name="searchfield-input" onBlur={[Function]} onChange={[Function]} @@ -9536,7 +9536,7 @@ exports[` renders correctly with dashboard analytics data renders inact > renders correctly with dashboard analytics data renders inact renders correctly with dashboard analytics data renders inact > Filter by course @@ -10900,7 +10900,7 @@ exports[` renders correctly with dashboard analytics data renders inact > renders correctly with dashboard analytics data renders inact > Filter by start date @@ -10958,7 +10958,7 @@ exports[` renders correctly with dashboard analytics data renders inact renders correctly with dashboard analytics data renders inact > renders correctly with dashboard analytics data renders inact className="form-control" data-hj-suppress={true} disabled={false} - id="pgn-searchfield-input-40" + id="pgn-searchfield-input-46" name="searchfield-input" onBlur={[Function]} onChange={[Function]} @@ -11081,7 +11081,7 @@ exports[` renders correctly with dashboard analytics data renders inact > renders correctly with dashboard analytics data renders inact renders correctly with dashboard analytics data renders learn > Filter by course @@ -12445,7 +12445,7 @@ exports[` renders correctly with dashboard analytics data renders learn > renders correctly with dashboard analytics data renders learn > Filter by start date @@ -12503,7 +12503,7 @@ exports[` renders correctly with dashboard analytics data renders learn renders correctly with dashboard analytics data renders learn > renders correctly with dashboard analytics data renders learn className="form-control" data-hj-suppress={true} disabled={false} - id="pgn-searchfield-input-26" + id="pgn-searchfield-input-30" name="searchfield-input" onBlur={[Function]} onChange={[Function]} @@ -12626,7 +12626,7 @@ exports[` renders correctly with dashboard analytics data renders learn > renders correctly with dashboard analytics data renders learn renders correctly with dashboard analytics data renders regis > Filter by course @@ -13990,7 +13990,7 @@ exports[` renders correctly with dashboard analytics data renders regis > renders correctly with dashboard analytics data renders regis > Filter by start date @@ -14048,7 +14048,7 @@ exports[` renders correctly with dashboard analytics data renders regis renders correctly with dashboard analytics data renders regis > renders correctly with dashboard analytics data renders regis className="form-control" data-hj-suppress={true} disabled={false} - id="pgn-searchfield-input-12" + id="pgn-searchfield-input-14" name="searchfield-input" onBlur={[Function]} onChange={[Function]} @@ -14171,7 +14171,7 @@ exports[` renders correctly with dashboard analytics data renders regis > renders correctly with dashboard analytics data renders regis renders correctly with dashboard analytics data renders top a > Filter by course @@ -15535,7 +15535,7 @@ exports[` renders correctly with dashboard analytics data renders top a > renders correctly with dashboard analytics data renders top a > Filter by start date @@ -15593,7 +15593,7 @@ exports[` renders correctly with dashboard analytics data renders top a renders correctly with dashboard analytics data renders top a > renders correctly with dashboard analytics data renders top a className="form-control" data-hj-suppress={true} disabled={false} - id="pgn-searchfield-input-33" + id="pgn-searchfield-input-38" name="searchfield-input" onBlur={[Function]} onChange={[Function]} @@ -15716,7 +15716,7 @@ exports[` renders correctly with dashboard analytics data renders top a > renders correctly with dashboard analytics data renders top a renders correctly with dashboard insights data renders dashbo > Filter by course @@ -17129,7 +17129,7 @@ exports[` renders correctly with dashboard insights data renders dashbo > renders correctly with dashboard insights data renders dashbo > Filter by start date @@ -17187,7 +17187,7 @@ exports[` renders correctly with dashboard insights data renders dashbo renders correctly with dashboard insights data renders dashbo > renders correctly with dashboard insights data renders dashbo className="form-control" data-hj-suppress={true} disabled={false} - id="pgn-searchfield-input-86" + id="pgn-searchfield-input-100" name="searchfield-input" onBlur={[Function]} onChange={[Function]} @@ -17310,7 +17310,7 @@ exports[` renders correctly with dashboard insights data renders dashbo > renders correctly with dashboard insights data renders dashbo renders correctly with error state 1`] = ` > renders correctly with error state 1`] = ` renders correctly with loading state 1`] = ` > renders correctly with loading state 1`] = ` renders correctly with no dashboard insights data 1`] = ` > Filter by course @@ -20396,7 +20396,7 @@ exports[` renders correctly with no dashboard insights data 1`] = ` > renders correctly with no dashboard insights data 1`] = ` > Filter by start date @@ -20454,7 +20454,7 @@ exports[` renders correctly with no dashboard insights data 1`] = ` renders correctly with no dashboard insights data 1`] = ` > renders correctly with no dashboard insights data 1`] = ` className="form-control" data-hj-suppress={true} disabled={false} - id="pgn-searchfield-input-79" + id="pgn-searchfield-input-92" name="searchfield-input" onBlur={[Function]} onChange={[Function]} @@ -20577,7 +20577,7 @@ exports[` renders correctly with no dashboard insights data 1`] = ` > renders correctly with no dashboard insights data 1`] = ` - - - - - - There are no results. + + + + + + + + + + + + + + loading + + + + + + + + + + Email + + + + + + + + + + + + Account Created + + + + + + + + + + + + + + + + + Page 1, Current Page, of -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js b/src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js new file mode 100644 index 0000000000..7878c464f6 --- /dev/null +++ b/src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js @@ -0,0 +1,49 @@ +import { useCallback, useMemo, useState } from 'react'; +import { camelCaseObject } from '@edx/frontend-platform/utils'; +import debounce from 'lodash.debounce'; +import { logError } from '@edx/frontend-platform/logging'; +import EnterpriseDataApiService from '../../../../data/services/EnterpriseDataApiService'; + +const useRegisteredLearners = (enterpriseId) => { + const [isLoading, setIsLoading] = useState(true); + const [registeredLearners, setRegisteredLearners] = useState({ + itemCount: 0, + pageCount: 0, + results: [], + }); + + const fetchRegisteredLearners = useCallback(async (args) => { + try { + setIsLoading(true); + const options = { + page: args.pageIndex + 1, // `DataTable` uses zero-indexed array + pageSize: args.pageSize, + }; + const response = await EnterpriseDataApiService.fetchUnenrolledRegisteredLearners(enterpriseId, options); + const data = camelCaseObject(response.data); + + setRegisteredLearners({ + itemCount: data.count, + pageCount: data.numPages ?? Math.floor(data.count / options.pageSize), + results: data.results, + }); + } catch (error) { + logError(error); + } finally { + setIsLoading(false); + } + }, [enterpriseId]); + + const debouncedFetchRegisteredLearners = useMemo( + () => debounce(fetchRegisteredLearners, 300), + [fetchRegisteredLearners], + ); + + return { + isLoading, + registeredLearners, + fetchRegisteredLearners: debouncedFetchRegisteredLearners, + }; +}; + +export default useRegisteredLearners; diff --git a/src/components/RegisteredLearnersTable/index.jsx b/src/components/RegisteredLearnersTable/index.jsx index fefe7f95c9..dfb9e0c5c8 100644 --- a/src/components/RegisteredLearnersTable/index.jsx +++ b/src/components/RegisteredLearnersTable/index.jsx @@ -1,54 +1,74 @@ import React from 'react'; - +import PropTypes from 'prop-types'; import { useIntl } from '@edx/frontend-platform/i18n'; +import { DataTable } from '@openedx/paragon'; +import useRegisteredLearners from './data/hooks/useRegisteredLearners'; +import { i18nFormatTimestamp } from '../../utils'; -import TableContainer from '../../containers/TableContainer'; +const UserEmail = ({ row }) => ( + {row.original.user_email} +); -import { i18nFormatTimestamp } from '../../utils'; -import EnterpriseDataApiService from '../../data/services/EnterpriseDataApiService'; +UserEmail.propTypes = { + row: PropTypes.shape({ + original: PropTypes.shape({ + user_email: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, +}; -const RegisteredLearnersTable = () => { +const RegisteredLearnersTable = ({ enterpriseId }) => { const intl = useIntl(); + const { + isLoading, + registeredLearners: tableData, + fetchRegisteredLearners: fetchTableData, + } = useRegisteredLearners(enterpriseId); - const tableColumns = [ + const columns = [ { - label: intl.formatMessage({ + Header: intl.formatMessage({ id: 'admin.portal.lpr.registered.learners.table.user_email.column.heading', defaultMessage: 'Email', description: 'Column heading for the user email column in the registered learners table', }), - key: 'user_email', - columnSortable: true, + accessor: 'user_email', + Cell: UserEmail, }, { - label: intl.formatMessage({ + Header: intl.formatMessage({ id: 'admin.portal.lpr.registered.learners.table.lms_user_created.column.heading', defaultMessage: 'Account Created', description: 'Column heading for the lms user created column in the registered learners table', }), - key: 'lms_user_created', - columnSortable: true, + accessor: 'lms_user_created', + Cell: ({ row }) => i18nFormatTimestamp({ intl, timestamp: row.values.lms_user_created }), }, ]; - const formatLearnerData = learners => learners.map(learner => ({ - ...learner, - user_email: {learner.user_email}, - lms_user_created: i18nFormatTimestamp({ - intl, timestamp: learner.lms_user_created, - }), - })); - return ( - ); }; +RegisteredLearnersTable.propTypes = { + enterpriseId: PropTypes.string.isRequired, +}; + export default RegisteredLearnersTable;