Progress
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
"react-router": "^5.2.0",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-scripts": "4.0.1",
|
||||
"subscriptions-transport-ws": "^0.9.18",
|
||||
"web-vitals": "^0.2.4"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) => (
|
||||
|
||||
@@ -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()
|
||||
});
|
||||
|
||||
@@ -2689,6 +2689,11 @@ babylon@^6.18.0:
|
||||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
|
||||
integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
|
||||
|
||||
backo2@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
|
||||
integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
@@ -4693,6 +4698,11 @@ etag@~1.8.1:
|
||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
||||
|
||||
eventemitter3@^3.1.0:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
|
||||
integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==
|
||||
|
||||
eventemitter3@^4.0.0:
|
||||
version "4.0.7"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
||||
@@ -6222,6 +6232,11 @@ istanbul-reports@^3.0.2:
|
||||
html-escaper "^2.0.0"
|
||||
istanbul-lib-report "^3.0.0"
|
||||
|
||||
iterall@^1.2.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
|
||||
integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
|
||||
|
||||
jest-changed-files@^26.6.2:
|
||||
version "26.6.2"
|
||||
resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0"
|
||||
@@ -10349,6 +10364,17 @@ stylehacks@^4.0.0:
|
||||
postcss "^7.0.0"
|
||||
postcss-selector-parser "^3.0.0"
|
||||
|
||||
subscriptions-transport-ws@^0.9.18:
|
||||
version "0.9.18"
|
||||
resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.18.tgz#bcf02320c911fbadb054f7f928e51c6041a37b97"
|
||||
integrity sha512-tztzcBTNoEbuErsVQpTN2xUNN/efAZXyCyL5m3x4t6SKrEiTL2N8SaKWBFWM4u56pL79ULif3zjyeq+oV+nOaA==
|
||||
dependencies:
|
||||
backo2 "^1.0.2"
|
||||
eventemitter3 "^3.1.0"
|
||||
iterall "^1.2.1"
|
||||
symbol-observable "^1.0.4"
|
||||
ws "^5.2.0"
|
||||
|
||||
supports-color@^5.3.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||
@@ -10402,6 +10428,11 @@ svgo@^1.0.0, svgo@^1.2.2:
|
||||
unquote "~1.1.1"
|
||||
util.promisify "~1.0.0"
|
||||
|
||||
symbol-observable@^1.0.4:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
|
||||
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
|
||||
|
||||
symbol-observable@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-2.0.3.tgz#5b521d3d07a43c351055fa43b8355b62d33fd16a"
|
||||
@@ -11467,6 +11498,13 @@ write@1.0.3:
|
||||
dependencies:
|
||||
mkdirp "^0.5.1"
|
||||
|
||||
ws@^5.2.0:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
|
||||
integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==
|
||||
dependencies:
|
||||
async-limiter "~1.0.0"
|
||||
|
||||
ws@^6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user