Merge pull request #11 from AAVikings/master
Adding changes after team review
This commit is contained in:
15 files changed
+146
-121
No files matched your search
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@superalgos/operations-client",
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"description": "Superalgos Operations client-side web app",
|
||||
"main": "src/index.js",
|
||||
"dependencies": {
|
||||
|
||||
@@ -157,7 +157,6 @@ class AddClone extends Component {
|
||||
<FormHelperText>{this.state.selectedBot.kind}</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
{ /* TRADER BOT */ }
|
||||
{ this.state.selectedBot.kind === "TRADER" &&
|
||||
<React.Fragment>
|
||||
<Typography className={classes.typography} variant='subtitle1' align='justify'>
|
||||
@@ -213,6 +212,10 @@ class AddClone extends Component {
|
||||
fullWidth
|
||||
/>
|
||||
|
||||
<Typography className={classes.typography} variant='subtitle1' align='justify'>
|
||||
The Wait Time represent the number of miliseconds the bot will wait between executions.
|
||||
</Typography>
|
||||
|
||||
<TextField
|
||||
id="waitTime"
|
||||
label="Wait Time"
|
||||
@@ -261,7 +264,6 @@ class AddClone extends Component {
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
{ /* INDICATOR AND EXTRACTOR BOTS */ }
|
||||
{ (this.state.selectedBot.kind === "INDICATOR"
|
||||
|| this.state.selectedBot.kind === "EXTRACTOR") &&
|
||||
<React.Fragment>
|
||||
@@ -366,6 +368,11 @@ class AddClone extends Component {
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
|
||||
<Typography className={classes.typography} variant='subtitle1' align='justify'>
|
||||
You will your clone information under Active Clones until it finishes the execution, then it will moved to the History.
|
||||
</Typography>
|
||||
|
||||
<div className={classes.actionButton} >
|
||||
<Button
|
||||
type="submit"
|
||||
|
||||
@@ -107,8 +107,8 @@ class ListClones extends Component {
|
||||
<Typography className={classes.cloneInfoNormal}>{clone.buyAverage}</Typography>
|
||||
<Typography className={classes.cloneInfoNormal}>{clone.sellAverage}</Typography>
|
||||
<Typography className={classes.cloneInfoNormal}>{clone.marketRate}</Typography>
|
||||
<Typography className={classes.cloneInfoNormal}>{clone.combinedProfitsA}</Typography>
|
||||
<Typography className={classes.cloneInfoNormal}>{clone.combinedProfitsB}</Typography>
|
||||
<Typography className={classes.cloneInfoNormal}>{clone.combinedProfitsA}%</Typography>
|
||||
<Typography className={classes.cloneInfoNormal}>{clone.combinedProfitsB}%</Typography>
|
||||
</React.Fragment>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -24,13 +24,13 @@ class Home extends Component {
|
||||
</Typography>
|
||||
<div className='column'>
|
||||
<Typography align='justify'>
|
||||
The Operations module allows you to create copies of your bot
|
||||
The Operations module allows you to create instances of your bots
|
||||
that will be executed on a virtual machine.
|
||||
</Typography>
|
||||
</div>
|
||||
<div className='column'>
|
||||
<Typography align='justify'>
|
||||
|
||||
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"containers": [
|
||||
{
|
||||
"name": "aadev",
|
||||
"image": "benme/aadev:v3.5",
|
||||
"image": "benme/aadev:v3.6",
|
||||
"command": ["node", "Run.js"],
|
||||
"env": [
|
||||
]
|
||||
|
||||
@@ -7,17 +7,3 @@ export function toPlatformDatetime (epoch) {
|
||||
export function isDefined (d) {
|
||||
return d !== null && typeof d !== 'undefined'
|
||||
}
|
||||
|
||||
export function getJobNameFromClone (clone) {
|
||||
return clone.teamSlug + '-' + clone.botSlug + '-' + clone.mode.toLowerCase()
|
||||
}
|
||||
|
||||
export function getSelectedBot(botsByUser, selectedBotId){
|
||||
if(isDefined(botsByUser)){
|
||||
for (var i = 0; i < botsByUser.fb.length; i++) {
|
||||
if(botsByUser.fb[i].id === selectedBotId){
|
||||
return botsByUser.fb[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,15 @@ import logger from '../config/logger'
|
||||
|
||||
export class AuthentificationError extends Error {
|
||||
code = 401
|
||||
message = 'Autentification not found, you have to be authentificated to perform this action'
|
||||
message = 'Autentification not found, you have to be authentificated to perform this action.'
|
||||
constructor(){
|
||||
super()
|
||||
}
|
||||
}
|
||||
|
||||
export class AutorizationError extends Error {
|
||||
code = 401
|
||||
message = 'You are not authorized to perform this action.'
|
||||
constructor(){
|
||||
super()
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import logger from '../config/logger'
|
||||
import axios from 'axios'
|
||||
|
||||
const teamAvatar = async(authorization, teamId) => {
|
||||
logger.debug('GraphQL call teamAvatar.')
|
||||
|
||||
return axios({
|
||||
url: process.env.GATEWAY_ENDPOINT,
|
||||
method: 'post',
|
||||
data: {
|
||||
query: `
|
||||
query Teams_Team($teamId: String!){
|
||||
teams_TeamById(teamId:$teamId) {
|
||||
profile{
|
||||
avatar
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
teamId: teamId
|
||||
}
|
||||
},
|
||||
headers: {
|
||||
authorization: authorization
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
export default teamAvatar
|
||||
+12
-5
@@ -1,16 +1,16 @@
|
||||
import logger from '../config/logger'
|
||||
import axios from 'axios'
|
||||
|
||||
const teams_FbByTeamMember = (authorization) => {
|
||||
logger.debug('GraphQL call teams_FbByTeamMember')
|
||||
const teamQuery = async(authorization, teamId) => {
|
||||
logger.debug('GraphQL retrieving team information. %s', teamId)
|
||||
|
||||
return axios({
|
||||
url: process.env.GATEWAY_ENDPOINT,
|
||||
method: 'post',
|
||||
data: {
|
||||
query: `
|
||||
query Teams_FbByTeamMember {
|
||||
teams_FbByTeamMember {
|
||||
query Teams_Team($teamId: String!){
|
||||
teams_TeamById(teamId:$teamId) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
@@ -24,11 +24,18 @@ const teams_FbByTeamMember = (authorization) => {
|
||||
members {
|
||||
member {
|
||||
alias
|
||||
authId
|
||||
}
|
||||
}
|
||||
profile{
|
||||
avatar
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
teamId: teamId
|
||||
}
|
||||
},
|
||||
headers: {
|
||||
authorization: authorization
|
||||
@@ -36,4 +43,4 @@ const teams_FbByTeamMember = (authorization) => {
|
||||
})
|
||||
};
|
||||
|
||||
export default teams_FbByTeamMember
|
||||
export default teamQuery
|
||||
@@ -1,27 +1,55 @@
|
||||
import logger from '../config/logger'
|
||||
import { getJobNameFromClone, getSelectedBot } from '../config/utils'
|
||||
import teamAvatar from '../graphQLCalls/teamAvatar'
|
||||
import { isDefined } from '../config/utils'
|
||||
import { AutorizationError } from '../errors'
|
||||
|
||||
// TODO Refactor this code once financial beings api is ready
|
||||
const cloneDetails = async(authorization, botsByUser, clone) => {
|
||||
const cloneDetails = async(authId, team, clone) => {
|
||||
logger.debug('Retrieving clone details.')
|
||||
|
||||
let selectedBot = getSelectedBot(botsByUser.data.data.teams_FbByTeamMember, clone.botId)
|
||||
clone.teamId = botsByUser.data.data.teams_FbByTeamMember.id
|
||||
if(!isAuthorized(team, authId)){
|
||||
logger.debug('User %s is not authorized to manage team %s.', authId, team.slug )
|
||||
throw new AutorizationError()
|
||||
}
|
||||
|
||||
let selectedBot = getSelectedBot(team, clone.botId)
|
||||
clone.teamId = team.id
|
||||
clone.botId = selectedBot.id
|
||||
clone.kind = selectedBot.kind
|
||||
clone.teamSlug = botsByUser.data.data.teams_FbByTeamMember.slug
|
||||
clone.teamSlug = team.slug
|
||||
clone.botSlug = selectedBot.slug
|
||||
clone.cloneName = getJobNameFromClone(clone)
|
||||
clone.teamName = botsByUser.data.data.teams_FbByTeamMember.name
|
||||
clone.cloneName = clone.teamSlug + '-' + clone.botSlug + '-' + clone.mode.toLowerCase()
|
||||
clone.teamName = team.name
|
||||
clone.botName = selectedBot.name
|
||||
clone.botAvatar = selectedBot.avatar
|
||||
let team = await teamAvatar(authorization, botsByUser.data.data.teams_FbByTeamMember.id)
|
||||
clone.teamAvatar = team.data.data.teams_TeamById.profile.avatar
|
||||
clone.userLoggedIn = botsByUser.data.data.teams_FbByTeamMember.members[0].member.alias //TODO change by context info if possible
|
||||
clone.teamAvatar = team.profile.avatar
|
||||
clone.userLoggedIn = team.members[0].member.alias //TODO change by context info if possible
|
||||
|
||||
logger.debug('Retrieving clone details complete.')
|
||||
return clone
|
||||
};
|
||||
|
||||
function getSelectedBot(team, selectedBotId){
|
||||
logger.debug('Getting selected bot.')
|
||||
if(isDefined(team)){
|
||||
for (var i = 0; i < team.fb.length; i++) {
|
||||
if(team.fb[i].id === selectedBotId){
|
||||
return team.fb[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isAuthorized(team, authId){
|
||||
logger.debug('Checking if the user is authorized by the teams module.')
|
||||
let authorized = false
|
||||
if(isDefined(team)){
|
||||
for (var i = 0; i < team.members.length; i++) {
|
||||
if(team.members[i].member.authId === authId){
|
||||
authorized = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return authorized
|
||||
}
|
||||
|
||||
export default cloneDetails
|
||||
@@ -3,7 +3,7 @@ import { CloneType } from '../types';
|
||||
import { Clone } from '../../models';
|
||||
import { CloneModeEnum } from '../../enums/CloneMode';
|
||||
import { BotTypesEnum } from '../../enums/BotTypes';
|
||||
import teams_FbByTeamMember from '../../graphQLCalls/teams_FbByTeamMember';
|
||||
import teamQuery from '../../graphQLCalls/teamQuery'
|
||||
import cloneDetails from '../cloneDetails'
|
||||
|
||||
import {
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
|
||||
import logger from '../../config/logger'
|
||||
import createKubernetesClone from '../../kubernetes/createClone'
|
||||
import { isDefined, getSelectedBot } from '../../config/utils'
|
||||
import { isDefined } from '../../config/utils'
|
||||
|
||||
const args = {
|
||||
clone: {type: CloneInputType }
|
||||
@@ -50,10 +50,8 @@ const resolve = async(parent, { clone }, context) => {
|
||||
}
|
||||
|
||||
try{
|
||||
// Authorization is handled by the teams module
|
||||
let botsByUser = await teams_FbByTeamMember(context.authorization)
|
||||
clone = await cloneDetails(context.authorization, botsByUser, clone)
|
||||
let selectedBot = getSelectedBot(botsByUser.data.data.teams_FbByTeamMember, clone.botId)
|
||||
let team = await teamQuery(context.authorization)
|
||||
clone = await cloneDetails(context.userId, team.data.data.teams_TeamById, clone)
|
||||
clone.createDatetime = new Date().valueOf() / 1000|0
|
||||
clone.active = true
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ import {
|
||||
import { Clone } from '../../models'
|
||||
import logger from '../../config/logger'
|
||||
import removeKuberneteClone from '../../kubernetes/removeClone'
|
||||
import teams_FbByTeamMember from '../../graphQLCalls/teams_FbByTeamMember'
|
||||
import { isDefined, getSelectedBot } from '../../config/utils'
|
||||
import teamQuery from '../../graphQLCalls/teamQuery'
|
||||
import { isDefined } from '../../config/utils'
|
||||
import cloneDetails from '../cloneDetails'
|
||||
|
||||
const args = {
|
||||
@@ -37,8 +37,8 @@ const resolve = async (parent, { id }, context) => {
|
||||
throw new OperationsError('You are not authorized to remove this clone.')
|
||||
}
|
||||
|
||||
let botsByUser = await teams_FbByTeamMember(context.authorization)
|
||||
clone = await cloneDetails(context.authorization, botsByUser, clone)
|
||||
let team = await teamQuery(context.authorization)
|
||||
clone = await cloneDetails(context.userId, team.data.data.teams_TeamById, clone)
|
||||
|
||||
logger.debug('removeClone -> Removing Clone from Kubernates.')
|
||||
await removeKuberneteClone(clone)
|
||||
|
||||
@@ -7,12 +7,12 @@ import {
|
||||
} from 'graphql'
|
||||
|
||||
import {
|
||||
|
||||
OperationsError
|
||||
} from '../../errors'
|
||||
|
||||
import { Clone } from '../../models'
|
||||
import logger from '../../config/logger'
|
||||
import teamQuery from '../../graphQLCalls/teamQuery'
|
||||
|
||||
const args = {
|
||||
id: { type: new GraphQLNonNull(GraphQLID) },
|
||||
@@ -29,34 +29,57 @@ const args = {
|
||||
const resolve = async (parent,
|
||||
{ id, summaryDate, buyAverage, sellAverage, marketRate, combinedProfitsA,
|
||||
combinedProfitsB, assetA, assetB
|
||||
}) => {
|
||||
}, context) => {
|
||||
|
||||
logger.debug('UpdateExecutionSummary -> Entering Function.')
|
||||
|
||||
const query = { _id: id }
|
||||
const options = { new: true }
|
||||
const update = {
|
||||
summaryDate: summaryDate,
|
||||
buyAverage: buyAverage,
|
||||
sellAverage: sellAverage,
|
||||
marketRate: marketRate,
|
||||
combinedProfitsA: combinedProfitsA,
|
||||
combinedProfitsB: combinedProfitsB,
|
||||
assetA: assetA,
|
||||
assetB: assetB
|
||||
if (!context.userId) {
|
||||
throw new AuthentificationError()
|
||||
}
|
||||
|
||||
let sucessful
|
||||
await Clone.findOneAndUpdate(query, update, options, (err, doc) => {
|
||||
if (err){
|
||||
throw new OperationsError(err)
|
||||
} else {
|
||||
logger.debug('Execution summary updated')
|
||||
sucessful = true
|
||||
}
|
||||
})
|
||||
try{
|
||||
let sucessful
|
||||
|
||||
if(sucessful){
|
||||
return 'Execution summary updated.'
|
||||
let clone = await Clone.findOne( {
|
||||
_id: id,
|
||||
active: true
|
||||
})
|
||||
|
||||
let team = await teamQuery(context.authorization)
|
||||
clone = await cloneDetails(context.userId, team.data.data.teams_TeamById, clone)
|
||||
|
||||
logger.debug('removeClone -> Removing Clone from Kubernates.')
|
||||
await removeKuberneteClone(clone)
|
||||
|
||||
const query = { _id: id }
|
||||
const options = { new: true }
|
||||
const update = {
|
||||
summaryDate: summaryDate,
|
||||
buyAverage: buyAverage,
|
||||
sellAverage: sellAverage,
|
||||
marketRate: marketRate,
|
||||
combinedProfitsA: combinedProfitsA,
|
||||
combinedProfitsB: combinedProfitsB,
|
||||
assetA: assetA,
|
||||
assetB: assetB
|
||||
}
|
||||
|
||||
await Clone.update(query, update, (err) => {
|
||||
if (err){
|
||||
logger.error('Error updating execution summary on the database. %s', err.stack)
|
||||
throw new OperationsError(err.message)
|
||||
} else {
|
||||
logger.debug('Execution summary updated.')
|
||||
sucessful = true
|
||||
}
|
||||
})
|
||||
|
||||
if(sucessful){
|
||||
return 'Execution summary updated.'
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error updating the execution summary. %s', error.stack)
|
||||
throw new OperationsError(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ import {
|
||||
} from 'graphql'
|
||||
|
||||
import {
|
||||
AuthentificationError
|
||||
AuthentificationError,
|
||||
OperationsError
|
||||
} from '../../errors'
|
||||
|
||||
import { CloneType } from '../types'
|
||||
@@ -11,14 +12,14 @@ import { Clone } from '../../models'
|
||||
import logger from '../../config/logger'
|
||||
import getKuberneteClonePodStatus from '../../kubernetes/getClonePodStatus'
|
||||
import getKuberneteClonePodLogs from '../../kubernetes/getClonePodLogs'
|
||||
import teams_FbByTeamMember from '../../graphQLCalls/teams_FbByTeamMember'
|
||||
import cloneDetails from '../cloneDetails'
|
||||
import teamQuery from '../../graphQLCalls/teamQuery'
|
||||
|
||||
const args = {}
|
||||
|
||||
const resolve = async(parent, args, context) => {
|
||||
logger.debug('History Clones -> Entering Fuction.')
|
||||
|
||||
logger.debug('Retrieving History Clones.')
|
||||
try{
|
||||
if (!context.userId) {
|
||||
throw new AuthentificationError()
|
||||
}
|
||||
@@ -26,18 +27,19 @@ const resolve = async(parent, args, context) => {
|
||||
let clones = await Clone.find({
|
||||
authId: context.userId,
|
||||
active: false
|
||||
})
|
||||
|
||||
// TODO Refactor this code once financial beings api is ready
|
||||
// Authorization is handled by the teams module
|
||||
let botsByUser = await teams_FbByTeamMember(context.authorization)
|
||||
}).sort({createDatetime: -1})
|
||||
|
||||
for (var i = 0; i < clones.length; i++) {
|
||||
clones[i] = await cloneDetails(context.authorization, botsByUser, clones[i])
|
||||
let team = await teamQuery(context.authorization, clones[i].teamId)
|
||||
clones[i] = await cloneDetails(context.userId, team.data.data.teams_TeamById, clones[i])
|
||||
clones[i].botType = clones[i].kind // Only for listing we show the teams value
|
||||
}
|
||||
|
||||
return clones
|
||||
} catch (err){
|
||||
logger.error('Retrieving History Clones error: %s', err.stack)
|
||||
throw new OperationsError('There has been an error retrieving history clones.')
|
||||
}
|
||||
}
|
||||
|
||||
const query = {
|
||||
|
||||
@@ -12,7 +12,6 @@ import { Clone } from '../../models'
|
||||
import logger from '../../config/logger'
|
||||
import getCloneStatus from '../../kubernetes/getClonePodStatus'
|
||||
import getCloneLogs from '../../kubernetes/getClonePodLogs'
|
||||
import teams_FbByTeamMember from '../../graphQLCalls/teams_FbByTeamMember'
|
||||
import cloneDetails from '../cloneDetails'
|
||||
|
||||
const args = {}
|
||||
@@ -27,14 +26,11 @@ const resolve = async(parent, args, context) => {
|
||||
let clones = await Clone.find({
|
||||
authId: context.userId,
|
||||
active: true
|
||||
})
|
||||
|
||||
// TODO Refactor this code once financial beings api is ready
|
||||
// Authorization is handled by the teams module
|
||||
let botsByUser = await teams_FbByTeamMember(context.authorization)
|
||||
}).sort({createDatetime: -1})
|
||||
|
||||
for (var i = 0; i < clones.length; i++) {
|
||||
clones[i] = await cloneDetails(context.authorization, botsByUser, clones[i])
|
||||
let team = await teamQuery(context.authorization, clones[i].teamId)
|
||||
clones[i] = await cloneDetails(context.userId, team.data.data.teams_TeamById, clones[i])
|
||||
let state = await getCloneStatus(clones[i].cloneName)
|
||||
clones[i].state = state.substring(1, state.length-1)
|
||||
let lastLogs = await getCloneLogs(clones[i].cloneName)
|
||||
|
||||
Reference in new issue
Block a user