From 7af0894ee37ffb14df01f8c577008ec36512879a Mon Sep 17 00:00:00 2001
From: joshslee
Date: Tue, 8 Sep 2020 17:03:11 -0700
Subject: [PATCH 1/4] add slugs for home page
---
components/Hubs/HubPage.js | 60 ++++++++++++++----
config/utils/options.js | 54 +++++++++++++++-
config/utils/routing.js | 54 ++++++++++++++++
pages/[filter]/[scope]/index.js | 69 +++++++++++++++++++++
pages/[filter]/index.js | 59 ++++++++++++++++++
pages/_app.js | 10 +--
pages/hubs/[slug]/[filter]/[scope]/index.js | 0
pages/hubs/[slug]/[filter]/index.js | 0
pages/index.js | 17 ++---
pages/paper/[paperId]/[paperName]/index.js | 2 +-
redux/configureStore.js | 6 +-
11 files changed, 297 insertions(+), 34 deletions(-)
create mode 100644 pages/[filter]/[scope]/index.js
create mode 100644 pages/[filter]/index.js
create mode 100644 pages/hubs/[slug]/[filter]/[scope]/index.js
create mode 100644 pages/hubs/[slug]/[filter]/index.js
diff --git a/components/Hubs/HubPage.js b/components/Hubs/HubPage.js
index a897f247e0..3e5c4dc560 100644
--- a/components/Hubs/HubPage.js
+++ b/components/Hubs/HubPage.js
@@ -100,9 +100,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,
@@ -361,12 +364,27 @@ 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,
+ page: this.state.page + 1,
+ loadingMore: false,
+ },
+ () => {
+ let filter = this.state.filterBy.label
+ .split(" ")
+ .join("-")
+ .toLowerCase();
+ Router.push(
+ this.state.disableScope ? "/" : "/[filter]/[scope]",
+ this.state.disableScope
+ ? `/${filter}?page=${this.state.page}`
+ : `${filter}/${this.state.scope.value}?page=${this.state.page}`,
+ { shallow: true }
+ );
+ }
+ );
})
.then(
setTimeout(() => {
@@ -446,9 +464,27 @@ class HubPage extends React.Component {
let param = {};
param[type] = option;
showMessage({ show: true, load: true });
- this.setState({
- ...param,
- });
+ this.setState(
+ {
+ ...param,
+ },
+ () => {
+ let filter = this.state.filterBy.label
+ .split(" ")
+ .join("-")
+ .toLowerCase();
+ if (this.state.filterBy.disableScope) {
+ Router.push("/[filter]", `/${filter}`, {
+ shallow: true,
+ });
+ } else {
+ let scope = this.state.scope.value;
+ Router.push("/[filter]/[scope]", `/${filter}/${scope}`, {
+ shallow: true,
+ });
+ }
+ }
+ );
};
voteCallback = (index, paper) => {
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 ;
+};
+
+Index.getInitialProps = async (ctx) => {
+ let { query } = ctx;
+
+ let page = query.page ? query.page : 1;
+ let filter = query.filter ? slugToFilterQuery(query.filter) : "hot";
+ let scope = query.scope
+ ? calculateScopeFromSlug(query.scope)
+ : getInitialScope();
+
+ try {
+ const [initialFeed, leaderboardFeed, initialHubList] = await Promise.all([
+ fetch(
+ API.GET_HUB_PAPERS({
+ // Initial Feed
+ hubId: 0,
+ ordering: filter,
+ timePeriod: scope,
+ page,
+ }),
+ API.GET_CONFIG()
+ ).then((res) => res.json()),
+ fetch(
+ API.LEADERBOARD({ limit: 10, page: 1, hubId: 0 }), // Leaderboard
+ API.GET_CONFIG()
+ ).then((res) => res.json()),
+ fetch(API.SORTED_HUB({}), API.GET_CONFIG()).then((res) => res.json()),
+ ]);
+
+ let filterObj = filterOptions.filter((el) => el.value === filter)[0];
+ let scopeObj = scopeOptions.filter((el) => el.value === query.scope)[0];
+
+ return {
+ initialFeed,
+ leaderboardFeed,
+ initialHubList,
+ query,
+ filter: filterObj,
+ scope: scopeObj,
+ };
+ } catch {
+ let defaultProps = {
+ initialFeed: null,
+ leaderboardFeed: null,
+ initialHubList: null,
+ error: true,
+ query: query,
+ };
+ return defaultProps;
+ }
+};
+export default Index;
diff --git a/pages/[filter]/index.js b/pages/[filter]/index.js
new file mode 100644
index 0000000000..9ce73a1ac2
--- /dev/null
+++ b/pages/[filter]/index.js
@@ -0,0 +1,59 @@
+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 } from "~/config/utils/routing";
+import { filterOptions } from "~/config/utils/options";
+
+const Index = (props) => {
+ return ;
+};
+
+Index.getInitialProps = async (ctx) => {
+ let { query } = ctx;
+ let defaultProps = {
+ initialFeed: null,
+ leaderboardFeed: null,
+ initialHubList: null,
+ };
+ let page = query.page ? query.page : 1;
+ let filter = query.filter && slugToFilterQuery(query.filter);
+
+ try {
+ const [initialFeed, leaderboardFeed, initialHubList] = await Promise.all([
+ fetch(
+ API.GET_HUB_PAPERS({
+ // Initial Feed
+ hubId: 0,
+ ordering: filter,
+ timePeriod: getInitialScope(),
+ page,
+ }),
+ API.GET_CONFIG()
+ ).then((res) => res.json()),
+ fetch(
+ API.LEADERBOARD({ limit: 10, page: 1, hubId: 0 }), // Leaderboard
+ API.GET_CONFIG()
+ ).then((res) => res.json()),
+ fetch(API.SORTED_HUB({}), API.GET_CONFIG()).then((res) => res.json()),
+ ]);
+
+ let filterObj = filterOptions.filter((el) => el.value === filter)[0];
+
+ return {
+ initialFeed,
+ leaderboardFeed,
+ initialHubList,
+ query,
+ filter: filterObj,
+ };
+ } catch {
+ return defaultProps;
+ }
+};
+
+export default Index;
diff --git a/pages/_app.js b/pages/_app.js
index 6f2aad38b5..cc0a3a3914 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -45,11 +45,11 @@ class MyApp extends App {
});
Router.events.on("routeChangeComplete", () => {
- window.scroll({
- top: 0,
- left: 0,
- behavior: "auto",
- });
+ // window.scroll({
+ // top: 0,
+ // left: 0,
+ // behavior: "auto",
+ // });
ReactGA.pageview(props.router.asPath);
props.store.dispatch(MessageActions.showMessage({ show: false }));
});
diff --git a/pages/hubs/[slug]/[filter]/[scope]/index.js b/pages/hubs/[slug]/[filter]/[scope]/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/pages/hubs/[slug]/[filter]/index.js b/pages/hubs/[slug]/[filter]/index.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/pages/index.js b/pages/index.js
index f145da38c2..8d155d0197 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -1,9 +1,10 @@
import { connect } from "react-redux";
import { StyleSheet } from "aphrodite";
-import API from "~/config/api";
+import { useRouter } from "next/router";
import HubPage from "../components/Hubs/HubPage";
+import API from "~/config/api";
import { getInitialScope } from "~/config/utils/dates";
class Index extends React.Component {
@@ -14,15 +15,16 @@ class Index extends React.Component {
leaderboardFeed: null,
initialHubList: null,
};
+ let page = query.page ? query.page : 1;
try {
const [initialFeed, leaderboardFeed] = await Promise.all([
fetch(
API.GET_HUB_PAPERS({
- // Initial Feed
hubId: 0,
ordering: "hot",
timePeriod: getInitialScope(),
+ page,
}),
API.GET_CONFIG()
).then((res) => res.json()),
@@ -44,13 +46,4 @@ class Index extends React.Component {
}
}
-var styles = StyleSheet.create({});
-
-const mapStateToProps = (state) => ({});
-
-const mapDispatchToProps = {};
-
-export default connect(
- mapStateToProps,
- mapDispatchToProps
-)(Index);
+export default Index;
diff --git a/pages/paper/[paperId]/[paperName]/index.js b/pages/paper/[paperId]/[paperName]/index.js
index 399017c352..b2f31d9edf 100644
--- a/pages/paper/[paperId]/[paperName]/index.js
+++ b/pages/paper/[paperId]/[paperName]/index.js
@@ -52,7 +52,7 @@ const Paper = (props) => {
if (props.redirectPath && typeof window !== "undefined") {
// updates the [paperName] without refetching data
- router.push("/paper/[paperId]/[paperName]", props.redirectPath, {
+ router.replace("/paper/[paperId]/[paperName]", props.redirectPath, {
shallow: true,
});
}
diff --git a/redux/configureStore.js b/redux/configureStore.js
index dd7d5b6624..7ab4da63ef 100644
--- a/redux/configureStore.js
+++ b/redux/configureStore.js
@@ -11,14 +11,14 @@ export function configureStore(initialState = {}) {
const logger = createLogger({
colors: false,
});
- middleware.push(logger); // Logger must be the last item in middleware
+ // middleware.push(logger); // Logger must be the last item in middleware
}
let store = createStore(
reducer,
initialState,
- composeWithDevTools(applyMiddleware(...middleware))
- // applyMiddleware(...middleware)
+ // composeWithDevTools(applyMiddleware(...middleware))
+ applyMiddleware(...middleware)
);
return store;
}
From 054071fa6fa6db23f164307f54c818c083e8ab14 Mon Sep 17 00:00:00 2001
From: joshslee
Date: Tue, 8 Sep 2020 18:37:25 -0700
Subject: [PATCH 2/4] selector slugs for hub page
---
components/Hubs/HubPage.js | 61 ++++---
pages/hubs/[slug]/[filter]/[scope]/index.js | 182 ++++++++++++++++++++
pages/hubs/[slug]/[filter]/index.js | 173 +++++++++++++++++++
3 files changed, 391 insertions(+), 25 deletions(-)
diff --git a/components/Hubs/HubPage.js b/components/Hubs/HubPage.js
index 3e5c4dc560..3e487fa775 100644
--- a/components/Hubs/HubPage.js
+++ b/components/Hubs/HubPage.js
@@ -372,17 +372,7 @@ class HubPage extends React.Component {
loadingMore: false,
},
() => {
- let filter = this.state.filterBy.label
- .split(" ")
- .join("-")
- .toLowerCase();
- Router.push(
- this.state.disableScope ? "/" : "/[filter]/[scope]",
- this.state.disableScope
- ? `/${filter}?page=${this.state.page}`
- : `${filter}/${this.state.scope.value}?page=${this.state.page}`,
- { shallow: true }
- );
+ this.updateSlugs();
}
);
})
@@ -393,6 +383,40 @@ class HubPage extends React.Component {
);
};
+ updateSlugs = () => {
+ let { filterBy, scope, page, 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}?page=${page}`;
+ } 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}?page=${page}`;
+ } else {
+ href = "/hubs/[slug]/[filter]/[scope]";
+ as = `/hubs/${this.props.slug}/${filter}/${scope.value}`;
+ }
+ }
+
+ Router.push(href, as, { shallow: true });
+ };
+
calculateScope = () => {
let scope = {
start: 0,
@@ -469,20 +493,7 @@ class HubPage extends React.Component {
...param,
},
() => {
- let filter = this.state.filterBy.label
- .split(" ")
- .join("-")
- .toLowerCase();
- if (this.state.filterBy.disableScope) {
- Router.push("/[filter]", `/${filter}`, {
- shallow: true,
- });
- } else {
- let scope = this.state.scope.value;
- Router.push("/[filter]/[scope]", `/${filter}/${scope}`, {
- shallow: true,
- });
- }
+ this.updateSlugs();
}
);
};
diff --git a/pages/hubs/[slug]/[filter]/[scope]/index.js b/pages/hubs/[slug]/[filter]/[scope]/index.js
index e69de29bb2..9e44e54677 100644
--- a/pages/hubs/[slug]/[filter]/[scope]/index.js
+++ b/pages/hubs/[slug]/[filter]/[scope]/index.js
@@ -0,0 +1,182 @@
+import React from "react";
+import Router from "next/router";
+import { connect } from "react-redux";
+
+// Components
+import Head from "~/components/Head";
+import HubPage from "~/components/Hubs/HubPage";
+
+// Redux
+import { AuthActions } from "~/redux/auth";
+
+// Config
+import API from "~/config/api";
+import { Helpers } from "@quantfive/js-web-config";
+import { toTitleCase } from "~/config/utils";
+import { getInitialScope } from "~/config/utils/dates";
+import {
+ slugToFilterQuery,
+ calculateScopeFromSlug,
+} from "~/config/utils/routing";
+import { filterOptions, scopeOptions } from "~/config/utils/options";
+
+class Index extends React.Component {
+ static async getInitialProps(ctx) {
+ let { query } = ctx;
+
+ let page = query.page ? query.page : 1;
+ let filter = query.filter && slugToFilterQuery(query.filter);
+ let scope = query.scope
+ ? calculateScopeFromSlug(query.scope)
+ : getInitialScope();
+
+ try {
+ const { slug, name } = ctx.query;
+ const currentHub = await fetch(API.HUB({ slug }), API.GET_CONFIG())
+ .then((res) => res.json())
+ .then((body) => body.results[0]);
+
+ const [initialFeed, leaderboardFeed, initialHubList] = await Promise.all([
+ fetch(
+ API.GET_HUB_PAPERS({
+ // Initial Feed
+ hubId: currentHub.id,
+ ordering: filter,
+ timePeriod: scope,
+ page,
+ }),
+ API.GET_CONFIG()
+ ).then((res) => res.json()),
+ fetch(
+ API.LEADERBOARD({ limit: 10, page: 1, hubId: currentHub.id }), // Leaderboard
+ API.GET_CONFIG()
+ ).then((res) => res.json()),
+ fetch(API.SORTED_HUB({}), API.GET_CONFIG()).then((res) => res.json()),
+ ]);
+
+ let filterObj = filterOptions.filter((el) => el.value === filter)[0];
+ let scopeObj = scopeOptions.filter((el) => el.value === query.scope)[0];
+
+ return {
+ slug,
+ name,
+ currentHub,
+ initialProps: {
+ initialFeed,
+ leaderboardFeed,
+ initialHubList,
+ },
+ filter: filterObj,
+ scope: scopeObj,
+ };
+ } catch {
+ let defaultProps = {
+ initialFeed: null,
+ leaderboardFeed: null,
+ initialHubList: null,
+ };
+
+ return {
+ slug: null,
+ name: null,
+ currentHub: null,
+ initialProps: { ...defaultProps },
+ };
+ }
+ }
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ slug: this.props.slug ? decodeURIComponent(this.props.slug) : "",
+ currentHub: this.props.currentHub
+ ? this.props.currentHub
+ : {
+ name: this.props.name
+ ? this.props.name
+ ? decodeURIComponent(this.props.name)
+ : "ResearchHub"
+ : "",
+ slug: this.props.slug ? decodeURIComponent(this.props.slug) : "",
+ },
+ hubDescription: this.props.currentHub
+ ? "Discuss and Discover " + toTitleCase(this.props.currentHub.name)
+ : "Discuss and Discover " + toTitleCase(this.props.slug),
+ };
+ }
+
+ componentDidMount() {
+ if (!this.props.initialProps) {
+ this.fetchHubInfo(this.state.slug);
+ }
+ }
+
+ componentDidUpdate(prevProp) {
+ if (Router.router.query.slug !== this.state.slug) {
+ this.setState(
+ {
+ slug: Router.router.query.slug,
+ },
+ () => {
+ this.fetchHubInfo(Router.router.query.slug);
+ }
+ );
+ }
+ }
+
+ fetchHubInfo = async (name) => {
+ const currentHub = await fetchHub(name);
+ if (currentHub) {
+ this.setState({
+ currentHub,
+ hubDescription: this.props.hub && this.props.hub.name,
+ });
+ }
+ };
+
+ render() {
+ const { currentHub, slug } = this.state;
+ return (
+
+ {process.browser ? (
+
+ ) : (
+
+ )}
+
+
+ );
+ }
+}
+
+function fetchHub(slug) {
+ return fetch(API.HUB({ slug }), API.GET_CONFIG())
+ .then(Helpers.checkStatus)
+ .then(Helpers.parseJSON)
+ .then((res) => {
+ return res.results[0]; // TODO: Shim and catch errors
+ });
+}
+
+export default Index;
diff --git a/pages/hubs/[slug]/[filter]/index.js b/pages/hubs/[slug]/[filter]/index.js
index e69de29bb2..6f2075787a 100644
--- a/pages/hubs/[slug]/[filter]/index.js
+++ b/pages/hubs/[slug]/[filter]/index.js
@@ -0,0 +1,173 @@
+import React from "react";
+import Router from "next/router";
+import { connect } from "react-redux";
+
+// Components
+import Head from "~/components/Head";
+import HubPage from "~/components/Hubs/HubPage";
+
+// Redux
+import { AuthActions } from "~/redux/auth";
+
+// Config
+import API from "~/config/api";
+import { Helpers } from "@quantfive/js-web-config";
+import { toTitleCase } from "~/config/utils";
+import { getInitialScope } from "~/config/utils/dates";
+import { slugToFilterQuery } from "~/config/utils/routing";
+import { filterOptions } from "~/config/utils/options";
+
+class Index extends React.Component {
+ static async getInitialProps(ctx) {
+ let { query } = ctx;
+
+ let page = query.page ? query.page : 1;
+ let filter = query.filter && slugToFilterQuery(query.filter);
+
+ try {
+ const { slug, name } = ctx.query;
+ const currentHub = await fetch(API.HUB({ slug }), API.GET_CONFIG())
+ .then((res) => res.json())
+ .then((body) => body.results[0]);
+
+ const [initialFeed, leaderboardFeed, initialHubList] = await Promise.all([
+ fetch(
+ API.GET_HUB_PAPERS({
+ // Initial Feed
+ hubId: currentHub.id,
+ ordering: filter,
+ timePeriod: getInitialScope(),
+ page,
+ }),
+ API.GET_CONFIG()
+ ).then((res) => res.json()),
+ fetch(
+ API.LEADERBOARD({ limit: 10, page: 1, hubId: currentHub.id }), // Leaderboard
+ API.GET_CONFIG()
+ ).then((res) => res.json()),
+ fetch(API.SORTED_HUB({}), API.GET_CONFIG()).then((res) => res.json()),
+ ]);
+
+ let filterObj = filterOptions.filter((el) => el.value === filter)[0];
+
+ return {
+ slug,
+ name,
+ currentHub,
+ initialProps: {
+ initialFeed,
+ leaderboardFeed,
+ initialHubList,
+ },
+ filter: filterObj,
+ };
+ } catch {
+ let defaultProps = {
+ initialFeed: null,
+ leaderboardFeed: null,
+ initialHubList: null,
+ };
+
+ return {
+ slug: null,
+ name: null,
+ currentHub: null,
+ initialProps: { ...defaultProps },
+ };
+ }
+ }
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ slug: this.props.slug ? decodeURIComponent(this.props.slug) : "",
+ currentHub: this.props.currentHub
+ ? this.props.currentHub
+ : {
+ name: this.props.name
+ ? this.props.name
+ ? decodeURIComponent(this.props.name)
+ : "ResearchHub"
+ : "",
+ slug: this.props.slug ? decodeURIComponent(this.props.slug) : "",
+ },
+ hubDescription: this.props.currentHub
+ ? "Discuss and Discover " + toTitleCase(this.props.currentHub.name)
+ : "Discuss and Discover " + toTitleCase(this.props.slug),
+ };
+ }
+
+ componentDidMount() {
+ if (!this.props.initialProps) {
+ this.fetchHubInfo(this.state.slug);
+ }
+ }
+
+ componentDidUpdate(prevProp) {
+ if (Router.router.query.slug !== this.state.slug) {
+ this.setState(
+ {
+ slug: Router.router.query.slug,
+ },
+ () => {
+ this.fetchHubInfo(Router.router.query.slug);
+ }
+ );
+ }
+ }
+
+ fetchHubInfo = async (name) => {
+ const currentHub = await fetchHub(name);
+ if (currentHub) {
+ this.setState({
+ currentHub,
+ hubDescription: this.props.hub && this.props.hub.name,
+ });
+ }
+ };
+
+ render() {
+ const { currentHub, slug } = this.state;
+ return (
+
+ {process.browser ? (
+
+ ) : (
+
+ )}
+
+
+ );
+ }
+}
+
+function fetchHub(slug) {
+ return fetch(API.HUB({ slug }), API.GET_CONFIG())
+ .then(Helpers.checkStatus)
+ .then(Helpers.parseJSON)
+ .then((res) => {
+ return res.results[0]; // TODO: Shim and catch errors
+ });
+}
+
+export default Index;
From ed6d01fcf0f34bf0ee7bb8a88062b7b50fc490a7 Mon Sep 17 00:00:00 2001
From: joshslee
Date: Wed, 9 Sep 2020 17:15:36 -0700
Subject: [PATCH 3/4] pagination and remove trending slug
---
components/Hubs/HubPage.js | 78 ++++++++++++++------------------------
1 file changed, 28 insertions(+), 50 deletions(-)
diff --git a/components/Hubs/HubPage.js b/components/Hubs/HubPage.js
index 3e487fa775..e154b48388 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];
@@ -368,11 +326,19 @@ class HubPage extends React.Component {
{
papers: [...this.state.papers, ...res.results.data],
next: res.next,
+ prev: !res.next ? res.previous : null,
page: this.state.page + 1,
loadingMore: false,
},
() => {
- this.updateSlugs();
+ 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);
}
);
})
@@ -383,8 +349,8 @@ class HubPage extends React.Component {
);
};
- updateSlugs = () => {
- let { filterBy, scope, page, disableScope } = this.state;
+ updateSlugs = (page) => {
+ let { filterBy, scope, disableScope } = this.state;
let filter = filterBy.label
.split(" ")
@@ -397,7 +363,7 @@ class HubPage extends React.Component {
// if filter, but no scope
if (this.props.home) {
href = "/[filter]";
- as = `/${filter}?page=${page}`;
+ as = `/${filter}`;
} else {
// Hub Page
href = "/hubs/[slug]/[filter]";
@@ -407,13 +373,25 @@ class HubPage extends React.Component {
// filter & scope
if (this.props.home) {
href = "/[filter]/[scope]";
- as = `${filter}/${scope.value}?page=${page}`;
+ 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 });
};
From a7c5e924c1c34fa128199185c3dd7edbd2767f83 Mon Sep 17 00:00:00 2001
From: joshslee
Date: Fri, 11 Sep 2020 18:25:18 -0700
Subject: [PATCH 4/4] faster thread submission
---
components/Paper/Tabs/DiscussionTab.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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) {