-
+
@@ -165,23 +170,8 @@ export default function ChallengeListing(props) {
hideSrm={hideSrm}
isAuth={Boolean(auth.user)}
setFilterState={props.setFilterState}
- hidden
- />
-
-
-
-
-
-
-
{challengeCardContainer}
@@ -270,4 +260,5 @@ ChallengeListing.propTypes = {
// userChallenges: PT.arrayOf(PT.string),
isLoggedIn: PT.bool.isRequired,
meta: PT.shape().isRequired,
+ setSearchText: PT.func.isRequired,
};
diff --git a/src/shared/containers/challenge-detail/index.jsx b/src/shared/containers/challenge-detail/index.jsx
index fc53688834..3966ac53d5 100644
--- a/src/shared/containers/challenge-detail/index.jsx
+++ b/src/shared/containers/challenge-detail/index.jsx
@@ -14,6 +14,7 @@ import pageActions from 'actions/page';
import ChallengeHeader from 'components/challenge-detail/Header';
import challengeListingActions from 'actions/challenge-listing';
import challengeListingSidebarActions from 'actions/challenge-listing/sidebar';
+import challengeListingFilterPanelActions from 'actions/challenge-listing/filter-panel';
import Registrants from 'components/challenge-detail/Registrants';
import shortId from 'shortid';
import Submissions from 'components/challenge-detail/Submissions';
@@ -877,12 +878,18 @@ const mapDispatchToProps = (dispatch) => {
return challengeDetails;
});
},
- setChallengeListingFilter: (filter) => {
+ setChallengeListingFilter: (filter, stateProps) => {
const cl = challengeListingActions.challengeListing;
const cls = challengeListingSidebarActions.challengeListing.sidebar;
- const newFilter = _.assign({}, { types: [], tags: [] }, filter);
+ const fp = challengeListingFilterPanelActions.challengeListing.filterPanel;
+ const newFilter = _.assign(
+ {},
+ { types: stateProps.challengeTypes.map(type => type.abbreviation), search: '' },
+ filter,
+ );
dispatch(cls.selectBucket(BUCKETS.OPEN_FOR_REGISTRATION));
dispatch(cl.setFilter(newFilter));
+ dispatch(fp.setSearchText(newFilter.search));
},
setSpecsTabState: state => dispatch(pageActions.page.challengeDetails.setSpecsTabState(state)),
unregisterFromChallenge: (auth, challengeId) => {
@@ -943,9 +950,17 @@ const mapDispatchToProps = (dispatch) => {
};
};
+const mergeProps = (stateProps, dispatchProps, ownProps) => ({
+ ...ownProps,
+ ...stateProps,
+ ...dispatchProps,
+ setChallengeListingFilter: filter => dispatchProps.setChallengeListingFilter(filter, stateProps),
+});
+
const ChallengeDetailContainer = connect(
mapStateToProps,
mapDispatchToProps,
+ mergeProps,
)(ChallengeDetailPageContainer);
export default ChallengeDetailContainer;
diff --git a/src/shared/containers/challenge-listing/FilterPanel.jsx b/src/shared/containers/challenge-listing/FilterPanel.jsx
index 47c26fe9c9..045710dd89 100644
--- a/src/shared/containers/challenge-listing/FilterPanel.jsx
+++ b/src/shared/containers/challenge-listing/FilterPanel.jsx
@@ -4,12 +4,12 @@
import actions from 'actions/challenge-listing/filter-panel';
import challengeListingActions from 'actions/challenge-listing';
-import sidebarActions from 'actions/challenge-listing/sidebar';
import communityActions from 'actions/tc-communities';
import shortId from 'shortid';
import FilterPanel from 'components/challenge-listing/Filters/FiltersPanel';
import PT from 'prop-types';
import React from 'react';
+import ReactDOM from 'react-dom';
import { BUCKETS, isReviewOpportunitiesBucket } from 'utils/challenge-listing/buckets';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
@@ -37,7 +37,6 @@ export class Container extends React.Component {
communityList,
getCommunityList,
auth,
- setPast,
setSearchText,
} = this.props;
@@ -57,15 +56,10 @@ export class Container extends React.Component {
}
if (query.bucket) {
- if (query.bucket === BUCKETS.ALL_PAST || query.bucket === BUCKETS.MY_PAST) {
- setPast(true);
- }
-
if (query.bucket !== BUCKETS.ALL_PAST && query.bucket !== BUCKETS.MY_PAST) {
delete query.endDateStart;
delete query.startDateEnd;
}
-
delete query.bucket;
}
@@ -93,6 +87,9 @@ export class Container extends React.Component {
if (!_.isEmpty(query)) {
setFilterState(query);
}
+
+ this.outlet = document.createElement('div');
+ document.body.appendChild(this.outlet);
}
componentDidUpdate() {
@@ -111,6 +108,10 @@ export class Container extends React.Component {
}
}
+ componentWillUnmount() {
+ this.outlet.parentElement.removeChild(this.outlet);
+ }
+
render() {
const {
activeBucket,
@@ -132,7 +133,7 @@ export class Container extends React.Component {
const isForReviewOpportunities = isReviewOpportunitiesBucket(activeBucket);
- return (
+ const filterPanel = (
);
+
+ if (hidden) {
+ return expanded ? ReactDOM.createPortal(filterPanel, this.outlet) : filterPanel;
+ }
+
+ return filterPanel;
}
}
@@ -182,15 +189,12 @@ Container.propTypes = {
hidden: PT.bool,
onClose: PT.func.isRequired,
validTypes: PT.arrayOf(PT.shape()).isRequired,
- past: PT.bool.isRequired,
- setPast: PT.func.isRequired,
setSearchText: PT.func.isRequired,
};
function mapDispatchToProps(dispatch) {
const a = actions.challengeListing.filterPanel;
const cla = challengeListingActions.challengeListing;
- const sba = sidebarActions.challengeListing.sidebar;
return {
...bindActionCreators(a, dispatch),
getTypes: () => {
@@ -209,14 +213,12 @@ function mapDispatchToProps(dispatch) {
selectCommunity: id => dispatch(cla.selectCommunity(id)),
setFilterState: s => dispatch(cla.setFilter(s)),
onClose: () => dispatch(a.setExpanded(false)),
- setPast: isPast => dispatch(sba.setPast(isPast)),
};
}
function mapStateToProps(state, ownProps) {
const cl = state.challengeListing;
const tc = state.tcCommunities;
- const sb = state.challengeListing.sidebar;
return {
...ownProps,
...state.challengeListing.filterPanel,
@@ -232,7 +234,6 @@ function mapStateToProps(state, ownProps) {
selectedCommunityId: cl.selectedCommunityId,
auth: state.auth,
tokenV2: state.auth.tokenV2,
- past: sb.past,
};
}
diff --git a/src/shared/containers/challenge-listing/Listing/index.jsx b/src/shared/containers/challenge-listing/Listing/index.jsx
index b2b02b8b60..8c996bd8e8 100644
--- a/src/shared/containers/challenge-listing/Listing/index.jsx
+++ b/src/shared/containers/challenge-listing/Listing/index.jsx
@@ -21,6 +21,7 @@ import { connect } from 'react-redux';
import ChallengeListing from 'components/challenge-listing';
import Banner from 'components/tc-communities/Banner';
import sidebarActions from 'actions/challenge-listing/sidebar';
+import filterPanelActions from 'actions/challenge-listing/filter-panel';
import communityActions from 'actions/tc-communities';
// import SORT from 'utils/challenge-listing/sort';
import { BUCKETS, filterChanged, sortChangedBucket } from 'utils/challenge-listing/buckets';
@@ -37,11 +38,6 @@ const { mapToBackend } = challengeUtils.filter;
let mounted = false;
export class ListingContainer extends React.Component {
- constructor(props) {
- super(props);
- this.firstReload = false;
- }
-
componentDidMount() {
const {
activeBucket,
@@ -118,7 +114,6 @@ export class ListingContainer extends React.Component {
dropOpenForRegistrationChallenges,
dropPastChallenges,
getPastChallenges,
- past,
} = this.props;
const oldUserId = _.get(prevProps, 'auth.user.userId');
const userId = _.get(this.props, 'auth.user.userId');
@@ -224,19 +219,7 @@ export class ListingContainer extends React.Component {
}
return;
}
- let reload;
- if (!this.firstReload) {
- reload = true;
- this.firstReload = true;
- } else if (prevProps.past === past) {
- reload = past
- ? filterChanged(filter, prevProps.filter)
- : filterChanged(
- _.omit(filter, 'startDateEnd', 'endDateStart'),
- _.omit(prevProps.filter, 'startDateEnd', 'endDateStart'),
- );
- }
- if (reload) {
+ if (filterChanged(filter, prevProps.filter)) {
this.reloadChallenges();
}
setTimeout(() => {
@@ -263,8 +246,7 @@ export class ListingContainer extends React.Component {
sorts,
filter,
} = this.props;
- const filterTemp = _.omit(filter, 'reviewOpportunityTypes', 'customDate',
- 'previousStartDate', 'previousEndDate');
+ const filterTemp = _.omit(filter, 'reviewOpportunityTypes', 'customDate');
// let communityFilter = communitiesList.data.find(
// item => item.communityId === selectedCommunityId,
// );
@@ -466,6 +448,7 @@ export class ListingContainer extends React.Component {
// isBucketSwitching,
// userChallenges,
meta,
+ setSearchText,
} = this.props;
const { tokenV3 } = auth;
@@ -636,6 +619,7 @@ export class ListingContainer extends React.Component {
// userChallenges={[]}
isLoggedIn={isLoggedIn}
meta={meta}
+ setSearchText={setSearchText}
/>
);
@@ -760,7 +744,7 @@ ListingContainer.propTypes = {
getTotalChallengesCount: PT.func.isRequired,
// userChallenges: PT.arrayOf(PT.string),
// getUserChallenges: PT.func.isRequired,
- past: PT.bool.isRequired,
+ setSearchText: PT.func.isRequired,
};
const mapStateToProps = (state, ownProps) => {
@@ -820,7 +804,6 @@ const mapStateToProps = (state, ownProps) => {
expandedTags: cl.expandedTags,
meta: cl.meta,
// userChallenges: cl.userChallenges,
- past: cl.sidebar.past,
};
};
@@ -828,6 +811,7 @@ function mapDispatchToProps(dispatch) {
const a = actions.challengeListing;
const ah = headerActions.topcoderHeader;
const sa = sidebarActions.challengeListing.sidebar;
+ const fp = filterPanelActions.challengeListing.filterPanel;
const ca = communityActions.tcCommunity;
return {
dropChallenges: () => dispatch(a.dropChallenges()),
@@ -901,6 +885,7 @@ function mapDispatchToProps(dispatch) {
// dispatch(a.getUserChallengesInit(uuid));
// dispatch(a.getUserChallengesDone(userId, tokenV3));
// },
+ setSearchText: text => dispatch(fp.setSearchText(text)),
};
}
diff --git a/src/shared/containers/challenge-listing/Sidebar.jsx b/src/shared/containers/challenge-listing/Sidebar.jsx
index c13bfccfff..cd53b07d1d 100644
--- a/src/shared/containers/challenge-listing/Sidebar.jsx
+++ b/src/shared/containers/challenge-listing/Sidebar.jsx
@@ -55,7 +55,7 @@ export class SidebarContainer extends React.Component {
}
render() {
- const {
+ // const {
// activeBucket,
// communityFilters,
// deleteSavedFilter,
@@ -69,9 +69,7 @@ export class SidebarContainer extends React.Component {
// updateAllSavedFilters,
// updateSavedFilter,
// userChallenges,
- past,
- setPast,
- } = this.props;
+ // } = this.props;
const {
previousBucketOfActiveTab,
@@ -128,8 +126,6 @@ export class SidebarContainer extends React.Component {
setPreviousBucketOfPastChallengesTab={(bucket) => {
this.setState({ previousBucketOfPastChallengesTab: bucket });
}}
- past={past}
- setPast={setPast}
/>
);
}
@@ -164,8 +160,6 @@ SidebarContainer.propTypes = {
// user: PT.shape(),
// userChallenges: PT.arrayOf(PT.string),
expanding: PT.bool,
- past: PT.bool.isRequired,
- setPast: PT.func.isRequired,
};
function mapDispatchToProps(dispatch) {
@@ -201,7 +195,6 @@ function mapStateToProps(state) {
// user: state.auth.user,
// userChallenges: state.challengeListing.userChallenges,
expanding: sb.expanding,
- past: sb.past,
};
}
diff --git a/src/shared/reducers/challenge-listing/index.js b/src/shared/reducers/challenge-listing/index.js
index 07af86f364..41ecc6b941 100644
--- a/src/shared/reducers/challenge-listing/index.js
+++ b/src/shared/reducers/challenge-listing/index.js
@@ -907,7 +907,7 @@ function create(initialState) {
DS: true,
QA: true,
},
- name: '',
+ search: '',
tags: [],
types: [],
groups: [],
diff --git a/src/shared/reducers/challenge-listing/sidebar.js b/src/shared/reducers/challenge-listing/sidebar.js
index b55abacb5a..bb3822811f 100644
--- a/src/shared/reducers/challenge-listing/sidebar.js
+++ b/src/shared/reducers/challenge-listing/sidebar.js
@@ -175,15 +175,6 @@ function onSelectBucketDone(state) {
// return { ...state, savedFilters };
// }
-function onSetPast(state, { payload }) {
- const { past } = payload;
-
- return {
- ...state,
- past,
- };
-}
-
function create(initialState = {}) {
const a = actions.challengeListing.sidebar;
return handleActions({
@@ -209,14 +200,12 @@ function create(initialState = {}) {
// editSavedFiltersMode: payload,
// }),
// [a.updateSavedFilter]: onUpdateSavedFilter,
- [a.setPast]: onSetPast,
}, _.defaults(initialState, {
activeBucket: BUCKETS.OPEN_FOR_REGISTRATION,
// activeSavedFilter: 0,
// editSavedFiltersMode: false,
// savedFilters: [],
// isSavingFilter: false,
- past: false,
}));
}
diff --git a/src/shared/utils/challenge-listing/buckets.js b/src/shared/utils/challenge-listing/buckets.js
index 87e0d1a0b0..e50a724de3 100644
--- a/src/shared/utils/challenge-listing/buckets.js
+++ b/src/shared/utils/challenge-listing/buckets.js
@@ -217,6 +217,7 @@ export function isFilterEmpty(filter, tab, bucket) {
if (tab === 'past') {
f = _.pick(filter, 'tracks', 'search', 'types', 'startDateEnd', 'endDateStart');
+ if (f.types) f.types = [...f.types].sort();
empty = {
tracks: {
Dev: true,
@@ -243,6 +244,7 @@ export function isFilterEmpty(filter, tab, bucket) {
};
} else {
f = _.pick(filter, 'tracks', 'search', 'types');
+ if (f.types) f.types = [...f.types].sort();
empty = {
tracks: {
Dev: true,
@@ -258,4 +260,8 @@ export function isFilterEmpty(filter, tab, bucket) {
return _.isEqual(f, empty);
}
+export function isPastBucket(bucket) {
+ return [BUCKETS.ALL_PAST, BUCKETS.MY_PAST].indexOf(bucket) !== -1;
+}
+
export default undefined;