Merge branch 'feature/azure-images' into develop

This commit is contained in:
Barry Low committed 2018-09-21 08:45:48 -07:00
commit f820fcd1fa
23 files changed
+2050 -348

No files matched your search

+1
View File
@@ -41,6 +41,7 @@ type TeamProfile {
description: String
motto: String
avatar: String
banner: String
updatedAt: DateTime!
createdAt: DateTime!
}
+402 -54
View File
@@ -3,6 +3,14 @@
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"@azure/storage-blob": {
"version": "10.0.0-preview",
"resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-10.0.0-preview.tgz",
"integrity": "sha512-PFXKm+gipKDfg5h08hPiEr0Za4RMiFzzte+ewh4ACZeRQa0XZK55NAZxW67ZytGBd7WXdQq6pcAgo5dBnwQANQ==",
"requires": {
"ms-rest-js": "0.21.413"
}
},
"@babel/generator": {
"version": "7.0.0-beta.38",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.38.tgz",
@@ -213,6 +221,14 @@
"@types/express": "*"
}
},
"@types/form-data": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
"integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==",
"requires": {
"@types/node": "*"
}
},
"@types/graphql": {
"version": "0.12.6",
"resolved": "http://registry.npmjs.org/@types/graphql/-/graphql-0.12.6.tgz",
@@ -247,6 +263,14 @@
"@types/mime": "*"
}
},
"@types/uuid": {
"version": "3.4.4",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.4.tgz",
"integrity": "sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw==",
"requires": {
"@types/node": "*"
}
},
"@types/zen-observable": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.5.4.tgz",
@@ -808,6 +832,86 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
},
"axios": {
"version": "0.18.0",
"resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
"requires": {
"follow-redirects": "^1.3.0",
"is-buffer": "^1.1.5"
}
},
"azure-storage": {
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.1.tgz",
"integrity": "sha512-rnFo1uMIPtilusRCpK91tfY3P4Q7qRsDNwriXdp+OeTIGkGt0cTxL4mhqYfNPYPK+WBQmBdGWhOk+iROM05dcw==",
"requires": {
"browserify-mime": "~1.2.9",
"extend": "~1.2.1",
"json-edm-parser": "0.1.2",
"md5.js": "1.3.4",
"readable-stream": "~2.0.0",
"request": "^2.86.0",
"underscore": "~1.8.3",
"uuid": "^3.0.0",
"validator": "~9.4.1",
"xml2js": "0.2.8",
"xmlbuilder": "0.4.3"
},
"dependencies": {
"extend": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz",
"integrity": "sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"readable-stream": {
"version": "2.0.6",
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "~1.0.0",
"process-nextick-args": "~1.0.6",
"string_decoder": "~0.10.x",
"util-deprecate": "~1.0.1"
}
},
"sax": {
"version": "0.5.8",
"resolved": "http://registry.npmjs.org/sax/-/sax-0.5.8.tgz",
"integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE="
},
"validator": {
"version": "9.4.1",
"resolved": "http://registry.npmjs.org/validator/-/validator-9.4.1.tgz",
"integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA=="
},
"xml2js": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz",
"integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=",
"requires": {
"sax": "0.5.x"
}
},
"xmlbuilder": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-0.4.3.tgz",
"integrity": "sha1-xGFLp04K0ZbmCcknLNnh3bKKilg="
}
}
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
@@ -968,6 +1072,21 @@
"qs": "6.5.2",
"raw-body": "2.3.3",
"type-is": "~1.6.16"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"body-parser-graphql": {
@@ -1028,6 +1147,11 @@
}
}
},
"browserify-mime": {
"version": "1.2.9",
"resolved": "https://registry.npmjs.org/browserify-mime/-/browserify-mime-1.2.9.tgz",
"integrity": "sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8="
},
"buffer": {
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
@@ -1746,18 +1870,11 @@
"integrity": "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw=="
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.0.1.tgz",
"integrity": "sha512-K23FHJ/Mt404FSlp6gSZCevIbTMLX0j3fmHhUEhQ3Wq0FMODW3+cUSoLdy1Gx4polAf4t/lphhmHH35BB8cLYw==",
"requires": {
"ms": "2.0.0"
},
"dependencies": {
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
"ms": "^2.1.1"
}
},
"decamelize": {
@@ -2271,6 +2388,14 @@
"to-regex": "^3.0.1"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"define-property": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@@ -2286,6 +2411,11 @@
"requires": {
"is-extendable": "^0.1.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
@@ -2409,11 +2539,24 @@
"type-is": "~1.6.15"
}
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"iconv-lite": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"qs": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
@@ -2680,6 +2823,14 @@
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
},
"fast-xml-parser": {
"version": "3.12.5",
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.12.5.tgz",
"integrity": "sha512-g8TSGUF1a2vdFmQ29vKcYBNnwuJQQuyr6It3cjGsiD3dkUXqVWuXZQvjEkgrrCe5K8D30X125ACyxaj7XaaH8g==",
"requires": {
"nimnjs": "^1.3.2"
}
},
"fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
@@ -2762,6 +2913,19 @@
"unpipe": "~1.0.0"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"statuses": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
@@ -2786,6 +2950,29 @@
"locate-path": "^2.0.0"
}
},
"follow-redirects": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.8.tgz",
"integrity": "sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg==",
"requires": {
"debug": "=3.1.0"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -4225,6 +4412,15 @@
}
}
},
"hash-base": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
"integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
"requires": {
"inherits": "^2.0.1",
"safe-buffer": "^5.0.1"
}
},
"header-case": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz",
@@ -4822,6 +5018,14 @@
"integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=",
"dev": true
},
"json-edm-parser": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz",
"integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=",
"requires": {
"jsonparse": "~1.2.0"
}
},
"json-parse-better-errors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
@@ -4898,6 +5102,11 @@
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
"dev": true
},
"jsonparse": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.2.0.tgz",
"integrity": "sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70="
},
"jsonwebtoken": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz",
@@ -4946,6 +5155,23 @@
"lru-memoizer": "^1.6.0",
"ms": "^2.0.0",
"request": "^2.73.0"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
},
"dependencies": {
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
}
}
},
"jws": {
@@ -5405,6 +5631,15 @@
"integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=",
"dev": true
},
"md5.js": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
"integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
"requires": {
"hash-base": "^3.0.0",
"inherits": "^2.0.1"
}
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -5419,9 +5654,9 @@
}
},
"memfs": {
"version": "2.9.4",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-2.9.4.tgz",
"integrity": "sha512-wstvgqSTBGf9rQHoaRpX3wJiGzB/sj649XaO+byuHiPZQaR3Y/mOgU6n9iMFLtAHlR4BwwBWFgA4hobiU6EcCg==",
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-2.10.0.tgz",
"integrity": "sha512-GuQXfXghDdDdkokv6cwaWLh8bOD9Ots4z11qUR9yKiCeO7oMPhBjFjKVc991DIHTXFbonqKYOEDAVTa4CvvkJg==",
"dev": true,
"requires": {
"fast-extend": "0.0.2",
@@ -5555,6 +5790,30 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
},
"ms-rest-js": {
"version": "0.21.413",
"resolved": "https://registry.npmjs.org/ms-rest-js/-/ms-rest-js-0.21.413.tgz",
"integrity": "sha512-eX+M98Y9s+zo85Unt83TYkpuJkW4d0wuiHrpWjAxx/7YzZd3uVq8HRhJHXGDqCd22nlEvtwlchfgwILmBcWnOg==",
"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"
},
"dependencies": {
"@types/node": {
"version": "9.6.31",
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.31.tgz",
"integrity": "sha512-kIVlvUBizL51ALNMPbmcZoM7quHyB7J6fLRwQe22JsMp39nrVSHdBeVVS3fnQCK1orxI3O8LScmb8cuiihkAfA=="
}
}
},
"multimatch": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz",
@@ -5608,6 +5867,25 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
"nimn-date-parser": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/nimn-date-parser/-/nimn-date-parser-1.0.0.tgz",
"integrity": "sha512-1Nf+x3EeMvHUiHsVuEhiZnwA8RMeOBVTQWfB1S2n9+i6PYCofHd2HRMD+WOHIHYshy4T4Gk8wQoCol7Hq3av8Q=="
},
"nimn_schema_builder": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/nimn_schema_builder/-/nimn_schema_builder-1.1.0.tgz",
"integrity": "sha512-DK5/B8CM4qwzG2URy130avcwPev4uO0ev836FbQyKo1ms6I9z/i6EJyiZ+d9xtgloxUri0W+5gfR8YbPq7SheA=="
},
"nimnjs": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/nimnjs/-/nimnjs-1.3.2.tgz",
"integrity": "sha512-TIOtI4iqkQrUM1tiM76AtTQem0c7e56SkDZ7sj1d1MfUsqRcq2ZWQvej/O+HBTZV7u/VKnwlKTDugK/75IRPPw==",
"requires": {
"nimn-date-parser": "^1.0.0",
"nimn_schema_builder": "^1.0.0"
}
},
"no-case": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
@@ -6330,6 +6608,23 @@
"async": "^1.5.2",
"debug": "^2.2.0",
"mkdirp": "0.5.x"
},
"dependencies": {
"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"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
}
}
},
"posix-character-classes": {
@@ -6338,9 +6633,9 @@
"integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
},
"postgres-array": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.2.tgz",
"integrity": "sha1-jgsy6wO/d6XAp4UeBEHBaaJWojg=",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.3.tgz",
"integrity": "sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==",
"dev": true
},
"postgres-bytea": {
@@ -6376,14 +6671,14 @@
"dev": true
},
"prisma": {
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-1.16.0.tgz",
"integrity": "sha512-8jZYCrkd1xjy+JJbQi81f8PBOLe8LLWwSu0fK0cqekm3FeafBd8xk5b0RWcIsHyVd6ypKCQt3tnZEMVzmbKrdQ==",
"version": "1.16.4",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-1.16.4.tgz",
"integrity": "sha512-ha+SJDnJ+NVtkoP4nivcmnKV/PmkbQiXVJUPEdYfkQPpuite1kOuFp9seolE4DJFaz3m8DlF24AQf7aePf09AQ==",
"dev": true,
"requires": {
"fs-extra": "^5.0.0",
"prisma-cli-core": "1.0.76",
"prisma-cli-engine": "1.0.79",
"prisma-cli-core": "1.0.79",
"prisma-cli-engine": "1.0.82",
"semver": "^5.4.1",
"source-map-support": "^0.4.18"
},
@@ -6502,9 +6797,9 @@
}
},
"prisma-cli-core": {
"version": "1.0.76",
"resolved": "https://registry.npmjs.org/prisma-cli-core/-/prisma-cli-core-1.0.76.tgz",
"integrity": "sha512-HtHn/RM2GlJi23KoIXHoboP97aC54SYDqr7B4uT/80JP6A6nQp5HLt4sJgNfKapaHFZVzXYM7M3LEfGq3tgQbw==",
"version": "1.0.79",
"resolved": "https://registry.npmjs.org/prisma-cli-core/-/prisma-cli-core-1.0.79.tgz",
"integrity": "sha512-3xaFE0wK48nZ8LOqx62gMoFgjIob121Uo6RHOnXNXMcCOdtGM7VfGw4o6gyDVwNDvu66fz0EVLaQGcJb5hnTpA==",
"dev": true,
"requires": {
"adm-zip": "^0.4.7",
@@ -6538,9 +6833,9 @@
"opn": "^5.1.0",
"pause": "^0.1.0",
"portfinder": "^1.0.13",
"prisma-db-introspection": "0.0.46",
"prisma-db-introspection": "0.0.50",
"prisma-json-schema": "0.0.4",
"prisma-yml": "1.0.96",
"prisma-yml": "1.0.100",
"scuid": "^1.0.2",
"semver": "^5.4.1",
"sillyname": "^0.1.0",
@@ -6646,12 +6941,12 @@
}
},
"graphql-config": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-2.1.0.tgz",
"integrity": "sha512-LWpkME3x+KSFMVuMpRmDHTIZLyQQsBoKtMXJrT4RgXk6y0GRf0lsJ81R3S2FmT1CKZQOJfFsOpUfPpAcfmoN/A==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-2.2.1.tgz",
"integrity": "sha512-U8+1IAhw9m6WkZRRcyj8ZarK96R6lQBQ0an4lp76Ps9FyhOXENC5YQOxOFGm5CxPrX2rD0g3Je4zG5xdNJjwzQ==",
"dev": true,
"requires": {
"graphql-import": "^0.4.4",
"graphql-import": "^0.7.1",
"graphql-request": "^1.5.0",
"js-yaml": "^3.10.0",
"lodash": "^4.17.4",
@@ -6697,12 +6992,13 @@
}
},
"graphql-import": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/graphql-import/-/graphql-import-0.4.5.tgz",
"integrity": "sha512-G/+I08Qp6/QGTb9qapknCm3yPHV0ZL7wbaalWFpxsfR8ZhZoTBe//LsbsCKlbALQpcMegchpJhpTSKiJjhaVqQ==",
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/graphql-import/-/graphql-import-0.7.1.tgz",
"integrity": "sha512-YpwpaPjRUVlw2SN3OPljpWbVRWAhMAyfSba5U47qGMOSsPLi2gYeJtngGpymjm9nk57RFWEpjqwh4+dpYuFAPw==",
"dev": true,
"requires": {
"lodash": "^4.17.4"
"lodash": "^4.17.4",
"resolve-from": "^4.0.0"
}
},
"inquirer": {
@@ -6778,9 +7074,9 @@
"dev": true
},
"prisma-yml": {
"version": "1.0.96",
"resolved": "https://registry.npmjs.org/prisma-yml/-/prisma-yml-1.0.96.tgz",
"integrity": "sha512-w3XGzJHUq5pwBoFy/amkGOcTDj4XoHh8UFUUUZcHo5fSyoF8AWeRTu1yWINaPVGxbcmpwKNetntAW4ijiq7M5g==",
"version": "1.0.100",
"resolved": "https://registry.npmjs.org/prisma-yml/-/prisma-yml-1.0.100.tgz",
"integrity": "sha512-W2a0dpfbXyapc3WZqcvUBqtsl2r9upQRUR2p53AqQR4tQz+/6nsMcqe30vqgnOW/WmNAnknqQT3Z5P0rsq4K3Q==",
"dev": true,
"requires": {
"ajv": "5",
@@ -6803,6 +7099,12 @@
"yaml-ast-parser": "^0.0.40"
}
},
"resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -6827,9 +7129,9 @@
}
},
"prisma-cli-engine": {
"version": "1.0.79",
"resolved": "https://registry.npmjs.org/prisma-cli-engine/-/prisma-cli-engine-1.0.79.tgz",
"integrity": "sha512-CdEIJs4ld1IiQQt2CFFPmeDypN4Ct4sTgmFODVjJix790mpEtxMagzCcA+mhfnRL65P6xiHn76Gdxbz60GyYBA==",
"version": "1.0.82",
"resolved": "https://registry.npmjs.org/prisma-cli-engine/-/prisma-cli-engine-1.0.82.tgz",
"integrity": "sha512-kEqNtH0bjzVX17Vcs77UiAwk0Ei9Za03bOINcrpIjNUyI9GOOU5p+6ss8cePfK21lxvy5RSlYwthBFLkXE73Gg==",
"dev": true,
"requires": {
"@heroku/linewrap": "^1.0.0",
@@ -6872,7 +7174,7 @@
"memfs": "^2.5.3",
"opn": "^5.1.0",
"prisma-json-schema": "0.0.4",
"prisma-yml": "1.0.96",
"prisma-yml": "1.0.100",
"raven": "2.3.0",
"replaceall": "^0.1.6",
"rwlockfile": "^1.4.8",
@@ -6937,9 +7239,9 @@
"dev": true
},
"prisma-yml": {
"version": "1.0.96",
"resolved": "https://registry.npmjs.org/prisma-yml/-/prisma-yml-1.0.96.tgz",
"integrity": "sha512-w3XGzJHUq5pwBoFy/amkGOcTDj4XoHh8UFUUUZcHo5fSyoF8AWeRTu1yWINaPVGxbcmpwKNetntAW4ijiq7M5g==",
"version": "1.0.100",
"resolved": "https://registry.npmjs.org/prisma-yml/-/prisma-yml-1.0.100.tgz",
"integrity": "sha512-W2a0dpfbXyapc3WZqcvUBqtsl2r9upQRUR2p53AqQR4tQz+/6nsMcqe30vqgnOW/WmNAnknqQT3Z5P0rsq4K3Q==",
"dev": true,
"requires": {
"ajv": "5",
@@ -6995,9 +7297,9 @@
}
},
"prisma-db-introspection": {
"version": "0.0.46",
"resolved": "https://registry.npmjs.org/prisma-db-introspection/-/prisma-db-introspection-0.0.46.tgz",
"integrity": "sha512-/b7evS9b5xKS7UrcOERkCmV+IWC6OAgFtInFsvdwn4MeLEaVbkOfzRakdOo+t2gb+N7Yy8Eey9eKYgB5jiJAbA==",
"version": "0.0.50",
"resolved": "https://registry.npmjs.org/prisma-db-introspection/-/prisma-db-introspection-0.0.50.tgz",
"integrity": "sha512-coeJ3SRumezVnsQwc/kwNzxWFUBKHNwnD+keUJeZFFY3j7EDtRFHoL5DD7vTREvMEugoWOiovc+MYHFkDt0l+w==",
"dev": true,
"requires": {
"ajv": "5",
@@ -7637,6 +7939,14 @@
"statuses": "~1.4.0"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -7799,6 +8109,14 @@
"use": "^3.1.0"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"define-property": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
@@ -7815,6 +8133,11 @@
"is-extendable": "^0.1.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -8061,9 +8384,9 @@
"dev": true
},
"string-similarity": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-1.2.1.tgz",
"integrity": "sha512-XqC6lRZF3UIYdxBRHjIfJwU2nYzPm+E8udKFHjIplnRQflkXP1A1Ie3HoEv04W/zY1wGnV6TQpklM2WwZO3gIA==",
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-1.2.2.tgz",
"integrity": "sha512-IoHUjcw3Srl8nsPlW04U3qwWPk3oG2ffLM0tN853d/E/JlIvcmZmDY2Kz5HzKp4lEi2T7QD7Zuvjq/1rDw+XcQ==",
"dev": true,
"requires": {
"lodash.every": "^4.6.0",
@@ -8463,6 +8786,11 @@
"yn": "^2.0.0"
}
},
"tslib": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -8492,9 +8820,9 @@
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
},
"unbzip2-stream": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz",
"integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==",
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.0.tgz",
"integrity": "sha512-kE2WkurNnPUMcryNioS68DDbhoPB8Qxsd8btHSj+sd5Pjh2GsjmeHLzMSqV9HHziAo8FzVxVCJl9ZYhk7yY1pA==",
"dev": true,
"requires": {
"buffer": "^3.0.1",
@@ -8532,8 +8860,28 @@
"integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=",
"requires": {
"debug": "^2.2.0"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
},
"union-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
+5 -1
View File
@@ -7,9 +7,13 @@
"dev": "npm-run-all --parallel debug playground"
},
"dependencies": {
"@azure/storage-blob": "^10.0.0-preview",
"azure-storage": "^2.10.1",
"cors": "^2.8.4",
"debug": "^4.0.1",
"dotenv": "^6.0.0",
"express-jwt": "^5.3.1",
"fast-xml-parser": "^3.12.5",
"graphql-import": "^0.6.0",
"graphql-tag": "^2.9.2",
"graphql-tools": "3.1.1",
@@ -23,6 +27,6 @@
"devDependencies": {
"graphql-cli": "^2.16.5",
"npm-run-all": "4.1.3",
"prisma": "^1.16.0"
"prisma": "^1.16.4"
}
}
+74 -3
View File
@@ -1,5 +1,5 @@
# source: http://localhost:4466
# timestamp: Wed Sep 12 2018 08:41:57 GMT-0700 (Pacific Daylight Time)
# timestamp: Thu Sep 20 2018 16:52:44 GMT-0700 (Pacific Daylight Time)
type AggregateFBStatus {
count: Int!
@@ -1400,7 +1400,9 @@ type TeamProfile {
description: String
motto: String
avatar: String
banner: String
updatedAt: DateTime!
createdAt: DateTime!
}
"""A connection to a list of items."""
@@ -1417,6 +1419,7 @@ input TeamProfileCreateInput {
description: String
motto: String
avatar: String
banner: String
}
input TeamProfileCreateOneInput {
@@ -1439,19 +1442,23 @@ enum TeamProfileOrderByInput {
motto_DESC
avatar_ASC
avatar_DESC
banner_ASC
banner_DESC
updatedAt_ASC
updatedAt_DESC
id_ASC
id_DESC
createdAt_ASC
createdAt_DESC
id_ASC
id_DESC
}
type TeamProfilePreviousValues {
description: String
motto: String
avatar: String
banner: String
updatedAt: DateTime!
createdAt: DateTime!
}
type TeamProfileSubscriptionPayload {
@@ -1497,12 +1504,14 @@ input TeamProfileUpdateDataInput {
description: String
motto: String
avatar: String
banner: String
}
input TeamProfileUpdateInput {
description: String
motto: String
avatar: String
banner: String
}
input TeamProfileUpdateOneInput {
@@ -1647,6 +1656,46 @@ input TeamProfileWhereInput {
"""All values not ending with the given string."""
avatar_not_ends_with: String
banner: String
"""All values that are not equal to given value."""
banner_not: String
"""All values that are contained in given list."""
banner_in: [String!]
"""All values that are not contained in given list."""
banner_not_in: [String!]
"""All values less than the given value."""
banner_lt: String
"""All values less than or equal the given value."""
banner_lte: String
"""All values greater than the given value."""
banner_gt: String
"""All values greater than or equal the given value."""
banner_gte: String
"""All values containing the given string."""
banner_contains: String
"""All values not containing the given string."""
banner_not_contains: String
"""All values starting with the given string."""
banner_starts_with: String
"""All values not starting with the given string."""
banner_not_starts_with: String
"""All values ending with the given string."""
banner_ends_with: String
"""All values not ending with the given string."""
banner_not_ends_with: String
updatedAt: DateTime
"""All values that are not equal to given value."""
@@ -1669,6 +1718,28 @@ input TeamProfileWhereInput {
"""All values greater than or equal the given value."""
updatedAt_gte: DateTime
createdAt: DateTime
"""All values that are not equal to given value."""
createdAt_not: DateTime
"""All values that are contained in given list."""
createdAt_in: [DateTime!]
"""All values that are not contained in given list."""
createdAt_not_in: [DateTime!]
"""All values less than the given value."""
createdAt_lt: DateTime
"""All values less than or equal the given value."""
createdAt_lte: DateTime
"""All values greater than the given value."""
createdAt_gt: DateTime
"""All values greater than or equal the given value."""
createdAt_gte: DateTime
}
type TeamStatus {
+1
View File
@@ -13,6 +13,7 @@ const TEAMS_FRAGMENT = gql`{
createdAt
profile {
avatar
banner
description
motto
updatedAt
+76 -3
View File
@@ -7,11 +7,32 @@ const {
} = require('prisma-binding')
const { makeExecutableSchema } = require('graphql-tools')
const { importSchema } = require('graphql-import')
const parser = require('fast-xml-parser')
const checkJwt = require('./auth/middleware/jwt')
const { getMember } = require('./auth/middleware/getMember')
const { validateIdToken } = require('./auth/validateIdToken')
const { directiveResolvers } = require('./auth/authDirectives')
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 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 TEAMS_FRAGMENT = require('./graphql/TeamsFragment')
const TEAMS_CONNECTIONS_FRAGMENT = require('./graphql/TeamsConnectionsFragment')
@@ -100,8 +121,8 @@ const resolvers = {
return err
})
},
async updateTeamProfile(parent, { slug, owner, description, motto, avatar }, ctx, info) {
return ctx.db.mutation.updateTeam({data:{profile: {update: {description: description, motto: motto, avatar: avatar}}}, where:{slug: slug}}, TEAMS_FRAGMENT)
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
@@ -115,6 +136,58 @@ const resolvers = {
return error.message
})
})
},
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
}
}
}
@@ -148,7 +221,7 @@ server.express.use(
server.options.endpoint,
checkJwt,
function (err, req, res, next) {
console.log('checkJwt: ', err, req)
// console.log('checkJwt: ', err, req)
if (err) {
return res.status(201).send(err.message)
} else {
+2 -6
View File
@@ -19,13 +19,9 @@ type Query {
type Mutation {
authenticate(idToken: String!): Member
createTeam(name: String!, slug: String!, owner: String!): Team @isAuthenticated
updateTeamProfile(slug: String!, owner: String!, description: String, motto: String, avatar: String): Team @isAuthenticated
updateTeamProfile(slug: String!, owner: String!, description: String, motto: String, avatar: String, banner: String): Team @isAuthenticated
deleteTeam(slug: String!): Team @isAuthenticated @isOwner(type: "Team")
}
input MemberProfileInput {
authId: String!
alias: String!
getAzureSAS(teamSlug: String!):String
}
fragment MemberInfo on Member {
+133
View File
@@ -0,0 +1,133 @@
const Azure = require('@azure/storage-blob')
/* 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) => {
return Azure.StorageURL.newPipeline(
new Azure.SharedKeyCredential(accountName, accountKey)
)
}
/* Create Azure Storage Service URL
* @storageURL: URL for Azure Storage endpoint (required) - Environment variable
* @pipeline: Azure Storage Pipline (required) - created using createStoragePipeline()
*/
const createServiceURL = async (storageURL, pipeline) => {
return new Azure.ServiceURL(
storageURL,
pipeline
)
}
/* List containers
* @pipeline: Azure Storage Pipline (required) - created using createServiceURL
* @service_url: URL for Azure Storage endpoint (required) - Environment variable
*/
const listContainers = async (serviceURL) => {
let marker;
do {
const listContainersResponse = await serviceURL.listContainersSegment(
Azure.Aborter.None,
marker,
);
marker = listContainersResponse.marker;
for (const container of listContainersResponse.containerItems) {
console.log(`Container: ${container.name}`);
}
} while (marker);
}
/* Create containers
* @serviceURL: URL for Azure Storage endpoint (required) - created using createServiceURL
* @containerName: Container Name
* Returns: containerURL
*/
const createContainer = async (serviceURL, containerName) => {
const containerURL = ContainerURL.fromServiceURL(serviceURL, containerName)
const createContainerResponse = await containerURL.create(Aborter.None)
console.log(
`Created container ${containerName} successfully`,
await createContainerResponse.requestId
)
return containerURL
}
/* Create containers
* @containerURL: continer URL (required) - created using createContainer
* @blobName: Blob Name
* Returns: blobURL
*/
const createBlob = async (containerURL, blobName) => {
const blobURL = Azure.BlobURL.fromContainerURL(containerURL, blobName)
console.log(`created blob successfully`, await blobURL)
return blobURL
}
/* Upload Blob
* @blobURL: blobURL (required) - created using createBlob
* @blobContent: Blob Content
* Returns: uploadBlobResponse
*/
const uploadBlob = async (blobURL, blobContent) => {
const blockBlobURL = Azure.BlockBlobURL.fromBlobURL(blobURL)
const uploadBlobResponse = await blockBlobURL.upload(
Azure.Aborter.None,
blobContent,
blobContent.length
);
console.log(`Upload block blob ${blobName} successfully`, await uploadBlobResponse)
return uploadBlobResponse
}
/* Download Blob
* @blobURL: blobURL (required) - created using createBlob
* @blobContent: Blob Content
* Returns: downloadBlockBlobResponse
*/
const downloadBlob = async (blobURL, blobContent) => {
const downloadBlockBlobResponse = await blobURL.download(Azure.Aborter.None, 0)
console.log(
"Downloaded blob content",
downloadBlockBlobResponse.readableStreamBody.read(content.length).toString()
)
console.log(`BlockBlobResponse: ${downloadBlockBlobResponse}`)
return downloadBlockBlobResponse
}
/* Delete Blob
* @blobURL: blobURL (required) - created using createBlob
* Returns: bool
*/
const deleteBlob = async (blobrURL) => {
await blobrURL.delete(Azure.Aborter.None);
console.log("deleted blob", blobrURL);
return true
}
/* Delete Container
* @containerURL: continer URL (required) - created using createContainer
* Returns: bool
*/
const deleteContainer = async (containerURL) => {
await containerURL.delete(Azure.Aborter.None);
console.log("deleted container", containerURL);
return true
}
module.exports = {
createStoragePipline,
createServiceURL,
listContainers,
createContainer,
createBlob,
uploadBlob,
downloadBlob,
deleteBlob,
deleteContainer
}
+2
View File
@@ -9,3 +9,5 @@ AUTH0_AUDIENCE=<auth0-audience>
AUTH0_ISSUER=<auth0-issuer>
AUTH0_CLIENTID=<auth0-clientid>
AUTH0_CALLBACKURL=<auth0-callbackurl>
AZURE_STORAGE_CONNECTION_STRING=<azure-connections-string>
+805 -196
View File
File diff suppressed because it is too large. Load diff
+8
View File
@@ -67,6 +67,7 @@
"workbox-cli": "^3.4.1"
},
"dependencies": {
"@azure/storage-blob": "^10.0.0-preview",
"@material-ui/core": "^3.0.3",
"@material-ui/icons": "^3.0.1",
"apollo-cache-inmemory": "^1.2.9",
@@ -78,7 +79,10 @@
"apollo-link-ws": "^1.0.8",
"apollo-utilities": "^1.0.20",
"auth0-lock": "^11.9.0",
"azure-storage": "^2.10.1",
"babel-polyfill": "^6.26.0",
"blob-util": "^2.0.2",
"browser-image-resizer": "^1.2.0",
"classnames": "^2.2.6",
"cross-fetch": "^2.2.2",
"dotenv-webpack": "^1.5.7",
@@ -88,8 +92,12 @@
"react": "^16.5.0",
"react-apollo": "^2.1.11",
"react-dom": "^16.5.0",
"react-dropzone": "^5.1.0",
"react-image-crop": "^5.0.0",
"react-image-cropper": "^1.3.0",
"react-router-dom": "^4.3.1",
"recompose": "^0.30.0",
"sharp": "^0.20.8",
"subscriptions-transport-ws": "^0.9.14"
},
"standard": {
@@ -18,6 +18,7 @@ export const GET_ALL_TEAMS_QUERY = gql`
createdAt
profile {
avatar
banner
description
motto
updatedAt
@@ -0,0 +1,10 @@
/* eslint-disable no-unused-vars */
import gql from 'graphql-tag'
export const GET_AZURE_SAS = gql`
mutation getAzureSAS($teamSlug: String!) {
getAzureSAS(teamSlug: $teamSlug)
}
`
export default GET_AZURE_SAS
@@ -16,6 +16,7 @@ export const GET_TEAMS_BY_OWNER = gql`
createdAt
profile {
avatar
banner
description
motto
updatedAt
+1
View File
@@ -15,6 +15,7 @@ export const TEAMS_FRAGMENT = gql`
createdAt
profile {
avatar
banner
description
motto
updatedAt
@@ -3,16 +3,20 @@ import gql from 'graphql-tag'
const UPDATE_TEAM_PROFILE = gql`
mutation UpdateTeamProfileMutation(
$slug: String!
$owner: String!
$description: String
$motto: String
$slug: String!,
$owner: String!,
$description: String,
$motto: String,
$avatar: String,
$banner: String
) {
updateTeamProfile(
slug: $slug
owner: $owner
description: $description
slug: $slug,
owner: $owner,
description: $description,
motto: $motto
avatar: $avatar,
banner: $banner
) {
id
name
@@ -26,6 +30,7 @@ const UPDATE_TEAM_PROFILE = gql`
createdAt
profile {
avatar
banner
description
motto
updatedAt
+345
View File
@@ -0,0 +1,345 @@
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, authId, 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, authId, 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,
authId: PropTypes.string.isRequired,
handleAvatar: PropTypes.func.isRequired,
handleBanner: PropTypes.func.isRequired
}
export default withStyles(styles)(UploadImage)
+2 -1
View File
@@ -1,3 +1,4 @@
import MessageCard from './MessageCard'
import UploadImage from './UploadImage'
export { MessageCard }
export { MessageCard, UploadImage }
@@ -5,10 +5,11 @@ import { withStyles } from '@material-ui/core/styles'
import Button from '@material-ui/core/Button'
import DetailsIcon from '@material-ui/icons/Details'
import Dialog from '@material-ui/core/Dialog'
import DialogActions from '@material-ui/core/DialogActions'
import DialogContent from '@material-ui/core/DialogContent'
import DialogTitle from '@material-ui/core/DialogTitle'
import Typography from '@material-ui/core/Typography'
import Card from '@material-ui/core/Card'
import CardContent from '@material-ui/core/CardContent'
import CardActions from '@material-ui/core/CardActions'
import CardMedia from '@material-ui/core/CardMedia'
const styles = theme => ({
dialogContainer: {
@@ -18,6 +19,33 @@ const styles = theme => ({
},
buttonRight: {
justifyContent: 'flex-end'
},
cardGrid: {
padding: `${theme.spacing.unit * 8}px 0`
},
card: {
display: 'flex',
width: '100%'
},
cardDetails: {
display: 'flex',
flex: 1
},
cardContent: {
flex: 1
},
cardAvatarMedia: {
flex: 1,
width: 100,
height: 100,
maxWidth: 100,
justifyContent: 'flex-start'
},
cardBannerMedia: {
flex: 1,
width: 600,
height: 150,
justifyContent: 'flex-start'
}
})
@@ -35,7 +63,20 @@ export class ManageTeamDetails extends Component {
render () {
console.log(this.props.team)
const { classes } = this.props
const { name, members, profile, createdAt } = this.props.team
let avatar
let banner
if (profile.avatar !== undefined && profile.avatar !== 'a') {
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'
}
if (profile.banner !== undefined && profile.banner !== 'a') {
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'
}
return (
<div>
<Button
@@ -51,51 +92,62 @@ export class ManageTeamDetails extends Component {
onClose={this.handleClose}
aria-labelledby='form-dialog-title'
>
<div classes={this.props.classes.dialogContainer}>
<DialogTitle id='form-dialog-title'>
{name} Team Details
</DialogTitle>
<DialogContent>
<Typography
variant='display3'
align='center'
color='textPrimary'
gutterBottom
>
{name}
</Typography>
<Typography variant='subheading' color='textSecondary'>
{createdAt}
</Typography>
<Typography variant='subheading' color='textSecondary'>
Motto: {profile.motto}
</Typography>
<Typography variant='subheading' color='textSecondary'>
Description: {profile.description}
</Typography>
<Typography variant='subheading' paragraph gutterBottom>
Members: {members.length}
</Typography>
<Typography variant='subheading' color='primary'>
Team Admin:&nbsp;
{members.map(member => {
if (member.role === 'OWNER' || member.role === 'ADMIN') {
if (
member.member !== null &&
<div classes={classes.dialogContainer}>
<Card className={classes.card}>
<CardContent>
<Typography variant='title' id='form-dialog-title'>
{name} Team Details
</Typography>
<CardMedia
className={classes.cardBannerMedia}
image={banner}
title={`${name} ${banner}`}
/>
<CardMedia
className={classes.cardAvatarMedia}
image={avatar}
title={`${name} ${avatar}`}
/>
<Typography
variant='display3'
align='center'
color='textPrimary'
gutterBottom
>
{name}
</Typography>
<Typography variant='subheading' color='textSecondary'>
{createdAt}
</Typography>
<Typography variant='subheading' color='textSecondary'>
Motto: {profile.motto}
</Typography>
<Typography variant='subheading' color='textSecondary'>
Description: {profile.description}
</Typography>
<Typography variant='subheading' paragraph gutterBottom>
Members: {members.length}
</Typography>
<Typography variant='subheading' color='primary'>
Team Admin:&nbsp;
{members.map(member => {
if (member.role === 'OWNER' || member.role === 'ADMIN') {
if (member.member !== null &&
member.member.alias !== undefined &&
member.member.alias !== null
) {
return member.member.alias
) {
return member.member.alias
}
}
}
})}
</Typography>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color='primary'>
Close
</Button>
</DialogActions>
})}
</Typography>
<CardActions>
<Button onClick={this.handleClose} color='primary'>
Close
</Button>
</CardActions>
</CardContent>
</Card>
</div>
</Dialog>
</div>
@@ -20,6 +20,8 @@ import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
import { checkGraphQLError } from '../../../utils/graphql-errors'
import { UploadImage } from '../../common'
const styles = theme => ({
dialogContainer: {
display: 'block',
@@ -39,13 +41,21 @@ export class ManageTeamEdit extends Component {
this.handleClose = this.handleClose.bind(this)
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.handleAvatar = this.handleAvatar.bind(this)
this.handleBanner = this.handleBanner.bind(this)
console.log('ManageTeamEdit', props.team)
const motto = props.team.profile.motto || ''
const description = props.team.profile.description || ''
const avatar = props.team.profile.avatar || ''
const banner = props.team.profile.banner || ''
this.state = {
open: false,
motto: motto,
description: description
description: description,
avatar: avatar,
banner: banner
}
}
@@ -101,6 +111,12 @@ export class ManageTeamEdit extends Component {
Edit Team Details
</DialogTitle>
<DialogContent>
<UploadImage
team={team}
authId={authId}
handleAvatar={this.handleAvatar}
handleBanner={this.handleBanner}
/>
<TextField
autoFocus
margin='dense'
@@ -178,7 +194,18 @@ export class ManageTeamEdit extends Component {
}
}
handleAvatar (avatarUrl) {
console.log('handleAvatar: ', avatarUrl)
this.setState({ avatar: avatarUrl })
}
handleBanner (bannerUrl) {
console.log('handleBanner: ', bannerUrl)
this.setState({ banner: bannerUrl })
}
async handleSubmit (e, updateTeamProfile, slug) {
console.log('handleSubmit: ', this.state)
e.preventDefault()
const currentUser = await getItem('user')
let authId = JSON.parse(currentUser)
@@ -188,7 +215,9 @@ export class ManageTeamEdit extends Component {
slug,
owner: authId,
description: this.state.description,
motto: this.state.motto
motto: this.state.motto,
avatar: this.state.avatar,
banner: this.state.banner
}
})
this.setState({ description: '', motto: '', open: false })
@@ -12,32 +12,41 @@ import ManageTeamDetails from './ManageTeamDetails'
import ManageTeamDelete from './ManageTeamDelete'
import ManageTeamEdit from './ManageTeamEdit'
export const ManageTeamsItem = ({ classes, team, authId }) => (
<Grid item xs={12}>
<Card className={classes.card}>
<div className={classes.cardDetails}>
<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} | Members: {team.members.length}
</Typography>
</CardContent>
<CardActions>
<ManageTeamDetails team={team} />
<ManageTeamEdit slug={team.slug} authId={authId} team={team} />
<ManageTeamDelete slug={team.slug} authId={authId} />
</CardActions>
</div>
</Card>
</Grid>
)
export const ManageTeamsItem = ({ classes, team, authId }) => {
console.log('ManageTeamsItem', team, team.profile, team.profile.avatar)
let avatar
if (team.profile.avatar !== undefined && team.profile.avatar !== 'a') {
avatar = team.profile.avatar
} else {
avatar = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22288%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20288%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_164edaf95ee%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A14pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_164edaf95ee%22%3E%3Crect%20width%3D%22288%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2296.32500076293945%22%20y%3D%22118.8%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
}
return (
<Grid item xs={12}>
<Card className={classes.card}>
<div className={classes.cardDetails}>
<CardMedia
className={classes.cardMedia}
image={avatar}
title={team.name}
/>
<CardContent className={classes.cardContent}>
<Typography gutterBottom variant='headline' component='h2'>
{team.name}
</Typography>
<Typography variant='caption' color='textSecondary'>
{team.createdAt} | Members: {team.members.length}
</Typography>
</CardContent>
<CardActions>
<ManageTeamDetails team={team} />
<ManageTeamEdit slug={team.slug} authId={authId} team={team} />
<ManageTeamDelete slug={team.slug} authId={authId} />
</CardActions>
</div>
</Card>
</Grid>
)
}
ManageTeamsItem.propTypes = {
classes: PropTypes.object.isRequired,
+2 -1
View File
@@ -40,7 +40,8 @@ module.exports = merge(commonConfig, {
loader: 'style-loader!css-loader!postcss-loader!sass-loader'
}
]
}
},
target: 'web'
})
module.exports.serve = {
+4 -3
View File
@@ -61,11 +61,12 @@ module.exports = merge(commonConfig, {
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{loader: 'css-loader', options: { importLoaders: 2 }},
{ loader: 'css-loader', options: { importLoaders: 2 } },
'postcss-loader',
{loader: 'sass-loader'}
{ loader: 'sass-loader' }
]
}
]
}
},
target: 'web'
})