Merge pull request #4 from AdvancedAlgos/develop

Refactor to Master App Build
This commit is contained in:
Barry Low authored and GitHub committed 2018-10-11 18:07:35 -07:00
commit beb35cd1b3
52 files changed
+2735 -6029

No files matched your search

+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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"]
}
+4
View File
@@ -70,3 +70,7 @@ dist/
#Mac specific files
.DS_Store
#yalc npm link
.yalc
yalc.lock
+15
View File
@@ -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
+1 -1
View File
@@ -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">
+2500 -4672
View File
File diff suppressed because it is too large. Load diff
+35 -37
View File
@@ -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",
-190
View File
@@ -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)
-7
View File
@@ -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
}
-268
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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)
+10
View File
@@ -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
}
-26
View File
@@ -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
-91
View File
@@ -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)
-7
View File
@@ -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 />
+1 -1
View File
@@ -14,7 +14,7 @@ const styles = theme => ({
const ManageTeams = ({ classes }) => (
<div>
<Typography variant='display1' gutterBottom>
<Typography variant='h4' gutterBottom>
Manage Your Teams
</Typography>
<ManageTeamsList />
+1 -1
View File
@@ -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:&nbsp;
{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'>
+1 -1
View File
@@ -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}>
-128
View File
@@ -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)
-61
View File
@@ -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)
-10
View File
@@ -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,
-78
View File
@@ -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
-107
View File
@@ -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)
-15
View File
@@ -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
-94
View File
@@ -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)
-141
View File
@@ -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)
+2 -2
View File
@@ -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
View File
@@ -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"
},