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",
|
||||
"other": "Other",
|
||||
"showTips": "Show tips",
|
||||
"showWelcomeTours": "Show guided tours for new versions",
|
||||
"help": "Node-RED website",
|
||||
"projects": "Projects",
|
||||
"projects-new": "New",
|
||||
|
@ -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 = '<div style="text-align:center;">'+
|
||||
'<img width="50px" src="red/images/node-red-icon.svg" />'+
|
||||
'</div>';
|
||||
|
||||
RED.sidebar.help.set(aboutHeader+RED.utils.renderMarkdown(data));
|
||||
});
|
||||
function checkFirstRun() {
|
||||
if (RED.settings.theme("tours") === false) {
|
||||
return;
|
||||
}
|
||||
if (!RED.settings.get("editor.view.view-show-welcome-tours", true)) {
|
||||
return;
|
||||
}
|
||||
RED.actions.invoke("core:show-welcome-tour", RED.settings.get("editor.tours.welcome"));
|
||||
}
|
||||
|
||||
function buildMainMenu() {
|
||||
@ -696,9 +695,6 @@ var RED = (function() {
|
||||
|
||||
$("#red-ui-main-container").show();
|
||||
|
||||
|
||||
RED.actions.add("core:show-about", showAbout);
|
||||
|
||||
loadPluginList();
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@ RED.settings = (function () {
|
||||
|
||||
var loadedSettings = {};
|
||||
var userSettings = {};
|
||||
var settingsDirty = false;
|
||||
var pendingSave;
|
||||
|
||||
var hasLocalStorage = function () {
|
||||
|
@ -25,7 +25,6 @@ RED.sidebar.help = (function() {
|
||||
var tocPanel;
|
||||
var helpIndex = {};
|
||||
|
||||
|
||||
function resizeStack() {
|
||||
var h = $(content).parent().height() - toolbar.outerHeight();
|
||||
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);
|
||||
|
||||
treeList = $("<div>").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, '<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);
|
||||
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) {
|
||||
$("<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>" );
|
||||
var foldingHeader = "H3";
|
||||
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);
|
||||
})
|
||||
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 = '<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 {
|
||||
init: init,
|
||||
show: show,
|
||||
|
@ -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",'');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
@ -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;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
export default {
|
||||
version: "2.1.0",
|
||||
steps: [
|
||||
{
|
||||
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>",
|
||||
},
|
||||
{
|
||||
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: "<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");
|
||||
setTimeout(done,800);
|
||||
},
|
||||
@ -57,7 +58,7 @@ export default {
|
||||
element: ".node-input-env-container-row .red-ui-editableList-addButton",
|
||||
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>',
|
||||
complete: function() {
|
||||
complete() {
|
||||
$("#node-dialog-cancel").trigger("click");
|
||||
}
|
||||
},
|
Loading…
Reference in New Issue
Block a user