Add semantic ui, refactoring
This commit is contained in:
parent
1604827f35
commit
02e657328f
|
@ -6,8 +6,10 @@ node_modules/
|
|||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
build
|
||||
# building
|
||||
.cache/
|
||||
dist/
|
||||
build/
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
|
|
13
api/.babelrc
13
api/.babelrc
|
@ -1 +1,12 @@
|
|||
{ "presets": ["env"] }
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"useBuiltIns": "usage",
|
||||
"corejs": 3
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": ["@babel/plugin-transform-spread"]
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 86 KiB |
|
@ -14,26 +14,38 @@
|
|||
"author": "William Lyon",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"apollo-boost": "^0.3.1",
|
||||
"@babel/plugin-transform-spread": "^7.2.2",
|
||||
"apollo-boost": "^0.4.3",
|
||||
"apollo-cache-inmemory": "^1.5.1",
|
||||
"apollo-client": "^2.5.1",
|
||||
"apollo-link-http": "^1.5.14",
|
||||
"apollo-server": "^2.6.2",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"dotenv": "^7.0.0",
|
||||
"core-js": "^3.1.4",
|
||||
"dotenv": "^8.0.0",
|
||||
"graphql-tag": "^2.10.1",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"neo4j-driver": "^1.7.3",
|
||||
"neo4j-graphql-js": "^2.6.3",
|
||||
"node-fetch": "^2.3.0",
|
||||
"regenerator-runtime": "^0.13.2",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"husky": "^1.3.1",
|
||||
"lint-staged": "^8.1.5",
|
||||
"nodemon": "^1.18.11"
|
||||
"@babel/cli": "^7.5.0",
|
||||
"@babel/core": "^7.5.0",
|
||||
"@babel/preset-env": "^7.5.0",
|
||||
"husky": "^3.0.0",
|
||||
"lint-staged": "^9.1.0",
|
||||
"nodemon": "^1.18.11",
|
||||
"prettier": "^1.18.2"
|
||||
},
|
||||
"prettier": {
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"semi": false,
|
||||
"singleQuote": true
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { neo4jgraphql } from "neo4j-graphql-js";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
|
|
115
api/src/index.js
115
api/src/index.js
|
@ -1,17 +1,15 @@
|
|||
import { typeDefs } from "./graphql-schema";
|
||||
import { ApolloServer } from "apollo-server-express";
|
||||
import express from "express";
|
||||
import bodyParser from "body-parser"
|
||||
import { v1 as neo4j } from "neo4j-driver";
|
||||
import { makeAugmentedSchema } from "neo4j-graphql-js";
|
||||
import dotenv from "dotenv";
|
||||
import jwt from 'jsonwebtoken'
|
||||
import uuid from 'uuid'
|
||||
import { typeDefs } from './graphql-schema'
|
||||
import { ApolloServer } from 'apollo-server-express'
|
||||
import express from 'express'
|
||||
import bodyParser from 'body-parser'
|
||||
import { v1 as neo4j } from 'neo4j-driver'
|
||||
import { makeAugmentedSchema } from 'neo4j-graphql-js'
|
||||
import dotenv from 'dotenv'
|
||||
|
||||
// set environment variables from ../.env
|
||||
dotenv.config();
|
||||
dotenv.config()
|
||||
|
||||
const app = express();
|
||||
const app = express()
|
||||
app.use(bodyParser.json())
|
||||
|
||||
/*
|
||||
|
@ -22,72 +20,23 @@ app.use(bodyParser.json())
|
|||
* https://grandstack.io/docs/neo4j-graphql-js-api.html#makeaugmentedschemaoptions-graphqlschema
|
||||
*/
|
||||
|
||||
import users from './resolvers/users'
|
||||
|
||||
const schema = makeAugmentedSchema({
|
||||
typeDefs,
|
||||
config: {
|
||||
auth: {
|
||||
isAuthenticated: true,
|
||||
hasRole: true
|
||||
hasRole: true,
|
||||
},
|
||||
mutation: false
|
||||
mutation: false,
|
||||
},
|
||||
resolvers: {
|
||||
Mutation: {
|
||||
async authorizeUser(root, args, ctx, info) {
|
||||
let {username, password} = args
|
||||
|
||||
let session = ctx.driver.session()
|
||||
|
||||
let result = await session.run("MATCH (usr:User {username: {username}, password: {password} }) RETURN usr.id", {username, password})
|
||||
|
||||
if (result.records.length == 0) {
|
||||
return {
|
||||
success: false,
|
||||
status: "Username or password was invalid",
|
||||
token: null
|
||||
}
|
||||
}
|
||||
|
||||
const record = result.records[0]
|
||||
|
||||
const userId = record.get('usr.id')
|
||||
|
||||
const token = jwt.sign({id: userId}, process.env.JWT_SECRET)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
status: "Authorized",
|
||||
token
|
||||
}
|
||||
...users.mutation,
|
||||
},
|
||||
async registerUser(root, args, ctx, info) {
|
||||
|
||||
let {username, password} = args
|
||||
|
||||
let session = ctx.driver.session()
|
||||
let result = await session.run("MATCH (usr:User {username: {username} }) RETURN usr", {username})
|
||||
|
||||
if (result.records.length > 0) {
|
||||
return {
|
||||
success: false,
|
||||
status: "Username is already taken",
|
||||
token: null
|
||||
}
|
||||
}
|
||||
|
||||
await session.run("CREATE (n:User { username: {username}, password: {password}, id: {id} }) return n", {username, password, id: uuid()})
|
||||
|
||||
session.close()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
status: "User created",
|
||||
token: "yay"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
})
|
||||
|
||||
/*
|
||||
* Create a Neo4j driver instance to connect to the database
|
||||
|
@ -95,12 +44,12 @@ const schema = makeAugmentedSchema({
|
|||
* with fallback to defaults
|
||||
*/
|
||||
const driver = neo4j.driver(
|
||||
process.env.NEO4J_URI || "bolt://localhost:7687",
|
||||
process.env.NEO4J_URI || 'bolt://localhost:7687',
|
||||
neo4j.auth.basic(
|
||||
process.env.NEO4J_USER || "neo4j",
|
||||
process.env.NEO4J_PASSWORD || "letmein"
|
||||
process.env.NEO4J_USER || 'neo4j',
|
||||
process.env.NEO4J_PASSWORD || 'letmein'
|
||||
)
|
||||
);
|
||||
)
|
||||
|
||||
/*
|
||||
* Create a new ApolloServer instance, serving the GraphQL schema
|
||||
|
@ -109,22 +58,22 @@ const driver = neo4j.driver(
|
|||
* generated resolvers to connect to the database.
|
||||
*/
|
||||
const server = new ApolloServer({
|
||||
context: ({ req }) => Object.assign(req, {driver}),
|
||||
context: ({ req }) => Object.assign(req, { driver }),
|
||||
schema: schema,
|
||||
introspection: true,
|
||||
playground: true
|
||||
});
|
||||
playground: true,
|
||||
})
|
||||
|
||||
// Specify port and path for GraphQL endpoint
|
||||
const port = process.env.GRAPHQL_LISTEN_PORT || 4001;
|
||||
const path = "/graphql";
|
||||
const port = process.env.GRAPHQL_LISTEN_PORT || 4001
|
||||
const path = '/graphql'
|
||||
|
||||
/*
|
||||
* Optionally, apply Express middleware for authentication, etc
|
||||
* This also also allows us to specify a path for the GraphQL endpoint
|
||||
*/
|
||||
server.applyMiddleware({app, path});
|
||||
* Optionally, apply Express middleware for authentication, etc
|
||||
* This also also allows us to specify a path for the GraphQL endpoint
|
||||
*/
|
||||
server.applyMiddleware({ app, path })
|
||||
|
||||
app.listen({port, path}, () => {
|
||||
console.log(`GraphQL server ready at http://localhost:${port}${path}`);
|
||||
});
|
||||
app.listen({ port, path }, () => {
|
||||
console.log(`GraphQL server ready at http://localhost:${port}${path}`)
|
||||
})
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
import jwt from 'jsonwebtoken'
|
||||
import uuid from 'uuid'
|
||||
|
||||
const mutation = {
|
||||
async authorizeUser(root, args, ctx, info) {
|
||||
let { username, password } = args
|
||||
|
||||
let session = ctx.driver.session()
|
||||
|
||||
let result = await session.run(
|
||||
'MATCH (usr:User {username: {username}, password: {password} }) RETURN usr.id',
|
||||
{ username, password }
|
||||
)
|
||||
|
||||
if (result.records.length == 0) {
|
||||
return {
|
||||
success: false,
|
||||
status: 'Username or password was invalid',
|
||||
token: null,
|
||||
}
|
||||
}
|
||||
|
||||
const record = result.records[0]
|
||||
|
||||
const userId = record.get('usr.id')
|
||||
|
||||
const token = jwt.sign({ id: userId }, process.env.JWT_SECRET)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
status: 'Authorized',
|
||||
token,
|
||||
}
|
||||
},
|
||||
async registerUser(root, args, ctx, info) {
|
||||
let { username, password } = args
|
||||
|
||||
let session = ctx.driver.session()
|
||||
let result = await session.run(
|
||||
'MATCH (usr:User {username: {username} }) RETURN usr',
|
||||
{ username }
|
||||
)
|
||||
|
||||
if (result.records.length > 0) {
|
||||
return {
|
||||
success: false,
|
||||
status: 'Username is already taken',
|
||||
token: null,
|
||||
}
|
||||
}
|
||||
|
||||
await session.run(
|
||||
'CREATE (n:User { username: {username}, password: {password}, id: {id} }) return n',
|
||||
{ username, password, id: uuid() }
|
||||
)
|
||||
|
||||
session.close()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
status: 'User created',
|
||||
token: 'yay',
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default {
|
||||
mutation,
|
||||
}
|
|
@ -7,6 +7,8 @@ type User @isAuthenticated {
|
|||
id: ID!
|
||||
username: String!
|
||||
albums: [Album] @relation(name: "OWNS", direction: "OUT")
|
||||
rootPath: String! @hasRole(roles: [Admin])
|
||||
admin: Boolean
|
||||
}
|
||||
|
||||
type Album @isAuthenticated {
|
||||
|
@ -23,6 +25,11 @@ type Photo @isAuthenticated {
|
|||
album: Album! @relation(name: "CONTAINS", direction: "IN")
|
||||
}
|
||||
|
||||
type SiteInfo {
|
||||
signupEnabled: Boolean!
|
||||
firstSignup: Boolean!
|
||||
}
|
||||
|
||||
type AuthorizeResult {
|
||||
success: Boolean!
|
||||
status: String
|
||||
|
@ -34,44 +41,9 @@ type Mutation {
|
|||
registerUser(username: String!, password: String!): AuthorizeResult!
|
||||
}
|
||||
|
||||
# type User {
|
||||
# id: ID!
|
||||
# name: String
|
||||
# friends: [User] @relation(name: "FRIENDS", direction: "BOTH")
|
||||
# reviews: [Review] @relation(name: "WROTE", direction: "OUT")
|
||||
# avgStars: Float
|
||||
# @cypher(
|
||||
# statement: "MATCH (this)-[:WROTE]->(r:Review) RETURN toFloat(avg(r.stars))"
|
||||
# )
|
||||
# numReviews: Int
|
||||
# @cypher(statement: "MATCH (this)-[:WROTE]->(r:Review) RETURN COUNT(r)")
|
||||
# recommendations(first: Int = 3): [Business] @cypher(statement: "MATCH (this)-[:WROTE]->(r:Review)-[:REVIEWS]->(:Business)<-[:REVIEWS]-(:Review)<-[:WROTE]-(:User)-[:WROTE]->(:Review)-[:REVIEWS]->(rec:Business) WHERE NOT EXISTS( (this)-[:WROTE]->(:Review)-[:REVIEWS]->(rec) )WITH rec, COUNT(*) AS num ORDER BY num DESC LIMIT $first RETURN rec")
|
||||
# }
|
||||
|
||||
# type Business {
|
||||
# id: ID!
|
||||
# name: String
|
||||
# address: String
|
||||
# city: String
|
||||
# state: String
|
||||
# avgStars: Float @cypher(statement: "MATCH (this)<-[:REVIEWS]-(r:Review) RETURN coalesce(avg(r.stars),0.0)")
|
||||
# reviews: [Review] @relation(name: "REVIEWS", direction: "IN")
|
||||
# categories: [Category] @relation(name: "IN_CATEGORY", direction: "OUT")
|
||||
# }
|
||||
|
||||
# type Review {
|
||||
# id: ID!
|
||||
# stars: Int
|
||||
# text: String
|
||||
# date: Date
|
||||
# business: Business @relation(name: "REVIEWS", direction: "OUT")
|
||||
# user: User @relation(name: "WROTE", direction: "IN")
|
||||
# }
|
||||
|
||||
# type Category {
|
||||
# name: ID!
|
||||
# businesses: [Business] @relation(name: "IN_CATEGORY", direction: "IN")
|
||||
# }
|
||||
type Query {
|
||||
siteInfo: SiteInfo
|
||||
}
|
||||
|
||||
# type Query {
|
||||
# usersBySubstring(substring: String): [User]
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
import ApolloClient from "apollo-client";
|
||||
import gql from "graphql-tag";
|
||||
import dotenv from "dotenv";
|
||||
import seedmutations from "./seed-mutations";
|
||||
import fetch from "node-fetch";
|
||||
import { HttpLink } from "apollo-link-http";
|
||||
import { InMemoryCache } from "apollo-cache-inmemory";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const client = new ApolloClient({
|
||||
link: new HttpLink({ uri: process.env.GRAPHQL_URI, fetch }),
|
||||
cache: new InMemoryCache()
|
||||
});
|
||||
|
||||
client
|
||||
.mutate({
|
||||
mutation: gql(seedmutations)
|
||||
})
|
||||
.then(data => console.log(data))
|
||||
.catch(error => console.error(error));
|
|
@ -1,394 +0,0 @@
|
|||
export default /* GraphQL */ `
|
||||
mutation {
|
||||
u1: CreateUser(id: "u1", name: "Will") {
|
||||
id
|
||||
name
|
||||
}
|
||||
u2: CreateUser(id: "u2", name: "Bob") {
|
||||
id
|
||||
name
|
||||
}
|
||||
u3: CreateUser(id: "u3", name: "Jenny") {
|
||||
id
|
||||
name
|
||||
}
|
||||
u4: CreateUser(id: "u4", name: "Angie") {
|
||||
id
|
||||
name
|
||||
}
|
||||
b1: CreateBusiness(
|
||||
id: "b1"
|
||||
name: "KettleHouse Brewing Co."
|
||||
address: "313 N 1st St W"
|
||||
city: "Missoula"
|
||||
state: "MT"
|
||||
) {
|
||||
id
|
||||
name
|
||||
}
|
||||
b2: CreateBusiness(
|
||||
id: "b2"
|
||||
name: "Imagine Nation Brewing"
|
||||
address: "1151 W Broadway St"
|
||||
city: "Missoula"
|
||||
state: "MT"
|
||||
) {
|
||||
id
|
||||
name
|
||||
}
|
||||
b3: CreateBusiness(
|
||||
id: "b3"
|
||||
name: "Ninja Mike's"
|
||||
address: "Food Truck - Farmers Market"
|
||||
city: "Missoula"
|
||||
state: "MT"
|
||||
) {
|
||||
id
|
||||
name
|
||||
}
|
||||
b4: CreateBusiness(
|
||||
id: "b4"
|
||||
name: "Market on Front"
|
||||
address: "201 E Front St"
|
||||
city: "Missoula"
|
||||
state: "MT"
|
||||
) {
|
||||
id
|
||||
name
|
||||
}
|
||||
b5: CreateBusiness(
|
||||
id: "b5"
|
||||
name: "Missoula Public Library"
|
||||
address: "301 E Main St"
|
||||
city: "Missoula"
|
||||
state: "MT"
|
||||
) {
|
||||
id
|
||||
name
|
||||
}
|
||||
b6: CreateBusiness(
|
||||
id: "b6"
|
||||
name: "Zootown Brew"
|
||||
address: "121 W Broadway St"
|
||||
city: "Missoula"
|
||||
state: "MT"
|
||||
) {
|
||||
id
|
||||
name
|
||||
}
|
||||
b7: CreateBusiness(
|
||||
id: "b7"
|
||||
name: "Hanabi"
|
||||
address: "723 California Dr"
|
||||
city: "Burlingame"
|
||||
state: "CA"
|
||||
) {
|
||||
id
|
||||
name
|
||||
}
|
||||
b8: CreateBusiness(
|
||||
id: "b8"
|
||||
name: "Philz Coffee"
|
||||
address: "113 B St"
|
||||
city: "San Mateo"
|
||||
state: "CA"
|
||||
) {
|
||||
id
|
||||
name
|
||||
}
|
||||
b9: CreateBusiness(
|
||||
id: "b9"
|
||||
name: "Alpha Acid Brewing Company"
|
||||
address: "121 Industrial Rd #11"
|
||||
city: "Belmont"
|
||||
state: "CA"
|
||||
) {
|
||||
id
|
||||
name
|
||||
}
|
||||
b10: CreateBusiness(
|
||||
id: "b10"
|
||||
name: "San Mateo Public Library Central Library"
|
||||
address: "55 W 3rd Ave"
|
||||
city: "San Mateo"
|
||||
state: "CA"
|
||||
) {
|
||||
id
|
||||
name
|
||||
}
|
||||
|
||||
c1: CreateCategory(name: "Coffee") {
|
||||
name
|
||||
}
|
||||
c2: CreateCategory(name: "Library") {
|
||||
name
|
||||
}
|
||||
c3: CreateCategory(name: "Beer") {
|
||||
name
|
||||
}
|
||||
c4: CreateCategory(name: "Restaurant") {
|
||||
name
|
||||
}
|
||||
c5: CreateCategory(name: "Ramen") {
|
||||
name
|
||||
}
|
||||
c6: CreateCategory(name: "Cafe") {
|
||||
name
|
||||
}
|
||||
c7: CreateCategory(name: "Deli") {
|
||||
name
|
||||
}
|
||||
c8: CreateCategory(name: "Breakfast") {
|
||||
name
|
||||
}
|
||||
c9: CreateCategory(name: "Brewery") {
|
||||
name
|
||||
}
|
||||
|
||||
a1: AddBusinessCategories(from: { id: "b1" }, to: { name: "Beer" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a1a: AddBusinessCategories(from: { id: "b1" }, to: { name: "Brewery" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a2: AddBusinessCategories(from: { id: "b2" }, to: { name: "Beer" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a2a: AddBusinessCategories(from: { id: "b2" }, to: { name: "Brewery" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a3: AddBusinessCategories(from: { id: "b3" }, to: { name: "Restaurant" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a4: AddBusinessCategories(from: { id: "b3" }, to: { name: "Breakfast" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a5: AddBusinessCategories(from: { id: "b4" }, to: { name: "Coffee" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a5a: AddBusinessCategories(from: { id: "b4" }, to: { name: "Restaurant" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a5b: AddBusinessCategories(from: { id: "b4" }, to: { name: "Cafe" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a5c: AddBusinessCategories(from: { id: "b4" }, to: { name: "Deli" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a5d: AddBusinessCategories(from: { id: "b4" }, to: { name: "Breakfast" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a6: AddBusinessCategories(from: { id: "b5" }, to: { name: "Library" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a7: AddBusinessCategories(from: { id: "b6" }, to: { name: "Coffee" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a8: AddBusinessCategories(from: { id: "b7" }, to: { name: "Restaurant" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a8a: AddBusinessCategories(from: { id: "b7" }, to: { name: "Ramen" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a9: AddBusinessCategories(from: { id: "b8" }, to: { name: "Coffee" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a9a: AddBusinessCategories(from: { id: "b8" }, to: { name: "Breakfast" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a10: AddBusinessCategories(from: { id: "b9" }, to: { name: "Brewery" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
a11: AddBusinessCategories(from: { id: "b10" }, to: { name: "Library" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
r1: CreateReview(id: "r1", stars: 4, text: "Great IPA selection!", date: { formatted: "2016-01-03"}) {
|
||||
id
|
||||
}
|
||||
ar1: AddUserReviews(from: { id: "u1" }, to: { id: "r1" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
ab1: AddReviewBusiness(from: { id: "r1" }, to: { id: "b1" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
r2: CreateReview(id: "r2", stars: 5, text: "", date: { formatted: "2016-07-14"}) {
|
||||
id
|
||||
}
|
||||
ar2: AddUserReviews(from: { id: "u3" }, to: { id: "r2" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
ab2: AddReviewBusiness(from: { id: "r2" }, to: { id: "b1" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
r3: CreateReview(id: "r3", stars: 3, text: "", date: { formatted: "2018-09-10"}) {
|
||||
id
|
||||
}
|
||||
ar3: AddUserReviews(from: { id: "u4" }, to: { id: "r3" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
ab3: AddReviewBusiness(from: { id: "r3" }, to: { id: "b2" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
r4: CreateReview(id: "r4", stars: 5, text: "", date: { formatted: "2017-11-13"}) {
|
||||
id
|
||||
}
|
||||
ar4: AddUserReviews(from: { id: "u3" }, to: { id: "r4" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
ab4: AddReviewBusiness(from: { id: "r4" }, to: { id: "b3" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
r5: CreateReview(
|
||||
id: "r5"
|
||||
stars: 4
|
||||
text: "Best breakfast sandwich at the Farmer's Market. Always get the works."
|
||||
date: { formatted: "2018-01-03"}
|
||||
) {
|
||||
id
|
||||
}
|
||||
ar5: AddUserReviews(from: { id: "u1" }, to: { id: "r5" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
ab5: AddReviewBusiness(from: { id: "r5" }, to: { id: "b3" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
r6: CreateReview(id: "r6", stars: 4, text: "", date: { formatted: "2018-03-24"}) {
|
||||
id
|
||||
}
|
||||
ar6: AddUserReviews(from: { id: "u2" }, to: { id: "r6" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
ab6: AddReviewBusiness(from: { id: "r6" }, to: { id: "b4" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
r7: CreateReview(
|
||||
id: "r7"
|
||||
stars: 3
|
||||
text: "Not a great selection of books, but fortunately the inter-library loan system is good. Wifi is quite slow. Not many comfortable places to site and read. Looking forward to the new building across the street in 2020!"
|
||||
date: { formatted: "2015-08-29"}
|
||||
) {
|
||||
id
|
||||
}
|
||||
ar7: AddUserReviews(from: { id: "u1" }, to: { id: "r7" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
ab7: AddReviewBusiness(from: { id: "r7" }, to: { id: "b5" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
r8: CreateReview(id: "r8", stars: 5, text: "", date: { formatted: "2018-08-11"}) {
|
||||
id
|
||||
}
|
||||
ar8: AddUserReviews(from: { id: "u4" }, to: { id: "r8" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
ab8: AddReviewBusiness(from: { id: "r8" }, to: { id: "b6" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
r9: CreateReview(id: "r9", stars: 5, text: "", date: { formatted: "2016-11-21"}) {
|
||||
id
|
||||
}
|
||||
ar9: AddUserReviews(from: { id: "u3" }, to: { id: "r9" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
ab9: AddReviewBusiness(from: { id: "r9" }, to: { id: "b7" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
r10: CreateReview(id: "r10", stars: 4, text: "", date: { formatted: "2015-12-15"}) {
|
||||
id
|
||||
}
|
||||
ar10: AddUserReviews(from: { id: "u2" }, to: { id: "r10" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
ab10: AddReviewBusiness(from: { id: "r10" }, to: { id: "b2" }) {
|
||||
from {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
|
@ -0,0 +1 @@
|
|||
const neo4j = require('neo4j-graphql-js')
|
|
@ -3,33 +3,36 @@
|
|||
"version": "0.0.1",
|
||||
"description": "UI app for GRANDstack",
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^3.9.3",
|
||||
"@material-ui/icons": "^3.0.2",
|
||||
"@babel/preset-env": "^7.5.0",
|
||||
"apollo-cache-inmemory": "^1.6.2",
|
||||
"apollo-client": "^2.6.3",
|
||||
"apollo-link": "^1.2.12",
|
||||
"apollo-link-context": "^1.0.18",
|
||||
"apollo-link-error": "^1.1.11",
|
||||
"apollo-link-http": "^1.5.15",
|
||||
"babel-plugin-styled-components": "^1.10.6",
|
||||
"graphql": "^14.2.1",
|
||||
"graphql-tag": "^2.10.1",
|
||||
"parcel-bundler": "^1.12.3",
|
||||
"prettier": "^1.18.2",
|
||||
"react": "^16.8.6",
|
||||
"react-apollo": "^2.5.5",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-router-dom": "^5.0.1",
|
||||
"react-scripts": "^3.0.0"
|
||||
"semantic-ui-react": "^0.87.2",
|
||||
"styled-components": "^4.3.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"start": "parcel start src/index.html",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject",
|
||||
"now-build": "react-scripts build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"husky": "^2.0.0",
|
||||
"lint-staged": "^8.1.5"
|
||||
"@babel/core": "^7.5.0",
|
||||
"husky": "^3.0.0",
|
||||
"lint-staged": "^9.1.0"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
@ -42,6 +45,19 @@
|
|||
"semi": false,
|
||||
"singleQuote": true
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"useBuiltIns": "entry"
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": [
|
||||
"babel-plugin-styled-components"
|
||||
]
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,json,css,md,graphql}": [
|
||||
"prettier --write",
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, { Component } from 'react'
|
|||
import gql from 'graphql-tag'
|
||||
import { Mutation } from 'react-apollo'
|
||||
import { Redirect } from 'react-router-dom'
|
||||
import { Button, Form, Message, Container, Header } from 'semantic-ui-react'
|
||||
|
||||
const authorizeMutation = gql`
|
||||
mutation Authorize($username: String!, $password: String!) {
|
||||
|
@ -45,7 +46,10 @@ class LoginPage extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<h1>Welcome</h1>
|
||||
<Container>
|
||||
<Header as="h1" textAlign="center">
|
||||
Welcome
|
||||
</Header>
|
||||
<Mutation
|
||||
mutation={authorizeMutation}
|
||||
onCompleted={data => {
|
||||
|
@ -58,38 +62,37 @@ class LoginPage extends Component {
|
|||
}}
|
||||
>
|
||||
{(authorize, { loading, error, data }) => {
|
||||
let signInBtn = <input type="submit" value="Sign in" />
|
||||
|
||||
if (loading) signInBtn = <span>Signing in...</span>
|
||||
|
||||
let status = ''
|
||||
let errorMessage = null
|
||||
if (data) {
|
||||
if (!data.authorizeUser.success)
|
||||
status = data.authorizeUser.status
|
||||
errorMessage = data.authorizeUser.status
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={e => this.signIn(e, authorize)}>
|
||||
<label htmlFor="username-field">Username:</label>
|
||||
<Form
|
||||
style={{ width: 500, margin: 'auto' }}
|
||||
error={!!errorMessage}
|
||||
onSubmit={e => this.signIn(e, authorize)}
|
||||
loading={loading || (data && data.authorizeUser.success)}
|
||||
>
|
||||
<Form.Field>
|
||||
<label>Username</label>
|
||||
<input onChange={e => this.handleChange(e, 'username')} />
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<label>Password</label>
|
||||
<input
|
||||
id="username-field"
|
||||
onChange={e => this.handleChange(e, 'username')}
|
||||
/>
|
||||
<br />
|
||||
<label htmlFor="password-field">Password:</label>
|
||||
<input
|
||||
id="password-field"
|
||||
type="password"
|
||||
onChange={e => this.handleChange(e, 'password')}
|
||||
/>
|
||||
<br />
|
||||
{signInBtn}
|
||||
<br />
|
||||
<span>{status}</span>
|
||||
</form>
|
||||
</Form.Field>
|
||||
<Message error content={errorMessage} />
|
||||
<Button type="submit">Sign in</Button>
|
||||
</Form>
|
||||
)
|
||||
}}
|
||||
</Mutation>
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -6,6 +6,8 @@ import client from './apolloClient'
|
|||
import { ApolloProvider } from 'react-apollo'
|
||||
import { BrowserRouter as Router } from 'react-router-dom'
|
||||
|
||||
import 'semantic-ui/dist/semantic.min.css'
|
||||
|
||||
const Main = () => (
|
||||
<ApolloProvider client={client}>
|
||||
<Router>
|
||||
|
|
7707
ui/yarn.lock
7707
ui/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue