mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge branch 'dev' into mqtt-reconnect-fix
This commit is contained in:
commit
8948ca5323
13
CHANGELOG.md
13
CHANGELOG.md
@ -18,6 +18,19 @@ Nodes
|
|||||||
- TCP: Add TLS option to tcp client nodes (#3307) @dceejay
|
- TCP: Add TLS option to tcp client nodes (#3307) @dceejay
|
||||||
- WebSocket: Implemented support for Websocket Subprotocols in WS Client Node. (#3333) @tobiasoort
|
- WebSocket: Implemented support for Websocket Subprotocols in WS Client Node. (#3333) @tobiasoort
|
||||||
|
|
||||||
|
#### 2.1.6: Maintenance Release
|
||||||
|
|
||||||
|
Editor
|
||||||
|
|
||||||
|
- Revert copy-text change and apply alternative fix (#3363) @knolleary
|
||||||
|
- Update marked to latest (#3362) @knolleary
|
||||||
|
- fix to make start of property error tooltip messages aligned (#3358) @HiroyasuNishiyama
|
||||||
|
|
||||||
|
Nodes
|
||||||
|
|
||||||
|
- Inject: fix JSON propety validation of inject node (#3349) @HiroyasuNishiyama
|
||||||
|
- Delay: fix unit value validation of delay node (#3351) @HiroyasuNishiyama
|
||||||
|
|
||||||
#### 2.1.5: Maintenance Release
|
#### 2.1.5: Maintenance Release
|
||||||
|
|
||||||
Runtime
|
Runtime
|
||||||
|
@ -107,7 +107,7 @@
|
|||||||
"i18next-http-backend": "1.3.1",
|
"i18next-http-backend": "1.3.1",
|
||||||
"jquery-i18next": "1.2.1",
|
"jquery-i18next": "1.2.1",
|
||||||
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
||||||
"marked": "3.0.7",
|
"marked": "4.0.10",
|
||||||
"minami": "1.2.3",
|
"minami": "1.2.3",
|
||||||
"mocha": "9.1.3",
|
"mocha": "9.1.3",
|
||||||
"node-red-node-test-helper": "^0.2.7",
|
"node-red-node-test-helper": "^0.2.7",
|
||||||
|
@ -75,6 +75,8 @@
|
|||||||
"view": {
|
"view": {
|
||||||
"view": "View",
|
"view": "View",
|
||||||
"grid": "Grid",
|
"grid": "Grid",
|
||||||
|
"storeZoom": "Restore zoom level on load",
|
||||||
|
"storePosition": "Restore scroll position on load",
|
||||||
"showGrid": "Show grid",
|
"showGrid": "Show grid",
|
||||||
"snapGrid": "Snap to grid",
|
"snapGrid": "Snap to grid",
|
||||||
"gridSize": "Grid size",
|
"gridSize": "Grid size",
|
||||||
|
@ -556,8 +556,7 @@ var RED = (function() {
|
|||||||
|
|
||||||
$(".red-ui-header-toolbar").show();
|
$(".red-ui-header-toolbar").show();
|
||||||
|
|
||||||
|
RED.sidebar.show(":first", true);
|
||||||
RED.sidebar.show(":first");
|
|
||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
loader.end();
|
loader.end();
|
||||||
|
@ -946,8 +946,10 @@ RED.clipboard = (function() {
|
|||||||
if (truncated) {
|
if (truncated) {
|
||||||
msg += "_truncated";
|
msg += "_truncated";
|
||||||
}
|
}
|
||||||
navigator.clipboard.writeText(value).then(function () {
|
var clipboardHidden = $('<textarea type="text" id="red-ui-clipboard-hidden" tabIndex="-1">').appendTo(document.body);
|
||||||
if (element) {
|
clipboardHidden.val(value).focus().select();
|
||||||
|
var result = document.execCommand("copy");
|
||||||
|
if (result && element) {
|
||||||
var popover = RED.popover.create({
|
var popover = RED.popover.create({
|
||||||
target: element,
|
target: element,
|
||||||
direction: 'left',
|
direction: 'left',
|
||||||
@ -959,10 +961,11 @@ RED.clipboard = (function() {
|
|||||||
},1000);
|
},1000);
|
||||||
popover.open();
|
popover.open();
|
||||||
}
|
}
|
||||||
|
clipboardHidden.remove();
|
||||||
if (currentFocus) {
|
if (currentFocus) {
|
||||||
$(currentFocus).focus();
|
$(currentFocus).focus();
|
||||||
}
|
}
|
||||||
}).catch(err => { console.error("Failed to copy:",err) });
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function importNodes(nodesStr,addFlow) {
|
function importNodes(nodesStr,addFlow) {
|
||||||
|
@ -19,6 +19,15 @@ RED.sidebar = (function() {
|
|||||||
var sidebar_tabs;
|
var sidebar_tabs;
|
||||||
var knownTabs = {};
|
var knownTabs = {};
|
||||||
|
|
||||||
|
// We store the current sidebar tab id in localStorage as 'last-sidebar-tab'
|
||||||
|
// This is restored when the editor is reloaded.
|
||||||
|
// We use sidebar_tabs.onchange to update localStorage. However that will
|
||||||
|
// also get triggered when the first tab gets added to the tabs - typically
|
||||||
|
// the 'info' tab. So we use the following variable to store the retrieved
|
||||||
|
// value from localStorage before we start adding the actual tabs
|
||||||
|
var lastSessionSelectedTab = null;
|
||||||
|
|
||||||
|
|
||||||
function addTab(title,content,closeable,visible) {
|
function addTab(title,content,closeable,visible) {
|
||||||
var options;
|
var options;
|
||||||
if (typeof title === "string") {
|
if (typeof title === "string") {
|
||||||
@ -194,16 +203,16 @@ RED.sidebar = (function() {
|
|||||||
RED.events.emit("sidebar:resize");
|
RED.events.emit("sidebar:resize");
|
||||||
}
|
}
|
||||||
|
|
||||||
function showSidebar(id) {
|
function showSidebar(id, skipShowSidebar) {
|
||||||
if (id === ":first") {
|
if (id === ":first") {
|
||||||
id = RED.settings.get("editor.sidebar.order",["info", "help", "version-control", "debug"])[0]
|
id = lastSessionSelectedTab || RED.settings.get("editor.sidebar.order",["info", "help", "version-control", "debug"])[0]
|
||||||
}
|
}
|
||||||
if (id) {
|
if (id) {
|
||||||
if (!containsTab(id) && knownTabs[id]) {
|
if (!containsTab(id) && knownTabs[id]) {
|
||||||
sidebar_tabs.addTab(knownTabs[id]);
|
sidebar_tabs.addTab(knownTabs[id]);
|
||||||
}
|
}
|
||||||
sidebar_tabs.activateTab(id);
|
sidebar_tabs.activateTab(id);
|
||||||
if (!RED.menu.isSelected("menu-item-sidebar")) {
|
if (!skipShowSidebar && !RED.menu.isSelected("menu-item-sidebar")) {
|
||||||
RED.menu.setSelected("menu-item-sidebar",true);
|
RED.menu.setSelected("menu-item-sidebar",true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,6 +236,7 @@ RED.sidebar = (function() {
|
|||||||
if (tab.toolbar) {
|
if (tab.toolbar) {
|
||||||
$(tab.toolbar).show();
|
$(tab.toolbar).show();
|
||||||
}
|
}
|
||||||
|
RED.settings.setLocal("last-sidebar-tab", tab.id)
|
||||||
},
|
},
|
||||||
onremove: function(tab) {
|
onremove: function(tab) {
|
||||||
$(tab.wrapper).hide();
|
$(tab.wrapper).hide();
|
||||||
@ -255,7 +265,9 @@ RED.sidebar = (function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
RED.popover.tooltip($("#red-ui-sidebar-separator").find(".red-ui-sidebar-control-right"),RED._("keyboard.toggleSidebar"),"core:toggle-sidebar");
|
RED.popover.tooltip($("#red-ui-sidebar-separator").find(".red-ui-sidebar-control-right"),RED._("keyboard.toggleSidebar"),"core:toggle-sidebar");
|
||||||
showSidebar();
|
|
||||||
|
lastSessionSelectedTab = RED.settings.getLocal("last-sidebar-tab")
|
||||||
|
|
||||||
RED.sidebar.info.init();
|
RED.sidebar.info.init();
|
||||||
RED.sidebar.help.init();
|
RED.sidebar.help.init();
|
||||||
RED.sidebar.config.init();
|
RED.sidebar.config.init();
|
||||||
|
@ -121,6 +121,13 @@ RED.userSettings = (function() {
|
|||||||
// {setting:"theme", label:"Theme",options:function(done){ done([{val:'',text:'default'}].concat(RED.settings.theme("themes"))) }},
|
// {setting:"theme", label:"Theme",options:function(done){ done([{val:'',text:'default'}].concat(RED.settings.theme("themes"))) }},
|
||||||
// ]
|
// ]
|
||||||
// },
|
// },
|
||||||
|
{
|
||||||
|
title: "menu.label.view.view",
|
||||||
|
options: [
|
||||||
|
{setting:"view-store-zoom",label:"menu.label.view.storeZoom", default: false, toggle:true, onchange: function(val) { if (!val) { RED.settings.removeLocal("zoom-level")}}},
|
||||||
|
{setting:"view-store-position",label:"menu.label.view.storePosition", default: false, toggle:true, onchange: function(val) { if (!val) { RED.settings.removeLocal("scroll-positions")}}},
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "menu.label.view.grid",
|
title: "menu.label.view.grid",
|
||||||
options: [
|
options: [
|
||||||
|
@ -109,7 +109,7 @@ RED.utils = (function() {
|
|||||||
window._marked.use({extensions: [descriptionList, description] } );
|
window._marked.use({extensions: [descriptionList, description] } );
|
||||||
|
|
||||||
function renderMarkdown(txt) {
|
function renderMarkdown(txt) {
|
||||||
var rendered = _marked(txt);
|
var rendered = _marked.parse(txt);
|
||||||
var cleaned = DOMPurify.sanitize(rendered, {SAFE_FOR_JQUERY: true})
|
var cleaned = DOMPurify.sanitize(rendered, {SAFE_FOR_JQUERY: true})
|
||||||
return cleaned;
|
return cleaned;
|
||||||
}
|
}
|
||||||
|
@ -678,6 +678,39 @@ RED.view = (function() {
|
|||||||
show: function(n) { return !n.valid }
|
show: function(n) { return !n.valid }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (RED.settings.get("editor.view.view-store-zoom")) {
|
||||||
|
var userZoomLevel = parseFloat(RED.settings.getLocal('zoom-level'))
|
||||||
|
if (!isNaN(userZoomLevel)) {
|
||||||
|
scaleFactor = userZoomLevel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var onScrollTimer = null;
|
||||||
|
function storeScrollPosition() {
|
||||||
|
workspaceScrollPositions[RED.workspaces.active()] = {
|
||||||
|
left:chart.scrollLeft(),
|
||||||
|
top:chart.scrollTop()
|
||||||
|
};
|
||||||
|
RED.settings.setLocal('scroll-positions', JSON.stringify(workspaceScrollPositions) )
|
||||||
|
}
|
||||||
|
chart.on("scroll", function() {
|
||||||
|
if (RED.settings.get("editor.view.view-store-position")) {
|
||||||
|
if (onScrollTimer) {
|
||||||
|
clearTimeout(onScrollTimer)
|
||||||
|
}
|
||||||
|
onScrollTimer = setTimeout(storeScrollPosition, 200);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (RED.settings.get("editor.view.view-store-position")) {
|
||||||
|
var scrollPositions = RED.settings.getLocal('scroll-positions')
|
||||||
|
if (scrollPositions) {
|
||||||
|
try {
|
||||||
|
workspaceScrollPositions = JSON.parse(scrollPositions)
|
||||||
|
} catch(err) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1965,6 +1998,7 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
function zoomZero() { zoomView(1); }
|
function zoomZero() { zoomView(1); }
|
||||||
|
|
||||||
|
|
||||||
function zoomView(factor) {
|
function zoomView(factor) {
|
||||||
var screenSize = [chart.width(),chart.height()];
|
var screenSize = [chart.width(),chart.height()];
|
||||||
var scrollPos = [chart.scrollLeft(),chart.scrollTop()];
|
var scrollPos = [chart.scrollLeft(),chart.scrollTop()];
|
||||||
@ -1977,6 +2011,9 @@ RED.view = (function() {
|
|||||||
|
|
||||||
RED.view.navigator.resize();
|
RED.view.navigator.resize();
|
||||||
redraw();
|
redraw();
|
||||||
|
if (RED.settings.get("editor.view.view-store-zoom")) {
|
||||||
|
RED.settings.setLocal('zoom-level', factor.toFixed(1))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectNone() {
|
function selectNone() {
|
||||||
|
@ -356,6 +356,11 @@ button.red-ui-button-small
|
|||||||
background: $secondary-background;
|
background: $secondary-background;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#red-ui-clipboard-hidden {
|
||||||
|
position: absolute;
|
||||||
|
top: -3000px;
|
||||||
|
}
|
||||||
|
|
||||||
.form-row .red-ui-editor-node-label-form-row {
|
.form-row .red-ui-editor-node-label-form-row {
|
||||||
margin: 5px 0 0 50px;
|
margin: 5px 0 0 50px;
|
||||||
label {
|
label {
|
||||||
|
@ -234,7 +234,7 @@
|
|||||||
}
|
}
|
||||||
} else if (v[i].vt === "jsonata") {
|
} else if (v[i].vt === "jsonata") {
|
||||||
try{jsonata(v[i].v);}catch(e){return false;}
|
try{jsonata(v[i].v);}catch(e){return false;}
|
||||||
} else if ([i].vt === "json") {
|
} else if (v[i].vt === "json") {
|
||||||
try{JSON.parse(v[i].v);}catch(e){return false;}
|
try{JSON.parse(v[i].v);}catch(e){return false;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,8 @@
|
|||||||
timeout: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
timeout: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||||
timeoutUnits: {value:"seconds"},
|
timeoutUnits: {value:"seconds"},
|
||||||
rate: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
rate: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||||
nbRateUnits: {value:"1", required:false, validate:RED.validators.regex(/\d+|/)},
|
nbRateUnits: {value:"1", required:false,
|
||||||
|
validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||||
rateUnits: {value: "second"},
|
rateUnits: {value: "second"},
|
||||||
randomFirst: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
randomFirst: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||||
randomLast: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
randomLast: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||||
|
@ -264,7 +264,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|||||||
if (opts.headers.hasOwnProperty('cookie')) {
|
if (opts.headers.hasOwnProperty('cookie')) {
|
||||||
var cookies = cookie.parse(opts.headers.cookie, {decode:String});
|
var cookies = cookie.parse(opts.headers.cookie, {decode:String});
|
||||||
for (var name in cookies) {
|
for (var name in cookies) {
|
||||||
opts.cookieJar.setCookie(cookie.serialize(name, cookies[name], {encode:String}), url, {ignoreError: true});
|
opts.cookieJar.setCookieSync(cookie.serialize(name, cookies[name], {encode:String}), url, {ignoreError: true});
|
||||||
}
|
}
|
||||||
delete opts.headers.cookie;
|
delete opts.headers.cookie;
|
||||||
}
|
}
|
||||||
@ -277,13 +277,13 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|||||||
} else if (typeof msg.cookies[name] === 'object') {
|
} else if (typeof msg.cookies[name] === 'object') {
|
||||||
if(msg.cookies[name].encode === false){
|
if(msg.cookies[name].encode === false){
|
||||||
// If the encode option is false, the value is not encoded.
|
// If the encode option is false, the value is not encoded.
|
||||||
opts.cookieJar.setCookie(cookie.serialize(name, msg.cookies[name].value, {encode: String}), url, {ignoreError: true});
|
opts.cookieJar.setCookieSync(cookie.serialize(name, msg.cookies[name].value, {encode: String}), url, {ignoreError: true});
|
||||||
} else {
|
} else {
|
||||||
// The value is encoded by encodeURIComponent().
|
// The value is encoded by encodeURIComponent().
|
||||||
opts.cookieJar.setCookie(cookie.serialize(name, msg.cookies[name].value), url, {ignoreError: true});
|
opts.cookieJar.setCookieSync(cookie.serialize(name, msg.cookies[name].value), url, {ignoreError: true});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
opts.cookieJar.setCookie(cookie.serialize(name, msg.cookies[name]), url, {ignoreError: true});
|
opts.cookieJar.setCookieSync(cookie.serialize(name, msg.cookies[name]), url, {ignoreError: true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user