diff --git a/Client/httpInterface.js b/Client/httpInterface.js index aa2ce7cb1..6f593a58c 100644 --- a/Client/httpInterface.js +++ b/Client/httpInterface.js @@ -570,7 +570,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE function onDirRead(err, fileList) { if (err) { - if (CONSOLE_ERROR_LOG === true) { console.log('[WARN] Error reading a directory content. filePath = ' + dirPath) } + if (CONSOLE_ERROR_LOG === true) { console.log('[WARN] Could not read this directory content. filePath = ' + dirPath) } respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), httpResponse) return } else { diff --git a/Projects/Ethereum/Schemas/AppSchema.json b/Projects/Ethereum/Schemas/AppSchema.json index 1de8383bf..30e3ea6d2 100644 --- a/Projects/Ethereum/Schemas/AppSchema.json +++ b/Projects/Ethereum/Schemas/AppSchema.json @@ -41,7 +41,33 @@ "addLeftIcons": true, "isPinned": true, "positionLocked": true, - "icon": "ethereum" + "icon": "ethereum", + "properties": [ + { + "name": "projectDefinition", + "type": "node", + "childType": "Project Definition", + "autoAdd": true + }, + { + "name": "spaces", + "type": "node", + "childType": "Spaces", + "autoAdd": true + }, + { + "name": "mines", + "type": "node", + "childType": "Mines", + "autoAdd": true + }, + { + "name": "otherHierarchies", + "type": "node", + "childType": "Other Hierarchies", + "autoAdd": true + } + ] }, { "type": "Ethereum Wallet", diff --git a/Projects/Superalgos/Function-Libraries/NodeDeleter.js b/Projects/Superalgos/Function-Libraries/NodeDeleter.js index 8ef06340f..5800726b9 100644 --- a/Projects/Superalgos/Function-Libraries/NodeDeleter.js +++ b/Projects/Superalgos/Function-Libraries/NodeDeleter.js @@ -65,50 +65,52 @@ function newSuperalgosFunctionLibraryNodeDeleter() { } /* Remove node from parent */ - let removedFromParent = false - if (node.payload !== undefined) { - if (node.payload.parentNode !== undefined) { - let parentNodeDefinition = getNodeDefinition(node.payload.parentNode) - if (parentNodeDefinition !== undefined) { - if (parentNodeDefinition.properties !== undefined) { - for (let i = 0; i < parentNodeDefinition.properties.length; i++) { - let property = parentNodeDefinition.properties[i] - if (nodeDefinition.propertyNameAtParent === property.name) { - switch (property.type) { - case 'node': { - node.payload.parentNode[property.name] = undefined - removedFromParent = true - } - break - case 'array': { - let nodePropertyArray = node.payload.parentNode[property.name] - if (nodePropertyArray !== undefined) { - for (let j = 0; j < nodePropertyArray.length; j++) { - let arrayItem = nodePropertyArray[j] - if (arrayItem.id === node.id) { - /* If this object is chained to the ones of the same type we need to give the next in the chain the reference to the current chain parent */ - if (nodeDefinition.chainedToSameType === true) { - if (j < nodePropertyArray.length - 1) { - let nextArrayItem = nodePropertyArray[j + 1] - nextArrayItem.payload.chainParent = node.payload.chainParent + if (nodeDefinition.propertyNameAtParent !== undefined) { + let removedFromParent = false + if (node.payload !== undefined) { + if (node.payload.parentNode !== undefined) { + let parentNodeDefinition = getNodeDefinition(node.payload.parentNode) + if (parentNodeDefinition !== undefined) { + if (parentNodeDefinition.properties !== undefined) { + for (let i = 0; i < parentNodeDefinition.properties.length; i++) { + let property = parentNodeDefinition.properties[i] + if (nodeDefinition.propertyNameAtParent === property.name) { + switch (property.type) { + case 'node': { + node.payload.parentNode[property.name] = undefined + removedFromParent = true + } + break + case 'array': { + let nodePropertyArray = node.payload.parentNode[property.name] + if (nodePropertyArray !== undefined) { + for (let j = 0; j < nodePropertyArray.length; j++) { + let arrayItem = nodePropertyArray[j] + if (arrayItem.id === node.id) { + /* If this object is chained to the ones of the same type we need to give the next in the chain the reference to the current chain parent */ + if (nodeDefinition.chainedToSameType === true) { + if (j < nodePropertyArray.length - 1) { + let nextArrayItem = nodePropertyArray[j + 1] + nextArrayItem.payload.chainParent = node.payload.chainParent + } } + + nodePropertyArray.splice(j, 1) + removedFromParent = true } - - nodePropertyArray.splice(j, 1) - removedFromParent = true } } } + break } - break } } } } - } - if (removedFromParent === false) { - console.log('[ERROR] Deleting Node: ' + node.type + ' ' + node.name + '. This node could not be deleted from its parent node (' + node.payload.parentNode.type + ') because its configured propertyNameAtParent (' + nodeDefinition.propertyNameAtParent + ') does not match any of the properties of its parent.') - return false + if (removedFromParent === false) { + console.log('[ERROR] Deleting Node: ' + node.type + ' ' + node.name + '. This node could not be deleted from its parent node (' + node.payload.parentNode.type + ') because its configured propertyNameAtParent (' + nodeDefinition.propertyNameAtParent + ') does not match any of the properties of its parent.') + return false + } } } } diff --git a/Projects/Superalgos/Function-Libraries/UiObjectsFromNodes.js b/Projects/Superalgos/Function-Libraries/UiObjectsFromNodes.js index 4cac8ec50..8f65c8eca 100644 --- a/Projects/Superalgos/Function-Libraries/UiObjectsFromNodes.js +++ b/Projects/Superalgos/Function-Libraries/UiObjectsFromNodes.js @@ -364,24 +364,38 @@ function newSuperalgosFunctionLibraryUiObjectsFromNodes() { } } + let chainParent = parentNode if (nodeDefinition.isHierarchyHead === true || nodeDefinition.isProjectHead) { rootNodes.push(object) + initializeArrayProperties() + applyInitialValues() createUiObject(true, object.type, object.name, object, parentNode, undefined) + autoAddChildren() + return object + } else { + checkChainToSelfTypeCollection() + initializeArrayProperties() + applyInitialValues() + connectToParent() + createUiObject(true, object.type, object.name, object, parentNode, chainParent) + autoAddChildren() return object } - /* For the cases where an node is not chained to its parent but to the one at the parent before it at its collection */ - let chainParent = parentNode - if (nodeDefinition.chainedToSameType === true) { - if (parentNodeDefinition.properties !== undefined) { - for (let i = 0; i < parentNodeDefinition.properties.length; i++) { - let property = parentNodeDefinition.properties[i] - if (property.childType === type) { - if (property.type === 'array') { - if (parentNode[property.name] !== undefined) { - if (parentNode[property.name].length > 0) { - let nodeChildren = parentNode[property.name] - chainParent = nodeChildren[nodeChildren.length - 1] + function checkChainToSelfTypeCollection() { + /* For the cases where a node is not chained to its parent but to the one at the parent before it at its own collection */ + + if (nodeDefinition.chainedToSameType === true) { + if (parentNodeDefinition.properties !== undefined) { + for (let i = 0; i < parentNodeDefinition.properties.length; i++) { + let property = parentNodeDefinition.properties[i] + if (property.childType === type) { + if (property.type === 'array') { + if (parentNode[property.name] !== undefined) { + if (parentNode[property.name].length > 0) { + let nodeChildren = parentNode[property.name] + chainParent = nodeChildren[nodeChildren.length - 1] + } } } } @@ -390,51 +404,88 @@ function newSuperalgosFunctionLibraryUiObjectsFromNodes() { } } - /* Create Empty Arrays for properties of type Array */ - if (nodeDefinition.properties !== undefined) { - for (let i = 0; i < nodeDefinition.properties.length; i++) { - let property = nodeDefinition.properties[i] - if (property.type === 'array') { - object[property.name] = [] + function initializeArrayProperties() { + /* Create Empty Arrays for properties of type Array */ + if (nodeDefinition.properties !== undefined) { + for (let i = 0; i < nodeDefinition.properties.length; i++) { + let property = nodeDefinition.properties[i] + if (property.type === 'array') { + object[property.name] = [] + } } } } - if (nodeDefinition.initialValues !== undefined) { - if (nodeDefinition.initialValues.code !== undefined) { - object.code = nodeDefinition.initialValues.code - } - if (nodeDefinition.initialValues.config !== undefined) { - object.config = nodeDefinition.initialValues.config + function applyInitialValues() { + if (nodeDefinition.initialValues !== undefined) { + if (nodeDefinition.initialValues.code !== undefined) { + object.code = nodeDefinition.initialValues.code + } + if (nodeDefinition.initialValues.config !== undefined) { + object.config = nodeDefinition.initialValues.config + } } } - /* Connect to Parent */ - if (parentNodeDefinition.properties !== undefined) { - let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children. - for (let i = 0; i < parentNodeDefinition.properties.length; i++) { - let property = parentNodeDefinition.properties[i] - if (property.childType === type) { + function connectToParent() { + /* Connect to Parent */ + if (parentNodeDefinition.properties !== undefined) { + let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children. + for (let i = 0; i < parentNodeDefinition.properties.length; i++) { + let property = parentNodeDefinition.properties[i] + if (property.childType === type) { + switch (property.type) { + case 'node': { + if (property.name !== previousPropertyName) { + parentNode[property.name] = object + previousPropertyName = property.name + } + } + break + case 'array': { + if (parentNode[property.name] === undefined) { + parentNode[property.name] = [] + } + if (property.maxItems !== undefined) { + if (parentNode[property.name].length < property.maxItems) { + parentNode[property.name].push(object) + } else { + return // Object can not be created. + } + } else { + parentNode[property.name].push(object) + } + } + break + } + } + } + } + } + + function autoAddChildren() { + /* Auto Add more Children */ + if (nodeDefinition.properties !== undefined) { + let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children. + for (let i = 0; i < nodeDefinition.properties.length; i++) { + let property = nodeDefinition.properties[i] + switch (property.type) { case 'node': { if (property.name !== previousPropertyName) { - parentNode[property.name] = object - previousPropertyName = property.name + if (property.autoAdd === true) { + addUIObject(object, property.childType) + previousPropertyName = property.name + } } } break case 'array': { - if (parentNode[property.name] === undefined) { - parentNode[property.name] = [] - } - if (property.maxItems !== undefined) { - if (parentNode[property.name].length < property.maxItems) { - parentNode[property.name].push(object) - } else { - return // Object can not be created. + if (property.autoAdd === true) { + if (object[property.name] === undefined) { + object[property.name] = [] } - } else { - parentNode[property.name].push(object) + addUIObject(object, property.childType) } } break @@ -442,39 +493,6 @@ function newSuperalgosFunctionLibraryUiObjectsFromNodes() { } } } - - createUiObject(true, object.type, object.name, object, parentNode, chainParent) - - /* Auto Add more Children */ - if (nodeDefinition.properties !== undefined) { - let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children. - for (let i = 0; i < nodeDefinition.properties.length; i++) { - let property = nodeDefinition.properties[i] - - switch (property.type) { - case 'node': { - if (property.name !== previousPropertyName) { - if (property.autoAdd === true) { - addUIObject(object, property.childType) - previousPropertyName = property.name - } - } - } - break - case 'array': { - if (property.autoAdd === true) { - if (object[property.name] === undefined) { - object[property.name] = [] - } - addUIObject(object, property.childType) - } - } - break - } - } - } - - return object } function addMissingChildren(node, rootNodes) { diff --git a/Projects/Superalgos/Function-Libraries/WorkspaceFunctions.js b/Projects/Superalgos/Function-Libraries/WorkspaceFunctions.js index 7e8a431c5..79abefb09 100644 --- a/Projects/Superalgos/Function-Libraries/WorkspaceFunctions.js +++ b/Projects/Superalgos/Function-Libraries/WorkspaceFunctions.js @@ -25,6 +25,7 @@ function newSuperalgosFunctionLibraryWorkspaceFunctions() { if (alreadyExist === false) { let child = UI.projects.superalgos.functionLibraries.uiObjectsFromNodes.addUIObject(node, project + ' Project', rootNodes, project) child.project = project + child.projectDefinition.name = project } } } diff --git a/Projects/Superalgos/Schemas/AppSchema.json b/Projects/Superalgos/Schemas/AppSchema.json index 2d0c1f828..435e9d563 100644 --- a/Projects/Superalgos/Schemas/AppSchema.json +++ b/Projects/Superalgos/Schemas/AppSchema.json @@ -25,6 +25,12 @@ "positionLocked": true, "icon": "superalgos", "properties": [ + { + "name": "projectDefinition", + "type": "node", + "childType": "Project Definition", + "autoAdd": true + }, { "name": "spaces", "type": "node", @@ -45,6 +51,26 @@ } ] }, + { + "type": "Project Definition", + "menuItems": [ + { + "action": "Delete UI Object", + "askConfirmation": true, + "confirmationLabel": "Confirm to Delete", + "actionFunction": "payload.executeAction", + "label": "Delete", + "iconPathOn": "delete", + "iconPathOff": "delete" + } + ], + "alternativeIcons": "Use Parent", + "isTitleAllwaysVisible": false, + "addLeftIcons": true, + "isPinned": false, + "level": 2, + "propertyNameAtParent": "projectDefinition" + }, { "type": "Spaces", "menuItems": [ diff --git a/Projects/Superalgos/Spaces/Floating-Space/UiObject.js b/Projects/Superalgos/Spaces/Floating-Space/UiObject.js index 90c46454f..f1af4cd7b 100644 --- a/Projects/Superalgos/Spaces/Floating-Space/UiObject.js +++ b/Projects/Superalgos/Spaces/Floating-Space/UiObject.js @@ -1166,8 +1166,27 @@ function newUiObject() { function iconPhysics() { icon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndType(thisObject.payload.node.project, thisObject.payload.node.type) let nodeDefinition = getNodeDefinition(thisObject.payload.node) + + /* + If we want this object to have an alternative icon (defined on a list of possible icons) but + this definition does not belong to the current node but to a relative of it, then + the property to use is alternativeIcons with a value of a string defining the nodePath to the + node that actually has the icon list. + + On the other hand, if this icon has the icon list definition, then the value of alternativeIcons + shoudl be an array of the possible icons. Then to pick one icon from that list we will check + the config.condeName of the node to see with which icon on the list matches. + + Finally, if the node we are pointing to does not have a config or does not have a list of + alternativeIcons, we will just use that node's icon for the current node. + */ if (nodeDefinition.alternativeIcons !== undefined) { let nodeToUse = thisObject.payload.node + if (nodeDefinition.alternativeIcons === 'Use Parent') { + if (thisObject.payload.node.payload.parentNode !== undefined) { + nodeToUse = thisObject.payload.node.payload.parentNode + } + } if (nodeDefinition.alternativeIcons === 'Use Reference Parent') { if (thisObject.payload.node.payload.referenceParent !== undefined) { nodeToUse = thisObject.payload.node.payload.referenceParent @@ -1184,22 +1203,31 @@ function newUiObject() { } nodeDefinition = getNodeDefinition(nodeToUse) let config = nodeToUse.config - try { - config = JSON.parse(config) - let alternativeIcon - let iconName - for (let i = 0; i < nodeDefinition.alternativeIcons.length; i++) { - alternativeIcon = nodeDefinition.alternativeIcons[i] - if (alternativeIcon.codeName === config.codeName) { - iconName = alternativeIcon.iconName + if (config !== undefined && (Array.isArray(nodeDefinition.alternativeIcons) === true)) { + try { + config = JSON.parse(config) + let alternativeIcon + let iconName + for (let i = 0; i < nodeDefinition.alternativeIcons.length; i++) { + alternativeIcon = nodeDefinition.alternativeIcons[i] + if (alternativeIcon.codeName === config.codeName) { + iconName = alternativeIcon.iconName + } + } + let newIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName(nodeToUse.project, iconName) + if (newIcon !== undefined) { + icon = newIcon + } + } catch (err) { + nodeToUse.payload.uiObject.setErrorMessage('The config is not well formatted as a JSON object.') + } + } else { + if (nodeDefinition.icon !== undefined) { + let newIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName(nodeToUse.project, nodeDefinition.icon) + if (newIcon !== undefined) { + icon = newIcon } } - let newIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName('Superalgos', iconName) - if (newIcon !== undefined) { - icon = newIcon - } - } catch (err) { - // Nothing to do if JSON is baddly formated. } } @@ -1625,8 +1653,8 @@ function newUiObject() { } if (UI.projects.superalgos.spaces.floatingSpace.inMapMode === true) { - labelPoint.x = position.x - getTextWidth(label) / 2, - labelPoint.y = position.y + 50 / 2 + lineSeparator * 2 + labelPoint.x = position.x - getTextWidth(label) / 2, + labelPoint.y = position.y + 50 / 2 + lineSeparator * 2 } printMessage(label)