Merge remote-tracking branch 'Superalgos/develop' into develop
This commit is contained in:
commit
eef1d93143
14 files changed
+1656
-1211
No files matched your search
@@ -23,6 +23,11 @@ enum FBKind {
|
||||
INDICATOR
|
||||
EXTRACTOR
|
||||
PLOTTER
|
||||
Trader
|
||||
Trading
|
||||
Indicator
|
||||
Sensor
|
||||
Plotter
|
||||
}
|
||||
|
||||
type Team {
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Generated
+1382
-1152
File diff suppressed because it is too large.
Load diff
+13
-12
@@ -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: [
|
||||
|
||||
Reference in new issue
Block a user