Merge branch 'master' into feature/member-mangement
This commit is contained in:
commit
4fe572411e
44 files changed
+1307
-919
No files matched your search
@@ -0,0 +1,51 @@
|
||||
# Contributing
|
||||
|
||||
We are thrilled you are interested in contributing to the this module. Your help may be essential to the project's success and we want you in!
|
||||
|
||||
Advanced Algos LTD is a startup, currently at a very early stage. Although this module is not open source software yet, we do welcome contributions from the community.
|
||||
|
||||
Contributions are deemed _work for hire_ and --as such-- are compensated on a case by case basis, with ALGO tokens. Contributors agree to provide an express grant of patent rights for their contributions. Our Balanced Contributor Intellectual Property Agreement is a direct implementation of GitHub's [Balanced Employee Intellectual Property Agreement 1.0.1](https://github.com/github/balanced-employee-ip-agreement/blob/master/Balanced_Employee_IP_Agreement.md).
|
||||
|
||||
# Balanced Contributor Intellectual Property Agreement 1.0.1
|
||||
|
||||
This BALANCED CONTRIBUTOR INTELLECTUAL PROPERTY AGREEMENT is between person named below and Advanced Algos ("Company").
|
||||
|
||||
**What is this?** This is the Company's Intellectual Property Agreement ("Agreement"). If you've worked in the technology space before, there's a good chance that you've run across one or more of these in the past. This document is the official, entire and exclusive agreement on what intellectual property ("IP") is yours, and what belongs to the Company.
|
||||
|
||||
**Why is this?** The Company needs to be clear on what IP it owns and has rights to. Its customers, contributors, and investors depend on the Company having the legal rights to the products and services it is providing so that the Company can continue operating and doing business.
|
||||
|
||||
The Company also believes that it's important to be clear on what it doesn't own. The Company doesn't want you looking over your shoulder every time you work on something personal or worrying that the Company will someday seize your open source non-lethal mousetrap simulation software. In other words, the Company isn't interested in appropriating your personal projects.
|
||||
|
||||
**Read this.** Please read this document and be sure you understand it before you sign it. Due to legal risk and corporate obligations, the Company cannot, by and large, negotiate its terms. If you feel you have a particular circumstance that keeps you from signing, please let the Company's legal department ("Legal") know. And, of course, you're always free and encouraged to get your own legal counsel to explain anything you're not clear on.
|
||||
|
||||
Cool? Then, by signing this Agreement, and as a condition of your contribution, you agree to the following:
|
||||
|
||||
1. **What the Company owns.** The Company owns any IP ("Company IP") that you create, or help create _as its contributor or contractor_, but only if it meets one or more of these additional conditions: The IP was (i) related to an existing or prospective Company product or service at the time you developed, invented, or created it, (ii) developed for use by the Company, or (iii) developed or promoted with existing Company IP or with the Company's endorsement. You hereby grant and assign, and will grant and assign, to the Company all rights and interests in all Company IP.
|
||||
|
||||
"Company IP" includes concepts, designs, developments, discoveries, ideas, improvements, inventions, trade secrets, trademarks, and works of authorship.
|
||||
|
||||
2. **What the Company doesn't own.** If you create IP that doesn't fit into one of the categories listed above, the Company doesn't own it. In other words, the Company doesn't own concepts, designs, developments, discoveries, ideas, improvements, inventions, trade secrets, trademarks, or works of authorship that you develop, invent, or create that do not meet any of the conditions in Section 1. This is true regardless of the computer you use to develop your IP, including the one furnished to you by the Company.
|
||||
|
||||
3. **Contribution of your IP to Company projects.** If you include your own IP – such as IP you created prior to working for the Company – into a Company product or service, it's still yours, of course, but you grant the Company a non-exclusive, irrevocable, fully paid-up, royalty-free, perpetual, sublicensable, transferable, worldwide license to use it without restriction in any way or implementation, in modified form, or as is, by itself, or incorporated into another product or service ("License"). If you include your name in any project over which the Company would have rights under this Agreement, such as in a copyright notice or a comment in code or documentation, then the License covers the rights associated with that use of your name as well.
|
||||
|
||||
4. **Your contributions to non-Company projects.** The Company recognizes that you may be engaged in work that requires you to submit IP to entities other than the Company, such as open source projects used by the Company. Please make sure that Legal is aware of what you're working on so that Legal can help with any licensing issues. If any project asks you to sign a contribution agreement, you should check with Legal before doing so. These agreements may be legally binding on the Company and so should be run through Legal first.
|
||||
|
||||
5. **Works made for hire.** All Company IP that you are involved with or create as part of your work for the Company is [work made for hire](http://www.copyright.gov/circs/circ09.pdf) under copyright law and compensated by your regular salary or pay.
|
||||
|
||||
6. **No conflicts.** You agree that you don't have any outstanding agreements or obligations that conflict with those in this Agreement, and that you won't enter into conflicting agreements in the future.
|
||||
|
||||
7. **IP protection.** The Company might someday need to show the work that went into the development of IP that it uses or has used, or to make government filings to establish that it owns the IP or has rights over it. To help in those situations, you agree not to destroy any records you maintain relating to the development of any Company IP or IP under License (together, "All IP"), and, if the Company asks, to provide those records to the Company. You agree to help the Company secure and defend its rights in All IP, including after you leave the Company. For your help the Company will compensate you at a reasonable rate. If the Company is unable to secure your help, you authorize the Company to act on your behalf (as your agent and attorney-in-fact) in securing all rights related to All IP.
|
||||
|
||||
8. **Confidentiality.** As an contributor or contractor of the Company, you will have access to sensitive confidential information that is important to the Company's business. You are responsible for keeping this information confidential, including after you end your work for the Company.
|
||||
|
||||
"Confidential Information" includes non-public technical details about our products or services, financial information, business strategies and forecasts, customer data, or any other information, data or know-how that is valuable to the Company because it is not publicly known.
|
||||
|
||||
The Company's Confidential Information is sensitive and we expect that you'll treat it as such. You agree to only use the Company's Confidential Information for the purpose of performing your job and for the benefit of the Company. You will do your best to keep Confidential Information secret. If you are not sure if something is Confidential Information, you should assume that it is, until you can confirm otherwise.
|
||||
|
||||
|
||||
Print Name: _____________
|
||||
|
||||
Sign: ________________
|
||||
|
||||
Date: ________________
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
© Copyright 2018 Advanced Algos LTD.
|
||||
|
||||
|
||||
LICENSE NOTICE
|
||||
|
||||
Advanced Algos LTD. is a startup, currently at a very early stage. Because certain aspects of
|
||||
the business are still not clearly defined, we have chosen to --temporarily-- grant a
|
||||
restrictive license for the use of this module, until those business aspects are clarified
|
||||
and a proper open source license can be granted.
|
||||
|
||||
Advanced Algos LTD. is publishing the code of this software for several reasons. However,
|
||||
it shall not be considered free software yet. Advanced Algos LTD. is a for-profit company
|
||||
in the crypto space and this module is still proprietary software.
|
||||
|
||||
The reasons for opening up the code of this module at this stage are the following:
|
||||
|
||||
* We believe that transparency is paramount to achieving our goals, so we want everyone
|
||||
to be able to understand what this module does and how. Opening up the code of this module allows
|
||||
anyone to take a close look.
|
||||
|
||||
* We welcome contributions from the community. Contributions are compensated on a case
|
||||
by case basis with ALGO tokens. Contributions are deemed _work for hire_ and contributors
|
||||
agree to provide an express grant of patent rights for their contributions.
|
||||
|
||||
|
||||
LICENSE WORDING
|
||||
|
||||
Advanced Algos LTD. grants a limited license for the following uses:
|
||||
|
||||
1. CODE REVIEW AND AUDITS. You are granted permission to clone the AACoud repository to analyze,
|
||||
review or audit the code.
|
||||
|
||||
2. COLLABORATING WITH ADVANCED ALGOS LTD. You are granted permission to fork the this module repository
|
||||
with the sole purpose of correcting bugs and developing functionality in agreement with
|
||||
Advanced Algos LTD. Before your contributions are merged into our repository, you will be requested
|
||||
to sign a Contributors Work for Hire Agreement.
|
||||
|
||||
PLEASE SEE CONTRIBUTING.MD FOR MORE DETAILS ON THE IMPLICATIONS SURROUNDING YOUR CONTRIBUTIONS TO THIS REPOSITORY.
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/.env
|
||||
/.env.prod
|
||||
/database/.env
|
||||
/database/docker-compose.prisma.prod.yml
|
||||
/docker-compose.prisma.prod.yml
|
||||
|
||||
@@ -96,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,11 +1,8 @@
|
||||
version: '3'
|
||||
services:
|
||||
api:
|
||||
image: aateamapi-dev:v1
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile
|
||||
env_file: ./.env
|
||||
image: advancedalgosteamsmodule/teammodule-api:v2
|
||||
env_file: ./.env.prod
|
||||
container_name: aateamapi
|
||||
tty: true
|
||||
stdin_open: true
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -67,6 +67,71 @@ const sendTeamMemberInvite = function(email, team) {
|
||||
return sendVerify
|
||||
}
|
||||
|
||||
const sendTeamCreateConfirmation = function(email, teamName, botName, sessionToken) {
|
||||
const dev = process.env.NODE_ENV === 'development' ? true : false
|
||||
console.log('sendTeamMemberInvite', email, team)
|
||||
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: {
|
||||
"aateamdeveloplink": "https://develop.advancedalgos.net/index.html?" + sessionToken,
|
||||
"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
|
||||
@@ -84,4 +149,4 @@ const verifyInviteToken = async function(token) {
|
||||
return verifiedToken
|
||||
}
|
||||
|
||||
module.exports = { sendTeamMemberInvite, verifyInviteToken }
|
||||
module.exports = { sendTeamMemberInvite, sendTeamCreateConfirmation, verifyInviteToken }
|
||||
@@ -1,5 +1,5 @@
|
||||
# source: http://localhost:4466
|
||||
# timestamp: Thu Sep 27 2018 23:28:16 GMT-0700 (Pacific Daylight Time)
|
||||
# timestamp: Fri Oct 05 2018 13:16:40 GMT-0700 (Pacific Daylight Time)
|
||||
|
||||
type AggregateFBStatus {
|
||||
count: Int!
|
||||
@@ -249,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!
|
||||
@@ -268,6 +271,9 @@ type FinancialBeingsConnection {
|
||||
input FinancialBeingsCreateInput {
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String!
|
||||
slug: String!
|
||||
avatar: String
|
||||
team: TeamCreateOneWithoutFbInput
|
||||
status: FBStatusCreateManyInput
|
||||
}
|
||||
@@ -280,6 +286,9 @@ input FinancialBeingsCreateManyWithoutTeamInput {
|
||||
input FinancialBeingsCreateWithoutTeamInput {
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String!
|
||||
slug: String!
|
||||
avatar: String
|
||||
status: FBStatusCreateManyInput
|
||||
}
|
||||
|
||||
@@ -299,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
|
||||
@@ -309,6 +324,9 @@ type FinancialBeingsPreviousValues {
|
||||
id: ID!
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String!
|
||||
slug: String!
|
||||
avatar: String
|
||||
updatedAt: DateTime!
|
||||
createdAt: DateTime!
|
||||
}
|
||||
@@ -355,6 +373,9 @@ input FinancialBeingsSubscriptionWhereInput {
|
||||
input FinancialBeingsUpdateInput {
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String
|
||||
slug: String
|
||||
avatar: String
|
||||
team: TeamUpdateOneWithoutFbInput
|
||||
status: FBStatusUpdateManyInput
|
||||
}
|
||||
@@ -371,6 +392,9 @@ input FinancialBeingsUpdateManyWithoutTeamInput {
|
||||
input FinancialBeingsUpdateWithoutTeamDataInput {
|
||||
type: FBType
|
||||
kind: FBKind
|
||||
name: String
|
||||
slug: String
|
||||
avatar: String
|
||||
status: FBStatusUpdateManyInput
|
||||
}
|
||||
|
||||
@@ -454,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."""
|
||||
|
||||
@@ -15,6 +15,7 @@ const TEAMS_CONNECTIONS_FRAGMENT = gql`{
|
||||
createdAt
|
||||
profile {
|
||||
avatar
|
||||
banner
|
||||
description
|
||||
motto
|
||||
updatedAt
|
||||
@@ -33,6 +34,18 @@ const TEAMS_CONNECTIONS_FRAGMENT = gql`{
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
fb {
|
||||
id
|
||||
name
|
||||
slug
|
||||
avatar
|
||||
kind
|
||||
status {
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
@@ -31,6 +31,18 @@ const TEAMS_FRAGMENT = gql`{
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
fb {
|
||||
id
|
||||
name
|
||||
slug
|
||||
avatar
|
||||
kind
|
||||
status {
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
module.exports = TEAMS_FRAGMENT
|
||||
+69
-86
@@ -8,34 +8,20 @@ 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')
|
||||
const { validateIdToken } = require('./auth/validateIdToken')
|
||||
const { directiveResolvers } = require('./auth/authDirectives')
|
||||
|
||||
const { sendTeamMemberInvite, verifyInviteToken } = require('./email/sendgrid')
|
||||
|
||||
const {
|
||||
createStoragePipline,
|
||||
createServiceURL,
|
||||
listContainers,
|
||||
createContainer,
|
||||
createBlob,
|
||||
uploadBlob,
|
||||
downloadBlob,
|
||||
deleteBlob,
|
||||
deleteContainer
|
||||
} = require('./storage/azure')
|
||||
//var azure = require('azure-storage')
|
||||
const Azure = require("@azure/storage-blob")
|
||||
const { createSASQueryURL } = require('./storage/azure')
|
||||
const azureAccount = process.env.AZURE_STORAGE_ACCOUNT
|
||||
const azureKey = process.env.AZURE_STORAGE_ACCESS_KEY
|
||||
const azureStorageUrl = process.env.AZURE_STORAGE_URL
|
||||
|
||||
var debug = require('debug')('http')
|
||||
, http = require('http')
|
||||
, name = 'My App';
|
||||
const { sendTeamMemberInvite, sendTeamCreateConfirmation, verifyInviteToken } = require('./email/sendgrid')
|
||||
|
||||
const TEAMS_FRAGMENT = require('./graphql/TeamsFragment')
|
||||
const TEAMS_CONNECTIONS_FRAGMENT = require('./graphql/TeamsConnectionsFragment')
|
||||
@@ -93,9 +79,8 @@ const resolvers = {
|
||||
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, args, ctx, info) {
|
||||
const authId = ctx.request.user.sub
|
||||
return ctx.db.query.teams({where: { owner: authId }, orderBy:'updatedAt_DESC'}, TEAMS_FRAGMENT)
|
||||
async teamsByOwner(parent, { ownerId }, ctx, info) {
|
||||
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
|
||||
@@ -136,6 +121,16 @@ const resolvers = {
|
||||
}
|
||||
return member
|
||||
},
|
||||
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
|
||||
@@ -154,16 +149,52 @@ const resolvers = {
|
||||
}
|
||||
return team
|
||||
},
|
||||
async createTeam(parent, { name, slug }, ctx, info) {
|
||||
async createTeam(parent, { name, slug, botName, botSlug }, ctx, info) {
|
||||
console.log('createTeam ctx:', ctx.request.user)
|
||||
const authId = ctx.request.user.sub
|
||||
return ctx.db.mutation.createTeam({ data: { name: name, slug: slug, owner: authId, members: { create: { member:{ connect:{ authId: authId} }, role: 'OWNER' } }, profile:{create:{avatar:"a"} } } }, TEAMS_FRAGMENT)
|
||||
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`)
|
||||
|
||||
console.log('getUserModuleUserId: ', await getUserModuleUser.data)
|
||||
|
||||
const alias = await getUserModuleUser.data.data.userByAuthId.alias
|
||||
const email = await 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'
|
||||
console.log('getUserModuleUserId: ', alias, email)
|
||||
/*
|
||||
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
|
||||
})
|
||||
*/
|
||||
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)
|
||||
|
||||
|
||||
/* update session token on user module
|
||||
const updateUserSession = await axios.post('https://users-api.advancedalgos.net/graphql', {
|
||||
query: 'mutation { language }'
|
||||
})
|
||||
*/
|
||||
|
||||
sendTeamCreateConfirmation(email, name, botName, sessionToken)
|
||||
|
||||
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, { teamId, avatar}, ctx, info) {
|
||||
return ctx.db.mutation.updateTeam({data:{profile: {update: {avatar: avatar}}}, where:{slug: teamId}}, info)
|
||||
.catch((err) => {
|
||||
console.log('createTeam error: ', err)
|
||||
return err
|
||||
@@ -179,66 +210,9 @@ const resolvers = {
|
||||
})
|
||||
},
|
||||
async getAzureSAS(parent, { teamSlug }, ctx, info) {
|
||||
// Create start and expiry times
|
||||
let today = new Date()
|
||||
let week = new Date()
|
||||
week.setDate(today.getDate() + 7)
|
||||
// Create SharedKeyCredential and attach to pipline
|
||||
const SKC = new Azure.SharedKeyCredential(azureAccount, azureKey)
|
||||
const pipeline = Azure.StorageURL.newPipeline(SKC)
|
||||
// Create container URL
|
||||
const serviceURL = new Azure.ServiceURL(azureStorageUrl, pipeline)
|
||||
const containerName = teamSlug
|
||||
const containerURL = Azure.ContainerURL.fromServiceURL(serviceURL, containerName)
|
||||
|
||||
let marker
|
||||
let containerCheck = null
|
||||
do {
|
||||
const listContainersResponse = await serviceURL.listContainersSegment(
|
||||
Azure.Aborter.None,
|
||||
marker,
|
||||
)
|
||||
console.log(`ContainerCheck marker: `, listContainersResponse)
|
||||
marker = listContainersResponse.marker;
|
||||
for (const container of listContainersResponse.containerItems) {
|
||||
console.log(`ContainerCheck: ${container.name} | ${containerName} | ${marker}`)
|
||||
if(container.name === containerName){
|
||||
containerCheck = container.name
|
||||
}
|
||||
}
|
||||
} while (marker)
|
||||
let newContainer
|
||||
if(containerCheck === null){
|
||||
newContainer = await containerURL.create(Azure.Aborter.None, { access: 'blob' })
|
||||
}
|
||||
console.log('getAzureSAS container: ', containerURL, containerCheck, newContainer)
|
||||
|
||||
// Set permissions for service, resource types and containers
|
||||
const SASServicePerms = Azure.AccountSASServices.parse('b')
|
||||
const SASResourceTypes = Azure.AccountSASResourceTypes.parse('co')
|
||||
const SASContainerPerms = Azure.ContainerSASPermissions.parse('rwl')
|
||||
// Generate SAS url
|
||||
const SASQueryParameters = Azure.generateAccountSASQueryParameters(
|
||||
{
|
||||
version: '2017-11-09',
|
||||
permissions: SASContainerPerms,
|
||||
startTime: today,
|
||||
expiryTime: week,
|
||||
protocol: 'https',
|
||||
services: SASServicePerms,
|
||||
resourceTypes: SASResourceTypes
|
||||
}, SKC )
|
||||
return SASQueryParameters
|
||||
},
|
||||
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
|
||||
const SASUrl = createSASQueryURL(teamSlug)
|
||||
console.log('createSASQueryURL: ', SASUrl)
|
||||
return SASUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -283,13 +257,22 @@ server.express.use(
|
||||
|
||||
server.express.post(server.options.endpoint, (req, res, done) => getUser(req, res, done, db))
|
||||
|
||||
const whitelist = [
|
||||
let whitelist = [
|
||||
'http://localhost:3000',
|
||||
'http://localhost:3001',
|
||||
'http://localhost:3002',
|
||||
'http://localhost:4000',
|
||||
'http://localhost:4002'
|
||||
'http://localhost:4002',
|
||||
'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'
|
||||
]
|
||||
|
||||
const corsOptionsDelegate = (req, callback) => {
|
||||
var corsOptions
|
||||
if (whitelist.indexOf(req.header('Origin')) !== -1) {
|
||||
|
||||
@@ -11,7 +11,7 @@ type Query {
|
||||
teamByName(name: String!): Team
|
||||
teamById(teamId: String!): Team
|
||||
teamWithRole(teamId: String!, role: String!): Team
|
||||
teamsByOwner: [Team!]! @isAuthenticated
|
||||
teamsByOwner(ownerId: String!): [Team!]! @isAuthenticated
|
||||
teamsByRole: [Team!]! @isAuthenticated
|
||||
owner: Member @isAuthenticated
|
||||
currentMember: Member @isAuthenticated
|
||||
@@ -21,8 +21,9 @@ type Query {
|
||||
type Mutation {
|
||||
authenticate(idToken: String!): Member
|
||||
verifyTeamInvite(token: String!): TeamMembers
|
||||
createTeam(name: String!, slug: String!): Team @isAuthenticated
|
||||
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(teamId: String!, avatar: String): FinancialBeings @isAuthenticated
|
||||
deleteTeam(slug: String!): Team @isAuthenticated @isOwner(type: "Team")
|
||||
getAzureSAS(teamSlug: String!):String
|
||||
sendMemberInviteSG(email: String!, teamId: String!): String
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
const Azure = require('@azure/storage-blob')
|
||||
const Azure = require("@azure/storage-blob")
|
||||
const azureAccount = process.env.AZURE_STORAGE_ACCOUNT
|
||||
const azureKey = process.env.AZURE_STORAGE_ACCESS_KEY
|
||||
const azureStorageUrl = process.env.AZURE_STORAGE_URL
|
||||
|
||||
/* Create Azure Storage pipeline
|
||||
* @accountName: Azure Blob Storage account name (required) - Environment variable
|
||||
* @accountKey: Azure Blob Storage storage key (required) - Environment variable
|
||||
*/
|
||||
const createStoragePipline = async (accountNAme, accountKey) => {
|
||||
const createStoragePipline = async (accountName, accountKey) => {
|
||||
return Azure.StorageURL.newPipeline(
|
||||
new Azure.SharedKeyCredential(accountName, accountKey)
|
||||
)
|
||||
@@ -120,6 +123,60 @@ const deleteContainer = async (containerURL) => {
|
||||
return true
|
||||
}
|
||||
|
||||
const createSASQueryURL = async (containerName) => {
|
||||
let today = new Date()
|
||||
let week = new Date()
|
||||
week.setDate(today.getDate() + 7)
|
||||
// Create SharedKeyCredential and attach to pipline
|
||||
const SKC = new Azure.SharedKeyCredential(azureAccount, azureKey)
|
||||
const pipeline = Azure.StorageURL.newPipeline(SKC)
|
||||
// Create container URL
|
||||
const serviceURL = new Azure.ServiceURL(azureStorageUrl, pipeline)
|
||||
const containerURL = Azure.ContainerURL.fromServiceURL(serviceURL, containerName)
|
||||
|
||||
//list container and check if already exists.
|
||||
let marker
|
||||
let containerCheck = null
|
||||
do {
|
||||
const listContainersResponse = await serviceURL.listContainersSegment(
|
||||
Azure.Aborter.None,
|
||||
marker,
|
||||
)
|
||||
// console.log(`ContainerCheck marker: `, listContainersResponse)
|
||||
marker = listContainersResponse.marker;
|
||||
for (const container of listContainersResponse.containerItems) {
|
||||
// console.log(`ContainerCheck: ${container.name} | ${containerName} | ${marker}`)
|
||||
if(container.name === containerName){
|
||||
containerCheck = container.name
|
||||
}
|
||||
}
|
||||
} while (marker)
|
||||
|
||||
// if container doesn't exist, create one
|
||||
let newContainer
|
||||
if(containerCheck === null){
|
||||
newContainer = await containerURL.create(Azure.Aborter.None, { access: 'blob' })
|
||||
}
|
||||
console.log('createSASQueryURL container: ', containerURL, containerCheck, newContainer)
|
||||
|
||||
// Set permissions for service, resource types and containers
|
||||
const SASContainerPerms = await Azure.AccountSASPermissions.parse('rwlacu')
|
||||
const SASServicePerms = await Azure.AccountSASServices.parse('b')
|
||||
const SASResourceTypes = await Azure.AccountSASResourceTypes.parse('co')
|
||||
console.log('createSASQueryURL permissions: ', SASServicePerms, SASResourceTypes, SASContainerPerms)
|
||||
// Generate SAS url
|
||||
const SASQueryParameters = await Azure.generateBlobSASQueryParameters(
|
||||
{
|
||||
version: '2017-11-09',
|
||||
protocol: 'https,http',
|
||||
expiryTime: week,
|
||||
permissions: 'rwlac',
|
||||
containerName: containerName
|
||||
}, SKC )
|
||||
console.log('createSASQueryURL SASQueryParameters: ', containerURL.url, SASQueryParameters)
|
||||
return SASQueryParameters
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createStoragePipline,
|
||||
createServiceURL,
|
||||
@@ -129,5 +186,6 @@ module.exports = {
|
||||
uploadBlob,
|
||||
downloadBlob,
|
||||
deleteBlob,
|
||||
deleteContainer
|
||||
deleteContainer,
|
||||
createSASQueryURL
|
||||
}
|
||||
@@ -56,6 +56,7 @@ typings/
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.prod
|
||||
|
||||
# Build folder js files
|
||||
build/
|
||||
|
||||
Generated
+311
-208
@@ -4,6 +4,133 @@
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@advancedalgos/web-components": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@advancedalgos/web-components/-/web-components-0.0.5.tgz",
|
||||
"integrity": "sha512-mgaS2AwtVcbP0W8/Rk95TNFTrDmp21rDmoqrO177WGLCcTH5n3rHisQtrdVaEvLiUGoZ/8us/GeclljVJP1edw==",
|
||||
"requires": {
|
||||
"@azure/storage-blob": "^10.1.0-preview",
|
||||
"@material-ui/core": "^3.0.3",
|
||||
"@material-ui/icons": "^3.0.1",
|
||||
"apollo-client": "^2.4.2",
|
||||
"blob-util": "^2.0.2",
|
||||
"browser-image-resizer": "^1.2.0",
|
||||
"graphql": "^14.0.2",
|
||||
"graphql-tag": "^2.9.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-apollo": "^2.1.11",
|
||||
"react-dropzone": "^5.1.0",
|
||||
"react-image-crop": "^5.0.0",
|
||||
"react-image-cropper": "^1.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/storage-blob": {
|
||||
"version": "10.1.0-preview",
|
||||
"resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-10.1.0-preview.tgz",
|
||||
"integrity": "sha512-vKY4dF8VCRCOOQ03Z1ResyjZbWg4jPOnQtRtlSEKE6a7WwFE3EuIbhE7OQfEihuNYyE+XWLkTjrHxeHDFx1hFg==",
|
||||
"requires": {
|
||||
"events": "3.0.0",
|
||||
"ms-rest-js": "0.22.425",
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "9.6.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.34.tgz",
|
||||
"integrity": "sha512-PzJpSs2afoYqBA4yLBgaKUdZRk8+1yvkxcUBW6958h4vYOC+pc4k4C+QmQ6AO5Pt7uA4EIIboFog6YNCuITD0g=="
|
||||
},
|
||||
"apollo-cache": {
|
||||
"version": "1.1.17",
|
||||
"resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.1.17.tgz",
|
||||
"integrity": "sha512-7sp24n2HZO4vXgTaKNomLyIfGxG4gDdDkBB0jkRzRi7HhnKmfwhiF/RCiKNbgLdrPX151INdls0KwIVliD0dHQ==",
|
||||
"requires": {
|
||||
"apollo-utilities": "^1.0.21"
|
||||
}
|
||||
},
|
||||
"apollo-client": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-2.4.2.tgz",
|
||||
"integrity": "sha512-g1z23umaVSoKLj9xNl0aAnk2KBF4JeBi7MeKFc9CGTixH7TkqeQUQtxcjrC7j2h4KmDbuhOAHOFUGf8YshN+ag==",
|
||||
"requires": {
|
||||
"@types/async": "2.0.49",
|
||||
"@types/zen-observable": "^0.8.0",
|
||||
"apollo-cache": "1.1.17",
|
||||
"apollo-link": "^1.0.0",
|
||||
"apollo-link-dedup": "^1.0.0",
|
||||
"apollo-utilities": "1.0.21",
|
||||
"symbol-observable": "^1.0.2",
|
||||
"zen-observable": "^0.8.0"
|
||||
}
|
||||
},
|
||||
"apollo-utilities": {
|
||||
"version": "1.0.21",
|
||||
"resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.21.tgz",
|
||||
"integrity": "sha512-ZcxELlEl+sDCYBgEMdNXJAsZtRVm8wk4HIA58bMsqYfd1DSAJQEtZ93F0GZgYNAGy3QyaoBeZtbb0/01++G8JQ==",
|
||||
"requires": {
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"fclone": "^1.0.11"
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
|
||||
"integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA=="
|
||||
},
|
||||
"graphql": {
|
||||
"version": "14.0.2",
|
||||
"resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.2.tgz",
|
||||
"integrity": "sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==",
|
||||
"requires": {
|
||||
"iterall": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"ms-rest-js": {
|
||||
"version": "0.22.425",
|
||||
"resolved": "https://registry.npmjs.org/ms-rest-js/-/ms-rest-js-0.22.425.tgz",
|
||||
"integrity": "sha512-PM9l0Si+T3kFxce8hwB/LlCxPJSHwSlFUSpjdJHzPvF+2w8lw7huE/FCPnRfdaUm7IikQESkJhydnbqX6g2OuQ==",
|
||||
"requires": {
|
||||
"@types/express": "^4.11.1",
|
||||
"@types/form-data": "^2.2.1",
|
||||
"@types/node": "^9.4.6",
|
||||
"@types/uuid": "^3.4.3",
|
||||
"axios": "^0.18.0",
|
||||
"form-data": "^2.3.2",
|
||||
"tough-cookie": "^2.4.3",
|
||||
"tslib": "^1.9.2",
|
||||
"uuid": "^3.2.1",
|
||||
"xml2js": "^0.4.19"
|
||||
}
|
||||
},
|
||||
"symbol-observable": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
|
||||
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
|
||||
"requires": {
|
||||
"psl": "^1.1.24",
|
||||
"punycode": "^1.4.1"
|
||||
}
|
||||
},
|
||||
"xml2js": {
|
||||
"version": "0.4.19",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
|
||||
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
|
||||
"requires": {
|
||||
"sax": ">=0.6.0",
|
||||
"xmlbuilder": "~9.0.1"
|
||||
}
|
||||
},
|
||||
"xmlbuilder": {
|
||||
"version": "9.0.7",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
|
||||
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@azure/storage-blob": {
|
||||
"version": "10.0.0-preview",
|
||||
"resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-10.0.0-preview.tgz",
|
||||
@@ -22,18 +149,18 @@
|
||||
}
|
||||
},
|
||||
"@babel/core": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.0.1.tgz",
|
||||
"integrity": "sha512-7Yy2vRB6KYbhWeIrrwJmKv9UwDxokmlo43wi6AV84oNs4Gi71NTNGh3YxY/hK3+CxuSc6wcKSl25F2tQOhm1GQ==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.1.2.tgz",
|
||||
"integrity": "sha512-IFeSSnjXdhDaoysIlev//UzHZbdEmm7D0EIH2qtse9xK7mXEZQpYjs2P00XlP1qYsYvid79p+Zgg6tz1mp6iVw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@babel/generator": "^7.0.0",
|
||||
"@babel/helpers": "^7.0.0",
|
||||
"@babel/parser": "^7.0.0",
|
||||
"@babel/template": "^7.0.0",
|
||||
"@babel/traverse": "^7.0.0",
|
||||
"@babel/types": "^7.0.0",
|
||||
"@babel/generator": "^7.1.2",
|
||||
"@babel/helpers": "^7.1.2",
|
||||
"@babel/parser": "^7.1.2",
|
||||
"@babel/template": "^7.1.2",
|
||||
"@babel/traverse": "^7.1.0",
|
||||
"@babel/types": "^7.1.2",
|
||||
"convert-source-map": "^1.1.0",
|
||||
"debug": "^3.1.0",
|
||||
"json5": "^0.5.0",
|
||||
@@ -43,22 +170,13 @@
|
||||
"source-map": "^0.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
|
||||
"integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/generator": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0.tgz",
|
||||
"integrity": "sha512-/BM2vupkpbZXq22l1ALO7MqXJZH2k8bKVv8Y+pABFnzWdztDB/ZLveP5At21vLz5c2YtSE6p7j2FZEsqafMz5Q==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.1.2.tgz",
|
||||
"integrity": "sha512-70A9HWLS/1RHk3Ck8tNHKxOoKQuSKocYgwDN85Pyl/RBduss6AKxUR7RIZ/lzduQMSYfWEM4DDBu6A+XGbkFig==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.0.0",
|
||||
"@babel/types": "^7.1.2",
|
||||
"jsesc": "^2.5.1",
|
||||
"lodash": "^4.17.10",
|
||||
"source-map": "^0.5.0",
|
||||
@@ -66,67 +184,44 @@
|
||||
}
|
||||
},
|
||||
"@babel/helper-function-name": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0.tgz",
|
||||
"integrity": "sha512-Zo+LGvfYp4rMtz84BLF3bavFTdf8y4rJtMPTe2J+rxYmnDOIeH8le++VFI/pRJU+rQhjqiXxE4LMaIau28Tv1Q==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
|
||||
"integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-get-function-arity": "^7.0.0",
|
||||
"@babel/template": "^7.0.0",
|
||||
"@babel/template": "^7.1.0",
|
||||
"@babel/types": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/helper-get-function-arity": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz",
|
||||
"integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/helper-split-export-declaration": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz",
|
||||
"integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
|
||||
"integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.0.0",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
"@babel/parser": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.1.2.tgz",
|
||||
"integrity": "sha512-x5HFsW+E/nQalGMw7hu+fvPqnBeBaIr0lWJ2SG0PPL2j+Pm9lYvCrsZJGIgauPIENx0v10INIyFjmSNUD/gSqQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0.tgz",
|
||||
"integrity": "sha512-VLQZik/G5mjYJ6u19U3W2u7eM+rA/NGzH+GtHDFFkLTKLW66OasFrxZ/yK7hkyQcswrmvugFyZpDFRW0DjcjCw==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz",
|
||||
"integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@babel/parser": "^7.0.0",
|
||||
"@babel/types": "^7.0.0"
|
||||
"@babel/parser": "^7.1.2",
|
||||
"@babel/types": "^7.1.2"
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0.tgz",
|
||||
"integrity": "sha512-ka/lwaonJZTlJyn97C4g5FYjPOx+Oxd3ab05hbDr1Mx9aP1FclJ+SUHyLx3Tx40sGmOVJApDxE6puJhd3ld2kw==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.0.tgz",
|
||||
"integrity": "sha512-bwgln0FsMoxm3pLOgrrnGaXk18sSM9JNf1/nHC/FksmNGFbYnPWY4GYCfLxyP1KRmfsxqkRpfoa6xr6VuuSxdw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@babel/generator": "^7.0.0",
|
||||
"@babel/helper-function-name": "^7.0.0",
|
||||
"@babel/helper-function-name": "^7.1.0",
|
||||
"@babel/helper-split-export-declaration": "^7.0.0",
|
||||
"@babel/parser": "^7.0.0",
|
||||
"@babel/parser": "^7.1.0",
|
||||
"@babel/types": "^7.0.0",
|
||||
"debug": "^3.1.0",
|
||||
"globals": "^11.1.0",
|
||||
@@ -134,21 +229,15 @@
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0.tgz",
|
||||
"integrity": "sha512-5tPDap4bGKTLPtci2SUl/B7Gv8RnuJFuQoWx26RJobS0fFrz4reUA3JnwIM+HVHEmWE0C1mzKhDtTp8NsWY02Q==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.1.2.tgz",
|
||||
"integrity": "sha512-pb1I05sZEKiSlMUV9UReaqsCPUpgbHHHu2n1piRm7JkuBkm6QxcaIzKu6FMnMtCbih/cEYTR+RGYYC96Yk9HAg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2",
|
||||
"lodash": "^4.17.10",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1183,100 +1272,55 @@
|
||||
}
|
||||
},
|
||||
"@babel/helpers": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.0.0.tgz",
|
||||
"integrity": "sha512-jbvgR8iLZPnyk6m/UqdXYsSxbVtRi7Pd3CzB4OPwPBnmhNG1DWjiiy777NTuoyIcniszK51R40L5pgfXAfHDtw==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.1.2.tgz",
|
||||
"integrity": "sha512-Myc3pUE8eswD73aWcartxB16K6CGmHDv9KxOmD2CeOs/FaEAQodr3VYGmlvOmog60vNQ2w8QbatuahepZwrHiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/template": "^7.0.0",
|
||||
"@babel/traverse": "^7.0.0",
|
||||
"@babel/types": "^7.0.0"
|
||||
"@babel/template": "^7.1.2",
|
||||
"@babel/traverse": "^7.1.0",
|
||||
"@babel/types": "^7.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
|
||||
"integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/generator": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0.tgz",
|
||||
"integrity": "sha512-/BM2vupkpbZXq22l1ALO7MqXJZH2k8bKVv8Y+pABFnzWdztDB/ZLveP5At21vLz5c2YtSE6p7j2FZEsqafMz5Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.0.0",
|
||||
"jsesc": "^2.5.1",
|
||||
"lodash": "^4.17.10",
|
||||
"source-map": "^0.5.0",
|
||||
"trim-right": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"@babel/helper-function-name": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0.tgz",
|
||||
"integrity": "sha512-Zo+LGvfYp4rMtz84BLF3bavFTdf8y4rJtMPTe2J+rxYmnDOIeH8le++VFI/pRJU+rQhjqiXxE4LMaIau28Tv1Q==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
|
||||
"integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-get-function-arity": "^7.0.0",
|
||||
"@babel/template": "^7.0.0",
|
||||
"@babel/template": "^7.1.0",
|
||||
"@babel/types": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/helper-get-function-arity": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz",
|
||||
"integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/helper-split-export-declaration": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz",
|
||||
"integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
|
||||
"integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.0.0",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
"@babel/parser": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.1.2.tgz",
|
||||
"integrity": "sha512-x5HFsW+E/nQalGMw7hu+fvPqnBeBaIr0lWJ2SG0PPL2j+Pm9lYvCrsZJGIgauPIENx0v10INIyFjmSNUD/gSqQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0.tgz",
|
||||
"integrity": "sha512-VLQZik/G5mjYJ6u19U3W2u7eM+rA/NGzH+GtHDFFkLTKLW66OasFrxZ/yK7hkyQcswrmvugFyZpDFRW0DjcjCw==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz",
|
||||
"integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@babel/parser": "^7.0.0",
|
||||
"@babel/types": "^7.0.0"
|
||||
"@babel/parser": "^7.1.2",
|
||||
"@babel/types": "^7.1.2"
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0.tgz",
|
||||
"integrity": "sha512-ka/lwaonJZTlJyn97C4g5FYjPOx+Oxd3ab05hbDr1Mx9aP1FclJ+SUHyLx3Tx40sGmOVJApDxE6puJhd3ld2kw==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.0.tgz",
|
||||
"integrity": "sha512-bwgln0FsMoxm3pLOgrrnGaXk18sSM9JNf1/nHC/FksmNGFbYnPWY4GYCfLxyP1KRmfsxqkRpfoa6xr6VuuSxdw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@babel/generator": "^7.0.0",
|
||||
"@babel/helper-function-name": "^7.0.0",
|
||||
"@babel/helper-function-name": "^7.1.0",
|
||||
"@babel/helper-split-export-declaration": "^7.0.0",
|
||||
"@babel/parser": "^7.0.0",
|
||||
"@babel/parser": "^7.1.0",
|
||||
"@babel/types": "^7.0.0",
|
||||
"debug": "^3.1.0",
|
||||
"globals": "^11.1.0",
|
||||
@@ -1284,21 +1328,15 @@
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0.tgz",
|
||||
"integrity": "sha512-5tPDap4bGKTLPtci2SUl/B7Gv8RnuJFuQoWx26RJobS0fFrz4reUA3JnwIM+HVHEmWE0C1mzKhDtTp8NsWY02Q==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.1.2.tgz",
|
||||
"integrity": "sha512-pb1I05sZEKiSlMUV9UReaqsCPUpgbHHHu2n1piRm7JkuBkm6QxcaIzKu6FMnMtCbih/cEYTR+RGYYC96Yk9HAg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2",
|
||||
"lodash": "^4.17.10",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3433,48 +3471,10 @@
|
||||
}
|
||||
},
|
||||
"babel-core": {
|
||||
"version": "6.26.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz",
|
||||
"integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-code-frame": "^6.26.0",
|
||||
"babel-generator": "^6.26.0",
|
||||
"babel-helpers": "^6.24.1",
|
||||
"babel-messages": "^6.23.0",
|
||||
"babel-register": "^6.26.0",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"babel-template": "^6.26.0",
|
||||
"babel-traverse": "^6.26.0",
|
||||
"babel-types": "^6.26.0",
|
||||
"babylon": "^6.18.0",
|
||||
"convert-source-map": "^1.5.1",
|
||||
"debug": "^2.6.9",
|
||||
"json5": "^0.5.1",
|
||||
"lodash": "^4.17.4",
|
||||
"minimatch": "^3.0.4",
|
||||
"path-is-absolute": "^1.0.1",
|
||||
"private": "^0.1.8",
|
||||
"slash": "^1.0.0",
|
||||
"source-map": "^0.5.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"babylon": {
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
|
||||
"integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
"version": "7.0.0-bridge.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
|
||||
"integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==",
|
||||
"dev": true
|
||||
},
|
||||
"babel-eslint": {
|
||||
"version": "9.0.0",
|
||||
@@ -3728,15 +3728,14 @@
|
||||
}
|
||||
},
|
||||
"babel-loader": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.2.tgz",
|
||||
"integrity": "sha512-Law0PGtRV1JL8Y9Wpzc0d6EE0GD7LzXWCfaeWwboUMcBWNG6gvaWTK1/+BK7a4X5EmeJiGEuDDFxUsOa8RSWCw==",
|
||||
"version": "7.1.5",
|
||||
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.5.tgz",
|
||||
"integrity": "sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-cache-dir": "^1.0.0",
|
||||
"loader-utils": "^1.0.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
"util.promisify": "^1.0.0"
|
||||
"mkdirp": "^0.5.1"
|
||||
}
|
||||
},
|
||||
"babel-messages": {
|
||||
@@ -3757,6 +3756,50 @@
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-preset-minify": "^0.3.0",
|
||||
"webpack-sources": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-core": {
|
||||
"version": "6.26.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz",
|
||||
"integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-code-frame": "^6.26.0",
|
||||
"babel-generator": "^6.26.0",
|
||||
"babel-helpers": "^6.24.1",
|
||||
"babel-messages": "^6.23.0",
|
||||
"babel-register": "^6.26.0",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"babel-template": "^6.26.0",
|
||||
"babel-traverse": "^6.26.0",
|
||||
"babel-types": "^6.26.0",
|
||||
"babylon": "^6.18.0",
|
||||
"convert-source-map": "^1.5.1",
|
||||
"debug": "^2.6.9",
|
||||
"json5": "^0.5.1",
|
||||
"lodash": "^4.17.4",
|
||||
"minimatch": "^3.0.4",
|
||||
"path-is-absolute": "^1.0.1",
|
||||
"private": "^0.1.8",
|
||||
"slash": "^1.0.0",
|
||||
"source-map": "^0.5.7"
|
||||
}
|
||||
},
|
||||
"babylon": {
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
|
||||
"integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-plugin-check-es2015-constants": {
|
||||
@@ -4534,6 +4577,50 @@
|
||||
"lodash": "^4.17.4",
|
||||
"mkdirp": "^0.5.1",
|
||||
"source-map-support": "^0.4.15"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-core": {
|
||||
"version": "6.26.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz",
|
||||
"integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-code-frame": "^6.26.0",
|
||||
"babel-generator": "^6.26.0",
|
||||
"babel-helpers": "^6.24.1",
|
||||
"babel-messages": "^6.23.0",
|
||||
"babel-register": "^6.26.0",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"babel-template": "^6.26.0",
|
||||
"babel-traverse": "^6.26.0",
|
||||
"babel-types": "^6.26.0",
|
||||
"babylon": "^6.18.0",
|
||||
"convert-source-map": "^1.5.1",
|
||||
"debug": "^2.6.9",
|
||||
"json5": "^0.5.1",
|
||||
"lodash": "^4.17.4",
|
||||
"minimatch": "^3.0.4",
|
||||
"path-is-absolute": "^1.0.1",
|
||||
"private": "^0.1.8",
|
||||
"slash": "^1.0.0",
|
||||
"source-map": "^0.5.7"
|
||||
}
|
||||
},
|
||||
"babylon": {
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
|
||||
"integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-runtime": {
|
||||
@@ -4543,6 +4630,13 @@
|
||||
"requires": {
|
||||
"core-js": "^2.4.0",
|
||||
"regenerator-runtime": "^0.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-template": {
|
||||
@@ -5799,10 +5893,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"convert-source-map": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz",
|
||||
"integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=",
|
||||
"dev": true
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz",
|
||||
"integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.1"
|
||||
}
|
||||
},
|
||||
"cookiejar": {
|
||||
"version": "2.1.2",
|
||||
@@ -7646,6 +7743,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"fclone": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz",
|
||||
"integrity": "sha1-EOhdo4v+p/xZk0HClu4ddyZu5kA="
|
||||
},
|
||||
"figures": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
|
||||
@@ -13625,6 +13727,12 @@
|
||||
"integrity": "sha512-piXx9N2WT8hWb7PBbX1glAuJVIkEyUV9F5fMXFINpZ0x3otVOFKKeGmeuiclFJlP/UrgTckyV606VjH2rNK4bw==",
|
||||
"dev": true
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
|
||||
"dev": true
|
||||
},
|
||||
"regexpp": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
|
||||
@@ -14259,11 +14367,6 @@
|
||||
"regenerate": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||
},
|
||||
"regenerator-transform": {
|
||||
"version": "0.13.3",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz",
|
||||
|
||||
+4
-2
@@ -18,13 +18,14 @@
|
||||
"author": "Barry Low <bearcanrun@gmail.com>",
|
||||
"license": "AGPL-3.0",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.1",
|
||||
"@babel/core": "^7.1.2",
|
||||
"@babel/plugin-proposal-class-properties": "^7.0.0",
|
||||
"@babel/preset-env": "^7.0.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"autoprefixer": "^8.6.5",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-eslint": "^9.0.0",
|
||||
"babel-loader": "^8.0.2",
|
||||
"babel-loader": "^7.1.5",
|
||||
"babel-minify-webpack-plugin": "^0.3.1",
|
||||
"babel-plugin-dynamic-import-node": "^1.2.0",
|
||||
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
||||
@@ -67,6 +68,7 @@
|
||||
"workbox-cli": "^3.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@advancedalgos/web-components": "0.0.5",
|
||||
"@azure/storage-blob": "^10.0.0-preview",
|
||||
"@material-ui/core": "^3.0.3",
|
||||
"@material-ui/icons": "^3.0.1",
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
const CREATE_TEAM = gql`
|
||||
mutation CreateTeamMutation($name: String!, $slug: String!) {
|
||||
createTeam(name: $name, slug: $slug) {
|
||||
mutation CreateTeamMutation($name: String!, $slug: String!, $botName: String!, $botSlug: String!) {
|
||||
createTeam(name: $name, slug: $slug, botName: $botName, botSlug: $botSlug) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
|
||||
@@ -18,6 +18,7 @@ export const GET_ALL_TEAMS_QUERY = gql`
|
||||
createdAt
|
||||
profile {
|
||||
avatar
|
||||
banner
|
||||
description
|
||||
motto
|
||||
updatedAt
|
||||
@@ -36,6 +37,18 @@ export const GET_ALL_TEAMS_QUERY = gql`
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
fb {
|
||||
id
|
||||
name
|
||||
slug
|
||||
avatar
|
||||
kind
|
||||
status {
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const GET_TEAMS_BY_OWNER = gql`
|
||||
query teamsByOwnerQuery {
|
||||
teamsByOwner {
|
||||
query teamsByOwnerQuery($authId: String!) {
|
||||
teamsByOwner(ownerId: $authId) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
@@ -16,6 +16,7 @@ export const GET_TEAMS_BY_OWNER = gql`
|
||||
createdAt
|
||||
profile {
|
||||
avatar
|
||||
banner
|
||||
description
|
||||
motto
|
||||
updatedAt
|
||||
@@ -34,6 +35,18 @@ export const GET_TEAMS_BY_OWNER = gql`
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
fb {
|
||||
id
|
||||
name
|
||||
slug
|
||||
avatar
|
||||
kind
|
||||
status {
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@@ -15,6 +15,7 @@ export const TEAMS_FRAGMENT = gql`
|
||||
createdAt
|
||||
profile {
|
||||
avatar
|
||||
banner
|
||||
description
|
||||
motto
|
||||
updatedAt
|
||||
@@ -33,6 +34,18 @@ export const TEAMS_FRAGMENT = gql`
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
fb {
|
||||
id
|
||||
name
|
||||
slug
|
||||
avatar
|
||||
kind
|
||||
status {
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
const UPDATE_FB = gql`
|
||||
mutation UpdateFBMutation($teamSlug: String!, $avatar: String) {
|
||||
updateFB(teamId, $teamSlug, avatar: $avatar) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
owner
|
||||
status {
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
createdAt
|
||||
profile {
|
||||
avatar
|
||||
banner
|
||||
description
|
||||
motto
|
||||
updatedAt
|
||||
}
|
||||
members {
|
||||
role
|
||||
email
|
||||
member {
|
||||
alias
|
||||
authId
|
||||
}
|
||||
status {
|
||||
id
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default UPDATE_FB
|
||||
@@ -28,6 +28,7 @@ const UPDATE_TEAM_PROFILE = gql`
|
||||
createdAt
|
||||
profile {
|
||||
avatar
|
||||
banner
|
||||
description
|
||||
motto
|
||||
updatedAt
|
||||
|
||||
@@ -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
|
||||
@@ -1,45 +0,0 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
|
||||
const styles = theme => ({
|
||||
card: {
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
margin: '1.5em',
|
||||
padding: '3em'
|
||||
},
|
||||
cardDetails: {
|
||||
display: 'flex',
|
||||
flex: 1
|
||||
},
|
||||
cardContent: {
|
||||
flex: 1
|
||||
}
|
||||
})
|
||||
|
||||
export const MessageCard = ({ classes, message, children }) => (
|
||||
<Card className={classes.card}>
|
||||
<div className={classes.cardDetails}>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography variant='headline' align='center' gutterBottom>
|
||||
{message}
|
||||
</Typography>
|
||||
{children}
|
||||
</CardContent>
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
|
||||
MessageCard.propTypes = {
|
||||
children: PropTypes.node,
|
||||
classes: PropTypes.object.isRequired,
|
||||
message: PropTypes.string
|
||||
}
|
||||
|
||||
export default withStyles(styles)(MessageCard)
|
||||
@@ -1,344 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Mutation } from 'react-apollo'
|
||||
import Dropzone from 'react-dropzone'
|
||||
import { Cropper } from 'react-image-cropper'
|
||||
import * as Azure from '@azure/storage-blob'
|
||||
import readAndCompressImage from 'browser-image-resizer'
|
||||
import { imgSrcToBlob } from 'blob-util'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import DialogActions from '@material-ui/core/DialogActions'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
|
||||
import MessageCard from './MessageCard'
|
||||
|
||||
import GET_AZURE_SAS from '../../graphql/teams/GetAzureSASMutation'
|
||||
|
||||
const styles = theme => ({
|
||||
dropzoneContainer: {
|
||||
display: 'block',
|
||||
margin: '1em',
|
||||
minWidth: 200,
|
||||
height: 200
|
||||
},
|
||||
dropzone: {
|
||||
display: 'block',
|
||||
padding: '3em',
|
||||
minWidth: 200,
|
||||
height: 200,
|
||||
borderWidth: 2,
|
||||
borderColor: '#999',
|
||||
backgroundColor: '#eee'
|
||||
},
|
||||
dropzoneText: {
|
||||
textAlign: 'center'
|
||||
},
|
||||
cropAvatarPreview: {
|
||||
width: 100,
|
||||
height: 100
|
||||
},
|
||||
cropBannerPreview: {
|
||||
width: 400,
|
||||
height: 100
|
||||
},
|
||||
cropAvatarBox: {
|
||||
width: 350,
|
||||
height: 350
|
||||
},
|
||||
cropBannerBox: {
|
||||
width: 650,
|
||||
height: 350
|
||||
},
|
||||
reactCrop: {
|
||||
}
|
||||
})
|
||||
|
||||
const imageAvatarConfig = {
|
||||
quality: 0.6,
|
||||
maxWidth: 200,
|
||||
maxHeight: 200,
|
||||
autoRotate: true,
|
||||
debug: true,
|
||||
mimeType: 'image/jpeg'
|
||||
}
|
||||
|
||||
const imageBannerConfig = {
|
||||
quality: 0.6,
|
||||
maxWidth: 800,
|
||||
maxHeight: 200,
|
||||
autoRotate: true,
|
||||
debug: true,
|
||||
mimeType: 'image/jpeg'
|
||||
}
|
||||
|
||||
class UploadImage extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.onDrop = this.onDrop.bind(this)
|
||||
this.handleCrop = this.handleCrop.bind(this)
|
||||
this.handleClickOpen = this.handleClickOpen.bind(this)
|
||||
this.handleClose = this.handleClose.bind(this)
|
||||
this.handleSubmit = this.handleSubmit.bind(this)
|
||||
this.handleChangeImage = this.handleChangeImage.bind(this)
|
||||
this.cancelChangeImage = this.cancelChangeImage.bind(this)
|
||||
this.saveImage = this.saveImage.bind(this)
|
||||
|
||||
this.state = {
|
||||
open: false,
|
||||
edit: 'avatar',
|
||||
change: false,
|
||||
file: null,
|
||||
src: null,
|
||||
crop: {
|
||||
x: 10,
|
||||
y: 10,
|
||||
width: 200,
|
||||
height: 200
|
||||
},
|
||||
cropping: false,
|
||||
cropped: null,
|
||||
rejected: null,
|
||||
uploaded: false,
|
||||
avatarImage: null,
|
||||
bannerImage: null,
|
||||
sasqr: null
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { classes, team, handleAvatar, handleBanner } = this.props
|
||||
let avatar = null
|
||||
let banner = null
|
||||
if ((team.profile !== null && team.profile.avatar !== undefined && team.profile.avatar !== null && team.profile.avatar !== 'a') || this.state.avatarImage !== null) {
|
||||
avatar = this.state.avatarImage !== null ? this.state.avatarImage : `${team.profile.avatar}?${Math.random()}`
|
||||
} 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'
|
||||
}
|
||||
if ((team.profile !== null && team.profile.banner !== undefined && team.profile.banner !== null && team.profile.banner !== '') || this.state.bannerImage !== null) {
|
||||
banner = this.state.bannerImage !== null ? this.state.bannerImage : `${team.profile.banner}?${Math.random()}`
|
||||
} 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'
|
||||
}
|
||||
|
||||
let handleImage
|
||||
this.state.edit === 'avatar' ? handleImage = handleAvatar : handleImage = handleBanner
|
||||
|
||||
console.log('UploadImage', team, avatar, banner, this.state)
|
||||
return (
|
||||
<div className={classes.dropzoneContainer}>
|
||||
<Mutation mutation={GET_AZURE_SAS} >
|
||||
{(getAzureSAS, { loading, error, data }) => {
|
||||
console.log('getAzureSAS: ', error, data)
|
||||
if (!this.state.uploaded) {
|
||||
if (data !== undefined && data.getAzureSAS !== null) {
|
||||
this.saveImage(data.getAzureSAS, team.slug, handleImage)
|
||||
}
|
||||
// this.handleSubmit(getAzureSAS, team.slug)
|
||||
}
|
||||
if (this.state.cropping) {
|
||||
return (
|
||||
<div>
|
||||
<MessageCard message='Cropping...' />
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div>
|
||||
{(this.state.change || (avatar === null && banner === null && this.state.src === null)) && (
|
||||
<React.Fragment>
|
||||
<Dropzone
|
||||
accept='image/jpeg, image/png'
|
||||
onDrop={(e) => this.onDrop(e, this.state.edit)}
|
||||
className={classes.dropzone}
|
||||
multiple={false}
|
||||
>
|
||||
<p>Drag-and-drop team {this.state.edit} here or click to select files. <br /> Only *.jpeg and *.png images</p>
|
||||
</Dropzone>
|
||||
<Button
|
||||
onClick={(e) => this.cancelChangeImage()}
|
||||
color='primary'
|
||||
>
|
||||
Cancel Image Change
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
)}
|
||||
{!this.state.change && (
|
||||
<React.Fragment>
|
||||
<img src={banner} className={classes.cropBannerPreview} alt='Banner Crop Preview' />
|
||||
<Button
|
||||
onClick={(e) => this.handleChangeImage(e, 'banner')}
|
||||
color='primary'
|
||||
>
|
||||
Change Banner
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
)}
|
||||
{!this.state.change && (
|
||||
<React.Fragment>
|
||||
<img src={avatar} className={classes.cropAvatarPreview} alt='AvatarCrop Preview' />
|
||||
<Button
|
||||
onClick={(e) => this.handleChangeImage(e, 'avatar')}
|
||||
color='primary'
|
||||
>
|
||||
Change Avatar
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
)}
|
||||
{(this.state.avatarImage !== null || this.state.bannerImage !== null) && (
|
||||
<Typography variant='title' color='primary' >Click Update Team to save image changes!</Typography>
|
||||
)}
|
||||
</div>
|
||||
<Dialog
|
||||
open={this.state.open}
|
||||
onClose={this.handleClose}
|
||||
aria-labelledby='form-dialog-title'
|
||||
>
|
||||
<div classes={classes.dialogContainer}>
|
||||
<DialogContent>
|
||||
<div className={this.state.edit === 'avatar' ? classes.cropAvatarBox : classes.cropBannerBox}>
|
||||
{this.state.src !== null && (
|
||||
<Cropper
|
||||
src={this.state.src}
|
||||
originX={100}
|
||||
originY={100}
|
||||
ref={ref => { this.cropper = ref }}
|
||||
onImgLoad={this.onImageLoaded}
|
||||
ratio={this.state.edit === 'avatar' ? 1 : 4}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleClose} color='primary'>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={(e) => this.handleCrop(e, getAzureSAS, team.slug, handleImage)}
|
||||
color='primary'
|
||||
>
|
||||
Crop Image
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</div>
|
||||
</Dialog>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}}
|
||||
</Mutation>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
onDrop (file, editImageType) {
|
||||
console.log('onDrop', file)
|
||||
this.onSelectFile(file, editImageType)
|
||||
this.setState({
|
||||
file
|
||||
})
|
||||
}
|
||||
|
||||
onSelectFile (file, editImageType) {
|
||||
if (file && file.length > 0) {
|
||||
const reader = new window.FileReader()
|
||||
reader.addEventListener(
|
||||
'load',
|
||||
() =>
|
||||
this.setState({
|
||||
src: reader.result,
|
||||
open: true
|
||||
}),
|
||||
false
|
||||
)
|
||||
reader.readAsDataURL(file[0])
|
||||
}
|
||||
}
|
||||
|
||||
async handleCrop (e, getAzureSAS, teamSlug, handleImage) {
|
||||
e.preventDefault()
|
||||
const data = await getAzureSAS({ variables: { teamSlug } })
|
||||
console.log('handleCrop', this.cropper, data)
|
||||
const cropped = this.cropper.crop()
|
||||
const croppedBlob = await imgSrcToBlob(cropped, 'image/png', 'Anonymous')
|
||||
let imageConfig = this.state.edit === 'avatar' ? imageAvatarConfig : imageBannerConfig
|
||||
let resizedBlob = await readAndCompressImage(croppedBlob, imageConfig)
|
||||
|
||||
return this.setState({ cropped: resizedBlob, cropping: true, open: false }, () => {
|
||||
this.saveImage(data.getAzureSAS, teamSlug, handleImage)
|
||||
})
|
||||
}
|
||||
|
||||
async handleSubmit (e, getAzureSAS, teamSlug) {
|
||||
e.preventDefault()
|
||||
let SAS = await getAzureSAS({ variables: { teamSlug } })
|
||||
console.log('handleSubmit: ', await SAS)
|
||||
return this.setState({ sasqr: SAS })
|
||||
}
|
||||
|
||||
async saveImage (SASQueryParameters, teamSlug, handleImage) {
|
||||
const fileName = this.state.edit === 'avatar' ? `${teamSlug}-avatar.jpg` : `${teamSlug}-banner.jpg`
|
||||
let SASurl
|
||||
if (this.state.sasqr === null) {
|
||||
SASurl = process.env.AZURE_SAS_URL
|
||||
} else {
|
||||
SASurl = `${process.env.AZURE_STORAGE_URL}?${this.state.sasqr}`
|
||||
}
|
||||
console.log('getAzureSAS2 SASurl: ', SASurl, this.state.sasqr)
|
||||
|
||||
const pipeline = Azure.StorageURL.newPipeline(new Azure.AnonymousCredential())
|
||||
const serviceURL = new Azure.ServiceURL(SASurl, pipeline)
|
||||
|
||||
const containerName = teamSlug
|
||||
const containerURL = Azure.ContainerURL.fromServiceURL(serviceURL, containerName)
|
||||
const blockBlobURL = Azure.BlockBlobURL.fromContainerURL(containerURL, fileName)
|
||||
|
||||
await Azure.uploadBrowserDataToBlockBlob(Azure.Aborter.None, this.state.cropped, blockBlobURL)
|
||||
|
||||
const image = `${process.env.AZURE_STORAGE_URL}${teamSlug}/${fileName}?${Math.random()}`
|
||||
handleImage(image)
|
||||
let avatarImage = this.state.edit === 'avatar' ? image : null
|
||||
let bannerImage = this.state.edit === 'banner' ? image : null
|
||||
this.setState({ cropping: false, uploaded: true, change: false, avatarImage: avatarImage, bannerImage: bannerImage })
|
||||
return image
|
||||
}
|
||||
|
||||
handleChangeImage (e, editImageType) {
|
||||
e.preventDefault()
|
||||
let crop = editImageType === 'avatar' ? { x: 10, y: 10, width: 200, height: 200 } : { x: 10, y: 10, width: 800, height: 200 }
|
||||
this.setState({
|
||||
edit: editImageType,
|
||||
change: true,
|
||||
crop: crop
|
||||
})
|
||||
}
|
||||
|
||||
cancelChangeImage () {
|
||||
this.setState({ change: false })
|
||||
}
|
||||
|
||||
handleClickOpen (e, editImageType) {
|
||||
e.preventDefault()
|
||||
this.setState({
|
||||
open: true
|
||||
})
|
||||
}
|
||||
|
||||
handleClose () {
|
||||
this.setState({ open: false, src: null, change: false })
|
||||
}
|
||||
}
|
||||
|
||||
UploadImage.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
team: PropTypes.object,
|
||||
handleAvatar: PropTypes.func.isRequired,
|
||||
handleBanner: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(UploadImage)
|
||||
@@ -1,4 +0,0 @@
|
||||
import MessageCard from './MessageCard'
|
||||
import UploadImage from './UploadImage'
|
||||
|
||||
export { MessageCard, UploadImage }
|
||||
@@ -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 '../common/'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
const styles = theme => ({
|
||||
tableContainer: {
|
||||
|
||||
@@ -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: ''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,43 +106,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)
|
||||
}}
|
||||
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>
|
||||
)
|
||||
@@ -150,27 +186,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 } })
|
||||
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: '' })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Query } from 'react-apollo'
|
||||
import { withStateHandlers, lifecycle, compose } from 'recompose'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
@@ -10,9 +11,31 @@ import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
|
||||
import DashTeamItem from './DashTeamItem'
|
||||
import CreateTeamDialog from './CreateTeamDialog'
|
||||
import { MessageCard } from '../../common/'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
export const DashTeam = ({ classes }) => {
|
||||
import { isDefined, isString } from '../../../utils/js-helpers'
|
||||
import { getItem } from '../../../utils/local-storage'
|
||||
|
||||
export const DashTeam = ({ classes, user = null }) => {
|
||||
let owner
|
||||
let authId = null
|
||||
console.log('DashTeam: ', user)
|
||||
if (user !== null && isString(user)) {
|
||||
owner = JSON.parse(user)
|
||||
if (isDefined(owner.authId)) authId = owner.authId
|
||||
}
|
||||
console.log('DashTeam 2: ', owner, authId)
|
||||
|
||||
if (authId === undefined || authId === null) {
|
||||
return (
|
||||
<Grid item md={6}>
|
||||
<Typography variant='display1' gutterBottom>
|
||||
Teams
|
||||
</Typography>
|
||||
<Typography variant='caption'>Loading...</Typography>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Grid item md={6} style={{ position: 'relative' }}>
|
||||
<Typography variant='display1' gutterBottom>
|
||||
@@ -21,7 +44,7 @@ export const DashTeam = ({ classes }) => {
|
||||
Manage Teams
|
||||
</Link>
|
||||
</Typography>
|
||||
<Query query={GET_TEAMS_BY_OWNER}>
|
||||
<Query query={GET_TEAMS_BY_OWNER} variables={{ authId }}>
|
||||
{({ loading, error, data }) => {
|
||||
console.log('GET_TEAMS_BY_OWNER: ', loading, error, data)
|
||||
let errors
|
||||
@@ -76,7 +99,25 @@ export const DashTeam = ({ classes }) => {
|
||||
}
|
||||
|
||||
DashTeam.propTypes = {
|
||||
user: PropTypes.any,
|
||||
classes: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default DashTeam
|
||||
const getUserOnMount = lifecycle({
|
||||
componentDidMount () {
|
||||
getItem('user').then(user => {
|
||||
this.setState({ user })
|
||||
}) // Set user to state
|
||||
}
|
||||
})
|
||||
|
||||
const mapStateToProps = withStateHandlers(() => ({ user: null }), {
|
||||
user: ({ user }) => () => ({ user })
|
||||
})
|
||||
|
||||
const DashTeamAuthId = compose(
|
||||
mapStateToProps,
|
||||
getUserOnMount
|
||||
)(DashTeam)
|
||||
|
||||
export default DashTeamAuthId
|
||||
@@ -35,39 +35,34 @@ const styles = theme => ({
|
||||
}
|
||||
})
|
||||
|
||||
export const DashTeamItem = ({ classes, team }) => {
|
||||
let avatar
|
||||
if (team.profile.avatar !== undefined && team.profile.avatar !== 'a') {
|
||||
avatar = team.profile.avatar
|
||||
} else {
|
||||
avatar = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22288%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20288%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_164edaf95ee%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A14pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_164edaf95ee%22%3E%3Crect%20width%3D%22288%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2296.32500076293945%22%20y%3D%22118.8%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
|
||||
}
|
||||
return (
|
||||
<Grid item>
|
||||
<Card className={classes.card}>
|
||||
<div className={classes.cardDetails}>
|
||||
<CardMedia
|
||||
className={classes.cardMedia}
|
||||
image={avatar}
|
||||
title={team.name}
|
||||
/>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography variant='headline'>{team.name}</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
{team.createdAt}
|
||||
</Typography>
|
||||
<Typography variant='subheading' paragraph>
|
||||
Members: {team.members.length}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<ManageTeamDetails team={team} />
|
||||
</CardActions>
|
||||
</div>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
const placeholder = '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' // eslint-disable-line max-len
|
||||
|
||||
export const DashTeamItem = ({ classes, team }) => (
|
||||
<Grid item>
|
||||
<Card className={classes.card}>
|
||||
<div className={classes.cardDetails}>
|
||||
<CardMedia
|
||||
className={classes.cardMedia}
|
||||
image={team.profile !== null && team.profile.avatar !== undefined && team.profile.avatar !== null ? team.profile.avatar : placeholder}
|
||||
title='Image title'
|
||||
/>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography variant='headline'>{team.name}</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
{team.createdAt}
|
||||
</Typography>
|
||||
<Typography variant='subheading' paragraph>
|
||||
Members: {team.members.length}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<ManageTeamDetails team={team} />
|
||||
</CardActions>
|
||||
</div>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
|
||||
DashTeamItem.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
team: PropTypes.object.isRequired
|
||||
|
||||
@@ -7,7 +7,7 @@ import Typography from '@material-ui/core/Typography'
|
||||
import ManageMemberDelete from './ManageMemberDelete'
|
||||
import ManageMemberRole from './ManageMemberRole'
|
||||
import ManageMemberStatus from './ManageMemberStatus'
|
||||
import { MessageCard } from '../../common/'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
export const ManageMembersItem = ({ classes, member, teamId, authId }) => {
|
||||
console.log('ManageMembersItem', member)
|
||||
|
||||
@@ -10,7 +10,7 @@ import Typography from '@material-ui/core/Typography'
|
||||
|
||||
import InviteMemberDialog from './InviteMemberDialog'
|
||||
import ManageMembersItem from './ManageMembersItem'
|
||||
import { MessageCard } from '../../common/'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
const styles = theme => ({
|
||||
heroContent: {
|
||||
@@ -61,7 +61,7 @@ export const ManageMembersTeamItem = ({ 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'
|
||||
}
|
||||
if (team.members.length > 0) {
|
||||
return (
|
||||
|
||||
@@ -55,13 +55,14 @@ export class ManageTeamDelete extends Component {
|
||||
|
||||
render () {
|
||||
console.log(this.props, this.props.slug)
|
||||
const { classes } = this.props
|
||||
const { classes, authId } = this.props
|
||||
return (
|
||||
<Mutation
|
||||
mutation={DELETE_TEAM}
|
||||
refetchQueries={[
|
||||
{
|
||||
query: GET_TEAMS_BY_OWNER
|
||||
query: GET_TEAMS_BY_OWNER,
|
||||
variables: { authId }
|
||||
}
|
||||
]}
|
||||
>
|
||||
@@ -148,7 +149,8 @@ export class ManageTeamDelete extends Component {
|
||||
|
||||
ManageTeamDelete.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
slug: PropTypes.string.isRequired
|
||||
slug: PropTypes.string.isRequired,
|
||||
authId: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageTeamDelete)
|
||||
@@ -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>
|
||||
|
||||
@@ -13,12 +13,14 @@ 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_TEAM_PROFILE from '../../../graphql/teams/UpdateTeamProfileMutation'
|
||||
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
|
||||
import { checkGraphQLError } from '../../../utils/graphql-errors'
|
||||
|
||||
import { UploadImage } from '../../common'
|
||||
import GET_AZURE_SAS from '../../../graphql/teams/GetAzureSASMutation'
|
||||
|
||||
const styles = theme => ({
|
||||
dialogContainer: {
|
||||
@@ -47,6 +49,7 @@ export class ManageTeamEdit extends Component {
|
||||
const description = props.team.profile.description || ''
|
||||
const avatar = props.team.profile.avatar || ''
|
||||
const banner = props.team.profile.banner || ''
|
||||
this.authId = props.authId
|
||||
|
||||
this.state = {
|
||||
open: false,
|
||||
@@ -58,14 +61,15 @@ export class ManageTeamEdit extends Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
console.log(this.props, this.props.slug)
|
||||
console.log('ManageTeamEdit ', this.props, this.props.slug, this.props.team)
|
||||
const { classes, team } = this.props
|
||||
return (
|
||||
<Mutation
|
||||
mutation={UPDATE_TEAM_PROFILE}
|
||||
refetchQueries={[
|
||||
{
|
||||
query: GET_TEAMS_BY_OWNER
|
||||
query: GET_TEAMS_BY_OWNER,
|
||||
variables: { authId: this.authId }
|
||||
}
|
||||
]}
|
||||
>
|
||||
@@ -108,11 +112,78 @@ export class ManageTeamEdit extends Component {
|
||||
Edit Team Details
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<UploadImage
|
||||
team={team}
|
||||
handleAvatar={this.handleAvatar}
|
||||
handleBanner={this.handleBanner}
|
||||
/>
|
||||
<Mutation mutation={GET_AZURE_SAS} >
|
||||
{(getAzureSAS, { loading, error, data }) => {
|
||||
console.log('getAzureSAS: ', loading, error, data, team.profile)
|
||||
const AzureStorageUrl = process.env.AZURE_STORAGE_URL
|
||||
const containerName = team.slug
|
||||
let AzureSASURL
|
||||
if (!loading && data !== undefined) {
|
||||
AzureSASURL = data.getAzureSAS
|
||||
} else {
|
||||
getAzureSAS({ variables: { teamSlug: containerName } })
|
||||
}
|
||||
|
||||
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) {
|
||||
return (<MessageCard message='Loading...' />)
|
||||
} else {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ImageUpload
|
||||
key='banner'
|
||||
handleUrl={this.handleBanner}
|
||||
fileName={`${team.slug}-banner.jpg`}
|
||||
containerName={containerName}
|
||||
existingImage={banner}
|
||||
cropContainer={{ x: 10, y: 10, width: 800, height: 200 }}
|
||||
cropPreviewBox={{ width: 650, height: 200 }}
|
||||
saveImageConfig={{
|
||||
quality: 0.6,
|
||||
maxWidth: 800,
|
||||
maxHeight: 200,
|
||||
autoRotate: true,
|
||||
mimeType: 'image/jpeg'
|
||||
}}
|
||||
AzureStorageUrl={AzureStorageUrl}
|
||||
AzureSASURL={AzureSASURL}
|
||||
cropRatio={4}
|
||||
debug
|
||||
/>
|
||||
<ImageUpload
|
||||
key='avatar'
|
||||
handleUrl={this.handleAvatar}
|
||||
fileName={`${team.slug}-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'
|
||||
@@ -192,12 +263,12 @@ export class ManageTeamEdit extends Component {
|
||||
|
||||
handleAvatar (avatarUrl) {
|
||||
console.log('handleAvatar: ', avatarUrl)
|
||||
this.setState({ avatar: avatarUrl })
|
||||
this.setState({ avatar: `${avatarUrl}?${Math.random()}` })
|
||||
}
|
||||
|
||||
handleBanner (bannerUrl) {
|
||||
console.log('handleBanner: ', bannerUrl)
|
||||
this.setState({ banner: bannerUrl })
|
||||
this.setState({ banner: `${bannerUrl}?${Math.random()}` })
|
||||
}
|
||||
|
||||
async handleSubmit (e, updateTeamProfile, slug) {
|
||||
@@ -207,6 +278,7 @@ export class ManageTeamEdit extends Component {
|
||||
await updateTeamProfile({
|
||||
variables: {
|
||||
slug,
|
||||
owner: this.authId,
|
||||
description: this.state.description,
|
||||
motto: this.state.motto,
|
||||
avatar: this.state.avatar,
|
||||
@@ -220,7 +292,8 @@ export class ManageTeamEdit extends Component {
|
||||
ManageTeamEdit.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
slug: PropTypes.string.isRequired,
|
||||
team: PropTypes.object
|
||||
team: PropTypes.object,
|
||||
authId: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ManageTeamEdit)
|
||||
@@ -12,7 +12,7 @@ import { getItem } from '../../../utils/local-storage'
|
||||
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
|
||||
import ManageMembersTeamItem from './ManageMembersTeamItem'
|
||||
import { MessageCard } from '../../common/'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
const styles = theme => ({
|
||||
heroContent: {
|
||||
@@ -67,6 +67,7 @@ export const ManageTeamMembersList = ({ classes, user = null }) => {
|
||||
return (
|
||||
<Query
|
||||
query={GET_TEAMS_BY_OWNER}
|
||||
variables={{ authId }}
|
||||
fetchPolicy='network-only'
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
|
||||
@@ -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,8 +39,8 @@ export const ManageTeamsItem = ({ classes, team, authId }) => {
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<ManageTeamDetails team={team} />
|
||||
<ManageTeamEdit slug={team.slug} team={team} />
|
||||
<ManageTeamDelete slug={team.slug} />
|
||||
<ManageTeamEdit slug={team.slug} team={team} authId={authId} />
|
||||
<ManageTeamDelete slug={team.slug} authId={authId} />
|
||||
</CardActions>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -4,6 +4,7 @@ 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'
|
||||
@@ -13,7 +14,6 @@ import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
|
||||
|
||||
import ManageTeamsItem from './ManageTeamsItem'
|
||||
import CreateTeamDialog from './CreateTeamDialog'
|
||||
import { MessageCard } from '../../common/'
|
||||
|
||||
const styles = theme => ({
|
||||
heroContent: {
|
||||
@@ -68,6 +68,7 @@ export const ManageTeamsList = ({ classes, user = null }) => {
|
||||
return (
|
||||
<Query
|
||||
query={GET_TEAMS_BY_OWNER}
|
||||
variables={{ authId }}
|
||||
fetchPolicy='network-only'
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
@@ -93,9 +94,6 @@ export const ManageTeamsList = ({ classes, user = null }) => {
|
||||
authId={authId}
|
||||
/>
|
||||
))}
|
||||
<MessageCard message='Create another team'>
|
||||
<CreateTeamDialog authId={authId} />
|
||||
</MessageCard>
|
||||
{errors}
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -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 '../common/'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
const styles = theme => ({
|
||||
tableContainer: {
|
||||
|
||||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
||||
|
||||
import queryString from 'query-string'
|
||||
|
||||
import { MessageCard } from '../common/'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
class AcceptTeamInvite extends Component {
|
||||
render () {
|
||||
|
||||
@@ -42,49 +42,68 @@ const styles = theme => ({
|
||||
maxWidth: 600,
|
||||
margin: '0 auto',
|
||||
padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px`
|
||||
},
|
||||
banner: {
|
||||
maxWidth: '100%',
|
||||
height: 'auto',
|
||||
margin: '0 auto'
|
||||
},
|
||||
avatar: {
|
||||
maxWidth: 100,
|
||||
height: 100,
|
||||
margin: '0 1em 1em 0',
|
||||
float: 'left'
|
||||
}
|
||||
})
|
||||
|
||||
const TeamsDetails = ({ classes, team }) => (
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<main className={classes.layout}>
|
||||
<Paper className={classes.paper}>
|
||||
<div className={classes.heroContent}>
|
||||
<Link to='/teams'>← Back to all teams</Link>
|
||||
<Typography
|
||||
variant='display3'
|
||||
align='center'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
>
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
{team.createdAt}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
Motto: {team.profile.motto}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
Description: {team.profile.description}
|
||||
</Typography>
|
||||
<Typography variant='subheading' paragraph gutterBottom>
|
||||
Members: {team.members.length}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='primary'>
|
||||
Team Admin:
|
||||
{team.members.map(member => {
|
||||
if (member.role === 'OWNER' || member.role === 'ADMIN') {
|
||||
return member.member.alias
|
||||
}
|
||||
})}
|
||||
</Typography>
|
||||
</div>
|
||||
</Paper>
|
||||
</main>
|
||||
</React.Fragment>
|
||||
)
|
||||
const TeamsDetails = ({ classes, team }) => {
|
||||
let avatar
|
||||
if (team.profile.avatar !== undefined && team.profile.avatar !== 'a') {
|
||||
avatar = team.profile.avatar
|
||||
} else {
|
||||
avatar = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22288%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20288%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_164edaf95ee%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A14pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_164edaf95ee%22%3E%3Crect%20width%3D%22288%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2296.32500076293945%22%20y%3D%22118.8%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
|
||||
}
|
||||
let banner
|
||||
if (team.profile.banner !== undefined && team.profile.banner !== 'a') {
|
||||
banner = team.profile.banner
|
||||
} else {
|
||||
banner = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22288%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20288%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_164edaf95ee%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A14pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_164edaf95ee%22%3E%3Crect%20width%3D%22288%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2296.32500076293945%22%20y%3D%22118.8%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<main className={classes.layout}>
|
||||
<Paper className={classes.paper}>
|
||||
<div className={classes.heroContent}>
|
||||
<Link to='/teams'>← Back to all teams</Link>
|
||||
<img src={banner} alt={team.name} className={classes.banner} />
|
||||
<img src={avatar} alt={team.name} className={classes.avatar} />
|
||||
<Typography
|
||||
variant='display3'
|
||||
align='center'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
>
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
{team.createdAt}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
Motto: {team.profile.motto}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
Description: {team.profile.description}
|
||||
</Typography>
|
||||
<Typography variant='subheading' paragraph gutterBottom>
|
||||
Members: {team.members.length}
|
||||
</Typography>
|
||||
</div>
|
||||
</Paper>
|
||||
</main>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
TeamsDetails.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
team: PropTypes.object.isRequired
|
||||
|
||||
@@ -12,40 +12,54 @@ import Typography from '@material-ui/core/Typography'
|
||||
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
export const TeamsItem = ({ classes, team }) => (
|
||||
<Grid item sm={6} md={4} lg={3}>
|
||||
<Card className={classes.card}>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
className={classes.cardMedia}
|
||||
image='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' // eslint-disable-line max-len
|
||||
title='Image title'
|
||||
/>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography gutterBottom variant='headline' component='h2'>
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography variant='caption' color='textSecondary'>
|
||||
{team.createdAt}
|
||||
</Typography>
|
||||
<Typography variant='caption' paragraph gutterBottom>
|
||||
Members: 1
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='primary'>
|
||||
Now recruiting!
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
<CardActions>
|
||||
<Link to={`/teams/${team.slug}`}>
|
||||
<Button size='small' color='primary' className={classes.buttonRight}>
|
||||
Details
|
||||
</Button>
|
||||
</Link>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
export const TeamsItem = ({ classes, team }) => {
|
||||
/* let avatar
|
||||
if (team.profile.avatar !== undefined && team.profile.avatar !== 'a') {
|
||||
avatar = team.profile.avatar
|
||||
} else {
|
||||
avatar = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22288%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20288%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_164edaf95ee%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A14pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_164edaf95ee%22%3E%3Crect%20width%3D%22288%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2296.32500076293945%22%20y%3D%22118.8%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
|
||||
} */
|
||||
let banner
|
||||
if (team.profile.banner !== undefined && team.profile.banner !== null) {
|
||||
banner = team.profile.banner
|
||||
} else {
|
||||
banner = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22288%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20288%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_164edaf95ee%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A14pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_164edaf95ee%22%3E%3Crect%20width%3D%22288%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2296.32500076293945%22%20y%3D%22118.8%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
|
||||
}
|
||||
return (
|
||||
<Grid item sm={6} md={4} lg={3}>
|
||||
<Card className={classes.card}>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
className={classes.cardMedia}
|
||||
image={banner}
|
||||
title={team.name}
|
||||
/>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography gutterBottom variant='headline' component='h2'>
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography variant='caption' color='textSecondary'>
|
||||
{team.createdAt}
|
||||
</Typography>
|
||||
<Typography variant='caption' paragraph gutterBottom>
|
||||
Members: 1
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='primary'>
|
||||
Now recruiting!
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
<CardActions>
|
||||
<Link to={`/teams/${team.slug}`}>
|
||||
<Button size='small' color='primary' className={classes.buttonRight}>
|
||||
Details
|
||||
</Button>
|
||||
</Link>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
TeamsItem.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
|
||||
@@ -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