diff --git a/editor/js/ui/tab-context.js b/editor/js/ui/tab-context.js
index 48176d624..863dacc76 100644
--- a/editor/js/ui/tab-context.js
+++ b/editor/js/ui/tab-context.js
@@ -14,11 +14,110 @@
* limitations under the License.
**/
RED.sidebar.context = (function() {
+
var content;
+ var sections;
+
+ var localCache = {};
+
+
+ var nodeSection;
+ // var subflowSection;
+ var flowSection;
+ var globalSection;
+
+ var currentNode;
+ var currentFlow;
function init() {
- content = document.createElement("div");
- content.className = "sidebar-node-info"
+ content = $("
").css({"position":"relative","height":"100%"});
+ content.className = "sidebar-context"
+ // var toolbar = $('').appendTo(content);
+
+ var footerToolbar = $('
'+
+ // ' ' +
+ '
');
+
+
+
+ var stackContainer = $("
",{class:"sidebar-context-stack"}).appendTo(content);
+ sections = RED.stack.create({
+ container: stackContainer
+ });
+
+ nodeSection = sections.add({
+ title: "Node",
+ collapsible: true,
+ // onexpand: function() {
+ // updateNode(currentNode,true);
+ // }
+ });
+ nodeSection.expand();
+ nodeSection.content.css({height:"100%"});
+ var table = $('
').appendTo(nodeSection.content);
+ nodeSection.table = $('
').appendTo(table);
+ var bg = $('').appendTo(nodeSection.header);
+ $('')
+ .appendTo(bg)
+ .click(function(evt) {
+ evt.stopPropagation();
+ evt.preventDefault();
+ updateNode(currentNode, true);
+ })
+
+ // subflowSection = sections.add({
+ // title: "Subflow",
+ // collapsible: true
+ // });
+ // subflowSection.expand();
+ // subflowSection.content.css({height:"100%"});
+ // bg = $('').appendTo(subflowSection.header);
+ // $('')
+ // .appendTo(bg)
+ // .click(function(evt) {
+ // evt.stopPropagation();
+ // evt.preventDefault();
+ // })
+ //
+ // subflowSection.container.hide();
+
+ flowSection = sections.add({
+ title: "Flow",
+ collapsible: true
+ });
+ flowSection.expand();
+ flowSection.content.css({height:"100%"});
+ var table = $('').appendTo(flowSection.content);
+ flowSection.table = $('').appendTo(table);
+ bg = $('').appendTo(flowSection.header);
+ $('')
+ .appendTo(bg)
+ .click(function(evt) {
+ evt.stopPropagation();
+ evt.preventDefault();
+ updateFlow(currentFlow);
+ })
+
+ globalSection = sections.add({
+ title: "Global",
+ collapsible: true
+ });
+ globalSection.expand();
+ globalSection.content.css({height:"100%"});
+ var table = $('').appendTo(globalSection.content);
+ globalSection.table = $('').appendTo(table);
+
+ bg = $('').appendTo(globalSection.header);
+ $('')
+ .appendTo(bg)
+ .click(function(evt) {
+ evt.stopPropagation();
+ evt.preventDefault();
+ updateEntry(globalSection,"context/global","global");
+ })
+
RED.actions.add("core:show-context-tab",show);
@@ -28,10 +127,137 @@ RED.sidebar.context = (function() {
name: RED._("sidebar.context.name"),
iconClass: "fa fa-database",
content: content,
- pinned: false,
+ toolbar: footerToolbar,
+ // pinned: true,
enableOnEdit: false
});
+
+ // var toggleLiveButton = $("#sidebar-context-toggle-live");
+ // toggleLiveButton.click(function(evt) {
+ // evt.preventDefault();
+ // if ($(this).hasClass("selected")) {
+ // $(this).removeClass("selected");
+ // $(this).find("i").removeClass("fa-pause");
+ // $(this).find("i").addClass("fa-play");
+ // } else {
+ // $(this).addClass("selected");
+ // $(this).find("i").removeClass("fa-play");
+ // $(this).find("i").addClass("fa-pause");
+ // }
+ // });
+ // RED.popover.tooltip(toggleLiveButton, function() {
+ // if (toggleLiveButton.hasClass("selected")) {
+ // return "Pause live updates"
+ // } else {
+ // return "Start live updates"
+ // }
+ // });
+
+
+ RED.events.on("view:selection-changed", function(event) {
+ var selectedNode = event.nodes && event.nodes.length === 1 && event.nodes[0];
+ updateNode(selectedNode);
+ })
+
+ RED.events.on("workspace:change", function(event) {
+ updateFlow(RED.nodes.workspace(event.workspace));
+ })
+
+ updateEntry(globalSection,"context/global","global");
}
+
+ function updateNode(node,force) {
+ currentNode = node;
+ if (force) {
+ if (node) {
+ updateEntry(nodeSection,"context/node/"+node.id,node.id);
+ // if (/^subflow:/.test(node.type)) {
+ // subflowSection.container.show();
+ // updateEntry(subflowSection,"context/flow/"+node.id,node.id);
+ // } else {
+ // subflowSection.container.hide();
+ // }
+ } else {
+ // subflowSection.container.hide();
+ updateEntry(nodeSection)
+ }
+ } else {
+ $(nodeSection.table).empty();
+ if (node) {
+ $('refresh to load |
').appendTo(nodeSection.table);
+
+ } else {
+ $('none selected |
').appendTo(nodeSection.table);
+ }
+
+ }
+ }
+ function updateFlow(flow) {
+ currentFlow = flow;
+ if (flow) {
+ updateEntry(flowSection,"context/flow/"+flow.id,flow.id);
+ } else {
+ updateEntry(flowSection)
+ }
+ }
+
+ function refreshEntry(section,baseUrl,id) {
+ var container = section.table;
+
+ $.getJSON(baseUrl, function(data) {
+ $(container).empty();
+ var propRow;
+
+ var keys = Object.keys(data);
+ 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]);
+ })
+ });
+
+
+ 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) {
+ $('empty |
').appendTo(container);
+ }
+ });
+ }
+ function updateEntry(section,baseUrl,id) {
+ var container = section.table;
+ if (id) {
+ refreshEntry(section,baseUrl,id);
+ } else {
+ $(container).empty();
+ $('none selected |
').appendTo(container);
+ }
+ }
+
+
+
function show() {
RED.sidebar.show("context");
}
diff --git a/editor/sass/style.scss b/editor/sass/style.scss
index 5d536c742..b160959c8 100644
--- a/editor/sass/style.scss
+++ b/editor/sass/style.scss
@@ -40,6 +40,7 @@
@import "panels";
@import "tabs";
@import "tab-config";
+@import "tab-context";
@import "tab-info";
@import "popover";
@import "flow";
diff --git a/editor/sass/tab-context.scss b/editor/sass/tab-context.scss
new file mode 100644
index 000000000..917b0dc48
--- /dev/null
+++ b/editor/sass/tab-context.scss
@@ -0,0 +1,41 @@
+/**
+ * Copyright JS Foundation and other contributors, http://js.foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+.sidebar-context-stack {
+ position: absolute;
+ top: 0; // with toolbar: 43px;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ overflow-y: scroll;
+
+ .palette-category {
+ &:not(.palette-category-expanded) button {
+ display: none;
+ }
+ }
+}
+
+.sidebar-context-property {
+ position: relative;
+ .debug-message-tools {
+ right: 3px;
+ display: none;
+ }
+ &:hover .debug-message-tools {
+ display: inline-block;
+ }
+}
diff --git a/red/api/admin/context.js b/red/api/admin/context.js
new file mode 100644
index 000000000..37c6462cb
--- /dev/null
+++ b/red/api/admin/context.js
@@ -0,0 +1,61 @@
+/**
+ * Copyright JS Foundation and other contributors, http://js.foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+var log;
+var redNodes;
+var util;
+
+module.exports = {
+ init: function(runtime) {
+ redNodes = runtime.nodes;
+ log = runtime.log;
+ util = runtime.util;
+ },
+
+ get: function(req,res) {
+ var scope = req.params.scope;
+ var id = req.params.id;
+ var key = req.params[0];
+ var result = {};
+ var ctx;
+ if (scope === 'global') {
+ ctx = redNodes.getContext('global');
+ } else if (scope === 'flow') {
+ ctx = redNodes.getContext(id);
+ } else if (scope === 'node') {
+ var node = redNodes.getNode(id);
+ if (node) {
+ ctx = node.context();
+ }
+ }
+ if (ctx) {
+ if (key) {
+ result = util.encodeObject({msg:ctx.get(key)});
+ } else {
+ var keys = ctx.keys();
+
+ var i = 0;
+ var l = keys.length;
+ while(i < l) {
+ var k = keys[i];
+ result[k] = util.encodeObject({msg:ctx.get(k)});
+ i++;
+ }
+ }
+ }
+ res.json(result);
+ }
+}
diff --git a/red/api/admin/index.js b/red/api/admin/index.js
index 57c79eb62..15e56aecf 100644
--- a/red/api/admin/index.js
+++ b/red/api/admin/index.js
@@ -19,6 +19,7 @@ var express = require("express");
var nodes = require("./nodes");
var flows = require("./flows");
var flow = require("./flow");
+var context = require("./context");
var auth = require("../auth");
var apiUtil = require("../util");
@@ -28,6 +29,7 @@ module.exports = {
flows.init(runtime);
flow.init(runtime);
nodes.init(runtime);
+ context.init(runtime);
var needsPermission = auth.needsPermission;
@@ -52,6 +54,12 @@ module.exports = {
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.read"),nodes.getSet,apiUtil.errorHandler);
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.write"),nodes.putSet,apiUtil.errorHandler);
+ // Context
+ adminApp.get("/context/:scope(global)",needsPermission("context.read"),context.get,apiUtil.errorHandler);
+ adminApp.get("/context/:scope(global)/*",needsPermission("context.read"),context.get,apiUtil.errorHandler);
+ adminApp.get("/context/:scope(node|flow)/:id",needsPermission("context.read"),context.get,apiUtil.errorHandler);
+ adminApp.get("/context/:scope(node|flow)/:id/*",needsPermission("context.read"),context.get,apiUtil.errorHandler);
+
return adminApp;
}
}
diff --git a/red/runtime/nodes/context.js b/red/runtime/nodes/context.js
index e71a1eaed..2d6e7ba32 100644
--- a/red/runtime/nodes/context.js
+++ b/red/runtime/nodes/context.js
@@ -84,6 +84,7 @@ function clean(flowConfig) {
module.exports = {
init: function(settings) {
globalContext = createContext("global",settings.functionGlobalContext || {});
+ contexts['global'] = globalContext;
},
get: getContext,
delete: deleteContext,
diff --git a/red/runtime/nodes/index.js b/red/runtime/nodes/index.js
index b2f8ff3b5..be84130ef 100644
--- a/red/runtime/nodes/index.js
+++ b/red/runtime/nodes/index.js
@@ -167,6 +167,8 @@ module.exports = {
createNode: createNode,
getNode: flows.get,
eachNode: flows.eachNode,
+ getContext: context.get,
+
paletteEditorEnabled: registry.paletteEditorEnabled,
installModule: installModule,