From b93dfab16ed96b31430c1c92ecfe32bf9d31c17a Mon Sep 17 00:00:00 2001 From: Cyril Nxumalo Date: Fri, 30 Aug 2024 10:15:54 +0200 Subject: [PATCH] chore: Migrate deprecated Table to DataTable for LearnerActivityTable --- .../LearnerActivityTable/data/hooks/index.js | 1 + .../data/hooks/useCourseEnrollments.js | 66 +++++ .../LearnerActivityTable/data/index.js | 1 + src/components/LearnerActivityTable/index.jsx | 269 +++++++++--------- 4 files changed, 199 insertions(+), 138 deletions(-) create mode 100644 src/components/LearnerActivityTable/data/hooks/index.js create mode 100644 src/components/LearnerActivityTable/data/hooks/useCourseEnrollments.js create mode 100644 src/components/LearnerActivityTable/data/index.js diff --git a/src/components/LearnerActivityTable/data/hooks/index.js b/src/components/LearnerActivityTable/data/hooks/index.js new file mode 100644 index 0000000000..bf41ac7da4 --- /dev/null +++ b/src/components/LearnerActivityTable/data/hooks/index.js @@ -0,0 +1 @@ +export { default as useCourseEnrollments } from './useCourseEnrollments'; diff --git a/src/components/LearnerActivityTable/data/hooks/useCourseEnrollments.js b/src/components/LearnerActivityTable/data/hooks/useCourseEnrollments.js new file mode 100644 index 0000000000..da43bddeca --- /dev/null +++ b/src/components/LearnerActivityTable/data/hooks/useCourseEnrollments.js @@ -0,0 +1,66 @@ +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 applySortByToOptions = (sortBy, options) => { + console.log(sortBy); + console.log(options); +}; + +const applyFiltersToOptions = (filters, options) => { + console.log(filters); + console.log(options); +}; + +const useCourseEnrollments = (enterpriseId, learnerActivity) => { + const [isLoading, setIsLoading] = useState(true); + const [courseEnrollments, setCourseEnrollments] = useState({ + itemCount: 0, + pageCount: 0, + results: [], + }); + + const fetchCourseEnrollments = useCallback(async (args) => { + try { + setIsLoading(true); + const options = { + page: args.pageIndex + 1, + pageSize: args.pageSize, + learnerActivity, + }; + if (args.sortBy?.length > 0) { + applySortByToOptions(args.sortBy, options); + } + if (args.filters?.length > 0) { + applyFiltersToOptions(args.filters, options); + } + const response = await EnterpriseDataApiService.fetchCourseEnrollments(enterpriseId, options); + const data = camelCaseObject(response.data); + + setCourseEnrollments({ + itemCount: data.count, + pageCount: data.numPages ?? Math.floor(data.count / options.pageSize), + results: data.results, + }); + } catch (error) { + logError(error); + } finally { + setIsLoading(false); + } + }, [enterpriseId, learnerActivity]); + + const debouncedFetchCourseEnrollments = useMemo( + () => debounce(fetchCourseEnrollments, 300), + [fetchCourseEnrollments], + ); + + return { + isLoading, + courseEnrollments, + fetchCourseEnrollments: debouncedFetchCourseEnrollments, + }; +}; + +export default useCourseEnrollments; diff --git a/src/components/LearnerActivityTable/data/index.js b/src/components/LearnerActivityTable/data/index.js new file mode 100644 index 0000000000..4cc90d02bd --- /dev/null +++ b/src/components/LearnerActivityTable/data/index.js @@ -0,0 +1 @@ +export * from './hooks'; diff --git a/src/components/LearnerActivityTable/index.jsx b/src/components/LearnerActivityTable/index.jsx index 114763aaa7..517419194b 100644 --- a/src/components/LearnerActivityTable/index.jsx +++ b/src/components/LearnerActivityTable/index.jsx @@ -1,153 +1,146 @@ import React from 'react'; import PropTypes from 'prop-types'; - -import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; - -import TableContainer from '../../containers/TableContainer'; +import { useIntl } from '@edx/frontend-platform/i18n'; +import { DataTable } from '@openedx/paragon'; +import { useCourseEnrollments } from './data'; import { - i18nFormatTimestamp, i18nFormatPassedTimestamp, i18nFormatProgressStatus, formatPercentage, + i18nFormatTimestamp, + i18nFormatPassedTimestamp, + i18nFormatProgressStatus, + formatPercentage, } from '../../utils'; -import EnterpriseDataApiService from '../../data/services/EnterpriseDataApiService'; -class LearnerActivityTable extends React.Component { - getTableColumns() { - const { activity, intl } = this.props; - const tableColumns = [ - { - label: intl.formatMessage({ - id: 'admin.portal.lpr.learner.activity.table.user_email.column.heading', - defaultMessage: 'Email', - description: 'Column heading for the user email column in the learner activity table', - }), - key: 'user_email', - columnSortable: true, - }, - { - label: intl.formatMessage({ - id: 'admin.portal.lpr.learner.activity.table.course_title.column.heading', - defaultMessage: 'Course Title', - description: 'Column heading for the course title column in the learner activity table', - }), - key: 'course_title', - columnSortable: true, - }, - { - label: intl.formatMessage({ - id: 'admin.portal.lpr.learner.activity.table.course_list_price.column.heading', - defaultMessage: 'Course Price', - description: 'Column heading for the course price column in the learner activity table', - }), - key: 'course_list_price', - columnSortable: true, - }, - { - label: intl.formatMessage({ - id: 'admin.portal.lpr.learner.activity.table.course_start_date.column.heading', - defaultMessage: 'Start Date', - description: 'Column heading for the course start date column in the learner activity table', - }), - key: 'course_start_date', - columnSortable: true, - }, - { - label: intl.formatMessage({ - id: 'admin.portal.lpr.learner.activity.table.course_end_date.column.heading', - defaultMessage: 'End Date', - description: 'Column heading for the course end date column in the learner activity table', - }), - key: 'course_end_date', - columnSortable: true, - }, - { - label: intl.formatMessage({ - id: 'admin.portal.lpr.learner.activity.table.passed_date.column.heading', - defaultMessage: 'Passed Date', - description: 'Column heading for the passed date column in the learner activity table', - }), - key: 'passed_date', - columnSortable: true, - }, - { - label: intl.formatMessage({ - id: 'admin.portal.lpr.learner.activity.table.current_grade.column.heading', - defaultMessage: 'Current Grade', - description: 'Column heading for the current grade column in the learner activity table', - }), - key: 'current_grade', - columnSortable: true, - }, - { - label: intl.formatMessage({ - id: 'admin.portal.lpr.learner.activity.table.progress_status.column.heading', - defaultMessage: 'Progress Status', - description: 'Column heading for the progress status column in the learner activity table', - }), - key: 'progress_status', - columnSortable: true, - }, - { - label: intl.formatMessage({ - id: 'admin.portal.lpr.learner.activity.table.enrollment_date.column.heading', - defaultMessage: 'Last Activity Date', - description: 'Column heading for the last activity date column in the learner activity table', - }), - key: 'last_activity_date', - columnSortable: true, - }, - ]; +const UserEmail = ({ row }) => ( + {row.original.user_email} +); - if (activity !== 'active_past_week') { - return tableColumns.filter(column => column.key !== 'passed_date'); - } - return tableColumns; - } +UserEmail.propTypes = { + row: PropTypes.shape({ + original: PropTypes.shape({ + user_email: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, +}; - formatTableData = enrollments => enrollments.map(enrollment => ({ - ...enrollment, - user_email: {enrollment.user_email}, - last_activity_date: i18nFormatTimestamp({ intl: this.props.intl, timestamp: enrollment.last_activity_date }), - course_start_date: i18nFormatTimestamp({ intl: this.props.intl, timestamp: enrollment.course_start_date }), - course_end_date: i18nFormatTimestamp({ intl: this.props.intl, timestamp: enrollment.course_end_date }), - enrollment_date: i18nFormatTimestamp({ - intl: this.props.intl, timestamp: enrollment.enrollment_date, - }), - passed_date: i18nFormatPassedTimestamp({ intl: this.props.intl, timestamp: enrollment.passed_date }), - user_account_creation_date: i18nFormatTimestamp({ - intl: this.props.intl, timestamp: enrollment.user_account_creation_date, - }), - progress_status: i18nFormatProgressStatus({ intl: this.props.intl, progressStatus: enrollment.progress_status }), - course_list_price: enrollment.course_list_price ? `$${enrollment.course_list_price}` : '', - current_grade: formatPercentage({ decimal: enrollment.current_grade }), - })); +const LearnerActivityTable = ({ enterpriseId, activity }) => { + const intl = useIntl(); + const { + isLoading, + enrolledLearners: tableData, + fetchEnrolledLearners: fetchTableData, + } = useCourseEnrollments(enterpriseId, { learnerActivity: activity }); - render() { - const { activity, id } = this.props; + const columns = [ + { + Header: intl.formatMessage({ + id: 'admin.portal.lpr.learner.activity.table.user_email.column.heading', + defaultMessage: 'Email', + description: 'Column heading for the user email column in the learner activity table', + }), + accessor: 'user_email', + Cell: UserEmail, + }, + { + Header: intl.formatMessage({ + id: 'admin.portal.lpr.learner.activity.table.course_title.column.heading', + defaultMessage: 'Course Title', + description: 'Column heading for the course title column in the learner activity table', + }), + accessor: 'course_title', + }, + { + Header: intl.formatMessage({ + id: 'admin.portal.lpr.learner.activity.table.course_list_price.column.heading', + defaultMessage: 'Course Price', + description: 'Column heading for the course price column in the learner activity table', + }), + accessor: 'course_list_price', + Cell: ({ row }) => (row.values.course_list_price ? `$${row.values.course_list_price}` : ''), + }, + { + Header: intl.formatMessage({ + id: 'admin.portal.lpr.learner.activity.table.course_start_date.column.heading', + defaultMessage: 'Start Date', + description: 'Column heading for the course start date column in the learner activity table', + }), + accessor: 'course_start_date', + Cell: ({ row }) => i18nFormatTimestamp({ intl, timestamp: row.values.course_start_date }), + }, + { + Header: intl.formatMessage({ + id: 'admin.portal.lpr.learner.activity.table.course_end_date.column.heading', + defaultMessage: 'End Date', + description: 'Column heading for the course end date column in the learner activity table', + }), + accessor: 'course_end_date', + Cell: ({ row }) => i18nFormatTimestamp({ intl, timestamp: row.values.course_end_date }), + }, + { + Header: intl.formatMessage({ + id: 'admin.portal.lpr.learner.activity.table.passed_date.column.heading', + defaultMessage: 'Passed Date', + description: 'Column heading for the passed date column in the learner activity table', + }), + accessor: 'passed_date', + Cell: ({ row }) => i18nFormatPassedTimestamp({ intl, timestamp: row.values.passed_date }), + }, + { + Header: intl.formatMessage({ + id: 'admin.portal.lpr.learner.activity.table.current_grade.column.heading', + defaultMessage: 'Current Grade', + description: 'Column heading for the current grade column in the learner activity table', + }), + accessor: 'current_grade', + Cell: ({ row }) => formatPercentage({ decimal: row.values.current_grade }), + }, + { + Header: intl.formatMessage({ + id: 'admin.portal.lpr.learner.activity.table.progress_status.column.heading', + defaultMessage: 'Progress Status', + description: 'Column heading for the progress status column in the learner activity table', + }), + accessor: 'progress_status', + Cell: ({ row }) => i18nFormatProgressStatus({ intl, progressStatus: row.values.progress_status }), + }, + { + Header: intl.formatMessage({ + id: 'admin.portal.lpr.learner.activity.table.enrollment_date.column.heading', + defaultMessage: 'Last Activity Date', + description: 'Column heading for the last activity date column in the learner activity table', + }), + accessor: 'last_activity_date', + Cell: ({ row }) => i18nFormatTimestamp({ intl, timestamp: row.values.last_activity_date }), + }, + ]; - return ( - EnterpriseDataApiService.fetchCourseEnrollments( - enterpriseId, - { - learnerActivity: activity, - ...options, - }, - )} - columns={this.getTableColumns()} - formatData={this.formatTableData} - tableSortable - /> - ); + if (activity !== 'active_past_week') { + columns.splice(columns.findIndex(col => col.accessor === 'passed_date'), 1); } -} + + return ( + + ); +}; LearnerActivityTable.propTypes = { - id: PropTypes.string.isRequired, + enterpriseId: PropTypes.string.isRequired, activity: PropTypes.string.isRequired, - // injected - intl: intlShape.isRequired, }; -export default injectIntl(LearnerActivityTable); +export default LearnerActivityTable;