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 2a1e16f1d..33747b96d 100755
--- 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
@@ -112,6 +112,7 @@
"editPalette":"Manage palette",
"other": "Other",
"showTips": "Show tips",
+ "showWelcomeTours": "Show guided tours for new versions",
"help": "Node-RED website",
"projects": "Projects",
"projects-new": "New",
diff --git a/packages/node_modules/@node-red/editor-client/src/js/red.js b/packages/node_modules/@node-red/editor-client/src/js/red.js
index ad68ea612..d9ef01021 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/red.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/red.js
@@ -535,19 +535,18 @@ var RED = (function() {
setTimeout(function() {
loader.end();
+ checkFirstRun();
},100);
}
- function showAbout() {
- $.get('red/about', function(data) {
- // data will be strictly markdown. Any HTML should be escaped.
- data = RED.utils.sanitize(data);
- var aboutHeader = '
").css({width: "100%"}).appendTo(tocPanel).treeList({data: []})
+ var pendingContentLoad;
treeList.on('treelistselect', function(e,item) {
+ pendingContentLoad = item;
if (item.nodeType) {
- showHelp(item.nodeType);
+ showNodeTypeHelp(item.nodeType);
+ } else if (item.content) {
+ helpSection.empty();
+ if (typeof item.content === "string") {
+ setInfoText(item.label, item.content);
+ } else if (typeof item.content === "function") {
+ if (item.content.length === 0) {
+ setInfoText(item.label, item.content());
+ } else {
+ setInfoText(item.label, '
',helpSection)
+ item.content(function(content) {
+ if (pendingContentLoad === item) {
+ helpSection.empty();
+ setInfoText(item.label, content);
+ }
+ })
+ }
+ }
}
})
@@ -174,21 +192,28 @@ RED.sidebar.help = (function() {
var moduleNames = Object.keys(modules);
moduleNames.sort();
- var helpData = [{
+ var nodeHelp = {
label: RED._("sidebar.help.nodeHelp"),
children: [],
expanded: true
- }]
-
+ }
+ var helpData = [
+ {
+ id: 'changelog',
+ label: "Node-RED v"+RED.settings.version,
+ content: getChangelog
+ },
+ nodeHelp
+ ]
var subflows = RED.nodes.registry.getNodeTypes().filter(function(t) {return /subflow/.test(t)});
if (subflows.length > 0) {
- helpData[0].children.push({
+ nodeHelp.children.push({
label: RED._("menu.label.subflows"),
children: []
})
subflows.forEach(function(nodeType) {
var sf = RED.nodes.getType(nodeType);
- helpData[0].children[0].children.push({
+ nodeHelp.children[0].children.push({
id:"node-type:"+nodeType,
nodeType: nodeType,
subflowLabel: sf.label().toLowerCase(),
@@ -218,7 +243,7 @@ RED.sidebar.help = (function() {
nodeTypes.sort(function(A,B) {
return A.nodeType.localeCompare(B.nodeType)
})
- helpData[0].children.push({
+ nodeHelp.children.push({
id: moduleName,
icon: "fa fa-cube",
label: moduleName,
@@ -244,7 +269,7 @@ RED.sidebar.help = (function() {
return div;
}
- function showHelp(nodeType) {
+ function showNodeTypeHelp(nodeType) {
helpSection.empty();
var helpText;
var title;
@@ -265,7 +290,7 @@ RED.sidebar.help = (function() {
}
}
}
- setInfoText(title, helpText, helpSection);
+ setInfoText(title, helpText);
var ratio = panels.ratio();
if (ratio > 0.7) {
@@ -282,7 +307,7 @@ RED.sidebar.help = (function() {
}
if (type) {
// hideTOC();
- showHelp(type);
+ showNodeTypeHelp(type);
}
resizeStack();
}
@@ -298,11 +323,12 @@ RED.sidebar.help = (function() {
return el;
}
- function setInfoText(title, infoText,target) {
+ function setInfoText(title, infoText) {
+ helpSection.empty();
if (title) {
- $("
",{class:"red-ui-help-title"}).text(title).appendTo(target);
+ $("",{class:"red-ui-help-title"}).text(title).appendTo(helpSection);
}
- var info = addTargetToExternalLinks($('
'+infoText+'
')).appendTo(target);
+ var info = addTargetToExternalLinks($(''+infoText+'
')).appendTo(helpSection);
info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "" );
var foldingHeader = "H3";
info.find(foldingHeader).wrapInner('')
@@ -316,12 +342,12 @@ RED.sidebar.help = (function() {
}
$(this).toggleClass('expanded',!isExpanded);
})
- target.parent().scrollTop(0);
+ helpSection.parent().scrollTop(0);
}
function set(html,title) {
$(helpSection).empty();
- setInfoText(title,html,helpSection);
+ setInfoText(title,html);
hideTOC();
show();
}
@@ -336,13 +362,83 @@ RED.sidebar.help = (function() {
if (node.type === "subflow" && node.direction) {
// ignore subflow virtual ports
} else if (node.type !== 'group'){
- showHelp(node.type);
+ showNodeTypeHelp(node.type);
}
}
}
}
RED.events.on("view:selection-changed",refreshSelection);
+ function getChangelog(done) {
+ $.get('red/about', function(data) {
+ // data will be strictly markdown. Any HTML should be escaped.
+ data = RED.utils.sanitize(data);
+ RED.tourGuide.load("./tours/welcome.js", function(err, tour) {
+ var tourHeader = '';
+ if (tour) {
+ var currentVersionParts = RED.settings.version.split(".");
+ var tourVersionParts = tour.version.split(".");
+ if (tourVersionParts[0] === currentVersionParts[0] && tourVersionParts[1] === currentVersionParts[1]) {
+ tourHeader = ''
+ }
+ }
+ var aboutHeader = ''+tourHeader+'
'
+ done(aboutHeader+RED.utils.renderMarkdown(data))
+ });
+
+ });
+ }
+ function showAbout() {
+ treeList.treeList("show","changelog")
+ treeList.treeList("select","changelog");
+ show();
+ }
+ function showWelcomeTour(lastSeenVersion) {
+ RED.tourGuide.load("./tours/welcome.js", function(err, tour) {
+ if (err) {
+ console.warn("Failed to load welcome tour",err);
+ return;
+ }
+ var currentVersionParts = RED.settings.version.split(".");
+ var tourVersionParts = tour.version.split(".");
+
+ // Only display the tour if its MAJ.MIN versions the current version
+ // This means if we update MAJ/MIN without updating the tour, the old tour won't get shown
+ if (tourVersionParts[0] !== currentVersionParts[0] || tourVersionParts[1] !== currentVersionParts[1]) {
+ return;
+ }
+
+ if (lastSeenVersion) {
+ // Previously displayed a welcome tour.
+ if (lastSeenVersion === RED.settings.version) {
+ // Exact match - don't show the tour
+ return;
+ }
+ var lastSeenParts = lastSeenVersion.split(".");
+ if (currentVersionParts[0] < lastSeenParts[0] || (currentVersionParts[0] === lastSeenParts[0] && currentVersionParts[1] < lastSeenParts[1])) {
+ // Running an *older* version than last displayed tour.
+ return;
+ }
+ if (currentVersionParts[0] === lastSeenParts[0] && currentVersionParts[1] === lastSeenParts[1]) {
+ if (lastSeenParts.length === 3 && currentVersionParts.length === 3) {
+ // Matching non-beta MAJ.MIN - don't repeat tour
+ return;
+ }
+ if (currentVersionParts.length === 4 && (lastSeenParts.length === 3 || currentVersionParts[3] < lastSeenParts[3])) {
+ // Running an *older* beta than last displayed tour.
+ return
+ }
+ }
+ }
+ RED.tourGuide.run("./tours/welcome.js", function(err) {
+ RED.settings.set("editor.tours.welcome", RED.settings.version)
+ })
+ })
+
+ }
+ RED.actions.add("core:show-about", showAbout);
+ RED.actions.add("core:show-welcome-tour", showWelcomeTour);
+
return {
init: init,
show: show,
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tour/tourGuide.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tour/tourGuide.js
index 9044e5980..019a14d4d 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/tour/tourGuide.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tour/tourGuide.js
@@ -15,17 +15,27 @@ RED.tourGuide = (function() {
console.error(err);
}
};
+ loadTour(tourPath, function(err, tour) {
+ if (err) {
+ console.warn("Error loading tour:",err);
+ return;
+ }
+ runTour(tour, done);
+ })
+
+ }
+
+ function loadTour(tourPath, done) {
if (tourCache[tourPath]) {
- runTour(tourCache[tourPath],done);
+ done(null, tourCache[tourPath]);
} else {
/* jshint ignore:start */
// jshint<2.13 doesn't support dynamic imports. Once grunt-contrib-jshint
// has been updated with the new jshint, we can stop ignoring this block
import(tourPath).then(function(module) {
tourCache[tourPath] = module.default;
- runTour(tourCache[tourPath],done);
+ done(null, tourCache[tourPath]);
}).catch(function(err) {
- console.warn("Error loading tour:",err);
done(err);
})
/* jshint ignore:end */
@@ -357,7 +367,11 @@ RED.tourGuide = (function() {
}
return {
- run: run
+ load: loadTour,
+ run: run,
+ reset: function() {
+ RED.settings.set("editor.tours.welcome",'');
+ }
}
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js b/packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js
index 2bdae4b13..3c1e295d2 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js
@@ -139,7 +139,8 @@ RED.userSettings = (function() {
{
title: "menu.label.other",
options: [
- {setting:"view-show-tips",oldSettings:"menu-menu-item-show-tips",label:"menu.label.showTips",toggle:true,default:true,onchange:"core:toggle-show-tips"}
+ {setting:"view-show-tips",oldSettings:"menu-menu-item-show-tips",label:"menu.label.showTips",toggle:true,default:true,onchange:"core:toggle-show-tips"},
+ {setting:"view-show-welcome-tours",label:"menu.label.showWelcomeTours",toggle:true,default:true}
]
}
];
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/colors.scss b/packages/node_modules/@node-red/editor-client/src/sass/colors.scss
index b397e05b7..eb0582ba1 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/colors.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/colors.scss
@@ -295,7 +295,7 @@ $group-default-stroke: #999;
$group-default-stroke-opacity: 1;
$group-default-label-color: #a4a4a4;
-$tourGuide-shade: rgba(100, 70, 70, 0.6);
+$tourGuide-shade: $shade-color;
$tourGuide-border: #a22222;
$tourGuide-heading-color: #a22222;
diff --git a/packages/node_modules/@node-red/editor-client/src/tours/welcome-2-1.js b/packages/node_modules/@node-red/editor-client/src/tours/welcome.js
similarity index 93%
rename from packages/node_modules/@node-red/editor-client/src/tours/welcome-2-1.js
rename to packages/node_modules/@node-red/editor-client/src/tours/welcome.js
index 33f6a1a88..1a4f59f9d 100644
--- a/packages/node_modules/@node-red/editor-client/src/tours/welcome-2-1.js
+++ b/packages/node_modules/@node-red/editor-client/src/tours/welcome.js
@@ -1,4 +1,5 @@
export default {
+ version: "2.1.0",
steps: [
{
titleIcon: "fa fa-map-o",
@@ -11,11 +12,11 @@ export default {
"You can choose not to see this tour in the future by disabling it under the View tab of User Settings.
",
},
{
- prepare:function() {
+ prepare() {
$("#red-ui-header-button-sidemenu").trigger("click");
$("#menu-item-edit-menu").parent().addClass("open")
},
- complete: function() {
+ complete() {
$("#menu-item-edit-menu").parent().removeClass("open")
},
element: "#menu-item-edit-menu-submenu",
@@ -27,11 +28,11 @@ export default {
},
{
- prepare: function() {
+ prepare() {
$("#red-ui-header-button-sidemenu").trigger("click");
$("#menu-item-arrange-menu").parent().addClass("open")
},
- complete: function() {
+ complete() {
$("#menu-item-arrange-menu").parent().removeClass("open")
},
element: "#menu-item-arrange-menu-submenu",
@@ -46,7 +47,7 @@ export default {
description: "
Flows and Groups can now have their own environment variables that can be referenced by nodes inside them.
",
},
{
- prepare: function(done) {
+ prepare(done) {
RED.editor.editFlow(RED.nodes.workspace(RED.workspaces.active()),"editor-tab-envProperties");
setTimeout(done,800);
},
@@ -57,7 +58,7 @@ export default {
element: ".node-input-env-container-row .red-ui-editableList-addButton",
direction: "top",
description: '
The environment variables are listed in this table and new ones can be added by clicking the button.
',
- complete: function() {
+ complete() {
$("#node-dialog-cancel").trigger("click");
}
},