From 8a30273fd59fbbbac5a18ac1140527cb5439b279 Mon Sep 17 00:00:00 2001 From: muhammad-ammar Date: Thu, 17 Oct 2024 11:55:39 +0500 Subject: [PATCH] feat: lpr budgets filtering --- src/components/Admin/Admin.test.jsx | 31 + src/components/Admin/AdminSearchForm.jsx | 64 +- src/components/Admin/AdminSearchForm.test.jsx | 33 + .../Admin/__snapshots__/Admin.test.jsx.snap | 2377 +++++++++++++++-- src/components/Admin/index.jsx | 12 +- src/containers/AdminPage/AdminPage.test.jsx | 4 + src/containers/AdminPage/index.jsx | 9 + src/data/actions/enterpriseBudgets.js | 41 + src/data/constants/enterpriseBudgets.js | 11 + src/data/reducers/enterpriseBudgets.js | 47 + src/data/reducers/enterpriseBudgets.test.js | 80 + src/data/reducers/index.js | 2 + src/data/services/EnterpriseDataApiService.js | 6 + src/utils.js | 3 + 14 files changed, 2555 insertions(+), 165 deletions(-) create mode 100644 src/data/actions/enterpriseBudgets.js create mode 100644 src/data/constants/enterpriseBudgets.js create mode 100644 src/data/reducers/enterpriseBudgets.js create mode 100644 src/data/reducers/enterpriseBudgets.test.js diff --git a/src/components/Admin/Admin.test.jsx b/src/components/Admin/Admin.test.jsx index c0a1105c74..0cd7685cf4 100644 --- a/src/components/Admin/Admin.test.jsx +++ b/src/components/Admin/Admin.test.jsx @@ -54,6 +54,10 @@ const store = mockStore({ loading: null, insights: null, }, + enterpriseBudgets: { + loading: null, + budgets: null, + }, }); const AdminWrapper = props => ( @@ -78,8 +82,14 @@ const AdminWrapper = props => ( pathname: '/', }} {...props} + budgets={[{ + subsidy_access_policy_uuid: '8d6503dd-e40d-42b8-442b-37dd4c5450e3', + subsidy_access_policy_display_name: 'Everything', + }]} fetchDashboardInsights={() => {}} clearDashboardInsights={() => {}} + fetchEnterpriseBudgets={() => {}} + clearEnterpriseBudgets={() => {}} /> @@ -97,6 +107,7 @@ describe('', () => { lastUpdatedDate: '2018-07-31T23:14:35Z', numberOfUsers: 3, insights: null, + budgets: [], }; describe('renders correctly', () => { @@ -370,6 +381,26 @@ describe('', () => { expect(tree).toMatchSnapshot(); }); }); + + describe('with enterprise budgets data', () => { + it('renders budgets correctly', () => { + const budgetUUID = '8d6503dd-e40d-42b8-442b-37dd4c5450e3'; + const budgets = [{ + subsidy_access_policy_uuid: budgetUUID, + subsidy_access_policy_display_name: 'Everything', + }]; + const tree = renderer + .create(( + + )) + .toJSON(); + + expect(tree).toMatchSnapshot(); + }); + }); }); describe('handle changes to enterpriseId prop', () => { diff --git a/src/components/Admin/AdminSearchForm.jsx b/src/components/Admin/AdminSearchForm.jsx index a2624cef84..e93626f166 100644 --- a/src/components/Admin/AdminSearchForm.jsx +++ b/src/components/Admin/AdminSearchForm.jsx @@ -1,6 +1,7 @@ /* eslint-disable camelcase */ import React from 'react'; import PropTypes from 'prop-types'; +import classNames from 'classnames'; import { Form } from '@openedx/paragon'; import { Info } from '@openedx/paragon/icons'; @@ -14,17 +15,22 @@ import { withLocation, withNavigate } from '../../hoc'; class AdminSearchForm extends React.Component { componentDidUpdate(prevProps) { - const { searchParams: { searchQuery, searchCourseQuery, searchDateQuery } } = this.props; + const { + searchParams: { + searchQuery, searchCourseQuery, searchDateQuery, searchBudgetQuery, + }, + } = this.props; const { searchParams: { searchQuery: prevSearchQuery, searchCourseQuery: prevSearchCourseQuery, searchDateQuery: prevSearchDateQuery, + searchBudgetQuery: prevSearchBudgetQuery, }, } = prevProps; if (searchQuery !== prevSearchQuery || searchCourseQuery !== prevSearchCourseQuery - || searchDateQuery !== prevSearchDateQuery) { + || searchDateQuery !== prevSearchDateQuery || searchBudgetQuery !== prevSearchBudgetQuery) { this.handleSearch(); } } @@ -45,14 +51,27 @@ class AdminSearchForm extends React.Component { updateUrl(navigate, location.pathname, updateParams); } + onBudgetSelect(event) { + const { navigate, location } = this.props; + const updateParams = { + budget_uuid: event.target.value, + page: 1, + }; + updateUrl(navigate, location.pathname, updateParams); + } + render() { const { intl, tableData, - searchParams: { searchCourseQuery, searchDateQuery, searchQuery }, + budgets, + searchParams: { + searchCourseQuery, searchDateQuery, searchQuery, searchBudgetQuery, + }, } = this.props; const courseTitles = Array.from(new Set(tableData.map(en => en.course_title).sort())); const courseDates = Array.from(new Set(tableData.map(en => en.course_start_date).sort().reverse())); + const columnWidth = budgets?.length ? 'col-md-3' : 'col-md-6'; return (
@@ -151,7 +170,7 @@ class AdminSearchForm extends React.Component {
-
+
+ {budgets?.length && ( +
+ + + + + this.onBudgetSelect(e)} + > + + {budgets.map(budget => ( + + ))} + + +
+ )}
@@ -193,8 +247,10 @@ AdminSearchForm.propTypes = { searchQuery: PropTypes.string, searchCourseQuery: PropTypes.string, searchDateQuery: PropTypes.string, + searchBudgetQuery: PropTypes.string, }).isRequired, tableData: PropTypes.arrayOf(PropTypes.shape({})), + budgets: PropTypes.arrayOf(PropTypes.shape({})), navigate: PropTypes.func, location: PropTypes.shape({ pathname: PropTypes.string, diff --git a/src/components/Admin/AdminSearchForm.test.jsx b/src/components/Admin/AdminSearchForm.test.jsx index 7a0d944ebf..dada76b682 100644 --- a/src/components/Admin/AdminSearchForm.test.jsx +++ b/src/components/Admin/AdminSearchForm.test.jsx @@ -5,6 +5,7 @@ import { IntlProvider } from '@edx/frontend-platform/i18n'; import AdminSearchForm from './AdminSearchForm'; import SearchBar from '../SearchBar'; +import { updateUrl } from '../../utils'; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), @@ -12,6 +13,10 @@ jest.mock('react-router-dom', () => ({ useNavigate: jest.fn(), })); +jest.mock('../../utils', () => ({ + updateUrl: jest.fn(), +})); + const DEFAULT_PROPS = { searchEnrollmentsList: () => {}, searchParams: {}, @@ -48,4 +53,32 @@ describe('', () => { expect(spy).toHaveBeenCalledTimes(1); }); }); + + it('select the correct budget', () => { + const budgetUUID = '8d6503dd-e40d-42b8-442b-37dd4c5450e3'; + const budgets = [{ + subsidy_access_policy_uuid: budgetUUID, + subsidy_access_policy_display_name: 'Everything', + }]; + const props = { + ...DEFAULT_PROPS, + budgets, + location: { pathname: '/admin/learners' }, + }; + const wrapper = mount( + , + ); + const selectElement = wrapper.find('.budgets-dropdown select'); + + selectElement.simulate('change', { target: { value: budgetUUID } }); + expect(updateUrl).toHaveBeenCalled(); + expect(updateUrl).toHaveBeenCalledWith( + undefined, + '/admin/learners', + { + budget_uuid: budgetUUID, + page: 1, + }, + ); + }); }); diff --git a/src/components/Admin/__snapshots__/Admin.test.jsx.snap b/src/components/Admin/__snapshots__/Admin.test.jsx.snap index 234d842110..5b2458ef53 100644 --- a/src/components/Admin/__snapshots__/Admin.test.jsx.snap +++ b/src/components/Admin/__snapshots__/Admin.test.jsx.snap @@ -1665,7 +1665,7 @@ exports[` renders correctly with dashboard analytics data renders # cou > @@ -1674,7 +1674,7 @@ exports[` renders correctly with dashboard analytics data renders # cou > renders correctly with dashboard analytics data renders # cou
+
+
+ +
+ +
+
+
@@ -1855,7 +1891,7 @@ exports[` renders correctly with dashboard analytics data renders # cou >