From d9d15e41c7dd3f5f7e744336fa36d1e030348010 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 16 Jul 2018 16:36:05 +0100 Subject: [PATCH] Support multiple stores in context sidebar --- editor/js/ui/tab-context.js | 83 ++++++++++++++++++------------ editor/sass/tab-context.scss | 11 +++- red/api/admin/context.js | 97 +++++++++++++++++++++++++++++------- 3 files changed, 140 insertions(+), 51 deletions(-) diff --git a/editor/js/ui/tab-context.js b/editor/js/ui/tab-context.js index aa02099b3..12fcfeb85 100644 --- a/editor/js/ui/tab-context.js +++ b/editor/js/ui/tab-context.js @@ -30,10 +30,10 @@ RED.sidebar.context = (function() { var currentFlow; function init() { + content = $("
").css({"position":"relative","height":"100%"}); content.className = "sidebar-context" // var toolbar = $('').appendTo(content); var footerToolbar = $('
'+ @@ -167,6 +167,7 @@ RED.sidebar.context = (function() { }) updateEntry(globalSection,"context/global","global"); + } function updateNode(node,force) { @@ -205,44 +206,64 @@ RED.sidebar.context = (function() { } function refreshEntry(section,baseUrl,id) { + + var contextStores = RED.settings.context.stores; var container = section.table; $.getJSON(baseUrl, function(data) { $(container).empty(); - var propRow; - - var keys = Object.keys(data); + var sortedData = {}; + for (var store in data) { + if (data.hasOwnProperty(store)) { + for (var key in data[store]) { + if (data[store].hasOwnProperty(key)) { + if (!sortedData.hasOwnProperty(key)) { + sortedData[key] = []; + } + data[store][key].store = store; + sortedData[key].push(data[store][key]) + } + } + } + } + var keys = Object.keys(sortedData); keys.sort(); var l = keys.length; for (var i = 0; i < l; i++) { - var k = keys[i]; - propRow = $('').appendTo(container); - var obj = $(propRow.children()[0]); - obj.text(k); - var tools = $('').appendTo(obj); - var refreshItem = $('').appendTo(tools).click(function(e) { - e.preventDefault(); - e.stopPropagation(); - $.getJSON(baseUrl+"/"+k, function(data) { - $(propRow.children()[1]).empty(); - var payload = data.msg; - var format = data.format; - payload = RED.utils.decodeObject(payload,format); - RED.utils.createObjectElement(payload, { - typeHint: data.format, - sourceId: id+"."+k - }).appendTo(propRow.children()[1]); - }) + sortedData[keys[i]].forEach(function(v) { + var k = keys[i]; + var l2 = sortedData[k].length; + var propRow = $('').appendTo(container); + var obj = $(propRow.children()[0]); + obj.text(k); + var tools = $('').appendTo(obj); + var refreshItem = $('').appendTo(tools).click(function(e) { + e.preventDefault(); + e.stopPropagation(); + $.getJSON(baseUrl+"/"+k+"?store="+v.store, function(data) { + $(propRow.children()[1]).empty(); + var payload = data.msg; + var format = data.format; + payload = RED.utils.decodeObject(payload,format); + RED.utils.createObjectElement(payload, { + typeHint: data.format, + sourceId: id+"."+k + }).appendTo(propRow.children()[1]); + }) + }); + + + var payload = v.msg; + var format = v.format; + payload = RED.utils.decodeObject(payload,format); + RED.utils.createObjectElement(payload, { + typeHint: v.format, + sourceId: id+"."+k + }).appendTo(propRow.children()[1]); + if (contextStores.length > 1) { + $("",{class:"sidebar-context-property-storename"}).text(v.store).appendTo($(propRow.children()[0])) + } }); - - - var payload = data[k].msg; - var format = data[k].format; - payload = RED.utils.decodeObject(payload,format); - RED.utils.createObjectElement(payload, { - typeHint: data[k].format, - sourceId: id+"."+k - }).appendTo(propRow.children()[1]); } if (l === 0) { $('').appendTo(container).i18n(); diff --git a/editor/sass/tab-context.scss b/editor/sass/tab-context.scss index 0c63a4794..16404c136 100644 --- a/editor/sass/tab-context.scss +++ b/editor/sass/tab-context.scss @@ -16,7 +16,7 @@ .sidebar-context-stack { position: absolute; - top: 0; // with toolbar: 43px; + top: 0; bottom: 0; left: 0; right: 0; @@ -32,7 +32,8 @@ .sidebar-context-property { position: relative; .debug-message-tools { - right: 3px; + right: 0px; + margin-right: 5px; display: none; } &:hover .debug-message-tools { @@ -45,3 +46,9 @@ color: #bbb; padding: 1px 3px; } +.sidebar-context-property-storename { + display: block; + font-size: 0.8em; + font-style: italic; + color: #aaa; +} diff --git a/red/api/admin/context.js b/red/api/admin/context.js index b99221dc4..2412085d1 100644 --- a/red/api/admin/context.js +++ b/red/api/admin/context.js @@ -17,18 +17,58 @@ var log; var redNodes; var util; +var settings; + +function exportContextStore(scope,ctx, store, result, callback) { + ctx.keys(store,function(err, keys) { + if (err) { + return callback(err); + } + result[store] = {}; + var c = keys.length; + if (c === 0) { + callback(null); + } else { + keys.forEach(function(key) { + ctx.get(key,store,function(err, v) { + if (err) { + return callback(err); + } + if (scope !== 'global' || + store === redNodes.listContextStores().default || + !settings.hasOwnProperty("functionGlobalContext") || + !settings.functionGlobalContext.hasOwnProperty(key) || + settings.functionGlobalContext[key] !== v) { + result[store][key] = util.encodeObject({msg:v}); + } + c--; + if (c === 0) { + callback(null); + } + }); + }); + } + }); +} module.exports = { init: function(runtime) { redNodes = runtime.nodes; log = runtime.log; util = runtime.util; + settings = runtime.settings; }, get: function(req,res) { var scope = req.params.scope; var id = req.params.id; var key = req.params[0]; + var availableStores = redNodes.listContextStores(); + //{ default: 'default', stores: [ 'default', 'file' ] } + var store = req.query['store']; + if (store && availableStores.stores.indexOf(store) === -1) { + return res.status(404).end(); + } var ctx; if (scope === 'global') { ctx = redNodes.getContext('global'); @@ -42,28 +82,49 @@ module.exports = { } if (ctx) { if (key) { - ctx.get(key,function(err, v) { - res.json(util.encodeObject({msg:v})); + store = store || availableStores.default; + ctx.get(key,store,function(err, v) { + var encoded = util.encodeObject({msg:v}); + if (store !== availableStores.default) { + encoded.store = store; + } + res.json(encoded); }); return; } else { - ctx.keys(function(err, keys) { - var result = {}; - var c = keys.length; - if (c === 0) { - res.json(result); - } else { - keys.forEach(function(key) { - ctx.get(key,function(err, v) { - result[key] = util.encodeObject({msg:v}); - c--; - if (c === 0) { - res.json(result); + var stores; + if (!store) { + stores = availableStores.stores; + } else { + stores = [store]; + } + + var result = {}; + var c = stores.length; + var errorReported = false; + stores.forEach(function(store) { + exportContextStore(scope,ctx,store,result,function(err) { + if (err) { + // TODO: proper error reporting + if (!errorReported) { + errorReported = true; + res.end(400); + } + return; + } + c--; + if (c === 0) { + if (!errorReported) { + if (stores.length > 1 && scope === 'global') { } - }); - }); - } - }); + res.json(result); + } + } + }); + }) + + + } } else { res.json({});