-
+
",{class:"form-row"});
+ $('
').appendTo(row); + $('').appendTo(row); + row.appendTo("#node-dialog-login-fields"); + } + $('').appendTo("#node-dialog-login-fields"); + $("#node-dialog-login-submit").button().click(function( event ) { + $("#node-dialog-login-submit").button("option","disabled",true); + $("#node-dialog-login-failed").hide(); + $(".login-spinner").show(); + $.ajax({ + url:"auth/token", + type: "POST", + data: { + grant_type: "password", + username: $("#node-dialog-login-username").val(), + password: $("#node-dialog-login-password").val(), + client_id: "node-red-admin", + scope:"*" + } + }).done(function(data,textStatus,xhr) { + $.ajaxSetup({ + headers:{"authorization":"bearer "+data.access_token} + }); + $("#node-dialog-login").dialog("close"); + load(); + }).fail(function(jqXHR,textStatus,errorThrown) { + $("#node-dialog-login-failed").show(); + }).always(function() { + $("#node-dialog-login-submit").button("option","disabled",false); + $(".login-spinner").hide(); + }); + event.preventDefault(); + }); + } + } + }); + + var dialog = $("#node-dialog-login"); + dialog.dialog({ + autoOpen: false, + dialogClass: "ui-dialog-no-close", + modal: true, + closeOnEscape: false, + width: 600, + resizable: false, + draggable: false, + open: function(event, ui) { console.log("opening");$(".ui-dialog-titlebar", ui.dialog || ui).hide(); } + }); + dialog.dialog("open"); + + } + }); + } $(function() { - RED.menu.init({id:"btn-sidemenu", - options: [ - {id:"btn-sidebar",label:"Sidebar",toggle:true,onselect:RED.sidebar.toggleSidebar, selected: true}, - {id:"btn-node-status",label:"Display node status",toggle:true,onselect:toggleStatus, selected: true}, - null, - {id:"btn-import-menu",label:"Import",options:[ - {id:"btn-import-clipboard",label:"Clipboard",onselect:RED.view.showImportNodesDialog}, - {id:"btn-import-library",label:"Library",options:[]} - ]}, - {id:"btn-export-menu",label:"Export",disabled:true,options:[ - {id:"btn-export-clipboard",label:"Clipboard",disabled:true,onselect:RED.view.showExportNodesDialog}, - {id:"btn-export-library",label:"Library",disabled:true,onselect:RED.view.showExportNodesLibraryDialog} - ]}, - null, - {id:"btn-config-nodes",label:"Configuration nodes",onselect:RED.sidebar.config.show}, - null, - {id:"btn-subflow-menu",label:"Subflows", options: [ - {id:"btn-create-subflow",label:"Create subflow",onselect:RED.view.createSubflow}, - {id:"btn-convert-subflow",label:"Selection to subflow",disabled:true,onselect:RED.view.convertToSubflow}, - ]}, - null, - {id:"btn-workspace-menu",label:"Workspaces",options:[ - {id:"btn-workspace-add",label:"Add"}, - {id:"btn-workspace-edit",label:"Rename"}, - {id:"btn-workspace-delete",label:"Delete"}, - null - ]}, - null, - {id:"btn-keyboard-shortcuts",label:"Keyboard Shortcuts",onselect:showHelp}, - {id:"btn-help",label:"Node-RED Website", href:"http://nodered.org/docs"} - ] - }); + + if ((window.location.hostname !== "localhost") && (window.location.hostname !== "127.0.0.1")) { + document.title = "Node-RED : "+window.location.hostname; + } + $("#btn-deploy").hide(); + $("#btn-sidemenu").hide(); - RED.menu.init({id:"btn-deploy-options", - options: [ - {id:"btn-deploy-full",toggle:"deploy-type",icon:"images/deploy-full.png",label:"Full",sublabel:"Deploys everything in the workspace",onselect:function(s) { if(s){changeDeploymentType("full")}}}, - {id:"btn-deploy-flow",toggle:"deploy-type",icon:"images/deploy-flows.png",label:"Modified Flows",sublabel:"Only deploys flows that contain changed nodes", onselect:function(s) {if(s){changeDeploymentType("flows")}}}, - {id:"btn-deploy-node",toggle:"deploy-type",icon:"images/deploy-nodes.png",label:"Modified Nodes",sublabel:"Only deploys nodes that have changed",onselect:function(s) { if(s){changeDeploymentType("nodes")}}} - ] - }); - - RED.menu.init({id:"workspace-subflow-edit-menu", - options: [ - {id:"btn-subflow-add-input",label:"Add Input", onselect:function() { }}, - {id:"btn-subflow-add-output",label:"Add Output", onselect:function() { }}, - {id:"btn-subflow-edit-name",label:"Edit Name", onselect:function() { }}, - {id:"btn-subflow-delete",label:"Delete", onselect:function() { }}, - ] - }); - - RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); - loadSettings(); - RED.comms.connect(); + load(); }); - if ((window.location.hostname !== "localhost") && (window.location.hostname !== "127.0.0.1")) { - document.title = "Node-RED : "+window.location.hostname; - } return { }; diff --git a/public/red/ui/library.js b/public/red/ui/library.js index 0329315f6..1757b659c 100644 --- a/public/red/ui/library.js +++ b/public/red/ui/library.js @@ -66,9 +66,6 @@ RED.library = (function() { $("#btn-import-library-submenu").replaceWith(menu); }); } - loadFlowLibrary(); - - function createUI(options) { var libraryData = {}; @@ -360,6 +357,9 @@ RED.library = (function() { } return { + init: function() { + loadFlowLibrary(); + }, create: createUI, loadFlowLibrary: loadFlowLibrary } diff --git a/public/red/ui/palette.js b/public/red/ui/palette.js index ecdb3c80c..42e096ba2 100644 --- a/public/red/ui/palette.js +++ b/public/red/ui/palette.js @@ -36,8 +36,6 @@ RED.palette = (function() { }); } - core.forEach(createCategoryContainer); - function setLabel(type, el,label) { var nodeWidth = 80; var nodeHeight = 25; @@ -241,32 +239,37 @@ RED.palette = (function() { }); } - $("#palette-search-input").focus(function(e) { - RED.keyboard.disable(); - }); - $("#palette-search-input").blur(function(e) { - RED.keyboard.enable(); - }); - - $("#palette-search-clear").on("click",function(e) { - e.preventDefault(); - $("#palette-search-input").val(""); - filterChange(); - $("#palette-search-input").focus(); - }); - - $("#palette-search-input").val(""); - $("#palette-search-input").on("keyup",function() { - filterChange(); - }); - - $("#palette-search-input").on("focus",function() { - $("body").one("mousedown",function() { - $("#palette-search-input").blur(); + function init() { + $(".palette-spinner").show(); + core.forEach(createCategoryContainer); + $("#palette-search-input").focus(function(e) { + RED.keyboard.disable(); }); - }); + $("#palette-search-input").blur(function(e) { + RED.keyboard.enable(); + }); + + $("#palette-search-clear").on("click",function(e) { + e.preventDefault(); + $("#palette-search-input").val(""); + filterChange(); + $("#palette-search-input").focus(); + }); + + $("#palette-search-input").val(""); + $("#palette-search-input").on("keyup",function() { + filterChange(); + }); + + $("#palette-search-input").on("focus",function() { + $("body").one("mousedown",function() { + $("#palette-search-input").blur(); + }); + }); + } return { + init: init, add:addNodeType, remove:removeNodeType, hide:hideNodeType, diff --git a/public/red/ui/sidebar.js b/public/red/ui/sidebar.js index ffc942c69..5e4bfb091 100644 --- a/public/red/ui/sidebar.js +++ b/public/red/ui/sidebar.js @@ -26,6 +26,7 @@ RED.sidebar = (function() { $("#"+tab.id).remove(); } }); + function addTab(title,content,closeable) { $("#sidebar-content").append(content); $(content).hide(); @@ -129,22 +130,23 @@ RED.sidebar = (function() { } function showSidebar(id) { - //RED.menu.setSelected("btn-sidebar", true); - sidebar_tabs.activateTab("tab-" + id); + if (id) { + sidebar_tabs.activateTab("tab-"+id); + } } function containsTab(id) { return sidebar_tabs.contains("tab-"+id); } - - $(function() { + function init () { RED.keyboard.add(/* SPACE */ 32,{ctrl:true},function(){RED.menu.setSelected("btn-sidebar",!RED.menu.isSelected("btn-sidebar"));d3.event.preventDefault();}); - showSidebar("info"); - }); - + showSidebar(); + RED.sidebar.info.show(); + } return { + init: init, addTab: addTab, removeTab: removeTab, show: showSidebar, diff --git a/public/red/ui/tab-info.js b/public/red/ui/tab-info.js index cba14d0ee..5de55bdbd 100644 --- a/public/red/ui/tab-info.js +++ b/public/red/ui/tab-info.js @@ -32,8 +32,13 @@ RED.sidebar.info = (function() { content.style.paddingLeft = "4px"; content.style.paddingRight = "4px"; - RED.sidebar.addTab("info",content); - + function show() { + if (!RED.sidebar.containsTab("info")) { + RED.sidebar.addTab("info",content,false); + } + RED.sidebar.show("info"); + } + function jsonFilter(key,value) { if (key === "") { return value; @@ -116,6 +121,7 @@ RED.sidebar.info = (function() { } return { + show: show, refresh:refresh, clear: function() { $("#tab-info").html(""); diff --git a/public/red/ui/view.js b/public/red/ui/view.js index 164ecbeeb..a5fd92e48 100644 --- a/public/red/ui/view.js +++ b/public/red/ui/view.js @@ -365,7 +365,8 @@ RED.view = (function() { RED.history.push({t:'add',workspaces:[ws],dirty:dirty}); RED.view.dirty(true); } - $(function() { + + function init() { $('#btn-workspace-add-tab').on("click",addWorkspace); RED.menu.setAction('btn-workspace-add',addWorkspace); @@ -375,7 +376,7 @@ RED.view = (function() { RED.menu.setAction('btn-workspace-delete',function() { deleteWorkspace(activeWorkspace); }); - }); + } function deleteWorkspace(id) { if (workspace_tabs.count() == 1) { @@ -2051,8 +2052,36 @@ RED.view = (function() { } }); + + function hideDropTarget() { + $("#dropTarget").hide(); + RED.keyboard.remove(/* ESCAPE */ 27); + } + $('#chart').on("dragenter",function(event) { + if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { + $("#dropTarget").css({display:'table'}); + RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget); + } + }); + + $('#dropTarget').on("dragover",function(event) { + if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { + event.preventDefault(); + } + }) + .on("dragleave",function(event) { + hideDropTarget(); + }) + .on("drop",function(event) { + var data = event.originalEvent.dataTransfer.getData("text/plain"); + hideDropTarget(); + RED.view.importNodes(data); + event.preventDefault(); + }); + return { + init: init, state:function(state) { if (state == null) { return mouse_mode diff --git a/red.js b/red.js index ff5886da8..f66b1c6fa 100644 --- a/red.js +++ b/red.js @@ -121,13 +121,14 @@ settings.flowFile = flowFile || settings.flowFile; RED.init(server,settings); -if (settings.httpAdminRoot !== false && settings.httpAdminAuth) { - app.use(settings.httpAdminRoot, - express.basicAuth(function(user, pass) { - return user === settings.httpAdminAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAdminAuth.pass; - }) - ); -} +//if (settings.httpAdminRoot !== false && settings.httpAdminAuth) { +// app.use(settings.httpAdminRoot, +// express.basicAuth(function(user, pass) { +// return user === settings.httpAdminAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAdminAuth.pass; +// }) +// ); +//} + if (settings.httpNodeRoot !== false && settings.httpNodeAuth) { app.use(settings.httpNodeRoot, express.basicAuth(function(user, pass) { diff --git a/red/api/auth/index.js b/red/api/auth/index.js index c3c1f7593..af20a481a 100644 --- a/red/api/auth/index.js +++ b/red/api/auth/index.js @@ -53,11 +53,20 @@ function getToken(req,res,next) { return server.token()(req,res,next); } +function login(req,res) { + var response = { + "type":"credentials", + "prompts":[{id:"username",type:"text",label:"Username"},{id:"password",type:"password",label:"Password"}] + } + + res.json(response); +} module.exports = { authenticate: authenticate, ensureClientSecret: ensureClientSecret, authenticateClient: authenticateClient, getToken: getToken, - errorHandler: server.errorHandler() + errorHandler: server.errorHandler(), + login: login } diff --git a/red/api/auth/strategies.js b/red/api/auth/strategies.js index 50be2303a..8300b47a6 100644 --- a/red/api/auth/strategies.js +++ b/red/api/auth/strategies.js @@ -29,7 +29,7 @@ var bearerStrategy = function (accessToken, done) { if (token) { users.get(token.user).then(function(user) { if (user) { - done(null,user,{scope:token.scope}); + done(null,{username:user.username},{scope:token.scope}); } else { done(null,false); } diff --git a/red/api/index.js b/red/api/index.js index 0dd4b6e84..24c5c039a 100644 --- a/red/api/index.js +++ b/red/api/index.js @@ -50,6 +50,7 @@ function init(adminApp) { auth.getToken, auth.errorHandler ); + apiApp.get("/auth/login",auth.login); // Flows apiApp.get("/flows",flows.get); diff --git a/red/api/info.js b/red/api/info.js index 8b77ef044..7a63f6a3a 100644 --- a/red/api/info.js +++ b/red/api/info.js @@ -19,7 +19,8 @@ module.exports = { settings: function(req,res) { var safeSettings = { httpNodeRoot: settings.httpNodeRoot, - version: settings.version + version: settings.version, + user: req.user }; res.json(safeSettings); } diff --git a/settings.js b/settings.js index 1bfacbe53..66f290d33 100644 --- a/settings.js +++ b/settings.js @@ -66,7 +66,7 @@ module.exports = { // You can protect the user interface with a userid and password by using the following property. // The password must be an md5 hash eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password') - //httpAdminAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, + httpAdminAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, // Some nodes, such as HTTP In, can be used to listen for incoming http requests. // By default, these are served relative to '/'. The following property
@@ -80,6 +80,7 @@
+
+Drop the flow here
@@ -238,6 +239,14 @@
+
+
+
+
diff --git a/public/red/main.js b/public/red/main.js
index ddc780023..528a82042 100644
--- a/public/red/main.js
+++ b/public/red/main.js
@@ -22,34 +22,6 @@ var RED = (function() {
}
var deploymentType = "full";
-
- function hideDropTarget() {
- $("#dropTarget").hide();
- RED.keyboard.remove(/* ESCAPE */ 27);
- }
-
- $('#chart').on("dragenter",function(event) {
- if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
- $("#dropTarget").css({display:'table'});
- RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget);
- }
- });
-
- $('#dropTarget').on("dragover",function(event) {
- if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
- event.preventDefault();
- }
- })
- .on("dragleave",function(event) {
- hideDropTarget();
- })
- .on("drop",function(event) {
- var data = event.originalEvent.dataTransfer.getData("text/plain");
- hideDropTarget();
- RED.view.importNodes(data);
- event.preventDefault();
- });
-
function save(force) {
if (RED.view.dirty()) {
//$("#debug-tab-clear").click(); // uncomment this to auto clear debug on deploy
@@ -290,72 +262,152 @@ var RED = (function() {
dialog.modal();
}
-
function changeDeploymentType(type) {
deploymentType = type;
$("#btn-deploy img").attr("src",deploymentTypes[type].img);
}
+
+ function load() {
+ RED.settings.init(function() {
+ RED.menu.init({id:"btn-sidemenu",
+ options: [
+ {id:"btn-sidebar",label:"Sidebar",toggle:true,onselect:RED.sidebar.toggleSidebar, selected: true},
+ {id:"btn-node-status",label:"Display node status",toggle:true,onselect:toggleStatus, selected: true},
+ null,
+ {id:"btn-import-menu",label:"Import",options:[
+ {id:"btn-import-clipboard",label:"Clipboard",onselect:RED.view.showImportNodesDialog},
+ {id:"btn-import-library",label:"Library",options:[]}
+ ]},
+ {id:"btn-export-menu",label:"Export",disabled:true,options:[
+ {id:"btn-export-clipboard",label:"Clipboard",disabled:true,onselect:RED.view.showExportNodesDialog},
+ {id:"btn-export-library",label:"Library",disabled:true,onselect:RED.view.showExportNodesLibraryDialog}
+ ]},
+ null,
+ {id:"btn-config-nodes",label:"Configuration nodes",onselect:RED.sidebar.config.show},
+ null,
+ {id:"btn-subflow-menu",label:"Subflows", options: [
+ {id:"btn-create-subflow",label:"Create subflow",onselect:RED.view.createSubflow},
+ {id:"btn-convert-subflow",label:"Selection to subflow",disabled:true,onselect:RED.view.convertToSubflow},
+ ]},
+ null,
+ {id:"btn-workspace-menu",label:"Workspaces",options:[
+ {id:"btn-workspace-add",label:"Add"},
+ {id:"btn-workspace-edit",label:"Rename"},
+ {id:"btn-workspace-delete",label:"Delete"},
+ null
+ ]},
+ null,
+ {id:"btn-keyboard-shortcuts",label:"Keyboard Shortcuts",onselect:showHelp},
+ {id:"btn-help",label:"Node-RED Website", href:"http://nodered.org/docs"}
+ ]
+ });
+
+ RED.menu.init({id:"btn-deploy-options",
+ options: [
+ {id:"btn-deploy-full",toggle:"deploy-type",icon:"images/deploy-full.png",label:"Full",sublabel:"Deploys everything in the workspace",onselect:function(s) { if(s){changeDeploymentType("full")}}},
+ {id:"btn-deploy-flow",toggle:"deploy-type",icon:"images/deploy-flows.png",label:"Modified Flows",sublabel:"Only deploys flows that contain changed nodes", onselect:function(s) {if(s){changeDeploymentType("flows")}}},
+ {id:"btn-deploy-node",toggle:"deploy-type",icon:"images/deploy-nodes.png",label:"Modified Nodes",sublabel:"Only deploys nodes that have changed",onselect:function(s) { if(s){changeDeploymentType("nodes")}}}
+ ]
+ });
+
+ RED.menu.init({id:"workspace-subflow-edit-menu",
+ options: [
+ {id:"btn-subflow-add-input",label:"Add Input", onselect:function() { }},
+ {id:"btn-subflow-add-output",label:"Add Output", onselect:function() { }},
+ {id:"btn-subflow-edit-name",label:"Edit Name", onselect:function() { }},
+ {id:"btn-subflow-delete",label:"Delete", onselect:function() { }},
+ ]
+ });
+
+ $("#main-container").show();
+ $("#btn-deploy").show();
+ $("#btn-sidemenu").show();
+
+ RED.library.init();
+ RED.palette.init();
+ RED.sidebar.init();
+ RED.view.init();
+
+ RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();});
+ RED.comms.connect();
+ loadNodeList();
+ },
+ function(err,msg) {
+ if (err == 401) {
+ $.ajax({
+ dataType: "json",
+ url: "auth/login",
+ success: function(data) {
+ if (data.type == "credentials") {
+ for (var i=0;i![](node-red-256.png)
+
+
+').appendTo(row); + $('').appendTo(row); + row.appendTo("#node-dialog-login-fields"); + } + $('').appendTo("#node-dialog-login-fields"); + $("#node-dialog-login-submit").button().click(function( event ) { + $("#node-dialog-login-submit").button("option","disabled",true); + $("#node-dialog-login-failed").hide(); + $(".login-spinner").show(); + $.ajax({ + url:"auth/token", + type: "POST", + data: { + grant_type: "password", + username: $("#node-dialog-login-username").val(), + password: $("#node-dialog-login-password").val(), + client_id: "node-red-admin", + scope:"*" + } + }).done(function(data,textStatus,xhr) { + $.ajaxSetup({ + headers:{"authorization":"bearer "+data.access_token} + }); + $("#node-dialog-login").dialog("close"); + load(); + }).fail(function(jqXHR,textStatus,errorThrown) { + $("#node-dialog-login-failed").show(); + }).always(function() { + $("#node-dialog-login-submit").button("option","disabled",false); + $(".login-spinner").hide(); + }); + event.preventDefault(); + }); + } + } + }); + + var dialog = $("#node-dialog-login"); + dialog.dialog({ + autoOpen: false, + dialogClass: "ui-dialog-no-close", + modal: true, + closeOnEscape: false, + width: 600, + resizable: false, + draggable: false, + open: function(event, ui) { console.log("opening");$(".ui-dialog-titlebar", ui.dialog || ui).hide(); } + }); + dialog.dialog("open"); + + } + }); + } $(function() { - RED.menu.init({id:"btn-sidemenu", - options: [ - {id:"btn-sidebar",label:"Sidebar",toggle:true,onselect:RED.sidebar.toggleSidebar, selected: true}, - {id:"btn-node-status",label:"Display node status",toggle:true,onselect:toggleStatus, selected: true}, - null, - {id:"btn-import-menu",label:"Import",options:[ - {id:"btn-import-clipboard",label:"Clipboard",onselect:RED.view.showImportNodesDialog}, - {id:"btn-import-library",label:"Library",options:[]} - ]}, - {id:"btn-export-menu",label:"Export",disabled:true,options:[ - {id:"btn-export-clipboard",label:"Clipboard",disabled:true,onselect:RED.view.showExportNodesDialog}, - {id:"btn-export-library",label:"Library",disabled:true,onselect:RED.view.showExportNodesLibraryDialog} - ]}, - null, - {id:"btn-config-nodes",label:"Configuration nodes",onselect:RED.sidebar.config.show}, - null, - {id:"btn-subflow-menu",label:"Subflows", options: [ - {id:"btn-create-subflow",label:"Create subflow",onselect:RED.view.createSubflow}, - {id:"btn-convert-subflow",label:"Selection to subflow",disabled:true,onselect:RED.view.convertToSubflow}, - ]}, - null, - {id:"btn-workspace-menu",label:"Workspaces",options:[ - {id:"btn-workspace-add",label:"Add"}, - {id:"btn-workspace-edit",label:"Rename"}, - {id:"btn-workspace-delete",label:"Delete"}, - null - ]}, - null, - {id:"btn-keyboard-shortcuts",label:"Keyboard Shortcuts",onselect:showHelp}, - {id:"btn-help",label:"Node-RED Website", href:"http://nodered.org/docs"} - ] - }); + + if ((window.location.hostname !== "localhost") && (window.location.hostname !== "127.0.0.1")) { + document.title = "Node-RED : "+window.location.hostname; + } + $("#btn-deploy").hide(); + $("#btn-sidemenu").hide(); - RED.menu.init({id:"btn-deploy-options", - options: [ - {id:"btn-deploy-full",toggle:"deploy-type",icon:"images/deploy-full.png",label:"Full",sublabel:"Deploys everything in the workspace",onselect:function(s) { if(s){changeDeploymentType("full")}}}, - {id:"btn-deploy-flow",toggle:"deploy-type",icon:"images/deploy-flows.png",label:"Modified Flows",sublabel:"Only deploys flows that contain changed nodes", onselect:function(s) {if(s){changeDeploymentType("flows")}}}, - {id:"btn-deploy-node",toggle:"deploy-type",icon:"images/deploy-nodes.png",label:"Modified Nodes",sublabel:"Only deploys nodes that have changed",onselect:function(s) { if(s){changeDeploymentType("nodes")}}} - ] - }); - - RED.menu.init({id:"workspace-subflow-edit-menu", - options: [ - {id:"btn-subflow-add-input",label:"Add Input", onselect:function() { }}, - {id:"btn-subflow-add-output",label:"Add Output", onselect:function() { }}, - {id:"btn-subflow-edit-name",label:"Edit Name", onselect:function() { }}, - {id:"btn-subflow-delete",label:"Delete", onselect:function() { }}, - ] - }); - - RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); - loadSettings(); - RED.comms.connect(); + load(); }); - if ((window.location.hostname !== "localhost") && (window.location.hostname !== "127.0.0.1")) { - document.title = "Node-RED : "+window.location.hostname; - } return { }; diff --git a/public/red/ui/library.js b/public/red/ui/library.js index 0329315f6..1757b659c 100644 --- a/public/red/ui/library.js +++ b/public/red/ui/library.js @@ -66,9 +66,6 @@ RED.library = (function() { $("#btn-import-library-submenu").replaceWith(menu); }); } - loadFlowLibrary(); - - function createUI(options) { var libraryData = {}; @@ -360,6 +357,9 @@ RED.library = (function() { } return { + init: function() { + loadFlowLibrary(); + }, create: createUI, loadFlowLibrary: loadFlowLibrary } diff --git a/public/red/ui/palette.js b/public/red/ui/palette.js index ecdb3c80c..42e096ba2 100644 --- a/public/red/ui/palette.js +++ b/public/red/ui/palette.js @@ -36,8 +36,6 @@ RED.palette = (function() { }); } - core.forEach(createCategoryContainer); - function setLabel(type, el,label) { var nodeWidth = 80; var nodeHeight = 25; @@ -241,32 +239,37 @@ RED.palette = (function() { }); } - $("#palette-search-input").focus(function(e) { - RED.keyboard.disable(); - }); - $("#palette-search-input").blur(function(e) { - RED.keyboard.enable(); - }); - - $("#palette-search-clear").on("click",function(e) { - e.preventDefault(); - $("#palette-search-input").val(""); - filterChange(); - $("#palette-search-input").focus(); - }); - - $("#palette-search-input").val(""); - $("#palette-search-input").on("keyup",function() { - filterChange(); - }); - - $("#palette-search-input").on("focus",function() { - $("body").one("mousedown",function() { - $("#palette-search-input").blur(); + function init() { + $(".palette-spinner").show(); + core.forEach(createCategoryContainer); + $("#palette-search-input").focus(function(e) { + RED.keyboard.disable(); }); - }); + $("#palette-search-input").blur(function(e) { + RED.keyboard.enable(); + }); + + $("#palette-search-clear").on("click",function(e) { + e.preventDefault(); + $("#palette-search-input").val(""); + filterChange(); + $("#palette-search-input").focus(); + }); + + $("#palette-search-input").val(""); + $("#palette-search-input").on("keyup",function() { + filterChange(); + }); + + $("#palette-search-input").on("focus",function() { + $("body").one("mousedown",function() { + $("#palette-search-input").blur(); + }); + }); + } return { + init: init, add:addNodeType, remove:removeNodeType, hide:hideNodeType, diff --git a/public/red/ui/sidebar.js b/public/red/ui/sidebar.js index ffc942c69..5e4bfb091 100644 --- a/public/red/ui/sidebar.js +++ b/public/red/ui/sidebar.js @@ -26,6 +26,7 @@ RED.sidebar = (function() { $("#"+tab.id).remove(); } }); + function addTab(title,content,closeable) { $("#sidebar-content").append(content); $(content).hide(); @@ -129,22 +130,23 @@ RED.sidebar = (function() { } function showSidebar(id) { - //RED.menu.setSelected("btn-sidebar", true); - sidebar_tabs.activateTab("tab-" + id); + if (id) { + sidebar_tabs.activateTab("tab-"+id); + } } function containsTab(id) { return sidebar_tabs.contains("tab-"+id); } - - $(function() { + function init () { RED.keyboard.add(/* SPACE */ 32,{ctrl:true},function(){RED.menu.setSelected("btn-sidebar",!RED.menu.isSelected("btn-sidebar"));d3.event.preventDefault();}); - showSidebar("info"); - }); - + showSidebar(); + RED.sidebar.info.show(); + } return { + init: init, addTab: addTab, removeTab: removeTab, show: showSidebar, diff --git a/public/red/ui/tab-info.js b/public/red/ui/tab-info.js index cba14d0ee..5de55bdbd 100644 --- a/public/red/ui/tab-info.js +++ b/public/red/ui/tab-info.js @@ -32,8 +32,13 @@ RED.sidebar.info = (function() { content.style.paddingLeft = "4px"; content.style.paddingRight = "4px"; - RED.sidebar.addTab("info",content); - + function show() { + if (!RED.sidebar.containsTab("info")) { + RED.sidebar.addTab("info",content,false); + } + RED.sidebar.show("info"); + } + function jsonFilter(key,value) { if (key === "") { return value; @@ -116,6 +121,7 @@ RED.sidebar.info = (function() { } return { + show: show, refresh:refresh, clear: function() { $("#tab-info").html(""); diff --git a/public/red/ui/view.js b/public/red/ui/view.js index 164ecbeeb..a5fd92e48 100644 --- a/public/red/ui/view.js +++ b/public/red/ui/view.js @@ -365,7 +365,8 @@ RED.view = (function() { RED.history.push({t:'add',workspaces:[ws],dirty:dirty}); RED.view.dirty(true); } - $(function() { + + function init() { $('#btn-workspace-add-tab').on("click",addWorkspace); RED.menu.setAction('btn-workspace-add',addWorkspace); @@ -375,7 +376,7 @@ RED.view = (function() { RED.menu.setAction('btn-workspace-delete',function() { deleteWorkspace(activeWorkspace); }); - }); + } function deleteWorkspace(id) { if (workspace_tabs.count() == 1) { @@ -2051,8 +2052,36 @@ RED.view = (function() { } }); + + function hideDropTarget() { + $("#dropTarget").hide(); + RED.keyboard.remove(/* ESCAPE */ 27); + } + $('#chart').on("dragenter",function(event) { + if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { + $("#dropTarget").css({display:'table'}); + RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget); + } + }); + + $('#dropTarget').on("dragover",function(event) { + if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { + event.preventDefault(); + } + }) + .on("dragleave",function(event) { + hideDropTarget(); + }) + .on("drop",function(event) { + var data = event.originalEvent.dataTransfer.getData("text/plain"); + hideDropTarget(); + RED.view.importNodes(data); + event.preventDefault(); + }); + return { + init: init, state:function(state) { if (state == null) { return mouse_mode diff --git a/red.js b/red.js index ff5886da8..f66b1c6fa 100644 --- a/red.js +++ b/red.js @@ -121,13 +121,14 @@ settings.flowFile = flowFile || settings.flowFile; RED.init(server,settings); -if (settings.httpAdminRoot !== false && settings.httpAdminAuth) { - app.use(settings.httpAdminRoot, - express.basicAuth(function(user, pass) { - return user === settings.httpAdminAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAdminAuth.pass; - }) - ); -} +//if (settings.httpAdminRoot !== false && settings.httpAdminAuth) { +// app.use(settings.httpAdminRoot, +// express.basicAuth(function(user, pass) { +// return user === settings.httpAdminAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAdminAuth.pass; +// }) +// ); +//} + if (settings.httpNodeRoot !== false && settings.httpNodeAuth) { app.use(settings.httpNodeRoot, express.basicAuth(function(user, pass) { diff --git a/red/api/auth/index.js b/red/api/auth/index.js index c3c1f7593..af20a481a 100644 --- a/red/api/auth/index.js +++ b/red/api/auth/index.js @@ -53,11 +53,20 @@ function getToken(req,res,next) { return server.token()(req,res,next); } +function login(req,res) { + var response = { + "type":"credentials", + "prompts":[{id:"username",type:"text",label:"Username"},{id:"password",type:"password",label:"Password"}] + } + + res.json(response); +} module.exports = { authenticate: authenticate, ensureClientSecret: ensureClientSecret, authenticateClient: authenticateClient, getToken: getToken, - errorHandler: server.errorHandler() + errorHandler: server.errorHandler(), + login: login } diff --git a/red/api/auth/strategies.js b/red/api/auth/strategies.js index 50be2303a..8300b47a6 100644 --- a/red/api/auth/strategies.js +++ b/red/api/auth/strategies.js @@ -29,7 +29,7 @@ var bearerStrategy = function (accessToken, done) { if (token) { users.get(token.user).then(function(user) { if (user) { - done(null,user,{scope:token.scope}); + done(null,{username:user.username},{scope:token.scope}); } else { done(null,false); } diff --git a/red/api/index.js b/red/api/index.js index 0dd4b6e84..24c5c039a 100644 --- a/red/api/index.js +++ b/red/api/index.js @@ -50,6 +50,7 @@ function init(adminApp) { auth.getToken, auth.errorHandler ); + apiApp.get("/auth/login",auth.login); // Flows apiApp.get("/flows",flows.get); diff --git a/red/api/info.js b/red/api/info.js index 8b77ef044..7a63f6a3a 100644 --- a/red/api/info.js +++ b/red/api/info.js @@ -19,7 +19,8 @@ module.exports = { settings: function(req,res) { var safeSettings = { httpNodeRoot: settings.httpNodeRoot, - version: settings.version + version: settings.version, + user: req.user }; res.json(safeSettings); } diff --git a/settings.js b/settings.js index 1bfacbe53..66f290d33 100644 --- a/settings.js +++ b/settings.js @@ -66,7 +66,7 @@ module.exports = { // You can protect the user interface with a userid and password by using the following property. // The password must be an md5 hash eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password') - //httpAdminAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, + httpAdminAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, // Some nodes, such as HTTP In, can be used to listen for incoming http requests. // By default, these are served relative to '/'. The following property