Merge remote-tracking branch 'Superalgos/develop' into develop

This commit is contained in:
Matias committed 2019-04-10 09:33:10 +02:00
commit eef1d93143
14 files changed
+1656 -1211

No files matched your search

+5
View File
@@ -23,6 +23,11 @@ enum FBKind {
INDICATOR
EXTRACTOR
PLOTTER
Trader
Trading
Indicator
Sensor
Plotter
}
type Team {
+5
View File
@@ -53,6 +53,11 @@ enum FBKind {
INDICATOR
EXTRACTOR
PLOTTER
Trader
Trading
Indicator
Sensor
Plotter
}
type FBStatus implements Node {
@@ -0,0 +1,40 @@
import gql from 'graphql-tag'
const FB_TEAM_FRAGMENT = gql`{
edges{
node{
id
name
slug
avatar
kind
status {
status
reason
createdAt
}
team {
id
name
slug
owner
profile {
avatar
banner
description
motto
updatedAt
}
members {
role
email
member {
alias
}
}
}
}
}
}`
module.exports = FB_TEAM_FRAGMENT
@@ -0,0 +1,40 @@
import axios from 'axios'
import { logger, DatabaseError } from '../../../logger'
export const createStrategy = fbSlug => {
logger.info('createStrategy')
logger.info(fbSlug)
return new Promise((resolve, reject) => {
try {
return axios.post(process.env.PLATFORM_API_URL, {
query: `mutation strategizer_CreateStrategy($fbSlug: String!) {
strategizer_CreateStrategy(fbSlug: $fbSlug){
id
}
}`,
variables: {
fbSlug: fbSlug
}
}, {
headers: {
'Content-Type': 'application/json'
}
})
.then(res => {
logger.info('createStrategy result')
logger.info(res.data)
resolve(res.data)
})
.catch(err => {
logger.error('createStrategy err')
logger.error(err)
reject(err)
})
} catch (error) {
reject(error)
}
})
}
export default createStrategy
+33 -19
View File
@@ -2,6 +2,7 @@ import axios from 'axios'
import { ApolloError } from 'apollo-server-express'
import { getUser } from '../../../middleware/getMember'
import { createStrategy } from './createStrategy'
import { notifications_sendTeamCreateConfirmation, notifications_sendTeamMemberInvite, notifications_VerifyTeamMemberInviteToken } from '../notifications/sendgrid'
@@ -97,40 +98,53 @@ export const resolvers = {
let createTeam
if(existingMember !== null && existingMember.id !== null){
logger.info('createTeam with existingMember:')
createTeam = await ctx.db.mutation.createTeam({ data: {name: name, slug: slug, owner: authId, members: {create: {member: {connect: {authId: authId}}, role: 'OWNER', status: { create: { status: 'ACTIVE', reason: `Connected to Team ${name}`}}}}, 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)
createTeam = await ctx.db.mutation.createTeam({ data: {name: name, slug: slug, owner: authId, members: {create: {member: {connect: {authId: authId}}, role: 'OWNER', status: { create: { status: 'ACTIVE', reason: `Connected to Team ${name}`}}}}, profile: {create: {avatar: avatar, banner: banner}}, fb: {create: {name: botName, slug: botSlug, kind:'Trading', avatar: avatar, status: {create: {status: 'ACTIVE', reason: "Cloned on team creation"}}}}, status: {create: {status: 'ACTIVE', reason:"Team created"}}} }, TEAMS_FRAGMENT)
.catch((err) => {
logger.debug(err, 'createTeamMutation error: ')
return new DatabaseError(err)
})
} else {
logger.info('createTeam without existingMember:')
createTeam = await ctx.db.mutation.createTeam({ data: {name: name, slug: slug, owner: authId, members: {create: {member: {create: {authId: authId, alias: alias, visible: true, status: { create: { status: 'ACTIVE', reason: `Created team ${name}`}}}}, role: 'OWNER', status: { create: { status: 'ACTIVE', reason: `Created with Team ${name}`}}}}, 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)
createTeam = await ctx.db.mutation.createTeam({ data: {name: name, slug: slug, owner: authId, members: {create: {member: {create: {authId: authId, alias: alias, visible: true, status: { create: { status: 'ACTIVE', reason: `Created team ${name}`}}}}, role: 'OWNER', status: { create: { status: 'ACTIVE', reason: `Created with Team ${name}`}}}}, profile: {create: {avatar: avatar, banner: banner}}, fb: {create: {name: botName, slug: botSlug, kind:'Trading', avatar: avatar, status: {create: {status: 'ACTIVE', reason: "Cloned on team creation"}}}}, status: {create: {status: 'ACTIVE', reason:"Team created"}}} }, TEAMS_FRAGMENT)
.catch((err) => {
logger.debug(err, 'createTeamMutation error: ')
return new DatabaseError(err)
})
if(createTeam) notifications_sendTeamCreateConfirmation(email, name, botName)
}
await ctx.db.mutation.createFinancialBeings({ data:{
type:'BOT',
kind:'INDICATOR',
name:'Simulator ' + botName,
slug:'simulator-' + botSlug,
avatar:avatar,
team: {
connect:{
id:createTeam.id
let createFB;
if(createTeam){
createFB = await ctx.db.mutation.createFinancialBeings({ data:{
type:'BOT',
kind:'Indicator',
name:'Simulator ' + botName,
slug:'simulator-' + botSlug,
avatar:avatar,
team: {
connect:{
id:createTeam.id
}
}
}
}, FB_FRAGMENT)
.catch((err) => {
logger.debug(err, 'Error creating the simulator: ')
return new DatabaseError(err)
})
logger.info('createTeam creating simulator success')
logger.info(JSON.stringify(await createFB))
let createdStrategy
if(await createFB){
logger.info('createStrategy:' + 'simulator-' + botSlug)
createdStrategy = await createStrategy('simulator-' + botSlug)
logger.info('createStrategy:')
logger.info(JSON.stringify(await createStrategy))
}
}, FB_FRAGMENT)
.catch((err) => {
logger.debug(err, 'Error creating the simulator: ')
return new DatabaseError(err)
})
logger.info('createTeam creating simulator success')
}
if(await createTeam && await createFB && await createStrategy){
notifications_sendTeamCreateConfirmation(email, name, botName)
}
return createTeam
},
async updateTeamProfile(parent, { slug, owner, description, motto, avatar, banner }, ctx, info) {
@@ -1,6 +1,9 @@
import { logger } from '../../../logger'
import FB_FRAGMENT from '../../fragments/FBFragment'
import FB_TEAM_FRAGMENT from '../../fragments/FBTeamFragment'
import { isDefined, isNull } from '../../../utils'
export const fbByFbId = async (parent, { fbId }, ctx, info) => {
logger.info(`fbByFbId: ${fbId}`)
@@ -15,3 +18,17 @@ export const fbByFbSlug = async (parent, { fbSlug }, ctx, info) => {
logger.info(`fbByFbSlug response: ${JSON.stringify(await FB)}`)
return FB[0]
}
export const fbByOwner = async (parent, { fbId, fbSlug }, ctx, info) => {
logger.info('teamsByOwner')
const authId = ctx.request.headers.userid
if (!authId) {
throw new AuthenticationError()
return
}
if ((isDefined(fbId) && !isNull(fbId)) || (isDefined(fbSlug) && !isNull(fbSlug))){
return ctx.db.query.financialBeingsesConnection({where: {AND:[{team:{members_some:{member:{authId: authId}}}},{OR:[{slug:fbSlug},{id:fbId}]}]}}, FB_TEAM_FRAGMENT)
} else {
return ctx.db.query.financialBeingsesConnection({where: {team:{members_some:{member:{authId: authId}}}}}, FB_TEAM_FRAGMENT)
}
}
+2 -1
View File
@@ -3,7 +3,7 @@ import { logger } from '../../../logger'
import { member, owner } from './Member'
import { teams, teamById, teamsByIds, teamByName, teamBySlug, teamWithRole, teamAuthorization, teamsByOwner, teamsByRole } from './Team'
import{ fbByTeamMember } from './TeamMember'
import{ fbByFbId, fbByFbSlug } from './FinancialBeing'
import{ fbByFbId, fbByFbSlug, fbByOwner } from './FinancialBeing'
export const resolvers = {
Query: {
@@ -19,6 +19,7 @@ export const resolvers = {
teamsByRole: (parent, arg, ctx, info) => teamsByRole(parent, arg, ctx, info),
owner: (parent, arg, ctx, info) => owner(parent, arg, ctx, info),
fbByTeamMember: (parent, arg, ctx, info) => fbByTeamMember(parent, arg, ctx, info),
fbByOwner: (parent, arg, ctx, info) => fbByOwner(parent, arg, ctx, info),
fbByFbId: (parent, arg, ctx, info) => fbByFbId(parent, arg, ctx, info),
fbByFbSlug: (parent, arg, ctx, info) => fbByFbSlug(parent, arg, ctx, info)
}
+2 -1
View File
@@ -1,4 +1,4 @@
# import Query.TeamConnection, Team, FinancialBeings from "../generated/prisma.graphql"
# import Query.TeamConnection, Query.FinancialBeingsConnection, Team, FinancialBeings from "../generated/prisma.graphql"
directive @isAuthenticated on QUERY | FIELD | MUTATION | FIELD_DEFINITION
directive @hasRole(roles: [String]) on QUERY | FIELD | MUTATION | FIELD_DEFINITION
@@ -17,6 +17,7 @@ type Query {
teamsByOwner: [Team!]! @isAuthenticated
teamsByRole: [Team!]! @isAuthenticated
fbByTeamMember: Team @isAuthenticated
fbByOwner(fbId: String, fbSlug: String): FinancialBeingsConnection @isAuthenticated
fbByFbId(fbId: String!): FinancialBeings
fbByFbSlug(fbSlug: String!): FinancialBeings
owner: Member @isAuthenticated
+69
View File
@@ -0,0 +1,69 @@
export const toLocalTime = (epoch) => {
const localDate = new Date(0);
localDate.setUTCSeconds(epoch);
const options = { year: 'numeric', month: 'long', day: '2-digit' };
return (
`${localDate.toLocaleDateString(options)
} at ${
localDate.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })}`
);
};
export const temporaryFunction = input => input;
export function isDefined (d) {
return d !== null && typeof d !== 'undefined'
}
export function isNull (d) {
return d === null
}
export const isArray = Array.isArray
export function isObject (d) {
return isDefined(d) && typeof d === 'object' && !Array.isArray(d)
}
export function isEmpty (obj) {
for (var key in obj) {
if (obj.hasOwnProperty(key)) return false
}
return true
}
export function validObject (object, ...keys) {
return keys.reduce((a, b) => (a || { })[b], object) !== undefined
}
export function mergeDeep (target, ...sources) {
if (!sources.length) return target
const source = sources.shift()
if (isObject(target) && isObject(source)) {
for (const key in source) {
if (isObject(source[key])) {
if (!target[key]) Object.assign(target, { [key]: {} })
mergeDeep(target[key], source[key])
} else {
Object.assign(target, { [key]: source[key] })
}
}
}
return mergeDeep(target, ...sources)
}
export function slugify (string) {
const a = 'àáäâãåèéëêìíïîòóöôùúüûñçßÿœæŕśńṕẃǵǹḿǘẍźḧ·/_,:;'
const b = 'aaaaaaeeeeiiiioooouuuuncsyoarsnpwgnmuxzh------'
const p = new RegExp(a.split('').join('|'), 'g')
return string.toString().toLowerCase()
.replace(/\s+/g, '-') // Replace spaces with -
.replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters
.replace(/&/g, '-and-') // Replace & with 'and'
.replace(/[^\w-]+/g, '') // Remove all non-word characters
.replace(/--+/g, '-') // Replace multiple - with single -
.replace(/^-+/, '') // Trim - from start of text
.replace(/-+$/, '') // Trim - from end of text
}
+1382 -1152
View File
File diff suppressed because it is too large. Load diff
+13 -12
View File
@@ -1,6 +1,6 @@
{
"name": "@superalgos/teams-client",
"version": "0.0.33",
"version": "0.0.35",
"description": "Superalgos Project Team client-side web app",
"main": "src/index.js",
"scripts": {
@@ -14,15 +14,15 @@
"apollo",
"graphql"
],
"repository": "",
"repository": "https://github.com/Superalgos/TeamsModule.git",
"author": "Barry Low <bearcanrun@gmail.com>",
"license": "READ LICENSE.MD",
"devDependencies": {
"@babel/cli": "^7.1.2",
"@babel/core": "^7.1.2",
"@babel/plugin-proposal-class-properties": "^7.1.0",
"@babel/core": "^7.4.0",
"@babel/plugin-proposal-class-properties": "^7.4.0",
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
"@babel/preset-env": "^7.1.0",
"@babel/preset-env": "^7.4.2",
"@babel/preset-react": "^7.0.0",
"autoprefixer": "^8.6.5",
"babel-core": "^7.0.0-bridge.0",
@@ -34,7 +34,7 @@
"babel-plugin-transform-react-jsx": "^6.24.1",
"connect-history-api-fallback": "^1.5.0",
"css-loader": "^0.28.11",
"eslint": "^5.6.1",
"eslint": "^5.15.3",
"eslint-config-prettier": "^3.1.0",
"eslint-config-standard": "^12.0.0",
"eslint-config-standard-react": "^7.0.2",
@@ -49,7 +49,7 @@
"html-webpack-plugin": "^3.2.0",
"koa-connect": "^2.0.1",
"mini-css-extract-plugin": "^0.4.4",
"node-sass": "^4.9.3",
"node-sass": "^4.11.0",
"optimize-css-assets-webpack-plugin": "^4.0.3",
"postcss-loader": "^2.1.6",
"prettier": "^1.14.3",
@@ -70,7 +70,7 @@
},
"dependencies": {
"@azure/storage-blob": "^10.0.0-preview",
"@superalgos/web-components": "0.0.18",
"@superalgos/web-components": "0.0.19",
"apollo-cache-inmemory": "^1.3.5",
"apollo-client": "^2.4.2",
"apollo-link": "^1.2.3",
@@ -85,21 +85,22 @@
"classnames": "^2.2.6",
"cross-fetch": "^2.2.2",
"dotenv-webpack": "^1.5.7",
"graphql": "^14.0.2",
"graphql": "^14.2.1",
"graphql-tag": "^2.10.0",
"minilog": "^3.1.0",
"prop-types": "^15.6.2",
"query-string": "^6.2.0",
"react": "^16.6.1",
"react": "^16.8.4",
"react-apollo": "^2.2.4",
"react-dom": "^16.6.1",
"react-dom": "^16.8.4",
"react-router-dom": "^4.3.1",
"recompose": "^0.30.0",
"subscriptions-transport-ws": "^0.9.15"
},
"peerDependencies": {
"@material-ui/core": "^3.6.2",
"@material-ui/icons": "^3.0.1"
"@material-ui/icons": "^3.0.1",
"ajv": "^6.10.0"
},
"standard": {
"parser": "babel-eslint",
@@ -40,32 +40,34 @@ const styles = theme => ({
export const ManageTeamProvileFBView = ({ classes, team }) => {
log.debug('ManageTeamProvileFBView', team, team.fb[0], team.fb[0].avatar)
let avatar = (team.fb[0].avatar !== undefined && team.fb[0].avatar !== null) ? team.fb[0].avatar : process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
return (
<Grid item xs={12} className={classes.fbContainer}>
<Card className={classes.card}>
<div className={classes.cardDetails}>
<CardMedia
className={classes.cardMedia}
image={avatar}
title={team.name}
/>
<CardContent className={classes.cardContent}>
<Typography gutterBottom variant='h5' component='h2'>
{team.fb[0].name}
</Typography>
<Typography variant='caption' color='textSecondary'>
{team.fb[0].kind}
</Typography>
</CardContent>
<CardActions>
<ManageTeamProfileFBEdit slug={team.slug} fb={team.fb[0]} />
</CardActions>
</div>
</Card>
</Grid>
)
let fbs = team.fb;
return fbs.map((fb, index) => {
let avatar = (fb.avatar !== undefined && fb.avatar !== null) ? fb.avatar : process.env.STORAGE_URL + '/module-teams/module-default/aa-avatar-default.png'
return (
<Grid item xs={12} className={classes.fbContainer} key={`fb-${index}`}>
<Card className={classes.card}>
<div className={classes.cardDetails}>
<CardMedia
className={classes.cardMedia}
image={avatar}
title={fb.name}
/>
<CardContent className={classes.cardContent}>
<Typography gutterBottom variant='h5' component='h2'>
{fb.name}
</Typography>
<Typography variant='caption' color='textSecondary'>
{fb.kind}
</Typography>
</CardContent>
<CardActions>
<ManageTeamProfileFBEdit slug={team.slug} fb={fb} />
</CardActions>
</div>
</Card>
</Grid>
)
})
}
ManageTeamProvileFBView.propTypes = {
@@ -35,6 +35,16 @@ module.exports = merge(commonConfig, {
],
module: {
rules: [
{
test: /\.js$/,
exclude: [
/(node_modules|bower_components)/,
],
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
},
{
test: /\.s?[ac]ss$/,
loader: 'style-loader!css-loader!postcss-loader!sass-loader'
@@ -64,6 +64,16 @@ module.exports = merge(commonConfig, {
],
module: {
rules: [
{
test: /\.js$/,
exclude: [
/(node_modules|bower_components)/
],
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
},
{
test: /\.scss$/,
use: [