diff --git a/src/containers/ListView/FilterStatusComponent.jsx b/src/containers/ListView/FilterStatusComponent.jsx
new file mode 100644
index 0000000..e6a2a69
--- /dev/null
+++ b/src/containers/ListView/FilterStatusComponent.jsx
@@ -0,0 +1,65 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Button, DataTableContext } from '@edx/paragon';
+
+import * as module from './FilterStatusComponent';
+
+export const filterHooks = () => {
+ const { state, setAllFilters, headers } = React.useContext(DataTableContext);
+ if (!setAllFilters || !state.filters) {
+ return {};
+ }
+ const clearFilters = React.useCallback(() => setAllFilters([]), []);
+ const headerMap = headers.reduce(
+ (obj, cur) => ({ ...obj, [cur.id]: cur.Header }),
+ {},
+ );
+ const filterNames = state.filters.map((filter) => headerMap[filter.id]);
+ return { clearFilters, filterNames };
+};
+
+export const FilterStatusComponent = ({
+ className,
+ variant,
+ size,
+ clearFiltersText,
+ buttonClassName,
+ showFilteredFields,
+}) => {
+ const { clearFilters, filterNames } = module.filterHooks();
+ if (!clearFilters) {
+ return null;
+ }
+ const filterTexts =
Filtered by {filterNames.join(', ')}
;
+ return (
+
+ {showFilteredFields && filterTexts}
+
+
+ );
+};
+
+FilterStatusComponent.defaultProps = {
+ className: '',
+ buttonClassName: 'pgn__smart-status-button',
+ variant: 'link',
+ size: 'inline',
+ clearFiltersText: 'Clear Filters',
+ showFilteredFields: true,
+};
+
+FilterStatusComponent.propTypes = {
+ className: PropTypes.string,
+ buttonClassName: PropTypes.string,
+ variant: PropTypes.string,
+ size: PropTypes.string,
+ clearFiltersText: PropTypes.string,
+ showFilteredFields: PropTypes.bool,
+};
diff --git a/src/containers/ListView/FilterStatusComponent.test.jsx b/src/containers/ListView/FilterStatusComponent.test.jsx
new file mode 100644
index 0000000..7157ff2
--- /dev/null
+++ b/src/containers/ListView/FilterStatusComponent.test.jsx
@@ -0,0 +1,80 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import * as module from './FilterStatusComponent';
+
+const mockFilterHooks = {
+ clearFilters: jest.fn().mockName('clearFilters'),
+ filterNames: ['some abitary', 'column'],
+};
+
+const mockSetAllFilters = jest.fn().mockName('setAllFilters');
+
+describe('FilterStatusComponent component', () => {
+ const props = {
+ className: 'css-class-name',
+ variant: 'button-variant',
+ size: 'button-size',
+ clearFiltersText: 'clear-filter-text',
+ buttonClassName: 'css-class-name-for-button',
+ showFilteredFields: true,
+ };
+
+ const contextProps = {
+ state: {
+ filters: [
+ {
+ id: 'filter-column',
+ value: 'abitary',
+ },
+ ],
+ },
+ setAllFilters: () => mockSetAllFilters,
+ headers: [
+ {
+ id: 'filter-column',
+ Header: 'Formatted Filter Column',
+ },
+ {
+ id: 'dummy-column',
+ Header: 'Not showing column',
+ },
+ ],
+ };
+ const { FilterStatusComponent } = module;
+ describe('snapshot', () => {
+ test('with filter', () => {
+ jest.spyOn(module, 'filterHooks').mockImplementationOnce(() => mockFilterHooks);
+ const el = shallow();
+ expect(el).toMatchSnapshot();
+ });
+
+ test('with filter but do not show filterd field', () => {
+ jest.spyOn(module, 'filterHooks').mockImplementationOnce(() => mockFilterHooks);
+ const el = shallow();
+ expect(el).toMatchSnapshot();
+ });
+
+ test('without filter', () => {
+ jest.spyOn(module, 'filterHooks').mockImplementationOnce(() => ({}));
+ const el = shallow();
+ expect(el).toMatchSnapshot();
+ });
+ });
+
+ describe('component', () => {
+ test('clear filter click', () => {
+ jest.spyOn(module, 'filterHooks').mockImplementationOnce(() => mockFilterHooks);
+ const el = shallow();
+ el.find('Button').simulate('click');
+ expect(mockFilterHooks.clearFilters).toHaveBeenCalledTimes(1);
+ });
+
+ test('on clear filter, set all filter get called with empty array', () => {
+ jest.spyOn(React, 'useContext').mockImplementationOnce(() => ({ ...contextProps }));
+ jest.spyOn(React, 'useCallback').mockImplementationOnce(cb => cb());
+ const el = shallow();
+ el.find('Button').simulate('click');
+ expect(mockSetAllFilters).toHaveBeenCalledTimes(1);
+ });
+ });
+});
diff --git a/src/containers/ListView/SubmissionsTable.jsx b/src/containers/ListView/SubmissionsTable.jsx
index fe4f2a6..e970402 100644
--- a/src/containers/ListView/SubmissionsTable.jsx
+++ b/src/containers/ListView/SubmissionsTable.jsx
@@ -15,6 +15,7 @@ import lmsMessages from 'data/services/lms/messages';
import { selectors, thunkActions } from 'data/redux';
import StatusBadge from 'components/StatusBadge';
+import FilterStatusComponent from './FilterStatusComponent';
import messages from './messages';
@@ -89,6 +90,7 @@ export class SubmissionsTable extends React.Component {
return (
jest.fn().mockName('FilterStatusComponent'));
+
jest.mock('data/redux', () => ({
selectors: {
app: {
diff --git a/src/containers/ListView/__snapshots__/FilterStatusComponent.test.jsx.snap b/src/containers/ListView/__snapshots__/FilterStatusComponent.test.jsx.snap
new file mode 100644
index 0000000..b2fc489
--- /dev/null
+++ b/src/containers/ListView/__snapshots__/FilterStatusComponent.test.jsx.snap
@@ -0,0 +1,37 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`FilterStatusComponent component snapshot with filter 1`] = `
+
+
+ Filtered by
+ some abitary, column
+
+
+
+`;
+
+exports[`FilterStatusComponent component snapshot with filter but do not show filterd field 1`] = `
+
+
+
+`;
+
+exports[`FilterStatusComponent component snapshot without filter 1`] = `""`;
diff --git a/src/containers/ListView/__snapshots__/SubmissionsTable.test.jsx.snap b/src/containers/ListView/__snapshots__/SubmissionsTable.test.jsx.snap
index 5bd942a..c6818f6 100644
--- a/src/containers/ListView/__snapshots__/SubmissionsTable.test.jsx.snap
+++ b/src/containers/ListView/__snapshots__/SubmissionsTable.test.jsx.snap
@@ -4,6 +4,7 @@ exports[`SubmissionsTable component component render tests snapshots snapshot: e
exports[`SubmissionsTable component component render tests snapshots snapshot: happy path 1`] = `
({
export const mapDispatchToProps = {
setShowReview: actions.app.setShowReview,
stopGrading: thunkActions.grading.cancelGrading,
- reloadSubmissions: thunkActions.app.reloadSubmissions,
+ reloadSubmissions: thunkActions.app.initialize,
};
export default connect(mapStateToProps, mapDispatchToProps)(ReviewModal);