diff --git a/Canvas.js b/Canvas.js index fcc1c23b6..113cd3047 100644 --- a/Canvas.js +++ b/Canvas.js @@ -47,6 +47,7 @@ function newCanvas () { let splashScreen let lastContainerMouseOver + let lastShortcutKeyRejection return thisObject @@ -80,7 +81,7 @@ function newCanvas () { } } - async function initialize () { + function initialize () { try { initializeBrowserCanvas() @@ -92,10 +93,10 @@ function newCanvas () { thisObject.floatingSpace.initialize() thisObject.topSpace = newTopSpace() - await thisObject.topSpace.initialize() + thisObject.topSpace.initialize() thisObject.designerSpace = newDesignerSpace() - await thisObject.designerSpace.initialize() + thisObject.designerSpace.initialize() thisObject.cockpitSpace = newCockpitSpace() thisObject.cockpitSpace.initialize() @@ -104,17 +105,10 @@ function newCanvas () { thisObject.panelsSpace.initialize() thisObject.chartSpace = newChartSpace() - thisObject.chartSpace.initialize(onCharSpaceInitialized) + thisObject.chartSpace.initialize() thisObject.bottomSpace = thisObject.cockpitSpace - function onCharSpaceInitialized (err) { - try { - viewPort.raiseEvents() // These events will impacts on objects just initialized. - } catch (err) { - if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> onCharSpaceInitialized -> err = ' + err.stack) } - } - } splashScreen = newSplashScreen() splashScreen.initialize() @@ -225,12 +219,27 @@ function newCanvas () { return } - if (event.shiftKey === true && event.code === 'ArrowLeft') { + if (event.altKey === true && event.code === 'ArrowLeft' || event.altKey === true && event.code === 'ArrowRight') { + thisObject.cockpitSpace.toMiddle() + return + } + + if (event.shiftKey === true && event.ctrlKey && event.code === 'ArrowUp') { + thisObject.cockpitSpace.moveUp() + return + } + + if (event.shiftKey === true && event.ctrlKey && event.code === 'ArrowDown') { + thisObject.cockpitSpace.moveDown() + return + } + + if (event.shiftKey === true && event.ctrlKey === false && event.code === 'ArrowLeft') { canvas.chartSpace.oneScreenLeft() return } - if (event.shiftKey === true && event.code === 'ArrowRight') { + if (event.shiftKey === true && event.ctrlKey === false && event.code === 'ArrowRight') { canvas.chartSpace.oneScreenRight() return } @@ -245,7 +254,7 @@ function newCanvas () { return } - if ((event.ctrlKey === true || event.metaKey === true) && event.code === 'ArrowLeft') { + if ((event.ctrlKey === true || event.metaKey === true) && event.shiftKey === false && event.code === 'ArrowLeft') { let displaceVector = canvas.floatingSpace.oneScreenLeft() dragVector.downX = dragVector.downX + displaceVector.x dragVector.downY = dragVector.downY + displaceVector.y @@ -253,7 +262,7 @@ function newCanvas () { return } - if ((event.ctrlKey === true || event.metaKey === true) && event.code === 'ArrowRight') { + if ((event.ctrlKey === true || event.metaKey === true) && event.shiftKey === false && event.code === 'ArrowRight') { let displaceVector = canvas.floatingSpace.oneScreenRight() dragVector.downX = dragVector.downX + displaceVector.x dragVector.downY = dragVector.downY + displaceVector.y @@ -285,7 +294,7 @@ function newCanvas () { } if ((event.ctrlKey === true || event.metaKey === true) && event.altKey === true) { - if (event.keyCode >= 65 && event.keyCode <= 90) { + if ((event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 65 && event.keyCode <= 90)) { /* From here we prevent the default behaviour */ event.preventDefault() @@ -304,8 +313,16 @@ function newCanvas () { nodeOnFocus.payload.uiObject.setValue('Shortcut Key Removed ') return } else { - nodeOnFocus.payload.uiObject.setErrorMessage('Key already in use by ' + nodeUsingThisKey.type + ' ' + nodeUsingThisKey.name) - return + if (lastShortcutKeyRejection !== event.key + nodeUsingThisKey.type + ' ' + nodeUsingThisKey.name) { + /* The first time we show a warning that this key is in use. */ + nodeOnFocus.payload.uiObject.setErrorMessage('Key already in use by ' + nodeUsingThisKey.type + ' ' + nodeUsingThisKey.name) + lastShortcutKeyRejection = event.key + nodeUsingThisKey.type + ' ' + nodeUsingThisKey.name + return + } else { + /* After the warning, we allow the key to be re-assigned */ + nodeUsingThisKey.payload.uiObject.shortcutKey = '' + nodeUsingThisKey === undefined + } } } /* If there is not node using this key and a node in focus, we assign this key to this node */ diff --git a/ChartsSpace/PlottersManager.js b/ChartsSpace/PlottersManager.js index 8b9fb6a7c..127d0ce6b 100644 --- a/ChartsSpace/PlottersManager.js +++ b/ChartsSpace/PlottersManager.js @@ -21,40 +21,48 @@ function newPlottersManager () { finalize: finalize } - thisObject.container = newContainer() - thisObject.container.initialize(MODULE_NAME) - let initializationReady = false let productsPanel let exchange let market + setupContainer() return thisObject - function finalize (callBackFunction) { - try { - for (let i = 0; i < productPlotters.length; i++) { - if (productPlotters[i].profile !== undefined) { - canvas.floatingSpace.profileBalls.destroyProfileBall(productPlotters[i].profile) - } - /* Destroyd the Note Set */ - canvas.floatingSpace.noteSets.destroyNoteSet(productPlotters[i].noteSet) - /* Then the panels. */ - for (let j = 0; j < productPlotters[i].panels.length; j++) { - canvas.panelsSpace.destroyPanel(productPlotters[i].panels[j]) - } - /* Finally the Storage Objects */ - productPlotters[i].storage.finalize() - if (productPlotters[i].plotter.finalize !== undefined) { - productPlotters[i].plotter.finalize() - } - productPlotters.splice(i, 1) // Delete item from array. + function setupContainer () { + thisObject.container = newContainer() + thisObject.container.initialize(MODULE_NAME) + } + + function finalize () { + for (let i = 0; i < productPlotters.length; i++) { + /* Then the panels. */ + for (let j = 0; j < productPlotters[i].panels.length; j++) { + canvas.panelsSpace.destroyPanel(productPlotters[i].panels[j]) + productPlotters[i].panels[j] = undefined } - } catch (err) { - if (ERROR_LOG === true) { logger.write('[ERROR] finalize -> err = ' + err.stack) } - callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) + productPlotters[i].panels = undefined + + /* Finalize the plotters */ + if (productPlotters[i].plotter.finalize !== undefined) { + productPlotters[i].plotter.finalize() + } + productPlotters[i].plotter = undefined + + /* Finally the Storage Objects */ + productPlotters[i].storage.finalize() + productPlotters[i].storage = undefined + + productPlotters[i] = undefined } + productPlotters = [] + + productsPanel = undefined + + thisObject.container.finalize() + thisObject.container = undefined + setupContainer() } function initialize (pProductsPanel, pExchange, pMarket, callBackFunction) { @@ -168,13 +176,24 @@ function newPlottersManager () { } } /* Now we have all the initial data loaded and ready to be delivered to the new instance of the plotter. */ - let plotter = getNewPlotter(pProductCard.product.plotter.devTeam, pProductCard.product.plotter.codeName, pProductCard.product.plotter.moduleName) + let plotter + let productDefinition + + if (pProductCard.product.plotter.legacy === false) { + plotter = newPlotter() + + /* We take a snapwhot of the current product definition to be used by the plotter. */ + let functionLibraryProtocolNode = newProtocolNode() + productDefinition = functionLibraryProtocolNode.getProtocolNode(pProductCard.product.node, false, true, true, false, false, true) + } else { + plotter = getNewPlotter(pProductCard.product.plotter.devTeam, pProductCard.product.plotter.codeName, pProductCard.product.plotter.moduleName) + } plotter.container.connectToParent(thisObject.container, true, true, false, true, true, true) plotter.container.frame.position.x = thisObject.container.frame.width / 2 - plotter.container.frame.width / 2 plotter.container.frame.position.y = thisObject.container.frame.height / 2 - plotter.container.frame.height / 2 plotter.fitFunction = thisObject.fitFunction - plotter.initialize(storage, exchange, market, datetime, timePeriod, onPlotterInizialized) + plotter.initialize(storage, exchange, market, datetime, timePeriod, onPlotterInizialized, productDefinition) function onPlotterInizialized () { try { @@ -190,6 +209,7 @@ function newPlottersManager () { /* Lets load now this plotter panels. */ productPlotter.panels = [] + /* Here is where we instantiate the legacy panels */ for (let i = 0; i < pProductCard.product.plotter.module.panels.length; i++) { let panelConfig = pProductCard.product.plotter.module.panels[i] @@ -209,6 +229,27 @@ function newPlottersManager () { productPlotter.panels.push(plotterPanelHandle) } + /* Here we instantiate the UI Defined Panels. */ + if (productDefinition !== undefined) { + for (let i = 0; i < productDefinition.referenceParent.panels.length; i++) { + let panel = productDefinition.referenceParent.panels[i] + + let parameters = { + devTeam: pProductCard.product.plotter.devTeam, + plotterCodeName: pProductCard.product.plotter.codeName, + moduleCodeName: pProductCard.product.plotter.moduleName, + panelCodeName: panel.id + } + let panelOwner = exchange + ' ' + market.assetB + '/' + market.assetA + let plotterPanelHandle = canvas.panelsSpace.createNewPanel('Plotter Panel', parameters, panelOwner, pProductCard.session, panel) + let plotterPanel = canvas.panelsSpace.getPanel(plotterPanelHandle, panelOwner) + + /* Connect Panel to the Plotter via an Event. */ + productPlotter.plotter.container.eventHandler.listenToEvent('Current Record Changed', plotterPanel.onRecordChange) + productPlotter.panels.push(plotterPanelHandle) + } + } + productPlotters.push(productPlotter) callBack(GLOBAL.DEFAULT_OK_RESPONSE) } catch (err) { diff --git a/ChartsSpace/TimeMachine.js b/ChartsSpace/TimeMachine.js index b56d543dd..8b35c71fe 100644 --- a/ChartsSpace/TimeMachine.js +++ b/ChartsSpace/TimeMachine.js @@ -28,17 +28,6 @@ function newTimeMachine () { finalize: finalize } - thisObject.container = newContainer() - thisObject.container.initialize(MODULE_NAME) - thisObject.container.isDraggeable = false - thisObject.container.detectMouseOver = true - - thisObject.container.frame.width = TIME_MACHINE_WIDTH - thisObject.container.frame.height = TIME_MACHINE_HEIGHT - - thisObject.container.frame.position.x = browserCanvas.width / 2 - TIME_MACHINE_WIDTH / 2 - thisObject.container.frame.position.y = browserCanvas.height / 2 - TIME_MACHINE_HEIGHT / 2 - let controlPanelHandle // We need this to destroy the Panel when this object is itself destroyed or no longer needs it... // ... also to request a reference to the object for the cases we need it. const SEPARATION_BETWEEN_TIMELINE_CHARTS = 1.5 @@ -52,21 +41,38 @@ function newTimeMachine () { } } + setupContainer() return thisObject + function setupContainer () { + thisObject.container = newContainer() + thisObject.container.initialize(MODULE_NAME) + thisObject.container.isDraggeable = false + thisObject.container.detectMouseOver = true + + thisObject.container.frame.width = TIME_MACHINE_WIDTH + thisObject.container.frame.height = TIME_MACHINE_HEIGHT + + thisObject.container.frame.position.x = browserCanvas.width / 2 - TIME_MACHINE_WIDTH / 2 + thisObject.container.frame.position.y = browserCanvas.height / 2 - TIME_MACHINE_HEIGHT / 2 + } + function finalize () { for (let i = 0; i < thisObject.charts.length; i++) { let chart = thisObject.charts[i] chart.finalize() } - thisObject.container.finalize() - thisObject.container = undefined + thisObject.charts = [] thisObject.timeScale.finalize() thisObject.timeScale = undefined thisObject.rateScale.finalize() thisObject.rateScale = undefined thisObject.fitFunction = undefined + + thisObject.container.finalize() + thisObject.container = undefined + setupContainer() } function initialize (callBackFunction) { @@ -235,8 +241,12 @@ function newTimeMachine () { } else { if (purpose === GET_CONTAINER_PURPOSE.MOUSE_OVER) { thisObject.container.eventHandler.raiseEvent('onMouseNotOver') - thisObject.timeScale.visible = false - thisObject.rateScale.visible = false + if (thisObject.timeScale !== undefined) { + thisObject.timeScale.visible = false + } + if (thisObject.rateScale !== undefined) { + thisObject.rateScale.visible = false + } } return } @@ -261,6 +271,9 @@ function newTimeMachine () { } function childrenPhysics () { + if (thisObject.timeScale === undefined) { return } + if (thisObject.rateScale === undefined) { return } + thisObject.timeScale.physics() thisObject.rateScale.physics() diff --git a/ChartsSpace/TimelineChart.js b/ChartsSpace/TimelineChart.js index e06b51dee..1ade95cc3 100644 --- a/ChartsSpace/TimelineChart.js +++ b/ChartsSpace/TimelineChart.js @@ -23,10 +23,6 @@ function newTimelineChart () { finalize: finalize } - thisObject.container = newContainer() - thisObject.container.initialize(MODULE_NAME) - thisObject.container.detectMouseOver = true - thisObject.fitFunction = canvas.chartSpace.fitIntoVisibleArea let initializationReady = false @@ -50,16 +46,25 @@ function newTimelineChart () { let productsPanelHandle let timePeriodScale + setupContainer() return thisObject - function finalize () { - try { - if (INFO_LOG === true) { logger.write('[INFO] finalize -> Entering function.') } + function setupContainer () { + thisObject.container = newContainer() + thisObject.container.initialize(MODULE_NAME) + thisObject.container.detectMouseOver = true + } - plotterManager.finalize() - } catch (err) { - if (ERROR_LOG === true) { logger.write('[ERROR] finalize -> err = ' + err.stack) } - } + function finalize () { + plotterManager.finalize() + plotterManager = undefined + timePeriodScale.finalize() + timePeriodScale = undefined + canvas.panelsSpace.destroyPanel(productsPanelHandle) + + thisObject.container.finalize() + thisObject.container = undefined + setupContainer() } function initialize (pExchange, pMarket, pTimeLineCoordinateSystem, callBackFunction) { diff --git a/ChartsSpace/ViewPort.js b/ChartsSpace/ViewPort.js index 55146cbd0..b96904c80 100644 --- a/ChartsSpace/ViewPort.js +++ b/ChartsSpace/ViewPort.js @@ -85,8 +85,8 @@ function newViewPort () { function resize () { TOP_MARGIN = 30 + TOP_SPACE_HEIGHT BOTTOM_MARGIN = 30 + browserCanvas.height - COCKPIT_SPACE_POSITION - LEFT_MARGIN = 50 - RIGHT_MARGIN = 50 + LEFT_MARGIN = 0 + RIGHT_MARGIN = 0 MARGINS = { TOP: TOP_MARGIN, BOTTOM: BOTTOM_MARGIN, diff --git a/Dashboard.js b/Dashboard.js index 5e0d85852..ff9e3d493 100644 --- a/Dashboard.js +++ b/Dashboard.js @@ -3,6 +3,8 @@ let markets let ecosystem = newEcosystem() let systemEventHandler let viewPort +let APP_SCHEMA_MAP = new Map() +let APP_SCHEMA_ARRAY = [] function newDashboard () { const MODULE_NAME = 'Dashboard' @@ -29,7 +31,23 @@ function newDashboard () { viewPort = newViewPort() systemEventHandler = newSystemEventHandler() - systemEventHandler.initialize(startCanvas) + systemEventHandler.initialize(setUpAppSchema) + + function setUpAppSchema () { + APP_SCHEMA_ARRAY = getAppSchema() + for (let i = 0; i < APP_SCHEMA_ARRAY.length; i++) { + let nodeDefinition = APP_SCHEMA_ARRAY[i] + let key + if (nodeDefinition.subType !== undefined) { + key = nodeDefinition.type + '-' + nodeDefinition.subType + } else { + key = nodeDefinition.type + } + APP_SCHEMA_MAP.set(key, nodeDefinition) + } + console.log(APP_SCHEMA_MAP) + startCanvas() + } function startCanvas () { /* If this method is executed for a second time, it should finalize the current execution structure */ @@ -110,4 +128,3 @@ function newDashboard () { } } } - diff --git a/DesignerSpace/StrategizerGateway.js b/DesignerSpace/StrategizerGateway.js deleted file mode 100644 index 2b626447f..000000000 --- a/DesignerSpace/StrategizerGateway.js +++ /dev/null @@ -1,95 +0,0 @@ - -function newStrategizerGateway () { - const MODULE_NAME = 'Strategizer Gateway' - const logger = newWebDebugLog() - logger.fileName = MODULE_NAME - - let thisObject = { - idAtStrategizer: undefined, - strategizerData: undefined, - container: undefined, - loadFromStrategyzer: loadFromStrategyzer - } - - let colletionItems = [] - - thisObject.container = newContainer() - thisObject.container.name = MODULE_NAME - thisObject.container.initialize() - - thisObject.container.frame.width = 0 - thisObject.container.frame.height = 0 - - thisObject.container.frame.position.x = 0 - thisObject.container.frame.position.y = 0 - - thisObject.container.isDraggeable = false - thisObject.container.isClickeable = false - - let graphQLServer - - return thisObject - - async function loadFromStrategyzer () { - try { - const accessToken = window.localStorage.getItem(LOGGED_IN_ACCESS_TOKEN_LOCAL_STORAGE_KEY) - if (accessToken === null) { - logger.write('[ERROR] loadFromStrategyzer -> Can load from strategizer because the accessToken is missing.') - return - } - - let user = window.localStorage.getItem(LOGGED_IN_USER_LOCAL_STORAGE_KEY) - if (user === null) { - logger.write('[ERROR] saveToStrategyzer -> Can not load from strategizer because user is not logged in. ') - return - } - - user = JSON.parse(user) - - if (window.canvasApp.executingAt === 'Local') { - window.localStorage.setItem(CANVAS_APP_NAME + '.' + MODULE_NAME + '.' + user.alias, 'Local File') - thisObject.strategizerData = JSON.parse('{"type":"Definition"}') - thisObject.idAtStrategizer = 'Local File' - return true - } else { - let fbSlug = 'simulator-bot-' + user.alias.replace('.', '') - - graphQLServer = await axios({ - url: window.canvasApp.graphQL.masterAppApiUrl, - method: 'post', - data: { - query: - ` - query($fbSlug: String!){ - strategizer_TradingSystemByFb(fbSlug: $fbSlug){ - id - fbSlug - data - } - } - `, - - variables: { - fbSlug: fbSlug - } - }, - headers: { - authorization: 'Bearer ' + accessToken - } - }) - - if (graphQLServer.data.errors) { - logger.write('[ERROR] loadFromStrategyzer -> GraphQL Error: ' + JSON.stringify(graphQLServer.data.errors)) - return false - } else { - thisObject.strategizerData = JSON.parse(JSON.stringify(graphQLServer.data.data.strategizer_TradingSystemByFb.data)) - thisObject.idAtStrategizer = graphQLServer.data.data.strategizer_TradingSystemByFb.id - window.localStorage.setItem(CANVAS_APP_NAME + '.' + MODULE_NAME + '.' + user.alias, thisObject.idAtStrategizer) - return true - } - } - } catch (err) { - logger.write('[ERROR] loadFromStrategyzer -> err = ' + err.stack) - } - } -} diff --git a/DesignerSpace/Workspace/FunctionLibraries/ChainAttachDetach.js b/DesignerSpace/Workspace/FunctionLibraries/ChainAttachDetach.js index 768153f6a..e4c5e9e04 100644 --- a/DesignerSpace/Workspace/FunctionLibraries/ChainAttachDetach.js +++ b/DesignerSpace/Workspace/FunctionLibraries/ChainAttachDetach.js @@ -501,8 +501,8 @@ function newChainAttachDetach () { completeDetachment(node, rootNodes) return } - case 'Code': { - node.payload.parentNode.code = undefined + case 'Javascript Code': { + node.payload.parentNode.javascriptCode = undefined completeDetachment(node, rootNodes) return } @@ -1100,10 +1100,10 @@ function newChainAttachDetach () { completeAttachment(node, rootNodes) } break - case 'Code': { + case 'Javascript Code': { node.payload.parentNode = attachToNode node.payload.chainParent = attachToNode - node.payload.parentNode.code = node + node.payload.parentNode.javascriptCode = node completeAttachment(node, rootNodes) } break diff --git a/DesignerSpace/Workspace/FunctionLibraries/NodeChildren.js b/DesignerSpace/Workspace/FunctionLibraries/NodeChildren.js index f96277c64..1eb525cd0 100644 --- a/DesignerSpace/Workspace/FunctionLibraries/NodeChildren.js +++ b/DesignerSpace/Workspace/FunctionLibraries/NodeChildren.js @@ -227,8 +227,8 @@ function newNodeChildren () { case 'Condition': { return countChildrenCondition(parentNode, childNode) } - case 'Code': { - return countChildrenCode(parentNode, childNode) + case 'Javascript Code': { + return countChildrenJavascriptCode(parentNode, childNode) } default: { console.log('WARNING this parentNode type is not listed at NodeChildren: ' + parentNode.type) @@ -1483,7 +1483,7 @@ function newNodeChildren () { return response } - function countChildrenCode (parentNode, childNode) { + function countChildrenJavascriptCode (parentNode, childNode) { let response = { childrenCount: 0, childIndex: undefined diff --git a/DesignerSpace/Workspace/FunctionLibraries/NodeDeleter.js b/DesignerSpace/Workspace/FunctionLibraries/NodeDeleter.js index 1435c1a90..da06b462f 100644 --- a/DesignerSpace/Workspace/FunctionLibraries/NodeDeleter.js +++ b/DesignerSpace/Workspace/FunctionLibraries/NodeDeleter.js @@ -69,7 +69,7 @@ function newNodeDeleter () { deleteFormula: deleteFormula, deleteSituation: deleteSituation, deleteCondition: deleteCondition, - deleteCode: deleteCode + deleteJavascriptCode: deleteJavascriptCode } return thisObject @@ -372,8 +372,8 @@ function newNodeDeleter () { deleteCondition(rootNode, rootNodes) break } - case 'Code': { - deleteCode(rootNode, rootNodes) + case 'Javascript Code': { + deleteJavascriptCode(rootNode, rootNodes) break } @@ -733,8 +733,8 @@ function newNodeDeleter () { payload.parentNode.loop = undefined } - if (node.code !== undefined) { - deleteCode(node.code, rootNodes) + if (node.javascriptCode !== undefined) { + deleteJavascriptCode(node.javascriptCode, rootNodes) } completeDeletion(node, rootNodes) @@ -919,8 +919,8 @@ function newNodeDeleter () { } } - if (node.code !== undefined) { - deleteCode(node.code, rootNodes) + if (node.javascriptCode !== undefined) { + deleteJavascriptCode(node.javascriptCode, rootNodes) } if (node.panels !== undefined) { @@ -946,8 +946,8 @@ function newNodeDeleter () { } } - if (node.code !== undefined) { - deleteCode(node.code, rootNodes) + if (node.javascriptCode !== undefined) { + deleteJavascriptCode(node.javascriptCode, rootNodes) } completeDeletion(node, rootNodes) @@ -1697,17 +1697,17 @@ function newNodeDeleter () { } else { completeDeletion(node, rootNodes) } - if (node.code !== undefined) { - deleteCode(node.code, rootNodes) + if (node.javascriptCode !== undefined) { + deleteJavascriptCode(node.javascriptCode, rootNodes) } destroyUiObject(node) cleanNode(node) } - function deleteCode (node, rootNodes) { + function deleteJavascriptCode (node, rootNodes) { let payload = node.payload if (payload.parentNode !== undefined) { - payload.parentNode.code = undefined + payload.parentNode.javascriptCode = undefined } else { completeDeletion(node, rootNodes) } diff --git a/DesignerSpace/Workspace/FunctionLibraries/OnFocus.js b/DesignerSpace/Workspace/FunctionLibraries/OnFocus.js index d3633c3d7..353eb3723 100644 --- a/DesignerSpace/Workspace/FunctionLibraries/OnFocus.js +++ b/DesignerSpace/Workspace/FunctionLibraries/OnFocus.js @@ -7,7 +7,7 @@ function newOnFocus () { function getNodeThatIsOnFocus (node) { if (node === undefined) { return } switch (node.type) { - case 'Code': + case 'Javascript Code': { if (node.payload.uiObject.isOnFocus === true) { return node diff --git a/DesignerSpace/Workspace/FunctionLibraries/ProtocolNode.js b/DesignerSpace/Workspace/FunctionLibraries/ProtocolNode.js index 2fdb0ae82..68482972f 100644 --- a/DesignerSpace/Workspace/FunctionLibraries/ProtocolNode.js +++ b/DesignerSpace/Workspace/FunctionLibraries/ProtocolNode.js @@ -7,7 +7,7 @@ function newProtocolNode () { function getProtocolNode (node, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) { if (node === undefined) { return } switch (node.type) { - case 'Code': + case 'Javascript Code': { let object = { type: node.type, @@ -29,7 +29,7 @@ function newProtocolNode () { type: node.type, subType: node.subType, name: node.name, - code: getProtocolNode(node.code, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) + javascriptCode: getProtocolNode(node.javascriptCode, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) } if (includeIds) { object.id = node.id @@ -1402,7 +1402,7 @@ function newProtocolNode () { type: node.type, subType: node.subType, name: node.name, - code: getProtocolNode(node.code, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) + javascriptCode: getProtocolNode(node.javascriptCode, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) } if (includeIds) { object.id = node.id @@ -1417,7 +1417,7 @@ function newProtocolNode () { type: node.type, subType: node.subType, name: node.name, - code: getProtocolNode(node.code, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) + javascriptCode: getProtocolNode(node.javascriptCode, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) } if (includeIds) { object.id = node.id @@ -1518,6 +1518,9 @@ function newProtocolNode () { if (includePayload) { object.savedPayload = getSavedPayload(node, includeReferences) } + if (followReferenceParent) { + object.referenceParent = getProtocolNode(node.payload.referenceParent, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) + } return object } case 'Record Definition': { @@ -1590,16 +1593,20 @@ function newProtocolNode () { type: node.type, subType: node.subType, name: node.name, + code: node.code, modules: [] } - if (node.modules !== undefined) { - for (let m = 0; m < node.modules.length; m++) { - let module = getProtocolNode(node.modules[m], removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) - if (module !== undefined) { - object.modules.push(module) + if (excludeChildren !== true) { + if (node.modules !== undefined) { + for (let m = 0; m < node.modules.length; m++) { + let module = getProtocolNode(node.modules[m], removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) + if (module !== undefined) { + object.modules.push(module) + } } } } + if (includeIds) { object.id = node.id } @@ -1613,9 +1620,16 @@ function newProtocolNode () { type: node.type, subType: node.subType, name: node.name, - code: getProtocolNode(node.code, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType), + code: node.code, + javascriptCode: getProtocolNode(node.javascriptCode, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType), + shapes: getProtocolNode(node.shapes, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType), panels: [] } + if (includeParent) { + followAncestors = true + excludeChildren = true + object.parentNode = getProtocolNode(node.payload.parentNode, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) + } if (node.panels !== undefined) { for (let m = 0; m < node.panels.length; m++) { let panel = getProtocolNode(node.panels[m], removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) @@ -1637,7 +1651,7 @@ function newProtocolNode () { type: node.type, subType: node.subType, name: node.name, - code: getProtocolNode(node.code, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) + javascriptCode: getProtocolNode(node.javascriptCode, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) } if (includeIds) { object.id = node.id @@ -1648,6 +1662,90 @@ function newProtocolNode () { return object } + default: { + let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + if (nodeDefinition !== undefined) { + if (removePersonalData === true && nodeDefinition.isPersonalData === true) { return } + let object = { + type: node.type, + subType: node.subType, + name: node.name, + code: node.code + } + + if (excludeChildren !== true) { + /* Children Nodes */ + if (nodeDefinition.properties !== undefined) { + for (i = 0; i < nodeDefinition.properties.length; i++) { + let property = nodeDefinition.properties[i] + + switch (property.type) { + case 'node': { + if (node[property.name] !== undefined) { + if (excludeType !== property.childType) { + object[property.name] = getProtocolNode(node.payload.parentNode, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) + } + } + break + } + case 'array': { + if (node[property.name] !== undefined) { + if (excludeType !== property.childType) { + let nodePropertyArray = node[property.name] + object[property.name] = [] + for (let m = 0; m < nodePropertyArray.length; m++) { + let protocolNode = getProtocolNode(nodePropertyArray[m], removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) + if (protocolNode !== undefined) { + object[property.name].push(protocolNode) + } + } + } + } + break + } + } + } + } + } + + /* Ancestors Nodes */ + if (includeParent) { + if (nodeDefinition.followAncestors !== undefined) { + followAncestors = nodeDefinition.followAncestors + } + if (nodeDefinition.excludeChildren !== undefined) { + excludeChildren = nodeDefinition.excludeChildren + } + if (nodeDefinition.excludeType !== undefined) { + excludeType = nodeDefinition.excludeType + } + object.parentNode = getProtocolNode(node.payload.parentNode, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) + } + + /* Ancestors Nodes */ + if (followAncestors) { + if (nodeDefinition.excludeChildren !== undefined) { + excludeChildren = nodeDefinition.excludeChildren + } + object.parentNode = getProtocolNode(node.payload.parentNode, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) + } + + if (parseCode) { + object.code = JSON.parse(node.code) + } + + if (includeIds) { + object.id = node.id + } + if (includePayload) { + object.savedPayload = getSavedPayload(node, includeReferences) + } + if (followReferenceParent) { + object.referenceParent = getProtocolNode(node.payload.referenceParent, removePersonalData, parseCode, includeIds, includePayload, includeReferences, followReferenceParent, includeParent, followAncestors, excludeChildren, excludeType) + } + return object + } + } } } diff --git a/DesignerSpace/Workspace/FunctionLibraries/ReferenceAttachDetach.js b/DesignerSpace/Workspace/FunctionLibraries/ReferenceAttachDetach.js index 0b5099aff..ad9ed3e4f 100644 --- a/DesignerSpace/Workspace/FunctionLibraries/ReferenceAttachDetach.js +++ b/DesignerSpace/Workspace/FunctionLibraries/ReferenceAttachDetach.js @@ -44,6 +44,10 @@ function newReferenceAttachDetach () { completeDetachment(node) return } + case 'Product Definition': { + completeDetachment(node) + return + } } } @@ -85,6 +89,10 @@ function newReferenceAttachDetach () { completeAttachment(node, attachToNode) } break + case 'Product Definition': { + completeAttachment(node, attachToNode) + } + break } } diff --git a/DesignerSpace/Workspace/FunctionLibraries/ShortcutKeys.js b/DesignerSpace/Workspace/FunctionLibraries/ShortcutKeys.js index 874f93f29..31e3c7070 100644 --- a/DesignerSpace/Workspace/FunctionLibraries/ShortcutKeys.js +++ b/DesignerSpace/Workspace/FunctionLibraries/ShortcutKeys.js @@ -7,7 +7,7 @@ function newShortcutKeys () { function getNodeByShortcutKey (node, searchingKey) { if (node === undefined) { return } switch (node.type) { - case 'Code': + case 'Javascript Code': { if (node.payload.uiObject.shortcutKey === searchingKey) { return node diff --git a/DesignerSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js b/DesignerSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js index dc713be6f..e2a05c867 100644 --- a/DesignerSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js +++ b/DesignerSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js @@ -2,6 +2,7 @@ function newUiObjectsFromNodes () { thisObject = { recreateWorkspace: recreateWorkspace, createUiObjectFromNode: createUiObjectFromNode, + addUIObject: addUIObject, addTeam: addTeam, addSensorBot: addSensorBot, addIndicatorBot: addIndicatorBot, @@ -65,7 +66,7 @@ function newUiObjectsFromNodes () { addNextPhaseEvent: addNextPhaseEvent, addSituation: addSituation, addCondition: addCondition, - addCode: addCode + addJavascriptCode: addJavascriptCode } let mapOfReferenceParents @@ -77,7 +78,7 @@ function newUiObjectsFromNodes () { mapOfReferenceParents = new Map() mapOfReferenceChildren = new Map() let workspace = node - createUiObject('Workspace', workspace.name, workspace, undefined, undefined, 'Workspace') + createUiObject(false, 'Workspace', workspace.name, workspace, undefined, undefined, 'Workspace') if (node.rootNodes !== undefined) { for (let i = 0; i < node.rootNodes.length; i++) { let rootNode = node.rootNodes[i] @@ -110,22 +111,23 @@ function newUiObjectsFromNodes () { function createUiObjectFromNode (node, parentNode, chainParent, positionOffset) { switch (node.type) { - case 'Code': + case 'Javascript Code': { - createUiObject('Code', node.name, node, parentNode, chainParent, 'Code', positionOffset) + createUiObject(false, 'Javascript Code', node.name, node, parentNode, chainParent, 'Javascript Code', positionOffset) return } case 'Condition': { - createUiObject('Condition', node.name, node, parentNode, chainParent, 'Condition', positionOffset) - if (node.code !== undefined) { - createUiObjectFromNode(node.code, node, node, positionOffset) + createUiObject(false, 'Condition', node.name, node, parentNode, chainParent, 'Condition', positionOffset) + + if (node.javascriptCode !== undefined) { + createUiObjectFromNode(node.javascriptCode, node, node, positionOffset) } return } case 'Situation': { let situation = node - createUiObject('Situation', situation.name, situation, parentNode, chainParent, 'Situation', positionOffset) + createUiObject(false, 'Situation', situation.name, situation, parentNode, chainParent, 'Situation', positionOffset) for (let m = 0; m < node.conditions.length; m++) { let condition = node.conditions[m] createUiObjectFromNode(condition, situation, situation, positionOffset) @@ -134,12 +136,12 @@ function newUiObjectsFromNodes () { } case 'Formula': { - createUiObject('Formula', node.name, node, parentNode, chainParent, 'Formula', positionOffset) + createUiObject(false, 'Formula', node.name, node, parentNode, chainParent, 'Formula', positionOffset) return } case 'Next Phase Event': { - createUiObject('Next Phase Event', node.name, node, parentNode, chainParent, 'Next Phase Event', positionOffset) + createUiObject(false, 'Next Phase Event', node.name, node, parentNode, chainParent, 'Next Phase Event', positionOffset) for (let m = 0; m < node.situations.length; m++) { let situation = node.situations[m] createUiObjectFromNode(situation, node, node, positionOffset) @@ -155,7 +157,7 @@ function newUiObjectsFromNodes () { } case 'Phase': { let phase = node - createUiObject('Phase', phase.name, phase, parentNode, chainParent, phase.subType, positionOffset) + createUiObject(false, 'Phase', phase.name, phase, parentNode, chainParent, phase.subType, positionOffset) if (node.formula !== undefined) { createUiObjectFromNode(node.formula, phase, phase, positionOffset) @@ -175,7 +177,7 @@ function newUiObjectsFromNodes () { case 'Stop': { let lastPhase let stop = node - createUiObject('Stop', stop.name, stop, parentNode, chainParent, 'Stop', positionOffset) + createUiObject(false, 'Stop', stop.name, stop, parentNode, chainParent, 'Stop', positionOffset) for (let m = 0; m < node.phases.length; m++) { let phase = node.phases[m] let thisChainParent @@ -192,7 +194,7 @@ function newUiObjectsFromNodes () { case 'Take Profit': { let lastPhase let takeProfit = node - createUiObject('Take Profit', takeProfit.name, takeProfit, parentNode, chainParent, 'Take Profit', positionOffset) + createUiObject(false, 'Take Profit', takeProfit.name, takeProfit, parentNode, chainParent, 'Take Profit', positionOffset) for (let m = 0; m < node.phases.length; m++) { let phase = node.phases[m] let thisChainParent @@ -208,16 +210,16 @@ function newUiObjectsFromNodes () { } case 'Open Execution': { - createUiObject('Open Execution', node.name, node, parentNode, chainParent, 'Open Execution', positionOffset) + createUiObject(false, 'Open Execution', node.name, node, parentNode, chainParent, 'Open Execution', positionOffset) return } case 'Close Execution': { - createUiObject('Close Execution', node.name, node, parentNode, chainParent, 'Close Execution', positionOffset) + createUiObject(false, 'Close Execution', node.name, node, parentNode, chainParent, 'Close Execution', positionOffset) return } case 'Initial Definition': { - createUiObject('Initial Definition', node.name, node, parentNode, chainParent, 'Initial Definition', positionOffset) + createUiObject(false, 'Initial Definition', node.name, node, parentNode, chainParent, 'Initial Definition', positionOffset) if (node.stopLoss !== undefined) { createUiObjectFromNode(node.stopLoss, node, node, positionOffset) @@ -235,7 +237,7 @@ function newUiObjectsFromNodes () { } case 'Take Position Event': { let event = node - createUiObject('Take Position Event', event.name, event, parentNode, chainParent, 'Take Position Event', positionOffset) + createUiObject(false, 'Take Position Event', event.name, event, parentNode, chainParent, 'Take Position Event', positionOffset) for (let m = 0; m < node.situations.length; m++) { let situation = node.situations[m] createUiObjectFromNode(situation, event, event, positionOffset) @@ -251,7 +253,7 @@ function newUiObjectsFromNodes () { } case 'Trigger On Event': { let event = node - createUiObject('Trigger On Event', event.name, event, parentNode, chainParent, 'Trigger On Event', positionOffset) + createUiObject(false, 'Trigger On Event', event.name, event, parentNode, chainParent, 'Trigger On Event', positionOffset) for (let m = 0; m < node.situations.length; m++) { let situation = node.situations[m] createUiObjectFromNode(situation, event, event, positionOffset) @@ -267,7 +269,7 @@ function newUiObjectsFromNodes () { } case 'Trigger Off Event': { let event = node - createUiObject('Trigger Off Event', event.name, event, parentNode, chainParent, 'Trigger Off Event', positionOffset) + createUiObject(false, 'Trigger Off Event', event.name, event, parentNode, chainParent, 'Trigger Off Event', positionOffset) for (let m = 0; m < node.situations.length; m++) { let situation = node.situations[m] createUiObjectFromNode(situation, event, event, positionOffset) @@ -282,14 +284,14 @@ function newUiObjectsFromNodes () { return } case 'Position Size': { - createUiObject('Position Size', node.name, node, parentNode, chainParent, 'Position Size', positionOffset) + createUiObject(false, 'Position Size', node.name, node, parentNode, chainParent, 'Position Size', positionOffset) if (node.formula !== undefined) { createUiObjectFromNode(node.formula, node, node, positionOffset) } return } case 'Position Rate': { - createUiObject('Position Rate', node.name, node, parentNode, chainParent, 'Position Rate', positionOffset) + createUiObject(false, 'Position Rate', node.name, node, parentNode, chainParent, 'Position Rate', positionOffset) if (node.formula !== undefined) { createUiObjectFromNode(node.formula, node, node, positionOffset) } @@ -297,7 +299,7 @@ function newUiObjectsFromNodes () { } case 'Trigger Stage': { let stage = node - createUiObject('Trigger Stage', stage.name, stage, parentNode, chainParent, 'Trigger Stage', positionOffset) + createUiObject(false, 'Trigger Stage', stage.name, stage, parentNode, chainParent, 'Trigger Stage', positionOffset) if (node.triggerOn !== undefined) { createUiObjectFromNode(node.triggerOn, stage, stage, positionOffset) @@ -312,7 +314,7 @@ function newUiObjectsFromNodes () { } case 'Open Stage': { let stage = node - createUiObject('Open Stage', stage.name, stage, parentNode, chainParent, 'Open Stage', positionOffset) + createUiObject(false, 'Open Stage', stage.name, stage, parentNode, chainParent, 'Open Stage', positionOffset) if (node.initialDefinition !== undefined) { createUiObjectFromNode(node.initialDefinition, stage, stage, positionOffset) @@ -324,7 +326,7 @@ function newUiObjectsFromNodes () { } case 'Manage Stage': { let stage = node - createUiObject('Manage Stage', stage.name, stage, parentNode, chainParent, 'Manage Stage', positionOffset) + createUiObject(false, 'Manage Stage', stage.name, stage, parentNode, chainParent, 'Manage Stage', positionOffset) if (node.stopLoss !== undefined) { createUiObjectFromNode(node.stopLoss, stage, stage, positionOffset) @@ -336,7 +338,7 @@ function newUiObjectsFromNodes () { } case 'Close Stage': { let stage = node - createUiObject('Close Stage', stage.name, stage, parentNode, chainParent, 'Close Stage', positionOffset) + createUiObject(false, 'Close Stage', stage.name, stage, parentNode, chainParent, 'Close Stage', positionOffset) if (node.closeExecution !== undefined) { createUiObjectFromNode(node.closeExecution, stage, stage, positionOffset) @@ -345,7 +347,7 @@ function newUiObjectsFromNodes () { } case 'Strategy': { let strategy = node - createUiObject('Strategy', strategy.name, strategy, parentNode, chainParent, 'Strategy', positionOffset) + createUiObject(false, 'Strategy', strategy.name, strategy, parentNode, chainParent, 'Strategy', positionOffset) if (node.triggerStage !== undefined) { createUiObjectFromNode(node.triggerStage, strategy, strategy, positionOffset) } @@ -361,27 +363,27 @@ function newUiObjectsFromNodes () { return } case 'Base Asset': { - createUiObject('Base Asset', node.name, node, parentNode, chainParent, 'Base Asset', positionOffset) + createUiObject(false, 'Base Asset', node.name, node, parentNode, chainParent, 'Base Asset', positionOffset) return } case 'Time Range': { - createUiObject('Time Range', node.name, node, parentNode, chainParent, 'Time Range', positionOffset) + createUiObject(false, 'Time Range', node.name, node, parentNode, chainParent, 'Time Range', positionOffset) return } case 'Time Period': { - createUiObject('Time Period', node.name, node, parentNode, chainParent, 'Time Period', positionOffset) + createUiObject(false, 'Time Period', node.name, node, parentNode, chainParent, 'Time Period', positionOffset) return } case 'Slippage': { - createUiObject('Slippage', node.name, node, parentNode, chainParent, 'Slippage', positionOffset) + createUiObject(false, 'Slippage', node.name, node, parentNode, chainParent, 'Slippage', positionOffset) return } case 'Fee Structure': { - createUiObject('Fee Structure', node.name, node, parentNode, chainParent, 'Fee Structure', positionOffset) + createUiObject(false, 'Fee Structure', node.name, node, parentNode, chainParent, 'Fee Structure', positionOffset) return } case 'Parameters': { - createUiObject('Parameters', node.name, node, parentNode, chainParent, 'Parameters', positionOffset) + createUiObject(false, 'Parameters', node.name, node, parentNode, chainParent, 'Parameters', positionOffset) if (node.baseAsset !== undefined) { createUiObjectFromNode(node.baseAsset, node, node, positionOffset) } @@ -404,7 +406,7 @@ function newUiObjectsFromNodes () { } case 'Trading System': { let tradingSystem = node - createUiObject('Trading System', tradingSystem.name, tradingSystem, parentNode, chainParent, 'Trading System', positionOffset) + createUiObject(false, 'Trading System', tradingSystem.name, tradingSystem, parentNode, chainParent, 'Trading System', positionOffset) for (let m = 0; m < node.strategies.length; m++) { let strategy = node.strategies[m] createUiObjectFromNode(strategy, tradingSystem, tradingSystem, positionOffset) @@ -415,7 +417,7 @@ function newUiObjectsFromNodes () { return } case 'Personal Data': { - createUiObject('Personal Data', node.name, node, parentNode, chainParent, 'Personal Data', positionOffset) + createUiObject(false, 'Personal Data', node.name, node, parentNode, chainParent, 'Personal Data', positionOffset) for (let m = 0; m < node.exchangeAccounts.length; m++) { let exchangeAccount = node.exchangeAccounts[m] createUiObjectFromNode(exchangeAccount, node, node, positionOffset) @@ -423,7 +425,7 @@ function newUiObjectsFromNodes () { return } case 'Exchange Account': { - createUiObject('Exchange Account', node.name, node, parentNode, chainParent, 'Exchange Account', positionOffset) + createUiObject(false, 'Exchange Account', node.name, node, parentNode, chainParent, 'Exchange Account', positionOffset) for (let m = 0; m < node.assets.length; m++) { let asset = node.assets[m] createUiObjectFromNode(asset, node, node, positionOffset) @@ -435,11 +437,11 @@ function newUiObjectsFromNodes () { return } case 'Exchange Account Asset': { - createUiObject('Exchange Account Asset', node.name, node, parentNode, chainParent, 'Exchange Account Asset', positionOffset) + createUiObject(false, 'Exchange Account Asset', node.name, node, parentNode, chainParent, 'Exchange Account Asset', positionOffset) return } case 'Exchange Account Key': { - createUiObject('Exchange Account Key', node.name, node, parentNode, chainParent, 'Exchange Account Key', positionOffset) + createUiObject(false, 'Exchange Account Key', node.name, node, parentNode, chainParent, 'Exchange Account Key', positionOffset) return } case 'Definition': { @@ -451,7 +453,7 @@ function newUiObjectsFromNodes () { referenceChildren = node.savedPayload.referenceChildren } } - createUiObject('Definition', node.name, node, parentNode, chainParent, 'Definition', positionOffset) + createUiObject(false, 'Definition', node.name, node, parentNode, chainParent, 'Definition', positionOffset) if (node.tradingSystem !== undefined) { createUiObjectFromNode(node.tradingSystem, node, node, positionOffset) } @@ -465,11 +467,13 @@ function newUiObjectsFromNodes () { node.savedPayload = { referenceChildren: referenceChildren } + } else { + node.referenceChildren = [] } return } case 'Network': { - createUiObject('Network', node.name, node, parentNode, chainParent, 'Network', positionOffset) + createUiObject(false, 'Network', node.name, node, parentNode, chainParent, 'Network', positionOffset) if (node.networkNodes !== undefined) { for (let m = 0; m < node.networkNodes.length; m++) { let networkNode = node.networkNodes[m] @@ -479,7 +483,7 @@ function newUiObjectsFromNodes () { return } case 'Network Node': { - createUiObject('Network Node', node.name, node, parentNode, chainParent, 'Network Node', positionOffset) + createUiObject(false, 'Network Node', node.name, node, parentNode, chainParent, 'Network Node', positionOffset) if (node.taskManagers !== undefined) { for (let m = 0; m < node.taskManagers.length; m++) { let taskManager = node.taskManagers[m] @@ -489,7 +493,7 @@ function newUiObjectsFromNodes () { return } case 'Social Bots': { - createUiObject('Social Bots', node.name, node, parentNode, chainParent, 'Social Bots', positionOffset) + createUiObject(false, 'Social Bots', node.name, node, parentNode, chainParent, 'Social Bots', positionOffset) for (let m = 0; m < node.bots.length; m++) { let bot = node.bots[m] createUiObjectFromNode(bot, node, node, positionOffset) @@ -497,7 +501,7 @@ function newUiObjectsFromNodes () { return } case 'Telegram Bot': { - createUiObject('Telegram Bot', node.name, node, parentNode, chainParent, 'Telegram Bot', positionOffset) + createUiObject(false, 'Telegram Bot', node.name, node, parentNode, chainParent, 'Telegram Bot', positionOffset) for (let m = 0; m < node.announcements.length; m++) { let announcement = node.announcements[m] createUiObjectFromNode(announcement, node, node, positionOffset) @@ -505,14 +509,14 @@ function newUiObjectsFromNodes () { return } case 'Announcement': { - createUiObject('Announcement', node.name, node, parentNode, chainParent, 'Announcement', positionOffset) + createUiObject(false, 'Announcement', node.name, node, parentNode, chainParent, 'Announcement', positionOffset) if (node.formula !== undefined) { createUiObjectFromNode(node.formula, node, node, positionOffset) } return } case 'Layer Manager': { - createUiObject('Layer Manager', node.name, node, parentNode, chainParent, 'Layer Manager', positionOffset) + createUiObject(false, 'Layer Manager', node.name, node, parentNode, chainParent, 'Layer Manager', positionOffset) for (let m = 0; m < node.layers.length; m++) { let layer = node.layers[m] createUiObjectFromNode(layer, node, node, positionOffset) @@ -520,11 +524,11 @@ function newUiObjectsFromNodes () { return } case 'Layer': { - createUiObject('Layer', node.name, node, parentNode, chainParent, 'Layer', positionOffset) + createUiObject(false, 'Layer', node.name, node, parentNode, chainParent, 'Layer', positionOffset) return } case 'Task Manager': { - createUiObject('Task Manager', node.name, node, parentNode, chainParent, 'Task Manager', positionOffset) + createUiObject(false, 'Task Manager', node.name, node, parentNode, chainParent, 'Task Manager', positionOffset) for (let m = 0; m < node.tasks.length; m++) { let task = node.tasks[m] createUiObjectFromNode(task, node, node, positionOffset) @@ -532,14 +536,14 @@ function newUiObjectsFromNodes () { return } case 'Task': { - createUiObject('Task', node.name, node, parentNode, chainParent, 'Task', positionOffset) + createUiObject(false, 'Task', node.name, node, parentNode, chainParent, 'Task', positionOffset) if (node.bot !== undefined) { createUiObjectFromNode(node.bot, node, node, positionOffset) } return } case 'Sensor Bot Instance': { - createUiObject('Sensor Bot Instance', node.name, node, parentNode, chainParent, 'Sensor Bot Instance', positionOffset) + createUiObject(false, 'Sensor Bot Instance', node.name, node, parentNode, chainParent, 'Sensor Bot Instance', positionOffset) for (let m = 0; m < node.processes.length; m++) { let process = node.processes[m] createUiObjectFromNode(process, node, node, positionOffset) @@ -547,7 +551,7 @@ function newUiObjectsFromNodes () { return } case 'Indicator Bot Instance': { - createUiObject('Indicator Bot Instance', node.name, node, parentNode, chainParent, 'Indicator Bot Instance', positionOffset) + createUiObject(false, 'Indicator Bot Instance', node.name, node, parentNode, chainParent, 'Indicator Bot Instance', positionOffset) for (let m = 0; m < node.processes.length; m++) { let process = node.processes[m] createUiObjectFromNode(process, node, node, positionOffset) @@ -555,7 +559,7 @@ function newUiObjectsFromNodes () { return } case 'Trading Bot Instance': { - createUiObject('Trading Bot Instance', node.name, node, parentNode, chainParent, 'Trading Bot Instance', positionOffset) + createUiObject(false, 'Trading Bot Instance', node.name, node, parentNode, chainParent, 'Trading Bot Instance', positionOffset) for (let m = 0; m < node.processes.length; m++) { let process = node.processes[m] createUiObjectFromNode(process, node, node, positionOffset) @@ -588,7 +592,7 @@ function newUiObjectsFromNodes () { } } } - createUiObject('Process Instance', node.name, node, parentNode, chainParent, 'Process Instance', positionOffset) + createUiObject(false, 'Process Instance', node.name, node, parentNode, chainParent, 'Process Instance', positionOffset) if (node.session !== undefined) { createUiObjectFromNode(node.session, node, node, positionOffset) } @@ -609,7 +613,7 @@ function newUiObjectsFromNodes () { } } } - createUiObject('Backtesting Session', node.name, node, parentNode, chainParent, 'Backtesting Session', positionOffset) + createUiObject(false, 'Backtesting Session', node.name, node, parentNode, chainParent, 'Backtesting Session', positionOffset) if (node.parameters !== undefined) { createUiObjectFromNode(node.parameters, node, node, positionOffset) } @@ -636,7 +640,7 @@ function newUiObjectsFromNodes () { } } } - createUiObject('Live Trading Session', node.name, node, parentNode, chainParent, 'Live Trading Session', positionOffset) + createUiObject(false, 'Live Trading Session', node.name, node, parentNode, chainParent, 'Live Trading Session', positionOffset) if (node.parameters !== undefined) { createUiObjectFromNode(node.parameters, node, node, positionOffset) } @@ -663,7 +667,7 @@ function newUiObjectsFromNodes () { } } } - createUiObject('Fordward Testing Session', node.name, node, parentNode, chainParent, 'Fordward Testing Session', positionOffset) + createUiObject(false, 'Fordward Testing Session', node.name, node, parentNode, chainParent, 'Fordward Testing Session', positionOffset) if (node.parameters !== undefined) { createUiObjectFromNode(node.parameters, node, node, positionOffset) } @@ -690,7 +694,7 @@ function newUiObjectsFromNodes () { } } } - createUiObject('Paper Trading Session', node.name, node, parentNode, chainParent, 'Paper Trading Session', positionOffset) + createUiObject(false, 'Paper Trading Session', node.name, node, parentNode, chainParent, 'Paper Trading Session', positionOffset) if (node.parameters !== undefined) { createUiObjectFromNode(node.parameters, node, node, positionOffset) } @@ -709,7 +713,7 @@ function newUiObjectsFromNodes () { } case 'Team': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) for (let m = 0; m < node.sensorBots.length; m++) { let sensorBot = node.sensorBots[m] createUiObjectFromNode(sensorBot, node, node, positionOffset) @@ -729,7 +733,7 @@ function newUiObjectsFromNodes () { return } case 'Sensor Bot': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) for (let m = 0; m < node.processes.length; m++) { let process = node.processes[m] createUiObjectFromNode(process, node, node, positionOffset) @@ -741,7 +745,7 @@ function newUiObjectsFromNodes () { return } case 'Indicator Bot': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) for (let m = 0; m < node.processes.length; m++) { let process = node.processes[m] createUiObjectFromNode(process, node, node, positionOffset) @@ -753,7 +757,7 @@ function newUiObjectsFromNodes () { return } case 'Trading Bot': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) for (let m = 0; m < node.processes.length; m++) { let process = node.processes[m] createUiObjectFromNode(process, node, node, positionOffset) @@ -773,7 +777,7 @@ function newUiObjectsFromNodes () { referenceChildren = node.savedPayload.referenceChildren } } - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) if (node.processOutput !== undefined) { createUiObjectFromNode(node.processOutput, node, node, positionOffset) } @@ -793,11 +797,13 @@ function newUiObjectsFromNodes () { node.savedPayload = { referenceChildren: referenceChildren } + } else { + node.referenceChildren = [] } return } case 'Process Output': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) for (let m = 0; m < node.outputDatasets.length; m++) { let outputDataset = node.outputDatasets[m] createUiObjectFromNode(outputDataset, node, node, positionOffset) @@ -805,7 +811,7 @@ function newUiObjectsFromNodes () { return } case 'Process Dependencies': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) for (let m = 0; m < node.statusDependencies.length; m++) { let statusDependency = node.statusDependencies[m] createUiObjectFromNode(statusDependency, node, node, positionOffset) @@ -825,11 +831,13 @@ function newUiObjectsFromNodes () { referenceChildren = node.savedPayload.referenceChildren } } - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) if (referenceChildren !== undefined) { node.savedPayload = { referenceChildren: referenceChildren } + } else { + node.referenceChildren = [] } return } @@ -843,7 +851,7 @@ function newUiObjectsFromNodes () { } } } - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) if (referenceParent !== undefined) { node.savedPayload = { referenceParent: referenceParent @@ -860,16 +868,18 @@ function newUiObjectsFromNodes () { referenceChildren = node.savedPayload.referenceChildren } } - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) if (referenceChildren !== undefined) { node.savedPayload = { referenceChildren: referenceChildren } + } else { + node.referenceChildren = [] } return } case 'Calculations Procedure': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) if (node.initialization !== undefined) { createUiObjectFromNode(node.initialization, node, node, positionOffset) } @@ -879,7 +889,7 @@ function newUiObjectsFromNodes () { return } case 'Data Building Procedure': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) if (node.initialization !== undefined) { createUiObjectFromNode(node.initialization, node, node, positionOffset) } @@ -889,16 +899,18 @@ function newUiObjectsFromNodes () { return } case 'Procedure Initialization': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) - if (node.code !== undefined) { - createUiObjectFromNode(node.code, node, node, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + + if (node.javascriptCode !== undefined) { + createUiObjectFromNode(node.javascriptCode, node, node, positionOffset) } return } case 'Procedure Loop': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) - if (node.code !== undefined) { - createUiObjectFromNode(node.code, node, node, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + + if (node.javascriptCode !== undefined) { + createUiObjectFromNode(node.javascriptCode, node, node, positionOffset) } return } @@ -912,7 +924,7 @@ function newUiObjectsFromNodes () { } } } - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) if (referenceParent !== undefined) { node.savedPayload = { referenceParent: referenceParent @@ -930,7 +942,7 @@ function newUiObjectsFromNodes () { } } } - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) if (referenceParent !== undefined) { node.savedPayload = { referenceParent: referenceParent @@ -948,7 +960,7 @@ function newUiObjectsFromNodes () { } } } - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) if (referenceParent !== undefined) { node.savedPayload = { referenceParent: referenceParent @@ -957,7 +969,16 @@ function newUiObjectsFromNodes () { return } case 'Product Definition': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + let referenceParent + if (mapOfReferenceChildren !== undefined) { + if (node.savedPayload.referenceParent !== undefined) { + if (node.savedPayload.referenceParent.id !== undefined) { + mapOfReferenceChildren.set(node.id, node) + referenceParent = node.savedPayload.referenceParent + } + } + } + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) if (node.record !== undefined) { createUiObjectFromNode(node.record, node, node, positionOffset) } @@ -971,10 +992,15 @@ function newUiObjectsFromNodes () { if (node.dataBuilding !== undefined) { createUiObjectFromNode(node.dataBuilding, node, node, positionOffset) } + if (referenceParent !== undefined) { + node.savedPayload = { + referenceParent: referenceParent + } + } return } case 'Record Definition': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) for (let m = 0; m < node.properties.length; m++) { let property = node.properties[m] createUiObjectFromNode(property, node, node, positionOffset) @@ -982,7 +1008,7 @@ function newUiObjectsFromNodes () { return } case 'Record Property': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) if (node.formula !== undefined) { createUiObjectFromNode(node.formula, node, node, positionOffset) } @@ -997,16 +1023,18 @@ function newUiObjectsFromNodes () { referenceChildren = node.savedPayload.referenceChildren } } - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) if (referenceChildren !== undefined) { node.savedPayload = { referenceChildren: referenceChildren } + } else { + node.referenceChildren = [] } return } case 'Plotter': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) for (let m = 0; m < node.modules.length; m++) { let module = node.modules[m] createUiObjectFromNode(module, node, node, positionOffset) @@ -1014,26 +1042,107 @@ function newUiObjectsFromNodes () { return } case 'Plotter Module': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) - if (node.code !== undefined) { - createUiObjectFromNode(node.code, node, node, positionOffset) + let referenceChildren + if (mapOfReferenceParents !== undefined) { + if (node.savedPayload.referenceChildren !== undefined) { + referenceChildren = [] + mapOfReferenceParents.set(node.id, node) + referenceChildren = node.savedPayload.referenceChildren + } } + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + + if (node.javascriptCode !== undefined) { + createUiObjectFromNode(node.javascriptCode, node, node, positionOffset) + } + + if (node.shapes !== undefined) { + createUiObjectFromNode(node.shapes, node, node, positionOffset) + } + for (let m = 0; m < node.panels.length; m++) { let panel = node.panels[m] createUiObjectFromNode(panel, node, node, positionOffset) } + if (referenceChildren !== undefined) { + node.savedPayload = { + referenceChildren: referenceChildren + } + } else { + node.referenceChildren = [] + } return } case 'Plotter Panel': { - createUiObject(node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) - if (node.code !== undefined) { - createUiObjectFromNode(node.code, node, node, positionOffset) + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + + if (node.javascriptCode !== undefined) { + createUiObjectFromNode(node.javascriptCode, node, node, positionOffset) + } + return + } + default: { + let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + if (nodeDefinition !== undefined) { + createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset) + + if (nodeDefinition.properties !== undefined) { + for (i = 0; i < nodeDefinition.properties.length; i++) { + let property = nodeDefinition.properties[i] + if (node[property.name] !== undefined) { + switch (property.type) { + case 'node': { + createUiObjectFromNode(node[property.name], node, node, positionOffset) + } + break + case 'array': { + let nodePropertyArray = node[property.name] + for (let m = 0; m < nodePropertyArray.length; m++) { + let arrayItem = nodePropertyArray[m] + createUiObjectFromNode(arrayItem, node, node, positionOffset) + } + } + break + } + } + } + } } return } } } + function addUIObject (parent, type) { + let object = { + name: 'New ' + type, + type: type + } + createUiObject(true, object.type, object.name, object, parent, parent) + + let nodeDefinition = APP_SCHEMA_MAP.get(parent.type) + if (nodeDefinition !== undefined) { + if (nodeDefinition.properties !== undefined) { + for (i = 0; i < nodeDefinition.properties.length; i++) { + let property = nodeDefinition.properties[i] + if (property.childType === type) { + switch (property.type) { + case 'node': { + parent[property.name] = object + } + break + case 'array': { + parent[property.name].push(object) + } + break + } + } + } + } + } + return object + } + function addTeam (node) { let team = { name: 'New Team', @@ -1045,7 +1154,7 @@ function newUiObjectsFromNodes () { plotters: [] } node.rootNodes.push(team) - createUiObject(team.type, team.name, team, undefined, undefined) + createUiObject(true, team.type, team.name, team, undefined, undefined) return team } @@ -1061,7 +1170,7 @@ function newUiObjectsFromNodes () { node.sensorBots = [] } node.sensorBots.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) return object } @@ -1078,7 +1187,7 @@ function newUiObjectsFromNodes () { node.indicatorBots = [] } node.indicatorBots.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) return object } @@ -1095,7 +1204,7 @@ function newUiObjectsFromNodes () { node.tradingBots = [] } node.tradingBots.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) return object } @@ -1111,7 +1220,7 @@ function newUiObjectsFromNodes () { node.processes = [] } node.processes.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) return object } @@ -1136,7 +1245,7 @@ function newUiObjectsFromNodes () { name: 'New Process Output', outputDatasets: [] } - createUiObject(node.processOutput.type, node.processOutput.name, node.processOutput, node, node) + createUiObject(true, node.processOutput.type, node.processOutput.name, node.processOutput, node, node) } return node.processOutput } @@ -1149,7 +1258,7 @@ function newUiObjectsFromNodes () { statusDependencies: [], dataDependencies: [] } - createUiObject(node.processDependencies.type, node.processDependencies.name, node.processDependencies, node, node) + createUiObject(true, node.processDependencies.type, node.processDependencies.name, node.processDependencies, node, node) } return node.processDependencies } @@ -1161,7 +1270,7 @@ function newUiObjectsFromNodes () { name: 'New Status Report', referenceChildren: [] } - createUiObject(node.statusReport.type, node.statusReport.name, node.statusReport, node, node) + createUiObject(true, node.statusReport.type, node.statusReport.name, node.statusReport, node, node) } return node.statusReport } @@ -1172,7 +1281,7 @@ function newUiObjectsFromNodes () { type: 'Execution Started Event', name: 'New Execution Started Event' } - createUiObject(node.executionStartedEvent.type, node.executionStartedEvent.name, node.executionStartedEvent, node, node) + createUiObject(true, node.executionStartedEvent.type, node.executionStartedEvent.name, node.executionStartedEvent, node, node) } return node.executionStartedEvent } @@ -1184,7 +1293,7 @@ function newUiObjectsFromNodes () { name: 'New Execution Finished Event', referenceChildren: [] } - createUiObject(node.executionFinishedEvent.type, node.executionFinishedEvent.name, node.executionFinishedEvent, node, node) + createUiObject(true, node.executionFinishedEvent.type, node.executionFinishedEvent.name, node.executionFinishedEvent, node, node) } return node.executionFinishedEvent } @@ -1195,7 +1304,7 @@ function newUiObjectsFromNodes () { type: 'Calculations Procedure', name: 'New Calculations Procedure' } - createUiObject(node.calculations.type, node.calculations.name, node.calculations, node, node) + createUiObject(true, node.calculations.type, node.calculations.name, node.calculations, node, node) } return node.calculations } @@ -1206,7 +1315,7 @@ function newUiObjectsFromNodes () { type: 'Data Building Procedure', name: 'New Data Building Procedure' } - createUiObject(node.dataBuilding.type, node.dataBuilding.name, node.dataBuilding, node, node) + createUiObject(true, node.dataBuilding.type, node.dataBuilding.name, node.dataBuilding, node, node) } return node.dataBuilding } @@ -1217,7 +1326,7 @@ function newUiObjectsFromNodes () { type: 'Procedure Initialization', name: 'New Procedure Initialization' } - createUiObject(node.initialization.type, node.initialization.name, node.initialization, node, node) + createUiObject(true, node.initialization.type, node.initialization.name, node.initialization, node, node) } return node.initialization } @@ -1228,7 +1337,7 @@ function newUiObjectsFromNodes () { type: 'Procedure Loop', name: 'New Procedure Loop' } - createUiObject(node.loop.type, node.loop.name, node.loop, node, node) + createUiObject(true, node.loop.type, node.loop.name, node.loop, node, node) } return node.loop } @@ -1242,7 +1351,7 @@ function newUiObjectsFromNodes () { node.outputDatasets = [] } node.outputDatasets.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) return object } @@ -1251,13 +1360,13 @@ function newUiObjectsFromNodes () { let object = { type: 'Status Dependency', name: 'New Status Dependency', - code: '{"mainUtility": "Self Reference|Market Starting Point|Market Ending Point"}' + code: '{ \n\"mainUtility\": \"Self Reference|Market Starting Point|Market Ending Point.\"\n}' } if (node.statusDependencies === undefined) { node.statusDependencies = [] } node.statusDependencies.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) return object } @@ -1271,7 +1380,7 @@ function newUiObjectsFromNodes () { node.dataDependencies = [] } node.dataDependencies.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) return object } @@ -1287,7 +1396,7 @@ function newUiObjectsFromNodes () { node.products = [] } node.products.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) return object } @@ -1299,7 +1408,7 @@ function newUiObjectsFromNodes () { name: 'New Record Definition', properties: [] } - createUiObject(node.record.type, node.record.name, node.record, node, node) + createUiObject(true, node.record.type, node.record.name, node.record, node, node) } return node.record } @@ -1308,13 +1417,17 @@ function newUiObjectsFromNodes () { let object = { type: 'Record Property', name: 'New Record Property', - code: '{}' + code: '{}', + formula: { + code: DEFAULT_FORMULA_TEXT + } } if (node.properties === undefined) { node.properties = [] } node.properties.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) + createUiObject(true, 'Formula', '', object.formula, object, object) return object } @@ -1330,7 +1443,7 @@ function newUiObjectsFromNodes () { node.datasets = [] } node.datasets.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) return object } @@ -1339,13 +1452,14 @@ function newUiObjectsFromNodes () { let object = { type: 'Plotter', name: 'New Plotter', + code: '{}', modules: [] } if (node.plotters === undefined) { node.plotters = [] } node.plotters.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) return object } @@ -1354,13 +1468,14 @@ function newUiObjectsFromNodes () { let object = { type: 'Plotter Module', name: 'New Plotter Module', + code: '{}', panels: [] } if (node.modules === undefined) { node.modules = [] } node.modules.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) return object } @@ -1374,7 +1489,7 @@ function newUiObjectsFromNodes () { node.panels = [] } node.panels.push(object) - createUiObject(object.type, object.name, object, node, node) + createUiObject(true, object.type, object.name, object, node, node) return object } @@ -1384,7 +1499,7 @@ function newUiObjectsFromNodes () { name: 'Superalgos' } node.rootNodes.push(network) - createUiObject('Network', network.name, network, node, undefined, 'Network') + createUiObject(true, 'Network', network.name, network, node, undefined, 'Network') return network } @@ -1397,7 +1512,7 @@ function newUiObjectsFromNodes () { node.networkNodes = [] } node.networkNodes.push(networkNode) - createUiObject('Network Node', networkNode.name, networkNode, node, node, 'Network Node') + createUiObject(true, 'Network Node', networkNode.name, networkNode, node, node, 'Network Node') return networkNode } @@ -1408,7 +1523,7 @@ function newUiObjectsFromNodes () { name: 'New Social Bots', bots: [] } - createUiObject('Social Bots', node.socialBots.name, node.socialBots, node, node, 'Social Bots') + createUiObject(true, 'Social Bots', node.socialBots.name, node.socialBots, node, node, 'Social Bots') } return node.socialBots @@ -1417,11 +1532,11 @@ function newUiObjectsFromNodes () { function addTelegramBot (node) { let bot = { name: 'New Telegram Bot', - code: '{ \n\"botToken\": \"Paste here the bot token obtained from Telegram Bot Father\",\n\"chatId\": Write here the chat or group id where the announcements are going to be sent to, as it is a number with no quotes please.\n}', + code: '{ \n\"botToken\": \"Paste here the bot token obtained from Telegram Bot Father\",\n\"chatId\": \"Write here the chat or group id where the announcements are going to be sent to, as it is a number with no quotes please.\"\n}', announcements: [] } node.bots.push(bot) - createUiObject('Telegram Bot', bot.name, bot, node, node, 'Telegram Bot') + createUiObject(true, 'Telegram Bot', bot.name, bot, node, node, 'Telegram Bot') return bot } @@ -1432,7 +1547,7 @@ function newUiObjectsFromNodes () { code: '{ \n\"text\": \"Write here what you want to announce.\",\n\"botType\": \"' + node.type + '\",\n\"botId\": \"' + node.id + '\"\n}' } node.announcements.push(announcement) - createUiObject('Announcement', announcement.name, announcement, node, node, 'Announcement') + createUiObject(true, 'Announcement', announcement.name, announcement, node, node, 'Announcement') return announcement } @@ -1443,7 +1558,7 @@ function newUiObjectsFromNodes () { name: 'New Layer Manager', layers: [] } - createUiObject('Layer Manager', node.layerManager.name, node.layerManager, node, node, 'Layer Manager') + createUiObject(true, 'Layer Manager', node.layerManager.name, node.layerManager, node, node, 'Layer Manager') } return node.layerManager @@ -1452,10 +1567,10 @@ function newUiObjectsFromNodes () { function addLayer (node) { let layer = { name: 'New Layer', - code: '{}' + code: '{ \n\"product\": \"Type here the codeName of the Product\"\n}' } node.layers.push(layer) - createUiObject('Layer', layer.name, layer, node, node, 'Layer') + createUiObject(true, 'Layer', layer.name, layer, node, node, 'Layer') return layer } @@ -1469,7 +1584,7 @@ function newUiObjectsFromNodes () { node.taskManagers = [] } node.taskManagers.push(taskManager) - createUiObject('Task Manager', taskManager.name, taskManager, node, node, 'Task Manager') + createUiObject(true, 'Task Manager', taskManager.name, taskManager, node, node, 'Task Manager') return taskManager } @@ -1479,7 +1594,7 @@ function newUiObjectsFromNodes () { name: 'New Task' } node.tasks.push(task) - createUiObject('Task', task.name, task, node, node, 'Task') + createUiObject(true, 'Task', task.name, task, node, node, 'Task') return task } @@ -1490,7 +1605,7 @@ function newUiObjectsFromNodes () { processes: [], code: '{}' } - createUiObject('Sensor Bot Instance', '', node.bot, node, node) + createUiObject(true, 'Sensor Bot Instance', '', node.bot, node, node) } return node.bot } @@ -1501,7 +1616,7 @@ function newUiObjectsFromNodes () { processes: [], code: '{}' } - createUiObject('Indicator Bot Instance', '', node.bot, node, node) + createUiObject(true, 'Indicator Bot Instance', '', node.bot, node, node) } return node.bot } @@ -1512,7 +1627,7 @@ function newUiObjectsFromNodes () { processes: [], code: '{}' } - createUiObject('Trading Bot Instance', '', node.bot, node, node) + createUiObject(true, 'Trading Bot Instance', '', node.bot, node, node) } return node.bot } @@ -1541,7 +1656,7 @@ function newUiObjectsFromNodes () { } } node.processes.push(process) - createUiObject('Process Instance', process.name, process, node, node, 'Process Instance') + createUiObject(true, 'Process Instance', process.name, process, node, node, 'Process Instance') return process } @@ -1550,9 +1665,9 @@ function newUiObjectsFromNodes () { if (node.session === undefined) { node.session = { name: 'New Backtesting Session', - code: '{}' + code: '{ \n\"folderName\": \"Type here the folder name where you want the logs of this process to be stored to.\"\n}' } - createUiObject('Backtesting Session', '', node.session, node, node) + createUiObject(true, 'Backtesting Session', '', node.session, node, node) } return node.session @@ -1564,7 +1679,7 @@ function newUiObjectsFromNodes () { name: 'New Live Trading Session', code: '{}' } - createUiObject('Live Trading Session', '', node.session, node, node) + createUiObject(true, 'Live Trading Session', '', node.session, node, node) } return node.session @@ -1574,9 +1689,9 @@ function newUiObjectsFromNodes () { if (node.session === undefined) { node.session = { name: 'New Fordward Testing Session', - code: '{}' + code: '{ \n\"folderName\": \"Type here the folder name where you want the logs of this process to be stored to.\",\n\"balancePercentage\": \"Type here the the % of the balance to be used in this test.\"\n}' } - createUiObject('Fordward Testing Session', '', node.session, node, node) + createUiObject(true, 'Fordward Testing Session', '', node.session, node, node) } return node.session @@ -1586,9 +1701,9 @@ function newUiObjectsFromNodes () { if (node.session === undefined) { node.session = { name: 'New Paper Trading Session', - code: '{}' + code: '{ \n\"folderName\": \"Type here the folder name where you want the logs of this process to be stored to.\"\n}' } - createUiObject('Paper Trading Session', '', node.session, node, node) + createUiObject(true, 'Paper Trading Session', '', node.session, node, node) } return node.session @@ -1600,7 +1715,7 @@ function newUiObjectsFromNodes () { referenceChildren: [] } node.rootNodes.push(definition) - createUiObject('Definition', definition.name, definition, node, undefined, 'Definition') + createUiObject(true, 'Definition', definition.name, definition, node, undefined, 'Definition') return definition } @@ -1610,7 +1725,7 @@ function newUiObjectsFromNodes () { node.tradingSystem = { strategies: [] } - createUiObject('Trading System', '', node.tradingSystem, node, node) + createUiObject(true, 'Trading System', '', node.tradingSystem, node, node) } return node.tradingSystem } @@ -1620,7 +1735,7 @@ function newUiObjectsFromNodes () { node.personalData = { exchangeAccounts: [] } - createUiObject('Personal Data', '', node.personalData, node, node) + createUiObject(true, 'Personal Data', '', node.personalData, node, node) } return node.personalData @@ -1634,7 +1749,7 @@ function newUiObjectsFromNodes () { keys: [] } personalData.exchangeAccounts.push(exchangeAccount) - createUiObject('Exchange Account', exchangeAccount.name, exchangeAccount, personalData, personalData, 'Exchange Account') + createUiObject(true, 'Exchange Account', exchangeAccount.name, exchangeAccount, personalData, personalData, 'Exchange Account') return exchangeAccount } @@ -1645,7 +1760,7 @@ function newUiObjectsFromNodes () { name: 'New Asset' } exchangeAccount.assets.push(asset) - createUiObject('Exchange Account Asset', asset.name, asset, exchangeAccount, exchangeAccount, 'Account Asset') + createUiObject(true, 'Exchange Account Asset', asset.name, asset, exchangeAccount, exchangeAccount, 'Account Asset') return asset } @@ -1657,7 +1772,7 @@ function newUiObjectsFromNodes () { code: 'Paste your exchange API secret key here and the put the key name as this key object title. Secret keys are filtered out and NOT exported when using the SHARE menu option on any object at your workspace. Secret keys ARE downloaded when using the download button.' } exchangeAccount.keys.push(key) - createUiObject('Exchange Account Key', key.name, key, exchangeAccount, exchangeAccount, 'Account Key') + createUiObject(true, 'Exchange Account Key', key.name, key, exchangeAccount, exchangeAccount, 'Account Key') return key } @@ -1708,22 +1823,22 @@ function newUiObjectsFromNodes () { } strategyParent.strategies.push(strategy) - createUiObject('Strategy', strategy.name, strategy, strategyParent, strategyParent, 'Strategy') - createUiObject('Trigger Stage', '', strategy.triggerStage, strategy, strategy, 'Trigger Stage') - createUiObject('Open Stage', '', strategy.openStage, strategy, strategy, 'Open Stage') - createUiObject('Manage Stage', '', strategy.manageStage, strategy, strategy, 'Manage Stage') - createUiObject('Close Stage', '', strategy.closeStage, strategy, strategy, 'Close Stage') - createUiObject('Trigger On Event', '', strategy.triggerStage.triggerOn, strategy.triggerStage, strategy.triggerStage) - createUiObject('Trigger Off Event', '', strategy.triggerStage.triggerOff, strategy.triggerStage, strategy.triggerStage) - createUiObject('Take Position Event', '', strategy.triggerStage.takePosition, strategy.triggerStage, strategy.triggerStage) - createUiObject('Initial Definition', '', strategy.openStage.initialDefinition, strategy.openStage, strategy.openStage) - createUiObject('Position Size', '', strategy.openStage.initialDefinition.positionSize, strategy.openStage.initialDefinition, strategy.openStage.initialDefinition) - createUiObject('Position Rate', '', strategy.openStage.initialDefinition.positionRate, strategy.openStage.initialDefinition, strategy.openStage.initialDefinition) - createUiObject('Stop', '', strategy.manageStage.stopLoss, strategy.manageStage, strategy.manageStage) - createUiObject('Take Profit', '', strategy.manageStage.takeProfit, strategy.manageStage, strategy.manageStage) - createUiObject('Stop', 'Initial Stop', strategy.openStage.initialDefinition.stopLoss, strategy.openStage.initialDefinition, strategy.openStage.initialDefinition) - createUiObject('Take Profit', 'Initial Take Profit', strategy.openStage.initialDefinition.takeProfit, strategy.openStage.initialDefinition, strategy.openStage.initialDefinition) - createUiObject('Formula', '', strategy.triggerStage.positionSize.formula, strategy.triggerStage.positionSize, strategy.triggerStage.positionSize) + createUiObject(true, 'Strategy', strategy.name, strategy, strategyParent, strategyParent, 'Strategy') + createUiObject(true, 'Trigger Stage', '', strategy.triggerStage, strategy, strategy, 'Trigger Stage') + createUiObject(true, 'Open Stage', '', strategy.openStage, strategy, strategy, 'Open Stage') + createUiObject(true, 'Manage Stage', '', strategy.manageStage, strategy, strategy, 'Manage Stage') + createUiObject(true, 'Close Stage', '', strategy.closeStage, strategy, strategy, 'Close Stage') + createUiObject(true, 'Trigger On Event', '', strategy.triggerStage.triggerOn, strategy.triggerStage, strategy.triggerStage) + createUiObject(true, 'Trigger Off Event', '', strategy.triggerStage.triggerOff, strategy.triggerStage, strategy.triggerStage) + createUiObject(true, 'Take Position Event', '', strategy.triggerStage.takePosition, strategy.triggerStage, strategy.triggerStage) + createUiObject(true, 'Initial Definition', '', strategy.openStage.initialDefinition, strategy.openStage, strategy.openStage) + createUiObject(true, 'Position Size', '', strategy.openStage.initialDefinition.positionSize, strategy.openStage.initialDefinition, strategy.openStage.initialDefinition) + createUiObject(true, 'Position Rate', '', strategy.openStage.initialDefinition.positionRate, strategy.openStage.initialDefinition, strategy.openStage.initialDefinition) + createUiObject(true, 'Stop', '', strategy.manageStage.stopLoss, strategy.manageStage, strategy.manageStage) + createUiObject(true, 'Take Profit', '', strategy.manageStage.takeProfit, strategy.manageStage, strategy.manageStage) + createUiObject(true, 'Stop', 'Initial Stop', strategy.openStage.initialDefinition.stopLoss, strategy.openStage.initialDefinition, strategy.openStage.initialDefinition) + createUiObject(true, 'Take Profit', 'Initial Take Profit', strategy.openStage.initialDefinition.takeProfit, strategy.openStage.initialDefinition, strategy.openStage.initialDefinition) + createUiObject(true, 'Formula', '', strategy.triggerStage.positionSize.formula, strategy.triggerStage.positionSize, strategy.triggerStage.positionSize) return strategy } @@ -1733,7 +1848,7 @@ function newUiObjectsFromNodes () { node.parameters = { name: 'Parameters' } - createUiObject('Parameters', '', node.parameters, node, node) + createUiObject(true, 'Parameters', '', node.parameters, node, node) addMissingParameters(node.parameters) } @@ -1744,37 +1859,37 @@ function newUiObjectsFromNodes () { if (node.baseAsset === undefined) { node.baseAsset = { name: 'Base Asset', - code: DEFAULT_CONFIG_TEXT + code: '{ \n\"name\": \"BTC\",\n"initialBalance\": 0.001,\n\"minimumBalance\": 0.0001,\n\"maximumBalance\": 0.1\n}' } - createUiObject('Base Asset', '', node.baseAsset, node, node) + createUiObject(true, 'Base Asset', '', node.baseAsset, node, node) } if (node.timeRange === undefined) { node.timeRange = { name: 'Time Range', - code: DEFAULT_CONFIG_TEXT + code: '{ \n\"initialDatetime\": \"2019-07-01T00:00:00.000Z\",\n\"finalDatetime\": \"2019-09-01T00:00:00.000Z\"\n}' } - createUiObject('Time Range', '', node.timeRange, node, node) + createUiObject(true, 'Time Range', '', node.timeRange, node, node) } if (node.timePeriod === undefined) { node.timePeriod = { name: 'Time Period', - code: DEFAULT_CONFIG_TEXT + code: '01-hs' } - createUiObject('Time Period', '', node.timePeriod, node, node) + createUiObject(true, 'Time Period', '', node.timePeriod, node, node) } if (node.slippage === undefined) { node.slippage = { name: 'Slippage', - code: DEFAULT_CONFIG_TEXT + code: '{ \n\"positionRate\": 0.1,\n"stopLoss\": 0.2,\n"takeProfit\": 0.3\n}' } - createUiObject('Slippage', '', node.slippage, node, node) + createUiObject(true, 'Slippage', '', node.slippage, node, node) } if (node.feeStructure === undefined) { node.feeStructure = { name: 'Fee Structure', - code: DEFAULT_CONFIG_TEXT + code: '{ \n\"maker\": 0.15,\n"taker\": 0.25\n}' } - createUiObject('Fee Structure', '', node.feeStructure, node, node) + createUiObject(true, 'Fee Structure', '', node.feeStructure, node, node) } } @@ -1796,11 +1911,11 @@ function newUiObjectsFromNodes () { } } } - createUiObject('Trigger Stage', '', node.triggerStage, node, node, 'Trigger Stage') - createUiObject('Trigger On Event', '', node.triggerStage.triggerOn, node.triggerStage, node.triggerStage) - createUiObject('Trigger Off Event', '', node.triggerStage.triggerOff, node.triggerStage, node.triggerStage) - createUiObject('Take Position Event', '', node.triggerStage.takePosition, node.triggerStage, node.triggerStage) - createUiObject('Formula', '', node.triggerStage.positionSize.formula, node.triggerStage.positionSize, node.triggerStage.positionSize) + createUiObject(true, 'Trigger Stage', '', node.triggerStage, node, node, 'Trigger Stage') + createUiObject(true, 'Trigger On Event', '', node.triggerStage.triggerOn, node.triggerStage, node.triggerStage) + createUiObject(true, 'Trigger Off Event', '', node.triggerStage.triggerOff, node.triggerStage, node.triggerStage) + createUiObject(true, 'Take Position Event', '', node.triggerStage.takePosition, node.triggerStage, node.triggerStage) + createUiObject(true, 'Formula', '', node.triggerStage.positionSize.formula, node.triggerStage.positionSize, node.triggerStage.positionSize) } if (node.openStage === undefined) { node.openStage = { @@ -1815,12 +1930,12 @@ function newUiObjectsFromNodes () { } } } - createUiObject('Open Stage', '', node.openStage, node, node, 'Open Stage') - createUiObject('Initial Definition', '', node.openStage.initialDefinition, node.openStage, node.openStage) - createUiObject('Stop', 'Initial Stop', node.openStage.initialDefinition.stopLoss, node.openStage.initialDefinition, node.openStage.initialDefinition) - createUiObject('Take Profit', 'Initial Take Profit', node.openStage.initialDefinition.takeProfit, node.openStage.initialDefinition, node.openStage.initialDefinition) - createUiObject('Position Size', 'Position Size', node.openStage.initialDefinition.positionSize, node.openStage.initialDefinition, node.openStage.initialDefinition) - createUiObject('Position Rate', 'Position Rate', node.openStage.initialDefinition.positionRate, node.openStage.initialDefinition, node.openStage.initialDefinition) + createUiObject(true, 'Open Stage', '', node.openStage, node, node, 'Open Stage') + createUiObject(true, 'Initial Definition', '', node.openStage.initialDefinition, node.openStage, node.openStage) + createUiObject(true, 'Stop', 'Initial Stop', node.openStage.initialDefinition.stopLoss, node.openStage.initialDefinition, node.openStage.initialDefinition) + createUiObject(true, 'Take Profit', 'Initial Take Profit', node.openStage.initialDefinition.takeProfit, node.openStage.initialDefinition, node.openStage.initialDefinition) + createUiObject(true, 'Position Size', 'Position Size', node.openStage.initialDefinition.positionSize, node.openStage.initialDefinition, node.openStage.initialDefinition) + createUiObject(true, 'Position Rate', 'Position Rate', node.openStage.initialDefinition.positionRate, node.openStage.initialDefinition, node.openStage.initialDefinition) } if (node.manageStage === undefined) { node.manageStage = { @@ -1831,14 +1946,14 @@ function newUiObjectsFromNodes () { phases: [] } } - createUiObject('Manage Stage', '', node.manageStage, node, node, 'Manage Stage') - createUiObject('Stop', '', node.manageStage.stopLoss, node.manageStage, node.manageStage) - createUiObject('Take Profit', '', node.manageStage.takeProfit, node.manageStage, node.manageStage) + createUiObject(true, 'Manage Stage', '', node.manageStage, node, node, 'Manage Stage') + createUiObject(true, 'Stop', '', node.manageStage.stopLoss, node.manageStage, node.manageStage) + createUiObject(true, 'Take Profit', '', node.manageStage.takeProfit, node.manageStage, node.manageStage) } if (node.closeStage === undefined) { node.closeStage = { } - createUiObject('Close Stage', '', node.closeStage, node, node, 'Close Stage') + createUiObject(true, 'Close Stage', '', node.closeStage, node, node, 'Close Stage') } } @@ -1848,21 +1963,21 @@ function newUiObjectsFromNodes () { situations: [], announcements: [] } - createUiObject('Trigger On Event', '', node.triggerOn, node, node) + createUiObject(true, 'Trigger On Event', '', node.triggerOn, node, node) } if (node.triggerOff === undefined) { node.triggerOff = { situations: [], announcements: [] } - createUiObject('Trigger Off Event', '', node.triggerOff, node, node) + createUiObject(true, 'Trigger Off Event', '', node.triggerOff, node, node) } if (node.takePosition === undefined) { node.takePosition = { situations: [], announcements: [] } - createUiObject('Take Position Event', '', node.takePosition, node, node) + createUiObject(true, 'Take Position Event', '', node.takePosition, node, node) } } @@ -1873,14 +1988,14 @@ function newUiObjectsFromNodes () { phases: [], maxPhases: 1 } - createUiObject('Stop', 'Initial Stop', node.stopLoss, node, node) + createUiObject(true, 'Stop', 'Initial Stop', node.stopLoss, node, node) } if (node.takeProfit === undefined) { node.takeProfit = { phases: [], maxPhases: 1 } - createUiObject('Take Profit', 'Initial Take Profit', node.takeProfit, node, node) + createUiObject(true, 'Take Profit', 'Initial Take Profit', node.takeProfit, node, node) } if (node.positionSize === undefined) { node.positionSize = { @@ -1889,8 +2004,8 @@ function newUiObjectsFromNodes () { code: DEFAULT_FORMULA_TEXT } } - createUiObject('Position Size', '', node.positionSize, node, node) - createUiObject('Formula', '', node.positionSize.formula, node.positionSize, node.positionSize) + createUiObject(true, 'Position Size', '', node.positionSize, node, node) + createUiObject(true, 'Formula', '', node.positionSize.formula, node.positionSize, node.positionSize) } if (node.positionRate === undefined) { node.positionRate = { @@ -1899,21 +2014,21 @@ function newUiObjectsFromNodes () { code: DEFAULT_FORMULA_TEXT } } - createUiObject('Position Rate', '', node.positionRate, node, node) - createUiObject('Formula', '', node.positionRate.formula, node.positionRate, node.positionRate) + createUiObject(true, 'Position Rate', '', node.positionRate, node, node) + createUiObject(true, 'Formula', '', node.positionRate.formula, node.positionRate, node.positionRate) } } else { if (node.stopLoss === undefined) { node.stopLoss = { phases: [] } - createUiObject('Stop', '', node.stopLoss, node, node) + createUiObject(true, 'Stop', '', node.stopLoss, node, node) } if (node.takeProfit === undefined) { node.takeProfit = { phases: [] } - createUiObject('Take Profit', '', node.takeProfit, node, node) + createUiObject(true, 'Take Profit', '', node.takeProfit, node, node) } } } @@ -1930,13 +2045,13 @@ function newUiObjectsFromNodes () { maxPhases: 1 } } - createUiObject('Initial Definition', '', node.initialDefinition, node, node) - createUiObject('Stop', 'Initial Stop', node.initialDefinition.stopLoss, node.initialDefinition, node.initialDefinition) - createUiObject('Take Profit', 'Initial Take Profit', node.initialDefinition.takeProfit, node.initialDefinition, node.initialDefinition) - createUiObject('Position Size', '', node.initialDefinition.positionSize, node.initialDefinition, node.initialDefinition) - createUiObject('Formula', '', node.initialDefinition.positionSize.formula, node.initialDefinition.positionSize, node.initialDefinition.positionSize) - createUiObject('Position Rate', '', node.initialDefinition.positionRate, node.initialDefinition, node.initialDefinition) - createUiObject('Formula', '', node.initialDefinition.positionRate.formula, node.initialDefinition.positionRate, node.initialDefinition.positionRate) + createUiObject(true, 'Initial Definition', '', node.initialDefinition, node, node) + createUiObject(true, 'Stop', 'Initial Stop', node.initialDefinition.stopLoss, node.initialDefinition, node.initialDefinition) + createUiObject(true, 'Take Profit', 'Initial Take Profit', node.initialDefinition.takeProfit, node.initialDefinition, node.initialDefinition) + createUiObject(true, 'Position Size', '', node.initialDefinition.positionSize, node.initialDefinition, node.initialDefinition) + createUiObject(true, 'Formula', '', node.initialDefinition.positionSize.formula, node.initialDefinition.positionSize, node.initialDefinition.positionSize) + createUiObject(true, 'Position Rate', '', node.initialDefinition.positionRate, node.initialDefinition, node.initialDefinition) + createUiObject(true, 'Formula', '', node.initialDefinition.positionRate.formula, node.initialDefinition.positionRate, node.initialDefinition.positionRate) } return node.initialDefinition @@ -1945,7 +2060,7 @@ function newUiObjectsFromNodes () { function addOpenExecution (node) { if (node.openExecution === undefined) { node.openExecution = {} - createUiObject('Open Execution', '', node.openExecution, node, node) + createUiObject(true, 'Open Execution', '', node.openExecution, node, node) } return node.openExecution @@ -1954,7 +2069,7 @@ function newUiObjectsFromNodes () { function addCloseExecution (node) { if (node.closeExecution === undefined) { node.closeExecution = {} - createUiObject('Close Execution', '', node.closeExecution, node, node) + createUiObject(true, 'Close Execution', '', node.closeExecution, node, node) } return node.closeExecution @@ -1965,7 +2080,7 @@ function newUiObjectsFromNodes () { node.formula = { code: DEFAULT_FORMULA_TEXT } - createUiObject('Formula', '', node.formula, node, node) + createUiObject(true, 'Formula', '', node.formula, node, node) } return node.formula @@ -1977,21 +2092,21 @@ function newUiObjectsFromNodes () { situations: [], announcements: [] } - createUiObject('Next Phase Event', '', node.nextPhaseEvent, node, node) + createUiObject(true, 'Next Phase Event', '', node.nextPhaseEvent, node, node) } return node.nextPhaseEvent } - function addCode (node) { - if (node.code === undefined) { - node.code = { + function addJavascriptCode (node) { + if (node.javascriptCode === undefined) { + node.javascriptCode = { code: DEFAULT_CODE_TEXT } - createUiObject('Code', '', node.code, node, node) + createUiObject(true, 'Javascript Code', '', node.code, node, node) } - return node.code + return node.javascriptCode } function addPhase (parentNode) { @@ -2024,9 +2139,9 @@ function newUiObjectsFromNodes () { } else { phaseChainParent = phaseParent } - createUiObject('Phase', phase.name, phase, phaseParent, phaseChainParent, 'Phase') - createUiObject('Formula', '', phase.formula, phase, phase, 'Formula') - createUiObject('Next Phase Event', '', phase.nextPhaseEvent, phase, phase) + createUiObject(true, 'Phase', phase.name, phase, phaseParent, phaseChainParent, 'Phase') + createUiObject(true, 'Formula', '', phase.formula, phase, phase, 'Formula') + createUiObject(true, 'Next Phase Event', '', phase.nextPhaseEvent, phase, phase) return phase } @@ -2038,7 +2153,7 @@ function newUiObjectsFromNodes () { conditions: [] } parentNode.situations.push(situation) - createUiObject('Situation', situation.name, situation, parentNode, parentNode, 'Situation') + createUiObject(true, 'Situation', situation.name, situation, parentNode, parentNode, 'Situation') return situation } @@ -2053,13 +2168,13 @@ function newUiObjectsFromNodes () { } } situation.conditions.push(condition) - createUiObject('Condition', condition.name, condition, situation, situation, 'Condition') - createUiObject('Code', '', condition.code, condition, condition, 'Code') + createUiObject(true, 'Condition', condition.name, condition, situation, situation, 'Condition') + createUiObject(true, 'Javascript Code', '', condition.code, condition, condition, 'Javascript Code') return condition } - function createUiObject (uiObjectType, name, node, parentNode, chainParent, title, positionOffset) { + function createUiObject (userAddingNew, uiObjectType, name, node, parentNode, chainParent, title, positionOffset) { let payload = {} if (name === '' || name === undefined) { name = 'My ' + uiObjectType } @@ -2119,6 +2234,6 @@ function newUiObjectsFromNodes () { } node.payload = payload node.type = uiObjectType - canvas.floatingSpace.uiObjectConstructor.createUiObject(payload) + canvas.floatingSpace.uiObjectConstructor.createUiObject(userAddingNew, payload) } } diff --git a/DesignerSpace/Workspace/Workspace.js b/DesignerSpace/Workspace/Workspace.js index 9ddfc5263..ed8f1f339 100644 --- a/DesignerSpace/Workspace/Workspace.js +++ b/DesignerSpace/Workspace/Workspace.js @@ -67,44 +67,23 @@ function newWorkspace () { thisObject.workspaceNode = undefined } - async function initialize () { + function initialize () { try { - let user = window.localStorage.getItem(LOGGED_IN_USER_LOCAL_STORAGE_KEY) - if (user === null) { - return - } - user = JSON.parse(user) + let savedWorkspace = window.localStorage.getItem(CANVAS_APP_NAME + '.' + 'Workspace') - let idAtStrategizer = window.localStorage.getItem(CANVAS_APP_NAME + '.' + 'Strategizer Gateway' + '.' + user.alias) - let savedWorkspace = window.localStorage.getItem(CANVAS_APP_NAME + '.' + 'Workspace' + '.' + user.alias) - - if (savedWorkspace === null || idAtStrategizer === null) { + if (savedWorkspace === null) { thisObject.workspaceNode.type = 'Workspace' thisObject.workspaceNode.name = 'My Workspace' - functionLibraryUiObjectsFromNodes.createUiObjectFromNode(thisObject.workspaceNode, undefined, undefined) - spawnPosition.y = spawnPosition.y + 250 - initializeLoadingFromStrategizer() } else { thisObject.workspaceNode = JSON.parse(savedWorkspace) - functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode) - thisObject.enabled = true } + functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode) + thisObject.enabled = true } catch (err) { if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> err = ' + err.stack) } } } - async function initializeLoadingFromStrategizer () { - let result = await canvas.designerSpace.strategizerGateway.loadFromStrategyzer() - if (result === true) { - thisObject.definition = canvas.designerSpace.strategizerGateway.strategizerData - thisObject.workspaceNode.rootNodes.push(thisObject.definition) - functionLibraryUiObjectsFromNodes.createUiObjectFromNode(thisObject.definition, undefined, undefined) - - thisObject.enabled = true - } - } - function chainDetachNode (node) { functionLibraryChainAttachDetach.chainDetachNode(node, thisObject.workspaceNode.rootNodes) } @@ -131,7 +110,7 @@ function newWorkspace () { user = JSON.parse(user) let textToSave = stringifyWorkspace() - window.localStorage.setItem(CANVAS_APP_NAME + '.' + 'Workspace' + '.' + user.alias, textToSave) + window.localStorage.setItem(CANVAS_APP_NAME + '.' + 'Workspace', textToSave) } function stringifyWorkspace (removePersonalData) { @@ -181,8 +160,12 @@ function newWorkspace () { let taskManager = networkNode.taskManagers[i] for (k = 0; k < taskManager.tasks.length; k++) { let task = taskManager.tasks[k] - if (task.bot.type === 'Trading Bot Instance') { - tradingBotInstances.push(task.bot) + if (task.bot !== undefined) { + if (task.bot.type === 'Trading Bot Instance') { + if (task.bot.payload.floatingObject.isCollapsed !== true) { + tradingBotInstances.push(task.bot) + } + } } } } @@ -222,8 +205,11 @@ function newWorkspace () { if (droppedNode.type === 'Workspace') { stopAllRunningTasks() functionLibraryNodeDeleter.deleteWorkspace(thisObject.workspaceNode, thisObject.workspaceNode.rootNodes) + canvas.floatingSpace.warmUp() thisObject.workspaceNode = droppedNode functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode) + canvas.chartSpace.finalize() + canvas.chartSpace.initialize() return } else { if ( @@ -262,8 +248,13 @@ function newWorkspace () { } } - async function onMenuItemClick (payload, action, callBackFunction) { + async function onMenuItemClick (payload, action, relatedUiObject, callBackFunction) { switch (action) { + case 'Add UI Object': + { + functionLibraryUiObjectsFromNodes.addUIObject(payload.node, relatedUiObject) + } + break case 'Share Workspace': { let text = stringifyWorkspace(true) @@ -651,7 +642,7 @@ function newWorkspace () { break case 'Add Code': { - functionLibraryUiObjectsFromNodes.addCode(payload.node) + functionLibraryUiObjectsFromNodes.addJavascriptCode(payload.node) } break case 'Add Exchange Account': @@ -936,7 +927,7 @@ function newWorkspace () { break } case 'Delete Code': { - functionLibraryNodeDeleter.deleteCode(payload.node, thisObject.workspaceNode.rootNodes) + functionLibraryNodeDeleter.deleteJavascriptCode(payload.node, thisObject.workspaceNode.rootNodes) break } case 'Delete Exchange Account': { diff --git a/FloatingSpace/CircularMenu.js b/FloatingSpace/CircularMenu.js index c8ef434f8..5a63f51a4 100644 --- a/FloatingSpace/CircularMenu.js +++ b/FloatingSpace/CircularMenu.js @@ -76,6 +76,8 @@ function newCircularMenu () { menuItem.dontShowAtFullscreen = menuItemInitialValue.dontShowAtFullscreen menuItem.askConfirmation = menuItemInitialValue.askConfirmation menuItem.confirmationLabel = menuItemInitialValue.confirmationLabel + menuItem.disableIfPropertyIsDefined = menuItemInitialValue.disableIfPropertyIsDefined + menuItem.propertyToCheckFor = menuItemInitialValue.propertyToCheckFor if (menuItem.label === undefined) { menuItem.type = 'Icon Only' diff --git a/FloatingSpace/CircularMenuItem.js b/FloatingSpace/CircularMenuItem.js index 2ce83ed0a..92ff2d7c5 100644 --- a/FloatingSpace/CircularMenuItem.js +++ b/FloatingSpace/CircularMenuItem.js @@ -10,6 +10,8 @@ function newCircularMenuItem () { iconOn: undefined, iconOff: undefined, currentIcon: undefined, + disableIfPropertyIsDefined: undefined, + propertyToCheckFor: undefined, action: undefined, actionFunction: undefined, actionStatus: undefined, @@ -35,6 +37,7 @@ function newCircularMenuItem () { payload: undefined, relatedUiObject: undefined, dontShowAtFullscreen: undefined, + isEnabled: true, internalClick: internalClick, physics: physics, drawBackground: drawBackground, @@ -93,6 +96,8 @@ function newCircularMenuItem () { thisObject.payload = undefined thisObject.actionFunction = undefined thisObject.actionStatus = undefined + thisObject.disableIfPropertyIsDefined = undefined + thisObject.propertyToCheckFor = undefined } function initialize (pPayload) { @@ -143,7 +148,6 @@ function newCircularMenuItem () { thisObject.container.frame.position.y = thisObject.container.frame.radius * 3 / 7 * Math.sin(toRadians(thisObject.angle)) - thisObject.container.frame.height / 2 /* Temporary Status impacts on the label to use and the background of that label */ - if (temporaryStatusCounter > 0) { temporaryStatusCounter-- } @@ -155,6 +159,16 @@ function newCircularMenuItem () { thisObject.nextAction = thisObject.action } + /* Here we will check if we need to monitor a property that influences the status of the Menu Item. */ + if (thisObject.disableIfPropertyIsDefined === true) { + if (thisObject.payload.node[thisObject.propertyToCheckFor] === undefined) { + /* This menu item is enabled. */ + thisObject.isEnabled = true + } else { + /* This menu item is disabled. */ + thisObject.isEnabled = false + } + } iconPhysics() } @@ -211,9 +225,11 @@ function newCircularMenuItem () { } function onMouseClick () { + if (thisObject.isEnabled === false) { return } + if (thisObject.label === undefined) { /* This is what we have in the case of menu items that are only Icons. In this situation there is no complex logic, just execute the specified action. */ - thisObject.actionFunction(thisObject.payload, thisObject.action) + thisObject.actionFunction(thisObject.payload, thisObject.action, thisObject.relatedUiObject) return } @@ -245,7 +261,7 @@ function newCircularMenuItem () { } /* Execute the action and wait for callbacks to update our statuus. */ - thisObject.actionFunction(thisObject.payload, thisObject.action, onPrimaryCallBack) + thisObject.actionFunction(thisObject.payload, thisObject.action, thisObject.relatedUiObject, onPrimaryCallBack) return } if (temporaryStatus === STATUS_PRIMARY_WORK_DONE && thisObject.secondaryAction !== undefined) { @@ -255,7 +271,7 @@ function newCircularMenuItem () { } /* Execute the action and wait for callbacks to update our statuus. */ - thisObject.actionFunction(thisObject.payload, thisObject.secondaryAction, onSecondaryCallBack) + thisObject.actionFunction(thisObject.payload, thisObject.secondaryAction, thisObject.relatedUiObject, onSecondaryCallBack) return } @@ -322,12 +338,16 @@ function newCircularMenuItem () { if (thisObject.container.frame.position.x > 0 && thisObject.isDeployed === true && thisObject.currentRadius >= thisObject.targetRadius) { if (thisObject.type === 'Icon & Text') { + let backgroundColor = backgroundColorToUse + if (thisObject.isEnabled === false) { + backgroundColor = UI_COLOR.GREY + } let params = { cornerRadius: 3, lineWidth: 0.1, container: thisObject.container, borderColor: UI_COLOR.DARK, - backgroundColor: backgroundColorToUse, + backgroundColor: backgroundColor, castShadow: false, xOffset: 40 } @@ -362,6 +382,7 @@ function newCircularMenuItem () { iconSize = thisObject.currentRadius } + if (thisObject.icon === undefined) { return } if (thisObject.icon.canDrawIcon === true && thisObject.currentRadius > 1 && thisObject.isDeployed === true) { browserCanvasContext.drawImage(thisObject.icon, menuPosition.x - iconSize, menuPosition.y - iconSize, iconSize * 2, iconSize * 2) @@ -387,4 +408,3 @@ function newCircularMenuItem () { } } } - diff --git a/FloatingSpace/CodeEditor.js b/FloatingSpace/CodeEditor.js index 1ed862964..cffba932a 100644 --- a/FloatingSpace/CodeEditor.js +++ b/FloatingSpace/CodeEditor.js @@ -1,6 +1,6 @@ function newCodeEditor () { - const MODULE_NAME = 'Circular Menu Iem' + const MODULE_NAME = 'Code Editor' let thisObject = { isVisibleFunction: undefined, @@ -80,6 +80,7 @@ function newCodeEditor () { thisObject.rawRadius = 8 thisObject.targetRadius = thisObject.container.frame.radius thisObject.currentRadius = 0 + thisObject.payload.uiObject.setErrorMessage('', 0) let textArea = document.getElementById('textArea') textArea.value = payload.node.code @@ -90,7 +91,7 @@ function newCodeEditor () { 'overflow:hidden;' + 'font-family: ' + UI_FONT.PRIMARY + ';' + 'font-size: 12px;' + - 'background-color: rgb(204, 88, 53);' + + 'background-color: rgb(' + UI_COLOR.RUSTED_RED + ');' + 'color:rgb(255, 255, 255);' + 'width: ' + thisObject.container.frame.width + 'px;' + 'height: ' + thisObject.container.frame.height + 'px' @@ -212,4 +213,3 @@ function newCodeEditor () { } } } - diff --git a/FloatingSpace/ConditionEditor.js b/FloatingSpace/ConditionEditor.js new file mode 100644 index 000000000..373c5def7 --- /dev/null +++ b/FloatingSpace/ConditionEditor.js @@ -0,0 +1,215 @@ + +function newConditionEditor () { + const MODULE_NAME = 'Condition Editor' + + let thisObject = { + isVisibleFunction: undefined, + iconOK: undefined, + iconNOT_OK: undefined, + visible: false, + imagePathOK: undefined, + imagePathNOT_OK: undefined, + rawRadius: undefined, + targetRadius: undefined, + currentRadius: undefined, + container: undefined, + payload: undefined, + deactivate: deactivate, + activate: activate, + physics: physics, + drawBackground: drawBackground, + drawForeground: drawForeground, + getContainer: getContainer, + finalize: finalize, + initialize: initialize + } + + thisObject.container = newContainer() + thisObject.container.initialize(MODULE_NAME) + thisObject.container.isClickeable = false + thisObject.container.isDraggeable = false + thisObject.container.detectMouseOver = false + thisObject.container.frame.radius = 0 + thisObject.container.frame.position.x = 0 + thisObject.container.frame.position.y = 0 + + let isMouseOver = false + + return thisObject + + function finalize () { + thisObject.container.finalize() + thisObject.container = undefined + thisObject.iconOK = undefined + thisObject.iconNOT_OK = undefined + thisObject.payload = undefined + thisObject.isVisibleFunction = undefined + } + + function initialize () { + /* Load Images */ + + thisObject.iconOK = new Image() + thisObject.iconOK.onload = onImageLoad + + function onImageLoad () { + thisObject.iconNOT_OK = new Image() + thisObject.iconNOT_OK.onload = onImageLoad + + function onImageLoad () { + thisObject.canDrawIcon = true + } + thisObject.iconNOT_OK.src = window.canvasApp.urlPrefix + thisObject.imagePathNOT_OK + } + // thisObject.iconOK.src = window.canvasApp.urlPrefix + thisObject.imagePathOK + // thisObject.icon = thisObject.iconOK // The default value is ON. + } + + function deactivate () { + if (thisObject.visible === true) { + thisObject.visible = false + let textArea = document.getElementById('textArea') + textArea.style.display = 'none' + thisObject.payload.node.code = textArea.value + } + } + + function activate (payload) { + thisObject.visible = true + thisObject.payload = payload + thisObject.rawRadius = 8 + thisObject.targetRadius = thisObject.container.frame.radius + thisObject.currentRadius = 0 + thisObject.payload.uiObject.setErrorMessage('', 0) + + let textArea = document.getElementById('textArea') + textArea.value = payload.node.code + textArea.style = 'resize: none;' + + ' border: none;' + + ' outline: none;' + + 'box-shadow: none;' + + 'overflow:hidden;' + + 'font-family: ' + UI_FONT.PRIMARY + ';' + + 'font-size: 12px;' + + 'background-color: rgb(' + UI_COLOR.GREEN + ');' + + 'color:rgb(255, 255, 255);' + + 'width: ' + thisObject.container.frame.width + 'px;' + + 'height: ' + thisObject.container.frame.height + 'px' + textArea.style.display = 'block' + textArea.focus() + } + + function getContainer (point) { + let container + if (thisObject.visible === true) { + if (point.x === VERY_LARGE_NUMBER) { + /* The the mouse leaves the canvas, and event of mouse over with a ridiculous coordinate is triggered so that + anyone can react. In our case, the code editor has a text area that is not part of the canvas, so the event is + triggered. We compensate recognizing this coordinate and returning our container. */ + return thisObject.container + } + + if (thisObject.container.frame.isThisPointHere(point, true, false) === true) { + return thisObject.container + } else { + return undefined + } + } + } + + function physics () { + if (Math.abs(thisObject.currentRadius - thisObject.targetRadius) >= 0.5) { + if (thisObject.currentRadius < thisObject.targetRadius) { + thisObject.currentRadius = thisObject.currentRadius + 0.5 + } else { + thisObject.currentRadius = thisObject.currentRadius - 0.5 + } + } + + thisObject.container.frame.position.x = 0 + thisObject.container.frame.position.y = 0 + + thisObject.container.frame.width = thisObject.container.frame.radius * 1.8 * 2 + thisObject.container.frame.height = thisObject.container.frame.radius * 1 * 2 + + let textAreaPosition = { + x: 0 - thisObject.container.frame.width / 2, + y: 0 - thisObject.container.frame.height * 3 / 7 + CURRENT_TOP_MARGIN + } + + textAreaPosition = thisObject.container.frame.frameThisPoint(textAreaPosition) + if (thisObject.visible === true) { + let checkPosition = { + x: textAreaPosition.x, + y: textAreaPosition.y - CURRENT_TOP_MARGIN + } + if (thisObject.isVisibleFunction(checkPosition) === false) { + deactivate() + } + } + if (thisObject.visible === true) { + let textAreaDiv = document.getElementById('textAreaDiv') + textAreaDiv.style = 'position:fixed; top:' + textAreaPosition.y + 'px; left:' + textAreaPosition.x + 'px; z-index:1; ' + } + } + + function drawBackground () { + if (thisObject.visible === true) { + let position = { + x: 0, + y: 0 + } + + position = thisObject.container.frame.frameThisPoint(position) + + let radius = thisObject.container.frame.radius * 2 + + if (radius > 0.5) { + browserCanvasContext.beginPath() + browserCanvasContext.arc(position.x, position.y, radius * 1.3 + 3, 0, Math.PI * 2, true) + browserCanvasContext.closePath() + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + 1 + ')' + browserCanvasContext.fill() + + browserCanvasContext.beginPath() + browserCanvasContext.arc(position.x, position.y, radius * 1.3, 0, Math.PI * 2, true) + browserCanvasContext.closePath() + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.GREEN + ', ' + 1 + ')' + browserCanvasContext.fill() + } + } + } + function drawForeground () { + let iconPosition = { + x: 0, + y: thisObject.currentRadius * 1.5 + } + + iconPosition = thisObject.container.frame.frameThisPoint(iconPosition) + + /* Menu Item */ + + if (thisObject.canDrawIcon === true && thisObject.currentRadius > 1) { + browserCanvasContext.drawImage(thisObject.icon, iconPosition.x - thisObject.currentRadius, iconPosition.y - thisObject.currentRadius, thisObject.currentRadius * 2, thisObject.currentRadius * 2) + + /* Menu Label */ + + let label = 'Code looks good!' + let labelPoint + let fontSize = 10 + + browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY + + if (label !== undefined && thisObject.currentRadius >= thisObject.targetRadius) { + labelPoint = { + x: iconPosition.x + thisObject.currentRadius + 10, + y: iconPosition.y + fontSize * FONT_ASPECT_RATIO + } + + browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)' + browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y) + } + } + } +} diff --git a/FloatingSpace/ConfigEditor.js b/FloatingSpace/ConfigEditor.js new file mode 100644 index 000000000..17fbd8818 --- /dev/null +++ b/FloatingSpace/ConfigEditor.js @@ -0,0 +1,221 @@ + +function newConfigEditor () { + const MODULE_NAME = 'Config Editor' + + let thisObject = { + isVisibleFunction: undefined, + iconOK: undefined, + iconNOT_OK: undefined, + visible: false, + imagePathOK: undefined, + imagePathNOT_OK: undefined, + rawRadius: undefined, + targetRadius: undefined, + currentRadius: undefined, + container: undefined, + payload: undefined, + deactivate: deactivate, + activate: activate, + physics: physics, + drawBackground: drawBackground, + drawForeground: drawForeground, + getContainer: getContainer, + finalize: finalize, + initialize: initialize + } + + thisObject.container = newContainer() + thisObject.container.initialize(MODULE_NAME) + thisObject.container.isClickeable = false + thisObject.container.isDraggeable = false + thisObject.container.detectMouseOver = false + thisObject.container.frame.radius = 0 + thisObject.container.frame.position.x = 0 + thisObject.container.frame.position.y = 0 + + let isMouseOver = false + + return thisObject + + function finalize () { + thisObject.container.finalize() + thisObject.container = undefined + thisObject.iconOK = undefined + thisObject.iconNOT_OK = undefined + thisObject.payload = undefined + thisObject.isVisibleFunction = undefined + } + + function initialize () { + /* Load Images */ + + thisObject.iconOK = new Image() + thisObject.iconOK.onload = onImageLoad + + function onImageLoad () { + thisObject.iconNOT_OK = new Image() + thisObject.iconNOT_OK.onload = onImageLoad + + function onImageLoad () { + thisObject.canDrawIcon = true + } + thisObject.iconNOT_OK.src = window.canvasApp.urlPrefix + thisObject.imagePathNOT_OK + } + // thisObject.iconOK.src = window.canvasApp.urlPrefix + thisObject.imagePathOK + // thisObject.icon = thisObject.iconOK // The default value is ON. + } + + function deactivate () { + if (thisObject.visible === true) { + thisObject.visible = false + let textArea = document.getElementById('textArea') + textArea.style.display = 'none' + thisObject.payload.node.code = textArea.value + + try { + let code = JSON.parse(thisObject.payload.node.code) + } catch (err) { + thisObject.payload.uiObject.setErrorMessage(err.message, 10) + } + } + } + + function activate (payload) { + thisObject.visible = true + thisObject.payload = payload + thisObject.rawRadius = 8 + thisObject.targetRadius = thisObject.container.frame.radius + thisObject.currentRadius = 0 + thisObject.payload.uiObject.setErrorMessage('', 0) + + let textArea = document.getElementById('textArea') + textArea.value = payload.node.code + textArea.style = 'resize: none;' + + ' border: none;' + + ' outline: none;' + + 'box-shadow: none;' + + 'overflow:hidden;' + + 'font-family: ' + UI_FONT.PRIMARY + ';' + + 'font-size: 12px;' + + 'background-color: rgb(' + UI_COLOR.DARK_TURQUOISE + ');' + + 'color:rgb(255, 255, 255);' + + 'width: ' + thisObject.container.frame.width + 'px;' + + 'height: ' + thisObject.container.frame.height + 'px' + textArea.style.display = 'block' + textArea.focus() + } + + function getContainer (point) { + let container + if (thisObject.visible === true) { + if (point.x === VERY_LARGE_NUMBER) { + /* The the mouse leaves the canvas, and event of mouse over with a ridiculous coordinate is triggered so that + anyone can react. In our case, the code editor has a text area that is not part of the canvas, so the event is + triggered. We compensate recognizing this coordinate and returning our container. */ + return thisObject.container + } + + if (thisObject.container.frame.isThisPointHere(point, true, false) === true) { + return thisObject.container + } else { + return undefined + } + } + } + + function physics () { + if (Math.abs(thisObject.currentRadius - thisObject.targetRadius) >= 0.5) { + if (thisObject.currentRadius < thisObject.targetRadius) { + thisObject.currentRadius = thisObject.currentRadius + 0.5 + } else { + thisObject.currentRadius = thisObject.currentRadius - 0.5 + } + } + + thisObject.container.frame.position.x = 0 + thisObject.container.frame.position.y = 0 + + thisObject.container.frame.width = thisObject.container.frame.radius * 1.8 * 2 + thisObject.container.frame.height = thisObject.container.frame.radius * 1 * 2 + + let textAreaPosition = { + x: 0 - thisObject.container.frame.width / 2, + y: 0 - thisObject.container.frame.height * 3 / 7 + CURRENT_TOP_MARGIN + } + + textAreaPosition = thisObject.container.frame.frameThisPoint(textAreaPosition) + if (thisObject.visible === true) { + let checkPosition = { + x: textAreaPosition.x, + y: textAreaPosition.y - CURRENT_TOP_MARGIN + } + if (thisObject.isVisibleFunction(checkPosition) === false) { + deactivate() + } + } + if (thisObject.visible === true) { + let textAreaDiv = document.getElementById('textAreaDiv') + textAreaDiv.style = 'position:fixed; top:' + textAreaPosition.y + 'px; left:' + textAreaPosition.x + 'px; z-index:1; ' + } + } + + function drawBackground () { + if (thisObject.visible === true) { + let position = { + x: 0, + y: 0 + } + + position = thisObject.container.frame.frameThisPoint(position) + + let radius = thisObject.container.frame.radius * 2 + + if (radius > 0.5) { + browserCanvasContext.beginPath() + browserCanvasContext.arc(position.x, position.y, radius * 1.3 + 3, 0, Math.PI * 2, true) + browserCanvasContext.closePath() + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + 1 + ')' + browserCanvasContext.fill() + + browserCanvasContext.beginPath() + browserCanvasContext.arc(position.x, position.y, radius * 1.3, 0, Math.PI * 2, true) + browserCanvasContext.closePath() + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.DARK_TURQUOISE + ', ' + 1 + ')' + browserCanvasContext.fill() + } + } + } + function drawForeground () { + let iconPosition = { + x: 0, + y: thisObject.currentRadius * 1.5 + } + + iconPosition = thisObject.container.frame.frameThisPoint(iconPosition) + + /* Menu Item */ + + if (thisObject.canDrawIcon === true && thisObject.currentRadius > 1) { + browserCanvasContext.drawImage(thisObject.icon, iconPosition.x - thisObject.currentRadius, iconPosition.y - thisObject.currentRadius, thisObject.currentRadius * 2, thisObject.currentRadius * 2) + + /* Menu Label */ + + let label = 'Code looks good!' + let labelPoint + let fontSize = 10 + + browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY + + if (label !== undefined && thisObject.currentRadius >= thisObject.targetRadius) { + labelPoint = { + x: iconPosition.x + thisObject.currentRadius + 10, + y: iconPosition.y + fontSize * FONT_ASPECT_RATIO + } + + browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)' + browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y) + } + } + } +} diff --git a/FloatingSpace/FloatingLayer.js b/FloatingSpace/FloatingLayer.js index c0c6a7f92..3d2bef34f 100644 --- a/FloatingSpace/FloatingLayer.js +++ b/FloatingSpace/FloatingLayer.js @@ -170,11 +170,6 @@ function newFloatingLayer () { let floatingObject = invisibleFloatingObjects[invisibleFloatingObjects.length - i - 1] floatingObject.drawForeground() } - - for (let i = 0; i < invisibleFloatingObjects.length; i++) { - let floatingObject = invisibleFloatingObjects[i] - floatingObject.drawOnFocus() - } } function drawVisibleObjects () { @@ -193,6 +188,12 @@ function newFloatingLayer () { floatingObject.drawForeground() } + /* Invisible objects on focus (freezed) should still have some priority */ + for (let i = 0; i < invisibleFloatingObjects.length; i++) { + let floatingObject = invisibleFloatingObjects[i] + floatingObject.drawOnFocus() + } + for (let i = 0; i < visibleFloatingObjects.length; i++) { let floatingObject = visibleFloatingObjects[i] floatingObject.drawOnFocus() @@ -206,6 +207,7 @@ function newFloatingLayer () { if (floatingObject.isFrozen === false && floatingObject.isParentCollapsed === false) { visibleFloatingObjects.push(floatingObject) invisibleFloatingObjects.splice(i, 1) // Delete item from array. + makeVisible() return // Only one at the time. } } @@ -218,6 +220,7 @@ function newFloatingLayer () { if (floatingObject.isFrozen === true || floatingObject.isParentCollapsed === true) { invisibleFloatingObjects.push(floatingObject) visibleFloatingObjects.splice(i, 1) // Delete item from array. + makeInvisible() return // Only one at the time. } } @@ -261,6 +264,8 @@ function newFloatingLayer () { for (let i = 0; i < visibleFloatingObjects.length; i++) { let floatingObject = visibleFloatingObjects[i] + if (canvas.floatingSpace.isItFar(floatingObject.payload)) { continue } + if (floatingObject.positionLocked === false) { floatingObject.container.frame.position.x = floatingObject.container.frame.position.x + floatingObject.currentSpeed.x floatingObject.container.frame.position.y = floatingObject.container.frame.position.y + floatingObject.currentSpeed.y @@ -747,4 +752,3 @@ function newFloatingLayer () { } } } - diff --git a/FloatingSpace/FloatingObject.js b/FloatingSpace/FloatingObject.js index 65a6672d5..70d4bc0f1 100644 --- a/FloatingSpace/FloatingObject.js +++ b/FloatingSpace/FloatingObject.js @@ -176,78 +176,86 @@ function newFloatingObject () { } function physics () { + collapsePhysics() + if (canvas.floatingSpace.isItFar(thisObject.payload)) { return } thisObjectPhysics() thisObject.payload.uiObject.physics() frozenPhysics() - collapsePhysics() tensionPhysics() } function frozenPhysics () { - if (thisObject.frozenManually === false) { - let parent = thisObject.payload.chainParent - if (parent !== undefined && parent.payload !== undefined) { - thisObject.isFrozen = parent.payload.floatingObject.isFrozen - } + if (thisObject.frozenManually !== false) { return } + if (thisObject.payload === undefined) { return } + let parent = thisObject.payload.chainParent + if (parent !== undefined && parent.payload !== undefined) { + thisObject.isFrozen = parent.payload.floatingObject.isFrozen } } function collapsePhysics () { let parent = thisObject.payload.chainParent - if (parent !== undefined) { - thisObject.isParentCollapsed = parent.payload.floatingObject.isCollapsed - if (thisObject.collapsedManually === false) { - thisObject.isCollapsed = parent.payload.floatingObject.isCollapsed - } + if (parent === undefined) { return } + if (parent.payload === undefined) { return } + if (parent.payload.floatingObject === undefined) { return } + + thisObject.isParentCollapsed = parent.payload.floatingObject.isCollapsed + if (thisObject.collapsedManually === false) { + thisObject.isCollapsed = parent.payload.floatingObject.isCollapsed } } function tensionPhysics () { /* Tension Effect */ + if (thisObject.isTensed === true) { let parent = thisObject.payload.chainParent - if (parent !== undefined) { - let distanceToChainParent = Math.sqrt(Math.pow(parent.payload.position.x - thisObject.container.frame.position.x, 2) + Math.pow(parent.payload.position.y - thisObject.container.frame.position.y, 2)) // ... we calculate the distance ... - let parentChildren = canvas.designerSpace.workspace.nodeChildren.childrenCount(parent, thisObject.payload.node) - let axisCount = parentChildren.childrenCount - let axisIndex = parentChildren.childIndex - let baseAngle = 0 + if (parent === undefined) { return } + if (parent.payload === undefined) { return } + if (parent.payload.position === undefined) { return } - if (axisIndex === undefined) { - axisCount = 1 - axisIndex = axisCount - } + let distanceToChainParent = Math.sqrt(Math.pow(parent.payload.position.x - thisObject.container.frame.position.x, 2) + Math.pow(parent.payload.position.y - thisObject.container.frame.position.y, 2)) // ... we calculate the distance ... + let parentChildren = canvas.designerSpace.workspace.nodeChildren.childrenCount(parent, thisObject.payload.node) + let axisCount = parentChildren.childrenCount + let axisIndex = parentChildren.childIndex + let baseAngle = 0 - if (parent.payload.chainParent !== undefined && parent.payload.angle !== undefined) { + if (axisIndex === undefined) { + axisCount = 1 + axisIndex = axisCount + } + + if (parent.payload.chainParent !== undefined && parent.payload.angle !== undefined) { + axisCount++ + axisIndex++ + baseAngle = parent.payload.angle + 180 + lastParentAngle = parent.payload.angle + } else { + if (lastParentAngle !== undefined) { axisCount++ axisIndex++ - baseAngle = parent.payload.angle + 180 - lastParentAngle = parent.payload.angle - } else { - if (lastParentAngle !== undefined) { - axisCount++ - axisIndex++ - baseAngle = lastParentAngle + 180 - } + baseAngle = lastParentAngle + 180 } + } - let angleStep = 360 / axisCount + let angleStep = 360 / axisCount - thisObject.payload.angle = baseAngle + (axisIndex - 1) * angleStep - if (thisObject.payload.angle >= 360) { - thisObject.payload.angle = thisObject.payload.angle - 360 - } + thisObject.payload.angle = baseAngle + (axisIndex - 1) * angleStep + if (thisObject.payload.angle >= 360) { + thisObject.payload.angle = thisObject.payload.angle - 360 + } - newPosition = { - x: parent.payload.position.x + distanceToChainParent * Math.cos(toRadians(thisObject.payload.angle)), - y: parent.payload.position.y + distanceToChainParent * Math.sin(toRadians(thisObject.payload.angle)) - } - if (isNaN(newPosition.x) === false) { - thisObject.container.frame.position.x = newPosition.x - } - if (isNaN(newPosition.y) === false) { - thisObject.container.frame.position.y = newPosition.y - } + if (distanceToChainParent > 1000) { return } // this is introduced to avoid edges cases when importing workspaces. + + newPosition = { + x: parent.payload.position.x + distanceToChainParent * Math.cos(toRadians(thisObject.payload.angle)), + y: parent.payload.position.y + distanceToChainParent * Math.sin(toRadians(thisObject.payload.angle)) + } + if (isNaN(newPosition.x) === false) { + thisObject.container.frame.position.x = newPosition.x + } + if (isNaN(newPosition.y) === false) { + thisObject.container.frame.position.y = newPosition.y } } } @@ -339,16 +347,19 @@ function newFloatingObject () { } function drawBackground () { + if (canvas.floatingSpace.isItFar(thisObject.payload)) { return } if ((thisObject.isCollapsed === true && thisObject.collapsedManually === false) || thisObject.isParentCollapsed === true) { return } thisObject.payload.uiObject.drawBackground() } function drawMiddleground () { + if (canvas.floatingSpace.isItFar(thisObject.payload)) { return } if ((thisObject.isCollapsed === true && thisObject.collapsedManually === false) || thisObject.isParentCollapsed === true) { return } thisObject.payload.uiObject.drawMiddleground() } function drawForeground () { + if (canvas.floatingSpace.isItFar(thisObject.payload)) { return } if ((thisObject.isCollapsed === true && thisObject.collapsedManually === false) || thisObject.isParentCollapsed === true) { return } thisObject.payload.uiObject.drawForeground() } diff --git a/FloatingSpace/FormulaEditor.js b/FloatingSpace/FormulaEditor.js new file mode 100644 index 000000000..f2e805485 --- /dev/null +++ b/FloatingSpace/FormulaEditor.js @@ -0,0 +1,215 @@ + +function newFormulaEditor () { + const MODULE_NAME = 'Formula Editor' + + let thisObject = { + isVisibleFunction: undefined, + iconOK: undefined, + iconNOT_OK: undefined, + visible: false, + imagePathOK: undefined, + imagePathNOT_OK: undefined, + rawRadius: undefined, + targetRadius: undefined, + currentRadius: undefined, + container: undefined, + payload: undefined, + deactivate: deactivate, + activate: activate, + physics: physics, + drawBackground: drawBackground, + drawForeground: drawForeground, + getContainer: getContainer, + finalize: finalize, + initialize: initialize + } + + thisObject.container = newContainer() + thisObject.container.initialize(MODULE_NAME) + thisObject.container.isClickeable = false + thisObject.container.isDraggeable = false + thisObject.container.detectMouseOver = false + thisObject.container.frame.radius = 0 + thisObject.container.frame.position.x = 0 + thisObject.container.frame.position.y = 0 + + let isMouseOver = false + + return thisObject + + function finalize () { + thisObject.container.finalize() + thisObject.container = undefined + thisObject.iconOK = undefined + thisObject.iconNOT_OK = undefined + thisObject.payload = undefined + thisObject.isVisibleFunction = undefined + } + + function initialize () { + /* Load Images */ + + thisObject.iconOK = new Image() + thisObject.iconOK.onload = onImageLoad + + function onImageLoad () { + thisObject.iconNOT_OK = new Image() + thisObject.iconNOT_OK.onload = onImageLoad + + function onImageLoad () { + thisObject.canDrawIcon = true + } + thisObject.iconNOT_OK.src = window.canvasApp.urlPrefix + thisObject.imagePathNOT_OK + } + // thisObject.iconOK.src = window.canvasApp.urlPrefix + thisObject.imagePathOK + // thisObject.icon = thisObject.iconOK // The default value is ON. + } + + function deactivate () { + if (thisObject.visible === true) { + thisObject.visible = false + let textArea = document.getElementById('textArea') + textArea.style.display = 'none' + thisObject.payload.node.code = textArea.value + } + } + + function activate (payload) { + thisObject.visible = true + thisObject.payload = payload + thisObject.rawRadius = 8 + thisObject.targetRadius = thisObject.container.frame.radius + thisObject.currentRadius = 0 + thisObject.payload.uiObject.setErrorMessage('', 0) + + let textArea = document.getElementById('textArea') + textArea.value = payload.node.code + textArea.style = 'resize: none;' + + ' border: none;' + + ' outline: none;' + + 'box-shadow: none;' + + 'overflow:hidden;' + + 'font-family: ' + UI_FONT.PRIMARY + ';' + + 'font-size: 12px;' + + 'background-color: rgb(' + UI_COLOR.MANGANESE_PURPLE + ');' + + 'color:rgb(255, 255, 255);' + + 'width: ' + thisObject.container.frame.width + 'px;' + + 'height: ' + thisObject.container.frame.height + 'px' + textArea.style.display = 'block' + textArea.focus() + } + + function getContainer (point) { + let container + if (thisObject.visible === true) { + if (point.x === VERY_LARGE_NUMBER) { + /* The the mouse leaves the canvas, and event of mouse over with a ridiculous coordinate is triggered so that + anyone can react. In our case, the code editor has a text area that is not part of the canvas, so the event is + triggered. We compensate recognizing this coordinate and returning our container. */ + return thisObject.container + } + + if (thisObject.container.frame.isThisPointHere(point, true, false) === true) { + return thisObject.container + } else { + return undefined + } + } + } + + function physics () { + if (Math.abs(thisObject.currentRadius - thisObject.targetRadius) >= 0.5) { + if (thisObject.currentRadius < thisObject.targetRadius) { + thisObject.currentRadius = thisObject.currentRadius + 0.5 + } else { + thisObject.currentRadius = thisObject.currentRadius - 0.5 + } + } + + thisObject.container.frame.position.x = 0 + thisObject.container.frame.position.y = 0 + + thisObject.container.frame.width = thisObject.container.frame.radius * 1.8 * 2 + thisObject.container.frame.height = thisObject.container.frame.radius * 1 * 2 + + let textAreaPosition = { + x: 0 - thisObject.container.frame.width / 2, + y: 0 - thisObject.container.frame.height * 3 / 7 + CURRENT_TOP_MARGIN + } + + textAreaPosition = thisObject.container.frame.frameThisPoint(textAreaPosition) + if (thisObject.visible === true) { + let checkPosition = { + x: textAreaPosition.x, + y: textAreaPosition.y - CURRENT_TOP_MARGIN + } + if (thisObject.isVisibleFunction(checkPosition) === false) { + deactivate() + } + } + if (thisObject.visible === true) { + let textAreaDiv = document.getElementById('textAreaDiv') + textAreaDiv.style = 'position:fixed; top:' + textAreaPosition.y + 'px; left:' + textAreaPosition.x + 'px; z-index:1; ' + } + } + + function drawBackground () { + if (thisObject.visible === true) { + let position = { + x: 0, + y: 0 + } + + position = thisObject.container.frame.frameThisPoint(position) + + let radius = thisObject.container.frame.radius * 2 + + if (radius > 0.5) { + browserCanvasContext.beginPath() + browserCanvasContext.arc(position.x, position.y, radius * 1.3 + 3, 0, Math.PI * 2, true) + browserCanvasContext.closePath() + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + 1 + ')' + browserCanvasContext.fill() + + browserCanvasContext.beginPath() + browserCanvasContext.arc(position.x, position.y, radius * 1.3, 0, Math.PI * 2, true) + browserCanvasContext.closePath() + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.MANGANESE_PURPLE + ', ' + 1 + ')' + browserCanvasContext.fill() + } + } + } + function drawForeground () { + let iconPosition = { + x: 0, + y: thisObject.currentRadius * 1.5 + } + + iconPosition = thisObject.container.frame.frameThisPoint(iconPosition) + + /* Menu Item */ + + if (thisObject.canDrawIcon === true && thisObject.currentRadius > 1) { + browserCanvasContext.drawImage(thisObject.icon, iconPosition.x - thisObject.currentRadius, iconPosition.y - thisObject.currentRadius, thisObject.currentRadius * 2, thisObject.currentRadius * 2) + + /* Menu Label */ + + let label = 'Code looks good!' + let labelPoint + let fontSize = 10 + + browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY + + if (label !== undefined && thisObject.currentRadius >= thisObject.targetRadius) { + labelPoint = { + x: iconPosition.x + thisObject.currentRadius + 10, + y: iconPosition.y + fontSize * FONT_ASPECT_RATIO + } + + browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)' + browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y) + } + } + } +} diff --git a/FloatingSpace/UiObject.js b/FloatingSpace/UiObject.js index 1f77f9847..50eb1d391 100644 --- a/FloatingSpace/UiObject.js +++ b/FloatingSpace/UiObject.js @@ -15,6 +15,9 @@ function newUiObject () { container: undefined, payload: undefined, codeEditor: undefined, + configEditor: undefined, + conditionEditor: undefined, + formulaEditor: undefined, uiObjectTitle: undefined, circularProgressBar: undefined, isExecuting: undefined, @@ -115,6 +118,21 @@ function newUiObject () { thisObject.codeEditor = undefined } + if (thisObject.configEditor !== undefined) { + thisObject.configEditor.finalize() + thisObject.configEditor = undefined + } + + if (thisObject.conditionEditor !== undefined) { + thisObject.conditionEditor.finalize() + thisObject.conditionEditor = undefined + } + + if (thisObject.formulaEditor !== undefined) { + thisObject.formulaEditor.finalize() + thisObject.formulaEditor = undefined + } + icon = undefined chainAttachToNode = undefined referenceAttachToNode = undefined @@ -156,6 +174,21 @@ function newUiObject () { if (container !== undefined) { return container } } + if (thisObject.configEditor !== undefined) { + container = thisObject.configEditor.getContainer(point) + if (container !== undefined) { return container } + } + + if (thisObject.conditionEditor !== undefined) { + container = thisObject.conditionEditor.getContainer(point) + if (container !== undefined) { return container } + } + + if (thisObject.formulaEditor !== undefined) { + container = thisObject.formulaEditor.getContainer(point) + if (container !== undefined) { return container } + } + container = thisObject.uiObjectTitle.getContainer(point) if (container !== undefined) { return container } @@ -178,6 +211,18 @@ function newUiObject () { thisObject.codeEditor.physics() } + if (thisObject.configEditor !== undefined) { + thisObject.configEditor.physics() + } + + if (thisObject.conditionEditor !== undefined) { + thisObject.conditionEditor.physics() + } + + if (thisObject.formulaEditor !== undefined) { + thisObject.formulaEditor.physics() + } + if (thisObject.payload.chainParent === undefined || thisObject.payload.chainParent.payload === undefined) { thisObject.payload.targetPosition.x = thisObject.payload.position.x, thisObject.payload.targetPosition.y = thisObject.payload.position.y @@ -505,7 +550,7 @@ function newUiObject () { compatibleType = '->' + 'Situation' + '->' compatibleSubType = undefined break - case 'Code': + case 'Javascript Code': compatibleType = '->' + 'Condition' + '->' + 'Procedure Initialization' + '->' + 'Procedure Loop' + '->' + 'Plotter Module' + '->' + 'Plotter Panel' + '->' compatibleSubType = undefined break @@ -564,7 +609,7 @@ function newUiObject () { if (thisObject.payload.node.type === 'Take Profit' && nearbyNode.takeProfit !== undefined) { continue } if (thisObject.payload.node.type === 'Formula' && nearbyNode.formula !== undefined) { continue } if (thisObject.payload.node.type === 'Next Phase Event' && nearbyNode.nextPhaseEvent !== undefined) { continue } - if (thisObject.payload.node.type === 'Code' && nearbyNode.code !== undefined) { continue } + if (thisObject.payload.node.type === 'Javascript Code' && nearbyNode.javascriptCode !== undefined) { continue } /* Here we check if the subtypes are compatible. */ if (nearbyNode.subType !== undefined && compatibleSubType !== undefined) { if (compatibleSubType.indexOf('->' + nearbyNode.subType + '->') < 0) { @@ -711,6 +756,10 @@ function newUiObject () { compatibleType = '->' + 'Process Definition' + '->' compatibleSubType = undefined break + case 'Product Definition': + compatibleType = '->' + 'Plotter Module' + '->' + compatibleSubType = undefined + break default: return } @@ -835,11 +884,12 @@ function newUiObject () { highlightCounter = 30 } - function setErrorMessage (message) { + function setErrorMessage (message, duration) { if (message !== undefined) { errorMessage = message hasError = true - errorMessageCounter = 100 + if (duration === undefined) { duration = 1 } + errorMessageCounter = 100 * duration } } @@ -923,6 +973,15 @@ function newUiObject () { if (thisObject.codeEditor !== undefined) { thisObject.codeEditor.deactivate() } + if (thisObject.configEditor !== undefined) { + thisObject.configEditor.deactivate() + } + if (thisObject.conditionEditor !== undefined) { + thisObject.conditionEditor.deactivate() + } + if (thisObject.formulaEditor !== undefined) { + thisObject.formulaEditor.deactivate() + } } function onDisplace (event) { @@ -934,6 +993,15 @@ function newUiObject () { if (thisObject.codeEditor !== undefined) { thisObject.codeEditor.deactivate() } + if (thisObject.configEditor !== undefined) { + thisObject.configEditor.deactivate() + } + if (thisObject.conditionEditor !== undefined) { + thisObject.conditionEditor.deactivate() + } + if (thisObject.formulaEditor !== undefined) { + thisObject.formulaEditor.deactivate() + } isDragging = true if (event.button === 2) { rightDragging = true @@ -1004,16 +1072,43 @@ function newUiObject () { thisObject.codeEditor.drawBackground() thisObject.codeEditor.drawForeground() } + if (thisObject.configEditor !== undefined) { + thisObject.configEditor.drawBackground() + thisObject.configEditor.drawForeground() + } + if (thisObject.conditionEditor !== undefined) { + thisObject.conditionEditor.drawBackground() + thisObject.conditionEditor.drawForeground() + } + if (thisObject.formulaEditor !== undefined) { + thisObject.formulaEditor.drawBackground() + thisObject.formulaEditor.drawForeground() + } + + let drawMenu = true if (thisObject.codeEditor !== undefined) { - if (thisObject.codeEditor.visible === false) { - drawBodyAndPicture() - if (isDragging === false) { - thisObject.menu.drawBackground() - thisObject.menu.drawForeground() - } + if (thisObject.codeEditor.visible === true) { + drawMenu = false } - } else { + } + if (thisObject.configEditor !== undefined) { + if (thisObject.configEditor.visible === true) { + drawMenu = false + } + } + if (thisObject.conditionEditor !== undefined) { + if (thisObject.conditionEditor.visible === true) { + drawMenu = false + } + } + if (thisObject.formulaEditor !== undefined) { + if (thisObject.formulaEditor.visible === true) { + drawMenu = false + } + } + + if (drawMenu === true) { drawBodyAndPicture() if (isDragging === false) { thisObject.menu.drawBackground() @@ -1089,6 +1184,8 @@ function newUiObject () { function drawReferenceLine () { if (thisObject.payload.referenceParent === undefined) { return } + if (thisObject.payload.referenceParent.payload === undefined) { return } + if (thisObject.payload.referenceParent.payload.floatingObject === undefined) { return } if (thisObject.payload.referenceParent.payload.floatingObject.isParentCollapsed === true) { return } let targetPoint = { diff --git a/FloatingSpace/UiObjectConstructor.js b/FloatingSpace/UiObjectConstructor.js index 538d29438..b05162849 100644 --- a/FloatingSpace/UiObjectConstructor.js +++ b/FloatingSpace/UiObjectConstructor.js @@ -18,16 +18,13 @@ function newUiObjectConstructor () { function finalize () { floatingLayer = undefined - - payload.uiObject.finalize() - payload.uiObject = undefined } function initialize (pFloatingLayer) { floatingLayer = pFloatingLayer } - function createUiObject (payload) { + function createUiObject (userAddingNew, payload) { let floatingObject = newFloatingObject() floatingObject.fitFunction = canvas.floatingSpace.fitIntoVisibleArea floatingObject.container.connectToParent(canvas.floatingSpace.container, false, false, false, false, false, false, false, false) @@ -59,6 +56,13 @@ function newUiObjectConstructor () { } } + if (userAddingNew === true) { + /* For brand new objects being created directly by the user, we will make them inherit some properties from their parents. */ + if (payload.parentNode.payload.floatingObject.isTensed === true) { + floatingObject.tensionToggle() + } + } + let uiObject = newUiObject() payload.uiObject = uiObject uiObject.fitFunction = canvas.floatingSpace.fitIntoVisibleArea @@ -249,6 +253,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Trading System', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'tradingSystem', actionFunction: payload.onMenuItemClick, label: 'Add Trading System', visible: true, @@ -262,6 +268,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Personal Data', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'personalData', actionFunction: payload.onMenuItemClick, label: 'Add Personal Data', visible: true, @@ -305,16 +313,16 @@ function newUiObjectConstructor () { break } case 'Team': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Team', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Bot', + action: 'Configure Team', + actionFunction: uiObject.configEditor.activate, + label: 'Configigure Team', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -410,16 +418,16 @@ function newUiObjectConstructor () { break } case 'Sensor Bot': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Bot', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Bot', + action: 'Configure Bot', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Bot', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -489,16 +497,16 @@ function newUiObjectConstructor () { break } case 'Indicator Bot': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Bot', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Bot', + action: 'Configure Bot', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Bot', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -568,16 +576,16 @@ function newUiObjectConstructor () { break } case 'Trading Bot': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Bot', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Bot', + action: 'Configure Bot', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Bot', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -647,16 +655,16 @@ function newUiObjectConstructor () { break } case 'Process Definition': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Process', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Process', + action: 'Configure Process', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Process', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -926,6 +934,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Procedure Initialization', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'initialization', actionFunction: payload.onMenuItemClick, label: 'Add Procedure Initialization', visible: true, @@ -939,6 +949,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Procedure Loop', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'loop', actionFunction: payload.onMenuItemClick, label: 'Add Procedure Loop', visible: true, @@ -986,6 +998,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Procedure Initialization', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'initialization', actionFunction: payload.onMenuItemClick, label: 'Add Procedure Initialization', visible: true, @@ -999,6 +1013,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Procedure Loop', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'loop', actionFunction: payload.onMenuItemClick, label: 'Add Procedure Loop', visible: true, @@ -1046,10 +1062,12 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Code', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'code', actionFunction: payload.onMenuItemClick, label: 'Add Code', visible: true, - relatedUiObject: 'Code', + relatedUiObject: 'Javascript Code', rawRadius: 8, targetRadius: 0, currentRadius: 0, @@ -1093,10 +1111,12 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Code', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'code', actionFunction: payload.onMenuItemClick, label: 'Add Code', visible: true, - relatedUiObject: 'Code', + relatedUiObject: 'Javascript Code', rawRadius: 8, targetRadius: 0, currentRadius: 0, @@ -1170,16 +1190,16 @@ function newUiObjectConstructor () { break } case 'Status Dependency': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Status Dependency', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Status Dependency', + action: 'Configure Status Dependency', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Status Dependency', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -1257,16 +1277,16 @@ function newUiObjectConstructor () { break } case 'Product Definition': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Product', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Product', + action: 'Configure Product', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Product', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -1280,6 +1300,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Record Definition', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'record', actionFunction: payload.onMenuItemClick, label: 'Add Record Definition', visible: true, @@ -1396,16 +1418,16 @@ function newUiObjectConstructor () { break } case 'Record Property': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Property', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Property', + action: 'Configure Property', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Property', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -1419,6 +1441,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Formula', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'formula', actionFunction: payload.onMenuItemClick, label: 'Add Formula', visible: true, @@ -1462,16 +1486,16 @@ function newUiObjectConstructor () { break } case 'Dataset Definition': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Definition', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Definition', + action: 'Configure Definition', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Definition', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -1515,7 +1539,26 @@ function newUiObjectConstructor () { break } case 'Plotter': { + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) + menuItemsInitialValues.push( + { + action: 'Configure Plotter', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Plotter', + visible: true, + iconPathOn: 'html', + iconPathOff: 'html', + rawRadius: 8, + targetRadius: 0, + currentRadius: 0, + angle: -30, + dontShowAtFullscreen: true + } + ) menuItemsInitialValues.push( { action: 'Add Plotter Module', @@ -1526,7 +1569,7 @@ function newUiObjectConstructor () { rawRadius: 8, targetRadius: 0, currentRadius: 0, - angle: -20 + angle: -10 } ) menuItemsInitialValues.push( @@ -1542,66 +1585,6 @@ function newUiObjectConstructor () { rawRadius: 8, targetRadius: 0, currentRadius: 0, - angle: 0 - } - ) - menuItemsInitialValues.push( - { - action: 'Share', - actionFunction: payload.onMenuItemClick, - label: 'Share', - visible: true, - iconPathOn: 'menu-share', - iconPathOff: 'menu-share', - rawRadius: 8, - targetRadius: 0, - currentRadius: 0, - angle: 20 - } - ) - break - } - case 'Plotter Module': { - addLeftIcons(menuItemsInitialValues, floatingObject) - menuItemsInitialValues.push( - { - action: 'Add Code', - actionFunction: payload.onMenuItemClick, - label: 'Add Code', - visible: true, - relatedUiObject: 'Code', - rawRadius: 8, - targetRadius: 0, - currentRadius: 0, - angle: -30 - } - ) - menuItemsInitialValues.push( - { - action: 'Add Plotter Panel', - actionFunction: payload.onMenuItemClick, - label: 'Add Plotter Panel', - visible: true, - relatedUiObject: 'Plotter Panel', - rawRadius: 8, - targetRadius: 0, - currentRadius: 0, - angle: -10 - } - ) - menuItemsInitialValues.push( - { - action: 'Delete Plotter Module', - askConfirmation: true, - confirmationLabel: 'Confirm to Delete', - actionFunction: payload.onMenuItemClick, - label: 'Delete Plotter Module', - visible: true, - iconPathOn: 'delete', - iconPathOff: 'delete', - rawRadius: 8, - targetRadius: 0, - currentRadius: 0, angle: 10 } ) @@ -1621,15 +1604,113 @@ function newUiObjectConstructor () { ) break } + case 'Plotter Module': { + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + addLeftIcons(menuItemsInitialValues, floatingObject) + menuItemsInitialValues.push( + { + action: 'Configure Plotter Module', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Plotter Module', + visible: true, + iconPathOn: 'html', + iconPathOff: 'html', + rawRadius: 8, + targetRadius: 0, + currentRadius: 0, + angle: -60, + dontShowAtFullscreen: true + } + ) + menuItemsInitialValues.push( + { + action: 'Add Code', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'code', + actionFunction: payload.onMenuItemClick, + label: 'Add Code', + visible: true, + relatedUiObject: 'Javascript Code', + rawRadius: 8, + targetRadius: 0, + currentRadius: 0, + angle: -30 + } + ) + menuItemsInitialValues.push( + { + action: 'Add UI Object', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'shapes', + actionFunction: payload.onMenuItemClick, + label: 'Add Shapes', + visible: true, + relatedUiObject: 'Shapes', + rawRadius: 8, + targetRadius: 0, + currentRadius: 0, + angle: -10 + } + ) + menuItemsInitialValues.push( + { + action: 'Add Plotter Panel', + actionFunction: payload.onMenuItemClick, + label: 'Add Plotter Panel', + visible: true, + relatedUiObject: 'Plotter Panel', + rawRadius: 8, + targetRadius: 0, + currentRadius: 0, + angle: 10 + } + ) + menuItemsInitialValues.push( + { + action: 'Delete Plotter Module', + askConfirmation: true, + confirmationLabel: 'Confirm to Delete', + actionFunction: payload.onMenuItemClick, + label: 'Delete Plotter Module', + visible: true, + iconPathOn: 'delete', + iconPathOff: 'delete', + rawRadius: 8, + targetRadius: 0, + currentRadius: 0, + angle: 30 + } + ) + menuItemsInitialValues.push( + { + action: 'Share', + actionFunction: payload.onMenuItemClick, + label: 'Share', + visible: true, + iconPathOn: 'menu-share', + iconPathOff: 'menu-share', + rawRadius: 8, + targetRadius: 0, + currentRadius: 0, + angle: 60 + } + ) + break + } case 'Plotter Panel': { addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { action: 'Add Code', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'code', actionFunction: payload.onMenuItemClick, label: 'Add Code', visible: true, - relatedUiObject: 'Code', + relatedUiObject: 'Javascript Code', rawRadius: 8, targetRadius: 0, currentRadius: 0, @@ -1810,10 +1891,10 @@ function newUiObjectConstructor () { break } case 'Telegram Bot': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { @@ -1830,9 +1911,9 @@ function newUiObjectConstructor () { ) menuItemsInitialValues.push( { - action: 'Edit Telegram Bot', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Telegram Bot', + action: 'Configure Telegram Bot', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Telegram Bot', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -1876,14 +1957,16 @@ function newUiObjectConstructor () { break } case 'Announcement': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { action: 'Add Formula', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'formula', actionFunction: payload.onMenuItemClick, label: 'Add Formula', visible: true, @@ -1897,9 +1980,9 @@ function newUiObjectConstructor () { addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Announcement', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Announcement', + action: 'Configure Announcement', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Announcement', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -1990,16 +2073,16 @@ function newUiObjectConstructor () { break } case 'Layer': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Layer', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Layer', + action: 'Configure Layer', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Layer', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -2145,6 +2228,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Sensor Bot Instance', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'bot', actionFunction: payload.onMenuItemClick, label: 'Add Sensor Bot Instance', visible: true, @@ -2158,6 +2243,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Indicator Bot Instance', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'bot', actionFunction: payload.onMenuItemClick, label: 'Add Indicator Bot Instance', visible: true, @@ -2171,6 +2258,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Trading Bot Instance', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'bot', actionFunction: payload.onMenuItemClick, label: 'Add Trading Bot Instance', visible: true, @@ -2214,17 +2303,17 @@ function newUiObjectConstructor () { break } case 'Sensor Bot Instance': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Sensor Bot Instance', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Sensor Bot Instance', + action: 'Configure Sensor Bot Instance', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Sensor Bot Instance', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -2281,17 +2370,17 @@ function newUiObjectConstructor () { break } case 'Indicator Bot Instance': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Indicator Bot Instance', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Indicator Bot Instance', + action: 'Configure Indicator Bot Instance', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Indicator Bot Instance', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -2348,17 +2437,17 @@ function newUiObjectConstructor () { break } case 'Trading Bot Instance': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Trading Bot Instance', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Trading Bot Instance', + action: 'Configure Trading Bot Instance', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Trading Bot Instance', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -2415,10 +2504,10 @@ function newUiObjectConstructor () { break } case 'Process Instance': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) @@ -2427,6 +2516,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Backtesting Session', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'session', actionFunction: payload.onMenuItemClick, label: 'Add Backtesting', visible: true, @@ -2440,6 +2531,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Live Trading Session', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'session', actionFunction: payload.onMenuItemClick, label: 'Add Live Trading', visible: true, @@ -2453,6 +2546,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Fordward Testing Session', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'session', actionFunction: payload.onMenuItemClick, label: 'Add Fordward Testing', visible: true, @@ -2466,6 +2561,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Paper Trading Session', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'session', actionFunction: payload.onMenuItemClick, label: 'Add Paper Trading', visible: true, @@ -2478,9 +2575,9 @@ function newUiObjectConstructor () { ) menuItemsInitialValues.push( { - action: 'Edit Process Instance', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Process Instance', + action: 'Configure Process Instance', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Process Instance', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -2526,9 +2623,9 @@ function newUiObjectConstructor () { default: { menuItemsInitialValues.push( { - action: 'Edit Process Instance', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Process Instance', + action: 'Configure Process Instance', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Process Instance', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -2575,10 +2672,10 @@ function newUiObjectConstructor () { break } case 'Backtesting Session': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( @@ -2607,6 +2704,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Layer Manager', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'layerManager', actionFunction: payload.onMenuItemClick, label: 'Add Layer Manager', visible: true, @@ -2620,6 +2719,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Parameters', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'parameters', actionFunction: payload.onMenuItemClick, label: 'Add Parameters', visible: true, @@ -2633,6 +2734,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Social Bots', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'socialBots', actionFunction: payload.onMenuItemClick, label: 'Add Social Bots', visible: true, @@ -2645,9 +2748,9 @@ function newUiObjectConstructor () { ) menuItemsInitialValues.push( { - action: 'Edit Session', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Session', + action: 'Configure Session', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Session', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -2691,10 +2794,10 @@ function newUiObjectConstructor () { break } case 'Live Trading Session': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( @@ -2723,6 +2826,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Layer Manager', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'layerManager', actionFunction: payload.onMenuItemClick, label: 'Add Layer Manager', visible: true, @@ -2736,6 +2841,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Parameters', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'parameters', actionFunction: payload.onMenuItemClick, label: 'Add Parameters', visible: true, @@ -2749,6 +2856,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Social Bots', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'socialBots', actionFunction: payload.onMenuItemClick, label: 'Add Social Bots', visible: true, @@ -2761,9 +2870,9 @@ function newUiObjectConstructor () { ) menuItemsInitialValues.push( { - action: 'Edit Session', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Session', + action: 'Configure Session', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Session', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -2807,10 +2916,10 @@ function newUiObjectConstructor () { break } case 'Fordward Testing Session': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( @@ -2839,6 +2948,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Layer Manager', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'layerManager', actionFunction: payload.onMenuItemClick, label: 'Add Layer Manager', visible: true, @@ -2852,6 +2963,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Parameters', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'parameters', actionFunction: payload.onMenuItemClick, label: 'Add Parameters', visible: true, @@ -2865,6 +2978,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Social Bots', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'socialBots', actionFunction: payload.onMenuItemClick, label: 'Add Social Bots', visible: true, @@ -2877,9 +2992,9 @@ function newUiObjectConstructor () { ) menuItemsInitialValues.push( { - action: 'Edit Session', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Session', + action: 'Configure Session', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Session', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -2923,10 +3038,10 @@ function newUiObjectConstructor () { break } case 'Paper Trading Session': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( @@ -2955,6 +3070,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Layer Manager', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'layerManager', actionFunction: payload.onMenuItemClick, label: 'Add Layer Manager', visible: true, @@ -2968,6 +3085,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Parameters', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'parameters', actionFunction: payload.onMenuItemClick, label: 'Add Parameters', visible: true, @@ -2981,6 +3100,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Social Bots', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'socialBots', actionFunction: payload.onMenuItemClick, label: 'Add Social Bots', visible: true, @@ -2993,9 +3114,9 @@ function newUiObjectConstructor () { ) menuItemsInitialValues.push( { - action: 'Edit Session', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Session', + action: 'Configure Session', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Session', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -3138,17 +3259,17 @@ function newUiObjectConstructor () { break } case 'Exchange Account Key': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Key Value', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Key Value', + action: 'Configure Key Value', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Key Value', visible: true, iconPathOn: 'html', iconPathOff: 'html', @@ -3195,6 +3316,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Parameters', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'parameters', actionFunction: payload.onMenuItemClick, label: 'Add Parameters', visible: true, @@ -3285,17 +3408,17 @@ function newUiObjectConstructor () { break } case 'Base Asset': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Base Asset', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Base Asset', + action: 'Configure Base Asset', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Base Asset', visible: true, iconPathOn: 'settings', iconPathOff: 'settings', @@ -3338,17 +3461,17 @@ function newUiObjectConstructor () { break } case 'Time Range': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Time Range', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Time Range', + action: 'Configure Time Range', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Time Range', visible: true, iconPathOn: 'settings', iconPathOff: 'settings', @@ -3391,17 +3514,17 @@ function newUiObjectConstructor () { break } case 'Time Period': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Time Period', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Time Period', + action: 'Configure Time Period', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Time Period', visible: true, iconPathOn: 'settings', iconPathOff: 'settings', @@ -3444,17 +3567,17 @@ function newUiObjectConstructor () { break } case 'Slippage': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Slippage', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Slippage', + action: 'Configure Slippage', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Slippage', visible: true, iconPathOn: 'settings', iconPathOff: 'settings', @@ -3497,17 +3620,17 @@ function newUiObjectConstructor () { break } case 'Fee Structure': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.configEditor = newConfigEditor() + uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.configEditor.initialize() + uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Edit Fee Structure', - actionFunction: uiObject.codeEditor.activate, - label: 'Edit Fee Structure', + action: 'Configure Fee Structure', + actionFunction: uiObject.configEditor.activate, + label: 'Configure Fee Structure', visible: true, iconPathOn: 'settings', iconPathOff: 'settings', @@ -3648,6 +3771,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Initial Definition', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'initialDefinition', actionFunction: payload.onMenuItemClick, label: 'Add Initial Definition', visible: true, @@ -3661,6 +3786,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Open Execution', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'openExecution', actionFunction: payload.onMenuItemClick, label: 'Add Open Execution', visible: true, @@ -3755,6 +3882,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Close Execution', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'closeExecution', actionFunction: payload.onMenuItemClick, label: 'Add Close Execution', visible: true, @@ -3802,6 +3931,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Formula', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'formula', actionFunction: payload.onMenuItemClick, label: 'Add Formula', visible: true, @@ -3849,6 +3980,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Formula', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'formula', actionFunction: payload.onMenuItemClick, label: 'Add Formula', visible: true, @@ -4246,6 +4379,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Formula', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'formula', actionFunction: payload.onMenuItemClick, label: 'Add Formula', visible: true, @@ -4259,6 +4394,8 @@ function newUiObjectConstructor () { menuItemsInitialValues.push( { action: 'Add Next Phase Event', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'nextPhaseEvent', actionFunction: payload.onMenuItemClick, label: 'Add Next Phase Event', visible: true, @@ -4302,16 +4439,16 @@ function newUiObjectConstructor () { break } case 'Formula': { - uiObject.codeEditor = newCodeEditor() - uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction - uiObject.codeEditor.initialize() - uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + uiObject.formulaEditor = newFormulaEditor() + uiObject.formulaEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.formulaEditor.initialize() + uiObject.formulaEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { action: 'Edit Formula', - actionFunction: uiObject.codeEditor.activate, + actionFunction: uiObject.formulaEditor.activate, label: 'Edit Formula', visible: true, iconPathOn: 'html', @@ -4450,18 +4587,40 @@ function newUiObjectConstructor () { break } case 'Condition': { + uiObject.conditionEditor = newConditionEditor() + uiObject.conditionEditor.isVisibleFunction = uiObject.isVisibleFunction + uiObject.conditionEditor.initialize() + uiObject.conditionEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false) + addLeftIcons(menuItemsInitialValues, floatingObject) menuItemsInitialValues.push( { - action: 'Add Code', - actionFunction: payload.onMenuItemClick, - label: 'Add Code', + action: 'Edit Condition', + actionFunction: uiObject.conditionEditor.activate, + label: 'Edit Condition', visible: true, - relatedUiObject: 'Code', + iconPathOn: 'html', + iconPathOff: 'html', rawRadius: 8, targetRadius: 0, currentRadius: 0, - angle: -40 + angle: -60, + dontShowAtFullscreen: true + } + ) + menuItemsInitialValues.push( + { + action: 'Add Code', + disableIfPropertyIsDefined: true, + propertyToCheckFor: 'code', + actionFunction: payload.onMenuItemClick, + label: 'Add Code', + visible: true, + relatedUiObject: 'Javascript Code', + rawRadius: 8, + targetRadius: 0, + currentRadius: 0, + angle: -20 } ) menuItemsInitialValues.push( @@ -4477,7 +4636,7 @@ function newUiObjectConstructor () { rawRadius: 8, targetRadius: 0, currentRadius: 0, - angle: 0 + angle: 20 } ) menuItemsInitialValues.push( @@ -4491,12 +4650,12 @@ function newUiObjectConstructor () { rawRadius: 8, targetRadius: 0, currentRadius: 0, - angle: 40 + angle: 60 } ) break } - case 'Code': { + case 'Javascript Code': { uiObject.codeEditor = newCodeEditor() uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction uiObject.codeEditor.initialize() @@ -4551,7 +4710,21 @@ function newUiObjectConstructor () { break } default: { - if (ERROR_LOG === true) { logger.write('[ERROR] getMenuItemsInitialValues -> UI Object Type not Recognized -> type = ' + payload.node.type) } + let nodeDefinition = APP_SCHEMA_MAP.get(payload.node.type) + if (nodeDefinition !== undefined) { + for (i = 0; i < nodeDefinition.menuItems.length; i++) { + let menutItemDefinition = nodeDefinition.menuItems[i] + let newMenuItem = JSON.parse(JSON.stringify(menutItemDefinition)) + + /* We need to reference the real function based on its name */ + if (menutItemDefinition.actionFunction !== undefined) { + newMenuItem.actionFunction = eval(menutItemDefinition.actionFunction) + } + menuItemsInitialValues.push(newMenuItem) + } + } else { + if (ERROR_LOG === true) { logger.write('[ERROR] getMenuItemsInitialValues -> UI Object Type not Recognized -> type = ' + payload.node.type) } + } } } @@ -4859,11 +5032,40 @@ function newUiObjectConstructor () { level_5() break } - case 'Code': { + case 'Javascript Code': { level_5() break } default: { + let nodeDefinition = APP_SCHEMA_MAP.get(payload.node.type) + if (nodeDefinition !== undefined) { + switch (nodeDefinition.level) { + case 0: { + level_0() + return + } + case 1: { + level_1() + return + } + case 2: { + level_2() + return + } + case 3: { + level_3() + return + } + case 4: { + level_4() + return + } + case 5: { + level_5() + return + } + } + } if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> UI Object Type not Recognized -> type = ' + payload.node.type) } return } diff --git a/Panels/PlotterPanel.js b/Panels/PlotterPanel.js new file mode 100644 index 000000000..493c41a05 --- /dev/null +++ b/Panels/PlotterPanel.js @@ -0,0 +1,122 @@ + +function newPlotterPanel () { + const MODULE_NAME = 'Plotter Panel' + const ERROR_LOG = true + const INTENSIVE_LOG = false + const logger = newWebDebugLog() + logger.fileName = MODULE_NAME + + let thisObject = { + fitFunction: undefined, + onRecordChange: onRecordChange, + container: undefined, + draw: draw, + getContainer: getContainer, + initialize: initialize + } + + let container = newContainer() + container.initialize() + thisObject.container = container + + container.frame.containerName = 'Plotter Panel' + + let currentRecord + let panelTabButton + let panelNode + + return thisObject + + function initialize (pPanelNode) { + panelNode = pPanelNode + container.frame.containerName = panelNode.name + + thisObject.container.frame.width = UI_PANEL.WIDTH.NORMAL + thisObject.container.frame.height = UI_PANEL.HEIGHT.NORMAL + + thisObject.container.frame.position.x = viewPort.visibleArea.topRight.x - thisObject.container.frame.width * 5 + thisObject.container.frame.position.y = viewPort.visibleArea.bottomLeft.y - thisObject.container.frame.height + + panelTabButton = newPanelTabButton() + panelTabButton.parentContainer = thisObject.container + panelTabButton.container.frame.parentFrame = thisObject.container.frame + panelTabButton.fitFunction = thisObject.fitFunction + panelTabButton.initialize() + } + + function getContainer (point) { + let container + + container = panelTabButton.getContainer(point) + if (container !== undefined) { return container } + + if (thisObject.container.frame.isThisPointHere(point, true) === true) { + let checkPoint = { + x: point.x, + y: point.y + } + + checkPoint = thisObject.fitFunction(checkPoint) + + if (point.x === checkPoint.x && point.y === checkPoint.y) { + return thisObject.container + } + } + } + + function onRecordChange (pCurrentRecord) { + currentRecord = pCurrentRecord + } + + function draw () { + thisObject.container.frame.draw(false, false, true, thisObject.fitFunction) + + plotCurrentRecordData() + + panelTabButton.draw() + } + + function plotCurrentRecordData () { + const frameBodyHeight = thisObject.container.frame.getBodyHeight() + const frameTitleHeight = thisObject.container.frame.height - frameBodyHeight + + const X_AXIS = thisObject.container.frame.width / 2 + const Y_AXIS = frameTitleHeight + frameBodyHeight / 2 + const PANEL_HEIGHT = frameTitleHeight + frameBodyHeight + + if (currentRecord === undefined) { return } + if (currentRecord.data === undefined) { return } + + try { + eval(panelNode.javascriptCode.code) + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] finalize -> err = ' + err.stack) } + } + + function printLabel (labelToPrint, x, y, opacity) { + let labelPoint + let fontSize = 10 + + browserCanvasContext.font = fontSize + 'px ' + UI_FONT.SECONDARY + + let label = '' + labelToPrint + + let xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO + + labelPoint = { + x: x - xOffset, + y: y + } + + labelPoint = thisObject.container.frame.frameThisPoint(labelPoint) + labelPoint = thisObject.fitFunction(labelPoint) + + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')' + browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y) + } + + browserCanvasContext.closePath() + browserCanvasContext.fill() + } +} + diff --git a/Panels/ProductCard.js b/Panels/ProductCard.js index 990f6a76e..49eba7250 100644 --- a/Panels/ProductCard.js +++ b/Panels/ProductCard.js @@ -152,10 +152,13 @@ function newProductCard () { let team = ecosystem.getTeam(thisObject.product.plotter.devTeam) let plotter = ecosystem.getPlotter(team, thisObject.product.plotter.codeName) - let plotterModule = ecosystem.getPlotterModule(plotter, thisObject.product.plotter.moduleName) - thisObject.product.plotter.profilePicture = plotterModule.profilePicture - thisObject.product.plotter.module = plotterModule + if (plotter !== undefined) { + let plotterModule = ecosystem.getPlotterModule(plotter, thisObject.product.plotter.moduleName) + + thisObject.product.plotter.profilePicture = plotterModule.profilePicture + thisObject.product.plotter.module = plotterModule + } /* Lets set the basic dimensions of this thisObject. */ diff --git a/Panels/ProductsPanel.js b/Panels/ProductsPanel.js index 32f500524..042560c73 100644 --- a/Panels/ProductsPanel.js +++ b/Panels/ProductsPanel.js @@ -66,6 +66,7 @@ function newProductsPanel () { ecosystem = getUserEcosystem() } + /* For legacy plotters, we will add product cards based on the old ecosystem file */ for (let i = 0; i < ecosystem.devTeams.length; i++) { let devTeam = ecosystem.devTeams[i] @@ -83,6 +84,116 @@ function newProductsPanel () { } } + /* For new plotters defined at the UI, we will add product cards based on what we find at the workspace */ + let workspaceNode = canvas.designerSpace.workspace.workspaceNode + for (let i = 0; i < workspaceNode.rootNodes.length; i++) { + let rootNode = workspaceNode.rootNodes[i] + if (rootNode.type === 'Team') { + let teamNode = rootNode + + let team = {} + if (teamNode.code === undefined) { continue } + try { + let code = JSON.parse(teamNode.code) + team.codeName = code.codeName + } catch (err) { + continue + } + for (let j = 0; j < teamNode.indicatorBots.length; j++) { + let botNode = teamNode.indicatorBots[j] + + let bot = {} + if (botNode.code === undefined) { continue } + try { + let code = JSON.parse(botNode.code) + bot.codeName = code.codeName + } catch (err) { + continue + } + + for (let k = 0; k < botNode.products.length; k++) { + let productNode = botNode.products[k] + + let product = {} + if (productNode.code === undefined) { continue } + try { + let code = JSON.parse(productNode.code) + product.codeName = code.codeName + } catch (err) { + continue + } + + if (productNode.payload.referenceParent === undefined) { continue } + let plotterModuleNode = productNode.payload.referenceParent + + let plotterModule = {} + if (plotterModuleNode.code === undefined) { continue } + try { + let code = JSON.parse(plotterModuleNode.code) + plotterModule.codeName = code.codeName + } catch (err) { + continue + } + + if (plotterModuleNode.payload.parentNode === undefined) { continue } + let plotterNode = plotterModuleNode.payload.parentNode + + let plotter = {} + if (plotterNode.code === undefined) { continue } + try { + let code = JSON.parse(plotterNode.code) + plotter.codeName = code.codeName + } catch (err) { + continue + } + + if (plotterNode.payload.parentNode === undefined) { continue } + let plotterTeamNode = plotterNode.payload.parentNode + + let plotterTeam = {} + if (plotterTeamNode.code === undefined) { continue } + try { + let code = JSON.parse(plotterTeamNode.code) + plotterTeam.codeName = code.codeName + } catch (err) { + continue + } + + if (plotterModuleNode.javascriptCode === undefined) { continue } + if (plotterModuleNode.javascriptCode.code === undefined) { continue } + + /* Conversion to fit old format */ + product.plotter = plotter + product.plotter.devTeam = plotterTeam.codeName + product.plotter.moduleName = plotterModule.codeName + product.plotter.legacy = false + product.plotter.module = { panels: [] } + product.displayName = productNode.name + product.dataSets = [] + product.exchangeList = [{'name': 'Poloniex'}] + product.node = productNode + team.displayName = teamNode.name + team.host = {'url': 'localhost'} + bot.displayName = botNode.name + + for (let m = 0; m < productNode.datasets.length; m++) { + let dataset = productNode.datasets[m] + + if (dataset.code === undefined) { continue } + try { + let code = JSON.parse(dataset.code) + product.dataSets.push(code) + } catch (err) { + continue + } + } + + addProductCard(team, bot, product) + } + } + } + } + thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel) isInitialized = true } @@ -313,27 +424,28 @@ function newProductsPanel () { if (process.session !== undefined) { if (process.session.layerManager !== undefined) { let layerManager = process.session.layerManager + if (layerManager.payload.floatingObject.isCollapsed !== true) { + if (bot.products !== undefined) { + for (let k = 0; k < bot.products.length; k++) { + let product = bot.products[k] - if (bot.products !== undefined) { - for (let k = 0; k < bot.products.length; k++) { - let product = bot.products[k] - - for (let p = 0; p < layerManager.layers.length; p++) { - let layer = layerManager.layers[p] - let layerCode - try { - layerCode = JSON.parse(layer.code) - } catch (err) { + for (let p = 0; p < layerManager.layers.length; p++) { + let layer = layerManager.layers[p] + let layerCode + try { + layerCode = JSON.parse(layer.code) + } catch (err) { // if we can not parse this, then we ignore this trading engine. - } + } - if (product.codeName === layerCode.product) { + if (product.codeName === layerCode.product) { /* We have a layer that is matching the current product */ - let cardCode = exchange + '-' + market.assetB + '/' + market.assetA + '-' + devTeam.codeName + '-' + bot.codeName + '-' + product.codeName + '-' + process.session.id - let cardFound = removeFromLocalProductCards(cardCode) - if (cardFound !== true) { - productCard = addProductCard(devTeam, bot, product, process.session) - onProductCardStatusChanged(productCard) + let cardCode = exchange + '-' + market.assetB + '/' + market.assetA + '-' + devTeam.codeName + '-' + bot.codeName + '-' + product.codeName + '-' + process.session.id + let cardFound = removeFromLocalProductCards(cardCode) + if (cardFound !== true) { + productCard = addProductCard(devTeam, bot, product, process.session) + onProductCardStatusChanged(productCard) + } } } } diff --git a/Plotter.js b/Plotter.js new file mode 100644 index 000000000..de33a8f26 --- /dev/null +++ b/Plotter.js @@ -0,0 +1,521 @@ +function newPlotter () { + const MODULE_NAME = 'Plotter' + const ERROR_LOG = true + const INTENSIVE_LOG = false + const logger = newWebDebugLog() + logger.fileName = MODULE_NAME + + let thisObject = { + + /* Events declared outside the plotter. */ + + onDailyFileLoaded: onDailyFileLoaded, + + // Main functions and properties. + + initialize: initialize, + finalize: finalize, + container: undefined, + getContainer: getContainer, + setTimePeriod: setTimePeriod, + setDatetime: setDatetime, + recalculateScale: recalculateScale, + draw: draw, + + // Secondary functions and properties. + + currentRecord: undefined // ---> Check Here + } + + let container = newContainer() + container.initialize() + thisObject.container = container + + let timeLineCoordinateSystem = newTimeLineCoordinateSystem() // Needed to be able to plot on the timeline, otherwise not. + + let timePeriod // This will hold the current Time Period the user is at. + let datetime // This will hold the current Datetime the user is at. + + let marketFile // This is the current Market File being plotted. + let fileCursor // This is the current File Cursor being used to retrieve Daily Files. + + let marketFiles // This object will provide the different Market Files at different Time Periods. + let dailyFiles // This object will provide the different File Cursors at different Time Periods. + + let productDefinition // Here we store a snapshot of the product definition which references this plotter. + + let records = [] // We will have the information to be plotted here. + + let zoomChangedEventSubscriptionId + let offsetChangedEventSubscriptionId + let dragFinishedEventSubscriptionId + let dimmensionsChangedEventSubscriptionId + let marketFilesUpdatedEventSubscriptionId + let dailyFilesUpdatedEventSubscriptionId + + return thisObject + + function finalize () { + try { + /* Stop listening to the necesary events. */ + viewPort.eventHandler.stopListening(zoomChangedEventSubscriptionId) + viewPort.eventHandler.stopListening(offsetChangedEventSubscriptionId) + canvas.eventHandler.stopListening(dragFinishedEventSubscriptionId) + thisObject.container.eventHandler.stopListening(dimmensionsChangedEventSubscriptionId) + marketFiles.eventHandler.stopListening(marketFilesUpdatedEventSubscriptionId) + dailyFiles.eventHandler.stopListening(dailyFilesUpdatedEventSubscriptionId) + + /* Clear References */ + marketFiles = undefined + dailyFiles = undefined + + datetime = undefined + timePeriod = undefined + + marketFile = undefined + fileCursor = undefined + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] finalize -> err = ' + err.stack) } + } + } + + function initialize (pStorage, pExchange, pMarket, pDatetime, pTimePeriod, callBackFunction, pProductDefinition) { + try { + /* Store the information received. */ + marketFiles = pStorage.marketFiles[0] + dailyFiles = pStorage.dailyFiles[0] + + datetime = pDatetime + timePeriod = pTimePeriod + + productDefinition = pProductDefinition + + /* We need a Market File in order to calculate the Y scale, since this scale depends on actual data. */ + marketFile = marketFiles.getFile(ONE_DAY_IN_MILISECONDS) // This file is the one processed faster. + + recalculateScale() + + /* Now we set the right files according to current Period. */ + marketFile = marketFiles.getFile(pTimePeriod) + fileCursor = dailyFiles.getFileCursor(pTimePeriod) + + /* Listen to the necesary events. */ + zoomChangedEventSubscriptionId = viewPort.eventHandler.listenToEvent('Zoom Changed', onZoomChanged) + offsetChangedEventSubscriptionId = viewPort.eventHandler.listenToEvent('Offset Changed', onOffsetChanged) + dragFinishedEventSubscriptionId = canvas.eventHandler.listenToEvent('Drag Finished', onDragFinished) + marketFilesUpdatedEventSubscriptionId = marketFiles.eventHandler.listenToEvent('Files Updated', onMarketFilesUpdated) + dailyFilesUpdatedEventSubscriptionId = dailyFiles.eventHandler.listenToEvent('Files Updated', onDailyFilesUpdated) + + /* Get ready for plotting. */ + recalculate() + dimmensionsChangedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('Dimmensions Changed', function () { + recalculateScale() + recalculate() + }) + + callBackFunction() + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> err = ' + err) } + callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) + } + } + + function onMarketFilesUpdated () { + try { + let newMarketFile = marketFiles.getFile(timePeriod) + if (newMarketFile !== undefined) { + marketFile = newMarketFile + recalculate() + } + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] onMarketFilesUpdated -> err = ' + err.stack) } + } + } + + function onDailyFilesUpdated () { + try { + let newFileCursor = dailyFiles.getFileCursor(timePeriod) + if (newFileCursor !== undefined) { + fileCursor = newFileCursor + recalculate() + } + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] onDailyFilesUpdated -> err = ' + err.stack) } + } + } + + function getContainer (point) { + try { + let container + /* First we check if this point is inside this space. */ + if (this.container.frame.isThisPointHere(point) === true) { + return this.container + } else { + /* This point does not belong to this space. */ + return undefined + } + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] getContainer -> err = ' + err) } + } + } + + function setTimePeriod (pTimePeriod) { + try { + if (timePeriod !== pTimePeriod) { + timePeriod = pTimePeriod + + if (timePeriod >= _1_HOUR_IN_MILISECONDS) { + let newMarketFile = marketFiles.getFile(pTimePeriod) + + if (newMarketFile !== undefined) { + marketFile = newMarketFile + recalculate() + } + } else { + let newFileCursor = dailyFiles.getFileCursor(pTimePeriod) + + if (newFileCursor !== undefined) { + fileCursor = newFileCursor + recalculate() + } + } + } + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] setTimePeriod -> err = ' + err) } + } + } + + function setDatetime (pDatetime) { + datetime = pDatetime + } + + function onDailyFileLoaded (event) { + try { + if (event.currentValue === event.totalValue) { + /* This happens only when all of the files in the cursor have been loaded. */ + recalculate() + } + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] onDailyFileLoaded -> err = ' + err) } + } + } + + function draw () { + try { + this.container.frame.draw() + plotChart() + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] draw -> err = ' + err) } + } + } + + function recalculate () { + try { + if (timePeriod >= _1_HOUR_IN_MILISECONDS) { + recalculateUsingMarketFiles() + } else { + recalculateUsingDailyFiles() + } + thisObject.container.eventHandler.raiseEvent('CandleStairs Changed', records) // --> Check This + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] recalculate -> err = ' + err) } + } + } + + function jsonifyDataFile (dataFile, recordDefinition, farLeftDate, farRightDate) { + /* + This function has as an input the raw data on files and creates with it an array of JSON objects + with not calculated properties for later being consumed by Formulas + */ + + let jsonifiedArray = [] + let previous + + for (let i = 0; i < dataFile.length; i++) { + let record = {} + for (let j = 0; j < recordDefinition.properties.length; j++) { + let property = recordDefinition.properties[j] + if (property.code.isCalculated !== true) { + record[property.code.codeName] = dataFile[i][j] + } + } + + if (record.begin >= farLeftDate.valueOf() && record.end <= farRightDate.valueOf()) { + record.previous = previous + jsonifiedArray.push(record) + previous = record + + if (datetime.valueOf() >= record.begin && datetime.valueOf() <= record.end) { + thisObject.currentRecord = record + thisObject.container.eventHandler.raiseEvent('Current Record Changed', thisObject.currentRecord) + } + } + } + + return jsonifiedArray + } + + function calculationsProcedure (jsonArray, recordDefinition, calculationsProcedure, timePeriod) { + /* + This function has as an input an array of JSON objects, and it adds calculated properties to + complete the set of properties that will be available. + */ + + let system = { // These are the available system variables to be used in User Code and Formulas + timePeriod: timePeriod, + ONE_DAY_IN_MILISECONDS: ONE_DAY_IN_MILISECONDS + } + let variable = {} // This is the structure where the user will define its own variables that will be shared across different code blocks and formulas. + let results = [] + + /* This is Initialization Code */ + if (calculationsProcedure.initialization !== undefined) { + if (calculationsProcedure.initialization.javascriptCode !== undefined) { + try { + eval(calculationsProcedure.initialization.javascriptCode.code) + } catch (err) { + logger.write('[ERROR] calculationsProcedure -> initialization -> Error executing User Code. Error = ' + err.stack) + logger.write('[ERROR] calculationsProcedure -> initialization -> Error executing User Code. Code = ' + calculationsProcedure.initialization.javascriptCode.code) + throw ('Error Executing User Code.') + } + } + } + + /* This is Initialization Code */ + if (calculationsProcedure.loop !== undefined) { + if (calculationsProcedure.loop.javascriptCode !== undefined) { + for (let index = 0; index < jsonArray.length; index++) { + let product = jsonArray[index] + + /* This is Loop Code */ + try { + eval(calculationsProcedure.loop.javascriptCode.code) + } catch (err) { + logger.write('[ERROR] calculationsProcedure -> loop -> Error executing User Code. Error = ' + err.stack) + logger.write('[ERROR] calculationsProcedure -> loop -> Error executing User Code. product = ' + JSON.stringify(product)) + logger.write('[ERROR] calculationsProcedure -> loop -> Error executing User Code. Code = ' + calculationsProcedure.loop.javascriptCode.code) + throw ('Error Executing User Code.') + } + + /* For each calculated property we apply its formula */ + for (let j = 0; j < recordDefinition.properties.length; j++) { + let property = recordDefinition.properties[j] + if (property.code.isCalculated === true) { + if (property.formula !== undefined) { + if (property.formula.code !== undefined) { + try { + let newValue = eval(property.formula.code) + let currentRecord = product + currentRecord[property.code.codeName] = newValue + } catch (err) { + logger.write('[ERROR] calculationsProcedure -> loop -> formula -> Error executing User Code. Error = ' + err.stack) + logger.write('[ERROR] calculationsProcedure -> loop -> formula -> Error executing User Code. product = ' + JSON.stringify(product)) + logger.write('[ERROR] calculationsProcedure -> loop -> formula -> Error executing User Code. Code = ' + property.formula.code) + throw ('Error Executing User Code.') + } + } + } + } + } + + /* Adding the new element to the resulting array */ + results.push(product) + } + } + } + return results + } + + function recalculateUsingDailyFiles () { + try { + if (fileCursor === undefined) { return } // We need to wait until there is a fileCursor + if (fileCursor.files.size === 0) { return } // We need to wait until there are files in the cursor + + let daysOnSides = getSideDays(timePeriod) + + let leftDate = getDateFromPoint(viewPort.visibleArea.topLeft, thisObject.container, timeLineCoordinateSystem) + let rightDate = getDateFromPoint(viewPort.visibleArea.topRight, thisObject.container, timeLineCoordinateSystem) + + let dateDiff = rightDate.valueOf() - leftDate.valueOf() + + let farLeftDate = new Date(leftDate.valueOf() - dateDiff * 1.5) + let farRightDate = new Date(rightDate.valueOf() + dateDiff * 1.5) + + let currentDate = new Date(farLeftDate.valueOf()) + + records = [] + + while (currentDate.valueOf() <= farRightDate.valueOf() + ONE_DAY_IN_MILISECONDS) { + let stringDate = currentDate.getFullYear() + '-' + pad(currentDate.getMonth() + 1, 2) + '-' + pad(currentDate.getDate(), 2) + + let dailyFile = fileCursor.files.get(stringDate) + + if (dailyFile !== undefined) { + /* Transform the current file content into an array of JSON objects */ + let jsonData = jsonifyDataFile(dailyFile, productDefinition.record, farLeftDate, farRightDate) + + /* Add the calculated properties */ + if (productDefinition.calculations !== undefined) { + let calculationsResult = calculationsProcedure(jsonData, productDefinition.record, productDefinition.calculations, timePeriod) + records.push(...calculationsResult) // This adds records to the current array. + } else { + records.push(...jsonData)// This adds records to the current array. + } + } + + currentDate = new Date(currentDate.valueOf() + ONE_DAY_IN_MILISECONDS) + } + + /* Lests check if all the visible screen is going to be covered by candle-record. */ + let lowerEnd = leftDate.valueOf() + let upperEnd = rightDate.valueOf() + + if (records.length > 0) { + if (records[0].begin > lowerEnd || records[records.length - 1].end < upperEnd) { + setTimeout(recalculate, 2000) + } + } + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] recalculateUsingDailyFiles -> err = ' + err) } + } + } + + function recalculateUsingMarketFiles () { + try { + if (marketFile === undefined) { return } // Initialization not complete yet. + + let daysOnSides = getSideDays(timePeriod) + + let leftDate = getDateFromPoint(viewPort.visibleArea.topLeft, thisObject.container, timeLineCoordinateSystem) + let rightDate = getDateFromPoint(viewPort.visibleArea.topRight, thisObject.container, timeLineCoordinateSystem) + + let dateDiff = rightDate.valueOf() - leftDate.valueOf() + + leftDate = new Date(leftDate.valueOf() - dateDiff * 1.5) + rightDate = new Date(rightDate.valueOf() + dateDiff * 1.5) + + records = [] + + /* Transform the current file content into an array of JSON objects */ + let jsonData = jsonifyDataFile(marketFile, productDefinition.record, leftDate, rightDate) + + /* Add the calculated properties */ + if (productDefinition.calculations !== undefined) { + let calculationsResult = calculationsProcedure(jsonData, productDefinition.record, productDefinition.calculations, timePeriod) + records.push(...calculationsResult) // This adds records to the current array. + } else { + records.push(...jsonData)// This adds records to the current array. + } + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] recalculateUsingMarketFiles -> err = ' + err) } + } + } + + function recalculateScale () { + try { + if (timeLineCoordinateSystem.maxValue > 0) { return } // Already calculated. + + let minValue = { + x: MIN_PLOTABLE_DATE.valueOf(), + y: 0 + } + + let maxValue = { + x: MAX_PLOTABLE_DATE.valueOf(), + y: nextPorwerOf10(USDT_BTC_HTH) / 4 // TODO: This 4 is temporary + } + + timeLineCoordinateSystem.initialize( + minValue, + maxValue, + thisObject.container.frame.width, + thisObject.container.frame.height + ) + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] recalculateScale -> err = ' + err) } + } + } + + function plotChart () { + try { + let userPosition = getUserPosition() + let userPositionDate = userPosition.point.x + + /* Clean the pannel at places where there is no record. */ + let currentRecord = { + data: undefined + } + thisObject.container.eventHandler.raiseEvent('Current Record Changed', currentRecord) + + for (let i = 0; i < records.length; i++) { + let record = records[i] + + let beginPoint = { + x: record.begin, + y: 0 + } + + let endPoint = { + x: record.end, + y: 0 + } + + beginPoint = timeLineCoordinateSystem.transformThisPoint(beginPoint) + endPoint = timeLineCoordinateSystem.transformThisPoint(endPoint) + + beginPoint = transformThisPoint(beginPoint, thisObject.container) + endPoint = transformThisPoint(endPoint, thisObject.container) + + if (endPoint.x < viewPort.visibleArea.bottomLeft.x || beginPoint.x > viewPort.visibleArea.bottomRight.x) { + continue + } + + let atMousePosition = false + if (userPositionDate >= record.begin && userPositionDate <= record.end) { + atMousePosition = true + + let currentRecord = { + data: record + } + thisObject.container.eventHandler.raiseEvent('Current Record Changed', currentRecord) + } + + eval(productDefinition.referenceParent.javascriptCode.code) + } + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] plotChart -> err = ' + err) } + } + } + + function onZoomChanged (event) { + try { + recalculate() + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] onZoomChanged -> err = ' + err) } + } + } + + function onDragFinished () { + try { + recalculate() + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] onDragFinished -> err = ' + err) } + } + } + + function onOffsetChanged (event) { + try { + if (event !== undefined) { + if (event.recalculate === true) { + recalculate() + return + } + } + if (Math.random() * 100 > 95) { + recalculate() + }; + } catch (err) { + if (ERROR_LOG === true) { logger.write('[ERROR] onOffsetChanged -> err = ' + err) } + } + } +} diff --git a/Scales/TimePeriodScale.js b/Scales/TimePeriodScale.js index 38ba997b4..93d2cb81b 100644 --- a/Scales/TimePeriodScale.js +++ b/Scales/TimePeriodScale.js @@ -14,13 +14,6 @@ function newTimePeriodScale () { const TIME_PERIOD_DEFAULT_VALUE = 0 const MIN_HEIGHT = 50 - thisObject.container = newContainer() - thisObject.container.initialize(MODULE_NAME) - - thisObject.container.isDraggeable = false - thisObject.container.isClickeable = false - thisObject.container.isWheelable = true - let mouse = { position: { x: 0, @@ -36,33 +29,57 @@ function newTimePeriodScale () { let timePeriodsMasterArray = [marketFilesPeriods, dailyFilePeriods] let timePeriodLabel = '' + let onMouseWheelEventSubscriptionId + let onMouseOverEventSubscriptionId + let onMouseNotOverEventSubscriptionId + let onZoomChangedEventSubscriptionId + + setupContainer() return thisObject + function setupContainer () { + thisObject.container = newContainer() + thisObject.container.initialize(MODULE_NAME) + + thisObject.container.isDraggeable = false + thisObject.container.isClickeable = false + thisObject.container.isWheelable = true + } + function finalize () { + thisObject.container.eventHandler.stopListening(onMouseWheelEventSubscriptionId) + thisObject.container.eventHandler.stopListening(onMouseOverEventSubscriptionId) + thisObject.container.eventHandler.stopListening(onMouseNotOverEventSubscriptionId) + thisObject.container.eventHandler.stopListening(onZoomChangedEventSubscriptionId) + + timeLineCoordinateSystem = undefined + objectStorage = undefined + thisObject.container.finalize() thisObject.container = undefined + setupContainer() } function initialize (pTimeLineCoordinateSystem) { timeLineCoordinateSystem = pTimeLineCoordinateSystem - thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel) + onMouseWheelEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel) readObjectState() newTimePeriod() - thisObject.container.eventHandler.listenToEvent('onMouseOver', function (event) { + onMouseOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', function (event) { mouse.position.x = event.x mouse.position.y = event.y visible = true }) - thisObject.container.eventHandler.listenToEvent('onMouseNotOver', function (event) { + onMouseWheelEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', function (event) { visible = false }) - viewPort.eventHandler.listenToEvent('Zoom Changed', onZoomChanged) + onZoomChangedEventSubscriptionId = viewPort.eventHandler.listenToEvent('Zoom Changed', onZoomChanged) } function onZoomChanged (event) { diff --git a/Spaces/ChartSpace.js b/Spaces/ChartSpace.js index 226ce4795..d7bb2c624 100644 --- a/Spaces/ChartSpace.js +++ b/Spaces/ChartSpace.js @@ -30,17 +30,21 @@ function newChartSpace () { finalize: finalize } - thisObject.container = newContainer() - thisObject.container.initialize(MODULE_NAME) - - thisObject.container.isDraggeable = false - thisObject.container.isWheelable = false - let canvasBrowserResizedEventSubscriptionId const PERCENTAGE_OF_SCREEN_FOR_DISPLACEMENT = 25 + + setupContainer() return thisObject + function setupContainer () { + thisObject.container = newContainer() + thisObject.container.initialize(MODULE_NAME) + + thisObject.container.isDraggeable = false + thisObject.container.isWheelable = false + } + function finalize () { for (let i = 0; i < thisObject.timeMachines.length; i++) { let timeMachine = thisObject.timeMachines[i] @@ -51,9 +55,10 @@ function newChartSpace () { thisObject.container.finalize() thisObject.container = undefined + setupContainer() } - function initialize (callBackFunction) { + function initialize () { let initializedCounter = 0 let toInitialize = 1 @@ -75,14 +80,14 @@ function newChartSpace () { initializedCounter++ if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { - callBackFunction(err) + if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> Initialization Failed. -> Err ' + err.message) } return } thisObject.timeMachines.push(timeMachine) if (initializedCounter === toInitialize) { - callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE) + viewPort.raiseEvents() // These events will impacts on objects just initialized. } } } diff --git a/Spaces/CockpitSpace.js b/Spaces/CockpitSpace.js index 453d5e779..39c2f2a0a 100644 --- a/Spaces/CockpitSpace.js +++ b/Spaces/CockpitSpace.js @@ -9,6 +9,9 @@ fullscreen: undefined, toTop: toTop, toBottom: toBottom, + toMiddle: toMiddle, + moveUp: moveUp, + moveDown: moveDown, draw: draw, physics: physics, getContainer: getContainer, @@ -87,6 +90,24 @@ thisObject.container.frame.position.y = browserCanvas.height - COCKPIT_SPACE_HEIGHT } + function toMiddle () { + thisObject.container.frame.position.y = browserCanvas.height / 2 - COCKPIT_SPACE_HEIGHT + } + + function moveUp () { + thisObject.container.frame.position.y = thisObject.container.frame.position.y - browserCanvas.height / 10 + if (thisObject.container.frame.position.y < 0) { + thisObject.container.frame.position.y = 0 + } + } + + function moveDown () { + thisObject.container.frame.position.y = thisObject.container.frame.position.y + browserCanvas.height / 10 + if (thisObject.container.frame.position.y > browserCanvas.height - COCKPIT_SPACE_HEIGHT) { + thisObject.container.frame.position.y = browserCanvas.height - COCKPIT_SPACE_HEIGHT + } + } + function physics () { thisObjectPhysics() childrenPhysics() diff --git a/Spaces/DesignerSpace.js b/Spaces/DesignerSpace.js index be4207f31..8cde058e0 100644 --- a/Spaces/DesignerSpace.js +++ b/Spaces/DesignerSpace.js @@ -3,7 +3,6 @@ function newDesignerSpace () { const MODULE_NAME = 'Strategy Space' let thisObject = { sidePanel: undefined, - strategizerGateway: undefined, container: undefined, iconCollection: undefined, iconByUiObjectType: undefined, @@ -27,12 +26,10 @@ function newDesignerSpace () { return thisObject - async function initialize () { + function initialize () { loadIconCollection() buildIconByUiObjectTypeMap() - thisObject.strategizerGateway = newStrategizerGateway() - thisObject.workspace = newWorkspace() thisObject.workspace.initialize() } @@ -89,7 +86,7 @@ function newDesignerSpace () { ['Next Phase Event', 'pantone'], ['Situation', 'pyramid'], ['Condition', 'testing'], - ['Code', 'html'], + ['Javascript Code', 'html'], ['Team', 'team'], ['Sensor Bot', 'bot-sensor'], ['Indicator Bot', 'bot-indicator'], @@ -121,6 +118,16 @@ function newDesignerSpace () { let icon = thisObject.iconCollection.get(record[1]) thisObject.iconByUiObjectType.set(record[0], icon) } + + /* Take types-icons relationships defined at the schema */ + for (let i = 0; i < APP_SCHEMA_ARRAY.length; i++) { + let nodeDefinition = APP_SCHEMA_ARRAY[i] + let iconName = nodeDefinition.icon + if (iconName !== undefined) { + let icon = thisObject.iconCollection.get(iconName) + thisObject.iconByUiObjectType.set(nodeDefinition.type, icon) + } + } } function loadIconCollection () { diff --git a/Spaces/FloatingSpace.js b/Spaces/FloatingSpace.js index da3c213d6..b5dbad099 100644 --- a/Spaces/FloatingSpace.js +++ b/Spaces/FloatingSpace.js @@ -20,6 +20,8 @@ function newFloatingSpace () { positionAtNode: positionAtNode, fitIntoVisibleArea: fitIntoVisibleArea, isThisPointVisible: isThisPointVisible, + isItFar: isItFar, + warmUp: warmUp, makeVisible: makeVisible, makeInvisible: makeInvisible, draw: draw, @@ -46,15 +48,27 @@ function newFloatingSpace () { thisObject.container.frame.position.y = browserCanvas.height / 2 - thisObject.container.frame.height / 2 let visible = false + let warmingUpCounter = 0 const PERCENTAGE_OF_SCREEN_FOR_DISPLACEMENT = 25 + let eventSubscriptionId + return thisObject function finalize () { + thisObject.container.eventHandler.stopListening(eventSubscriptionId) + thisObject.floatingLayer.finalize() thisObject.profileBalls.finalize() thisObject.uiObjectConstructor.finalize() thisObject.noteSets.finalize() + thisObject.container.finalize() + + thisObject.floatingLayer = undefined + thisObject.profileBalls = undefined + thisObject.uiObjectConstructor = undefined + thisObject.noteSets = undefined + thisObject.container = undefined } function initialize (callBackFunction) { @@ -70,7 +84,69 @@ function newFloatingSpace () { thisObject.uiObjectConstructor = newUiObjectConstructor() thisObject.uiObjectConstructor.initialize(thisObject.floatingLayer) - thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel) + eventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel) + } + + function warmUp () { + warmingUpCounter = 0 + } + + function isItFar (payload, dontCheckParent) { + /* If for any reason the paylaod is undefined we return false */ + if (payload === undefined) { return false } + + /* + We need a warm up in order to allow all objects to stabilize into a consistant state. + After that we will start evaluating which ones are too far from the current user view. + */ + + if (warmingUpCounter < 10000) { + warmingUpCounter++ + return false + } + + let radarFactor = 2 // How big is the margin + + /* If the chain parent is not far, they we dont consither this far. */ + if (dontCheckParent !== true) { + if (payload.chainParent !== undefined) { + if (isItFar(payload.chainParent.payload, true) === false) { return false } + } + } + + /* Exceptions that are never considered far. */ + if ( + payload.node.type === 'Definition' || + payload.node.type === 'Network' || + payload.node.type === 'Team' + ) { + return false + } + + /* Another exception are the ones who have reference parents */ + if (payload.referenceParent !== undefined) { return false } + + /* Here we will check the position of a floatingobject to see if it is outside the screen, with a margin of one screen around. */ + let point = thisObject.container.frame.frameThisPoint(payload.position) + + if (point.x > browserCanvas.width + browserCanvas.width * radarFactor) { + return true + } + + if (point.x < 0 - browserCanvas.width * radarFactor) { + return true + } + + let bottom = COCKPIT_SPACE_POSITION + COCKPIT_SPACE_HEIGHT + let heightDiff = browserCanvas.height - bottom + if (point.y < bottom - heightDiff * radarFactor) { + return true + } + + if (point.y > browserCanvas.height + heightDiff * radarFactor) { + return true + } + return false } function fitIntoVisibleArea (point) { diff --git a/Spaces/PanelsSpace.js b/Spaces/PanelsSpace.js index 34f3d6c13..b67add293 100644 --- a/Spaces/PanelsSpace.js +++ b/Spaces/PanelsSpace.js @@ -35,7 +35,7 @@ function newPanelsSpace () { } - function createNewPanel (pType, pParameters, pOwner, pSession) { + function createNewPanel (pType, pParameters, pOwner, pSession, pPanelCode) { let panel switch (pType) { @@ -56,11 +56,20 @@ function newPanelsSpace () { } case 'Plotter Panel': { - panel = getNewPlotterPanel(pParameters.devTeam, pParameters.plotterCodeName, pParameters.moduleCodeName, pParameters.panelCodeName) - panel.fitFunction = canvas.chartSpace.fitIntoVisibleArea - panel.container.isVisibleFunction = canvas.chartSpace.isThisPointVisible - panel.session = pSession - panel.initialize() + if (pPanelCode !== undefined) { + panel = newPlotterPanel() + panel.fitFunction = canvas.chartSpace.fitIntoVisibleArea + panel.container.isVisibleFunction = canvas.chartSpace.isThisPointVisible + panel.session = pSession + panel.initialize(pPanelCode) + } else { + panel = getNewPlotterPanel(pParameters.devTeam, pParameters.plotterCodeName, pParameters.moduleCodeName, pParameters.panelCodeName) + panel.fitFunction = canvas.chartSpace.fitIntoVisibleArea + panel.container.isVisibleFunction = canvas.chartSpace.isThisPointVisible + panel.session = pSession + panel.initialize() + } + break } } diff --git a/SplashScreen.js b/SplashScreen.js index 6cf8032d3..86e429b7d 100644 --- a/SplashScreen.js +++ b/SplashScreen.js @@ -57,13 +57,14 @@ function newSplashScreen () { function draw () { if (splashScreenNeeded === false) { stepsInitializationCounter = 100 + canDrawLogo = false fadeOutCounter++ - if (fadeOutCounter > 20) { + if (fadeOutCounter > 2) { return } - opacity = opacity - 0.1 + opacity = opacity - 1 } thisObject.container.frame.draw(false, false) @@ -100,7 +101,7 @@ function newSplashScreen () { /* Second the % of Advance. */ let label = '' + Math.trunc(stepsInitializationCounter) + ' %' - stepsInitializationCounter = stepsInitializationCounter + 2.0 + stepsInitializationCounter = stepsInitializationCounter + 5.0 if (stepsInitializationCounter > 99) { splashScreenNeeded = false