Merge pull request #4 from AdvancedAlgos/develop
Refactor to Master App Build
This commit is contained in:
52 files changed
+2735
-6029
No files matched your search
@@ -1,9 +1,9 @@
|
||||
version: '3'
|
||||
services:
|
||||
api:
|
||||
image: advancedalgosteamsmodule/teammodule-api:v2
|
||||
env_file: ./.env.prod
|
||||
container_name: aateamapi
|
||||
image: advancedalgosteamsmodule/teammodule-api:v5
|
||||
env_file: ./.env
|
||||
container_name: aateamapi-imagetest
|
||||
tty: true
|
||||
stdin_open: true
|
||||
volumes:
|
||||
|
||||
+31
-14
@@ -152,27 +152,44 @@ const resolvers = {
|
||||
async createTeam(parent, { name, slug, botName, botSlug }, ctx, info) {
|
||||
console.log('createTeam ctx:', ctx.request.user)
|
||||
const authId = ctx.request.user.sub
|
||||
const encodedAuthId = encodeURI(authId)
|
||||
const getUserModuleUser = await axios.get(`https://users-api.advancedalgos.net/graphql?query=%7B%0A%20%20userByAuthId(authId%3A%22${encodedAuthId}%22)%7B%0A%20%20%20%20id%0A%09%09email%0A%20%20%20%20alias%0A%20%20%7D%0A%7D`)
|
||||
const encodedAuthId = encodeURI(`:"${authId}"`)
|
||||
const encodedURL = `https://users-api.advancedalgos.net/graphql?query=%7B%0A%20%20userByAuthId(authId${encodedAuthId})%7B%0A%20%20%20%20id%0A%09%09email%0A%20%20%20%20alias%0A%20%20%7D%0A%7D`
|
||||
const decodedURL = decodeURI(encodedURL)
|
||||
console.log('decoded URL: ', decodedURL)
|
||||
const getUserModuleUser = await axios.get(encodedURL)
|
||||
.then((result) => {
|
||||
console.log('getUserModuleUser:', result)
|
||||
return result
|
||||
})
|
||||
.catch(err =>{
|
||||
console.log('getUserModuleUser err:', err)
|
||||
})
|
||||
|
||||
console.log('getUserModuleUser:', await getUserModuleUser)
|
||||
const alias = await getUserModuleUser.data.data.userByAuthId.alias
|
||||
const email = getUserModuleUser.data.data.userByAuthId.email
|
||||
const avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
const banner = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-banner-default.png'
|
||||
/*
|
||||
const createTeamUrl = encodeURI(`${slug}/${name}/${alias}/${botSlug}`)
|
||||
const platformUrl = 'https://develop.advancedalgos.net/AABrowserAPI/teamSetup/'
|
||||
// const platformUrl = 'http://localhost:1337/AABrowserAPI/teamSetup/'
|
||||
|
||||
const createTeamUrl = encodeURI(`${slug}/${name}/${alias}/${botSlug}/${authId}`)
|
||||
// const platformUrl = 'https://develop.advancedalgos.net/AABrowserAPI/teamSetup/'
|
||||
const platformUrl = 'http://localhost:1337/AABrowserAPI/teamSetup/'
|
||||
const createPlatformTeam = await axios.get(`${platformUrl}${createTeamUrl}`)
|
||||
.then((result) => {
|
||||
console.log('createPlatformTeam:', result)
|
||||
if(result.data.message === 'Team Name already taken'){
|
||||
throw new Error(result.data.message)
|
||||
}
|
||||
return result
|
||||
})
|
||||
.catch(err =>{
|
||||
console.log('createPlatformTeam err:', err)
|
||||
throw new Error(err)
|
||||
})
|
||||
console.log('createPlatformTeam: ', await createPlatformTeam)
|
||||
|
||||
// const sessionToken = getUserModuleUser.data.data.userByAuthId.id
|
||||
update session token on user module
|
||||
const updateUserSession = await axios.post('https://users-api.advancedalgos.net/graphql', {
|
||||
query: 'mutation { language }'
|
||||
})
|
||||
|
||||
*/
|
||||
if(createPlatformTeam === 'Error: Team Name already taken'){
|
||||
return createPlatformTeam
|
||||
}
|
||||
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)
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"presets": ["@babel/preset-env", "@babel/preset-react"],
|
||||
"plugins": ["@babel/plugin-proposal-class-properties"]
|
||||
"env": {
|
||||
"development": {
|
||||
"presets": [["@babel/preset-react", { "development": true }]]
|
||||
}
|
||||
},
|
||||
"plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-syntax-dynamic-import", "dynamic-import-node"]
|
||||
}
|
||||
@@ -70,3 +70,7 @@ dist/
|
||||
|
||||
#Mac specific files
|
||||
.DS_Store
|
||||
|
||||
#yalc npm link
|
||||
.yalc
|
||||
yalc.lock
|
||||
@@ -0,0 +1,15 @@
|
||||
dist
|
||||
build
|
||||
node_modules
|
||||
html
|
||||
tools/docker
|
||||
tools/webpack
|
||||
.env
|
||||
.env.prod
|
||||
.env.sample
|
||||
.eslintrc
|
||||
docker-compose.yml
|
||||
Dockerfile
|
||||
postcss.config.js
|
||||
webpack.config.js
|
||||
.DS_Store
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>AlgoCommunity</title>
|
||||
<title>Advanced Algos Teams</title>
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="The AlgoCommunity is a collaborative setting for developing, competing and evolving Advanced Algos financial beings">
|
||||
|
||||
Generated
+2500
-4672
File diff suppressed because it is too large.
Load diff
+35
-37
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "aateam-client",
|
||||
"version": "0.0.1",
|
||||
"name": "@advancedalgos/teams-client",
|
||||
"version": "0.0.17",
|
||||
"description": "Advanced Algos Team client-side web app",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
@@ -18,9 +18,11 @@
|
||||
"author": "Barry Low <bearcanrun@gmail.com>",
|
||||
"license": "AGPL-3.0",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.1.2",
|
||||
"@babel/core": "^7.1.2",
|
||||
"@babel/plugin-proposal-class-properties": "^7.0.0",
|
||||
"@babel/preset-env": "^7.0.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.1.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"autoprefixer": "^8.6.5",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
@@ -28,19 +30,17 @@
|
||||
"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",
|
||||
"babel-plugin-transform-es2015-spread": "^6.22.0",
|
||||
"babel-plugin-transform-react-jsx": "^6.24.1",
|
||||
"connect-history-api-fallback": "^1.5.0",
|
||||
"css-loader": "^0.28.11",
|
||||
"eslint": "^5.5.0",
|
||||
"eslint-config-prettier": "^3.0.1",
|
||||
"eslint": "^5.6.1",
|
||||
"eslint-config-prettier": "^3.1.0",
|
||||
"eslint-config-standard": "^12.0.0",
|
||||
"eslint-config-standard-react": "^7.0.2",
|
||||
"eslint-plugin-import": "^2.14.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.1.1",
|
||||
"eslint-plugin-node": "^7.0.1",
|
||||
"eslint-plugin-prettier": "^2.6.2",
|
||||
"eslint-plugin-prettier": "^2.7.0",
|
||||
"eslint-plugin-promise": "^4.0.1",
|
||||
"eslint-plugin-react": "^7.11.1",
|
||||
"eslint-plugin-standard": "^4.0.0",
|
||||
@@ -48,58 +48,56 @@
|
||||
"html-webpack-harddisk-plugin": "^0.2.0",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"koa-connect": "^2.0.1",
|
||||
"mini-css-extract-plugin": "^0.4.2",
|
||||
"minilog": "^3.1.0",
|
||||
"mini-css-extract-plugin": "^0.4.4",
|
||||
"node-sass": "^4.9.3",
|
||||
"optimize-css-assets-webpack-plugin": "^4.0.3",
|
||||
"postcss-loader": "^2.1.6",
|
||||
"prettier": "^1.14.2",
|
||||
"prettier": "^1.14.3",
|
||||
"prettier-standard": "^8.0.1",
|
||||
"react-hot-loader": "^4.3.11",
|
||||
"sass-loader": "^6.0.7",
|
||||
"script-ext-html-webpack-plugin": "^2.0.1",
|
||||
"style-loader": "^0.21.0",
|
||||
"uglifyjs-webpack-plugin": "^1.3.0",
|
||||
"webpack": "^4.20.2",
|
||||
"webpack-cli": "^3.1.1",
|
||||
"webpack-bundle-analyzer": "^3.0.2",
|
||||
"webpack-cli": "^3.1.2",
|
||||
"webpack-hot-client": "^4.1.1",
|
||||
"webpack-merge": "^4.1.4",
|
||||
"webpack-serve": "^1.0.4",
|
||||
"workbox-build": "^3.4.1",
|
||||
"workbox-cli": "^3.4.1"
|
||||
"workbox-build": "^3.6.2",
|
||||
"workbox-cli": "^3.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@advancedalgos/web-components": "0.0.5",
|
||||
"@advancedalgos/web-components": "0.0.10",
|
||||
"@azure/storage-blob": "^10.0.0-preview",
|
||||
"@material-ui/core": "^3.0.3",
|
||||
"@material-ui/core": "^3.2.0",
|
||||
"@material-ui/icons": "^3.0.1",
|
||||
"apollo-cache-inmemory": "^1.2.9",
|
||||
"apollo-client": "^2.4.1",
|
||||
"apollo-link": "^1.2.2",
|
||||
"apollo-link-context": "^1.0.8",
|
||||
"apollo-link-error": "^1.1.0",
|
||||
"apollo-link-http": "^1.5.4",
|
||||
"apollo-link-ws": "^1.0.8",
|
||||
"apollo-utilities": "^1.0.20",
|
||||
"auth0-lock": "^11.9.0",
|
||||
"apollo-cache-inmemory": "^1.3.5",
|
||||
"apollo-client": "^2.4.2",
|
||||
"apollo-link": "^1.2.3",
|
||||
"apollo-link-context": "^1.0.9",
|
||||
"apollo-link-error": "^1.1.1",
|
||||
"apollo-link-http": "^1.5.5",
|
||||
"apollo-link-ws": "^1.0.9",
|
||||
"apollo-utilities": "^1.0.21",
|
||||
"auth0-lock": "^11.10.0",
|
||||
"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",
|
||||
"graphql": "^0.13.2",
|
||||
"graphql-tag": "^2.9.2",
|
||||
"graphql": "^14.0.2",
|
||||
"graphql-tag": "^2.10.0",
|
||||
"minilog": "^3.1.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"query-string": "^6.1.0",
|
||||
"react": "^16.5.0",
|
||||
"react-apollo": "^2.1.11",
|
||||
"react-dom": "^16.5.0",
|
||||
"react-dropzone": "^5.1.0",
|
||||
"react-image-cropper": "^1.3.0",
|
||||
"query-string": "^6.2.0",
|
||||
"react": "^16.5.2",
|
||||
"react-apollo": "^2.2.4",
|
||||
"react-dom": "^16.5.2",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"recompose": "^0.30.0",
|
||||
"sharp": "^0.20.8",
|
||||
"subscriptions-transport-ws": "^0.9.14"
|
||||
"subscriptions-transport-ws": "^0.9.15"
|
||||
},
|
||||
"standard": {
|
||||
"parser": "babel-eslint",
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
import { ApolloClient } from 'apollo-client'
|
||||
import { ApolloProvider } from 'react-apollo'
|
||||
import { HttpLink } from 'apollo-link-http'
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory'
|
||||
import { ApolloLink, split, Observable } from 'apollo-link'
|
||||
import { onError } from 'apollo-link-error'
|
||||
import { setContext } from 'apollo-link-context'
|
||||
import { WebSocketLink } from 'apollo-link-ws'
|
||||
import { SubscriptionClient } from 'subscriptions-transport-ws'
|
||||
import { getMainDefinition } from 'apollo-utilities'
|
||||
|
||||
import React, { Component } from 'react'
|
||||
import { Route, BrowserRouter, Switch } from 'react-router-dom'
|
||||
|
||||
import MuiThemeProvider from '@material-ui/core/styles/MuiThemeProvider'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import {
|
||||
NavBar,
|
||||
Footer,
|
||||
Callback,
|
||||
AcceptTeamInvite,
|
||||
Home,
|
||||
About,
|
||||
Dashboard,
|
||||
Teams,
|
||||
theme,
|
||||
globalStyles
|
||||
} from './views'
|
||||
|
||||
import Auth from './auth'
|
||||
|
||||
// import log from '../../tools/log'
|
||||
import { getItem } from './utils/local-storage'
|
||||
|
||||
const graphqlEndpoint =
|
||||
process.env.NODE_ENV === 'production'
|
||||
? process.env.PROD_GRAPHQL
|
||||
: process.env.DEV_GRAPHQL
|
||||
|
||||
const wsUri = graphqlEndpoint.replace(/^http/, 'ws')
|
||||
|
||||
const globalVar =
|
||||
typeof global !== 'undefined'
|
||||
? global
|
||||
: typeof window !== 'undefined'
|
||||
? window
|
||||
: {}
|
||||
const webSocketImpl = globalVar.WebSocket || globalVar.MozWebSocket
|
||||
|
||||
const wsClient = new SubscriptionClient(
|
||||
wsUri,
|
||||
{
|
||||
reconnect: true
|
||||
},
|
||||
webSocketImpl
|
||||
)
|
||||
|
||||
wsClient.onDisconnected(() => {
|
||||
// console.log('onDisconnected')
|
||||
})
|
||||
|
||||
wsClient.onReconnected(() => {
|
||||
// console.log('onReconnected')
|
||||
})
|
||||
|
||||
const httpLink = new HttpLink({ uri: graphqlEndpoint })
|
||||
const httpUserLink = new HttpLink({ uri: 'https://users-api.advancedalgos.net/graphql' })
|
||||
|
||||
const link = split(
|
||||
({ query }) => {
|
||||
const { kind, operation } = getMainDefinition(query)
|
||||
return kind === 'OperationDefinition' && operation === 'subscription'
|
||||
},
|
||||
new WebSocketLink(wsClient),
|
||||
httpLink
|
||||
)
|
||||
|
||||
const authRetryLink = onError(
|
||||
({ graphQLErrors, networkError, operation, forward }) => {
|
||||
if (graphQLErrors) {
|
||||
// User access token has expired
|
||||
// console.log('authLink: ', graphQLErrors) // check for error message to intercept and resend with Auth0 access token
|
||||
if (graphQLErrors[0].message === 'Not logged in') {
|
||||
// We assume we have auth0 access token needed to run the async request
|
||||
// Let's refresh token through async request
|
||||
return new Observable(observer => {
|
||||
getItem('access_token')
|
||||
.then(accessToken => {
|
||||
operation.setContext(({ headers = {} }) => ({
|
||||
headers: {
|
||||
// Re-add old headers
|
||||
...headers,
|
||||
// Switch out old access token for new one
|
||||
Authorization: `Bearer ${accessToken}` || null
|
||||
}
|
||||
}))
|
||||
})
|
||||
.then(() => {
|
||||
const subscriber = {
|
||||
next: observer.next.bind(observer),
|
||||
error: observer.error.bind(observer),
|
||||
complete: observer.complete.bind(observer)
|
||||
}
|
||||
|
||||
// Retry last failed request
|
||||
forward(operation).subscribe(subscriber)
|
||||
})
|
||||
.catch(error => {
|
||||
// No auth0 access token available, we force user to login
|
||||
observer.error(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const authLink = setContext(async (_, { headers }) => {
|
||||
// get the authentication token from local storage if it exists
|
||||
await getItem('access_token').then(token => {
|
||||
return {
|
||||
headers: {
|
||||
...headers,
|
||||
Authorization: token ? `Bearer ${token}` : ``
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const cache = new InMemoryCache().restore(window.__APOLLO_STATE__)
|
||||
|
||||
export const client = new ApolloClient({
|
||||
link: ApolloLink.from([authRetryLink, authLink, link]),
|
||||
cache,
|
||||
connectToDevTools: true
|
||||
})
|
||||
|
||||
export const UserClient = new ApolloClient({
|
||||
link: ApolloLink.from([authRetryLink, authLink, httpUserLink]),
|
||||
cache
|
||||
})
|
||||
|
||||
export const auth = new Auth(
|
||||
result => console.log('auth result', result),
|
||||
client
|
||||
)
|
||||
|
||||
class App extends Component {
|
||||
render () {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<ApolloProvider client={client}>
|
||||
<MuiThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<div className='App'>
|
||||
<NavBar auth={auth} />
|
||||
<Switch>
|
||||
<Route exact path='/' component={Home} />
|
||||
<Route exact path='/about' component={About} />
|
||||
<Route exact path='/teams' component={Teams} />
|
||||
<Route exact path='/teams/:slug' component={Teams} />
|
||||
<Route
|
||||
exact
|
||||
path='/(dashboard|manage-teams|team-members|financial-beings|settings)/'
|
||||
render={props => <Dashboard {...props} auth={auth} />}
|
||||
/>
|
||||
<Route
|
||||
path='/callback'
|
||||
render={props => {
|
||||
auth.handleAuthentication(props)
|
||||
return <Callback {...props} />
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path='/activate-team-membership'
|
||||
render={props => <AcceptTeamInvite {...props} auth={auth} />}
|
||||
/>
|
||||
</Switch>
|
||||
<Footer />
|
||||
</div>
|
||||
</MuiThemeProvider>
|
||||
</ApolloProvider>
|
||||
</BrowserRouter>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(globalStyles)(App)
|
||||
@@ -1,7 +0,0 @@
|
||||
export const AUTH_CONFIG = {
|
||||
api_audience: process.env.AUTH0_AUDIENCE,
|
||||
domain: process.env.AUTH0_DOMAIN,
|
||||
clientId: process.env.AUTH0_CLIENTID,
|
||||
callbackUrl: process.env.AUTH0_CALLBACK_URL,
|
||||
logoutUrl: process.env.AUTH0_LOGOUT_URL
|
||||
}
|
||||
@@ -1,268 +0,0 @@
|
||||
import Auth0Lock from 'auth0-lock'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
import { getItem, setItem, removeItem } from '../utils/local-storage'
|
||||
import { validObject, deleteCookie } from '../utils/js-helpers'
|
||||
|
||||
import { client } from '../App'
|
||||
|
||||
import { AUTH_CONFIG } from './Auth0' // create by renaming Auth0.sample.js to Auth0.js and setting vars
|
||||
|
||||
const AUTHENTICATE = gql`
|
||||
mutation authenticate($idToken: String!) {
|
||||
authenticate(idToken: $idToken) {
|
||||
alias
|
||||
authId
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const VERIFY_TEAM_INVITE = gql`
|
||||
mutation verifyTeamInvite($token: String!) {
|
||||
verifyTeamInvite(token: $token) {
|
||||
email
|
||||
team {
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const defaultOptions = {
|
||||
oidcConformant: true,
|
||||
autoclose: true,
|
||||
auth: {
|
||||
sso: true,
|
||||
redirectUrl: window.location.origin + '/callback',
|
||||
responseType: 'token id_token',
|
||||
audience: `${AUTH_CONFIG.api_audience}`,
|
||||
params: {
|
||||
scope: `openid profile email user_metadata app_metadata picture`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const inviteOptions = {
|
||||
oidcConformant: true,
|
||||
autoclose: false,
|
||||
allowedConnections: ['Username-Password-Authentication'],
|
||||
allowShowPassword: true,
|
||||
auth: {
|
||||
sso: false,
|
||||
redirectUrl: window.location.origin + '/callback',
|
||||
responseType: 'token id_token',
|
||||
audience: `${AUTH_CONFIG.api_audience}`,
|
||||
params: {
|
||||
state: '',
|
||||
scope: `email`
|
||||
}
|
||||
},
|
||||
prefill: { email: '' }
|
||||
}
|
||||
|
||||
let lock = new Auth0Lock(AUTH_CONFIG.clientId, AUTH_CONFIG.domain, defaultOptions)
|
||||
|
||||
class Auth {
|
||||
constructor (cb, apolloClient) {
|
||||
this.handleAuthentication()
|
||||
// binds functions to keep this context
|
||||
this.apolloClient = apolloClient
|
||||
this.cb = cb.bind(this)
|
||||
this.login = this.login.bind(this)
|
||||
this.loginInvite = this.loginInvite.bind(this)
|
||||
this.logout = this.logout.bind(this)
|
||||
this.isAuthenticated = this.isAuthenticated.bind(this)
|
||||
this.checkSession = this.checkSession.bind(this)
|
||||
}
|
||||
|
||||
login () {
|
||||
// Call the show method to display the widget.
|
||||
lock.show()
|
||||
}
|
||||
|
||||
async loginInvite (jwt) {
|
||||
let email
|
||||
let team
|
||||
try {
|
||||
const data = await client.mutate({
|
||||
mutation: VERIFY_TEAM_INVITE,
|
||||
variables: { token: jwt }
|
||||
})
|
||||
|
||||
console.log('loginInvite auth: ', await data.data.verifyTeamInvite)
|
||||
setItem('invite', JSON.stringify(data.data.verifyTeamInvite))
|
||||
|
||||
email = data.data.verifyTeamInvite.email
|
||||
team = data.data.verifyTeamInvite.team.slug
|
||||
} catch (err) {
|
||||
return console.log('loginInvite err: ', err)
|
||||
}
|
||||
inviteOptions.prefill.email = email
|
||||
inviteOptions.auth.params.state = `${email}|${team}`
|
||||
let lockInvite = new Auth0Lock(AUTH_CONFIG.clientId, AUTH_CONFIG.domain, inviteOptions)
|
||||
lockInvite.show()
|
||||
}
|
||||
|
||||
handleAuthentication () {
|
||||
// Add a callback for Lock's `authenticated` event
|
||||
lock.on('authenticated', this.setSession.bind(this))
|
||||
// Add a callback for Lock's `authorization_error` event
|
||||
lock.on('authorization_error', err => {
|
||||
console.log(err)
|
||||
const data = { status: `error`, errMessage: err.error }
|
||||
this.cb(data)
|
||||
})
|
||||
}
|
||||
|
||||
checkSession () {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Add a callback for Lock's `authenticated` event
|
||||
lock.checkSession(
|
||||
{
|
||||
responseType: 'token id_token',
|
||||
audience: AUTH_CONFIG.api_audience,
|
||||
scope:
|
||||
'openid email profile read:teams write:teams read:member write:member',
|
||||
connection: 'github',
|
||||
prompt: 'none'
|
||||
},
|
||||
function (err, authResult) {
|
||||
if (!err) {
|
||||
resolve(authResult)
|
||||
} else {
|
||||
reject(err)
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
setSession (authResult) {
|
||||
console.log('setSession')
|
||||
if (authResult && authResult.accessToken && authResult.idToken) {
|
||||
// Set the time that the access token will expire at
|
||||
let expiresAt = JSON.stringify(
|
||||
authResult.expiresIn * 1000 + new Date().getTime()
|
||||
)
|
||||
setItem('access_token', authResult.accessToken)
|
||||
setItem('id_token', authResult.idToken)
|
||||
setItem('expires_at', expiresAt)
|
||||
const data = {
|
||||
status: `success`,
|
||||
accessToken: authResult.accessToken,
|
||||
idToken: authResult.idToken,
|
||||
expiresAt
|
||||
}
|
||||
console.log('setSession idTokenPayload: ', authResult.idTokenPayload)
|
||||
|
||||
this.signinOrCreateAccount({ ...data })
|
||||
this.cb(data)
|
||||
console.log(authResult.idTokenPayload)
|
||||
const user = {
|
||||
authId: authResult.idTokenPayload.sub,
|
||||
alias: authResult.idTokenPayload.nickname
|
||||
}
|
||||
setItem('user', JSON.stringify(user))
|
||||
if (window.location.href.includes(`callback`)) {
|
||||
// window.location.href = '/dashboard'
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
async signinOrCreateAccount ({ accessToken, idToken, expiresAt }) {
|
||||
console.log(
|
||||
'signinOrCreateAccount: ',
|
||||
client,
|
||||
this.apolloClient,
|
||||
accessToken,
|
||||
idToken,
|
||||
expiresAt
|
||||
)
|
||||
try {
|
||||
const data = await client.mutate({
|
||||
mutation: AUTHENTICATE,
|
||||
variables: { idToken }
|
||||
})
|
||||
|
||||
console.log('signinOrCreateAccount auth: ', await data)
|
||||
const user = {
|
||||
authId: data.data.authenticate.authId,
|
||||
alias: data.data.authenticate.alias
|
||||
}
|
||||
setItem('user', JSON.stringify(user))
|
||||
if (window.location.href.includes(`callback`)) {
|
||||
window.location.href = '/dashboard'
|
||||
}
|
||||
return data
|
||||
} catch (err) {
|
||||
return console.log('Sign in or create account error: ', err)
|
||||
}
|
||||
}
|
||||
|
||||
logout () {
|
||||
// Clear access token and ID token from local storage
|
||||
removeItem('access_token')
|
||||
removeItem('id_token')
|
||||
removeItem('expires_at')
|
||||
removeItem('user')
|
||||
removeItem('auth0.ssodata')
|
||||
window.localStorage.clear()
|
||||
deleteCookie('ajs_anonymous_id')
|
||||
deleteCookie('ajs_user_id')
|
||||
deleteCookie('current_tenant')
|
||||
|
||||
lock.logout({ returnTo: AUTH_CONFIG.logoutUrl })
|
||||
console.log('logout')
|
||||
}
|
||||
|
||||
async isAuthenticated () {
|
||||
// check session and run Auth0 SS0
|
||||
const getUser = await getItem('user')
|
||||
const getExpires = await getItem('expires_at')
|
||||
let user = JSON.parse(getUser)
|
||||
|
||||
if (new Date().getTime() < getExpires * 1000) {
|
||||
console.log(
|
||||
'handleAuth.user exp: ',
|
||||
user,
|
||||
getExpires,
|
||||
window.location.href
|
||||
)
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
const checkSSO = await this.checkSession()
|
||||
.then(result => {
|
||||
console.log('handleAuth.checksessions: ', result)
|
||||
const user = {
|
||||
authId: result.idTokenPayload.sub,
|
||||
alias: result.idTokenPayload.nickname
|
||||
}
|
||||
setItem('user', JSON.stringify(user))
|
||||
// user confirmed, log into client
|
||||
this.setSession(result)
|
||||
return result.idTokenPayload
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('handleAuth.checksessions err: ', err)
|
||||
if (err.error === 'login_required') {
|
||||
// return this.login()
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
if (/manage|profile|create|dashboard/.test(window.location.href) && !user) {
|
||||
this.login()
|
||||
}
|
||||
|
||||
if (validObject(checkSSO, 'error')) {
|
||||
return false
|
||||
} else {
|
||||
return checkSSO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Auth
|
||||
@@ -3,7 +3,7 @@ import gql from 'graphql-tag'
|
||||
|
||||
export const GET_ALL_TEAMS_QUERY = gql`
|
||||
query teamsQuery {
|
||||
teams {
|
||||
TeamsModuleTeams {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
|
||||
+40
-22
@@ -1,26 +1,44 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Route, BrowserRouter, Switch } from 'react-router-dom'
|
||||
import { hot } from 'react-hot-loader'
|
||||
|
||||
import App from './App'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import {
|
||||
AcceptTeamInvite,
|
||||
Dashboard,
|
||||
Teams,
|
||||
globalStyles
|
||||
} from './views'
|
||||
|
||||
import log from '../tools/log'
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root'))
|
||||
|
||||
let frontendReloadCount = 0
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
if (module.hot) {
|
||||
module.hot.accept()
|
||||
|
||||
module.hot.accept('./index', () => {
|
||||
try {
|
||||
log.debug('Updating front-end')
|
||||
frontendReloadCount = (frontendReloadCount || 0) + 1
|
||||
} catch (err) {
|
||||
log(err.stack)
|
||||
}
|
||||
})
|
||||
class App extends Component {
|
||||
render () {
|
||||
return (
|
||||
<BrowserRouter basename={window.location.pathname}>
|
||||
<div className='App'>
|
||||
<Switch>
|
||||
<Route exact path='/' component={Teams} />
|
||||
<Route exact path='/:slug' component={Teams} />
|
||||
<Route
|
||||
exact
|
||||
path='/(dashboard|manage-teams|team-members|financial-beings|settings)/'
|
||||
render={props => <Dashboard {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path='/activate-team-membership'
|
||||
render={props => <AcceptTeamInvite {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
</Switch>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
App.propTypes = {
|
||||
auth: PropTypes.object
|
||||
}
|
||||
|
||||
const StyledApp = withStyles(globalStyles)(App)
|
||||
export default hot(module)(StyledApp)
|
||||
@@ -68,3 +68,13 @@ export function slugify (string) {
|
||||
.replace(/^-+/, '') // Trim - from start of text
|
||||
.replace(/-+$/, '') // Trim - from end of text
|
||||
}
|
||||
|
||||
export function parse (queryString) {
|
||||
var query = {}
|
||||
var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&')
|
||||
for (var i = 0; i < pairs.length; i++) {
|
||||
var pair = pairs[i].split('=')
|
||||
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '')
|
||||
}
|
||||
return query
|
||||
}
|
||||
@@ -1,34 +1,8 @@
|
||||
const getStateFromStorage = version => {
|
||||
const localState = JSON.parse(window.localStorage.getItem('aa-team'))
|
||||
|
||||
try {
|
||||
if (localState !== undefined && localState !== null) {
|
||||
if (
|
||||
localState.appVersion !== undefined &&
|
||||
localState.appVersion !== null
|
||||
) {
|
||||
if (localState.appVersion === version) {
|
||||
return localState
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Error()
|
||||
}
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const storeStateInStorage = state =>
|
||||
window.localStorage.setItem('aa-team', JSON.stringify(state))
|
||||
|
||||
const getItem = async name => window.localStorage.getItem(name)
|
||||
const setItem = async (name, value) => window.localStorage.setItem(name, value)
|
||||
const removeItem = async name => window.localStorage.removeItem(name)
|
||||
|
||||
export {
|
||||
getStateFromStorage,
|
||||
storeStateInStorage,
|
||||
getItem,
|
||||
setItem,
|
||||
removeItem
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
const styles = theme => ({
|
||||
'@global': {
|
||||
body: {
|
||||
backgroundColor: theme.palette.common.white
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
width: 'auto',
|
||||
marginLeft: theme.spacing.unit * 3,
|
||||
marginRight: theme.spacing.unit * 3,
|
||||
[theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 900,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto'
|
||||
}
|
||||
},
|
||||
heroContent: {
|
||||
maxWidth: 600,
|
||||
margin: '0 auto',
|
||||
padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px`
|
||||
}
|
||||
})
|
||||
|
||||
const About = ({ classes }) => (
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<main className={classes.layout}>
|
||||
<div className={classes.heroContent}>
|
||||
<Typography
|
||||
variant='display1'
|
||||
align='center'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
>
|
||||
Welcome to Advanced Algos Teams!
|
||||
</Typography>
|
||||
<Typography
|
||||
variant='title'
|
||||
align='center'
|
||||
color='textSecondary'
|
||||
component='h3'
|
||||
>
|
||||
This module is responsible for managing teams and their members across
|
||||
the Advanced Algos system. You can browser teams and their details,
|
||||
and with an account, create and manage your own teams.
|
||||
</Typography>
|
||||
<Typography align='center' color='textSecondary' component='p'>
|
||||
<strong>Development Status</strong>
|
||||
<br />
|
||||
This module is is currently under heavy development. Implementation
|
||||
started 1st of September 2018 and this is the result of the 1st sprint
|
||||
of 2 weeks of work.
|
||||
</Typography>
|
||||
<Typography align='center' color='textSecondary' component='p'>
|
||||
<strong>What can you do?</strong>
|
||||
<br />
|
||||
Basic team creation and management.
|
||||
</Typography>
|
||||
<Typography align='center' color='textSecondary' component='p'>
|
||||
<strong>What is next?</strong>
|
||||
<br />
|
||||
<ol>
|
||||
<li> Managing team profile images.</li>
|
||||
<li>
|
||||
{' '}
|
||||
Managing team members - inviting members and administrating roles
|
||||
</li>
|
||||
<li>
|
||||
{' '}
|
||||
More detailed team profiles + allowing members to apply to
|
||||
recruiting teams
|
||||
</li>
|
||||
</ol>
|
||||
</Typography>
|
||||
</div>
|
||||
</main>
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
About.propTypes = {
|
||||
classes: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(About)
|
||||
@@ -1,7 +0,0 @@
|
||||
import React from 'react'
|
||||
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
const Callback = () => <MessageCard message='Authenticating...' />
|
||||
|
||||
export default Callback
|
||||
@@ -14,7 +14,7 @@ const styles = theme => ({
|
||||
|
||||
const FinancialBeings = ({ classes }) => (
|
||||
<div>
|
||||
<Typography variant='display1' gutterBottom>
|
||||
<Typography variant='h4' gutterBottom>
|
||||
Financial Beings
|
||||
</Typography>
|
||||
<ManageFBList />
|
||||
|
||||
@@ -14,7 +14,7 @@ const styles = theme => ({
|
||||
|
||||
const ManageTeams = ({ classes }) => (
|
||||
<div>
|
||||
<Typography variant='display1' gutterBottom>
|
||||
<Typography variant='h4' gutterBottom>
|
||||
Manage Your Teams
|
||||
</Typography>
|
||||
<ManageTeamsList />
|
||||
|
||||
@@ -15,7 +15,7 @@ const styles = theme => ({
|
||||
|
||||
const TeamMembers = ({ classes }) => (
|
||||
<div>
|
||||
<Typography variant='display1' gutterBottom>
|
||||
<Typography variant='h4' gutterBottom>
|
||||
Team Members
|
||||
<MessageCard message='Coming soon. Invite and manage team members.' />
|
||||
</Typography>
|
||||
|
||||
@@ -80,7 +80,7 @@ export class CreateTeamDialog extends Component {
|
||||
let loader = null
|
||||
if (loading) {
|
||||
loader = (
|
||||
<Typography variant='subheading'>Submitting team...</Typography>
|
||||
<Typography variant='subtitle1'>Submitting team...</Typography>
|
||||
)
|
||||
}
|
||||
if (error) {
|
||||
@@ -116,7 +116,7 @@ export class CreateTeamDialog extends Component {
|
||||
required
|
||||
error={this.state.nameError !== '' || this.state.botNameError !== '' || error !== null}
|
||||
>
|
||||
<Typography variant='subheading' align='center'>Create a name for your team</Typography>
|
||||
<Typography variant='subtitle1' align='center'>Create a name for your team</Typography>
|
||||
<TextField
|
||||
autoFocus
|
||||
margin='dense'
|
||||
@@ -132,7 +132,7 @@ export class CreateTeamDialog extends Component {
|
||||
{this.state.nameError !== '' && (
|
||||
<FormHelperText>{this.state.nameError}</FormHelperText>
|
||||
)}
|
||||
<Typography variant='subheading' align='center' ><br />
|
||||
<Typography variant='subtitle1' align='center' ><br />
|
||||
Create a name for your teams bot.
|
||||
</Typography>
|
||||
<Typography align='center' >
|
||||
@@ -209,7 +209,7 @@ export class CreateTeamDialog extends Component {
|
||||
e.preventDefault()
|
||||
console.log('createTeam submit: ', name, botName)
|
||||
const slug = this.slugify(name)
|
||||
const botSlug = this.slugify(name)
|
||||
const botSlug = this.slugify(botName)
|
||||
await createTeam({ variables: { name, slug, botName, botSlug } })
|
||||
this.setState({ name: '', open: false })
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ export class CreateTeamDialog extends Component {
|
||||
onClick={this.handleClickOpen}
|
||||
>
|
||||
<AddIcon className={this.props.classes.extendedIcon} />
|
||||
<Typography variant='subheading'>Create A Team</Typography>
|
||||
<Typography variant='subtitle1'>Create A Team</Typography>
|
||||
</Button>
|
||||
<Dialog
|
||||
open={this.state.open}
|
||||
@@ -69,7 +69,7 @@ export class CreateTeamDialog extends Component {
|
||||
>
|
||||
<DialogTitle id='form-dialog-title'>Subscribe</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography variant='subheading'>Team Creation</Typography>
|
||||
<Typography variant='subtitle1'>Team Creation</Typography>
|
||||
<DialogContentText>Name your team!</DialogContentText>
|
||||
<TextField
|
||||
autoFocus
|
||||
|
||||
@@ -13,7 +13,7 @@ import aaweb from '../../../assets/AlgonetWebPlatform.jpg'
|
||||
|
||||
export const DashEditor = ({ classes }) => (
|
||||
<Grid item md={6}>
|
||||
<Typography variant='display1' gutterBottom>
|
||||
<Typography variant='h4' gutterBottom>
|
||||
Develop
|
||||
</Typography>
|
||||
<Grid container spacing={24}>
|
||||
@@ -25,7 +25,7 @@ export const DashEditor = ({ classes }) => (
|
||||
title='Image title'
|
||||
/>
|
||||
<CardActions>
|
||||
<Typography variant='title' color='inherit' aligh='right'>
|
||||
<Typography variant='h6' color='inherit' aligh='right'>
|
||||
<Button>Start Developing ></Button>
|
||||
</Typography>
|
||||
</CardActions>
|
||||
|
||||
@@ -29,7 +29,7 @@ export const DashTeam = ({ classes, user = null }) => {
|
||||
if (authId === undefined || authId === null) {
|
||||
return (
|
||||
<Grid item md={6}>
|
||||
<Typography variant='display1' gutterBottom>
|
||||
<Typography variant='h4' gutterBottom>
|
||||
Teams
|
||||
</Typography>
|
||||
<Typography variant='caption'>Loading...</Typography>
|
||||
@@ -38,7 +38,7 @@ export const DashTeam = ({ classes, user = null }) => {
|
||||
}
|
||||
return (
|
||||
<Grid item md={6} style={{ position: 'relative' }}>
|
||||
<Typography variant='display1' gutterBottom>
|
||||
<Typography variant='h4' gutterBottom>
|
||||
Teams{' '}
|
||||
<Link to='/manage-teams' className={classes.dashLink}>
|
||||
Manage Teams
|
||||
@@ -84,7 +84,7 @@ export const DashTeam = ({ classes, user = null }) => {
|
||||
} else {
|
||||
return (
|
||||
<Grid container spacing={24}>
|
||||
<Typography variant='subheading' gutterBottom>
|
||||
<Typography variant='subtitle1' gutterBottom>
|
||||
Loading...
|
||||
</Typography>
|
||||
{queryLoader}
|
||||
|
||||
@@ -47,11 +47,11 @@ export const DashTeamItem = ({ classes, team }) => (
|
||||
title='Image title'
|
||||
/>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography variant='headline'>{team.name}</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
<Typography variant='h5'>{team.name}</Typography>
|
||||
<Typography variant='subtitle1' color='textSecondary'>
|
||||
{team.createdAt}
|
||||
</Typography>
|
||||
<Typography variant='subheading' paragraph>
|
||||
<Typography variant='subtitle1' paragraph>
|
||||
Members: {team.members.length}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
|
||||
@@ -65,7 +65,7 @@ export class InviteMemberDialog extends Component {
|
||||
let loader = null
|
||||
if (loading) {
|
||||
loader = (
|
||||
<Typography variant='subheading'>Submitting invitation...</Typography>
|
||||
<Typography variant='subtitle1'>Submitting invitation...</Typography>
|
||||
)
|
||||
}
|
||||
if (error) {
|
||||
@@ -120,7 +120,7 @@ export class InviteMemberDialog extends Component {
|
||||
</FormControl>
|
||||
)}
|
||||
{data !== undefined && data.sendMemberInviteSG === 'Success' && (
|
||||
<Typography variant='subheading'>Invitation successfully sent!</Typography>
|
||||
<Typography variant='subtitle1'>Invitation successfully sent!</Typography>
|
||||
)}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
|
||||
@@ -28,7 +28,7 @@ export const ManageFBItem = ({ classes, team, authId }) => {
|
||||
title={team.name}
|
||||
/>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography gutterBottom variant='headline' component='h2'>
|
||||
<Typography gutterBottom variant='h5' component='h2'>
|
||||
{team.fb[0].name}
|
||||
</Typography>
|
||||
<Typography variant='caption' color='textSecondary'>
|
||||
|
||||
@@ -100,10 +100,10 @@ export class ManageMemberDelete extends Component {
|
||||
Remove Team Member
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography variant='subheading' color='primary'>
|
||||
<Typography variant='subtitle1' color='primary'>
|
||||
DANGER - Removing your team cannot be undone
|
||||
</Typography>
|
||||
<Typography variant='subheading'>
|
||||
<Typography variant='subtitle1'>
|
||||
Are you sure you want to remove this team member?
|
||||
</Typography>
|
||||
{loader}
|
||||
|
||||
@@ -108,7 +108,7 @@ export class ManageMemberRole extends Component {
|
||||
Set Team Member Role
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography variant='subheading'>
|
||||
<Typography variant='subtitle1'>
|
||||
Admin members can approve new team members, send team invitations, and remove team members.
|
||||
</Typography>
|
||||
<TextField
|
||||
|
||||
@@ -67,12 +67,12 @@ export class ManageMemberStatus extends Component {
|
||||
<div classes={classes.dialogContainer}>
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<Typography variant='title' id='form-dialog-title'>
|
||||
<Typography variant='h6' id='form-dialog-title'>
|
||||
Member Status Details
|
||||
</Typography>
|
||||
{status !== null && status.map(stat => {
|
||||
return (
|
||||
<Typography variant='title' id='form-dialog-title' key={stat.createdAt}>
|
||||
<Typography variant='h6' id='form-dialog-title' key={stat.createdAt}>
|
||||
{stat.status} | {stat.reason} | {stat.createdAt}
|
||||
</Typography>
|
||||
)
|
||||
|
||||
@@ -25,7 +25,7 @@ export const ManageMembersItem = ({ classes, member, teamId, authId }) => {
|
||||
return (
|
||||
<Grid container className={classes.memberContainer}>
|
||||
<Grid item xs={4}>
|
||||
<Typography gutterBottom variant='subheading' component='h2' align='left' >
|
||||
<Typography gutterBottom variant='subtitle1' component='h2' align='left' >
|
||||
{profile !== null ? profile.alias : email}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
@@ -79,7 +79,7 @@ export const ManageMembersTeamItem = ({ classes, team, authId }) => {
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<Typography gutterBottom variant='headline' component='h2'>
|
||||
<Typography gutterBottom variant='h5' component='h2'>
|
||||
{team.name}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
||||
@@ -105,10 +105,10 @@ export class ManageTeamDelete extends Component {
|
||||
Delete Team Team
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography variant='subheading' color='primary'>
|
||||
<Typography variant='subtitle1' color='primary'>
|
||||
DANGER - Deleting your team cannot be undone
|
||||
</Typography>
|
||||
<Typography variant='subheading'>
|
||||
<Typography variant='subtitle1'>
|
||||
Are you sure you want to delete this team?
|
||||
</Typography>
|
||||
{loader}
|
||||
|
||||
@@ -95,7 +95,7 @@ export class ManageTeamDetails extends Component {
|
||||
<div classes={classes.dialogContainer}>
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<Typography variant='title' id='form-dialog-title'>
|
||||
<Typography variant='h6' id='form-dialog-title'>
|
||||
{name} Team Details
|
||||
</Typography>
|
||||
<CardMedia
|
||||
@@ -109,26 +109,26 @@ export class ManageTeamDetails extends Component {
|
||||
title={`${name} ${avatar}`}
|
||||
/>
|
||||
<Typography
|
||||
variant='display3'
|
||||
variant='h2'
|
||||
align='center'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
>
|
||||
{name}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
<Typography variant='subtitle1' color='textSecondary'>
|
||||
{createdAt}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
<Typography variant='subtitle1' color='textSecondary'>
|
||||
Motto: {profile.motto}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
<Typography variant='subtitle1' color='textSecondary'>
|
||||
Description: {profile.description}
|
||||
</Typography>
|
||||
<Typography variant='subheading' paragraph gutterBottom>
|
||||
<Typography variant='subtitle1' paragraph gutterBottom>
|
||||
Members: {members.length}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='primary'>
|
||||
<Typography variant='subtitle1' color='primary'>
|
||||
Team Admin:
|
||||
{members.map(member => {
|
||||
if (member.role === 'OWNER' || member.role === 'ADMIN') {
|
||||
|
||||
@@ -125,12 +125,12 @@ export class ManageTeamEdit extends Component {
|
||||
}
|
||||
|
||||
let avatar = null
|
||||
if (this.state.avatar !== null) avatar = this.state.avatar
|
||||
if (team.profile !== null && team.profile.avatar !== undefined && team.profile.avatar !== null) avatar = team.profile.avatar
|
||||
if (this.state.avatar !== null) avatar = this.state.avatar
|
||||
if (this.state.avatar === null && team.profile !== null && team.profile.avatar === undefined) avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
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) banner = this.state.banner
|
||||
if (this.state.banner === null && team.profile !== null && team.profile.banner === undefined) banner = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-banner-default.png'
|
||||
console.log('team images: ', avatar, banner)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ export const ManageTeamsItem = ({ classes, team, authId }) => {
|
||||
title={team.name}
|
||||
/>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography gutterBottom variant='headline' component='h2'>
|
||||
<Typography gutterBottom variant='h5' component='h2'>
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography variant='caption' color='textSecondary'>
|
||||
|
||||
@@ -14,7 +14,7 @@ const styles = theme => ({
|
||||
|
||||
export const Settings = ({ classes }) => (
|
||||
<div>
|
||||
<Typography variant='display1' gutterBottom>
|
||||
<Typography variant='h4' gutterBottom>
|
||||
Settings
|
||||
</Typography>
|
||||
<div className={classes.tableContainer}>
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { NavLink } from 'react-router-dom'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import classNames from 'classnames'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
|
||||
import aalogo from '../../assets/logos/advanced-algos/aa-logo-vert.svg'
|
||||
|
||||
const styles = theme => ({
|
||||
'@global': {
|
||||
body: {
|
||||
backgroundColor: theme.palette.common.white
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
width: 'auto',
|
||||
marginLeft: theme.spacing.unit * 3,
|
||||
marginRight: theme.spacing.unit * 3,
|
||||
[theme.breakpoints.up(1200 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 1200,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto'
|
||||
}
|
||||
},
|
||||
footer: {
|
||||
borderTop: `1px solid ${theme.palette.divider}`,
|
||||
padding: `${theme.spacing.unit * 6}px 0`
|
||||
},
|
||||
footerContainer: {
|
||||
marginRight: theme.spacing.unit * 8,
|
||||
marginLeft: theme.spacing.unit * 8
|
||||
},
|
||||
footerLink: {
|
||||
textDecoration: 'none'
|
||||
}
|
||||
})
|
||||
|
||||
const Footer = ({ classes }) => {
|
||||
return (
|
||||
<footer className={classNames(classes.footer, classes.layout)}>
|
||||
<Grid
|
||||
container
|
||||
spacing={32}
|
||||
justify='space-evenly'
|
||||
className={classNames(classes.footerContainer)}
|
||||
>
|
||||
<Grid item xs>
|
||||
<Typography variant='title' color='textPrimary' gutterBottom>
|
||||
Pages
|
||||
</Typography>
|
||||
<NavLink to='/' className={classNames(classes.footerLink)}>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
Home
|
||||
</Typography>
|
||||
</NavLink>
|
||||
<NavLink to='/teams' className={classNames(classes.footerLink)}>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
Teams
|
||||
</Typography>
|
||||
</NavLink>
|
||||
<NavLink to='/about' className={classNames(classes.footerLink)}>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
About
|
||||
</Typography>
|
||||
</NavLink>
|
||||
</Grid>
|
||||
<Grid item xs>
|
||||
<a
|
||||
href='https://t.me/advancedalgoscommunity'
|
||||
target='_blank>'
|
||||
className={classNames(classes.footerLink)}
|
||||
>
|
||||
<Typography variant='title' color='textPrimary' gutterBottom>
|
||||
Support
|
||||
</Typography>
|
||||
</a>
|
||||
<a
|
||||
href='https://advancedalgos.net/documentation-quick-start.shtml'
|
||||
target='_blank>'
|
||||
className={classNames(classes.footerLink)}
|
||||
>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
Documentation
|
||||
</Typography>
|
||||
</a>
|
||||
<NavLink to='/' className={classNames(classes.footerLink)}>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
Telegram
|
||||
</Typography>
|
||||
</NavLink>
|
||||
</Grid>
|
||||
<Grid item xs>
|
||||
<Typography variant='title' color='textPrimary' gutterBottom>
|
||||
Modules
|
||||
</Typography>
|
||||
<NavLink to='/' className={classNames(classes.footerLink)}>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
Teams
|
||||
</Typography>
|
||||
</NavLink>
|
||||
<NavLink to='/' className={classNames(classes.footerLink)}>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
Users
|
||||
</Typography>
|
||||
</NavLink>
|
||||
<NavLink to='/' className={classNames(classes.footerLink)}>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
KeyVault
|
||||
</Typography>
|
||||
</NavLink>
|
||||
</Grid>
|
||||
<Grid item xs>
|
||||
<NavLink to='/'>
|
||||
<img src={aalogo} width={98} height={140} />
|
||||
</NavLink>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
|
||||
Footer.propTypes = {
|
||||
classes: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(Footer)
|
||||
@@ -1,61 +0,0 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
const styles = theme => ({
|
||||
'@global': {
|
||||
body: {
|
||||
backgroundColor: theme.palette.common.white
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
width: 'auto',
|
||||
marginLeft: theme.spacing.unit * 3,
|
||||
marginRight: theme.spacing.unit * 3,
|
||||
[theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 900,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto'
|
||||
}
|
||||
},
|
||||
heroContent: {
|
||||
maxWidth: 600,
|
||||
margin: '0 auto',
|
||||
padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px`
|
||||
}
|
||||
})
|
||||
|
||||
const Home = ({ classes }) => (
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<main className={classes.layout}>
|
||||
<div className={classes.heroContent}>
|
||||
<Typography
|
||||
variant='display3'
|
||||
align='center'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
>
|
||||
Collaborate. Innovate. Evolve.
|
||||
</Typography>
|
||||
<Typography
|
||||
variant='title'
|
||||
align='center'
|
||||
color='textSecondary'
|
||||
component='h3'
|
||||
>
|
||||
Welcome to Advanced Algos Teams
|
||||
</Typography>
|
||||
</div>
|
||||
</main>
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
Home.propTypes = {
|
||||
classes: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(Home)
|
||||
@@ -1,8 +1,3 @@
|
||||
import NavBar from './navbar'
|
||||
import Footer from './footer'
|
||||
import Callback from './callback'
|
||||
import Home from './home'
|
||||
import About from './about'
|
||||
import Dashboard from './dashboard'
|
||||
import Teams from './teams'
|
||||
import AcceptTeamInvite from './teams/AcceptTeamInvite'
|
||||
@@ -10,12 +5,7 @@ import AcceptTeamInvite from './teams/AcceptTeamInvite'
|
||||
import { theme, globalStyles } from './theme'
|
||||
|
||||
export {
|
||||
NavBar,
|
||||
Footer,
|
||||
Callback,
|
||||
AcceptTeamInvite,
|
||||
Home,
|
||||
About,
|
||||
Dashboard,
|
||||
Teams,
|
||||
theme,
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Query } from 'react-apollo'
|
||||
|
||||
import LoggedInMenu from './LoggedInMenu'
|
||||
|
||||
import { UserClient } from '../../App'
|
||||
import { USER_BY_AUTHID } from '../../graphql/members'
|
||||
|
||||
import { isDefined } from '../../utils/js-helpers'
|
||||
|
||||
export const LoggedIn = props => {
|
||||
let { data, user, auth } = props
|
||||
console.log('LoggedIn :', data, user, auth)
|
||||
let displayName = 'No Display Name'
|
||||
let authId = null
|
||||
if (isDefined(user.authId)) {
|
||||
authId = user.authId
|
||||
}
|
||||
|
||||
if (isDefined(user.alias)) {
|
||||
displayName = user.alias
|
||||
}
|
||||
|
||||
if (isDefined(user.nickname)) {
|
||||
displayName = user.nickname
|
||||
}
|
||||
|
||||
if (isDefined(user.firstName)) {
|
||||
displayName = user.firstName
|
||||
}
|
||||
|
||||
if (isDefined(user.firstName) && isDefined(user.lastName)) {
|
||||
displayName = user.firstName + ' ' + user.lastName
|
||||
}
|
||||
|
||||
if (authId === null) {
|
||||
return (
|
||||
<div>Loading...</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Query
|
||||
query={USER_BY_AUTHID}
|
||||
fetchPolicy='network-only'
|
||||
variables={{ authId }}
|
||||
client={UserClient}
|
||||
>
|
||||
{({ loading, error, data }) => {
|
||||
console.log('USER_BY_AUTHID: ', loading, error, data)
|
||||
|
||||
if (loading) {
|
||||
return <div>Loading...</div>
|
||||
}
|
||||
|
||||
if (error) {
|
||||
error.graphQLErrors.map(({ message }, i) => {
|
||||
return <div>{message}</div>
|
||||
})
|
||||
}
|
||||
return (
|
||||
<p>
|
||||
<LoggedInMenu menuLabel={displayName} auth={auth} user={data.userByAuthId} />
|
||||
</p>
|
||||
)
|
||||
}}
|
||||
</Query>
|
||||
)
|
||||
}
|
||||
|
||||
LoggedIn.propTypes = {
|
||||
data: PropTypes.object,
|
||||
user: PropTypes.object.isRequired,
|
||||
auth: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default LoggedIn
|
||||
@@ -1,107 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Menu from '@material-ui/core/Menu'
|
||||
import MenuItem from '@material-ui/core/MenuItem'
|
||||
import Drawer from '@material-ui/core/Drawer'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import ProfileIcon from '@material-ui/icons/Person'
|
||||
import LogoutIcon from '@material-ui/icons/DirectionsWalk'
|
||||
|
||||
import UserProfile from './Profile'
|
||||
|
||||
const LogoutLink = props => <Link to='/' {...props} />
|
||||
|
||||
const styles = {
|
||||
drawer: {
|
||||
width: 250
|
||||
},
|
||||
fullList: {
|
||||
width: 'auto'
|
||||
}
|
||||
}
|
||||
|
||||
class LoggedInUserMenu extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.handleMenu = this.handleMenu.bind(this)
|
||||
this.handleClose = this.handleClose.bind(this)
|
||||
this.handleLogout = this.handleLogout.bind(this)
|
||||
this.toggleDrawer = this.toggleDrawer.bind(this)
|
||||
|
||||
this.state = {
|
||||
menu: null,
|
||||
open: false
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { menuLabel, user, classes } = this.props
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Button
|
||||
aria-owns={this.state.open ? 'render-props-menu' : null}
|
||||
aria-haspopup='true'
|
||||
onClick={e => this.handleMenu(e)}
|
||||
color='inherit'
|
||||
>
|
||||
{menuLabel}
|
||||
</Button>
|
||||
<Menu
|
||||
id='render-props-menu'
|
||||
anchorEl={this.state.menu}
|
||||
open={Boolean(this.state.menu)}
|
||||
onClose={this.handleClose}
|
||||
>
|
||||
<MenuItem onClick={this.toggleDrawer}>
|
||||
<ProfileIcon />
|
||||
<div>Profile</div>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={this.handleLogout} component={LogoutLink}>
|
||||
<LogoutIcon />
|
||||
<div>Logout</div>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<Drawer anchor='right' open={this.state.open} onClose={this.toggleDrawer} className={classes.drawer}>
|
||||
<div
|
||||
tabIndex={0}
|
||||
role='button'
|
||||
onClick={this.toggleDrawer}
|
||||
>
|
||||
<UserProfile user={user} toggleDrawer={this.toggleDrawer} />
|
||||
</div>
|
||||
</Drawer>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
handleMenu (e) {
|
||||
this.setState({ menu: e.currentTarget })
|
||||
}
|
||||
|
||||
handleClose () {
|
||||
this.setState({ menu: null })
|
||||
}
|
||||
|
||||
handleLogout () {
|
||||
this.props.auth.logout()
|
||||
this.setState({ menu: null })
|
||||
}
|
||||
|
||||
toggleDrawer () {
|
||||
this.setState({ open: !this.state.open })
|
||||
}
|
||||
}
|
||||
|
||||
LoggedInUserMenu.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
menuLabel: PropTypes.string.isRequired,
|
||||
auth: PropTypes.object.isRequired,
|
||||
user: PropTypes.object
|
||||
}
|
||||
|
||||
export default withStyles(styles)(LoggedInUserMenu)
|
||||
@@ -1,15 +0,0 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Button from '@material-ui/core/Button'
|
||||
|
||||
export const LoggedOut = ({ auth }) => (
|
||||
<div onClick={() => auth.login()}>
|
||||
<Button color='inherit'>Login / Sign up</Button>
|
||||
</div>
|
||||
)
|
||||
|
||||
LoggedOut.propTypes = {
|
||||
auth: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default LoggedOut // This binds the querty to the component
|
||||
@@ -1,94 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
// Materia UI
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import CardMedia from '@material-ui/core/CardMedia'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Divider from '@material-ui/core/Divider'
|
||||
|
||||
// Images
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
padding: 60,
|
||||
margin: 2
|
||||
},
|
||||
card: {
|
||||
maxWidth: 240,
|
||||
minWidth: 240,
|
||||
paddingTop: '30'
|
||||
},
|
||||
media: {
|
||||
paddingTop: '56.25%', // 16:9,
|
||||
marginTop: '30',
|
||||
width: 100,
|
||||
height: 100,
|
||||
maxWidth: 100
|
||||
},
|
||||
grid: {
|
||||
paddingTop: '30',
|
||||
marginTop: '30'
|
||||
},
|
||||
typography: {
|
||||
width: '100%',
|
||||
marginTop: 20,
|
||||
marginBottom: 20
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
class UserProfile extends Component {
|
||||
render () {
|
||||
const { classes, user, toggleDrawer } = this.props
|
||||
return (
|
||||
<Grid container justify='center' spacing={24}>
|
||||
<Grid key={user.id} item>
|
||||
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<Button
|
||||
onClick={toggleDrawer}
|
||||
color='inherit'
|
||||
>
|
||||
Close Profile
|
||||
</Button>
|
||||
<CardMedia
|
||||
className={classes.media}
|
||||
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'
|
||||
title='User Profile'
|
||||
|
||||
/>
|
||||
<Typography className={classes.typography} gutterBottom variant='headline' component='h2'>
|
||||
{ user.firstName } { user.lastName } ( {user.alias} )
|
||||
</Typography>
|
||||
<Divider />
|
||||
|
||||
<Typography className={classes.typography} align='left' gutterBottom variant='subheading' component='h2'>
|
||||
{ user.role.name }
|
||||
</Typography>
|
||||
<Divider />
|
||||
|
||||
<Typography className={classes.typography} component='p'>
|
||||
{ user.bio }
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
UserProfile.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
user: PropTypes.object,
|
||||
toggleDrawer: PropTypes.func
|
||||
}
|
||||
export default withStyles(styles)(UserProfile)
|
||||
@@ -1,141 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import AppBar from '@material-ui/core/AppBar'
|
||||
import Toolbar from '@material-ui/core/Toolbar'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import Button from '@material-ui/core/Button'
|
||||
|
||||
// icons
|
||||
import HomeIcon from '@material-ui/icons/Home'
|
||||
import DashboardIcon from '@material-ui/icons/Dashboard'
|
||||
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import { getItem } from '../../utils/local-storage'
|
||||
|
||||
// components
|
||||
import { LoggedIn } from './LoggedIn'
|
||||
import { LoggedOut } from './LoggedOut'
|
||||
|
||||
import AALogo from '../../assets/logos/advanced-algos/aa-logo-dark.svg'
|
||||
|
||||
const AboutLink = props => <Link to='/about' {...props} />
|
||||
const TeamsLink = props => <Link to='/teams' {...props} />
|
||||
const DashboardLink = props => <Link to='/dashboard' {...props} />
|
||||
const HomeLink = props => <Link to='/' {...props} />
|
||||
|
||||
const styles = theme => ({
|
||||
'@global': {
|
||||
body: {
|
||||
backgroundColor: theme.palette.common.white
|
||||
}
|
||||
},
|
||||
root: {
|
||||
flexGrow: 1
|
||||
},
|
||||
colorDefault: {
|
||||
color: '#000'
|
||||
},
|
||||
flex: {
|
||||
flexGrow: 1
|
||||
},
|
||||
toolbarTitle: {
|
||||
flex: 1
|
||||
},
|
||||
menuButton: {
|
||||
marginLeft: -12,
|
||||
marginRight: 20
|
||||
},
|
||||
appBar: {
|
||||
position: 'relative'
|
||||
},
|
||||
img: {
|
||||
margin: 20,
|
||||
display: 'block',
|
||||
maxWidth: 240,
|
||||
maxHeight: 48
|
||||
}
|
||||
})
|
||||
|
||||
class NavBar extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
user: null,
|
||||
open: false
|
||||
}
|
||||
}
|
||||
|
||||
async componentDidMount () {
|
||||
const user = await getItem('user')
|
||||
console.log('NavBar CDM: ', user, this.state)
|
||||
this.setState({ user })
|
||||
}
|
||||
|
||||
render () {
|
||||
let { classes, auth } = this.props
|
||||
|
||||
let user = JSON.parse(this.state.user)
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<AppBar
|
||||
position='static'
|
||||
classes={{ root: classes.appBar, colorDefault: classes.colorDefault }}
|
||||
>
|
||||
<Toolbar>
|
||||
<img className={classes.img} src={AALogo} alt='Advanced Algos' />
|
||||
<Typography
|
||||
variant='title'
|
||||
color='inherit'
|
||||
className={classes.toolbarTitle}
|
||||
>
|
||||
Teams
|
||||
</Typography>
|
||||
|
||||
<IconButton
|
||||
className={classes.menuButton}
|
||||
color='inherit'
|
||||
title='Home'
|
||||
component={HomeLink}
|
||||
>
|
||||
<HomeIcon />
|
||||
</IconButton>
|
||||
<Button component={TeamsLink} color='inherit'>
|
||||
Teams
|
||||
</Button>
|
||||
<Button component={AboutLink} color='inherit'>
|
||||
About
|
||||
</Button>
|
||||
|
||||
{this.state.user !== undefined && this.state.user !== null ? (
|
||||
<React.Fragment>
|
||||
<IconButton
|
||||
className={classes.menuButton}
|
||||
color='inherit'
|
||||
title='Dashboard'
|
||||
component={DashboardLink}
|
||||
>
|
||||
<DashboardIcon />
|
||||
</IconButton>
|
||||
<LoggedIn user={user} auth={auth} styles={styles} />
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<LoggedOut auth={auth} styles={styles} />
|
||||
)}
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
NavBar.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
auth: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default withStyles(styles)(NavBar)
|
||||
@@ -1,14 +1,14 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import queryString from 'query-string'
|
||||
import { parse } from '../../utils/js-helpers'
|
||||
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
class AcceptTeamInvite extends Component {
|
||||
render () {
|
||||
const { location, auth } = this.props
|
||||
const param = queryString.parse(location.search)
|
||||
const param = parse(location.search)
|
||||
console.log(param, auth)
|
||||
|
||||
if (auth === undefined) {
|
||||
|
||||
@@ -79,23 +79,23 @@ const TeamsDetails = ({ classes, team }) => {
|
||||
<img src={banner} alt={team.name} className={classes.banner} />
|
||||
<img src={avatar} alt={team.name} className={classes.avatar} />
|
||||
<Typography
|
||||
variant='display3'
|
||||
variant='h2'
|
||||
align='center'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
>
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
<Typography variant='subtitle1' color='textSecondary'>
|
||||
{team.createdAt}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
<Typography variant='subtitle1' color='textSecondary'>
|
||||
Motto: {team.profile.motto}
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='textSecondary'>
|
||||
<Typography variant='subtitle1' color='textSecondary'>
|
||||
Description: {team.profile.description}
|
||||
</Typography>
|
||||
<Typography variant='subheading' paragraph gutterBottom>
|
||||
<Typography variant='subtitle1' paragraph gutterBottom>
|
||||
Members: {team.members.length}
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
@@ -35,7 +35,7 @@ export const TeamsItem = ({ classes, team }) => {
|
||||
title={team.name}
|
||||
/>
|
||||
<CardContent className={classes.cardContent}>
|
||||
<Typography gutterBottom variant='headline' component='h2'>
|
||||
<Typography gutterBottom variant='h5' component='h2'>
|
||||
{team.name}
|
||||
</Typography>
|
||||
<Typography variant='caption' color='textSecondary'>
|
||||
@@ -44,7 +44,7 @@ export const TeamsItem = ({ classes, team }) => {
|
||||
<Typography variant='caption' paragraph gutterBottom>
|
||||
Members: 1
|
||||
</Typography>
|
||||
<Typography variant='subheading' color='primary'>
|
||||
<Typography variant='subtitle1' color='primary'>
|
||||
Now recruiting!
|
||||
</Typography>
|
||||
</CardContent>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Query } from 'react-apollo'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import { MessageCard } from '@advancedalgos/web-components'
|
||||
|
||||
import GET_ALL_TEAMS_QUERY from '../../../graphql/teams/GetAllTeamsQuery'
|
||||
|
||||
@@ -78,7 +79,7 @@ export const TeamsList = ({ classes, match }) => (
|
||||
<React.Fragment>
|
||||
<div className={classes.heroContent}>
|
||||
<Typography
|
||||
variant='display3'
|
||||
variant='h3'
|
||||
align='center'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
@@ -105,9 +106,7 @@ export const TeamsList = ({ classes, match }) => (
|
||||
} else {
|
||||
return (
|
||||
<Grid container spacing={40}>
|
||||
<Typography variant='subheading' gutterBottom>
|
||||
Loading...
|
||||
</Typography>
|
||||
<MessageCard message='Loading...' />
|
||||
{queryLoader}
|
||||
{errors}
|
||||
</Grid>
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
const path = require('path')
|
||||
const nodeExternals = require('webpack-node-externals')
|
||||
|
||||
module.exports = {
|
||||
entry: path.resolve(__dirname, './src/lib/index.js'),
|
||||
output: {
|
||||
path: path.resolve(__dirname, './dist/lib'),
|
||||
filename: 'index.js',
|
||||
library: '',
|
||||
libraryTarget: 'commonjs'
|
||||
},
|
||||
externals: [nodeExternals()],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /(node_modules|bower_components)/,
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
presets: ['@babel/preset-env', '@babel/preset-react']
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ['style-loader', 'css-loader']
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin')
|
||||
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
|
||||
const Dotenv = require('dotenv-webpack')
|
||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
|
||||
.BundleAnalyzerPlugin
|
||||
|
||||
module.exports = merge(commonConfig, {
|
||||
mode: 'production',
|
||||
@@ -54,6 +56,10 @@ module.exports = merge(commonConfig, {
|
||||
new HtmlWebpackHarddiskPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('production')
|
||||
}),
|
||||
new BundleAnalyzerPlugin({
|
||||
analyzerMode: 'static',
|
||||
reportFilename: 'report.html'
|
||||
})
|
||||
],
|
||||
module: {
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "AATeamModule",
|
||||
"version": "0.0.1",
|
||||
"version": "2.0.1",
|
||||
"description": "Advanced Algos Team Module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
@@ -13,7 +13,7 @@
|
||||
"Advanced Algos"
|
||||
],
|
||||
"author": "Barry Low <bearcanru@gmail.com>",
|
||||
"license": "AGPL-3.0",
|
||||
"license": "SEE LICENSE IN LICENSE.MD",
|
||||
"bugs": {
|
||||
"url": "https://github.com/AdvancedAlgos/AATeamModule.git/issues"
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user