This commit is contained in:
Riccardo
2021-01-03 20:53:38 +01:00
parent e72890fe28
commit 61acbf02d8
12 changed files with 282 additions and 241 deletions

View File

@@ -1,13 +1,9 @@
// import logo from './../logo.svg';
// import './../styles/App.css';
import React, { Component } from 'react';
import AppointmentList from './AppointmentList';
import CreateAppointment from './CreateAppointment'
import React from 'react';
// import CreateAppointment from './CreateAppointment';
import Header from './Header';
import Login from './Login'
import Search from './Search';
import { Redirect, Route, Switch } from 'react-router-dom';
// import AppointmentList from './AppointmentList';
import ProductList from './ProductList';
import { Switch, Route } from 'react-router-dom';
const App = () => {
return (
@@ -15,19 +11,9 @@ const App = () => {
<Header />
<div className="ph3 pv1 background-gray">
<Switch>
<Route exact path="/" component={AppointmentList} />
<Route
exact
path="/create"
component={CreateAppointment}
/>
<Route exact path="/login" component={Login} />
<Route exact path="/search" component={Search} />
<Route
exact
path="/new/:page"
component={AppointmentList}
/>
<Route exact path="/" component={ProductList} />
{/* <Route exact path="/" component={AppointmentList} /> */}
{/* <Route exact path="/create" component={CreateAppointment} /> */}
</Switch>
</div>
</div>
@@ -35,3 +21,42 @@ const App = () => {
};
export default App;
// // import logo from './../logo.svg';
// // import './../styles/App.css';
// import React, { Component } from 'react';
// import AppointmentList from './AppointmentList';
// import CreateAppointment from './CreateAppointment'
// // import Header from './Header';
// import Login from './Login'
// import Search from './Search';
// import { Redirect, Route, Switch } from 'react-router-dom';
// const App = () => {
// return (
// <div className="center w85">
// <Header />
// <div className="ph3 pv1 background-gray">
// <Switch>
// <Route exact path="/" component={AppointmentList} />
// <Route
// exact
// path="/create"
// component={CreateAppointment}
// />
// <Route exact path="/login" component={Login} />
// <Route exact path="/search" component={Search} />
// <Route
// exact
// path="/new/:page"
// component={AppointmentList}
// />
// </Switch>
// </div>
// </div>
// );
// };
// export default App;

View File

@@ -6,56 +6,56 @@ import { useQuery, gql } from '@apollo/client';
import { Link } from 'react-router-dom';
export const FEED_QUERY = gql`
query FeedQuery(
query AppointmentManyQuery(
$take: Int
$skip: Int
$orderBy: AppointmentOrderByInput
) {
feed(take: $take, skip: $skip, orderBy: $orderBy) {
appointmentMany(take: $take, skip: $skip, orderBy: $orderBy) {
id
appointments {
id
createdAt
title
start
end
# start
# end
description
createdBy {
id
name
}
follows {
id
user {
id
}
}
# createdBy {
# id
# name
# }
# follows {
# id
# user {
# id
# }
# }
}
count
}
}
`;
const NEW_APPOINTMENTS_SUBSCRIPTION = gql`
subscription {
newAppointment {
id
url
description
createdAt
createdBy {
id
name
}
follows {
id
user {
id
}
}
}
}
`;
// const NEW_APPOINTMENTS_SUBSCRIPTION = gql`
// subscription {
// newAppointment {
// id
// url
// description
// createdAt
// createdBy {
// id
// name
// }
// follows {
// id
// user {
// id
// }
// }
// }
// }
// `;
const getQueryVariables = (isNewPage, page) => {
const skip = isNewPage ? (page - 1) * APPOINTMENTS_PER_PAGE : 0;
@@ -102,25 +102,25 @@ const AppointmentList = () => {
return rankedAppointments;
};
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;
// 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 Object.assign({}, prev, {
feed: {
appointments: [newAppointment, ...prev.feed.appointments],
count: prev.feed.appointments.length + 1,
__typename: prev.feed.__typename
}
});
}
});
// return Object.assign({}, prev, {
// feed: {
// appointments: [newAppointment, ...prev.feed.appointments],
// count: prev.feed.appointments.length + 1,
// __typename: prev.feed.__typename
// }
// });
// }
// });
return (
<>

View File

@@ -1,11 +1,9 @@
import React from 'react';
import { useHistory } from 'react-router';
import { Link } from 'react-router-dom';
import { AUTH_TOKEN } from '../constants';
import { Link, withRouter } from 'react-router-dom';
const Header = () => {
const history = useHistory();
const authToken = localStorage.getItem(AUTH_TOKEN);
return (
<div className="flex pa1 justify-between nowrap orange">
<div className="flex flex-fixed black">
@@ -14,44 +12,12 @@ const Header = () => {
new
</Link>
<div className="ml1">|</div>
<Link to="/top" className="ml1 no-underline black">
top
</Link>
<div className="ml1">|</div>
<Link to="/search" className="ml1 no-underline black">
search
</Link>
{authToken && (
<div className="flex">
<div className="ml1">|</div>
<Link
to="/create"
className="ml1 no-underline black"
>
submit
</Link>
</div>
)}
</div>
<div className="flex flex-fixed">
{authToken ? (
<div
className="ml1 pointer black"
onClick={() => {
localStorage.removeItem(AUTH_TOKEN);
history.push(`/`);
}}
>
logout
</div>
) : (
<Link
to="/login"
className="ml1 no-underline black"
>
login
</Link>
)}
<Link
to="/create"
className="ml1 no-underline black"
>
submit
</Link>
</div>
</div>
);

View File

@@ -0,0 +1,14 @@
import React from 'react';
const Product = (props) => {
const { product } = props;
return (
<div>
<div>
<b>{product.title}</b>: only {product.qty}!
</div>
</div>
);
};
export default Product;

View File

@@ -0,0 +1,29 @@
import React from 'react';
import Product from './Product';
import { useQuery, gql } from '@apollo/client';
const FEED_QUERY = gql`
{
allProducts{
title
qty
}
}
`;
const ProductList = () => {
const { data } = useQuery(FEED_QUERY);
console.log("Fah!", data);
return (
<div>
{data.allProducts.map((product) => (
<Product key={product.id} product={product} />
))}
</div>
);
};
export default ProductList;

View File

@@ -52,10 +52,10 @@ const Search = () => {
OK
</button>
</div>
{data &&
{/* {data &&
data.feed.appointments.map((appointment, index) => (
<Link key={appointment.id} link={appointment} index={index} />
))}
))} */}
</>
);
};

View File

@@ -2,6 +2,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import './styles/index.css';
import App from './components/App';
import { BrowserRouter } from 'react-router-dom';
// import * as serviceWorker from './serviceWorker';
// 1
@@ -14,7 +15,7 @@ import {
// 2
const httpLink = createHttpLink({
uri: 'http://localhost:4000'
uri: 'http://localhost:5000/graphql'
});
// 3
@@ -25,9 +26,11 @@ const client = new ApolloClient({
// 4
ReactDOM.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
<BrowserRouter>
<ApolloProvider client={client}>
<App />
</ApolloProvider>
</BrowserRouter>,
document.getElementById('root')
);
// serviceWorker.unregister();

View File

@@ -7,18 +7,20 @@ import schema from './schema.js';
import './utils/db.js';
import fs from 'fs';
import path from 'path';
import cors from 'cors';
const moduleURL = new URL(import.meta.url);
const __dirname = path.dirname(moduleURL.pathname);
const app = express();
const pubsub = new PubSub();
const PORT = 4000;
dotenv.config();
app.use(cors());
app.get('/', (req, res) => {
res.json({
msg: 'Welcome to GraphQL'
msg: 'GraphQL home!'
})
});
@@ -28,32 +30,33 @@ app.use('/graphql', graphqlHTTP({
}));
const server = new ApolloServer({
typeDefs: fs.readFileSync(
path.join(__dirname, 'schema.graphql'),
'utf8'
),
// 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

@@ -1,41 +1,38 @@
import Product from './models/product.js';
// import User from './resolvers/User.js';
// import Appointment from './resolvers/Appointment.js';
// import Follow from './resolvers/Follow.js';
// import Query from './resolvers/Query.js';
// import Mutation from './resolvers/Mutation.js';
// import Subscription from './resolvers/Subscription.js';
export const resolvers = {
Query: {
async allProducts() {
return await Product.find();
const products = await Product.find();
console.log("Tah!", products);
return products;
// return {
// products
// };
},
},
Mutation: {
async createProduct(root, {
input
}) {
return await Product.create(input);
},
async updateProduct(root, {
_id,
input
}) {
return await Product.findOneAndUpdate({
_id
}, input, {
new: true
})
},
async deleteProduct(root, {
_id
}) {
return await Product.findOneAndRemove({
_id
});
},
// async feed(parent, args, context, info) {
// const where = args.filter
// ? {
// OR: [
// { title: { contains: args.filter } },
// { description: { contains: args.filter } }
// ]
// }
// : {};
// console.log(context.mongo);
// const appointments = await context.mongo.appointment.findMany({
// where,
// skip: args.skip,
// take: args.take,
// orderBy: args.orderBy
// });
// const count = await context.mongo.appointment.count({ where });
// return {
// id: 'main-feed',
// appointments,
// count
// };
// }
}
};

View File

@@ -7,7 +7,7 @@ type Query {
orderBy: AppointmentOrderByInput
): Feed!
allProducts: [Product]
# users: [User!]!
users: [User!]!
}
type Feed {
@@ -22,7 +22,17 @@ type Mutation {
description: String!,
start: DateTime!,
end: DateTime!,
): Appointment!
): Appointment!
createProduct(
input: ProductInput
) : Product
updateProduct(
_id: ID!,
input: ProductInput
): Product
deleteProduct(
_id: ID!
) : Product
signup(
email: String!
password: String!
@@ -68,7 +78,7 @@ type Appointment {
type Product {
id: ID!
title: String!
qty: Integer
qty: Int
}
type Follow {
@@ -77,6 +87,12 @@ type Follow {
user: User!
}
input ProductInput {
title: String!
qty: Int
}
input AppointmentOrderByInput {
description: Sort
url: Sort
@@ -88,5 +104,4 @@ enum Sort {
desc
}
scalar Integer
scalar DateTime

View File

@@ -1,45 +1,54 @@
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 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]
// }
// `;
// import fs from 'fs';
// import path from 'path';
// const moduleURL = new URL(import.meta.url);
// const __dirname = path.dirname(moduleURL.pathname);
// const typeDefs = fs.readFileSync(
// path.join(__dirname, 'schema.graphql'),
// 'utf8'
// );
// const schema = makeExecutableSchema({
// typeDefs,
// resolvers
// // 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;

View File

@@ -1,20 +0,0 @@
import { SchemaComposer } from 'graphql-compose';
import db from '../utils/db.js';
const schemaComposer = new SchemaComposer();
import { UserQuery, UserMutation } from './user.js';
import { AppointmentQuery, AppointmentMutation } from './appointment.js';
schemaComposer.Query.addFields({
...UserQuery,
...AppointmentQuery,
});
schemaComposer.Mutation.addFields({
...UserMutation,
...AppointmentMutation,
});
export default schemaComposer.buildSchema();