mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Add core:show-welcome-tour action and logic to display on first-run
This commit is contained in:
parent
e20cfb3dae
commit
e9e03c945b
@ -112,6 +112,7 @@
|
|||||||
"editPalette":"Manage palette",
|
"editPalette":"Manage palette",
|
||||||
"other": "Other",
|
"other": "Other",
|
||||||
"showTips": "Show tips",
|
"showTips": "Show tips",
|
||||||
|
"showWelcomeTours": "Show guided tours for new versions",
|
||||||
"help": "Node-RED website",
|
"help": "Node-RED website",
|
||||||
"projects": "Projects",
|
"projects": "Projects",
|
||||||
"projects-new": "New",
|
"projects-new": "New",
|
||||||
|
@ -535,19 +535,18 @@ var RED = (function() {
|
|||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
loader.end();
|
loader.end();
|
||||||
|
checkFirstRun();
|
||||||
},100);
|
},100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showAbout() {
|
function checkFirstRun() {
|
||||||
$.get('red/about', function(data) {
|
if (RED.settings.theme("tours") === false) {
|
||||||
// data will be strictly markdown. Any HTML should be escaped.
|
return;
|
||||||
data = RED.utils.sanitize(data);
|
}
|
||||||
var aboutHeader = '<div style="text-align:center;">'+
|
if (!RED.settings.get("editor.view.view-show-welcome-tours", true)) {
|
||||||
'<img width="50px" src="red/images/node-red-icon.svg" />'+
|
return;
|
||||||
'</div>';
|
}
|
||||||
|
RED.actions.invoke("core:show-welcome-tour", RED.settings.get("editor.tours.welcome"));
|
||||||
RED.sidebar.help.set(aboutHeader+RED.utils.renderMarkdown(data));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMainMenu() {
|
function buildMainMenu() {
|
||||||
@ -696,9 +695,6 @@ var RED = (function() {
|
|||||||
|
|
||||||
$("#red-ui-main-container").show();
|
$("#red-ui-main-container").show();
|
||||||
|
|
||||||
|
|
||||||
RED.actions.add("core:show-about", showAbout);
|
|
||||||
|
|
||||||
loadPluginList();
|
loadPluginList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ RED.settings = (function () {
|
|||||||
|
|
||||||
var loadedSettings = {};
|
var loadedSettings = {};
|
||||||
var userSettings = {};
|
var userSettings = {};
|
||||||
var settingsDirty = false;
|
|
||||||
var pendingSave;
|
var pendingSave;
|
||||||
|
|
||||||
var hasLocalStorage = function () {
|
var hasLocalStorage = function () {
|
||||||
|
@ -25,7 +25,6 @@ RED.sidebar.help = (function() {
|
|||||||
var tocPanel;
|
var tocPanel;
|
||||||
var helpIndex = {};
|
var helpIndex = {};
|
||||||
|
|
||||||
|
|
||||||
function resizeStack() {
|
function resizeStack() {
|
||||||
var h = $(content).parent().height() - toolbar.outerHeight();
|
var h = $(content).parent().height() - toolbar.outerHeight();
|
||||||
panels.resize(h)
|
panels.resize(h)
|
||||||
@ -93,9 +92,28 @@ RED.sidebar.help = (function() {
|
|||||||
$('<span class="red-ui-help-info-none">'+RED._("sidebar.help.noHelp")+'</span>').appendTo(helpSection);
|
$('<span class="red-ui-help-info-none">'+RED._("sidebar.help.noHelp")+'</span>').appendTo(helpSection);
|
||||||
|
|
||||||
treeList = $("<div>").css({width: "100%"}).appendTo(tocPanel).treeList({data: []})
|
treeList = $("<div>").css({width: "100%"}).appendTo(tocPanel).treeList({data: []})
|
||||||
|
var pendingContentLoad;
|
||||||
treeList.on('treelistselect', function(e,item) {
|
treeList.on('treelistselect', function(e,item) {
|
||||||
|
pendingContentLoad = item;
|
||||||
if (item.nodeType) {
|
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, '<div class="red-ui-component-spinner red-ui-component-spinner-contain"><img src="red/images/spin.svg" /></div>',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);
|
var moduleNames = Object.keys(modules);
|
||||||
moduleNames.sort();
|
moduleNames.sort();
|
||||||
|
|
||||||
var helpData = [{
|
var nodeHelp = {
|
||||||
label: RED._("sidebar.help.nodeHelp"),
|
label: RED._("sidebar.help.nodeHelp"),
|
||||||
children: [],
|
children: [],
|
||||||
expanded: true
|
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)});
|
var subflows = RED.nodes.registry.getNodeTypes().filter(function(t) {return /subflow/.test(t)});
|
||||||
if (subflows.length > 0) {
|
if (subflows.length > 0) {
|
||||||
helpData[0].children.push({
|
nodeHelp.children.push({
|
||||||
label: RED._("menu.label.subflows"),
|
label: RED._("menu.label.subflows"),
|
||||||
children: []
|
children: []
|
||||||
})
|
})
|
||||||
subflows.forEach(function(nodeType) {
|
subflows.forEach(function(nodeType) {
|
||||||
var sf = RED.nodes.getType(nodeType);
|
var sf = RED.nodes.getType(nodeType);
|
||||||
helpData[0].children[0].children.push({
|
nodeHelp.children[0].children.push({
|
||||||
id:"node-type:"+nodeType,
|
id:"node-type:"+nodeType,
|
||||||
nodeType: nodeType,
|
nodeType: nodeType,
|
||||||
subflowLabel: sf.label().toLowerCase(),
|
subflowLabel: sf.label().toLowerCase(),
|
||||||
@ -218,7 +243,7 @@ RED.sidebar.help = (function() {
|
|||||||
nodeTypes.sort(function(A,B) {
|
nodeTypes.sort(function(A,B) {
|
||||||
return A.nodeType.localeCompare(B.nodeType)
|
return A.nodeType.localeCompare(B.nodeType)
|
||||||
})
|
})
|
||||||
helpData[0].children.push({
|
nodeHelp.children.push({
|
||||||
id: moduleName,
|
id: moduleName,
|
||||||
icon: "fa fa-cube",
|
icon: "fa fa-cube",
|
||||||
label: moduleName,
|
label: moduleName,
|
||||||
@ -244,7 +269,7 @@ RED.sidebar.help = (function() {
|
|||||||
return div;
|
return div;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showHelp(nodeType) {
|
function showNodeTypeHelp(nodeType) {
|
||||||
helpSection.empty();
|
helpSection.empty();
|
||||||
var helpText;
|
var helpText;
|
||||||
var title;
|
var title;
|
||||||
@ -265,7 +290,7 @@ RED.sidebar.help = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setInfoText(title, helpText, helpSection);
|
setInfoText(title, helpText);
|
||||||
|
|
||||||
var ratio = panels.ratio();
|
var ratio = panels.ratio();
|
||||||
if (ratio > 0.7) {
|
if (ratio > 0.7) {
|
||||||
@ -282,7 +307,7 @@ RED.sidebar.help = (function() {
|
|||||||
}
|
}
|
||||||
if (type) {
|
if (type) {
|
||||||
// hideTOC();
|
// hideTOC();
|
||||||
showHelp(type);
|
showNodeTypeHelp(type);
|
||||||
}
|
}
|
||||||
resizeStack();
|
resizeStack();
|
||||||
}
|
}
|
||||||
@ -298,11 +323,12 @@ RED.sidebar.help = (function() {
|
|||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setInfoText(title, infoText,target) {
|
function setInfoText(title, infoText) {
|
||||||
|
helpSection.empty();
|
||||||
if (title) {
|
if (title) {
|
||||||
$("<h1>",{class:"red-ui-help-title"}).text(title).appendTo(target);
|
$("<h1>",{class:"red-ui-help-title"}).text(title).appendTo(helpSection);
|
||||||
}
|
}
|
||||||
var info = addTargetToExternalLinks($('<div class="red-ui-help"><span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div>')).appendTo(target);
|
var info = addTargetToExternalLinks($('<div class="red-ui-help"><span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div>')).appendTo(helpSection);
|
||||||
info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
|
info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
|
||||||
var foldingHeader = "H3";
|
var foldingHeader = "H3";
|
||||||
info.find(foldingHeader).wrapInner('<a class="red-ui-help-info-header expanded" href="#"></a>')
|
info.find(foldingHeader).wrapInner('<a class="red-ui-help-info-header expanded" href="#"></a>')
|
||||||
@ -316,12 +342,12 @@ RED.sidebar.help = (function() {
|
|||||||
}
|
}
|
||||||
$(this).toggleClass('expanded',!isExpanded);
|
$(this).toggleClass('expanded',!isExpanded);
|
||||||
})
|
})
|
||||||
target.parent().scrollTop(0);
|
helpSection.parent().scrollTop(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function set(html,title) {
|
function set(html,title) {
|
||||||
$(helpSection).empty();
|
$(helpSection).empty();
|
||||||
setInfoText(title,html,helpSection);
|
setInfoText(title,html);
|
||||||
hideTOC();
|
hideTOC();
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
@ -336,13 +362,83 @@ RED.sidebar.help = (function() {
|
|||||||
if (node.type === "subflow" && node.direction) {
|
if (node.type === "subflow" && node.direction) {
|
||||||
// ignore subflow virtual ports
|
// ignore subflow virtual ports
|
||||||
} else if (node.type !== 'group'){
|
} else if (node.type !== 'group'){
|
||||||
showHelp(node.type);
|
showNodeTypeHelp(node.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RED.events.on("view:selection-changed",refreshSelection);
|
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 = '<div><img width="50px" src="red/images/node-red-icon.svg" /></div>';
|
||||||
|
if (tour) {
|
||||||
|
var currentVersionParts = RED.settings.version.split(".");
|
||||||
|
var tourVersionParts = tour.version.split(".");
|
||||||
|
if (tourVersionParts[0] === currentVersionParts[0] && tourVersionParts[1] === currentVersionParts[1]) {
|
||||||
|
tourHeader = '<div><button type="button" onclick="RED.actions.invoke(\'core:show-welcome-tour\')" class="red-ui-button">Take a tour</button></div>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var aboutHeader = '<div style="text-align:center;">'+tourHeader+'</div>'
|
||||||
|
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 {
|
return {
|
||||||
init: init,
|
init: init,
|
||||||
show: show,
|
show: show,
|
||||||
|
@ -15,17 +15,27 @@ RED.tourGuide = (function() {
|
|||||||
console.error(err);
|
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]) {
|
if (tourCache[tourPath]) {
|
||||||
runTour(tourCache[tourPath],done);
|
done(null, tourCache[tourPath]);
|
||||||
} else {
|
} else {
|
||||||
/* jshint ignore:start */
|
/* jshint ignore:start */
|
||||||
// jshint<2.13 doesn't support dynamic imports. Once grunt-contrib-jshint
|
// 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
|
// has been updated with the new jshint, we can stop ignoring this block
|
||||||
import(tourPath).then(function(module) {
|
import(tourPath).then(function(module) {
|
||||||
tourCache[tourPath] = module.default;
|
tourCache[tourPath] = module.default;
|
||||||
runTour(tourCache[tourPath],done);
|
done(null, tourCache[tourPath]);
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
console.warn("Error loading tour:",err);
|
|
||||||
done(err);
|
done(err);
|
||||||
})
|
})
|
||||||
/* jshint ignore:end */
|
/* jshint ignore:end */
|
||||||
@ -357,7 +367,11 @@ RED.tourGuide = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
run: run
|
load: loadTour,
|
||||||
|
run: run,
|
||||||
|
reset: function() {
|
||||||
|
RED.settings.set("editor.tours.welcome",'');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -139,7 +139,8 @@ RED.userSettings = (function() {
|
|||||||
{
|
{
|
||||||
title: "menu.label.other",
|
title: "menu.label.other",
|
||||||
options: [
|
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}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -295,7 +295,7 @@ $group-default-stroke: #999;
|
|||||||
$group-default-stroke-opacity: 1;
|
$group-default-stroke-opacity: 1;
|
||||||
$group-default-label-color: #a4a4a4;
|
$group-default-label-color: #a4a4a4;
|
||||||
|
|
||||||
$tourGuide-shade: rgba(100, 70, 70, 0.6);
|
$tourGuide-shade: $shade-color;
|
||||||
$tourGuide-border: #a22222;
|
$tourGuide-border: #a22222;
|
||||||
$tourGuide-heading-color: #a22222;
|
$tourGuide-heading-color: #a22222;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
export default {
|
export default {
|
||||||
|
version: "2.1.0",
|
||||||
steps: [
|
steps: [
|
||||||
{
|
{
|
||||||
titleIcon: "fa fa-map-o",
|
titleIcon: "fa fa-map-o",
|
||||||
@ -11,11 +12,11 @@ export default {
|
|||||||
"<p>You can choose not to see this tour in the future by disabling it under the View tab of User Settings.</p>",
|
"<p>You can choose not to see this tour in the future by disabling it under the View tab of User Settings.</p>",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
prepare:function() {
|
prepare() {
|
||||||
$("#red-ui-header-button-sidemenu").trigger("click");
|
$("#red-ui-header-button-sidemenu").trigger("click");
|
||||||
$("#menu-item-edit-menu").parent().addClass("open")
|
$("#menu-item-edit-menu").parent().addClass("open")
|
||||||
},
|
},
|
||||||
complete: function() {
|
complete() {
|
||||||
$("#menu-item-edit-menu").parent().removeClass("open")
|
$("#menu-item-edit-menu").parent().removeClass("open")
|
||||||
},
|
},
|
||||||
element: "#menu-item-edit-menu-submenu",
|
element: "#menu-item-edit-menu-submenu",
|
||||||
@ -27,11 +28,11 @@ export default {
|
|||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
prepare: function() {
|
prepare() {
|
||||||
$("#red-ui-header-button-sidemenu").trigger("click");
|
$("#red-ui-header-button-sidemenu").trigger("click");
|
||||||
$("#menu-item-arrange-menu").parent().addClass("open")
|
$("#menu-item-arrange-menu").parent().addClass("open")
|
||||||
},
|
},
|
||||||
complete: function() {
|
complete() {
|
||||||
$("#menu-item-arrange-menu").parent().removeClass("open")
|
$("#menu-item-arrange-menu").parent().removeClass("open")
|
||||||
},
|
},
|
||||||
element: "#menu-item-arrange-menu-submenu",
|
element: "#menu-item-arrange-menu-submenu",
|
||||||
@ -46,7 +47,7 @@ export default {
|
|||||||
description: "<p>Flows and Groups can now have their own environment variables that can be referenced by nodes inside them.</p>",
|
description: "<p>Flows and Groups can now have their own environment variables that can be referenced by nodes inside them.</p>",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
prepare: function(done) {
|
prepare(done) {
|
||||||
RED.editor.editFlow(RED.nodes.workspace(RED.workspaces.active()),"editor-tab-envProperties");
|
RED.editor.editFlow(RED.nodes.workspace(RED.workspaces.active()),"editor-tab-envProperties");
|
||||||
setTimeout(done,800);
|
setTimeout(done,800);
|
||||||
},
|
},
|
||||||
@ -57,7 +58,7 @@ export default {
|
|||||||
element: ".node-input-env-container-row .red-ui-editableList-addButton",
|
element: ".node-input-env-container-row .red-ui-editableList-addButton",
|
||||||
direction: "top",
|
direction: "top",
|
||||||
description: '<p>The environment variables are listed in this table and new ones can be added by clicking the <i class="fa fa-plus"></i> button.</p>',
|
description: '<p>The environment variables are listed in this table and new ones can be added by clicking the <i class="fa fa-plus"></i> button.</p>',
|
||||||
complete: function() {
|
complete() {
|
||||||
$("#node-dialog-cancel").trigger("click");
|
$("#node-dialog-cancel").trigger("click");
|
||||||
}
|
}
|
||||||
},
|
},
|
Loading…
Reference in New Issue
Block a user