This commit is contained in:
Riccardo
2021-01-01 17:53:30 +01:00
parent 129d036f6b
commit 529c99cc9d
9 changed files with 216 additions and 12 deletions

View File

@@ -7,7 +7,7 @@ import CreateLink from './CreateLink'
import Header from './Header';
import Login from './Login'
import Search from './Search';
import { Switch, Route } from 'react-router-dom';
import { Redirect, Route, Switch } from 'react-router-dom';
const App = () => {
return (
@@ -23,6 +23,11 @@ const App = () => {
/>
<Route exact path="/login" component={Login} />
<Route exact path="/search" component={Search} />
<Route
exact
path="/new/:page"
component={LinkList}
/>
</Switch>
</div>
</div>

View File

@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import { useHistory } from 'react-router';
import { useMutation, gql } from '@apollo/client';
import { LINKS_PER_PAGE } from '../constants';
import { FEED_QUERY } from './LinkList';
const CREATE_LINK_MUTATION = gql`

View File

@@ -16,7 +16,7 @@ const Header = () => {
<div className="ml1">|</div>
<Link to="/top" className="ml1 no-underline black">
top
</Link>
</Link>
<div className="ml1">|</div>
<Link to="/search" className="ml1 no-underline black">
search

View File

@@ -2,6 +2,7 @@ import React from 'react';
import { useMutation, gql } from '@apollo/client';
import { AUTH_TOKEN, LINKS_PER_PAGE } from '../constants';
import { timeDifferenceForDate } from '../utils'
import { FEED_QUERY } from './LinkList'
const VOTE_MUTATION = gql`
mutation VoteMutation($linkId: ID!) {
@@ -23,6 +24,10 @@ const VOTE_MUTATION = gql`
}
`;
const take = LINKS_PER_PAGE;
const skip = 0;
const orderBy = { createdAt: 'desc' };
const Link = (props) => {
const { link } = props;
const authToken = localStorage.getItem(AUTH_TOKEN);

View File

@@ -1,11 +1,16 @@
import React from 'react';
import Link from './Link';
import { useHistory } from 'react-router';
import { LINKS_PER_PAGE } from '../constants';
import { useQuery, gql } from '@apollo/client';
export const FEED_QUERY = gql`
{
feed {
query FeedQuery(
$take: Int
$skip: Int
$orderBy: LinkOrderByInput
) {
feed(take: $take, skip: $skip, orderBy: $orderBy) {
id
links {
id
@@ -23,23 +28,146 @@ export const FEED_QUERY = gql`
}
}
}
count
}
}
`;
const NEW_LINKS_SUBSCRIPTION = gql`
subscription {
newLink {
id
url
description
createdAt
postedBy {
id
name
}
votes {
id
user {
id
}
}
}
}
`;
const getQueryVariables = (isNewPage, page) => {
const skip = isNewPage ? (page - 1) * LINKS_PER_PAGE : 0;
const take = isNewPage ? LINKS_PER_PAGE : 10;
const orderBy = { createdAt: 'desc' };
console.log(isNewPage, page, LINKS_PER_PAGE, skip, take, orderBy);
return { take, skip, orderBy };
};
const LinkList = () => {
const { data } = useQuery(FEED_QUERY);
const history = useHistory();
const isNewPage = history.location.pathname.includes(
'new'
);
const pageIndexParams = history.location.pathname.split(
'/'
);
const page = parseInt(
pageIndexParams.length - 1
// pageIndexParams[pageIndexParams.length - 1]
);
console.log(pageIndexParams.length, page);
const pageIndex = page ? (page - 1) * LINKS_PER_PAGE : 0;
const {
data,
loading,
error,
subscribeToMore
} = useQuery(FEED_QUERY, {
variables: getQueryVariables(isNewPage, page)
});
// const { data } = useQuery(FEED_QUERY);
const getLinksToRender = (isNewPage, data) => {
if (isNewPage) {
return data.feed.links;
}
const rankedLinks = data.feed.links.slice();
rankedLinks.sort(
(l1, l2) => l2.votes.length - l1.votes.length
);
return rankedLinks;
};
subscribeToMore({
document: NEW_LINKS_SUBSCRIPTION,
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) return prev;
const newLink = subscriptionData.data.newLink;
const exists = prev.feed.links.find(
({ id }) => id === newLink.id
);
if (exists) return prev;
return Object.assign({}, prev, {
feed: {
links: [newLink, ...prev.feed.links],
count: prev.feed.links.length + 1,
__typename: prev.feed.__typename
}
});
}
});
return (
<div>
<>
{loading && <p>Loading...</p>}
{error && <pre>{JSON.stringify(error, null, 2)}</pre>}
{data && (
<>
{data.feed.links.map((link, index) => (
<Link key={link.id} link={link} index={index} />
))}
{getLinksToRender(isNewPage, data).map(
(link, index) => (
<Link
key={link.id}
link={link}
index={index + pageIndex}
/>
)
)}
{isNewPage && (
<div className="flex ml4 mv3 gray">
<div
className="pointer mr2"
onClick={() => {
if (page > 1) {
history.push(`/new/${page - 1}`);
}
}}
>
Previous
</div>
<div
className="pointer"
onClick={() => {
if (
page <=
data.feed.count / LINKS_PER_PAGE
) {
const nextPage = page + 1;
history.push(`/new/${nextPage}`);
}
}}
>
Next
</div>
</div>
)}
</>
)}
</div>
</>
);
};
@@ -57,7 +185,7 @@ const LinkList = () => {
// url: 'https://www.apollographql.com/docs/react/'
// }
// ];
//
// return (
// <div>
// {linksToRender.map((link) => (

View File

@@ -2,6 +2,10 @@ import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import { setContext } from '@apollo/client/link/context';
import { AUTH_TOKEN } from './constants';
import { split } from '@apollo/client';
import { WebSocketLink } from '@apollo/client/link/ws';
import { getMainDefinition } from '@apollo/client/utilities';
// import LinkList from './components/LinkList';
// class App extends Component {
@@ -43,9 +47,31 @@ const authLink = setContext((_, { headers }) => {
};
});
const wsLink = new WebSocketLink({
uri: `ws://localhost:4000/graphql`,
options: {
reconnect: true,
connectionParams: {
authToken: localStorage.getItem(AUTH_TOKEN)
}
}
});
const link = split(
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return (
kind === 'OperationDefinition' &&
operation === 'subscription'
);
},
wsLink,
authLink.concat(httpLink)
);
// 3
const client = new ApolloClient({
link: authLink.concat(httpLink),
link,
// link: httpLink,
cache: new InMemoryCache()
});