From 5806538de1b86a8618a75a175338e399c601d51c Mon Sep 17 00:00:00 2001 From: Barry Low Date: Wed, 12 Sep 2018 21:41:38 -0700 Subject: [PATCH 01/19] Server: Update resolver to use auth context --- api/.graphqlconfig.yml | 2 +- api/Dockerfile | 2 +- api/database/datamodel.graphql | 3 +- api/docker-compose.api.yml | 19 + api/docker-compose.yml | 19 - api/package-lock.json | 120 +- api/package.json | 2 +- api/src/auth/authDirectives.js | 44 +- api/src/auth/validateIdToken.js | 4 +- api/src/generated/prisma.graphql | 2327 +++++++++++++++++++ api/src/index.js | 84 +- api/src/{schema.graphqls => schema.graphql} | 35 +- client/src/views/index.js | 3 +- client/src/views/teams/index.js | 53 + docs/CodeStyle.md | 5 + 15 files changed, 2577 insertions(+), 145 deletions(-) create mode 100644 api/docker-compose.api.yml create mode 100644 api/src/generated/prisma.graphql rename api/src/{schema.graphqls => schema.graphql} (69%) create mode 100644 client/src/views/teams/index.js create mode 100644 docs/CodeStyle.md diff --git a/api/.graphqlconfig.yml b/api/.graphqlconfig.yml index a35fd2e44..d65be026a 100644 --- a/api/.graphqlconfig.yml +++ b/api/.graphqlconfig.yml @@ -4,7 +4,7 @@ projects: extensions: endpoints: dev1: - url: http://0.0.0.0:4000/graphql + url: http://localhost:4001/graphql database: schemaPath: src/generated/prisma.graphql diff --git a/api/Dockerfile b/api/Dockerfile index 0506ccdef..32704198c 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -1,6 +1,6 @@ FROM mhart/alpine-node:8 -ENV PORT=4000 +ENV PORT=4001 RUN mkdir -p /var/www/app && \ mkdir -p /var/www/app/node_modules diff --git a/api/database/datamodel.graphql b/api/database/datamodel.graphql index 0ba5945e1..7a55f466d 100644 --- a/api/database/datamodel.graphql +++ b/api/database/datamodel.graphql @@ -30,6 +30,7 @@ type Team { slug: String! @unique profile: TeamProfile members: [TeamMembers!]! @relation (name: "TeamMembers", onDelete: SET_NULL) + owner: String! wallet: Wallet fb: [FinancialBeings!]! @relation (name: "TeamFinancialBeing", onDelete: SET_NULL) status: [TeamStatus!]! @@ -59,7 +60,7 @@ type TeamMembers { type Member { id: ID! @unique - nickname: String + alias: String team: TeamMembers @relation (name: "MemberOnTeam", onDelete: SET_NULL) authId: String! @unique visible: Boolean! @default(value: true) diff --git a/api/docker-compose.api.yml b/api/docker-compose.api.yml new file mode 100644 index 000000000..689c37fa6 --- /dev/null +++ b/api/docker-compose.api.yml @@ -0,0 +1,19 @@ +version: '3' +services: + api: + image: aateamapi-dev:v1 + build: + context: . + dockerfile: ./Dockerfile + env_file: ./.env + container_name: aateamapi + tty: true + stdin_open: true + volumes: + - ./:/var/www/app + - /var/www/app/node_modules + working_dir: /var/www/app + restart: always + command: node -r dotenv/config src/index.js + ports: + - "4001:4001" diff --git a/api/docker-compose.yml b/api/docker-compose.yml index 37a6ee436..57dc62ef6 100644 --- a/api/docker-compose.yml +++ b/api/docker-compose.yml @@ -27,24 +27,5 @@ services: POSTGRES_PASSWORD: prisma volumes: - postgres:/var/lib/postgresql/data - node: - image: aateamapi-dev:v1 - build: - context: . - dockerfile: ./Dockerfile - depends_on: - - prisma - env_file: ./.env - container_name: aateamapi - tty: true - stdin_open: true - volumes: - - ./:/var/www/app - - /var/www/app/node_modules - working_dir: /var/www/app - restart: always - command: node -r dotenv/config src/index.js - ports: - - "4000:4000" volumes: postgres: diff --git a/api/package-lock.json b/api/package-lock.json index f49d52a1e..d43af47d4 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -568,7 +568,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -614,7 +614,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -923,7 +923,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -1462,7 +1462,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -1492,9 +1492,9 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "config-chain": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", - "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", "dev": true, "requires": { "ini": "^1.3.4", @@ -1640,7 +1640,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -4997,7 +4997,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -5366,7 +5366,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -6371,14 +6371,14 @@ "dev": true }, "prisma": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-1.15.3.tgz", - "integrity": "sha512-95s0Kk8PtptrVhp4ajXPd7A7QrbWdCEyZ/nnvcz0Sz9nzufYYZfBjxgibUyoaNs/XL0KXtiibQIdZhpWIJgOhw==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-1.16.0.tgz", + "integrity": "sha512-8jZYCrkd1xjy+JJbQi81f8PBOLe8LLWwSu0fK0cqekm3FeafBd8xk5b0RWcIsHyVd6ypKCQt3tnZEMVzmbKrdQ==", "dev": true, "requires": { "fs-extra": "^5.0.0", - "prisma-cli-core": "1.0.75", - "prisma-cli-engine": "1.0.78", + "prisma-cli-core": "1.0.76", + "prisma-cli-engine": "1.0.79", "semver": "^5.4.1", "source-map-support": "^0.4.18" }, @@ -6497,9 +6497,9 @@ } }, "prisma-cli-core": { - "version": "1.0.75", - "resolved": "https://registry.npmjs.org/prisma-cli-core/-/prisma-cli-core-1.0.75.tgz", - "integrity": "sha512-DiH686w2u9aiz4RoNX3T0XgGzeai8IrXX/Qsocam+lKtBB63aupqCxbj6kp16sNoiXhDPzI2Zx/Hwm0GG9sUhw==", + "version": "1.0.76", + "resolved": "https://registry.npmjs.org/prisma-cli-core/-/prisma-cli-core-1.0.76.tgz", + "integrity": "sha512-HtHn/RM2GlJi23KoIXHoboP97aC54SYDqr7B4uT/80JP6A6nQp5HLt4sJgNfKapaHFZVzXYM7M3LEfGq3tgQbw==", "dev": true, "requires": { "adm-zip": "^0.4.7", @@ -6533,9 +6533,9 @@ "opn": "^5.1.0", "pause": "^0.1.0", "portfinder": "^1.0.13", - "prisma-db-introspection": "0.0.45", + "prisma-db-introspection": "0.0.46", "prisma-json-schema": "0.0.4", - "prisma-yml": "1.0.90", + "prisma-yml": "1.0.96", "scuid": "^1.0.2", "semver": "^5.4.1", "sillyname": "^0.1.0", @@ -6599,12 +6599,12 @@ } }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "dotenv": { @@ -6693,7 +6693,7 @@ }, "graphql-import": { "version": "0.4.5", - "resolved": "https://registry.npmjs.org/graphql-import/-/graphql-import-0.4.5.tgz", + "resolved": "http://registry.npmjs.org/graphql-import/-/graphql-import-0.4.5.tgz", "integrity": "sha512-G/+I08Qp6/QGTb9qapknCm3yPHV0ZL7wbaalWFpxsfR8ZhZoTBe//LsbsCKlbALQpcMegchpJhpTSKiJjhaVqQ==", "dev": true, "requires": { @@ -6766,12 +6766,6 @@ "regex-cache": "^0.4.2" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, "prisma-json-schema": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/prisma-json-schema/-/prisma-json-schema-0.0.4.tgz", @@ -6779,9 +6773,9 @@ "dev": true }, "prisma-yml": { - "version": "1.0.90", - "resolved": "https://registry.npmjs.org/prisma-yml/-/prisma-yml-1.0.90.tgz", - "integrity": "sha512-i5qMN/p1YvLV931YgfJtUAaHO7nOL07oW/EqQ1AixBGRi9nB21TpZGy9b50TwunaMt8LfVYB5ER82338qrJA5g==", + "version": "1.0.96", + "resolved": "https://registry.npmjs.org/prisma-yml/-/prisma-yml-1.0.96.tgz", + "integrity": "sha512-w3XGzJHUq5pwBoFy/amkGOcTDj4XoHh8UFUUUZcHo5fSyoF8AWeRTu1yWINaPVGxbcmpwKNetntAW4ijiq7M5g==", "dev": true, "requires": { "ajv": "5", @@ -6828,9 +6822,9 @@ } }, "prisma-cli-engine": { - "version": "1.0.78", - "resolved": "https://registry.npmjs.org/prisma-cli-engine/-/prisma-cli-engine-1.0.78.tgz", - "integrity": "sha512-chtmecxBgXPQUzvDS0U/R+pHZ/nzV1ksO+OiKr98kT7dBR9QJQbRG0v/j+zoIW4vdR9eyIaXy5i+dW8HU8XnDg==", + "version": "1.0.79", + "resolved": "https://registry.npmjs.org/prisma-cli-engine/-/prisma-cli-engine-1.0.79.tgz", + "integrity": "sha512-CdEIJs4ld1IiQQt2CFFPmeDypN4Ct4sTgmFODVjJix790mpEtxMagzCcA+mhfnRL65P6xiHn76Gdxbz60GyYBA==", "dev": true, "requires": { "@heroku/linewrap": "^1.0.0", @@ -6873,7 +6867,7 @@ "memfs": "^2.5.3", "opn": "^5.1.0", "prisma-json-schema": "0.0.4", - "prisma-yml": "1.0.90", + "prisma-yml": "1.0.96", "raven": "2.3.0", "replaceall": "^0.1.6", "rwlockfile": "^1.4.8", @@ -6890,12 +6884,12 @@ }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "dotenv": { @@ -6931,12 +6925,6 @@ "through": "^2.3.6" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, "prisma-json-schema": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/prisma-json-schema/-/prisma-json-schema-0.0.4.tgz", @@ -6944,9 +6932,9 @@ "dev": true }, "prisma-yml": { - "version": "1.0.90", - "resolved": "https://registry.npmjs.org/prisma-yml/-/prisma-yml-1.0.90.tgz", - "integrity": "sha512-i5qMN/p1YvLV931YgfJtUAaHO7nOL07oW/EqQ1AixBGRi9nB21TpZGy9b50TwunaMt8LfVYB5ER82338qrJA5g==", + "version": "1.0.96", + "resolved": "https://registry.npmjs.org/prisma-yml/-/prisma-yml-1.0.96.tgz", + "integrity": "sha512-w3XGzJHUq5pwBoFy/amkGOcTDj4XoHh8UFUUUZcHo5fSyoF8AWeRTu1yWINaPVGxbcmpwKNetntAW4ijiq7M5g==", "dev": true, "requires": { "ajv": "5", @@ -7002,9 +6990,9 @@ } }, "prisma-db-introspection": { - "version": "0.0.45", - "resolved": "https://registry.npmjs.org/prisma-db-introspection/-/prisma-db-introspection-0.0.45.tgz", - "integrity": "sha512-tOdv4mBFZLVds1Wst92l2iarmzlxwFo/EFHs4kW1P0rR2My7BoxRgV0HSZy9xvo9gbU3P8e5JEZofMNrS+5v+g==", + "version": "0.0.46", + "resolved": "https://registry.npmjs.org/prisma-db-introspection/-/prisma-db-introspection-0.0.46.tgz", + "integrity": "sha512-/b7evS9b5xKS7UrcOERkCmV+IWC6OAgFtInFsvdwn4MeLEaVbkOfzRakdOo+t2gb+N7Yy8Eey9eKYgB5jiJAbA==", "dev": true, "requires": { "ajv": "5", @@ -7029,12 +7017,12 @@ }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "dotenv": { @@ -7043,12 +7031,6 @@ "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=", "dev": true }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, "prisma-json-schema": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/prisma-json-schema/-/prisma-json-schema-0.0.1.tgz", @@ -7608,7 +7590,7 @@ "dependencies": { "commander": { "version": "2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.8.1.tgz", "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", "dev": true, "requires": { @@ -8196,7 +8178,7 @@ }, "table": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", + "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz", "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", "dev": true, "requires": { @@ -8257,7 +8239,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -8522,7 +8504,7 @@ }, "buffer": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", "dev": true, "requires": { @@ -9105,7 +9087,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { diff --git a/api/package.json b/api/package.json index 9df8a2bf9..8bc857126 100644 --- a/api/package.json +++ b/api/package.json @@ -22,6 +22,6 @@ "devDependencies": { "graphql-cli": "^2.16.5", "npm-run-all": "4.1.3", - "prisma": "^1.14.0" + "prisma": "^1.16.0" } } diff --git a/api/src/auth/authDirectives.js b/api/src/auth/authDirectives.js index 56720ff10..f098fa4ec 100644 --- a/api/src/auth/authDirectives.js +++ b/api/src/auth/authDirectives.js @@ -1,6 +1,5 @@ const _get = require('lodash.get') -const validateAndParseIdToken = require('./helpers/validateAndParseIdToken') -const createMember = require('./index') +const { validateIdToken } = require('./validateIdToken') const memberLocationOnContext = 'request.member' const bearerAccessToken = 'request.headers.authorization' @@ -8,11 +7,29 @@ const bearerAccessToken = 'request.headers.authorization' const ctxMember = ctx => _get(ctx, memberLocationOnContext) const ctxToken = ctx => _get(ctx, bearerAccessToken) +const createMember = async (ctx, idToken, info) => { + console.log('createMember', idToken) + const member = await ctx.db.mutation.upsertMember({ + where: { + authId: idToken.sub, + }, + create: { + authId: idToken.sub, + alias: idToken.nickname + }, + update: { + authId: idToken.sub, + alias: idToken.nickname + } + }, info) + return member +} + const isLoggedIn = async ctx => { let member = ctxMember(ctx, memberLocationOnContext) let token = ctxToken(ctx, bearerAccessToken) let memberToken - + console.log('isLoggedIn: ', member, token) if (!member && token) { let scheme, credentials const tokenParts = token.split(' ') @@ -24,21 +41,28 @@ const isLoggedIn = async ctx => { if (/^Bearer$/i.test(scheme)) { token = credentials //verify token + console.log('isLoggedIn2 : ', token) try { - memberToken = await validateAndParseIdToken(token) - const auth0id = memberToken.sub + memberToken = await validateIdToken(token) + const authId = memberToken.sub + console.log('isLoggedIn3 : ', await authId, ctx.db.query.member) + exists = await ctx.db.query.member({ where: { authId: authId } }) + console.log('isLoggedIn4 : ', await exists, createMember ) + if (!member && exists === null) { + member = await createMember(ctx, memberToken).then(res => { + console.log('isLoggedIn5 : ', res) + return res + }) - member = await ctx.db.query.member({ where: { auth0id } }) - - if (!member) { - member = await createMember(ctx, memberToken) + return member } + return member } catch (err) { memberToken = false } } } - + console.log('isLoggedIn5 : ', await member) if (!member) { throw new Error(`Not logged in`) } diff --git a/api/src/auth/validateIdToken.js b/api/src/auth/validateIdToken.js index 25434c85f..dd0b794b3 100644 --- a/api/src/auth/validateIdToken.js +++ b/api/src/auth/validateIdToken.js @@ -7,7 +7,7 @@ const jwks = jwksClient({ jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json` }) -const validateParseIdToken = idToken => +const validateIdToken = idToken => new Promise((resolve, reject) => { const { header, payload } = jwt.decode(idToken, { complete: true }) if (!header || !header.kid || !payload) reject(new Error('Invalid Token')) @@ -25,4 +25,4 @@ const validateParseIdToken = idToken => }) }) -module.exports = validateParseIdToken +module.exports = { validateIdToken } diff --git a/api/src/generated/prisma.graphql b/api/src/generated/prisma.graphql new file mode 100644 index 000000000..6d118e29a --- /dev/null +++ b/api/src/generated/prisma.graphql @@ -0,0 +1,2327 @@ +# source: http://localhost:4466 +# timestamp: Wed Sep 12 2018 08:41:57 GMT-0700 (Pacific Daylight Time) + +type AggregateFBStatus { + count: Int! +} + +type AggregateFinancialBeings { + count: Int! +} + +type AggregateMember { + count: Int! +} + +type AggregateMemberStatus { + count: Int! +} + +type AggregateTeam { + count: Int! +} + +type AggregateTeamMembers { + count: Int! +} + +type AggregateTeamProfile { + count: Int! +} + +type AggregateTeamStatus { + count: Int! +} + +type AggregateWallet { + count: Int! +} + +type BatchPayload { + """The number of nodes that have been affected by the Batch operation.""" + count: Long! +} + +scalar DateTime + +enum FBKind { + TRADER + INDICATOR + EXTRACTOR + PLOTTER +} + +type FBStatus { + status: Status + reason: String + createdAt: DateTime! +} + +"""A connection to a list of items.""" +type FBStatusConnection { + """Information to aid in pagination.""" + pageInfo: PageInfo! + + """A list of edges.""" + edges: [FBStatusEdge]! + aggregate: AggregateFBStatus! +} + +input FBStatusCreateInput { + status: Status + reason: String +} + +input FBStatusCreateManyInput { + create: [FBStatusCreateInput!] +} + +"""An edge in a connection.""" +type FBStatusEdge { + """The item at the end of the edge.""" + node: FBStatus! + + """A cursor for use in pagination.""" + cursor: String! +} + +enum FBStatusOrderByInput { + status_ASC + status_DESC + reason_ASC + reason_DESC + createdAt_ASC + createdAt_DESC + id_ASC + id_DESC + updatedAt_ASC + updatedAt_DESC +} + +type FBStatusPreviousValues { + status: Status + reason: String + createdAt: DateTime! +} + +type FBStatusSubscriptionPayload { + mutation: MutationType! + node: FBStatus + updatedFields: [String!] + previousValues: FBStatusPreviousValues +} + +input FBStatusSubscriptionWhereInput { + """Logical AND on all given filters.""" + AND: [FBStatusSubscriptionWhereInput!] + + """Logical OR on all given filters.""" + OR: [FBStatusSubscriptionWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [FBStatusSubscriptionWhereInput!] + + """ + The subscription event gets dispatched when it's listed in mutation_in + """ + mutation_in: [MutationType!] + + """ + The subscription event gets only dispatched when one of the updated fields names is included in this list + """ + updatedFields_contains: String + + """ + The subscription event gets only dispatched when all of the field names included in this list have been updated + """ + updatedFields_contains_every: [String!] + + """ + The subscription event gets only dispatched when some of the field names included in this list have been updated + """ + updatedFields_contains_some: [String!] + node: FBStatusWhereInput +} + +input FBStatusUpdateInput { + status: Status + reason: String +} + +input FBStatusUpdateManyInput { + create: [FBStatusCreateInput!] +} + +input FBStatusWhereInput { + """Logical AND on all given filters.""" + AND: [FBStatusWhereInput!] + + """Logical OR on all given filters.""" + OR: [FBStatusWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [FBStatusWhereInput!] + status: Status + + """All values that are not equal to given value.""" + status_not: Status + + """All values that are contained in given list.""" + status_in: [Status!] + + """All values that are not contained in given list.""" + status_not_in: [Status!] + reason: String + + """All values that are not equal to given value.""" + reason_not: String + + """All values that are contained in given list.""" + reason_in: [String!] + + """All values that are not contained in given list.""" + reason_not_in: [String!] + + """All values less than the given value.""" + reason_lt: String + + """All values less than or equal the given value.""" + reason_lte: String + + """All values greater than the given value.""" + reason_gt: String + + """All values greater than or equal the given value.""" + reason_gte: String + + """All values containing the given string.""" + reason_contains: String + + """All values not containing the given string.""" + reason_not_contains: String + + """All values starting with the given string.""" + reason_starts_with: String + + """All values not starting with the given string.""" + reason_not_starts_with: String + + """All values ending with the given string.""" + reason_ends_with: String + + """All values not ending with the given string.""" + reason_not_ends_with: String + createdAt: DateTime + + """All values that are not equal to given value.""" + createdAt_not: DateTime + + """All values that are contained in given list.""" + createdAt_in: [DateTime!] + + """All values that are not contained in given list.""" + createdAt_not_in: [DateTime!] + + """All values less than the given value.""" + createdAt_lt: DateTime + + """All values less than or equal the given value.""" + createdAt_lte: DateTime + + """All values greater than the given value.""" + createdAt_gt: DateTime + + """All values greater than or equal the given value.""" + createdAt_gte: DateTime +} + +enum FBType { + BOT + NET + ADVANCED +} + +type FinancialBeings implements Node { + id: ID! + type: FBType + kind: FBKind + team(where: TeamWhereInput): Team + status(where: FBStatusWhereInput, orderBy: FBStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [FBStatus!] + updatedAt: DateTime! + createdAt: DateTime! +} + +"""A connection to a list of items.""" +type FinancialBeingsConnection { + """Information to aid in pagination.""" + pageInfo: PageInfo! + + """A list of edges.""" + edges: [FinancialBeingsEdge]! + aggregate: AggregateFinancialBeings! +} + +input FinancialBeingsCreateInput { + type: FBType + kind: FBKind + team: TeamCreateOneWithoutFbInput + status: FBStatusCreateManyInput +} + +input FinancialBeingsCreateManyWithoutTeamInput { + create: [FinancialBeingsCreateWithoutTeamInput!] + connect: [FinancialBeingsWhereUniqueInput!] +} + +input FinancialBeingsCreateWithoutTeamInput { + type: FBType + kind: FBKind + status: FBStatusCreateManyInput +} + +"""An edge in a connection.""" +type FinancialBeingsEdge { + """The item at the end of the edge.""" + node: FinancialBeings! + + """A cursor for use in pagination.""" + cursor: String! +} + +enum FinancialBeingsOrderByInput { + id_ASC + id_DESC + type_ASC + type_DESC + kind_ASC + kind_DESC + updatedAt_ASC + updatedAt_DESC + createdAt_ASC + createdAt_DESC +} + +type FinancialBeingsPreviousValues { + id: ID! + type: FBType + kind: FBKind + updatedAt: DateTime! + createdAt: DateTime! +} + +type FinancialBeingsSubscriptionPayload { + mutation: MutationType! + node: FinancialBeings + updatedFields: [String!] + previousValues: FinancialBeingsPreviousValues +} + +input FinancialBeingsSubscriptionWhereInput { + """Logical AND on all given filters.""" + AND: [FinancialBeingsSubscriptionWhereInput!] + + """Logical OR on all given filters.""" + OR: [FinancialBeingsSubscriptionWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [FinancialBeingsSubscriptionWhereInput!] + + """ + The subscription event gets dispatched when it's listed in mutation_in + """ + mutation_in: [MutationType!] + + """ + The subscription event gets only dispatched when one of the updated fields names is included in this list + """ + updatedFields_contains: String + + """ + The subscription event gets only dispatched when all of the field names included in this list have been updated + """ + updatedFields_contains_every: [String!] + + """ + The subscription event gets only dispatched when some of the field names included in this list have been updated + """ + updatedFields_contains_some: [String!] + node: FinancialBeingsWhereInput +} + +input FinancialBeingsUpdateInput { + type: FBType + kind: FBKind + team: TeamUpdateOneWithoutFbInput + status: FBStatusUpdateManyInput +} + +input FinancialBeingsUpdateManyWithoutTeamInput { + create: [FinancialBeingsCreateWithoutTeamInput!] + connect: [FinancialBeingsWhereUniqueInput!] + disconnect: [FinancialBeingsWhereUniqueInput!] + delete: [FinancialBeingsWhereUniqueInput!] + update: [FinancialBeingsUpdateWithWhereUniqueWithoutTeamInput!] + upsert: [FinancialBeingsUpsertWithWhereUniqueWithoutTeamInput!] +} + +input FinancialBeingsUpdateWithoutTeamDataInput { + type: FBType + kind: FBKind + status: FBStatusUpdateManyInput +} + +input FinancialBeingsUpdateWithWhereUniqueWithoutTeamInput { + where: FinancialBeingsWhereUniqueInput! + data: FinancialBeingsUpdateWithoutTeamDataInput! +} + +input FinancialBeingsUpsertWithWhereUniqueWithoutTeamInput { + where: FinancialBeingsWhereUniqueInput! + update: FinancialBeingsUpdateWithoutTeamDataInput! + create: FinancialBeingsCreateWithoutTeamInput! +} + +input FinancialBeingsWhereInput { + """Logical AND on all given filters.""" + AND: [FinancialBeingsWhereInput!] + + """Logical OR on all given filters.""" + OR: [FinancialBeingsWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [FinancialBeingsWhereInput!] + id: ID + + """All values that are not equal to given value.""" + id_not: ID + + """All values that are contained in given list.""" + id_in: [ID!] + + """All values that are not contained in given list.""" + id_not_in: [ID!] + + """All values less than the given value.""" + id_lt: ID + + """All values less than or equal the given value.""" + id_lte: ID + + """All values greater than the given value.""" + id_gt: ID + + """All values greater than or equal the given value.""" + id_gte: ID + + """All values containing the given string.""" + id_contains: ID + + """All values not containing the given string.""" + id_not_contains: ID + + """All values starting with the given string.""" + id_starts_with: ID + + """All values not starting with the given string.""" + id_not_starts_with: ID + + """All values ending with the given string.""" + id_ends_with: ID + + """All values not ending with the given string.""" + id_not_ends_with: ID + type: FBType + + """All values that are not equal to given value.""" + type_not: FBType + + """All values that are contained in given list.""" + type_in: [FBType!] + + """All values that are not contained in given list.""" + type_not_in: [FBType!] + kind: FBKind + + """All values that are not equal to given value.""" + kind_not: FBKind + + """All values that are contained in given list.""" + kind_in: [FBKind!] + + """All values that are not contained in given list.""" + kind_not_in: [FBKind!] + updatedAt: DateTime + + """All values that are not equal to given value.""" + updatedAt_not: DateTime + + """All values that are contained in given list.""" + updatedAt_in: [DateTime!] + + """All values that are not contained in given list.""" + updatedAt_not_in: [DateTime!] + + """All values less than the given value.""" + updatedAt_lt: DateTime + + """All values less than or equal the given value.""" + updatedAt_lte: DateTime + + """All values greater than the given value.""" + updatedAt_gt: DateTime + + """All values greater than or equal the given value.""" + updatedAt_gte: DateTime + createdAt: DateTime + + """All values that are not equal to given value.""" + createdAt_not: DateTime + + """All values that are contained in given list.""" + createdAt_in: [DateTime!] + + """All values that are not contained in given list.""" + createdAt_not_in: [DateTime!] + + """All values less than the given value.""" + createdAt_lt: DateTime + + """All values less than or equal the given value.""" + createdAt_lte: DateTime + + """All values greater than the given value.""" + createdAt_gt: DateTime + + """All values greater than or equal the given value.""" + createdAt_gte: DateTime + team: TeamWhereInput + status_every: FBStatusWhereInput + status_some: FBStatusWhereInput + status_none: FBStatusWhereInput +} + +input FinancialBeingsWhereUniqueInput { + id: ID +} + +""" +The `Long` scalar type represents non-fractional signed whole numeric values. +Long can represent values between -(2^63) and 2^63 - 1. +""" +scalar Long + +type Member implements Node { + id: ID! + alias: String + team(where: TeamMembersWhereInput): TeamMembers + authId: String! + visible: Boolean! + createdAt: DateTime! +} + +"""A connection to a list of items.""" +type MemberConnection { + """Information to aid in pagination.""" + pageInfo: PageInfo! + + """A list of edges.""" + edges: [MemberEdge]! + aggregate: AggregateMember! +} + +input MemberCreateInput { + alias: String + authId: String! + visible: Boolean + team: TeamMembersCreateOneWithoutMemberInput +} + +input MemberCreateOneWithoutTeamInput { + create: MemberCreateWithoutTeamInput + connect: MemberWhereUniqueInput +} + +input MemberCreateWithoutTeamInput { + alias: String + authId: String! + visible: Boolean +} + +"""An edge in a connection.""" +type MemberEdge { + """The item at the end of the edge.""" + node: Member! + + """A cursor for use in pagination.""" + cursor: String! +} + +enum MemberOrderByInput { + id_ASC + id_DESC + alias_ASC + alias_DESC + authId_ASC + authId_DESC + visible_ASC + visible_DESC + createdAt_ASC + createdAt_DESC + updatedAt_ASC + updatedAt_DESC +} + +type MemberPreviousValues { + id: ID! + alias: String + authId: String! + visible: Boolean! + createdAt: DateTime! +} + +type MemberStatus { + status: Status + reason: String + createdAt: DateTime! +} + +"""A connection to a list of items.""" +type MemberStatusConnection { + """Information to aid in pagination.""" + pageInfo: PageInfo! + + """A list of edges.""" + edges: [MemberStatusEdge]! + aggregate: AggregateMemberStatus! +} + +input MemberStatusCreateInput { + status: Status + reason: String +} + +input MemberStatusCreateManyInput { + create: [MemberStatusCreateInput!] +} + +"""An edge in a connection.""" +type MemberStatusEdge { + """The item at the end of the edge.""" + node: MemberStatus! + + """A cursor for use in pagination.""" + cursor: String! +} + +enum MemberStatusOrderByInput { + status_ASC + status_DESC + reason_ASC + reason_DESC + createdAt_ASC + createdAt_DESC + id_ASC + id_DESC + updatedAt_ASC + updatedAt_DESC +} + +type MemberStatusPreviousValues { + status: Status + reason: String + createdAt: DateTime! +} + +type MemberStatusSubscriptionPayload { + mutation: MutationType! + node: MemberStatus + updatedFields: [String!] + previousValues: MemberStatusPreviousValues +} + +input MemberStatusSubscriptionWhereInput { + """Logical AND on all given filters.""" + AND: [MemberStatusSubscriptionWhereInput!] + + """Logical OR on all given filters.""" + OR: [MemberStatusSubscriptionWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [MemberStatusSubscriptionWhereInput!] + + """ + The subscription event gets dispatched when it's listed in mutation_in + """ + mutation_in: [MutationType!] + + """ + The subscription event gets only dispatched when one of the updated fields names is included in this list + """ + updatedFields_contains: String + + """ + The subscription event gets only dispatched when all of the field names included in this list have been updated + """ + updatedFields_contains_every: [String!] + + """ + The subscription event gets only dispatched when some of the field names included in this list have been updated + """ + updatedFields_contains_some: [String!] + node: MemberStatusWhereInput +} + +input MemberStatusUpdateInput { + status: Status + reason: String +} + +input MemberStatusUpdateManyInput { + create: [MemberStatusCreateInput!] +} + +input MemberStatusWhereInput { + """Logical AND on all given filters.""" + AND: [MemberStatusWhereInput!] + + """Logical OR on all given filters.""" + OR: [MemberStatusWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [MemberStatusWhereInput!] + status: Status + + """All values that are not equal to given value.""" + status_not: Status + + """All values that are contained in given list.""" + status_in: [Status!] + + """All values that are not contained in given list.""" + status_not_in: [Status!] + reason: String + + """All values that are not equal to given value.""" + reason_not: String + + """All values that are contained in given list.""" + reason_in: [String!] + + """All values that are not contained in given list.""" + reason_not_in: [String!] + + """All values less than the given value.""" + reason_lt: String + + """All values less than or equal the given value.""" + reason_lte: String + + """All values greater than the given value.""" + reason_gt: String + + """All values greater than or equal the given value.""" + reason_gte: String + + """All values containing the given string.""" + reason_contains: String + + """All values not containing the given string.""" + reason_not_contains: String + + """All values starting with the given string.""" + reason_starts_with: String + + """All values not starting with the given string.""" + reason_not_starts_with: String + + """All values ending with the given string.""" + reason_ends_with: String + + """All values not ending with the given string.""" + reason_not_ends_with: String + createdAt: DateTime + + """All values that are not equal to given value.""" + createdAt_not: DateTime + + """All values that are contained in given list.""" + createdAt_in: [DateTime!] + + """All values that are not contained in given list.""" + createdAt_not_in: [DateTime!] + + """All values less than the given value.""" + createdAt_lt: DateTime + + """All values less than or equal the given value.""" + createdAt_lte: DateTime + + """All values greater than the given value.""" + createdAt_gt: DateTime + + """All values greater than or equal the given value.""" + createdAt_gte: DateTime +} + +type MemberSubscriptionPayload { + mutation: MutationType! + node: Member + updatedFields: [String!] + previousValues: MemberPreviousValues +} + +input MemberSubscriptionWhereInput { + """Logical AND on all given filters.""" + AND: [MemberSubscriptionWhereInput!] + + """Logical OR on all given filters.""" + OR: [MemberSubscriptionWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [MemberSubscriptionWhereInput!] + + """ + The subscription event gets dispatched when it's listed in mutation_in + """ + mutation_in: [MutationType!] + + """ + The subscription event gets only dispatched when one of the updated fields names is included in this list + """ + updatedFields_contains: String + + """ + The subscription event gets only dispatched when all of the field names included in this list have been updated + """ + updatedFields_contains_every: [String!] + + """ + The subscription event gets only dispatched when some of the field names included in this list have been updated + """ + updatedFields_contains_some: [String!] + node: MemberWhereInput +} + +input MemberUpdateInput { + alias: String + authId: String + visible: Boolean + team: TeamMembersUpdateOneWithoutMemberInput +} + +input MemberUpdateOneWithoutTeamInput { + create: MemberCreateWithoutTeamInput + connect: MemberWhereUniqueInput + disconnect: Boolean + delete: Boolean + update: MemberUpdateWithoutTeamDataInput + upsert: MemberUpsertWithoutTeamInput +} + +input MemberUpdateWithoutTeamDataInput { + alias: String + authId: String + visible: Boolean +} + +input MemberUpsertWithoutTeamInput { + update: MemberUpdateWithoutTeamDataInput! + create: MemberCreateWithoutTeamInput! +} + +input MemberWhereInput { + """Logical AND on all given filters.""" + AND: [MemberWhereInput!] + + """Logical OR on all given filters.""" + OR: [MemberWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [MemberWhereInput!] + id: ID + + """All values that are not equal to given value.""" + id_not: ID + + """All values that are contained in given list.""" + id_in: [ID!] + + """All values that are not contained in given list.""" + id_not_in: [ID!] + + """All values less than the given value.""" + id_lt: ID + + """All values less than or equal the given value.""" + id_lte: ID + + """All values greater than the given value.""" + id_gt: ID + + """All values greater than or equal the given value.""" + id_gte: ID + + """All values containing the given string.""" + id_contains: ID + + """All values not containing the given string.""" + id_not_contains: ID + + """All values starting with the given string.""" + id_starts_with: ID + + """All values not starting with the given string.""" + id_not_starts_with: ID + + """All values ending with the given string.""" + id_ends_with: ID + + """All values not ending with the given string.""" + id_not_ends_with: ID + alias: String + + """All values that are not equal to given value.""" + alias_not: String + + """All values that are contained in given list.""" + alias_in: [String!] + + """All values that are not contained in given list.""" + alias_not_in: [String!] + + """All values less than the given value.""" + alias_lt: String + + """All values less than or equal the given value.""" + alias_lte: String + + """All values greater than the given value.""" + alias_gt: String + + """All values greater than or equal the given value.""" + alias_gte: String + + """All values containing the given string.""" + alias_contains: String + + """All values not containing the given string.""" + alias_not_contains: String + + """All values starting with the given string.""" + alias_starts_with: String + + """All values not starting with the given string.""" + alias_not_starts_with: String + + """All values ending with the given string.""" + alias_ends_with: String + + """All values not ending with the given string.""" + alias_not_ends_with: String + authId: String + + """All values that are not equal to given value.""" + authId_not: String + + """All values that are contained in given list.""" + authId_in: [String!] + + """All values that are not contained in given list.""" + authId_not_in: [String!] + + """All values less than the given value.""" + authId_lt: String + + """All values less than or equal the given value.""" + authId_lte: String + + """All values greater than the given value.""" + authId_gt: String + + """All values greater than or equal the given value.""" + authId_gte: String + + """All values containing the given string.""" + authId_contains: String + + """All values not containing the given string.""" + authId_not_contains: String + + """All values starting with the given string.""" + authId_starts_with: String + + """All values not starting with the given string.""" + authId_not_starts_with: String + + """All values ending with the given string.""" + authId_ends_with: String + + """All values not ending with the given string.""" + authId_not_ends_with: String + visible: Boolean + + """All values that are not equal to given value.""" + visible_not: Boolean + createdAt: DateTime + + """All values that are not equal to given value.""" + createdAt_not: DateTime + + """All values that are contained in given list.""" + createdAt_in: [DateTime!] + + """All values that are not contained in given list.""" + createdAt_not_in: [DateTime!] + + """All values less than the given value.""" + createdAt_lt: DateTime + + """All values less than or equal the given value.""" + createdAt_lte: DateTime + + """All values greater than the given value.""" + createdAt_gt: DateTime + + """All values greater than or equal the given value.""" + createdAt_gte: DateTime + team: TeamMembersWhereInput +} + +input MemberWhereUniqueInput { + id: ID + authId: String +} + +type Mutation { + createTeam(data: TeamCreateInput!): Team! + createTeamMembers(data: TeamMembersCreateInput!): TeamMembers! + createMember(data: MemberCreateInput!): Member! + createFinancialBeings(data: FinancialBeingsCreateInput!): FinancialBeings! + createTeamProfile(data: TeamProfileCreateInput!): TeamProfile! + createWallet(data: WalletCreateInput!): Wallet! + createFBStatus(data: FBStatusCreateInput!): FBStatus! + createTeamStatus(data: TeamStatusCreateInput!): TeamStatus! + createMemberStatus(data: MemberStatusCreateInput!): MemberStatus! + updateTeam(data: TeamUpdateInput!, where: TeamWhereUniqueInput!): Team + updateMember(data: MemberUpdateInput!, where: MemberWhereUniqueInput!): Member + updateFinancialBeings(data: FinancialBeingsUpdateInput!, where: FinancialBeingsWhereUniqueInput!): FinancialBeings + deleteTeam(where: TeamWhereUniqueInput!): Team + deleteMember(where: MemberWhereUniqueInput!): Member + deleteFinancialBeings(where: FinancialBeingsWhereUniqueInput!): FinancialBeings + upsertTeam(where: TeamWhereUniqueInput!, create: TeamCreateInput!, update: TeamUpdateInput!): Team! + upsertMember(where: MemberWhereUniqueInput!, create: MemberCreateInput!, update: MemberUpdateInput!): Member! + upsertFinancialBeings(where: FinancialBeingsWhereUniqueInput!, create: FinancialBeingsCreateInput!, update: FinancialBeingsUpdateInput!): FinancialBeings! + updateManyTeams(data: TeamUpdateInput!, where: TeamWhereInput): BatchPayload! + updateManyTeamMemberses(data: TeamMembersUpdateInput!, where: TeamMembersWhereInput): BatchPayload! + updateManyMembers(data: MemberUpdateInput!, where: MemberWhereInput): BatchPayload! + updateManyFinancialBeingses(data: FinancialBeingsUpdateInput!, where: FinancialBeingsWhereInput): BatchPayload! + updateManyTeamProfiles(data: TeamProfileUpdateInput!, where: TeamProfileWhereInput): BatchPayload! + updateManyWallets(data: WalletUpdateInput!, where: WalletWhereInput): BatchPayload! + updateManyFBStatuses(data: FBStatusUpdateInput!, where: FBStatusWhereInput): BatchPayload! + updateManyTeamStatuses(data: TeamStatusUpdateInput!, where: TeamStatusWhereInput): BatchPayload! + updateManyMemberStatuses(data: MemberStatusUpdateInput!, where: MemberStatusWhereInput): BatchPayload! + deleteManyTeams(where: TeamWhereInput): BatchPayload! + deleteManyTeamMemberses(where: TeamMembersWhereInput): BatchPayload! + deleteManyMembers(where: MemberWhereInput): BatchPayload! + deleteManyFinancialBeingses(where: FinancialBeingsWhereInput): BatchPayload! + deleteManyTeamProfiles(where: TeamProfileWhereInput): BatchPayload! + deleteManyWallets(where: WalletWhereInput): BatchPayload! + deleteManyFBStatuses(where: FBStatusWhereInput): BatchPayload! + deleteManyTeamStatuses(where: TeamStatusWhereInput): BatchPayload! + deleteManyMemberStatuses(where: MemberStatusWhereInput): BatchPayload! +} + +enum MutationType { + CREATED + UPDATED + DELETED +} + +"""An object with an ID""" +interface Node { + """The id of the object.""" + id: ID! +} + +"""Information about pagination in a connection.""" +type PageInfo { + """When paginating forwards, are there more items?""" + hasNextPage: Boolean! + + """When paginating backwards, are there more items?""" + hasPreviousPage: Boolean! + + """When paginating backwards, the cursor to continue.""" + startCursor: String + + """When paginating forwards, the cursor to continue.""" + endCursor: String +} + +type Query { + teams(where: TeamWhereInput, orderBy: TeamOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Team]! + teamMemberses(where: TeamMembersWhereInput, orderBy: TeamMembersOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamMembers]! + members(where: MemberWhereInput, orderBy: MemberOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Member]! + financialBeingses(where: FinancialBeingsWhereInput, orderBy: FinancialBeingsOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [FinancialBeings]! + teamProfiles(where: TeamProfileWhereInput, orderBy: TeamProfileOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamProfile]! + wallets(where: WalletWhereInput, orderBy: WalletOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Wallet]! + fBStatuses(where: FBStatusWhereInput, orderBy: FBStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [FBStatus]! + teamStatuses(where: TeamStatusWhereInput, orderBy: TeamStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamStatus]! + memberStatuses(where: MemberStatusWhereInput, orderBy: MemberStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [MemberStatus]! + team(where: TeamWhereUniqueInput!): Team + member(where: MemberWhereUniqueInput!): Member + financialBeings(where: FinancialBeingsWhereUniqueInput!): FinancialBeings + teamsConnection(where: TeamWhereInput, orderBy: TeamOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): TeamConnection! + teamMembersesConnection(where: TeamMembersWhereInput, orderBy: TeamMembersOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): TeamMembersConnection! + membersConnection(where: MemberWhereInput, orderBy: MemberOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): MemberConnection! + financialBeingsesConnection(where: FinancialBeingsWhereInput, orderBy: FinancialBeingsOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): FinancialBeingsConnection! + teamProfilesConnection(where: TeamProfileWhereInput, orderBy: TeamProfileOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): TeamProfileConnection! + walletsConnection(where: WalletWhereInput, orderBy: WalletOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): WalletConnection! + fBStatusesConnection(where: FBStatusWhereInput, orderBy: FBStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): FBStatusConnection! + teamStatusesConnection(where: TeamStatusWhereInput, orderBy: TeamStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): TeamStatusConnection! + memberStatusesConnection(where: MemberStatusWhereInput, orderBy: MemberStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): MemberStatusConnection! + + """Fetches an object given its ID""" + node( + """The ID of an object""" + id: ID! + ): Node +} + +enum Role { + OWNER + ADMIN + MEMBER +} + +enum Status { + ACTIVE + INACTIVE + APPLY + INVITE +} + +type Subscription { + team(where: TeamSubscriptionWhereInput): TeamSubscriptionPayload + teamMembers(where: TeamMembersSubscriptionWhereInput): TeamMembersSubscriptionPayload + member(where: MemberSubscriptionWhereInput): MemberSubscriptionPayload + financialBeings(where: FinancialBeingsSubscriptionWhereInput): FinancialBeingsSubscriptionPayload + teamProfile(where: TeamProfileSubscriptionWhereInput): TeamProfileSubscriptionPayload + wallet(where: WalletSubscriptionWhereInput): WalletSubscriptionPayload + fBStatus(where: FBStatusSubscriptionWhereInput): FBStatusSubscriptionPayload + teamStatus(where: TeamStatusSubscriptionWhereInput): TeamStatusSubscriptionPayload + memberStatus(where: MemberStatusSubscriptionWhereInput): MemberStatusSubscriptionPayload +} + +type Team implements Node { + id: ID! + name: String! + slug: String! + profile(where: TeamProfileWhereInput): TeamProfile + members(where: TeamMembersWhereInput, orderBy: TeamMembersOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamMembers!] + owner: String! + wallet(where: WalletWhereInput): Wallet + fb(where: FinancialBeingsWhereInput, orderBy: FinancialBeingsOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [FinancialBeings!] + status(where: TeamStatusWhereInput, orderBy: TeamStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamStatus!] + createdAt: DateTime! +} + +"""A connection to a list of items.""" +type TeamConnection { + """Information to aid in pagination.""" + pageInfo: PageInfo! + + """A list of edges.""" + edges: [TeamEdge]! + aggregate: AggregateTeam! +} + +input TeamCreateInput { + name: String! + slug: String! + owner: String! + profile: TeamProfileCreateOneInput + members: TeamMembersCreateManyWithoutTeamInput + wallet: WalletCreateOneInput + fb: FinancialBeingsCreateManyWithoutTeamInput + status: TeamStatusCreateManyInput +} + +input TeamCreateOneWithoutFbInput { + create: TeamCreateWithoutFbInput + connect: TeamWhereUniqueInput +} + +input TeamCreateOneWithoutMembersInput { + create: TeamCreateWithoutMembersInput + connect: TeamWhereUniqueInput +} + +input TeamCreateWithoutFbInput { + name: String! + slug: String! + owner: String! + profile: TeamProfileCreateOneInput + members: TeamMembersCreateManyWithoutTeamInput + wallet: WalletCreateOneInput + status: TeamStatusCreateManyInput +} + +input TeamCreateWithoutMembersInput { + name: String! + slug: String! + owner: String! + profile: TeamProfileCreateOneInput + wallet: WalletCreateOneInput + fb: FinancialBeingsCreateManyWithoutTeamInput + status: TeamStatusCreateManyInput +} + +"""An edge in a connection.""" +type TeamEdge { + """The item at the end of the edge.""" + node: Team! + + """A cursor for use in pagination.""" + cursor: String! +} + +type TeamMembers { + member(where: MemberWhereInput): Member + team(where: TeamWhereInput): Team + role: Role + status(where: MemberStatusWhereInput, orderBy: MemberStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [MemberStatus!] + updatedAt: DateTime! +} + +"""A connection to a list of items.""" +type TeamMembersConnection { + """Information to aid in pagination.""" + pageInfo: PageInfo! + + """A list of edges.""" + edges: [TeamMembersEdge]! + aggregate: AggregateTeamMembers! +} + +input TeamMembersCreateInput { + role: Role + member: MemberCreateOneWithoutTeamInput + team: TeamCreateOneWithoutMembersInput + status: MemberStatusCreateManyInput +} + +input TeamMembersCreateManyWithoutTeamInput { + create: [TeamMembersCreateWithoutTeamInput!] +} + +input TeamMembersCreateOneWithoutMemberInput { + create: TeamMembersCreateWithoutMemberInput +} + +input TeamMembersCreateWithoutMemberInput { + role: Role + team: TeamCreateOneWithoutMembersInput + status: MemberStatusCreateManyInput +} + +input TeamMembersCreateWithoutTeamInput { + role: Role + member: MemberCreateOneWithoutTeamInput + status: MemberStatusCreateManyInput +} + +"""An edge in a connection.""" +type TeamMembersEdge { + """The item at the end of the edge.""" + node: TeamMembers! + + """A cursor for use in pagination.""" + cursor: String! +} + +enum TeamMembersOrderByInput { + role_ASC + role_DESC + updatedAt_ASC + updatedAt_DESC + id_ASC + id_DESC + createdAt_ASC + createdAt_DESC +} + +type TeamMembersPreviousValues { + role: Role + updatedAt: DateTime! +} + +type TeamMembersSubscriptionPayload { + mutation: MutationType! + node: TeamMembers + updatedFields: [String!] + previousValues: TeamMembersPreviousValues +} + +input TeamMembersSubscriptionWhereInput { + """Logical AND on all given filters.""" + AND: [TeamMembersSubscriptionWhereInput!] + + """Logical OR on all given filters.""" + OR: [TeamMembersSubscriptionWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [TeamMembersSubscriptionWhereInput!] + + """ + The subscription event gets dispatched when it's listed in mutation_in + """ + mutation_in: [MutationType!] + + """ + The subscription event gets only dispatched when one of the updated fields names is included in this list + """ + updatedFields_contains: String + + """ + The subscription event gets only dispatched when all of the field names included in this list have been updated + """ + updatedFields_contains_every: [String!] + + """ + The subscription event gets only dispatched when some of the field names included in this list have been updated + """ + updatedFields_contains_some: [String!] + node: TeamMembersWhereInput +} + +input TeamMembersUpdateInput { + role: Role + member: MemberUpdateOneWithoutTeamInput + team: TeamUpdateOneWithoutMembersInput + status: MemberStatusUpdateManyInput +} + +input TeamMembersUpdateManyWithoutTeamInput { + create: [TeamMembersCreateWithoutTeamInput!] +} + +input TeamMembersUpdateOneWithoutMemberInput { + create: TeamMembersCreateWithoutMemberInput + disconnect: Boolean + delete: Boolean + update: TeamMembersUpdateWithoutMemberDataInput + upsert: TeamMembersUpsertWithoutMemberInput +} + +input TeamMembersUpdateWithoutMemberDataInput { + role: Role + team: TeamUpdateOneWithoutMembersInput + status: MemberStatusUpdateManyInput +} + +input TeamMembersUpsertWithoutMemberInput { + update: TeamMembersUpdateWithoutMemberDataInput! + create: TeamMembersCreateWithoutMemberInput! +} + +input TeamMembersWhereInput { + """Logical AND on all given filters.""" + AND: [TeamMembersWhereInput!] + + """Logical OR on all given filters.""" + OR: [TeamMembersWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [TeamMembersWhereInput!] + role: Role + + """All values that are not equal to given value.""" + role_not: Role + + """All values that are contained in given list.""" + role_in: [Role!] + + """All values that are not contained in given list.""" + role_not_in: [Role!] + updatedAt: DateTime + + """All values that are not equal to given value.""" + updatedAt_not: DateTime + + """All values that are contained in given list.""" + updatedAt_in: [DateTime!] + + """All values that are not contained in given list.""" + updatedAt_not_in: [DateTime!] + + """All values less than the given value.""" + updatedAt_lt: DateTime + + """All values less than or equal the given value.""" + updatedAt_lte: DateTime + + """All values greater than the given value.""" + updatedAt_gt: DateTime + + """All values greater than or equal the given value.""" + updatedAt_gte: DateTime + member: MemberWhereInput + team: TeamWhereInput + status_every: MemberStatusWhereInput + status_some: MemberStatusWhereInput + status_none: MemberStatusWhereInput +} + +enum TeamOrderByInput { + id_ASC + id_DESC + name_ASC + name_DESC + slug_ASC + slug_DESC + owner_ASC + owner_DESC + createdAt_ASC + createdAt_DESC + updatedAt_ASC + updatedAt_DESC +} + +type TeamPreviousValues { + id: ID! + name: String! + slug: String! + owner: String! + createdAt: DateTime! +} + +type TeamProfile { + description: String + motto: String + avatar: String + updatedAt: DateTime! +} + +"""A connection to a list of items.""" +type TeamProfileConnection { + """Information to aid in pagination.""" + pageInfo: PageInfo! + + """A list of edges.""" + edges: [TeamProfileEdge]! + aggregate: AggregateTeamProfile! +} + +input TeamProfileCreateInput { + description: String + motto: String + avatar: String +} + +input TeamProfileCreateOneInput { + create: TeamProfileCreateInput +} + +"""An edge in a connection.""" +type TeamProfileEdge { + """The item at the end of the edge.""" + node: TeamProfile! + + """A cursor for use in pagination.""" + cursor: String! +} + +enum TeamProfileOrderByInput { + description_ASC + description_DESC + motto_ASC + motto_DESC + avatar_ASC + avatar_DESC + updatedAt_ASC + updatedAt_DESC + id_ASC + id_DESC + createdAt_ASC + createdAt_DESC +} + +type TeamProfilePreviousValues { + description: String + motto: String + avatar: String + updatedAt: DateTime! +} + +type TeamProfileSubscriptionPayload { + mutation: MutationType! + node: TeamProfile + updatedFields: [String!] + previousValues: TeamProfilePreviousValues +} + +input TeamProfileSubscriptionWhereInput { + """Logical AND on all given filters.""" + AND: [TeamProfileSubscriptionWhereInput!] + + """Logical OR on all given filters.""" + OR: [TeamProfileSubscriptionWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [TeamProfileSubscriptionWhereInput!] + + """ + The subscription event gets dispatched when it's listed in mutation_in + """ + mutation_in: [MutationType!] + + """ + The subscription event gets only dispatched when one of the updated fields names is included in this list + """ + updatedFields_contains: String + + """ + The subscription event gets only dispatched when all of the field names included in this list have been updated + """ + updatedFields_contains_every: [String!] + + """ + The subscription event gets only dispatched when some of the field names included in this list have been updated + """ + updatedFields_contains_some: [String!] + node: TeamProfileWhereInput +} + +input TeamProfileUpdateDataInput { + description: String + motto: String + avatar: String +} + +input TeamProfileUpdateInput { + description: String + motto: String + avatar: String +} + +input TeamProfileUpdateOneInput { + create: TeamProfileCreateInput + disconnect: Boolean + delete: Boolean + update: TeamProfileUpdateDataInput + upsert: TeamProfileUpsertNestedInput +} + +input TeamProfileUpsertNestedInput { + update: TeamProfileUpdateDataInput! + create: TeamProfileCreateInput! +} + +input TeamProfileWhereInput { + """Logical AND on all given filters.""" + AND: [TeamProfileWhereInput!] + + """Logical OR on all given filters.""" + OR: [TeamProfileWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [TeamProfileWhereInput!] + description: String + + """All values that are not equal to given value.""" + description_not: String + + """All values that are contained in given list.""" + description_in: [String!] + + """All values that are not contained in given list.""" + description_not_in: [String!] + + """All values less than the given value.""" + description_lt: String + + """All values less than or equal the given value.""" + description_lte: String + + """All values greater than the given value.""" + description_gt: String + + """All values greater than or equal the given value.""" + description_gte: String + + """All values containing the given string.""" + description_contains: String + + """All values not containing the given string.""" + description_not_contains: String + + """All values starting with the given string.""" + description_starts_with: String + + """All values not starting with the given string.""" + description_not_starts_with: String + + """All values ending with the given string.""" + description_ends_with: String + + """All values not ending with the given string.""" + description_not_ends_with: String + motto: String + + """All values that are not equal to given value.""" + motto_not: String + + """All values that are contained in given list.""" + motto_in: [String!] + + """All values that are not contained in given list.""" + motto_not_in: [String!] + + """All values less than the given value.""" + motto_lt: String + + """All values less than or equal the given value.""" + motto_lte: String + + """All values greater than the given value.""" + motto_gt: String + + """All values greater than or equal the given value.""" + motto_gte: String + + """All values containing the given string.""" + motto_contains: String + + """All values not containing the given string.""" + motto_not_contains: String + + """All values starting with the given string.""" + motto_starts_with: String + + """All values not starting with the given string.""" + motto_not_starts_with: String + + """All values ending with the given string.""" + motto_ends_with: String + + """All values not ending with the given string.""" + motto_not_ends_with: String + avatar: String + + """All values that are not equal to given value.""" + avatar_not: String + + """All values that are contained in given list.""" + avatar_in: [String!] + + """All values that are not contained in given list.""" + avatar_not_in: [String!] + + """All values less than the given value.""" + avatar_lt: String + + """All values less than or equal the given value.""" + avatar_lte: String + + """All values greater than the given value.""" + avatar_gt: String + + """All values greater than or equal the given value.""" + avatar_gte: String + + """All values containing the given string.""" + avatar_contains: String + + """All values not containing the given string.""" + avatar_not_contains: String + + """All values starting with the given string.""" + avatar_starts_with: String + + """All values not starting with the given string.""" + avatar_not_starts_with: String + + """All values ending with the given string.""" + avatar_ends_with: String + + """All values not ending with the given string.""" + avatar_not_ends_with: String + updatedAt: DateTime + + """All values that are not equal to given value.""" + updatedAt_not: DateTime + + """All values that are contained in given list.""" + updatedAt_in: [DateTime!] + + """All values that are not contained in given list.""" + updatedAt_not_in: [DateTime!] + + """All values less than the given value.""" + updatedAt_lt: DateTime + + """All values less than or equal the given value.""" + updatedAt_lte: DateTime + + """All values greater than the given value.""" + updatedAt_gt: DateTime + + """All values greater than or equal the given value.""" + updatedAt_gte: DateTime +} + +type TeamStatus { + status: Status + reason: String + createdAt: DateTime! +} + +"""A connection to a list of items.""" +type TeamStatusConnection { + """Information to aid in pagination.""" + pageInfo: PageInfo! + + """A list of edges.""" + edges: [TeamStatusEdge]! + aggregate: AggregateTeamStatus! +} + +input TeamStatusCreateInput { + status: Status + reason: String +} + +input TeamStatusCreateManyInput { + create: [TeamStatusCreateInput!] +} + +"""An edge in a connection.""" +type TeamStatusEdge { + """The item at the end of the edge.""" + node: TeamStatus! + + """A cursor for use in pagination.""" + cursor: String! +} + +enum TeamStatusOrderByInput { + status_ASC + status_DESC + reason_ASC + reason_DESC + createdAt_ASC + createdAt_DESC + id_ASC + id_DESC + updatedAt_ASC + updatedAt_DESC +} + +type TeamStatusPreviousValues { + status: Status + reason: String + createdAt: DateTime! +} + +type TeamStatusSubscriptionPayload { + mutation: MutationType! + node: TeamStatus + updatedFields: [String!] + previousValues: TeamStatusPreviousValues +} + +input TeamStatusSubscriptionWhereInput { + """Logical AND on all given filters.""" + AND: [TeamStatusSubscriptionWhereInput!] + + """Logical OR on all given filters.""" + OR: [TeamStatusSubscriptionWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [TeamStatusSubscriptionWhereInput!] + + """ + The subscription event gets dispatched when it's listed in mutation_in + """ + mutation_in: [MutationType!] + + """ + The subscription event gets only dispatched when one of the updated fields names is included in this list + """ + updatedFields_contains: String + + """ + The subscription event gets only dispatched when all of the field names included in this list have been updated + """ + updatedFields_contains_every: [String!] + + """ + The subscription event gets only dispatched when some of the field names included in this list have been updated + """ + updatedFields_contains_some: [String!] + node: TeamStatusWhereInput +} + +input TeamStatusUpdateInput { + status: Status + reason: String +} + +input TeamStatusUpdateManyInput { + create: [TeamStatusCreateInput!] +} + +input TeamStatusWhereInput { + """Logical AND on all given filters.""" + AND: [TeamStatusWhereInput!] + + """Logical OR on all given filters.""" + OR: [TeamStatusWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [TeamStatusWhereInput!] + status: Status + + """All values that are not equal to given value.""" + status_not: Status + + """All values that are contained in given list.""" + status_in: [Status!] + + """All values that are not contained in given list.""" + status_not_in: [Status!] + reason: String + + """All values that are not equal to given value.""" + reason_not: String + + """All values that are contained in given list.""" + reason_in: [String!] + + """All values that are not contained in given list.""" + reason_not_in: [String!] + + """All values less than the given value.""" + reason_lt: String + + """All values less than or equal the given value.""" + reason_lte: String + + """All values greater than the given value.""" + reason_gt: String + + """All values greater than or equal the given value.""" + reason_gte: String + + """All values containing the given string.""" + reason_contains: String + + """All values not containing the given string.""" + reason_not_contains: String + + """All values starting with the given string.""" + reason_starts_with: String + + """All values not starting with the given string.""" + reason_not_starts_with: String + + """All values ending with the given string.""" + reason_ends_with: String + + """All values not ending with the given string.""" + reason_not_ends_with: String + createdAt: DateTime + + """All values that are not equal to given value.""" + createdAt_not: DateTime + + """All values that are contained in given list.""" + createdAt_in: [DateTime!] + + """All values that are not contained in given list.""" + createdAt_not_in: [DateTime!] + + """All values less than the given value.""" + createdAt_lt: DateTime + + """All values less than or equal the given value.""" + createdAt_lte: DateTime + + """All values greater than the given value.""" + createdAt_gt: DateTime + + """All values greater than or equal the given value.""" + createdAt_gte: DateTime +} + +type TeamSubscriptionPayload { + mutation: MutationType! + node: Team + updatedFields: [String!] + previousValues: TeamPreviousValues +} + +input TeamSubscriptionWhereInput { + """Logical AND on all given filters.""" + AND: [TeamSubscriptionWhereInput!] + + """Logical OR on all given filters.""" + OR: [TeamSubscriptionWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [TeamSubscriptionWhereInput!] + + """ + The subscription event gets dispatched when it's listed in mutation_in + """ + mutation_in: [MutationType!] + + """ + The subscription event gets only dispatched when one of the updated fields names is included in this list + """ + updatedFields_contains: String + + """ + The subscription event gets only dispatched when all of the field names included in this list have been updated + """ + updatedFields_contains_every: [String!] + + """ + The subscription event gets only dispatched when some of the field names included in this list have been updated + """ + updatedFields_contains_some: [String!] + node: TeamWhereInput +} + +input TeamUpdateInput { + name: String + slug: String + owner: String + profile: TeamProfileUpdateOneInput + members: TeamMembersUpdateManyWithoutTeamInput + wallet: WalletUpdateOneInput + fb: FinancialBeingsUpdateManyWithoutTeamInput + status: TeamStatusUpdateManyInput +} + +input TeamUpdateOneWithoutFbInput { + create: TeamCreateWithoutFbInput + connect: TeamWhereUniqueInput + disconnect: Boolean + delete: Boolean + update: TeamUpdateWithoutFbDataInput + upsert: TeamUpsertWithoutFbInput +} + +input TeamUpdateOneWithoutMembersInput { + create: TeamCreateWithoutMembersInput + connect: TeamWhereUniqueInput + disconnect: Boolean + delete: Boolean + update: TeamUpdateWithoutMembersDataInput + upsert: TeamUpsertWithoutMembersInput +} + +input TeamUpdateWithoutFbDataInput { + name: String + slug: String + owner: String + profile: TeamProfileUpdateOneInput + members: TeamMembersUpdateManyWithoutTeamInput + wallet: WalletUpdateOneInput + status: TeamStatusUpdateManyInput +} + +input TeamUpdateWithoutMembersDataInput { + name: String + slug: String + owner: String + profile: TeamProfileUpdateOneInput + wallet: WalletUpdateOneInput + fb: FinancialBeingsUpdateManyWithoutTeamInput + status: TeamStatusUpdateManyInput +} + +input TeamUpsertWithoutFbInput { + update: TeamUpdateWithoutFbDataInput! + create: TeamCreateWithoutFbInput! +} + +input TeamUpsertWithoutMembersInput { + update: TeamUpdateWithoutMembersDataInput! + create: TeamCreateWithoutMembersInput! +} + +input TeamWhereInput { + """Logical AND on all given filters.""" + AND: [TeamWhereInput!] + + """Logical OR on all given filters.""" + OR: [TeamWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [TeamWhereInput!] + id: ID + + """All values that are not equal to given value.""" + id_not: ID + + """All values that are contained in given list.""" + id_in: [ID!] + + """All values that are not contained in given list.""" + id_not_in: [ID!] + + """All values less than the given value.""" + id_lt: ID + + """All values less than or equal the given value.""" + id_lte: ID + + """All values greater than the given value.""" + id_gt: ID + + """All values greater than or equal the given value.""" + id_gte: ID + + """All values containing the given string.""" + id_contains: ID + + """All values not containing the given string.""" + id_not_contains: ID + + """All values starting with the given string.""" + id_starts_with: ID + + """All values not starting with the given string.""" + id_not_starts_with: ID + + """All values ending with the given string.""" + id_ends_with: ID + + """All values not ending with the given string.""" + id_not_ends_with: ID + name: String + + """All values that are not equal to given value.""" + name_not: String + + """All values that are contained in given list.""" + name_in: [String!] + + """All values that are not contained in given list.""" + name_not_in: [String!] + + """All values less than the given value.""" + name_lt: String + + """All values less than or equal the given value.""" + name_lte: String + + """All values greater than the given value.""" + name_gt: String + + """All values greater than or equal the given value.""" + name_gte: String + + """All values containing the given string.""" + name_contains: String + + """All values not containing the given string.""" + name_not_contains: String + + """All values starting with the given string.""" + name_starts_with: String + + """All values not starting with the given string.""" + name_not_starts_with: String + + """All values ending with the given string.""" + name_ends_with: String + + """All values not ending with the given string.""" + name_not_ends_with: String + slug: String + + """All values that are not equal to given value.""" + slug_not: String + + """All values that are contained in given list.""" + slug_in: [String!] + + """All values that are not contained in given list.""" + slug_not_in: [String!] + + """All values less than the given value.""" + slug_lt: String + + """All values less than or equal the given value.""" + slug_lte: String + + """All values greater than the given value.""" + slug_gt: String + + """All values greater than or equal the given value.""" + slug_gte: String + + """All values containing the given string.""" + slug_contains: String + + """All values not containing the given string.""" + slug_not_contains: String + + """All values starting with the given string.""" + slug_starts_with: String + + """All values not starting with the given string.""" + slug_not_starts_with: String + + """All values ending with the given string.""" + slug_ends_with: String + + """All values not ending with the given string.""" + slug_not_ends_with: String + owner: String + + """All values that are not equal to given value.""" + owner_not: String + + """All values that are contained in given list.""" + owner_in: [String!] + + """All values that are not contained in given list.""" + owner_not_in: [String!] + + """All values less than the given value.""" + owner_lt: String + + """All values less than or equal the given value.""" + owner_lte: String + + """All values greater than the given value.""" + owner_gt: String + + """All values greater than or equal the given value.""" + owner_gte: String + + """All values containing the given string.""" + owner_contains: String + + """All values not containing the given string.""" + owner_not_contains: String + + """All values starting with the given string.""" + owner_starts_with: String + + """All values not starting with the given string.""" + owner_not_starts_with: String + + """All values ending with the given string.""" + owner_ends_with: String + + """All values not ending with the given string.""" + owner_not_ends_with: String + createdAt: DateTime + + """All values that are not equal to given value.""" + createdAt_not: DateTime + + """All values that are contained in given list.""" + createdAt_in: [DateTime!] + + """All values that are not contained in given list.""" + createdAt_not_in: [DateTime!] + + """All values less than the given value.""" + createdAt_lt: DateTime + + """All values less than or equal the given value.""" + createdAt_lte: DateTime + + """All values greater than the given value.""" + createdAt_gt: DateTime + + """All values greater than or equal the given value.""" + createdAt_gte: DateTime + profile: TeamProfileWhereInput + members_every: TeamMembersWhereInput + members_some: TeamMembersWhereInput + members_none: TeamMembersWhereInput + wallet: WalletWhereInput + fb_every: FinancialBeingsWhereInput + fb_some: FinancialBeingsWhereInput + fb_none: FinancialBeingsWhereInput + status_every: TeamStatusWhereInput + status_some: TeamStatusWhereInput + status_none: TeamStatusWhereInput +} + +input TeamWhereUniqueInput { + id: ID + name: String + slug: String +} + +type Wallet { + balance: Float + updatedAt: DateTime! +} + +"""A connection to a list of items.""" +type WalletConnection { + """Information to aid in pagination.""" + pageInfo: PageInfo! + + """A list of edges.""" + edges: [WalletEdge]! + aggregate: AggregateWallet! +} + +input WalletCreateInput { + balance: Float +} + +input WalletCreateOneInput { + create: WalletCreateInput +} + +"""An edge in a connection.""" +type WalletEdge { + """The item at the end of the edge.""" + node: Wallet! + + """A cursor for use in pagination.""" + cursor: String! +} + +enum WalletOrderByInput { + balance_ASC + balance_DESC + updatedAt_ASC + updatedAt_DESC + id_ASC + id_DESC + createdAt_ASC + createdAt_DESC +} + +type WalletPreviousValues { + balance: Float + updatedAt: DateTime! +} + +type WalletSubscriptionPayload { + mutation: MutationType! + node: Wallet + updatedFields: [String!] + previousValues: WalletPreviousValues +} + +input WalletSubscriptionWhereInput { + """Logical AND on all given filters.""" + AND: [WalletSubscriptionWhereInput!] + + """Logical OR on all given filters.""" + OR: [WalletSubscriptionWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [WalletSubscriptionWhereInput!] + + """ + The subscription event gets dispatched when it's listed in mutation_in + """ + mutation_in: [MutationType!] + + """ + The subscription event gets only dispatched when one of the updated fields names is included in this list + """ + updatedFields_contains: String + + """ + The subscription event gets only dispatched when all of the field names included in this list have been updated + """ + updatedFields_contains_every: [String!] + + """ + The subscription event gets only dispatched when some of the field names included in this list have been updated + """ + updatedFields_contains_some: [String!] + node: WalletWhereInput +} + +input WalletUpdateDataInput { + balance: Float +} + +input WalletUpdateInput { + balance: Float +} + +input WalletUpdateOneInput { + create: WalletCreateInput + disconnect: Boolean + delete: Boolean + update: WalletUpdateDataInput + upsert: WalletUpsertNestedInput +} + +input WalletUpsertNestedInput { + update: WalletUpdateDataInput! + create: WalletCreateInput! +} + +input WalletWhereInput { + """Logical AND on all given filters.""" + AND: [WalletWhereInput!] + + """Logical OR on all given filters.""" + OR: [WalletWhereInput!] + + """Logical NOT on all given filters combined by AND.""" + NOT: [WalletWhereInput!] + balance: Float + + """All values that are not equal to given value.""" + balance_not: Float + + """All values that are contained in given list.""" + balance_in: [Float!] + + """All values that are not contained in given list.""" + balance_not_in: [Float!] + + """All values less than the given value.""" + balance_lt: Float + + """All values less than or equal the given value.""" + balance_lte: Float + + """All values greater than the given value.""" + balance_gt: Float + + """All values greater than or equal the given value.""" + balance_gte: Float + updatedAt: DateTime + + """All values that are not equal to given value.""" + updatedAt_not: DateTime + + """All values that are contained in given list.""" + updatedAt_in: [DateTime!] + + """All values that are not contained in given list.""" + updatedAt_not_in: [DateTime!] + + """All values less than the given value.""" + updatedAt_lt: DateTime + + """All values less than or equal the given value.""" + updatedAt_lte: DateTime + + """All values greater than the given value.""" + updatedAt_gt: DateTime + + """All values greater than or equal the given value.""" + updatedAt_gte: DateTime +} diff --git a/api/src/index.js b/api/src/index.js index 33439b574..be92331cd 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -1,3 +1,4 @@ +require('dotenv').config(); const { GraphQLServer } = require('graphql-yoga') const { Prisma, @@ -8,15 +9,39 @@ const { makeExecutableSchema } = require('graphql-tools') const { importSchema } = require('graphql-import') const { checkJwt } = require('./auth/middleware/jwt') const { getMember } = require('./auth/middleware/getMember') -const validateParseIdToken = require('./auth/helpers/validate-parse-id-token') -const { directiveResolvers } = require('./auth-directives') +const { validateIdToken } = require('./auth/validateIdToken') +const { directiveResolvers } = require('./auth/authDirectives') + +const createMember = async function (ctx, info, idToken) { + console.log('createMember', idToken) + const member = await ctx.db.mutation.upsertMember({ + where: { + authId: idToken.sub, + }, + create: { + authId: idToken.sub, + alias: idToken.nickname + }, + update: { + authId: idToken.sub, + alias: idToken.nickname + } + }, info) + return member +} const ctxMember = ctx => ctx.request.member const resolvers = { Query: { - async member(parent, { auth0id }, ctx, info) { - return ctx.db.query.member({ where: { auth0id } }, info) + async member(parent, arg, ctx, info) { + console.log('member: ', parent, arg) + return ctx.db.query.member({ where: { authId: arg.authId } }, info) + }, + async currentMember(parent, args, ctx, info) { + console.log('currentMember: ', ctx.request.res.req.user) + const authId = ctx.request.res.req.user.sub + return ctx.db.query.member({ where: { authId } }, info) }, teams(parent, args, ctx, info) { return ctx.db.query.teamsConnection({}, @@ -59,7 +84,7 @@ const resolvers = { return ctx.db.query.team({ where: { name: name } }, `{ name }`) }, async teamByOwner(parent, { ownerId }, ctx, info) { - return ctx.db.query.teamsConnection({where: { owner: { auth0id: ownerId }}}, + return ctx.db.query.teamsConnection({where: { owner: { authId: ownerId }}}, `{ edges { node { @@ -72,7 +97,7 @@ const resolvers = { motto } owner { - auth0id + authId nickname visible profile { @@ -95,28 +120,27 @@ const resolvers = { }, async owner(parent, args, ctx, info) { console.log('resolver.query.owner ctx: ', ctxMember(ctx)) - return ctx.db.query.member({ where: { id: ctxMember(ctx).auth0id } }, info) + return ctx.db.query.member({ where: { id: ctxMember(ctx).authId } }, info) .catch((res) => { console.log('createTeam error: ', res) const errors = res.graphQLErrors.map((error) => { return error.message }) }) - }, - members: forwardTo('db') + } }, Mutation: { async authenticate(parent, { idToken }, ctx, info) { let memberToken = null try { - memberToken = await validateAndParseIdToken(idToken) + memberToken = await validateIdToken(idToken) console.log('authenticate.memberToken: ', await memberToken) } catch (err) { - console.log('authenticat.validateAndParseIdToken err: ', err) + console.log('authenticat.validateIdToken err: ', err) throw new Error(err.message) } - const auth0id = memberToken.sub - let member = await ctx.db.query.member({ where: { auth0id } }, info) + const authId = memberToken.sub + let member = await ctx.db.query.member({ where: { authId } }, info) if (!member) { try { @@ -124,7 +148,6 @@ const resolvers = { } catch (error) { throw new Error(error.message) } - } } return member }, @@ -133,15 +156,12 @@ const resolvers = { data: { name: name, slug: slug, - owner: {connect:{auth0id: owner}}, - members: {create: {role: 'OWNER', member: {connect: {auth0id: owner}}}} + owner: owner } }, info) - .catch((res) => { - console.log('createTeam error: ', res) - const errors = res.graphQLErrors.map((error) => { - return error.message - }) + .catch((err) => { + console.log('createTeam error: ', err) + return err }) }, async deleteTeam(parent, { id }, ctx, info) { @@ -176,25 +196,30 @@ const server = new GraphQLServer({ context: req => ({ ...req, db - }) + }), }) -server.express.post( +server.express.use( server.options.endpoint, checkJwt, (err, req, res, next) => { + console.log('checkJwt: ', err, req.user) if (err) return res.status(401).send(err.message) next() } ) -server.express.post(server.options.endpoint, (req, res, done) => +server.express.post(server.options.endpoint, (err, req, res, done) => { + console.log('getMember: ', err, req.user) getMember(req, res, done, db) -) +}) const whitelist = [ - 'http://localhost:1337', - 'http://0.0.0.0:5000' + 'http://localhost:3000', + 'http://localhost:3001', + 'http://localhost:3002', + 'http://localhost:4000', + 'http://localhost:4002' ] const corsOptionsDelegate = (req, callback) => { var corsOptions @@ -207,12 +232,13 @@ const corsOptionsDelegate = (req, callback) => { } const options = { + port: 4001, cors: corsOptionsDelegate, endpoint: '/graphql', subscriptions: '/graphql', playground: '/playground' } -server.start(options, () => console.log(`Server is running on http://localhost:4000${server.options.endpoint}`)) +server.start(options, () => console.log(`Server is running on http://localhost:4001${server.options.endpoint}`)) -module.exports= { createPrismaMember: createPrismaMember } +module.exports= { createMember } diff --git a/api/src/schema.graphqls b/api/src/schema.graphql similarity index 69% rename from api/src/schema.graphqls rename to api/src/schema.graphql index b61df8546..82bae531d 100644 --- a/api/src/schema.graphqls +++ b/api/src/schema.graphql @@ -12,24 +12,37 @@ type Query { teamById(teamId: String!): Team teamByOwner(ownerId: String!): TeamConnection owner: Member @isAuthenticated - member(auth0id: String!): Member @isAuthenticated + currentMember: Member @isAuthenticated + member(authId: String!): Member @isAuthenticated } type Mutation { authenticate(idToken: String!): Member createTeam(name: String!, slug: String, owner: String): Team @isAuthenticated deleteTeam(id: ID!): Team @isAuthenticated @isOwner(type: "Team") - updateProfile(data: MemberProfileInput): Member @isAuthenticated } input MemberProfileInput { - auth0id: String! - nickname: String! - anonymous: Boolean - visible: Boolean - avatar: String - email: String - repo: String - bio: String - status: String + authId: String! + alias: String! +} + +fragment MemberInfo on Member { + id + authId + alias + isActive + profile { + ...MemberProfileInfo + } +} + +fragment MemberProfileInfo on MemberProfile { + firstName + lastName + email + avatar + role { + name + } } diff --git a/client/src/views/index.js b/client/src/views/index.js index a1e5c1f8a..6759b33df 100644 --- a/client/src/views/index.js +++ b/client/src/views/index.js @@ -3,7 +3,8 @@ import Footer from './footer' import Callback from './callback' import Home from './home' import Dashboard from './dashboard' +import Teams from './teams' import { theme, globalStyles } from './theme' -export { NavBar, Footer, Callback, Home, Dashboard, theme, globalStyles } +export { NavBar, Footer, Callback, Home, Dashboard, Teams, theme, globalStyles } diff --git a/client/src/views/teams/index.js b/client/src/views/teams/index.js new file mode 100644 index 000000000..69dbd99aa --- /dev/null +++ b/client/src/views/teams/index.js @@ -0,0 +1,53 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import CssBaseline from '@material-ui/core/CssBaseline' +import Typography from '@material-ui/core/Typography' +import { withStyles } from '@material-ui/core/styles' + +const styles = theme => ({ + '@global': { + body: { + backgroundColor: theme.palette.common.white + } + }, + layout: { + width: 'auto', + marginLeft: theme.spacing.unit * 3, + marginRight: theme.spacing.unit * 3, + [theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: { + width: 900, + marginLeft: 'auto', + marginRight: 'auto' + } + }, + heroContent: { + maxWidth: 600, + margin: '0 auto', + padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px` + } +}) + +const Home = ({ classes }) => ( + + +
+
+ + Teams + +
+
+
+) + +Home.propTypes = { + classes: PropTypes.object.isRequired +} + +export default withStyles(styles)(Home) diff --git a/docs/CodeStyle.md b/docs/CodeStyle.md new file mode 100644 index 000000000..483afda50 --- /dev/null +++ b/docs/CodeStyle.md @@ -0,0 +1,5 @@ +# Code Styling and Formatting + +``` +npm install --save-dev eslint-config-standard eslint-config-standard-react eslint-plugin-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-node eslint-plugin-react +``` From 7c85c00b418ca8dfffdad1b430f6f126e4a9cbfa Mon Sep 17 00:00:00 2001 From: Barry Low Date: Wed, 12 Sep 2018 22:36:33 -0700 Subject: [PATCH 02/19] Client: break apart dashboard --- client/src/App.js | 6 +- .../src/graphql/teams/CreateTeamMutation.js | 2 +- client/src/views/dashboard/ManageTeams.js | 30 +++ client/src/views/dashboard/Overview.js | 73 +++++++ client/src/views/dashboard/TeamMembers.js | 30 +++ .../views/dashboard/components/CreateTeam.js | 16 +- .../views/dashboard/components/DashEditor.js | 50 +++++ .../views/dashboard/components/DashTeam.js | 22 ++ .../dashboard/components/DashTeamItem.js | 72 +++++++ client/src/views/dashboard/index.js | 164 ++------------ client/src/views/dashboard/members.js | 111 ---------- client/src/views/dashboard/settings.js | 202 +----------------- client/src/views/dashboard/teams.js | 111 ---------- 13 files changed, 313 insertions(+), 576 deletions(-) create mode 100644 client/src/views/dashboard/ManageTeams.js create mode 100644 client/src/views/dashboard/Overview.js create mode 100644 client/src/views/dashboard/TeamMembers.js create mode 100644 client/src/views/dashboard/components/DashEditor.js create mode 100644 client/src/views/dashboard/components/DashTeam.js create mode 100644 client/src/views/dashboard/components/DashTeamItem.js delete mode 100644 client/src/views/dashboard/members.js delete mode 100644 client/src/views/dashboard/teams.js diff --git a/client/src/App.js b/client/src/App.js index 5dcdda261..60dddf69d 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -148,7 +148,11 @@ class App extends Component { - + { diff --git a/client/src/graphql/teams/CreateTeamMutation.js b/client/src/graphql/teams/CreateTeamMutation.js index 752546daa..25858f6ed 100644 --- a/client/src/graphql/teams/CreateTeamMutation.js +++ b/client/src/graphql/teams/CreateTeamMutation.js @@ -8,7 +8,7 @@ export const CreateTeamMutation = gql` name slug owner - members{ + members { role member { authId diff --git a/client/src/views/dashboard/ManageTeams.js b/client/src/views/dashboard/ManageTeams.js new file mode 100644 index 000000000..7c284e75e --- /dev/null +++ b/client/src/views/dashboard/ManageTeams.js @@ -0,0 +1,30 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import Typography from '@material-ui/core/Typography' +import { withStyles } from '@material-ui/core/styles' + +import { TeamTable } from './components/TeamTable' + +const styles = theme => ({ + tableContainer: { + height: 320 + } +}) + +const ManageTeams = ({ classes }) => ( +
+ + Teams + +
+ +
+
+) + +ManageTeams.propTypes = { + classes: PropTypes.object.isRequired +} + +export default withStyles(styles)(ManageTeams) diff --git a/client/src/views/dashboard/Overview.js b/client/src/views/dashboard/Overview.js new file mode 100644 index 000000000..19f30450f --- /dev/null +++ b/client/src/views/dashboard/Overview.js @@ -0,0 +1,73 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { graphql } from 'react-apollo' + +import { withStyles } from '@material-ui/core/styles' + +import Grid from '@material-ui/core/Grid' +import Card from '@material-ui/core/Card' +import CardContent from '@material-ui/core/CardContent' + +import { CreateTeamDialog } from './components/CreateTeam' +import { DashTeam } from './components/DashTeam' +import { DashEditor } from './components/DashEditor' + +import { CreateTeamMutation } from '../../graphql/teams/CreateTeamMutation' + +const styles = theme => ({ + card: { + display: 'flex', + width: '100%' + }, + cardDetails: { + display: 'flex', + flex: 1 + }, + cardContent: { + flex: 1 + }, + cardMedia: { + flex: 1, + width: 160, + height: 160, + justifyContent: 'flex-start' + }, + buttonRight: { + justifyContent: 'flex-end' + } +}) + +export const Overview = ({ classes, createTeamMutation }) => ( + + + + +
+ + + +
+
+
+
+ + +
+) + +Overview.propTypes = { + classes: PropTypes.object.isRequired, + createTeamMutation: PropTypes.object +} + +const OverviewWithMutation = graphql(CreateTeamMutation, { + name: 'createTeamMutation', + options: props => ({ + // Options are computed from `props` here. + }) +})(Overview) + +export default withStyles(styles)(OverviewWithMutation) diff --git a/client/src/views/dashboard/TeamMembers.js b/client/src/views/dashboard/TeamMembers.js new file mode 100644 index 000000000..a22de3714 --- /dev/null +++ b/client/src/views/dashboard/TeamMembers.js @@ -0,0 +1,30 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import Typography from '@material-ui/core/Typography' +import { withStyles } from '@material-ui/core/styles' + +import { TeamTable } from './components/TeamTable' + +const styles = theme => ({ + tableContainer: { + height: 320 + } +}) + +const TeamMembers = ({ classes }) => ( +
+ + Members + +
+ +
+
+) + +TeamMembers.propTypes = { + classes: PropTypes.object.isRequired +} + +export default withStyles(styles)(TeamMembers) diff --git a/client/src/views/dashboard/components/CreateTeam.js b/client/src/views/dashboard/components/CreateTeam.js index 2d0bda554..98e3aebc6 100644 --- a/client/src/views/dashboard/components/CreateTeam.js +++ b/client/src/views/dashboard/components/CreateTeam.js @@ -52,9 +52,7 @@ export class CreateTeamDialog extends Component { onClick={this.handleClickOpen} > - - Create A Team - + Create A Team Subscribe - - Team Creation - - - Name your team! - + Team Creation + Name your team! b.charAt(a.indexOf(c))) // Replace special characters .replace(/&/g, '-and-') // Replace & with 'and' diff --git a/client/src/views/dashboard/components/DashEditor.js b/client/src/views/dashboard/components/DashEditor.js new file mode 100644 index 000000000..1f6aa4cae --- /dev/null +++ b/client/src/views/dashboard/components/DashEditor.js @@ -0,0 +1,50 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import Typography from '@material-ui/core/Typography' +import { withStyles } from '@material-ui/core/styles' + +import Grid from '@material-ui/core/Grid' +import Card from '@material-ui/core/Card' +import CardMedia from '@material-ui/core/CardMedia' +import CardActions from '@material-ui/core/CardActions' +import Button from '@material-ui/core/Button' + +import aaweb from '../../assets/AlgonetWebPlatform.jpg' + +const styles = theme => ({ + aawebMedia: { + width: '100%', + height: 320 + } +}) + +export const DashEditor = ({ classes }) => ( + + + Develop + + + + + + + + + + + + + + +) + +DashEditor.propTypes = { + classes: PropTypes.object.isRequired +} + +export default withStyles(styles)(DashEditor) diff --git a/client/src/views/dashboard/components/DashTeam.js b/client/src/views/dashboard/components/DashTeam.js new file mode 100644 index 000000000..e56695511 --- /dev/null +++ b/client/src/views/dashboard/components/DashTeam.js @@ -0,0 +1,22 @@ +import React from 'react' +import { Query } from 'react-apollo' + +import Typography from '@material-ui/core/Typography' +import Grid from '@material-ui/core/Grid' + +import { DashTeamIteam } from './DashTeamIteam' + +export const DashTeam = () => ( + + + + Teams + + + + + + +) + +export default DashTeam diff --git a/client/src/views/dashboard/components/DashTeamItem.js b/client/src/views/dashboard/components/DashTeamItem.js new file mode 100644 index 000000000..cdf585c8f --- /dev/null +++ b/client/src/views/dashboard/components/DashTeamItem.js @@ -0,0 +1,72 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import Typography from '@material-ui/core/Typography' +import { withStyles } from '@material-ui/core/styles' + +import Grid from '@material-ui/core/Grid' +import Card from '@material-ui/core/Card' +import CardContent from '@material-ui/core/CardContent' +import CardMedia from '@material-ui/core/CardMedia' +import CardActions from '@material-ui/core/CardActions' +import Button from '@material-ui/core/Button' + +const styles = theme => ({ + card: { + display: 'flex', + width: '100%' + }, + cardDetails: { + display: 'flex', + flex: 1 + }, + cardContent: { + flex: 1 + }, + cardMedia: { + flex: 1, + width: 160, + height: 160, + justifyContent: 'flex-start' + }, + buttonRight: { + justifyContent: 'flex-end' + } +}) + +export const DashTeamItem = ({ classes }) => ( + + +
+ + + Goodester + + 09.15.2018 + + + Members:6 + + + Now recruiting! + + + + + +
+
+
+) + +DashTeamItem.propTypes = { + classes: PropTypes.object.isRequired +} + +export default withStyles(styles)(DashTeamItem) diff --git a/client/src/views/dashboard/index.js b/client/src/views/dashboard/index.js index 6392347ed..3d39c1057 100644 --- a/client/src/views/dashboard/index.js +++ b/client/src/views/dashboard/index.js @@ -1,25 +1,18 @@ import React from 'react' import PropTypes from 'prop-types' -import { graphql } from 'react-apollo' +import { Route, Switch } from 'react-router-dom' -import Typography from '@material-ui/core/Typography' import { withStyles } from '@material-ui/core/styles' import Drawer from '@material-ui/core/Drawer' import List from '@material-ui/core/List' import Divider from '@material-ui/core/Divider' -import Grid from '@material-ui/core/Grid' -import Card from '@material-ui/core/Card' -import CardContent from '@material-ui/core/CardContent' -import CardMedia from '@material-ui/core/CardMedia' -import CardActions from '@material-ui/core/CardActions' -import Button from '@material-ui/core/Button' import { MainDrawerItems, SecondaryDrawerItems } from './components/DrawerLinks' -import { CreateTeamDialog } from './components/CreateTeam' -import { CreateTeamMutation } from '../../graphql/teams/CreateTeamMutation' - -import aaweb from '../../assets/AlgonetWebPlatform.jpg' +import { Overview } from 'Overview' +import { ManageTeams } from 'ManageTeams' +import { TeamMembers } from 'TeamMembers' +import { Settings } from 'Settings' const drawerWidth = 240 @@ -49,37 +42,7 @@ const styles = theme => ({ overflow: 'auto', width: `calc(90% - ${drawerWidth}px)` }, - appBarSpacer: theme.mixins.toolbar, - tableContainer: { - height: 320 - }, - card: { - display: 'flex', - width: '100%' - }, - cardDetails: { - display: 'flex', - flex: 1 - }, - cardContent: { - flex: 1 - }, - cardMedia: { - flex: 1, - width: 160, - height: 160, - justifyContent: 'flex-start' - }, - aawebMedia: { - width: '100%', - height: 320 - }, - buttonRight: { - justifyContent: 'flex-end' - }, - extendedIcon: { - marginRight: theme.spacing.unit - } + appBarSpacer: theme.mixins.toolbar }) const Dashboard = ({ classes, createTeamMutation, ...props }) => ( @@ -97,109 +60,12 @@ const Dashboard = ({ classes, createTeamMutation, ...props }) => (
- - - - Teams - - - - -
- - - -
-
-
- - -
- - - Goodester - - 09.15.2018 - - - Members:6 - - - Now recruiting! - - - - - -
-
-
- - -
- - - Goodester - - 09.15.2018 - - - Members:6 - - - Now recruiting! - - - - - -
-
-
-
-
- - - Develop - - - - - - - - - - - - - - -
+ + + + + +
) @@ -209,8 +75,4 @@ Dashboard.propTypes = { createTeamMutation: PropTypes.function } -const CreateTeamDialogWithMutation = graphql(CreateTeamMutation, { - name: 'createTeamMutation' // name of the injected prop: this.props.createTeamMutation... -})(Dashboard) - -export default withStyles(styles)(CreateTeamDialogWithMutation) +export default withStyles(styles)(Dashboard) diff --git a/client/src/views/dashboard/members.js b/client/src/views/dashboard/members.js deleted file mode 100644 index da5524ed0..000000000 --- a/client/src/views/dashboard/members.js +++ /dev/null @@ -1,111 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { graphql } from 'react-apollo' - -import Typography from '@material-ui/core/Typography' -import { withStyles } from '@material-ui/core/styles' -import Drawer from '@material-ui/core/Drawer' -import List from '@material-ui/core/List' -import Divider from '@material-ui/core/Divider' - -import { MainDrawerItems, SecondaryDrawerItems } from './components/DrawerLinks' -import { TeamTable } from './components/TeamTable' - -import { CreateTeamMutation } from '../../graphql/teams/CreateTeamMutation' - -const drawerWidth = 240 - -const styles = theme => ({ - root: { - display: 'flex' - }, - '@global': { - body: { - backgroundColor: theme.palette.common.white - } - }, - appBar: { - zIndex: theme.zIndex.drawer + 1 - }, - drawerPaper: { - position: 'relative', - width: drawerWidth, - whiteSpace: 'nowrap', - zIndex: 1000 - }, - content: { - flexGrow: 1, - backgroundColor: theme.palette.background.default, - padding: theme.spacing.unit * 3, - height: '100vh', - overflow: 'auto', - width: `calc(90% - ${drawerWidth}px)` - }, - appBarSpacer: theme.mixins.toolbar, - tableContainer: { - height: 320 - }, - card: { - display: 'flex', - width: '100%' - }, - cardDetails: { - display: 'flex', - flex: 1 - }, - cardContent: { - flex: 1 - }, - cardMedia: { - flex: 1, - width: 160, - height: 160, - justifyContent: 'flex-start' - }, - aawebMedia: { - width: '100%', - height: 320 - }, - buttonRight: { - justifyContent: 'flex-end' - }, - extendedIcon: { - marginRight: theme.spacing.unit - } -}) - -const Dashboard = ({ classes, createTeamMutation, ...props }) => ( -
- -
- {MainDrawerItems} - - {SecondaryDrawerItems} - -
-
- - Members - -
- -
-
-
-) - -Dashboard.propTypes = { - classes: PropTypes.object.isRequired, - createTeamMutation: PropTypes.function -} - -const CreateTeamDialogWithMutation = graphql(CreateTeamMutation, { - name: 'createTeamMutation' // name of the injected prop: this.props.createTeamMutation... -})(Dashboard) - -export default withStyles(styles)(CreateTeamDialogWithMutation) diff --git a/client/src/views/dashboard/settings.js b/client/src/views/dashboard/settings.js index 0fac8c47e..3ae32bfcc 100644 --- a/client/src/views/dashboard/settings.js +++ b/client/src/views/dashboard/settings.js @@ -1,210 +1,30 @@ import React from 'react' import PropTypes from 'prop-types' -import { graphql } from 'react-apollo' import Typography from '@material-ui/core/Typography' import { withStyles } from '@material-ui/core/styles' -import Drawer from '@material-ui/core/Drawer' -import List from '@material-ui/core/List' -import Divider from '@material-ui/core/Divider' -import Grid from '@material-ui/core/Grid' -import Card from '@material-ui/core/Card' -import CardContent from '@material-ui/core/CardContent' -import CardMedia from '@material-ui/core/CardMedia' -import CardActions from '@material-ui/core/CardActions' -import Button from '@material-ui/core/Button' -import { MainDrawerItems, SecondaryDrawerItems } from './components/DrawerLinks' import { TeamTable } from './components/TeamTable' -import { CreateTeamDialog } from './components/CreateTeam' - -import { CreateTeamMutation } from '../../graphql/teams/CreateTeamMutation' - -const drawerWidth = 240 const styles = theme => ({ - root: { - display: 'flex' - }, - '@global': { - body: { - backgroundColor: theme.palette.common.white - } - }, - appBar: { - zIndex: theme.zIndex.drawer + 1 - }, - drawerPaper: { - position: 'relative', - width: drawerWidth, - whiteSpace: 'nowrap', - zIndex: 1000 - }, - content: { - flexGrow: 1, - backgroundColor: theme.palette.background.default, - padding: theme.spacing.unit * 3, - height: '100vh', - overflow: 'auto', - width: `calc(90% - ${drawerWidth}px)` - }, - appBarSpacer: theme.mixins.toolbar, tableContainer: { height: 320 - }, - card: { - display: 'flex', - width: '100%' - }, - cardDetails: { - display: 'flex', - flex: 1 - }, - cardContent: { - flex: 1 - }, - cardMedia: { - flex: 1, - width: 160, - height: 160, - justifyContent: 'flex-start' - }, - aawebMedia: { - width: '100%', - height: 320 - }, - buttonRight: { - justifyContent: 'flex-end' - }, - extendedIcon: { - marginRight: theme.spacing.unit } }) -const Dashboard = ({ classes, createTeamMutation, ...props }) => ( -
- -
- {MainDrawerItems} - - {SecondaryDrawerItems} - -
-
- - - - Settings - - - - -
- - - -
-
-
- - -
- - - Goodester - - 09.15.2018 - - - Members:6 - - - Now recruiting! - - - - - -
-
-
- - -
- - - Goodester - - 09.15.2018 - - - Members:6 - - - Now recruiting! - - - - - -
-
-
-
-
- - - Notifications - - - - - - - - - - - - - -
-
+const Settings = ({ classes }) => ( +
+ + Settings + +
+ +
) -Dashboard.propTypes = { - classes: PropTypes.object.isRequired, - createTeamMutation: PropTypes.function +Settings.propTypes = { + classes: PropTypes.object.isRequired } -const CreateTeamDialogWithMutation = graphql(CreateTeamMutation, { - name: 'createTeamMutation' // name of the injected prop: this.props.createTeamMutation... -})(Dashboard) - -export default withStyles(styles)(CreateTeamDialogWithMutation) +export default withStyles(styles)(Settings) diff --git a/client/src/views/dashboard/teams.js b/client/src/views/dashboard/teams.js deleted file mode 100644 index 9d223e372..000000000 --- a/client/src/views/dashboard/teams.js +++ /dev/null @@ -1,111 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { graphql } from 'react-apollo' - -import Typography from '@material-ui/core/Typography' -import { withStyles } from '@material-ui/core/styles' -import Drawer from '@material-ui/core/Drawer' -import List from '@material-ui/core/List' -import Divider from '@material-ui/core/Divider' - -import { MainDrawerItems, SecondaryDrawerItems } from './components/DrawerLinks' -import { TeamTable } from './components/TeamTable' - -import { CreateTeamMutation } from '../../graphql/teams/CreateTeamMutation' - -const drawerWidth = 240 - -const styles = theme => ({ - root: { - display: 'flex' - }, - '@global': { - body: { - backgroundColor: theme.palette.common.white - } - }, - appBar: { - zIndex: theme.zIndex.drawer + 1 - }, - drawerPaper: { - position: 'relative', - width: drawerWidth, - whiteSpace: 'nowrap', - zIndex: 1000 - }, - content: { - flexGrow: 1, - backgroundColor: theme.palette.background.default, - padding: theme.spacing.unit * 3, - height: '100vh', - overflow: 'auto', - width: `calc(90% - ${drawerWidth}px)` - }, - appBarSpacer: theme.mixins.toolbar, - tableContainer: { - height: 320 - }, - card: { - display: 'flex', - width: '100%' - }, - cardDetails: { - display: 'flex', - flex: 1 - }, - cardContent: { - flex: 1 - }, - cardMedia: { - flex: 1, - width: 160, - height: 160, - justifyContent: 'flex-start' - }, - aawebMedia: { - width: '100%', - height: 320 - }, - buttonRight: { - justifyContent: 'flex-end' - }, - extendedIcon: { - marginRight: theme.spacing.unit - } -}) - -const Dashboard = ({ classes, createTeamMutation, ...props }) => ( -
- -
- {MainDrawerItems} - - {SecondaryDrawerItems} - -
-
- - Teams - -
- -
-
-
-) - -Dashboard.propTypes = { - classes: PropTypes.object.isRequired, - createTeamMutation: PropTypes.function -} - -const CreateTeamDialogWithMutation = graphql(CreateTeamMutation, { - name: 'createTeamMutation' // name of the injected prop: this.props.createTeamMutation... -})(Dashboard) - -export default withStyles(styles)(CreateTeamDialogWithMutation) From e4f03fb701866d6a7fc21bbfd296ddfe56c9a257 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Wed, 12 Sep 2018 22:43:12 -0700 Subject: [PATCH 03/19] Client: fix dashboard paths --- client/src/views/dashboard/ManageTeams.js | 2 +- client/src/views/dashboard/TeamMembers.js | 2 +- client/src/views/dashboard/components/DashEditor.js | 2 +- client/src/views/dashboard/components/DashTeam.js | 2 +- client/src/views/dashboard/index.js | 8 ++++---- client/src/views/dashboard/settings.js | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/client/src/views/dashboard/ManageTeams.js b/client/src/views/dashboard/ManageTeams.js index 7c284e75e..432007a95 100644 --- a/client/src/views/dashboard/ManageTeams.js +++ b/client/src/views/dashboard/ManageTeams.js @@ -12,7 +12,7 @@ const styles = theme => ({ } }) -const ManageTeams = ({ classes }) => ( +export const ManageTeams = ({ classes }) => (
Teams diff --git a/client/src/views/dashboard/TeamMembers.js b/client/src/views/dashboard/TeamMembers.js index a22de3714..ab74d6f31 100644 --- a/client/src/views/dashboard/TeamMembers.js +++ b/client/src/views/dashboard/TeamMembers.js @@ -12,7 +12,7 @@ const styles = theme => ({ } }) -const TeamMembers = ({ classes }) => ( +export const TeamMembers = ({ classes }) => (
Members diff --git a/client/src/views/dashboard/components/DashEditor.js b/client/src/views/dashboard/components/DashEditor.js index 1f6aa4cae..095f22300 100644 --- a/client/src/views/dashboard/components/DashEditor.js +++ b/client/src/views/dashboard/components/DashEditor.js @@ -10,7 +10,7 @@ import CardMedia from '@material-ui/core/CardMedia' import CardActions from '@material-ui/core/CardActions' import Button from '@material-ui/core/Button' -import aaweb from '../../assets/AlgonetWebPlatform.jpg' +import aaweb from '../../../assets/AlgonetWebPlatform.jpg' const styles = theme => ({ aawebMedia: { diff --git a/client/src/views/dashboard/components/DashTeam.js b/client/src/views/dashboard/components/DashTeam.js index e56695511..e5be5398b 100644 --- a/client/src/views/dashboard/components/DashTeam.js +++ b/client/src/views/dashboard/components/DashTeam.js @@ -4,7 +4,7 @@ import { Query } from 'react-apollo' import Typography from '@material-ui/core/Typography' import Grid from '@material-ui/core/Grid' -import { DashTeamIteam } from './DashTeamIteam' +import { DashTeamIteam } from './DashTeamItem' export const DashTeam = () => ( diff --git a/client/src/views/dashboard/index.js b/client/src/views/dashboard/index.js index 3d39c1057..b6331118d 100644 --- a/client/src/views/dashboard/index.js +++ b/client/src/views/dashboard/index.js @@ -9,10 +9,10 @@ import Divider from '@material-ui/core/Divider' import { MainDrawerItems, SecondaryDrawerItems } from './components/DrawerLinks' -import { Overview } from 'Overview' -import { ManageTeams } from 'ManageTeams' -import { TeamMembers } from 'TeamMembers' -import { Settings } from 'Settings' +import { Overview } from './Overview' +import { ManageTeams } from './ManageTeams' +import { TeamMembers } from './TeamMembers' +import { Settings } from './Settings' const drawerWidth = 240 diff --git a/client/src/views/dashboard/settings.js b/client/src/views/dashboard/settings.js index 3ae32bfcc..a9ee58b58 100644 --- a/client/src/views/dashboard/settings.js +++ b/client/src/views/dashboard/settings.js @@ -12,7 +12,7 @@ const styles = theme => ({ } }) -const Settings = ({ classes }) => ( +export const Settings = ({ classes }) => (
Settings From 40c658023cc7eecda54609eaa23c90a94336da96 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Thu, 13 Sep 2018 16:33:47 -0700 Subject: [PATCH 04/19] Client: update named imports to default imports --- api/src/index.js | 25 +-- api/src/schema.graphql | 2 +- client/src/App.js | 2 +- client/src/auth/index.js | 2 +- .../src/graphql/teams/CreateTeamMutation.js | 4 +- client/src/graphql/teams/GetTeamQuery.js | 40 ---- .../src/graphql/teams/GetTeamsByOwnerQuery.js | 38 ++++ client/src/utils/js-helpers.js | 4 + client/src/views/dashboard/ManageTeams.js | 4 +- client/src/views/dashboard/Overview.js | 72 +++---- client/src/views/dashboard/TeamMembers.js | 2 +- .../views/dashboard/components/CreateTeam.js | 198 +++++++----------- .../dashboard/components/CreateTeamForm.js | 131 ++++++++++++ .../views/dashboard/components/DashEditor.js | 10 +- .../views/dashboard/components/DashTeam.js | 99 ++++++++- .../views/dashboard/components/DrawerLinks.js | 6 +- client/src/views/dashboard/index.js | 29 ++- 17 files changed, 419 insertions(+), 249 deletions(-) delete mode 100644 client/src/graphql/teams/GetTeamQuery.js create mode 100644 client/src/graphql/teams/GetTeamsByOwnerQuery.js create mode 100644 client/src/views/dashboard/components/CreateTeamForm.js diff --git a/api/src/index.js b/api/src/index.js index be92331cd..d81c1e1eb 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -83,7 +83,7 @@ const resolvers = { async teamByName(parent, { name }, ctx, info) { return ctx.db.query.team({ where: { name: name } }, `{ name }`) }, - async teamByOwner(parent, { ownerId }, ctx, info) { + async teamsByOwner(parent, { ownerId }, ctx, info) { return ctx.db.query.teamsConnection({where: { owner: { authId: ownerId }}}, `{ edges { @@ -91,27 +91,24 @@ const resolvers = { id name slug + owner + status { + status + reason + createdAt + } + createdAt profile { avatar description motto - } - owner { - authId - nickname - visible - profile { - avatar - } + updatedAt } members { role member { - nickname - visible - profile { - avatar - } + alias + authId } } } diff --git a/api/src/schema.graphql b/api/src/schema.graphql index 82bae531d..f63570229 100644 --- a/api/src/schema.graphql +++ b/api/src/schema.graphql @@ -10,7 +10,7 @@ type Query { teamDetails: [Team!]! @isAuthenticated teamByName(name: String!): Team teamById(teamId: String!): Team - teamByOwner(ownerId: String!): TeamConnection + teamsByOwner(ownerId: String!): TeamConnection owner: Member @isAuthenticated currentMember: Member @isAuthenticated member(authId: String!): Member @isAuthenticated diff --git a/client/src/App.js b/client/src/App.js index 60dddf69d..adf708aa3 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -151,7 +151,7 @@ class App extends Component { } /> (a || {})[b], object) !== undefined } diff --git a/client/src/views/dashboard/ManageTeams.js b/client/src/views/dashboard/ManageTeams.js index 432007a95..ecf65c9db 100644 --- a/client/src/views/dashboard/ManageTeams.js +++ b/client/src/views/dashboard/ManageTeams.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types' import Typography from '@material-ui/core/Typography' import { withStyles } from '@material-ui/core/styles' -import { TeamTable } from './components/TeamTable' +import TeamTable from './components/TeamTable' const styles = theme => ({ tableContainer: { @@ -12,7 +12,7 @@ const styles = theme => ({ } }) -export const ManageTeams = ({ classes }) => ( +const ManageTeams = ({ classes }) => (
Teams diff --git a/client/src/views/dashboard/Overview.js b/client/src/views/dashboard/Overview.js index 19f30450f..19d8a2bf9 100644 --- a/client/src/views/dashboard/Overview.js +++ b/client/src/views/dashboard/Overview.js @@ -1,20 +1,19 @@ -import React from 'react' +import React, { Component } from 'react' import PropTypes from 'prop-types' -import { graphql } from 'react-apollo' - import { withStyles } from '@material-ui/core/styles' import Grid from '@material-ui/core/Grid' import Card from '@material-ui/core/Card' import CardContent from '@material-ui/core/CardContent' -import { CreateTeamDialog } from './components/CreateTeam' -import { DashTeam } from './components/DashTeam' -import { DashEditor } from './components/DashEditor' - -import { CreateTeamMutation } from '../../graphql/teams/CreateTeamMutation' +import CreateTeam from './components/CreateTeam' +import DashTeam from './components/DashTeam' +import DashEditor from './components/DashEditor' const styles = theme => ({ + root: { + display: 'flex' + }, card: { display: 'flex', width: '100%' @@ -34,40 +33,37 @@ const styles = theme => ({ }, buttonRight: { justifyContent: 'flex-end' + }, + aawebMedia: { + width: '100%', + height: 320 } }) -export const Overview = ({ classes, createTeamMutation }) => ( - - - - -
- - - -
-
+export class Overview extends Component { + render () { + const { classes } = this.props + return ( + + + + +
+ + + +
+
+
+
+ +
-
- - -
-) - + ) + } +} Overview.propTypes = { - classes: PropTypes.object.isRequired, - createTeamMutation: PropTypes.object + classes: PropTypes.object.isRequired } -const OverviewWithMutation = graphql(CreateTeamMutation, { - name: 'createTeamMutation', - options: props => ({ - // Options are computed from `props` here. - }) -})(Overview) - -export default withStyles(styles)(OverviewWithMutation) +export default withStyles(styles)(Overview) diff --git a/client/src/views/dashboard/TeamMembers.js b/client/src/views/dashboard/TeamMembers.js index ab74d6f31..a22de3714 100644 --- a/client/src/views/dashboard/TeamMembers.js +++ b/client/src/views/dashboard/TeamMembers.js @@ -12,7 +12,7 @@ const styles = theme => ({ } }) -export const TeamMembers = ({ classes }) => ( +const TeamMembers = ({ classes }) => (
Members diff --git a/client/src/views/dashboard/components/CreateTeam.js b/client/src/views/dashboard/components/CreateTeam.js index 98e3aebc6..b01184b7d 100644 --- a/client/src/views/dashboard/components/CreateTeam.js +++ b/client/src/views/dashboard/components/CreateTeam.js @@ -1,131 +1,87 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { withRouter } from 'react-router-dom' -import Button from '@material-ui/core/Button' -import AddIcon from '@material-ui/icons/Add' -import TextField from '@material-ui/core/TextField' -import Dialog from '@material-ui/core/Dialog' -import DialogActions from '@material-ui/core/DialogActions' -import DialogContent from '@material-ui/core/DialogContent' -import DialogContentText from '@material-ui/core/DialogContentText' -import DialogTitle from '@material-ui/core/DialogTitle' +import React from 'react' +import { Mutation } from 'react-apollo' + import Typography from '@material-ui/core/Typography' import { getItem } from '../../../utils/local-storage' -export class CreateTeamDialog extends Component { - constructor (props) { - super(props) +import CREATE_TEAM from '../../../graphql/teams/CreateTeamMutation' +import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' - this.handleClickOpen = this.handleClickOpen.bind(this) - this.handleClose = this.handleClose.bind(this) - this.handlePost = this.handlePost.bind(this) - this.slugify = this.slugify.bind(this) - this.handleChange = this.handleChange.bind(this) +const CreateTeam = () => { + let input - this.state = { - open: false, - name: '' - } - } - - handleClickOpen () { - this.setState({ open: true }) - } - - handleClose () { - this.setState({ open: false }) - } - - handleChange (e) { - this.setState({ name: e.target.value }) - } - - render () { - console.log(this.props) - return ( -
- - - Subscribe - - Team Creation - Name your team! - - - - - - - -
- ) - } - - slugify (string) { - const a = 'àáäâãåèéëêìíïîòóöôùúüûñçßÿœæŕśńṕẃǵǹḿǘẍźḧ·/_,:;' - const b = 'aaaaaaeeeeiiiioooouuuuncsyoarsnpwgnmuxzh------' - const p = new RegExp(a.split('').join('|'), 'g') - - return string - .toString() - .toLowerCase() - .replace(/\s+/g, '-') // Replace spaces with - - .replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters - .replace(/&/g, '-and-') // Replace & with 'and' - .replace(/[^\w-]+/g, '') // Remove all non-word characters - .replace(/--+/g, '-') // Replace multiple - with single - - .replace(/^-+/, '') // Trim - from start of text - .replace(/-+$/, '') // Trim - from end of text - } - - async handlePost (e) { - e.preventDefault() - const { name } = this.state - const slug = this.slugify(name) - const currentUser = await getItem('user') - let authId = JSON.parse(currentUser) - authId = authId.sub - console.log('createPage cu:', JSON.parse(currentUser)) - await this.props.createTeamMutation({ - variables: { - name, - slug, - owner: authId - } - }) - this.setState({ open: false }) - } + return ( + { + const { teamsByOwner } = cache.readQuery({ query: GET_TEAMS_BY_OWNER }) + cache.writeQuery({ + query: GET_TEAMS_BY_OWNER, + data: { teamsByOwner: teamsByOwner.concat([createTeam]) } + }) + }} + > + {(createTeam, { loading, error, data }) => { + let errors + let loader + if (loading) { + loader = (Submitting team...) + } + if (error) { + errors = error.graphQLErrors.map(({ message }, i) => ( + {message} + )) + } + return ( +
+
{ + handleSubmit(e, createTeam, input) + }} + > + { + input = node + }} + /> + +
+ {loader} + {errors} +
+ ) + }} +
+ ) } -CreateTeamDialog.propTypes = { - classes: PropTypes.object.isRequired, - createTeamMutation: PropTypes.function +const handleSubmit = async (e, createTeam, input) => { + e.preventDefault() + const currentUser = await getItem('user') + let authId = JSON.parse(currentUser) + authId = authId.sub + const name = input.value + const slug = slugify(name) + await createTeam({ variables: { name, slug, owner: authId } }) + input.value = '' } -export default withRouter(CreateTeamDialog) +const slugify = string => { + const a = 'àáäâãåèéëêìíïîòóöôùúüûñçßÿœæŕśńṕẃǵǹḿǘẍźḧ·/_,:;' + const b = 'aaaaaaeeeeiiiioooouuuuncsyoarsnpwgnmuxzh------' + const p = new RegExp(a.split('').join('|'), 'g') + + return string + .toString() + .toLowerCase() + .replace(/\s+/g, '-') // Replace spaces with - + .replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters + .replace(/&/g, '-and-') // Replace & with 'and' + .replace(/[^\w-]+/g, '') // Remove all non-word characters + .replace(/--+/g, '-') // Replace multiple - with single - + .replace(/^-+/, '') // Trim - from start of text + .replace(/-+$/, '') // Trim - from end of text +} + +export default CreateTeam diff --git a/client/src/views/dashboard/components/CreateTeamForm.js b/client/src/views/dashboard/components/CreateTeamForm.js new file mode 100644 index 000000000..98e3aebc6 --- /dev/null +++ b/client/src/views/dashboard/components/CreateTeamForm.js @@ -0,0 +1,131 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import { withRouter } from 'react-router-dom' +import Button from '@material-ui/core/Button' +import AddIcon from '@material-ui/icons/Add' +import TextField from '@material-ui/core/TextField' +import Dialog from '@material-ui/core/Dialog' +import DialogActions from '@material-ui/core/DialogActions' +import DialogContent from '@material-ui/core/DialogContent' +import DialogContentText from '@material-ui/core/DialogContentText' +import DialogTitle from '@material-ui/core/DialogTitle' +import Typography from '@material-ui/core/Typography' + +import { getItem } from '../../../utils/local-storage' + +export class CreateTeamDialog extends Component { + constructor (props) { + super(props) + + this.handleClickOpen = this.handleClickOpen.bind(this) + this.handleClose = this.handleClose.bind(this) + this.handlePost = this.handlePost.bind(this) + this.slugify = this.slugify.bind(this) + this.handleChange = this.handleChange.bind(this) + + this.state = { + open: false, + name: '' + } + } + + handleClickOpen () { + this.setState({ open: true }) + } + + handleClose () { + this.setState({ open: false }) + } + + handleChange (e) { + this.setState({ name: e.target.value }) + } + + render () { + console.log(this.props) + return ( +
+ + + Subscribe + + Team Creation + Name your team! + + + + + + + +
+ ) + } + + slugify (string) { + const a = 'àáäâãåèéëêìíïîòóöôùúüûñçßÿœæŕśńṕẃǵǹḿǘẍźḧ·/_,:;' + const b = 'aaaaaaeeeeiiiioooouuuuncsyoarsnpwgnmuxzh------' + const p = new RegExp(a.split('').join('|'), 'g') + + return string + .toString() + .toLowerCase() + .replace(/\s+/g, '-') // Replace spaces with - + .replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters + .replace(/&/g, '-and-') // Replace & with 'and' + .replace(/[^\w-]+/g, '') // Remove all non-word characters + .replace(/--+/g, '-') // Replace multiple - with single - + .replace(/^-+/, '') // Trim - from start of text + .replace(/-+$/, '') // Trim - from end of text + } + + async handlePost (e) { + e.preventDefault() + const { name } = this.state + const slug = this.slugify(name) + const currentUser = await getItem('user') + let authId = JSON.parse(currentUser) + authId = authId.sub + console.log('createPage cu:', JSON.parse(currentUser)) + await this.props.createTeamMutation({ + variables: { + name, + slug, + owner: authId + } + }) + this.setState({ open: false }) + } +} + +CreateTeamDialog.propTypes = { + classes: PropTypes.object.isRequired, + createTeamMutation: PropTypes.function +} + +export default withRouter(CreateTeamDialog) diff --git a/client/src/views/dashboard/components/DashEditor.js b/client/src/views/dashboard/components/DashEditor.js index 095f22300..246a921f0 100644 --- a/client/src/views/dashboard/components/DashEditor.js +++ b/client/src/views/dashboard/components/DashEditor.js @@ -2,7 +2,6 @@ import React from 'react' import PropTypes from 'prop-types' import Typography from '@material-ui/core/Typography' -import { withStyles } from '@material-ui/core/styles' import Grid from '@material-ui/core/Grid' import Card from '@material-ui/core/Card' @@ -12,13 +11,6 @@ import Button from '@material-ui/core/Button' import aaweb from '../../../assets/AlgonetWebPlatform.jpg' -const styles = theme => ({ - aawebMedia: { - width: '100%', - height: 320 - } -}) - export const DashEditor = ({ classes }) => ( @@ -47,4 +39,4 @@ DashEditor.propTypes = { classes: PropTypes.object.isRequired } -export default withStyles(styles)(DashEditor) +export default DashEditor diff --git a/client/src/views/dashboard/components/DashTeam.js b/client/src/views/dashboard/components/DashTeam.js index e5be5398b..f46bb6e30 100644 --- a/client/src/views/dashboard/components/DashTeam.js +++ b/client/src/views/dashboard/components/DashTeam.js @@ -1,22 +1,105 @@ import React from 'react' +import PropTypes from 'prop-types' import { Query } from 'react-apollo' +import { withStateHandlers, lifecycle, compose } from 'recompose' import Typography from '@material-ui/core/Typography' import Grid from '@material-ui/core/Grid' -import { DashTeamIteam } from './DashTeamItem' +import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' -export const DashTeam = () => ( - +import DashTeamItem from './DashTeamItem' + +import { isDefined, isString } from '../../../utils/js-helpers' +import { getItem } from '../../../utils/local-storage' + +export const DashTeam = ({ user = null }) => { + console.log('DashTeam 1: ', user) + let owner + let loader + let authId = null + if (user !== null && isString(user)) { + owner = JSON.parse(user) + if (isDefined(owner.sub)) authId = owner.sub + } else { + loader = (Loading...) + } + + console.log('DashTeam 2: ', owner, authId) + if (authId === null) { + return ( + + + Teams + + Loading... + + ) + } + return ( Teams - - - + + {({ loading, error, data }) => { + console.log('GET_TEAMS_BY_OWNER: ', loading, error, data) + let errors + let queryLoader + if (error) { + errors = error.graphQLErrors.map(({ message }, i) => ( + {message} + )) + } + if (!loading) { + return ( + + {!loading && data.teamsByOwner.edges.map(team => ( + + ))} + {queryLoader} + {errors} + {loader} + + ) + } else { + return ( + + + Loading... + + {queryLoader} + {errors} + + ) + } + }} + - + ) +} + +DashTeam.propTypes = { + user: PropTypes.any +} + +const getUserOnMount = lifecycle({ + componentDidMount () { + getItem('user').then(user => { + this.setState({ user }) + }) // Set user to state + } +}) + +const mapStateToProps = withStateHandlers( + () => ({ user: null }), { + user: ({ user }) => () => ({ user }) + } ) -export default DashTeam +const DashTeamAuthId = compose( + mapStateToProps, + getUserOnMount +)(DashTeam) + +export default DashTeamAuthId diff --git a/client/src/views/dashboard/components/DrawerLinks.js b/client/src/views/dashboard/components/DrawerLinks.js index b2a178697..66d9e7d51 100644 --- a/client/src/views/dashboard/components/DrawerLinks.js +++ b/client/src/views/dashboard/components/DrawerLinks.js @@ -13,8 +13,8 @@ import SentimentSatisfiedAltIcon from '@material-ui/icons/SentimentSatisfiedAlt' import AndroidIcon from '@material-ui/icons/Android' const DashboardLink = props => -const TeamsLink = props => -const MembersLink = props => +const TeamsLink = props => +const MembersLink = props => const SettingsLink = props => export const MainDrawerItems = ( @@ -35,7 +35,7 @@ export const MainDrawerItems = ( - + diff --git a/client/src/views/dashboard/index.js b/client/src/views/dashboard/index.js index b6331118d..f62ac733a 100644 --- a/client/src/views/dashboard/index.js +++ b/client/src/views/dashboard/index.js @@ -1,6 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' import { Route, Switch } from 'react-router-dom' +import { lifecycle } from 'recompose' import { withStyles } from '@material-ui/core/styles' import Drawer from '@material-ui/core/Drawer' @@ -9,10 +10,10 @@ import Divider from '@material-ui/core/Divider' import { MainDrawerItems, SecondaryDrawerItems } from './components/DrawerLinks' -import { Overview } from './Overview' -import { ManageTeams } from './ManageTeams' -import { TeamMembers } from './TeamMembers' -import { Settings } from './Settings' +import Overview from './Overview' +import ManageTeams from './ManageTeams' +import TeamMembers from './TeamMembers' +import Settings from './Settings' const drawerWidth = 240 @@ -45,7 +46,7 @@ const styles = theme => ({ appBarSpacer: theme.mixins.toolbar }) -const Dashboard = ({ classes, createTeamMutation, ...props }) => ( +const Dashboard = ({ classes }) => (
(
- + @@ -71,8 +72,18 @@ const Dashboard = ({ classes, createTeamMutation, ...props }) => ( ) Dashboard.propTypes = { - classes: PropTypes.object.isRequired, - createTeamMutation: PropTypes.function + classes: PropTypes.object.isRequired } -export default withStyles(styles)(Dashboard) +const DashboardCheckSession = lifecycle({ + async componentDidMount () { + try { + const authenticated = await this.props.auth.isAuthenticated() + console.log('DashboardCheckSession res: ', authenticated) + } catch (err) { + console.log('DashboardCheckSession err: ', err) + } + } +})(Dashboard) + +export default withStyles(styles)(DashboardCheckSession) From 57dc13f574b2a98ee1d469ddc76b640a155cac9a Mon Sep 17 00:00:00 2001 From: Barry Low Date: Thu, 13 Sep 2018 21:42:02 -0700 Subject: [PATCH 05/19] Client: create DashCreateTeamWrapper --- api/src/index.js | 22 ++++----- client/src/auth/index.js | 32 ++++++------ client/src/graphql/teams/GetAllTeamsQuery.js | 22 ++++----- client/src/graphql/teams/Teams.js | 36 ++++++++++++++ client/src/utils/graphql-errors.js | 13 +++++ client/src/views/dashboard/Overview.js | 15 +----- .../dashboard/components/CreateTeamWrapper.js | 49 +++++++++++++++++++ .../views/dashboard/components/DashTeam.js | 48 +++++++++++------- 8 files changed, 167 insertions(+), 70 deletions(-) create mode 100644 client/src/graphql/teams/Teams.js create mode 100644 client/src/utils/graphql-errors.js create mode 100644 client/src/views/dashboard/components/CreateTeamWrapper.js diff --git a/api/src/index.js b/api/src/index.js index d81c1e1eb..a6598ea9b 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -51,26 +51,24 @@ const resolvers = { id name slug + owner + status { + status + reason + createdAt + } + createdAt profile { avatar description motto - } - owner { - nickname - visible - profile { - avatar - } + updatedAt } members { role member { - nickname - visible - profile { - avatar - } + alias + authId } } } diff --git a/client/src/auth/index.js b/client/src/auth/index.js index 2196c4f38..05ea56a26 100644 --- a/client/src/auth/index.js +++ b/client/src/auth/index.js @@ -102,7 +102,11 @@ class Auth { this.signinOrCreateAccount({ ...data }) this.cb(data) console.log(authResult.idTokenPayload) - setItem('user', JSON.stringify(authResult.idTokenPayload)) + const user = { + authID: authResult.idTokenPayload.sub, + alias: authResult.idTokenPayload.nickname + } + setItem('user', JSON.stringify(user)) if (window.location.href.includes(`callback`)) { // window.location.href = '/dashboard' } @@ -126,11 +130,13 @@ class Auth { }) console.log('signinOrCreateAccount auth: ', await data) - setItem('user', JSON.stringify(data.data.authenticate)) + const user = { + authID: data.data.authenticate.authId, + alias: data.data.authenticate.authId.alias + } + setItem('user', JSON.stringify(user)) if (window.location.href.includes(`callback`)) { window.location.href = '/dashboard' - } else { - window.location.reload() } return data } catch (err) { @@ -157,10 +163,11 @@ class Auth { async isAuthenticated () { // check session and run Auth0 SS0 const getUser = await getItem('user') + const getExpires = await getItem('expires_at') let user = JSON.parse(getUser) - if (validObject(user, 'exp') && new Date().getTime() < user.exp * 1000) { - console.log('handleAuth.user exp: ', user, window.location.href) + if (new Date().getTime() < getExpires * 1000) { + console.log('handleAuth.user exp: ', user, getExpires, window.location.href) return user } @@ -168,7 +175,11 @@ class Auth { const checkSSO = await this.checkSession() .then(result => { console.log('handleAuth.checksessions: ', result) - setItem('user', result.idTokenPayload.sub) + const user = { + authID: result.idTokenPayload.sub, + alias: result.idTokenPayload.nickname + } + setItem('user', JSON.stringify(user)) // user confirmed, log into client this.setSession(result) return result.idTokenPayload @@ -180,13 +191,6 @@ class Auth { } return err }) - if ( - (window.location.href.includes(`manage`) || - window.location.href.includes(`profile`)) && - !user - ) { - window.location.href = '/' - } if (/manage|profile|create|dashboard/.test(window.location.href) && !user) { this.login() diff --git a/client/src/graphql/teams/GetAllTeamsQuery.js b/client/src/graphql/teams/GetAllTeamsQuery.js index 12acb8702..55902f4c8 100644 --- a/client/src/graphql/teams/GetAllTeamsQuery.js +++ b/client/src/graphql/teams/GetAllTeamsQuery.js @@ -9,26 +9,24 @@ export const GetAllTeamsQuery = gql` id name slug + owner + status { + status + reason + createdAt + } + createdAt profile { avatar description motto - } - owner { - nickname - visible - profile { - avatar - } + updatedAt } members { role member { - nickname - visible - profile { - avatar - } + alias + authId } } } diff --git a/client/src/graphql/teams/Teams.js b/client/src/graphql/teams/Teams.js new file mode 100644 index 000000000..23e54fcc3 --- /dev/null +++ b/client/src/graphql/teams/Teams.js @@ -0,0 +1,36 @@ +/* eslint-disable no-unused-vars */ +import gql from 'graphql-tag' + +export const TEAMS_FRAGMENT = gql` + fragment TeamsRespons on teamsConnection { + edges { + node { + id + name + slug + owner + status { + status + reason + createdAt + } + createdAt + profile { + avatar + description + motto + updatedAt + } + members { + role + member { + alias + authId + } + } + } + } + } +` + +export default TEAMS_FRAGMENT diff --git a/client/src/utils/graphql-errors.js b/client/src/utils/graphql-errors.js new file mode 100644 index 000000000..3df684a1d --- /dev/null +++ b/client/src/utils/graphql-errors.js @@ -0,0 +1,13 @@ +const ErrorResponse = { + 'unique constraint': 'Sorry, already taken! Please create a unique ' +} + +export const checkGraphQLError = (error) => { + console.log('checkGraphQLError ', ErrorResponse) + if (error.search(/unique constraint/)) { + const field = error.substring(error.indexOf('=') + 1) + console.log('unique constraint', field.replace(/ +/g, '')) + } +} + +export default checkGraphQLError diff --git a/client/src/views/dashboard/Overview.js b/client/src/views/dashboard/Overview.js index 19d8a2bf9..c79b2eec9 100644 --- a/client/src/views/dashboard/Overview.js +++ b/client/src/views/dashboard/Overview.js @@ -3,10 +3,7 @@ import PropTypes from 'prop-types' import { withStyles } from '@material-ui/core/styles' import Grid from '@material-ui/core/Grid' -import Card from '@material-ui/core/Card' -import CardContent from '@material-ui/core/CardContent' -import CreateTeam from './components/CreateTeam' import DashTeam from './components/DashTeam' import DashEditor from './components/DashEditor' @@ -45,23 +42,13 @@ export class Overview extends Component { const { classes } = this.props return ( - - - -
- - - -
-
-
-
) } } + Overview.propTypes = { classes: PropTypes.object.isRequired } diff --git a/client/src/views/dashboard/components/CreateTeamWrapper.js b/client/src/views/dashboard/components/CreateTeamWrapper.js new file mode 100644 index 000000000..c4a44b312 --- /dev/null +++ b/client/src/views/dashboard/components/CreateTeamWrapper.js @@ -0,0 +1,49 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { withStyles } from '@material-ui/core/styles' + +import Grid from '@material-ui/core/Grid' +import Card from '@material-ui/core/Card' +import CardContent from '@material-ui/core/CardContent' + +import CreateTeam from './CreateTeam' + +const styles = theme => ({ + card: { + display: 'flex', + width: '100%' + }, + cardDetails: { + display: 'flex', + flex: 1 + }, + cardContent: { + flex: 1 + }, + cardMedia: { + flex: 1, + width: 160, + height: 160, + justifyContent: 'flex-start' + } +}) + +const CreateTeamWrapper = ({ classes }) => ( + + + +
+ + + +
+
+
+
+) + +CreateTeamWrapper.propTypes = { + classes: PropTypes.object.isRequired +} + +export default withStyles(styles)(CreateTeamWrapper) diff --git a/client/src/views/dashboard/components/DashTeam.js b/client/src/views/dashboard/components/DashTeam.js index f46bb6e30..39aef9fad 100644 --- a/client/src/views/dashboard/components/DashTeam.js +++ b/client/src/views/dashboard/components/DashTeam.js @@ -5,27 +5,29 @@ import { withStateHandlers, lifecycle, compose } from 'recompose' import Typography from '@material-ui/core/Typography' import Grid from '@material-ui/core/Grid' +import Card from '@material-ui/core/Card' +import CardContent from '@material-ui/core/CardContent' import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' import DashTeamItem from './DashTeamItem' +import CreateTeamWrapper from './CreateTeamWrapper' +import { checkGraphQLError } from '../../../utils/graphql-errors' import { isDefined, isString } from '../../../utils/js-helpers' import { getItem } from '../../../utils/local-storage' -export const DashTeam = ({ user = null }) => { - console.log('DashTeam 1: ', user) +export const DashTeam = ({ classes, user = null }) => { let owner let loader let authId = null if (user !== null && isString(user)) { owner = JSON.parse(user) - if (isDefined(owner.sub)) authId = owner.sub + if (isDefined(owner.authId)) authId = owner.authId } else { loader = (Loading...) } - console.log('DashTeam 2: ', owner, authId) if (authId === null) { return ( @@ -47,21 +49,30 @@ export const DashTeam = ({ user = null }) => { let errors let queryLoader if (error) { - errors = error.graphQLErrors.map(({ message }, i) => ( - {message} - )) + errors = error.graphQLErrors.map(({ message }, i) => { + const displayMessage = checkGraphQLError(message) + return ( + {displayMessage} + ) + }) } if (!loading) { - return ( - - {!loading && data.teamsByOwner.edges.map(team => ( - - ))} - {queryLoader} - {errors} - {loader} - - ) + if (data.teamsByOwner.edges.length > 0) { + return ( + + {!loading && data.teamsByOwner.edges.map(team => ( + + ))} + {queryLoader} + {errors} + {loader} + + ) + } else { + return ( + + ) + } } else { return ( @@ -80,7 +91,8 @@ export const DashTeam = ({ user = null }) => { } DashTeam.propTypes = { - user: PropTypes.any + user: PropTypes.any, + classes: PropTypes.object.isRequired } const getUserOnMount = lifecycle({ From 432a5c076f32fdde91fc3e5cab0c9b770d1a0988 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Thu, 13 Sep 2018 23:55:57 -0700 Subject: [PATCH 06/19] Server: Fix Mutation authorization --- api/src/auth/authDirectives.js | 4 +- api/src/auth/middleware/getMember.js | 4 +- api/src/auth/middleware/jwt.js | 2 +- api/src/index.js | 74 +++++++++---------- api/src/schema.graphql | 2 +- client/src/auth/index.js | 8 +- .../src/graphql/teams/GetTeamsByOwnerQuery.js | 46 ++++++------ .../views/dashboard/components/CreateTeam.js | 22 +++--- .../views/dashboard/components/DashTeam.js | 19 ++--- 9 files changed, 88 insertions(+), 93 deletions(-) diff --git a/api/src/auth/authDirectives.js b/api/src/auth/authDirectives.js index f098fa4ec..471be4692 100644 --- a/api/src/auth/authDirectives.js +++ b/api/src/auth/authDirectives.js @@ -1,7 +1,7 @@ const _get = require('lodash.get') const { validateIdToken } = require('./validateIdToken') -const memberLocationOnContext = 'request.member' +const memberLocationOnContext = 'request.user' const bearerAccessToken = 'request.headers.authorization' const ctxMember = ctx => _get(ctx, memberLocationOnContext) @@ -29,7 +29,7 @@ const isLoggedIn = async ctx => { let member = ctxMember(ctx, memberLocationOnContext) let token = ctxToken(ctx, bearerAccessToken) let memberToken - console.log('isLoggedIn: ', member, token) + console.log('isLoggedIn: ', ctx, member, token) if (!member && token) { let scheme, credentials const tokenParts = token.split(' ') diff --git a/api/src/auth/middleware/getMember.js b/api/src/auth/middleware/getMember.js index 7b2642c50..7d19b2d6c 100644 --- a/api/src/auth/middleware/getMember.js +++ b/api/src/auth/middleware/getMember.js @@ -1,9 +1,9 @@ const getMember = async (req, res, next, db) => { if (!req.user) return next() const member = await db.query.member({ - where: { auth0id: req.user.sub } + where: { authId: req.user.sub } }) - req.user = { token: req.user, ...member } + req.user = { user: member } next() } diff --git a/api/src/auth/middleware/jwt.js b/api/src/auth/middleware/jwt.js index 39e8ecbe3..0ff677156 100644 --- a/api/src/auth/middleware/jwt.js +++ b/api/src/auth/middleware/jwt.js @@ -21,4 +21,4 @@ const checkJwt = jwt({ algorithms: [`RS256`] }) -module.exports = { checkJwt } +module.exports = checkJwt diff --git a/api/src/index.js b/api/src/index.js index a6598ea9b..9782f24b9 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -7,7 +7,8 @@ const { } = require('prisma-binding') const { makeExecutableSchema } = require('graphql-tools') const { importSchema } = require('graphql-import') -const { checkJwt } = require('./auth/middleware/jwt') + +const checkJwt = require('./auth/middleware/jwt') const { getMember } = require('./auth/middleware/getMember') const { validateIdToken } = require('./auth/validateIdToken') const { directiveResolvers } = require('./auth/authDirectives') @@ -30,7 +31,7 @@ const createMember = async function (ctx, info, idToken) { return member } -const ctxMember = ctx => ctx.request.member +const ctxMember = ctx => ctx.request.user const resolvers = { Query: { @@ -82,35 +83,32 @@ const resolvers = { return ctx.db.query.team({ where: { name: name } }, `{ name }`) }, async teamsByOwner(parent, { ownerId }, ctx, info) { - return ctx.db.query.teamsConnection({where: { owner: { authId: ownerId }}}, + console.log('teamsByOwner: ', ctx.user) + return ctx.db.query.teams({where: { owner: ownerId }}, `{ - edges { - node { - id - name - slug - owner - status { - status - reason - createdAt - } + id + name + slug + owner + status { + status + reason createdAt - profile { - avatar - description - motto - updatedAt - } - members { - role - member { - alias - authId - } + } + createdAt + profile { + avatar + description + motto + updatedAt + } + members { + role + member { + alias + authId } } - } }`) }, async owner(parent, args, ctx, info) { @@ -189,25 +187,27 @@ const schema = makeExecutableSchema({ const server = new GraphQLServer({ schema, context: req => ({ - ...req, - db + token: req.headers, + user: req.user, + db, + ...req }), }) server.express.use( server.options.endpoint, checkJwt, - (err, req, res, next) => { - console.log('checkJwt: ', err, req.user) - if (err) return res.status(401).send(err.message) - next() + function (err, req, res, next) { + console.log('checkJwt: ', err, req) + if (err) { + return res.status(201).send(err.message) + } else { + next() + } } ) -server.express.post(server.options.endpoint, (err, req, res, done) => { - console.log('getMember: ', err, req.user) - getMember(req, res, done, db) -}) +server.express.post(server.options.endpoint, (req, res, done) => getUser(req, res, done, db)) const whitelist = [ 'http://localhost:3000', diff --git a/api/src/schema.graphql b/api/src/schema.graphql index f63570229..9e315174c 100644 --- a/api/src/schema.graphql +++ b/api/src/schema.graphql @@ -10,7 +10,7 @@ type Query { teamDetails: [Team!]! @isAuthenticated teamByName(name: String!): Team teamById(teamId: String!): Team - teamsByOwner(ownerId: String!): TeamConnection + teamsByOwner(ownerId: String!): [Team!]! @isAuthenticated owner: Member @isAuthenticated currentMember: Member @isAuthenticated member(authId: String!): Member @isAuthenticated diff --git a/client/src/auth/index.js b/client/src/auth/index.js index 05ea56a26..b1e788a86 100644 --- a/client/src/auth/index.js +++ b/client/src/auth/index.js @@ -103,7 +103,7 @@ class Auth { this.cb(data) console.log(authResult.idTokenPayload) const user = { - authID: authResult.idTokenPayload.sub, + authId: authResult.idTokenPayload.sub, alias: authResult.idTokenPayload.nickname } setItem('user', JSON.stringify(user)) @@ -131,8 +131,8 @@ class Auth { console.log('signinOrCreateAccount auth: ', await data) const user = { - authID: data.data.authenticate.authId, - alias: data.data.authenticate.authId.alias + authId: data.data.authenticate.authId, + alias: data.data.authenticate.alias } setItem('user', JSON.stringify(user)) if (window.location.href.includes(`callback`)) { @@ -176,7 +176,7 @@ class Auth { .then(result => { console.log('handleAuth.checksessions: ', result) const user = { - authID: result.idTokenPayload.sub, + authId: result.idTokenPayload.sub, alias: result.idTokenPayload.nickname } setItem('user', JSON.stringify(user)) diff --git a/client/src/graphql/teams/GetTeamsByOwnerQuery.js b/client/src/graphql/teams/GetTeamsByOwnerQuery.js index f5b2f327a..d2f60c882 100644 --- a/client/src/graphql/teams/GetTeamsByOwnerQuery.js +++ b/client/src/graphql/teams/GetTeamsByOwnerQuery.js @@ -4,31 +4,27 @@ import gql from 'graphql-tag' export const GET_TEAMS_BY_OWNER = gql` query teamsByOwnerQuery($authId: String!) { teamsByOwner(ownerId: $authId) { - edges { - node { - id - name - slug - owner - status { - status - reason - createdAt - } - createdAt - profile { - avatar - description - motto - updatedAt - } - members { - role - member { - alias - authId - } - } + id + name + slug + owner + status { + status + reason + createdAt + } + createdAt + profile { + avatar + description + motto + updatedAt + } + members { + role + member { + alias + authId } } } diff --git a/client/src/views/dashboard/components/CreateTeam.js b/client/src/views/dashboard/components/CreateTeam.js index b01184b7d..c4d884672 100644 --- a/client/src/views/dashboard/components/CreateTeam.js +++ b/client/src/views/dashboard/components/CreateTeam.js @@ -4,6 +4,7 @@ import { Mutation } from 'react-apollo' import Typography from '@material-ui/core/Typography' import { getItem } from '../../../utils/local-storage' +import { checkGraphQLError } from '../../../utils/graphql-errors' import CREATE_TEAM from '../../../graphql/teams/CreateTeamMutation' import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' @@ -15,11 +16,10 @@ const CreateTeam = () => { { - const { teamsByOwner } = cache.readQuery({ query: GET_TEAMS_BY_OWNER }) - cache.writeQuery({ - query: GET_TEAMS_BY_OWNER, - data: { teamsByOwner: teamsByOwner.concat([createTeam]) } - }) + const data = cache.readQuery({ query: GET_TEAMS_BY_OWNER }) + console.log('Mutation cache update: ', createTeam, data) + data.getTeamsByOwner.push(createTeam) + cache.writeQuery({ query: GET_TEAMS_BY_OWNER, data }) }} > {(createTeam, { loading, error, data }) => { @@ -29,9 +29,13 @@ const CreateTeam = () => { loader = (Submitting team...) } if (error) { - errors = error.graphQLErrors.map(({ message }, i) => ( - {message} - )) + errors = error.graphQLErrors.map(({ message }, i) => { + const displayMessage = checkGraphQLError(message) + console.log('createTeam error:', displayMessage) + return ( + {message} + ) + }) } return (
@@ -60,7 +64,7 @@ const handleSubmit = async (e, createTeam, input) => { e.preventDefault() const currentUser = await getItem('user') let authId = JSON.parse(currentUser) - authId = authId.sub + authId = authId.authId const name = input.value const slug = slugify(name) await createTeam({ variables: { name, slug, owner: authId } }) diff --git a/client/src/views/dashboard/components/DashTeam.js b/client/src/views/dashboard/components/DashTeam.js index 39aef9fad..8be96d370 100644 --- a/client/src/views/dashboard/components/DashTeam.js +++ b/client/src/views/dashboard/components/DashTeam.js @@ -5,15 +5,12 @@ import { withStateHandlers, lifecycle, compose } from 'recompose' import Typography from '@material-ui/core/Typography' import Grid from '@material-ui/core/Grid' -import Card from '@material-ui/core/Card' -import CardContent from '@material-ui/core/CardContent' import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' import DashTeamItem from './DashTeamItem' import CreateTeamWrapper from './CreateTeamWrapper' -import { checkGraphQLError } from '../../../utils/graphql-errors' import { isDefined, isString } from '../../../utils/js-helpers' import { getItem } from '../../../utils/local-storage' @@ -21,12 +18,14 @@ export const DashTeam = ({ classes, user = null }) => { let owner let loader let authId = null + console.log('DashTeam: ', user) if (user !== null && isString(user)) { owner = JSON.parse(user) if (isDefined(owner.authId)) authId = owner.authId } else { loader = (Loading...) } + console.log('DashTeam 2: ', owner, authId) if (authId === null) { return ( @@ -43,6 +42,7 @@ export const DashTeam = ({ classes, user = null }) => { Teams + {({ loading, error, data }) => { console.log('GET_TEAMS_BY_OWNER: ', loading, error, data) @@ -50,17 +50,16 @@ export const DashTeam = ({ classes, user = null }) => { let queryLoader if (error) { errors = error.graphQLErrors.map(({ message }, i) => { - const displayMessage = checkGraphQLError(message) return ( - {displayMessage} + {message} ) }) } - if (!loading) { - if (data.teamsByOwner.edges.length > 0) { + if (!loading && !error) { + if (data.teamsByOwner.length > 0) { return ( - {!loading && data.teamsByOwner.edges.map(team => ( + {!loading && data.teamsByOwner.map(team => ( ))} {queryLoader} @@ -68,10 +67,6 @@ export const DashTeam = ({ classes, user = null }) => { {loader} ) - } else { - return ( - - ) } } else { return ( From 3735f85c2e449613f6a5f3b89b77608fc4e3b100 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Fri, 14 Sep 2018 01:14:24 -0700 Subject: [PATCH 07/19] Client: Teams page basic --- api/package-lock.json | 31 +++-- api/package.json | 1 + api/src/graphql/TeamsFragment.js | 29 +++++ api/src/index.js | 37 +----- client/src/App.js | 2 + client/src/auth/index.js | 7 +- client/src/graphql/teams/GetAllTeamsQuery.js | 4 +- client/src/graphql/teams/Teams.js | 48 ++++---- client/src/utils/graphql-errors.js | 2 +- .../views/dashboard/components/CreateTeam.js | 6 +- .../views/dashboard/components/DashTeam.js | 21 ++-- .../dashboard/components/DashTeamItem.js | 9 +- .../src/views/teams/components/TeamsItem.js | 111 ++++++++++++++++++ .../src/views/teams/components/TeamsList.js | 61 ++++++++++ client/src/views/teams/index.js | 12 +- 15 files changed, 286 insertions(+), 95 deletions(-) create mode 100644 api/src/graphql/TeamsFragment.js create mode 100644 client/src/views/teams/components/TeamsItem.js create mode 100644 client/src/views/teams/components/TeamsList.js diff --git a/api/package-lock.json b/api/package-lock.json index d43af47d4..81ed969ea 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -568,7 +568,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -614,7 +614,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -923,7 +923,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -1462,7 +1462,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -1640,7 +1640,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -4084,6 +4084,11 @@ "iterall": "^1.2.1" } }, + "graphql-tag": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.9.2.tgz", + "integrity": "sha512-qnNmof9pAqj/LUzs3lStP0Gw1qhdVCUS7Ab7+SUB6KD5aX1uqxWQRwMnOGTkhKuLvLNIs1TvNz+iS9kUGl1MhA==" + }, "graphql-tools": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-3.1.1.tgz", @@ -4997,7 +5002,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -5366,7 +5371,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -6693,7 +6698,7 @@ }, "graphql-import": { "version": "0.4.5", - "resolved": "http://registry.npmjs.org/graphql-import/-/graphql-import-0.4.5.tgz", + "resolved": "https://registry.npmjs.org/graphql-import/-/graphql-import-0.4.5.tgz", "integrity": "sha512-G/+I08Qp6/QGTb9qapknCm3yPHV0ZL7wbaalWFpxsfR8ZhZoTBe//LsbsCKlbALQpcMegchpJhpTSKiJjhaVqQ==", "dev": true, "requires": { @@ -7590,7 +7595,7 @@ "dependencies": { "commander": { "version": "2.8.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", "dev": true, "requires": { @@ -8178,7 +8183,7 @@ }, "table": { "version": "4.0.3", - "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", "dev": true, "requires": { @@ -8239,7 +8244,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -8504,7 +8509,7 @@ }, "buffer": { "version": "3.6.0", - "resolved": "http://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", "dev": true, "requires": { @@ -9087,7 +9092,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { diff --git a/api/package.json b/api/package.json index 8bc857126..784b66264 100644 --- a/api/package.json +++ b/api/package.json @@ -11,6 +11,7 @@ "dotenv": "^6.0.0", "express-jwt": "^5.3.1", "graphql-import": "^0.6.0", + "graphql-tag": "^2.9.2", "graphql-tools": "3.1.1", "graphql-yoga": "^1.16.1", "jsonwebtoken": "^8.3.0", diff --git a/api/src/graphql/TeamsFragment.js b/api/src/graphql/TeamsFragment.js new file mode 100644 index 000000000..e75ce8382 --- /dev/null +++ b/api/src/graphql/TeamsFragment.js @@ -0,0 +1,29 @@ +const gql = require('graphql-tag') + +const TEAMS_FRAGMENT = gql`{ + id + name + slug + owner + status { + status + reason + createdAt + } + createdAt + profile { + avatar + description + motto + updatedAt + } + members { + role + member { + alias + authId + } + } +}` + +module.exports = TEAMS_FRAGMENT diff --git a/api/src/index.js b/api/src/index.js index 9782f24b9..0386ba61b 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -13,6 +13,8 @@ const { getMember } = require('./auth/middleware/getMember') const { validateIdToken } = require('./auth/validateIdToken') const { directiveResolvers } = require('./auth/authDirectives') +const TEAMS_FRAGMENT = require('./graphql/TeamsFragment') + const createMember = async function (ctx, info, idToken) { console.log('createMember', idToken) const member = await ctx.db.mutation.upsertMember({ @@ -84,32 +86,7 @@ const resolvers = { }, async teamsByOwner(parent, { ownerId }, ctx, info) { console.log('teamsByOwner: ', ctx.user) - return ctx.db.query.teams({where: { owner: ownerId }}, - `{ - id - name - slug - owner - status { - status - reason - createdAt - } - createdAt - profile { - avatar - description - motto - updatedAt - } - members { - role - member { - alias - authId - } - } - }`) + return ctx.db.query.teams({where: { owner: ownerId }}, TEAMS_FRAGMENT) }, async owner(parent, args, ctx, info) { console.log('resolver.query.owner ctx: ', ctxMember(ctx)) @@ -145,13 +122,7 @@ const resolvers = { return member }, async createTeam(parent, { name, slug, owner }, ctx, info) { - return ctx.db.mutation.createTeam({ - data: { - name: name, - slug: slug, - owner: owner - } - }, info) + return ctx.db.mutation.createTeam({ data: { name: name, slug: slug, owner: owner, members: { create: { member:{ connect:{ authId: owner} }, role: 'OWNER' } } } }, TEAMS_FRAGMENT) .catch((err) => { console.log('createTeam error: ', err) return err diff --git a/client/src/App.js b/client/src/App.js index adf708aa3..e2f28ac3c 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -21,6 +21,7 @@ import { Callback, Home, Dashboard, + Teams, theme, globalStyles } from './views' @@ -148,6 +149,7 @@ class App extends Component { + { +export const checkGraphQLError = error => { console.log('checkGraphQLError ', ErrorResponse) if (error.search(/unique constraint/)) { const field = error.substring(error.indexOf('=') + 1) diff --git a/client/src/views/dashboard/components/CreateTeam.js b/client/src/views/dashboard/components/CreateTeam.js index c4d884672..90cac23f7 100644 --- a/client/src/views/dashboard/components/CreateTeam.js +++ b/client/src/views/dashboard/components/CreateTeam.js @@ -26,14 +26,16 @@ const CreateTeam = () => { let errors let loader if (loading) { - loader = (Submitting team...) + loader = Submitting team... } if (error) { errors = error.graphQLErrors.map(({ message }, i) => { const displayMessage = checkGraphQLError(message) console.log('createTeam error:', displayMessage) return ( - {message} + + {message} + ) }) } diff --git a/client/src/views/dashboard/components/DashTeam.js b/client/src/views/dashboard/components/DashTeam.js index 8be96d370..d8b2df1ce 100644 --- a/client/src/views/dashboard/components/DashTeam.js +++ b/client/src/views/dashboard/components/DashTeam.js @@ -23,7 +23,7 @@ export const DashTeam = ({ classes, user = null }) => { owner = JSON.parse(user) if (isDefined(owner.authId)) authId = owner.authId } else { - loader = (Loading...) + loader = Loading... } console.log('DashTeam 2: ', owner, authId) @@ -51,7 +51,9 @@ export const DashTeam = ({ classes, user = null }) => { if (error) { errors = error.graphQLErrors.map(({ message }, i) => { return ( - {message} + + {message} + ) }) } @@ -59,9 +61,10 @@ export const DashTeam = ({ classes, user = null }) => { if (data.teamsByOwner.length > 0) { return ( - {!loading && data.teamsByOwner.map(team => ( - - ))} + {!loading && + data.teamsByOwner.map(team => ( + + ))} {queryLoader} {errors} {loader} @@ -98,11 +101,9 @@ const getUserOnMount = lifecycle({ } }) -const mapStateToProps = withStateHandlers( - () => ({ user: null }), { - user: ({ user }) => () => ({ user }) - } -) +const mapStateToProps = withStateHandlers(() => ({ user: null }), { + user: ({ user }) => () => ({ user }) +}) const DashTeamAuthId = compose( mapStateToProps, diff --git a/client/src/views/dashboard/components/DashTeamItem.js b/client/src/views/dashboard/components/DashTeamItem.js index cdf585c8f..1de33a7a4 100644 --- a/client/src/views/dashboard/components/DashTeamItem.js +++ b/client/src/views/dashboard/components/DashTeamItem.js @@ -34,7 +34,7 @@ const styles = theme => ({ } }) -export const DashTeamItem = ({ classes }) => ( +export const DashTeamItem = ({ classes, team }) => (
@@ -44,9 +44,9 @@ export const DashTeamItem = ({ classes }) => ( title='Image title' /> - Goodester + {team.name} - 09.15.2018 + {team.createdAt} Members:6 @@ -66,7 +66,8 @@ export const DashTeamItem = ({ classes }) => ( ) DashTeamItem.propTypes = { - classes: PropTypes.object.isRequired + classes: PropTypes.object.isRequired, + team: PropTypes.object.isRequired } export default withStyles(styles)(DashTeamItem) diff --git a/client/src/views/teams/components/TeamsItem.js b/client/src/views/teams/components/TeamsItem.js new file mode 100644 index 000000000..16d833c32 --- /dev/null +++ b/client/src/views/teams/components/TeamsItem.js @@ -0,0 +1,111 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import Typography from '@material-ui/core/Typography' +import { withStyles } from '@material-ui/core/styles' + +import Grid from '@material-ui/core/Grid' +import Paper from '@material-ui/core/Paper' +import Button from '@material-ui/core/Button' +import ButtonBase from '@material-ui/core/ButtonBase' + +const styles = theme => ({ + layout: { + width: 'auto', + marginLeft: theme.spacing.unit * 2, + marginRight: theme.spacing.unit * 2, + [theme.breakpoints.up(600 + theme.spacing.unit * 2 * 2)]: { + width: 600, + marginLeft: 'auto', + marginRight: 'auto' + } + }, + paper: { + marginTop: theme.spacing.unit * 0.1, + marginBottom: theme.spacing.unit * 0.1, + padding: theme.spacing.unit * 2, + [theme.breakpoints.up(600 + theme.spacing.unit * 3 * 2)]: { + marginTop: theme.spacing.unit * 1, + marginBottom: theme.spacing.unit * 1, + padding: theme.spacing.unit * 3 + } + }, + card: { + display: 'block', + width: '100%' + }, + cardDetails: { + display: 'flex', + flex: 1 + }, + cardContent: { + flex: 1 + }, + buttonRight: { + justifyContent: 'flex-end' + }, + image: { + width: 140, + height: 140 + }, + img: { + margin: 'auto', + display: 'block', + maxWidth: '100%', + maxHeight: '100%' + } +}) + +export const TeamsItem = ({ classes, team }) => ( + +
+ + + + + complex + + + + + + {team.name} + + {team.createdAt} + + + Members: 1 + + + + + Now recruiting! + + + + + + + + + +
+
+) + +TeamsItem.propTypes = { + classes: PropTypes.object.isRequired, + team: PropTypes.object.isRequired +} + +export default withStyles(styles)(TeamsItem) diff --git a/client/src/views/teams/components/TeamsList.js b/client/src/views/teams/components/TeamsList.js new file mode 100644 index 000000000..c156b244b --- /dev/null +++ b/client/src/views/teams/components/TeamsList.js @@ -0,0 +1,61 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { Query } from 'react-apollo' + +import Typography from '@material-ui/core/Typography' +import Grid from '@material-ui/core/Grid' + +import GET_ALL_TEAMS_QUERY from '../../../graphql/teams/GetAllTeamsQuery' + +import TeamsItem from './TeamsItem' + +export const TeamsList = ({ classes }) => ( + + + {({ loading, error, data }) => { + console.log('GET_TEAMS_BY_OWNER: ', loading, error, data) + let errors + let queryLoader + if (error) { + errors = error.graphQLErrors.map(({ message }, i) => { + return ( + + {message} + + ) + }) + } + if (!loading && !error) { + if (data.teams.edges.length > 0) { + return ( + + {!loading && + data.teams.edges.map(team => ( + + ))} + {queryLoader} + {errors} + + ) + } + } else { + return ( + + + Loading... + + {queryLoader} + {errors} + + ) + } + }} + + +) + +TeamsList.propTypes = { + classes: PropTypes.object.isRequired +} + +export default TeamsList diff --git a/client/src/views/teams/index.js b/client/src/views/teams/index.js index 69dbd99aa..96fd0e5c8 100644 --- a/client/src/views/teams/index.js +++ b/client/src/views/teams/index.js @@ -3,8 +3,11 @@ import PropTypes from 'prop-types' import CssBaseline from '@material-ui/core/CssBaseline' import Typography from '@material-ui/core/Typography' +import Grid from '@material-ui/core/Grid' import { withStyles } from '@material-ui/core/styles' +import TeamsList from './components/TeamsList' + const styles = theme => ({ '@global': { body: { @@ -28,7 +31,7 @@ const styles = theme => ({ } }) -const Home = ({ classes }) => ( +const Teams = ({ classes }) => (
@@ -41,13 +44,16 @@ const Home = ({ classes }) => ( > Teams + + +
) -Home.propTypes = { +Teams.propTypes = { classes: PropTypes.object.isRequired } -export default withStyles(styles)(Home) +export default withStyles(styles)(Teams) From 8bd31bd91b3d5bba0466fc8131c3be0aca8fad25 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Fri, 14 Sep 2018 07:35:25 -0700 Subject: [PATCH 08/19] Client: Team Details subpage --- client/src/App.js | 1 + .../views/teams/components/TeamsDetails.js | 89 +++++++++++ .../src/views/teams/components/TeamsItem.js | 134 +++++----------- .../src/views/teams/components/TeamsList.js | 143 +++++++++++++----- client/src/views/teams/index.js | 30 +--- 5 files changed, 242 insertions(+), 155 deletions(-) create mode 100644 client/src/views/teams/components/TeamsDetails.js diff --git a/client/src/App.js b/client/src/App.js index e2f28ac3c..241fa8d1b 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -150,6 +150,7 @@ class App extends Component { + ({ + root: { + flexGrow: 1 + }, + '@global': { + body: { + backgroundColor: theme.palette.common.white + } + }, + layout: { + width: 'auto', + marginLeft: theme.spacing.unit * 3, + marginRight: theme.spacing.unit * 3, + marginBottom: theme.spacing.unit * 6, + [theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: { + width: 900, + marginLeft: 'auto', + marginRight: 'auto' + } + }, + paper: { + marginTop: theme.spacing.unit * 3, + marginBottom: theme.spacing.unit * 3, + padding: theme.spacing.unit * 2, + [theme.breakpoints.up(600 + theme.spacing.unit * 3 * 2)]: { + marginTop: theme.spacing.unit * 6, + marginBottom: theme.spacing.unit * 6, + padding: theme.spacing.unit * 3 + } + }, + heroContent: { + maxWidth: 600, + margin: '0 auto', + padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px` + } +}) + +const TeamsDetails = ({ classes, team }) => ( + + +
+ +
+ ← Back to all teams + + {team.name} + + + {team.createdAt} + + + Members: {team.members.length} + + + Team Admin: + { + team.members.map(member => { + if (member.role === 'OWNER' || member.role === 'ADMIN') { + return member.member.alias + } + }) + } + +
+
+
+
+) +TeamsDetails.propTypes = { + classes: PropTypes.object.isRequired, + team: PropTypes.object.isRequired +} + +export default withStyles(styles)(TeamsDetails) diff --git a/client/src/views/teams/components/TeamsItem.js b/client/src/views/teams/components/TeamsItem.js index 16d833c32..6b2e20bb1 100644 --- a/client/src/views/teams/components/TeamsItem.js +++ b/client/src/views/teams/components/TeamsItem.js @@ -1,105 +1,49 @@ import React from 'react' import PropTypes from 'prop-types' -import Typography from '@material-ui/core/Typography' -import { withStyles } from '@material-ui/core/styles' - import Grid from '@material-ui/core/Grid' -import Paper from '@material-ui/core/Paper' +import Card from '@material-ui/core/Card' +import CardActionArea from '@material-ui/core/CardActionArea' +import CardActions from '@material-ui/core/CardActions' +import CardContent from '@material-ui/core/CardContent' +import CardMedia from '@material-ui/core/CardMedia' import Button from '@material-ui/core/Button' -import ButtonBase from '@material-ui/core/ButtonBase' +import Typography from '@material-ui/core/Typography' -const styles = theme => ({ - layout: { - width: 'auto', - marginLeft: theme.spacing.unit * 2, - marginRight: theme.spacing.unit * 2, - [theme.breakpoints.up(600 + theme.spacing.unit * 2 * 2)]: { - width: 600, - marginLeft: 'auto', - marginRight: 'auto' - } - }, - paper: { - marginTop: theme.spacing.unit * 0.1, - marginBottom: theme.spacing.unit * 0.1, - padding: theme.spacing.unit * 2, - [theme.breakpoints.up(600 + theme.spacing.unit * 3 * 2)]: { - marginTop: theme.spacing.unit * 1, - marginBottom: theme.spacing.unit * 1, - padding: theme.spacing.unit * 3 - } - }, - card: { - display: 'block', - width: '100%' - }, - cardDetails: { - display: 'flex', - flex: 1 - }, - cardContent: { - flex: 1 - }, - buttonRight: { - justifyContent: 'flex-end' - }, - image: { - width: 140, - height: 140 - }, - img: { - margin: 'auto', - display: 'block', - maxWidth: '100%', - maxHeight: '100%' - } -}) +import { Link } from 'react-router-dom' export const TeamsItem = ({ classes, team }) => ( - -
- - - - - complex - - - - - - {team.name} - - {team.createdAt} - - - Members: 1 - - - - - Now recruiting! - - - - - - - - - -
+ + + + + + + {team.name} + + + {team.createdAt} + + + Members: 1 + + + Now recruiting! + + + + + + + + + ) @@ -108,4 +52,4 @@ TeamsItem.propTypes = { team: PropTypes.object.isRequired } -export default withStyles(styles)(TeamsItem) +export default TeamsItem diff --git a/client/src/views/teams/components/TeamsList.js b/client/src/views/teams/components/TeamsList.js index c156b244b..8ae962ead 100644 --- a/client/src/views/teams/components/TeamsList.js +++ b/client/src/views/teams/components/TeamsList.js @@ -4,58 +4,125 @@ import { Query } from 'react-apollo' import Typography from '@material-ui/core/Typography' import Grid from '@material-ui/core/Grid' +import { withStyles } from '@material-ui/core/styles' import GET_ALL_TEAMS_QUERY from '../../../graphql/teams/GetAllTeamsQuery' -import TeamsItem from './TeamsItem' +import { isEmpty } from '../../../utils/js-helpers' -export const TeamsList = ({ classes }) => ( - - - {({ loading, error, data }) => { - console.log('GET_TEAMS_BY_OWNER: ', loading, error, data) - let errors - let queryLoader - if (error) { - errors = error.graphQLErrors.map(({ message }, i) => { +import TeamsItem from './TeamsItem' +import TeamsDetails from './TeamsDetails' + +const styles = theme => ({ + heroContent: { + maxWidth: 600, + margin: '0 auto', + padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px` + }, + cardGrid: { + padding: `${theme.spacing.unit * 8}px 0` + }, + card: { + height: '100%', + display: 'flex', + flexDirection: 'column' + }, + cardMedia: { + paddingTop: '56.25%' // 16:9 + }, + cardContent: { + flexGrow: 1 + }, + buttonRight: { + justifyContent: 'flex-end' + } +}) + +export const TeamsList = ({ classes, match }) => ( + + {({ loading, error, data }) => { + console.log('GET_TEAMS_BY_OWNER: ', loading, error, data, match) + let slug = null + if (!isEmpty(match.params) && match.params.slug) slug = match.params.slug + + let errors + let queryLoader + if (error) { + errors = error.graphQLErrors.map(({ message }, i) => { + return ( + + {message} + + ) + }) + } + if (!loading && !error) { + if (data.teams.edges.length > 0) { + if (slug !== null) { return ( - - {message} - - ) - }) - } - if (!loading && !error) { - if (data.teams.edges.length > 0) { - return ( - + {!loading && - data.teams.edges.map(team => ( - - ))} + data.teams.edges.map(team => { + if (team.node.slug === slug) { + return ( + + ) + } + })} {queryLoader} {errors} ) + } else { + return ( + +
+ + Teams + +
+ + {!loading && + data.teams.edges.map(team => ( + + ))} + {queryLoader} + {errors} + +
+ ) } - } else { - return ( - - - Loading... - - {queryLoader} - {errors} - - ) } - }} -
-
+ } else { + return ( + + + Loading... + + {queryLoader} + {errors} + + ) + } + }} +
) TeamsList.propTypes = { - classes: PropTypes.object.isRequired + classes: PropTypes.object.isRequired, + match: PropTypes.object } -export default TeamsList +export default withStyles(styles)(TeamsList) diff --git a/client/src/views/teams/index.js b/client/src/views/teams/index.js index 96fd0e5c8..3c2087d83 100644 --- a/client/src/views/teams/index.js +++ b/client/src/views/teams/index.js @@ -2,13 +2,14 @@ import React from 'react' import PropTypes from 'prop-types' import CssBaseline from '@material-ui/core/CssBaseline' -import Typography from '@material-ui/core/Typography' -import Grid from '@material-ui/core/Grid' import { withStyles } from '@material-ui/core/styles' import TeamsList from './components/TeamsList' const styles = theme => ({ + root: { + flexGrow: 1 + }, '@global': { body: { backgroundColor: theme.palette.common.white @@ -18,42 +19,27 @@ const styles = theme => ({ width: 'auto', marginLeft: theme.spacing.unit * 3, marginRight: theme.spacing.unit * 3, + marginBottom: theme.spacing.unit * 6, [theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: { width: 900, marginLeft: 'auto', marginRight: 'auto' } - }, - heroContent: { - maxWidth: 600, - margin: '0 auto', - padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px` } }) -const Teams = ({ classes }) => ( +const Teams = ({ classes, match }) => (
-
- - Teams - - - - -
+
) Teams.propTypes = { - classes: PropTypes.object.isRequired + classes: PropTypes.object.isRequired, + match: PropTypes.object } export default withStyles(styles)(Teams) From 1dc270852d20503dd9cad8acd5e1e382e29f509a Mon Sep 17 00:00:00 2001 From: Barry Low Date: Fri, 14 Sep 2018 07:56:51 -0700 Subject: [PATCH 09/19] Add basic Team Management --- api/src/graphql/TeamsConnectionsFragment.js | 33 +++++ api/src/index.js | 39 ++--- api/src/schema.graphql | 3 +- .../teams/UpdateTeamProfileMutation.js | 34 +++++ client/src/views/dashboard/ManageTeams.js | 6 +- .../dashboard/components/ManageTeamEdit.js | 133 ++++++++++++++++++ .../components/ManageTeamsDetails.js | 89 ++++++++++++ .../dashboard/components/ManageTeamsItem.js | 55 ++++++++ .../dashboard/components/ManageTeamsList.js | 128 +++++++++++++++++ .../src/views/teams/components/TeamsList.js | 2 +- 10 files changed, 487 insertions(+), 35 deletions(-) create mode 100644 api/src/graphql/TeamsConnectionsFragment.js create mode 100644 client/src/graphql/teams/UpdateTeamProfileMutation.js create mode 100644 client/src/views/dashboard/components/ManageTeamEdit.js create mode 100644 client/src/views/dashboard/components/ManageTeamsDetails.js create mode 100644 client/src/views/dashboard/components/ManageTeamsItem.js create mode 100644 client/src/views/dashboard/components/ManageTeamsList.js diff --git a/api/src/graphql/TeamsConnectionsFragment.js b/api/src/graphql/TeamsConnectionsFragment.js new file mode 100644 index 000000000..89a22a8c4 --- /dev/null +++ b/api/src/graphql/TeamsConnectionsFragment.js @@ -0,0 +1,33 @@ +const gql = require('graphql-tag') + +const TEAMS_CONNECTIONS_FRAGMENT = gql`{ + edges { + node { + id + name + slug + owner + status { + status + reason + createdAt + } + createdAt + profile { + avatar + description + motto + updatedAt + } + members { + role + member { + alias + authId + } + } + } + } +}` + +module.exports = TEAMS_CONNECTIONS_FRAGMENT diff --git a/api/src/index.js b/api/src/index.js index 0386ba61b..6b4a5167d 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -14,6 +14,7 @@ const { validateIdToken } = require('./auth/validateIdToken') const { directiveResolvers } = require('./auth/authDirectives') const TEAMS_FRAGMENT = require('./graphql/TeamsFragment') +const TEAMS_CONNECTIONS_FRAGMENT = require('./graphql/TeamsConnectionsFragment') const createMember = async function (ctx, info, idToken) { console.log('createMember', idToken) @@ -47,36 +48,7 @@ const resolvers = { return ctx.db.query.member({ where: { authId } }, info) }, teams(parent, args, ctx, info) { - return ctx.db.query.teamsConnection({}, - `{ - edges { - node { - id - name - slug - owner - status { - status - reason - createdAt - } - createdAt - profile { - avatar - description - motto - updatedAt - } - members { - role - member { - alias - authId - } - } - } - } - }`) + return ctx.db.query.teamsConnection({}, TEAMS_CONNECTIONS_FRAGMENT) }, async teamById(parent, { id }, ctx, info) { return ctx.db.query.team({ where: { id } }, info) @@ -128,6 +100,13 @@ const resolvers = { return err }) }, + async updateTeamProfile(parent, { slug, owner, description, motto, avatar }, ctx, info) { + return ctx.db.mutation.updateTeam({data:{profile: {update: {description: description, motto: motto, avatar: avatar}}}, where:{slug: slug}}), TEAMS_FRAGMENT) + .catch((err) => { + console.log('createTeam error: ', err) + return err + }) + }, async deleteTeam(parent, { id }, ctx, info) { return ctx.db.mutation.deleteTeam({ where: { id } }, info) .catch((res) => { diff --git a/api/src/schema.graphql b/api/src/schema.graphql index 9e315174c..8b5d48d77 100644 --- a/api/src/schema.graphql +++ b/api/src/schema.graphql @@ -18,7 +18,8 @@ type Query { type Mutation { authenticate(idToken: String!): Member - createTeam(name: String!, slug: String, owner: String): Team @isAuthenticated + createTeam(name: String!, slug: String!, owner: String!): Team @isAuthenticated + updateTeamProfile(slug: String!, owner: String!, description: String, motto: String, avatar: String): Team @isAuthenticated deleteTeam(id: ID!): Team @isAuthenticated @isOwner(type: "Team") } diff --git a/client/src/graphql/teams/UpdateTeamProfileMutation.js b/client/src/graphql/teams/UpdateTeamProfileMutation.js new file mode 100644 index 000000000..6672a7a24 --- /dev/null +++ b/client/src/graphql/teams/UpdateTeamProfileMutation.js @@ -0,0 +1,34 @@ +/* eslint-disable no-unused-vars */ +import gql from 'graphql-tag' + +const CREATE_TEAM = gql` + mutation UpdateTeamMutation($slug: String!, $owner: String!, $description: String, $motto: String) { + createTeam(slug: $slug, owner: $owner, description: $description, motto: $motto) { + id + name + slug + owner + status { + status + reason + createdAt + } + createdAt + profile { + avatar + description + motto + updatedAt + } + members { + role + member { + alias + authId + } + } + } + } +` + +export default CREATE_TEAM diff --git a/client/src/views/dashboard/ManageTeams.js b/client/src/views/dashboard/ManageTeams.js index ecf65c9db..175c4aded 100644 --- a/client/src/views/dashboard/ManageTeams.js +++ b/client/src/views/dashboard/ManageTeams.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types' import Typography from '@material-ui/core/Typography' import { withStyles } from '@material-ui/core/styles' -import TeamTable from './components/TeamTable' +import ManageTeamsList from './components/ManageTeamsList' const styles = theme => ({ tableContainer: { @@ -15,10 +15,10 @@ const styles = theme => ({ const ManageTeams = ({ classes }) => (
- Teams + Manage Your Teams
- +
) diff --git a/client/src/views/dashboard/components/ManageTeamEdit.js b/client/src/views/dashboard/components/ManageTeamEdit.js new file mode 100644 index 000000000..d10dd5728 --- /dev/null +++ b/client/src/views/dashboard/components/ManageTeamEdit.js @@ -0,0 +1,133 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import { withRouter } from 'react-router-dom' +import Button from '@material-ui/core/Button' +import AddIcon from '@material-ui/icons/Add' +import TextField from '@material-ui/core/TextField' +import Dialog from '@material-ui/core/Dialog' +import DialogActions from '@material-ui/core/DialogActions' +import DialogContent from '@material-ui/core/DialogContent' +import DialogContentText from '@material-ui/core/DialogContentText' +import DialogTitle from '@material-ui/core/DialogTitle' +import Typography from '@material-ui/core/Typography' + +import { getItem } from '../../../utils/local-storage' + +export class ManageTeamEdit extends Component { + constructor (props) { + super(props) + + this.handleClickOpen = this.handleClickOpen.bind(this) + this.handleClose = this.handleClose.bind(this) + this.handlePost = this.handlePost.bind(this) + this.slugify = this.slugify.bind(this) + this.handleChange = this.handleChange.bind(this) + + this.state = { + open: false, + motto: '', + description: '' + } + } + + handleClickOpen () { + this.setState({ open: true }) + } + + handleClose () { + this.setState({ open: false }) + } + + handleChange (e) { + this.setState({ name: e.target.value }) + } + + render () { + console.log(this.props, this.props.team) + return ( +
+ + + Edit Team Details + + Team Creation + Team Motto: + + + + + + + +
+ ) + } + + slugify (string) { + const a = 'àáäâãåèéëêìíïîòóöôùúüûñçßÿœæŕśńṕẃǵǹḿǘẍźḧ·/_,:;' + const b = 'aaaaaaeeeeiiiioooouuuuncsyoarsnpwgnmuxzh------' + const p = new RegExp(a.split('').join('|'), 'g') + + return string + .toString() + .toLowerCase() + .replace(/\s+/g, '-') // Replace spaces with - + .replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters + .replace(/&/g, '-and-') // Replace & with 'and' + .replace(/[^\w-]+/g, '') // Remove all non-word characters + .replace(/--+/g, '-') // Replace multiple - with single - + .replace(/^-+/, '') // Trim - from start of text + .replace(/-+$/, '') // Trim - from end of text + } + + async handlePost (e) { + e.preventDefault() + const { name } = this.state + const slug = this.slugify(name) + const currentUser = await getItem('user') + let authId = JSON.parse(currentUser) + authId = authId.sub + console.log('createPage cu:', JSON.parse(currentUser)) + await this.props.createTeamMutation({ + variables: { + name, + slug, + owner: authId + } + }) + this.setState({ open: false }) + } +} + +ManageTeamEdit.propTypes = { + classes: PropTypes.object.isRequired, + team: PropTypes.object.isRequired, + createTeamMutation: PropTypes.function +} + +export default withRouter(ManageTeamEdit) diff --git a/client/src/views/dashboard/components/ManageTeamsDetails.js b/client/src/views/dashboard/components/ManageTeamsDetails.js new file mode 100644 index 000000000..65a988215 --- /dev/null +++ b/client/src/views/dashboard/components/ManageTeamsDetails.js @@ -0,0 +1,89 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import CssBaseline from '@material-ui/core/CssBaseline' +import Typography from '@material-ui/core/Typography' +import Paper from '@material-ui/core/Paper' +import { withStyles } from '@material-ui/core/styles' + +import { Link } from 'react-router-dom' + +const styles = theme => ({ + root: { + flexGrow: 1 + }, + '@global': { + body: { + backgroundColor: theme.palette.common.white + } + }, + layout: { + width: 'auto', + marginLeft: theme.spacing.unit * 3, + marginRight: theme.spacing.unit * 3, + marginBottom: theme.spacing.unit * 6, + [theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: { + width: 900, + marginLeft: 'auto', + marginRight: 'auto' + } + }, + paper: { + marginTop: theme.spacing.unit * 3, + marginBottom: theme.spacing.unit * 3, + padding: theme.spacing.unit * 2, + [theme.breakpoints.up(600 + theme.spacing.unit * 3 * 2)]: { + marginTop: theme.spacing.unit * 6, + marginBottom: theme.spacing.unit * 6, + padding: theme.spacing.unit * 3 + } + }, + heroContent: { + maxWidth: 600, + margin: '0 auto', + padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px` + } +}) + +const ManageTeamsDetails = ({ classes, team }) => ( + + +
+ +
+ ← Back to all teams + + {team.name} + + + {team.createdAt} + + + Members: {team.members.length} + + + Team Admin: + { + team.members.map(member => { + if (member.role === 'OWNER' || member.role === 'ADMIN') { + return member.member.alias + } + }) + } + +
+
+
+
+) +ManageTeamsDetails.propTypes = { + classes: PropTypes.object.isRequired, + team: PropTypes.object.isRequired +} + +export default withStyles(styles)(ManageTeamsDetails) diff --git a/client/src/views/dashboard/components/ManageTeamsItem.js b/client/src/views/dashboard/components/ManageTeamsItem.js new file mode 100644 index 000000000..7c00639d9 --- /dev/null +++ b/client/src/views/dashboard/components/ManageTeamsItem.js @@ -0,0 +1,55 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import Grid from '@material-ui/core/Grid' +import Card from '@material-ui/core/Card' +import CardActionArea from '@material-ui/core/CardActionArea' +import CardActions from '@material-ui/core/CardActions' +import CardContent from '@material-ui/core/CardContent' +import CardMedia from '@material-ui/core/CardMedia' +import Button from '@material-ui/core/Button' +import Typography from '@material-ui/core/Typography' + +import { Link } from 'react-router-dom' + +export const ManageTeamsItem = ({ classes, team }) => ( + + + + + + + {team.name} + + + {team.createdAt} + + + Members: 1 + + + Now recruiting! + + + + + + + + + + +) + +ManageTeamsItem.propTypes = { + classes: PropTypes.object.isRequired, + team: PropTypes.object.isRequired +} + +export default ManageTeamsItem diff --git a/client/src/views/dashboard/components/ManageTeamsList.js b/client/src/views/dashboard/components/ManageTeamsList.js new file mode 100644 index 000000000..b02592c8e --- /dev/null +++ b/client/src/views/dashboard/components/ManageTeamsList.js @@ -0,0 +1,128 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { Query } from 'react-apollo' + +import Typography from '@material-ui/core/Typography' +import Grid from '@material-ui/core/Grid' +import { withStyles } from '@material-ui/core/styles' + +import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' + +import { isEmpty } from '../../../utils/js-helpers' + +import ManageTeamsItem from './ManageTeamsItem' +import ManageTeamsDetails from './ManageTeamsDetails' + +const styles = theme => ({ + heroContent: { + maxWidth: 600, + margin: '0 auto', + padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px` + }, + cardGrid: { + padding: `${theme.spacing.unit * 8}px 0` + }, + card: { + height: '100%', + display: 'flex', + flexDirection: 'column' + }, + cardMedia: { + paddingTop: '56.25%' // 16:9 + }, + cardContent: { + flexGrow: 1 + }, + buttonRight: { + justifyContent: 'flex-end' + } +}) + +export const ManageTeamsList = ({ classes, match }) => ( + + {({ loading, error, data }) => { + console.log('GET_TEAMS_BY_OWNER: ', loading, error, data, match) + let slug = null + if (!isEmpty(match.params) && match.params.slug) slug = match.params.slug + + let errors + let queryLoader + if (error) { + errors = error.graphQLErrors.map(({ message }, i) => { + return ( + + {message} + + ) + }) + } + if (!loading && !error) { + if (data.teams.edges.length > 0) { + if (slug !== null) { + return ( + + {!loading && + data.teams.edges.map(team => { + if (team.node.slug === slug) { + return ( + + ) + } + })} + {queryLoader} + {errors} + + ) + } else { + return ( + +
+ + Teams + +
+ + {!loading && + data.teams.edges.map(team => ( + + ))} + {queryLoader} + {errors} + +
+ ) + } + } + } else { + return ( + + + Loading... + + {queryLoader} + {errors} + + ) + } + }} +
+) + +ManageTeamsList.propTypes = { + classes: PropTypes.object.isRequired, + match: PropTypes.object +} + +export default withStyles(styles)(ManageTeamsList) diff --git a/client/src/views/teams/components/TeamsList.js b/client/src/views/teams/components/TeamsList.js index 8ae962ead..64493cdff 100644 --- a/client/src/views/teams/components/TeamsList.js +++ b/client/src/views/teams/components/TeamsList.js @@ -41,7 +41,7 @@ const styles = theme => ({ export const TeamsList = ({ classes, match }) => ( {({ loading, error, data }) => { - console.log('GET_TEAMS_BY_OWNER: ', loading, error, data, match) + console.log('GET_ALL_TEAMS: ', loading, error, data, match) let slug = null if (!isEmpty(match.params) && match.params.slug) slug = match.params.slug From ea2a1c07347aa5a7710f83728f7974aae17c95a5 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Fri, 14 Sep 2018 08:43:07 -0700 Subject: [PATCH 10/19] Client Add Manage Actions --- api/src/index.js | 6 +- api/src/schema.graphql | 2 +- .../teams/UpdateTeamProfileMutation.js | 8 +- client/src/views/dashboard/ManageTeams.js | 4 +- .../dashboard/components/ManageTeamsItem.js | 29 ++- .../dashboard/components/ManageTeamsList.js | 167 +++++++++--------- 6 files changed, 105 insertions(+), 111 deletions(-) diff --git a/api/src/index.js b/api/src/index.js index 6b4a5167d..3e0880065 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -101,14 +101,14 @@ const resolvers = { }) }, async updateTeamProfile(parent, { slug, owner, description, motto, avatar }, ctx, info) { - return ctx.db.mutation.updateTeam({data:{profile: {update: {description: description, motto: motto, avatar: avatar}}}, where:{slug: slug}}), TEAMS_FRAGMENT) + return ctx.db.mutation.updateTeam({data:{profile: {update: {description: description, motto: motto, avatar: avatar}}}, where:{slug: slug}}, TEAMS_FRAGMENT) .catch((err) => { console.log('createTeam error: ', err) return err }) }, - async deleteTeam(parent, { id }, ctx, info) { - return ctx.db.mutation.deleteTeam({ where: { id } }, info) + async deleteTeam(parent, { slug }, ctx, info) { + return ctx.db.mutation.deleteTeam({ where: { slug } }, info) .catch((res) => { console.log('deleteTeam error: ', res) const errors = res.graphQLErrors.map((error) => { diff --git a/api/src/schema.graphql b/api/src/schema.graphql index 8b5d48d77..1450c6000 100644 --- a/api/src/schema.graphql +++ b/api/src/schema.graphql @@ -20,7 +20,7 @@ type Mutation { authenticate(idToken: String!): Member createTeam(name: String!, slug: String!, owner: String!): Team @isAuthenticated updateTeamProfile(slug: String!, owner: String!, description: String, motto: String, avatar: String): Team @isAuthenticated - deleteTeam(id: ID!): Team @isAuthenticated @isOwner(type: "Team") + deleteTeam(slug: String!): Team @isAuthenticated @isOwner(type: "Team") } input MemberProfileInput { diff --git a/client/src/graphql/teams/UpdateTeamProfileMutation.js b/client/src/graphql/teams/UpdateTeamProfileMutation.js index 6672a7a24..6da940d4c 100644 --- a/client/src/graphql/teams/UpdateTeamProfileMutation.js +++ b/client/src/graphql/teams/UpdateTeamProfileMutation.js @@ -1,9 +1,9 @@ /* eslint-disable no-unused-vars */ import gql from 'graphql-tag' -const CREATE_TEAM = gql` - mutation UpdateTeamMutation($slug: String!, $owner: String!, $description: String, $motto: String) { - createTeam(slug: $slug, owner: $owner, description: $description, motto: $motto) { +const UPDATE_TEAM_PROFILE = gql` + mutation UpdateTeamProfileMutation($slug: String!, $owner: String!, $description: String, $motto: String) { + updateTeamProfile(slug: $slug, owner: $owner, description: $description, motto: $motto) { id name slug @@ -31,4 +31,4 @@ const CREATE_TEAM = gql` } ` -export default CREATE_TEAM +export default UPDATE_TEAM_PROFILE diff --git a/client/src/views/dashboard/ManageTeams.js b/client/src/views/dashboard/ManageTeams.js index 175c4aded..7eceeb1ca 100644 --- a/client/src/views/dashboard/ManageTeams.js +++ b/client/src/views/dashboard/ManageTeams.js @@ -17,9 +17,7 @@ const ManageTeams = ({ classes }) => ( Manage Your Teams -
- -
+
) diff --git a/client/src/views/dashboard/components/ManageTeamsItem.js b/client/src/views/dashboard/components/ManageTeamsItem.js index 7c00639d9..d765e0ad0 100644 --- a/client/src/views/dashboard/components/ManageTeamsItem.js +++ b/client/src/views/dashboard/components/ManageTeamsItem.js @@ -3,19 +3,16 @@ import PropTypes from 'prop-types' import Grid from '@material-ui/core/Grid' import Card from '@material-ui/core/Card' -import CardActionArea from '@material-ui/core/CardActionArea' import CardActions from '@material-ui/core/CardActions' import CardContent from '@material-ui/core/CardContent' import CardMedia from '@material-ui/core/CardMedia' import Button from '@material-ui/core/Button' import Typography from '@material-ui/core/Typography' -import { Link } from 'react-router-dom' - export const ManageTeamsItem = ({ classes, team }) => ( - + - +
( {team.name} - {team.createdAt} - - - Members: 1 - - - Now recruiting! + {team.createdAt} | Members: {team.members.length} - - - + - - + + + +
) diff --git a/client/src/views/dashboard/components/ManageTeamsList.js b/client/src/views/dashboard/components/ManageTeamsList.js index b02592c8e..c15316e60 100644 --- a/client/src/views/dashboard/components/ManageTeamsList.js +++ b/client/src/views/dashboard/components/ManageTeamsList.js @@ -1,17 +1,18 @@ import React from 'react' import PropTypes from 'prop-types' import { Query } from 'react-apollo' +import { withStateHandlers, lifecycle, compose } from 'recompose' import Typography from '@material-ui/core/Typography' import Grid from '@material-ui/core/Grid' import { withStyles } from '@material-ui/core/styles' +import { isDefined, isString } from '../../../utils/js-helpers' +import { getItem } from '../../../utils/local-storage' + import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' -import { isEmpty } from '../../../utils/js-helpers' - import ManageTeamsItem from './ManageTeamsItem' -import ManageTeamsDetails from './ManageTeamsDetails' const styles = theme => ({ heroContent: { @@ -22,107 +23,107 @@ const styles = theme => ({ cardGrid: { padding: `${theme.spacing.unit * 8}px 0` }, - card: { - height: '100%', - display: 'flex', - flexDirection: 'column' - }, - cardMedia: { - paddingTop: '56.25%' // 16:9 - }, - cardContent: { - flexGrow: 1 - }, buttonRight: { justifyContent: 'flex-end' + }, + card: { + display: 'flex', + width: '100%' + }, + cardDetails: { + display: 'flex', + flex: 1 + }, + cardContent: { + flex: 1 + }, + cardMedia: { + flex: 1, + width: 100, + height: 100, + maxWidth: 100, + justifyContent: 'flex-start' } }) -export const ManageTeamsList = ({ classes, match }) => ( - - {({ loading, error, data }) => { - console.log('GET_TEAMS_BY_OWNER: ', loading, error, data, match) - let slug = null - if (!isEmpty(match.params) && match.params.slug) slug = match.params.slug +export const ManageTeamsList = ({ classes, user = null }) => { + let owner + let authId = null + console.log('ManageTeamsList: ', user) + if (user !== null && isString(user)) { + owner = JSON.parse(user) + if (isDefined(owner.authId)) authId = owner.authId + } + console.log('ManageTeamsList 2: ', owner, authId) - let errors - let queryLoader - if (error) { - errors = error.graphQLErrors.map(({ message }, i) => { - return ( - - {message} - - ) - }) - } - if (!loading && !error) { - if (data.teams.edges.length > 0) { - if (slug !== null) { + return ( + + {({ loading, error, data }) => { + console.log('GET_TEAMS_BY_OWNER: ', loading, error, data) + + let errors + if (error) { + errors = error.graphQLErrors.map(({ message }, i) => { return ( - - {!loading && - data.teams.edges.map(team => { - if (team.node.slug === slug) { - return ( - - ) - } - })} - {queryLoader} - {errors} - + + {message} + ) - } else { + }) + } + if (!loading && !error) { + if (data.teamsByOwner.length > 0) { return ( -
- - Teams - -
{!loading && - data.teams.edges.map(team => ( + data.teamsByOwner.map(team => ( ))} - {queryLoader} {errors}
) } + } else { + return ( + + + Loading... + + {errors} + + ) } - } else { - return ( - - - Loading... - - {queryLoader} - {errors} - - ) - } - }} -
-) - -ManageTeamsList.propTypes = { - classes: PropTypes.object.isRequired, - match: PropTypes.object + }} +
+ ) } -export default withStyles(styles)(ManageTeamsList) +ManageTeamsList.propTypes = { + user: PropTypes.any, + classes: PropTypes.object.isRequired +} + +const getUserOnMount = lifecycle({ + componentDidMount () { + getItem('user').then(user => { + this.setState({ user }) + }) // Set user to state + } +}) + +const mapStateToProps = withStateHandlers(() => ({ user: null }), { + user: ({ user }) => () => ({ user }) +}) + +const ManageTeamsListAuthId = compose( + mapStateToProps, + getUserOnMount +)(ManageTeamsList) + +export default withStyles(styles)(ManageTeamsListAuthId) From 5b521b3620ce9a0a09908b4e8e94d2e1ccd30b9e Mon Sep 17 00:00:00 2001 From: Barry Low Date: Fri, 14 Sep 2018 22:52:41 -0700 Subject: [PATCH 11/19] Solidify Dash Panel Queries and Mutations --- api/src/index.js | 2 +- .../src/graphql/teams/DeleteTeamMutation.js | 4 +++- .../views/dashboard/components/CreateTeam.js | 21 ++++++++++++------- .../dashboard/components/CreateTeamWrapper.js | 7 ++++--- .../views/dashboard/components/DashTeam.js | 4 ++-- .../dashboard/components/ManageTeamsItem.js | 6 +++--- 6 files changed, 27 insertions(+), 17 deletions(-) diff --git a/api/src/index.js b/api/src/index.js index 3e0880065..8f3670a7a 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -58,7 +58,7 @@ const resolvers = { }, async teamsByOwner(parent, { ownerId }, ctx, info) { console.log('teamsByOwner: ', ctx.user) - return ctx.db.query.teams({where: { owner: ownerId }}, TEAMS_FRAGMENT) + return ctx.db.query.teams({where: { owner: ownerId }, orderBy:'updatedAt_DESC'}, TEAMS_FRAGMENT) }, async owner(parent, args, ctx, info) { console.log('resolver.query.owner ctx: ', ctxMember(ctx)) diff --git a/client/src/graphql/teams/DeleteTeamMutation.js b/client/src/graphql/teams/DeleteTeamMutation.js index 91723348d..998e5c643 100644 --- a/client/src/graphql/teams/DeleteTeamMutation.js +++ b/client/src/graphql/teams/DeleteTeamMutation.js @@ -1,10 +1,12 @@ /* eslint-disable no-unused-vars */ import gql from 'graphql-tag' -export const DeleteTeamMutation = gql` +export const DELETE_TEAM = gql` mutation deleteTeam($id: ID!) { deleteTeam(id: $id) { id } } ` + +export default DELETE_TEAM diff --git a/client/src/views/dashboard/components/CreateTeam.js b/client/src/views/dashboard/components/CreateTeam.js index 90cac23f7..1dfb75850 100644 --- a/client/src/views/dashboard/components/CreateTeam.js +++ b/client/src/views/dashboard/components/CreateTeam.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { Mutation } from 'react-apollo' import Typography from '@material-ui/core/Typography' @@ -9,18 +10,19 @@ import { checkGraphQLError } from '../../../utils/graphql-errors' import CREATE_TEAM from '../../../graphql/teams/CreateTeamMutation' import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' -const CreateTeam = () => { +const CreateTeam = ({ authId }) => { let input + console.log('CreateTeam', authId) return ( { - const data = cache.readQuery({ query: GET_TEAMS_BY_OWNER }) - console.log('Mutation cache update: ', createTeam, data) - data.getTeamsByOwner.push(createTeam) - cache.writeQuery({ query: GET_TEAMS_BY_OWNER, data }) - }} + refetchQueries={[ + { + query: GET_TEAMS_BY_OWNER, + variables: { authId } + } + ]} > {(createTeam, { loading, error, data }) => { let errors @@ -62,11 +64,16 @@ const CreateTeam = () => { ) } +CreateTeam.propTypes = { + authId: PropTypes.any +} + const handleSubmit = async (e, createTeam, input) => { e.preventDefault() const currentUser = await getItem('user') let authId = JSON.parse(currentUser) authId = authId.authId + console.log('createTeam submit: ', authId) const name = input.value const slug = slugify(name) await createTeam({ variables: { name, slug, owner: authId } }) diff --git a/client/src/views/dashboard/components/CreateTeamWrapper.js b/client/src/views/dashboard/components/CreateTeamWrapper.js index c4a44b312..68750bffc 100644 --- a/client/src/views/dashboard/components/CreateTeamWrapper.js +++ b/client/src/views/dashboard/components/CreateTeamWrapper.js @@ -28,13 +28,13 @@ const styles = theme => ({ } }) -const CreateTeamWrapper = ({ classes }) => ( +const CreateTeamWrapper = ({ classes, authId }) => (
- +
@@ -43,7 +43,8 @@ const CreateTeamWrapper = ({ classes }) => ( ) CreateTeamWrapper.propTypes = { - classes: PropTypes.object.isRequired + classes: PropTypes.object.isRequired, + authId: PropTypes.string } export default withStyles(styles)(CreateTeamWrapper) diff --git a/client/src/views/dashboard/components/DashTeam.js b/client/src/views/dashboard/components/DashTeam.js index d8b2df1ce..cad20bf57 100644 --- a/client/src/views/dashboard/components/DashTeam.js +++ b/client/src/views/dashboard/components/DashTeam.js @@ -27,7 +27,7 @@ export const DashTeam = ({ classes, user = null }) => { } console.log('DashTeam 2: ', owner, authId) - if (authId === null) { + if (authId === undefined || authId === null) { return ( @@ -42,7 +42,7 @@ export const DashTeam = ({ classes, user = null }) => { Teams - + {({ loading, error, data }) => { console.log('GET_TEAMS_BY_OWNER: ', loading, error, data) diff --git a/client/src/views/dashboard/components/ManageTeamsItem.js b/client/src/views/dashboard/components/ManageTeamsItem.js index d765e0ad0..fdb6534f4 100644 --- a/client/src/views/dashboard/components/ManageTeamsItem.js +++ b/client/src/views/dashboard/components/ManageTeamsItem.js @@ -9,6 +9,8 @@ import CardMedia from '@material-ui/core/CardMedia' import Button from '@material-ui/core/Button' import Typography from '@material-ui/core/Typography' +import ManageTeamDelete from './ManageTeamDelete' + export const ManageTeamsItem = ({ classes, team }) => ( @@ -30,9 +32,7 @@ export const ManageTeamsItem = ({ classes, team }) => ( - + From 4e75489949b9ba5f084fcdd5b651eec2c76bfe39 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Sun, 16 Sep 2018 22:51:14 -0700 Subject: [PATCH 12/19] Client: Manage Team Dialogs --- api/src/auth/authDirectives.js | 16 +- .../src/graphql/teams/DeleteTeamMutation.js | 4 +- client/src/views/common/MessageCard.js | 43 ++++ client/src/views/common/index.js | 3 + client/src/views/dashboard/Overview.js | 7 + .../dashboard/components/CreateTeamDialog.js | 196 +++++++++++++++++ .../views/dashboard/components/DashTeam.js | 19 +- .../dashboard/components/ManageTeamDelete.js | 130 ++++++++++++ .../dashboard/components/ManageTeamEdit.js | 199 ++++++++++-------- .../dashboard/components/ManageTeamsItem.js | 12 +- .../dashboard/components/ManageTeamsList.js | 108 ++++++---- 11 files changed, 593 insertions(+), 144 deletions(-) create mode 100644 client/src/views/common/MessageCard.js create mode 100644 client/src/views/common/index.js create mode 100644 client/src/views/dashboard/components/CreateTeamDialog.js create mode 100644 client/src/views/dashboard/components/ManageTeamDelete.js diff --git a/api/src/auth/authDirectives.js b/api/src/auth/authDirectives.js index 471be4692..0ba153fce 100644 --- a/api/src/auth/authDirectives.js +++ b/api/src/auth/authDirectives.js @@ -71,8 +71,8 @@ const isLoggedIn = async ctx => { const isRequestingMemberAlsoOwner = ({ ctx, memberId, type, typeId }) => - ctx.db.exists[type]({ id: typeId, owner: { auth0id: memberId } }) -const isRequestingMember = ({ ctx, memberId }) => ctx.db.exists.Member({ auth0id: memberId }) + ctx.db.exists[type]({ slug: typeId, owner: memberId }) +const isRequestingMember = ({ ctx, memberId }) => ctx.db.exists.Member({ authId: memberId }) const directiveResolvers = { isAuthenticated: async (next, source, args, ctx) => { @@ -89,12 +89,14 @@ const directiveResolvers = { throw new Error(`Unauthorized, incorrect role`) }, isOwner: async (next, source, { type }, ctx) => { - const { id: typeId } = + console.log('directive isOwner: ', source, type, ctx) + const { slug: typeId } = source && source.id ? source : ctx.request.body.variables ? ctx.request.body.variables : { id: null } - const { auth0id: memberId } = await isLoggedIn(ctx) - console.log('directive isOwner 0: ', type, typeId, memberId) + const user = await isLoggedIn(ctx) + console.log('directive isOwner 0: ', typeId, user.sub) + const memberId = user.sub const isOwner = type === `Member` ? memberId === typeId @@ -106,14 +108,14 @@ const directiveResolvers = { throw new Error(`Unauthorized, must be owner`) }, isOwnerOrHasRole: async (next, source, { roles, type }, ctx, ...p) => { - const { auth0id: memberId } = await isLoggedIn(ctx) + const { authId: memberId } = await isLoggedIn(ctx) console.log('directive isOwnerOrHasRole 1: ', memberId, roles, type) if(memberId === undefined && role=== undefined) throw new Error(`Not logged in`) if (roles.includes(role)) { return next() } - const { auth0id: typeId } = ctx.request.body.variables + const { authId: typeId } = ctx.request.body.variables const isOwner = await isRequestingMemberAlsoOwner({ ctx, memberId, diff --git a/client/src/graphql/teams/DeleteTeamMutation.js b/client/src/graphql/teams/DeleteTeamMutation.js index 998e5c643..8e349c58a 100644 --- a/client/src/graphql/teams/DeleteTeamMutation.js +++ b/client/src/graphql/teams/DeleteTeamMutation.js @@ -2,8 +2,8 @@ import gql from 'graphql-tag' export const DELETE_TEAM = gql` - mutation deleteTeam($id: ID!) { - deleteTeam(id: $id) { + mutation deleteTeam($slug: String!) { + deleteTeam(slug: $slug) { id } } diff --git a/client/src/views/common/MessageCard.js b/client/src/views/common/MessageCard.js new file mode 100644 index 000000000..60668fd62 --- /dev/null +++ b/client/src/views/common/MessageCard.js @@ -0,0 +1,43 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import Typography from '@material-ui/core/Typography' +import { withStyles } from '@material-ui/core/styles' + +import Card from '@material-ui/core/Card' +import CardContent from '@material-ui/core/CardContent' + +const styles = theme => ({ + card: { + display: 'flex', + width: '100%', + margin: '1.5em', + padding: '3em' + }, + cardDetails: { + display: 'flex', + flex: 1 + }, + cardContent: { + flex: 1 + } +}) + +export const MessageCard = ({ classes, message, children }) => ( + +
+ + {message} + {children} + +
+
+) + +MessageCard.propTypes = { + children: PropTypes.node, + classes: PropTypes.object.isRequired, + message: PropTypes.string.isRequired +} + +export default withStyles(styles)(MessageCard) diff --git a/client/src/views/common/index.js b/client/src/views/common/index.js new file mode 100644 index 000000000..fe07e8f49 --- /dev/null +++ b/client/src/views/common/index.js @@ -0,0 +1,3 @@ +import MessageCard from './MessageCard' + +export { MessageCard } diff --git a/client/src/views/dashboard/Overview.js b/client/src/views/dashboard/Overview.js index c79b2eec9..87aa217bf 100644 --- a/client/src/views/dashboard/Overview.js +++ b/client/src/views/dashboard/Overview.js @@ -34,6 +34,13 @@ const styles = theme => ({ aawebMedia: { width: '100%', height: 320 + }, + dashLink: { + float: 'right', + color: '#111', + fontSize: 16, + textDecoration: 'none', + paddingRight: '1em' } }) diff --git a/client/src/views/dashboard/components/CreateTeamDialog.js b/client/src/views/dashboard/components/CreateTeamDialog.js new file mode 100644 index 000000000..66e0f00e5 --- /dev/null +++ b/client/src/views/dashboard/components/CreateTeamDialog.js @@ -0,0 +1,196 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import { Mutation } from 'react-apollo' +import { withStyles } from '@material-ui/core/styles' + +import Button from '@material-ui/core/Button' +import AddIcon from '@material-ui/icons/Add' +import TextField from '@material-ui/core/TextField' +import FormControl from '@material-ui/core/FormControl' +import FormHelperText from '@material-ui/core/FormHelperText' +import Dialog from '@material-ui/core/Dialog' +import DialogActions from '@material-ui/core/DialogActions' +import DialogContent from '@material-ui/core/DialogContent' +import DialogContentText from '@material-ui/core/DialogContentText' +import DialogTitle from '@material-ui/core/DialogTitle' +import Typography from '@material-ui/core/Typography' + +import { getItem } from '../../../utils/local-storage' +import { isEmpty } from '../../../utils/js-helpers' + +import CREATE_TEAM from '../../../graphql/teams/CreateTeamMutation' +import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' + +// import { checkGraphQLError } from '../../../utils/graphql-errors' + +const styles = theme => ({ + dialogStyle: { + padding: '3em' + }, + buttonRight: { + // position: 'absolute', + // right: '3em' + marginTop: '1em', + marginRight: 'auto', + marginLeft: 'auto', + display: 'block', + lineHeight: '1em' + } +}) + +export class CreateTeamDialog extends Component { + constructor (props) { + super(props) + + this.handleClickOpen = this.handleClickOpen.bind(this) + this.handleClose = this.handleClose.bind(this) + this.handleChange = this.handleChange.bind(this) + this.handleSubmit = this.handleSubmit.bind(this) + this.validate = this.validate.bind(this) + this.slugify = this.slugify.bind(this) + + this.state = { + open: false, + name: '', + errors: { + name: '' + } + } + } + + render () { + const { classes, authId } = this.props + return ( + + {(createTeam, { loading, error, data }) => { + let errors + let loader = null + if (loading) { + loader = Submitting team... + } + if (error) { + errors = error.graphQLErrors.map(({ message }, i) => { + // const displayMessage = checkGraphQLError(message) + return ( + + {message} + + ) + }) + } + return ( +
+ + + Create a Team + + Team Name: + (this.state.errors.name !== '' || error)}> + this.state.errors.name !== '' || error} + /> + {this.state.errors.name !== '' && ({this.state.errors.name})} + {error && ({errors})} + {loader} + + + + + + + +
+ ) + }} +
+ ) + } + + handleClickOpen () { + this.setState({ open: true }) + } + + handleClose () { + this.setState({ open: false }) + } + + handleChange (e) { + const errors = this.validate(e.target.value) + if (isEmpty(errors)) { + this.setState({ errors: { name: '' } }) + this.setState({ name: e.target.value }) + } else { + this.setState({ errors: errors }) + this.setState({ name: e.target.value }) + } + } + + async handleSubmit (e, createTeam, name) { + e.preventDefault() + const currentUser = await getItem('user') + let authId = JSON.parse(currentUser) + authId = authId.authId + console.log('createTeam submit: ', authId, name) + const slug = this.slugify(name) + await createTeam({ variables: { name, slug, owner: authId } }) + this.setState({ name: '' }) + } + + validate (data) { + const errors = {} + if (data === '') errors.name = 'Please enter a team name' + return errors + } + + slugify (string) { + const a = 'àáäâãåèéëêìíïîòóöôùúüûñçßÿœæŕśńṕẃǵǹḿǘẍźḧ·/_,:;' + const b = 'aaaaaaeeeeiiiioooouuuuncsyoarsnpwgnmuxzh------' + const p = new RegExp(a.split('').join('|'), 'g') + + return string + .toString() + .toLowerCase() + .replace(/\s+/g, '-') // Replace spaces with - + .replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters + .replace(/&/g, '-and-') // Replace & with 'and' + .replace(/[^\w-]+/g, '') // Remove all non-word characters + .replace(/--+/g, '-') // Replace multiple - with single - + .replace(/^-+/, '') // Trim - from start of text + .replace(/-+$/, '') // Trim - from end of text + } +} + +CreateTeamDialog.propTypes = { + classes: PropTypes.object.isRequired, + authId: PropTypes.string +} + +export default withStyles(styles)(CreateTeamDialog) diff --git a/client/src/views/dashboard/components/DashTeam.js b/client/src/views/dashboard/components/DashTeam.js index cad20bf57..8201e9d4d 100644 --- a/client/src/views/dashboard/components/DashTeam.js +++ b/client/src/views/dashboard/components/DashTeam.js @@ -2,6 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import { Query } from 'react-apollo' import { withStateHandlers, lifecycle, compose } from 'recompose' +import { Link } from 'react-router-dom' import Typography from '@material-ui/core/Typography' import Grid from '@material-ui/core/Grid' @@ -9,7 +10,8 @@ import Grid from '@material-ui/core/Grid' import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' import DashTeamItem from './DashTeamItem' -import CreateTeamWrapper from './CreateTeamWrapper' +import CreateTeamDialog from './CreateTeamDialog' +import { MessageCard } from '../../common/' import { isDefined, isString } from '../../../utils/js-helpers' import { getItem } from '../../../utils/local-storage' @@ -38,11 +40,10 @@ export const DashTeam = ({ classes, user = null }) => { ) } return ( - + - Teams + Teams Manage Teams - {({ loading, error, data }) => { console.log('GET_TEAMS_BY_OWNER: ', loading, error, data) @@ -70,6 +71,16 @@ export const DashTeam = ({ classes, user = null }) => { {loader} ) + } else { + return ( + + + + + + + + ) } } else { return ( diff --git a/client/src/views/dashboard/components/ManageTeamDelete.js b/client/src/views/dashboard/components/ManageTeamDelete.js new file mode 100644 index 000000000..231dbab14 --- /dev/null +++ b/client/src/views/dashboard/components/ManageTeamDelete.js @@ -0,0 +1,130 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import { withRouter } from 'react-router-dom' +import { Mutation } from 'react-apollo' + +import Button from '@material-ui/core/Button' +import DeleteIcon from '@material-ui/icons/Delete' +import Dialog from '@material-ui/core/Dialog' +import DialogActions from '@material-ui/core/DialogActions' +import DialogContent from '@material-ui/core/DialogContent' +import DialogTitle from '@material-ui/core/DialogTitle' +import Typography from '@material-ui/core/Typography' + +import DELETE_TEAM from '../../../graphql/teams/DeleteTeamMutation' +import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' + +import { checkGraphQLError } from '../../../utils/graphql-errors' + +export class ManageTeamDelete extends Component { + constructor (props) { + super(props) + + this.handleClickOpen = this.handleClickOpen.bind(this) + this.handleClose = this.handleClose.bind(this) + this.handleChange = this.handleChange.bind(this) + this.handleSubmit = this.handleSubmit.bind(this) + + this.state = { + open: false, + motto: '', + description: '' + } + } + + handleClickOpen () { + this.setState({ open: true }) + } + + handleClose () { + this.setState({ open: false }) + } + + handleChange (e) { + this.setState({ name: e.target.value }) + } + + render () { + console.log(this.props, this.props.slug) + const authId = this.props.authId + return ( + { + const data = cache.readQuery({ query: GET_TEAMS_BY_OWNER }) + console.log('Mutation cache update: ', deleteTeam, data) + data.getTeamsByOwner.push(deleteTeam) + cache.writeQuery({ query: GET_TEAMS_BY_OWNER, data }) + }} + > + {(deleteTeam, { loading, error, data }) => { + let errors + let loader + if (loading) { + loader = Submitting team... + } + if (error) { + errors = error.graphQLErrors.map(({ message }, i) => { + const displayMessage = checkGraphQLError(message) + console.log('createTeam error:', displayMessage) + return ( + + {message} + + ) + }) + } + return ( +
+ + + Delete Team Team + + DANGER - Deleting your team cannot be undone + Are you sure you want to delete this team? + {loader} + {errors} + + + + + + +
+ ) + }} +
+ ) + } + + async handleSubmit (e, deleteTeam, slug, authId) { + e.preventDefault() + await deleteTeam({ variables: { slug, owner: authId } }) + } +} + +ManageTeamDelete.propTypes = { + classes: PropTypes.object.isRequired, + slug: PropTypes.string.isRequired, + authId: PropTypes.string.isRequired +} + +export default withRouter(ManageTeamDelete) diff --git a/client/src/views/dashboard/components/ManageTeamEdit.js b/client/src/views/dashboard/components/ManageTeamEdit.js index d10dd5728..6937cc7f9 100644 --- a/client/src/views/dashboard/components/ManageTeamEdit.js +++ b/client/src/views/dashboard/components/ManageTeamEdit.js @@ -1,8 +1,10 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import { withRouter } from 'react-router-dom' +import { Mutation } from 'react-apollo' + import Button from '@material-ui/core/Button' -import AddIcon from '@material-ui/icons/Add' +import EditIcon from '@material-ui/icons/Edit' import TextField from '@material-ui/core/TextField' import Dialog from '@material-ui/core/Dialog' import DialogActions from '@material-ui/core/DialogActions' @@ -13,15 +15,19 @@ import Typography from '@material-ui/core/Typography' import { getItem } from '../../../utils/local-storage' +import UPDATE_TEAM_PROFILE from '../../../graphql/teams/UpdateTeamProfileMutation' +import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' + +import { checkGraphQLError } from '../../../utils/graphql-errors' + export class ManageTeamEdit extends Component { constructor (props) { super(props) this.handleClickOpen = this.handleClickOpen.bind(this) this.handleClose = this.handleClose.bind(this) - this.handlePost = this.handlePost.bind(this) - this.slugify = this.slugify.bind(this) this.handleChange = this.handleChange.bind(this) + this.handleSubmit = this.handleSubmit.bind(this) this.state = { open: false, @@ -30,6 +36,101 @@ export class ManageTeamEdit extends Component { } } + render () { + console.log(this.props, this.props.slug) + return ( + { + const data = cache.readQuery({ query: GET_TEAMS_BY_OWNER }) + console.log('Mutation cache update: ', deleteTeam, data) + data.getTeamsByOwner.push(deleteTeam) + cache.writeQuery({ query: GET_TEAMS_BY_OWNER, data }) + }} + > + {(updateTeamProfile, { loading, error, data }) => { + let errors + let loader + let description + let motto + if (loading) { + loader = Submitting team... + } + if (error) { + errors = error.graphQLErrors.map(({ message }, i) => { + const displayMessage = checkGraphQLError(message) + console.log('updateTeamProfile error:', displayMessage) + return ( + + {message} + + ) + }) + } + return ( +
+ + + Edit Team Details + + Team Creation + Team Motto: + { + motto = node + }} + /> + Team description: + { + description = node + }} + /> + {loader} + {errors} + + + + + + +
+ ) + }} +
+ ) + } + handleClickOpen () { this.setState({ open: true }) } @@ -39,95 +140,29 @@ export class ManageTeamEdit extends Component { } handleChange (e) { - this.setState({ name: e.target.value }) + switch (e.target.id) { + case 'motto': + this.setState({ motto: e.target.value }) + break + case 'description': + this.setState({ description: e.target.value }) + break + default: + } } - render () { - console.log(this.props, this.props.team) - return ( -
- - - Edit Team Details - - Team Creation - Team Motto: - - - - - - - -
- ) - } - - slugify (string) { - const a = 'àáäâãåèéëêìíïîòóöôùúüûñçßÿœæŕśńṕẃǵǹḿǘẍźḧ·/_,:;' - const b = 'aaaaaaeeeeiiiioooouuuuncsyoarsnpwgnmuxzh------' - const p = new RegExp(a.split('').join('|'), 'g') - - return string - .toString() - .toLowerCase() - .replace(/\s+/g, '-') // Replace spaces with - - .replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters - .replace(/&/g, '-and-') // Replace & with 'and' - .replace(/[^\w-]+/g, '') // Remove all non-word characters - .replace(/--+/g, '-') // Replace multiple - with single - - .replace(/^-+/, '') // Trim - from start of text - .replace(/-+$/, '') // Trim - from end of text - } - - async handlePost (e) { + async handleSubmit (e, updateTeamProfile, slug, description, motto) { e.preventDefault() - const { name } = this.state - const slug = this.slugify(name) const currentUser = await getItem('user') let authId = JSON.parse(currentUser) - authId = authId.sub - console.log('createPage cu:', JSON.parse(currentUser)) - await this.props.createTeamMutation({ - variables: { - name, - slug, - owner: authId - } - }) - this.setState({ open: false }) + authId = authId.authId + await updateTeamProfile({ variables: { slug, owner: authId, description: description, motto: motto } }) } } ManageTeamEdit.propTypes = { classes: PropTypes.object.isRequired, - team: PropTypes.object.isRequired, - createTeamMutation: PropTypes.function + slug: PropTypes.string.isRequired } export default withRouter(ManageTeamEdit) diff --git a/client/src/views/dashboard/components/ManageTeamsItem.js b/client/src/views/dashboard/components/ManageTeamsItem.js index fdb6534f4..f84fe3d40 100644 --- a/client/src/views/dashboard/components/ManageTeamsItem.js +++ b/client/src/views/dashboard/components/ManageTeamsItem.js @@ -10,8 +10,9 @@ import Button from '@material-ui/core/Button' import Typography from '@material-ui/core/Typography' import ManageTeamDelete from './ManageTeamDelete' +import ManageTeamEdit from './ManageTeamEdit' -export const ManageTeamsItem = ({ classes, team }) => ( +export const ManageTeamsItem = ({ classes, team, authId }) => (
@@ -32,10 +33,8 @@ export const ManageTeamsItem = ({ classes, team }) => ( - - + +
@@ -44,7 +43,8 @@ export const ManageTeamsItem = ({ classes, team }) => ( ManageTeamsItem.propTypes = { classes: PropTypes.object.isRequired, - team: PropTypes.object.isRequired + team: PropTypes.object.isRequired, + authId: PropTypes.string.isRequired } export default ManageTeamsItem diff --git a/client/src/views/dashboard/components/ManageTeamsList.js b/client/src/views/dashboard/components/ManageTeamsList.js index c15316e60..6a6bebde4 100644 --- a/client/src/views/dashboard/components/ManageTeamsList.js +++ b/client/src/views/dashboard/components/ManageTeamsList.js @@ -3,7 +3,6 @@ import PropTypes from 'prop-types' import { Query } from 'react-apollo' import { withStateHandlers, lifecycle, compose } from 'recompose' -import Typography from '@material-ui/core/Typography' import Grid from '@material-ui/core/Grid' import { withStyles } from '@material-ui/core/styles' @@ -13,6 +12,8 @@ import { getItem } from '../../../utils/local-storage' import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' import ManageTeamsItem from './ManageTeamsItem' +import CreateTeamDialog from './CreateTeamDialog' +import { MessageCard } from '../../common/' const styles = theme => ({ heroContent: { @@ -55,53 +56,74 @@ export const ManageTeamsList = ({ classes, user = null }) => { if (isDefined(owner.authId)) authId = owner.authId } console.log('ManageTeamsList 2: ', owner, authId) + if (authId === undefined || authId === null) { + return ( + + + + + + ) + } else { + return ( + + {({ loading, error, data }) => { + console.log('GET_TEAMS_BY_OWNER: ', loading, error, data) - return ( - - {({ loading, error, data }) => { - console.log('GET_TEAMS_BY_OWNER: ', loading, error, data) - - let errors - if (error) { - errors = error.graphQLErrors.map(({ message }, i) => { - return ( - - {message} - - ) - }) - } - if (!loading && !error) { - if (data.teamsByOwner.length > 0) { - return ( - + let errors = null + if (error) { + errors = error.graphQLErrors.map(({ message }, i) => { + return ( + + ) + }) + } + if (!loading && !error) { + if (data.teamsByOwner.length > 0) { + return ( + + + {!loading && + data.teamsByOwner.map(team => ( + + ))} + + + + {errors} + + + ) + } else { + return ( - {!loading && - data.teamsByOwner.map(team => ( - - ))} - {errors} + + + + + - + ) + } + } else { + return ( + + + + if (errors !== null) () + + ) } - } else { - return ( - - - Loading... - - {errors} - - ) - } - }} - - ) + }} + + ) + } } ManageTeamsList.propTypes = { From 59028023a827ff5ce853f6fc64f742d6f9ff789e Mon Sep 17 00:00:00 2001 From: Barry Low Date: Sun, 16 Sep 2018 23:29:23 -0700 Subject: [PATCH 13/19] Client: Manage Team Edit Details Dialog --- api/database/datamodel.graphql | 1 + api/src/index.js | 2 +- client/src/views/common/MessageCard.js | 2 +- .../dashboard/components/CreateTeamDialog.js | 2 +- .../views/dashboard/components/DashTeam.js | 2 +- .../dashboard/components/ManageTeamEdit.js | 35 ++++++++----------- .../dashboard/components/ManageTeamsList.js | 4 +-- 7 files changed, 21 insertions(+), 27 deletions(-) diff --git a/api/database/datamodel.graphql b/api/database/datamodel.graphql index 7a55f466d..ddc89814c 100644 --- a/api/database/datamodel.graphql +++ b/api/database/datamodel.graphql @@ -42,6 +42,7 @@ type TeamProfile { motto: String avatar: String updatedAt: DateTime! + createdAt: DateTime! } type TeamStatus { diff --git a/api/src/index.js b/api/src/index.js index 8f3670a7a..d640b8682 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -94,7 +94,7 @@ const resolvers = { return member }, async createTeam(parent, { name, slug, owner }, ctx, info) { - return ctx.db.mutation.createTeam({ data: { name: name, slug: slug, owner: owner, members: { create: { member:{ connect:{ authId: owner} }, role: 'OWNER' } } } }, TEAMS_FRAGMENT) + return ctx.db.mutation.createTeam({ data: { name: name, slug: slug, owner: owner, members: { create: { member:{ connect:{ authId: owner} }, role: 'OWNER' } }, profile:{create:{avatar:"a"} } } }, TEAMS_FRAGMENT) .catch((err) => { console.log('createTeam error: ', err) return err diff --git a/client/src/views/common/MessageCard.js b/client/src/views/common/MessageCard.js index 60668fd62..9c45891d0 100644 --- a/client/src/views/common/MessageCard.js +++ b/client/src/views/common/MessageCard.js @@ -37,7 +37,7 @@ export const MessageCard = ({ classes, message, children }) => ( MessageCard.propTypes = { children: PropTypes.node, classes: PropTypes.object.isRequired, - message: PropTypes.string.isRequired + message: PropTypes.string } export default withStyles(styles)(MessageCard) diff --git a/client/src/views/dashboard/components/CreateTeamDialog.js b/client/src/views/dashboard/components/CreateTeamDialog.js index 66e0f00e5..4db5b5638 100644 --- a/client/src/views/dashboard/components/CreateTeamDialog.js +++ b/client/src/views/dashboard/components/CreateTeamDialog.js @@ -109,7 +109,7 @@ export class CreateTeamDialog extends Component { fullWidth value={this.state.name} onChange={this.handleChange} - error={e => this.state.errors.name !== '' || error} + error={this.state.errors.name !== '' || error} /> {this.state.errors.name !== '' && ({this.state.errors.name})} {error && ({errors})} diff --git a/client/src/views/dashboard/components/DashTeam.js b/client/src/views/dashboard/components/DashTeam.js index 8201e9d4d..1213f7eb1 100644 --- a/client/src/views/dashboard/components/DashTeam.js +++ b/client/src/views/dashboard/components/DashTeam.js @@ -74,7 +74,7 @@ export const DashTeam = ({ classes, user = null }) => { } else { return ( - + diff --git a/client/src/views/dashboard/components/ManageTeamEdit.js b/client/src/views/dashboard/components/ManageTeamEdit.js index 6937cc7f9..6fc498144 100644 --- a/client/src/views/dashboard/components/ManageTeamEdit.js +++ b/client/src/views/dashboard/components/ManageTeamEdit.js @@ -38,21 +38,20 @@ export class ManageTeamEdit extends Component { render () { console.log(this.props, this.props.slug) + const { authId } = this.props return ( { - const data = cache.readQuery({ query: GET_TEAMS_BY_OWNER }) - console.log('Mutation cache update: ', deleteTeam, data) - data.getTeamsByOwner.push(deleteTeam) - cache.writeQuery({ query: GET_TEAMS_BY_OWNER, data }) - }} + refetchQueries={[ + { + query: GET_TEAMS_BY_OWNER, + variables: { authId } + } + ]} > {(updateTeamProfile, { loading, error, data }) => { let errors let loader - let description - let motto if (loading) { loader = Submitting team... } @@ -84,21 +83,17 @@ export class ManageTeamEdit extends Component { { - motto = node - }} /> Team description: { - description = node - }} /> {loader} {errors} @@ -118,7 +110,7 @@ export class ManageTeamEdit extends Component { Cancel @@ -151,18 +143,19 @@ export class ManageTeamEdit extends Component { } } - async handleSubmit (e, updateTeamProfile, slug, description, motto) { + async handleSubmit (e, updateTeamProfile, slug) { e.preventDefault() const currentUser = await getItem('user') let authId = JSON.parse(currentUser) authId = authId.authId - await updateTeamProfile({ variables: { slug, owner: authId, description: description, motto: motto } }) + await updateTeamProfile({ variables: { slug, owner: authId, description: this.state.description, motto: this.state.motto } }) } } ManageTeamEdit.propTypes = { classes: PropTypes.object.isRequired, - slug: PropTypes.string.isRequired + slug: PropTypes.string.isRequired, + authId: PropTypes.string } export default withRouter(ManageTeamEdit) diff --git a/client/src/views/dashboard/components/ManageTeamsList.js b/client/src/views/dashboard/components/ManageTeamsList.js index 6a6bebde4..5a5349e86 100644 --- a/client/src/views/dashboard/components/ManageTeamsList.js +++ b/client/src/views/dashboard/components/ManageTeamsList.js @@ -102,7 +102,7 @@ export const ManageTeamsList = ({ classes, user = null }) => { } else { return ( - + @@ -113,7 +113,7 @@ export const ManageTeamsList = ({ classes, user = null }) => { } else { return ( - + if (errors !== null) () From 8858626d8edfd59316fddac84ba00ca1610325da Mon Sep 17 00:00:00 2001 From: Barry Low Date: Sun, 16 Sep 2018 23:50:19 -0700 Subject: [PATCH 14/19] Client: Manage Team Details Dialog --- .../dashboard/components/ManageTeamDetails.js | 94 +++++++++++++++++++ .../dashboard/components/ManageTeamEdit.js | 11 ++- .../components/ManageTeamsDetails.js | 89 ------------------ .../dashboard/components/ManageTeamsItem.js | 8 +- 4 files changed, 104 insertions(+), 98 deletions(-) create mode 100644 client/src/views/dashboard/components/ManageTeamDetails.js delete mode 100644 client/src/views/dashboard/components/ManageTeamsDetails.js diff --git a/client/src/views/dashboard/components/ManageTeamDetails.js b/client/src/views/dashboard/components/ManageTeamDetails.js new file mode 100644 index 000000000..b9420b564 --- /dev/null +++ b/client/src/views/dashboard/components/ManageTeamDetails.js @@ -0,0 +1,94 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' + +import Button from '@material-ui/core/Button' +import DetailsIcon from '@material-ui/icons/Details' +import Dialog from '@material-ui/core/Dialog' +import DialogActions from '@material-ui/core/DialogActions' +import DialogContent from '@material-ui/core/DialogContent' +import DialogTitle from '@material-ui/core/DialogTitle' +import Typography from '@material-ui/core/Typography' + +export class ManageTeamDetails extends Component { + constructor (props) { + super(props) + + this.handleClickOpen = this.handleClickOpen.bind(this) + this.handleClose = this.handleClose.bind(this) + + this.state = { + open: false + } + } + + render () { + console.log(this.props.team) + const { name, members, profile, createdAt } = this.props.team + return ( +
+ + + {name} Team Details + + + {name} + + + {createdAt} + + + Motto: {profile.motto} + + + Description: {profile.description} + + + Members: {members.length} + + + Team Admin: + { + members.map(member => { + if (member.role === 'OWNER' || member.role === 'ADMIN') { + return member.member.alias + } + }) + } + + + + + + +
+ ) + } + + handleClickOpen () { + this.setState({ open: true }) + } + + handleClose () { + this.setState({ open: false }) + } +} + +ManageTeamDetails.propTypes = { + classes: PropTypes.object.isRequired, + team: PropTypes.any +} + +export default ManageTeamDetails diff --git a/client/src/views/dashboard/components/ManageTeamEdit.js b/client/src/views/dashboard/components/ManageTeamEdit.js index 6fc498144..92def9d44 100644 --- a/client/src/views/dashboard/components/ManageTeamEdit.js +++ b/client/src/views/dashboard/components/ManageTeamEdit.js @@ -28,11 +28,13 @@ export class ManageTeamEdit extends Component { this.handleClose = this.handleClose.bind(this) this.handleChange = this.handleChange.bind(this) this.handleSubmit = this.handleSubmit.bind(this) - + console.log('ManageTeamEdit', props.team) + const motto = props.team.profile.motto + const description = props.team.profile.description this.state = { open: false, - motto: '', - description: '' + motto: motto, + description: description } } @@ -155,7 +157,8 @@ export class ManageTeamEdit extends Component { ManageTeamEdit.propTypes = { classes: PropTypes.object.isRequired, slug: PropTypes.string.isRequired, - authId: PropTypes.string + authId: PropTypes.string, + team: PropTypes.object } export default withRouter(ManageTeamEdit) diff --git a/client/src/views/dashboard/components/ManageTeamsDetails.js b/client/src/views/dashboard/components/ManageTeamsDetails.js deleted file mode 100644 index 65a988215..000000000 --- a/client/src/views/dashboard/components/ManageTeamsDetails.js +++ /dev/null @@ -1,89 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' - -import CssBaseline from '@material-ui/core/CssBaseline' -import Typography from '@material-ui/core/Typography' -import Paper from '@material-ui/core/Paper' -import { withStyles } from '@material-ui/core/styles' - -import { Link } from 'react-router-dom' - -const styles = theme => ({ - root: { - flexGrow: 1 - }, - '@global': { - body: { - backgroundColor: theme.palette.common.white - } - }, - layout: { - width: 'auto', - marginLeft: theme.spacing.unit * 3, - marginRight: theme.spacing.unit * 3, - marginBottom: theme.spacing.unit * 6, - [theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: { - width: 900, - marginLeft: 'auto', - marginRight: 'auto' - } - }, - paper: { - marginTop: theme.spacing.unit * 3, - marginBottom: theme.spacing.unit * 3, - padding: theme.spacing.unit * 2, - [theme.breakpoints.up(600 + theme.spacing.unit * 3 * 2)]: { - marginTop: theme.spacing.unit * 6, - marginBottom: theme.spacing.unit * 6, - padding: theme.spacing.unit * 3 - } - }, - heroContent: { - maxWidth: 600, - margin: '0 auto', - padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px` - } -}) - -const ManageTeamsDetails = ({ classes, team }) => ( - - -
- -
- ← Back to all teams - - {team.name} - - - {team.createdAt} - - - Members: {team.members.length} - - - Team Admin: - { - team.members.map(member => { - if (member.role === 'OWNER' || member.role === 'ADMIN') { - return member.member.alias - } - }) - } - -
-
-
-
-) -ManageTeamsDetails.propTypes = { - classes: PropTypes.object.isRequired, - team: PropTypes.object.isRequired -} - -export default withStyles(styles)(ManageTeamsDetails) diff --git a/client/src/views/dashboard/components/ManageTeamsItem.js b/client/src/views/dashboard/components/ManageTeamsItem.js index f84fe3d40..8552bfaf5 100644 --- a/client/src/views/dashboard/components/ManageTeamsItem.js +++ b/client/src/views/dashboard/components/ManageTeamsItem.js @@ -6,9 +6,9 @@ import Card from '@material-ui/core/Card' import CardActions from '@material-ui/core/CardActions' import CardContent from '@material-ui/core/CardContent' import CardMedia from '@material-ui/core/CardMedia' -import Button from '@material-ui/core/Button' import Typography from '@material-ui/core/Typography' +import ManageTeamDetails from './ManageTeamDetails' import ManageTeamDelete from './ManageTeamDelete' import ManageTeamEdit from './ManageTeamEdit' @@ -30,10 +30,8 @@ export const ManageTeamsItem = ({ classes, team, authId }) => (
- - + +
From 2e44917491805ae40aff4c96c93686bf5e0737d5 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Mon, 17 Sep 2018 08:14:58 -0700 Subject: [PATCH 15/19] Client: Component style cleanup --- client/src/App.js | 2 + client/src/views/about/index.js | 61 ++++++++++ client/src/views/dashboard/TeamMembers.js | 4 +- .../dashboard/components/DashTeamItem.js | 3 - .../views/dashboard/components/DrawerLinks.js | 6 +- .../dashboard/components/ManageTeamDelete.js | 55 +++++---- .../dashboard/components/ManageTeamDetails.js | 92 +++++++++------ .../dashboard/components/ManageTeamEdit.js | 111 +++++++++++------- .../dashboard/components/ManageTeamsItem.js | 6 +- client/src/views/dashboard/settings.js | 4 +- client/src/views/footer/index.js | 16 +-- client/src/views/index.js | 3 +- 12 files changed, 238 insertions(+), 125 deletions(-) create mode 100644 client/src/views/about/index.js diff --git a/client/src/App.js b/client/src/App.js index 241fa8d1b..652531151 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -20,6 +20,7 @@ import { Footer, Callback, Home, + About, Dashboard, Teams, theme, @@ -149,6 +150,7 @@ class App extends Component { + ({ + '@global': { + body: { + backgroundColor: theme.palette.common.white + } + }, + layout: { + width: 'auto', + marginLeft: theme.spacing.unit * 3, + marginRight: theme.spacing.unit * 3, + [theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: { + width: 900, + marginLeft: 'auto', + marginRight: 'auto' + } + }, + heroContent: { + maxWidth: 600, + margin: '0 auto', + padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px` + } +}) + +const About = ({ classes }) => ( + + +
+
+ + Collaborate. Innovate. Evolve. + + + Welcome to the Advanced Algos Teams Module + +
+
+
+) + +About.propTypes = { + classes: PropTypes.object.isRequired +} + +export default withStyles(styles)(About) diff --git a/client/src/views/dashboard/TeamMembers.js b/client/src/views/dashboard/TeamMembers.js index a22de3714..8b2b43aeb 100644 --- a/client/src/views/dashboard/TeamMembers.js +++ b/client/src/views/dashboard/TeamMembers.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types' import Typography from '@material-ui/core/Typography' import { withStyles } from '@material-ui/core/styles' -import { TeamTable } from './components/TeamTable' +import { MessageCard } from '../common/' const styles = theme => ({ tableContainer: { @@ -18,7 +18,7 @@ const TeamMembers = ({ classes }) => ( Members
- +
) diff --git a/client/src/views/dashboard/components/DashTeamItem.js b/client/src/views/dashboard/components/DashTeamItem.js index 1de33a7a4..b5210e73c 100644 --- a/client/src/views/dashboard/components/DashTeamItem.js +++ b/client/src/views/dashboard/components/DashTeamItem.js @@ -51,9 +51,6 @@ export const DashTeamItem = ({ classes, team }) => ( Members:6 - - Now recruiting! - - Delete Team Team - - DANGER - Deleting your team cannot be undone - Are you sure you want to delete this team? - {loader} - {errors} - - - - - +
+ Delete Team Team + + DANGER - Deleting your team cannot be undone + Are you sure you want to delete this team? + {loader} + {errors} + + + + + +
) @@ -127,4 +140,4 @@ ManageTeamDelete.propTypes = { authId: PropTypes.string.isRequired } -export default withRouter(ManageTeamDelete) +export default withStyles(styles)(ManageTeamDelete) diff --git a/client/src/views/dashboard/components/ManageTeamDetails.js b/client/src/views/dashboard/components/ManageTeamDetails.js index b9420b564..183db0ea8 100644 --- a/client/src/views/dashboard/components/ManageTeamDetails.js +++ b/client/src/views/dashboard/components/ManageTeamDetails.js @@ -1,5 +1,6 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' +import { withStyles } from '@material-ui/core/styles' import Button from '@material-ui/core/Button' import DetailsIcon from '@material-ui/icons/Details' @@ -9,6 +10,17 @@ import DialogContent from '@material-ui/core/DialogContent' import DialogTitle from '@material-ui/core/DialogTitle' import Typography from '@material-ui/core/Typography' +const styles = theme => ({ + dialogContainer: { + display: 'block', + margin: '3em', + minWidth: 400 + }, + buttonRight: { + justifyContent: 'flex-end' + } +}) + export class ManageTeamDetails extends Component { constructor (props) { super(props) @@ -34,44 +46,46 @@ export class ManageTeamDetails extends Component { onClose={this.handleClose} aria-labelledby='form-dialog-title' > - {name} Team Details - - - {name} - - - {createdAt} - - - Motto: {profile.motto} - - - Description: {profile.description} - - - Members: {members.length} - - - Team Admin: - { - members.map(member => { - if (member.role === 'OWNER' || member.role === 'ADMIN') { - return member.member.alias - } - }) - } - - - - - +
+ {name} Team Details + + + {name} + + + {createdAt} + + + Motto: {profile.motto} + + + Description: {profile.description} + + + Members: {members.length} + + + Team Admin: + { + members.map(member => { + if (member.role === 'OWNER' || member.role === 'ADMIN') { + return member.member.alias + } + }) + } + + + + + +
) @@ -91,4 +105,4 @@ ManageTeamDetails.propTypes = { team: PropTypes.any } -export default ManageTeamDetails +export default withStyles(styles)(ManageTeamDetails) diff --git a/client/src/views/dashboard/components/ManageTeamEdit.js b/client/src/views/dashboard/components/ManageTeamEdit.js index 92def9d44..7db8b46be 100644 --- a/client/src/views/dashboard/components/ManageTeamEdit.js +++ b/client/src/views/dashboard/components/ManageTeamEdit.js @@ -1,7 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' -import { withRouter } from 'react-router-dom' import { Mutation } from 'react-apollo' +import { withStyles } from '@material-ui/core/styles' import Button from '@material-ui/core/Button' import EditIcon from '@material-ui/icons/Edit' @@ -20,6 +20,17 @@ import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' import { checkGraphQLError } from '../../../utils/graphql-errors' +const styles = theme => ({ + dialogContainer: { + display: 'block', + margin: '3em', + minWidth: 400 + }, + buttonRight: { + justifyContent: 'flex-end' + } +}) + export class ManageTeamEdit extends Component { constructor (props) { super(props) @@ -29,8 +40,8 @@ export class ManageTeamEdit extends Component { this.handleChange = this.handleChange.bind(this) this.handleSubmit = this.handleSubmit.bind(this) console.log('ManageTeamEdit', props.team) - const motto = props.team.profile.motto - const description = props.team.profile.description + const motto = props.team.profile.motto || '' + const description = props.team.profile.description || '' this.state = { open: false, motto: motto, @@ -40,7 +51,7 @@ export class ManageTeamEdit extends Component { render () { console.log(this.props, this.props.slug) - const { authId } = this.props + const { classes, team, authId } = this.props return ( - - Edit Team Details - - Team Creation - Team Motto: - - Team description: - - {loader} - {errors} - - - - - +
+ Edit Team Details + + + + Team description: + + {loader} + {errors} + + + + + +
) @@ -161,4 +182,4 @@ ManageTeamEdit.propTypes = { team: PropTypes.object } -export default withRouter(ManageTeamEdit) +export default withStyles(styles)(ManageTeamEdit) diff --git a/client/src/views/dashboard/components/ManageTeamsItem.js b/client/src/views/dashboard/components/ManageTeamsItem.js index 8552bfaf5..378dde27e 100644 --- a/client/src/views/dashboard/components/ManageTeamsItem.js +++ b/client/src/views/dashboard/components/ManageTeamsItem.js @@ -30,9 +30,9 @@ export const ManageTeamsItem = ({ classes, team, authId }) => ( - - - + + + diff --git a/client/src/views/dashboard/settings.js b/client/src/views/dashboard/settings.js index a9ee58b58..d28df4d79 100644 --- a/client/src/views/dashboard/settings.js +++ b/client/src/views/dashboard/settings.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types' import Typography from '@material-ui/core/Typography' import { withStyles } from '@material-ui/core/styles' -import { TeamTable } from './components/TeamTable' +import { MessageCard } from '../common/' const styles = theme => ({ tableContainer: { @@ -18,7 +18,7 @@ export const Settings = ({ classes }) => ( Settings
- +
) diff --git a/client/src/views/footer/index.js b/client/src/views/footer/index.js index a7abff6b7..ecbd0c594 100644 --- a/client/src/views/footer/index.js +++ b/client/src/views/footer/index.js @@ -55,26 +55,28 @@ const Footer = ({ classes }) => { Home - + Teams - + About - - Support - - +
+ + Support + + + Documentation - + Telegram diff --git a/client/src/views/index.js b/client/src/views/index.js index 6759b33df..8ff455e85 100644 --- a/client/src/views/index.js +++ b/client/src/views/index.js @@ -2,9 +2,10 @@ import NavBar from './navbar' import Footer from './footer' import Callback from './callback' import Home from './home' +import About from './about' import Dashboard from './dashboard' import Teams from './teams' import { theme, globalStyles } from './theme' -export { NavBar, Footer, Callback, Home, Dashboard, Teams, theme, globalStyles } +export { NavBar, Footer, Callback, Home, About, Dashboard, Teams, theme, globalStyles } From 5364b2eff2e0cbba181d0c919f3ffba14efd6868 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Mon, 17 Sep 2018 08:30:59 -0700 Subject: [PATCH 16/19] Client: style navbar --- .../logos/advanced-algos/aa-logo-dark.svg | 1 + client/src/views/navbar/index.js | 18 +++++++++++++++--- client/src/views/theme.js | 4 ++-- 3 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 client/src/assets/logos/advanced-algos/aa-logo-dark.svg diff --git a/client/src/assets/logos/advanced-algos/aa-logo-dark.svg b/client/src/assets/logos/advanced-algos/aa-logo-dark.svg new file mode 100644 index 000000000..479feeb86 --- /dev/null +++ b/client/src/assets/logos/advanced-algos/aa-logo-dark.svg @@ -0,0 +1 @@ +aa-logo-dark \ No newline at end of file diff --git a/client/src/views/navbar/index.js b/client/src/views/navbar/index.js index 34fd52f5f..ca33893d2 100644 --- a/client/src/views/navbar/index.js +++ b/client/src/views/navbar/index.js @@ -20,6 +20,8 @@ import { getItem } from '../../utils/local-storage' import { LoggedIn } from './LoggedIn' import { LoggedOut } from './LoggedOut' +import AALogo from '../../assets/logos/advanced-algos/aa-logo-dark.svg' + const AboutLink = props => const TeamsLink = props => const DashboardLink = props => @@ -34,6 +36,9 @@ const styles = theme => ({ root: { flexGrow: 1 }, + colorDefault: { + color: '#000' + }, flex: { flexGrow: 1 }, @@ -46,6 +51,12 @@ const styles = theme => ({ }, appBar: { position: 'relative' + }, + img: { + margin: 20, + display: 'block', + maxWidth: 240, + maxHeight: 48 } }) @@ -71,8 +82,9 @@ class NavBar extends Component { return (
- + + Advanced Algos - - + + {this.state.user !== undefined && this.state.user !== null ? ( diff --git a/client/src/views/theme.js b/client/src/views/theme.js index 4a2e00ee8..26043dfc0 100644 --- a/client/src/views/theme.js +++ b/client/src/views/theme.js @@ -1,10 +1,10 @@ import { createMuiTheme } from '@material-ui/core/styles' import indigo from '@material-ui/core/colors/indigo' -import red from '@material-ui/core/colors/red' +// import red from '@material-ui/core/colors/red' export const theme = createMuiTheme({ palette: { - primary: red, + primary: { main: '#303036' }, secondary: indigo }, typography: { From 54b735f9d5c52791aebbc88daca9c6c6e1b84ec0 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Mon, 17 Sep 2018 12:39:45 -0700 Subject: [PATCH 17/19] Client: simplify to pass user info via props --- client/src/views/dashboard/FinancialBeings.js | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 client/src/views/dashboard/FinancialBeings.js diff --git a/client/src/views/dashboard/FinancialBeings.js b/client/src/views/dashboard/FinancialBeings.js new file mode 100644 index 000000000..be6ac2aba --- /dev/null +++ b/client/src/views/dashboard/FinancialBeings.js @@ -0,0 +1,30 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import Typography from '@material-ui/core/Typography' +import { withStyles } from '@material-ui/core/styles' + +import { MessageCard } from '../common/' + +const styles = theme => ({ + tableContainer: { + height: 320 + } +}) + +const FinancialBeings = ({ classes }) => ( +
+ + Financial Beings + +
+ +
+
+) + +FinancialBeings.propTypes = { + classes: PropTypes.object.isRequired +} + +export default withStyles(styles)(FinancialBeings) From 6ddfb7d0af951aee308af4ed0e6a8aa73925ce78 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Mon, 17 Sep 2018 12:40:02 -0700 Subject: [PATCH 18/19] Client: simplify to pass user info via props --- .../teams/UpdateTeamProfileMutation.js | 14 +++++- client/src/views/common/MessageCard.js | 4 +- client/src/views/dashboard/TeamMembers.js | 2 +- .../dashboard/components/CreateTeamDialog.js | 41 ++++++++++------ .../views/dashboard/components/DashTeam.js | 5 +- .../dashboard/components/DashTeamItem.js | 9 ++-- .../views/dashboard/components/DrawerLinks.js | 12 ++++- .../dashboard/components/ManageTeamDelete.js | 48 ++++++++++++------- .../dashboard/components/ManageTeamDetails.js | 23 +++++---- .../dashboard/components/ManageTeamEdit.js | 34 ++++++++++--- .../dashboard/components/ManageTeamsList.js | 12 +++-- client/src/views/footer/index.js | 12 ++++- client/src/views/index.js | 12 ++++- client/src/views/navbar/index.js | 13 +++-- .../views/teams/components/TeamsDetails.js | 20 ++++---- .../src/views/teams/components/TeamsItem.js | 2 +- .../src/views/teams/components/TeamsList.js | 7 +-- 17 files changed, 186 insertions(+), 84 deletions(-) diff --git a/client/src/graphql/teams/UpdateTeamProfileMutation.js b/client/src/graphql/teams/UpdateTeamProfileMutation.js index 6da940d4c..4a63adffe 100644 --- a/client/src/graphql/teams/UpdateTeamProfileMutation.js +++ b/client/src/graphql/teams/UpdateTeamProfileMutation.js @@ -2,8 +2,18 @@ import gql from 'graphql-tag' const UPDATE_TEAM_PROFILE = gql` - mutation UpdateTeamProfileMutation($slug: String!, $owner: String!, $description: String, $motto: String) { - updateTeamProfile(slug: $slug, owner: $owner, description: $description, motto: $motto) { + mutation UpdateTeamProfileMutation( + $slug: String! + $owner: String! + $description: String + $motto: String + ) { + updateTeamProfile( + slug: $slug + owner: $owner + description: $description + motto: $motto + ) { id name slug diff --git a/client/src/views/common/MessageCard.js b/client/src/views/common/MessageCard.js index 9c45891d0..fff952915 100644 --- a/client/src/views/common/MessageCard.js +++ b/client/src/views/common/MessageCard.js @@ -27,7 +27,9 @@ export const MessageCard = ({ classes, message, children }) => (
- {message} + + {message} + {children}
diff --git a/client/src/views/dashboard/TeamMembers.js b/client/src/views/dashboard/TeamMembers.js index 8b2b43aeb..8d86d4155 100644 --- a/client/src/views/dashboard/TeamMembers.js +++ b/client/src/views/dashboard/TeamMembers.js @@ -15,7 +15,7 @@ const styles = theme => ({ const TeamMembers = ({ classes }) => (
- Members + Team Members
diff --git a/client/src/views/dashboard/components/CreateTeamDialog.js b/client/src/views/dashboard/components/CreateTeamDialog.js index 4db5b5638..bd28c00cb 100644 --- a/client/src/views/dashboard/components/CreateTeamDialog.js +++ b/client/src/views/dashboard/components/CreateTeamDialog.js @@ -14,8 +14,6 @@ import DialogContent from '@material-ui/core/DialogContent' import DialogContentText from '@material-ui/core/DialogContentText' import DialogTitle from '@material-ui/core/DialogTitle' import Typography from '@material-ui/core/Typography' - -import { getItem } from '../../../utils/local-storage' import { isEmpty } from '../../../utils/js-helpers' import CREATE_TEAM from '../../../graphql/teams/CreateTeamMutation' @@ -74,7 +72,9 @@ export class CreateTeamDialog extends Component { let errors let loader = null if (loading) { - loader = Submitting team... + loader = ( + Submitting team... + ) } if (error) { errors = error.graphQLErrors.map(({ message }, i) => { @@ -88,7 +88,13 @@ export class CreateTeamDialog extends Component { } return (
- Create a Team Team Name: - (this.state.errors.name !== '' || error)}> + - {this.state.errors.name !== '' && ({this.state.errors.name})} - {error && ({errors})} + {this.state.errors.name !== '' && ( + {this.state.errors.name} + )} + {error && {errors}} {loader} @@ -120,9 +131,12 @@ export class CreateTeamDialog extends Component { - @@ -153,15 +167,12 @@ export class CreateTeamDialog extends Component { } } - async handleSubmit (e, createTeam, name) { + async handleSubmit (e, createTeam, name, authId) { e.preventDefault() - const currentUser = await getItem('user') - let authId = JSON.parse(currentUser) - authId = authId.authId console.log('createTeam submit: ', authId, name) const slug = this.slugify(name) await createTeam({ variables: { name, slug, owner: authId } }) - this.setState({ name: '' }) + this.setState({ name: '', open: false }) } validate (data) { diff --git a/client/src/views/dashboard/components/DashTeam.js b/client/src/views/dashboard/components/DashTeam.js index 1213f7eb1..1f6fc42c7 100644 --- a/client/src/views/dashboard/components/DashTeam.js +++ b/client/src/views/dashboard/components/DashTeam.js @@ -42,7 +42,10 @@ export const DashTeam = ({ classes, user = null }) => { return ( - Teams Manage Teams + Teams{' '} + + Manage Teams + {({ loading, error, data }) => { diff --git a/client/src/views/dashboard/components/DashTeamItem.js b/client/src/views/dashboard/components/DashTeamItem.js index b5210e73c..e917b9006 100644 --- a/client/src/views/dashboard/components/DashTeamItem.js +++ b/client/src/views/dashboard/components/DashTeamItem.js @@ -9,7 +9,8 @@ import Card from '@material-ui/core/Card' import CardContent from '@material-ui/core/CardContent' import CardMedia from '@material-ui/core/CardMedia' import CardActions from '@material-ui/core/CardActions' -import Button from '@material-ui/core/Button' + +import ManageTeamDetails from './ManageTeamDetails' const styles = theme => ({ card: { @@ -49,13 +50,11 @@ export const DashTeamItem = ({ classes, team }) => ( {team.createdAt} - Members:6 + Members: {team.members.length} - +
diff --git a/client/src/views/dashboard/components/DrawerLinks.js b/client/src/views/dashboard/components/DrawerLinks.js index 29321211e..2109efb47 100644 --- a/client/src/views/dashboard/components/DrawerLinks.js +++ b/client/src/views/dashboard/components/DrawerLinks.js @@ -16,8 +16,16 @@ const DashboardLink = props => const TeamsLink = props => const MembersLink = props => const SettingsLink = props => -const DocumentationLink = props => -const SupportLink = props => +const DocumentationLink = props => ( + +) +const SupportLink = props => ( + +) export const MainDrawerItems = (
diff --git a/client/src/views/dashboard/components/ManageTeamDelete.js b/client/src/views/dashboard/components/ManageTeamDelete.js index 4cb3e3204..9f88ba9a3 100644 --- a/client/src/views/dashboard/components/ManageTeamDelete.js +++ b/client/src/views/dashboard/components/ManageTeamDelete.js @@ -37,9 +37,7 @@ export class ManageTeamDelete extends Component { this.handleSubmit = this.handleSubmit.bind(this) this.state = { - open: false, - motto: '', - description: '' + open: false } } @@ -67,18 +65,14 @@ export class ManageTeamDelete extends Component { variables: { authId } } ]} - update={(cache, { data: { deleteTeam } }) => { - const data = cache.readQuery({ query: GET_TEAMS_BY_OWNER }) - console.log('Mutation cache update: ', deleteTeam, data) - data.getTeamsByOwner.push(deleteTeam) - cache.writeQuery({ query: GET_TEAMS_BY_OWNER, data }) - }} > {(deleteTeam, { loading, error, data }) => { let errors let loader if (loading) { - loader = Submitting team... + loader = ( + Submitting team... + ) } if (error) { errors = error.graphQLErrors.map(({ message }, i) => { @@ -93,7 +87,12 @@ export class ManageTeamDelete extends Component { } return (
-
- Delete Team Team + + Delete Team Team + - DANGER - Deleting your team cannot be undone - Are you sure you want to delete this team? + + DANGER - Deleting your team cannot be undone + + + Are you sure you want to delete this team? + {loader} {errors} @@ -113,9 +118,17 @@ export class ManageTeamDelete extends Component { - @@ -131,6 +144,7 @@ export class ManageTeamDelete extends Component { async handleSubmit (e, deleteTeam, slug, authId) { e.preventDefault() await deleteTeam({ variables: { slug, owner: authId } }) + this.setState({ open: false }) } } diff --git a/client/src/views/dashboard/components/ManageTeamDetails.js b/client/src/views/dashboard/components/ManageTeamDetails.js index 183db0ea8..dac382392 100644 --- a/client/src/views/dashboard/components/ManageTeamDetails.js +++ b/client/src/views/dashboard/components/ManageTeamDetails.js @@ -38,7 +38,12 @@ export class ManageTeamDetails extends Component { const { name, members, profile, createdAt } = this.props.team return (
-
- {name} Team Details + + {name} Team Details + - Team Admin: - { - members.map(member => { - if (member.role === 'OWNER' || member.role === 'ADMIN') { + Team Admin:  + {members.map(member => { + if (member.role === 'OWNER' || member.role === 'ADMIN') { + if (member.member !== null && member.member.alias !== undefined && member.member.alias !== null) { return member.member.alias } - }) - } + } + })} diff --git a/client/src/views/dashboard/components/ManageTeamEdit.js b/client/src/views/dashboard/components/ManageTeamEdit.js index 7db8b46be..7d10e1a7a 100644 --- a/client/src/views/dashboard/components/ManageTeamEdit.js +++ b/client/src/views/dashboard/components/ManageTeamEdit.js @@ -66,7 +66,9 @@ export class ManageTeamEdit extends Component { let errors let loader if (loading) { - loader = Submitting team... + loader = ( + Submitting team... + ) } if (error) { errors = error.graphQLErrors.map(({ message }, i) => { @@ -81,7 +83,12 @@ export class ManageTeamEdit extends Component { } return (
-
- Edit Team Details + + Edit Team Details + Cancel - @@ -171,7 +183,15 @@ export class ManageTeamEdit extends Component { const currentUser = await getItem('user') let authId = JSON.parse(currentUser) authId = authId.authId - await updateTeamProfile({ variables: { slug, owner: authId, description: this.state.description, motto: this.state.motto } }) + await updateTeamProfile({ + variables: { + slug, + owner: authId, + description: this.state.description, + motto: this.state.motto + } + }) + this.setState({ description: '', motto: '', open: false }) } } diff --git a/client/src/views/dashboard/components/ManageTeamsList.js b/client/src/views/dashboard/components/ManageTeamsList.js index 5a5349e86..d72921486 100644 --- a/client/src/views/dashboard/components/ManageTeamsList.js +++ b/client/src/views/dashboard/components/ManageTeamsList.js @@ -66,16 +66,18 @@ export const ManageTeamsList = ({ classes, user = null }) => { ) } else { return ( - + {({ loading, error, data }) => { console.log('GET_TEAMS_BY_OWNER: ', loading, error, data) let errors = null if (error) { errors = error.graphQLErrors.map(({ message }, i) => { - return ( - - ) + return }) } if (!loading && !error) { @@ -115,7 +117,7 @@ export const ManageTeamsList = ({ classes, user = null }) => { - if (errors !== null) () + {errors !== null && } ) diff --git a/client/src/views/footer/index.js b/client/src/views/footer/index.js index ecbd0c594..2fb5b72e9 100644 --- a/client/src/views/footer/index.js +++ b/client/src/views/footer/index.js @@ -67,12 +67,20 @@ const Footer = ({ classes }) => { - + Support - + Documentation diff --git a/client/src/views/index.js b/client/src/views/index.js index 8ff455e85..195ec74ff 100644 --- a/client/src/views/index.js +++ b/client/src/views/index.js @@ -8,4 +8,14 @@ import Teams from './teams' import { theme, globalStyles } from './theme' -export { NavBar, Footer, Callback, Home, About, Dashboard, Teams, theme, globalStyles } +export { + NavBar, + Footer, + Callback, + Home, + About, + Dashboard, + Teams, + theme, + globalStyles +} diff --git a/client/src/views/navbar/index.js b/client/src/views/navbar/index.js index ca33893d2..06531ebfe 100644 --- a/client/src/views/navbar/index.js +++ b/client/src/views/navbar/index.js @@ -82,7 +82,10 @@ class NavBar extends Component { return (
- + Advanced Algos - - + + {this.state.user !== undefined && this.state.user !== null ? ( diff --git a/client/src/views/teams/components/TeamsDetails.js b/client/src/views/teams/components/TeamsDetails.js index 5c590a54b..5383895b6 100644 --- a/client/src/views/teams/components/TeamsDetails.js +++ b/client/src/views/teams/components/TeamsDetails.js @@ -63,18 +63,22 @@ const TeamsDetails = ({ classes, team }) => ( {team.createdAt} + + Motto: {team.profile.motto} + + + Description: {team.profile.description} + Members: {team.members.length} - Team Admin: - { - team.members.map(member => { - if (member.role === 'OWNER' || member.role === 'ADMIN') { - return member.member.alias - } - }) - } + Team Admin:  + {team.members.map(member => { + if (member.role === 'OWNER' || member.role === 'ADMIN') { + return member.member.alias + } + })}
diff --git a/client/src/views/teams/components/TeamsItem.js b/client/src/views/teams/components/TeamsItem.js index 6b2e20bb1..9f0d78bf9 100644 --- a/client/src/views/teams/components/TeamsItem.js +++ b/client/src/views/teams/components/TeamsItem.js @@ -37,7 +37,7 @@ export const TeamsItem = ({ classes, team }) => ( - + diff --git a/client/src/views/teams/components/TeamsList.js b/client/src/views/teams/components/TeamsList.js index 64493cdff..8b628e2c3 100644 --- a/client/src/views/teams/components/TeamsList.js +++ b/client/src/views/teams/components/TeamsList.js @@ -39,7 +39,7 @@ const styles = theme => ({ }) export const TeamsList = ({ classes, match }) => ( - + {({ loading, error, data }) => { console.log('GET_ALL_TEAMS: ', loading, error, data, match) let slug = null @@ -65,10 +65,7 @@ export const TeamsList = ({ classes, match }) => ( data.teams.edges.map(team => { if (team.node.slug === slug) { return ( - + ) } })} From 2e412742e8433e9a2575b96021e0e0f353f925ca Mon Sep 17 00:00:00 2001 From: Barry Low Date: Mon, 17 Sep 2018 17:02:32 -0700 Subject: [PATCH 19/19] Client: Small cosmetic fixes --- client/src/App.js | 2 +- client/src/views/about/index.js | 32 +++++++++++++++++-- .../dashboard/components/CreateTeamDialog.js | 2 -- .../views/dashboard/components/DrawerLinks.js | 3 +- client/src/views/dashboard/index.js | 2 ++ client/src/views/home/index.js | 2 +- client/src/views/navbar/index.js | 2 +- 7 files changed, 36 insertions(+), 9 deletions(-) diff --git a/client/src/App.js b/client/src/App.js index 652531151..2fdbb7578 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -155,7 +155,7 @@ class App extends Component { } /> (
- Collaborate. Innovate. Evolve. + Welcome to Advanced Algos Teams! ( color='textSecondary' component='h3' > - Welcome to the Advanced Algos Teams Module + This module is responsible for managing teams and their members across the Advanced Algos system. You can browser teams and their details, and with an account, create and manage your own teams. + + + Development Status
This module is is currently under heavy development. Implementation started 1st of September 2018 and this is the result of the 1st sprint of 2 weeks of work. +
+ + What can you do?
Basic team creation and management. +
+ + What is next?
+
    +
  1. Managing team profile images.
  2. +
  3. Managing team members - inviting members and administrating roles
  4. +
  5. More detailed team profiles + allowing members to apply to recruiting teams
  6. +
diff --git a/client/src/views/dashboard/components/CreateTeamDialog.js b/client/src/views/dashboard/components/CreateTeamDialog.js index bd28c00cb..d215581a4 100644 --- a/client/src/views/dashboard/components/CreateTeamDialog.js +++ b/client/src/views/dashboard/components/CreateTeamDialog.js @@ -11,7 +11,6 @@ import FormHelperText from '@material-ui/core/FormHelperText' import Dialog from '@material-ui/core/Dialog' import DialogActions from '@material-ui/core/DialogActions' import DialogContent from '@material-ui/core/DialogContent' -import DialogContentText from '@material-ui/core/DialogContentText' import DialogTitle from '@material-ui/core/DialogTitle' import Typography from '@material-ui/core/Typography' import { isEmpty } from '../../../utils/js-helpers' @@ -104,7 +103,6 @@ export class CreateTeamDialog extends Component { > Create a Team - Team Name: const TeamsLink = props => const MembersLink = props => const SettingsLink = props => +const FBLink = props => const DocumentationLink = props => (
- + diff --git a/client/src/views/dashboard/index.js b/client/src/views/dashboard/index.js index f62ac733a..b83675af4 100644 --- a/client/src/views/dashboard/index.js +++ b/client/src/views/dashboard/index.js @@ -12,6 +12,7 @@ import { MainDrawerItems, SecondaryDrawerItems } from './components/DrawerLinks' import Overview from './Overview' import ManageTeams from './ManageTeams' +import FinancialBeings from './FinancialBeings' import TeamMembers from './TeamMembers' import Settings from './Settings' @@ -65,6 +66,7 @@ const Dashboard = ({ classes }) => ( + diff --git a/client/src/views/home/index.js b/client/src/views/home/index.js index 5d780b5a2..bfa124910 100644 --- a/client/src/views/home/index.js +++ b/client/src/views/home/index.js @@ -47,7 +47,7 @@ const Home = ({ classes }) => ( color='textSecondary' component='h3' > - Welcome to the Advanced Algos Teams Module + Welcome to Advanced Algos Teams
diff --git a/client/src/views/navbar/index.js b/client/src/views/navbar/index.js index 06531ebfe..f144156e0 100644 --- a/client/src/views/navbar/index.js +++ b/client/src/views/navbar/index.js @@ -93,7 +93,7 @@ class NavBar extends Component { color='inherit' className={classes.toolbarTitle} > - Teams Module + Teams