Compare commits

..

2 Commits

Author SHA1 Message Date
Dave Conway-Jones
c2ea29e251 remove down carat from typed input with only 1 type 2018-02-03 00:02:49 +00:00
Dave Conway-Jones
6e1a2c436b let labels expand if really necessary, and pin min-width
(should we add max width also ?)
2018-02-02 22:54:51 +00:00
17 changed files with 98 additions and 213 deletions

View File

@@ -1,33 +1,3 @@
#### 0.18.2: Maintenance Release
Projects
- Filter out %D from git log command for older git versions
- Ensure projects are created as logged in user
- Better error handling/reporting in project creation
- Add Project Settings menu option
- Refresh vc sidebar on remote add/remove
- Fix auth prompt for ssh repos
- Prevent http git urls from including username/pword
- Fix fetch auth handling on non-default remote
- Avoid exception if git not installed
- Check version of git client on startup
- Fix pull/push when no tracked branch
- Add git_pull_unrelated_history handling
- Handle delete of last remote in project settings
Node Fixes
- Fix and Add some Chinese translations
- Update sort/batch docs
- Don't assume node has defaults when exporting icon property
- Ensure send is last thing trigger does
- Ensure trigger doesn't set two simultaneous timeouts
- Add missing property select var to HTML node
- Add a default keepalive to tcp client mode
- Move node.send in exec and httprequest nodes
#### 0.18.1: Maintenance Release
Projects

View File

@@ -67,7 +67,6 @@
if (!activeProject) {
// Projects enabled but no active project
RED.menu.setDisabled('menu-item-projects-open',true);
RED.menu.setDisabled('menu-item-projects-settings',true);
if (activeProject === false) {
// User previously decline the migration to projects.
} else { // null/undefined
@@ -321,9 +320,8 @@
var menuOptions = [];
if (RED.settings.theme("projects.enabled",false)) {
menuOptions.push({id:"menu-item-projects-menu",label:"Projects",options:[
{id:"menu-item-projects-new",label:"New",disabled:false,onselect:"core:new-project"},
{id:"menu-item-projects-open",label:"Open",disabled:false,onselect:"core:open-project"},
{id:"menu-item-projects-settings",label:"Project Settings",disabled:false,onselect:"core:show-project-settings"}
{id:"menu-item-projects-new",label:"New...",disabled:false,onselect:"core:new-project"},
{id:"menu-item-projects-open",label:"Open...",disabled:false,onselect:"core:open-project"}
]});
}

View File

@@ -116,7 +116,9 @@
this.options.types = this.options.types||Object.keys(allOptions);
this.selectTrigger = $('<button tabindex="0"></button>').prependTo(this.uiSelect);
$('<i class="fa fa-sort-desc"></i>').appendTo(this.selectTrigger);
if (this.options.types.length > 1) {
$('<i class="fa fa-sort-desc"></i>').appendTo(this.selectTrigger);
}
this.selectLabel = $('<span></span>').appendTo(this.selectTrigger);
this.types(this.options.types);

View File

@@ -49,7 +49,7 @@ RED.projects.settings = (function() {
var tabContainer;
var trayOptions = {
title: "Project Settings",// RED._("menu.label.userSettings"),, // TODO: nls
title: "Project Information",// RED._("menu.label.userSettings"),, // TODO: nls
buttons: [
{
id: "node-dialog-ok",
@@ -143,8 +143,7 @@ RED.projects.settings = (function() {
RED.sidebar.versionControl.refresh(true);
},
400: {
'*': function(error) {
utils.reportUnexpectedError(error);
'unexpected_error': function(error) {
done(error,null);
}
},
@@ -209,8 +208,7 @@ RED.projects.settings = (function() {
done(null,data);
},
400: {
'*': function(error) {
utils.reportUnexpectedError(error);
'unexpected_error': function(error) {
done(error,null);
}
},
@@ -964,7 +962,7 @@ RED.projects.settings = (function() {
var done = function(err) {
spinner.remove();
if (err) {
utils.reportUnexpectedError(err);
console.log(err);
return;
}
flowFileLabelText.text(flowFileInput.val());
@@ -1007,6 +1005,10 @@ RED.projects.settings = (function() {
'credentials_load_failed': function(error) {
done(error);
},
'unexpected_error': function(error) {
console.log(error);
done(error);
},
'missing_current_credential_key': function(error) {
credentialSecretExistingInput.addClass("input-error");
popover = RED.popover.create({
@@ -1017,9 +1019,6 @@ RED.projects.settings = (function() {
autoClose: 3000
}).open();
done(error);
},
'*': function(error) {
done(error);
}
},
}
@@ -1143,8 +1142,8 @@ RED.projects.settings = (function() {
]
});
},
'*': function(error) {
utils.reportUnexpectedError(error);
'unexpected_error': function(error) {
console.log(error);
spinner.remove();
}
},
@@ -1194,19 +1193,12 @@ RED.projects.settings = (function() {
editRepoButton.attr('disabled',true);
addRemoteDialog.slideDown(200, function() {
addRemoteDialog[0].scrollIntoView();
if (isEmpty) {
remoteNameInput.val('origin');
remoteURLInput.focus();
} else {
remoteNameInput.focus();
}
validateForm();
});
});
var emptyItem = { empty: true };
var isEmpty = true;
var row = $('<div class="user-settings-row"></div>').appendTo(repoContainer);
var addRemoteDialog = $('<div class="projects-dialog-list-dialog"></div>').hide().appendTo(row);
row = $('<div class="user-settings-row projects-dialog-list"></div>').appendTo(repoContainer);
@@ -1264,7 +1256,6 @@ RED.projects.settings = (function() {
setTimeout(spinner.remove, 100);
if (data.remotes.length === 0) {
delete activeProject.git.remotes;
isEmpty = true;
remotesList.editableList('addItem',emptyItem);
} else {
activeProject.git.remotes = {};
@@ -1274,12 +1265,11 @@ RED.projects.settings = (function() {
activeProject.git.remotes[name] = remote;
});
}
RED.sidebar.versionControl.refresh();
});
},
400: {
'*': function(error) {
utils.reportUnexpectedError(error);
'unexpected_error': function(error) {
console.log(error);
spinner.remove();
}
},
@@ -1300,26 +1290,16 @@ RED.projects.settings = (function() {
var validateForm = function() {
var validName = /^[a-zA-Z0-9\-_]+$/.test(remoteNameInput.val());
var repo = remoteURLInput.val();
// var validRepo = /^(?:file|git|ssh|https?|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?[\w\.@:\/~_-]+(?:\.git)?(?:\/?|\#[\d\w\.\-_]+?)$/.test(remoteURLInput.val());
var validRepo = repo.length > 0 && !/\s/.test(repo);
if (/^https?:\/\/[^/]+@/i.test(repo)) {
remoteURLLabel.text("Do not include the username/password in the url");
validRepo = false;
} else {
remoteURLLabel.text("https://, ssh:// or file://");
}
var validRepo = !/\s/.test(remoteURLInput.val());
saveButton.attr('disabled',(!validName || !validRepo))
remoteNameInput.toggleClass('input-error',remoteNameInputChanged&&!validName);
remoteURLInput.toggleClass('input-error',remoteURLInputChanged&&!validRepo);
if (popover) {
popover.close();
popover = null;
}
};
var popover;
var remoteNameInputChanged = false;
var remoteURLInputChanged = false;
$('<div class="projects-dialog-list-dialog-header">').text('Add remote').appendTo(addRemoteDialog);
@@ -1329,14 +1309,11 @@ RED.projects.settings = (function() {
remoteNameInputChanged = true;
validateForm();
});
var remoteNameInputChanged = false;
$('<label class="projects-edit-form-sublabel"><small>Must contain only A-Z 0-9 _ -</small></label>').appendTo(row).find("small");
row = $('<div class="user-settings-row"></div>').appendTo(addRemoteDialog);
$('<label for=""></label>').text('URL').appendTo(row);
var remoteURLInput = $('<input type="text">').appendTo(row).on("change keyup paste",function() {
remoteURLInputChanged = true;
validateForm()
});
var remoteURLLabel = $('<label class="projects-edit-form-sublabel"><small>https://, ssh:// or file://</small></label>').appendTo(row).find("small");
var remoteURLInput = $('<input type="text">').appendTo(row).on("change keyup paste",validateForm);
var hideEditForm = function() {
editRepoButton.attr('disabled',false);
@@ -1390,7 +1367,6 @@ RED.projects.settings = (function() {
activeProject.git.remotes[name] = remote;
});
updateForm();
RED.sidebar.versionControl.refresh();
done();
},
400: {
@@ -1405,15 +1381,14 @@ RED.projects.settings = (function() {
remoteNameInput.addClass('input-error');
done(error);
},
'*': function(error) {
utils.reportUnexpectedError(error);
'unexpected_error': function(error) {
console.log(error);
done(error);
}
},
}
},payload);
});
var updateForm = function() {
remotesList.editableList('empty');
var count = 0;
@@ -1425,8 +1400,7 @@ RED.projects.settings = (function() {
}
}
}
isEmpty = (count === 0);
if (isEmpty) {
if (count === 0) {
remotesList.editableList('addItem',emptyItem);
}
}

View File

@@ -19,45 +19,7 @@ RED.projects = (function() {
var dialogBody;
var activeProject;
function reportUnexpectedError(error) {
var notification;
if (error.error === 'git_missing_user') {
notification = RED.notify("<p>You Git client is not configured with a username/email.</p>",{
fixed: true,
type:'error',
buttons: [
{
text: "Cancel",
click: function() {
notification.close();
}
},
{
text: "Configure Git client",
click: function() {
RED.userSettings.show('gitconfig');
notification.close();
}
}
]
})
} else {
console.log(error);
notification = RED.notify("<p>An unexpected error occurred:</p><p>"+error.message+"</p><small>code: "+error.error+"</small>",{
fixed: true,
modal: true,
type: 'error',
buttons: [
{
text: "Close",
click: function() {
notification.close();
}
}
]
})
}
}
var screens = {};
function initScreens() {
var migrateProjectHeader = $('<div class="projects-dialog-screen-start-hero"></div>');
@@ -584,7 +546,6 @@ RED.projects = (function() {
} else {
show('create-success');
RED.menu.setDisabled('menu-item-projects-open',false);
RED.menu.setDisabled('menu-item-projects-settings',false);
}
},
400: {
@@ -603,9 +564,8 @@ RED.projects = (function() {
// getRepoAuthDetails(req);
console.log("git auth error",error);
},
'*': function(error) {
reportUnexpectedError(error);
$( dialog ).dialog( "close" );
'unexpected_error': function(error) {
console.log("unexpected_error",error)
}
}
}
@@ -722,11 +682,7 @@ RED.projects = (function() {
var repo = projectRepoInput.val();
// var validRepo = /^(?:file|git|ssh|https?|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?[\w\.@:\/~_-]+(?:\/?|\#[\d\w\.\-_]+?)$/.test(repo);
var validRepo = repo.length > 0 && !/\s/.test(repo);
if (/^https?:\/\/[^/]+@/i.test(repo)) {
$("#projects-dialog-screen-create-project-repo-label small").text("Do not include the username/password in the url");
validRepo = false;
}
var validRepo = !/\s/.test(repo);
if (!validRepo) {
if (projectRepoChanged) {
projectRepoInput.addClass("input-error");
@@ -1561,7 +1517,7 @@ RED.projects = (function() {
'</div>');
var isSSH = false;
if (/^https?:\/\//.test(url)) {
if (/^https?:\/\//) {
$('<div class="form-row"><label for="projects-user-auth-username">Username</label><input id="projects-user-auth-username" type="text"></input></div>'+
'<div class="form-row"><label for=projects-user-auth-password">Password</label><input id="projects-user-auth-password" type="password"></input></div>').appendTo(message);
} else if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(url)) {
@@ -1782,17 +1738,8 @@ RED.projects = (function() {
},Math.max(300-(Date.now() - start),0));
},
400: {
'git_connection_failed': function(error) {
RED.notify(error.message,'error');
},
'git_not_a_repository': function(error) {
RED.notify(error.message,'error');
},
'git_repository_not_found': function(error) {
RED.notify(error.message,'error');
},
'unexpected_error': function(error) {
reportUnexpectedError(error);
console.log(error);
}
}
}
@@ -1835,12 +1782,11 @@ RED.projects = (function() {
RED.actions.add("core:new-project",RED.projects.newProject);
RED.actions.add("core:open-project",RED.projects.selectProject);
RED.actions.add("core:show-project-settings",RED.projects.settings.show);
var projectsAPI = {
sendRequest:sendRequest,
createBranchList:createBranchList,
addSpinnerOverlay:addSpinnerOverlay,
reportUnexpectedError:reportUnexpectedError
addSpinnerOverlay:addSpinnerOverlay
};
RED.projects.settings.init(projectsAPI);
RED.projects.userSettings.init(projectsAPI);

View File

@@ -487,8 +487,8 @@ RED.sidebar.versionControl = (function() {
refresh(true);
},
400: {
'*': function(error) {
utils.reportUnexpectedError(error);
'unexpected_error': function(error) {
console.log(error);
}
},
}
@@ -749,13 +749,7 @@ RED.sidebar.versionControl = (function() {
},
400: {
'git_connection_failed': function(error) {
RED.notify(error.message,'error');
},
'git_not_a_repository': function(error) {
RED.notify(error.message,'error');
},
'git_repository_not_found': function(error) {
RED.notify(error.message,'error');
RED.notify(error.message);
},
'unexpected_error': function(error) {
console.log(error);

View File

@@ -178,7 +178,7 @@
}
.form-row label {
display: inline-block;
width: 100px;
min-width: 100px;
}
.form-row input, .form-row div[contenteditable="true"] {
width:70%;
@@ -323,6 +323,7 @@
margin-right: 20px;
text-align: right;
width: 30px;
min-width: 30px;
}
button {
margin-left: 10px;

View File

@@ -64,9 +64,10 @@
vertical-align: middle;
color: #555;
i {
position:relative;
top:-3px;
margin-right:4px;
position: relative;
top: -3px;
margin-left: 1px;
margin-right: 2px;
margin-top: 1px;
vertical-align: middle;
&.fa-ellipsis-h {

View File

@@ -100,6 +100,8 @@ module.exports = function(RED) {
msg.payload = RED.util.evaluateNodeProperty(node.op1,node.op1type,node,msg);
}
if (node.op1type !== "nul") { node.send(RED.util.cloneMessage(msg)); }
if (node.duration === 0) { node.topics[topic].tout = 0; }
else if (node.loop === true) {
/* istanbul ignore else */
@@ -111,24 +113,21 @@ module.exports = function(RED) {
}
}
else {
if (!node.topics[topic].tout) {
node.topics[topic].tout = setTimeout(function() {
var msg2 = null;
if (node.op2type !== "nul") {
msg2 = RED.util.cloneMessage(msg);
if (node.op2type === "flow" || node.op2type === "global") {
node.topics[topic].m2 = RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg);
}
msg2.payload = node.topics[topic].m2;
delete node.topics[topic];
node.send(msg2);
node.topics[topic].tout = setTimeout(function() {
var msg2 = null;
if (node.op2type !== "nul") {
msg2 = RED.util.cloneMessage(msg);
if (node.op2type === "flow" || node.op2type === "global") {
node.topics[topic].m2 = RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg);
}
node.status({});
}, node.duration);
}
msg2.payload = node.topics[topic].m2;
}
delete node.topics[topic];
node.status({});
node.send(msg2);
}, node.duration);
}
node.status({fill:"blue",shape:"dot",text:" "});
if (node.op1type !== "nul") { node.send(RED.util.cloneMessage(msg)); }
}
else if ((node.extend === "true" || node.extend === true) && (node.duration > 0)) {
/* istanbul ignore else */

View File

@@ -263,8 +263,9 @@ module.exports = function(RED) {
catch(e) { node.warn(RED._("httpin.errors.json-error")); }
}
}
node.status({});
node.send(msg);
node.status({});
}
});
});
@@ -279,8 +280,8 @@ module.exports = function(RED) {
node.error(err,msg);
msg.payload = err.toString() + " : " + url;
msg.statusCode = err.code;
node.status({fill:"red",shape:"ring",text:err.code});
node.send(msg);
node.status({fill:"red",shape:"ring",text:err.code});
});
if (payload) {
req.write(payload);

View File

@@ -52,7 +52,6 @@ module.exports = function(RED) {
node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
node.status({fill:"green",shape:"dot",text:"common.status.connected"});
});
client.setKeepAlive(true,120000);
connectionPool[id] = client;
client.on('data', function (data) {
@@ -124,8 +123,7 @@ module.exports = function(RED) {
clearTimeout(reconnectTimeout);
if (!node.connected) { done(); }
});
}
else {
} else {
var server = net.createServer(function (socket) {
socket.setKeepAlive(true,120000);
if (socketTimeout !== null) { socket.setTimeout(socketTimeout); }
@@ -186,7 +184,6 @@ module.exports = function(RED) {
node.log(err);
});
});
server.on('error', function(err) {
if (err) {
node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()}));
@@ -240,7 +237,6 @@ module.exports = function(RED) {
node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
node.status({fill:"green",shape:"dot",text:"common.status.connected"});
});
client.setKeepAlive(true,120000);
client.on('error', function (err) {
node.log(RED._("tcpin.errors.error",{error:err.toString()}));
});
@@ -292,8 +288,7 @@ module.exports = function(RED) {
if (!node.connected) { done(); }
});
}
else if (node.beserver == "reply") {
} else if (node.beserver == "reply") {
node.on("input",function(msg) {
if (msg._session && msg._session.type == "tcp") {
var client = connectionPool[msg._session.id];
@@ -319,8 +314,7 @@ module.exports = function(RED) {
}
}
});
}
else {
} else {
var connectedSockets = [];
node.status({text:RED._("tcpin.status.connections",{count:0})});
var server = net.createServer(function (socket) {

View File

@@ -58,7 +58,6 @@
color:"#DEBD5C",
defaults: {
name: {value:""},
property: {value:"payload"},
tag: {value:""},
ret: {value:"html"},
as: {value:"single"}
@@ -71,9 +70,6 @@
},
labelStyle: function() {
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
$("#node-input-property").typedInput({default:'msg',types:['msg']});
}
});
</script>

View File

@@ -1,6 +1,6 @@
{
"name": "node-red",
"version": "0.18.2",
"version": "0.18.1",
"description": "A visual tool for wiring the Internet of Things",
"homepage": "http://nodered.org",
"license": "Apache-2.0",
@@ -60,7 +60,7 @@
"mustache": "2.3.0",
"node-red-node-email": "0.1.*",
"node-red-node-feedparser": "0.1.*",
"node-red-node-rbe": "0.2.*",
"node-red-node-rbe": "0.1.*",
"node-red-node-twitter": "0.1.*",
"nopt": "4.0.1",
"oauth2orize": "1.11.0",

View File

@@ -248,11 +248,8 @@ module.exports = {
res.redirect(303,req.baseUrl+"/"+projectName+"/status");
})
.catch(function(err) {
if (err.code) {
res.status(400).json({error:err.code, message: err.message});
} else {
res.status(400).json({error:"unexpected_error", message:err.toString()});
}
console.log(err.stack);
res.status(400).json({error:"unexpected_error", message:err.toString()});
})
});
@@ -504,10 +501,6 @@ module.exports = {
// Add a remote
app.post("/:id/remotes", needsPermission("projects.write"), function(req,res) {
var projectName = req.params.id;
if (/^https?:\/\/[^/]+@/i.test(req.body.url)) {
res.status(400).json({error:"unexpected_error", message:"Git http url must not include username/password"});
return;
}
runtime.storage.projects.addRemote(req.user, projectName, req.body).then(function() {
res.redirect(303,req.baseUrl+"/"+projectName+"/remotes");
}).catch(function(err) {

View File

@@ -912,17 +912,40 @@ function createProject(user, metadata) {
);
auth = authCache.get(project,originRemote.url,username);
}
return gitTools.clone(originRemote,auth,projectPath);
return gitTools.clone(originRemote,auth,projectPath).then(function(result) {
// Check this is a valid project
// If it is empty
// - if 'populate' flag is set, call populateProject
// - otherwise reject with suitable error to allow UI to confirm population
// If it is missing package.json/flow.json/flow_cred.json
// - reject as invalid project
// checkProjectFiles(project).then(function(results) {
// console.log("checkProjectFiles");
// console.log(results);
// });
// return gitTools.getFiles(projectPath).then(function() {
// // It wasn't an empty repository.
// // TODO: check for required files - checkProjectFiles
//
// }).catch(function(err) {
// if (/ambiguous argument/.test(err.message)) {
// // Empty repository
// err.code = "project_empty";
// err.message = "Project is empty";
// }
// throw err;
// });
resolve(getProject(project));
}).catch(function(error) {
fs.remove(projectPath,function() {
reject(error);
});
})
} else {
return createDefaultProject(user, metadata);
createDefaultProject(user, metadata).then(function() { resolve(getProject(project))}).catch(reject);
}
}).then(function() {
resolve(getProject(project))
}).catch(function(err) {
fs.remove(projectPath,function() {
reject(err);
});
});
}).catch(reject);
})
})
}

View File

@@ -69,14 +69,8 @@ function runGitCommand(args,cwd,env) {
err.code = "git_not_a_repository";
} else if (/Repository not found/i.test(stderr)) {
err.code = "git_repository_not_found";
} else if (/repository '.*' does not exist/i.test(stderr)) {
err.code = "git_repository_not_found";
} else if (/refusing to merge unrelated histories/.test(stderr)) {
err.code = "git_pull_unrelated_history"
} else if (/Please tell me who you are/.test(stderr)) {
err.code = "git_missing_user";
} else if (/name consists only of disallowed characters/.test(stderr)) {
err.code = "git_missing_user";
}
return reject(err);
}
@@ -288,8 +282,7 @@ function parseLog(log) {
}
var m = /^(.*): (.*)$/.exec(l);
if (m) {
// git 2.1.4 (Debian Stable) doesn't support %D for refs - so filter out
if (m[1] === 'refs' && m[2] && m[2] !== '%D') {
if (m[1] === 'refs' && m[2]) {
currentCommit[m[1]] = m[2].split(",").map(function(v) { return v.trim() });
} else {
if (m[1] === 'parents') {

View File

@@ -341,7 +341,7 @@ function createProject(user, metadata) {
metadata.files.oldCredentials = credentialsFile;
metadata.files.credentialSecret = currentEncryptionKey;
}
return Projects.create(user, metadata).then(function(p) {
return Projects.create(null,metadata).then(function(p) {
return setActiveProject(user, p.name);
}).then(function() {
return getProject(user, metadata.name);