mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #3136 from node-red/tour-guide-2
Add Tour Guide component
This commit is contained in:
commit
b427eca21f
15
Gruntfile.js
15
Gruntfile.js
@ -199,7 +199,8 @@ module.exports = function(grunt) {
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectUserSettings.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/tab-versionControl.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/touch/radialMenu.js"
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/touch/radialMenu.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tour/*.js"
|
||||
],
|
||||
dest: "packages/node_modules/@node-red/editor-client/public/red/red.js"
|
||||
},
|
||||
@ -326,6 +327,12 @@ module.exports = function(grunt) {
|
||||
],
|
||||
tasks: ['jsonlint:keymaps','copy:build']
|
||||
},
|
||||
tours: {
|
||||
files: [
|
||||
'packages/node_modules/@node-red/editor-client/src/tours/**/*.js'
|
||||
],
|
||||
tasks: ['copy:build']
|
||||
},
|
||||
misc: {
|
||||
files: [
|
||||
'CHANGELOG.md'
|
||||
@ -423,6 +430,12 @@ module.exports = function(grunt) {
|
||||
src: '**',
|
||||
expand: true,
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/ace/'
|
||||
},
|
||||
{
|
||||
cwd: 'packages/node_modules/@node-red/editor-client/src/tours',
|
||||
src: '**',
|
||||
expand: true,
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/red/tours/'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -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",
|
||||
@ -1132,6 +1133,10 @@
|
||||
"preview": "UI Preview",
|
||||
"defaultValue": "Default value"
|
||||
},
|
||||
"tourGuide": {
|
||||
"start": "Start",
|
||||
"next": "Next"
|
||||
},
|
||||
"languages" : {
|
||||
"de": "German",
|
||||
"en-US": "English",
|
||||
|
@ -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 () {
|
||||
|
@ -17,20 +17,12 @@
|
||||
RED.popover = (function() {
|
||||
var deltaSizes = {
|
||||
"default": {
|
||||
top: 10,
|
||||
topTop: 30,
|
||||
leftRight: 17,
|
||||
leftLeft: 25,
|
||||
leftBottom: 8,
|
||||
leftTop: 11
|
||||
x: 12,
|
||||
y: 12
|
||||
},
|
||||
"small": {
|
||||
top: 6,
|
||||
topTop: 20,
|
||||
leftRight: 8,
|
||||
leftLeft: 26,
|
||||
leftBottom: 8,
|
||||
leftTop: 9
|
||||
x:8,
|
||||
y:8
|
||||
}
|
||||
}
|
||||
function createPopover(options) {
|
||||
@ -41,7 +33,9 @@ RED.popover = (function() {
|
||||
var delay = options.delay || { show: 750, hide: 50 };
|
||||
var autoClose = options.autoClose;
|
||||
var width = options.width||"auto";
|
||||
var maxWidth = options.maxWidth;
|
||||
var size = options.size||"default";
|
||||
var popupOffset = options.offset || 0;
|
||||
if (!deltaSizes[size]) {
|
||||
throw new Error("Invalid RED.popover size value:",size);
|
||||
}
|
||||
@ -49,6 +43,8 @@ RED.popover = (function() {
|
||||
var timer = null;
|
||||
var active;
|
||||
var div;
|
||||
var contentDiv;
|
||||
var currentStyle;
|
||||
|
||||
var openPopup = function(instant) {
|
||||
if (active) {
|
||||
@ -58,6 +54,10 @@ RED.popover = (function() {
|
||||
return;
|
||||
}
|
||||
div = $('<div class="red-ui-popover"></div>');
|
||||
if (options.class) {
|
||||
div.addClass(options.class);
|
||||
}
|
||||
contentDiv = $('<div class="red-ui-popover-content">').appendTo(div);
|
||||
if (size !== "default") {
|
||||
div.addClass("red-ui-popover-size-"+size);
|
||||
}
|
||||
@ -67,71 +67,23 @@ RED.popover = (function() {
|
||||
return;
|
||||
}
|
||||
if (typeof result === 'string') {
|
||||
div.text(result);
|
||||
contentDiv.text(result);
|
||||
} else {
|
||||
div.append(result);
|
||||
contentDiv.append(result);
|
||||
}
|
||||
} else {
|
||||
div.html(content);
|
||||
}
|
||||
if (width !== "auto") {
|
||||
div.width(width);
|
||||
contentDiv.html(content);
|
||||
}
|
||||
div.appendTo("body");
|
||||
|
||||
var targetPos = target.offset();
|
||||
var targetWidth = target.outerWidth();
|
||||
var targetHeight = target.outerHeight();
|
||||
var divHeight = div.height();
|
||||
var divWidth = div.width();
|
||||
var paddingRight = 10;
|
||||
movePopup({target,direction,width,maxWidth});
|
||||
|
||||
var viewportTop = $(window).scrollTop();
|
||||
var viewportLeft = $(window).scrollLeft();
|
||||
var viewportBottom = viewportTop + $(window).height();
|
||||
var viewportRight = viewportLeft + $(window).width();
|
||||
var top = 0;
|
||||
var left = 0;
|
||||
var d = direction;
|
||||
if (d === 'right') {
|
||||
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
|
||||
left = targetPos.left+targetWidth+deltaSizes[size].leftRight;
|
||||
} else if (d === 'left') {
|
||||
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
|
||||
left = targetPos.left-deltaSizes[size].leftLeft-divWidth;
|
||||
} else if (d === 'bottom') {
|
||||
top = targetPos.top+targetHeight+deltaSizes[size].top;
|
||||
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftBottom;
|
||||
if (left < 0) {
|
||||
d = "right";
|
||||
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
|
||||
left = targetPos.left+targetWidth+deltaSizes[size].leftRight;
|
||||
} else if (left+divWidth+paddingRight > viewportRight) {
|
||||
d = "left";
|
||||
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
|
||||
left = targetPos.left-deltaSizes[size].leftLeft-divWidth;
|
||||
if (top+divHeight+targetHeight/2 + 5 > viewportBottom) {
|
||||
top -= (top+divHeight+targetHeight/2 - viewportBottom + 5)
|
||||
}
|
||||
} else if (top+divHeight > viewportBottom) {
|
||||
d = 'top';
|
||||
top = targetPos.top-deltaSizes[size].topTop-divHeight;
|
||||
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftTop;
|
||||
}
|
||||
} else if (d === 'top') {
|
||||
top = targetPos.top-deltaSizes[size].topTop-divHeight;
|
||||
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftTop;
|
||||
if (top < 0) {
|
||||
d = 'bottom';
|
||||
top = targetPos.top+targetHeight+deltaSizes[size].top;
|
||||
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftBottom;
|
||||
}
|
||||
}
|
||||
div.addClass('red-ui-popover-'+d).css({top: top, left: left});
|
||||
if (existingPopover) {
|
||||
existingPopover.close(true);
|
||||
}
|
||||
if (options.trigger !== 'manual') {
|
||||
target.data("red-ui-popover",res)
|
||||
}
|
||||
if (options.tooltip) {
|
||||
div.on("mousedown", function(evt) {
|
||||
closePopup(true);
|
||||
@ -161,6 +113,102 @@ RED.popover = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
var movePopup = function(options) {
|
||||
target = options.target || target;
|
||||
direction = options.direction || direction || "right";
|
||||
popupOffset = options.offset || popupOffset;
|
||||
var transition = options.transition;
|
||||
|
||||
var width = options.width||"auto";
|
||||
div.width(width);
|
||||
if (options.maxWidth) {
|
||||
div.css("max-width",options.maxWidth)
|
||||
}
|
||||
|
||||
var targetPos = target[0].getBoundingClientRect();
|
||||
var targetHeight = targetPos.height;
|
||||
var targetWidth = targetPos.width;
|
||||
|
||||
var divHeight = div.outerHeight();
|
||||
var divWidth = div.outerWidth();
|
||||
var paddingRight = 10;
|
||||
|
||||
var viewportTop = $(window).scrollTop();
|
||||
var viewportLeft = $(window).scrollLeft();
|
||||
var viewportBottom = viewportTop + $(window).height();
|
||||
var viewportRight = viewportLeft + $(window).width();
|
||||
var top = 0;
|
||||
var left = 0;
|
||||
if (direction === 'right') {
|
||||
top = targetPos.top+targetHeight/2-divHeight/2;
|
||||
left = targetPos.left+targetWidth+deltaSizes[size].x+popupOffset;
|
||||
} else if (direction === 'left') {
|
||||
top = targetPos.top+targetHeight/2-divHeight/2;
|
||||
left = targetPos.left-deltaSizes[size].x-divWidth-popupOffset;
|
||||
} else if (direction === 'bottom') {
|
||||
top = targetPos.top+targetHeight+deltaSizes[size].y+popupOffset;
|
||||
left = targetPos.left+targetWidth/2-divWidth/2;
|
||||
if (left < 0) {
|
||||
direction = "right";
|
||||
top = targetPos.top+targetHeight/2-divHeight/2;
|
||||
left = targetPos.left+targetWidth+deltaSizes[size].x+popupOffset;
|
||||
} else if (left+divWidth+paddingRight > viewportRight) {
|
||||
direction = "left";
|
||||
top = targetPos.top+targetHeight/2-divHeight/2;
|
||||
left = targetPos.left-deltaSizes[size].x-divWidth-popupOffset;
|
||||
if (top+divHeight+targetHeight/2 + 5 > viewportBottom) {
|
||||
top -= (top+divHeight+targetHeight/2 - viewportBottom + 5)
|
||||
}
|
||||
} else if (top+divHeight > viewportBottom) {
|
||||
direction = 'top';
|
||||
top = targetPos.top-deltaSizes[size].y-divHeight-popupOffset;
|
||||
left = targetPos.left+targetWidth/2-divWidth/2;
|
||||
}
|
||||
} else if (direction === 'top') {
|
||||
top = targetPos.top-deltaSizes[size].y-divHeight-popupOffset;
|
||||
left = targetPos.left+targetWidth/2-divWidth/2;
|
||||
if (top < 0) {
|
||||
direction = 'bottom';
|
||||
top = targetPos.top+targetHeight+deltaSizes[size].y+popupOffset;
|
||||
left = targetPos.left+targetWidth/2-divWidth/2;
|
||||
}
|
||||
} else if (/inset/.test(direction)) {
|
||||
top = targetPos.top + targetHeight/2 - divHeight/2;
|
||||
left = targetPos.left + targetWidth/2 - divWidth/2;
|
||||
|
||||
if (/bottom/.test(direction)) {
|
||||
top = targetPos.top + targetHeight - divHeight-popupOffset;
|
||||
}
|
||||
if (/top/.test(direction)) {
|
||||
top = targetPos.top+popupOffset;
|
||||
}
|
||||
if (/left/.test(direction)) {
|
||||
left = targetPos.left+popupOffset;
|
||||
}
|
||||
if (/right/.test(direction)) {
|
||||
left = targetPos.left + targetWidth - divWidth-popupOffset;
|
||||
}
|
||||
}
|
||||
if (currentStyle) {
|
||||
div.removeClass(currentStyle);
|
||||
}
|
||||
if (transition) {
|
||||
div.css({
|
||||
"transition": "0.6s ease",
|
||||
"transition-property": "top,left,right,bottom"
|
||||
})
|
||||
}
|
||||
currentStyle = 'red-ui-popover-'+direction;
|
||||
div.addClass(currentStyle).css({top: top, left: left});
|
||||
if (transition) {
|
||||
setTimeout(function() {
|
||||
div.css({
|
||||
"transition": "none"
|
||||
});
|
||||
},600);
|
||||
}
|
||||
|
||||
}
|
||||
var closePopup = function(instant) {
|
||||
$(document).off('mousedown.red-ui-popover');
|
||||
if (!active) {
|
||||
@ -236,8 +284,10 @@ RED.popover = (function() {
|
||||
},autoClose);
|
||||
}
|
||||
var res = {
|
||||
get element() { return div },
|
||||
setContent: function(_content) {
|
||||
content = _content;
|
||||
|
||||
return res;
|
||||
},
|
||||
open: function (instant) {
|
||||
@ -249,6 +299,10 @@ RED.popover = (function() {
|
||||
active = false;
|
||||
closePopup(instant);
|
||||
return res;
|
||||
},
|
||||
move: function(options) {
|
||||
movePopup(options);
|
||||
return
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
@ -1409,7 +1409,7 @@ RED.editor = (function() {
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
|
||||
function showEditSubflowDialog(subflow) {
|
||||
function showEditSubflowDialog(subflow, defaultTab) {
|
||||
if (buildingEditDialog) { return }
|
||||
buildingEditDialog = true;
|
||||
var editing_node = subflow;
|
||||
@ -1549,7 +1549,7 @@ RED.editor = (function() {
|
||||
'editor-tab-appearance'
|
||||
];
|
||||
|
||||
prepareEditDialog(trayBody, nodeEditPanes, subflow, subflow._def, "node-input", null, function(_activeEditPanes) {
|
||||
prepareEditDialog(trayBody, nodeEditPanes, subflow, subflow._def, "node-input", defaultTab, function(_activeEditPanes) {
|
||||
activeEditPanes = _activeEditPanes;
|
||||
$("#subflow-input-name").val(subflow.name);
|
||||
RED.text.bidi.prepareInput($("#subflow-input-name"));
|
||||
@ -1579,7 +1579,7 @@ RED.editor = (function() {
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
|
||||
function showEditGroupDialog(group) {
|
||||
function showEditGroupDialog(group, defaultTab) {
|
||||
if (buildingEditDialog) { return }
|
||||
buildingEditDialog = true;
|
||||
var editing_node = group;
|
||||
@ -1661,7 +1661,7 @@ RED.editor = (function() {
|
||||
'editor-tab-envProperties',
|
||||
'editor-tab-description'
|
||||
];
|
||||
prepareEditDialog(trayBody, nodeEditPanes, group,group._def,"node-input", null, function(_activeEditPanes) {
|
||||
prepareEditDialog(trayBody, nodeEditPanes, group,group._def,"node-input", defaultTab, function(_activeEditPanes) {
|
||||
activeEditPanes = _activeEditPanes;
|
||||
trayBody.i18n();
|
||||
buildingEditDialog = false;
|
||||
@ -1692,7 +1692,7 @@ RED.editor = (function() {
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
|
||||
function showEditFlowDialog(workspace) {
|
||||
function showEditFlowDialog(workspace, defaultTab) {
|
||||
if (buildingEditDialog) { return }
|
||||
buildingEditDialog = true;
|
||||
var activeEditPanes = [];
|
||||
@ -1796,8 +1796,7 @@ RED.editor = (function() {
|
||||
disabledIcon: "fa-ban",
|
||||
invertState: true
|
||||
})
|
||||
|
||||
prepareEditDialog(trayBody, nodeEditPanes, workspace, {}, "node-input", null, function(_activeEditPanes) {
|
||||
prepareEditDialog(trayBody, nodeEditPanes, workspace, {}, "node-input", defaultTab, function(_activeEditPanes) {
|
||||
activeEditPanes = _activeEditPanes;
|
||||
trayBody.i18n();
|
||||
trayFooter.i18n();
|
||||
|
@ -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,
|
||||
|
410
packages/node_modules/@node-red/editor-client/src/js/ui/tour/tourGuide.js
vendored
Normal file
410
packages/node_modules/@node-red/editor-client/src/js/ui/tour/tourGuide.js
vendored
Normal file
@ -0,0 +1,410 @@
|
||||
RED.tourGuide = (function() {
|
||||
var activeListeners = [];
|
||||
var shade;
|
||||
var focus;
|
||||
var popover;
|
||||
var stepContent;
|
||||
var targetElement;
|
||||
var fullscreen;
|
||||
|
||||
var tourCache = {};
|
||||
|
||||
function run(tourPath, done) {
|
||||
done = done || function(err) {
|
||||
if (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]) {
|
||||
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;
|
||||
done(null, tourCache[tourPath]);
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
})
|
||||
/* jshint ignore:end */
|
||||
}
|
||||
}
|
||||
|
||||
function repositionFocus() {
|
||||
if (targetElement) {
|
||||
var pos = targetElement[0].getBoundingClientRect();
|
||||
var dimension = Math.max(50, Math.max(pos.width,pos.height)*1.5);
|
||||
if (!fullscreen) {
|
||||
focus.css({
|
||||
left: (pos.left+pos.width/2)+"px",
|
||||
top: (pos.top+pos.height/2)+"px",
|
||||
width: (2*dimension)+"px",
|
||||
height: (2*dimension)+"px"
|
||||
})
|
||||
var flush = focus[0].offsetHeight; // Flush CSS changes
|
||||
focus.addClass("transition");
|
||||
focus.css({
|
||||
width: dimension+"px",
|
||||
height: dimension+"px"
|
||||
})
|
||||
} else {
|
||||
focus.css({
|
||||
left: ($(window).width()/2)+"px",
|
||||
top: ($(window).height()/2)+"px",
|
||||
width: "0px",
|
||||
height: "0px"
|
||||
})
|
||||
}
|
||||
if (popover) {
|
||||
popover.move({
|
||||
target: targetElement,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
function runTour(tour, done) {
|
||||
|
||||
shade = $('<div class="red-ui-tourGuide-shade"></div>').appendTo(document.body);
|
||||
focus = $('<div class="red-ui-tourGuide-shade-focus"></div>').appendTo(shade);
|
||||
|
||||
// var resizeTimer;
|
||||
//
|
||||
$(window).on("resize.red-ui-tourGuide", function() {
|
||||
repositionFocus();
|
||||
})
|
||||
|
||||
|
||||
|
||||
var i = 0;
|
||||
var state = {
|
||||
index: 0,
|
||||
count: tour.steps.length
|
||||
};
|
||||
|
||||
function endTour(err) {
|
||||
$(window).off("resize.red-ui-tourGuide");
|
||||
$(document).off('keydown.red-ui-tourGuide');
|
||||
if (popover) {
|
||||
popover.close();
|
||||
}
|
||||
stepContent = null;
|
||||
popover = null;
|
||||
shade.remove();
|
||||
shade = null;
|
||||
done(err);
|
||||
}
|
||||
function runStep(carryOn) {
|
||||
if (carryOn === false) {
|
||||
endTour(false);
|
||||
return;
|
||||
}
|
||||
if (i === tour.steps.length) {
|
||||
endTour();
|
||||
return
|
||||
}
|
||||
state.index = i;
|
||||
// console.log("TOUR STEP",i+1,"OF",tour.steps.length)
|
||||
try {
|
||||
runTourStep(tour.steps[i++], state, runStep)
|
||||
} catch(err) {
|
||||
endTour(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
runStep();
|
||||
}
|
||||
|
||||
function clearListeners() {
|
||||
activeListeners.forEach(function(listener) {
|
||||
if (listener.type === "dom-event") {
|
||||
listener.target[0].removeEventListener(listener.event,listener.listener,listener.opts);
|
||||
} else if (listener.type === "nr-event") {
|
||||
RED.events.off(listener.event, listener.listener)
|
||||
}
|
||||
})
|
||||
activeListeners = [];
|
||||
}
|
||||
|
||||
function prepareStep(step, state, done) {
|
||||
if (step.prepare) {
|
||||
if (step.prepare.length === 0) {
|
||||
step.prepare.call(state);
|
||||
} else {
|
||||
step.prepare.call(state, done)
|
||||
return;
|
||||
}
|
||||
}
|
||||
done();
|
||||
}
|
||||
function completeStep(step, state, done) {
|
||||
function finish() {
|
||||
clearListeners();
|
||||
setTimeout(function() {
|
||||
done();
|
||||
},0)
|
||||
}
|
||||
if (step.complete) {
|
||||
if (step.complete.length === 0) {
|
||||
step.complete.call(state);
|
||||
} else {
|
||||
step.complete.call(state, finish)
|
||||
return;
|
||||
}
|
||||
}
|
||||
finish();
|
||||
|
||||
}
|
||||
function getLocaleText(property) {
|
||||
if (typeof property === 'string') {
|
||||
return property;
|
||||
}
|
||||
var currentLang = RED.i18n.lang() || 'en-US';
|
||||
var availableLangs = Object.keys(property);
|
||||
return property[currentLang]||property['en-US']||property[availableLangs[0]]
|
||||
|
||||
}
|
||||
function runTourStep(step, state, done) {
|
||||
shade.fadeIn();
|
||||
prepareStep(step, state, function() {
|
||||
var zIndex;
|
||||
var direction = step.direction || "bottom";
|
||||
fullscreen = false;
|
||||
|
||||
if (typeof step.element === "string") {
|
||||
targetElement = $(step.element)
|
||||
} else if (typeof step.element === "function") {
|
||||
targetElement = step.element.call(state);
|
||||
} else if (!step.element) {
|
||||
targetElement = $(".red-ui-editor")
|
||||
fullscreen = true;
|
||||
direction = "inset";
|
||||
} else {
|
||||
targetElement = step.element;
|
||||
}
|
||||
|
||||
if (targetElement.length === 0) {
|
||||
targetElement = null;
|
||||
shade.hide();
|
||||
throw new Error("Element not found")
|
||||
}
|
||||
if ($(window).width() < 400) {
|
||||
targetElement = $(".red-ui-editor");
|
||||
fullscreen = true;
|
||||
direction = "inset";
|
||||
}
|
||||
|
||||
zIndex = targetElement.css("z-index");
|
||||
if (!fullscreen) {
|
||||
targetElement.css("z-index",2002);
|
||||
}
|
||||
repositionFocus();
|
||||
focus.toggleClass("disableInteraction", step.interactive === false)
|
||||
|
||||
if (!stepContent) {
|
||||
stepContent = $('<div style="position:relative"></div>');
|
||||
} else {
|
||||
stepContent.empty();
|
||||
}
|
||||
$('<button type="button" class="red-ui-button red-ui-button-small" style="float: right; margin-top: -4px; margin-right: -4px;"><i class="fa fa-times"></i></button>').appendTo(stepContent).click(function(evt) {
|
||||
evt.preventDefault();
|
||||
completeStep(step, state, function() {
|
||||
done(false);
|
||||
});
|
||||
})
|
||||
|
||||
var stepDescription = $('<div class="red-ui-tourGuide-popover-description"></div>').appendTo(stepContent);
|
||||
if (step.titleIcon) {
|
||||
$('<h2><i class="'+step.titleIcon+'"></i></h2>').appendTo(stepDescription);
|
||||
}
|
||||
if (step.title) {
|
||||
$('<h2>').text(getLocaleText(step.title)).appendTo(stepDescription);
|
||||
}
|
||||
$('<div>').css("text-align","left").html(getLocaleText(step.description)).appendTo(stepDescription);
|
||||
|
||||
var stepToolbar = $('<div>',{class:"red-ui-tourGuide-toolbar"}).appendTo(stepContent);
|
||||
|
||||
// var breadcrumbs = $('<div>',{class:"red-ui-tourGuide-breadcrumbs"}).appendTo(stepToolbar);
|
||||
// var bcStart = Math.max(0,state.index - 3);
|
||||
// var bcEnd = Math.min(state.count, bcStart + 7);
|
||||
// if (bcEnd === state.count) {
|
||||
// bcStart = Math.max(0,bcEnd - 7);
|
||||
// }
|
||||
// for (var i = bcStart; i < bcEnd; i++) {
|
||||
// var bullet = $('<i class="fa"></i>').addClass(i===state.index ? "fa-circle":"fa-circle-o").appendTo(breadcrumbs);
|
||||
// if (i === bcStart) {
|
||||
// if (i > 1) {
|
||||
// bullet.css("font-size", "3px");
|
||||
// } else if (i === 1) {
|
||||
// bullet.css("font-size", "4px");
|
||||
// }
|
||||
// } else if (i === bcStart + 1) {
|
||||
// if (i > 2) {
|
||||
// bullet.css("font-size", "4px");
|
||||
// }
|
||||
// }
|
||||
// if (i === bcEnd - 1) {
|
||||
// if (i < state.count - 2) {
|
||||
// bullet.css("font-size", "3px");
|
||||
// } else if (i === state.count - 2) {
|
||||
// bullet.css("font-size", "4px");
|
||||
// }
|
||||
// } else if (i === bcEnd - 2) {
|
||||
// if (i < state.count - 3) {
|
||||
// bullet.css("font-size", "4px");
|
||||
// }
|
||||
// }
|
||||
// // if (i === bcEnd - 1) {
|
||||
// // if (i < state.count - 2) {
|
||||
// // bullet.css("font-size", "3px");
|
||||
// // } else if (i === state.count - 2) {
|
||||
// // bullet.css("font-size", "4px");
|
||||
// // }
|
||||
// // }
|
||||
// }
|
||||
|
||||
$('<small>').text((state.index+1)+"/"+state.count).appendTo(stepToolbar)
|
||||
var nextButton;
|
||||
if (fullscreen || !step.wait) {
|
||||
nextButton = $('<button type="button" class="red-ui-button" style="position: absolute; right:0;bottom:0;"></button>').appendTo(stepToolbar).one('click',function(evt) {
|
||||
evt.preventDefault();
|
||||
stepEventListener();
|
||||
});
|
||||
if (state.index === state.count - 1) {
|
||||
$('<span></span>').text(RED._("common.label.close")).appendTo(nextButton);
|
||||
} else if (state.index === 0) {
|
||||
$('<span>start</span>').text(RED._("tourGuide.start")).appendTo(nextButton);
|
||||
} else if (state.index < state.count-1) {
|
||||
$('<span></span>').text(RED._("tourGuide.next")).appendTo(nextButton);
|
||||
$('<span style="margin-left: 4px"><i class="fa fa-chevron-right"></i></span>').appendTo(nextButton);
|
||||
}
|
||||
}
|
||||
|
||||
var width = step.width;
|
||||
if (fullscreen) {
|
||||
width = 500;
|
||||
}
|
||||
var maxWidth = Math.min($(window).width()-10,Math.max(width || 0, 300));
|
||||
if (!popover) {
|
||||
popover = RED.popover.create({
|
||||
target: targetElement,
|
||||
width: width || "auto",
|
||||
maxWidth: maxWidth+"px",
|
||||
direction: direction,
|
||||
class: "red-ui-tourGuide-popover"+(fullscreen?" ":""),
|
||||
trigger: "manual",
|
||||
content: stepContent
|
||||
}).open();
|
||||
}
|
||||
$(document).off('keydown.red-ui-tourGuide');
|
||||
$(document).on('keydown.red-ui-tourGuide', function(evt) {
|
||||
if (evt.key === "Escape" || evt.key === "Esc") {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
completeStep(step, state, function() {
|
||||
done(false);
|
||||
});
|
||||
}
|
||||
})
|
||||
popover.element.toggleClass("red-ui-tourGuide-popover-full",!!fullscreen);
|
||||
popover.move({
|
||||
target: targetElement,
|
||||
width: width || "auto",
|
||||
maxWidth: maxWidth+"px",
|
||||
direction: direction,
|
||||
})
|
||||
|
||||
if (nextButton) {
|
||||
setTimeout(function() {
|
||||
nextButton.focus();
|
||||
},50);
|
||||
}
|
||||
|
||||
var isSVG = targetElement[0] instanceof SVGElement;
|
||||
if (step.fallback) {
|
||||
focus.one("mouseenter", function(evt) {
|
||||
setTimeout(function() {
|
||||
focus.css({
|
||||
width: (4*dimension)+"px",
|
||||
height: (4*dimension)+"px"
|
||||
})
|
||||
shade.fadeOut();
|
||||
popover.move({
|
||||
target: $(".red-ui-editor"),
|
||||
direction: step.fallback,
|
||||
offset: 10,
|
||||
transition: true
|
||||
})
|
||||
// popover.element.addClass('red-ui-tourGuide-popover-bounce');
|
||||
},isSVG?0:500);
|
||||
})
|
||||
}
|
||||
|
||||
var stepEventListener = function() {
|
||||
focus.removeClass("transition");
|
||||
targetElement.css("z-index",zIndex);
|
||||
completeStep(step, state, done);
|
||||
}
|
||||
|
||||
if (step.wait) {
|
||||
if (step.wait.type === "dom-event") {
|
||||
var eventTarget = targetElement;
|
||||
if (step.wait.element) {
|
||||
if (typeof step.wait.element === "string") {
|
||||
eventTarget = $(step.wait.element);
|
||||
} else if (typeof step.wait.element === "function") {
|
||||
eventTarget = step.wait.element.call(state);
|
||||
}
|
||||
}
|
||||
var listener = {
|
||||
type: step.wait.type,
|
||||
target: eventTarget,
|
||||
event: step.wait.event,
|
||||
listener: function() {
|
||||
stepEventListener();
|
||||
},
|
||||
opts: { once: true }
|
||||
}
|
||||
activeListeners.push(listener)
|
||||
eventTarget[0].addEventListener(listener.event,listener.listener,listener.opts)
|
||||
} else if (step.wait.type === "nr-event") {
|
||||
var listener = {
|
||||
type: step.wait.type,
|
||||
event: step.wait.event,
|
||||
listener: function() {
|
||||
if (step.wait.filter) {
|
||||
if (!step.wait.filter.apply(state,arguments)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
stepEventListener();
|
||||
}
|
||||
}
|
||||
activeListeners.push(listener);
|
||||
RED.events.on(listener.event,listener.listener);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
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}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
@ -140,8 +140,8 @@ $workspace-button-color-focus-outline: $form-input-focus-color;
|
||||
|
||||
$shade-color: rgba(160,160,160,0.5);
|
||||
|
||||
|
||||
$popover-background: #333;
|
||||
$popover-border: $popover-background;
|
||||
$popover-color: #eee;
|
||||
$popover-button-border-color: #bbb;
|
||||
$popover-button-border-color-hover: #666;
|
||||
@ -295,6 +295,10 @@ $group-default-stroke: #999;
|
||||
$group-default-stroke-opacity: 1;
|
||||
$group-default-label-color: #a4a4a4;
|
||||
|
||||
$tourGuide-shade: $shade-color;
|
||||
$tourGuide-border: #a22222;
|
||||
$tourGuide-heading-color: #a22222;
|
||||
|
||||
// Deprecated
|
||||
$text-color-green: $text-color-success;
|
||||
$info-text-code-color: $text-color-code;
|
||||
|
@ -132,6 +132,7 @@
|
||||
|
||||
|
||||
.red-ui-menu-dropdown > li > a:hover,
|
||||
.red-ui-menu-dropdown > li.open > a,
|
||||
.red-ui-menu-dropdown > li > a:focus,
|
||||
.red-ui-menu-dropdown-submenu:hover > a,
|
||||
.red-ui-menu-dropdown-submenu:focus > a {
|
||||
@ -148,6 +149,7 @@
|
||||
margin-top: -6px;
|
||||
margin-left: -1px;
|
||||
}
|
||||
&.open > .red-ui-menu-dropdown,
|
||||
&:hover > .red-ui-menu-dropdown {
|
||||
display: block;
|
||||
}
|
||||
|
@ -224,6 +224,7 @@
|
||||
}
|
||||
}
|
||||
> li > a:hover,
|
||||
> li.open > a,
|
||||
> li > a:focus,
|
||||
> li:hover > a,
|
||||
> li:focus > a {
|
||||
|
@ -19,19 +19,23 @@
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: auto;
|
||||
padding: 10px;
|
||||
padding: 2px;
|
||||
height: auto;
|
||||
background: $popover-background;
|
||||
color: $popover-color;
|
||||
background: var(--red-ui-popover-border);
|
||||
color: var(--red-ui-popover-color);
|
||||
border-radius: 4px;
|
||||
z-index: 1000;
|
||||
font-family: $primary-font;
|
||||
font-size: 14px;
|
||||
line-height: 1.4em;
|
||||
@include component-shadow;
|
||||
border-color: $popover-background;
|
||||
border-color: var(--red-ui-popover-border);
|
||||
}
|
||||
.red-ui-popover-content {
|
||||
padding: 8px;
|
||||
border-radius: 2px;
|
||||
background: var(--red-ui-popover-background);
|
||||
}
|
||||
|
||||
.red-ui-popover:after, .red-ui-popover:before {
|
||||
border: solid transparent;
|
||||
content: " ";
|
||||
@ -61,26 +65,26 @@
|
||||
|
||||
.red-ui-popover.red-ui-popover-right:after {
|
||||
border-color: transparent;
|
||||
border-right-color: $popover-background;
|
||||
border-right-color: var(--red-ui-popover-border);
|
||||
border-width: 10px;
|
||||
margin-top: -10px;
|
||||
}
|
||||
.red-ui-popover.red-ui-popover-right:before {
|
||||
border-color: transparent;
|
||||
border-right-color: $popover-background;
|
||||
border-right-color: var(--red-ui-popover-border);
|
||||
border-width: 11px;
|
||||
margin-top: -11px;
|
||||
}
|
||||
|
||||
.red-ui-popover.red-ui-popover-left:after {
|
||||
border-color: transparent;
|
||||
border-left-color: $popover-background;
|
||||
border-left-color: var(--red-ui-popover-border);
|
||||
border-width: 10px;
|
||||
margin-top: -10px;
|
||||
}
|
||||
.red-ui-popover.red-ui-popover-left:before {
|
||||
border-color: transparent;
|
||||
border-left-color: $popover-background;
|
||||
border-left-color: var(--red-ui-popover-border);
|
||||
border-width: 11px;
|
||||
margin-top: -11px;
|
||||
}
|
||||
@ -88,26 +92,26 @@
|
||||
|
||||
.red-ui-popover.red-ui-popover-bottom:after {
|
||||
border-color: transparent;
|
||||
border-bottom-color: $popover-background;
|
||||
border-bottom-color: var(--red-ui-popover-border);
|
||||
border-width: 10px;
|
||||
margin-left: -10px;
|
||||
}
|
||||
.red-ui-popover.red-ui-popover-bottom:before {
|
||||
border-color: transparent;
|
||||
border-bottom-color: $popover-background;
|
||||
border-bottom-color: var(--red-ui-popover-border);
|
||||
border-width: 11px;
|
||||
margin-left: -11px;
|
||||
}
|
||||
|
||||
.red-ui-popover.red-ui-popover-top:after {
|
||||
border-color: transparent;
|
||||
border-top-color: $popover-background;
|
||||
border-top-color: var(--red-ui-popover-border);
|
||||
border-width: 10px;
|
||||
margin-left: -10px;
|
||||
}
|
||||
.red-ui-popover.red-ui-popover-top:before {
|
||||
border-color: transparent;
|
||||
border-top-color: $popover-background;
|
||||
border-top-color: var(--red-ui-popover-border);
|
||||
border-width: 11px;
|
||||
margin-left: -11px;
|
||||
}
|
||||
@ -116,9 +120,10 @@
|
||||
|
||||
.red-ui-popover-size-small {
|
||||
font-size: 12px;
|
||||
padding: 5px 7px;
|
||||
line-height: 1.8em;
|
||||
|
||||
.red-ui-popover-content {
|
||||
padding: 1px 4px;
|
||||
}
|
||||
&.red-ui-popover-right:after, &.red-ui-popover-left:after {
|
||||
border-width: 7px;
|
||||
margin-top: -7px;
|
||||
@ -143,7 +148,7 @@
|
||||
font-size: 11px;
|
||||
font-family: $monospace-font;
|
||||
margin-left: 3px;
|
||||
border: 1px solid $popover-color;
|
||||
border: 1px solid var(--red-ui-popover-color);
|
||||
border-radius:3px;
|
||||
padding: 1px 2px;
|
||||
}
|
||||
@ -152,8 +157,8 @@
|
||||
.red-ui-popover button.red-ui-button {
|
||||
&:not(.primary) {
|
||||
border-color: $popover-button-border-color;
|
||||
background: $popover-background;
|
||||
color: $popover-color !important;
|
||||
background: var(--red-ui-popover-background);
|
||||
color: var(--red-ui-popover-color) !important;
|
||||
}
|
||||
&:not(.primary):not(.disabled):not(.ui-button-disabled):hover {
|
||||
border-color: $popover-button-border-color-hover;
|
||||
|
@ -69,3 +69,5 @@
|
||||
@import "debug";
|
||||
|
||||
@import "radialMenu";
|
||||
|
||||
@import "tourGuide";
|
||||
|
122
packages/node_modules/@node-red/editor-client/src/sass/tourGuide.scss
vendored
Normal file
122
packages/node_modules/@node-red/editor-client/src/sass/tourGuide.scss
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
.red-ui-tourGuide-shade {
|
||||
position: absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
bottom:0;
|
||||
right:0;
|
||||
z-index: 2000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.red-ui-tourGuide-shade-focus {
|
||||
display: block;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
position: absolute;
|
||||
z-index: 2001;
|
||||
transform: translate(-50%, -50%);
|
||||
border-radius: 50%;
|
||||
border: 2px solid $tourGuide-border;
|
||||
|
||||
&.transition {
|
||||
transition: 0.4s ease;
|
||||
transition-property: width,height;
|
||||
}
|
||||
|
||||
&.disableInteraction {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
border: solid 6000px $tourGuide-shade;
|
||||
margin-left: -6000px;
|
||||
margin-top: -6000px;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
.red-ui-popover.red-ui-tourGuide-popover {
|
||||
z-index: 2003;
|
||||
--red-ui-popover-background: #{$secondary-background};
|
||||
--red-ui-popover-border: #{$tourGuide-border};
|
||||
--red-ui-popover-color: #{$primary-text-color};
|
||||
|
||||
.red-ui-popover-content {
|
||||
h2 {
|
||||
text-align: center;
|
||||
margin-top: 0px;
|
||||
color: #a22222;
|
||||
i.fa {
|
||||
font-size: 1.5em
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.red-ui-tourGuide-toolbar {
|
||||
min-height: 36px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.red-ui-tourGuide-breadcrumbs {
|
||||
flex-grow: 1;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 6px;
|
||||
& > div {
|
||||
display: inline-block;
|
||||
}
|
||||
i {
|
||||
line-height: 16px;
|
||||
margin: 0 3px;
|
||||
}
|
||||
}
|
||||
.red-ui-tourGuide-popover-description {
|
||||
padding: 10px 20px 5px;
|
||||
}
|
||||
.red-ui-tourGuide-popover-full {
|
||||
.red-ui-tourGuide-popover-description {
|
||||
padding: 20px 40px 10px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.red-ui-popover.red-ui-tourGuide-popover button.red-ui-button {
|
||||
&:not(.primary) {
|
||||
border-color: transparent;
|
||||
background: $secondary-background;
|
||||
color: $primary-text-color !important;
|
||||
}
|
||||
&:not(.primary):not(.disabled):not(.ui-button-disabled):hover {
|
||||
border-color: $popover-button-border-color-hover;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// .red-ui-tourGuide-popover-bounce {
|
||||
// animation: 10s ease-in 5s infinite both red-ui-tourGuide-popover-bounce;
|
||||
// }
|
||||
// // @keyframes *must* be on multiple lines so build-custom-theme can filter them out
|
||||
// @keyframes red-ui-tourGuide-popover-bounce {
|
||||
// 0%,
|
||||
// 10%,
|
||||
// 100% {
|
||||
// -webkit-transform: translateY(0);
|
||||
// transform: translateY(0);
|
||||
// }
|
||||
// 2%,8% {
|
||||
// -webkit-transform: translateY(-5px);
|
||||
// transform: translateY(-5px);
|
||||
// }
|
||||
// 5% {
|
||||
// -webkit-transform: translateY(5px);
|
||||
// transform: translateY(5px);
|
||||
// }
|
||||
// }
|
@ -81,12 +81,15 @@
|
||||
--red-ui-node-status-changed-border: #{$node-status-changed-border};
|
||||
--red-ui-node-status-changed-background: #{$node-status-changed-background};
|
||||
|
||||
|
||||
|
||||
--red-ui-node-border: #{$node-border};
|
||||
--red-ui-node-port-background:#{$node-port-background};
|
||||
|
||||
--red-ui-node-label-color: #{$node-label-color};
|
||||
--red-ui-node-selected-color: #{$node-selected-color};
|
||||
--red-ui-port-selected-color: #{$port-selected-color};
|
||||
|
||||
--red-ui-popover-background: #{$popover-background};
|
||||
--red-ui-popover-border: #{$popover-border};
|
||||
--red-ui-popover-color: #{$popover-color};
|
||||
|
||||
}
|
||||
|
80
packages/node_modules/@node-red/editor-client/src/tours/first-flow.js
vendored
Normal file
80
packages/node_modules/@node-red/editor-client/src/tours/first-flow.js
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
export default {
|
||||
steps: [
|
||||
{
|
||||
title: "Create your first flow",
|
||||
width: 400,
|
||||
description: 'This tutorial will guide you through creating your first flow',
|
||||
nextButton: 'start'
|
||||
},
|
||||
{
|
||||
element: "#red-ui-workspace .red-ui-tab-button.red-ui-tabs-add",
|
||||
description: 'To add a new tab, click the <i class="fa fa-plus"></i> button',
|
||||
wait: {
|
||||
type: "dom-event",
|
||||
event: "click",
|
||||
element: "#red-ui-workspace .red-ui-tab-button.red-ui-tabs-add a"
|
||||
},
|
||||
},
|
||||
{
|
||||
element: '.red-ui-palette-node[data-palette-type="inject"]',
|
||||
direction: 'right',
|
||||
description: 'The palette lists all of the nodes available to use. Drag a new Inject node into the workspace.',
|
||||
fallback: 'inset-bottom-right',
|
||||
wait: {
|
||||
type: "nr-event",
|
||||
event: "nodes:add",
|
||||
filter: function(event) {
|
||||
if (event.type === "inject") {
|
||||
this.injectNode = event;
|
||||
return true;
|
||||
}
|
||||
return false
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
$('.red-ui-palette-node[data-palette-type="inject"]').css("z-index","auto");
|
||||
}
|
||||
},
|
||||
{
|
||||
element: '.red-ui-palette-node[data-palette-type="debug"]',
|
||||
direction: 'right',
|
||||
description: 'Next, drag a new Debug node into the workspace.',
|
||||
fallback: 'inset-bottom-right',
|
||||
wait: {
|
||||
type: "nr-event",
|
||||
event: "nodes:add",
|
||||
filter: function(event) {
|
||||
if (event.type === "debug") {
|
||||
this.debugNode = event;
|
||||
return true;
|
||||
}
|
||||
return false
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
$('.red-ui-palette-node[data-palette-type="debug"]').css("z-index","auto");
|
||||
},
|
||||
},
|
||||
{
|
||||
element: function() { return $("#"+this.injectNode.id+" .red-ui-flow-port") },
|
||||
description: 'Add a wire from the output of the Inject node to the input of the Debug node',
|
||||
fallback: 'inset-bottom-right',
|
||||
wait: {
|
||||
type: "nr-event",
|
||||
event: "links:add",
|
||||
filter: function(event) {
|
||||
return event.source.id === this.injectNode.id && event.target.id === this.debugNode.id;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
element: "#red-ui-header-button-deploy",
|
||||
description: 'Deploy your changes so the flow is active in the runtime',
|
||||
width: 200,
|
||||
wait: {
|
||||
type: "dom-event",
|
||||
event: "click"
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
70
packages/node_modules/@node-red/editor-client/src/tours/welcome.js
vendored
Normal file
70
packages/node_modules/@node-red/editor-client/src/tours/welcome.js
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
export default {
|
||||
version: "2.1.0",
|
||||
steps: [
|
||||
{
|
||||
titleIcon: "fa fa-map-o",
|
||||
title: { "en-US": "Welcome to Node-RED 2.1!" },
|
||||
description: { "en-US": "Let's take a moment to discover the new features in this release." }
|
||||
},
|
||||
{
|
||||
title: { "en-US": "A new Tour Guide" },
|
||||
description: { "en-US": "<p>First, as you've already found, we now have this tour of new features. We'll only show the tour the first time you open the editor for each new version of Node-RED.</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() {
|
||||
$("#red-ui-header-button-sidemenu").trigger("click");
|
||||
$("#menu-item-edit-menu").parent().addClass("open")
|
||||
},
|
||||
complete() {
|
||||
$("#menu-item-edit-menu").parent().removeClass("open")
|
||||
},
|
||||
element: "#menu-item-edit-menu-submenu",
|
||||
interactive: false,
|
||||
direction: "left",
|
||||
title: { "en-US": "New Edit menu" },
|
||||
description: { "en-US": "<p>The main menu has been updated with a new 'Edit' section. This includes all of the familar options, like cut/paste and undo/redo.</p>"+
|
||||
"<p>The menu now displays keyboard shortcuts for the options.</p>" }
|
||||
|
||||
},
|
||||
{
|
||||
prepare() {
|
||||
$("#red-ui-header-button-sidemenu").trigger("click");
|
||||
$("#menu-item-arrange-menu").parent().addClass("open")
|
||||
},
|
||||
complete() {
|
||||
$("#menu-item-arrange-menu").parent().removeClass("open")
|
||||
},
|
||||
element: "#menu-item-arrange-menu-submenu",
|
||||
interactive: false,
|
||||
direction: "left",
|
||||
title: { "en-US": "Arranging nodes" },
|
||||
description: { "en-US": "<p>The new 'Arrange' section of the menu provides new options to help arrange your nodes. You can align them to a common edge, spread them out evenly or change their order.</p>" },
|
||||
},
|
||||
{
|
||||
element: "#red-ui-workspace-tabs > li:first-child",
|
||||
title: { "en-US": "Flow and Group level environment variables" },
|
||||
description: { "en-US": "<p>Flows and Groups can now have their own environment variables that can be referenced by nodes inside them.</p>" },
|
||||
},
|
||||
{
|
||||
prepare(done) {
|
||||
RED.editor.editFlow(RED.nodes.workspace(RED.workspaces.active()),"editor-tab-envProperties");
|
||||
setTimeout(done,800);
|
||||
},
|
||||
element: "#red-ui-tab-editor-tab-envProperties-link-button",
|
||||
description: { "en-US": "<p>Flows and Groups now have an Environment Variables section in their edit dialog.</p>" },
|
||||
},
|
||||
{
|
||||
element: ".node-input-env-container-row .red-ui-editableList-addButton",
|
||||
direction: "top",
|
||||
description: { "en-US": '<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() {
|
||||
$("#node-dialog-cancel").trigger("click");
|
||||
}
|
||||
},
|
||||
{
|
||||
title: { "en-US": "And that's not all..." },
|
||||
description: { "en-US": "<p>There's more still to come before 2.1.0 is released. Watch this space!</p>" }
|
||||
},
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user