Skip to content

Commit

Permalink
chore: Migrate deprecated Table to DataTable for PastWeekPassedLearne…
Browse files Browse the repository at this point in the history
…rsTable
  • Loading branch information
zwidekalanga committed Sep 12, 2024
1 parent ec24029 commit af7103f
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import {
useCallback, useMemo, useRef, useState,
} from 'react';
import { camelCaseObject } from '@edx/frontend-platform/utils';
import debounce from 'lodash.debounce';
import { logError } from '@edx/frontend-platform/logging';
import { sendEnterpriseTrackEvent } from '@edx/frontend-enterprise-utils';
import EnterpriseDataApiService from '../../../../data/services/EnterpriseDataApiService';
import EVENT_NAMES from '../../../../eventTracking';

const applySortByToOptions = (sortBy, options) => {
if (!sortBy || sortBy.length === 0) {
return;
}
const apiFieldsForColumnAccessor = {
userEmail: { key: 'user_email' },
CourseTitle: { key: 'course_title' },
PassedDate: { key: 'passed_date' },
};
const orderingStrings = sortBy.map(({ id, desc }) => {
const apiFieldForColumnAccessor = apiFieldsForColumnAccessor[id];
if (!apiFieldForColumnAccessor) {
return undefined;
}
const apiFieldKey = apiFieldForColumnAccessor.key;
return desc ? `-${apiFieldKey}` : apiFieldKey;
}).filter(orderingString => !!orderingString);
Object.assign(options, {
ordering: orderingStrings.join(','),
});
};

const usePastWeekPassedLearners = (enterpriseId) => {
const shouldTrackFetchEvents = useRef(false);
const [isLoading, setIsLoading] = useState(true);
const [pastWeekPassedLearners, setPastWeekPassedLearners] = useState({
itemCount: 0,
pageCount: 0,
results: [],
});

const fetchPastWeekPassedLearners = useCallback(async (args) => {
try {
setIsLoading(true);
const options = {
page: args.pageIndex + 1,
pageSize: args.pageSize,
passedDate: 'last_week',
};
applySortByToOptions(args.sortBy, options);

const response = await EnterpriseDataApiService.fetchCourseEnrollments(enterpriseId, options);
const data = camelCaseObject(response.data);
setPastWeekPassedLearners({
itemCount: data.count,
pageCount: data.numPages ?? Math.floor(data.count / options.pageSize),
results: data.results,
});

if (shouldTrackFetchEvents.current) {
// track event only after original API query to avoid sending event on initial page load. instead,
// only track event when user performs manual data operation (e.g., pagination, sort, filter) and
// send all table state as event properties.
sendEnterpriseTrackEvent(
enterpriseId,
EVENT_NAMES.PROGRESS_REPORT.DATATABLE_SORT_BY_OR_FILTER,
{
tableId: 'completed-learners-week',
...options,
},
);
} else {
// set to true to enable tracking events on future API queries
shouldTrackFetchEvents.current = true;
}
} catch (error) {
logError(error);
} finally {
setIsLoading(false);
}
}, [enterpriseId]);

const debouncedFetchPastWeekPassedLearners = useMemo(
() => debounce(fetchPastWeekPassedLearners, 300),
[fetchPastWeekPassedLearners],
);

return {
isLoading,
pastWeekPassedLearners,
fetchPastWeekPassedLearners: debouncedFetchPastWeekPassedLearners,
};
};

export default usePastWeekPassedLearners;
117 changes: 66 additions & 51 deletions src/components/PastWeekPassedLearnersTable/index.jsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,81 @@
import React from 'react';

import PropTypes from 'prop-types';
import { useIntl } from '@edx/frontend-platform/i18n';

import TableContainer from '../../containers/TableContainer';
import EnterpriseDataApiService from '../../data/services/EnterpriseDataApiService';
import { DataTable } from '@openedx/paragon';
import usePastWeekPassedLearners from './data/hooks/usePastWeekPassedLearners';
import { i18nFormatTimestamp } from '../../utils';

const PastWeekPassedLearnersTable = () => {
const intl = useIntl();
const UserEmail = ({ row }) => (
<span data-hj-suppress>{row.original.userEmail}</span>
);

const tableColumns = [
{
label: intl.formatMessage({
id: 'admin.portal.lpr.past.week.passed.learners.table.user_email.column.heading',
defaultMessage: 'Email',
description: 'Column heading for the user email column in the past week passed learners table',
}),
key: 'user_email',
columnSortable: true,
},
{
label: intl.formatMessage({
id: 'admin.portal.lpr.past.week.passed.learners.table.course_title.column.heading',
defaultMessage: 'Course Title',
description: 'Column heading for the course title column in the past week passed learners table',
}),
key: 'course_title',
columnSortable: true,
},
{
label: intl.formatMessage({
id: 'admin.portal.lpr.past.week.passed.learners.table.passed_date.column.heading',
defaultMessage: 'Passed Date',
description: 'Column heading for the passed date column in the past week passed learners table',
}),
key: 'passed_date',
columnSortable: true,
},
];
UserEmail.propTypes = {
row: PropTypes.shape({
original: PropTypes.shape({
userEmail: PropTypes.string.isRequired,
}).isRequired,
}).isRequired,
};

const formatLearnerData = learners => learners.map(learner => ({
...learner,
user_email: <span data-hj-suppress>{learner.user_email}</span>,
passed_date: i18nFormatTimestamp({ intl, timestamp: learner.passed_date }),
}));
const PastWeekPassedLearnersTable = ({ enterpriseId }) => {
const intl = useIntl();
const {
isLoading,
pastWeekPassedLearners: tableData,
fetchPastWeekPassedLearners: fetchTableData,
} = usePastWeekPassedLearners(enterpriseId);

return (
<TableContainer
id="completed-learners-week"
className="completed-learners-week"
fetchMethod={(enterpriseId, options) => EnterpriseDataApiService.fetchCourseEnrollments(
enterpriseId,
<DataTable
isSortable
manualSortBy
isPaginated
manualPagination
isLoading={isLoading}
columns={[
{
passedDate: 'last_week',
...options,
Header: intl.formatMessage({
id: 'admin.portal.lpr.past.week.passed.learners.table.user_email.column.heading',
defaultMessage: 'Email',
description: 'Column heading for the user email column in the past week passed learners table',
}),
accessor: 'userEmail',
Cell: UserEmail,
},
)}
columns={tableColumns}
formatData={formatLearnerData}
tableSortable
{
Header: intl.formatMessage({
id: 'admin.portal.lpr.past.week.passed.learners.table.course_title.column.heading',
defaultMessage: 'Course Title',
description: 'Column heading for the course title column in the past week passed learners table',
}),
accessor: 'courseTitle',
},
{
Header: intl.formatMessage({
id: 'admin.portal.lpr.past.week.passed.learners.table.passed_date.column.heading',
defaultMessage: 'Passed Date',
description: 'Column heading for the passed date column in the past week passed learners table',
}),
accessor: 'passedDate',
Cell: ({ row }) => i18nFormatTimestamp({ intl, timestamp: row.values.passedDate }),
},
]}
initialState={{
pageSize: 20, // Set this according to your requirements
pageIndex: 0,
sortBy: [{ id: 'passedDate', desc: true }],
selectedRowsOrdered: [],
}}
fetchData={fetchTableData}
data={tableData.results}
itemCount={tableData.itemCount}
pageCount={tableData.pageCount}
/>
);
};

PastWeekPassedLearnersTable.propTypes = {
enterpriseId: PropTypes.string.isRequired,
};

export default PastWeekPassedLearnersTable;
6 changes: 6 additions & 0 deletions src/eventTracking.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const SUBSCRIPTION_PREFIX = `${PROJECT_NAME}.subscriptions`;
const SETTINGS_PREFIX = `${PROJECT_NAME}.settings`;
const CONTENT_HIGHLIGHTS_PREFIX = `${PROJECT_NAME}.content_highlights`;
const LEARNER_CREDIT_MANAGEMENT_PREFIX = `${PROJECT_NAME}.learner_credit_management`;
const PROGRESS_REPORT_PREFIX = `${PROJECT_NAME}.progress_report`;

// Sub-prefixes
// Subscriptions
Expand Down Expand Up @@ -95,6 +96,10 @@ export const CONTENT_HIGHLIGHTS_EVENTS = {

const SETTINGS_ACCESS_PREFIX = `${SETTINGS_PREFIX}.ACCESS`;

export const PROGRESS_REPORT_EVENTS = {
DATATABLE_SORT_BY_OR_FILTER: `${PROGRESS_REPORT_PREFIX}.datatable.sort_by_or_filter.changed`,
};

export const SETTINGS_ACCESS_EVENTS = {
UNIVERSAL_LINK_TOGGLE: `${SETTINGS_ACCESS_PREFIX}.universal-link.toggle.clicked`,
UNIVERSAL_LINK_GENERATE: `${SETTINGS_ACCESS_PREFIX}.universal-link.generate.clicked`,
Expand Down Expand Up @@ -184,6 +189,7 @@ const EVENT_NAMES = {
SUBSCRIPTIONS: SUBSCRIPTION_EVENTS,
CONTENT_HIGHLIGHTS: CONTENT_HIGHLIGHTS_EVENTS,
LEARNER_CREDIT_MANAGEMENT: LEARNER_CREDIT_MANAGEMENT_EVENTS,
PROGRESS_REPORT: PROGRESS_REPORT_EVENTS,
};

export default EVENT_NAMES;

0 comments on commit af7103f

Please sign in to comment.