diff --git a/src/shared/components/challenge-detail/Header/ChallengeTags.jsx b/src/shared/components/challenge-detail/Header/ChallengeTags.jsx index 36ac709378..4f624164a2 100644 --- a/src/shared/components/challenge-detail/Header/ChallengeTags.jsx +++ b/src/shared/components/challenge-detail/Header/ChallengeTags.jsx @@ -66,7 +66,7 @@ export default function ChallengeTags(props) { setImmediate(() => setChallengeListingFilter({ types: [challengeType.abbreviation] })) ) } - to={`${challengesUrl}?filter[types][0]=${encodeURIComponent(challengeType.abbreviation)}`} + to={`${challengesUrl}?types[]=${encodeURIComponent(challengeType.abbreviation)}`} > {challengeType.name} @@ -90,7 +90,7 @@ export default function ChallengeTags(props) { key={tag} onClick={() => setImmediate(() => setChallengeListingFilter({ tags: [tag] })) } - to={`${challengesUrl}?filter[tags][0]=${ + to={`${challengesUrl}?tags[]=${ encodeURIComponent(tag)}`} > {tag} diff --git a/src/shared/components/challenge-listing/Filters/ChallengeFilters.jsx b/src/shared/components/challenge-listing/Filters/ChallengeFilters.jsx index ca7087d0f9..142912f9a6 100644 --- a/src/shared/components/challenge-listing/Filters/ChallengeFilters.jsx +++ b/src/shared/components/challenge-listing/Filters/ChallengeFilters.jsx @@ -4,7 +4,7 @@ import React from 'react'; import PT from 'prop-types'; import SwitchWithLabel from 'components/SwitchWithLabel'; -// import { challenge as challengeUtils } from 'topcoder-react-lib'; +import { challenge as challengeUtils } from 'topcoder-react-lib'; // import { COMPETITION_TRACKS as TRACKS } from 'utils/tc'; import _ from 'lodash'; @@ -17,7 +17,7 @@ import FiltersSwitch from './FiltersSwitch'; import './ChallengeFilters.scss'; -// const Filter = challengeUtils.filter; +const Filter = challengeUtils.filter; export default function ChallengeFilters({ communityFilters, @@ -56,9 +56,9 @@ export default function ChallengeFilters({ const isTrackOn = track => filterState.tracks && filterState.tracks[track]; const switchTrack = (track, on) => { - const newFilter = _.cloneDeep(filterState); - newFilter.tracks[track] = on; - setFilterState({ ...newFilter }); + const act = on ? Filter.addTrack : Filter.removeTrack; + const filterObj = act(filterState, track); + setFilterState({ ...filterObj }); }; const clearSearch = () => { diff --git a/src/shared/containers/challenge-listing/FilterPanel.jsx b/src/shared/containers/challenge-listing/FilterPanel.jsx index 3fe14bf3a1..c83d7d1277 100644 --- a/src/shared/containers/challenge-listing/FilterPanel.jsx +++ b/src/shared/containers/challenge-listing/FilterPanel.jsx @@ -16,7 +16,8 @@ import React from 'react'; import { isReviewOpportunitiesBucket } from 'utils/challenge-listing/buckets'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; -// import qs from 'qs'; +import qs from 'qs'; +import _ from 'lodash'; /* The default name for user-saved challenge filters. An integer * number will be appended to it, when necessary, to keep filter @@ -47,8 +48,8 @@ export class Container extends React.Component { getTypes, loadingKeywords, loadingTypes, - // setFilterState, - // filterState, + setFilterState, + filterState, communityList, getCommunityList, auth, @@ -62,10 +63,10 @@ export class Container extends React.Component { if (!loadingKeywords) getKeywords(); - // const query = qs.parse(window.location.search.slice(1)); - // if (query.filter && !filterState.track) { - // setFilterState(query.filter); - // } else { + const query = qs.parse(window.location.search.slice(1)); + if (!_.isEmpty(query) && !filterState.track) { + setFilterState(query); + } // const trackStatus = localStorage.getItem('trackStatus'); // const filterObj = trackStatus ? JSON.parse(trackStatus) : null; // if (filterObj) { @@ -189,7 +190,7 @@ function mapDispatchToProps(dispatch) { // }, // selectBucket: bucket => dispatch(sa.selectBucket(bucket)), selectCommunity: id => dispatch(cla.selectCommunity(id)), - // setFilterState: s => dispatch(cla.setFilter(s)), + setFilterState: s => dispatch(cla.setFilter(s)), }; } diff --git a/src/shared/reducers/challenge-listing/index.js b/src/shared/reducers/challenge-listing/index.js index 3bc317a20d..51d68178a3 100644 --- a/src/shared/reducers/challenge-listing/index.js +++ b/src/shared/reducers/challenge-listing/index.js @@ -409,7 +409,7 @@ function onSetFilter(state, { payload }) { * do it very carefuly (many params are not validated). */ const filter = _.pickBy(_.pick( payload, - ['tags', 'types', 'name', 'startDateEnd', 'endDateStart', 'groups'], + ['tags', 'types', 'name', 'startDateEnd', 'endDateStart', 'groups', 'tracks'], ), value => (!_.isArray(value) && value && value !== '') || (_.isArray(value) && value.length > 0)); // if (_.isPlainObject(filter.tags)) { // filter.tags = _.values(filter.tags); diff --git a/src/shared/reducers/challenge-listing/sidebar.js b/src/shared/reducers/challenge-listing/sidebar.js index d822716a6d..e12ddd13b1 100644 --- a/src/shared/reducers/challenge-listing/sidebar.js +++ b/src/shared/reducers/challenge-listing/sidebar.js @@ -123,7 +123,7 @@ function onSelectBucket(state, { payload }) { switch (payload.bucket) { case BUCKETS.ALL: // case BUCKETS.SAVED_FILTER: - updateQuery({ bucket: undefined }); + updateQuery({ bucket: payload.bucket }); break; default: updateQuery({ bucket: payload.expanding ? undefined : payload.bucket }); diff --git a/src/shared/utils/url.js b/src/shared/utils/url.js index 26fe87be81..f7c76b3da9 100644 --- a/src/shared/utils/url.js +++ b/src/shared/utils/url.js @@ -7,7 +7,7 @@ import _ from 'lodash'; import qs from 'qs'; import { isomorphy } from 'topcoder-react-utils'; - +import { BUCKETS } from 'utils/challenge-listing/buckets'; /** * Get current URL hash parameters as object */ @@ -37,7 +37,25 @@ export function getQuery() { export function updateQuery(update) { if (isomorphy.isServerSide()) return; - // let query = qs.parse(window.location.search.slice(1)); + let filterObj = {}; + // check if bucket is selected + if (update.bucket) { + // fetching everything else from url except bucket + filterObj = { + ...qs.parse(window.location.search.slice(1)), + ...update, + }; + if (update.bucket === BUCKETS.ALL) { + delete filterObj.bucket; // delete bucket field for all challenges + } + } else { + // fetch only bucket from url + const query = qs.parse(window.location.search.slice(1)); + filterObj = { + ...(query.bucket && { bucket: query.bucket }), // fetch only bucket from url + ...update, + }; + } let query = '?'; const { hash } = window.location; const filterArray = []; @@ -45,11 +63,14 @@ export function updateQuery(update) { /* _.merge won't work here, because it just ignores the fields explicitely * set as undefined in the objects to be merged, rather than deleting such * fields in the target object. */ - _.forIn(update, (value, key) => { + _.forIn(filterObj, (value, key) => { if (_.isArray(value) && value.length > 0) filterArray.push(value.map(item => `${key}[]=${item}`).join('&')); // eslint-disable-next-line max-len else if (_.isUndefined(value) || _.isEmpty(value) || (_.isArray(value) && value.length === 0)) delete query[key]; - else { + else if (typeof value === 'object') { + const separator = query === '?' ? '' : '&'; + query += `${separator}${qs.stringify({ tracks: value }, { encodeValuesOnly: true })}`; + } else { const separator = query === '?' ? '' : '&'; query += `${separator}${key}=${value}`; }