diff --git a/assets/agenda/components/AgendaCoverageExistsFilter.tsx b/assets/agenda/components/AgendaCoverageExistsFilter.tsx
index 6bcf84845..a6681ff42 100644
--- a/assets/agenda/components/AgendaCoverageExistsFilter.tsx
+++ b/assets/agenda/components/AgendaCoverageExistsFilter.tsx
@@ -5,8 +5,8 @@ import {get} from 'lodash';
import {gettext} from 'utils';
import {AgendaDropdown} from './AgendaDropdown';
-const filter = {
- label: gettext('Coverage status'),
+export const agendaCoverageStatusFilter = {
+ label: gettext('Any coverage status'),
field: 'coverage_status',
nestedField: 'coverage_status',
};
@@ -18,7 +18,7 @@ const FILTER_VALUES = {
COMPLETED: 'completed'
};
-function getActiveFilterLabel(filter: any, activeFilter: any) {
+export function getActiveFilterLabel(filter: any, activeFilter: any) {
const filterValue = get(activeFilter, `${filter.field}[0]`);
switch (filterValue) {
@@ -38,7 +38,7 @@ function getActiveFilterLabel(filter: any, activeFilter: any) {
function AgendaCoverageExistsFilter ({toggleFilter, activeFilter}: any) {
return (
toggleFilter(filter.field, FILTER_VALUES.PLANNED)}
+ onClick={() => toggleFilter(agendaCoverageStatusFilter.field, FILTER_VALUES.PLANNED)}
>{gettext('Coverage is planned')}
diff --git a/assets/agenda/components/AgendaDropdown.tsx b/assets/agenda/components/AgendaDropdown.tsx
index fb6854ee4..9a954c156 100644
--- a/assets/agenda/components/AgendaDropdown.tsx
+++ b/assets/agenda/components/AgendaDropdown.tsx
@@ -42,7 +42,7 @@ export function AgendaDropdown({
return (
0}
icon={filter.icon}
optionLabel={optionLabel}
label={getActiveFilterLabel(filter, activeFilter, isActive)}
diff --git a/assets/search/actions.ts b/assets/search/actions.ts
index 58e9b3279..250257ad4 100644
--- a/assets/search/actions.ts
+++ b/assets/search/actions.ts
@@ -182,6 +182,12 @@ export function resetFilter(filter?: any) {
};
}
+export const CLEAR_QUICK_FILTER = 'CLEAR_QUICK_FILTER';
+export function clearQuickFilter(filter?: string) {
+ return {type: CLEAR_QUICK_FILTER, filter};
+}
+
+
export const SET_VIEW = 'SET_VIEW';
export function setView(view: any) {
localStorage.setItem('view', view);
diff --git a/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx b/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
index 8c008a6a1..62fcd54f1 100644
--- a/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
+++ b/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
@@ -3,7 +3,7 @@ import * as React from 'react';
import {SearchResultsTopicRow} from './SearchResultsTopicRow';
import {SearchResultsQueryRow} from './SearchResultsQueryRow';
import {SearchResultsAdvancedSearchRow} from './SearchResultsAdvancedSearchRow';
-import {SearchResultsFiltersRow} from './SearchResultsFiltersRow';
+import SearchResultsFiltersRow from './SearchResultsFiltersRow';
import {IFilterGroup, INavigation, ISearchFields, ISearchParams, ITopic, IUser} from 'interfaces';
import {SearchResultTagList} from './SearchResultTagList';
import {gettext} from 'utils';
@@ -34,6 +34,7 @@ export interface IProps {
saveMyTopic?: (params: ISearchParams) => void;
deselectMyTopic?: (topicId: ITopic['_id']) => void;
+ clearQuickFilter: (filter: string) => void;
}
export function SearchResultTagsList({
@@ -58,6 +59,7 @@ export function SearchResultTagsList({
deselectMyTopic,
resetFilter,
refresh,
+ clearQuickFilter,
}: IProps) {
return (
;
+> & {clearQuickFilter: (filter: string) => void;};
+
+type IActiveFilter = {
+ calendar?: any;
+ location?: any;
+ region?: any;
+ coverage_type?: any;
+ coverage_status?: any;
+};
+
+type IActiveFilterUnionType = keyof IActiveFilter;
+
+interface IReduxStateProps {
+ itemTypeFilter?: string;
+ activeFilter?: IActiveFilter;
+}
+
+interface IReduxDispatchProps {
+ clearItemTypeFilter: () => void;
+}
+
+type IPropsAgendaExtended = IReduxDispatchProps & IReduxStateProps & IProps;
-export function SearchResultsFiltersRow({readonly, searchParams, filterGroups, toggleFilter, setCreatedFilter, resetFilter}: IProps) {
+function SearchResultsFiltersRow({
+ readonly,
+ searchParams,
+ filterGroups,
+ toggleFilter,
+ setCreatedFilter,
+ resetFilter,
+ itemTypeFilter,
+ clearItemTypeFilter,
+ activeFilter,
+ clearQuickFilter,
+}: IPropsAgendaExtended) {
const tags = [];
+ /**
+ * FIXME: This is a bad implementation, but the proper fix would be too time consuming at this moment.
+ * Ideally we would want to unify the searchParameters so they are stored in the same variable both from
+ * agenda and wire. Another solution would be to not reuse the same component in wire and agenda filters
+ * so that wire has its own filter component and agenda has a separate one. The first solution is the better
+ * one since from a UI stand point the filters component is identical and should be reused ideally.
+ */
+ if (IS_AGENDA) {
+ if (itemTypeFilter != null) {
+ tags.push(
+ {
+ event.preventDefault();
+ clearItemTypeFilter();
+ }}
+ />
+ );
+ }
+
+ Object.keys(activeFilter ?? {}).filter((filter) => activeFilter?.[filter as IActiveFilterUnionType] != null)
+ .forEach((filter) => {
+ tags.push(
+ {
+ event.preventDefault();
+ clearQuickFilter(filter);
+ }}
+ />
+ );
+ });
+ }
+
if (searchParams.created) {
const created = getCreatedSearchParamLabel(searchParams.created);
@@ -81,7 +160,7 @@ export function SearchResultsFiltersRow({readonly, searchParams, filterGroups, t
}
}
- if (searchParams.filter != null) {
+ if (searchParams.filter != null && IS_AGENDA !== true) {
for (const field in searchParams.filter) {
const group = filterGroups[field];
@@ -129,6 +208,7 @@ export function SearchResultsFiltersRow({readonly, searchParams, filterGroups, t
onClick={(event) => {
event.preventDefault();
resetFilter();
+ clearItemTypeFilter?.();
}}
>
{gettext('Clear filters')}
@@ -145,10 +225,19 @@ export function SearchResultsFiltersRow({readonly, searchParams, filterGroups, t
);
}
-SearchResultsFiltersRow.propTypes = {
- searchParams: PropTypes.object,
- filterGroups: PropTypes.object,
- toggleFilter: PropTypes.func.isRequired,
- setCreatedFilter: PropTypes.func.isRequired,
- resetFilter: PropTypes.func.isRequired,
-};
+const mapStateToProps = (state: any) => ({
+ itemTypeFilter: state.agenda.itemType,
+ activeFilter: searchFilterSelector(state),
+});
+
+const mapDispatchToProps = (dispatch: any) => ({
+ clearItemTypeFilter: () => dispatch(setItemTypeFilter(null)),
+});
+
+let component: React.ComponentType = SearchResultsFiltersRow as React.ComponentType;
+
+if (IS_AGENDA) {
+ component = connect(mapStateToProps, mapDispatchToProps)(SearchResultsFiltersRow);
+}
+
+export default component;
diff --git a/assets/search/components/SearchResultsBar/index.tsx b/assets/search/components/SearchResultsBar/index.tsx
index 326b817f6..f641d615d 100644
--- a/assets/search/components/SearchResultsBar/index.tsx
+++ b/assets/search/components/SearchResultsBar/index.tsx
@@ -16,6 +16,7 @@ import {
clearAdvancedSearchParams,
resetFilter,
deselectMyTopic,
+ clearQuickFilter,
} from '../../actions';
import {Dropdown} from './../../../components/Dropdown';
@@ -196,6 +197,7 @@ class SearchResultsBarComponent extends React.Component {
)}
{!isTagSectionShown ? null : (
= connect(mapStateToProps, mapDispatchToProps)(SearchResultsBarComponent);
diff --git a/assets/search/components/TopicForm.tsx b/assets/search/components/TopicForm.tsx
index b6aa37047..eb30f431b 100644
--- a/assets/search/components/TopicForm.tsx
+++ b/assets/search/components/TopicForm.tsx
@@ -12,6 +12,7 @@ import {FormSection} from 'components/FormSection';
import {SearchResultTagsList} from './SearchResultsBar/SearchResultTagsList';
import {TopicFolderEditor} from './TopicFolderEditor';
+import {noop} from 'lodash';
const TOPIC_NAME_MAXLENGTH = 30;
@@ -178,7 +179,7 @@ const TopicForm: React.FC = ({
{newFolder != null && (
-
@@ -254,8 +255,10 @@ const TopicForm: React.FC
= ({