Merge pull request #1385 from Luis-Fernando-Molina/develop
Contribution: Install as Plugin action implemented for User Profiles and others
This commit is contained in:
13 files changed
+252
-31
No files matched your search
@@ -61,7 +61,7 @@
|
||||
"name": "pluginFilePosition",
|
||||
"type": "node",
|
||||
"childType": "Plugin File Position",
|
||||
"autoAdd": true
|
||||
"autoAdd": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -114,6 +114,11 @@ function newFoundationsActionSwitch() {
|
||||
UI.projects.foundations.functionLibraries.nodeDeleter.deleteUIObject(action.node, action.rootNodes)
|
||||
}
|
||||
break
|
||||
case 'Install as Plugin':
|
||||
{
|
||||
UI.projects.foundations.functionLibraries.pluginsFunctions.installAsPlugin(action.node, action.rootNodes)
|
||||
}
|
||||
break
|
||||
case 'Edit Code':
|
||||
|
||||
break
|
||||
|
||||
@@ -13,7 +13,8 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
|
||||
addMissingPluginApiMaps: addMissingPluginApiMaps,
|
||||
enableSavingWithWorkspace: enableSavingWithWorkspace,
|
||||
disableSavingWithWorkspace: disableSavingWithWorkspace,
|
||||
savePlugin: savePlugin
|
||||
savePlugin: savePlugin,
|
||||
installAsPlugin: installAsPlugin
|
||||
}
|
||||
return thisObject
|
||||
|
||||
@@ -60,7 +61,7 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Data-Mines', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'Data-Mines', 'Data Mine')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Data-Mines', 'Data Mine')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +77,7 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Trading-Mines', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'Trading-Mines', 'Trading Mine')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Trading-Mines', 'Trading Mine')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +93,7 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Trading-Systems', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'Trading-Systems', 'Trading System')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Trading-Systems', 'Trading System')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +109,7 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Trading-Engines', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'Trading-Engines', 'Trading Engine')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Trading-Engines', 'Trading Engine')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +125,7 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Learning-Mines', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'Learning-Mines', 'Learning Mine')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Learning-Mines', 'Learning Mine')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +141,7 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Learning-Systems', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'Learning-Systems', 'Learning System')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Learning-Systems', 'Learning System')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +157,7 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Learning-Engines', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'Learning-Engines', 'Learning Engine')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Learning-Engines', 'Learning Engine')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +173,7 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Tutorials', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'Tutorials', 'Tutorial')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Tutorials', 'Tutorial')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +189,7 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'API-Maps', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'API-Maps', 'API Map')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'API-Maps', 'API Map')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,4 +206,15 @@ function newFoundationsFunctionLibraryPluginsFunctions() {
|
||||
function savePlugin(node, rootNodes) {
|
||||
UI.projects.foundations.utilities.plugins.savePluginFile(node)
|
||||
}
|
||||
|
||||
function installAsPlugin(node, rootNodes) {
|
||||
let plugins = UI.projects.foundations.spaces.designSpace.workspace.getHierarchyHeadByNodeType('Plugins')
|
||||
let pluginProject = UI.projects.foundations.utilities.children.findChildByCodeName(plugins, node.project)
|
||||
let pluginFolderName = UI.projects.foundations.utilities.plugins.getPluginFolderNamesByNodeType(node.type)
|
||||
let pluginForlderNodeType = 'Plugin ' + pluginFolderName.replaceAll('-', ' ')
|
||||
let pluginFolderNode = UI.projects.foundations.utilities.children.findChildByType(pluginProject, pluginForlderNodeType)
|
||||
let pluginFile = UI.projects.foundations.utilities.plugins.addMissingPluginFile(pluginFolderNode, node.name, pluginFolderName, node.type, true)
|
||||
node.isPlugin = true
|
||||
UI.projects.foundations.utilities.plugins.savePluginFile(pluginFile)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
function newFoundationsUtilitiesNodeChildren() {
|
||||
let thisObject = {
|
||||
isMissingChildrenById: isMissingChildrenById,
|
||||
isMissingChildrenByType: isMissingChildrenByType,
|
||||
isMissingChildrenByType: isMissingChildrenByType,
|
||||
findChildReferencingThisNode: findChildReferencingThisNode,
|
||||
findChildByType: findChildByType,
|
||||
findChildByCodeName: findChildByCodeName,
|
||||
findOrCreateChildWithReference: findOrCreateChildWithReference,
|
||||
findAndRecreateChildWithReference: findAndRecreateChildWithReference,
|
||||
findChildIndexAtParentNode: findChildIndexAtParentNode,
|
||||
@@ -73,7 +75,7 @@ function newFoundationsUtilitiesNodeChildren() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function isMissingChildrenByName(startingNode, nodeName) {
|
||||
/*
|
||||
This functioin scan all the children of a node and returns true or false
|
||||
@@ -211,6 +213,106 @@ function newFoundationsUtilitiesNodeChildren() {
|
||||
}
|
||||
}
|
||||
|
||||
function findChildByType(startingNode, nodeType) {
|
||||
/*
|
||||
This functioin scan all the children of a node and returns the child
|
||||
that has a type as specified via parameter.
|
||||
*/
|
||||
if (startingNode === undefined) { return }
|
||||
if (nodeType === undefined) { return }
|
||||
|
||||
let schemaDocument = getSchemaDocument(startingNode)
|
||||
if (schemaDocument === undefined) { return }
|
||||
|
||||
/* We scan through this node children */
|
||||
if (schemaDocument.childrenNodesProperties !== undefined) {
|
||||
for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) {
|
||||
let property = schemaDocument.childrenNodesProperties[i]
|
||||
|
||||
switch (property.type) {
|
||||
case 'node': {
|
||||
let child = startingNode[property.name]
|
||||
if (child === undefined) { continue }
|
||||
if (child.payload !== undefined) {
|
||||
if (child.type === nodeType) {
|
||||
return child
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'array': {
|
||||
let startingNodePropertyArray = startingNode[property.name]
|
||||
if (startingNodePropertyArray !== undefined) {
|
||||
for (let m = 0; m < startingNodePropertyArray.length; m++) {
|
||||
let arrayItem = startingNodePropertyArray[m]
|
||||
|
||||
if (arrayItem.payload !== undefined) {
|
||||
if (arrayItem.type === nodeType) {
|
||||
return arrayItem
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function findChildByCodeName(startingNode, checkCodeName) {
|
||||
/*
|
||||
This functioin scan all the children of a node and returns the child
|
||||
that has a codeName as specified via parameter.
|
||||
*/
|
||||
if (startingNode === undefined) { return }
|
||||
if (checkCodeName === undefined) { return }
|
||||
|
||||
let schemaDocument = getSchemaDocument(startingNode)
|
||||
if (schemaDocument === undefined) { return }
|
||||
|
||||
/* We scan through this node children */
|
||||
if (schemaDocument.childrenNodesProperties !== undefined) {
|
||||
for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) {
|
||||
let property = schemaDocument.childrenNodesProperties[i]
|
||||
|
||||
switch (property.type) {
|
||||
case 'node': {
|
||||
let child = startingNode[property.name]
|
||||
if (child === undefined) { continue }
|
||||
if (child.payload !== undefined) {
|
||||
let codeName = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(child.payload, 'codeName')
|
||||
if (codeName !== undefined) {
|
||||
if (codeName === checkCodeName) {
|
||||
return child
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'array': {
|
||||
let startingNodePropertyArray = startingNode[property.name]
|
||||
if (startingNodePropertyArray !== undefined) {
|
||||
for (let m = 0; m < startingNodePropertyArray.length; m++) {
|
||||
let arrayItem = startingNodePropertyArray[m]
|
||||
|
||||
if (arrayItem.payload !== undefined) {
|
||||
let codeName = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(arrayItem.payload, 'codeName')
|
||||
if (codeName !== undefined) {
|
||||
if (codeName === checkCodeName) {
|
||||
return arrayItem
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function findOrCreateChildWithReference(startingNode, childType, referencedNode) {
|
||||
/*
|
||||
This function find the child node of starting node that references
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
function newFoundationsUtilitiesPlugins() {
|
||||
let thisObject = {
|
||||
getPluginFileNames: getPluginFileNames,
|
||||
addPluginFileIfNeeded: addPluginFileIfNeeded,
|
||||
getPluginFolderNamesByNodeType: getPluginFolderNamesByNodeType,
|
||||
addMissingPluginFiles: addMissingPluginFiles,
|
||||
addMissingPluginFile: addMissingPluginFile,
|
||||
getProjectName: getProjectName,
|
||||
savePluginFile: savePluginFile
|
||||
}
|
||||
@@ -22,19 +24,69 @@ function newFoundationsUtilitiesPlugins() {
|
||||
}
|
||||
}
|
||||
|
||||
function addPluginFileIfNeeded(node, fileNames, pluginFolder, nodeType) {
|
||||
function addMissingPluginFiles(node, fileNames, pluginFolder, nodeType) {
|
||||
for (let i = 0; i < fileNames.length; i++) {
|
||||
let fileName = fileNames[i]
|
||||
fileName = fileName.replace('.json', '')
|
||||
if (UI.projects.foundations.utilities.children.isMissingChildrenByName(node, fileName) === true) {
|
||||
let child = UI.projects.foundations.functionLibraries.uiObjectsFromNodes.addUIObject(node, 'Plugin File', undefined, 'Foundations')
|
||||
child.name = fileName
|
||||
child.config = JSON.stringify({
|
||||
project: node.project,
|
||||
fileName: fileName,
|
||||
folderName: pluginFolder,
|
||||
nodeType: nodeType
|
||||
})
|
||||
addMissingPluginFile(node, fileName, pluginFolder, nodeType, false)
|
||||
}
|
||||
}
|
||||
|
||||
function addMissingPluginFile(node, fileName, pluginFolder, nodeType, saveWithWorkspace) {
|
||||
if (UI.projects.foundations.utilities.children.isMissingChildrenByName(node, fileName) === true) {
|
||||
let child = UI.projects.foundations.functionLibraries.uiObjectsFromNodes.addUIObject(node, 'Plugin File', undefined, 'Foundations')
|
||||
child.name = fileName
|
||||
child.config = JSON.stringify({
|
||||
project: node.project,
|
||||
fileName: fileName,
|
||||
folderName: pluginFolder,
|
||||
nodeType: nodeType,
|
||||
saveWithWorkspace: saveWithWorkspace
|
||||
})
|
||||
return child
|
||||
}
|
||||
}
|
||||
|
||||
function getPluginFolderNamesByNodeType(nodeType) {
|
||||
switch (nodeType) {
|
||||
case 'API Map': {
|
||||
return 'API-Maps'
|
||||
}
|
||||
case 'Data Mine': {
|
||||
return 'Data-Mines'
|
||||
}
|
||||
case 'Learning Engine': {
|
||||
return 'Learning-Engines'
|
||||
}
|
||||
case 'Learning Mine': {
|
||||
return 'Learning-Mines'
|
||||
}
|
||||
case 'Learning System': {
|
||||
return 'Learning-Systems'
|
||||
}
|
||||
case 'Trading Engine': {
|
||||
return 'Trading-Engines'
|
||||
}
|
||||
case 'Trading Mine': {
|
||||
return 'Trading-Mines'
|
||||
}
|
||||
case 'Trading System': {
|
||||
return 'Trading-Systems'
|
||||
}
|
||||
case 'Assets': {
|
||||
return 'Assets'
|
||||
}
|
||||
case 'Features': {
|
||||
return 'Features'
|
||||
}
|
||||
case 'Pools': {
|
||||
return 'Pools'
|
||||
}
|
||||
case 'Positions': {
|
||||
return 'Positions'
|
||||
}
|
||||
case 'User Profile': {
|
||||
return 'User-Profiles'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1345,7 +1345,7 @@
|
||||
"floatingObject": {
|
||||
"isPinned": false,
|
||||
"isFrozen": false,
|
||||
"isCollapsed": false,
|
||||
"isCollapsed": true,
|
||||
"angleToParent": 1,
|
||||
"distanceToParent": 3,
|
||||
"arrangementStyle": 0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "Positions",
|
||||
"name": "Superalgos-Marketing",
|
||||
"config": "{\"codeName\":\"Superalgos\"}",
|
||||
"config": "{\"codeName\":\"Superalgos-Marketing\"}",
|
||||
"project": "Governance",
|
||||
"positionClasss": [
|
||||
{
|
||||
|
||||
@@ -32,6 +32,16 @@
|
||||
"label": "Add Asset",
|
||||
"relatedUiObject": "Asset"
|
||||
},
|
||||
{
|
||||
"action": "Install as Plugin",
|
||||
"actionProject": "Foundations",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Install",
|
||||
"label": "Install as Plugin",
|
||||
"iconPathOn": "configuration",
|
||||
"iconPathOff": "configuration",
|
||||
"actionFunction": "payload.executeAction"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"actionProject": "Foundations",
|
||||
|
||||
@@ -15,6 +15,16 @@
|
||||
"label": "Add Feature",
|
||||
"relatedUiObject": "Feature"
|
||||
},
|
||||
{
|
||||
"action": "Install as Plugin",
|
||||
"actionProject": "Foundations",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Install",
|
||||
"label": "Install as Plugin",
|
||||
"iconPathOn": "configuration",
|
||||
"iconPathOff": "configuration",
|
||||
"actionFunction": "payload.executeAction"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"actionProject": "Foundations",
|
||||
|
||||
@@ -22,6 +22,16 @@
|
||||
"label": "Add Pool",
|
||||
"relatedUiObject": "Pool"
|
||||
},
|
||||
{
|
||||
"action": "Install as Plugin",
|
||||
"actionProject": "Foundations",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Install",
|
||||
"label": "Install as Plugin",
|
||||
"iconPathOn": "configuration",
|
||||
"iconPathOff": "configuration",
|
||||
"actionFunction": "payload.executeAction"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"actionProject": "Foundations",
|
||||
|
||||
@@ -15,6 +15,16 @@
|
||||
"relatedUiObject": "Position",
|
||||
"actionFunction": "payload.executeAction"
|
||||
},
|
||||
{
|
||||
"action": "Install as Plugin",
|
||||
"actionProject": "Foundations",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Install",
|
||||
"label": "Install as Plugin",
|
||||
"iconPathOn": "configuration",
|
||||
"iconPathOff": "configuration",
|
||||
"actionFunction": "payload.executeAction"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"actionProject": "Foundations",
|
||||
|
||||
@@ -26,6 +26,16 @@
|
||||
"label": "Add Tokens Mined",
|
||||
"relatedUiObject": "Tokens Mined"
|
||||
},
|
||||
{
|
||||
"action": "Install as Plugin",
|
||||
"actionProject": "Foundations",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Install",
|
||||
"label": "Install as Plugin",
|
||||
"iconPathOn": "configuration",
|
||||
"iconPathOff": "configuration",
|
||||
"actionFunction": "payload.executeAction"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"actionProject": "Foundations",
|
||||
|
||||
@@ -20,7 +20,7 @@ function newGovernanceFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'User-Profiles', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'User-Profiles', 'User Profile')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'User-Profiles', 'User Profile')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ function newGovernanceFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Pools', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'Pools', 'Pools')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Pools', 'Pools')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ function newGovernanceFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Assets', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'Assets', 'Assets')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Assets', 'Assets')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ function newGovernanceFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Features', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'Features', 'Features')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Features', 'Features')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ function newGovernanceFunctionLibraryPluginsFunctions() {
|
||||
UI.projects.foundations.utilities.plugins.getPluginFileNames(projectName, 'Positions', onNamesArrived)
|
||||
|
||||
function onNamesArrived(fileNames) {
|
||||
UI.projects.foundations.utilities.plugins.addPluginFileIfNeeded(node, fileNames, 'Positions', 'Positions')
|
||||
UI.projects.foundations.utilities.plugins.addMissingPluginFiles(node, fileNames, 'Positions', 'Positions')
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user