useQuery fix

This commit is contained in:
Riccardo
2021-01-04 18:48:05 +01:00
parent 61acbf02d8
commit 82055b4040
11 changed files with 405 additions and 381 deletions

View File

@@ -1,9 +1,9 @@
import React from 'react';
// import CreateAppointment from './CreateAppointment';
import Header from './Header';
// import AppointmentList from './AppointmentList';
import ProductList from './ProductList';
import { Switch, Route } from 'react-router-dom';
import ProductList from './ProductList';
import AppointmentList from './AppointmentList';
const App = () => {
return (
@@ -11,8 +11,8 @@ const App = () => {
<Header />
<div className="ph3 pv1 background-gray">
<Switch>
<Route exact path="/" component={ProductList} />
{/* <Route exact path="/" component={AppointmentList} /> */}
{/* <Route exact path="/" component={ProductList} /> */}
<Route exact path="/" component={AppointmentList} />
{/* <Route exact path="/create" component={CreateAppointment} /> */}
</Switch>
</div>

View File

@@ -1,98 +1,113 @@
import React from 'react';
import { useMutation, gql } from '@apollo/client';
import { AUTH_TOKEN, APPOINTMENTS_PER_PAGE } from '../constants';
import { timeDifferenceForDate } from '../utils'
import { FEED_QUERY } from './AppointmentList'
const FOLLOW_MUTATION = gql`
mutation FollowMutation($appointmentId: ID!) {
follow(followId: $followId) {
id
appointment {
id
follows {
id
user {
id
}
}
}
user {
id
}
}
}
`;
const take = APPOINTMENTS_PER_PAGE;
const skip = 0;
const orderBy = { createdAt: 'desc' };
const Appointment = (props) => {
const { appointment } = props;
const authToken = localStorage.getItem(AUTH_TOKEN);
const take = APPOINTMENTS_PER_PAGE;
const skip = 0;
const orderBy = { createdAt: 'desc' };
const [follow] = useMutation(FOLLOW_MUTATION, {
variables: {
appointmentId: appointment.id
},
update(cache, { data: { follow } }) {
const { feed } = cache.readQuery({
query: FEED_QUERY
});
const updatedAppointments = feed.follows.map((feedFollow) => {
if (feedFollow.id === appointment.id) {
return {
...feedFollow,
follows: [...feedFollow.follows, follow]
};
}
return feedFollow;
});
cache.writeQuery({
query: FEED_QUERY,
data: {
feed: {
appointments: updatedAppointments
}
}
});
}
});
return (
<div className="flex mt2 items-start">
<div className="flex items-center">
<span className="gray">{props.index + 1}.</span>
{authToken && (
<div
className="ml1 gray f11"
style={{ cursor: 'pointer' }}
onClick={follow}
>
</div>
)}
</div>
<div className="ml1">
<div>
{appointment.title} ({appointment.description})
</div>
{authToken && (
<div className="f6 lh-copy gray">
{appointment.follows.length} follows | by{' '}
{follow.createdBy ? follow.createdBy.name : 'Unknown'}{' '}
{timeDifferenceForDate(appointment.createdAt)}
</div>
)}
</div>
<div>
<div>
<b>{appointment.title}</b> starts at {appointment.timeStart}, ends at {appointment.timeEnd}. It is described as "{appointment.description}"
</div>
</div>
);
};
export default Appointment;
export default Appointment;
// import React from 'react';
// import { useMutation, gql } from '@apollo/client';
// import { AUTH_TOKEN, APPOINTMENTS_PER_PAGE } from '../constants';
// import { timeDifferenceForDate } from '../utils'
// import { FEED_QUERY } from './AppointmentList'
// const FOLLOW_MUTATION = gql`
// mutation FollowMutation($appointmentId: ID!) {
// follow(followId: $followId) {
// id
// appointment {
// id
// follows {
// id
// user {
// id
// }
// }
// }
// user {
// id
// }
// }
// }
// `;
// const take = APPOINTMENTS_PER_PAGE;
// const skip = 0;
// const orderBy = { createdAt: 'desc' };
// const Appointment = (props) => {
// const { appointment } = props;
// const authToken = localStorage.getItem(AUTH_TOKEN);
// const take = APPOINTMENTS_PER_PAGE;
// const skip = 0;
// const orderBy = { createdAt: 'desc' };
// const [follow] = useMutation(FOLLOW_MUTATION, {
// variables: {
// appointmentId: appointment.id
// },
// update(cache, { data: { follow } }) {
// const { feed } = cache.readQuery({
// query: FEED_QUERY
// });
// const updatedAppointments = feed.follows.map((feedFollow) => {
// if (feedFollow.id === appointment.id) {
// return {
// ...feedFollow,
// follows: [...feedFollow.follows, follow]
// };
// }
// return feedFollow;
// });
// cache.writeQuery({
// query: FEED_QUERY,
// data: {
// feed: {
// appointments: updatedAppointments
// }
// }
// });
// }
// });
// return (
// <div className="flex mt2 items-start">
// <div className="flex items-center">
// <span className="gray">{props.index + 1}.</span>
// {authToken && (
// <div
// className="ml1 gray f11"
// style={{ cursor: 'pointer' }}
// onClick={follow}
// >
// ▲
// </div>
// )}
// </div>
// <div className="ml1">
// <div>
// {appointment.title} ({appointment.description})
// </div>
// {authToken && (
// <div className="f6 lh-copy gray">
// {appointment.follows.length} follows | by{' '}
// {follow.createdBy ? follow.createdBy.name : 'Unknown'}{' '}
// {timeDifferenceForDate(appointment.createdAt)}
// </div>
// )}
// </div>
// </div>
// );
// };
// export default Appointment;

View File

@@ -1,174 +1,217 @@
import React from 'react';
import Appointment from './Appointment';
import { useHistory } from 'react-router';
import { APPOINTMENTS_PER_PAGE } from '../constants';
import { useQuery, gql } from '@apollo/client';
import { Link } from 'react-router-dom';
export const FEED_QUERY = gql`
query AppointmentManyQuery(
$take: Int
$skip: Int
$orderBy: AppointmentOrderByInput
) {
appointmentMany(take: $take, skip: $skip, orderBy: $orderBy) {
id
appointments {
id
createdAt
title
# start
# end
description
# createdBy {
# id
# name
# }
# follows {
# id
# user {
# id
# }
# }
}
count
const APPOINTMENTS_QUERY = gql`
{
allAppointments{
title
description
timeStart
timeEnd
}
}
`;
// const NEW_APPOINTMENTS_SUBSCRIPTION = gql`
// subscription {
// newAppointment {
const AppointmentList = () => {
const { data } = useQuery(APPOINTMENTS_QUERY);
console.log("Data:", data);
if (data !== undefined) {
return (
<div>
{
data.allAppointments.map((appointment) => (
<Appointment key={appointment.id} appointment={appointment} />
))
}
</div>
);
} else {
return (
<div>
Rendering...
</div>
)
}
};
export default AppointmentList;
// import React from 'react';
// import Appointment from './Appointment';
// import { useHistory } from 'react-router';
// import { APPOINTMENTS_PER_PAGE } from '../constants';
// import { useQuery, gql } from '@apollo/client';
// import { Link } from 'react-router-dom';
// export const FEED_QUERY = gql`
// query AppointmentManyQuery(
// $take: Int
// $skip: Int
// $orderBy: AppointmentOrderByInput
// ) {
// appointmentMany(take: $take, skip: $skip, orderBy: $orderBy) {
// id
// url
// description
// createdAt
// createdBy {
// appointments {
// id
// name
// }
// follows {
// id
// user {
// id
// }
// createdAt
// title
// # start
// # end
// description
// # createdBy {
// # id
// # name
// # }
// # follows {
// # id
// # user {
// # id
// # }
// # }
// }
// count
// }
// }
// `;
const getQueryVariables = (isNewPage, page) => {
const skip = isNewPage ? (page - 1) * APPOINTMENTS_PER_PAGE : 0;
const take = isNewPage ? APPOINTMENTS_PER_PAGE : 100;
const orderBy = { createdAt: 'desc' };
// // const NEW_APPOINTMENTS_SUBSCRIPTION = gql`
// // subscription {
// // newAppointment {
// // id
// // url
// // description
// // createdAt
// // createdBy {
// // id
// // name
// // }
// // follows {
// // id
// // user {
// // id
// // }
// // }
// // }
// // }
// // `;
return { take, skip, orderBy };
};
// const getQueryVariables = (isNewPage, page) => {
// const skip = isNewPage ? (page - 1) * APPOINTMENTS_PER_PAGE : 0;
// const take = isNewPage ? APPOINTMENTS_PER_PAGE : 100;
// const orderBy = { createdAt: 'desc' };
const AppointmentList = () => {
const history = useHistory();
const isNewPage = history.location.pathname.includes(
'new'
);
const pageIndexParams = history.location.pathname.split(
'/'
);
// return { take, skip, orderBy };
// };
const page = parseInt(
pageIndexParams[pageIndexParams.length - 1]
);
// const AppointmentList = () => {
// const history = useHistory();
// const isNewPage = history.location.pathname.includes(
// 'new'
// );
// const pageIndexParams = history.location.pathname.split(
// '/'
// );
const pageIndex = page ? (page - 1) * APPOINTMENTS_PER_PAGE : 0;
// const page = parseInt(
// pageIndexParams[pageIndexParams.length - 1]
// );
const {
data,
loading,
error,
subscribeToMore
} = useQuery(FEED_QUERY, {
variables: getQueryVariables(isNewPage, page)
});
// const pageIndex = page ? (page - 1) * APPOINTMENTS_PER_PAGE : 0;
// const { data } = useQuery(FEED_QUERY);
// const {
// data,
// loading,
// error,
// subscribeToMore
// } = useQuery(FEED_QUERY, {
// variables: getQueryVariables(isNewPage, page)
// });
const getAppointmentsToRender = (isNewPage, data) => {
if (isNewPage) {
return data.feed.appointments;
}
const rankedAppointments = data.feed.appointments.slice();
rankedAppointments.sort(
(l1, l2) => l2.follows.length - l1.follows.length
);
return rankedAppointments;
};
// // const { data } = useQuery(FEED_QUERY);
// subscribeToMore({
// document: NEW_APPOINTMENTS_SUBSCRIPTION,
// updateQuery: (prev, { subscriptionData }) => {
// if (!subscriptionData.data) return prev;
// const newAppointment = subscriptionData.data.newAppointment;
// const exists = prev.feed.appointments.find(
// ({ id }) => id === newAppointment.id
// );
// if (exists) return prev;
// const getAppointmentsToRender = (isNewPage, data) => {
// if (isNewPage) {
// return data.feed.appointments;
// }
// const rankedAppointments = data.feed.appointments.slice();
// rankedAppointments.sort(
// (l1, l2) => l2.follows.length - l1.follows.length
// );
// return rankedAppointments;
// };
// return Object.assign({}, prev, {
// feed: {
// appointments: [newAppointment, ...prev.feed.appointments],
// count: prev.feed.appointments.length + 1,
// __typename: prev.feed.__typename
// }
// });
// }
// });
// // subscribeToMore({
// // document: NEW_APPOINTMENTS_SUBSCRIPTION,
// // updateQuery: (prev, { subscriptionData }) => {
// // if (!subscriptionData.data) return prev;
// // const newAppointment = subscriptionData.data.newAppointment;
// // const exists = prev.feed.appointments.find(
// // ({ id }) => id === newAppointment.id
// // );
// // if (exists) return prev;
return (
<>
{loading && <p>Loading...</p>}
{error && <pre>{JSON.stringify(error, null, 2)}</pre>}
{data && (
<>
{getAppointmentsToRender(isNewPage, data).map(
(appointment, index) => (
<Link
key={appointment.id}
link={appointment}
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 / APPOINTMENTS_PER_PAGE
) {
const nextPage = page + 1;
history.push(`/new/${nextPage}`);
}
}}
>
Next
</div>
</div>
)}
</>
)}
</>
);
};
// // return Object.assign({}, prev, {
// // feed: {
// // appointments: [newAppointment, ...prev.feed.appointments],
// // count: prev.feed.appointments.length + 1,
// // __typename: prev.feed.__typename
// // }
// // });
// // }
// // });
export default AppointmentList;
// return (
// <>
// {loading && <p>Loading...</p>}
// {error && <pre>{JSON.stringify(error, null, 2)}</pre>}
// {data && (
// <>
// {getAppointmentsToRender(isNewPage, data).map(
// (appointment, index) => (
// <Link
// key={appointment.id}
// link={appointment}
// 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 / APPOINTMENTS_PER_PAGE
// ) {
// const nextPage = page + 1;
// history.push(`/new/${nextPage}`);
// }
// }}
// >
// Next
// </div>
// </div>
// )}
// </>
// )}
// </>
// );
// };
// export default AppointmentList;

View File

@@ -1,14 +1,14 @@
import React from 'react';
import { useHistory } from 'react-router';
import { Link, withRouter } from 'react-router-dom';
// import { useHistory } from 'react-router';
// import { Link, withRouter } from 'react-router-dom';
const Header = () => {
const history = useHistory();
// const history = useHistory();
return (
<div className="flex pa1 justify-between nowrap orange">
<div className="flex flex-fixed black">
<div className="fw7 mr1">Hacker News</div>
<Link to="/" className="ml1 no-underline black">
<div className="fw7 mr1">Store!</div>
{/* <Link to="/" className="ml1 no-underline black">
new
</Link>
<div className="ml1">|</div>
@@ -17,7 +17,7 @@ const Header = () => {
className="ml1 no-underline black"
>
submit
</Link>
</Link> */}
</div>
</div>
);

View File

@@ -15,15 +15,26 @@ const ProductList = () => {
const { data } = useQuery(FEED_QUERY);
console.log("Fah!", data);
console.log("Data:", data);
if (data !== undefined) {
return (
<div>
{
data.allProducts.map((product) => (
<Product key={product.id} product={product} />
))
}
</div>
);
} else {
return (
<div>
Rendering...
</div>
)
}
return (
<div>
{data.allProducts.map((product) => (
<Product key={product.id} product={product} />
))}
</div>
);
};
export default ProductList;

View File

@@ -5,7 +5,6 @@ import App from './components/App';
import { BrowserRouter } from 'react-router-dom';
// import * as serviceWorker from './serviceWorker';
// 1
import {
ApolloProvider,
ApolloClient,
@@ -13,18 +12,15 @@ import {
InMemoryCache
} from '@apollo/client';
// 2
const httpLink = createHttpLink({
uri: 'http://localhost:5000/graphql'
uri: 'http://localhost:4000/graphql'
});
// 3
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache()
});
// 4
ReactDOM.render(
<BrowserRouter>
<ApolloProvider client={client}>
@@ -36,9 +32,6 @@ ReactDOM.render(
// serviceWorker.unregister();
// import React from 'react';
// import { BrowserRouter } from 'react-router-dom';
// import { setContext } from '@apollo/client/link/context';
// import { AUTH_TOKEN } from './constants';
@@ -55,25 +48,6 @@ ReactDOM.render(
// // export default App;
// // import React from 'react';
// import ReactDOM from 'react-dom';
// import './styles/index.css';
// import './styles/tachyons.min.css'
// import App from './components/App';
// // // import * as serviceWorker from './serviceWorker';
// // // 1
// import {
// ApolloProvider,
// ApolloClient,
// createHttpLink,
// InMemoryCache
// } from '@apollo/client';
// // 2
// const httpLink = createHttpLink({
// uri: 'http://localhost:4000'
// });
// // attach the auth_token to all requests to GraphQL server
// const authLink = setContext((_, { headers }) => {
@@ -114,17 +88,6 @@ ReactDOM.render(
// cache: new InMemoryCache()
// });
// // 4
// ReactDOM.render(
// <BrowserRouter>
// <ApolloProvider client={client}>
// <App />
// </ApolloProvider>
// </BrowserRouter>,
// document.getElementById('root')
// );
// // serviceWorker.unregister();
// // If you want to start measuring performance in your app, pass a function
// // to log results (for example: reportWebVitals(console.log))
// // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals

View File

@@ -30,33 +30,33 @@ app.use('/graphql', graphqlHTTP({
}));
const server = new ApolloServer({
// typeDefs: fs.readFileSync(
// path.join(__dirname, 'schema.graphql'),
// 'utf8'
// ),
schema,
typeDefs: fs.readFileSync(
path.join(__dirname, 'schema.graphql'),
'utf8'
),
// schema,
cors: true,
playground: process.env.NODE_ENV === 'development' ? true : false,
// context: async ({ req }) => {
// // if (!db) {
// // try {
// // if (!dbClient.isConnected()) await dbClient.connect()
// // mongo = dbClient.db('Calendar') // database name
// // console.log(db);
// // } catch (e) {
// // console.log('--->error while connecting with graphql context (db)', e)
// // }
context: async ({ req }) => {
// if (!db) {
// try {
// if (!dbClient.isConnected()) await dbClient.connect()
// mongo = dbClient.db('Calendar') // database name
// console.log(db);
// } catch (e) {
// console.log('--->error while connecting with graphql context (db)', e)
// }
// return {
// ...req,
// mongoose,
// pubsub,
// userId:
// req && req.headers.authorization
// ? getUserId(req)
// : null
// }
// },
return {
...req,
mongoose,
pubsub,
// userId:
// req && req.headers.authorization
// ? getUserId(req)
// : null
}
},
// subscriptions: {
// onConnect: (connectionParams) => {
// if (connectionParams.authToken) {

View File

@@ -0,0 +1,25 @@
import mongoose from 'mongoose';
const Schema = mongoose.Schema;
const AppointmentSchema = new Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: false
},
timeStart: {
type: Date,
required: true
},
timeEnd: {
type: Date,
required: true
},
deleted: {
type: Boolean,
required: false
}
});
export default mongoose.model('appointment', AppointmentSchema);

View File

@@ -1,14 +1,14 @@
// import Appointment from '../../client/src/components/Appointment.js';
import Product from './models/product.js';
import Appointment from './models/appointment.js';
export const resolvers = {
Query: {
async allProducts() {
const products = await Product.find();
console.log("Tah!", products);
return products;
// return {
// products
// };
return await Product.find();
},
async allAppointments() {
return await Appointment.find();
},
},
Mutation: {

View File

@@ -7,6 +7,7 @@ type Query {
orderBy: AppointmentOrderByInput
): Feed!
allProducts: [Product]
allAppointments: [Appointment]
users: [User!]!
}
@@ -20,8 +21,8 @@ type Mutation {
createAppointment(
title: String!,
description: String!,
start: DateTime!,
end: DateTime!,
timeStart: DateTime!,
timeEnd: DateTime!,
): Appointment!
createProduct(
input: ProductInput
@@ -58,31 +59,32 @@ type AuthPayload {
}
type User {
id: ID!
_id: ID!
name: String!
email: String!
appointments: [Appointment!]!
}
type Appointment {
id: ID!
_id: ID!
title: String!
description: String!
start: DateTime!
end: DateTime!
createdBy: User
follows: [Follow!]!
createdAt: DateTime!
timeStart: DateTime!
timeEnd: DateTime!
deleted: Boolean
# createdBy: User
# follows: [Follow!]!
# createdAt: DateTime!
}
type Product {
id: ID!
_id: ID!
title: String!
qty: Int
}
type Follow {
id: ID!
_id: ID!
appointment: Appointment!
user: User!
}

View File

@@ -1,54 +1,19 @@
// import {
// makeExecutableSchema
// } from 'graphql-tools';
// import {
// resolvers
// } from './resolvers.js';
import fs from 'fs';
import path from 'path';
import { makeExecutableSchema } from 'graphql-tools';
import { resolvers } from './resolvers.js';
// import fs from 'fs';
// import path from 'path';
const moduleURL = new URL(import.meta.url);
const __dirname = path.dirname(moduleURL.pathname);
// const moduleURL = new URL(import.meta.url);
// const __dirname = path.dirname(moduleURL.pathname);
const typeDefs = fs.readFileSync(
path.join(__dirname, 'schema.graphql'),
'utf8'
);
// const typeDefs = fs.readFileSync(
// path.join(__dirname, 'schema.graphql'),
// 'utf8'
// );
// const schema = makeExecutableSchema({
// typeDefs,
// // resolvers
// });
// export default schema;
import {
makeExecutableSchema
} from 'graphql-tools';
import {
resolvers
} from './resolvers.js';
const typeDefs = `
type Product {
_id: ID!
title: String!
qty: Int
}
type Query {
allProducts: [Product]
}
input ProductInput {
title: String!
qty: Int
}
type Mutation {
createProduct(input: ProductInput) : Product
updateProduct(_id: ID!, input: ProductInput): Product
deleteProduct(_id: ID!) : Product
}
`;
const schema = makeExecutableSchema({
typeDefs,
resolvers
});
export default schema;
export default schema;