diff --git a/src/components/ReportingConfig/index.jsx b/src/components/ReportingConfig/index.jsx index 5108504f0f..b9db86955d 100644 --- a/src/components/ReportingConfig/index.jsx +++ b/src/components/ReportingConfig/index.jsx @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Collapsible, Icon } from '@openedx/paragon'; +import { Collapsible, Icon, Pagination } from '@openedx/paragon'; import { Check, Close } from '@openedx/paragon/icons'; import { camelCaseObject } from '@edx/frontend-platform'; import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n'; @@ -12,6 +12,7 @@ import LoadingMessage from '../LoadingMessage'; import ErrorPage from '../ErrorPage'; const STATUS_FULFILLED = 'fulfilled'; +const DEFAULT_PAGE_SIZE = 10; class ReportingConfig extends React.Component { // eslint-disable-next-line react/state-in-constructor @@ -33,7 +34,15 @@ class ReportingConfig extends React.Component { LMSApiService.fetchReportingConfigTypes(this.props.enterpriseId), ]) .then((responses) => { + let totalPages = responses[0].status === STATUS_FULFILLED ? responses[0].value.data.num_pages : 1; + if (!totalPages) { + totalPages = 1; + } + this.setState({ + totalPages, + currentPage: 1, + totalRecords: responses[0].status === STATUS_FULFILLED ? responses[0].value.data.count : 0, reportingConfigs: responses[0].status === STATUS_FULFILLED ? responses[0].value.data.results : undefined, availableCatalogs: responses[1].status === STATUS_FULFILLED ? responses[1].value.data.results : undefined, reportingConfigTypes: responses[2].status === STATUS_FULFILLED ? responses[2].value.data : undefined, @@ -55,13 +64,15 @@ class ReportingConfig extends React.Component { // snake_case the data before sending it to the backend const transformedData = snakeCaseFormData(formData); try { - const response = await LMSApiService.postNewReportingConfig(transformedData); - this.setState(prevState => ({ - reportingConfigs: [ - ...prevState.reportingConfigs, - response.data, - ], - })); + await LMSApiService.postNewReportingConfig(transformedData); + + const lastPageHaveSpace = this.state.totalRecords % this.state.totalPages > 0; + + if (lastPageHaveSpace || this.state.reportingConfigs.length < DEFAULT_PAGE_SIZE) { + this.handlePageSelect(this.state.totalPages); + } else { + this.handlePageSelect(this.state.totalPages + 1); + } this.newConfigFormRef.current.close(); return undefined; } catch (error) { @@ -72,18 +83,17 @@ class ReportingConfig extends React.Component { deleteConfig = async (uuid) => { try { await LMSApiService.deleteReportingConfig(uuid); - const deletedIndex = this.state.reportingConfigs - .findIndex(config => config.uuid === uuid); - - this.setState((state) => { - // Copy the existing, needs to be updated, list of reporting configs - const newReportingConfig = [...state.reportingConfigs]; - // Splice out the one that's being deleted - newReportingConfig.splice(deletedIndex, 1); - return { - reportingConfigs: newReportingConfig, - }; - }); + + const isLastPage = this.state.currentPage === this.state.totalPages; + const hasOneRecord = this.state.reportingConfigs.length === 1; + const isOnlyRecordOnLastPage = hasOneRecord && isLastPage; + + if (isOnlyRecordOnLastPage && this.state.currentPage > 1) { + this.handlePageSelect(this.state.totalPages - 1); + } else { + this.handlePageSelect(this.state.currentPage); + } + return undefined; } catch (error) { return error; @@ -111,6 +121,32 @@ class ReportingConfig extends React.Component { } }; + /** + * Handles page select event and fetches the data for the selected page + * @param {number} page - The page number to fetch data for + */ + handlePageSelect = async (page) => { + this.setState({ + loading: true, + }); + + try { + const response = await LMSApiService.fetchReportingConfigs(this.props.enterpriseId, page); + this.setState({ + totalPages: response.data.num_pages || 1, + totalRecords: response.data.count, + currentPage: page, + reportingConfigs: response.data.results, + loading: false, + }); + } catch (error) { + this.setState({ + loading: false, + error, + }); + } + }; + render() { const { reportingConfigs, @@ -118,6 +154,8 @@ class ReportingConfig extends React.Component { error, availableCatalogs, reportingConfigTypes, + currentPage, + totalPages, } = this.state; const { intl } = this.props; if (loading) { @@ -200,6 +238,17 @@ class ReportingConfig extends React.Component { ))} + + {reportingConfigs && reportingConfigs.length > 0 && ( + + )} + ', () => { const afterClickingDeleteButton = wrapper.find('button[data-testid="deleteConfigButton"]'); expect(afterClickingDeleteButton.exists()).toBe(false); }); + it('should not render Pagination when reportingConfigs is empty', async () => { + LmsApiService.fetchReportingConfigs.mockResolvedValue({ + data: { + results: [], + count: 0, + num_pages: 0, + }, + }); + + let wrapper; + await act(async () => { + wrapper = mount( + + + , + ); + }); + + wrapper.update(); + + // Check that Pagination component is not rendered when no configs + const paginationComponent = wrapper.find(Pagination); + expect(paginationComponent.exists()).toBe(false); + }); + it('should render Pagination when reportingConfigs has items', async () => { + let wrapper; + + LmsApiService.fetchReportingConfigs.mockResolvedValue({ + data: { + results: [{ + enterpriseCustomerId: 'test-customer-uuid', + active: true, + delivery_method: 'email', + uuid: 'test-config-uuid', + }], + count: 1, + num_pages: 1, + }, + }); + + await act(async () => { + wrapper = mount( + + + , + ); + }); + + wrapper.update(); + + // Check that Pagination component is rendered when configs exist + const paginationComponent = wrapper.find(Pagination); + expect(paginationComponent.exists()).toBe(true); + }); }); diff --git a/src/data/services/LmsApiService.js b/src/data/services/LmsApiService.js index 7fd5fc65e7..9e5b2f99b9 100644 --- a/src/data/services/LmsApiService.js +++ b/src/data/services/LmsApiService.js @@ -119,8 +119,13 @@ class LmsApiService { return LmsApiService.apiClient().post(requestCodesUrl, postParams); } - static fetchReportingConfigs(uuid) { - return LmsApiService.apiClient().get(`${LmsApiService.reportingConfigUrl}?enterprise_customer=${uuid}`); + static fetchReportingConfigs(uuid, pageNumber) { + let url = `${LmsApiService.reportingConfigUrl}?enterprise_customer=${uuid}`; + if (pageNumber) { + url += `&page=${pageNumber}`; + } + + return LmsApiService.apiClient().get(url); } static fetchReportingConfigTypes(uuid) {