From 7fde73fbe8f0c1230303e53990dfbf0b6fa7d36c Mon Sep 17 00:00:00 2001
From: thecalcc <me@kmarkov.io>
Date: Wed, 11 Oct 2023 13:11:43 +0300
Subject: [PATCH 1/6] Init

---
 assets/agenda/components/AgendaApp.tsx        |   1 +
 .../components/AgendaCoverageExistsFilter.tsx |  14 +-
 assets/agenda/components/AgendaDropdown.tsx   |   2 +-
 assets/search/actions.ts                      |   6 +
 .../SearchResultsBar/SearchResultTagsList.tsx |   2 +
 .../SearchResultsAgendaQucikFiltersRow.tsx    | 163 ++++++++++++++++++
 .../SearchResultsFiltersRow.tsx               |  11 +-
 assets/search/reducers.ts                     |  18 ++
 8 files changed, 199 insertions(+), 18 deletions(-)
 create mode 100644 assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx

diff --git a/assets/agenda/components/AgendaApp.tsx b/assets/agenda/components/AgendaApp.tsx
index 67e1fae84..5ed35a5ae 100644
--- a/assets/agenda/components/AgendaApp.tsx
+++ b/assets/agenda/components/AgendaApp.tsx
@@ -150,6 +150,7 @@ class AgendaApp extends BaseApp {
             this.props.activeQuery != null ||
             this.props.itemTypeFilter != null;
 
+        // console.log(this.props.itemTypeFilter, this.props.activeFilter);
         return (
             (this.props.itemToOpen ? [<AgendaItemDetails key="itemDetails"
                 item={this.props.itemToOpen}
diff --git a/assets/agenda/components/AgendaCoverageExistsFilter.tsx b/assets/agenda/components/AgendaCoverageExistsFilter.tsx
index 794655c91..42c7d3490 100644
--- a/assets/agenda/components/AgendaCoverageExistsFilter.tsx
+++ b/assets/agenda/components/AgendaCoverageExistsFilter.tsx
@@ -5,7 +5,7 @@ import {get} from 'lodash';
 import {gettext} from 'utils';
 import {AgendaDropdown} from './AgendaDropdown';
 
-const filter = {
+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 (
         <AgendaDropdown
-            filter={filter}
+            filter={agendaCoverageStatusFilter}
             activeFilter={activeFilter}
             toggleFilter={toggleFilter}
             getFilterLabel={getActiveFilterLabel}
@@ -47,25 +47,25 @@ function AgendaCoverageExistsFilter ({toggleFilter, activeFilter}: any) {
             <button
                 key='coverage-planned'
                 className='dropdown-item'
-                onClick={() => toggleFilter(filter.field, FILTER_VALUES.PLANNED)}
+                onClick={() => toggleFilter(agendaCoverageStatusFilter.field, FILTER_VALUES.PLANNED)}
             >{gettext('Coverage is planned')}
             </button>
             <button
                 key='coverage-not-planned'
                 className='dropdown-item'
-                onClick={() => toggleFilter(filter.field, FILTER_VALUES.NOT_PLANNED)}
+                onClick={() => toggleFilter(agendaCoverageStatusFilter.field, FILTER_VALUES.NOT_PLANNED)}
             >{gettext('Coverage not planned')}
             </button>
             <button
                 key='coverage-not-decided'
                 className='dropdown-item'
-                onClick={() => toggleFilter(filter.field, FILTER_VALUES.MAY_BE)}
+                onClick={() => toggleFilter(agendaCoverageStatusFilter.field, FILTER_VALUES.MAY_BE)}
             >{gettext('Coverage not decided')}
             </button>
             <button
                 key='coverage-completed'
                 className='dropdown-item'
-                onClick={() => toggleFilter(filter.field, FILTER_VALUES.COMPLETED)}
+                onClick={() => toggleFilter(agendaCoverageStatusFilter.field, FILTER_VALUES.COMPLETED)}
             >{gettext('Coverage completed')}
             </button>
         </AgendaDropdown>
diff --git a/assets/agenda/components/AgendaDropdown.tsx b/assets/agenda/components/AgendaDropdown.tsx
index 5c146de91..228a35141 100644
--- a/assets/agenda/components/AgendaDropdown.tsx
+++ b/assets/agenda/components/AgendaDropdown.tsx
@@ -32,7 +32,7 @@ export function AgendaDropdown({
     return (
         <Dropdown
             borderless={borderless}
-            isActive={isActive}
+            isActive={(isActive?.length ?? 0) > 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..45cea6628 100644
--- a/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
+++ b/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
@@ -8,6 +8,7 @@ import {IFilterGroup, INavigation, ISearchFields, ISearchParams, ITopic, IUser}
 import {SearchResultTagList} from './SearchResultTagList';
 import {gettext} from 'utils';
 import {getTopicUrl} from 'search/utils';
+import {SearchResultsAgendaQuickFilters} from './SearchResultsAgendaQucikFiltersRow';
 
 export interface IProps {
     user: IUser;
@@ -100,6 +101,7 @@ export function SearchResultTagsList({
                 resetFilter={resetFilter}
                 readonly={readonly}
             />
+            <SearchResultsAgendaQuickFilters />
             {readonly === true && activeTopic._id && (
                 <SearchResultTagList
                     testId="search-results--edit-button"
diff --git a/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx b/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx
new file mode 100644
index 000000000..12e6f5881
--- /dev/null
+++ b/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx
@@ -0,0 +1,163 @@
+import * as React from 'react';
+import {gettext} from 'utils';
+
+import {SearchResultTagList} from './SearchResultTagList';
+import {Tag} from 'components/Tag';
+
+import {searchFilterSelector} from 'search/selectors';
+import {connect} from 'react-redux';
+import {clearQuickFilter} from 'search/actions';
+import {agendaCoverageStatusFilter, getActiveFilterLabel} from 'agenda/components/AgendaCoverageExistsFilter';
+import {setItemTypeFilter} from 'agenda/actions';
+
+type IProps = any;
+
+function SearchResultsAgendaQuickFiltersRow({
+    itemTypeFilter,
+    activeFilter,
+    clearQuickFilter,
+    clearItemTypeFilter,
+    clearAllQuickFilters,
+}: IProps) {
+    const pills = [];
+
+    if (itemTypeFilter != null) {
+        pills.push(
+            <Tag
+                key={`tags-filters--from-${itemTypeFilter}`}
+                testId="tags-filters--agenda-quick-filters"
+                text={itemTypeFilter === 'events' ? gettext('Events Only') : gettext('Planning Only')}
+                // readOnly={readonly}
+                onClick={(event) => {
+                    event.preventDefault();
+                    clearItemTypeFilter();
+                }}
+            />
+        );
+    }
+
+    if (activeFilter?.['calendar'] != null) {
+        pills.push(
+            <Tag
+                key="tags-filters--calendar"
+                testId="tags-filters--agenda-quick-filters-calendar"
+                text={activeFilter['calendar']}
+                // readOnly={readonly}
+                onClick={(event) => {
+                    event.preventDefault();
+                    clearQuickFilter('calendar');
+                }}
+            />
+        );
+    }
+
+    if (activeFilter?.['location'] != null) {
+        pills.push(
+            <Tag
+                key="tags-filters--location"
+                testId="tags-filters--agenda-quick-filters-location"
+                text={activeFilter['location']}
+                // readOnly={readonly}
+                onClick={(event) => {
+                    event.preventDefault();
+                    clearQuickFilter('location');
+                }}
+            />
+        );
+    }
+
+    if (activeFilter?.['region'] != null) {
+        pills.push(
+            <Tag
+                key="tags-filters--region"
+                testId="tags-filters--agenda-quick-filters-region"
+                text={activeFilter['region']}
+                // readOnly={readonly}
+                onClick={(event) => {
+                    event.preventDefault();
+                    clearQuickFilter('region');
+                }}
+            />
+        );
+    }
+
+    if (activeFilter?.['coverage_type'] != null) {
+        pills.push(
+            <Tag
+                key="tags-filters--coverage_type"
+                testId="tags-filters--agenda-quick-filters-coverage_type"
+                text={activeFilter['coverage_type']}
+                // readOnly={readonly}
+                onClick={(event) => {
+                    event.preventDefault();
+                    clearQuickFilter('coverage_type');
+                }}
+            />
+        );
+    }
+
+    if (activeFilter?.['coverage_status'] != null) {
+        pills.push(
+            <Tag
+                key="tags-filters--coverage_status"
+                testId="tags-filters--agenda-quick-filters-coverage_status"
+                text={getActiveFilterLabel(agendaCoverageStatusFilter, activeFilter)}
+                // readOnly={readonly}
+                onClick={(event) => {
+                    event.preventDefault();
+                    clearQuickFilter('coverage_status');
+                }}
+            />
+        );
+    }
+
+    if ((pills?.length ?? 0) < 1) {
+        return <li>no content</li>;
+    }
+
+    pills.push(
+        <span
+            key="tags-filters-separator--clear-1"
+            className="tag-list__separator tag-list__separator--blanc"
+        />
+    );
+
+    pills.push(
+        <button
+            key="tag-filters--clear-button-1"
+            className='nh-button nh-button--tertiary nh-button--small'
+            onClick={(event) => {
+                event.preventDefault();
+                clearAllQuickFilters();
+            }}
+        >
+            {gettext('Clear filters')}
+        </button>
+    );
+
+    return (
+        <SearchResultTagList
+            testId="search-results--filters"
+            title={gettext('Quick filters')}
+            tags={pills}
+        />
+    );
+}
+
+const mapStateToProps = (state: any) => ({
+    itemTypeFilter: state.agenda.itemType,
+    activeFilter: searchFilterSelector(state),
+});
+
+const mapDispatchToProps = (dispatch: any) => ({
+    clearQuickFilter: (filter: string) => dispatch(clearQuickFilter(filter)),
+    clearItemTypeFilter: () => dispatch(setItemTypeFilter(null)),
+    clearAllQuickFilters: () => {
+        dispatch(setItemTypeFilter(null));
+        dispatch(clearQuickFilter());
+    }
+});
+
+
+export const SearchResultsAgendaQuickFilters: React.ComponentType<any> =
+    connect<any>(mapStateToProps, mapDispatchToProps)(SearchResultsAgendaQuickFiltersRow);
diff --git a/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx b/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx
index ee7cca9bc..c30f9303d 100644
--- a/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx
+++ b/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx
@@ -1,12 +1,11 @@
 import * as React from 'react';
-import PropTypes from 'prop-types';
-
 import {gettext, getCreatedSearchParamLabel} from 'utils';
 
 import {SearchResultTagList} from './SearchResultTagList';
 import {Tag} from 'components/Tag';
 
 import {IProps as IParentProps} from './SearchResultTagsList';
+import {SearchResultsAgendaQuickFilters} from './SearchResultsAgendaQucikFiltersRow';
 
 type IProps = Pick<IParentProps,
     'readonly' |
@@ -144,11 +143,3 @@ 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,
-};
diff --git a/assets/search/reducers.ts b/assets/search/reducers.ts
index 6142184de..91b9bf85f 100644
--- a/assets/search/reducers.ts
+++ b/assets/search/reducers.ts
@@ -23,6 +23,7 @@ import {
     CLEAR_ADVANCED_SEARCH_PARAMS,
     SET_ADVANCED_SEARCH_PARAMS,
     SET_SEARCH_SORT_QUERY,
+    CLEAR_QUICK_FILTER,
 } from './actions';
 
 import {EXTENDED_VIEW} from 'wire/defaults';
@@ -120,6 +121,23 @@ export function searchReducer(state=INITIAL_STATE, action?: any, context?: any)
         };
     }
 
+    case CLEAR_QUICK_FILTER:
+        if (action.filter == null) {
+            return {
+                ...state,
+                activeFilter: {},
+            };
+        }
+
+        // eslint-disable-next-line no-case-declarations
+        const updatedQuickFilters = {...state.activeFilter};
+        delete updatedQuickFilters[action.filter];
+
+        return {
+            ...state,
+            activeFilter: updatedQuickFilters,
+        };
+
     case RESET_FILTER:
         return {
             ...state,

From eb51b49d1131793db2590a12546e86826640e0fe Mon Sep 17 00:00:00 2001
From: thecalcc <me@kmarkov.io>
Date: Thu, 12 Oct 2023 14:42:47 +0300
Subject: [PATCH 2/6] Fix breaking of agenda, wire pills dropdown

---
 .../components/SearchResultsBar/SearchResultTagsList.tsx      | 4 +++-
 .../SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx   | 4 ++--
 .../components/SearchResultsBar/SearchResultsFiltersRow.tsx   | 3 +--
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx b/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
index 45cea6628..416984ae9 100644
--- a/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
+++ b/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
@@ -101,7 +101,9 @@ export function SearchResultTagsList({
                 resetFilter={resetFilter}
                 readonly={readonly}
             />
-            <SearchResultsAgendaQuickFilters />
+            {location.pathname.includes('/agenda') && (
+                <SearchResultsAgendaQuickFilters />
+            )}
             {readonly === true && activeTopic._id && (
                 <SearchResultTagList
                     testId="search-results--edit-button"
diff --git a/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx b/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx
index 12e6f5881..248ddc021 100644
--- a/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx
+++ b/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx
@@ -112,7 +112,7 @@ function SearchResultsAgendaQuickFiltersRow({
     }
 
     if ((pills?.length ?? 0) < 1) {
-        return <li>no content</li>;
+        return null;
     }
 
     pills.push(
@@ -138,7 +138,7 @@ function SearchResultsAgendaQuickFiltersRow({
     return (
         <SearchResultTagList
             testId="search-results--filters"
-            title={gettext('Quick filters')}
+            title={gettext('Quick filters applied')}
             tags={pills}
         />
     );
diff --git a/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx b/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx
index c30f9303d..2a5b8cdaa 100644
--- a/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx
+++ b/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx
@@ -5,7 +5,6 @@ import {SearchResultTagList} from './SearchResultTagList';
 import {Tag} from 'components/Tag';
 
 import {IProps as IParentProps} from './SearchResultTagsList';
-import {SearchResultsAgendaQuickFilters} from './SearchResultsAgendaQucikFiltersRow';
 
 type IProps = Pick<IParentProps,
     'readonly' |
@@ -80,7 +79,7 @@ export function SearchResultsFiltersRow({readonly, searchParams, filterGroups, t
         }
     }
 
-    if (searchParams.filter != null) {
+    if (searchParams.filter != null && location.pathname.includes('/agenda') !== true) {
         for (const field in searchParams.filter) {
             const group = filterGroups[field];
 

From 1a0fccf650f38fa3dd22706e02db4de19cfc5dde Mon Sep 17 00:00:00 2001
From: thecalcc <me@kmarkov.io>
Date: Thu, 12 Oct 2023 15:16:52 +0300
Subject: [PATCH 3/6] Add types

---
 assets/agenda/components/AgendaApp.tsx        |  1 -
 .../SearchResultsAgendaQucikFiltersRow.tsx    | 23 ++++++++++++++++---
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/assets/agenda/components/AgendaApp.tsx b/assets/agenda/components/AgendaApp.tsx
index 5ed35a5ae..67e1fae84 100644
--- a/assets/agenda/components/AgendaApp.tsx
+++ b/assets/agenda/components/AgendaApp.tsx
@@ -150,7 +150,6 @@ class AgendaApp extends BaseApp {
             this.props.activeQuery != null ||
             this.props.itemTypeFilter != null;
 
-        // console.log(this.props.itemTypeFilter, this.props.activeFilter);
         return (
             (this.props.itemToOpen ? [<AgendaItemDetails key="itemDetails"
                 item={this.props.itemToOpen}
diff --git a/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx b/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx
index 248ddc021..9e17ea78e 100644
--- a/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx
+++ b/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx
@@ -10,7 +10,24 @@ import {clearQuickFilter} from 'search/actions';
 import {agendaCoverageStatusFilter, getActiveFilterLabel} from 'agenda/components/AgendaCoverageExistsFilter';
 import {setItemTypeFilter} from 'agenda/actions';
 
-type IProps = any;
+interface IReduxStateProps {
+    itemTypeFilter?: string;
+    activeFilter?: {
+        calendar?: any;
+        location?: any;
+        region?: any;
+        coverage_type?: any;
+        coverage_status?: any;
+    };
+}
+
+interface IReduxDispatchProps {
+    clearQuickFilter: (filter: string) => void;
+    clearItemTypeFilter: () => void;
+    clearAllQuickFilters: () => void;
+}
+
+type IProps = IReduxDispatchProps & IReduxStateProps;
 
 function SearchResultsAgendaQuickFiltersRow({
     itemTypeFilter,
@@ -159,5 +176,5 @@ const mapDispatchToProps = (dispatch: any) => ({
 });
 
 
-export const SearchResultsAgendaQuickFilters: React.ComponentType<any> =
-    connect<any>(mapStateToProps, mapDispatchToProps)(SearchResultsAgendaQuickFiltersRow);
+export const SearchResultsAgendaQuickFilters: React.ComponentType =
+    connect<IReduxStateProps, IReduxDispatchProps>(mapStateToProps, mapDispatchToProps)(SearchResultsAgendaQuickFiltersRow);

From b1c73d69ae5c36b038db384a2105618e4e3438d3 Mon Sep 17 00:00:00 2001
From: thecalcc <me@kmarkov.io>
Date: Tue, 24 Oct 2023 15:31:07 +0300
Subject: [PATCH 4/6] Move agenda filter pills to quick filter pills

---
 .../SearchResultsBar/SearchResultTagsList.tsx |   6 +-
 .../SearchResultsAgendaQucikFiltersRow.tsx    | 180 ------------------
 .../SearchResultsFiltersRow.tsx               | 102 +++++++++-
 3 files changed, 101 insertions(+), 187 deletions(-)
 delete mode 100644 assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx

diff --git a/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx b/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
index 416984ae9..912d90436 100644
--- a/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
+++ b/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
@@ -3,12 +3,11 @@ 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';
 import {getTopicUrl} from 'search/utils';
-import {SearchResultsAgendaQuickFilters} from './SearchResultsAgendaQucikFiltersRow';
 
 export interface IProps {
     user: IUser;
@@ -101,9 +100,6 @@ export function SearchResultTagsList({
                 resetFilter={resetFilter}
                 readonly={readonly}
             />
-            {location.pathname.includes('/agenda') && (
-                <SearchResultsAgendaQuickFilters />
-            )}
             {readonly === true && activeTopic._id && (
                 <SearchResultTagList
                     testId="search-results--edit-button"
diff --git a/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx b/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx
deleted file mode 100644
index 9e17ea78e..000000000
--- a/assets/search/components/SearchResultsBar/SearchResultsAgendaQucikFiltersRow.tsx
+++ /dev/null
@@ -1,180 +0,0 @@
-import * as React from 'react';
-import {gettext} from 'utils';
-
-import {SearchResultTagList} from './SearchResultTagList';
-import {Tag} from 'components/Tag';
-
-import {searchFilterSelector} from 'search/selectors';
-import {connect} from 'react-redux';
-import {clearQuickFilter} from 'search/actions';
-import {agendaCoverageStatusFilter, getActiveFilterLabel} from 'agenda/components/AgendaCoverageExistsFilter';
-import {setItemTypeFilter} from 'agenda/actions';
-
-interface IReduxStateProps {
-    itemTypeFilter?: string;
-    activeFilter?: {
-        calendar?: any;
-        location?: any;
-        region?: any;
-        coverage_type?: any;
-        coverage_status?: any;
-    };
-}
-
-interface IReduxDispatchProps {
-    clearQuickFilter: (filter: string) => void;
-    clearItemTypeFilter: () => void;
-    clearAllQuickFilters: () => void;
-}
-
-type IProps = IReduxDispatchProps & IReduxStateProps;
-
-function SearchResultsAgendaQuickFiltersRow({
-    itemTypeFilter,
-    activeFilter,
-    clearQuickFilter,
-    clearItemTypeFilter,
-    clearAllQuickFilters,
-}: IProps) {
-    const pills = [];
-
-    if (itemTypeFilter != null) {
-        pills.push(
-            <Tag
-                key={`tags-filters--from-${itemTypeFilter}`}
-                testId="tags-filters--agenda-quick-filters"
-                text={itemTypeFilter === 'events' ? gettext('Events Only') : gettext('Planning Only')}
-                // readOnly={readonly}
-                onClick={(event) => {
-                    event.preventDefault();
-                    clearItemTypeFilter();
-                }}
-            />
-        );
-    }
-
-    if (activeFilter?.['calendar'] != null) {
-        pills.push(
-            <Tag
-                key="tags-filters--calendar"
-                testId="tags-filters--agenda-quick-filters-calendar"
-                text={activeFilter['calendar']}
-                // readOnly={readonly}
-                onClick={(event) => {
-                    event.preventDefault();
-                    clearQuickFilter('calendar');
-                }}
-            />
-        );
-    }
-
-    if (activeFilter?.['location'] != null) {
-        pills.push(
-            <Tag
-                key="tags-filters--location"
-                testId="tags-filters--agenda-quick-filters-location"
-                text={activeFilter['location']}
-                // readOnly={readonly}
-                onClick={(event) => {
-                    event.preventDefault();
-                    clearQuickFilter('location');
-                }}
-            />
-        );
-    }
-
-    if (activeFilter?.['region'] != null) {
-        pills.push(
-            <Tag
-                key="tags-filters--region"
-                testId="tags-filters--agenda-quick-filters-region"
-                text={activeFilter['region']}
-                // readOnly={readonly}
-                onClick={(event) => {
-                    event.preventDefault();
-                    clearQuickFilter('region');
-                }}
-            />
-        );
-    }
-
-    if (activeFilter?.['coverage_type'] != null) {
-        pills.push(
-            <Tag
-                key="tags-filters--coverage_type"
-                testId="tags-filters--agenda-quick-filters-coverage_type"
-                text={activeFilter['coverage_type']}
-                // readOnly={readonly}
-                onClick={(event) => {
-                    event.preventDefault();
-                    clearQuickFilter('coverage_type');
-                }}
-            />
-        );
-    }
-
-    if (activeFilter?.['coverage_status'] != null) {
-        pills.push(
-            <Tag
-                key="tags-filters--coverage_status"
-                testId="tags-filters--agenda-quick-filters-coverage_status"
-                text={getActiveFilterLabel(agendaCoverageStatusFilter, activeFilter)}
-                // readOnly={readonly}
-                onClick={(event) => {
-                    event.preventDefault();
-                    clearQuickFilter('coverage_status');
-                }}
-            />
-        );
-    }
-
-    if ((pills?.length ?? 0) < 1) {
-        return null;
-    }
-
-    pills.push(
-        <span
-            key="tags-filters-separator--clear-1"
-            className="tag-list__separator tag-list__separator--blanc"
-        />
-    );
-
-    pills.push(
-        <button
-            key="tag-filters--clear-button-1"
-            className='nh-button nh-button--tertiary nh-button--small'
-            onClick={(event) => {
-                event.preventDefault();
-                clearAllQuickFilters();
-            }}
-        >
-            {gettext('Clear filters')}
-        </button>
-    );
-
-    return (
-        <SearchResultTagList
-            testId="search-results--filters"
-            title={gettext('Quick filters applied')}
-            tags={pills}
-        />
-    );
-}
-
-const mapStateToProps = (state: any) => ({
-    itemTypeFilter: state.agenda.itemType,
-    activeFilter: searchFilterSelector(state),
-});
-
-const mapDispatchToProps = (dispatch: any) => ({
-    clearQuickFilter: (filter: string) => dispatch(clearQuickFilter(filter)),
-    clearItemTypeFilter: () => dispatch(setItemTypeFilter(null)),
-    clearAllQuickFilters: () => {
-        dispatch(setItemTypeFilter(null));
-        dispatch(clearQuickFilter());
-    }
-});
-
-
-export const SearchResultsAgendaQuickFilters: React.ComponentType =
-    connect<IReduxStateProps, IReduxDispatchProps>(mapStateToProps, mapDispatchToProps)(SearchResultsAgendaQuickFiltersRow);
diff --git a/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx b/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx
index 2a5b8cdaa..b43065262 100644
--- a/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx
+++ b/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx
@@ -5,6 +5,13 @@ import {SearchResultTagList} from './SearchResultTagList';
 import {Tag} from 'components/Tag';
 
 import {IProps as IParentProps} from './SearchResultTagsList';
+import {setItemTypeFilter} from 'agenda/actions';
+import {clearQuickFilter} from 'search/actions';
+import {searchFilterSelector} from 'search/selectors';
+import {connect} from 'react-redux';
+import {agendaCoverageStatusFilter, getActiveFilterLabel} from 'agenda/components/AgendaCoverageExistsFilter';
+
+const IS_AGENDA = location.pathname.includes('/agenda');
 
 type IProps = Pick<IParentProps,
     'readonly' |
@@ -15,9 +22,78 @@ type IProps = Pick<IParentProps,
     'resetFilter'
 >;
 
-export function SearchResultsFiltersRow({readonly, searchParams, filterGroups, toggleFilter, setCreatedFilter, resetFilter}: IProps) {
+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 {
+    clearQuickFilter: (filter: string) => void;
+    clearItemTypeFilter: () => void;
+    clearAllQuickFilters: () => void;
+}
+
+type IPropsAgendaExtended = IReduxDispatchProps & IReduxStateProps & IProps;
+
+function SearchResultsFiltersRow({
+    readonly,
+    searchParams,
+    filterGroups,
+    toggleFilter,
+    setCreatedFilter,
+    resetFilter,
+    itemTypeFilter,
+    clearItemTypeFilter,
+    activeFilter,
+}: IPropsAgendaExtended) {
     const tags = [];
 
+    if (IS_AGENDA) {
+        if (itemTypeFilter != null) {
+            tags.push(
+                <Tag
+                    key={`tags-filters--from-${itemTypeFilter}`}
+                    testId="tags-filters--agenda-quick-filters"
+                    text={itemTypeFilter === 'events' ? gettext('Events Only') : gettext('Planning Only')}
+                    readOnly={readonly}
+                    onClick={(event) => {
+                        event.preventDefault();
+                        clearItemTypeFilter();
+                    }}
+                />
+            );
+        }
+
+        Object.keys(activeFilter ?? {}).filter((filter) => activeFilter?.[filter as IActiveFilterUnionType] != null)
+            .forEach((filter) => {
+                tags.push(
+                    <Tag
+                        key={`tags-filters--${filter}`}
+                        testId={`tags-filters--agenda-quick-filters-${filter}`}
+                        text={filter === 'coverage_status'
+                            ? getActiveFilterLabel(agendaCoverageStatusFilter, activeFilter)
+                            :  activeFilter?.[filter as IActiveFilterUnionType]
+                        }
+                        readOnly={readonly}
+                        onClick={(event) => {
+                            event.preventDefault();
+                            clearQuickFilter(filter);
+                        }}
+                    />
+                );
+            });
+    }
+
     if (searchParams.created) {
         const created = getCreatedSearchParamLabel(searchParams.created);
 
@@ -79,7 +155,7 @@ export function SearchResultsFiltersRow({readonly, searchParams, filterGroups, t
         }
     }
 
-    if (searchParams.filter != null && location.pathname.includes('/agenda') !== true) {
+    if (searchParams.filter != null && IS_AGENDA !== true) {
         for (const field in searchParams.filter) {
             const group = filterGroups[field];
 
@@ -142,3 +218,25 @@ export function SearchResultsFiltersRow({readonly, searchParams, filterGroups, t
         />
     );
 }
+
+const mapStateToProps = (state: any) => ({
+    itemTypeFilter: state.agenda.itemType,
+    activeFilter: searchFilterSelector(state),
+});
+
+const mapDispatchToProps = (dispatch: any) => ({
+    clearQuickFilter: (filter: string) => dispatch(clearQuickFilter(filter)),
+    clearItemTypeFilter: () => dispatch(setItemTypeFilter(null)),
+    clearAllQuickFilters: () => {
+        dispatch(setItemTypeFilter(null));
+        dispatch(clearQuickFilter());
+    }
+});
+
+let component: React.ComponentType<IProps> = SearchResultsFiltersRow as React.ComponentType<IProps>;
+
+if (IS_AGENDA) {
+    component = connect<IReduxStateProps, IReduxDispatchProps, IProps>(mapStateToProps, mapDispatchToProps)(SearchResultsFiltersRow);
+}
+
+export default component;

From 04585ca3fb07f08e817e2989066d7d28bc9b8907 Mon Sep 17 00:00:00 2001
From: thecalcc <me@kmarkov.io>
Date: Thu, 26 Oct 2023 15:18:11 +0300
Subject: [PATCH 5/6] Add coment, fix X button not removing agenda filters

---
 .../SearchResultsBar/SearchResultTagsList.tsx |  4 ++++
 .../SearchResultsFiltersRow.tsx               | 19 ++++++++++---------
 .../components/SearchResultsBar/index.tsx     |  3 +++
 3 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx b/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
index 912d90436..ce7fc16e0 100644
--- a/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
+++ b/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
@@ -34,6 +34,8 @@ export interface IProps {
 
     saveMyTopic?: (params: ISearchParams) => void;
     deselectMyTopic?: (topicId: ITopic['_id']) => void;
+    clearQuickFilter: (filter: string) => void;
+
 }
 
 export function SearchResultTagsList({
@@ -58,6 +60,7 @@ export function SearchResultTagsList({
     deselectMyTopic,
     resetFilter,
     refresh,
+    clearQuickFilter,
 }: IProps) {
     return (
         <ul
@@ -93,6 +96,7 @@ export function SearchResultTagsList({
                 readonly={readonly}
             />
             <SearchResultsFiltersRow
+                clearQuickFilter={clearQuickFilter}
                 searchParams={searchParams}
                 filterGroups={filterGroups}
                 toggleFilter={toggleFilter}
diff --git a/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx b/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx
index b43065262..6037e96be 100644
--- a/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx
+++ b/assets/search/components/SearchResultsBar/SearchResultsFiltersRow.tsx
@@ -6,7 +6,6 @@ import {Tag} from 'components/Tag';
 
 import {IProps as IParentProps} from './SearchResultTagsList';
 import {setItemTypeFilter} from 'agenda/actions';
-import {clearQuickFilter} from 'search/actions';
 import {searchFilterSelector} from 'search/selectors';
 import {connect} from 'react-redux';
 import {agendaCoverageStatusFilter, getActiveFilterLabel} from 'agenda/components/AgendaCoverageExistsFilter';
@@ -20,7 +19,7 @@ type IProps = Pick<IParentProps,
     'toggleFilter' |
     'setCreatedFilter' |
     'resetFilter'
->;
+> & {clearQuickFilter: (filter: string) => void;};
 
 type IActiveFilter = {
     calendar?: any;
@@ -38,9 +37,7 @@ interface IReduxStateProps {
 }
 
 interface IReduxDispatchProps {
-    clearQuickFilter: (filter: string) => void;
     clearItemTypeFilter: () => void;
-    clearAllQuickFilters: () => void;
 }
 
 type IPropsAgendaExtended = IReduxDispatchProps & IReduxStateProps & IProps;
@@ -55,9 +52,17 @@ function SearchResultsFiltersRow({
     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(
@@ -203,6 +208,7 @@ function SearchResultsFiltersRow({
                 onClick={(event) => {
                     event.preventDefault();
                     resetFilter();
+                    clearItemTypeFilter?.();
                 }}
             >
                 {gettext('Clear filters')}
@@ -225,12 +231,7 @@ const mapStateToProps = (state: any) => ({
 });
 
 const mapDispatchToProps = (dispatch: any) => ({
-    clearQuickFilter: (filter: string) => dispatch(clearQuickFilter(filter)),
     clearItemTypeFilter: () => dispatch(setItemTypeFilter(null)),
-    clearAllQuickFilters: () => {
-        dispatch(setItemTypeFilter(null));
-        dispatch(clearQuickFilter());
-    }
 });
 
 let component: React.ComponentType<IProps> = SearchResultsFiltersRow as React.ComponentType<IProps>;
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<any, any> {
                     )}
                     {!isTagSectionShown ? null : (
                         <SearchResultTagsList
+                            clearQuickFilter={this.props.clearQuickFilter}
                             refresh={this.props.refresh}
                             user={this.props.user}
                             showSaveTopic={this.props.showSaveTopic}
@@ -299,6 +301,7 @@ const mapDispatchToProps = {
     clearAdvancedSearchParams,
     deselectMyTopic,
     resetFilter,
+    clearQuickFilter,
 };
 
 export const SearchResultsBar: React.ComponentType<any> = connect(mapStateToProps, mapDispatchToProps)(SearchResultsBarComponent);

From 3b9ca37473b312c08917c5425eaacdfacc4864f2 Mon Sep 17 00:00:00 2001
From: thecalcc <me@kmarkov.io>
Date: Thu, 26 Oct 2023 20:54:32 +0300
Subject: [PATCH 6/6] Fix lint

---
 .../components/SearchResultsBar/SearchResultTagsList.tsx   | 1 -
 assets/search/components/TopicForm.tsx                     | 7 +++++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx b/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
index ce7fc16e0..62fcd54f1 100644
--- a/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
+++ b/assets/search/components/SearchResultsBar/SearchResultTagsList.tsx
@@ -35,7 +35,6 @@ export interface IProps {
     saveMyTopic?: (params: ISearchParams) => void;
     deselectMyTopic?: (topicId: ITopic['_id']) => void;
     clearQuickFilter: (filter: string) => void;
-
 }
 
 export function SearchResultTagsList({
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<IProps> = ({
                                 </Dropdown>
                             </div>
                             {newFolder != null && (
-                                <div 
+                                <div
                                     style={{zIndex:'1', insetBlockStart: '-75px', marginBlockEnd: '-56px'}}
                                     className="simple-card__group position-relative"
                                 >
@@ -254,8 +255,10 @@ const TopicForm: React.FC<IProps> = ({
                 <div className="nh-flex__row">
                     <FormSection initiallyOpen={true} name={gettext('Topic details')} dataTestId="topic-form-group--params">
                         <SearchResultTagsList
-                            user={user}
                             readonly={true}
+                            // Clearing filters isn't available in readOnly mode.
+                            clearQuickFilter={noop}
+                            user={user}
                             showSaveTopic={false}
                             showMyTopic={false}
                             searchParams={topic}