diff --git a/src/components/HOCs/WithReviewTasks/WithReviewTasks.js b/src/components/HOCs/WithReviewTasks/WithReviewTasks.js index 5d52edf8b..443906e2e 100644 --- a/src/components/HOCs/WithReviewTasks/WithReviewTasks.js +++ b/src/components/HOCs/WithReviewTasks/WithReviewTasks.js @@ -144,6 +144,10 @@ export const WithReviewTasks = function(WrappedComponent) { } } + clearCriteria = () => { + this.props.clearFilters() + } + updateURL(props, criteria) { let searchCriteria = _merge({filters:{}}, criteria) @@ -238,6 +242,7 @@ export const WithReviewTasks = function(WrappedComponent) { updateReviewTasks={(criteria) => this.update(this.props, criteria)} refresh={this.refresh} reviewCriteria={criteria} + clearFilterCriteria={this.clearCriteria} pageSize={criteria.pageSize} changePageSize={this.changePageSize} setFiltered={this.setFiltered} diff --git a/src/components/HOCs/WithSavedFilters/WithSavedFilters.js b/src/components/HOCs/WithSavedFilters/WithSavedFilters.js index a59d8a4bf..6d9c67ae4 100644 --- a/src/components/HOCs/WithSavedFilters/WithSavedFilters.js +++ b/src/components/HOCs/WithSavedFilters/WithSavedFilters.js @@ -100,6 +100,7 @@ const WithSavedFilters = function(WrappedComponent, appSettingName) { getBriefFilters = savedFilters => { const criteria = buildSearchCriteriafromURL(savedFilters) + return _compact(_map(criteria.filters, (value, key) => { let op = '=' let textValue = value diff --git a/src/components/KeywordAutosuggestInput/InTableTagFilter.js b/src/components/KeywordAutosuggestInput/InTableTagFilter.js index bb4fba155..a7a2a8326 100644 --- a/src/components/KeywordAutosuggestInput/InTableTagFilter.js +++ b/src/components/KeywordAutosuggestInput/InTableTagFilter.js @@ -3,6 +3,7 @@ import { FormattedMessage } from 'react-intl' import KeywordAutosuggestInput from './KeywordAutosuggestInput' import External from '../External/External' import Modal from '../Modal/Modal' +import SvgSymbol from '../SvgSymbol/SvgSymbol' import messages from './Messages' /** @@ -23,16 +24,27 @@ export default class InTableTagFilter extends Component { this.setState({showTagChooser: false, currentValue: null}) } + clearFilter = () => { + this.setState({currentValue: ''}, () => { + this.props.onChange(this.state.currentValue) + }) + } + render() { return (
- { - if (!this.state.showTagChooser) { - this.setState({showTagChooser: true}) - } - }} - /> +
+ { + if (!this.state.showTagChooser) { + this.setState({showTagChooser: true}) + } + }} + /> + {this.props.value && } +
  • {listSearches.length > 0 &&
  • diff --git a/src/components/TaskAnalysisTable/TaskAnalysisTable.js b/src/components/TaskAnalysisTable/TaskAnalysisTable.js index 9a36f5621..9d173537b 100644 --- a/src/components/TaskAnalysisTable/TaskAnalysisTable.js +++ b/src/components/TaskAnalysisTable/TaskAnalysisTable.js @@ -229,6 +229,28 @@ export class TaskAnalysisTableInternal extends Component { { + const filterValue = filter ? filter.value : '' + const clearFilter = () => onChange('') + return ( +
    + { + onChange(event.target.value) + }} + /> + {filterValue && } +
    + ) + } + } SubComponent={props => } @@ -712,7 +734,7 @@ const setupColumnTypes = (props, taskBaseRoute, manager, data, openComments) => {...props} preferredTags={preferredTags} onChange={onChange} - value={_get(filter, 'value')} + value={_get(filter, 'value') ?? ""} /> ) } diff --git a/src/components/TaskAnalysisTable/TaskAnalysisTableHeader.js b/src/components/TaskAnalysisTable/TaskAnalysisTableHeader.js index 9e212ee19..fcef1313f 100644 --- a/src/components/TaskAnalysisTable/TaskAnalysisTableHeader.js +++ b/src/components/TaskAnalysisTable/TaskAnalysisTableHeader.js @@ -127,7 +127,7 @@ export class TaskAnalysisTableHeader extends Component { className="mr-fill-current mr-w-5 mr-h-5" /> )} - dropdownContent={() => + dropdownContent={(dropdown) =>
      {manager.canWriteProject(this.props.challenge.parent) && @@ -204,7 +204,10 @@ export class TaskAnalysisTableHeader extends Component {
    • diff --git a/src/pages/Review/Review.js b/src/pages/Review/Review.js index 9f6ea4892..3b6bc6a3b 100644 --- a/src/pages/Review/Review.js +++ b/src/pages/Review/Review.js @@ -33,7 +33,6 @@ import WithReviewTasks from '../../components/HOCs/WithReviewTasks/WithReviewTas import TasksReviewChallenges from './TasksReview/TasksReviewChallenges' import messages from './Messages' - const WIDGET_WORKSPACE_NAME = "reviewOverview" const ReviewWidgetWorkspace = WithReviewTasks(WidgetWorkspace) @@ -176,6 +175,10 @@ export class ReviewTasksDashboard extends Component { }) } + clearFilters = () => { + this.setSelectedFilters({}, true) + } + changeTab = (tab) => { this.props.history.push({ pathname: `/review/${tab}` @@ -338,6 +341,7 @@ export class ReviewTasksDashboard extends Component { reviewTasksSubType={this.state.showSubType} defaultFilters={this.state.filterSelected[showType]} clearSelected={this.clearSelected} + clearFilters={this.clearFilters} pageId={showType} metaReviewEnabled={metaReviewEnabled} /> diff --git a/src/pages/Review/TasksReview/Messages.js b/src/pages/Review/TasksReview/Messages.js index caa6820d5..0a4e74f95 100644 --- a/src/pages/Review/TasksReview/Messages.js +++ b/src/pages/Review/TasksReview/Messages.js @@ -19,6 +19,11 @@ export default defineMessages({ defaultMessage: "Toggle Map", }, + clearFiltersLabel: { + id: "Review.TaskAnalysisTable.clearFilters", + defaultMessage: "Clear Filters" + }, + startReviewing: { id: "Review.TaskAnalysisTable.startReviewing", defaultMessage: "Review these Tasks", diff --git a/src/pages/Review/TasksReview/TasksReviewTable.js b/src/pages/Review/TasksReview/TasksReviewTable.js index 689e3393b..5e19e33cf 100644 --- a/src/pages/Review/TasksReview/TasksReviewTable.js +++ b/src/pages/Review/TasksReview/TasksReviewTable.js @@ -53,7 +53,6 @@ import ReactTable from 'react-table-6' export const getFilterIds = (search, param) => { const searchParams = new URLSearchParams(search); - for (let pair of searchParams.entries()) { if (pair[0] === param && pair[1]) { if (pair[1] === '0') { @@ -73,7 +72,7 @@ export const getFilterIds = (search, param) => { * @author [Kelli Rotstan](https://github.com/krotstan) */ export class TaskReviewTable extends Component { - componentIsMounted: false + componentIsMounted = false state = { displayMap: localStorage.getItem('displayMap') === 'true' ? true : false, @@ -125,7 +124,7 @@ export class TaskReviewTable extends Component { } if (this.componentIsMounted) { - this.setState({lastTableState: _pick(tableState, ["sorted", "filtered"])}) + this.setState({lastTableState: _pick(tableState, ["sorted", "filtered", "page"])}) this.props.updateReviewTasks({sortCriteria, filters, page: tableState.page, boundingBox: this.props.reviewCriteria.boundingBox, includeTags: !!_get(this.props.addedColumns, 'tags')}) @@ -284,7 +283,7 @@ export class TaskReviewTable extends Component { ( @@ -364,6 +365,20 @@ export class TaskReviewTable extends Component { ) } + clearFiltersControl = () => { + return ( +
      + +
      + ) + } + render() { // Setup tasks table. See react-table docs for details. const data = _get(this.props, 'reviewData.tasks', []) @@ -475,7 +490,6 @@ export class TaskReviewTable extends Component { ) ); - return (
      @@ -520,8 +534,9 @@ export class TaskReviewTable extends Component { > -
      -
      +
      +
      + {this.clearFiltersControl()} {this.filterDropdown(this.props.reviewTasksType)} {this.gearDropdown(this.props.reviewTasksType)}
      @@ -558,6 +573,30 @@ export class TaskReviewTable extends Component { loading={this.props.loading} {...intlTableProps(this.props.intl)} PaginationComponent={IntlTablePagination} + FilterComponent={({ filter, onChange }) => { + const filterValue = filter ? filter.value : '' + const clearFilter = () => onChange('') + return ( +
      + { + onChange(event.target.value) + }} + /> + {filterValue && ( + + )} +
      + ) + } + } />
      @@ -780,18 +819,33 @@ export const setupColumnTypes = (props, openComments, data, criteria) => { }, Filter: ({ filter, onChange }) => { return ( - { - onChange(item) - setTimeout(() => props.updateChallengeFilterIds(item), 0) - }} - value={filter ? filter.value : ""} - itemList={props.reviewChallenges} - multiselect={props.challengeFilterIds} - /> +
      +
      + { + onChange(item) + setTimeout(() => props.updateChallengeFilterIds(item), 0) + }} + value={filter ? filter.value : ""} + itemList={props.reviewChallenges} + multiselect={props.challengeFilterIds} + /> +
      + {props.challengeFilterIds && props.challengeFilterIds.length && props.challengeFilterIds?.[0] !== -2 ? ( + + ) : null} +
      ) } } @@ -826,18 +880,33 @@ export const setupColumnTypes = (props, openComments, data, criteria) => { }, Filter: ({ filter, onChange }) => { return ( - { - onChange(item) - setTimeout(() => props.updateProjectFilterIds(item), 0) - }} - value={filter ? filter.value : ""} - itemList={_map(props.reviewProjects, p => ({id: p.id, name: p.displayName}))} - multiselect={props.projectFilterIds} - /> +
      +
      + { + onChange(item) + setTimeout(() => props.updateProjectFilterIds(item), 0) + }} + value={filter ? filter.value : ""} + itemList={_map(props.reviewProjects, p => ({id: p.id, name: p.displayName}))} + multiselect={props.projectFilterIds} + /> +
      + {props.projectFilterIds && props.projectFilterIds.length && props.projectFilterIds?.[0] !== -2 ? ( + + ) : null} +
      ) } } @@ -867,8 +936,11 @@ export const setupColumnTypes = (props, openComments, data, criteria) => { if (typeof mappedOn === "string" && mappedOn !== "") { mappedOn = parse(mappedOn) } + + const clearFilter = () => props.setFiltered("mappedOn", null) + return ( -
      +
      { @@ -876,6 +948,11 @@ export const setupColumnTypes = (props, openComments, data, criteria) => { }} intl={props.intl} /> + {mappedOn && ( + + )}
      ) }, @@ -907,8 +984,11 @@ export const setupColumnTypes = (props, openComments, data, criteria) => { if (typeof reviewedAt === "string" && reviewedAt !== "") { reviewedAt = parse(reviewedAt) } + + const clearFilter = () => props.setFiltered("reviewedAt", null) + return ( -
      +
      { @@ -916,6 +996,11 @@ export const setupColumnTypes = (props, openComments, data, criteria) => { }} intl={props.intl} /> + {reviewedAt && ( + + )}
      ) }, @@ -1263,7 +1348,7 @@ export const setupColumnTypes = (props, openComments, data, criteria) => { ) } diff --git a/src/services/Search/Search.js b/src/services/Search/Search.js index e7d9a6276..30a95b610 100644 --- a/src/services/Search/Search.js +++ b/src/services/Search/Search.js @@ -333,8 +333,8 @@ export const generateSearchParametersString = (filters, boundingBox, savedChalle } if (filters.tags) { - searchParameters[PARAMS_MAP.tags] = filters.tags.trim() - } + searchParameters[PARAMS_MAP.tags] = `${filters.tags}`.trim() + } if (excludeTasks && excludeTasks.length > 0) { searchParameters[PARAMS_MAP.excludeTasks] = excludeTasks.join(',')