diff --git a/.circleci/config.yml b/.circleci/config.yml
index 76135f8..21fcb93 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -77,7 +77,6 @@ workflows:
branches:
only:
- dev
- - challenge-details-page
# Production builds are exectuted only on tagged commits to the
# master branch.
diff --git a/src/App.jsx b/src/App.jsx
index d44d161..b6291e9 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -2,16 +2,30 @@
* Main App component
*/
import React, { useEffect, useLayoutEffect, useRef } from "react";
-import { useLocation, Router } from "@reach/router";
+import { useLocation, Router, Redirect } from "@reach/router";
+import { usePreviousLocation } from "./utils/hooks";
import ChallengeList from "./routers/challenge-list";
import ChallengeDetail from "./routers/challenge-detail";
import "./styles/main.scss";
const App = () => {
+ const location = useLocation();
+ const previousLocation = usePreviousLocation();
+
+ const varsRef = useRef();
+ varsRef.current = { previousLocation };
+
+ useEffect(() => {
+ if (location.pathname !== varsRef.current.previousLocation.pathname) {
+ window.scrollTo(0, 0);
+ }
+ }, [location]);
+
return (
-
+
+
);
};
diff --git a/src/actions/challenge.js b/src/actions/challenge.js
index 8d6737b..19dbaf1 100644
--- a/src/actions/challenge.js
+++ b/src/actions/challenge.js
@@ -92,23 +92,23 @@ function getBasicDetailsDone(challengeId, tokenV3, tokenV2) {
* @param {Number|String} challengeId Challenge ID
* @return {Action}
*/
- function getFullDetailsInit(challengeId) {
- return _.toString(challengeId);
- }
+function getFullDetailsInit(challengeId) {
+ return _.toString(challengeId);
+}
- /**
- * @static
- * @desc Creates an action that loads full challenge details.
- * @param {Number|String} challengeId Challenge ID.
- * @param {String} tokenV3 Topcoder v3 auth token.
- * @param {String} tokenV2 Topcoder v2 auth token.
- * @return {Action}
- */
- function getFullDetailsDone(challengeId, tokenV3, tokenV2) {
- const service = getChallengesService(tokenV3, tokenV2);
- const v3Promise = service.getFullChallengeDetails(challengeId);
- return v3Promise;
- }
+/**
+ * @static
+ * @desc Creates an action that loads full challenge details.
+ * @param {Number|String} challengeId Challenge ID.
+ * @param {String} tokenV3 Topcoder v3 auth token.
+ * @param {String} tokenV2 Topcoder v2 auth token.
+ * @return {Action}
+ */
+function getFullDetailsDone(challengeId, tokenV3, tokenV2) {
+ const service = getChallengesService(tokenV3, tokenV2);
+ const v3Promise = service.getFullChallengeDetails(challengeId);
+ return v3Promise;
+}
/**
* @static
diff --git a/src/components/challenge-detail/Header/index.jsx b/src/components/challenge-detail/Header/index.jsx
index 1b7b04e..0ff5f8d 100644
--- a/src/components/challenge-detail/Header/index.jsx
+++ b/src/components/challenge-detail/Header/index.jsx
@@ -391,7 +391,12 @@ export default function ChallengeHeader(props) {
) : (
updateChallenge(x, auth.tokenV3)}
/>
)}
- {!isEmpty && selectedTab === DETAIL_TABS.REGISTRANTS && isLoadingFullChallenge && (
-
- )}
- {!isEmpty && selectedTab === DETAIL_TABS.REGISTRANTS && !isLoadingFullChallenge && (
- {
- notFoundCountryFlagUrl[countryInfo.countryCode] = true;
- this.setState({ notFoundCountryFlagUrl });
- }}
- onSortChange={(sort) => this.setState({ registrantsSort: sort })}
- />
- )}
+ {!isEmpty &&
+ selectedTab === DETAIL_TABS.REGISTRANTS &&
+ isLoadingFullChallenge && }
+ {!isEmpty &&
+ selectedTab === DETAIL_TABS.REGISTRANTS &&
+ !isLoadingFullChallenge && (
+ {
+ notFoundCountryFlagUrl[countryInfo.countryCode] = true;
+ this.setState({ notFoundCountryFlagUrl });
+ }}
+ onSortChange={(sort) =>
+ this.setState({ registrantsSort: sort })
+ }
+ />
+ )}
{!isEmpty && selectedTab === DETAIL_TABS.CHECKPOINTS && (
)}
- {!isEmpty && isLoggedIn && selectedTab === DETAIL_TABS.SUBMISSIONS && isLoadingFullChallenge && (
-
- )}
- {!isEmpty && isLoggedIn && selectedTab === DETAIL_TABS.SUBMISSIONS && !isLoadingFullChallenge && (
- {
- notFoundCountryFlagUrl[countryInfo.countryCode] = true;
- this.setState({ notFoundCountryFlagUrl });
- }}
- onSortChange={(sort) => this.setState({ submissionsSort: sort })}
- hasRegistered={challenge.isRegistered}
- unregistering={unregistering}
- isLegacyMM={isLegacyMM}
- submissionEnded={submissionEnded}
- challengesUrl={challengesUrl}
- />
- )}
+ {!isEmpty &&
+ isLoggedIn &&
+ selectedTab === DETAIL_TABS.SUBMISSIONS &&
+ isLoadingFullChallenge && }
+ {!isEmpty &&
+ isLoggedIn &&
+ selectedTab === DETAIL_TABS.SUBMISSIONS &&
+ !isLoadingFullChallenge && (
+ {
+ notFoundCountryFlagUrl[countryInfo.countryCode] = true;
+ this.setState({ notFoundCountryFlagUrl });
+ }}
+ onSortChange={(sort) =>
+ this.setState({ submissionsSort: sort })
+ }
+ hasRegistered={challenge.isRegistered}
+ unregistering={unregistering}
+ isLegacyMM={isLegacyMM}
+ submissionEnded={submissionEnded}
+ challengesUrl={challengesUrl}
+ />
+ )}
{isMM && !isEmpty && selectedTab === DETAIL_TABS.MY_SUBMISSIONS && (
{
});
},
loadFullChallengeDetails: (tokens, challengeId) => {
- const a = actions.challenge;
+ const a = actions.challenge;
- dispatch(a.getFullDetailsInit(challengeId));
- dispatch(
- a.getFullDetailsDone(challengeId, tokens.tokenV3, tokens.tokenV2)
- ).then((res) => {
- return res;
- });
- },
+ dispatch(a.getFullDetailsInit(challengeId));
+ dispatch(
+ a.getFullDetailsDone(challengeId, tokens.tokenV3, tokens.tokenV2)
+ ).then((res) => {
+ return res;
+ });
+ },
registerForChallenge: (auth, challengeId) => {
const a = actions.challenge;
dispatch(a.registerInit());
diff --git a/src/services/challenges.js b/src/services/challenges.js
index 219946b..7e6728a 100644
--- a/src/services/challenges.js
+++ b/src/services/challenges.js
@@ -398,7 +398,7 @@ class ChallengesService {
* @param {Number|String} challengeId
* @returns {Promise} Resolves to the basic challenge object.
*/
- async getBasicChallengeDetails(challengeId){
+ async getBasicChallengeDetails(challengeId) {
let challenge = {};
let isLegacyChallenge = false;
@@ -427,7 +427,7 @@ class ChallengesService {
eventId: e.id,
description: e.name,
})),
- fetchedWithAuth: Boolean(this.private.apiV5.private.token)
+ fetchedWithAuth: Boolean(this.private.apiV5.private.token),
};
}
diff --git a/src/utils/hooks/index.js b/src/utils/hooks/index.js
new file mode 100644
index 0000000..ea39f96
--- /dev/null
+++ b/src/utils/hooks/index.js
@@ -0,0 +1 @@
+export * from "./usePreviousLocation";
diff --git a/src/utils/hooks/usePreviousLocation.js b/src/utils/hooks/usePreviousLocation.js
new file mode 100644
index 0000000..872d667
--- /dev/null
+++ b/src/utils/hooks/usePreviousLocation.js
@@ -0,0 +1,13 @@
+import { useLocation } from "@reach/router";
+import { useEffect, useRef } from "react";
+
+export const usePreviousLocation = () => {
+ const location = useLocation();
+ const ref = useRef(location);
+
+ useEffect(() => {
+ ref.current = location;
+ }, [location]);
+
+ return ref.current;
+};