-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Migrate deprecated Table to DataTable for PastWeekPassedLearne…
…rsTable
- Loading branch information
1 parent
ec24029
commit af7103f
Showing
3 changed files
with
167 additions
and
51 deletions.
There are no files selected for viewing
95 changes: 95 additions & 0 deletions
95
src/components/PastWeekPassedLearnersTable/data/hooks/usePastWeekPassedLearners.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters