Merge branch 'master' of https://github.com/AdvancedAlgos/TeamsModule
This commit is contained in:
commit
b4790c4756
58 files changed
+4587
-3538
No files matched your search
@@ -2,6 +2,8 @@
|
||||
/.env.prod
|
||||
/database/.env
|
||||
/database/docker-compose.prisma.prod.yml
|
||||
/database/*.zip
|
||||
/database/data-archive
|
||||
/docker-compose.prisma.prod.yml
|
||||
/docker-compose.prod.yml
|
||||
.graphqlconfig.prod.yml
|
||||
|
||||
@@ -39,15 +39,17 @@ type Team {
|
||||
}
|
||||
|
||||
type TeamProfile {
|
||||
id: ID! @unique
|
||||
description: String
|
||||
motto: String
|
||||
avatar: String
|
||||
banner: String
|
||||
updatedAt: DateTime!
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
type TeamStatus {
|
||||
id: ID! @unique
|
||||
status: Status @Default(value: inactive)
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
@@ -61,7 +63,6 @@ type TeamMembers {
|
||||
status: [TeamMemberStatus!]!
|
||||
email: String @unique
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
type TeamMemberStatus {
|
||||
@@ -82,14 +83,16 @@ type Member {
|
||||
}
|
||||
|
||||
type MemberStatus {
|
||||
id: ID! @unique
|
||||
status: Status @Default(value: INACTIVE)
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
}
|
||||
|
||||
type Wallet {
|
||||
id: ID! @unique
|
||||
balance: Float
|
||||
updatedAt: DateTime!
|
||||
createdAt: DateTime!
|
||||
}
|
||||
|
||||
type FinancialBeings {
|
||||
@@ -101,11 +104,10 @@ type FinancialBeings {
|
||||
avatar: String
|
||||
team: Team @relation (name: "TeamFinancialBeing", onDelete: SET_NULL)
|
||||
status: [FBStatus!]!
|
||||
updatedAt: DateTime!
|
||||
createdAt: DateTime!
|
||||
}
|
||||
|
||||
type FBStatus {
|
||||
id: ID! @unique
|
||||
status: Status @Default(value: inactive)
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: '3'
|
||||
services:
|
||||
prisma:
|
||||
image: prismagraphql/prisma:1.15.1
|
||||
image: prismagraphql/prisma:1.20
|
||||
restart: always
|
||||
ports:
|
||||
- "4466:4466"
|
||||
|
||||
Generated
+1471
-2870
File diff suppressed because it is too large.
Load diff
+18
-18
@@ -7,42 +7,42 @@
|
||||
"dev": "npm-run-all --parallel debug playground"
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/storage-blob": "^10.0.0-preview",
|
||||
"@babel/cli": "^7.1.2",
|
||||
"@babel/core": "^7.1.2",
|
||||
"@babel/node": "^7.0.0",
|
||||
"@azure/storage-blob": "^10.1.0-preview",
|
||||
"@babel/cli": "^7.2.0",
|
||||
"@babel/core": "^7.2.0",
|
||||
"@babel/node": "^7.2.0",
|
||||
"@babel/polyfill": "^7.0.0",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-env": "^7.2.0",
|
||||
"@babel/register": "^7.0.0",
|
||||
"apollo-errors": "^1.9.0",
|
||||
"apollo-server-express": "^2.1.0",
|
||||
"apollo-server-express": "^2.2.6",
|
||||
"axios": "^0.18.0",
|
||||
"cors": "^2.8.4",
|
||||
"cors": "^2.8.5",
|
||||
"debug": "^4.1.0",
|
||||
"dotenv": "^6.1.0",
|
||||
"express": "^4.16.4",
|
||||
"express-jwt": "^5.3.1",
|
||||
"fast-xml-parser": "^3.12.5",
|
||||
"fast-xml-parser": "^3.12.10",
|
||||
"graphql-import": "^0.7.1",
|
||||
"graphql-middleware": "^1.7.7",
|
||||
"graphql-middleware": "^1.7.8",
|
||||
"graphql-subscriptions": "^1.0.0",
|
||||
"graphql-tag": "^2.10.0",
|
||||
"graphql-tools": "^4.0.1",
|
||||
"jsonwebtoken": "^8.3.0",
|
||||
"graphql-tools": "^4.0.3",
|
||||
"jsonwebtoken": "^8.4.0",
|
||||
"jwks-rsa": "^1.3.0",
|
||||
"lodash.get": "^4.4.2",
|
||||
"nodemon": "^1.18.4",
|
||||
"prisma-binding": "^2.1.6",
|
||||
"nodemon": "^1.18.7",
|
||||
"prisma-binding": "^2.2.8",
|
||||
"request": "^2.88.0",
|
||||
"request-promise-native": "^1.0.5",
|
||||
"winston": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-class-properties": "^7.1.0",
|
||||
"@babel/plugin-proposal-throw-expressions": "^7.0.0",
|
||||
"graphql-cli": "^2.16.5",
|
||||
"@babel/plugin-proposal-class-properties": "^7.2.1",
|
||||
"@babel/plugin-proposal-throw-expressions": "^7.2.0",
|
||||
"graphql-cli": "^2.17.0",
|
||||
"lodash.merge": "^4.6.1",
|
||||
"npm-run-all": "4.1.3",
|
||||
"prisma": "^1.18.1"
|
||||
"npm-run-all": "4.1.5",
|
||||
"prisma": "^1.22.0"
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
var jwt = require('jsonwebtoken')
|
||||
var axios = require('axios')
|
||||
|
||||
import { logger } from '../logger'
|
||||
|
||||
const sendTeamMemberInvite = function(email, team) {
|
||||
const dev = process.env.NODE_ENV === 'development' ? true : false
|
||||
logger.info(`sendTeamMemberInvite email|team: ${email} | ${team}`)
|
||||
const API_KEY = process.env.SG_APIKEY
|
||||
const token = jwt.sign({ email: email, team: team.slug }, API_KEY, { expiresIn: '7d' })
|
||||
let origin = 'https://teams.advancedalgos.net'
|
||||
const params = '/activate-team-membership/'
|
||||
if (dev){
|
||||
origin = 'http://localhost:3001'
|
||||
}
|
||||
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin' : origin,
|
||||
'Access-Control-Allow-Credentials': 'true'
|
||||
};
|
||||
|
||||
const data = JSON.stringify({
|
||||
"personalizations": [
|
||||
{
|
||||
"to": [
|
||||
{
|
||||
"email": email
|
||||
}
|
||||
],
|
||||
dynamic_template_data: {
|
||||
"aateaminvitelink": origin + params + token,
|
||||
"aateamname": team.name,
|
||||
"subject": "INVITATION: Join team " + team.name
|
||||
},
|
||||
"subject": "INVITATION: Join team " + team.name
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"email": "noreply@advancedalgos.net",
|
||||
"name": "Advanced Algos Teams"
|
||||
},
|
||||
"reply_to": {
|
||||
"email": "feedback@advancedalgos.net",
|
||||
"name": "Advanced Algos Teams"
|
||||
},
|
||||
"template_id": process.env.SG_INVITE_EMAILID
|
||||
})
|
||||
|
||||
let sendVerify = axios({
|
||||
method: 'post',
|
||||
url: 'https://api.sendgrid.com/v3/mail/send',
|
||||
data: data,
|
||||
headers:{
|
||||
'content-type': 'application/json',
|
||||
'authorization': 'Bearer ' + API_KEY
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return 'Success'
|
||||
} else {
|
||||
throw response.data.errors[0].message
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
return `${error.status}-${error.response.data.errors[0].message}`
|
||||
})
|
||||
return sendVerify
|
||||
}
|
||||
|
||||
const sendTeamCreateConfirmation = function(email, teamName, botName) {
|
||||
const dev = process.env.NODE_ENV === 'development' ? true : false
|
||||
logger.info(`sendTeamCreateConfirmation email|teamName|botName: ${email} | ${teamName} | ${botName}`)
|
||||
const API_KEY = process.env.SG_APIKEY
|
||||
let origin = 'https://teams.advancedalgos.net'
|
||||
if (dev){
|
||||
origin = 'http://localhost:3001'
|
||||
}
|
||||
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin' : origin,
|
||||
'Access-Control-Allow-Credentials': 'true'
|
||||
};
|
||||
|
||||
const data = JSON.stringify({
|
||||
"personalizations": [
|
||||
{
|
||||
"to": [
|
||||
{
|
||||
"email": email
|
||||
}
|
||||
],
|
||||
dynamic_template_data: {
|
||||
"aadeveloplink": "https://develop.advancedalgos.net/index.html",
|
||||
"aateamname": teamName,
|
||||
"aabotname": botName,
|
||||
"subject": "Team " + teamName + " has been created!"
|
||||
},
|
||||
"subject": "Team " + teamName + " has been created!"
|
||||
}
|
||||
],
|
||||
"from": {
|
||||
"email": "noreply@advancedalgos.net",
|
||||
"name": "Advanced Algos Teams"
|
||||
},
|
||||
"reply_to": {
|
||||
"email": "feedback@advancedalgos.net",
|
||||
"name": "Advanced Algos Teams"
|
||||
},
|
||||
"template_id": process.env.SG_TEAMCREATE_EMAILID
|
||||
})
|
||||
|
||||
let sendTeamCreation = axios({
|
||||
method: 'post',
|
||||
url: 'https://api.sendgrid.com/v3/mail/send',
|
||||
data: data,
|
||||
headers:{
|
||||
'content-type': 'application/json',
|
||||
'authorization': 'Bearer ' + API_KEY
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return 'Success'
|
||||
} else {
|
||||
throw response.data.errors[0].message
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
return `${error.status}-${error.response.data.errors[0].message}`
|
||||
})
|
||||
return sendTeamCreation
|
||||
}
|
||||
|
||||
const verifyInviteToken = async function(token) {
|
||||
const API_KEY = process.env.SG_APIKEY
|
||||
let verifiedToken
|
||||
try {
|
||||
verifiedToken = await jwt.verify(token, API_KEY, {maxAge: '7d'})
|
||||
} catch(err) {
|
||||
if (err.name === "TokenExpiredError"){
|
||||
throw new Error ("Error: Token Expired. Please request new invitation or apply to the team again")
|
||||
} else {
|
||||
throw new Error (`Error: Token error - ${err.message}`)
|
||||
}
|
||||
}
|
||||
logger.info(`verifyInviteToken: ${verifiedToken}`)
|
||||
return verifiedToken
|
||||
}
|
||||
|
||||
module.exports = { sendTeamMemberInvite, sendTeamCreateConfirmation, verifyInviteToken }
|
||||
@@ -1,5 +1,5 @@
|
||||
# source: http://localhost:4466
|
||||
# timestamp: Fri Oct 05 2018 13:16:40 GMT-0700 (Pacific Daylight Time)
|
||||
# timestamp: Tue Nov 20 2018 09:55:31 GMT-0800 (Pacific Standard Time)
|
||||
|
||||
type AggregateFBStatus {
|
||||
count: Int!
|
||||
@@ -55,7 +55,8 @@ enum FBKind {
|
||||
PLOTTER
|
||||
}
|
||||
|
||||
type FBStatus {
|
||||
type FBStatus implements Node {
|
||||
id: ID!
|
||||
status: Status
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
@@ -78,6 +79,7 @@ input FBStatusCreateInput {
|
||||
|
||||
input FBStatusCreateManyInput {
|
||||
create: [FBStatusCreateInput!]
|
||||
connect: [FBStatusWhereUniqueInput!]
|
||||
}
|
||||
|
||||
"""An edge in a connection."""
|
||||
@@ -90,19 +92,20 @@ type FBStatusEdge {
|
||||
}
|
||||
|
||||
enum FBStatusOrderByInput {
|
||||
id_ASC
|
||||
id_DESC
|
||||
status_ASC
|
||||
status_DESC
|
||||
reason_ASC
|
||||
reason_DESC
|
||||
createdAt_ASC
|
||||
createdAt_DESC
|
||||
id_ASC
|
||||
id_DESC
|
||||
updatedAt_ASC
|
||||
updatedAt_DESC
|
||||
}
|
||||
|
||||
type FBStatusPreviousValues {
|
||||
id: ID!
|
||||
status: Status
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
@@ -147,6 +150,11 @@ input FBStatusSubscriptionWhereInput {
|
||||
node: FBStatusWhereInput
|
||||
}
|
||||
|
||||
input FBStatusUpdateDataInput {
|
||||
status: Status
|
||||
reason: String
|
||||
}
|
||||
|
||||
input FBStatusUpdateInput {
|
||||
status: Status
|
||||
reason: String
|
||||
@@ -154,6 +162,27 @@ input FBStatusUpdateInput {
|
||||
|
||||
input FBStatusUpdateManyInput {
|
||||
create: [FBStatusCreateInput!]
|
||||
connect: [FBStatusWhereUniqueInput!]
|
||||
disconnect: [FBStatusWhereUniqueInput!]
|
||||
delete: [FBStatusWhereUniqueInput!]
|
||||
update: [FBStatusUpdateWithWhereUniqueNestedInput!]
|
||||
upsert: [FBStatusUpsertWithWhereUniqueNestedInput!]
|
||||
}
|
||||
|
||||
input FBStatusUpdateManyMutationInput {
|
||||
status: Status
|
||||
reason: String
|
||||
}
|
||||
|
||||
input FBStatusUpdateWithWhereUniqueNestedInput {
|
||||
where: FBStatusWhereUniqueInput!
|
||||
data: FBStatusUpdateDataInput!
|
||||
}
|
||||
|
||||
input FBStatusUpsertWithWhereUniqueNestedInput {
|
||||
where: FBStatusWhereUniqueInput!
|
||||
update: FBStatusUpdateDataInput!
|
||||
create: FBStatusCreateInput!
|
||||
}
|
||||
|
||||
input FBStatusWhereInput {
|
||||
@@ -165,6 +194,46 @@ input FBStatusWhereInput {
|
||||
|
||||
"""Logical NOT on all given filters combined by AND."""
|
||||
NOT: [FBStatusWhereInput!]
|
||||
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
|
||||
status: Status
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
@@ -239,6 +308,10 @@ input FBStatusWhereInput {
|
||||
createdAt_gte: DateTime
|
||||
}
|
||||
|
||||
input FBStatusWhereUniqueInput {
|
||||
id: ID
|
||||
}
|
||||
|
||||
enum FBType {
|
||||
BOT
|
||||
NET
|
||||
@@ -252,7 +325,7 @@ type FinancialBeings implements Node {
|
||||
name: String!
|
||||
slug: String!
|
||||
avatar: String
|
||||
team(where: TeamWhereInput): Team
|
||||
team: Team
|
||||
status(where: FBStatusWhereInput, orderBy: FBStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [FBStatus!]
|
||||
updatedAt: DateTime!
|
||||
createdAt: DateTime!
|
||||
@@ -380,6 +453,14 @@ input FinancialBeingsUpdateInput {
|
||||
status: FBStatusUpdateManyInput
|
||||
}
|
||||
|
||||
input FinancialBeingsUpdateManyMutationInput {
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String
|
||||
slug: String
|
||||
avatar: String
|
||||
}
|
||||
|
||||
input FinancialBeingsUpdateManyWithoutTeamInput {
|
||||
create: [FinancialBeingsCreateWithoutTeamInput!]
|
||||
connect: [FinancialBeingsWhereUniqueInput!]
|
||||
@@ -730,7 +811,8 @@ type MemberPreviousValues {
|
||||
createdAt: DateTime!
|
||||
}
|
||||
|
||||
type MemberStatus {
|
||||
type MemberStatus implements Node {
|
||||
id: ID!
|
||||
status: Status
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
@@ -753,6 +835,7 @@ input MemberStatusCreateInput {
|
||||
|
||||
input MemberStatusCreateManyInput {
|
||||
create: [MemberStatusCreateInput!]
|
||||
connect: [MemberStatusWhereUniqueInput!]
|
||||
}
|
||||
|
||||
"""An edge in a connection."""
|
||||
@@ -765,19 +848,20 @@ type MemberStatusEdge {
|
||||
}
|
||||
|
||||
enum MemberStatusOrderByInput {
|
||||
id_ASC
|
||||
id_DESC
|
||||
status_ASC
|
||||
status_DESC
|
||||
reason_ASC
|
||||
reason_DESC
|
||||
createdAt_ASC
|
||||
createdAt_DESC
|
||||
id_ASC
|
||||
id_DESC
|
||||
updatedAt_ASC
|
||||
updatedAt_DESC
|
||||
}
|
||||
|
||||
type MemberStatusPreviousValues {
|
||||
id: ID!
|
||||
status: Status
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
@@ -822,6 +906,11 @@ input MemberStatusSubscriptionWhereInput {
|
||||
node: MemberStatusWhereInput
|
||||
}
|
||||
|
||||
input MemberStatusUpdateDataInput {
|
||||
status: Status
|
||||
reason: String
|
||||
}
|
||||
|
||||
input MemberStatusUpdateInput {
|
||||
status: Status
|
||||
reason: String
|
||||
@@ -829,6 +918,27 @@ input MemberStatusUpdateInput {
|
||||
|
||||
input MemberStatusUpdateManyInput {
|
||||
create: [MemberStatusCreateInput!]
|
||||
connect: [MemberStatusWhereUniqueInput!]
|
||||
disconnect: [MemberStatusWhereUniqueInput!]
|
||||
delete: [MemberStatusWhereUniqueInput!]
|
||||
update: [MemberStatusUpdateWithWhereUniqueNestedInput!]
|
||||
upsert: [MemberStatusUpsertWithWhereUniqueNestedInput!]
|
||||
}
|
||||
|
||||
input MemberStatusUpdateManyMutationInput {
|
||||
status: Status
|
||||
reason: String
|
||||
}
|
||||
|
||||
input MemberStatusUpdateWithWhereUniqueNestedInput {
|
||||
where: MemberStatusWhereUniqueInput!
|
||||
data: MemberStatusUpdateDataInput!
|
||||
}
|
||||
|
||||
input MemberStatusUpsertWithWhereUniqueNestedInput {
|
||||
where: MemberStatusWhereUniqueInput!
|
||||
update: MemberStatusUpdateDataInput!
|
||||
create: MemberStatusCreateInput!
|
||||
}
|
||||
|
||||
input MemberStatusWhereInput {
|
||||
@@ -840,6 +950,46 @@ input MemberStatusWhereInput {
|
||||
|
||||
"""Logical NOT on all given filters combined by AND."""
|
||||
NOT: [MemberStatusWhereInput!]
|
||||
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
|
||||
status: Status
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
@@ -914,6 +1064,10 @@ input MemberStatusWhereInput {
|
||||
createdAt_gte: DateTime
|
||||
}
|
||||
|
||||
input MemberStatusWhereUniqueInput {
|
||||
id: ID
|
||||
}
|
||||
|
||||
type MemberSubscriptionPayload {
|
||||
mutation: MutationType!
|
||||
node: Member
|
||||
@@ -961,6 +1115,12 @@ input MemberUpdateInput {
|
||||
status: MemberStatusUpdateManyInput
|
||||
}
|
||||
|
||||
input MemberUpdateManyMutationInput {
|
||||
alias: String
|
||||
authId: String
|
||||
visible: Boolean
|
||||
}
|
||||
|
||||
input MemberUpdateOneWithoutTeamsInput {
|
||||
create: MemberCreateWithoutTeamsInput
|
||||
connect: MemberWhereUniqueInput
|
||||
@@ -1165,27 +1325,42 @@ type Mutation {
|
||||
updateTeamMembers(data: TeamMembersUpdateInput!, where: TeamMembersWhereUniqueInput!): TeamMembers
|
||||
updateMember(data: MemberUpdateInput!, where: MemberWhereUniqueInput!): Member
|
||||
updateFinancialBeings(data: FinancialBeingsUpdateInput!, where: FinancialBeingsWhereUniqueInput!): FinancialBeings
|
||||
updateTeamProfile(data: TeamProfileUpdateInput!, where: TeamProfileWhereUniqueInput!): TeamProfile
|
||||
updateWallet(data: WalletUpdateInput!, where: WalletWhereUniqueInput!): Wallet
|
||||
updateMemberStatus(data: MemberStatusUpdateInput!, where: MemberStatusWhereUniqueInput!): MemberStatus
|
||||
updateFBStatus(data: FBStatusUpdateInput!, where: FBStatusWhereUniqueInput!): FBStatus
|
||||
updateTeamMemberStatus(data: TeamMemberStatusUpdateInput!, where: TeamMemberStatusWhereUniqueInput!): TeamMemberStatus
|
||||
updateTeamStatus(data: TeamStatusUpdateInput!, where: TeamStatusWhereUniqueInput!): TeamStatus
|
||||
deleteTeam(where: TeamWhereUniqueInput!): Team
|
||||
deleteTeamMembers(where: TeamMembersWhereUniqueInput!): TeamMembers
|
||||
deleteMember(where: MemberWhereUniqueInput!): Member
|
||||
deleteFinancialBeings(where: FinancialBeingsWhereUniqueInput!): FinancialBeings
|
||||
deleteTeamProfile(where: TeamProfileWhereUniqueInput!): TeamProfile
|
||||
deleteWallet(where: WalletWhereUniqueInput!): Wallet
|
||||
deleteMemberStatus(where: MemberStatusWhereUniqueInput!): MemberStatus
|
||||
deleteFBStatus(where: FBStatusWhereUniqueInput!): FBStatus
|
||||
deleteTeamMemberStatus(where: TeamMemberStatusWhereUniqueInput!): TeamMemberStatus
|
||||
deleteTeamStatus(where: TeamStatusWhereUniqueInput!): TeamStatus
|
||||
upsertTeam(where: TeamWhereUniqueInput!, create: TeamCreateInput!, update: TeamUpdateInput!): Team!
|
||||
upsertTeamMembers(where: TeamMembersWhereUniqueInput!, create: TeamMembersCreateInput!, update: TeamMembersUpdateInput!): TeamMembers!
|
||||
upsertMember(where: MemberWhereUniqueInput!, create: MemberCreateInput!, update: MemberUpdateInput!): Member!
|
||||
upsertFinancialBeings(where: FinancialBeingsWhereUniqueInput!, create: FinancialBeingsCreateInput!, update: FinancialBeingsUpdateInput!): FinancialBeings!
|
||||
upsertTeamProfile(where: TeamProfileWhereUniqueInput!, create: TeamProfileCreateInput!, update: TeamProfileUpdateInput!): TeamProfile!
|
||||
upsertWallet(where: WalletWhereUniqueInput!, create: WalletCreateInput!, update: WalletUpdateInput!): Wallet!
|
||||
upsertMemberStatus(where: MemberStatusWhereUniqueInput!, create: MemberStatusCreateInput!, update: MemberStatusUpdateInput!): MemberStatus!
|
||||
upsertFBStatus(where: FBStatusWhereUniqueInput!, create: FBStatusCreateInput!, update: FBStatusUpdateInput!): FBStatus!
|
||||
upsertTeamMemberStatus(where: TeamMemberStatusWhereUniqueInput!, create: TeamMemberStatusCreateInput!, update: TeamMemberStatusUpdateInput!): TeamMemberStatus!
|
||||
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!
|
||||
updateManyMemberStatuses(data: MemberStatusUpdateInput!, where: MemberStatusWhereInput): BatchPayload!
|
||||
updateManyFBStatuses(data: FBStatusUpdateInput!, where: FBStatusWhereInput): BatchPayload!
|
||||
updateManyTeamMemberStatuses(data: TeamMemberStatusUpdateInput!, where: TeamMemberStatusWhereInput): BatchPayload!
|
||||
updateManyTeamStatuses(data: TeamStatusUpdateInput!, where: TeamStatusWhereInput): BatchPayload!
|
||||
upsertTeamStatus(where: TeamStatusWhereUniqueInput!, create: TeamStatusCreateInput!, update: TeamStatusUpdateInput!): TeamStatus!
|
||||
updateManyTeams(data: TeamUpdateManyMutationInput!, where: TeamWhereInput): BatchPayload!
|
||||
updateManyTeamMemberses(data: TeamMembersUpdateManyMutationInput!, where: TeamMembersWhereInput): BatchPayload!
|
||||
updateManyMembers(data: MemberUpdateManyMutationInput!, where: MemberWhereInput): BatchPayload!
|
||||
updateManyFinancialBeingses(data: FinancialBeingsUpdateManyMutationInput!, where: FinancialBeingsWhereInput): BatchPayload!
|
||||
updateManyTeamProfiles(data: TeamProfileUpdateManyMutationInput!, where: TeamProfileWhereInput): BatchPayload!
|
||||
updateManyWallets(data: WalletUpdateManyMutationInput!, where: WalletWhereInput): BatchPayload!
|
||||
updateManyMemberStatuses(data: MemberStatusUpdateManyMutationInput!, where: MemberStatusWhereInput): BatchPayload!
|
||||
updateManyFBStatuses(data: FBStatusUpdateManyMutationInput!, where: FBStatusWhereInput): BatchPayload!
|
||||
updateManyTeamMemberStatuses(data: TeamMemberStatusUpdateManyMutationInput!, where: TeamMemberStatusWhereInput): BatchPayload!
|
||||
updateManyTeamStatuses(data: TeamStatusUpdateManyMutationInput!, where: TeamStatusWhereInput): BatchPayload!
|
||||
deleteManyTeams(where: TeamWhereInput): BatchPayload!
|
||||
deleteManyTeamMemberses(where: TeamMembersWhereInput): BatchPayload!
|
||||
deleteManyMembers(where: MemberWhereInput): BatchPayload!
|
||||
@@ -1240,7 +1415,12 @@ type Query {
|
||||
teamMembers(where: TeamMembersWhereUniqueInput!): TeamMembers
|
||||
member(where: MemberWhereUniqueInput!): Member
|
||||
financialBeings(where: FinancialBeingsWhereUniqueInput!): FinancialBeings
|
||||
teamProfile(where: TeamProfileWhereUniqueInput!): TeamProfile
|
||||
wallet(where: WalletWhereUniqueInput!): Wallet
|
||||
memberStatus(where: MemberStatusWhereUniqueInput!): MemberStatus
|
||||
fBStatus(where: FBStatusWhereUniqueInput!): FBStatus
|
||||
teamMemberStatus(where: TeamMemberStatusWhereUniqueInput!): TeamMemberStatus
|
||||
teamStatus(where: TeamStatusWhereUniqueInput!): TeamStatus
|
||||
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!
|
||||
@@ -1290,13 +1470,14 @@ type Team implements Node {
|
||||
id: ID!
|
||||
name: String!
|
||||
slug: String!
|
||||
profile(where: TeamProfileWhereInput): TeamProfile
|
||||
profile: TeamProfile
|
||||
members(where: TeamMembersWhereInput, orderBy: TeamMembersOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamMembers!]
|
||||
owner: String!
|
||||
wallet(where: WalletWhereInput): Wallet
|
||||
wallet: 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!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
"""A connection to a list of items."""
|
||||
@@ -1361,8 +1542,8 @@ type TeamEdge {
|
||||
|
||||
type TeamMembers implements Node {
|
||||
id: ID!
|
||||
member(where: MemberWhereInput): Member
|
||||
team(where: TeamWhereInput): Team
|
||||
member: Member
|
||||
team: Team
|
||||
role: Role
|
||||
status(where: TeamMemberStatusWhereInput, orderBy: TeamMemberStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamMemberStatus!]
|
||||
email: String
|
||||
@@ -1595,6 +1776,11 @@ input TeamMemberStatusUpdateManyInput {
|
||||
upsert: [TeamMemberStatusUpsertWithWhereUniqueNestedInput!]
|
||||
}
|
||||
|
||||
input TeamMemberStatusUpdateManyMutationInput {
|
||||
status: Status
|
||||
reason: String
|
||||
}
|
||||
|
||||
input TeamMemberStatusUpdateWithWhereUniqueNestedInput {
|
||||
where: TeamMemberStatusWhereUniqueInput!
|
||||
data: TeamMemberStatusUpdateDataInput!
|
||||
@@ -1741,6 +1927,11 @@ input TeamMembersUpdateInput {
|
||||
status: TeamMemberStatusUpdateManyInput
|
||||
}
|
||||
|
||||
input TeamMembersUpdateManyMutationInput {
|
||||
role: Role
|
||||
email: String
|
||||
}
|
||||
|
||||
input TeamMembersUpdateManyWithoutMemberInput {
|
||||
create: [TeamMembersCreateWithoutMemberInput!]
|
||||
connect: [TeamMembersWhereUniqueInput!]
|
||||
@@ -1971,9 +2162,11 @@ type TeamPreviousValues {
|
||||
slug: String!
|
||||
owner: String!
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
type TeamProfile {
|
||||
type TeamProfile implements Node {
|
||||
id: ID!
|
||||
description: String
|
||||
motto: String
|
||||
avatar: String
|
||||
@@ -2001,6 +2194,7 @@ input TeamProfileCreateInput {
|
||||
|
||||
input TeamProfileCreateOneInput {
|
||||
create: TeamProfileCreateInput
|
||||
connect: TeamProfileWhereUniqueInput
|
||||
}
|
||||
|
||||
"""An edge in a connection."""
|
||||
@@ -2013,6 +2207,8 @@ type TeamProfileEdge {
|
||||
}
|
||||
|
||||
enum TeamProfileOrderByInput {
|
||||
id_ASC
|
||||
id_DESC
|
||||
description_ASC
|
||||
description_DESC
|
||||
motto_ASC
|
||||
@@ -2025,11 +2221,10 @@ enum TeamProfileOrderByInput {
|
||||
updatedAt_DESC
|
||||
createdAt_ASC
|
||||
createdAt_DESC
|
||||
id_ASC
|
||||
id_DESC
|
||||
}
|
||||
|
||||
type TeamProfilePreviousValues {
|
||||
id: ID!
|
||||
description: String
|
||||
motto: String
|
||||
avatar: String
|
||||
@@ -2091,8 +2286,16 @@ input TeamProfileUpdateInput {
|
||||
banner: String
|
||||
}
|
||||
|
||||
input TeamProfileUpdateManyMutationInput {
|
||||
description: String
|
||||
motto: String
|
||||
avatar: String
|
||||
banner: String
|
||||
}
|
||||
|
||||
input TeamProfileUpdateOneInput {
|
||||
create: TeamProfileCreateInput
|
||||
connect: TeamProfileWhereUniqueInput
|
||||
disconnect: Boolean
|
||||
delete: Boolean
|
||||
update: TeamProfileUpdateDataInput
|
||||
@@ -2113,6 +2316,46 @@ input TeamProfileWhereInput {
|
||||
|
||||
"""Logical NOT on all given filters combined by AND."""
|
||||
NOT: [TeamProfileWhereInput!]
|
||||
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
|
||||
description: String
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
@@ -2319,7 +2562,12 @@ input TeamProfileWhereInput {
|
||||
createdAt_gte: DateTime
|
||||
}
|
||||
|
||||
type TeamStatus {
|
||||
input TeamProfileWhereUniqueInput {
|
||||
id: ID
|
||||
}
|
||||
|
||||
type TeamStatus implements Node {
|
||||
id: ID!
|
||||
status: Status
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
@@ -2342,6 +2590,7 @@ input TeamStatusCreateInput {
|
||||
|
||||
input TeamStatusCreateManyInput {
|
||||
create: [TeamStatusCreateInput!]
|
||||
connect: [TeamStatusWhereUniqueInput!]
|
||||
}
|
||||
|
||||
"""An edge in a connection."""
|
||||
@@ -2354,19 +2603,20 @@ type TeamStatusEdge {
|
||||
}
|
||||
|
||||
enum TeamStatusOrderByInput {
|
||||
id_ASC
|
||||
id_DESC
|
||||
status_ASC
|
||||
status_DESC
|
||||
reason_ASC
|
||||
reason_DESC
|
||||
createdAt_ASC
|
||||
createdAt_DESC
|
||||
id_ASC
|
||||
id_DESC
|
||||
updatedAt_ASC
|
||||
updatedAt_DESC
|
||||
}
|
||||
|
||||
type TeamStatusPreviousValues {
|
||||
id: ID!
|
||||
status: Status
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
@@ -2411,6 +2661,11 @@ input TeamStatusSubscriptionWhereInput {
|
||||
node: TeamStatusWhereInput
|
||||
}
|
||||
|
||||
input TeamStatusUpdateDataInput {
|
||||
status: Status
|
||||
reason: String
|
||||
}
|
||||
|
||||
input TeamStatusUpdateInput {
|
||||
status: Status
|
||||
reason: String
|
||||
@@ -2418,6 +2673,27 @@ input TeamStatusUpdateInput {
|
||||
|
||||
input TeamStatusUpdateManyInput {
|
||||
create: [TeamStatusCreateInput!]
|
||||
connect: [TeamStatusWhereUniqueInput!]
|
||||
disconnect: [TeamStatusWhereUniqueInput!]
|
||||
delete: [TeamStatusWhereUniqueInput!]
|
||||
update: [TeamStatusUpdateWithWhereUniqueNestedInput!]
|
||||
upsert: [TeamStatusUpsertWithWhereUniqueNestedInput!]
|
||||
}
|
||||
|
||||
input TeamStatusUpdateManyMutationInput {
|
||||
status: Status
|
||||
reason: String
|
||||
}
|
||||
|
||||
input TeamStatusUpdateWithWhereUniqueNestedInput {
|
||||
where: TeamStatusWhereUniqueInput!
|
||||
data: TeamStatusUpdateDataInput!
|
||||
}
|
||||
|
||||
input TeamStatusUpsertWithWhereUniqueNestedInput {
|
||||
where: TeamStatusWhereUniqueInput!
|
||||
update: TeamStatusUpdateDataInput!
|
||||
create: TeamStatusCreateInput!
|
||||
}
|
||||
|
||||
input TeamStatusWhereInput {
|
||||
@@ -2429,6 +2705,46 @@ input TeamStatusWhereInput {
|
||||
|
||||
"""Logical NOT on all given filters combined by AND."""
|
||||
NOT: [TeamStatusWhereInput!]
|
||||
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
|
||||
status: Status
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
@@ -2503,6 +2819,10 @@ input TeamStatusWhereInput {
|
||||
createdAt_gte: DateTime
|
||||
}
|
||||
|
||||
input TeamStatusWhereUniqueInput {
|
||||
id: ID
|
||||
}
|
||||
|
||||
type TeamSubscriptionPayload {
|
||||
mutation: MutationType!
|
||||
node: Team
|
||||
@@ -2553,6 +2873,12 @@ input TeamUpdateInput {
|
||||
status: TeamStatusUpdateManyInput
|
||||
}
|
||||
|
||||
input TeamUpdateManyMutationInput {
|
||||
name: String
|
||||
slug: String
|
||||
owner: String
|
||||
}
|
||||
|
||||
input TeamUpdateOneWithoutFbInput {
|
||||
create: TeamCreateWithoutFbInput
|
||||
connect: TeamWhereUniqueInput
|
||||
@@ -2792,6 +3118,28 @@ input TeamWhereInput {
|
||||
|
||||
"""All values greater than or equal the given value."""
|
||||
createdAt_gte: DateTime
|
||||
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
|
||||
profile: TeamProfileWhereInput
|
||||
members_every: TeamMembersWhereInput
|
||||
members_some: TeamMembersWhereInput
|
||||
@@ -2811,7 +3159,8 @@ input TeamWhereUniqueInput {
|
||||
slug: String
|
||||
}
|
||||
|
||||
type Wallet {
|
||||
type Wallet implements Node {
|
||||
id: ID!
|
||||
balance: Float
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
@@ -2832,6 +3181,7 @@ input WalletCreateInput {
|
||||
|
||||
input WalletCreateOneInput {
|
||||
create: WalletCreateInput
|
||||
connect: WalletWhereUniqueInput
|
||||
}
|
||||
|
||||
"""An edge in a connection."""
|
||||
@@ -2844,17 +3194,18 @@ type WalletEdge {
|
||||
}
|
||||
|
||||
enum WalletOrderByInput {
|
||||
id_ASC
|
||||
id_DESC
|
||||
balance_ASC
|
||||
balance_DESC
|
||||
updatedAt_ASC
|
||||
updatedAt_DESC
|
||||
id_ASC
|
||||
id_DESC
|
||||
createdAt_ASC
|
||||
createdAt_DESC
|
||||
}
|
||||
|
||||
type WalletPreviousValues {
|
||||
id: ID!
|
||||
balance: Float
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
@@ -2906,8 +3257,13 @@ input WalletUpdateInput {
|
||||
balance: Float
|
||||
}
|
||||
|
||||
input WalletUpdateManyMutationInput {
|
||||
balance: Float
|
||||
}
|
||||
|
||||
input WalletUpdateOneInput {
|
||||
create: WalletCreateInput
|
||||
connect: WalletWhereUniqueInput
|
||||
disconnect: Boolean
|
||||
delete: Boolean
|
||||
update: WalletUpdateDataInput
|
||||
@@ -2928,6 +3284,46 @@ input WalletWhereInput {
|
||||
|
||||
"""Logical NOT on all given filters combined by AND."""
|
||||
NOT: [WalletWhereInput!]
|
||||
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
|
||||
balance: Float
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
@@ -2973,3 +3369,7 @@ input WalletWhereInput {
|
||||
"""All values greater than or equal the given value."""
|
||||
updatedAt_gte: DateTime
|
||||
}
|
||||
|
||||
input WalletWhereUniqueInput {
|
||||
id: ID
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { ApolloError } from 'apollo-server-express'
|
||||
|
||||
import { getUser } from '../../../middleware/getMember'
|
||||
|
||||
import { sendTeamMemberInvite, sendTeamCreateConfirmation, verifyInviteToken } from '../../../email/sendgrid'
|
||||
import { notifications_sendTeamCreateConfirmation, notifications_sendTeamMemberInvite, notifications_VerifyTeamMemberInviteToken } from '../notifications/sendgrid'
|
||||
|
||||
import TEAMS_CONNECTIONS_FRAGMENT from '../../fragments/TeamsConnectionsFragment'
|
||||
import TEAMS_FRAGMENT from '../../fragments/TeamsFragment'
|
||||
@@ -20,14 +20,14 @@ export const resolvers = {
|
||||
create:{role:'MEMBER', email:email, team: {connect: {id: teamId}}, status:{create:{status: 'INVITED', reason: `Invited by ${team.members[0].member.alias}`}}},
|
||||
update:{role: 'MEMBER', email: email, team: {connect: {id: teamId}}, status:{create:{status: 'INVITED', reason: `Invite resent by ${team.members[0].member.alias}`}}}},
|
||||
`{ id }`)
|
||||
const sendInvite = await sendTeamMemberInvite(email, team)
|
||||
const sendInvite = await notifications_sendTeamMemberInvite(email, team)
|
||||
return sendInvite
|
||||
},
|
||||
async verifyTeamInvite(parent, { token }, ctx, info) {
|
||||
let verifiedToken = null
|
||||
let team = null
|
||||
try {
|
||||
verifiedToken = await verifyInviteToken(token)
|
||||
verifiedToken = await notifications_VerifyTeamMemberInviteToken(token)
|
||||
team = {
|
||||
email: verifiedToken.email,
|
||||
team: {
|
||||
@@ -53,18 +53,17 @@ export const resolvers = {
|
||||
logger.info(JSON.stringify(await userData))
|
||||
const alias = await userData.data.users_User.alias
|
||||
const email = await userData.data.users_User.email
|
||||
const avatar = 'https://aadevelop.blob.core.windows.net/module-teams/module-default/aa-avatar-default.png'
|
||||
const banner = 'https://aadevelop.blob.core.windows.net/module-teams/module-default/aa-banner-default.png'
|
||||
const avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
const banner = process.env.STORAGE_URL + '/module-teams/module-default/aa-banner-default.png'
|
||||
|
||||
const createTeamUrl = encodeURI(`${slug}/${name}/${alias}/${botSlug}/${botName}`)
|
||||
logger.info('createTeamUrl:')
|
||||
logger.info(JSON.stringify(await createTeamUrl))
|
||||
|
||||
const platformUrl = 'https://develop.advancedalgos.net/AABrowserAPI/newTeam/'
|
||||
// const platformUrl = 'http://localhost:1337/AABrowserAPI/teamSetup/'
|
||||
const chartsUrl = process.env.CHARTS_URL + '/AABrowserAPI/newTeam/'
|
||||
|
||||
logger.info(`${platformUrl}${createTeamUrl}/${authId}`)
|
||||
const createPlatformTeam = await axios.get(`${platformUrl}${createTeamUrl}/${authId}`)
|
||||
logger.info(`${chartsUrl}${createTeamUrl}/${authId}`)
|
||||
const createPlatformTeam = await axios.get(`${chartsUrl}${createTeamUrl}/${authId}/${process.env.AAWEB_TEAM_SHARED_SECRET}`)
|
||||
.then((result) => {
|
||||
console.log('createPlatformTeam result:', result.data)
|
||||
if(result.data.message === 'Team Name already taken'){
|
||||
@@ -112,7 +111,7 @@ export const resolvers = {
|
||||
})
|
||||
}
|
||||
|
||||
sendTeamCreateConfirmation(email, name, botName)
|
||||
notifications_sendTeamCreateConfirmation(email, name, botName)
|
||||
|
||||
return createTeam
|
||||
},
|
||||
@@ -152,11 +151,10 @@ export const resolvers = {
|
||||
logger.info('deleteTeamUrl:')
|
||||
logger.info(JSON.stringify(await deleteTeamUrl))
|
||||
|
||||
const platformUrl = 'https://develop.advancedalgos.net/AABrowserAPI/deleteTeam/'
|
||||
// const platformUrl = 'http://localhost:1337/AABrowserAPI/teamSetup/'
|
||||
const chartsUrl = process.env.CHARTS_URL + '/AABrowserAPI/deleteTeam/'
|
||||
|
||||
logger.info(`${platformUrl}${deleteTeamUrl}/${authId}`)
|
||||
const deletePlatformTeam = await axios.get(`${platformUrl}${deleteTeamUrl}/${authId}`)
|
||||
logger.info(`${chartsUrl}${deleteTeamUrl}/${authId}`)
|
||||
const deletePlatformTeam = await axios.get(`${chartsUrl}${deleteTeamUrl}/${authId}/${process.env.AAWEB_DELETE_TEAM_SHARED_SECRET}`)
|
||||
.then((result) => {
|
||||
console.log('deletePlatformTeam result:', result.data)
|
||||
if(result.data.result === 'Fail'){
|
||||
|
||||
@@ -16,7 +16,13 @@ export const teamById = async (parent, { teamId }, ctx, info) => {
|
||||
}
|
||||
|
||||
export const teamByName = async (parent, { name }, ctx, info) => {
|
||||
return ctx.db.query.team({ where: { name: name } }, `{ name }`)
|
||||
return ctx.db.query.team({ where: { name: name } }, TEAMS_FRAGMENT)
|
||||
}
|
||||
|
||||
export const teamBySlug= async (parent, { slug }, ctx, info) => {
|
||||
logger.info('teamsBySlug')
|
||||
logger.info(`slug: ${slug}`)
|
||||
return ctx.db.query.team({ where: { slug: slug } }, TEAMS_FRAGMENT)
|
||||
}
|
||||
|
||||
export const teamWithRole = async (parent, { teamId, role }, ctx, info) => {
|
||||
@@ -30,7 +36,7 @@ export const teamsByOwner = async (parent, args, ctx, info) => {
|
||||
throw new AuthenticationError()
|
||||
return
|
||||
}
|
||||
return ctx.db.query.teams({where: { owner: authId }, orderBy:'updatedAt_DESC'}, TEAMS_FRAGMENT)
|
||||
return ctx.db.query.teams({where: { owner: authId }, orderBy:'createdAt_DESC'}, TEAMS_FRAGMENT)
|
||||
}
|
||||
|
||||
export const teamsByRole = async (parent, args, ctx, info) => {
|
||||
|
||||
@@ -8,7 +8,7 @@ export const fbByTeamMember = async (parent, args, ctx, info) => {
|
||||
if (!authId) {
|
||||
throw new AuthenticationError()
|
||||
}
|
||||
let teamMemberFB = await ctx.db.query.teams({where: {members_some: {AND: [{member: {authId: authId}}]}}, orderBy: 'updatedAt_DESC'}, TEAM_FB_FRAGMENT)
|
||||
let teamMemberFB = await ctx.db.query.teams({where: {members_some: {AND: [{member: {authId: authId}}]}}, orderBy: 'createdAt_DESC'}, TEAM_FB_FRAGMENT)
|
||||
logger.info('fbByTeamMember response: ', await teamMemberFB[0])
|
||||
return teamMemberFB[0]
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { logger } from '../../../logger'
|
||||
|
||||
import { member, owner } from './Member'
|
||||
import { teams, teamById, teamByName, teamWithRole, teamsByOwner, teamsByRole } from './Team'
|
||||
import { teams, teamById, teamByName, teamBySlug, teamWithRole, teamsByOwner, teamsByRole } from './Team'
|
||||
import{ fbByTeamMember } from './TeamMember'
|
||||
|
||||
export const resolvers = {
|
||||
@@ -10,6 +10,7 @@ export const resolvers = {
|
||||
teams: (parent, arg, ctx, info) => teams(parent, arg, ctx, info),
|
||||
teamById: (parent, arg, ctx, info) => teamById(parent, arg, ctx, info),
|
||||
teamByName: (parent, arg, ctx, info) => teamByName(parent, arg, ctx, info),
|
||||
teamBySlug: (parent, arg, ctx, info) => teamBySlug(parent, arg, ctx, info),
|
||||
teamWithRole: (parent, arg, ctx, info) => teamWithRole(parent, arg, ctx, info),
|
||||
teamsByOwner: (parent, arg, ctx, info) => teamsByOwner(parent, arg, ctx, info),
|
||||
teamsByRole: (parent, arg, ctx, info) => teamsByRole(parent, arg, ctx, info),
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
var jwt = require('jsonwebtoken')
|
||||
var axios = require('axios')
|
||||
|
||||
import { logger } from '../logger'
|
||||
|
||||
export const notifications_sendTeamMemberInvite = (email, team) => {
|
||||
logger.info('notifications_sendTeamMemberInvite')
|
||||
logger.info(email)
|
||||
logger.info(teamName)
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
return axios.post(process.env.PLATFORM_API_URL, {
|
||||
query: `mutation notifications_Teams_SendTeamMemberInvite($email:String!, $teamName:String!){
|
||||
notifications_Teams_SendTeamMemberInvite(email:$email, teamName:$teamName)
|
||||
}`,
|
||||
variables: {
|
||||
email: email,
|
||||
teamName: team.name
|
||||
}
|
||||
}, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
logger.info('sendTeamMemberInvite result')
|
||||
logger.info(res.data)
|
||||
resolve(res.data)
|
||||
})
|
||||
.catch(err => {
|
||||
logger.info('sendTeamMemberInvite err')
|
||||
logger.info(err)
|
||||
reject(err)
|
||||
})
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const notifications_sendTeamCreateConfirmation = (email, teamName, botName) => {
|
||||
logger.info('notifications_sendTeamCreateConfirmation')
|
||||
logger.info(email)
|
||||
logger.info(teamName)
|
||||
logger.info(botName)
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
return axios.post(process.env.PLATFORM_API_URL, {
|
||||
query: `mutation notifications_sendTeamCreateConfirmation($email: String!, $teamName: String!, $botName: String!){
|
||||
notifications_Teams_SendTeamCreateConfirmation(email: $email, teamName: $teamName, botName: $botName)
|
||||
}`,
|
||||
variables: {
|
||||
email: email,
|
||||
teamName: teamName,
|
||||
botName: botName
|
||||
}
|
||||
}, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
logger.info('sendTeamCreateConfirmation result')
|
||||
logger.info(res.data)
|
||||
resolve(res.data)
|
||||
})
|
||||
.catch(err => {
|
||||
logger.info('sendTeamCreateConfirmation err')
|
||||
logger.info(err)
|
||||
reject(err)
|
||||
})
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const notifications_VerifyTeamMemberInviteToken = (token) => {
|
||||
logger.info('notifications_VerifyTeamMemberInviteToken')
|
||||
logger.info(token)
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
return axios.post(process.env.PLATFORM_API_URL, {
|
||||
query: `mutation notifications_VerifyTeamMemberInviteToken($token: String!){
|
||||
notifications_Teams_VerifyTeamMemberInviteToken(token: $token)
|
||||
}`,
|
||||
variables: {
|
||||
token: token
|
||||
}
|
||||
}, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
logger.info('VerifyTeamMemberInviteToken result')
|
||||
logger.info(res.data)
|
||||
resolve(res.data)
|
||||
})
|
||||
.catch(err => {
|
||||
logger.info('VerifyTeamMemberInviteToken err')
|
||||
logger.info(err)
|
||||
reject(err)
|
||||
})
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const verifyInviteToken = async function(token) {
|
||||
const API_KEY = process.env.SG_APIKEY
|
||||
let verifiedToken
|
||||
try {
|
||||
verifiedToken = await jwt.verify(token, API_KEY, {maxAge: '7d'})
|
||||
} catch(err) {
|
||||
if (err.name === "TokenExpiredError"){
|
||||
throw new Error ("Error: Token Expired. Please request new invitation or apply to the team again")
|
||||
} else {
|
||||
throw new Error (`Error: Token error - ${err.message}`)
|
||||
}
|
||||
}
|
||||
logger.info(`verifyInviteToken: ${verifiedToken}`)
|
||||
return verifiedToken
|
||||
}
|
||||
|
||||
module.exports = { sendTeamMemberInvite, sendTeamCreateConfirmation, verifyInviteToken }
|
||||
@@ -9,6 +9,7 @@ type Query {
|
||||
teams: TeamConnection
|
||||
teamDetails: [Team!]! @isAuthenticated
|
||||
teamByName(name: String!): Team
|
||||
teamBySlug(slug: String!): Team
|
||||
teamById(teamId: String!): Team
|
||||
teamWithRole(teamId: String!, role: String!): Team
|
||||
teamsByOwner: [Team!]! @isAuthenticated
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ const db = new Prisma({
|
||||
typeDefs: 'src/generated/prisma.graphql',
|
||||
endpoint: process.env.PRISMA_ENDPOINT,
|
||||
secret: process.env.PRISMA_SECRET,
|
||||
debug: true
|
||||
debug: false
|
||||
})
|
||||
|
||||
const app = express()
|
||||
|
||||
@@ -19,10 +19,9 @@ export const getMember = async (req, res, next, db) => {
|
||||
export const getUser = authId => {
|
||||
logger.info('getUser MiddleWare')
|
||||
logger.info(authId)
|
||||
const API_URL = 'https://app-api.advancedalgos.net/graphql'
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
return axios.post(API_URL, {
|
||||
return axios.post(process.env.PLATFORM_API_URL, {
|
||||
query: `query users_User($userId: ID!) {
|
||||
users_User(id: $userId){
|
||||
id
|
||||
|
||||
Generated
+300
-149
@@ -1,27 +1,30 @@
|
||||
{
|
||||
"name": "@advancedalgos/teams-client",
|
||||
"version": "0.0.22",
|
||||
"version": "0.0.31",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@advancedalgos/web-components": {
|
||||
"version": "0.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@advancedalgos/web-components/-/web-components-0.0.13.tgz",
|
||||
"integrity": "sha512-jXz2w/r08GX8uqB4UTDaow27T3juvR7Bk/80TWmDORVPNCPK152MEUBgxF161hAyOj1jdB+K4M1Fy5GkEpDhmw==",
|
||||
"version": "0.0.17",
|
||||
"resolved": "https://registry.npmjs.org/@advancedalgos/web-components/-/web-components-0.0.17.tgz",
|
||||
"integrity": "sha512-xD+0E4XBltgIxH/9TkzMS6a6iz7973YjxOzEr2O/D93lGIeHaYJQTDwykOLtSocuSaSSYRzxFlf82pVh22wLIA==",
|
||||
"requires": {
|
||||
"@azure/storage-blob": "^10.1.0-preview",
|
||||
"@material-ui/core": "^3.2.2",
|
||||
"@bearcanrun/react-image-cropper": "^1.3.6",
|
||||
"@material-ui/core": "^3.6.1",
|
||||
"@material-ui/icons": "^3.0.1",
|
||||
"apollo-client": "^2.4.2",
|
||||
"apollo-client": "^2.4.7",
|
||||
"blob-util": "^2.0.2",
|
||||
"browser-image-resizer": "^1.2.0",
|
||||
"graphql": "^14.0.2",
|
||||
"graphql-tag": "^2.9.2",
|
||||
"graphql-tag": "^2.10.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-apollo": "^2.1.11",
|
||||
"react": "^16.6.1",
|
||||
"react-apollo": "^2.3.2",
|
||||
"react-dom": "^16.6.1",
|
||||
"react-dropzone": "^5.1.0",
|
||||
"react-image-crop": "^5.0.0",
|
||||
"react-image-cropper": "^1.3.0"
|
||||
"react-helmet": "^5.2.0",
|
||||
"react-router-dom": "^4.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/storage-blob": {
|
||||
@@ -34,16 +37,76 @@
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"@types/async": {
|
||||
"version": "2.0.50",
|
||||
"resolved": "https://registry.npmjs.org/@types/async/-/async-2.0.50.tgz",
|
||||
"integrity": "sha512-VMhZMMQgV1zsR+lX/0IBfAk+8Eb7dPVMWiQGFAt3qjo5x7Ml6b77jUo0e1C3ToD+XRDXqtrfw+6AB0uUsPEr3Q==",
|
||||
"optional": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "9.6.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.35.tgz",
|
||||
"integrity": "sha512-h5zvHS8wXHGa+Gcqs9K8vqCgOtqjr0+NqG/DDJmQIX1wpR9HivAfgV8bjcD3mGM4bPfQw5Aneb2Pn8355L83jA=="
|
||||
"version": "9.6.40",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.40.tgz",
|
||||
"integrity": "sha512-M3HHoXXndsho/sTbQML2BJr7/uwNhMg8P0D4lb+UsM65JQZx268faiz9hKpY4FpocWqpwlLwa8vevw8hLtKjOw=="
|
||||
},
|
||||
"apollo-cache": {
|
||||
"version": "1.1.21",
|
||||
"resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.1.21.tgz",
|
||||
"integrity": "sha512-5ErNb78KHtrJNimkDBTEigcvHkIqUmS7QJIk4lpZZ+XLVVgvk2fD+GhD1PLP+s8vHfAKVbO6vdbRxCCjGGrh5w==",
|
||||
"requires": {
|
||||
"apollo-utilities": "^1.0.26"
|
||||
}
|
||||
},
|
||||
"apollo-client": {
|
||||
"version": "2.4.7",
|
||||
"resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-2.4.7.tgz",
|
||||
"integrity": "sha512-6aAm+16AFBYZhJF8eKxrup6AbYni01InDiwTfZhMMTP2xaXQWjsQnfaHbI2oE+hd3+AZFy1drkse8RZKghR/WQ==",
|
||||
"requires": {
|
||||
"@types/async": "2.0.50",
|
||||
"@types/zen-observable": "^0.8.0",
|
||||
"apollo-cache": "1.1.21",
|
||||
"apollo-link": "^1.0.0",
|
||||
"apollo-link-dedup": "^1.0.0",
|
||||
"apollo-utilities": "1.0.26",
|
||||
"symbol-observable": "^1.0.2",
|
||||
"zen-observable": "^0.8.0"
|
||||
}
|
||||
},
|
||||
"apollo-utilities": {
|
||||
"version": "1.0.26",
|
||||
"resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.26.tgz",
|
||||
"integrity": "sha512-URw7o3phymliqYCYatcird2YRPUU2eWCNvip64U9gQrX56mEfK4m99yBIDCMTpmcvOFsKLii1sIEZsHIs/bvnw==",
|
||||
"requires": {
|
||||
"fast-json-stable-stringify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
|
||||
"integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA=="
|
||||
},
|
||||
"fbjs": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-1.0.0.tgz",
|
||||
"integrity": "sha512-MUgcMEJaFhCaF1QtWGnmq9ZDRAzECTCRAF7O6UZIlAlkTs1SasiX9aP0Iw7wfD2mJ7wDTNfg2w7u5fSCwJk1OA==",
|
||||
"requires": {
|
||||
"core-js": "^2.4.1",
|
||||
"fbjs-css-vars": "^1.0.0",
|
||||
"isomorphic-fetch": "^2.1.1",
|
||||
"loose-envify": "^1.0.0",
|
||||
"object-assign": "^4.1.0",
|
||||
"promise": "^7.1.1",
|
||||
"setimmediate": "^1.0.5",
|
||||
"ua-parser-js": "^0.7.18"
|
||||
}
|
||||
},
|
||||
"hoist-non-react-statics": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.2.1.tgz",
|
||||
"integrity": "sha512-TFsu3TV3YLY+zFTZDrN8L2DTFanObwmBLpWvJs1qfUuEQ5bTAdFcwfx2T/bsCXfM9QHSLvjfP+nihEl0yvozxw==",
|
||||
"requires": {
|
||||
"react-is": "^16.3.2"
|
||||
}
|
||||
},
|
||||
"ms-rest-js": {
|
||||
"version": "0.22.425",
|
||||
"resolved": "https://registry.npmjs.org/ms-rest-js/-/ms-rest-js-0.22.425.tgz",
|
||||
@@ -61,13 +124,36 @@
|
||||
"xml2js": "^0.4.19"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"react-apollo": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/react-apollo/-/react-apollo-2.3.2.tgz",
|
||||
"integrity": "sha512-3lU9iqmj4KMIZvlWWSuLihxMGLEAL6oNmnSTWrb3/mRP36Zy0zJD4rdaonDx4WzqFYQAnUPaOiFnHGp0UQUTwA==",
|
||||
"requires": {
|
||||
"psl": "^1.1.24",
|
||||
"punycode": "^1.4.1"
|
||||
"fbjs": "^1.0.0",
|
||||
"hoist-non-react-statics": "^3.0.0",
|
||||
"invariant": "^2.2.2",
|
||||
"lodash.flowright": "^3.5.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"prop-types": "^15.6.0"
|
||||
}
|
||||
},
|
||||
"symbol-observable": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
|
||||
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"requires": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1992,12 +2078,100 @@
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@bearcanrun/react-image-cropper": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@bearcanrun/react-image-cropper/-/react-image-cropper-1.3.6.tgz",
|
||||
"integrity": "sha512-/6F2rNd/bNR7jB/Pxhan1T6KDF+CHl9hEeybumtOyZrYc2foxawMNjxgD4MW0Z3Wh6GxZKDM9dlsxaaC+/y0Zg==",
|
||||
"requires": {
|
||||
"deep-extend": "^0.6.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prop-types": "15.6.0",
|
||||
"react": "16.5.2",
|
||||
"react-dom": "16.5.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
|
||||
"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
|
||||
},
|
||||
"fbjs": {
|
||||
"version": "0.8.17",
|
||||
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
|
||||
"integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
|
||||
"requires": {
|
||||
"core-js": "^1.0.0",
|
||||
"isomorphic-fetch": "^2.1.1",
|
||||
"loose-envify": "^1.0.0",
|
||||
"object-assign": "^4.1.0",
|
||||
"promise": "^7.1.1",
|
||||
"setimmediate": "^1.0.5",
|
||||
"ua-parser-js": "^0.7.18"
|
||||
}
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.6.0",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz",
|
||||
"integrity": "sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY=",
|
||||
"requires": {
|
||||
"fbjs": "^0.8.16",
|
||||
"loose-envify": "^1.3.1",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"react": {
|
||||
"version": "16.5.2",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.5.2.tgz",
|
||||
"integrity": "sha512-FDCSVd3DjVTmbEAjUNX6FgfAmQ+ypJfHUsqUJOYNCBUp1h8lqmtC+0mXJ+JjsWx4KAVTkk1vKd1hLQPvEviSuw==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"schedule": "^0.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"prop-types": {
|
||||
"version": "15.6.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
|
||||
"integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.3.1",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-dom": {
|
||||
"version": "16.5.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.5.2.tgz",
|
||||
"integrity": "sha512-RC8LDw8feuZOHVgzEf7f+cxBr/DnKdqp56VU0lAs1f4UfKc4cU8wU4fTq/mgnvynLQo8OtlPC19NUFh/zjZPuA==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"schedule": "^0.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"prop-types": {
|
||||
"version": "15.6.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
|
||||
"integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.3.1",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@material-ui/core": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-3.2.2.tgz",
|
||||
"integrity": "sha512-wDTJyR76+OBdlltiPs3lc1gD6zR+dSA6nITtgkBeLf1NvWfNotMWdvldIDnF3bu24ySAX9imfzDfkBu4Edtqww==",
|
||||
"version": "3.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-3.6.1.tgz",
|
||||
"integrity": "sha512-jmDtLQVXYHzvv6TljspaoHazGXkgmgnLUosFateBdB3Vva6WVJZ7WY5LaAGOqtuTEUW6KUKDumaGoOQs4xuJWA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "7.1.2",
|
||||
"@material-ui/utils": "^3.0.0-alpha.0",
|
||||
"@types/jss": "^9.5.6",
|
||||
"@types/react-transition-group": "^2.0.8",
|
||||
"brcast": "^3.0.1",
|
||||
@@ -2006,7 +2180,7 @@
|
||||
"debounce": "^1.1.0",
|
||||
"deepmerge": "^2.0.1",
|
||||
"dom-helpers": "^3.2.1",
|
||||
"hoist-non-react-statics": "^2.5.0",
|
||||
"hoist-non-react-statics": "^3.0.0",
|
||||
"is-plain-object": "^2.0.4",
|
||||
"jss": "^9.3.3",
|
||||
"jss-camel-case": "^6.0.0",
|
||||
@@ -2032,6 +2206,14 @@
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.12.0"
|
||||
}
|
||||
},
|
||||
"hoist-non-react-statics": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.2.1.tgz",
|
||||
"integrity": "sha512-TFsu3TV3YLY+zFTZDrN8L2DTFanObwmBLpWvJs1qfUuEQ5bTAdFcwfx2T/bsCXfM9QHSLvjfP+nihEl0yvozxw==",
|
||||
"requires": {
|
||||
"react-is": "^16.3.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2083,6 +2265,24 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@material-ui/utils": {
|
||||
"version": "3.0.0-alpha.0",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-3.0.0-alpha.0.tgz",
|
||||
"integrity": "sha512-HwC/pBcPG81UP4Jh0BaH2i4wAY9aDOrvL5+B/7J6cyFlG/Wip5Li+qI+GDlk9MR3kpG8v0sxfpWA0IlQYcHK6g==",
|
||||
"requires": {
|
||||
"@babel/runtime": "7.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.1.2.tgz",
|
||||
"integrity": "sha512-Y3SCjmhSupzFB6wcv1KmmFucH6gDVnI30WjOcicV10ju0cZjak3Jcs67YLIXBrmZYw1xCrVeJPbycFwrqNyxpg==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.12.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@sheerun/eslint-config-standard": {
|
||||
"version": "10.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@sheerun/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz",
|
||||
@@ -2219,9 +2419,9 @@
|
||||
"integrity": "sha512-HtKGu+qG1NPvYe1z7ezLsyIaXYyi8SoAVqWDZgDQ8dLrsZvSzUNCwZyfX33uhWxL/SU0ZDQZ3nwZ0nimt507Kw=="
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "16.4.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.18.tgz",
|
||||
"integrity": "sha512-eFzJKEg6pdeaukVLVZ8Xb79CTl/ysX+ExmOfAAqcFlCCK5TgFDD9kWR0S18sglQ3EmM8U+80enjUqbfnUyqpdA==",
|
||||
"version": "16.7.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.7.13.tgz",
|
||||
"integrity": "sha512-WhqrQLAE9z65hfcvWqZfR6qUtIazFRyb8LXqHo8440R53dAQqNkt2OlVJ3FXwqOwAXXg4nfYxt0qgBvE18o5XA==",
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^2.2.0"
|
||||
@@ -5313,9 +5513,9 @@
|
||||
}
|
||||
},
|
||||
"csstype": {
|
||||
"version": "2.5.7",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.5.7.tgz",
|
||||
"integrity": "sha512-Nt5VDyOTIIV4/nRFswoCKps1R5CD1hkiyjBE9/thNaNZILLEviVw9yWQw15+O+CpNjQKB/uvdcxFFOrSflY3Yw=="
|
||||
"version": "2.5.8",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.5.8.tgz",
|
||||
"integrity": "sha512-r4DbsyNJ7slwBSKoGesxDubRWJ71ghG8W2+1HcsDlAo12KGca9dDLv0u98tfdFw7ldBdoA7XmCnI6Q8LpAJXaQ=="
|
||||
},
|
||||
"currently-unhandled": {
|
||||
"version": "0.4.1",
|
||||
@@ -5393,14 +5593,12 @@
|
||||
"deep-equal": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
|
||||
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
|
||||
"dev": true
|
||||
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
|
||||
},
|
||||
"deep-extend": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
|
||||
},
|
||||
"deep-is": {
|
||||
"version": "0.1.3",
|
||||
@@ -5654,7 +5852,8 @@
|
||||
"duplexer": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
||||
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E="
|
||||
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
|
||||
"dev": true
|
||||
},
|
||||
"duplexer3": {
|
||||
"version": "0.1.4",
|
||||
@@ -6353,21 +6552,6 @@
|
||||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
|
||||
"dev": true
|
||||
},
|
||||
"event-stream": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.6.tgz",
|
||||
"integrity": "sha512-dGXNg4F/FgVzlApjzItL+7naHutA3fDqbV/zAZqDDlXTjiMnQmZKu+prImWKszeBM5UQeGvAl3u1wBiKeDh61g==",
|
||||
"requires": {
|
||||
"duplexer": "^0.1.1",
|
||||
"flatmap-stream": "^0.1.0",
|
||||
"from": "^0.1.7",
|
||||
"map-stream": "0.0.7",
|
||||
"pause-stream": "^0.0.11",
|
||||
"split": "^1.0.1",
|
||||
"stream-combiner": "^0.2.2",
|
||||
"through": "^2.3.8"
|
||||
}
|
||||
},
|
||||
"eventemitter3": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
|
||||
@@ -6404,6 +6588,11 @@
|
||||
"strip-eof": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"exenv": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
|
||||
"integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
|
||||
},
|
||||
"expand-brackets": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
|
||||
@@ -6814,11 +7003,6 @@
|
||||
"write": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"flatmap-stream": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/flatmap-stream/-/flatmap-stream-0.1.1.tgz",
|
||||
"integrity": "sha512-lAq4tLbm3sidmdCN8G3ExaxH7cUCtP5mgDvrYowsx84dcYkJJ4I28N7gkxA6+YlSXzaGLJYIDEi9WGfXzMiXdw=="
|
||||
},
|
||||
"flatten": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
|
||||
@@ -6896,11 +7080,6 @@
|
||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
|
||||
"dev": true
|
||||
},
|
||||
"from": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
|
||||
"integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4="
|
||||
},
|
||||
"from2": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
|
||||
@@ -8255,17 +8434,17 @@
|
||||
"dev": true
|
||||
},
|
||||
"indefinite-observable": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/indefinite-observable/-/indefinite-observable-1.0.1.tgz",
|
||||
"integrity": "sha1-CZFUI8yNb36xy3iCrRNGM8mm7cM=",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/indefinite-observable/-/indefinite-observable-1.0.2.tgz",
|
||||
"integrity": "sha512-Mps0898zEduHyPhb7UCgNmfzlqNZknVmaFz5qzr0mm04YQ5FGLhAyK/dJ+NaRxGyR6juQXIxh5Ev0xx+qq0nYA==",
|
||||
"requires": {
|
||||
"symbol-observable": "1.0.4"
|
||||
"symbol-observable": "1.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"symbol-observable": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz",
|
||||
"integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0="
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
|
||||
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -9464,11 +9643,6 @@
|
||||
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
|
||||
"dev": true
|
||||
},
|
||||
"map-stream": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz",
|
||||
"integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg="
|
||||
},
|
||||
"map-visit": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
|
||||
@@ -10309,16 +10483,16 @@
|
||||
}
|
||||
},
|
||||
"npm-run-all": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.3.tgz",
|
||||
"integrity": "sha512-aOG0N3Eo/WW+q6sUIdzcV2COS8VnTZCmdji0VQIAZF3b+a3YWb0AD0vFIyjKec18A7beLGbaQ5jFTNI2bPt9Cg==",
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
|
||||
"integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.0",
|
||||
"chalk": "^2.1.0",
|
||||
"cross-spawn": "^6.0.4",
|
||||
"ansi-styles": "^3.2.1",
|
||||
"chalk": "^2.4.1",
|
||||
"cross-spawn": "^6.0.5",
|
||||
"memorystream": "^0.3.1",
|
||||
"minimatch": "^3.0.4",
|
||||
"ps-tree": "^1.1.0",
|
||||
"pidtree": "^0.3.0",
|
||||
"read-pkg": "^3.0.0",
|
||||
"shell-quote": "^1.6.1",
|
||||
"string.prototype.padend": "^3.0.0"
|
||||
@@ -10856,14 +11030,6 @@
|
||||
"pify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"pause-stream": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
|
||||
"integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
|
||||
"requires": {
|
||||
"through": "~2.3"
|
||||
}
|
||||
},
|
||||
"pbkdf2": {
|
||||
"version": "3.0.17",
|
||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
|
||||
@@ -10883,6 +11049,11 @@
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||
"dev": true
|
||||
},
|
||||
"pidtree": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz",
|
||||
"integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg=="
|
||||
},
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
@@ -10920,9 +11091,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"popper.js": {
|
||||
"version": "1.14.4",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.4.tgz",
|
||||
"integrity": "sha1-juwdj/AqWjoVLdQ0FKFce3n9abY="
|
||||
"version": "1.14.6",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.6.tgz",
|
||||
"integrity": "sha512-AGwHGQBKumlk/MDfrSOf0JHhJCImdDMcGNoqKmKkU+68GFazv3CQ6q9r7Ja1sKDZmYWTckY/uLyEznheTDycnA=="
|
||||
},
|
||||
"posix-character-classes": {
|
||||
"version": "0.1.1",
|
||||
@@ -11846,14 +12017,6 @@
|
||||
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
|
||||
"dev": true
|
||||
},
|
||||
"ps-tree": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz",
|
||||
"integrity": "sha1-tCGyQUDWID8e08dplrRCewjowBQ=",
|
||||
"requires": {
|
||||
"event-stream": "~3.3.0"
|
||||
}
|
||||
},
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
@@ -12040,14 +12203,14 @@
|
||||
}
|
||||
},
|
||||
"react": {
|
||||
"version": "16.5.2",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.5.2.tgz",
|
||||
"integrity": "sha512-FDCSVd3DjVTmbEAjUNX6FgfAmQ+ypJfHUsqUJOYNCBUp1h8lqmtC+0mXJ+JjsWx4KAVTkk1vKd1hLQPvEviSuw==",
|
||||
"version": "16.6.1",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.6.1.tgz",
|
||||
"integrity": "sha512-OtawJThYlvRgm9BXK+xTL7BIlDx8vv21j+fbQDjRRUyok6y7NyjlweGorielTahLZHYIdKUoK2Dp9ByVWuMqxw==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"schedule": "^0.5.0"
|
||||
"scheduler": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"react-apollo": {
|
||||
@@ -12089,14 +12252,14 @@
|
||||
}
|
||||
},
|
||||
"react-dom": {
|
||||
"version": "16.5.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.5.2.tgz",
|
||||
"integrity": "sha512-RC8LDw8feuZOHVgzEf7f+cxBr/DnKdqp56VU0lAs1f4UfKc4cU8wU4fTq/mgnvynLQo8OtlPC19NUFh/zjZPuA==",
|
||||
"version": "16.6.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.6.1.tgz",
|
||||
"integrity": "sha512-zm+wBuEMGm009Wt1uE4Zw5KcXOW7qC4E/xW/fpJsCsbOco4U/R84u+DzzO/S4SYSdNBcqcaulcp4w3FXl8pImw==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"schedule": "^0.5.0"
|
||||
"scheduler": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"react-dropzone": {
|
||||
@@ -12118,6 +12281,17 @@
|
||||
"warning": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"react-helmet": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-5.2.0.tgz",
|
||||
"integrity": "sha1-qBgR3yExOm1VxfBYxK66XW89l6c=",
|
||||
"requires": {
|
||||
"deep-equal": "^1.0.1",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.5.4",
|
||||
"react-side-effect": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"react-hot-loader": {
|
||||
"version": "4.3.11",
|
||||
"resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-4.3.11.tgz",
|
||||
@@ -12132,30 +12306,6 @@
|
||||
"shallowequal": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"react-image-crop": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-image-crop/-/react-image-crop-5.0.0.tgz",
|
||||
"integrity": "sha512-MBT18tcHeEpmrhbSS6hx00MmfNgrnlhZuwY96cGRPhUmNeabxM7UBCcoU+oJCZXB0iGZk38zy/YGoZ4ELVp/LQ=="
|
||||
},
|
||||
"react-image-cropper": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-image-cropper/-/react-image-cropper-1.3.0.tgz",
|
||||
"integrity": "sha512-OPEMv66xXQdNsAixqxhlsSX3+D3KVRQMYc6YHmgGINeKx433xB9l04hMFynngPuUa+ChiKal6aQmbzpg79iJ+Q==",
|
||||
"requires": {
|
||||
"deep-extend": "^0.4.1",
|
||||
"npm-run-all": "^4.1.1",
|
||||
"prop-types": "^15.6.0",
|
||||
"react": "^16.2.0",
|
||||
"react-dom": "^16.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"deep-extend": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz",
|
||||
"integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8="
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.5.2",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.5.2.tgz",
|
||||
@@ -12193,6 +12343,15 @@
|
||||
"warning": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"react-side-effect": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-1.1.5.tgz",
|
||||
"integrity": "sha512-Z2ZJE4p/jIfvUpiUMRydEVpQRf2f8GMHczT6qLcARmX7QRb28JDBTpnM2g/i5y/p7ZDEXYGHWg0RbhikE+hJRw==",
|
||||
"requires": {
|
||||
"exenv": "^1.2.1",
|
||||
"shallowequal": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"react-transition-group": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.5.0.tgz",
|
||||
@@ -13096,6 +13255,15 @@
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"scheduler": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.11.0.tgz",
|
||||
"integrity": "sha512-MAYbBfmiEHxF0W+c4CxMpEqMYK+rYF584VP/qMKSiHM6lTkBKKYOJaDiSILpJHla6hBOsVd6GucPL46o2Uq3sg==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "0.4.5",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz",
|
||||
@@ -13322,8 +13490,7 @@
|
||||
"shallowequal": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
|
||||
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "1.2.0",
|
||||
@@ -13563,14 +13730,6 @@
|
||||
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz",
|
||||
"integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA=="
|
||||
},
|
||||
"split": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
|
||||
"integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
|
||||
"requires": {
|
||||
"through": "2"
|
||||
}
|
||||
},
|
||||
"split-string": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
|
||||
@@ -13658,15 +13817,6 @@
|
||||
"readable-stream": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"stream-combiner": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz",
|
||||
"integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=",
|
||||
"requires": {
|
||||
"duplexer": "~0.1.1",
|
||||
"through": "~2.3.4"
|
||||
}
|
||||
},
|
||||
"stream-each": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
|
||||
@@ -13980,7 +14130,8 @@
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
||||
"dev": true
|
||||
},
|
||||
"through2": {
|
||||
"version": "2.0.3",
|
||||
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@advancedalgos/teams-client",
|
||||
"version": "0.0.24",
|
||||
"version": "0.0.32",
|
||||
"description": "Advanced Algos Team client-side web app",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
@@ -69,7 +69,7 @@
|
||||
"workbox-cli": "^3.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@advancedalgos/web-components": "0.0.13",
|
||||
"@advancedalgos/web-components": "0.0.18",
|
||||
"@azure/storage-blob": "^10.0.0-preview",
|
||||
"apollo-cache-inmemory": "^1.3.5",
|
||||
"apollo-client": "^2.4.2",
|
||||
@@ -90,15 +90,15 @@
|
||||
"minilog": "^3.1.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"query-string": "^6.2.0",
|
||||
"react": "^16.5.2",
|
||||
"react": "^16.6.1",
|
||||
"react-apollo": "^2.2.4",
|
||||
"react-dom": "^16.5.2",
|
||||
"react-dom": "^16.6.1",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"recompose": "^0.30.0",
|
||||
"subscriptions-transport-ws": "^0.9.15"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@material-ui/core": "^3.2.0",
|
||||
"@material-ui/core": "^3.6.2",
|
||||
"@material-ui/icons": "^3.0.1"
|
||||
},
|
||||
"standard": {
|
||||
|
||||
+34
-44
@@ -1,6 +1,6 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Route, BrowserRouter, Switch } from 'react-router-dom'
|
||||
import { Route, Switch } from 'react-router-dom'
|
||||
import { hot } from 'react-hot-loader'
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
@@ -8,10 +8,9 @@ import {
|
||||
AcceptTeamInvite,
|
||||
ManageTeams,
|
||||
TeamMembers,
|
||||
FinancialBeings,
|
||||
Settings,
|
||||
Teams,
|
||||
TeamBar,
|
||||
Landing,
|
||||
globalStyles
|
||||
} from './views'
|
||||
|
||||
@@ -35,48 +34,39 @@ class App extends Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { match } = this.props
|
||||
let loggedIn
|
||||
if (this.state.user !== null) {
|
||||
loggedIn = (<TeamBar match={match} user={this.state.user} />)
|
||||
} else {
|
||||
loggedIn = ''
|
||||
}
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<div className='App'>
|
||||
{loggedIn}
|
||||
<Switch>
|
||||
<Route exact path={`${match.path}`} component={Teams} />
|
||||
<Route
|
||||
exact
|
||||
path={`${match.path}/manage-teams`}
|
||||
render={props => <ManageTeams {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${match.path}/team-members`}
|
||||
render={props => <TeamMembers {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${match.path}/financial-beings`}
|
||||
render={props => <FinancialBeings {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${match.path}/financial-beings`}
|
||||
render={props => <Settings {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${match.path}/activate-team-membership`}
|
||||
render={props => <AcceptTeamInvite {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route path='/teams/:slug' component={Teams} />
|
||||
</Switch>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
<div className='App'>
|
||||
<Switch>
|
||||
<Route exact path={`/teams`} component={Landing} />
|
||||
<Route exact path={`/teams/explore`} component={Teams} />
|
||||
<Route
|
||||
exact
|
||||
path={`/teams/manage-teams`}
|
||||
render={props => <ManageTeams {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`/teams/manage-teams/:slug`}
|
||||
render={props => <ManageTeams {...props} auth={this.props.auth} user={this.state.user} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`/teams/team-members`}
|
||||
render={props => <TeamMembers {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`/teams/settings`}
|
||||
render={props => <Settings {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`/teams/activate-team-membership`}
|
||||
render={props => <AcceptTeamInvite {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route exact path='/teams/:slug' component={Teams} />
|
||||
</Switch>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
|
||||
const BannerTopBar = ({
|
||||
size,
|
||||
backgroundUrl,
|
||||
title,
|
||||
text
|
||||
}) => (
|
||||
<div className={`bannerTopBar ${size}`} style={backgroundUrl ? { backgroundImage: `url(${backgroundUrl})` } : {}}>
|
||||
<div className='caption'>
|
||||
<Typography className='title' variant='h1' align='center'>{title}</Typography>
|
||||
<Typography className='text' variant='h2' align='center'>{text}</Typography>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
BannerTopBar.propTypes = {
|
||||
backgroundUrl: PropTypes.string,
|
||||
size: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
text: PropTypes.string
|
||||
}
|
||||
|
||||
export default BannerTopBar
|
||||
@@ -0,0 +1,39 @@
|
||||
const styles = () => ({
|
||||
rootBig: {
|
||||
backgroundImage: 'url(https://aacorporatesitedevelop.azurewebsites.net/img/photos/connect.jpg)',
|
||||
width: '100%',
|
||||
height: '100vh'
|
||||
},
|
||||
rootMedium: {
|
||||
backgroundImage: 'url(https://aacorporatesitedevelop.azurewebsites.net/img/photos/connect.jpg)',
|
||||
width: '100%',
|
||||
height: '50vh'
|
||||
},
|
||||
rootSmall: {
|
||||
backgroundImage: 'url(https://aacorporatesitedevelop.azurewebsites.net/img/photos/connect.jpg)',
|
||||
width: '100%',
|
||||
height: '220px'
|
||||
},
|
||||
captions: {
|
||||
position: 'relative',
|
||||
top: '50%',
|
||||
transform: 'translateY(-50%)'
|
||||
},
|
||||
title: {
|
||||
fontFamily: 'Saira',
|
||||
color: 'white',
|
||||
fontSize: '64px',
|
||||
lineHeight: '78px',
|
||||
fontWeight: 100
|
||||
},
|
||||
text: {
|
||||
fontFamily: 'Saira',
|
||||
color: 'white',
|
||||
fontSize: '20px',
|
||||
lineHeight: '30px',
|
||||
fontWeight: 600,
|
||||
padding: '20px 0 0.5em 0'
|
||||
}
|
||||
})
|
||||
|
||||
export default styles
|
||||
@@ -1,3 +1,4 @@
|
||||
import TeamBar from './components/TeamBar'
|
||||
import BannerTopBar from './components/BannerTopBar'
|
||||
|
||||
export { TeamBar }
|
||||
export { TeamBar, BannerTopBar }
|
||||
@@ -120,7 +120,7 @@ export class ManageFBEdit extends Component {
|
||||
let avatar = null
|
||||
if (fb.avatar !== undefined && fb.avatar !== null) avatar = fb.avatar
|
||||
if (this.state.avatar !== null) avatar = this.state.avatar
|
||||
if (this.state.avatar === null && fb.avatar === undefined) avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
if (this.state.avatar === null && fb.avatar === undefined) avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
|
||||
if (loading || data === undefined) {
|
||||
return (<MessageCard message='Loading...' />)
|
||||
|
||||
@@ -18,7 +18,7 @@ export const ManageFBItem = ({ classes, team, authId }) => {
|
||||
if (team.fb[0].avatar !== undefined && team.fb[0].avatar !== 'a') {
|
||||
avatar = team.fb[0].avatar
|
||||
} else {
|
||||
avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
avatar = process.env.STORAGE_URL+'/module-teams/module-default/aa-avatar-default.png'
|
||||
}
|
||||
return (
|
||||
<Grid item xs={12}>
|
||||
|
||||
@@ -32,7 +32,7 @@ export const ManageMembersItem = ({ classes, member, teamId, authId }) => {
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<Typography color='textSecondary' variant='body2' component='h4' align='left' >
|
||||
<Typography color='textSecondary' variant='body1' component='h4' align='left' >
|
||||
{email !== null ? `${memberStatus[memberStatus.length - 1].status} | Sent: ${memberStatus[memberStatus.length - 1].createdAt}` : `${member.role} | Member since: `}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
@@ -63,7 +63,7 @@ export const ManageMembersTeamItem = ({ classes, team, authId }) => {
|
||||
if (team.profile.avatar !== undefined && team.profile.avatar !== 'a') {
|
||||
avatar = team.profile.avatar
|
||||
} else {
|
||||
avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
}
|
||||
if (team.members.length > 0) {
|
||||
return (
|
||||
|
||||
@@ -72,12 +72,12 @@ export class ManageTeamDetails extends Component {
|
||||
if (profile.avatar !== undefined && profile.avatar !== null) {
|
||||
avatar = profile.avatar
|
||||
} else {
|
||||
avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
}
|
||||
if (profile.banner !== undefined && profile.banner !== null) {
|
||||
banner = profile.banner
|
||||
} else {
|
||||
banner = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-banner-default.png'
|
||||
banner = process.env.STORAGE_URL + '/module-teams/module-default/aa-banner-default.png'
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -129,11 +129,11 @@ export class ManageTeamEdit extends Component {
|
||||
let avatar = null
|
||||
if (team.profile !== null && team.profile.avatar !== undefined && team.profile.avatar !== null) avatar = team.profile.avatar
|
||||
if (this.state.avatar !== null) avatar = this.state.avatar
|
||||
if (this.state.avatar === null && team.profile !== null && team.profile.avatar === undefined) avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
if (this.state.avatar === null && team.profile !== null && team.profile.avatar === undefined) avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
let banner = null
|
||||
if (team.profile !== null && team.profile.banner !== undefined && team.profile.banner !== null) banner = team.profile.banner
|
||||
if (this.state.banner !== null) banner = this.state.banner
|
||||
if (this.state.banner === null && team.profile !== null && team.profile.banner === undefined) banner = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-banner-default.png'
|
||||
if (this.state.banner === null && team.profile !== null && team.profile.banner === undefined) banner = process.env.STORAGE_URL + '/module-teams/module-default/aa-banner-default.png'
|
||||
log.debug('team images: ', avatar, banner)
|
||||
|
||||
if (loading || data === undefined) {
|
||||
|
||||
@@ -20,7 +20,7 @@ export const ManageTeamsItem = ({ classes, team, authId }) => {
|
||||
if (team.profile.avatar !== undefined && team.profile.avatar !== 'a') {
|
||||
avatar = team.profile.avatar
|
||||
} else {
|
||||
avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
}
|
||||
return (
|
||||
<Grid item xs={12}>
|
||||
|
||||
@@ -68,7 +68,7 @@ export class ManageFBEdit extends Component {
|
||||
const containerName = slug
|
||||
|
||||
let avatar = null
|
||||
if (this.state.avatar === null && fb.avatar === undefined) avatar = 'https://aadevelop.blob.core.windows.net/module-teams/module-default/aa-avatar-default.png'
|
||||
if (this.state.avatar === null && fb.avatar === undefined) avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
if (fb.avatar !== undefined && fb.avatar !== null) avatar = fb.avatar
|
||||
if (this.state.avatar !== null) avatar = this.state.avatar
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export const ManageFBItem = ({ classes, team }) => {
|
||||
if (team.fb[0].avatar !== undefined && team.fb[0].avatar !== 'a') {
|
||||
avatar = team.fb[0].avatar
|
||||
} else {
|
||||
avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
}
|
||||
return (
|
||||
<Grid item xs={12}>
|
||||
|
||||
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types'
|
||||
import { Query } from 'react-apollo'
|
||||
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
@@ -13,10 +15,13 @@ import log from '../../../utils/log'
|
||||
import ManageFBItem from './ManageFBItem'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1
|
||||
},
|
||||
heroContent: {
|
||||
maxWidth: 600,
|
||||
margin: '0 auto',
|
||||
padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px`
|
||||
maxWidth: 800,
|
||||
margin: `${theme.spacing.unit * 4}px auto`,
|
||||
padding: 0
|
||||
},
|
||||
cardGrid: {
|
||||
padding: `${theme.spacing.unit * 8}px 0`
|
||||
@@ -61,36 +66,53 @@ export const ManageFBList = ({ classes }) => (
|
||||
if (!loading && !error) {
|
||||
if (data.teams_TeamsByOwner.length > 0) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Grid container spacing={40}>
|
||||
{!loading &&
|
||||
data.teams_TeamsByOwner.map(team => (
|
||||
<ManageFBItem
|
||||
key={team.id}
|
||||
team={team}
|
||||
classes={classes}
|
||||
/>
|
||||
))}
|
||||
{errors}
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
<div className={classes.root}>
|
||||
<div className={classes.heroContent}>
|
||||
<Grid container spacing={8} direction='column' alignItems='stretch'>
|
||||
{!loading &&
|
||||
data.teams_TeamsByOwner.map(team => (
|
||||
<ManageFBItem
|
||||
key={team.id}
|
||||
team={team}
|
||||
classes={classes}
|
||||
/>
|
||||
))}
|
||||
{errors}
|
||||
</Grid>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid item xs={12}>
|
||||
<MessageCard message='No financial beings yet — Create a team first!' />
|
||||
{errors !== null && <MessageCard message={errors} />}
|
||||
<Paper>
|
||||
<Grid container spacing={0} direction='column' justify='center' alignItems='center' className={classes.container}>
|
||||
<Grid item xs={10}>
|
||||
<Typography variant='h5' align='center'>
|
||||
You don’t have any financial being. To create one, create a team first!
|
||||
</Typography>
|
||||
<Typography variant='body1' align='center' gutterBottom>
|
||||
After you create a team, a default trading algobot will be cloned and added to your team so
|
||||
that you can begin experimenting right away.
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid spacing={0} direction='column' justify='center' alignItems='center'>
|
||||
<Grid item xs={12}>
|
||||
<MessageCard message='Loading...' />
|
||||
{errors !== null && <MessageCard message={errors} />}
|
||||
{errors === null &&
|
||||
<Typography variant='h5' align='center' gutterBottom>
|
||||
Loading...
|
||||
</Typography>
|
||||
}
|
||||
{errors !== null &&
|
||||
<Typography variant='h5' align='center' gutterBottom>
|
||||
{errors}
|
||||
</Typography>
|
||||
}
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { BannerTopBar } from '../common'
|
||||
import ManageFBList from './components/ManageFBList'
|
||||
|
||||
const styles = theme => ({
|
||||
@@ -14,9 +14,7 @@ const styles = theme => ({
|
||||
|
||||
const FinancialBeings = ({ classes }) => (
|
||||
<div>
|
||||
<Typography variant='h4' gutterBottom>
|
||||
Financial Beings
|
||||
</Typography>
|
||||
<BannerTopBar size='medium' title='Manage Your Financial Beings' text='Manage your Advanced Algos Financial Beings' backgroundUrl='https://advancedalgos.net/img/photos/teams.jpg' />
|
||||
<ManageFBList />
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ import FinancialBeings from './financial-beings'
|
||||
import Settings from './settings'
|
||||
import Teams from './teams'
|
||||
import AcceptTeamInvite from './teams/AcceptTeamInvite'
|
||||
import Landing from './landing'
|
||||
|
||||
import { TeamBar } from './common'
|
||||
|
||||
@@ -17,6 +18,7 @@ export {
|
||||
Settings,
|
||||
Teams,
|
||||
TeamBar,
|
||||
Landing,
|
||||
theme,
|
||||
globalStyles
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { BannerTopBar } from '../common'
|
||||
|
||||
const styles = theme => ({
|
||||
container: {
|
||||
width: 'auto',
|
||||
marginTop: theme.spacing.unit * 3,
|
||||
marginLeft: theme.spacing.unit * 3,
|
||||
marginRight: theme.spacing.unit * 3,
|
||||
marginBottom: theme.spacing.unit * 6,
|
||||
[theme.breakpoints.up(800 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 800,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const Landing = ({ classes, ...props }) => (
|
||||
<React.Fragment>
|
||||
<BannerTopBar size='big' title='Teams Module' text='Responsible for all teams at Advanced Algos.' backgroundUrl='https://advancedalgos.net/img/photos/teams.jpg' />
|
||||
<div className='homePage container'>
|
||||
<Typography variant='h1' align='center' className='title'>
|
||||
Welcome to the Teams Module!
|
||||
</Typography>
|
||||
<Typography variant='h2' align='center' className='subtitle'>
|
||||
Multidisciplinary groups of humans joining forces to breed financial beings and compete.
|
||||
</Typography>
|
||||
<div className='column'>
|
||||
<Typography align='justify'>
|
||||
One of the core propositions of Advanced Algos revolves around people teaming up to breed financial beings and compete in algorithmic trading competitions. Both developing and competing are team activities.
|
||||
</Typography>
|
||||
<Typography align='justify'>
|
||||
If you are a user of the system but still haven’t joined any teams, the Teams Module is the right place to find one or even create your own.
|
||||
</Typography>
|
||||
</div>
|
||||
<div className='column'>
|
||||
<Typography align='justify'>
|
||||
You may join and participate in as many teams as you wish.
|
||||
</Typography>
|
||||
<Typography align='justify'>
|
||||
When you create your own team, you become the team’s owner and may allow more people in the team at your sole discretion. It has been shown that larger teams tend to become more intelligent.
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
Landing.propTypes = {
|
||||
classes: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(Landing)
|
||||
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
|
||||
import { Mutation } from 'react-apollo'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import AddIcon from '@material-ui/icons/Add'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
@@ -34,14 +35,8 @@ const styles = theme => ({
|
||||
marginLeft: '20%',
|
||||
marginBottom: 10
|
||||
},
|
||||
buttonRight: {
|
||||
// position: 'absolute',
|
||||
// right: '3em'
|
||||
marginTop: '1em',
|
||||
marginRight: 'auto',
|
||||
marginLeft: 'auto',
|
||||
display: 'block',
|
||||
lineHeight: '1em'
|
||||
buttonFab: {
|
||||
backgroundColor: '#CCCCCC'
|
||||
}
|
||||
})
|
||||
|
||||
@@ -93,12 +88,12 @@ export class CreateTeamDialog extends Component {
|
||||
})
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<Grid container justify='center'>
|
||||
<Button
|
||||
variant='fab'
|
||||
color='primary'
|
||||
aria-label='Add'
|
||||
className={classes.buttonRight}
|
||||
className={classes.buttonFab}
|
||||
onClick={this.handleClickOpen}
|
||||
>
|
||||
<AddIcon />
|
||||
@@ -172,7 +167,7 @@ export class CreateTeamDialog extends Component {
|
||||
</DialogActions>
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
</Grid>
|
||||
)
|
||||
}}
|
||||
</Mutation>
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
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 TextField from '@material-ui/core/TextField'
|
||||
import FormControl from '@material-ui/core/FormControl'
|
||||
import FormHelperText from '@material-ui/core/FormHelperText'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import { isEmpty } from '../../../utils/js-helpers'
|
||||
|
||||
import CREATE_TEAM from '../../../graphql/teams/CreateTeamMutation'
|
||||
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
|
||||
import log from '../../../utils/log'
|
||||
|
||||
const styles = theme => ({
|
||||
formContainer: {
|
||||
width: '100%',
|
||||
margin: '3em 0 1em'
|
||||
},
|
||||
typography: {
|
||||
width: '80%',
|
||||
marginLeft: '10%',
|
||||
marginTop: 40
|
||||
},
|
||||
dialogStyle: {
|
||||
padding: '3em'
|
||||
},
|
||||
textField: {
|
||||
width: '80%',
|
||||
marginLeft: '10%',
|
||||
marginTop: 25
|
||||
},
|
||||
submitButton: {
|
||||
margin: theme.spacing.unit,
|
||||
marginTop: theme.spacing.unit * 3
|
||||
}
|
||||
})
|
||||
|
||||
export class CreateTeamForm 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: '',
|
||||
botName: '',
|
||||
nameError: '',
|
||||
botNameError: ''
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { classes } = this.props
|
||||
return (
|
||||
<Mutation
|
||||
mutation={CREATE_TEAM}
|
||||
refetchQueries={[{
|
||||
query: GET_TEAMS_BY_OWNER
|
||||
}]}
|
||||
>
|
||||
{(createTeam, { loading, error, data }) => {
|
||||
let errors
|
||||
let loader = null
|
||||
if (loading) {
|
||||
loader = (
|
||||
<Typography variant='subtitle1'>Submitting team...</Typography>
|
||||
)
|
||||
}
|
||||
if (error) {
|
||||
errors = error.graphQLErrors.map(({ message }, i) => {
|
||||
// const displayMessage = checkGraphQLError(message)
|
||||
return (
|
||||
<Typography key={i} variant='caption'>
|
||||
{message}
|
||||
</Typography>
|
||||
)
|
||||
})
|
||||
}
|
||||
return (
|
||||
<FormControl
|
||||
required
|
||||
error={this.state.nameError !== '' || this.state.botNameError !== '' || error !== null}
|
||||
className={classes.formContainer}
|
||||
>
|
||||
<Typography className={classes.typography} variant='body1' gutterBottom align='left'>
|
||||
Give a nice and memorable name to your team.
|
||||
</Typography>
|
||||
|
||||
<TextField
|
||||
autoFocus
|
||||
id='name'
|
||||
label='Team Name'
|
||||
type='text'
|
||||
fullWidth
|
||||
className={classes.textField}
|
||||
value={this.state.name}
|
||||
onChange={this.handleChange}
|
||||
error={this.state.nameError !== ''}
|
||||
/>
|
||||
{this.state.nameError !== '' && (
|
||||
<FormHelperText>{this.state.nameError}</FormHelperText>
|
||||
)}
|
||||
<Typography className={classes.typography} variant='body1' gutterBottom align='left'>
|
||||
Give a name for to the bot you are forking.
|
||||
</Typography>
|
||||
<TextField
|
||||
autoFocus
|
||||
id='botName'
|
||||
label='Team Bot Name'
|
||||
type='text'
|
||||
fullWidth
|
||||
className={classes.textField}
|
||||
value={this.state.botName}
|
||||
onChange={this.handleChange}
|
||||
error={this.state.botNameError !== ''}
|
||||
/>
|
||||
{this.state.botNameError !== '' && (
|
||||
<FormHelperText>{this.state.botNameError}</FormHelperText>
|
||||
)}
|
||||
{error && <FormHelperText>{errors}</FormHelperText>}
|
||||
{loader}
|
||||
|
||||
<Grid container justify='center' >
|
||||
<Grid item>
|
||||
|
||||
<Button
|
||||
onClick={e => {
|
||||
this.handleSubmit(e, createTeam, this.state.name, this.state.botName)
|
||||
}}
|
||||
variant='contained'
|
||||
color='secondary'
|
||||
className={classes.submitButton}
|
||||
>
|
||||
Create Team
|
||||
</Button>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</FormControl>
|
||||
)
|
||||
}}
|
||||
</Mutation>
|
||||
)
|
||||
}
|
||||
|
||||
handleClickOpen () {
|
||||
this.setState({ open: true })
|
||||
}
|
||||
|
||||
handleClose () {
|
||||
this.setState({ open: false })
|
||||
}
|
||||
|
||||
handleChange (e) {
|
||||
let id = e.target.id
|
||||
let value = e.target.value
|
||||
let error = this.validate({ id, value })
|
||||
switch (id) {
|
||||
case 'name':
|
||||
if (!isEmpty(error)) this.setState({ nameError: error })
|
||||
this.setState({ name: value })
|
||||
break
|
||||
case 'botName':
|
||||
if (!isEmpty(error)) this.setState({ botNameError: error })
|
||||
this.setState({ botName: value })
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
async handleSubmit (e, createTeam, name, botName) {
|
||||
e.preventDefault()
|
||||
log.debug('createTeam submit: ', name, botName)
|
||||
const slug = this.slugify(name)
|
||||
const botSlug = this.slugify(botName)
|
||||
await createTeam({ variables: { name, slug, botName, botSlug } })
|
||||
window.canvasApp.eventHandler.raiseEvent('User Profile Changed')
|
||||
this.setState({ name: '', open: false })
|
||||
}
|
||||
|
||||
validate (data) {
|
||||
const errors = {}
|
||||
switch (data.id) {
|
||||
case 'name':
|
||||
if (data.value === '') {
|
||||
this.setState({ nameError: 'Please enter a team name' })
|
||||
} else {
|
||||
this.setState({ nameError: '' })
|
||||
}
|
||||
break
|
||||
case 'botName':
|
||||
if (data.value === '') {
|
||||
this.setState({ botNameError: 'Please enter a bot name' })
|
||||
} else {
|
||||
this.setState({ botNameError: '' })
|
||||
}
|
||||
break
|
||||
default:
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
CreateTeamForm.propTypes = {
|
||||
classes: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(CreateTeamForm)
|
||||
@@ -72,12 +72,12 @@ export class ManageTeamDetails extends Component {
|
||||
if (profile.avatar !== undefined && profile.avatar !== null) {
|
||||
avatar = profile.avatar
|
||||
} else {
|
||||
avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
}
|
||||
if (profile.banner !== undefined && profile.banner !== null) {
|
||||
banner = profile.banner
|
||||
} else {
|
||||
banner = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-banner-default.png'
|
||||
banner = process.env.STORAGE_URL + '/module-teams/module-default/aa-banner-default.png'
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -75,12 +75,12 @@ export class ManageTeamEdit extends Component {
|
||||
const AzureStorageSAS = process.env.AZURE_STORAGE_SAS_TEAMS
|
||||
const containerName = team.slug
|
||||
let avatar = null
|
||||
if (this.state.avatar === null && team.profile !== null && (team.profile.avatar === undefined || team.profile.avatar === null)) avatar = 'https://aadevelop.blob.core.windows.net/module-teams/module-default/aa-avatar-default.png'
|
||||
if (this.state.avatar === null && team.profile !== null && (team.profile.avatar === undefined || team.profile.avatar === null)) avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
if (team.profile !== null && team.profile.avatar !== undefined && team.profile.avatar !== null) avatar = team.profile.avatar
|
||||
if (this.state.avatar !== null) avatar = this.state.avatar
|
||||
|
||||
let banner = null
|
||||
if (this.state.banner === null && team.profile !== null && (team.profile.banner === undefined || team.profile.banner === null)) banner = 'https://aadevelop.blob.core.windows.net/module-teams/module-default/aa-banner-default.png'
|
||||
if (this.state.banner === null && team.profile !== null && (team.profile.banner === undefined || team.profile.banner === null)) banner = process.env.STORAGE_URL + '/module-teams/module-default/aa-banner-default.png'
|
||||
if (team.profile !== null && team.profile.banner !== undefined && team.profile.banner !== null) banner = team.profile.banner
|
||||
if (this.state.banner !== null) banner = this.state.banner
|
||||
log.debug('team images: ', avatar, banner)
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import ManageTeamProfileView from './ManageTeamProfileView'
|
||||
import ManageTeamProfileEdit from './ManageTeamProfileEdit'
|
||||
|
||||
import log from '../../../utils/log'
|
||||
|
||||
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(800 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 800,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto'
|
||||
}
|
||||
},
|
||||
paper: {
|
||||
marginTop: 0,
|
||||
marginBottom: theme.spacing.unit * 1,
|
||||
padding: 0,
|
||||
[theme.breakpoints.up(800 + theme.spacing.unit * 3 * 2)]: {
|
||||
marginTop: theme.spacing.unit * 3,
|
||||
marginBottom: theme.spacing.unit * 2,
|
||||
padding: `0 0 ${theme.spacing.unit * 2}px`
|
||||
}
|
||||
},
|
||||
heroContent: {
|
||||
maxWidth: 800,
|
||||
margin: '0 auto',
|
||||
padding: 0
|
||||
},
|
||||
teamContent: {
|
||||
margin: `${theme.spacing.unit * 1}px ${theme.spacing.unit * 3}px 0 0`
|
||||
},
|
||||
banner: {
|
||||
maxWidth: '100%',
|
||||
height: 'auto'
|
||||
},
|
||||
avatar: {
|
||||
maxWidth: 100,
|
||||
height: 100,
|
||||
margin: `${theme.spacing.unit * 1}px 0 0 ${theme.spacing.unit * 3}px `
|
||||
},
|
||||
profileButtons: {
|
||||
width: '90%',
|
||||
margin: `${theme.spacing.unit * 3}px auto 0`,
|
||||
padding: `${theme.spacing.unit * 2}px ${theme.spacing.unit * 2}px 0`,
|
||||
borderTop: '1px solid #CCCCCC'
|
||||
}
|
||||
})
|
||||
|
||||
export class ManageTeamProfile extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.toggleEdit = this.toggleEdit.bind(this)
|
||||
this.handleSave = this.handleSave.bind(this)
|
||||
this.handleUpdate = this.handleUpdate.bind(this)
|
||||
|
||||
this.state = {
|
||||
edit: false,
|
||||
save: false
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { classes, team, slug, match } = this.props
|
||||
log.debug('ManageTeamProfile render', this.state)
|
||||
return (
|
||||
<div className='container'>
|
||||
<main className={classes.layout}>
|
||||
<Paper className={classes.paper}>
|
||||
<div className={classes.heroContent}>
|
||||
{!this.state.edit && <ManageTeamProfileView team={team} />}
|
||||
{this.state.edit &&
|
||||
<ManageTeamProfileEdit
|
||||
team={team}
|
||||
slug={slug}
|
||||
match={match}
|
||||
save={this.state.save}
|
||||
handleUpdate={this.handleUpdate}
|
||||
/>
|
||||
}
|
||||
<Grid container justify='flex-end' direction='row' spacing={24} className={classes.profileButtons}>
|
||||
{!this.state.edit &&
|
||||
<React.Fragment>
|
||||
<Grid item>
|
||||
<Button
|
||||
component={Link}
|
||||
to='/teams/manage-teams'
|
||||
color='primary'
|
||||
variant='contained'
|
||||
>
|
||||
Back to all teams
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Button
|
||||
onClick={e => this.toggleEdit()}
|
||||
color='secondary'
|
||||
variant='contained'
|
||||
>
|
||||
Edit Profile
|
||||
</Button>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
}
|
||||
{this.state.edit &&
|
||||
<React.Fragment>
|
||||
<Grid item>
|
||||
<Button
|
||||
onClick={e => this.toggleEdit()}
|
||||
variant='contained'
|
||||
color='primary'
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Button
|
||||
onClick={e => this.handleSave(e)}
|
||||
variant='contained'
|
||||
color='secondary'
|
||||
>
|
||||
Save Changes
|
||||
</Button>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
}
|
||||
</Grid>
|
||||
</div>
|
||||
</Paper>
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
toggleEdit () {
|
||||
this.setState({ edit: !this.state.edit })
|
||||
}
|
||||
|
||||
handleSave (e) {
|
||||
e.preventDefault()
|
||||
log.debug('handleSave')
|
||||
this.setState({ save: true })
|
||||
}
|
||||
|
||||
handleUpdate () {
|
||||
log.debug('handleUpdate')
|
||||
this.setState({ edit: false, save: false })
|
||||
}
|
||||
}
|
||||
|
||||
ManageTeamProfile.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
team: PropTypes.object.isRequired,
|
||||
match: PropTypes.object.isRequired,
|
||||
slug: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageTeamProfile)
|
||||
@@ -0,0 +1,379 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Mutation } from 'react-apollo'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
|
||||
import { ImageUpload } from '@advancedalgos/web-components'
|
||||
|
||||
import UPDATE_TEAM_PROFILE from '../../../graphql/teams/UpdateTeamProfileMutation'
|
||||
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
|
||||
import { checkGraphQLError } from '../../../utils/graphql-errors'
|
||||
import log from '../../../utils/log'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1
|
||||
},
|
||||
'@global': {
|
||||
body: {
|
||||
backgroundColor: theme.palette.common.white
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
width: '100%',
|
||||
marginBottom: theme.spacing.unit * 6,
|
||||
[theme.breakpoints.up(800 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 800,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto'
|
||||
}
|
||||
},
|
||||
paper: {
|
||||
marginTop: 0,
|
||||
marginBottom: theme.spacing.unit * 3,
|
||||
padding: 0,
|
||||
[theme.breakpoints.up(800 + theme.spacing.unit * 3 * 2)]: {
|
||||
marginTop: theme.spacing.unit * 3,
|
||||
marginBottom: theme.spacing.unit * 6,
|
||||
padding: `0 0 ${theme.spacing.unit * 2}px`
|
||||
}
|
||||
},
|
||||
heroContent: {
|
||||
maxWidth: 800,
|
||||
margin: '0 auto',
|
||||
padding: `0 0 ${theme.spacing.unit * 2}px`
|
||||
},
|
||||
editContentContainer: {
|
||||
marginBottom: `${theme.spacing.unit * 3}px`
|
||||
},
|
||||
metaContainer: {
|
||||
marginTop: `${theme.spacing.unit * 1}px`,
|
||||
alignSelf: 'stretch',
|
||||
borderRight: '1px solid #CCCCCC'
|
||||
},
|
||||
teamMeta: {
|
||||
margin: `${theme.spacing.unit * 3}px 0 0`,
|
||||
paddingLeft: `${theme.spacing.unit * 2}px`,
|
||||
textAlign: 'center',
|
||||
height: '100%'
|
||||
},
|
||||
teamContent: {
|
||||
'& h2': {
|
||||
padding: `${theme.spacing.unit * 4}px ${theme.spacing.unit * 3}px 0`
|
||||
},
|
||||
'& h4': {
|
||||
padding: `0 ${theme.spacing.unit * 3}px 0`
|
||||
},
|
||||
'& h6': {
|
||||
padding: `0 ${theme.spacing.unit * 3}px 0`
|
||||
}
|
||||
},
|
||||
editInput: {
|
||||
padding: `0 ${theme.spacing.unit * 3}px ${theme.spacing.unit * 2}px`,
|
||||
'& label': {
|
||||
display: 'none',
|
||||
padding: `0 ${theme.spacing.unit * 4}px 0`
|
||||
}
|
||||
},
|
||||
banner: {
|
||||
maxWidth: '100%',
|
||||
height: 'auto',
|
||||
width: '100%'
|
||||
},
|
||||
avatar: {
|
||||
maxWidth: 125,
|
||||
height: 125,
|
||||
margin: `0 auto ${theme.spacing.unit * 2}px`,
|
||||
verticalAlign: 'middle',
|
||||
borderRadius: '50%'
|
||||
}
|
||||
})
|
||||
|
||||
export class ManageTeamProfileEdit 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.handleAvatar = this.handleAvatar.bind(this)
|
||||
this.handleBanner = this.handleBanner.bind(this)
|
||||
this.startSave = this.startSave.bind(this)
|
||||
|
||||
log.debug('ManageTeamProfileEdit constructor', props.team)
|
||||
const motto = props.team.profile.motto || ''
|
||||
const description = props.team.profile.description || ''
|
||||
const avatar = props.team.profile.avatar || null
|
||||
const banner = props.team.profile.banner || null
|
||||
|
||||
this.state = {
|
||||
open: false,
|
||||
motto: motto,
|
||||
description: description,
|
||||
avatar: avatar,
|
||||
banner: banner,
|
||||
save: false
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { classes, team, match, save, handleUpdate } = this.props
|
||||
log.debug('ManageTeamProfileEdit render', this.props, this.props.slug, this.props.team, match)
|
||||
|
||||
const created = new Date(team.createdAt)
|
||||
|
||||
return (
|
||||
<Mutation
|
||||
mutation={UPDATE_TEAM_PROFILE}
|
||||
refetchQueries={[
|
||||
{
|
||||
query: GET_TEAMS_BY_OWNER
|
||||
}
|
||||
]}
|
||||
>
|
||||
{(updateTeamProfile, { loading, error, data }) => {
|
||||
const AzureStorageUrl = process.env.AZURE_STORAGE_URL_TEAMS
|
||||
const AzureStorageSAS = process.env.AZURE_STORAGE_SAS_TEAMS
|
||||
const containerName = team.slug
|
||||
let avatar = null
|
||||
if (this.state.avatar === null && team.profile !== null && (team.profile.avatar === undefined || team.profile.avatar === null)) avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
if (team.profile !== null && team.profile.avatar !== undefined && team.profile.avatar !== null) avatar = team.profile.avatar
|
||||
if (this.state.avatar !== null) avatar = this.state.avatar
|
||||
|
||||
let banner = null
|
||||
if (this.state.banner === null && team.profile !== null && (team.profile.banner === undefined || team.profile.banner === null)) banner = process.env.STORAGE_URL + '/module-teams/module-default/aa-banner-default.png'
|
||||
if (team.profile !== null && team.profile.banner !== undefined && team.profile.banner !== null) banner = team.profile.banner
|
||||
if (this.state.banner !== null) banner = this.state.banner
|
||||
log.debug('team images: ', avatar, banner)
|
||||
log.debug('saving profile status: ', save)
|
||||
if (save && !this.state.save) {
|
||||
log.debug('saving profile: ', save)
|
||||
this.startSave(updateTeamProfile, team.slug, handleUpdate)
|
||||
}
|
||||
|
||||
let errors
|
||||
let loader
|
||||
if (loading) {
|
||||
loader = (
|
||||
<Typography variant='caption'>Updating profile...</Typography>
|
||||
)
|
||||
}
|
||||
if (error) {
|
||||
errors = error.graphQLErrors.map(({ message }, i) => {
|
||||
const displayMessage = checkGraphQLError(message)
|
||||
log.debug('updateTeamProfile error:', displayMessage)
|
||||
return (
|
||||
<Typography key={i} variant='caption'>
|
||||
{message}
|
||||
</Typography>
|
||||
)
|
||||
})
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ImageUpload
|
||||
key='banner'
|
||||
handleUrl={this.handleBanner}
|
||||
fileName={`${team.slug}-banner.jpg`}
|
||||
containerName={containerName}
|
||||
existingImage={banner}
|
||||
imagePreviewConfig={{
|
||||
width: '800px',
|
||||
height: '200px',
|
||||
title: 'Change Banner',
|
||||
fontSize: '1.5em'
|
||||
}}
|
||||
cropContainerConfig={{ x: 10, y: 10, width: 800, height: 200 }}
|
||||
cropPreviewBox={{ width: 650, height: 200 }}
|
||||
saveImageConfig={{
|
||||
quality: 0.6,
|
||||
maxWidth: 800,
|
||||
maxHeight: 200,
|
||||
autoRotate: true,
|
||||
mimeType: 'image/jpeg'
|
||||
}}
|
||||
containerStyle={{
|
||||
display: 'block',
|
||||
margin: 0,
|
||||
height: '200px',
|
||||
width: '800px',
|
||||
overflow: 'visible'
|
||||
}}
|
||||
AzureStorageUrl={AzureStorageUrl}
|
||||
AzureSASURL={AzureStorageSAS}
|
||||
cropRatio={4}
|
||||
/>
|
||||
<Grid container className={classes.editContentContainer}>
|
||||
<Grid item md={3} className={classes.metaContainer}>
|
||||
<Grid container className={classes.teamMeta} direction='column' justify='flex-start'>
|
||||
<Grid item>
|
||||
<ImageUpload
|
||||
key='avatar1'
|
||||
handleUrl={this.handleAvatar}
|
||||
fileName={`${team.slug}-avatar.jpg`}
|
||||
containerName={containerName}
|
||||
existingImage={avatar}
|
||||
imagePreviewConfig={{
|
||||
width: '125px',
|
||||
height: '125px',
|
||||
title: 'Change Avatar',
|
||||
fontSize: '1.5em'
|
||||
}}
|
||||
cropContainerConfig={{ x: 10, y: 10, width: 200, height: 200 }}
|
||||
cropPreviewBox={{ width: 350, height: 350 }}
|
||||
saveImageConfig={{
|
||||
quality: 0.6,
|
||||
maxWidth: 200,
|
||||
maxHeight: 200,
|
||||
autoRotate: true,
|
||||
mimeType: 'image/jpeg'
|
||||
}}
|
||||
containerStyle={{
|
||||
display: 'block',
|
||||
margin: '0 auto 12px',
|
||||
height: '125px',
|
||||
width: '125px',
|
||||
overflow: 'visible'
|
||||
}}
|
||||
dropzoneStyle={{
|
||||
height: 125,
|
||||
title: 'Drop new image or click to select'
|
||||
}}
|
||||
AzureStorageUrl={AzureStorageUrl}
|
||||
AzureSASURL={AzureStorageSAS}
|
||||
cropRatio={1}
|
||||
/>
|
||||
</Grid>
|
||||
<Typography variant='subtitle1' paragraph gutterBottom>
|
||||
Members: {team.members.length}
|
||||
</Typography>
|
||||
<Typography variant='subtitle1' paragraph gutterBottom>
|
||||
Financial Beings: 1
|
||||
</Typography>
|
||||
<Typography variant='subtitle1' paragraph gutterBottom>
|
||||
Created: {created.toLocaleDateString()}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item md={9}>
|
||||
<Grid container className={classes.teamContent} direction='column'>
|
||||
<Typography
|
||||
variant='h2'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
>
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant='h4'
|
||||
color='textSecondary'
|
||||
>
|
||||
Motto:
|
||||
</Typography>
|
||||
<TextField
|
||||
autoFocus
|
||||
margin='dense'
|
||||
id='motto'
|
||||
type='text'
|
||||
fullWidth
|
||||
value={this.state.motto}
|
||||
onChange={this.handleChange}
|
||||
className={classes.editInput}
|
||||
/>
|
||||
<Typography variant='h6' color='textPrimary'>
|
||||
Description:
|
||||
</Typography>
|
||||
<TextField
|
||||
margin='dense'
|
||||
id='description'
|
||||
type='text'
|
||||
rows={4}
|
||||
multiline
|
||||
fullWidth
|
||||
value={this.state.description}
|
||||
onChange={this.handleChange}
|
||||
className={classes.editInput}
|
||||
/>
|
||||
<Typography variant='h6' color='secondary'>
|
||||
{loader}
|
||||
{errors}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
)
|
||||
}}
|
||||
</Mutation>
|
||||
)
|
||||
}
|
||||
|
||||
handleClickOpen () {
|
||||
this.setState({ open: true })
|
||||
}
|
||||
|
||||
handleClose () {
|
||||
this.setState({ open: false })
|
||||
}
|
||||
|
||||
handleChange (e) {
|
||||
log.debug('handleChange: ', e.target.id, 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:
|
||||
}
|
||||
}
|
||||
|
||||
handleAvatar (avatarUrl) {
|
||||
log.debug('handleAvatar: ', avatarUrl)
|
||||
this.setState({ avatar: `${avatarUrl}?${Math.random()}` })
|
||||
}
|
||||
|
||||
handleBanner (bannerUrl) {
|
||||
log.debug('handleBanner: ', bannerUrl)
|
||||
this.setState({ banner: `${bannerUrl}?${Math.random()}` })
|
||||
}
|
||||
|
||||
startSave (updateTeamProfile, slug, handleUpdate) {
|
||||
this.setState({ save: 'done' })
|
||||
this.handleSubmit(updateTeamProfile, slug, handleUpdate)
|
||||
}
|
||||
|
||||
async handleSubmit (updateTeamProfile, slug, handleUpdate) {
|
||||
log.debug('updateTeamProfile, handleSubmit: ', this.state)
|
||||
await updateTeamProfile({
|
||||
variables: {
|
||||
slug,
|
||||
owner: this.authId,
|
||||
description: this.state.description,
|
||||
motto: this.state.motto,
|
||||
avatar: this.state.avatar,
|
||||
banner: this.state.banner
|
||||
}
|
||||
})
|
||||
window.canvasApp.eventHandler.raiseEvent('User Profile Changed')
|
||||
handleUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
ManageTeamProfileEdit.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
slug: PropTypes.string.isRequired,
|
||||
team: PropTypes.object,
|
||||
match: PropTypes.object,
|
||||
save: PropTypes.bool,
|
||||
handleUpdate: PropTypes.func
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageTeamProfileEdit)
|
||||
@@ -0,0 +1,210 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Mutation } from 'react-apollo'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import EditIcon from '@material-ui/icons/Edit'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
|
||||
import { ImageUpload } from '@advancedalgos/web-components'
|
||||
|
||||
import UPDATE_FB from '../../../graphql/teams/UpdateFBMutation'
|
||||
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
|
||||
import { checkGraphQLError } from '../../../utils/graphql-errors'
|
||||
|
||||
import log from '../../../utils/log'
|
||||
|
||||
const styles = theme => ({
|
||||
dialogTitle: {
|
||||
textAlign: 'center',
|
||||
paddingBottom: `${theme.spacing.unit * 2}px`
|
||||
},
|
||||
buttonRight: {
|
||||
justifyContent: 'flex-end'
|
||||
}
|
||||
})
|
||||
|
||||
export class ManageTeamProfileFBEdit extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.handleClickOpen = this.handleClickOpen.bind(this)
|
||||
this.handleClose = this.handleClose.bind(this)
|
||||
this.handleSubmit = this.handleSubmit.bind(this)
|
||||
this.handleAvatar = this.handleAvatar.bind(this)
|
||||
|
||||
const avatar = props.fb.avatar || ''
|
||||
|
||||
this.state = {
|
||||
open: false,
|
||||
avatar: avatar
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
log.debug('ManageTeamProfileFBEdit ', this.props, this.props.slug, this.props.fb)
|
||||
const { classes, fb, slug } = this.props
|
||||
return (
|
||||
<Mutation
|
||||
mutation={UPDATE_FB}
|
||||
refetchQueries={[
|
||||
{
|
||||
query: GET_TEAMS_BY_OWNER
|
||||
}
|
||||
]}
|
||||
>
|
||||
{(updateFB, { loading, error, data }) => {
|
||||
const AzureStorageUrl = process.env.AZURE_STORAGE_URL_TEAMS
|
||||
const AzureStorageSAS = process.env.AZURE_STORAGE_SAS_TEAMS
|
||||
const containerName = slug
|
||||
|
||||
let avatar = null
|
||||
if (this.state.avatar === null && fb.avatar === undefined) avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
if (fb.avatar !== undefined && fb.avatar !== null) avatar = fb.avatar
|
||||
if (this.state.avatar !== null) avatar = this.state.avatar
|
||||
|
||||
let errors
|
||||
let loader
|
||||
if (loading) {
|
||||
loader = (
|
||||
<Typography variant='caption'>Updating avatar...</Typography>
|
||||
)
|
||||
}
|
||||
if (error) {
|
||||
errors = error.graphQLErrors.map(({ message }, i) => {
|
||||
const displayMessage = checkGraphQLError(message)
|
||||
log.debug('updateTeamProfile error:', displayMessage)
|
||||
return (
|
||||
<Typography key={i} variant='caption'>
|
||||
{message}
|
||||
</Typography>
|
||||
)
|
||||
})
|
||||
}
|
||||
log.debug('ManageTeamProfileFBEdit mutation:', classes)
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
size='small'
|
||||
color='primary'
|
||||
className={classes.buttonRight}
|
||||
onClick={this.handleClickOpen}
|
||||
>
|
||||
<EditIcon /> Edit
|
||||
</Button>
|
||||
<Dialog
|
||||
open={this.state.open}
|
||||
onClose={this.handleClose}
|
||||
aria-labelledby='form-dialog-title'
|
||||
>
|
||||
<DialogContent>
|
||||
<Grid container justify='center' direction='column'>
|
||||
<Grid item className={classes.dialogTitle}>
|
||||
<Typography variant='h4'>
|
||||
Edit Financial Being
|
||||
</Typography>
|
||||
</Grid>
|
||||
<ImageUpload
|
||||
key='avatar'
|
||||
handleUrl={this.handleAvatar}
|
||||
fileName={`${fb.slug}-fb-avatar.jpg`}
|
||||
containerName={containerName}
|
||||
existingImage={avatar}
|
||||
imagePreviewConfig={{
|
||||
width: '125px',
|
||||
height: '125px',
|
||||
title: 'Change FB Avatar',
|
||||
fontSize: '1.5em'
|
||||
}}
|
||||
cropContainerConfig={{ x: 10, y: 10, width: 200, height: 200 }}
|
||||
cropPreviewBox={{ width: 350, height: 350 }}
|
||||
saveImageConfig={{
|
||||
quality: 0.6,
|
||||
maxWidth: 200,
|
||||
maxHeight: 200,
|
||||
autoRotate: true,
|
||||
mimeType: 'image/jpeg'
|
||||
}}
|
||||
containerStyle={{
|
||||
display: 'block',
|
||||
margin: '0 auto 3em',
|
||||
height: '125px',
|
||||
width: '125px',
|
||||
overflow: 'visible'
|
||||
}}
|
||||
dropzoneStyle={{
|
||||
height: 125,
|
||||
title: 'Drop new image or click to select'
|
||||
}}
|
||||
AzureStorageUrl={AzureStorageUrl}
|
||||
AzureSASURL={AzureStorageSAS}
|
||||
cropRatio={1}
|
||||
debug
|
||||
/>
|
||||
{loader}
|
||||
{errors}
|
||||
<Grid container justify='center' alignItems='center' direction='column'>
|
||||
<Button
|
||||
onClick={e => {
|
||||
this.handleSubmit(e, updateFB, fb.id, slug)
|
||||
}}
|
||||
color='secondary'
|
||||
variant='contained'
|
||||
size='small'
|
||||
>
|
||||
Update Financial Being
|
||||
</Button>
|
||||
<Button onClick={this.handleClose} color='primary'>
|
||||
Cancel
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</Mutation>
|
||||
)
|
||||
}
|
||||
|
||||
handleClickOpen () {
|
||||
this.setState({ open: true })
|
||||
}
|
||||
|
||||
handleClose () {
|
||||
this.setState({ open: false })
|
||||
}
|
||||
|
||||
handleAvatar (avatarUrl) {
|
||||
log.debug('handleAvatar: ', avatarUrl)
|
||||
this.setState({ avatar: `${avatarUrl}?${Math.random()}` })
|
||||
}
|
||||
|
||||
async handleSubmit (e, updateFB, fbId, slug) {
|
||||
log.debug('handleSubmit: ', this.state)
|
||||
e.preventDefault()
|
||||
|
||||
await updateFB({
|
||||
variables: {
|
||||
fbId,
|
||||
avatar: this.state.avatar
|
||||
}
|
||||
})
|
||||
window.canvasApp.eventHandler.raiseEvent('User Profile Changed')
|
||||
this.setState({ open: false })
|
||||
}
|
||||
}
|
||||
|
||||
ManageTeamProfileFBEdit.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
slug: PropTypes.string.isRequired,
|
||||
fb: PropTypes.object
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageTeamProfileFBEdit)
|
||||
@@ -0,0 +1,76 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import CardActions from '@material-ui/core/CardActions'
|
||||
import CardMedia from '@material-ui/core/CardMedia'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import ManageTeamProfileFBEdit from './ManageTeamProfileFBEdit'
|
||||
|
||||
import log from '../../../utils/log'
|
||||
|
||||
const styles = theme => ({
|
||||
fbContainer: {
|
||||
margin: `0 0 ${theme.spacing.unit * 2}px`
|
||||
},
|
||||
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 ManageTeamProvileFBView = ({ classes, team }) => {
|
||||
log.debug('ManageTeamProvileFBView', team, team.fb[0], team.fb[0].avatar)
|
||||
|
||||
let avatar = (team.fb[0].avatar !== undefined && team.fb[0].avatar !== null) ? team.fb[0].avatar : process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
|
||||
return (
|
||||
<Grid item xs={12} className={classes.fbContainer}>
|
||||
<Card className={classes.card}>
|
||||
<div className={classes.cardDetails}>
|
||||
<CardMedia
|
||||
className={classes.cardMedia}
|
||||
image={avatar}
|
||||
title={team.name}
|
||||
/>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography gutterBottom variant='h5' component='h2'>
|
||||
{team.fb[0].name}
|
||||
</Typography>
|
||||
<Typography variant='caption' color='textSecondary'>
|
||||
{team.fb[0].kind}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<ManageTeamProfileFBEdit slug={team.slug} fb={team.fb[0]} />
|
||||
</CardActions>
|
||||
</div>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
ManageTeamProvileFBView.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
team: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageTeamProvileFBView)
|
||||
@@ -0,0 +1,155 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import ManageTeamProfileFBView from './ManageTeamProfileFBView'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1
|
||||
},
|
||||
'@global': {
|
||||
body: {
|
||||
backgroundColor: theme.palette.common.white
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
width: '100%',
|
||||
marginBottom: theme.spacing.unit * 6,
|
||||
[theme.breakpoints.up(800 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 800,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto'
|
||||
}
|
||||
},
|
||||
paper: {
|
||||
marginTop: 0,
|
||||
marginBottom: theme.spacing.unit * 3,
|
||||
padding: 0,
|
||||
[theme.breakpoints.up(800 + theme.spacing.unit * 3 * 2)]: {
|
||||
marginTop: theme.spacing.unit * 3,
|
||||
marginBottom: theme.spacing.unit * 6,
|
||||
padding: `0 0 ${theme.spacing.unit * 2}px`
|
||||
}
|
||||
},
|
||||
heroContent: {
|
||||
maxWidth: 800,
|
||||
margin: '0 auto',
|
||||
padding: `0 0 ${theme.spacing.unit * 2}px`
|
||||
},
|
||||
metaContainer: {
|
||||
marginTop: `${theme.spacing.unit * 1}px`,
|
||||
alignSelf: 'stretch',
|
||||
borderRight: '1px solid #CCCCCC'
|
||||
},
|
||||
teamMeta: {
|
||||
margin: `${theme.spacing.unit * 3}px 0 0`,
|
||||
paddingLeft: `${theme.spacing.unit * 2}px`,
|
||||
textAlign: 'center'
|
||||
},
|
||||
teamContent: {
|
||||
'& h2': {
|
||||
padding: `${theme.spacing.unit * 4}px ${theme.spacing.unit * 3}px 0`
|
||||
},
|
||||
'& h4': {
|
||||
padding: `0 ${theme.spacing.unit * 3}px ${theme.spacing.unit * 1}px`
|
||||
},
|
||||
'& h6': {
|
||||
padding: `0 ${theme.spacing.unit * 3}px 0`
|
||||
}
|
||||
},
|
||||
fbContent: {
|
||||
borderTop: '1px solid #CCCCCC',
|
||||
width: '90%',
|
||||
margin: `${theme.spacing.unit * 3}px auto`,
|
||||
paddingTop: `${theme.spacing.unit * 3}px`
|
||||
},
|
||||
banner: {
|
||||
maxWidth: '100%',
|
||||
height: 'auto',
|
||||
width: '100%'
|
||||
},
|
||||
avatar: {
|
||||
maxWidth: 125,
|
||||
height: 125,
|
||||
margin: `0 auto ${theme.spacing.unit * 2}px`,
|
||||
verticalAlign: 'middle',
|
||||
borderRadius: '50%'
|
||||
},
|
||||
backLink: {
|
||||
display: 'block',
|
||||
textDecoration: 'none',
|
||||
margin: `${theme.spacing.unit * 3}px 0 0`,
|
||||
color: theme.palette.secondary.main
|
||||
}
|
||||
})
|
||||
|
||||
const ManageTeamProfileView = ({ classes, team }) => {
|
||||
let avatar = team.profile.avatar || process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
let banner = team.profile.banner || process.env.STORAGE_URL + '/module-teams/module-default/aa-banner-default.png'
|
||||
|
||||
const created = new Date(team.createdAt)
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<img src={banner} alt={team.name} className={classes.banner} />
|
||||
<Grid container>
|
||||
<Grid item md={3} className={classes.metaContainer}>
|
||||
<Grid container className={classes.teamMeta} direction='column' justify='center'>
|
||||
<img src={avatar} alt={team.name} className={classes.avatar} />
|
||||
<Typography variant='subtitle1' paragraph gutterBottom>
|
||||
Members: {team.members.length}
|
||||
</Typography>
|
||||
<Typography variant='subtitle1' paragraph gutterBottom>
|
||||
Financial Beings: 1
|
||||
</Typography>
|
||||
<Typography variant='subtitle1' paragraph gutterBottom>
|
||||
Created: {created.toLocaleDateString()}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item md={9}>
|
||||
<Grid container className={classes.teamContent} direction='column'>
|
||||
<Typography
|
||||
variant='h2'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
>
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant='h4'
|
||||
color='textSecondary'
|
||||
gutterBottom
|
||||
>
|
||||
Motto: {team.profile.motto}
|
||||
</Typography>
|
||||
<Typography variant='h6' color='textPrimary' gutterBottom>
|
||||
Description: {team.profile.description}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container className={classes.fbContent} direction='column'>
|
||||
<Typography
|
||||
variant='h4'
|
||||
color='textSecondary'
|
||||
gutterBottom
|
||||
>
|
||||
Financial Beings
|
||||
</Typography>
|
||||
<ManageTeamProfileFBView team={team} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
ManageTeamProfileView.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
team: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageTeamProfileView)
|
||||
@@ -0,0 +1,121 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import CreateTeamForm from './CreateTeamForm'
|
||||
|
||||
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(800 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 800,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto'
|
||||
}
|
||||
},
|
||||
paper: {
|
||||
marginTop: 0,
|
||||
marginBottom: theme.spacing.unit * 3,
|
||||
padding: 0,
|
||||
[theme.breakpoints.up(800 + theme.spacing.unit * 3 * 2)]: {
|
||||
marginTop: theme.spacing.unit * 3,
|
||||
marginBottom: theme.spacing.unit * 6,
|
||||
padding: `0 0 ${theme.spacing.unit * 6}px`
|
||||
}
|
||||
},
|
||||
heroContent: {
|
||||
maxWidth: 800,
|
||||
margin: '0 auto',
|
||||
padding: 0
|
||||
},
|
||||
teamContent: {
|
||||
margin: `${theme.spacing.unit * 1}px ${theme.spacing.unit * 3}px 0 0`
|
||||
},
|
||||
banner: {
|
||||
maxWidth: '100%',
|
||||
height: 'auto'
|
||||
},
|
||||
avatar: {
|
||||
maxWidth: 100,
|
||||
height: 100,
|
||||
margin: `${theme.spacing.unit * 1}px 0 0 ${theme.spacing.unit * 3}px `
|
||||
},
|
||||
backLink: {
|
||||
display: 'block',
|
||||
textDecoration: 'none',
|
||||
margin: `${theme.spacing.unit * 3}px 0 0`,
|
||||
color: theme.palette.secondary.main
|
||||
}
|
||||
})
|
||||
|
||||
export class ManageTeamProfile extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.toggleEdit = this.toggleEdit.bind(this)
|
||||
this.handleSave = this.handleSave.bind(this)
|
||||
|
||||
this.state = {
|
||||
edit: false,
|
||||
save: false
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { classes, team, slug, match } = this.props
|
||||
|
||||
return (
|
||||
<div className='container'>
|
||||
<Paper>
|
||||
<Grid container spacing={0} direction='column' justify='stretch' alignItems='center'>
|
||||
<Grid item xs={10}>
|
||||
<Typography variant='h5' align='center'>
|
||||
You don’t have any teams. Create one!
|
||||
</Typography>
|
||||
<Typography variant='body1' align='center' gutterBottom>
|
||||
To begin developing on the Advanced Algos platform, as well as participate in Algobot competitions,
|
||||
you'll need to create a team. A default trading algobot will be cloned and added to your team so
|
||||
that you can begin experimenting right away.
|
||||
</Typography>
|
||||
<CreateTeamForm />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Paper>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
toggleEdit () {
|
||||
this.setState({ edit: !this.state.edit })
|
||||
}
|
||||
|
||||
handleSave () {
|
||||
this.setState({ save: !this.state.edit })
|
||||
}
|
||||
}
|
||||
|
||||
ManageTeamProfile.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
team: PropTypes.object.isRequired,
|
||||
match: PropTypes.object.isRequired,
|
||||
slug: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageTeamProfile)
|
||||
@@ -7,20 +7,22 @@ import CardActions from '@material-ui/core/CardActions'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import CardMedia from '@material-ui/core/CardMedia'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import EditIcon from '@material-ui/icons/Edit'
|
||||
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import ManageTeamDetails from './ManageTeamDetails'
|
||||
import ManageTeamDelete from './ManageTeamDelete'
|
||||
import ManageTeamEdit from './ManageTeamEdit'
|
||||
|
||||
import log from '../../../utils/log'
|
||||
|
||||
export const ManageTeamsItem = ({ classes, team, ...props }) => {
|
||||
export const ManageTeamsItem = ({ classes, team, match, ...props }) => {
|
||||
log.debug('ManageTeamsItem', team, team.profile, team.profile.avatar)
|
||||
let avatar
|
||||
if (team.profile.avatar !== undefined && team.profile.avatar !== 'a') {
|
||||
avatar = team.profile.avatar
|
||||
} else {
|
||||
avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
}
|
||||
return (
|
||||
<Grid item xs={12}>
|
||||
@@ -36,13 +38,22 @@ export const ManageTeamsItem = ({ classes, team, ...props }) => {
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography variant='caption' color='textSecondary'>
|
||||
{team.createdAt} | Members: {team.members.length}
|
||||
Members: {team.members.length} | Financial Beings: {1}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<ManageTeamDetails team={team} />
|
||||
<ManageTeamEdit slug={team.slug} team={team} {...props} />
|
||||
<ManageTeamDelete slug={team.slug} botSlug={team.fb[0].slug} />
|
||||
<Grid container direction='row' justify='flex-end'>
|
||||
<Button
|
||||
size='small'
|
||||
color='primary'
|
||||
className={classes.buttonRight}
|
||||
component={Link}
|
||||
to={`${match.url}/${team.slug}`}
|
||||
>
|
||||
<EditIcon /> Manage Profile
|
||||
</Button>
|
||||
<ManageTeamDelete slug={team.slug} botSlug={team.fb[0].slug} />
|
||||
</Grid>
|
||||
</CardActions>
|
||||
</div>
|
||||
</Card>
|
||||
@@ -52,7 +63,8 @@ export const ManageTeamsItem = ({ classes, team, ...props }) => {
|
||||
|
||||
ManageTeamsItem.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
team: PropTypes.object.isRequired
|
||||
team: PropTypes.object.isRequired,
|
||||
match: PropTypes.object
|
||||
}
|
||||
|
||||
export default ManageTeamsItem
|
||||
@@ -3,21 +3,37 @@ import PropTypes from 'prop-types'
|
||||
import { Query } from 'react-apollo'
|
||||
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { isEmpty } from '../../../utils/js-helpers'
|
||||
|
||||
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
|
||||
import ManageTeamsItem from './ManageTeamsItem'
|
||||
import CreateTeamDialog from './CreateTeamDialog'
|
||||
import ManageTeamProfile from './ManageTeamProfile'
|
||||
import CreateTeamForm from './CreateTeamForm'
|
||||
|
||||
import log from '../../../utils/log'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1
|
||||
},
|
||||
typography: {
|
||||
width: '80%',
|
||||
marginLeft: '10%',
|
||||
marginTop: 40
|
||||
},
|
||||
heroContent: {
|
||||
maxWidth: 600,
|
||||
margin: '0 auto',
|
||||
padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px`
|
||||
maxWidth: 800,
|
||||
margin: `${theme.spacing.unit * 4}px auto`,
|
||||
padding: 0
|
||||
},
|
||||
newTeamContainer: {
|
||||
padding: `${theme.spacing.unit * 4}px 0`
|
||||
},
|
||||
cardGrid: {
|
||||
padding: `${theme.spacing.unit * 8}px 0`
|
||||
@@ -42,16 +58,25 @@ const styles = theme => ({
|
||||
height: 100,
|
||||
maxWidth: 100,
|
||||
justifyContent: 'flex-start'
|
||||
},
|
||||
paper: {
|
||||
width: '100%',
|
||||
flexGrow: 1,
|
||||
padding: 10,
|
||||
marginTop: '5%',
|
||||
marginBottom: '10%'
|
||||
}
|
||||
})
|
||||
|
||||
export const ManageTeamsList = ({ classes, user = null, ...props }) => (
|
||||
export const ManageTeamsList = ({ classes, match, ...props }) => (
|
||||
<Query
|
||||
query={GET_TEAMS_BY_OWNER}
|
||||
fetchPolicy='network-only'
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
log.debug('GET_TEAMS_BY_OWNER: ', loading, error, data)
|
||||
let slug = null
|
||||
if (!isEmpty(match.params) && match.params.slug) slug = match.params.slug
|
||||
|
||||
let errors = null
|
||||
if (error) {
|
||||
@@ -62,40 +87,77 @@ export const ManageTeamsList = ({ classes, user = null, ...props }) => (
|
||||
if (!loading && !error) {
|
||||
if (data.teams_TeamsByOwner.length > 0) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Grid container spacing={40}>
|
||||
{!loading &&
|
||||
data.teams_TeamsByOwner.map(team => (
|
||||
<ManageTeamsItem
|
||||
key={team.id}
|
||||
team={team}
|
||||
classes={classes}
|
||||
{...props}
|
||||
/>
|
||||
))}
|
||||
{errors}
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
<div className={classes.root}>
|
||||
<div className={slug === null ? classes.heroContent : ''}>
|
||||
<Grid container spacing={8} direction='column' alignItems='stretch'>
|
||||
{!loading &&
|
||||
data.teams_TeamsByOwner.map(team => {
|
||||
if (slug === team.slug) {
|
||||
return (
|
||||
<ManageTeamProfile
|
||||
key={`team-profile-${team.id}`}
|
||||
team={team}
|
||||
slug={team.slug}
|
||||
match={match}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<ManageTeamsItem
|
||||
key={`team-list-${team.id}`}
|
||||
team={team}
|
||||
classes={classes}
|
||||
match={match}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
})}
|
||||
{errors}
|
||||
</Grid>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid item xs={10}>
|
||||
<MessageCard message='You don’t have any teams. Create one!'>
|
||||
<CreateTeamDialog />
|
||||
</MessageCard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<div className='container'>
|
||||
<Paper className={classes.paper} >
|
||||
|
||||
<Typography className={classes.typography} variant='h5' gutterBottom>
|
||||
Your First Team
|
||||
</Typography>
|
||||
|
||||
<Typography className={classes.typography} variant='body1' gutterBottom align='left'>
|
||||
To begin developing on the Advanced Algos platform, as well as to participate in trading competitions,
|
||||
you will need to create a team or become a member of an existing one. Currently, the only option is to create your own team. As part of the same process, an already existing trading bot will be forked for you so that you do not have to start from scratch. It will be added to your team so
|
||||
that you can begin experimenting right away.
|
||||
</Typography>
|
||||
<CreateTeamForm />
|
||||
|
||||
</Paper>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid item xs={12}>
|
||||
<MessageCard message='Loading...' />
|
||||
{errors !== null && <MessageCard message={errors} />}
|
||||
<div className={classes.root} >
|
||||
<Grid container spacing={0} direction='column' justify='center' alignItems='center'>
|
||||
<Grid item xs={12}>
|
||||
{errors === null &&
|
||||
<Typography variant='h5' align='center' gutterBottom>
|
||||
Loading...
|
||||
</Typography>
|
||||
}
|
||||
{errors !== null &&
|
||||
<Typography variant='h5' align='center' gutterBottom>
|
||||
{errors}
|
||||
</Typography>
|
||||
}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}}
|
||||
@@ -104,7 +166,8 @@ export const ManageTeamsList = ({ classes, user = null, ...props }) => (
|
||||
|
||||
ManageTeamsList.propTypes = {
|
||||
user: PropTypes.any,
|
||||
classes: PropTypes.object.isRequired
|
||||
classes: PropTypes.object.isRequired,
|
||||
match: PropTypes.object
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageTeamsList)
|
||||
@@ -1,28 +1,25 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { BannerTopBar } from '../common'
|
||||
import ManageTeamsList from './components/ManageTeamsList'
|
||||
|
||||
const styles = theme => ({
|
||||
tableContainer: {
|
||||
height: 320
|
||||
}
|
||||
})
|
||||
|
||||
const ManageTeams = ({ classes, ...props }) => (
|
||||
const ManageTeams = ({ match, ...props }) => (
|
||||
<div>
|
||||
<Typography variant='h4' gutterBottom>
|
||||
Manage Your Teams
|
||||
</Typography>
|
||||
<ManageTeamsList {...props} />
|
||||
<BannerTopBar
|
||||
size={match.params.slug !== undefined ? 'small' : 'medium'}
|
||||
title='Your Teams'
|
||||
text='Create and manage your teams here.'
|
||||
backgroundUrl='https://advancedalgos.net/img/photos/teams.jpg'
|
||||
/>
|
||||
<div className='container'>
|
||||
<ManageTeamsList {...props} match={match} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
ManageTeams.propTypes = {
|
||||
classes: PropTypes.object.isRequired
|
||||
match: PropTypes.object
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageTeams)
|
||||
export default ManageTeams
|
||||
@@ -0,0 +1,207 @@
|
||||
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 DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { isEmpty } from '../../../utils/js-helpers'
|
||||
|
||||
import SEND_MEMBER_INVITE from '../../../graphql/teams/SendMemberInvite'
|
||||
|
||||
// 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 InviteMemberDialog 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.state = {
|
||||
open: false,
|
||||
email: '',
|
||||
errors: {
|
||||
email: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { classes, teamId } = this.props
|
||||
|
||||
if (this.state.open) {
|
||||
return (
|
||||
<Mutation mutation={SEND_MEMBER_INVITE} >
|
||||
{(sendMemberInvite, { loading, error, data }) => {
|
||||
console.log('sendMemberInvite: ', data)
|
||||
let errors
|
||||
let loader = null
|
||||
if (loading) {
|
||||
loader = (
|
||||
<Typography variant='subtitle1'>Submitting invitation...</Typography>
|
||||
)
|
||||
}
|
||||
if (error) {
|
||||
errors = error.graphQLErrors.map(({ message }, i) => {
|
||||
// const displayMessage = checkGraphQLError(message)
|
||||
return (
|
||||
<Typography key={i} variant='caption'>
|
||||
{message}
|
||||
</Typography>
|
||||
)
|
||||
})
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
variant='fab'
|
||||
color='primary'
|
||||
aria-label='Add'
|
||||
className={classes.buttonRight}
|
||||
onClick={this.handleClickOpen}
|
||||
>
|
||||
<AddIcon />
|
||||
</Button>
|
||||
<Dialog
|
||||
open={this.state.open}
|
||||
onClose={this.handleClose}
|
||||
aria-labelledby='form-dialog-title'
|
||||
>
|
||||
<DialogTitle id='form-dialog-title'>Invite a New Team Member</DialogTitle>
|
||||
<DialogContent>
|
||||
{(data === undefined || data.sendMemberInviteSG !== 'Success') && (
|
||||
<FormControl
|
||||
required
|
||||
error={this.state.errors.email !== '' || (error !== undefined || error !== null)}
|
||||
>
|
||||
<TextField
|
||||
autoFocus
|
||||
margin='dense'
|
||||
id='email'
|
||||
label='Email Address'
|
||||
type='text'
|
||||
fullWidth
|
||||
value={this.state.email}
|
||||
onChange={e => this.handleChange(e)}
|
||||
error={this.state.errors.email !== ''}
|
||||
/>
|
||||
{this.state.errors.email !== '' && (
|
||||
<FormHelperText>{this.state.errors.email}</FormHelperText>
|
||||
)}
|
||||
{error && <FormHelperText>{errors}</FormHelperText>}
|
||||
{loader}
|
||||
</FormControl>
|
||||
)}
|
||||
{data !== undefined && data.sendMemberInviteSG === 'Success' && (
|
||||
<Typography variant='subtitle1'>Invitation successfully sent!</Typography>
|
||||
)}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
{(data === undefined || data.sendMemberInviteSG !== 'Success') && (
|
||||
<React.Fragment>
|
||||
<Button onClick={this.handleClose} color='primary'>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={e => {
|
||||
this.handleSubmit(e, sendMemberInvite, this.state.email, teamId)
|
||||
}}
|
||||
color='primary'
|
||||
>
|
||||
Send Invitation
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
)}
|
||||
{data !== undefined && data.sendMemberInviteSG === 'Success' && (
|
||||
<Button onClick={this.handleClose} color='primary'>
|
||||
Close
|
||||
</Button>
|
||||
)}
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</Mutation>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Button
|
||||
variant='fab'
|
||||
color='primary'
|
||||
aria-label='Add'
|
||||
className={classes.buttonRight}
|
||||
onClick={this.handleClickOpen}
|
||||
>
|
||||
<AddIcon />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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: { email: '' } })
|
||||
this.setState({ email: e.target.value })
|
||||
} else {
|
||||
this.setState({ errors: errors })
|
||||
this.setState({ email: e.target.value })
|
||||
}
|
||||
}
|
||||
|
||||
async handleSubmit (e, sendMemberInvite, email, teamId) {
|
||||
e.preventDefault()
|
||||
console.log('sendMemberInvite submit: ', email, teamId)
|
||||
await sendMemberInvite({ variables: { email, teamId } })
|
||||
this.setState({ email: '' })
|
||||
}
|
||||
|
||||
validate (data) {
|
||||
const errors = {}
|
||||
if (data === '') errors.email = 'Please enter an email address'
|
||||
return errors
|
||||
}
|
||||
}
|
||||
|
||||
InviteMemberDialog.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
teamId: PropTypes.string
|
||||
}
|
||||
|
||||
export default withStyles(styles)(InviteMemberDialog)
|
||||
@@ -32,7 +32,7 @@ export const ManageMembersItem = ({ classes, member, teamId, authId }) => {
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<Typography color='textSecondary' variant='body2' component='h4' align='left' >
|
||||
<Typography color='textSecondary' variant='body1' component='h4' align='left' >
|
||||
{email !== null ? `${memberStatus[memberStatus.length - 1].status} | Sent: ${memberStatus[memberStatus.length - 1].createdAt}` : `${member.role} | Member since: `}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
@@ -63,7 +63,7 @@ export const ManageMembersTeamItem = ({ classes, team, authId }) => {
|
||||
if (team.profile.avatar !== undefined && team.profile.avatar !== 'a') {
|
||||
avatar = team.profile.avatar
|
||||
} else {
|
||||
avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
}
|
||||
if (team.members.length > 0) {
|
||||
return (
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
// import ManageTeamMembersList from './components/ManageTeamMembersList'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
import { BannerTopBar } from '../common'
|
||||
|
||||
const styles = theme => ({
|
||||
tableContainer: {
|
||||
@@ -15,11 +14,7 @@ const styles = theme => ({
|
||||
|
||||
const TeamMembers = ({ classes }) => (
|
||||
<div>
|
||||
<Typography variant='h4' gutterBottom>
|
||||
Team Members
|
||||
<MessageCard message='Coming soon. Invite and manage team members.' />
|
||||
</Typography>
|
||||
|
||||
<BannerTopBar size='big' title='Team Members' text='Coming soon. Invite and manage team members.' backgroundUrl='https://advancedalgos.net/img/photos/teams.jpg' />
|
||||
</div>
|
||||
)
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
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 Grid from '@material-ui/core/Grid'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import TeamsFBView from './TeamsFBView'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1
|
||||
@@ -18,41 +20,73 @@ const styles = theme => ({
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
width: 'auto',
|
||||
marginLeft: theme.spacing.unit * 3,
|
||||
marginRight: theme.spacing.unit * 3,
|
||||
width: '100%',
|
||||
marginBottom: theme.spacing.unit * 6,
|
||||
[theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 900,
|
||||
[theme.breakpoints.up(800 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 800,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto'
|
||||
}
|
||||
},
|
||||
paper: {
|
||||
marginTop: theme.spacing.unit * 3,
|
||||
marginTop: 0,
|
||||
marginBottom: theme.spacing.unit * 3,
|
||||
padding: theme.spacing.unit * 2,
|
||||
[theme.breakpoints.up(600 + theme.spacing.unit * 3 * 2)]: {
|
||||
marginTop: theme.spacing.unit * 6,
|
||||
padding: 0,
|
||||
[theme.breakpoints.up(800 + theme.spacing.unit * 3 * 2)]: {
|
||||
marginTop: theme.spacing.unit * 3,
|
||||
marginBottom: theme.spacing.unit * 6,
|
||||
padding: theme.spacing.unit * 3
|
||||
padding: `0 0 ${theme.spacing.unit * 2}px`
|
||||
}
|
||||
},
|
||||
heroContent: {
|
||||
maxWidth: 600,
|
||||
maxWidth: 800,
|
||||
margin: '0 auto',
|
||||
padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px`
|
||||
padding: `0 0 ${theme.spacing.unit * 2}px`
|
||||
},
|
||||
metaContainer: {
|
||||
marginTop: `${theme.spacing.unit * 1}px`,
|
||||
alignSelf: 'stretch',
|
||||
borderRight: '1px solid #CCCCCC'
|
||||
},
|
||||
teamMeta: {
|
||||
margin: `${theme.spacing.unit * 3}px 0 0`,
|
||||
paddingLeft: `${theme.spacing.unit * 2}px`,
|
||||
textAlign: 'center'
|
||||
},
|
||||
teamContent: {
|
||||
'& h2': {
|
||||
padding: `${theme.spacing.unit * 4}px ${theme.spacing.unit * 3}px ${theme.spacing.unit * 2}px`
|
||||
},
|
||||
'& h4': {
|
||||
padding: `0 ${theme.spacing.unit * 3}px ${theme.spacing.unit * 2}px`
|
||||
},
|
||||
'& h6': {
|
||||
padding: `0 ${theme.spacing.unit * 3}px 0`
|
||||
}
|
||||
},
|
||||
fbContent: {
|
||||
borderTop: '1px solid #CCCCCC',
|
||||
width: '90%',
|
||||
margin: `${theme.spacing.unit * 3}px auto`,
|
||||
paddingTop: `${theme.spacing.unit * 3}px`
|
||||
},
|
||||
banner: {
|
||||
maxWidth: '100%',
|
||||
height: 'auto',
|
||||
margin: '0 auto'
|
||||
width: '100%'
|
||||
},
|
||||
avatar: {
|
||||
maxWidth: 100,
|
||||
height: 100,
|
||||
margin: '0 1em 1em 0',
|
||||
float: 'left'
|
||||
maxWidth: 125,
|
||||
height: 125,
|
||||
margin: `0 auto ${theme.spacing.unit * 2}px`,
|
||||
verticalAlign: 'middle',
|
||||
borderRadius: '50%'
|
||||
},
|
||||
backLink: {
|
||||
display: 'block',
|
||||
textDecoration: 'none',
|
||||
margin: `${theme.spacing.unit * 3}px 0 0`,
|
||||
color: theme.palette.secondary.main
|
||||
}
|
||||
})
|
||||
|
||||
@@ -61,47 +95,75 @@ const TeamsDetails = ({ classes, team }) => {
|
||||
if (team.profile.avatar !== undefined && team.profile.avatar !== null) {
|
||||
avatar = team.profile.avatar
|
||||
} else {
|
||||
avatar = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22288%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20288%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_164edaf95ee%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A14pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_164edaf95ee%22%3E%3Crect%20width%3D%22288%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2296.32500076293945%22%20y%3D%22118.8%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
|
||||
avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
}
|
||||
let banner
|
||||
if (team.profile.banner !== undefined && team.profile.banner !== null) {
|
||||
banner = team.profile.banner
|
||||
} else {
|
||||
banner = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22288%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20288%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_164edaf95ee%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A14pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_164edaf95ee%22%3E%3Crect%20width%3D%22288%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2296.32500076293945%22%20y%3D%22118.8%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
|
||||
banner = process.env.STORAGE_URL + '/module-teams/module-default/aa-banner-default.png'
|
||||
}
|
||||
|
||||
const created = new Date(team.createdAt)
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<div className='container'>
|
||||
<main className={classes.layout}>
|
||||
<Link to='/teams/explore' className={classes.backLink}>← Back to all teams</Link>
|
||||
<Paper className={classes.paper}>
|
||||
<Link to='/teams'>← Back to all teams</Link>
|
||||
<div className={classes.heroContent}>
|
||||
<img src={banner} alt={team.name} className={classes.banner} />
|
||||
<img src={avatar} alt={team.name} className={classes.avatar} />
|
||||
<Typography
|
||||
variant='h2'
|
||||
align='center'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
>
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography variant='subtitle1' color='textSecondary'>
|
||||
{team.createdAt}
|
||||
</Typography>
|
||||
<Typography variant='subtitle1' color='textSecondary'>
|
||||
Motto: {team.profile.motto}
|
||||
</Typography>
|
||||
<Typography variant='subtitle1' color='textSecondary'>
|
||||
Description: {team.profile.description}
|
||||
</Typography>
|
||||
<Typography variant='subtitle1' paragraph gutterBottom>
|
||||
Members: {team.members.length}
|
||||
</Typography>
|
||||
<Grid container>
|
||||
<Grid md={3} className={classes.metaContainer}>
|
||||
<Grid container className={classes.teamMeta} direction='column' justify='center'>
|
||||
<img src={avatar} alt={team.name} className={classes.avatar} />
|
||||
<Typography variant='subtitle1' paragraph gutterBottom>
|
||||
Members: {team.members.length}
|
||||
</Typography>
|
||||
<Typography variant='subtitle1' paragraph gutterBottom>
|
||||
Financial Beings: 1
|
||||
</Typography>
|
||||
<Typography variant='subtitle1' paragraph gutterBottom>
|
||||
Created: {created.toLocaleDateString()}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid md={9}>
|
||||
<Grid container className={classes.teamContent} direction='column'>
|
||||
<Typography
|
||||
variant='h2'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
>
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant='h4'
|
||||
color='textSecondary'
|
||||
gutterBottom
|
||||
>
|
||||
Motto: {team.profile.motto}
|
||||
</Typography>
|
||||
<Typography variant='h6' color='textPrimary' gutterBottom>
|
||||
Description: {team.profile.description}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid container className={classes.fbContent} direction='column'>
|
||||
<Typography
|
||||
variant='h4'
|
||||
color='textSecondary'
|
||||
gutterBottom
|
||||
>
|
||||
Financial Beings
|
||||
</Typography>
|
||||
<TeamsFBView team={team} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
</Paper>
|
||||
</main>
|
||||
</React.Fragment>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
TeamsDetails.propTypes = {
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
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 Typography from '@material-ui/core/Typography'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import log from '../../../utils/log'
|
||||
|
||||
const styles = theme => ({
|
||||
fbContainer: {
|
||||
margin: `0 0 ${theme.spacing.unit * 2}px`
|
||||
},
|
||||
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 TeamsFBView = ({ classes, team }) => {
|
||||
log.debug('ManageTeamProvileFBView', team, team.fb[0])
|
||||
let avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
if (team.fb.length > 0) {
|
||||
avatar = team.fb[0].avatar
|
||||
|
||||
return (
|
||||
<Grid item xs={12} className={classes.fbContainer}>
|
||||
<Card className={classes.card}>
|
||||
<div className={classes.cardDetails}>
|
||||
<CardMedia
|
||||
className={classes.cardMedia}
|
||||
image={avatar}
|
||||
title={team.name}
|
||||
/>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography gutterBottom variant='h5' component='h2'>
|
||||
{team.fb[0].name}
|
||||
</Typography>
|
||||
<Typography variant='caption' color='textSecondary'>
|
||||
{team.fb[0].kind}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</div>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Grid item xs={12} className={classes.fbContainer}>
|
||||
<Card className={classes.card}>
|
||||
<div className={classes.cardDetails}>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography gutterBottom variant='h6'>
|
||||
No Financial Beings
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</div>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
TeamsFBView.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
team: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(TeamsFBView)
|
||||
@@ -4,55 +4,93 @@ 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 { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { Link } from 'react-router-dom'
|
||||
// const TeamDetailsLink = ({ teamSlug, ...props }) => <Link to={`/teams/${teamSlug}`} {...props} />
|
||||
|
||||
const styles = theme => ({
|
||||
card: {
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
},
|
||||
cardMedia: {
|
||||
paddingTop: '25%', // 16:9
|
||||
width: '100%'
|
||||
},
|
||||
cardContent: {
|
||||
flexGrow: 1
|
||||
},
|
||||
avatar: {
|
||||
maxWidth: 65,
|
||||
height: 65,
|
||||
margin: '0 0.875em 0 0',
|
||||
borderRadius: '50%',
|
||||
verticalAlign: 'middle',
|
||||
alignSelf: 'flex-start'
|
||||
},
|
||||
buttonRight: {
|
||||
textDecoration: 'none'
|
||||
}
|
||||
})
|
||||
|
||||
export const TeamsItem = ({ classes, team }) => {
|
||||
/* let avatar
|
||||
let avatar
|
||||
if (team.profile.avatar !== undefined && team.profile.avatar !== 'a') {
|
||||
avatar = team.profile.avatar
|
||||
} else {
|
||||
avatar = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22288%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20288%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_164edaf95ee%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A14pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_164edaf95ee%22%3E%3Crect%20width%3D%22288%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2296.32500076293945%22%20y%3D%22118.8%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
|
||||
} */
|
||||
avatar = process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
|
||||
}
|
||||
let banner
|
||||
if (team.profile.banner !== undefined && team.profile.banner !== null) {
|
||||
banner = team.profile.banner
|
||||
} else {
|
||||
banner = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22288%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20288%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_164edaf95ee%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A14pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_164edaf95ee%22%3E%3Crect%20width%3D%22288%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2296.32500076293945%22%20y%3D%22118.8%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
|
||||
banner = process.env.STORAGE_URL + '/module-teams/module-default/aa-banner-default.png'
|
||||
}
|
||||
return (
|
||||
<Grid item sm={6} md={4} lg={3}>
|
||||
<Grid item xs={12} sm={6} md={4}>
|
||||
<Card className={classes.card}>
|
||||
<CardActionArea>
|
||||
<CardActionArea component={Link} to={`/teams/${team.slug}`}>
|
||||
<CardMedia
|
||||
className={classes.cardMedia}
|
||||
image={banner}
|
||||
title={team.name}
|
||||
/>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography gutterBottom variant='h5' component='h2'>
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography variant='caption' paragraph gutterBottom>
|
||||
Members: 1
|
||||
</Typography>
|
||||
<Typography variant='subtitle1' color='primary'>
|
||||
Now recruiting!
|
||||
</Typography>
|
||||
<Grid container>
|
||||
<Grid item md={3} >
|
||||
<img src={avatar} alt={team.name} className={classes.avatar} />
|
||||
</Grid>
|
||||
<Grid item md={9}>
|
||||
<Grid container direction='column'>
|
||||
<Grid item xs={12}>
|
||||
<Typography gutterBottom variant='h5' component='h2'>
|
||||
{team.name}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Grid container spacing={8}>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant='caption'>
|
||||
Members: 1
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant='caption'>
|
||||
Financial Beings: 1
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
<CardActions>
|
||||
<Link to={`/teams/${team.slug}`}>
|
||||
<Button size='small' color='primary' className={classes.buttonRight}>
|
||||
Details
|
||||
</Button>
|
||||
</Link>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
@@ -63,4 +101,4 @@ TeamsItem.propTypes = {
|
||||
team: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default TeamsItem
|
||||
export default withStyles(styles)(TeamsItem)
|
||||
@@ -16,27 +16,8 @@ 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'
|
||||
teamListsContainer: {
|
||||
margin: `${theme.spacing.unit * 3}px 0 ${theme.spacing.unit * 6}px`
|
||||
}
|
||||
})
|
||||
|
||||
@@ -62,7 +43,7 @@ export const TeamsList = ({ classes, match }) => (
|
||||
if (data.teams_Teams.edges.length > 0) {
|
||||
if (slug !== null) {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid container >
|
||||
{!loading &&
|
||||
data.teams_Teams.edges.map(team => {
|
||||
if (team.node.slug === slug) {
|
||||
@@ -77,42 +58,31 @@ export const TeamsList = ({ classes, match }) => (
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className={classes.heroContent}>
|
||||
<Typography
|
||||
variant='h3'
|
||||
align='center'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
>
|
||||
Teams
|
||||
</Typography>
|
||||
</div>
|
||||
<Grid container spacing={40}>
|
||||
<div className={classes.teamListsContainer} >
|
||||
<Grid container spacing={24}>
|
||||
{!loading &&
|
||||
data.teams_Teams.edges.map(team => (
|
||||
<TeamsItem
|
||||
key={team.node.id}
|
||||
team={team.node}
|
||||
classes={classes}
|
||||
/>
|
||||
))}
|
||||
{queryLoader}
|
||||
{errors}
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid container>
|
||||
<MessageCard message='No teams found' />
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid container>
|
||||
<MessageCard message='Loading...' />
|
||||
{queryLoader}
|
||||
{errors}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { BannerTopBar } from '../common'
|
||||
import TeamsList from './components/TeamsList'
|
||||
|
||||
const styles = theme => ({
|
||||
@@ -17,11 +17,12 @@ const styles = theme => ({
|
||||
},
|
||||
layout: {
|
||||
width: 'auto',
|
||||
marginTop: theme.spacing.unit * 3,
|
||||
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,
|
||||
[theme.breakpoints.up(1200 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 1200,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto'
|
||||
}
|
||||
@@ -30,10 +31,10 @@ const styles = theme => ({
|
||||
|
||||
const Teams = ({ classes, match }) => (
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<main className={classes.layout}>
|
||||
<BannerTopBar size={match.params.slug !== undefined ? 'small' : 'medium'} title='Teams Directory' text='All teams in Advanced Algos are here.' backgroundUrl='https://advancedalgos.net/img/photos/teams.jpg' />
|
||||
<div className='container'>
|
||||
<TeamsList match={match} />
|
||||
</main>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ export const theme = createMuiTheme({
|
||||
secondary: indigo
|
||||
},
|
||||
typography: {
|
||||
fontFamily: '"Saira","Saira Condenses", sans-serif'
|
||||
fontFamily: '"Saira","Saira Condensed", sans-serif'
|
||||
},
|
||||
overrides: {
|
||||
Paper: {
|
||||
|
||||
Generated
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "AATeamModule",
|
||||
"version": "2.0.1",
|
||||
"lockfileVersion": 1
|
||||
}
|
||||
Reference in new issue
Block a user