Skip to content

Commit

Permalink
chore: Migrate deprecated Table to DataTable for LearnerActivityTable
Browse files Browse the repository at this point in the history
  • Loading branch information
zwidekalanga committed Aug 30, 2024
1 parent 7ac9d86 commit b93dfab
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 138 deletions.
1 change: 1 addition & 0 deletions src/components/LearnerActivityTable/data/hooks/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as useCourseEnrollments } from './useCourseEnrollments';

Check failure on line 1 in src/components/LearnerActivityTable/data/hooks/index.js

View workflow job for this annotation

GitHub Actions / tests (18)

Prefer default export on a file with single export

Check failure on line 1 in src/components/LearnerActivityTable/data/hooks/index.js

View workflow job for this annotation

GitHub Actions / tests (20)

Prefer default export on a file with single export
Original file line number Diff line number Diff line change
@@ -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);

Check warning on line 8 in src/components/LearnerActivityTable/data/hooks/useCourseEnrollments.js

View workflow job for this annotation

GitHub Actions / tests (18)

Unexpected console statement

Check warning on line 8 in src/components/LearnerActivityTable/data/hooks/useCourseEnrollments.js

View workflow job for this annotation

GitHub Actions / tests (20)

Unexpected console statement
console.log(options);

Check warning on line 9 in src/components/LearnerActivityTable/data/hooks/useCourseEnrollments.js

View workflow job for this annotation

GitHub Actions / tests (18)

Unexpected console statement

Check warning on line 9 in src/components/LearnerActivityTable/data/hooks/useCourseEnrollments.js

View workflow job for this annotation

GitHub Actions / tests (20)

Unexpected console statement
};

const applyFiltersToOptions = (filters, options) => {
console.log(filters);

Check warning on line 13 in src/components/LearnerActivityTable/data/hooks/useCourseEnrollments.js

View workflow job for this annotation

GitHub Actions / tests (18)

Unexpected console statement

Check warning on line 13 in src/components/LearnerActivityTable/data/hooks/useCourseEnrollments.js

View workflow job for this annotation

GitHub Actions / tests (20)

Unexpected console statement
console.log(options);

Check warning on line 14 in src/components/LearnerActivityTable/data/hooks/useCourseEnrollments.js

View workflow job for this annotation

GitHub Actions / tests (18)

Unexpected console statement

Check warning on line 14 in src/components/LearnerActivityTable/data/hooks/useCourseEnrollments.js

View workflow job for this annotation

GitHub Actions / tests (20)

Unexpected console statement
};

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;
1 change: 1 addition & 0 deletions src/components/LearnerActivityTable/data/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './hooks';
269 changes: 131 additions & 138 deletions src/components/LearnerActivityTable/index.jsx
Original file line number Diff line number Diff line change
@@ -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 }) => (
<span data-hj-suppress>{row.original.user_email}</span>
);

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: <span data-hj-suppress>{enrollment.user_email}</span>,
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 (
<TableContainer
id={id}
className={id}
key={id}
fetchMethod={(enterpriseId, options) => 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 (
<DataTable
isSortable
manualSortBy
isPaginated
manualPagination
isLoading={isLoading}
columns={columns}
initialState={{
pageSize: 20, // Set this according to your requirements
pageIndex: 0,
sortBy: [{ id: 'last_activity_date', desc: true }],
}}
fetchData={fetchTableData}
data={tableData.results}
itemCount={tableData.itemCount}
pageCount={tableData.pageCount}
/>
);
};

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;

0 comments on commit b93dfab

Please sign in to comment.