diff --git a/packages/node_modules/@node-red/editor-api/lib/admin/context.js b/packages/node_modules/@node-red/editor-api/lib/admin/context.js
index 09b1aa53b..6a2efd82d 100644
--- a/packages/node_modules/@node-red/editor-api/lib/admin/context.js
+++ b/packages/node_modules/@node-red/editor-api/lib/admin/context.js
@@ -37,5 +37,20 @@ module.exports = {
}).catch(function(err) {
apiUtils.rejectHandler(req,res,err);
})
+ },
+
+ delete: function(req,res) {
+ var opts = {
+ user: req.user,
+ scope: req.params.scope,
+ id: req.params.id,
+ key: req.params[0],
+ store: req.query['store']
+ }
+ runtimeAPI.context.delete(opts).then(function(result) {
+ res.status(204).end();
+ }).catch(function(err) {
+ apiUtils.rejectHandler(req,res,err);
+ })
}
}
diff --git a/packages/node_modules/@node-red/editor-api/lib/admin/index.js b/packages/node_modules/@node-red/editor-api/lib/admin/index.js
index 1f77b70b4..32bf010c5 100644
--- a/packages/node_modules/@node-red/editor-api/lib/admin/index.js
+++ b/packages/node_modules/@node-red/editor-api/lib/admin/index.js
@@ -62,6 +62,11 @@ module.exports = {
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);
+ // adminApp.delete("/context/:scope(global)",needsPermission("context.write"),context.delete,apiUtil.errorHandler);
+ adminApp.delete("/context/:scope(global)/*",needsPermission("context.write"),context.delete,apiUtil.errorHandler);
+ // adminApp.delete("/context/:scope(node|flow)/:id",needsPermission("context.write"),context.delete,apiUtil.errorHandler);
+ adminApp.delete("/context/:scope(node|flow)/:id/*",needsPermission("context.write"),context.delete,apiUtil.errorHandler);
+
return adminApp;
}
}
diff --git a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
index 23df7550d..7a7661b1f 100644
--- a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
@@ -515,7 +515,8 @@
"empty": "empty",
"node": "Node",
"flow": "Flow",
- "global": "Global"
+ "global": "Global",
+ "deleteConfirm": "Are you sure you want to delete this item?"
},
"palette": {
"name": "Palette management",
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
index 065fcd7f9..5b5057666 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
@@ -131,6 +131,7 @@ RED.popover = (function() {
}
}
var closePopup = function(instant) {
+ $(document).off('mousedown.modal-popover-close');
if (!active) {
if (div) {
if (instant) {
@@ -171,6 +172,17 @@ RED.popover = (function() {
openPopup();
}
});
+ } else if (trigger === 'modal') {
+ $(document).on('mousedown.modal-popover-close', function (event) {
+ var target = event.target;
+ while (target.nodeName !== 'BODY' && target !== div[0]) {
+ target = target.parentElement;
+ }
+ if (target.nodeName === 'BODY') {
+ active = false;
+ closePopup();
+ }
+ });
} else if (autoClose) {
setTimeout(function() {
active = false;
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js
index 65758fbb6..b62ad13c3 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js
@@ -237,29 +237,83 @@ RED.sidebar.context = (function() {
var propRow = $('
|
').appendTo(container);
var obj = $(propRow.children()[0]);
obj.text(k);
- var tools = $('').appendTo(obj);
+ var tools = $('');
+
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]);
+ if (data.msg !== payload || data.format !== format) {
+ payload = data.msg;
+ format = data.format;
+ tools.detach();
+ $(propRow.children()[1]).empty();
+ RED.utils.createObjectElement(RED.utils.decodeObject(payload,format), {
+ typeHint: data.format,
+ sourceId: id+"."+k,
+ tools: tools
+ }).appendTo(propRow.children()[1]);
+ }
})
});
+ var deleteItem = $('').appendTo(tools).click(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ var popover = RED.popover.create({
+ trigger: 'modal',
+ target: propRow,
+ direction: "left",
+ content: function() {
+ var content = $('');
+ $('
').appendTo(content);
+ var row = $('
').appendTo(content);
+ var bg = $('').appendTo(row);
+ $('').appendTo(bg).click(function(e) {
+ e.preventDefault();
+ popover.close();
+ });
+ bg = $('').appendTo(row);
+ $('').appendTo(bg).click(function(e) {
+ e.preventDefault();
+ popover.close();
+ $.ajax({
+ url: baseUrl+"/"+k+"?store="+v.store,
+ type: "DELETE"
+ }).done(function(data,textStatus,xhr) {
+ $.getJSON(baseUrl+"/"+k+"?store="+v.store, function(data) {
+ if (data.format === 'undefined') {
+ propRow.remove();
+ if (container.children().length === 0) {
+ $('
| |
').appendTo(container).i18n();
+ }
+ } else {
+ payload = data.msg;
+ format = data.format;
+ tools.detach();
+ $(propRow.children()[1]).empty();
+ RED.utils.createObjectElement(RED.utils.decodeObject(payload,format), {
+ typeHint: data.format,
+ sourceId: id+"."+k,
+ tools: tools
+ }).appendTo(propRow.children()[1]);
+ }
+ });
+ }).fail(function(xhr,textStatus,err) {
+ })
+ });
+ return content.i18n();
+ }
+ });
+ popover.open();
+ });
var payload = v.msg;
var format = v.format;
- payload = RED.utils.decodeObject(payload,format);
- RED.utils.createObjectElement(payload, {
+ RED.utils.createObjectElement(RED.utils.decodeObject(payload,format), {
typeHint: v.format,
- sourceId: id+"."+k
+ sourceId: id+"."+k,
+ tools: tools
}).appendTo(propRow.children()[1]);
if (contextStores.length > 1) {
$("
",{class:"sidebar-context-property-storename"}).text(v.store).appendTo($(propRow.children()[0]))
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
index 77faf60ab..43d3cced3 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
@@ -113,7 +113,7 @@ RED.utils = (function() {
var pinnedPaths = {};
var formattedPaths = {};
- function addMessageControls(obj,sourceId,key,msg,rootPath,strippedKey) {
+ function addMessageControls(obj,sourceId,key,msg,rootPath,strippedKey,extraTools) {
if (!pinnedPaths.hasOwnProperty(sourceId)) {
pinnedPaths[sourceId] = {}
}
@@ -150,6 +150,10 @@ RED.utils = (function() {
}).toggleClass("selected",isPinned);
obj.toggleClass("debug-message-row-pinned",isPinned);
}
+ if (extraTools) {
+ extraTools.addClass("debug-message-tools-other");
+ extraTools.appendTo(tools);
+ }
}
function checkExpanded(strippedKey,expandPaths,minRange,maxRange) {
if (expandPaths && expandPaths.length > 0) {
@@ -243,6 +247,7 @@ RED.utils = (function() {
var expandPaths = options.expandPaths;
var ontoggle = options.ontoggle;
var exposeApi = options.exposeApi;
+ var tools = options.tools;
var subElements = {};
var i;
@@ -262,7 +267,7 @@ RED.utils = (function() {
}
header = $('').appendTo(element);
if (sourceId) {
- addMessageControls(header,sourceId,path,obj,rootPath,strippedKey);
+ addMessageControls(header,sourceId,path,obj,rootPath,strippedKey,tools);
}
if (!key) {
element.addClass("debug-message-top-level");
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/debug.scss b/packages/node_modules/@node-red/editor-client/src/sass/debug.scss
index a3acd18ff..456ef2559 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/debug.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/debug.scss
@@ -81,6 +81,9 @@
.debug-message-tools-pin {
display: inline-block;
}
+ .debug-message-tools-other {
+ display: inline-block;
+ }
}
}
}
@@ -134,6 +137,9 @@
.debug-message-tools-copy {
display: none;
}
+ .debug-message-tools-other {
+ display: none;
+ }
}
.debug-message-payload {
display: block;
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/popover.scss b/packages/node_modules/@node-red/editor-client/src/sass/popover.scss
index bfc182ec4..55b88452f 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/popover.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/popover.scss
@@ -146,3 +146,16 @@
border-radius:3px;
padding: 1px 2px;
}
+
+.red-ui-popover .editor-button {
+ &:not(.primary) {
+ color: #444 !important;
+ border-color: rgba(0,0,0,0);
+ }
+ &.primary {
+ border-color: #bbb;
+ }
+ &.primary:hover {
+ border-color: #666 !important;
+ }
+}
diff --git a/packages/node_modules/@node-red/runtime/lib/api/context.js b/packages/node_modules/@node-red/runtime/lib/api/context.js
index 1ef875356..64eddda93 100644
--- a/packages/node_modules/@node-red/runtime/lib/api/context.js
+++ b/packages/node_modules/@node-red/runtime/lib/api/context.js
@@ -20,7 +20,6 @@
var runtime;
-// TODO: move runtime/util to util/index
var util = require("@node-red/util").util;
function exportContextStore(scope,ctx, store, result, callback) {
@@ -152,5 +151,104 @@ var api = module.exports = {
resolve({});
}
})
+ },
+
+ /**
+ * Gets the info of an individual node set
+ * @param {Object} opts
+ * @param {User} opts.user - the user calling the api
+ * @param {String} opts.scope - the scope of the context
+ * @param {String} opts.id - the id of the context
+ * @param {String} opts.store - the context store
+ * @param {String} opts.key - the context key
+
+ * @return {Promise} - the node information
+ * @memberof RED.nodes
+ */
+ delete: function(opts) {
+ return new Promise(function(resolve,reject) {
+ var scope = opts.scope;
+ var id = opts.id;
+ var store = opts.store;
+ var key = opts.key;
+
+ var availableStores = runtime.nodes.listContextStores();
+ //{ default: 'default', stores: [ 'default', 'file' ] }
+ if (store && availableStores.stores.indexOf(store) === -1) {
+ runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"});
+ var err = new Error();
+ err.code = "not_found";
+ err.status = 404;
+ return reject(err);
+ }
+ var ctx;
+ if (scope === 'global') {
+ ctx = runtime.nodes.getContext('global');
+ } else if (scope === 'flow') {
+ ctx = runtime.nodes.getContext(id);
+ } else if (scope === 'node') {
+ var node = runtime.nodes.getNode(id);
+ if (node) {
+ ctx = node.context();
+ }
+ }
+ if (ctx) {
+ if (key) {
+ store = store || availableStores.default;
+ ctx.set(key,undefined,store,function(err) {
+ runtime.log.audit({event: "context.delete",scope:scope,id:id,store:store,key:key});
+ resolve();
+ });
+ return;
+ } else {
+ // TODO: support deleting whole context
+ runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"});
+ var err = new Error();
+ err.code = "not_found";
+ err.status = 404;
+ return reject(err);
+ // 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;
+ // runtime.log.audit({event: "context.delete",scope:scope,id:id,store:store,key:key,error:"unexpected_error"});
+ // var err = new Error();
+ // err.code = "unexpected_error";
+ // err.status = 400;
+ // return reject(err);
+ // }
+ //
+ // return;
+ // }
+ // c--;
+ // if (c === 0) {
+ // if (!errorReported) {
+ // runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key});
+ // resolve(result);
+ // }
+ // }
+ // });
+ // })
+ }
+ } else {
+ runtime.log.audit({event: "context.delete",scope:scope,id:id,store:store,key:key});
+ resolve();
+ }
+
+
+ });
}
+
}