Merge pull request #3 from AdvancedAlgos/feature/member-mangement
Feature/member mangement
This commit is contained in:
51 files changed
+4096
-282
No files matched your search
@@ -1,4 +1,5 @@
|
||||
/.env
|
||||
/.env.prod
|
||||
/database/.env
|
||||
/database/docker-compose.prisma.prod.yml
|
||||
/docker-compose.prisma.prod.yml
|
||||
|
||||
@@ -7,8 +7,9 @@ enum Role {
|
||||
enum Status {
|
||||
ACTIVE
|
||||
INACTIVE
|
||||
APPLY
|
||||
INVITE
|
||||
APPLIED
|
||||
INVITED
|
||||
REMOVED
|
||||
}
|
||||
|
||||
enum FBType {
|
||||
@@ -53,24 +54,35 @@ type TeamStatus {
|
||||
}
|
||||
|
||||
type TeamMembers {
|
||||
id: ID! @unique
|
||||
member: Member @relation (name: "MemberOnTeam", onDelete: SET_NULL)
|
||||
team: Team @relation (name: "TeamMembers", onDelete: SET_NULL)
|
||||
role: Role @default(value: MEMBER)
|
||||
status: [MemberStatus!]!
|
||||
status: [TeamMemberStatus!]!
|
||||
email: String @unique
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
type TeamMemberStatus {
|
||||
id: ID! @unique
|
||||
status: Status @Default(value: INACTIVE)
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
}
|
||||
|
||||
type Member {
|
||||
id: ID! @unique
|
||||
alias: String
|
||||
team: TeamMembers @relation (name: "MemberOnTeam", onDelete: SET_NULL)
|
||||
teams: [TeamMembers!]! @relation (name: "MemberOnTeam", onDelete: SET_NULL)
|
||||
authId: String! @unique
|
||||
visible: Boolean! @default(value: true)
|
||||
status: [MemberStatus!]!
|
||||
createdAt: DateTime!
|
||||
}
|
||||
|
||||
type MemberStatus {
|
||||
status: Status @Default(value: inactive)
|
||||
status: Status @Default(value: INACTIVE)
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
}
|
||||
@@ -84,6 +96,9 @@ type FinancialBeings {
|
||||
id: ID! @unique
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String!
|
||||
slug: String!
|
||||
avatar: String
|
||||
team: Team @relation (name: "TeamFinancialBeing", onDelete: SET_NULL)
|
||||
status: [FBStatus!]!
|
||||
updatedAt: DateTime!
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
version: '3'
|
||||
services:
|
||||
api:
|
||||
image: advancedalgosteamsmodule/teammodule-api:v1
|
||||
env_file: ./.env
|
||||
image: advancedalgosteamsmodule/teammodule-api:v2
|
||||
env_file: ./.env.prod
|
||||
container_name: aateamapi
|
||||
tty: true
|
||||
stdin_open: true
|
||||
|
||||
Generated
+1358
-71
File diff suppressed because it is too large.
Load diff
+2
-1
@@ -8,6 +8,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/storage-blob": "^10.0.0-preview",
|
||||
"axios": "^0.18.0",
|
||||
"azure-storage": "^2.10.1",
|
||||
"cors": "^2.8.4",
|
||||
"debug": "^4.0.1",
|
||||
@@ -27,6 +28,6 @@
|
||||
"devDependencies": {
|
||||
"graphql-cli": "^2.16.5",
|
||||
"npm-run-all": "4.1.3",
|
||||
"prisma": "^1.16.4"
|
||||
"prisma": "^1.17.1"
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ const isLoggedIn = async ctx => {
|
||||
let member = ctxMember(ctx, memberLocationOnContext)
|
||||
let token = ctxToken(ctx, bearerAccessToken)
|
||||
let memberToken
|
||||
console.log('isLoggedIn: ', ctx, member, token)
|
||||
// console.log('isLoggedIn: ', ctx, member, token)
|
||||
if (!member && token) {
|
||||
let scheme, credentials
|
||||
const tokenParts = token.split(' ')
|
||||
@@ -41,16 +41,16 @@ const isLoggedIn = async ctx => {
|
||||
if (/^Bearer$/i.test(scheme)) {
|
||||
token = credentials
|
||||
//verify token
|
||||
console.log('isLoggedIn2 : ', token)
|
||||
// console.log('isLoggedIn2 : ', token)
|
||||
try {
|
||||
memberToken = await validateIdToken(token)
|
||||
const authId = memberToken.sub
|
||||
console.log('isLoggedIn3 : ', await authId, ctx.db.query.member)
|
||||
// console.log('isLoggedIn3 : ', await authId, ctx.db.query.member)
|
||||
exists = await ctx.db.query.member({ where: { authId: authId } })
|
||||
console.log('isLoggedIn4 : ', await exists, createMember )
|
||||
// console.log('isLoggedIn4 : ', await exists, createMember )
|
||||
if (!member && exists === null) {
|
||||
member = await createMember(ctx, memberToken).then(res => {
|
||||
console.log('isLoggedIn5 : ', res)
|
||||
// console.log('isLoggedIn5 : ', res)
|
||||
return res
|
||||
})
|
||||
|
||||
@@ -62,7 +62,7 @@ const isLoggedIn = async ctx => {
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log('isLoggedIn5 : ', await member)
|
||||
// console.log('isLoggedIn5 : ', await member)
|
||||
if (!member) {
|
||||
throw new Error(`Not logged in`)
|
||||
}
|
||||
@@ -95,13 +95,13 @@ const directiveResolvers = {
|
||||
? source
|
||||
: ctx.request.body.variables ? ctx.request.body.variables : { id: null }
|
||||
const user = await isLoggedIn(ctx)
|
||||
console.log('directive isOwner 0: ', typeId, user.sub)
|
||||
// console.log('directive isOwner 0: ', typeId, user.sub)
|
||||
const memberId = user.sub
|
||||
const isOwner =
|
||||
type === `Member`
|
||||
? memberId === typeId
|
||||
: await isRequestingMemberAlsoOwner({ ctx, memberId, type, typeId })
|
||||
console.log('directive isOwner 1: ', source, isOwner, type, typeId, memberId)
|
||||
// console.log('directive isOwner 1: ', source, isOwner, type, typeId, memberId)
|
||||
if (isOwner) {
|
||||
return next()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
var jwt = require('jsonwebtoken')
|
||||
var axios = require('axios')
|
||||
|
||||
const sendTeamMemberInvite = function(email, team) {
|
||||
const dev = process.env.NODE_ENV === 'development' ? true : false
|
||||
console.log('sendTeamMemberInvite', 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
|
||||
console.log('sendTeamMemberInvite', 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}`)
|
||||
}
|
||||
}
|
||||
|
||||
console.log('verifyInviteToken', verifiedToken)
|
||||
return verifiedToken
|
||||
}
|
||||
|
||||
module.exports = { sendTeamMemberInvite, sendTeamCreateConfirmation, verifyInviteToken }
|
||||
@@ -1,5 +1,5 @@
|
||||
# source: http://localhost:4466
|
||||
# timestamp: Thu Sep 20 2018 16:52:44 GMT-0700 (Pacific Daylight Time)
|
||||
# timestamp: Fri Oct 05 2018 13:16:40 GMT-0700 (Pacific Daylight Time)
|
||||
|
||||
type AggregateFBStatus {
|
||||
count: Int!
|
||||
@@ -25,6 +25,10 @@ type AggregateTeamMembers {
|
||||
count: Int!
|
||||
}
|
||||
|
||||
type AggregateTeamMemberStatus {
|
||||
count: Int!
|
||||
}
|
||||
|
||||
type AggregateTeamProfile {
|
||||
count: Int!
|
||||
}
|
||||
@@ -245,6 +249,9 @@ type FinancialBeings implements Node {
|
||||
id: ID!
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String!
|
||||
slug: String!
|
||||
avatar: String
|
||||
team(where: TeamWhereInput): Team
|
||||
status(where: FBStatusWhereInput, orderBy: FBStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [FBStatus!]
|
||||
updatedAt: DateTime!
|
||||
@@ -264,6 +271,9 @@ type FinancialBeingsConnection {
|
||||
input FinancialBeingsCreateInput {
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String!
|
||||
slug: String!
|
||||
avatar: String
|
||||
team: TeamCreateOneWithoutFbInput
|
||||
status: FBStatusCreateManyInput
|
||||
}
|
||||
@@ -276,6 +286,9 @@ input FinancialBeingsCreateManyWithoutTeamInput {
|
||||
input FinancialBeingsCreateWithoutTeamInput {
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String!
|
||||
slug: String!
|
||||
avatar: String
|
||||
status: FBStatusCreateManyInput
|
||||
}
|
||||
|
||||
@@ -295,6 +308,12 @@ enum FinancialBeingsOrderByInput {
|
||||
type_DESC
|
||||
kind_ASC
|
||||
kind_DESC
|
||||
name_ASC
|
||||
name_DESC
|
||||
slug_ASC
|
||||
slug_DESC
|
||||
avatar_ASC
|
||||
avatar_DESC
|
||||
updatedAt_ASC
|
||||
updatedAt_DESC
|
||||
createdAt_ASC
|
||||
@@ -305,6 +324,9 @@ type FinancialBeingsPreviousValues {
|
||||
id: ID!
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String!
|
||||
slug: String!
|
||||
avatar: String
|
||||
updatedAt: DateTime!
|
||||
createdAt: DateTime!
|
||||
}
|
||||
@@ -351,6 +373,9 @@ input FinancialBeingsSubscriptionWhereInput {
|
||||
input FinancialBeingsUpdateInput {
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String
|
||||
slug: String
|
||||
avatar: String
|
||||
team: TeamUpdateOneWithoutFbInput
|
||||
status: FBStatusUpdateManyInput
|
||||
}
|
||||
@@ -367,6 +392,9 @@ input FinancialBeingsUpdateManyWithoutTeamInput {
|
||||
input FinancialBeingsUpdateWithoutTeamDataInput {
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String
|
||||
slug: String
|
||||
avatar: String
|
||||
status: FBStatusUpdateManyInput
|
||||
}
|
||||
|
||||
@@ -450,6 +478,126 @@ input FinancialBeingsWhereInput {
|
||||
|
||||
"""All values that are not contained in given list."""
|
||||
kind_not_in: [FBKind!]
|
||||
name: String
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
name_not: String
|
||||
|
||||
"""All values that are contained in given list."""
|
||||
name_in: [String!]
|
||||
|
||||
"""All values that are not contained in given list."""
|
||||
name_not_in: [String!]
|
||||
|
||||
"""All values less than the given value."""
|
||||
name_lt: String
|
||||
|
||||
"""All values less than or equal the given value."""
|
||||
name_lte: String
|
||||
|
||||
"""All values greater than the given value."""
|
||||
name_gt: String
|
||||
|
||||
"""All values greater than or equal the given value."""
|
||||
name_gte: String
|
||||
|
||||
"""All values containing the given string."""
|
||||
name_contains: String
|
||||
|
||||
"""All values not containing the given string."""
|
||||
name_not_contains: String
|
||||
|
||||
"""All values starting with the given string."""
|
||||
name_starts_with: String
|
||||
|
||||
"""All values not starting with the given string."""
|
||||
name_not_starts_with: String
|
||||
|
||||
"""All values ending with the given string."""
|
||||
name_ends_with: String
|
||||
|
||||
"""All values not ending with the given string."""
|
||||
name_not_ends_with: String
|
||||
slug: String
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
slug_not: String
|
||||
|
||||
"""All values that are contained in given list."""
|
||||
slug_in: [String!]
|
||||
|
||||
"""All values that are not contained in given list."""
|
||||
slug_not_in: [String!]
|
||||
|
||||
"""All values less than the given value."""
|
||||
slug_lt: String
|
||||
|
||||
"""All values less than or equal the given value."""
|
||||
slug_lte: String
|
||||
|
||||
"""All values greater than the given value."""
|
||||
slug_gt: String
|
||||
|
||||
"""All values greater than or equal the given value."""
|
||||
slug_gte: String
|
||||
|
||||
"""All values containing the given string."""
|
||||
slug_contains: String
|
||||
|
||||
"""All values not containing the given string."""
|
||||
slug_not_contains: String
|
||||
|
||||
"""All values starting with the given string."""
|
||||
slug_starts_with: String
|
||||
|
||||
"""All values not starting with the given string."""
|
||||
slug_not_starts_with: String
|
||||
|
||||
"""All values ending with the given string."""
|
||||
slug_ends_with: String
|
||||
|
||||
"""All values not ending with the given string."""
|
||||
slug_not_ends_with: String
|
||||
avatar: String
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
avatar_not: String
|
||||
|
||||
"""All values that are contained in given list."""
|
||||
avatar_in: [String!]
|
||||
|
||||
"""All values that are not contained in given list."""
|
||||
avatar_not_in: [String!]
|
||||
|
||||
"""All values less than the given value."""
|
||||
avatar_lt: String
|
||||
|
||||
"""All values less than or equal the given value."""
|
||||
avatar_lte: String
|
||||
|
||||
"""All values greater than the given value."""
|
||||
avatar_gt: String
|
||||
|
||||
"""All values greater than or equal the given value."""
|
||||
avatar_gte: String
|
||||
|
||||
"""All values containing the given string."""
|
||||
avatar_contains: String
|
||||
|
||||
"""All values not containing the given string."""
|
||||
avatar_not_contains: String
|
||||
|
||||
"""All values starting with the given string."""
|
||||
avatar_starts_with: String
|
||||
|
||||
"""All values not starting with the given string."""
|
||||
avatar_not_starts_with: String
|
||||
|
||||
"""All values ending with the given string."""
|
||||
avatar_ends_with: String
|
||||
|
||||
"""All values not ending with the given string."""
|
||||
avatar_not_ends_with: String
|
||||
updatedAt: DateTime
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
@@ -513,9 +661,10 @@ scalar Long
|
||||
type Member implements Node {
|
||||
id: ID!
|
||||
alias: String
|
||||
team(where: TeamMembersWhereInput): TeamMembers
|
||||
teams(where: TeamMembersWhereInput, orderBy: TeamMembersOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamMembers!]
|
||||
authId: String!
|
||||
visible: Boolean!
|
||||
status(where: MemberStatusWhereInput, orderBy: MemberStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [MemberStatus!]
|
||||
createdAt: DateTime!
|
||||
}
|
||||
|
||||
@@ -533,18 +682,20 @@ input MemberCreateInput {
|
||||
alias: String
|
||||
authId: String!
|
||||
visible: Boolean
|
||||
team: TeamMembersCreateOneWithoutMemberInput
|
||||
teams: TeamMembersCreateManyWithoutMemberInput
|
||||
status: MemberStatusCreateManyInput
|
||||
}
|
||||
|
||||
input MemberCreateOneWithoutTeamInput {
|
||||
create: MemberCreateWithoutTeamInput
|
||||
input MemberCreateOneWithoutTeamsInput {
|
||||
create: MemberCreateWithoutTeamsInput
|
||||
connect: MemberWhereUniqueInput
|
||||
}
|
||||
|
||||
input MemberCreateWithoutTeamInput {
|
||||
input MemberCreateWithoutTeamsInput {
|
||||
alias: String
|
||||
authId: String!
|
||||
visible: Boolean
|
||||
status: MemberStatusCreateManyInput
|
||||
}
|
||||
|
||||
"""An edge in a connection."""
|
||||
@@ -806,27 +957,29 @@ input MemberUpdateInput {
|
||||
alias: String
|
||||
authId: String
|
||||
visible: Boolean
|
||||
team: TeamMembersUpdateOneWithoutMemberInput
|
||||
teams: TeamMembersUpdateManyWithoutMemberInput
|
||||
status: MemberStatusUpdateManyInput
|
||||
}
|
||||
|
||||
input MemberUpdateOneWithoutTeamInput {
|
||||
create: MemberCreateWithoutTeamInput
|
||||
input MemberUpdateOneWithoutTeamsInput {
|
||||
create: MemberCreateWithoutTeamsInput
|
||||
connect: MemberWhereUniqueInput
|
||||
disconnect: Boolean
|
||||
delete: Boolean
|
||||
update: MemberUpdateWithoutTeamDataInput
|
||||
upsert: MemberUpsertWithoutTeamInput
|
||||
update: MemberUpdateWithoutTeamsDataInput
|
||||
upsert: MemberUpsertWithoutTeamsInput
|
||||
}
|
||||
|
||||
input MemberUpdateWithoutTeamDataInput {
|
||||
input MemberUpdateWithoutTeamsDataInput {
|
||||
alias: String
|
||||
authId: String
|
||||
visible: Boolean
|
||||
status: MemberStatusUpdateManyInput
|
||||
}
|
||||
|
||||
input MemberUpsertWithoutTeamInput {
|
||||
update: MemberUpdateWithoutTeamDataInput!
|
||||
create: MemberCreateWithoutTeamInput!
|
||||
input MemberUpsertWithoutTeamsInput {
|
||||
update: MemberUpdateWithoutTeamsDataInput!
|
||||
create: MemberCreateWithoutTeamsInput!
|
||||
}
|
||||
|
||||
input MemberWhereInput {
|
||||
@@ -984,7 +1137,12 @@ input MemberWhereInput {
|
||||
|
||||
"""All values greater than or equal the given value."""
|
||||
createdAt_gte: DateTime
|
||||
team: TeamMembersWhereInput
|
||||
teams_every: TeamMembersWhereInput
|
||||
teams_some: TeamMembersWhereInput
|
||||
teams_none: TeamMembersWhereInput
|
||||
status_every: MemberStatusWhereInput
|
||||
status_some: MemberStatusWhereInput
|
||||
status_none: MemberStatusWhereInput
|
||||
}
|
||||
|
||||
input MemberWhereUniqueInput {
|
||||
@@ -999,36 +1157,45 @@ type Mutation {
|
||||
createFinancialBeings(data: FinancialBeingsCreateInput!): FinancialBeings!
|
||||
createTeamProfile(data: TeamProfileCreateInput!): TeamProfile!
|
||||
createWallet(data: WalletCreateInput!): Wallet!
|
||||
createFBStatus(data: FBStatusCreateInput!): FBStatus!
|
||||
createTeamStatus(data: TeamStatusCreateInput!): TeamStatus!
|
||||
createMemberStatus(data: MemberStatusCreateInput!): MemberStatus!
|
||||
createFBStatus(data: FBStatusCreateInput!): FBStatus!
|
||||
createTeamMemberStatus(data: TeamMemberStatusCreateInput!): TeamMemberStatus!
|
||||
createTeamStatus(data: TeamStatusCreateInput!): TeamStatus!
|
||||
updateTeam(data: TeamUpdateInput!, where: TeamWhereUniqueInput!): Team
|
||||
updateTeamMembers(data: TeamMembersUpdateInput!, where: TeamMembersWhereUniqueInput!): TeamMembers
|
||||
updateMember(data: MemberUpdateInput!, where: MemberWhereUniqueInput!): Member
|
||||
updateFinancialBeings(data: FinancialBeingsUpdateInput!, where: FinancialBeingsWhereUniqueInput!): FinancialBeings
|
||||
updateTeamMemberStatus(data: TeamMemberStatusUpdateInput!, where: TeamMemberStatusWhereUniqueInput!): TeamMemberStatus
|
||||
deleteTeam(where: TeamWhereUniqueInput!): Team
|
||||
deleteTeamMembers(where: TeamMembersWhereUniqueInput!): TeamMembers
|
||||
deleteMember(where: MemberWhereUniqueInput!): Member
|
||||
deleteFinancialBeings(where: FinancialBeingsWhereUniqueInput!): FinancialBeings
|
||||
deleteTeamMemberStatus(where: TeamMemberStatusWhereUniqueInput!): TeamMemberStatus
|
||||
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!
|
||||
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!
|
||||
updateManyFBStatuses(data: FBStatusUpdateInput!, where: FBStatusWhereInput): BatchPayload!
|
||||
updateManyTeamStatuses(data: TeamStatusUpdateInput!, where: TeamStatusWhereInput): 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!
|
||||
deleteManyTeams(where: TeamWhereInput): BatchPayload!
|
||||
deleteManyTeamMemberses(where: TeamMembersWhereInput): BatchPayload!
|
||||
deleteManyMembers(where: MemberWhereInput): BatchPayload!
|
||||
deleteManyFinancialBeingses(where: FinancialBeingsWhereInput): BatchPayload!
|
||||
deleteManyTeamProfiles(where: TeamProfileWhereInput): BatchPayload!
|
||||
deleteManyWallets(where: WalletWhereInput): BatchPayload!
|
||||
deleteManyFBStatuses(where: FBStatusWhereInput): BatchPayload!
|
||||
deleteManyTeamStatuses(where: TeamStatusWhereInput): BatchPayload!
|
||||
deleteManyMemberStatuses(where: MemberStatusWhereInput): BatchPayload!
|
||||
deleteManyFBStatuses(where: FBStatusWhereInput): BatchPayload!
|
||||
deleteManyTeamMemberStatuses(where: TeamMemberStatusWhereInput): BatchPayload!
|
||||
deleteManyTeamStatuses(where: TeamStatusWhereInput): BatchPayload!
|
||||
}
|
||||
|
||||
enum MutationType {
|
||||
@@ -1065,21 +1232,25 @@ type Query {
|
||||
financialBeingses(where: FinancialBeingsWhereInput, orderBy: FinancialBeingsOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [FinancialBeings]!
|
||||
teamProfiles(where: TeamProfileWhereInput, orderBy: TeamProfileOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamProfile]!
|
||||
wallets(where: WalletWhereInput, orderBy: WalletOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Wallet]!
|
||||
fBStatuses(where: FBStatusWhereInput, orderBy: FBStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [FBStatus]!
|
||||
teamStatuses(where: TeamStatusWhereInput, orderBy: TeamStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamStatus]!
|
||||
memberStatuses(where: MemberStatusWhereInput, orderBy: MemberStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [MemberStatus]!
|
||||
fBStatuses(where: FBStatusWhereInput, orderBy: FBStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [FBStatus]!
|
||||
teamMemberStatuses(where: TeamMemberStatusWhereInput, orderBy: TeamMemberStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamMemberStatus]!
|
||||
teamStatuses(where: TeamStatusWhereInput, orderBy: TeamStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamStatus]!
|
||||
team(where: TeamWhereUniqueInput!): Team
|
||||
teamMembers(where: TeamMembersWhereUniqueInput!): TeamMembers
|
||||
member(where: MemberWhereUniqueInput!): Member
|
||||
financialBeings(where: FinancialBeingsWhereUniqueInput!): FinancialBeings
|
||||
teamMemberStatus(where: TeamMemberStatusWhereUniqueInput!): TeamMemberStatus
|
||||
teamsConnection(where: TeamWhereInput, orderBy: TeamOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): TeamConnection!
|
||||
teamMembersesConnection(where: TeamMembersWhereInput, orderBy: TeamMembersOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): TeamMembersConnection!
|
||||
membersConnection(where: MemberWhereInput, orderBy: MemberOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): MemberConnection!
|
||||
financialBeingsesConnection(where: FinancialBeingsWhereInput, orderBy: FinancialBeingsOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): FinancialBeingsConnection!
|
||||
teamProfilesConnection(where: TeamProfileWhereInput, orderBy: TeamProfileOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): TeamProfileConnection!
|
||||
walletsConnection(where: WalletWhereInput, orderBy: WalletOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): WalletConnection!
|
||||
fBStatusesConnection(where: FBStatusWhereInput, orderBy: FBStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): FBStatusConnection!
|
||||
teamStatusesConnection(where: TeamStatusWhereInput, orderBy: TeamStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): TeamStatusConnection!
|
||||
memberStatusesConnection(where: MemberStatusWhereInput, orderBy: MemberStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): MemberStatusConnection!
|
||||
fBStatusesConnection(where: FBStatusWhereInput, orderBy: FBStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): FBStatusConnection!
|
||||
teamMemberStatusesConnection(where: TeamMemberStatusWhereInput, orderBy: TeamMemberStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): TeamMemberStatusConnection!
|
||||
teamStatusesConnection(where: TeamStatusWhereInput, orderBy: TeamStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): TeamStatusConnection!
|
||||
|
||||
"""Fetches an object given its ID"""
|
||||
node(
|
||||
@@ -1097,8 +1268,9 @@ enum Role {
|
||||
enum Status {
|
||||
ACTIVE
|
||||
INACTIVE
|
||||
APPLY
|
||||
INVITE
|
||||
APPLIED
|
||||
INVITED
|
||||
REMOVED
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
@@ -1108,9 +1280,10 @@ type Subscription {
|
||||
financialBeings(where: FinancialBeingsSubscriptionWhereInput): FinancialBeingsSubscriptionPayload
|
||||
teamProfile(where: TeamProfileSubscriptionWhereInput): TeamProfileSubscriptionPayload
|
||||
wallet(where: WalletSubscriptionWhereInput): WalletSubscriptionPayload
|
||||
fBStatus(where: FBStatusSubscriptionWhereInput): FBStatusSubscriptionPayload
|
||||
teamStatus(where: TeamStatusSubscriptionWhereInput): TeamStatusSubscriptionPayload
|
||||
memberStatus(where: MemberStatusSubscriptionWhereInput): MemberStatusSubscriptionPayload
|
||||
fBStatus(where: FBStatusSubscriptionWhereInput): FBStatusSubscriptionPayload
|
||||
teamMemberStatus(where: TeamMemberStatusSubscriptionWhereInput): TeamMemberStatusSubscriptionPayload
|
||||
teamStatus(where: TeamStatusSubscriptionWhereInput): TeamStatusSubscriptionPayload
|
||||
}
|
||||
|
||||
type Team implements Node {
|
||||
@@ -1186,11 +1359,14 @@ type TeamEdge {
|
||||
cursor: String!
|
||||
}
|
||||
|
||||
type TeamMembers {
|
||||
type TeamMembers implements Node {
|
||||
id: ID!
|
||||
member(where: MemberWhereInput): Member
|
||||
team(where: TeamWhereInput): Team
|
||||
role: Role
|
||||
status(where: MemberStatusWhereInput, orderBy: MemberStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [MemberStatus!]
|
||||
status(where: TeamMemberStatusWhereInput, orderBy: TeamMemberStatusOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [TeamMemberStatus!]
|
||||
email: String
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
@@ -1206,29 +1382,34 @@ type TeamMembersConnection {
|
||||
|
||||
input TeamMembersCreateInput {
|
||||
role: Role
|
||||
member: MemberCreateOneWithoutTeamInput
|
||||
email: String
|
||||
member: MemberCreateOneWithoutTeamsInput
|
||||
team: TeamCreateOneWithoutMembersInput
|
||||
status: MemberStatusCreateManyInput
|
||||
status: TeamMemberStatusCreateManyInput
|
||||
}
|
||||
|
||||
input TeamMembersCreateManyWithoutMemberInput {
|
||||
create: [TeamMembersCreateWithoutMemberInput!]
|
||||
connect: [TeamMembersWhereUniqueInput!]
|
||||
}
|
||||
|
||||
input TeamMembersCreateManyWithoutTeamInput {
|
||||
create: [TeamMembersCreateWithoutTeamInput!]
|
||||
}
|
||||
|
||||
input TeamMembersCreateOneWithoutMemberInput {
|
||||
create: TeamMembersCreateWithoutMemberInput
|
||||
connect: [TeamMembersWhereUniqueInput!]
|
||||
}
|
||||
|
||||
input TeamMembersCreateWithoutMemberInput {
|
||||
role: Role
|
||||
email: String
|
||||
team: TeamCreateOneWithoutMembersInput
|
||||
status: MemberStatusCreateManyInput
|
||||
status: TeamMemberStatusCreateManyInput
|
||||
}
|
||||
|
||||
input TeamMembersCreateWithoutTeamInput {
|
||||
role: Role
|
||||
member: MemberCreateOneWithoutTeamInput
|
||||
status: MemberStatusCreateManyInput
|
||||
email: String
|
||||
member: MemberCreateOneWithoutTeamsInput
|
||||
status: TeamMemberStatusCreateManyInput
|
||||
}
|
||||
|
||||
"""An edge in a connection."""
|
||||
@@ -1241,18 +1422,23 @@ type TeamMembersEdge {
|
||||
}
|
||||
|
||||
enum TeamMembersOrderByInput {
|
||||
role_ASC
|
||||
role_DESC
|
||||
updatedAt_ASC
|
||||
updatedAt_DESC
|
||||
id_ASC
|
||||
id_DESC
|
||||
role_ASC
|
||||
role_DESC
|
||||
email_ASC
|
||||
email_DESC
|
||||
createdAt_ASC
|
||||
createdAt_DESC
|
||||
updatedAt_ASC
|
||||
updatedAt_DESC
|
||||
}
|
||||
|
||||
type TeamMembersPreviousValues {
|
||||
id: ID!
|
||||
role: Role
|
||||
email: String
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
@@ -1295,36 +1481,320 @@ input TeamMembersSubscriptionWhereInput {
|
||||
node: TeamMembersWhereInput
|
||||
}
|
||||
|
||||
type TeamMemberStatus implements Node {
|
||||
id: ID!
|
||||
status: Status
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
}
|
||||
|
||||
"""A connection to a list of items."""
|
||||
type TeamMemberStatusConnection {
|
||||
"""Information to aid in pagination."""
|
||||
pageInfo: PageInfo!
|
||||
|
||||
"""A list of edges."""
|
||||
edges: [TeamMemberStatusEdge]!
|
||||
aggregate: AggregateTeamMemberStatus!
|
||||
}
|
||||
|
||||
input TeamMemberStatusCreateInput {
|
||||
status: Status
|
||||
reason: String
|
||||
}
|
||||
|
||||
input TeamMemberStatusCreateManyInput {
|
||||
create: [TeamMemberStatusCreateInput!]
|
||||
connect: [TeamMemberStatusWhereUniqueInput!]
|
||||
}
|
||||
|
||||
"""An edge in a connection."""
|
||||
type TeamMemberStatusEdge {
|
||||
"""The item at the end of the edge."""
|
||||
node: TeamMemberStatus!
|
||||
|
||||
"""A cursor for use in pagination."""
|
||||
cursor: String!
|
||||
}
|
||||
|
||||
enum TeamMemberStatusOrderByInput {
|
||||
id_ASC
|
||||
id_DESC
|
||||
status_ASC
|
||||
status_DESC
|
||||
reason_ASC
|
||||
reason_DESC
|
||||
createdAt_ASC
|
||||
createdAt_DESC
|
||||
updatedAt_ASC
|
||||
updatedAt_DESC
|
||||
}
|
||||
|
||||
type TeamMemberStatusPreviousValues {
|
||||
id: ID!
|
||||
status: Status
|
||||
reason: String
|
||||
createdAt: DateTime!
|
||||
}
|
||||
|
||||
type TeamMemberStatusSubscriptionPayload {
|
||||
mutation: MutationType!
|
||||
node: TeamMemberStatus
|
||||
updatedFields: [String!]
|
||||
previousValues: TeamMemberStatusPreviousValues
|
||||
}
|
||||
|
||||
input TeamMemberStatusSubscriptionWhereInput {
|
||||
"""Logical AND on all given filters."""
|
||||
AND: [TeamMemberStatusSubscriptionWhereInput!]
|
||||
|
||||
"""Logical OR on all given filters."""
|
||||
OR: [TeamMemberStatusSubscriptionWhereInput!]
|
||||
|
||||
"""Logical NOT on all given filters combined by AND."""
|
||||
NOT: [TeamMemberStatusSubscriptionWhereInput!]
|
||||
|
||||
"""
|
||||
The subscription event gets dispatched when it's listed in mutation_in
|
||||
"""
|
||||
mutation_in: [MutationType!]
|
||||
|
||||
"""
|
||||
The subscription event gets only dispatched when one of the updated fields names is included in this list
|
||||
"""
|
||||
updatedFields_contains: String
|
||||
|
||||
"""
|
||||
The subscription event gets only dispatched when all of the field names included in this list have been updated
|
||||
"""
|
||||
updatedFields_contains_every: [String!]
|
||||
|
||||
"""
|
||||
The subscription event gets only dispatched when some of the field names included in this list have been updated
|
||||
"""
|
||||
updatedFields_contains_some: [String!]
|
||||
node: TeamMemberStatusWhereInput
|
||||
}
|
||||
|
||||
input TeamMemberStatusUpdateDataInput {
|
||||
status: Status
|
||||
reason: String
|
||||
}
|
||||
|
||||
input TeamMemberStatusUpdateInput {
|
||||
status: Status
|
||||
reason: String
|
||||
}
|
||||
|
||||
input TeamMemberStatusUpdateManyInput {
|
||||
create: [TeamMemberStatusCreateInput!]
|
||||
connect: [TeamMemberStatusWhereUniqueInput!]
|
||||
disconnect: [TeamMemberStatusWhereUniqueInput!]
|
||||
delete: [TeamMemberStatusWhereUniqueInput!]
|
||||
update: [TeamMemberStatusUpdateWithWhereUniqueNestedInput!]
|
||||
upsert: [TeamMemberStatusUpsertWithWhereUniqueNestedInput!]
|
||||
}
|
||||
|
||||
input TeamMemberStatusUpdateWithWhereUniqueNestedInput {
|
||||
where: TeamMemberStatusWhereUniqueInput!
|
||||
data: TeamMemberStatusUpdateDataInput!
|
||||
}
|
||||
|
||||
input TeamMemberStatusUpsertWithWhereUniqueNestedInput {
|
||||
where: TeamMemberStatusWhereUniqueInput!
|
||||
update: TeamMemberStatusUpdateDataInput!
|
||||
create: TeamMemberStatusCreateInput!
|
||||
}
|
||||
|
||||
input TeamMemberStatusWhereInput {
|
||||
"""Logical AND on all given filters."""
|
||||
AND: [TeamMemberStatusWhereInput!]
|
||||
|
||||
"""Logical OR on all given filters."""
|
||||
OR: [TeamMemberStatusWhereInput!]
|
||||
|
||||
"""Logical NOT on all given filters combined by AND."""
|
||||
NOT: [TeamMemberStatusWhereInput!]
|
||||
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."""
|
||||
status_not: Status
|
||||
|
||||
"""All values that are contained in given list."""
|
||||
status_in: [Status!]
|
||||
|
||||
"""All values that are not contained in given list."""
|
||||
status_not_in: [Status!]
|
||||
reason: String
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
reason_not: String
|
||||
|
||||
"""All values that are contained in given list."""
|
||||
reason_in: [String!]
|
||||
|
||||
"""All values that are not contained in given list."""
|
||||
reason_not_in: [String!]
|
||||
|
||||
"""All values less than the given value."""
|
||||
reason_lt: String
|
||||
|
||||
"""All values less than or equal the given value."""
|
||||
reason_lte: String
|
||||
|
||||
"""All values greater than the given value."""
|
||||
reason_gt: String
|
||||
|
||||
"""All values greater than or equal the given value."""
|
||||
reason_gte: String
|
||||
|
||||
"""All values containing the given string."""
|
||||
reason_contains: String
|
||||
|
||||
"""All values not containing the given string."""
|
||||
reason_not_contains: String
|
||||
|
||||
"""All values starting with the given string."""
|
||||
reason_starts_with: String
|
||||
|
||||
"""All values not starting with the given string."""
|
||||
reason_not_starts_with: String
|
||||
|
||||
"""All values ending with the given string."""
|
||||
reason_ends_with: String
|
||||
|
||||
"""All values not ending with the given string."""
|
||||
reason_not_ends_with: String
|
||||
createdAt: DateTime
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
createdAt_not: DateTime
|
||||
|
||||
"""All values that are contained in given list."""
|
||||
createdAt_in: [DateTime!]
|
||||
|
||||
"""All values that are not contained in given list."""
|
||||
createdAt_not_in: [DateTime!]
|
||||
|
||||
"""All values less than the given value."""
|
||||
createdAt_lt: DateTime
|
||||
|
||||
"""All values less than or equal the given value."""
|
||||
createdAt_lte: DateTime
|
||||
|
||||
"""All values greater than the given value."""
|
||||
createdAt_gt: DateTime
|
||||
|
||||
"""All values greater than or equal the given value."""
|
||||
createdAt_gte: DateTime
|
||||
}
|
||||
|
||||
input TeamMemberStatusWhereUniqueInput {
|
||||
id: ID
|
||||
}
|
||||
|
||||
input TeamMembersUpdateInput {
|
||||
role: Role
|
||||
member: MemberUpdateOneWithoutTeamInput
|
||||
email: String
|
||||
member: MemberUpdateOneWithoutTeamsInput
|
||||
team: TeamUpdateOneWithoutMembersInput
|
||||
status: MemberStatusUpdateManyInput
|
||||
status: TeamMemberStatusUpdateManyInput
|
||||
}
|
||||
|
||||
input TeamMembersUpdateManyWithoutMemberInput {
|
||||
create: [TeamMembersCreateWithoutMemberInput!]
|
||||
connect: [TeamMembersWhereUniqueInput!]
|
||||
disconnect: [TeamMembersWhereUniqueInput!]
|
||||
delete: [TeamMembersWhereUniqueInput!]
|
||||
update: [TeamMembersUpdateWithWhereUniqueWithoutMemberInput!]
|
||||
upsert: [TeamMembersUpsertWithWhereUniqueWithoutMemberInput!]
|
||||
}
|
||||
|
||||
input TeamMembersUpdateManyWithoutTeamInput {
|
||||
create: [TeamMembersCreateWithoutTeamInput!]
|
||||
}
|
||||
|
||||
input TeamMembersUpdateOneWithoutMemberInput {
|
||||
create: TeamMembersCreateWithoutMemberInput
|
||||
disconnect: Boolean
|
||||
delete: Boolean
|
||||
update: TeamMembersUpdateWithoutMemberDataInput
|
||||
upsert: TeamMembersUpsertWithoutMemberInput
|
||||
connect: [TeamMembersWhereUniqueInput!]
|
||||
disconnect: [TeamMembersWhereUniqueInput!]
|
||||
delete: [TeamMembersWhereUniqueInput!]
|
||||
update: [TeamMembersUpdateWithWhereUniqueWithoutTeamInput!]
|
||||
upsert: [TeamMembersUpsertWithWhereUniqueWithoutTeamInput!]
|
||||
}
|
||||
|
||||
input TeamMembersUpdateWithoutMemberDataInput {
|
||||
role: Role
|
||||
email: String
|
||||
team: TeamUpdateOneWithoutMembersInput
|
||||
status: MemberStatusUpdateManyInput
|
||||
status: TeamMemberStatusUpdateManyInput
|
||||
}
|
||||
|
||||
input TeamMembersUpsertWithoutMemberInput {
|
||||
input TeamMembersUpdateWithoutTeamDataInput {
|
||||
role: Role
|
||||
email: String
|
||||
member: MemberUpdateOneWithoutTeamsInput
|
||||
status: TeamMemberStatusUpdateManyInput
|
||||
}
|
||||
|
||||
input TeamMembersUpdateWithWhereUniqueWithoutMemberInput {
|
||||
where: TeamMembersWhereUniqueInput!
|
||||
data: TeamMembersUpdateWithoutMemberDataInput!
|
||||
}
|
||||
|
||||
input TeamMembersUpdateWithWhereUniqueWithoutTeamInput {
|
||||
where: TeamMembersWhereUniqueInput!
|
||||
data: TeamMembersUpdateWithoutTeamDataInput!
|
||||
}
|
||||
|
||||
input TeamMembersUpsertWithWhereUniqueWithoutMemberInput {
|
||||
where: TeamMembersWhereUniqueInput!
|
||||
update: TeamMembersUpdateWithoutMemberDataInput!
|
||||
create: TeamMembersCreateWithoutMemberInput!
|
||||
}
|
||||
|
||||
input TeamMembersUpsertWithWhereUniqueWithoutTeamInput {
|
||||
where: TeamMembersWhereUniqueInput!
|
||||
update: TeamMembersUpdateWithoutTeamDataInput!
|
||||
create: TeamMembersCreateWithoutTeamInput!
|
||||
}
|
||||
|
||||
input TeamMembersWhereInput {
|
||||
"""Logical AND on all given filters."""
|
||||
AND: [TeamMembersWhereInput!]
|
||||
@@ -1334,6 +1804,46 @@ input TeamMembersWhereInput {
|
||||
|
||||
"""Logical NOT on all given filters combined by AND."""
|
||||
NOT: [TeamMembersWhereInput!]
|
||||
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
|
||||
role: Role
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
@@ -1344,6 +1854,68 @@ input TeamMembersWhereInput {
|
||||
|
||||
"""All values that are not contained in given list."""
|
||||
role_not_in: [Role!]
|
||||
email: String
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
email_not: String
|
||||
|
||||
"""All values that are contained in given list."""
|
||||
email_in: [String!]
|
||||
|
||||
"""All values that are not contained in given list."""
|
||||
email_not_in: [String!]
|
||||
|
||||
"""All values less than the given value."""
|
||||
email_lt: String
|
||||
|
||||
"""All values less than or equal the given value."""
|
||||
email_lte: String
|
||||
|
||||
"""All values greater than the given value."""
|
||||
email_gt: String
|
||||
|
||||
"""All values greater than or equal the given value."""
|
||||
email_gte: String
|
||||
|
||||
"""All values containing the given string."""
|
||||
email_contains: String
|
||||
|
||||
"""All values not containing the given string."""
|
||||
email_not_contains: String
|
||||
|
||||
"""All values starting with the given string."""
|
||||
email_starts_with: String
|
||||
|
||||
"""All values not starting with the given string."""
|
||||
email_not_starts_with: String
|
||||
|
||||
"""All values ending with the given string."""
|
||||
email_ends_with: String
|
||||
|
||||
"""All values not ending with the given string."""
|
||||
email_not_ends_with: String
|
||||
createdAt: DateTime
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
createdAt_not: DateTime
|
||||
|
||||
"""All values that are contained in given list."""
|
||||
createdAt_in: [DateTime!]
|
||||
|
||||
"""All values that are not contained in given list."""
|
||||
createdAt_not_in: [DateTime!]
|
||||
|
||||
"""All values less than the given value."""
|
||||
createdAt_lt: DateTime
|
||||
|
||||
"""All values less than or equal the given value."""
|
||||
createdAt_lte: DateTime
|
||||
|
||||
"""All values greater than the given value."""
|
||||
createdAt_gt: DateTime
|
||||
|
||||
"""All values greater than or equal the given value."""
|
||||
createdAt_gte: DateTime
|
||||
updatedAt: DateTime
|
||||
|
||||
"""All values that are not equal to given value."""
|
||||
@@ -1368,9 +1940,14 @@ input TeamMembersWhereInput {
|
||||
updatedAt_gte: DateTime
|
||||
member: MemberWhereInput
|
||||
team: TeamWhereInput
|
||||
status_every: MemberStatusWhereInput
|
||||
status_some: MemberStatusWhereInput
|
||||
status_none: MemberStatusWhereInput
|
||||
status_every: TeamMemberStatusWhereInput
|
||||
status_some: TeamMemberStatusWhereInput
|
||||
status_none: TeamMemberStatusWhereInput
|
||||
}
|
||||
|
||||
input TeamMembersWhereUniqueInput {
|
||||
id: ID
|
||||
email: String
|
||||
}
|
||||
|
||||
enum TeamOrderByInput {
|
||||
|
||||
@@ -22,10 +22,29 @@ const TEAMS_CONNECTIONS_FRAGMENT = gql`{
|
||||
}
|
||||
members {
|
||||
role
|
||||
email
|
||||
member {
|
||||
alias
|
||||
authId
|
||||
}
|
||||
status {
|
||||
id
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
fb {
|
||||
id
|
||||
name
|
||||
slug
|
||||
avatar
|
||||
kind
|
||||
status {
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,17 +13,35 @@ const TEAMS_FRAGMENT = gql`{
|
||||
createdAt
|
||||
profile {
|
||||
avatar
|
||||
banner
|
||||
description
|
||||
motto
|
||||
updatedAt
|
||||
}
|
||||
members {
|
||||
role
|
||||
email
|
||||
member {
|
||||
alias
|
||||
authId
|
||||
}
|
||||
status {
|
||||
id
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
fb {
|
||||
id
|
||||
name
|
||||
slug
|
||||
avatar
|
||||
kind
|
||||
status {
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
|
||||
+86
-17
@@ -8,6 +8,7 @@ const {
|
||||
const { makeExecutableSchema } = require('graphql-tools')
|
||||
const { importSchema } = require('graphql-import')
|
||||
const parser = require('fast-xml-parser')
|
||||
var axios = require('axios')
|
||||
|
||||
const checkJwt = require('./auth/middleware/jwt')
|
||||
const { getMember } = require('./auth/middleware/getMember')
|
||||
@@ -20,6 +21,8 @@ const azureAccount = process.env.AZURE_STORAGE_ACCOUNT
|
||||
const azureKey = process.env.AZURE_STORAGE_ACCESS_KEY
|
||||
const azureStorageUrl = process.env.AZURE_STORAGE_URL
|
||||
|
||||
const { sendTeamMemberInvite, sendTeamCreateConfirmation, verifyInviteToken } = require('./email/sendgrid')
|
||||
|
||||
const TEAMS_FRAGMENT = require('./graphql/TeamsFragment')
|
||||
const TEAMS_CONNECTIONS_FRAGMENT = require('./graphql/TeamsConnectionsFragment')
|
||||
|
||||
@@ -73,10 +76,18 @@ const resolvers = {
|
||||
async teamByName(parent, { name }, ctx, info) {
|
||||
return ctx.db.query.team({ where: { name: name } }, `{ name }`)
|
||||
},
|
||||
async teamWithRole(parent, { teamId, role }, ctx, info) {
|
||||
return ctx.db.query.teamsConnection({where: {AND: [{id: teamId},{members_some:{role: role}}]}, first:1}, info)
|
||||
},
|
||||
async teamsByOwner(parent, { ownerId }, ctx, info) {
|
||||
console.log('teamsByOwner: ', ctx)
|
||||
return ctx.db.query.teams({where: { owner: ownerId }, orderBy:'updatedAt_DESC'}, TEAMS_FRAGMENT)
|
||||
},
|
||||
async teamsByRole(parent, args, ctx, info) {
|
||||
const authId = ctx.request.user.sub
|
||||
let teamAdmin = await ctx.db.query.teams({where: {members_some: {OR: [{role: 'ADMIN'}, {role: 'OWNER'}], AND: [{member: {authId: authId}}]}}, orderBy: 'updatedAt_DESC'}, TEAMS_FRAGMENT)
|
||||
console.log('teamsByRole teamAdmin: ', teamAdmin)
|
||||
return teamAdmin
|
||||
},
|
||||
async owner(parent, args, ctx, info) {
|
||||
console.log('resolver.query.owner ctx: ', ctxMember(ctx))
|
||||
return ctx.db.query.member({ where: { id: ctxMember(ctx).authId } }, info)
|
||||
@@ -110,15 +121,77 @@ const resolvers = {
|
||||
}
|
||||
return member
|
||||
},
|
||||
async createTeam(parent, { name, slug, owner }, ctx, info) {
|
||||
return ctx.db.mutation.createTeam({ data: { name: name, slug: slug, owner: owner, members: { create: { member:{ connect:{ authId: owner} }, role: 'OWNER' } }, profile:{create:{avatar:"a"} } } }, TEAMS_FRAGMENT)
|
||||
async sendMemberInviteSG(parent, { email, teamId }, ctx, info) {
|
||||
const team = await ctx.db.query.team({ where: { id: teamId } }, TEAMS_FRAGMENT)
|
||||
const addMember = await ctx.db.mutation.upsertTeamMembers({
|
||||
where:{email: email},
|
||||
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)
|
||||
return sendInvite
|
||||
},
|
||||
async verifyTeamInvite(parent, { token }, ctx, info) {
|
||||
let verifiedToken = null
|
||||
let team = null
|
||||
try {
|
||||
verifiedToken = await verifyInviteToken(token)
|
||||
team = {
|
||||
email: verifiedToken.email,
|
||||
team: {
|
||||
slug: verifiedToken.team
|
||||
}
|
||||
}
|
||||
console.log('verifyTeamInvite.token: ', await verifiedToken)
|
||||
} catch (err) {
|
||||
console.log('verifyTeamInvite. err: ', err)
|
||||
throw new Error(err.message)
|
||||
}
|
||||
return team
|
||||
},
|
||||
async createTeam(parent, { name, slug, botName, botSlug }, ctx, info) {
|
||||
console.log('createTeam ctx:', ctx.request.user)
|
||||
const authId = ctx.request.user.sub
|
||||
const encodedAuthId = encodeURI(authId)
|
||||
const getUserModuleUser = await axios.get(`https://users-api.advancedalgos.net/graphql?query=%7B%0A%20%20userByAuthId(authId%3A%22${encodedAuthId}%22)%7B%0A%20%20%20%20id%0A%09%09email%0A%20%20%20%20alias%0A%20%20%7D%0A%7D`)
|
||||
|
||||
const alias = await getUserModuleUser.data.data.userByAuthId.alias
|
||||
const email = getUserModuleUser.data.data.userByAuthId.email
|
||||
const avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
const banner = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-banner-default.png'
|
||||
/*
|
||||
const createTeamUrl = encodeURI(`${slug}/${name}/${alias}/${botSlug}`)
|
||||
const platformUrl = 'https://develop.advancedalgos.net/AABrowserAPI/teamSetup/'
|
||||
// const platformUrl = 'http://localhost:1337/AABrowserAPI/teamSetup/'
|
||||
const createPlatformTeam = await axios.get(`${platformUrl}${createTeamUrl}`)
|
||||
console.log('createPlatformTeam: ', await createPlatformTeam)
|
||||
|
||||
// const sessionToken = getUserModuleUser.data.data.userByAuthId.id
|
||||
update session token on user module
|
||||
const updateUserSession = await axios.post('https://users-api.advancedalgos.net/graphql', {
|
||||
query: 'mutation { language }'
|
||||
})
|
||||
|
||||
*/
|
||||
const createTeam = await ctx.db.mutation.createTeam({ data: {name: name, slug: slug, owner: authId, members: {create: {member: {connect: {authId: authId}}, role: 'OWNER'}}, profile: {create: {avatar: avatar, banner: banner}}, fb: {create: {name: botName, slug: botSlug, kind:'TRADER', avatar: avatar, status: {create: {status: 'ACTIVE', reason: "Cloned on team creation"}}}}, status: {create: {status: 'ACTIVE', reason:"Team created"}}} }, TEAMS_FRAGMENT)
|
||||
.catch((err) => {
|
||||
console.log('createTeam error: ', err)
|
||||
return err
|
||||
})
|
||||
|
||||
sendTeamCreateConfirmation(email, name, botName)
|
||||
|
||||
return createTeam
|
||||
},
|
||||
async updateTeamProfile(parent, { slug, owner, description, motto, avatar, banner }, ctx, info) {
|
||||
return ctx.db.mutation.updateTeam({data:{profile: {update: {description: description, motto: motto, avatar: avatar, banner: banner}}}, where:{slug: slug}}, TEAMS_FRAGMENT)
|
||||
.catch((err) => {
|
||||
console.log('createTeam error: ', err)
|
||||
return err
|
||||
})
|
||||
},
|
||||
async updateTeamProfile(parent, { slug, owner, description, motto, avatar, banner }, ctx, info) {
|
||||
return ctx.db.mutation.updateTeam({data:{profile: {update: {description: description, motto: motto, avatar: avatar, banner: banner}}}, where:{slug: slug}}, TEAMS_FRAGMENT)
|
||||
async updateFB(parent, { fbId, avatar}, ctx, info) {
|
||||
return ctx.db.mutation.updateFinancialBeings({data:{avatar:avatar}, where:{id:fbId}}, info)
|
||||
.catch((err) => {
|
||||
console.log('createTeam error: ', err)
|
||||
return err
|
||||
@@ -187,19 +260,15 @@ let whitelist = [
|
||||
'http://localhost:3002',
|
||||
'http://localhost:4000',
|
||||
'http://localhost:4002',
|
||||
'http://localhost:1337'
|
||||
'http://localhost:1337',
|
||||
'https://teams.advancedalgos.net',
|
||||
'https://users.advancedalgos.net',
|
||||
'https://users-api.advancedalgos.net',
|
||||
'https://keyvault.advancedalgos.net',
|
||||
'https://keyvault-api.advancedalgos.net',
|
||||
'https://aawebdevelop.azurewebsites.net',
|
||||
'https://develop.advancedalgos.net'
|
||||
]
|
||||
if(process.env.NODE_ENV === 'production'){
|
||||
whitelist = [
|
||||
'https://teams.advancedalgos.net',
|
||||
'https://users.advancedalgos.net',
|
||||
'https://users-api.advancedalgos.net',
|
||||
'https://keyvault.advancedalgos.net',
|
||||
'https://keyvault-api.advancedalgos.net',
|
||||
'http://localhost:1337'
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
const corsOptionsDelegate = (req, callback) => {
|
||||
var corsOptions
|
||||
|
||||
@@ -10,7 +10,9 @@ type Query {
|
||||
teamDetails: [Team!]! @isAuthenticated
|
||||
teamByName(name: String!): Team
|
||||
teamById(teamId: String!): Team
|
||||
teamWithRole(teamId: String!, role: String!): Team
|
||||
teamsByOwner(ownerId: String!): [Team!]! @isAuthenticated
|
||||
teamsByRole: [Team!]! @isAuthenticated
|
||||
owner: Member @isAuthenticated
|
||||
currentMember: Member @isAuthenticated
|
||||
member(authId: String!): Member @isAuthenticated
|
||||
@@ -18,10 +20,15 @@ type Query {
|
||||
|
||||
type Mutation {
|
||||
authenticate(idToken: String!): Member
|
||||
createTeam(name: String!, slug: String!, owner: String!): Team @isAuthenticated
|
||||
updateTeamProfile(slug: String!, owner: String!, description: String, motto: String, avatar: String, banner: String): Team @isAuthenticated
|
||||
verifyTeamInvite(token: String!): TeamMembers
|
||||
createTeam(name: String!, slug: String!, botName: String!, botSlug: String!): Team @isAuthenticated
|
||||
updateTeamProfile(slug: String!, description: String, motto: String, avatar: String, banner: String): Team @isAuthenticated
|
||||
updateFB(fbId: String!, avatar: String): FinancialBeings @isAuthenticated
|
||||
deleteTeam(slug: String!): Team @isAuthenticated @isOwner(type: "Team")
|
||||
getAzureSAS(teamSlug: String!):String
|
||||
sendMemberInviteSG(email: String!, teamId: String!): String
|
||||
confirmMember(token: String!): String
|
||||
removeTeamMember(teamId: String!, memberId: String!): String
|
||||
}
|
||||
|
||||
fragment MemberInfo on Member {
|
||||
|
||||
@@ -145,7 +145,7 @@ const createSASQueryURL = async (containerName) => {
|
||||
// console.log(`ContainerCheck marker: `, listContainersResponse)
|
||||
marker = listContainersResponse.marker;
|
||||
for (const container of listContainersResponse.containerItems) {
|
||||
// console.log(`ContainerCheck: ${container.name} | ${containerName} | ${marker}`)
|
||||
console.log(`ContainerCheck: ${container.name} | ${containerName} | ${marker}`)
|
||||
if(container.name === containerName){
|
||||
containerCheck = container.name
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ typings/
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.prod
|
||||
|
||||
# Build folder js files
|
||||
build/
|
||||
|
||||
Generated
+25
-8
@@ -6363,8 +6363,7 @@
|
||||
"decode-uri-component": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
||||
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
|
||||
"dev": true
|
||||
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
|
||||
},
|
||||
"decompress-response": {
|
||||
"version": "3.3.0",
|
||||
@@ -12204,6 +12203,18 @@
|
||||
"prepend-http": "^1.0.0",
|
||||
"query-string": "^4.1.0",
|
||||
"sort-keys": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"query-string": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
|
||||
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"object-assign": "^4.1.0",
|
||||
"strict-uri-encode": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"npm-run-all": {
|
||||
@@ -13899,13 +13910,19 @@
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"query-string": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
|
||||
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
|
||||
"dev": true,
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.1.0.tgz",
|
||||
"integrity": "sha512-pNB/Gr8SA8ff8KpUFM36o/WFAlthgaThka5bV19AD9PNTH20Pwq5Zxodif2YyHwrctp6SkL4GqlOot0qR/wGaw==",
|
||||
"requires": {
|
||||
"object-assign": "^4.1.0",
|
||||
"strict-uri-encode": "^1.0.0"
|
||||
"decode-uri-component": "^0.2.0",
|
||||
"strict-uri-encode": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"strict-uri-encode": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
|
||||
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
|
||||
}
|
||||
}
|
||||
},
|
||||
"querystring": {
|
||||
|
||||
+3
-4
@@ -59,8 +59,8 @@
|
||||
"script-ext-html-webpack-plugin": "^2.0.1",
|
||||
"style-loader": "^0.21.0",
|
||||
"uglifyjs-webpack-plugin": "^1.3.0",
|
||||
"webpack": "^4.17.1",
|
||||
"webpack-cli": "^2.1.5",
|
||||
"webpack": "^4.20.2",
|
||||
"webpack-cli": "^3.1.1",
|
||||
"webpack-hot-client": "^4.1.1",
|
||||
"webpack-merge": "^4.1.4",
|
||||
"webpack-serve": "^1.0.4",
|
||||
@@ -81,7 +81,6 @@
|
||||
"apollo-link-ws": "^1.0.8",
|
||||
"apollo-utilities": "^1.0.20",
|
||||
"auth0-lock": "^11.9.0",
|
||||
"azure-storage": "^2.10.1",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"blob-util": "^2.0.2",
|
||||
"browser-image-resizer": "^1.2.0",
|
||||
@@ -91,11 +90,11 @@
|
||||
"graphql": "^0.13.2",
|
||||
"graphql-tag": "^2.9.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"query-string": "^6.1.0",
|
||||
"react": "^16.5.0",
|
||||
"react-apollo": "^2.1.11",
|
||||
"react-dom": "^16.5.0",
|
||||
"react-dropzone": "^5.1.0",
|
||||
"react-image-crop": "^5.0.0",
|
||||
"react-image-cropper": "^1.3.0",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"recompose": "^0.30.0",
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
NavBar,
|
||||
Footer,
|
||||
Callback,
|
||||
AcceptTeamInvite,
|
||||
Home,
|
||||
About,
|
||||
Dashboard,
|
||||
@@ -171,6 +172,11 @@ class App extends Component {
|
||||
return <Callback {...props} />
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path='/activate-team-membership'
|
||||
render={props => <AcceptTeamInvite {...props} auth={auth} />}
|
||||
/>
|
||||
</Switch>
|
||||
<Footer />
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,19 @@ const AUTHENTICATE = gql`
|
||||
}
|
||||
}
|
||||
`
|
||||
const lock = new Auth0Lock(AUTH_CONFIG.clientId, AUTH_CONFIG.domain, {
|
||||
|
||||
const VERIFY_TEAM_INVITE = gql`
|
||||
mutation verifyTeamInvite($token: String!) {
|
||||
verifyTeamInvite(token: $token) {
|
||||
email
|
||||
team {
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const defaultOptions = {
|
||||
oidcConformant: true,
|
||||
autoclose: true,
|
||||
auth: {
|
||||
@@ -28,7 +40,27 @@ const lock = new Auth0Lock(AUTH_CONFIG.clientId, AUTH_CONFIG.domain, {
|
||||
scope: `openid profile email user_metadata app_metadata picture`
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const inviteOptions = {
|
||||
oidcConformant: true,
|
||||
autoclose: false,
|
||||
allowedConnections: ['Username-Password-Authentication'],
|
||||
allowShowPassword: true,
|
||||
auth: {
|
||||
sso: false,
|
||||
redirectUrl: window.location.origin + '/callback',
|
||||
responseType: 'token id_token',
|
||||
audience: `${AUTH_CONFIG.api_audience}`,
|
||||
params: {
|
||||
state: '',
|
||||
scope: `email`
|
||||
}
|
||||
},
|
||||
prefill: { email: '' }
|
||||
}
|
||||
|
||||
let lock = new Auth0Lock(AUTH_CONFIG.clientId, AUTH_CONFIG.domain, defaultOptions)
|
||||
|
||||
class Auth {
|
||||
constructor (cb, apolloClient) {
|
||||
@@ -37,6 +69,7 @@ class Auth {
|
||||
this.apolloClient = apolloClient
|
||||
this.cb = cb.bind(this)
|
||||
this.login = this.login.bind(this)
|
||||
this.loginInvite = this.loginInvite.bind(this)
|
||||
this.logout = this.logout.bind(this)
|
||||
this.isAuthenticated = this.isAuthenticated.bind(this)
|
||||
this.checkSession = this.checkSession.bind(this)
|
||||
@@ -47,6 +80,29 @@ class Auth {
|
||||
lock.show()
|
||||
}
|
||||
|
||||
async loginInvite (jwt) {
|
||||
let email
|
||||
let team
|
||||
try {
|
||||
const data = await client.mutate({
|
||||
mutation: VERIFY_TEAM_INVITE,
|
||||
variables: { token: jwt }
|
||||
})
|
||||
|
||||
console.log('loginInvite auth: ', await data.data.verifyTeamInvite)
|
||||
setItem('invite', JSON.stringify(data.data.verifyTeamInvite))
|
||||
|
||||
email = data.data.verifyTeamInvite.email
|
||||
team = data.data.verifyTeamInvite.team.slug
|
||||
} catch (err) {
|
||||
return console.log('loginInvite err: ', err)
|
||||
}
|
||||
inviteOptions.prefill.email = email
|
||||
inviteOptions.auth.params.state = `${email}|${team}`
|
||||
let lockInvite = new Auth0Lock(AUTH_CONFIG.clientId, AUTH_CONFIG.domain, inviteOptions)
|
||||
lockInvite.show()
|
||||
}
|
||||
|
||||
handleAuthentication () {
|
||||
// Add a callback for Lock's `authenticated` event
|
||||
lock.on('authenticated', this.setSession.bind(this))
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
const CREATE_TEAM = gql`
|
||||
mutation CreateTeamMutation($name: String!, $slug: String!, $owner: String!) {
|
||||
createTeam(name: $name, slug: $slug, owner: $owner) {
|
||||
mutation CreateTeamMutation($name: String!, $slug: String!, $botName: String!, $botSlug: String!) {
|
||||
createTeam(name: $name, slug: $slug, botName: $botName, botSlug: $botSlug) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
|
||||
@@ -25,10 +25,29 @@ export const GET_ALL_TEAMS_QUERY = gql`
|
||||
}
|
||||
members {
|
||||
role
|
||||
email
|
||||
member {
|
||||
alias
|
||||
authId
|
||||
}
|
||||
status {
|
||||
id
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
fb {
|
||||
id
|
||||
name
|
||||
slug
|
||||
avatar
|
||||
kind
|
||||
status {
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,29 @@ export const GET_TEAMS_BY_OWNER = gql`
|
||||
}
|
||||
members {
|
||||
role
|
||||
email
|
||||
member {
|
||||
alias
|
||||
authId
|
||||
}
|
||||
status {
|
||||
id
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
fb {
|
||||
id
|
||||
name
|
||||
slug
|
||||
avatar
|
||||
kind
|
||||
status {
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const REMOVE_TEAM_MEMBER = gql`
|
||||
mutation removeTeamMember($teamId: String!, $memberId: String!) {
|
||||
removeTeamMember(teamId: $teamId, memberId: $memberId) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default REMOVE_TEAM_MEMBER
|
||||
@@ -0,0 +1,10 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const SEND_MEMBER_INVITE = gql`
|
||||
mutation sendMemberInvite($email: String!, $teamId: String!) {
|
||||
sendMemberInviteSG(email: $email, teamId: $teamId)
|
||||
}
|
||||
`
|
||||
|
||||
export default SEND_MEMBER_INVITE
|
||||
@@ -0,0 +1,12 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const SET_TEAM_MEMBER_ROLE = gql`
|
||||
mutation setTeamMemberRole($teamId: String!, $memberId: String!, $role: String!) {
|
||||
setTeamMemberRole(teamId: $teamId, memberId: $memberId, role: $role) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default SET_TEAM_MEMBER_ROLE
|
||||
@@ -22,10 +22,29 @@ export const TEAMS_FRAGMENT = gql`
|
||||
}
|
||||
members {
|
||||
role
|
||||
email
|
||||
member {
|
||||
alias
|
||||
authId
|
||||
}
|
||||
status {
|
||||
id
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
fb {
|
||||
id
|
||||
name
|
||||
slug
|
||||
avatar
|
||||
kind
|
||||
status {
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
const UPDATE_FB = gql`
|
||||
mutation UpdateFBMutation($fbId: String!, $avatar: String) {
|
||||
updateFB(fbId: $fbId, avatar: $avatar) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
avatar
|
||||
kind
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default UPDATE_FB
|
||||
@@ -4,7 +4,6 @@ import gql from 'graphql-tag'
|
||||
const UPDATE_TEAM_PROFILE = gql`
|
||||
mutation UpdateTeamProfileMutation(
|
||||
$slug: String!,
|
||||
$owner: String!,
|
||||
$description: String,
|
||||
$motto: String,
|
||||
$avatar: String,
|
||||
@@ -12,7 +11,6 @@ const UPDATE_TEAM_PROFILE = gql`
|
||||
) {
|
||||
updateTeamProfile(
|
||||
slug: $slug,
|
||||
owner: $owner,
|
||||
description: $description,
|
||||
motto: $motto
|
||||
avatar: $avatar,
|
||||
@@ -37,10 +35,17 @@ const UPDATE_TEAM_PROFILE = gql`
|
||||
}
|
||||
members {
|
||||
role
|
||||
email
|
||||
member {
|
||||
alias
|
||||
authId
|
||||
}
|
||||
status {
|
||||
id
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React from 'react'
|
||||
|
||||
const Callback = () => <div>Authenticating...</div>
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
const Callback = () => <MessageCard message='Authenticating...' />
|
||||
|
||||
export default Callback
|
||||
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
import ManageFBList from './components/ManageFBList'
|
||||
|
||||
const styles = theme => ({
|
||||
tableContainer: {
|
||||
@@ -17,9 +17,7 @@ const FinancialBeings = ({ classes }) => (
|
||||
<Typography variant='display1' gutterBottom>
|
||||
Financial Beings
|
||||
</Typography>
|
||||
<div className={classes.tableContainer}>
|
||||
<MessageCard message='Coming soon. View your financial beings by team.' />
|
||||
</div>
|
||||
<ManageFBList />
|
||||
</div>
|
||||
)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ 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'
|
||||
|
||||
const styles = theme => ({
|
||||
@@ -16,10 +17,9 @@ const TeamMembers = ({ classes }) => (
|
||||
<div>
|
||||
<Typography variant='display1' gutterBottom>
|
||||
Team Members
|
||||
<MessageCard message='Coming soon. Invite and manage team members.' />
|
||||
</Typography>
|
||||
<div className={classes.tableContainer}>
|
||||
<MessageCard message='Coming soon. Invite and manage team members' />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)
|
||||
|
||||
|
||||
@@ -21,9 +21,19 @@ import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
// import { checkGraphQLError } from '../../../utils/graphql-errors'
|
||||
|
||||
const styles = theme => ({
|
||||
dialogContainer: {
|
||||
display: 'block',
|
||||
margin: '3em',
|
||||
minWidth: 400
|
||||
},
|
||||
dialogStyle: {
|
||||
padding: '3em'
|
||||
},
|
||||
textField: {
|
||||
width: '60%',
|
||||
marginLeft: '20%',
|
||||
marginBottom: 10
|
||||
},
|
||||
buttonRight: {
|
||||
// position: 'absolute',
|
||||
// right: '3em'
|
||||
@@ -49,9 +59,9 @@ export class CreateTeamDialog extends Component {
|
||||
this.state = {
|
||||
open: false,
|
||||
name: '',
|
||||
errors: {
|
||||
name: ''
|
||||
}
|
||||
botName: '',
|
||||
nameError: '',
|
||||
botNameError: ''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,12 +70,10 @@ export class CreateTeamDialog extends Component {
|
||||
return (
|
||||
<Mutation
|
||||
mutation={CREATE_TEAM}
|
||||
refetchQueries={[
|
||||
{
|
||||
query: GET_TEAMS_BY_OWNER,
|
||||
variables: { authId }
|
||||
}
|
||||
]}
|
||||
refetchQueries={[{
|
||||
query: GET_TEAMS_BY_OWNER,
|
||||
variables: { authId: authId }
|
||||
}]}
|
||||
>
|
||||
{(createTeam, { loading, error, data }) => {
|
||||
let errors
|
||||
@@ -101,43 +109,69 @@ export class CreateTeamDialog extends Component {
|
||||
onClose={this.handleClose}
|
||||
aria-labelledby='form-dialog-title'
|
||||
>
|
||||
<DialogTitle id='form-dialog-title'>Create a Team</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormControl
|
||||
required
|
||||
error={this.state.errors.name !== '' || error}
|
||||
>
|
||||
<TextField
|
||||
autoFocus
|
||||
margin='dense'
|
||||
id='teamname'
|
||||
label='Team Name'
|
||||
type='text'
|
||||
fullWidth
|
||||
value={this.state.name}
|
||||
onChange={this.handleChange}
|
||||
error={this.state.errors.name !== '' || error}
|
||||
/>
|
||||
{this.state.errors.name !== '' && (
|
||||
<FormHelperText>{this.state.errors.name}</FormHelperText>
|
||||
)}
|
||||
{error && <FormHelperText>{errors}</FormHelperText>}
|
||||
{loader}
|
||||
</FormControl>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleClose} color='primary'>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={e => {
|
||||
this.handleSubmit(e, createTeam, this.state.name, authId)
|
||||
}}
|
||||
color='primary'
|
||||
>
|
||||
Create Team
|
||||
</Button>
|
||||
</DialogActions>
|
||||
<div classes={classes.dialogContainer}>
|
||||
<DialogTitle id='form-dialog-title'>Create a Team</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormControl
|
||||
required
|
||||
error={this.state.nameError !== '' || this.state.botNameError !== '' || error !== null}
|
||||
>
|
||||
<Typography variant='subheading' align='center'>Create a name for your team</Typography>
|
||||
<TextField
|
||||
autoFocus
|
||||
margin='dense'
|
||||
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 variant='subheading' align='center' ><br />
|
||||
Create a name for your teams bot.
|
||||
</Typography>
|
||||
<Typography align='center' >
|
||||
<em>(Temporary: In the future, creating multiple Financial Beings <br />
|
||||
will occur in a separate module)</em>
|
||||
</Typography>
|
||||
<TextField
|
||||
autoFocus
|
||||
margin='dense'
|
||||
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}
|
||||
</FormControl>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleClose} color='primary'>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={e => {
|
||||
this.handleSubmit(e, createTeam, this.state.name, this.state.botName)
|
||||
}}
|
||||
color='primary'
|
||||
>
|
||||
Create Team
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
@@ -155,27 +189,50 @@ export class CreateTeamDialog extends Component {
|
||||
}
|
||||
|
||||
handleChange (e) {
|
||||
const errors = this.validate(e.target.value)
|
||||
if (isEmpty(errors)) {
|
||||
this.setState({ errors: { name: '' } })
|
||||
this.setState({ name: e.target.value })
|
||||
} else {
|
||||
this.setState({ errors: errors })
|
||||
this.setState({ name: e.target.value })
|
||||
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, authId) {
|
||||
async handleSubmit (e, createTeam, name, botName) {
|
||||
e.preventDefault()
|
||||
console.log('createTeam submit: ', authId, name)
|
||||
console.log('createTeam submit: ', name, botName)
|
||||
const slug = this.slugify(name)
|
||||
await createTeam({ variables: { name, slug, owner: authId } })
|
||||
const botSlug = this.slugify(name)
|
||||
await createTeam({ variables: { name, slug, botName, botSlug } })
|
||||
this.setState({ name: '', open: false })
|
||||
}
|
||||
|
||||
validate (data) {
|
||||
const errors = {}
|
||||
if (data === '') errors.name = 'Please enter a team name'
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@ import DialogContentText from '@material-ui/core/DialogContentText'
|
||||
import DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
|
||||
import { getItem } from '../../../utils/local-storage'
|
||||
|
||||
export class CreateTeamDialog extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
@@ -25,7 +23,8 @@ export class CreateTeamDialog extends Component {
|
||||
|
||||
this.state = {
|
||||
open: false,
|
||||
name: ''
|
||||
name: '',
|
||||
botName: ''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +37,16 @@ export class CreateTeamDialog extends Component {
|
||||
}
|
||||
|
||||
handleChange (e) {
|
||||
this.setState({ name: e.target.value })
|
||||
let value = e.target.value
|
||||
switch (e.target.id) {
|
||||
case 'name':
|
||||
this.setState({ name: value })
|
||||
break
|
||||
case 'botName':
|
||||
this.setState({ botName: value })
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
@@ -73,6 +81,17 @@ export class CreateTeamDialog extends Component {
|
||||
value={this.state.name}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<DialogContentText>Create a name for you teams bot. (Temporary: In the future, creating multiple Financial Beings will occur in a separate module)</DialogContentText>
|
||||
<TextField
|
||||
autoFocus
|
||||
margin='dense'
|
||||
id='botname'
|
||||
label='Team Bot Name'
|
||||
type='text'
|
||||
fullWidth
|
||||
value={this.state.botName}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleClose} color='primary'>
|
||||
@@ -106,20 +125,19 @@ export class CreateTeamDialog extends Component {
|
||||
|
||||
async handlePost (e) {
|
||||
e.preventDefault()
|
||||
const { name } = this.state
|
||||
const { name, botName } = this.state
|
||||
const slug = this.slugify(name)
|
||||
const currentUser = await getItem('user')
|
||||
let authId = JSON.parse(currentUser)
|
||||
authId = authId.sub
|
||||
console.log('createPage cu:', JSON.parse(currentUser))
|
||||
const botSlug = this.slugify(botName)
|
||||
|
||||
await this.props.createTeamMutation({
|
||||
variables: {
|
||||
name,
|
||||
slug,
|
||||
owner: authId
|
||||
botName,
|
||||
botSlug
|
||||
}
|
||||
})
|
||||
this.setState({ open: false })
|
||||
this.setState({ open: false, name: '', botName: '' })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,14 +18,11 @@ import { getItem } from '../../../utils/local-storage'
|
||||
|
||||
export const DashTeam = ({ classes, user = null }) => {
|
||||
let owner
|
||||
let loader
|
||||
let authId = null
|
||||
console.log('DashTeam: ', user)
|
||||
if (user !== null && isString(user)) {
|
||||
owner = JSON.parse(user)
|
||||
if (isDefined(owner.authId)) authId = owner.authId
|
||||
} else {
|
||||
loader = <Typography variant='caption'>Loading...</Typography>
|
||||
}
|
||||
console.log('DashTeam 2: ', owner, authId)
|
||||
|
||||
@@ -71,7 +68,6 @@ export const DashTeam = ({ classes, user = null }) => {
|
||||
))}
|
||||
{queryLoader}
|
||||
{errors}
|
||||
{loader}
|
||||
</Grid>
|
||||
)
|
||||
} else {
|
||||
@@ -79,7 +75,7 @@ export const DashTeam = ({ classes, user = null }) => {
|
||||
<Grid container spacing={40}>
|
||||
<Grid item xs={10}>
|
||||
<MessageCard message='No teams yet...'>
|
||||
<CreateTeamDialog authId={authId} />
|
||||
<CreateTeamDialog />
|
||||
</MessageCard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -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='subheading'>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='subheading'>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)
|
||||
@@ -0,0 +1,223 @@
|
||||
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 EditIcon from '@material-ui/icons/Edit'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import DialogActions from '@material-ui/core/DialogActions'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import DialogContentText from '@material-ui/core/DialogContentText'
|
||||
import DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
|
||||
import { MessageCard, 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 GET_AZURE_SAS from '../../../graphql/teams/GetAzureSASMutation'
|
||||
|
||||
const styles = theme => ({
|
||||
dialogContainer: {
|
||||
display: 'block',
|
||||
margin: '3em',
|
||||
minWidth: 400
|
||||
},
|
||||
buttonRight: {
|
||||
justifyContent: 'flex-end'
|
||||
}
|
||||
})
|
||||
|
||||
export class ManageFBEdit 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.authId = props.authId
|
||||
|
||||
this.state = {
|
||||
open: false,
|
||||
avatar: avatar
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
console.log('ManageFBEdit ', 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,
|
||||
variables: { authId: this.authId }
|
||||
}
|
||||
]}
|
||||
>
|
||||
{(updateFB, { loading, error, data }) => {
|
||||
let errors
|
||||
let loader
|
||||
if (loading) {
|
||||
loader = (
|
||||
<Typography variant='caption'>Submitting team...</Typography>
|
||||
)
|
||||
}
|
||||
if (error) {
|
||||
errors = error.graphQLErrors.map(({ message }, i) => {
|
||||
const displayMessage = checkGraphQLError(message)
|
||||
console.log('updateTeamProfile error:', displayMessage)
|
||||
return (
|
||||
<Typography key={i} variant='caption'>
|
||||
{message}
|
||||
</Typography>
|
||||
)
|
||||
})
|
||||
}
|
||||
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'
|
||||
>
|
||||
<div classes={classes.dialogContainer}>
|
||||
<DialogTitle id='form-dialog-title'>
|
||||
Edit Financial Being
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Mutation mutation={GET_AZURE_SAS} >
|
||||
{(getAzureSAS, { loading, error, data }) => {
|
||||
console.log('getAzureSAS: ', loading, error, data, fb)
|
||||
const AzureStorageUrl = process.env.AZURE_STORAGE_URL
|
||||
const containerName = slug
|
||||
let AzureSASURL
|
||||
if (!loading && data !== undefined) {
|
||||
AzureSASURL = data.getAzureSAS
|
||||
} else {
|
||||
getAzureSAS({ variables: { teamSlug: containerName } })
|
||||
}
|
||||
|
||||
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 (loading || data === undefined) {
|
||||
return (<MessageCard message='Loading...' />)
|
||||
} else {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<DialogContentText>Update Financial Beings's Avatar</DialogContentText>
|
||||
<ImageUpload
|
||||
key='avatar'
|
||||
handleUrl={this.handleAvatar}
|
||||
fileName={`${fb.slug}-fb-avatar.jpg`}
|
||||
containerName={containerName}
|
||||
existingImage={avatar}
|
||||
cropContainer={{ 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'
|
||||
}}
|
||||
AzureStorageUrl={AzureStorageUrl}
|
||||
AzureSASURL={AzureSASURL}
|
||||
cropRatio={1}
|
||||
debug
|
||||
/>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}}
|
||||
</Mutation>
|
||||
<TextField
|
||||
autoFocus
|
||||
margin='dense'
|
||||
id='name'
|
||||
label='Team Name'
|
||||
type='text'
|
||||
fullWidth
|
||||
disabled
|
||||
value={fb.name}
|
||||
/>
|
||||
{loader}
|
||||
{errors}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleClose} color='primary'>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={e => {
|
||||
this.handleSubmit(e, updateFB, fb.id, slug)
|
||||
}}
|
||||
color='primary'
|
||||
>
|
||||
Update Financial Being
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</Mutation>
|
||||
)
|
||||
}
|
||||
|
||||
handleClickOpen () {
|
||||
this.setState({ open: true })
|
||||
}
|
||||
|
||||
handleClose () {
|
||||
this.setState({ open: false })
|
||||
}
|
||||
|
||||
handleAvatar (avatarUrl) {
|
||||
console.log('handleAvatar: ', avatarUrl)
|
||||
this.setState({ avatar: `${avatarUrl}?${Math.random()}` })
|
||||
}
|
||||
|
||||
async handleSubmit (e, updateFB, fbId, slug) {
|
||||
console.log('handleSubmit: ', this.state)
|
||||
e.preventDefault()
|
||||
|
||||
await updateFB({
|
||||
variables: {
|
||||
fbId,
|
||||
avatar: this.state.avatar
|
||||
}
|
||||
})
|
||||
this.setState({ open: false })
|
||||
}
|
||||
}
|
||||
|
||||
ManageFBEdit.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
slug: PropTypes.string.isRequired,
|
||||
fb: PropTypes.object,
|
||||
authId: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageFBEdit)
|
||||
@@ -0,0 +1,53 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardActions from '@material-ui/core/CardActions'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import CardMedia from '@material-ui/core/CardMedia'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
|
||||
import ManageFBEdit from './ManageFBEdit'
|
||||
|
||||
export const ManageFBItem = ({ classes, team, authId }) => {
|
||||
console.log('ManageFBItem', team, team.fb[0], team.profile.avatar)
|
||||
let avatar
|
||||
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'
|
||||
}
|
||||
return (
|
||||
<Grid item xs={12}>
|
||||
<Card className={classes.card}>
|
||||
<div className={classes.cardDetails}>
|
||||
<CardMedia
|
||||
className={classes.cardMedia}
|
||||
image={avatar}
|
||||
title={team.name}
|
||||
/>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography gutterBottom variant='headline' component='h2'>
|
||||
{team.fb[0].name}
|
||||
</Typography>
|
||||
<Typography variant='caption' color='textSecondary'>
|
||||
{team.fb[0].kind}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<ManageFBEdit slug={team.slug} fb={team.fb[0]} authId={authId} />
|
||||
</CardActions>
|
||||
</div>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
ManageFBItem.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
team: PropTypes.object.isRequired,
|
||||
authId: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default ManageFBItem
|
||||
@@ -0,0 +1,150 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Query } from 'react-apollo'
|
||||
import { withStateHandlers, lifecycle, compose } from 'recompose'
|
||||
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { isDefined, isString } from '../../../utils/js-helpers'
|
||||
import { getItem } from '../../../utils/local-storage'
|
||||
|
||||
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
|
||||
import ManageFBItem from './ManageFBItem'
|
||||
import CreateTeamDialog from './CreateTeamDialog'
|
||||
|
||||
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`
|
||||
},
|
||||
buttonRight: {
|
||||
justifyContent: 'flex-end'
|
||||
},
|
||||
card: {
|
||||
display: 'flex',
|
||||
width: '100%'
|
||||
},
|
||||
cardDetails: {
|
||||
display: 'flex',
|
||||
flex: 1
|
||||
},
|
||||
cardContent: {
|
||||
flex: 1
|
||||
},
|
||||
cardMedia: {
|
||||
flex: 1,
|
||||
width: 100,
|
||||
height: 100,
|
||||
maxWidth: 100,
|
||||
justifyContent: 'flex-start'
|
||||
}
|
||||
})
|
||||
|
||||
export const ManageFBList = ({ classes, user = null }) => {
|
||||
let owner
|
||||
let authId = null
|
||||
console.log('ManageTeamsList: ', user)
|
||||
if (user !== null && isString(user)) {
|
||||
owner = JSON.parse(user)
|
||||
if (isDefined(owner.authId)) authId = owner.authId
|
||||
}
|
||||
console.log('ManageTeamsList 2: ', owner, authId)
|
||||
if (authId === undefined || authId === null) {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid>
|
||||
<MessageCard message='Loading...' />
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Query
|
||||
query={GET_TEAMS_BY_OWNER}
|
||||
variables={{ authId }}
|
||||
fetchPolicy='network-only'
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
console.log('GET_TEAMS_BY_OWNER: ', loading, error, data)
|
||||
|
||||
let errors = null
|
||||
if (error) {
|
||||
errors = error.graphQLErrors.map(({ message }, i) => {
|
||||
return <MessageCard message={message} />
|
||||
})
|
||||
}
|
||||
if (!loading && !error) {
|
||||
if (data.teamsByOwner.length > 0) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Grid container spacing={40}>
|
||||
{!loading &&
|
||||
data.teamsByOwner.map(team => (
|
||||
<ManageFBItem
|
||||
key={team.id}
|
||||
team={team}
|
||||
classes={classes}
|
||||
authId={authId}
|
||||
/>
|
||||
))}
|
||||
{errors}
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid item xs={10}>
|
||||
<MessageCard message='You don’t have any teams. Create one!'>
|
||||
<CreateTeamDialog authId={authId} />
|
||||
</MessageCard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid item xs={12}>
|
||||
<MessageCard message='Loading...' />
|
||||
{errors !== null && <MessageCard message={errors} />}
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
}}
|
||||
</Query>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ManageFBList.propTypes = {
|
||||
user: PropTypes.any,
|
||||
classes: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
const getUserOnMount = lifecycle({
|
||||
componentDidMount () {
|
||||
getItem('user').then(user => {
|
||||
this.setState({ user })
|
||||
}) // Set user to state
|
||||
}
|
||||
})
|
||||
|
||||
const mapStateToProps = withStateHandlers(() => ({ user: null }), {
|
||||
user: ({ user }) => () => ({ user })
|
||||
})
|
||||
|
||||
const ManageFBListAuthId = compose(
|
||||
mapStateToProps,
|
||||
getUserOnMount
|
||||
)(ManageFBList)
|
||||
|
||||
export default withStyles(styles)(ManageFBListAuthId)
|
||||
@@ -0,0 +1,152 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import { Mutation } from 'react-apollo'
|
||||
|
||||
import Button from '@material-ui/core/Button'
|
||||
import PersonAddDisabledIcon from '@material-ui/icons/PersonAddDisabled'
|
||||
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 REMOVE_TEAM_MEMBER from '../../../graphql/teams/RemoveTeamMemberMutation'
|
||||
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
|
||||
import { checkGraphQLError } from '../../../utils/graphql-errors'
|
||||
|
||||
const styles = theme => ({
|
||||
dialogContainer: {
|
||||
display: 'block',
|
||||
margin: '3em',
|
||||
minWidth: 400
|
||||
},
|
||||
buttonRight: {
|
||||
justifyContent: 'flex-end'
|
||||
}
|
||||
})
|
||||
|
||||
export class ManageMemberDelete extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.handleClickOpen = this.handleClickOpen.bind(this)
|
||||
this.handleClose = this.handleClose.bind(this)
|
||||
this.handleChange = this.handleChange.bind(this)
|
||||
this.handleSubmit = this.handleSubmit.bind(this)
|
||||
|
||||
this.state = {
|
||||
open: false
|
||||
}
|
||||
}
|
||||
|
||||
handleClickOpen () {
|
||||
this.setState({ open: true })
|
||||
}
|
||||
|
||||
handleClose () {
|
||||
this.setState({ open: false })
|
||||
}
|
||||
|
||||
handleChange (e) {
|
||||
this.setState({ name: e.target.value })
|
||||
}
|
||||
|
||||
render () {
|
||||
console.log(this.props, this.props.teamId)
|
||||
const { classes, teamId, authId } = this.props
|
||||
return (
|
||||
<Mutation
|
||||
mutation={REMOVE_TEAM_MEMBER}
|
||||
refetchQueries={[{ query: GET_TEAMS_BY_OWNER }]}
|
||||
>
|
||||
{(deleteTeam, { loading, error, data }) => {
|
||||
let errors
|
||||
let loader
|
||||
if (loading) {
|
||||
loader = (
|
||||
<Typography variant='caption'>Submitting team...</Typography>
|
||||
)
|
||||
}
|
||||
if (error) {
|
||||
errors = error.graphQLErrors.map(({ message }, i) => {
|
||||
const displayMessage = checkGraphQLError(message)
|
||||
console.log('createTeam error:', displayMessage)
|
||||
return (
|
||||
<Typography key={i} variant='caption'>
|
||||
{message}
|
||||
</Typography>
|
||||
)
|
||||
})
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Button
|
||||
size='small'
|
||||
color='primary'
|
||||
className={classes.buttonRight}
|
||||
onClick={this.handleClickOpen}
|
||||
>
|
||||
<PersonAddDisabledIcon /> Remove
|
||||
</Button>
|
||||
<Dialog
|
||||
open={this.state.open}
|
||||
onClose={this.handleClose}
|
||||
aria-labelledby='form-dialog-title'
|
||||
>
|
||||
<div classes={classes.dialogContainer}>
|
||||
<DialogTitle id='form-dialog-title'>
|
||||
Remove Team Member
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography variant='subheading' color='primary'>
|
||||
DANGER - Removing your team cannot be undone
|
||||
</Typography>
|
||||
<Typography variant='subheading'>
|
||||
Are you sure you want to remove this team member?
|
||||
</Typography>
|
||||
{loader}
|
||||
{errors}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleClose} color='primary'>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={e => {
|
||||
this.handleSubmit(
|
||||
e,
|
||||
deleteTeam,
|
||||
teamId,
|
||||
authId
|
||||
)
|
||||
}}
|
||||
color='primary'
|
||||
>
|
||||
Remove Member
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</div>
|
||||
</Dialog>
|
||||
</React.Fragment>
|
||||
)
|
||||
}}
|
||||
</Mutation>
|
||||
)
|
||||
}
|
||||
|
||||
async handleSubmit (e, deleteTeam, teamId, memberId) {
|
||||
e.preventDefault()
|
||||
await deleteTeam({ variables: { teamId, memberId } })
|
||||
this.setState({ open: false })
|
||||
}
|
||||
}
|
||||
|
||||
ManageMemberDelete.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
teamId: PropTypes.string.isRequired,
|
||||
authId: PropTypes.string
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageMemberDelete)
|
||||
@@ -0,0 +1,169 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import { Mutation } from 'react-apollo'
|
||||
|
||||
import Button from '@material-ui/core/Button'
|
||||
import AssignmentIndIcon from '@material-ui/icons/AssignmentInd'
|
||||
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 TextField from '@material-ui/core/TextField'
|
||||
import MenuItem from '@material-ui/core/MenuItem'
|
||||
|
||||
import SET_TEAM_MEMBER_ROLE from '../../../graphql/teams/SetTeamMemberRoleMutation'
|
||||
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
|
||||
import { checkGraphQLError } from '../../../utils/graphql-errors'
|
||||
|
||||
const styles = theme => ({
|
||||
dialogContainer: {
|
||||
display: 'block',
|
||||
margin: '3em',
|
||||
minWidth: 400
|
||||
},
|
||||
buttonRight: {
|
||||
justifyContent: 'flex-end'
|
||||
}
|
||||
})
|
||||
|
||||
const roles = [
|
||||
{ role: 'Admin' },
|
||||
{ role: 'Member' }
|
||||
]
|
||||
|
||||
export class ManageMemberRole extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.handleClickOpen = this.handleClickOpen.bind(this)
|
||||
this.handleClose = this.handleClose.bind(this)
|
||||
this.handleChange = this.handleChange.bind(this)
|
||||
this.handleSubmit = this.handleSubmit.bind(this)
|
||||
|
||||
this.state = {
|
||||
open: false,
|
||||
role: ''
|
||||
}
|
||||
}
|
||||
|
||||
handleClickOpen () {
|
||||
this.setState({ open: true })
|
||||
}
|
||||
|
||||
handleClose () {
|
||||
this.setState({ open: false })
|
||||
}
|
||||
|
||||
handleChange (e) {
|
||||
this.setState({ name: e.target.value })
|
||||
}
|
||||
|
||||
render () {
|
||||
console.log(this.props, this.props.teamId)
|
||||
const { classes, teamId, authId } = this.props
|
||||
return (
|
||||
<Mutation
|
||||
mutation={SET_TEAM_MEMBER_ROLE}
|
||||
refetchQueries={[{ query: GET_TEAMS_BY_OWNER }]}
|
||||
>
|
||||
{(setTeamMemberRole, { loading, error, data }) => {
|
||||
let errors
|
||||
let loader
|
||||
if (loading) {
|
||||
loader = (
|
||||
<Typography variant='caption'>Submitting team...</Typography>
|
||||
)
|
||||
}
|
||||
if (error) {
|
||||
errors = error.graphQLErrors.map(({ message }, i) => {
|
||||
const displayMessage = checkGraphQLError(message)
|
||||
console.log('createTeam error:', displayMessage)
|
||||
return (
|
||||
<Typography key={i} variant='caption'>
|
||||
{message}
|
||||
</Typography>
|
||||
)
|
||||
})
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Button
|
||||
size='small'
|
||||
color='primary'
|
||||
className={classes.buttonRight}
|
||||
onClick={this.handleClickOpen}
|
||||
>
|
||||
<AssignmentIndIcon /> Set Role
|
||||
</Button>
|
||||
<Dialog
|
||||
open={this.state.open}
|
||||
onClose={this.handleClose}
|
||||
aria-labelledby='form-dialog-title'
|
||||
>
|
||||
<div classes={classes.dialogContainer}>
|
||||
<DialogTitle id='form-dialog-title'>
|
||||
Set Team Member Role
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography variant='subheading'>
|
||||
Admin members can approve new team members, send team invitations, and remove team members.
|
||||
</Typography>
|
||||
<TextField
|
||||
select
|
||||
label='Team Role'
|
||||
value={this.state.role}
|
||||
onChange={(e) => this.setState({ role: e.target.value })}
|
||||
fullWidth
|
||||
>
|
||||
{roles.map(role => (
|
||||
<MenuItem key={role.role} value={role.role}>{role.role}</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
{loader}
|
||||
{errors}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleClose} color='primary'>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={e => {
|
||||
this.handleSubmit(
|
||||
e,
|
||||
setTeamMemberRole,
|
||||
teamId,
|
||||
authId
|
||||
)
|
||||
}}
|
||||
color='primary'
|
||||
>
|
||||
Set Member Role
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</div>
|
||||
</Dialog>
|
||||
</React.Fragment>
|
||||
)
|
||||
}}
|
||||
</Mutation>
|
||||
)
|
||||
}
|
||||
|
||||
async handleSubmit (e, setTeamMemberRole, teamId, authId) {
|
||||
e.preventDefault()
|
||||
const role = this.state.role
|
||||
await setTeamMemberRole({ variables: { teamId, memberId: authId, role: role } })
|
||||
this.setState({ open: false })
|
||||
}
|
||||
}
|
||||
|
||||
ManageMemberRole.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
teamId: PropTypes.string.isRequired,
|
||||
authId: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageMemberRole)
|
||||
@@ -0,0 +1,99 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import Button from '@material-ui/core/Button'
|
||||
import HistoryIcon from '@material-ui/icons/History'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import CardActions from '@material-ui/core/CardActions'
|
||||
|
||||
const styles = theme => ({
|
||||
dialogContainer: {
|
||||
display: 'block',
|
||||
margin: '3em',
|
||||
minWidth: 400
|
||||
},
|
||||
buttonRight: {
|
||||
justifyContent: 'flex-end'
|
||||
}
|
||||
})
|
||||
|
||||
export class ManageMemberStatus extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.handleClickOpen = this.handleClickOpen.bind(this)
|
||||
this.handleClose = this.handleClose.bind(this)
|
||||
|
||||
this.state = {
|
||||
open: false,
|
||||
role: ''
|
||||
}
|
||||
}
|
||||
|
||||
handleClickOpen () {
|
||||
this.setState({ open: true })
|
||||
}
|
||||
|
||||
handleClose () {
|
||||
this.setState({ open: false })
|
||||
}
|
||||
|
||||
handleChange (e) {
|
||||
this.setState({ name: e.target.value })
|
||||
}
|
||||
|
||||
render () {
|
||||
console.log(this.props, this.props.status)
|
||||
const { classes, status } = this.props
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
size='small'
|
||||
color='primary'
|
||||
className={this.props.classes.buttonRight}
|
||||
onClick={this.handleClickOpen}
|
||||
>
|
||||
<HistoryIcon /> Status Details
|
||||
</Button>
|
||||
<Dialog
|
||||
open={this.state.open}
|
||||
onClose={this.handleClose}
|
||||
aria-labelledby='form-dialog-title'
|
||||
>
|
||||
<div classes={classes.dialogContainer}>
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<Typography variant='title' id='form-dialog-title'>
|
||||
Member Status Details
|
||||
</Typography>
|
||||
{status !== null && status.map(stat => {
|
||||
return (
|
||||
<Typography variant='title' id='form-dialog-title' key={stat.createdAt}>
|
||||
{stat.status} | {stat.reason} | {stat.createdAt}
|
||||
</Typography>
|
||||
)
|
||||
})}
|
||||
<CardActions>
|
||||
<Button onClick={this.handleClose} color='primary'>
|
||||
Close
|
||||
</Button>
|
||||
</CardActions>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ManageMemberStatus.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
status: PropTypes.array
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageMemberStatus)
|
||||
@@ -0,0 +1,64 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
|
||||
import ManageMemberDelete from './ManageMemberDelete'
|
||||
import ManageMemberRole from './ManageMemberRole'
|
||||
import ManageMemberStatus from './ManageMemberStatus'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
export const ManageMembersItem = ({ classes, member, teamId, authId }) => {
|
||||
console.log('ManageMembersItem', member)
|
||||
let profile = null
|
||||
let email = null
|
||||
let memberStatus = null
|
||||
if (member.member !== null) {
|
||||
profile = member.member
|
||||
}
|
||||
if (member.member === null && member.email !== null) {
|
||||
email = member.email
|
||||
}
|
||||
if (member.status.length > 0) memberStatus = member.status
|
||||
if (profile !== null || email !== null) {
|
||||
return (
|
||||
<Grid container className={classes.memberContainer}>
|
||||
<Grid item xs={4}>
|
||||
<Typography gutterBottom variant='subheading' component='h2' align='left' >
|
||||
{profile !== null ? profile.alias : email}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<Typography color='textSecondary' variant='body2' component='h4' align='left' >
|
||||
{email !== null ? `${memberStatus[memberStatus.length - 1].status} | Sent: ${memberStatus[memberStatus.length - 1].createdAt}` : `${member.role} | Member since: `}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
{ profile !== null && member.role !== 'OWNER' && (
|
||||
<ManageMemberRole teamId={teamId} authId={profile !== null ? profile.authId : null} className={classes.buttonRight} />
|
||||
)}
|
||||
{(email !== null || member.role !== 'OWNER') && (
|
||||
<ManageMemberStatus status={member.status} className={classes.buttonRight} />
|
||||
)}
|
||||
{(email !== null || member.role !== 'OWNER') && (
|
||||
<ManageMemberDelete teamId={teamId} authId={profile !== null ? profile.authId : null} email={email !== null ? email : null} className={classes.buttonRight} />
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<MessageCard message='No Member info found' />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ManageMembersItem.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
member: PropTypes.object.isRequired,
|
||||
teamId: PropTypes.string.isRequired,
|
||||
authId: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default ManageMembersItem
|
||||
@@ -0,0 +1,116 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import CardMedia from '@material-ui/core/CardMedia'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
|
||||
import InviteMemberDialog from './InviteMemberDialog'
|
||||
import ManageMembersItem from './ManageMembersItem'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
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`
|
||||
},
|
||||
buttonRight: {
|
||||
justifyContent: 'flex-end'
|
||||
},
|
||||
card: {
|
||||
display: 'flex',
|
||||
width: '100%'
|
||||
},
|
||||
cardDetails: {
|
||||
display: 'flex',
|
||||
flex: 1
|
||||
},
|
||||
cardContent: {
|
||||
flex: 1
|
||||
},
|
||||
cardMedia: {
|
||||
flex: 1,
|
||||
width: 100,
|
||||
height: 100,
|
||||
maxWidth: 100,
|
||||
justifyContent: 'flex-start'
|
||||
},
|
||||
cardMemberMedia: {
|
||||
flex: 1,
|
||||
width: 36,
|
||||
height: 36,
|
||||
maxWidth: 36,
|
||||
justifyContent: 'flex-start'
|
||||
},
|
||||
memberContainer: {
|
||||
margin: 10,
|
||||
padding: 6
|
||||
}
|
||||
})
|
||||
|
||||
export const ManageMembersTeamItem = ({ classes, team, authId }) => {
|
||||
console.log('ManageMembersItem', 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'
|
||||
}
|
||||
if (team.members.length > 0) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Grid item xs={12} key={team.id}>
|
||||
<Card className={classes.card}>
|
||||
<div className={classes.cardDetails}>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Grid container>
|
||||
<Grid item xs={2}>
|
||||
<CardMedia
|
||||
className={classes.cardMedia}
|
||||
image={avatar}
|
||||
title={team.name}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<Typography gutterBottom variant='headline' component='h2'>
|
||||
{team.name}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={1}>
|
||||
<InviteMemberDialog teamId={team.id} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
{team.members.length > 0 && team.members.map((member, index) => (
|
||||
<ManageMembersItem
|
||||
member={member}
|
||||
teamId={team.id}
|
||||
authId={authId}
|
||||
classes={classes}
|
||||
key={`${team.id}-${index}`}
|
||||
/>
|
||||
))}
|
||||
</CardContent>
|
||||
</div>
|
||||
</Card>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
)
|
||||
} else {
|
||||
return <MessageCard message='No Member info found' />
|
||||
}
|
||||
}
|
||||
|
||||
ManageMembersTeamItem.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
team: PropTypes.object.isRequired,
|
||||
authId: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageMembersTeamItem)
|
||||
@@ -123,8 +123,7 @@ export class ManageTeamDelete extends Component {
|
||||
this.handleSubmit(
|
||||
e,
|
||||
deleteTeam,
|
||||
this.props.slug,
|
||||
authId
|
||||
this.props.slug
|
||||
)
|
||||
}}
|
||||
color='primary'
|
||||
@@ -141,9 +140,9 @@ export class ManageTeamDelete extends Component {
|
||||
)
|
||||
}
|
||||
|
||||
async handleSubmit (e, deleteTeam, slug, authId) {
|
||||
async handleSubmit (e, deleteTeam, slug) {
|
||||
e.preventDefault()
|
||||
await deleteTeam({ variables: { slug, owner: authId } })
|
||||
await deleteTeam({ variables: { slug } })
|
||||
this.setState({ open: false })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,15 +67,15 @@ export class ManageTeamDetails extends Component {
|
||||
const { name, members, profile, createdAt } = this.props.team
|
||||
let avatar
|
||||
let banner
|
||||
if (profile.avatar !== undefined && profile.avatar !== 'a') {
|
||||
if (profile.avatar !== undefined && profile.avatar !== null) {
|
||||
avatar = 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%3EAvatar%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
|
||||
avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
}
|
||||
if (profile.banner !== undefined && profile.banner !== 'a') {
|
||||
if (profile.banner !== undefined && profile.banner !== null) {
|
||||
banner = profile.banner
|
||||
} else {
|
||||
banner = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22800%22%20height%3D%22200%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Asvg%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23banner_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%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%3E%3Ctitle%3EBanner%20Placeholder%3C%2Ftitle%3E%3Crect%20stroke%3D%22null%22%20id%3D%22svg_1%22%20fill%3D%22%2355595c%22%20height%3D%22200%22%20width%3D%22800%22%2F%3E%3Cg%20stroke%3D%22null%22%20id%3D%22banner_164edaf95ee%22%3E%3Ctext%20stroke%3D%22null%22%20id%3D%22svg_3%22%20y%3D%22106.5%22%20x%3D%22367.73438%22%3EBanner%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
|
||||
banner = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-banner-default.png'
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -127,10 +127,11 @@ export class ManageTeamEdit extends Component {
|
||||
let avatar = null
|
||||
if (this.state.avatar !== null) avatar = this.state.avatar
|
||||
if (team.profile !== null && team.profile.avatar !== undefined && team.profile.avatar !== null) avatar = team.profile.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'
|
||||
let banner = null
|
||||
if (this.state.banner !== null) banner = this.state.banner
|
||||
if (team.profile !== null && team.profile.banner !== undefined && team.profile.banner !== null) banner = team.profile.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'
|
||||
console.log('team images: ', avatar, banner)
|
||||
|
||||
if (loading || data === undefined) {
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Query } from 'react-apollo'
|
||||
import { withStateHandlers, lifecycle, compose } from 'recompose'
|
||||
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { isDefined, isString } from '../../../utils/js-helpers'
|
||||
import { getItem } from '../../../utils/local-storage'
|
||||
|
||||
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
|
||||
import ManageMembersTeamItem from './ManageMembersTeamItem'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
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`
|
||||
},
|
||||
buttonRight: {
|
||||
justifyContent: 'flex-end'
|
||||
},
|
||||
card: {
|
||||
display: 'flex',
|
||||
width: '100%'
|
||||
},
|
||||
cardDetails: {
|
||||
display: 'flex',
|
||||
flex: 1
|
||||
},
|
||||
cardContent: {
|
||||
flex: 1
|
||||
},
|
||||
cardMedia: {
|
||||
flex: 1,
|
||||
width: 100,
|
||||
height: 100,
|
||||
maxWidth: 100,
|
||||
justifyContent: 'flex-start'
|
||||
}
|
||||
})
|
||||
|
||||
export const ManageTeamMembersList = ({ classes, user = null }) => {
|
||||
let owner
|
||||
let authId = null
|
||||
console.log('ManageTeamsList: ', user)
|
||||
if (user !== null && isString(user)) {
|
||||
owner = JSON.parse(user)
|
||||
if (isDefined(owner.authId)) authId = owner.authId
|
||||
}
|
||||
console.log('ManageTeamsList 2: ', owner, authId)
|
||||
if (authId === undefined || authId === null) {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid>
|
||||
<MessageCard message='Loading...' />
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Query
|
||||
query={GET_TEAMS_BY_OWNER}
|
||||
variables={{ authId }}
|
||||
fetchPolicy='network-only'
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
console.log('GET_TEAMS_BY_OWNER: ', loading, error, data)
|
||||
let errors = null
|
||||
if (error) {
|
||||
errors = error.graphQLErrors.map(({ message }, i) => {
|
||||
return <MessageCard message={message} />
|
||||
})
|
||||
}
|
||||
if (!loading && !error) {
|
||||
if (data.teamsByOwner.length > 0) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Grid container spacing={40}>
|
||||
{!loading &&
|
||||
data.teamsByOwner.map(team => (
|
||||
<ManageMembersTeamItem key={team.id} team={team} authId={authId} />
|
||||
))
|
||||
}
|
||||
{errors}
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid item xs={10}>
|
||||
<MessageCard message='You don’t have any members. Somethings not right...' />
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Grid item xs={12}>
|
||||
<MessageCard message='Loading...' />
|
||||
{errors !== null && <MessageCard message={errors} />}
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
}}
|
||||
</Query>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ManageTeamMembersList.propTypes = {
|
||||
user: PropTypes.any,
|
||||
classes: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
const getUserOnMount = lifecycle({
|
||||
componentDidMount () {
|
||||
getItem('user').then(user => {
|
||||
this.setState({ user })
|
||||
}) // Set user to state
|
||||
}
|
||||
})
|
||||
|
||||
const mapStateToProps = withStateHandlers(() => ({ user: null }), {
|
||||
user: ({ user }) => () => ({ user })
|
||||
})
|
||||
|
||||
const ManageTeamMembersListAuthId = compose(
|
||||
mapStateToProps,
|
||||
getUserOnMount
|
||||
)(ManageTeamMembersList)
|
||||
|
||||
export default withStyles(styles)(ManageTeamMembersListAuthId)
|
||||
@@ -18,7 +18,7 @@ export const ManageTeamsItem = ({ classes, team, authId }) => {
|
||||
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 = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
}
|
||||
return (
|
||||
<Grid item xs={12}>
|
||||
@@ -39,7 +39,7 @@ export const ManageTeamsItem = ({ classes, team, authId }) => {
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<ManageTeamDetails team={team} />
|
||||
<ManageTeamEdit slug={team.slug} authId={authId} team={team} />
|
||||
<ManageTeamEdit slug={team.slug} team={team} authId={authId} />
|
||||
<ManageTeamDelete slug={team.slug} authId={authId} />
|
||||
</CardActions>
|
||||
</div>
|
||||
|
||||
@@ -68,8 +68,8 @@ export const ManageTeamsList = ({ classes, user = null }) => {
|
||||
return (
|
||||
<Query
|
||||
query={GET_TEAMS_BY_OWNER}
|
||||
fetchPolicy='network-only'
|
||||
variables={{ authId }}
|
||||
fetchPolicy='network-only'
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
console.log('GET_TEAMS_BY_OWNER: ', loading, error, data)
|
||||
@@ -94,9 +94,6 @@ export const ManageTeamsList = ({ classes, user = null }) => {
|
||||
authId={authId}
|
||||
/>
|
||||
))}
|
||||
<MessageCard message='Create another team'>
|
||||
<CreateTeamDialog authId={authId} />
|
||||
</MessageCard>
|
||||
{errors}
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -5,6 +5,7 @@ import Home from './home'
|
||||
import About from './about'
|
||||
import Dashboard from './dashboard'
|
||||
import Teams from './teams'
|
||||
import AcceptTeamInvite from './teams/AcceptTeamInvite'
|
||||
|
||||
import { theme, globalStyles } from './theme'
|
||||
|
||||
@@ -12,6 +13,7 @@ export {
|
||||
NavBar,
|
||||
Footer,
|
||||
Callback,
|
||||
AcceptTeamInvite,
|
||||
Home,
|
||||
About,
|
||||
Dashboard,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import queryString from 'query-string'
|
||||
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
class AcceptTeamInvite extends Component {
|
||||
render () {
|
||||
const { location, auth } = this.props
|
||||
const param = queryString.parse(location.search)
|
||||
console.log(param, auth)
|
||||
|
||||
if (auth === undefined) {
|
||||
return <MessageCard message='Loading...' />
|
||||
}
|
||||
|
||||
auth.loginInvite(param.token)
|
||||
|
||||
return (
|
||||
<MessageCard message='Verifying Invitation' />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AcceptTeamInvite.propTypes = {
|
||||
location: PropTypes.object.isRequired,
|
||||
auth: PropTypes.object
|
||||
}
|
||||
|
||||
export default AcceptTeamInvite
|
||||
@@ -12,6 +12,7 @@ const Dotenv = require('dotenv-webpack')
|
||||
|
||||
module.exports = merge(commonConfig, {
|
||||
mode: 'production',
|
||||
devtool: 'inline-sourcemap',
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../../build'),
|
||||
filename: 'script.js'
|
||||
|
||||
Reference in new issue
Block a user