aboutsummaryrefslogtreecommitdiff
path: root/vnext/src/ui/Feeds.js
diff options
context:
space:
mode:
Diffstat (limited to 'vnext/src/ui/Feeds.js')
-rw-r--r--vnext/src/ui/Feeds.js171
1 files changed, 171 insertions, 0 deletions
diff --git a/vnext/src/ui/Feeds.js b/vnext/src/ui/Feeds.js
new file mode 100644
index 00000000..c7b857b7
--- /dev/null
+++ b/vnext/src/ui/Feeds.js
@@ -0,0 +1,171 @@
+import React, { useState, useEffect } from 'react';
+import PropTypes from 'prop-types';
+import ReactRouterPropTypes from 'react-router-prop-types';
+import { Link } from 'react-router-dom';
+import qs from 'qs';
+import moment from 'moment';
+
+import Message from './Message';
+import Spinner from './Spinner';
+
+import UserInfo from './UserInfo';
+
+import { getMessages } from '../api';
+import { UserType } from './Types';
+
+export function Discover(props) {
+ let search = qs.parse(props.location.search.substring(1));
+ const query = {
+ baseUrl: '/api/messages',
+ search: search,
+ pageParam: search.search ? 'page' : 'before_mid'
+ };
+ return (<Feed authRequired={false} query={query} {...props} />);
+}
+
+export function Discussions(props) {
+ const query = {
+ baseUrl: '/api/messages/discussions',
+ pageParam: 'to'
+ };
+ return (<Feed authRequired={false} query={query} {...props} />);
+}
+
+export function Blog(props) {
+ const { user } = props.match.params;
+ let search = qs.parse(props.location.search.substring(1));
+ search.uname = user;
+ const query = {
+ baseUrl: '/api/messages',
+ search: search,
+ pageParam: search.search ? 'page' : 'before_mid'
+ };
+ return (
+ <>
+ <div className="msg-cont">
+ <UserInfo user={user} />
+ </div>
+ <Feed authRequired={false} query={query} {...props} />
+ </>
+ );
+}
+
+export function Tag(props) {
+ const { tag } = props.match.params;
+ const query = {
+ baseUrl: '/api/messages',
+ search: {
+ tag: tag
+ },
+ pageParam: 'before_mid'
+ };
+ return (<Feed authRequired={false} query={query} {...props} />);
+}
+
+export function Home(props) {
+ const query = {
+ baseUrl: '/api/home',
+ pageParam: 'before_mid'
+ };
+ return (<Feed authRequired={true} query={query} {...props} />);
+}
+
+function Feed(props) {
+ const [msgs, setMsgs] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [nextpage, setNextpage] = useState(null);
+ const [error, setError] = useState(false);
+
+ useEffect(() => {
+ let loadMessages = (hash = '', filter = '') => {
+ document.body.scrollTop = 0;
+ document.documentElement.scrollTop = 0;
+ setMsgs([]);
+ const filterParams = qs.parse(filter);
+ let params = Object.assign({}, filterParams || {}, props.query.search || {});
+ let url = props.query.baseUrl;
+ if (hash) {
+ params.hash = hash;
+ }
+ if (!params.hash && props.authRequired) {
+ props.history.push('/');
+ }
+ getMessages(url, params)
+ .then(response => {
+ const { data } = response;
+ const { pageParam } = props.query;
+ const lastMessage = data.slice(-1)[0] || {};
+ const nextpage = getPageParam(pageParam, lastMessage, filterParams);
+ setMsgs(data);
+ setLoading(false);
+ setNextpage(nextpage);
+ }).catch(ex => {
+ setError(true);
+ });
+ };
+ loadMessages(props.visitor.hash, props.location.search.substring(1));
+ }, [props]);
+
+ let getPageParam = (pageParam, lastMessage, filterParams) => {
+ const pageValue = pageParam === 'before_mid' ? lastMessage.mid : pageParam === 'page' ? (Number(filterParams.page) || 0) + 1 : moment.utc(lastMessage.updated).valueOf();
+ let newFilter = { ...filterParams };
+ newFilter[pageParam] = pageValue;
+ return `?${qs.stringify(newFilter)}`;
+ };
+ const { tag } = qs.parse(location.search.substring(1) || {});
+ const nodes = (
+ <>
+ {
+ tag && (
+ <p className="page">
+ <Link to={{ pathname: `/tag/${tag}` }}>
+ <span>← All posts with tag&nbsp;</span><b>{tag}</b>
+ </Link>
+ </p>
+ )
+ }
+ {
+ msgs.map(msg =>
+ <Message key={msg.mid} data={msg} visitor={props.visitor} />)
+ }
+ {
+ msgs.length >= 20 && (
+ <p className="page">
+ <Link to={{ pathname: props.location.pathname, search: nextpage }} rel="prev">Next →</Link>
+ </p>
+ )
+ }
+ </>
+ );
+ return msgs.length > 0 ? (
+ <div className="msgs">{nodes}</div>
+ ) : error ? <div>error</div> : loading ? <div className="msgs"><Spinner /><Spinner /><Spinner /><Spinner /></div> : <div>No more messages</div>;
+}
+
+Discover.propTypes = {
+ location: ReactRouterPropTypes.location.isRequired,
+ search: PropTypes.string
+};
+
+Blog.propTypes = {
+ match: ReactRouterPropTypes.match.isRequired,
+ location: ReactRouterPropTypes.location.isRequired,
+ search: PropTypes.string
+};
+
+Tag.propTypes = {
+ match: ReactRouterPropTypes.match.isRequired
+};
+
+Feed.propTypes = {
+ authRequired: PropTypes.bool,
+ visitor: UserType,
+ history: ReactRouterPropTypes.history.isRequired,
+ location: ReactRouterPropTypes.location.isRequired,
+ msgs: PropTypes.array,
+ query: PropTypes.shape({
+ baseUrl: PropTypes.string.isRequired,
+ search: PropTypes.object,
+ pageParam: PropTypes.string.isRequired
+ })
+};