diff --git a/extensions/web-scripts/view-addon.lua b/extensions/web-scripts/view-addon.lua new file mode 100644 index 0000000..8e26887 --- /dev/null +++ b/extensions/web-scripts/view-addon.lua @@ -0,0 +1,5 @@ +local extension = ... + +local webBaseAddons = extension:require('web-base.addons', true) + +webBaseAddons.register(extension, 'init.js') diff --git a/extensions/web-scripts/view-init.js b/extensions/web-scripts/view-init.js deleted file mode 100644 index 4c779bb..0000000 --- a/extensions/web-scripts/view-init.js +++ /dev/null @@ -1,117 +0,0 @@ -define(['./config.json', './view.xml'], function(config, viewXml) { - - function getPropertyValue(things, properties, path) { - var parts = path.split('/', 2); - var thingId = parts[0]; - var propName = parts[1]; - var props = properties[thingId]; - if (props) { - var value = props[propName]; - if (value !== undefined) { - return value; - } - } - var thing = things[thingId]; - if (thing) { - var thgProp = thing.properties[propName]; - if (thgProp) { - var propType = thgProp['@type']; - switch (propType) { - case 'integer': - case 'number': - return 0; - case 'string': - return ''; - case 'boolean': - return false; - } - } - } - return undefined; - } - - var script = ''; - for(;;) { - // type="text/javascript" - var i = viewXml.indexOf('', i); - if (j < 0) { - break; - } - script += '\n' + viewXml.substring(i + 8, j); - viewXml = viewXml.substring(0, i) + viewXml.substring(j + 9); - } - - var options = { - template: [ - '', - viewXml, - '' - ].join('\n') - }; - - if (config.properties && config.properties.length > 0) { - assignMap(options, { - data: { - property: {} - }, - methods: { - onShow: function() { - this.onDataChange(); - }, - onDataChange: function() { - Promise.all([ - app.getThings(), - app.getPropertiesByThingId() - ]).then(apply(this, function(things, properties) { - var propertyMap = {}; - for (var i = 0; i < config.properties.length; i++) { - var cfgProp = config.properties[i]; - propertyMap[cfgProp.name] = getPropertyValue(things, properties, cfgProp.path); - } - this.property = propertyMap; - })); - }, - getPropertyByPath: function(path) { - return Promise.all([ - app.getThings(), - app.getPropertiesByThingId() - ]).then(apply(this, function(things, properties) { - return getPropertyValue(things, properties, path); - })); - }, - setPropertyByPath: function(path, value) { - var parts = path.split('/', 2); - var thingId = parts[0]; - var propName = parts[1]; - var valueByName = {}; - valueByName[propName] = value; - return fetch('/things/' + thingId + '/properties', { - method: 'PUT', - body: JSON.stringify(valueByName) - }).then(rejectIfNotOk); - }, - setProperty: function(name, value) { - for (var i = 0; i < config.properties.length; i++) { - var cfgProp = config.properties[i]; - if (cfgProp.name === name) { - return this.setPropertyByPath(cfgProp.path, value); - } - } - return Promise.reject('not found'); - } - } - }); - } - - if (script.length > 0) { - var fn = Function('options', 'config', '"use strict";' + script); - fn.call(this, options, config); - } - var vue = new Vue(options); - addPageComponent(vue, config.icon); - -}); \ No newline at end of file diff --git a/extensions/web-scripts/view-loader.js b/extensions/web-scripts/view-loader.js new file mode 100644 index 0000000..0d2faab --- /dev/null +++ b/extensions/web-scripts/view-loader.js @@ -0,0 +1,120 @@ +define(function() { + + function getPropertyValue(things, properties, path) { + var parts = path.split('/', 2); + var thingId = parts[0]; + var propName = parts[1]; + var props = properties[thingId]; + if (props) { + var value = props[propName]; + if (value !== undefined) { + return value; + } + } + var thing = things[thingId]; + if (thing) { + var thgProp = thing.properties[propName]; + if (thgProp) { + var propType = thgProp['@type']; + switch (propType) { + case 'integer': + case 'number': + return 0; + case 'string': + return ''; + case 'boolean': + return false; + } + } + } + return undefined; + } + + function load(config, viewXml) { + var script = ''; + for(;;) { + // type="text/javascript" + var i = viewXml.indexOf('', i); + if (j < 0) { + break; + } + script += '\n' + viewXml.substring(i + 8, j); + viewXml = viewXml.substring(0, i) + viewXml.substring(j + 9); + } + var options = { + template: [ + '', + viewXml, + '' + ].join('\n') + }; + if (config.properties && config.properties.length > 0) { + assignMap(options, { + data: { + property: {} + }, + methods: { + onShow: function() { + this.onDataChange(); + }, + onDataChange: function() { + Promise.all([ + app.getThings(), + app.getPropertiesByThingId() + ]).then(apply(this, function(things, properties) { + var propertyMap = {}; + for (var i = 0; i < config.properties.length; i++) { + var cfgProp = config.properties[i]; + propertyMap[cfgProp.name] = getPropertyValue(things, properties, cfgProp.path); + } + this.property = propertyMap; + })); + }, + getPropertyByPath: function(path) { + return Promise.all([ + app.getThings(), + app.getPropertiesByThingId() + ]).then(apply(this, function(things, properties) { + return getPropertyValue(things, properties, path); + })); + }, + setPropertyByPath: function(path, value) { + var parts = path.split('/', 2); + var thingId = parts[0]; + var propName = parts[1]; + var valueByName = {}; + valueByName[propName] = value; + return fetch('/things/' + thingId + '/properties', { + method: 'PUT', + body: JSON.stringify(valueByName) + }).then(rejectIfNotOk); + }, + setProperty: function(name, value) { + for (var i = 0; i < config.properties.length; i++) { + var cfgProp = config.properties[i]; + if (cfgProp.name === name) { + return this.setPropertyByPath(cfgProp.path, value); + } + } + return Promise.reject('not found'); + } + } + }); + } + if (script.length > 0) { + var fn = Function('options', 'config', '"use strict";' + script); + fn.call(this, options, config); + } + var vue = new Vue(options); + addPageComponent(vue, config.icon); + } + + return { + load: load + }; + +}); \ No newline at end of file diff --git a/extensions/web-scripts/view-script.lua b/extensions/web-scripts/view-script.lua deleted file mode 100644 index fb903c9..0000000 --- a/extensions/web-scripts/view-script.lua +++ /dev/null @@ -1,5 +0,0 @@ -local extension = ... -local loader = require('jls.lang.loader') -local coreExtPath = extension:getEngine().lhaExtensionsDir:getPath() -local webBaseAddons = loader.load('web-base.addons', coreExtPath) -webBaseAddons.register(extension, 'init.js') \ No newline at end of file diff --git a/extensions/web-scripts/web-scripts.js b/extensions/web-scripts/web-scripts.js index 7b839a2..3339eef 100644 --- a/extensions/web-scripts/web-scripts.js +++ b/extensions/web-scripts/web-scripts.js @@ -1,10 +1,10 @@ define(['./scripts.xml', './scripts-add.xml', './script-blockly.xml', './toolbox.xml', './blocks.json', './blocks-lua', - './script-view.xml', './script-view-config.xml', './view-schema.json', './view-init.js!', './view-script.lua', + './script-view.xml', './script-view-config.xml', './view-schema.json', './script-editor.xml'], function(scriptsTemplate, scriptsAddTemplate, scriptBlocklyTemplate, toolboxXml, blocks, blocksLua, - scriptViewTemplate, scriptViewConfigTemplate, scriptsViewConfigSchema, viewInitJs, viewScriptLua, + scriptViewTemplate, scriptViewConfigTemplate, scriptsViewConfigSchema, scriptEditorTemplate) { @@ -340,10 +340,7 @@ define(['./scripts.xml', './scripts-add.xml', if (!this.scriptId) { return; } - return Promise.all([ - fetch(scriptFilesPath + this.scriptId + '/view.xml', {method: 'PUT', body: this.text}).then(assertIsOk), - fetch(scriptFilesPath + this.scriptId + '/init.js', {method: 'PUT', body: viewInitJs}).then(assertIsOk) - ]).then(function() { + return fetch(scriptFilesPath + this.scriptId + '/view.xml', {method: 'PUT', body: this.text}).then(assertIsOk).then(function() { toaster.toast('Saved'); }); }, @@ -442,7 +439,7 @@ define(['./scripts.xml', './scripts-add.xml', }); }, newBlocks: function () { - fetch(scriptPath, {method: 'PUT', body: 'New Blocks'}).then(assertIsOk).then(getResponseText).then(function(scriptId) { + fetch(scriptPath, {method: 'PUT', headers: {'LHA-Name': 'New Blocks'}}).then(assertIsOk).then(getResponseText).then(function(scriptId) { return fetch(scriptFilesPath + scriptId + '/blocks.xml', { method: 'PUT', body: '' @@ -452,12 +449,23 @@ define(['./scripts.xml', './scripts-add.xml', }); }, newView: function () { - fetch(scriptPath, {method: 'PUT', body: 'New View'}).then(assertIsOk).then(getResponseText).then(function(scriptId) { + fetch(scriptPath, {method: 'PUT', headers: { + 'LHA-Name': 'New View', + 'LHA-Script': '//web-scripts/view-addon.lua' + }}).then(assertIsOk).then(getResponseText).then(function(scriptId) { return Promise.all([ fetch(scriptFilesPath + scriptId + '/view.xml', {method: 'PUT', body: ''}), - fetch(scriptFilesPath + scriptId + '/config.json', {method: 'PUT', body: '{"id": "view-' + scriptId + '", "title": "View ' + scriptId + '"}'}), - fetch(scriptFilesPath + scriptId + '/init.js', {method: 'PUT', body: viewInitJs}), - fetch(scriptFilesPath + scriptId + '/script.lua', {method: 'PUT', body: viewScriptLua}), + fetch(scriptFilesPath + scriptId + '/config.json', {method: 'PUT', body: [ + '{', + ' "id": "view-' + scriptId + '",', + ' "title": "View ' + scriptId + '"', + '}' + ].join('\n')}), + fetch(scriptFilesPath + scriptId + '/init.js', {method: 'PUT', body: [ + "define(['addon/web-scripts/view-loader.js', './config.json', './view.xml'], function(viewLoader, config, viewXml) {", + " viewLoader.load(config, viewXml);", + "});" + ].join('\n')}) ]); }).then(function() { app.replacePage('scripts'); diff --git a/extensions/web-scripts/web-scripts.lua b/extensions/web-scripts/web-scripts.lua index 2dafe42..e41c2c8 100644 --- a/extensions/web-scripts/web-scripts.lua +++ b/extensions/web-scripts/web-scripts.lua @@ -48,22 +48,20 @@ local REST_SCRIPTS = { end return list end, - ['(engine)?method=PUT'] = function(exchange, engine) - local name = exchange:getRequest():getBody() - if not name or name == '' then - name = 'New script' - end - local scriptName = 'script.lua' + ['(engine, name, script)?method=PUT&:LHA-Name+=name&:LHA-Script+=script'] = function(_, engine, name, script) local extId = engine:generateId() local extDir = File:new(engine:getScriptsDirectory(), extId) extDir:mkdir() - local scriptFile = File:new(extDir, scriptName) - scriptFile:write('local script = ...\n\n') + if not script then + script = 'script.lua' + local scriptFile = File:new(extDir, script) + scriptFile:write('local script = ...\n\n') + end local manifestFile = File:new(extDir, 'manifest.json') local manifest = { - name = name, + name = name or 'New script', version = '1.0', - script = scriptName + script = script } manifestFile:write(json.stringify(manifest, 2)) logger:fine('Created script "%s"', extId)