Skip to content

Commit

Permalink
chore: Migrate deprecated Table to DataTable for RegisteredLearnersTable
Browse files Browse the repository at this point in the history
  • Loading branch information
zwidekalanga committed Sep 12, 2024
1 parent ec24029 commit 5aa50bd
Show file tree
Hide file tree
Showing 4 changed files with 398 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,245 @@

exports[`RegisteredLearnersTable renders empty state correctly 1`] = `
<div
className="fade alert-content alert alert-warning show"
role="alert"
className="pgn__data-table-layout-wrapper"
>
<span
className="pgn__icon alert-icon"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2Zm1 15h-2v-2h2v2Zm0-4h-2V7h2v6Z"
fill="currentColor"
/>
</svg>
</span>
<div
className="pgn__alert-message-wrapper"
className="pgn__data-table-layout-main"
>
<div
className="alert-message-content"
className="pgn__data-table-wrapper"
>
There are no results.
<div
className="pgn__data-table-status-bar"
data-testid="table-control-bar"
>
<div
className="pgn__data-table-status"
>
<div
className="pgn__data-table-status-left"
/>
<div
className="pgn__data-table-actions-right"
>
<div
className="pgn__data-table-toggle"
/>
<div />
</div>
</div>
</div>
<div
className="pgn__data-table-container is-loading"
data-testid="data-table-container"
>
<div
className="pgn__data-table-spinner"
data-testid="data-table-spinner"
>
<div
className="pgn__spinner spinner-border"
role="status"
>
<span
className="sr-only"
>
loading
</span>
</div>
</div>
<table
className="pgn__data-table is-striped"
role="table"
>
<thead>
<tr
role="row"
>
<th
colSpan={1}
onClick={[Function]}
role="columnheader"
style={
{
"cursor": "pointer",
}
}
title="Toggle SortBy"
>
<span
className="d-flex align-items-center"
>
<span>
Email
</span>
<span
className="pgn__icon"
data-testid="arrow-drop-up-down"
style={
{
"opacity": 0.5,
}
}
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m7 10 5-5 5 5H7ZM7 14l5 5 5-5H7Z"
fill="currentColor"
/>
</svg>
</span>
</span>
</th>
<th
colSpan={1}
onClick={[Function]}
role="columnheader"
style={
{
"cursor": "pointer",
}
}
title="Toggle SortBy"
>
<span
className="d-flex align-items-center"
>
<span>
Account Created
</span>
<span
className="pgn__icon"
data-testid="arrow-drop-down"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m7 10 5 5 5-5H7Z"
fill="currentColor"
/>
</svg>
</span>
</span>
</th>
</tr>
</thead>
<tbody
role="rowgroup"
/>
</table>
</div>
<div
className="pgn__data-table-footer"
data-testid="table-footer"
>
<nav
aria-label="table pagination"
className="pagination-minimal"
>
<div
aria-atomic={true}
aria-live="polite"
aria-relevant="text"
className="sr-only"
>
Page 1, Current Page, of -1
</div>
<ul
className="pagination"
>
<li
className="page-item disabled"
>
<button
aria-label="Previous"
className="btn-icon btn-icon-primary btn-icon-md previous page-link"
disabled={true}
onClick={[Function]}
tabIndex="-1"
type="button"
>
<span
className="btn-icon__icon-container"
>
<span
className="pgn__icon btn-icon__icon"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17.51 3.87 15.73 2.1 5.84 12l9.9 9.9 1.77-1.77L9.38 12l8.13-8.13Z"
fill="currentColor"
/>
</svg>
</span>
</span>
</button>
</li>
<li
className="page-item disabled"
>
<button
aria-label="Next, Page 2"
className="btn-icon btn-icon-primary btn-icon-md next page-link"
disabled={true}
onClick={[Function]}
tabIndex="-1"
type="button"
>
<span
className="btn-icon__icon-container"
>
<span
className="pgn__icon btn-icon__icon"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m6.49 20.13 1.77 1.77 9.9-9.9-9.9-9.9-1.77 1.77L14.62 12l-8.13 8.13Z"
fill="currentColor"
/>
</svg>
</span>
</span>
</button>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
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;

Check warning on line 13 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L13

Added line #L13 was not covered by tests
}
const apiFieldsForColumnAccessor = {

Check warning on line 15 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L15

Added line #L15 was not covered by tests
lmsUserCreated: { key: 'lms_user_created' },
userEmail: { key: 'user_email' },
};
const orderingStrings = sortBy.map(({ id, desc }) => {
const apiFieldForColumnAccessor = apiFieldsForColumnAccessor[id];

Check warning on line 20 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L19-L20

Added lines #L19 - L20 were not covered by tests
if (!apiFieldForColumnAccessor) {
return undefined;

Check warning on line 22 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L22

Added line #L22 was not covered by tests
}
const apiFieldKey = apiFieldForColumnAccessor.key;

Check warning on line 24 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L24

Added line #L24 was not covered by tests
return desc ? `-${apiFieldKey}` : apiFieldKey;
}).filter(orderingString => !!orderingString);
Object.assign(options, {

Check warning on line 27 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L26-L27

Added lines #L26 - L27 were not covered by tests
ordering: orderingStrings.join(','),
});
};

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

const fetchRegisteredLearners = useCallback(async (args) => {
try {
setIsLoading(true);
const options = {

Check warning on line 44 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L42-L44

Added lines #L42 - L44 were not covered by tests
page: args.pageIndex + 1, // `DataTable` uses zero-indexed array
pageSize: args.pageSize,
};
applySortByToOptions(args.sortBy, options);

Check warning on line 48 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L48

Added line #L48 was not covered by tests

const response = await EnterpriseDataApiService.fetchUnenrolledRegisteredLearners(enterpriseId, options);
const data = camelCaseObject(response.data);
setRegisteredLearners({

Check warning on line 52 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L50-L52

Added lines #L50 - L52 were not covered by tests
itemCount: data.count,
pageCount: data.numPages ?? Math.floor(data.count / options.pageSize),

Check warning on line 54 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L54

Added line #L54 was not covered by tests
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(

Check warning on line 62 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L62

Added line #L62 was not covered by tests
enterpriseId,
EVENT_NAMES.PROGRESS_REPORT.DATATABLE_SORT_BY_OR_FILTER,
{
tableId: 'registered-unenrolled-learners',
...options,
},
);
} else {

Check warning on line 70 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L70

Added line #L70 was not covered by tests
// set to true to enable tracking events on future API queries
shouldTrackFetchEvents.current = true;

Check warning on line 72 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L72

Added line #L72 was not covered by tests
}
} catch (error) {
logError(error);

Check warning on line 75 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L75

Added line #L75 was not covered by tests
} finally {
setIsLoading(false);

Check warning on line 77 in src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js

View check run for this annotation

Codecov / codecov/patch

src/components/RegisteredLearnersTable/data/hooks/useRegisteredLearners.js#L77

Added line #L77 was not covered by tests
}
}, [enterpriseId]);

const debouncedFetchRegisteredLearners = useMemo(
() => debounce(fetchRegisteredLearners, 300),
[fetchRegisteredLearners],
);

return {
isLoading,
registeredLearners,
fetchRegisteredLearners: debouncedFetchRegisteredLearners,
};
};

export default useRegisteredLearners;
Loading

0 comments on commit 5aa50bd

Please sign in to comment.