diff --git a/components/Hubs/HubPage.js b/components/Hubs/HubPage.js
index 7bc820aa18..657434ed4d 100644
--- a/components/Hubs/HubPage.js
+++ b/components/Hubs/HubPage.js
@@ -18,6 +18,7 @@ import PaperPlaceholder from "../Placeholders/PaperPlaceholder";
import PermissionNotificationWrapper from "~/components/PermissionNotificationWrapper";
import ResearchHubBanner from "../ResearchHubBanner";
import Head from "~/components/Head";
+import LeaderboardContainer from "../Leaderboard/LeaderboardContainer";
// Redux
import { AuthActions } from "~/redux/auth";
@@ -29,51 +30,8 @@ import { HubActions } from "~/redux/hub";
import API from "~/config/api";
import { Helpers } from "@quantfive/js-web-config";
import colors from "~/config/themes/colors";
-import LeaderboardContainer from "../Leaderboard/LeaderboardContainer";
-
-const filterOptions = [
- {
- value: "hot",
- label: "Trending",
- disableScope: true,
- },
- {
- value: "top_rated",
- label: "Top Rated",
- },
- {
- value: "newest",
- label: "Newest",
- disableScope: true,
- },
- {
- value: "most_discussed",
- label: "Most Discussed",
- },
-];
-
-const scopeOptions = [
- {
- value: "day",
- label: "Today",
- },
- {
- value: "week",
- label: "This Week",
- },
- {
- value: "month",
- label: "This Month",
- },
- {
- value: "year",
- label: "This Year",
- },
- {
- value: "all-time",
- label: "All Time",
- },
-];
+import { getFragmentParameterByName } from "~/config/utils";
+import { filterOptions, scopeOptions } from "~/config/utils/options";
const defaultFilter = filterOptions[0];
const defaultScope = scopeOptions[0];
@@ -100,9 +58,12 @@ class HubPage extends React.Component {
? this.props.initialFeed.next
: null,
doneFetching: this.props.initialFeed ? true : false,
- filterBy: defaultFilter,
- scope: defaultScope,
- disableScope: true,
+ filterBy: this.props.filter ? this.props.filter : defaultFilter,
+ scope: this.props.scope ? this.props.scope : defaultScope,
+ disableScope: this.props.filter
+ ? this.props.filter.value === "hot" ||
+ this.props.filter.value === "newest"
+ : true,
mobileView: false,
mobileBanner: false,
papersLoading: false,
@@ -357,12 +318,25 @@ class HubPage extends React.Component {
.then(Helpers.parseJSON)
.then((res) => {
this.detectPromoted([...res.results.data]);
- this.setState({
- papers: [...this.state.papers, ...res.results.data],
- next: res.next,
- page: this.state.page + 1,
- loadingMore: false,
- });
+ this.setState(
+ {
+ papers: [...this.state.papers, ...res.results.data],
+ next: res.next,
+ prev: !res.next ? res.previous : null,
+ page: this.state.page + 1,
+ loadingMore: false,
+ },
+ () => {
+ let page = getFragmentParameterByName(
+ "page",
+ this.state.next ? this.state.next : this.state.prev
+ ); // grab page from backend response
+ let offset = this.state.next ? -1 : 1;
+ page = Number(page) + offset;
+
+ this.updateSlugs(page);
+ }
+ );
})
.then(
setTimeout(() => {
@@ -371,6 +345,52 @@ class HubPage extends React.Component {
);
};
+ updateSlugs = (page) => {
+ let { filterBy, scope, disableScope } = this.state;
+
+ let filter = filterBy.label
+ .split(" ")
+ .join("-")
+ .toLowerCase();
+
+ let href, as;
+
+ if (disableScope) {
+ // if filter, but no scope
+ if (this.props.home) {
+ href = "/[filter]";
+ as = `/${filter}`;
+ } else {
+ // Hub Page
+ href = "/hubs/[slug]/[filter]";
+ as = `/hubs/${this.props.slug}/${filter}`;
+ }
+ } else {
+ // filter & scope
+ if (this.props.home) {
+ href = "/[filter]/[scope]";
+ as = `/${filter}/${scope.value}`;
+ } else {
+ href = "/hubs/[slug]/[filter]/[scope]";
+ as = `/hubs/${this.props.slug}/${filter}/${scope.value}`;
+ }
+ }
+
+ if (this.props.home && filter === "trending") {
+ href = "/";
+ as = "/";
+ } else if (!this.props.home && filter === "trending") {
+ href = "/hubs/[slug]";
+ as = `/hubs/${this.props.slug}`;
+ }
+
+ if (page) {
+ as += `?page=${page}`;
+ }
+
+ Router.push(href, as, { shallow: true });
+ };
+
calculateScope = () => {
let scope = {
start: 0,
@@ -442,9 +462,14 @@ class HubPage extends React.Component {
let param = {};
param[type] = option;
showMessage({ show: true, load: true });
- this.setState({
- ...param,
- });
+ this.setState(
+ {
+ ...param,
+ },
+ () => {
+ this.updateSlugs();
+ }
+ );
};
voteCallback = (index, paper) => {
diff --git a/components/Paper/Tabs/DiscussionTab.js b/components/Paper/Tabs/DiscussionTab.js
index 8ffd6c2bf4..f484a550ea 100644
--- a/components/Paper/Tabs/DiscussionTab.js
+++ b/components/Paper/Tabs/DiscussionTab.js
@@ -245,7 +245,7 @@ const DiscussionTab = (props) => {
cancel();
props.checkUserFirstTime(!props.auth.user.has_seen_first_coin_modal);
props.getUser();
- }, 800);
+ }, 200);
})
.catch((err) => {
if (err.response.status === 429) {
diff --git a/config/utils/options.js b/config/utils/options.js
index 644a821a29..516547177c 100644
--- a/config/utils/options.js
+++ b/config/utils/options.js
@@ -69,4 +69,56 @@ const cslFields = [
{ label: "ISSN", key: "ISSN" },
];
-export { months, range, convertNumToMonth, convertMonthToNum, cslFields };
+const filterOptions = [
+ {
+ value: "hot",
+ label: "Trending",
+ disableScope: true,
+ },
+ {
+ value: "top_rated",
+ label: "Top Rated",
+ },
+ {
+ value: "newest",
+ label: "Newest",
+ disableScope: true,
+ },
+ {
+ value: "most_discussed",
+ label: "Most Discussed",
+ },
+];
+
+const scopeOptions = [
+ {
+ value: "day",
+ label: "Today",
+ },
+ {
+ value: "week",
+ label: "This Week",
+ },
+ {
+ value: "month",
+ label: "This Month",
+ },
+ {
+ value: "year",
+ label: "This Year",
+ },
+ {
+ value: "all-time",
+ label: "All Time",
+ },
+];
+
+export {
+ months,
+ range,
+ convertNumToMonth,
+ convertMonthToNum,
+ cslFields,
+ filterOptions,
+ scopeOptions,
+};
diff --git a/config/utils/routing.js b/config/utils/routing.js
index 861217ea84..99678eea21 100644
--- a/config/utils/routing.js
+++ b/config/utils/routing.js
@@ -1,3 +1,5 @@
+import moment from "moment";
+
export function redirect(ctx, baseKey, path) {
path = buildRedirectPath(ctx, baseKey, path);
const { res } = ctx;
@@ -51,3 +53,55 @@ export function openExternalLink(url) {
const tab = window.open(url);
tab.focus();
}
+
+export function slugToFilterQuery(slug) {
+ switch (slug) {
+ case "trending":
+ return "hot";
+ case "top-rated":
+ return "top_rated";
+ case "most-discussed":
+ return "most_discussed";
+ default:
+ return slug;
+ }
+}
+
+export function calculateScopeFromSlug(scopeId) {
+ let scope = {
+ start: 0,
+ end: 0,
+ };
+
+ let now = moment();
+ let today = moment().startOf("day");
+ let week = moment()
+ .startOf("day")
+ .subtract(7, "days");
+ let month = moment()
+ .startOf("day")
+ .subtract(30, "days");
+ let year = moment()
+ .startOf("day")
+ .subtract(365, "days");
+
+ scope.end = now.unix();
+
+ if (scopeId === "day") {
+ scope.start = today.unix();
+ } else if (scopeId === "week") {
+ scope.start = week.unix();
+ } else if (scopeId === "month") {
+ scope.start = month.unix();
+ } else if (scopeId === "year") {
+ scope.start = year.unix();
+ } else if (scopeId === "all-time") {
+ let start = "2019-01-01";
+ let diff = now.diff(start, "days") + 1;
+
+ let alltime = now.startOf("day").subtract(diff, "days");
+ scope.start = alltime.unix();
+ }
+
+ return scope;
+}
diff --git a/pages/[filter]/[scope]/index.js b/pages/[filter]/[scope]/index.js
new file mode 100644
index 0000000000..ec0dbddd90
--- /dev/null
+++ b/pages/[filter]/[scope]/index.js
@@ -0,0 +1,69 @@
+import { connect } from "react-redux";
+import { StyleSheet } from "aphrodite";
+import { useRouter } from "next/router";
+
+import HubPage from "~/components/Hubs/HubPage";
+
+import API from "~/config/api";
+import { getInitialScope } from "~/config/utils/dates";
+import {
+ slugToFilterQuery,
+ calculateScopeFromSlug,
+} from "~/config/utils/routing";
+import { filterOptions, scopeOptions } from "~/config/utils/options";
+
+const Index = (props) => {
+ return
+ )}
+
+ ) : ( +
+ )}
+