Skip to content

Commit

Permalink
feat: lpr budgets filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
muhammad-ammar committed Oct 23, 2024
1 parent 888fb6b commit 8a30273
Show file tree
Hide file tree
Showing 14 changed files with 2,555 additions and 165 deletions.
31 changes: 31 additions & 0 deletions src/components/Admin/Admin.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ const store = mockStore({
loading: null,
insights: null,
},
enterpriseBudgets: {
loading: null,
budgets: null,
},
});

const AdminWrapper = props => (
Expand All @@ -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={() => {}}
/>
</IntlProvider>
</Provider>
Expand All @@ -97,6 +107,7 @@ describe('<Admin />', () => {
lastUpdatedDate: '2018-07-31T23:14:35Z',
numberOfUsers: 3,
insights: null,
budgets: [],
};

describe('renders correctly', () => {
Expand Down Expand Up @@ -370,6 +381,26 @@ describe('<Admin />', () => {
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((
<AdminWrapper
{...baseProps}
budgets={budgets}
/>
))
.toJSON();

expect(tree).toMatchSnapshot();
});
});
});

describe('handle changes to enterpriseId prop', () => {
Expand Down
64 changes: 60 additions & 4 deletions src/components/Admin/AdminSearchForm.jsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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();
}
}
Expand All @@ -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 (
<div className="row">
Expand Down Expand Up @@ -151,7 +170,7 @@ class AdminSearchForm extends React.Component {
</Form.Control>
</Form.Group>
</div>
<div className="col-12 col-md-6 my-2 my-md-0 px-0 px-md-2 px-lg-3">
<div className={classNames('col-12 my-2 my-md-0 px-0 px-md-2 px-lg-3', columnWidth)}>
<Form.Label id="search-email-label" className="mb-2">
<FormattedMessage
id="admin.portal.lpr.filter.by.email.input.label"
Expand All @@ -176,6 +195,41 @@ class AdminSearchForm extends React.Component {
inputProps={{ 'data-hj-suppress': true }}
/>
</div>
{budgets?.length && (
<div className="col-12 col-md-3 my-2 my-md-0 px-0 px-md-2 px-lg-3">
<Form.Group>
<Form.Label className="search-label mb-2">
<FormattedMessage
id="admin.portal.lpr.filter.by.budget.dropdown.label"
defaultMessage="Filter by budget"
description="Label for the budget filter dropdown in the admin portal LPR page."
/>
</Form.Label>
<Form.Control
className="w-100 budgets-dropdown"
as="select"
value={searchBudgetQuery}
onChange={e => this.onBudgetSelect(e)}
>
<option value="">
{intl.formatMessage({
id: 'admin.portal.lpr.filter.by.budget.dropdown.option.all.budgets',
defaultMessage: 'All budgets',
description: 'Label for the all budgets option in the budget filter dropdown in the admin portal LPR page.',
})}
</option>
{budgets.map(budget => (
<option
value={budget.subsidy_access_policy_uuid}
key={budget.subsidy_access_policy_uuid}
>
{budget.subsidy_access_policy_display_name}
</option>
))}
</Form.Control>
</Form.Group>
</div>
)}
</div>
</div>
</div>
Expand All @@ -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,
Expand Down
33 changes: 33 additions & 0 deletions src/components/Admin/AdminSearchForm.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ 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'),
useLocation: jest.fn(),
useNavigate: jest.fn(),
}));

jest.mock('../../utils', () => ({
updateUrl: jest.fn(),
}));

const DEFAULT_PROPS = {
searchEnrollmentsList: () => {},
searchParams: {},
Expand Down Expand Up @@ -48,4 +53,32 @@ describe('<AdminSearchForm />', () => {
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(
<AdminSearchFormWrapper {...props} />,
);
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,
},
);
});
});
Loading

0 comments on commit 8a30273

Please sign in to comment.