From 82055b40408abaad943232dd08e240e0331433ee Mon Sep 17 00:00:00 2001 From: Riccardo Date: Mon, 4 Jan 2021 18:48:05 +0100 Subject: [PATCH] useQuery fix --- client/src/components/App.js | 8 +- client/src/components/Appointment.js | 193 +++++++------ client/src/components/AppointmentList.js | 339 +++++++++++++---------- client/src/components/Header.js | 12 +- client/src/components/ProductList.js | 27 +- client/src/index.js | 39 +-- server/src/index.js | 48 ++-- server/src/models/appointment.js | 25 ++ server/src/resolvers.js | 12 +- server/src/schema.graphql | 24 +- server/src/schema.js | 59 +--- 11 files changed, 405 insertions(+), 381 deletions(-) create mode 100644 server/src/models/appointment.js diff --git a/client/src/components/App.js b/client/src/components/App.js index d2ab917..4ec12af 100644 --- a/client/src/components/App.js +++ b/client/src/components/App.js @@ -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 = () => {
- - {/* */} + {/* */} + {/* */}
diff --git a/client/src/components/Appointment.js b/client/src/components/Appointment.js index 9d09ba9..7bde2a8 100644 --- a/client/src/components/Appointment.js +++ b/client/src/components/Appointment.js @@ -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 ( -
-
- {props.index + 1}. - {authToken && ( -
- ▲ -
- )} -
-
-
- {appointment.title} ({appointment.description}) -
- {authToken && ( -
- {appointment.follows.length} follows | by{' '} - {follow.createdBy ? follow.createdBy.name : 'Unknown'}{' '} - {timeDifferenceForDate(appointment.createdAt)} -
- )} -
+
+
+ {appointment.title} starts at {appointment.timeStart}, ends at {appointment.timeEnd}. It is described as "{appointment.description}" +
); }; -export default Appointment; \ No newline at end of file +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 ( +//
+//
+// {props.index + 1}. +// {authToken && ( +//
+// ▲ +//
+// )} +//
+//
+//
+// {appointment.title} ({appointment.description}) +//
+// {authToken && ( +//
+// {appointment.follows.length} follows | by{' '} +// {follow.createdBy ? follow.createdBy.name : 'Unknown'}{' '} +// {timeDifferenceForDate(appointment.createdAt)} +//
+// )} +//
+//
+// ); +// }; + +// export default Appointment; \ No newline at end of file diff --git a/client/src/components/AppointmentList.js b/client/src/components/AppointmentList.js index 1019b98..6aa816e 100644 --- a/client/src/components/AppointmentList.js +++ b/client/src/components/AppointmentList.js @@ -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 ( +
+ { + data.allAppointments.map((appointment) => ( + + )) + } +
+ ); + } else { + return ( +
+ Rendering... +
+ ) + } + +}; + +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 &&

Loading...

} - {error &&
{JSON.stringify(error, null, 2)}
} - {data && ( - <> - {getAppointmentsToRender(isNewPage, data).map( - (appointment, index) => ( - - ) - )} - {isNewPage && ( -
-
{ - if (page > 1) { - history.push(`/new/${page - 1}`); - } - }} - > - Previous -
-
{ - if ( - page <= - data.feed.count / APPOINTMENTS_PER_PAGE - ) { - const nextPage = page + 1; - history.push(`/new/${nextPage}`); - } - }} - > - Next -
-
- )} - - )} - - ); -}; +// // return Object.assign({}, prev, { +// // feed: { +// // appointments: [newAppointment, ...prev.feed.appointments], +// // count: prev.feed.appointments.length + 1, +// // __typename: prev.feed.__typename +// // } +// // }); +// // } +// // }); -export default AppointmentList; \ No newline at end of file +// return ( +// <> +// {loading &&

Loading...

} +// {error &&
{JSON.stringify(error, null, 2)}
} +// {data && ( +// <> +// {getAppointmentsToRender(isNewPage, data).map( +// (appointment, index) => ( +// +// ) +// )} +// {isNewPage && ( +//
+//
{ +// if (page > 1) { +// history.push(`/new/${page - 1}`); +// } +// }} +// > +// Previous +//
+//
{ +// if ( +// page <= +// data.feed.count / APPOINTMENTS_PER_PAGE +// ) { +// const nextPage = page + 1; +// history.push(`/new/${nextPage}`); +// } +// }} +// > +// Next +//
+//
+// )} +// +// )} +// +// ); +// }; + +// export default AppointmentList; \ No newline at end of file diff --git a/client/src/components/Header.js b/client/src/components/Header.js index ce7b572..3abecfd 100644 --- a/client/src/components/Header.js +++ b/client/src/components/Header.js @@ -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 (
-
Hacker News
- +
Store!
+ {/* new
|
@@ -17,7 +17,7 @@ const Header = () => { className="ml1 no-underline black" > submit - + */}
); diff --git a/client/src/components/ProductList.js b/client/src/components/ProductList.js index 44bfeee..972735f 100644 --- a/client/src/components/ProductList.js +++ b/client/src/components/ProductList.js @@ -15,15 +15,26 @@ const ProductList = () => { const { data } = useQuery(FEED_QUERY); - console.log("Fah!", data); + console.log("Data:", data); + + if (data !== undefined) { + return ( +
+ { + data.allProducts.map((product) => ( + + )) + } +
+ ); + } else { + return ( +
+ Rendering... +
+ ) + } - return ( -
- {data.allProducts.map((product) => ( - - ))} -
- ); }; export default ProductList; \ No newline at end of file diff --git a/client/src/index.js b/client/src/index.js index 4785511..da1ddc1 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -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( @@ -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( -// -// -// -// -// , -// 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 diff --git a/server/src/index.js b/server/src/index.js index 1bf2c68..dfa7666 100644 --- a/server/src/index.js +++ b/server/src/index.js @@ -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) { diff --git a/server/src/models/appointment.js b/server/src/models/appointment.js new file mode 100644 index 0000000..5a3a26a --- /dev/null +++ b/server/src/models/appointment.js @@ -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); \ No newline at end of file diff --git a/server/src/resolvers.js b/server/src/resolvers.js index 2d64476..a9c46f2 100644 --- a/server/src/resolvers.js +++ b/server/src/resolvers.js @@ -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: { diff --git a/server/src/schema.graphql b/server/src/schema.graphql index ef61707..ec3a95b 100644 --- a/server/src/schema.graphql +++ b/server/src/schema.graphql @@ -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! } diff --git a/server/src/schema.js b/server/src/schema.js index ff5def4..7cd7598 100644 --- a/server/src/schema.js +++ b/server/src/schema.js @@ -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; \ No newline at end of file + +export default schema;