mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
134 Commits
labels-wid
...
runnable-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c256e27a83 | ||
|
|
3f41036919 | ||
|
|
95753ce5cd | ||
|
|
1906818c87 | ||
|
|
02765f8aad | ||
|
|
89f1dedf20 | ||
|
|
7a8906535e | ||
|
|
499d22daca | ||
|
|
838c7a5e89 | ||
|
|
89bfc90f40 | ||
|
|
acad9f57f9 | ||
|
|
0d08dc410e | ||
|
|
ebb3fb96cd | ||
|
|
f31f23ff07 | ||
|
|
8b0e76dd55 | ||
|
|
884618adfe | ||
|
|
98f7271ac8 | ||
|
|
087cd121b8 | ||
|
|
2d52527fb4 | ||
|
|
fe289e62b5 | ||
|
|
2845475e3f | ||
|
|
b307492487 | ||
|
|
d48284f7ea | ||
|
|
7e416797e9 | ||
|
|
5d54ca7477 | ||
|
|
b979b4e61a | ||
|
|
2527f7984a | ||
|
|
d9350b2362 | ||
|
|
bd0b903f1a | ||
|
|
f243c0df19 | ||
|
|
7482978953 | ||
|
|
77966689d4 | ||
|
|
cf43939d65 | ||
|
|
391ac4b351 | ||
|
|
e1e48aadd9 | ||
|
|
0681f206c4 | ||
|
|
d257c6f3d3 | ||
|
|
fa45c82cdc | ||
|
|
e805b58da6 | ||
|
|
943976d207 | ||
|
|
3a2e5a6ccd | ||
|
|
35ef036246 | ||
|
|
e09c3bbdd3 | ||
|
|
3b12076d4b | ||
|
|
cfcf78ae28 | ||
|
|
341ff9bf5c | ||
|
|
4ebb5d099e | ||
|
|
1e82b66bf0 | ||
|
|
06a5e4273b | ||
|
|
e123e7b0b0 | ||
|
|
aeadc40c65 | ||
|
|
7ef418ec52 | ||
|
|
2ed52820b6 | ||
|
|
e8fd7484b6 | ||
|
|
ce5242cfe8 | ||
|
|
af947879d8 | ||
|
|
3ed112cde6 | ||
|
|
99c6a9eccd | ||
|
|
2029f6ea0a | ||
|
|
e984e1f30f | ||
|
|
f21260370f | ||
|
|
fdae75c99b | ||
|
|
a0489f2a0d | ||
|
|
0123eacbdb | ||
|
|
53401b6aa7 | ||
|
|
9a5139f452 | ||
|
|
2ee0c8c228 | ||
|
|
c53562cc9c | ||
|
|
ec5d7c2e5c | ||
|
|
d6fc258485 | ||
|
|
f953612695 | ||
|
|
2ab93acca8 | ||
|
|
326c6c496e | ||
|
|
9f7f50664c | ||
|
|
f6f1436123 | ||
|
|
c3c519419d | ||
|
|
e569a80b72 | ||
|
|
284f437c1a | ||
|
|
1fd44a9958 | ||
|
|
cad34742f6 | ||
|
|
323359b3c8 | ||
|
|
35db8b45f0 | ||
|
|
50ae815ceb | ||
|
|
1a4389c90d | ||
|
|
fdaa5ce1da | ||
|
|
09d9936aed | ||
|
|
b3f6109b1c | ||
|
|
5fb3ffc240 | ||
|
|
360db252bb | ||
|
|
0b6e290271 | ||
|
|
7f0174e6db | ||
|
|
a25dad6c2e | ||
|
|
6191a49ed3 | ||
|
|
6252b075bc | ||
|
|
7face138fd | ||
|
|
382b83b093 | ||
|
|
691687d1bc | ||
|
|
5814b80a72 | ||
|
|
e147fbb1fa | ||
|
|
b9e256adfa | ||
|
|
3b7bf04e22 | ||
|
|
43408a724c | ||
|
|
5fbd5bf9e2 | ||
|
|
5e87828b29 | ||
|
|
9066cedc29 | ||
|
|
aa1cf0b228 | ||
|
|
06a6a4408f | ||
|
|
d5619d2b9d | ||
|
|
2f6ac42efe | ||
|
|
0bba3dd83d | ||
|
|
abe60b62e6 | ||
|
|
555b7df986 | ||
|
|
b3786700e6 | ||
|
|
ce9643d21b | ||
|
|
4a5cb7f2f5 | ||
|
|
42a7e902e6 | ||
|
|
aebe080e85 | ||
|
|
c316284924 | ||
|
|
8d98b228ab | ||
|
|
5b4c42ff05 | ||
|
|
a596a4551a | ||
|
|
0968f96982 | ||
|
|
5931e13b9c | ||
|
|
415c768ae4 | ||
|
|
b4c8bf21d5 | ||
|
|
5fe5db603d | ||
|
|
9f7dd7f5d4 | ||
|
|
e6d32aab7b | ||
|
|
08bd6d963c | ||
|
|
ff05fb14a6 | ||
|
|
22d942b705 | ||
|
|
0526372f28 | ||
|
|
f99051906a | ||
|
|
d1f7fd8bfd |
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,3 +1,4 @@
|
||||
<!--
|
||||
## Before you hit that Submit button....
|
||||
|
||||
This issue tracker is for problems with the Node-RED runtime, the editor or the core nodes.
|
||||
@@ -14,6 +15,7 @@ That way the whole Node-RED user community can help, rather than rely on the cor
|
||||
## So you have a real issue to raise...
|
||||
|
||||
To help us understand the issue, please fill-in as much of the following information as you can:
|
||||
-->
|
||||
|
||||
### What are the steps to reproduce?
|
||||
|
||||
|
||||
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,3 +1,4 @@
|
||||
<!--
|
||||
## Before you hit that Submit button....
|
||||
|
||||
Please read our [contribution guidelines](https://github.com/node-red/node-red/blob/master/CONTRIBUTING.md)
|
||||
@@ -6,23 +7,26 @@ before submitting a pull-request.
|
||||
## Types of changes
|
||||
|
||||
What types of changes does your code introduce?
|
||||
_Put an `x` in the boxes that apply_
|
||||
Put an `x` in the boxes that apply
|
||||
-->
|
||||
|
||||
- [ ] Bugfix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
|
||||
<!--
|
||||
If you want to raise a pull-request with a new feature, or a refactoring
|
||||
of existing code, it **may well get rejected** if it hasn't been discussed on
|
||||
the [mailing list](https://groups.google.com/forum/#!forum/node-red) or
|
||||
[slack team](https://nodered.org/slack) first.
|
||||
|
||||
-->
|
||||
|
||||
## Proposed changes
|
||||
|
||||
Describe the nature of this change. What problem does it address?
|
||||
<!-- Describe the nature of this change. What problem does it address? -->
|
||||
|
||||
## Checklist
|
||||
_Put an `x` in the boxes that apply_
|
||||
<!-- Put an `x` in the boxes that apply -->
|
||||
|
||||
- [ ] I have read the [contribution guidelines](https://github.com/node-red/node-red/blob/master/CONTRIBUTING.md)
|
||||
- [ ] For non-bugfix PRs, I have discussed this change on the mailing list/slack team.
|
||||
|
||||
84
CHANGELOG.md
84
CHANGELOG.md
@@ -1,3 +1,87 @@
|
||||
#### 0.18.4: Maintenance Release
|
||||
|
||||
Projects
|
||||
|
||||
- Ensure sshkey file path is properly escaped on Windows
|
||||
- Normalize ssh key paths for Windows file names
|
||||
- Ensure userDir is an absolute path when used with sshkeygen
|
||||
- Detect if there are no existing flows to migrate into a project
|
||||
- Use relative urls when retriving flow history
|
||||
- Add credentialSecret to clone pane
|
||||
- Delay clearing inflight when changing credentials key
|
||||
- Mark deploy inflight when reverting a file change
|
||||
- Handle missing_flow_file error on clone properly
|
||||
- Remote project from cached list on delete so it can be reused
|
||||
- Fix tests for existing file flag in settings
|
||||
|
||||
Editor Fixes
|
||||
|
||||
- Fix merging a remote diff
|
||||
- Fixed the problems when using a node without defaults
|
||||
- Disable user defined icon for subflow
|
||||
- getDefaultNodeIcon should handle subflow instance nodes Fixes #1635
|
||||
- Add Japanese info text for core nodes
|
||||
- Fix message lookup for core nodes in case of i18 locales directory exists
|
||||
- Prevent the last tab from being deleted
|
||||
|
||||
Node Fixes
|
||||
|
||||
- Ensure trigger gets reset when 2nd output is null
|
||||
|
||||
|
||||
#### 0.18.3: Maintenance Release
|
||||
|
||||
Projects
|
||||
|
||||
- Fix permissions on git/ssh scripts
|
||||
- Add support for GIT_SSH on older levels of git
|
||||
- Handle host key verification as auth error
|
||||
- Ensure commit list has a refs object even if empty
|
||||
- Make git error detection case-insensitive
|
||||
- Fix up merge conflict handling
|
||||
- Use flow-diff when looking at flow file changes
|
||||
|
||||
Node Fixes
|
||||
|
||||
- Ensure debug tools show for 'complete msg object'
|
||||
- Fix msg.parts handling in concat mode of Batch node
|
||||
|
||||
Editor Fixes
|
||||
|
||||
- Fix offset calculation when dragging node from palette
|
||||
- Allow a library entry to use non-default node-input- prefixes
|
||||
- Change remote-diff shortcut and add it to keymap Fixes #1628
|
||||
|
||||
#### 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
|
||||
|
||||
@@ -392,9 +392,9 @@ module.exports = function(grunt) {
|
||||
mode: '755'
|
||||
},
|
||||
release: {
|
||||
// Target-specific file/dir lists and/or options go here.
|
||||
src: [
|
||||
path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>/nodes/core/hardware/nrgpio*')
|
||||
path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>/nodes/core/hardware/nrgpio*'),
|
||||
path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>/red/runtime/storage/localfilesystem/projects/git/node-red-*sh')
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -191,7 +191,7 @@ RED.history = (function() {
|
||||
} else if (ev.t == "edit") {
|
||||
for (i in ev.changes) {
|
||||
if (ev.changes.hasOwnProperty(i)) {
|
||||
if (ev.node._def.defaults[i] && ev.node._def.defaults[i].type) {
|
||||
if (ev.node._def.defaults && ev.node._def.defaults[i] && ev.node._def.defaults[i].type) {
|
||||
// This is a config node property
|
||||
var currentConfigNode = RED.nodes.node(ev.node[i]);
|
||||
if (currentConfigNode) {
|
||||
@@ -229,10 +229,12 @@ RED.history = (function() {
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.editor.validateNode(ev.node);
|
||||
RED.nodes.filterNodes({type:"subflow:"+ev.node.id}).forEach(function(n) {
|
||||
n.inputs = ev.node.in.length;
|
||||
n.outputs = ev.node.out.length;
|
||||
RED.editor.updateNodeProperties(n);
|
||||
RED.editor.validateNode(n);
|
||||
});
|
||||
} else {
|
||||
var outputMap;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"ctrl-i": "core:show-import-dialog",
|
||||
"ctrl-space": "core:toggle-sidebar",
|
||||
"ctrl-,": "core:show-user-settings",
|
||||
|
||||
"ctrl-alt-r": "core:show-remote-diff",
|
||||
"ctrl-alt-n": "core:new-project",
|
||||
"ctrl-alt-o": "core:open-project",
|
||||
"ctrl-g v": "core:show-version-control-tab"
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
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
|
||||
@@ -130,11 +131,12 @@
|
||||
var project = RED.projects.getActiveProject();
|
||||
var message = {
|
||||
"change-branch":"Change to local branch '"+project.git.branches.local+"'",
|
||||
"abort-merge":"Git merge aborted",
|
||||
"merge-abort":"Git merge aborted",
|
||||
"loaded":"Project '"+msg.project+"' loaded",
|
||||
"updated":"Project '"+msg.project+"' updated",
|
||||
"pull":"Project '"+msg.project+"' reloaded",
|
||||
"revert": "Project '"+msg.project+"' reloaded"
|
||||
"revert": "Project '"+msg.project+"' reloaded",
|
||||
"merge-complete":"Git merge completed"
|
||||
}[msg.action];
|
||||
RED.notify("<p>"+message+"</p>");
|
||||
RED.sidebar.info.refresh()
|
||||
@@ -218,6 +220,20 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
} else if (msg.error === "git_merge_conflict") {
|
||||
RED.nodes.clear();
|
||||
RED.sidebar.versionControl.refresh(true);
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: "Show merge conflicts",
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.sidebar.versionControl.showLocalChanges();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!persistentNotifications.hasOwnProperty(notificationId)) {
|
||||
@@ -320,8 +336,9 @@
|
||||
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-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"}
|
||||
]});
|
||||
}
|
||||
|
||||
|
||||
@@ -355,7 +355,7 @@ RED.nodes = (function() {
|
||||
RED.nodes.registerType("subflow:"+sf.id, {
|
||||
defaults:{name:{value:""}},
|
||||
info: sf.info,
|
||||
icon:"subflow.png",
|
||||
icon: function() { return sf.icon||"subflow.png" },
|
||||
category: "subflows",
|
||||
inputs: sf.in.length,
|
||||
outputs: sf.out.length,
|
||||
@@ -550,7 +550,11 @@ RED.nodes = (function() {
|
||||
if (node.out.length > 0 && n.outputLabels && !/^\s*$/.test(n.outputLabels.join(""))) {
|
||||
node.outputLabels = n.outputLabels.slice();
|
||||
}
|
||||
|
||||
if (n.icon) {
|
||||
if (n.icon !== "node-red/subflow.png") {
|
||||
node.icon = n.icon;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -408,9 +408,12 @@ RED.deploy = (function() {
|
||||
delete confNode.credentials;
|
||||
}
|
||||
});
|
||||
RED.nodes.eachSubflow(function(subflow) {
|
||||
subflow.changed = false;
|
||||
});
|
||||
RED.nodes.eachWorkspace(function(ws) {
|
||||
ws.changed = false;
|
||||
})
|
||||
});
|
||||
// Once deployed, cannot undo back to a clean state
|
||||
RED.history.markAllDirty();
|
||||
RED.view.redraw();
|
||||
|
||||
@@ -9,29 +9,30 @@ RED.diff = (function() {
|
||||
// RED.actions.add("core:show-current-diff",showLocalDiff);
|
||||
RED.actions.add("core:show-remote-diff",showRemoteDiff);
|
||||
// RED.keyboard.add("*","ctrl-shift-l","core:show-current-diff");
|
||||
RED.keyboard.add("*","ctrl-shift-r","core:show-remote-diff");
|
||||
// RED.keyboard.add("*","ctrl-shift-r","core:show-remote-diff");
|
||||
|
||||
|
||||
RED.actions.add("core:show-test-flow-diff-1",function(){showTestFlowDiff(1)});
|
||||
RED.keyboard.add("*","ctrl-shift-f 1","core:show-test-flow-diff-1");
|
||||
|
||||
RED.actions.add("core:show-test-flow-diff-2",function(){showTestFlowDiff(2)});
|
||||
RED.keyboard.add("*","ctrl-shift-f 2","core:show-test-flow-diff-2");
|
||||
RED.actions.add("core:show-test-flow-diff-3",function(){showTestFlowDiff(3)});
|
||||
RED.keyboard.add("*","ctrl-shift-f 3","core:show-test-flow-diff-3");
|
||||
// RED.actions.add("core:show-test-flow-diff-1",function(){showTestFlowDiff(1)});
|
||||
// RED.keyboard.add("*","ctrl-shift-f 1","core:show-test-flow-diff-1");
|
||||
//
|
||||
// RED.actions.add("core:show-test-flow-diff-2",function(){showTestFlowDiff(2)});
|
||||
// RED.keyboard.add("*","ctrl-shift-f 2","core:show-test-flow-diff-2");
|
||||
// RED.actions.add("core:show-test-flow-diff-3",function(){showTestFlowDiff(3)});
|
||||
// RED.keyboard.add("*","ctrl-shift-f 3","core:show-test-flow-diff-3");
|
||||
|
||||
}
|
||||
function createDiffTable(container) {
|
||||
function createDiffTable(container,CurrentDiff) {
|
||||
var diffList = $('<ol class="node-dialog-view-diff-diff"></ol>').appendTo(container);
|
||||
diffList.editableList({
|
||||
addButton: false,
|
||||
height: "auto",
|
||||
scrollOnAdd: false,
|
||||
addItem: function(container,i,object) {
|
||||
var localDiff = object.diff;
|
||||
var remoteDiff = object.remoteDiff;
|
||||
var tab = object.tab.n;
|
||||
var def = object.def;
|
||||
var conflicts = currentDiff.conflicts;
|
||||
var conflicts = CurrentDiff.conflicts;
|
||||
|
||||
var tabDiv = $('<div>',{class:"node-diff-tab"}).appendTo(container);
|
||||
tabDiv.addClass('collapsed');
|
||||
@@ -150,10 +151,10 @@ RED.diff = (function() {
|
||||
}
|
||||
div.addClass("node-diff-node-entry-conflict");
|
||||
} else {
|
||||
selectState = currentDiff.resolutions[tab.id];
|
||||
selectState = CurrentDiff.resolutions[tab.id];
|
||||
}
|
||||
// Tab properties row
|
||||
createNodeConflictRadioBoxes(tab,div,localNodeDiv,remoteNodeDiv,true,!conflicts[tab.id],selectState);
|
||||
createNodeConflictRadioBoxes(tab,div,localNodeDiv,remoteNodeDiv,true,!conflicts[tab.id],selectState,CurrentDiff);
|
||||
}
|
||||
}
|
||||
// var stats = $('<span>',{class:"node-diff-tab-stats"}).appendTo(titleRow);
|
||||
@@ -162,14 +163,14 @@ RED.diff = (function() {
|
||||
var seen = {};
|
||||
object.tab.nodes.forEach(function(node) {
|
||||
seen[node.id] = true;
|
||||
createNodeDiffRow(node,flowStats).appendTo(nodesDiv)
|
||||
createNodeDiffRow(node,flowStats,CurrentDiff).appendTo(nodesDiv)
|
||||
});
|
||||
if (object.newTab) {
|
||||
localNodeCount = object.newTab.nodes.length;
|
||||
object.newTab.nodes.forEach(function(node) {
|
||||
if (!seen[node.id]) {
|
||||
seen[node.id] = true;
|
||||
createNodeDiffRow(node,flowStats).appendTo(nodesDiv)
|
||||
createNodeDiffRow(node,flowStats,CurrentDiff).appendTo(nodesDiv)
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -177,7 +178,7 @@ RED.diff = (function() {
|
||||
remoteNodeCount = object.remoteTab.nodes.length;
|
||||
object.remoteTab.nodes.forEach(function(node) {
|
||||
if (!seen[node.id]) {
|
||||
createNodeDiffRow(node,flowStats).appendTo(nodesDiv)
|
||||
createNodeDiffRow(node,flowStats,CurrentDiff).appendTo(nodesDiv)
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -269,12 +270,12 @@ RED.diff = (function() {
|
||||
if (flowStats.conflicts > 0) {
|
||||
titleRow.addClass("node-diff-node-entry-conflict");
|
||||
} else {
|
||||
selectState = currentDiff.resolutions[tab.id];
|
||||
selectState = CurrentDiff.resolutions[tab.id];
|
||||
}
|
||||
if (tab.id) {
|
||||
var hide = !(flowStats.conflicts > 0 &&(localDiff.deleted[tab.id] || remoteDiff.deleted[tab.id]));
|
||||
// Tab parent row
|
||||
createNodeConflictRadioBoxes(tab,titleRow,localCell,remoteCell, false, hide, selectState);
|
||||
createNodeConflictRadioBoxes(tab,titleRow,localCell,remoteCell, false, hide, selectState, CurrentDiff);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,11 +292,8 @@ RED.diff = (function() {
|
||||
var diffHeaders = $('<div class="node-dialog-view-diff-headers"></div>').appendTo(diffPanel);
|
||||
if (options.mode === "merge") {
|
||||
diffPanel.addClass("node-dialog-view-diff-panel-merge");
|
||||
var toolbar = $('<div class="node-diff-toolbar">'+
|
||||
'<span><span id="node-diff-toolbar-resolved-conflicts"></span></span> '+
|
||||
'</div>').prependTo(diffPanel);
|
||||
}
|
||||
var diffList = createDiffTable(diffPanel);
|
||||
var diffList = createDiffTable(diffPanel, diff);
|
||||
|
||||
var localDiff = diff.localDiff;
|
||||
var remoteDiff = diff.remoteDiff;
|
||||
@@ -512,10 +510,10 @@ RED.diff = (function() {
|
||||
$('<span>',{class:"node-diff-node-label"}).html(nodeLabel).appendTo(contentDiv);
|
||||
return nodeTitleDiv;
|
||||
}
|
||||
function createNodeDiffRow(node,stats) {
|
||||
var localDiff = currentDiff.localDiff;
|
||||
var remoteDiff = currentDiff.remoteDiff;
|
||||
var conflicted = currentDiff.conflicts[node.id];
|
||||
function createNodeDiffRow(node,stats,CurrentDiff) {
|
||||
var localDiff = CurrentDiff.localDiff;
|
||||
var remoteDiff = CurrentDiff.remoteDiff;
|
||||
var conflicted = CurrentDiff.conflicts[node.id];
|
||||
|
||||
var hasChanges = false; // exists in original and local/remote but with changes
|
||||
var unChanged = true; // existing in original,local,remote unchanged
|
||||
@@ -703,10 +701,10 @@ RED.diff = (function() {
|
||||
}
|
||||
div.addClass("node-diff-node-entry-conflict");
|
||||
} else {
|
||||
selectState = currentDiff.resolutions[node.id];
|
||||
selectState = CurrentDiff.resolutions[node.id];
|
||||
}
|
||||
// Node row
|
||||
createNodeConflictRadioBoxes(node,div,localNodeDiv,remoteNodeDiv,false,!conflicted,selectState);
|
||||
createNodeConflictRadioBoxes(node,div,localNodeDiv,remoteNodeDiv,false,!conflicted,selectState,CurrentDiff);
|
||||
row.click(function(evt) {
|
||||
$(this).parent().toggleClass('collapsed');
|
||||
});
|
||||
@@ -982,7 +980,7 @@ RED.diff = (function() {
|
||||
});
|
||||
return nodePropertiesDiv;
|
||||
}
|
||||
function createNodeConflictRadioBoxes(node,row,localDiv,remoteDiv,propertiesTable,hide,state) {
|
||||
function createNodeConflictRadioBoxes(node,row,localDiv,remoteDiv,propertiesTable,hide,state,diff) {
|
||||
var safeNodeId = "node-diff-selectbox-"+node.id.replace(/\./g,'-')+(propertiesTable?"-props":"");
|
||||
var className = "";
|
||||
if (node.z||propertiesTable) {
|
||||
@@ -1019,7 +1017,7 @@ RED.diff = (function() {
|
||||
row.addClass("node-diff-select-remote");
|
||||
row.removeClass("node-diff-select-local");
|
||||
}
|
||||
refreshConflictHeader();
|
||||
refreshConflictHeader(diff);
|
||||
}
|
||||
|
||||
var localSelectDiv = $('<label>',{class:"node-diff-selectbox",for:safeNodeId+"-local"}).click(function(e) { e.stopPropagation();}).appendTo(localDiv);
|
||||
@@ -1037,7 +1035,7 @@ RED.diff = (function() {
|
||||
}
|
||||
|
||||
}
|
||||
function refreshConflictHeader() {
|
||||
function refreshConflictHeader(currentDiff) {
|
||||
var resolutionCount = 0;
|
||||
$(".node-diff-selectbox>input:checked").each(function() {
|
||||
if (currentDiff.conflicts[$(this).data('node-id')]) {
|
||||
@@ -1053,6 +1051,7 @@ RED.diff = (function() {
|
||||
}
|
||||
if (conflictCount === resolutionCount) {
|
||||
$("#node-diff-view-diff-merge").removeClass('disabled');
|
||||
$("#node-diff-view-resolve-diff").removeClass('disabled');
|
||||
}
|
||||
}
|
||||
function getRemoteDiff(callback) {
|
||||
@@ -1231,7 +1230,7 @@ RED.diff = (function() {
|
||||
var localDiff = diff.localDiff;
|
||||
var remoteDiff = diff.remoteDiff;
|
||||
var conflicts = diff.conflicts;
|
||||
currentDiff = diff;
|
||||
// currentDiff = diff;
|
||||
|
||||
var trayOptions = {
|
||||
title: options.title||"Review Changes", //TODO: nls
|
||||
@@ -1250,7 +1249,11 @@ RED.diff = (function() {
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var diffTable = buildDiffPanel(trayBody,diff,options);
|
||||
var toolbar = $('<div class="node-diff-toolbar">'+
|
||||
'<span><span id="node-diff-toolbar-resolved-conflicts"></span></span> '+
|
||||
'</div>').prependTo(trayBody);
|
||||
var diffContainer = $('<div class="node-diff-container"></div>').appendTo(trayBody);
|
||||
var diffTable = buildDiffPanel(diffContainer,diff,options);
|
||||
diffTable.list.hide();
|
||||
if (remoteDiff) {
|
||||
$("#node-diff-view-diff-merge").show();
|
||||
@@ -1262,7 +1265,7 @@ RED.diff = (function() {
|
||||
} else {
|
||||
$("#node-diff-view-diff-merge").hide();
|
||||
}
|
||||
refreshConflictHeader();
|
||||
refreshConflictHeader(diff);
|
||||
// console.log("--------------");
|
||||
// console.log(localDiff);
|
||||
// console.log(remoteDiff);
|
||||
@@ -1290,8 +1293,8 @@ RED.diff = (function() {
|
||||
class: "primary disabled",
|
||||
click: function() {
|
||||
if (!$("#node-diff-view-diff-merge").hasClass('disabled')) {
|
||||
refreshConflictHeader();
|
||||
mergeDiff(currentDiff);
|
||||
refreshConflictHeader(diff);
|
||||
mergeDiff(diff);
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
@@ -1302,7 +1305,7 @@ RED.diff = (function() {
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
|
||||
function mergeDiff(diff) {
|
||||
function applyDiff(diff) {
|
||||
var currentConfig = diff.localDiff.currentConfig;
|
||||
var localDiff = diff.localDiff;
|
||||
var remoteDiff = diff.remoteDiff;
|
||||
@@ -1356,6 +1359,20 @@ RED.diff = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
config: newConfig,
|
||||
nodeChangedStates: nodeChangedStates,
|
||||
localChangedStates: localChangedStates
|
||||
}
|
||||
}
|
||||
|
||||
function mergeDiff(diff) {
|
||||
var appliedDiff = applyDiff(diff);
|
||||
|
||||
var newConfig = appliedDiff.config;
|
||||
var nodeChangedStates = appliedDiff.nodeChangedStates;
|
||||
var localChangedStates = appliedDiff.localChangedStates;
|
||||
|
||||
var historyEvent = {
|
||||
t:"replace",
|
||||
config: RED.nodes.createCompleteNodeSet(),
|
||||
@@ -1374,7 +1391,7 @@ RED.diff = (function() {
|
||||
}
|
||||
})
|
||||
|
||||
RED.nodes.version(remoteDiff.rev);
|
||||
RED.nodes.version(diff.remoteDiff.rev);
|
||||
|
||||
RED.view.redraw(true);
|
||||
RED.palette.refresh();
|
||||
@@ -1417,7 +1434,7 @@ RED.diff = (function() {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var diffPanel = $('<div class="node-text-diff"></div>').appendTo(trayBody);
|
||||
|
||||
var codeTable = $("<table>").appendTo(diffPanel);
|
||||
var codeTable = $("<table>",{class:"node-text-diff-content"}).appendTo(diffPanel);
|
||||
$('<colgroup><col width="50"><col width="50%"><col width="50"><col width="50%"></colgroup>').appendTo(codeTable);
|
||||
var codeBody = $('<tbody>').appendTo(codeTable);
|
||||
var diffSummary = diffText(textA||"",textB||"");
|
||||
@@ -1681,7 +1698,7 @@ RED.diff = (function() {
|
||||
files.forEach(function(file) {
|
||||
var hunks = file.hunks;
|
||||
var isBinary = file.binary;
|
||||
var codeTable = $("<table>").appendTo(diffPanel);
|
||||
var codeTable = $("<table>",{class:"node-text-diff-content"}).appendTo(diffPanel);
|
||||
$('<colgroup><col width="50"><col width="50"><col width="100%"></colgroup>').appendTo(codeTable);
|
||||
var codeBody = $('<tbody>').appendTo(codeTable);
|
||||
|
||||
@@ -1700,49 +1717,82 @@ RED.diff = (function() {
|
||||
var unresolvedConflicts = 0;
|
||||
var resolvedConflicts = 0;
|
||||
var conflictResolutions = {};
|
||||
if (commitOptions.project.files && commitOptions.project.files.flow === file.file) {
|
||||
if (commitOptions.unmerged) {
|
||||
$('<span style="float: right;"><span id="node-diff-toolbar-resolved-conflicts"></span></span>').appendTo(content);
|
||||
}
|
||||
var diffRow = $('<tr class="node-text-diff-header">').appendTo(codeBody);
|
||||
var flowDiffContent = $('<td class="flow-diff" colspan="3"></td>').appendTo(diffRow);
|
||||
|
||||
if (!commitOptions.unmerged && commitOptions.project.files && commitOptions.project.files.flow === file.file) {
|
||||
var tools = $('<span style="float: right;" class="button-group"></span>').appendTo(content);
|
||||
$('<button class="editor-button editor-button-small">show flow diff</button>').appendTo(tools).click(function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var projectName = commitOptions.project.name;
|
||||
var filename = commitOptions.project.files.flow;
|
||||
var oldVersionUrl = "/projects/"+projectName+"/files/"+commitOptions.oldRev+"/"+filename;
|
||||
var newVersionUrl = "/projects/"+projectName+"/files/"+commitOptions.newRev+"/"+filename;
|
||||
$.when($.getJSON(oldVersionUrl),$.getJSON(newVersionUrl)).done(function(oldVersion,newVersion) {
|
||||
var oldFlow;
|
||||
var newFlow;
|
||||
var projectName = commitOptions.project.name;
|
||||
var filename = commitOptions.project.files.flow;
|
||||
var commonVersionUrl = "projects/"+projectName+"/files/"+commitOptions.commonRev+"/"+filename;
|
||||
var oldVersionUrl = "projects/"+projectName+"/files/"+commitOptions.oldRev+"/"+filename;
|
||||
var newVersionUrl = "projects/"+projectName+"/files/"+commitOptions.newRev+"/"+filename;
|
||||
var promises = [$.Deferred(),$.Deferred(),$.Deferred()];
|
||||
if (commitOptions.commonRev) {
|
||||
var commonVersionUrl = "projects/"+projectName+"/files/"+commitOptions.commonRev+"/"+filename;
|
||||
$.ajax({dataType: "json",url: commonVersionUrl}).then(function(data) { promises[0].resolve(data); }).fail(function() { promises[0].resolve(null);})
|
||||
} else {
|
||||
promises[0].resolve(null);
|
||||
}
|
||||
|
||||
$.ajax({dataType: "json",url: oldVersionUrl}).then(function(data) { promises[1].resolve(data); }).fail(function() { promises[1].resolve({content:"[]"});})
|
||||
$.ajax({dataType: "json",url: newVersionUrl}).then(function(data) { promises[2].resolve(data); }).fail(function() { promises[2].resolve({content:"[]"});})
|
||||
$.when.apply($,promises).always(function(commonVersion, oldVersion,newVersion) {
|
||||
var commonFlow;
|
||||
var oldFlow;
|
||||
var newFlow;
|
||||
if (commonVersion) {
|
||||
try {
|
||||
oldFlow = JSON.parse(oldVersion[0].content||"[]");
|
||||
commonFlow = JSON.parse(commonVersion.content||"[]");
|
||||
} catch(err) {
|
||||
console.log("Old Version doesn't contain valid JSON:",oldVersionUrl);
|
||||
console.log("Common Version doesn't contain valid JSON:",commonVersionUrl);
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
newFlow = JSON.parse(newVersion[0].content||"[]");
|
||||
} catch(err) {
|
||||
console.log("New Version doesn't contain valid JSON:",newFlow);
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
var localDiff = generateDiff(oldFlow,oldFlow);
|
||||
var remoteDiff = generateDiff(oldFlow,newFlow);
|
||||
var diff = resolveDiffs(localDiff,remoteDiff);
|
||||
showDiff(diff,{
|
||||
title: filename,
|
||||
mode: 'view',
|
||||
oldRevTitle: commitOptions.oldRevTitle,
|
||||
newRevTitle: commitOptions.newRevTitle
|
||||
});
|
||||
// var flowDiffRow = $("<tr>").insertAfter(diffRow);
|
||||
// var content = $('<td colspan="3"></td>').appendTo(flowDiffRow);
|
||||
// currentDiff = diff;
|
||||
// var diffTable = buildDiffPanel(content,diff,{mode:"view"}).finish();
|
||||
}
|
||||
try {
|
||||
oldFlow = JSON.parse(oldVersion.content||"[]");
|
||||
} catch(err) {
|
||||
console.log("Old Version doesn't contain valid JSON:",oldVersionUrl);
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
if (!commonFlow) {
|
||||
commonFlow = oldFlow;
|
||||
}
|
||||
try {
|
||||
newFlow = JSON.parse(newVersion.content||"[]");
|
||||
} catch(err) {
|
||||
console.log("New Version doesn't contain valid JSON:",newFlow);
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
var localDiff = generateDiff(commonFlow,oldFlow);
|
||||
var remoteDiff = generateDiff(commonFlow,newFlow);
|
||||
commitOptions.currentDiff = resolveDiffs(localDiff,remoteDiff);
|
||||
var diffTable = buildDiffPanel(flowDiffContent,commitOptions.currentDiff,{
|
||||
title: filename,
|
||||
mode: commitOptions.commonRev?'merge':'view',
|
||||
oldRevTitle: commitOptions.oldRevTitle,
|
||||
newRevTitle: commitOptions.newRevTitle
|
||||
});
|
||||
})
|
||||
}
|
||||
diffTable.list.hide();
|
||||
refreshConflictHeader(commitOptions.currentDiff);
|
||||
setTimeout(function() {
|
||||
diffTable.finish();
|
||||
diffTable.list.show();
|
||||
},300);
|
||||
// var flowDiffRow = $("<tr>").insertAfter(diffRow);
|
||||
// var content = $('<td colspan="3"></td>').appendTo(flowDiffRow);
|
||||
// currentDiff = diff;
|
||||
// var diffTable = buildDiffPanel(content,diff,{mode:"view"}).finish();
|
||||
});
|
||||
|
||||
|
||||
|
||||
} else
|
||||
|
||||
if (isBinary) {
|
||||
var diffBinaryRow = $('<tr class="node-text-diff-header">').appendTo(codeBody);
|
||||
@@ -1750,6 +1800,9 @@ RED.diff = (function() {
|
||||
$('<span></span>').text("Cannot show binary file contents").appendTo(binaryContent);
|
||||
|
||||
} else {
|
||||
if (commitOptions.unmerged) {
|
||||
conflictHeader = $('<span style="float: right;"><span>'+resolvedConflicts+'</span> of <span>'+unresolvedConflicts+'</span> conflicts resolved</span>').appendTo(content);
|
||||
}
|
||||
hunks.forEach(function(hunk) {
|
||||
var diffRow = $('<tr class="node-text-diff-header">').appendTo(codeBody);
|
||||
var content = $('<td colspan="3"></td>').appendTo(diffRow);
|
||||
@@ -1768,7 +1821,7 @@ RED.diff = (function() {
|
||||
// }
|
||||
|
||||
var actualLineNumber = hunk.diffStart + lineNumber;
|
||||
var isMergeHeader = isConflict && /^..(<<<<<<<|=======$|>>>>>>>)/.test(lineText);
|
||||
var isMergeHeader = isConflict && /^\+\+(<<<<<<<|=======$|>>>>>>>)/.test(lineText);
|
||||
var diffRow = $('<tr>').appendTo(codeBody);
|
||||
var localLineNo = $('<td class="lineno">').appendTo(diffRow);
|
||||
var remoteLineNo;
|
||||
@@ -1827,7 +1880,7 @@ RED.diff = (function() {
|
||||
$('<span>').text(lineText.substring(prefixEnd)).appendTo(line);
|
||||
} else {
|
||||
diffRow.addClass("mergeHeader");
|
||||
var isSeparator = /^..(=======$)/.test(lineText);
|
||||
var isSeparator = /^\+\+=======$/.test(lineText);
|
||||
if (!isSeparator) {
|
||||
var isOurs = /^..<<<<<<</.test(lineText);
|
||||
if (isOurs) {
|
||||
@@ -1886,9 +1939,6 @@ RED.diff = (function() {
|
||||
});
|
||||
});
|
||||
}
|
||||
if (commitOptions.unmerged) {
|
||||
conflictHeader = $('<span style="float: right;"><span>'+resolvedConflicts+'</span> of <span>'+unresolvedConflicts+'</span> conflicts resolved</span>').appendTo(content);
|
||||
}
|
||||
});
|
||||
return diffPanel;
|
||||
}
|
||||
@@ -1914,7 +1964,7 @@ RED.diff = (function() {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var diffPanel = $('<div class="node-text-diff"></div>').appendTo(trayBody);
|
||||
|
||||
var codeTable = $("<table>").appendTo(diffPanel);
|
||||
var codeTable = $("<table>",{class:"node-text-diff-content"}).appendTo(diffPanel);
|
||||
$('<colgroup><col width="50"><col width="50"><col width="100%"></colgroup>').appendTo(codeTable);
|
||||
var codeBody = $('<tbody>').appendTo(codeTable);
|
||||
|
||||
@@ -1957,7 +2007,6 @@ RED.diff = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var trayOptions = {
|
||||
title: title||"Compare Changes", //TODO: nls
|
||||
width: Infinity,
|
||||
@@ -1996,6 +2045,15 @@ RED.diff = (function() {
|
||||
class: "primary disabled",
|
||||
click: function() {
|
||||
if (!$("#node-diff-view-resolve-diff").hasClass('disabled')) {
|
||||
if (options.currentDiff) {
|
||||
// This is a flow file. Need to apply the diff
|
||||
// and generate the new flow.
|
||||
var result = applyDiff(options.currentDiff);
|
||||
currentResolution = {
|
||||
resolutions:{}
|
||||
};
|
||||
currentResolution.resolutions[options.project.files.flow] = JSON.stringify(result.config,"",4);
|
||||
}
|
||||
if (options.onresolve) {
|
||||
options.onresolve(currentResolution);
|
||||
}
|
||||
@@ -2047,7 +2105,7 @@ RED.diff = (function() {
|
||||
} else {
|
||||
lines = diff.split("\n");
|
||||
}
|
||||
var diffHeader = /^diff --git a\/(.*) b\/(.*)$/;
|
||||
var diffHeader = /^diff (?:(?:--git a\/(.*) b\/(.*))|(?:--cc (.*)))$/;
|
||||
var fileHeader = /^\+\+\+ b\/(.*)\t?/;
|
||||
var binaryFile = /^Binary files /;
|
||||
var hunkHeader = /^@@ -((\d+)(,(\d+))?) \+((\d+)(,(\d+))?) @@ ?(.*)$/;
|
||||
@@ -2066,7 +2124,7 @@ RED.diff = (function() {
|
||||
}
|
||||
currentHunk = null;
|
||||
currentFile = {
|
||||
file: diffLine[1],
|
||||
file: diffLine[1]||diffLine[3],
|
||||
hunks: []
|
||||
}
|
||||
} else if (binaryFile.test(line)) {
|
||||
|
||||
@@ -48,7 +48,7 @@ RED.editor = (function() {
|
||||
isValid = validateNode(subflow);
|
||||
hasChanged = subflow.changed;
|
||||
}
|
||||
node.valid = isValid;
|
||||
node.valid = isValid && validateNodeProperties(node, node._def.defaults, node);
|
||||
node.changed = node.changed || hasChanged;
|
||||
} else if (node._def) {
|
||||
node.valid = validateNodeProperties(node, node._def.defaults, node);
|
||||
@@ -170,6 +170,10 @@ RED.editor = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
validateIcon(node);
|
||||
}
|
||||
|
||||
function validateIcon(node) {
|
||||
if (node._def.hasOwnProperty("defaults") && !node._def.defaults.hasOwnProperty("icon") && node.icon) {
|
||||
var iconPath = RED.utils.separateIconPath(node.icon);
|
||||
var iconSets = RED.nodes.getIconSets();
|
||||
@@ -188,6 +192,7 @@ RED.editor = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateNodeEditorProperty(node,defaults,property,prefix) {
|
||||
var input = $("#"+prefix+"-"+property);
|
||||
if (input.length > 0) {
|
||||
@@ -742,7 +747,7 @@ RED.editor = (function() {
|
||||
buildLabelRow().appendTo(outputsDiv);
|
||||
}
|
||||
|
||||
if (!node._def.defaults.hasOwnProperty("icon")) {
|
||||
if ((!node._def.defaults || !node._def.defaults.hasOwnProperty("icon"))) {
|
||||
$('<div class="form-row"><div id="node-settings-icon"></div></div>').appendTo(dialogForm);
|
||||
var iconDiv = $("#node-settings-icon");
|
||||
$('<label data-i18n="editor.settingIcon">').appendTo(iconDiv);
|
||||
@@ -816,9 +821,51 @@ RED.editor = (function() {
|
||||
});
|
||||
}
|
||||
selectIconFile.prop("disabled", !iconFileList);
|
||||
selectIconFile.removeClass("input-error");
|
||||
selectIconModule.removeClass("input-error");
|
||||
}
|
||||
|
||||
function updateLabels(editing_node, changes, outputMap) {
|
||||
var inputLabels = $("#node-label-form-inputs").children().find("input");
|
||||
var outputLabels = $("#node-label-form-outputs").children().find("input");
|
||||
|
||||
var hasNonBlankLabel = false;
|
||||
var changed = false;
|
||||
var newValue = inputLabels.map(function() {
|
||||
var v = $(this).val();
|
||||
hasNonBlankLabel = hasNonBlankLabel || v!== "";
|
||||
return v;
|
||||
}).toArray().slice(0,editing_node.inputs);
|
||||
if ((editing_node.inputLabels === undefined && hasNonBlankLabel) ||
|
||||
(editing_node.inputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(editing_node.inputLabels))) {
|
||||
changes.inputLabels = editing_node.inputLabels;
|
||||
editing_node.inputLabels = newValue;
|
||||
changed = true;
|
||||
}
|
||||
hasNonBlankLabel = false;
|
||||
newValue = new Array(editing_node.outputs);
|
||||
outputLabels.each(function() {
|
||||
var index = $(this).attr('id').substring(23); // node-label-form-output-<index>
|
||||
if (outputMap && outputMap.hasOwnProperty(index)) {
|
||||
index = parseInt(outputMap[index]);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var v = $(this).val();
|
||||
hasNonBlankLabel = hasNonBlankLabel || v!== "";
|
||||
newValue[index] = v;
|
||||
});
|
||||
|
||||
if ((editing_node.outputLabels === undefined && hasNonBlankLabel) ||
|
||||
(editing_node.outputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(editing_node.outputLabels))) {
|
||||
changes.outputLabels = editing_node.outputLabels;
|
||||
editing_node.outputLabels = newValue;
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
function showEditDialog(node) {
|
||||
var editing_node = node;
|
||||
var isDefaultIcon;
|
||||
@@ -1034,44 +1081,11 @@ RED.editor = (function() {
|
||||
// }
|
||||
var removedLinks = updateNodeProperties(editing_node,outputMap);
|
||||
|
||||
var inputLabels = $("#node-label-form-inputs").children().find("input");
|
||||
var outputLabels = $("#node-label-form-outputs").children().find("input");
|
||||
|
||||
var hasNonBlankLabel = false;
|
||||
newValue = inputLabels.map(function() {
|
||||
var v = $(this).val();
|
||||
hasNonBlankLabel = hasNonBlankLabel || v!== "";
|
||||
return v;
|
||||
}).toArray().slice(0,editing_node.inputs);
|
||||
if ((editing_node.inputLabels === undefined && hasNonBlankLabel) ||
|
||||
(editing_node.inputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(editing_node.inputLabels))) {
|
||||
changes.inputLabels = editing_node.inputLabels;
|
||||
editing_node.inputLabels = newValue;
|
||||
changed = true;
|
||||
}
|
||||
hasNonBlankLabel = false;
|
||||
newValue = new Array(editing_node.outputs);
|
||||
outputLabels.each(function() {
|
||||
var index = $(this).attr('id').substring(23); // node-label-form-output-<index>
|
||||
if (outputMap && outputMap.hasOwnProperty(index)) {
|
||||
index = parseInt(outputMap[index]);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var v = $(this).val();
|
||||
hasNonBlankLabel = hasNonBlankLabel || v!== "";
|
||||
newValue[index] = v;
|
||||
})
|
||||
|
||||
if ((editing_node.outputLabels === undefined && hasNonBlankLabel) ||
|
||||
(editing_node.outputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(editing_node.outputLabels))) {
|
||||
changes.outputLabels = editing_node.outputLabels;
|
||||
editing_node.outputLabels = newValue;
|
||||
if (updateLabels(editing_node, changes, outputMap)) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (!editing_node._def.defaults.hasOwnProperty("icon")) {
|
||||
if (!editing_node._def.defaults || !editing_node._def.defaults.hasOwnProperty("icon")) {
|
||||
var iconModule = $("#node-settings-icon-module-hidden").val();
|
||||
var iconFile = $("#node-settings-icon-file-hidden").val();
|
||||
var icon = (iconModule && iconFile) ? iconModule+"/"+iconFile : "";
|
||||
@@ -1675,25 +1689,25 @@ RED.editor = (function() {
|
||||
editing_node.info = newDescription;
|
||||
changed = true;
|
||||
}
|
||||
var inputLabels = $("#node-label-form-inputs").children().find("input");
|
||||
var outputLabels = $("#node-label-form-outputs").children().find("input");
|
||||
|
||||
var newValue = inputLabels.map(function() { return $(this).val();}).toArray().slice(0,editing_node.inputs);
|
||||
if (JSON.stringify(newValue) !== JSON.stringify(editing_node.inputLabels)) {
|
||||
changes.inputLabels = editing_node.inputLabels;
|
||||
editing_node.inputLabels = newValue;
|
||||
if (updateLabels(editing_node, changes, null)) {
|
||||
changed = true;
|
||||
}
|
||||
newValue = outputLabels.map(function() { return $(this).val();}).toArray().slice(0,editing_node.outputs);
|
||||
if (JSON.stringify(newValue) !== JSON.stringify(editing_node.outputLabels)) {
|
||||
changes.outputLabels = editing_node.outputLabels;
|
||||
editing_node.outputLabels = newValue;
|
||||
var iconModule = $("#node-settings-icon-module-hidden").val();
|
||||
var iconFile = $("#node-settings-icon-file-hidden").val();
|
||||
var icon = (iconModule && iconFile) ? iconModule+"/"+iconFile : "";
|
||||
if ((editing_node.icon === undefined && icon !== "node-red/subflow.png") ||
|
||||
(editing_node.icon !== undefined && editing_node.icon !== icon)) {
|
||||
changes.icon = editing_node.icon;
|
||||
editing_node.icon = icon;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
RED.palette.refresh();
|
||||
|
||||
if (changed) {
|
||||
var wasChanged = editing_node.changed;
|
||||
editing_node.changed = true;
|
||||
validateNode(editing_node);
|
||||
var subflowInstances = [];
|
||||
RED.nodes.eachNode(function(n) {
|
||||
if (n.type == "subflow:"+editing_node.id) {
|
||||
@@ -1704,10 +1718,9 @@ RED.editor = (function() {
|
||||
n.changed = true;
|
||||
n.dirty = true;
|
||||
updateNodeProperties(n);
|
||||
validateNode(n);
|
||||
}
|
||||
});
|
||||
var wasChanged = editing_node.changed;
|
||||
editing_node.changed = true;
|
||||
RED.nodes.dirty(true);
|
||||
var historyEvent = {
|
||||
t:'edit',
|
||||
@@ -1786,6 +1799,7 @@ RED.editor = (function() {
|
||||
$("#subflow-dialog-user-count").html(RED._("subflow.subflowInstances", {count:userCount})).show();
|
||||
|
||||
buildLabelForm(portLabels.content,subflow);
|
||||
validateIcon(subflow);
|
||||
trayBody.i18n();
|
||||
},
|
||||
close: function() {
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
**/
|
||||
RED.library = (function() {
|
||||
|
||||
|
||||
var exportToLibraryDialog;
|
||||
var elementPrefix = "node-input-";
|
||||
|
||||
function loadFlowLibrary() {
|
||||
$.getJSON("library/flows",function(data) {
|
||||
@@ -86,6 +86,7 @@ RED.library = (function() {
|
||||
var libraryData = {};
|
||||
var selectedLibraryItem = null;
|
||||
var libraryEditor = null;
|
||||
elementPrefix = options.elementPrefix || "node-input-";
|
||||
|
||||
// Orion editor has set/getText
|
||||
// ACE editor has set/getValue
|
||||
@@ -157,8 +158,8 @@ RED.library = (function() {
|
||||
return ul;
|
||||
}
|
||||
|
||||
$('#node-input-name').css("width","66%").after(
|
||||
'<div class="btn-group" style="margin-left: 5px;">'+
|
||||
$('#'+elementPrefix+"name").css("width","calc(100% - 52px)").after(
|
||||
'<div class="btn-group" style="margin-left:5px;">'+
|
||||
'<a id="node-input-'+options.type+'-lookup" class="editor-button" data-toggle="dropdown"><i class="fa fa-book"></i> <i class="fa fa-caret-down"></i></a>'+
|
||||
'<ul class="dropdown-menu pull-right" role="menu">'+
|
||||
'<li><a id="node-input-'+options.type+'-menu-open-library" tabindex="-1" href="#">'+RED._("library.openLibrary")+'</a></li>'+
|
||||
@@ -187,7 +188,7 @@ RED.library = (function() {
|
||||
|
||||
$('#node-input-'+options.type+'-menu-save-library').click(function(e) {
|
||||
//var found = false;
|
||||
var name = $("#node-input-name").val().replace(/(^\s*)|(\s*$)/g,"");
|
||||
var name = $("#"+elementPrefix+"name").val().replace(/(^\s*)|(\s*$)/g,"");
|
||||
|
||||
//var buildPathList = function(data,root) {
|
||||
// var paths = [];
|
||||
@@ -264,7 +265,7 @@ RED.library = (function() {
|
||||
if (selectedLibraryItem) {
|
||||
for (var i=0; i<options.fields.length; i++) {
|
||||
var field = options.fields[i];
|
||||
$("#node-input-"+field).val(selectedLibraryItem[field]);
|
||||
$("#"+elementPrefix+field).val(selectedLibraryItem[field]);
|
||||
}
|
||||
options.editor.setValue(libraryEditor.getValue(),-1);
|
||||
}
|
||||
@@ -286,7 +287,7 @@ RED.library = (function() {
|
||||
});
|
||||
|
||||
function saveToLibrary(overwrite) {
|
||||
var name = $("#node-input-name").val().replace(/(^\s*)|(\s*$)/g,"");
|
||||
var name = $("#"+elementPrefix+"name").val().replace(/(^\s*)|(\s*$)/g,"");
|
||||
if (name === "") {
|
||||
name = RED._("library.unnamedType",{type:options.type});
|
||||
}
|
||||
@@ -330,7 +331,7 @@ RED.library = (function() {
|
||||
if (field == "name") {
|
||||
data.name = name;
|
||||
} else {
|
||||
data[field] = $("#node-input-"+field).val();
|
||||
data[field] = $("#"+elementPrefix+field).val();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,6 +116,12 @@ RED.palette = (function() {
|
||||
el.data('popover').setContent(popOverContent);
|
||||
}
|
||||
|
||||
function setIcon(element,sf) {
|
||||
var iconElement = element.find(".palette_icon");
|
||||
var icon_url = RED.utils.getNodeIcon(sf._def,sf);
|
||||
iconElement.attr("style", "background-image: url("+icon_url+")");
|
||||
}
|
||||
|
||||
function escapeNodeType(nt) {
|
||||
return nt.replace(" ","_").replace(".","_").replace(":","_");
|
||||
}
|
||||
@@ -219,13 +225,19 @@ RED.palette = (function() {
|
||||
var mouseX;
|
||||
var mouseY;
|
||||
var spliceTimer;
|
||||
var paletteWidth;
|
||||
var paletteTop;
|
||||
$(d).draggable({
|
||||
helper: 'clone',
|
||||
appendTo: 'body',
|
||||
revert: true,
|
||||
revertDuration: 50,
|
||||
containment:'#main-container',
|
||||
start: function() {RED.view.focus();},
|
||||
start: function() {
|
||||
paletteWidth = $("#palette").width();
|
||||
paletteTop = $("#palette").parent().position().top + $("#palette-container").position().top;
|
||||
RED.view.focus();
|
||||
},
|
||||
stop: function() { d3.select('.link_splice').classed('link_splice',false); if (spliceTimer) { clearTimeout(spliceTimer); spliceTimer = null;}},
|
||||
drag: function(e,ui) {
|
||||
|
||||
@@ -235,9 +247,8 @@ RED.palette = (function() {
|
||||
ui.position.left += 17.5;
|
||||
|
||||
if (def.inputs > 0 && def.outputs > 0) {
|
||||
mouseX = ui.position.left+(ui.helper.width()/2) - chartOffset.left + chart.scrollLeft();
|
||||
mouseY = ui.position.top+(ui.helper.height()/2) - chartOffset.top + chart.scrollTop();
|
||||
|
||||
mouseX = ui.position.left-paletteWidth+(ui.helper.width()/2) - chartOffset.left + chart.scrollLeft();
|
||||
mouseY = ui.position.top-paletteTop+(ui.helper.height()/2) - chartOffset.top + chart.scrollTop();
|
||||
if (!spliceTimer) {
|
||||
spliceTimer = setTimeout(function() {
|
||||
var nodes = [];
|
||||
@@ -259,6 +270,7 @@ RED.palette = (function() {
|
||||
mouseY /= RED.view.scale();
|
||||
nodes = RED.view.getLinksAtPoint(mouseX,mouseY);
|
||||
}
|
||||
|
||||
for (var i=0;i<nodes.length;i++) {
|
||||
if (d3.select(nodes[i]).classed('link_background')) {
|
||||
var length = nodes[i].getTotalLength();
|
||||
@@ -369,6 +381,7 @@ RED.palette = (function() {
|
||||
portOutput.remove();
|
||||
}
|
||||
setLabel(sf.type+":"+sf.id,paletteNode,sf.name,marked(sf.info||""));
|
||||
setIcon(paletteNode,sf);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ RED.projects.settings = (function() {
|
||||
var tabContainer;
|
||||
|
||||
var trayOptions = {
|
||||
title: "Project Information",// RED._("menu.label.userSettings"),, // TODO: nls
|
||||
title: "Project Settings",// RED._("menu.label.userSettings"),, // TODO: nls
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
@@ -143,7 +143,8 @@ RED.projects.settings = (function() {
|
||||
RED.sidebar.versionControl.refresh(true);
|
||||
},
|
||||
400: {
|
||||
'unexpected_error': function(error) {
|
||||
'*': function(error) {
|
||||
utils.reportUnexpectedError(error);
|
||||
done(error,null);
|
||||
}
|
||||
},
|
||||
@@ -208,7 +209,8 @@ RED.projects.settings = (function() {
|
||||
done(null,data);
|
||||
},
|
||||
400: {
|
||||
'unexpected_error': function(error) {
|
||||
'*': function(error) {
|
||||
utils.reportUnexpectedError(error);
|
||||
done(error,null);
|
||||
}
|
||||
},
|
||||
@@ -350,6 +352,7 @@ RED.projects.settings = (function() {
|
||||
}
|
||||
},{dependencies:dependencies});
|
||||
}
|
||||
|
||||
function editDependencies(activeProject,depsJSON,container,depsList) {
|
||||
var json = depsJSON||JSON.stringify(activeProject.dependencies||{},"",4);
|
||||
if (json === "{}") {
|
||||
@@ -378,6 +381,7 @@ RED.projects.settings = (function() {
|
||||
|
||||
function createDependenciesPane(activeProject) {
|
||||
var pane = $('<div id="project-settings-tab-deps" class="project-settings-tab-pane node-help"></div>');
|
||||
var nrDepButton;
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
$('<button class="editor-button editor-button-small" style="margin-top:10px;float: right;">edit</button>')
|
||||
.appendTo(pane)
|
||||
@@ -385,6 +389,16 @@ RED.projects.settings = (function() {
|
||||
evt.preventDefault();
|
||||
editDependencies(activeProject,null,pane,depsList)
|
||||
});
|
||||
|
||||
nrDepButton = $('<button class="editor-button editor-button-small" style="margin-top:10px;">add Node-RED core</button>')
|
||||
.appendTo(pane)
|
||||
.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
activeProject.dependencies["node-red"] = "~"+RED.settings.version;
|
||||
updateProjectDependencies(activeProject,depsList);
|
||||
$(this).hide();
|
||||
});
|
||||
if (activeProject.dependencies.hasOwnProperty("node-red")) { nrDepButton.hide(); }
|
||||
}
|
||||
var depsList = $("<ol>",{style:"position: absolute;top: 60px;bottom: 20px;left: 20px;right: 20px;"}).appendTo(pane);
|
||||
depsList.editableList({
|
||||
@@ -471,6 +485,7 @@ RED.projects.settings = (function() {
|
||||
evt.preventDefault();
|
||||
var deps = $.extend(true, {}, activeProject.dependencies);
|
||||
delete deps[entry.id];
|
||||
if (entry.id === "node-red") { nrDepButton.show(); }
|
||||
saveDependencies(depsList,row,deps,function(err) {
|
||||
if (!err) {
|
||||
row.fadeOut(200,function() {
|
||||
@@ -517,7 +532,6 @@ RED.projects.settings = (function() {
|
||||
|
||||
updateProjectDependencies(activeProject,depsList);
|
||||
return pane;
|
||||
|
||||
}
|
||||
|
||||
function showProjectFileListing(row,activeProject,current,filter,done) {
|
||||
@@ -962,7 +976,7 @@ RED.projects.settings = (function() {
|
||||
var done = function(err) {
|
||||
spinner.remove();
|
||||
if (err) {
|
||||
console.log(err);
|
||||
utils.reportUnexpectedError(err);
|
||||
return;
|
||||
}
|
||||
flowFileLabelText.text(flowFileInput.val());
|
||||
@@ -1005,10 +1019,6 @@ 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({
|
||||
@@ -1019,11 +1029,16 @@ RED.projects.settings = (function() {
|
||||
autoClose: 3000
|
||||
}).open();
|
||||
done(error);
|
||||
},
|
||||
'*': function(error) {
|
||||
done(error);
|
||||
}
|
||||
},
|
||||
}
|
||||
},payload).always(function() {
|
||||
RED.deploy.setDeployInflight(false);
|
||||
setTimeout(function() {
|
||||
RED.deploy.setDeployInflight(false);
|
||||
},500);
|
||||
});
|
||||
});
|
||||
var updateForm = function() {
|
||||
@@ -1142,8 +1157,8 @@ RED.projects.settings = (function() {
|
||||
]
|
||||
});
|
||||
},
|
||||
'unexpected_error': function(error) {
|
||||
console.log(error);
|
||||
'*': function(error) {
|
||||
utils.reportUnexpectedError(error);
|
||||
spinner.remove();
|
||||
}
|
||||
},
|
||||
@@ -1193,12 +1208,19 @@ 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);
|
||||
@@ -1256,6 +1278,7 @@ 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 = {};
|
||||
@@ -1265,11 +1288,12 @@ RED.projects.settings = (function() {
|
||||
activeProject.git.remotes[name] = remote;
|
||||
});
|
||||
}
|
||||
RED.sidebar.versionControl.refresh();
|
||||
});
|
||||
},
|
||||
400: {
|
||||
'unexpected_error': function(error) {
|
||||
console.log(error);
|
||||
'*': function(error) {
|
||||
utils.reportUnexpectedError(error);
|
||||
spinner.remove();
|
||||
}
|
||||
},
|
||||
@@ -1290,16 +1314,26 @@ 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 = !/\s/.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://");
|
||||
}
|
||||
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);
|
||||
|
||||
@@ -1309,11 +1343,14 @@ 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",validateForm);
|
||||
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 hideEditForm = function() {
|
||||
editRepoButton.attr('disabled',false);
|
||||
@@ -1367,6 +1404,7 @@ RED.projects.settings = (function() {
|
||||
activeProject.git.remotes[name] = remote;
|
||||
});
|
||||
updateForm();
|
||||
RED.sidebar.versionControl.refresh();
|
||||
done();
|
||||
},
|
||||
400: {
|
||||
@@ -1381,14 +1419,15 @@ RED.projects.settings = (function() {
|
||||
remoteNameInput.addClass('input-error');
|
||||
done(error);
|
||||
},
|
||||
'unexpected_error': function(error) {
|
||||
console.log(error);
|
||||
'*': function(error) {
|
||||
utils.reportUnexpectedError(error);
|
||||
done(error);
|
||||
}
|
||||
},
|
||||
}
|
||||
},payload);
|
||||
});
|
||||
|
||||
var updateForm = function() {
|
||||
remotesList.editableList('empty');
|
||||
var count = 0;
|
||||
@@ -1400,7 +1439,8 @@ RED.projects.settings = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count === 0) {
|
||||
isEmpty = (count === 0);
|
||||
if (isEmpty) {
|
||||
remotesList.editableList('addItem',emptyItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,45 @@ 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>');
|
||||
@@ -39,8 +77,8 @@ RED.projects = (function() {
|
||||
var body = $('<div class="projects-dialog-screen-start-body"></div>').appendTo(container);
|
||||
$('<p>').text("Hello! We have introduced 'projects' to Node-RED.").appendTo(body);
|
||||
$('<p>').text("This is a new way for you to manage your flow files and includes version control of your flows.").appendTo(body);
|
||||
$('<p>').text("To get started you can create your first project using your current flow files in a few easy steps.").appendTo(body);
|
||||
$('<p>').text("If you are not sure, you can skip this for now. You will still be able to create your first project from the 'Projects' menu option at any time.").appendTo(body);
|
||||
$('<p>').text("To get started you can create your first project or clone an existing project from a git repository.").appendTo(body);
|
||||
$('<p>').text("If you are not sure, you can skip this for now. You will still be able to create your first project from the 'Projects' menu at any time.").appendTo(body);
|
||||
|
||||
return container;
|
||||
},
|
||||
@@ -275,9 +313,9 @@ RED.projects = (function() {
|
||||
var body = $('<div class="projects-dialog-screen-start-body"></div>').appendTo(container);
|
||||
|
||||
$('<p>').text("Create your project files").appendTo(body);
|
||||
$('<p>').text("A project contains your flow files, a README file, a package.json file and a settings file.").appendTo(body);
|
||||
$('<p>').text("A project contains your flow files, a README file and a package.json file.").appendTo(body);
|
||||
$('<p>').text("It can contain any other files you want to maintain in the Git repository.").appendTo(body);
|
||||
if (!options.existingProject) {
|
||||
if (!options.existingProject && RED.settings.files) {
|
||||
$('<p>').text("Your existing flow and credential files will be copied into the project.").appendTo(body);
|
||||
}
|
||||
|
||||
@@ -311,14 +349,14 @@ RED.projects = (function() {
|
||||
var row = $('<div class="form-row"></div>').appendTo(body);
|
||||
$('<label for="projects-dialog-screen-create-project-file">Flow file</label>').appendTo(row);
|
||||
var subrow = $('<div style="position:relative;"></div>').appendTo(row);
|
||||
var defaultFlowFile = (createProjectOptions.files &&createProjectOptions.files.flow) || RED.settings.files.flow||"flow.json";
|
||||
var defaultFlowFile = (createProjectOptions.files &&createProjectOptions.files.flow) || (RED.settings.files && RED.settings.files.flow)||"flow.json";
|
||||
projectFlowFileInput = $('<input id="projects-dialog-screen-create-project-file" type="text">').val(defaultFlowFile)
|
||||
.on("change keyup paste",validateForm)
|
||||
.appendTo(subrow);
|
||||
$('<div class="projects-dialog-screen-input-status"></div>').appendTo(subrow);
|
||||
$('<label class="projects-edit-form-sublabel"><small>*.json</small></label>').appendTo(row);
|
||||
|
||||
var defaultCredentialsFile = (createProjectOptions.files &&createProjectOptions.files.credentials) || RED.settings.files.credentials||"flow_cred.json";
|
||||
var defaultCredentialsFile = (createProjectOptions.files &&createProjectOptions.files.credentials) || (RED.settings.files && RED.settings.files.credentials)||"flow_cred.json";
|
||||
row = $('<div class="form-row"></div>').appendTo(body);
|
||||
$('<label for="projects-dialog-screen-create-project-credfile">Credentials file</label>').appendTo(row);
|
||||
subrow = $('<div style="position:relative;"></div>').appendTo(row);
|
||||
@@ -546,6 +584,7 @@ RED.projects = (function() {
|
||||
} else {
|
||||
show('create-success');
|
||||
RED.menu.setDisabled('menu-item-projects-open',false);
|
||||
RED.menu.setDisabled('menu-item-projects-settings',false);
|
||||
}
|
||||
},
|
||||
400: {
|
||||
@@ -564,8 +603,9 @@ RED.projects = (function() {
|
||||
// getRepoAuthDetails(req);
|
||||
console.log("git auth error",error);
|
||||
},
|
||||
'unexpected_error': function(error) {
|
||||
console.log("unexpected_error",error)
|
||||
'*': function(error) {
|
||||
reportUnexpectedError(error);
|
||||
$( dialog ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -614,6 +654,7 @@ RED.projects = (function() {
|
||||
var projectSecretSelect;
|
||||
var copyProject;
|
||||
var projectRepoInput;
|
||||
var projectCloneSecret;
|
||||
var emptyProjectCredentialInput;
|
||||
var projectRepoUserInput;
|
||||
var projectRepoPasswordInput;
|
||||
@@ -682,7 +723,11 @@ RED.projects = (function() {
|
||||
var repo = projectRepoInput.val();
|
||||
|
||||
// var validRepo = /^(?:file|git|ssh|https?|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?[\w\.@:\/~_-]+(?:\/?|\#[\d\w\.\-_]+?)$/.test(repo);
|
||||
var validRepo = !/\s/.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;
|
||||
}
|
||||
if (!validRepo) {
|
||||
if (projectRepoChanged) {
|
||||
projectRepoInput.addClass("input-error");
|
||||
@@ -769,7 +814,11 @@ RED.projects = (function() {
|
||||
validateForm();
|
||||
},
|
||||
delete: function(project) {
|
||||
if (projectList) {
|
||||
delete projectList[project.name];
|
||||
}
|
||||
selectedProject = null;
|
||||
|
||||
validateForm();
|
||||
}
|
||||
}).appendTo(row);
|
||||
@@ -971,10 +1020,12 @@ RED.projects = (function() {
|
||||
// -----------------------------------------------------
|
||||
|
||||
|
||||
// // Secret - clone
|
||||
// row = $('<div class="hide form-row projects-dialog-screen-create-row projects-dialog-screen-create-row-clone"></div>').appendTo(container);
|
||||
// $('<label>Credentials encryption key</label>').appendTo(row);
|
||||
// projectSecretInput = $('<input type="text"></input>').appendTo(row);
|
||||
// Secret - clone
|
||||
row = $('<div class="hide form-row projects-dialog-screen-create-row projects-dialog-screen-create-row-clone"></div>').appendTo(container);
|
||||
$('<label>Credentials encryption key</label>').appendTo(row);
|
||||
projectSecretInput = $('<input type="password"></input>').appendTo(row);
|
||||
|
||||
|
||||
switch(options.screen||"empty") {
|
||||
case "empty": createAsEmpty.click(); break;
|
||||
case "open": openProject.click(); break;
|
||||
@@ -1032,7 +1083,7 @@ RED.projects = (function() {
|
||||
} else if (projectType === 'copy') {
|
||||
projectData.copy = copyProject.name;
|
||||
} else if (projectType === 'clone') {
|
||||
// projectData.credentialSecret = projectSecretInput.val();
|
||||
projectData.credentialSecret = projectSecretInput.val();
|
||||
var repoUrl = projectRepoInput.val();
|
||||
var metaData = {};
|
||||
if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(repoUrl)) {
|
||||
@@ -1082,7 +1133,6 @@ RED.projects = (function() {
|
||||
projectRepoSSHKeySelect.removeClass("input-error");
|
||||
projectRepoPassphrase.removeClass("input-error");
|
||||
|
||||
|
||||
RED.deploy.setDeployInflight(true);
|
||||
RED.projects.settings.switchProject(projectData.name);
|
||||
|
||||
@@ -1122,6 +1172,10 @@ RED.projects = (function() {
|
||||
projectRepoSSHKeySelect.addClass("input-error");
|
||||
projectRepoPassphrase.addClass("input-error");
|
||||
},
|
||||
'missing_flow_file': function(error) {
|
||||
// This is handled via a runtime notification.
|
||||
dialog.dialog("close");
|
||||
},
|
||||
'project_empty': function(error) {
|
||||
// This is handled via a runtime notification.
|
||||
dialog.dialog("close");
|
||||
@@ -1130,8 +1184,9 @@ RED.projects = (function() {
|
||||
// This is handled via a runtime notification.
|
||||
dialog.dialog("close");
|
||||
},
|
||||
'unexpected_error': function(error) {
|
||||
console.log("unexpected_error",error)
|
||||
'*': function(error) {
|
||||
reportUnexpectedError(error);
|
||||
$( dialog ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1517,7 +1572,7 @@ RED.projects = (function() {
|
||||
'</div>');
|
||||
|
||||
var isSSH = false;
|
||||
if (/^https?:\/\//) {
|
||||
if (/^https?:\/\//.test(url)) {
|
||||
$('<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)) {
|
||||
@@ -1738,8 +1793,17 @@ 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) {
|
||||
console.log(error);
|
||||
reportUnexpectedError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1782,11 +1846,12 @@ 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
|
||||
addSpinnerOverlay:addSpinnerOverlay,
|
||||
reportUnexpectedError:reportUnexpectedError
|
||||
};
|
||||
RED.projects.settings.init(projectsAPI);
|
||||
RED.projects.userSettings.init(projectsAPI);
|
||||
|
||||
@@ -30,7 +30,6 @@ RED.sidebar.versionControl = (function() {
|
||||
var unmergedContent;
|
||||
var unmergedChangesList;
|
||||
var commitButton;
|
||||
var mergeConflictNotification;
|
||||
var localChanges;
|
||||
|
||||
var localCommitList;
|
||||
@@ -51,10 +50,6 @@ RED.sidebar.versionControl = (function() {
|
||||
// done(error,null);
|
||||
},
|
||||
200: function(data) {
|
||||
if (mergeConflictNotification) {
|
||||
mergeConflictNotification.close();
|
||||
mergeConflictNotification = null;
|
||||
}
|
||||
var title;
|
||||
if (state === 'unstaged') {
|
||||
title = 'Unstaged changes : '+entry.file
|
||||
@@ -80,6 +75,11 @@ RED.sidebar.versionControl = (function() {
|
||||
options.oldRev = "@";
|
||||
options.newRev = ":0";
|
||||
} else {
|
||||
options.oldRevTitle = "Local";
|
||||
options.newRevTitle = "Remote";
|
||||
options.commonRev = ":1";
|
||||
options.oldRev = ":2";
|
||||
options.newRev = ":3";
|
||||
options.onresolve = function(resolution) {
|
||||
utils.sendRequest({
|
||||
url: "projects/"+activeProject.name+"/resolve/"+encodeURIComponent(entry.file),
|
||||
@@ -102,9 +102,7 @@ RED.sidebar.versionControl = (function() {
|
||||
},{resolutions:resolution.resolutions[entry.file]});
|
||||
}
|
||||
}
|
||||
options.oncancel = showMergeConflictNotification;
|
||||
RED.diff.showUnifiedDiff(options);
|
||||
// console.log(data.diff);
|
||||
},
|
||||
400: {
|
||||
'unexpected_error': function(error) {
|
||||
@@ -122,6 +120,18 @@ RED.sidebar.versionControl = (function() {
|
||||
if (entry.label) {
|
||||
row.addClass('node-info-none');
|
||||
container.text(entry.label);
|
||||
if (entry.button) {
|
||||
container.css({
|
||||
display: "inline-block",
|
||||
maxWidth: "300px",
|
||||
textAlign: "left"
|
||||
})
|
||||
var toolbar = $('<div style="float: right; margin: 5px; height: 50px;"></div>').appendTo(container);
|
||||
|
||||
$('<button class="editor-button editor-button-small"></button>').text(entry.button.label)
|
||||
.appendTo(toolbar)
|
||||
.click(entry.button.click);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -144,6 +154,7 @@ RED.sidebar.versionControl = (function() {
|
||||
.appendTo(bg)
|
||||
.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
|
||||
var spinner = utils.addSpinnerOverlay(container).addClass('projects-dialog-spinner-contain');
|
||||
var notification = RED.notify("Are you sure you want to revert the changes to '"+entry.file+"'? This cannot be undone.", {
|
||||
type: "warning",
|
||||
@@ -178,7 +189,12 @@ RED.sidebar.versionControl = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
utils.sendRequest(options);
|
||||
RED.deploy.setDeployInflight(true);
|
||||
utils.sendRequest(options).always(function() {
|
||||
setTimeout(function() {
|
||||
RED.deploy.setDeployInflight(false);
|
||||
},500);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,6 +368,7 @@ RED.sidebar.versionControl = (function() {
|
||||
evt.stopPropagation();
|
||||
var spinner = utils.addSpinnerOverlay(unmergedContent);
|
||||
var activeProject = RED.projects.getActiveProject();
|
||||
RED.deploy.setDeployInflight(true);
|
||||
utils.sendRequest({
|
||||
url: "projects/"+activeProject.name+"/merge",
|
||||
type: "DELETE",
|
||||
@@ -369,6 +386,10 @@ RED.sidebar.versionControl = (function() {
|
||||
}
|
||||
},
|
||||
}
|
||||
}).always(function() {
|
||||
setTimeout(function() {
|
||||
RED.deploy.setDeployInflight(false);
|
||||
},500);
|
||||
});
|
||||
});
|
||||
unmergedChangesList = $("<ol>",{style:"position: absolute; top: 30px; bottom: 0; right:0; left:0;"}).appendTo(unmergedContent);
|
||||
@@ -376,6 +397,16 @@ RED.sidebar.versionControl = (function() {
|
||||
addButton: false,
|
||||
scrollOnAdd: false,
|
||||
addItem: function(row,index,entry) {
|
||||
if (entry === emptyMergedItem) {
|
||||
entry.button = {
|
||||
label: 'commit',
|
||||
click: function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
showCommitBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
createChangeEntry(row,entry,entry.treeStatus,'unmerged');
|
||||
},
|
||||
sort: function(A,B) {
|
||||
@@ -395,28 +426,32 @@ RED.sidebar.versionControl = (function() {
|
||||
header = $('<div class="sidebar-version-control-change-header">Changes to commit</div>').appendTo(stagedContent);
|
||||
|
||||
bg = $('<div style="float: right"></div>').appendTo(header);
|
||||
var showCommitBox = function() {
|
||||
commitMessage.val("");
|
||||
submitCommitButton.attr("disabled",true);
|
||||
unstagedContent.css("height","30px");
|
||||
if (unmergedContent.is(":visible")) {
|
||||
unmergedContent.css("height","30px");
|
||||
stagedContent.css("height","calc(100% - 60px - 175px)");
|
||||
} else {
|
||||
stagedContent.css("height","calc(100% - 30px - 175px)");
|
||||
}
|
||||
commitBox.show();
|
||||
setTimeout(function() {
|
||||
commitBox.css("height","175px");
|
||||
},10);
|
||||
stageAllButton.attr("disabled",true);
|
||||
unstageAllButton.attr("disabled",true);
|
||||
commitButton.attr("disabled",true);
|
||||
abortMergeButton.attr("disabled",true);
|
||||
commitMessage.focus();
|
||||
}
|
||||
commitButton = $('<button class="editor-button editor-button-small" style="margin-right: 5px;">commit</button>')
|
||||
.appendTo(bg)
|
||||
.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
commitMessage.val("");
|
||||
submitCommitButton.attr("disabled",true);
|
||||
unstagedContent.css("height","30px");
|
||||
if (unmergedContent.is(":visible")) {
|
||||
unmergedContent.css("height","30px");
|
||||
stagedContent.css("height","calc(100% - 60px - 175px)");
|
||||
} else {
|
||||
stagedContent.css("height","calc(100% - 30px - 175px)");
|
||||
}
|
||||
commitBox.show();
|
||||
setTimeout(function() {
|
||||
commitBox.css("height","175px");
|
||||
},10);
|
||||
stageAllButton.attr("disabled",true);
|
||||
unstageAllButton.attr("disabled",true);
|
||||
commitButton.attr("disabled",true);
|
||||
commitMessage.focus();
|
||||
showCommitBox();
|
||||
});
|
||||
unstageAllButton = $('<button class="editor-button editor-button-small"><i class="fa fa-minus"></i> all</button>')
|
||||
.appendTo(bg)
|
||||
@@ -445,7 +480,7 @@ RED.sidebar.versionControl = (function() {
|
||||
|
||||
commitBox = $('<div class="sidebar-version-control-slide-box sidebar-version-control-slide-box-bottom"></div>').hide().appendTo(localChanges.content);
|
||||
|
||||
var commitMessage = $('<textarea>')
|
||||
var commitMessage = $('<textarea placeholder="Enter your commit message"></textarea>')
|
||||
.appendTo(commitBox)
|
||||
.on("change keyup paste",function() {
|
||||
submitCommitButton.attr('disabled',$(this).val().trim()==="");
|
||||
@@ -467,6 +502,8 @@ RED.sidebar.versionControl = (function() {
|
||||
stageAllButton.attr("disabled",false);
|
||||
unstageAllButton.attr("disabled",false);
|
||||
commitButton.attr("disabled",false);
|
||||
abortMergeButton.attr("disabled",false);
|
||||
|
||||
})
|
||||
var submitCommitButton = $('<button class="editor-button">Commit</button>')
|
||||
.appendTo(commitToolbar)
|
||||
@@ -474,6 +511,7 @@ RED.sidebar.versionControl = (function() {
|
||||
evt.preventDefault();
|
||||
var spinner = utils.addSpinnerOverlay(submitCommitButton).addClass('projects-dialog-spinner-sidebar');
|
||||
var activeProject = RED.projects.getActiveProject();
|
||||
RED.deploy.setDeployInflight(true);
|
||||
utils.sendRequest({
|
||||
url: "projects/"+activeProject.name+"/commit",
|
||||
type: "POST",
|
||||
@@ -487,17 +525,18 @@ RED.sidebar.versionControl = (function() {
|
||||
refresh(true);
|
||||
},
|
||||
400: {
|
||||
'unexpected_error': function(error) {
|
||||
console.log(error);
|
||||
'*': function(error) {
|
||||
utils.reportUnexpectedError(error);
|
||||
}
|
||||
},
|
||||
}
|
||||
},{
|
||||
message:commitMessage.val()
|
||||
});
|
||||
|
||||
|
||||
|
||||
}).always(function() {
|
||||
setTimeout(function() {
|
||||
RED.deploy.setDeployInflight(false);
|
||||
},500);
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -511,7 +550,7 @@ RED.sidebar.versionControl = (function() {
|
||||
.appendTo(bg)
|
||||
.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
refresh(true);
|
||||
refresh(true,true);
|
||||
})
|
||||
|
||||
var localBranchToolbar = $('<div class="sidebar-version-control-change-header" style="text-align: right;"></div>').appendTo(localHistory.content);
|
||||
@@ -749,7 +788,13 @@ RED.sidebar.versionControl = (function() {
|
||||
},
|
||||
400: {
|
||||
'git_connection_failed': function(error) {
|
||||
RED.notify(error.message);
|
||||
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) {
|
||||
console.log(error);
|
||||
@@ -854,54 +899,87 @@ RED.sidebar.versionControl = (function() {
|
||||
});
|
||||
});
|
||||
|
||||
var pullRemote = function(options) {
|
||||
options = options || {};
|
||||
var spinner = utils.addSpinnerOverlay(remoteBox).addClass("projects-dialog-spinner-contain");
|
||||
var activeProject = RED.projects.getActiveProject();
|
||||
var url = "projects/"+activeProject.name+"/pull";
|
||||
if (activeProject.git.branches.remoteAlt) {
|
||||
url+="/"+activeProject.git.branches.remoteAlt;
|
||||
}
|
||||
if (options.setUpstream || options.allowUnrelatedHistories) {
|
||||
url+="?";
|
||||
}
|
||||
if (options.setUpstream) {
|
||||
url += "setUpstream=true"
|
||||
if (options.allowUnrelatedHistories) {
|
||||
url += "&";
|
||||
}
|
||||
}
|
||||
if (options.allowUnrelatedHistories) {
|
||||
url += "allowUnrelatedHistories=true"
|
||||
}
|
||||
utils.sendRequest({
|
||||
url: url,
|
||||
type: "POST",
|
||||
responses: {
|
||||
0: function(error) {
|
||||
console.log(error);
|
||||
// done(error,null);
|
||||
},
|
||||
200: function(data) {
|
||||
refresh(true);
|
||||
closeRemoteBox();
|
||||
},
|
||||
400: {
|
||||
'git_local_overwrite': function(err) {
|
||||
RED.notify("<p>Unable to pull remote changes; your unstaged local changes would be overwritten.</p><p>Commit your changes and try again.</p>"+
|
||||
'<p><a href="#" onclick="RED.sidebar.versionControl.showLocalChanges(); return false;">'+'Show unstaged changes'+'</a></p>',"error",false,10000000);
|
||||
},
|
||||
'git_pull_merge_conflict': function(err) {
|
||||
refresh(true);
|
||||
closeRemoteBox();
|
||||
},
|
||||
'git_connection_failed': function(err) {
|
||||
RED.notify("Could not connect to remote repository: "+err.toString(),"warning")
|
||||
},
|
||||
'git_pull_unrelated_history': function(error) {
|
||||
var notification = RED.notify("<p>The remote has an unrelated history of commits.</p><p>Are you sure you want to pull the changes into your local repository?</p>",{
|
||||
type: 'error',
|
||||
modal: true,
|
||||
fixed: true,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
notification.close();
|
||||
}
|
||||
},{
|
||||
text: 'Pull changes',
|
||||
click: function() {
|
||||
notification.close();
|
||||
options.allowUnrelatedHistories = true;
|
||||
pullRemote(options)
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
},
|
||||
'*': function(error) {
|
||||
utils.reportUnexpectedError(error);
|
||||
}
|
||||
},
|
||||
}
|
||||
},{}).always(function() {
|
||||
spinner.remove();
|
||||
});
|
||||
}
|
||||
$('<button id="sidebar-version-control-repo-pull" class="sidebar-version-control-repo-sub-action editor-button"><i class="fa fa-long-arrow-down"></i> <span>pull</span></button>')
|
||||
.appendTo(row)
|
||||
.click(function(e) {
|
||||
e.preventDefault();
|
||||
var spinner = utils.addSpinnerOverlay(remoteBox).addClass("projects-dialog-spinner-contain");
|
||||
var activeProject = RED.projects.getActiveProject();
|
||||
var url = "projects/"+activeProject.name+"/pull";
|
||||
if (activeProject.git.branches.remoteAlt) {
|
||||
url+="/"+activeProject.git.branches.remoteAlt;
|
||||
}
|
||||
if ($("#sidebar-version-control-repo-toolbar-set-upstream").prop('checked')) {
|
||||
url+="?u=true"
|
||||
}
|
||||
|
||||
utils.sendRequest({
|
||||
url: url,
|
||||
type: "POST",
|
||||
responses: {
|
||||
0: function(error) {
|
||||
console.log(error);
|
||||
// done(error,null);
|
||||
},
|
||||
200: function(data) {
|
||||
refresh(true);
|
||||
closeRemoteBox();
|
||||
},
|
||||
400: {
|
||||
'git_local_overwrite': function(err) {
|
||||
RED.notify("Unable to pull remote changes; your unstaged local changes would be overwritten. Commit your changes and try again."+
|
||||
'<p><a href="#" onclick="RED.sidebar.versionControl.showLocalChanges(); return false;">'+'Show unstaged changes'+'</a></p>',"error",false,10000000);
|
||||
},
|
||||
'git_pull_merge_conflict': function(err) {
|
||||
refresh(true);
|
||||
},
|
||||
'git_connection_failed': function(err) {
|
||||
RED.notify("Could not connect to remote repository: "+err.toString(),"warning")
|
||||
},
|
||||
'unexpected_error': function(error) {
|
||||
console.log(error);
|
||||
// done(error,null);
|
||||
},
|
||||
'git_pull_unrelated_history': function(error) {
|
||||
RED.notify("Unable to pull remote changes; refusing to merge unrelated histories.","error");
|
||||
}
|
||||
},
|
||||
}
|
||||
},{}).always(function() {
|
||||
spinner.remove();
|
||||
pullRemote({
|
||||
setUpstream: $("#sidebar-version-control-repo-toolbar-set-upstream").prop('checked')
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1039,16 +1117,6 @@ RED.sidebar.versionControl = (function() {
|
||||
// }
|
||||
// }
|
||||
|
||||
function showMergeConflictNotification() {
|
||||
if (isMerging) {
|
||||
mergeConflictNotification = RED.notify("NLS: Automatic merging of remote changes failed. Fix the unmerged conflicts then commit the results."+
|
||||
'<p><a href="#" onclick="RED.sidebar.versionControl.showLocalChanges(); return false;">'+'Show merge conflicts'+'</a></p>',"error",true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function refreshFiles(result) {
|
||||
var files = result.files;
|
||||
if (bulkChangeSpinner) {
|
||||
@@ -1057,16 +1125,9 @@ RED.sidebar.versionControl = (function() {
|
||||
}
|
||||
isMerging = !!result.merging;
|
||||
if (isMerging) {
|
||||
if (!mergeConflictNotification) {
|
||||
showMergeConflictNotification();
|
||||
}
|
||||
sidebarContent.addClass("sidebar-version-control-merging");
|
||||
unmergedContent.show();
|
||||
} else {
|
||||
if (mergeConflictNotification) {
|
||||
mergeConflictNotification.close();
|
||||
mergeConflictNotification = null;
|
||||
}
|
||||
sidebarContent.removeClass("sidebar-version-control-merging");
|
||||
unmergedContent.hide();
|
||||
}
|
||||
@@ -1173,7 +1234,7 @@ RED.sidebar.versionControl = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
function refresh(full) {
|
||||
function refresh(full, includeRemote) {
|
||||
if (refreshInProgress) {
|
||||
return;
|
||||
}
|
||||
@@ -1193,7 +1254,11 @@ RED.sidebar.versionControl = (function() {
|
||||
|
||||
var activeProject = RED.projects.getActiveProject();
|
||||
if (activeProject) {
|
||||
$.getJSON("projects/"+activeProject.name+"/status",function(result) {
|
||||
var url = "projects/"+activeProject.name+"/status";
|
||||
if (includeRemote) {
|
||||
url += "?remote=true"
|
||||
}
|
||||
$.getJSON(url,function(result) {
|
||||
refreshFiles(result);
|
||||
|
||||
$('#sidebar-version-control-local-branch').text(result.branches.local);
|
||||
@@ -1237,6 +1302,8 @@ RED.sidebar.versionControl = (function() {
|
||||
}
|
||||
refreshInProgress = false;
|
||||
$('.sidebar-version-control-shade').hide();
|
||||
}).fail(function() {
|
||||
refreshInProgress = false;
|
||||
});
|
||||
} else {
|
||||
$('.sidebar-version-control-shade').show();
|
||||
|
||||
@@ -476,7 +476,7 @@ RED.utils = (function() {
|
||||
for (i=0;i<keys.length;i++) {
|
||||
var row = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(element);
|
||||
var newPath = path;
|
||||
if (newPath) {
|
||||
if (newPath !== undefined) {
|
||||
if (/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(keys[i])) {
|
||||
newPath += (newPath.length > 0?".":"")+keys[i];
|
||||
} else {
|
||||
@@ -708,7 +708,9 @@ RED.utils = (function() {
|
||||
|
||||
function getDefaultNodeIcon(def,node) {
|
||||
var icon_url;
|
||||
if (typeof def.icon === "function") {
|
||||
if (node && node.type === "subflow") {
|
||||
icon_url = "node-red/subflow.png";
|
||||
} else if (typeof def.icon === "function") {
|
||||
try {
|
||||
icon_url = def.icon.call(node);
|
||||
} catch(err) {
|
||||
@@ -721,11 +723,26 @@ RED.utils = (function() {
|
||||
|
||||
var iconPath = separateIconPath(icon_url);
|
||||
if (!iconPath.module) {
|
||||
iconPath.module = def.set.module;
|
||||
if (def.set) {
|
||||
iconPath.module = def.set.module;
|
||||
} else {
|
||||
// Handle subflow instance nodes that don't have def.set
|
||||
iconPath.module = "node-red";
|
||||
}
|
||||
}
|
||||
return iconPath;
|
||||
}
|
||||
|
||||
function isIconExists(iconPath) {
|
||||
var iconSets = RED.nodes.getIconSets();
|
||||
var iconFileList = iconSets[iconPath.module];
|
||||
if (iconFileList && iconFileList.indexOf(iconPath.file) !== -1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getNodeIcon(def,node) {
|
||||
if (def.category === 'config') {
|
||||
return "icons/node-red/cog.png"
|
||||
@@ -733,18 +750,19 @@ RED.utils = (function() {
|
||||
return "icons/node-red/subflow.png"
|
||||
} else if (node && node.type === 'unknown') {
|
||||
return "icons/node-red/alert.png"
|
||||
} else if (node && node.type === 'subflow') {
|
||||
return "icons/node-red/subflow.png"
|
||||
} else if (node && node.icon) {
|
||||
var iconPath = separateIconPath(node.icon);
|
||||
var iconSets = RED.nodes.getIconSets();
|
||||
var iconFileList = iconSets[iconPath.module];
|
||||
if (iconFileList && iconFileList.indexOf(iconPath.file) !== -1) {
|
||||
if (isIconExists(iconPath)) {
|
||||
return "icons/" + node.icon;
|
||||
}
|
||||
}
|
||||
|
||||
var iconPath = getDefaultNodeIcon(def, node);
|
||||
if (def.category === 'subflows') {
|
||||
if (!isIconExists(iconPath)) {
|
||||
return "icons/node-red/subflow.png";
|
||||
}
|
||||
}
|
||||
return "icons/"+iconPath.module+"/"+iconPath.file;
|
||||
}
|
||||
|
||||
|
||||
@@ -490,6 +490,7 @@ RED.view = (function() {
|
||||
}
|
||||
} else {
|
||||
var subflow = RED.nodes.subflow(m[1]);
|
||||
nn.name = "";
|
||||
nn.inputs = subflow.in.length;
|
||||
nn.outputs = subflow.out.length;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ RED.workspaces = (function() {
|
||||
return ws;
|
||||
}
|
||||
function deleteWorkspace(ws) {
|
||||
if (workspace_tabs.count() == 1) {
|
||||
if (workspaceTabCount === 1) {
|
||||
return;
|
||||
}
|
||||
removeWorkspace(ws);
|
||||
@@ -65,7 +65,7 @@ RED.workspaces = (function() {
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-delete",
|
||||
class: 'leftButton'+((workspace_tabs.count() == 1)?" disabled":""),
|
||||
class: 'leftButton'+((workspaceTabCount === 1)?" disabled":""),
|
||||
text: RED._("common.label.delete"), //'<i class="fa fa-trash"></i>',
|
||||
click: function() {
|
||||
deleteWorkspace(workspace);
|
||||
@@ -214,6 +214,7 @@ RED.workspaces = (function() {
|
||||
|
||||
|
||||
var workspace_tabs;
|
||||
var workspaceTabCount = 0;
|
||||
function createWorkspaceTabs() {
|
||||
workspace_tabs = RED.tabs.create({
|
||||
id: "workspace-tabs",
|
||||
@@ -240,18 +241,24 @@ RED.workspaces = (function() {
|
||||
}
|
||||
},
|
||||
onadd: function(tab) {
|
||||
if (tab.type === "tab") {
|
||||
workspaceTabCount++;
|
||||
}
|
||||
$('<span class="workspace-disabled-icon"><i class="fa fa-ban"></i> </span>').prependTo("#red-ui-tab-"+(tab.id.replace(".","-"))+" .red-ui-tab-label");
|
||||
if (tab.disabled) {
|
||||
$("#red-ui-tab-"+(tab.id.replace(".","-"))).addClass('workspace-disabled');
|
||||
}
|
||||
RED.menu.setDisabled("menu-item-workspace-delete",workspace_tabs.count() <= 1);
|
||||
if (workspace_tabs.count() === 1) {
|
||||
RED.menu.setDisabled("menu-item-workspace-delete",workspaceTabCount <= 1);
|
||||
if (workspaceTabCount === 1) {
|
||||
showWorkspace();
|
||||
}
|
||||
},
|
||||
onremove: function(tab) {
|
||||
RED.menu.setDisabled("menu-item-workspace-delete",workspace_tabs.count() <= 1);
|
||||
if (workspace_tabs.count() === 0) {
|
||||
if (tab.type === "tab") {
|
||||
workspaceTabCount--;
|
||||
}
|
||||
RED.menu.setDisabled("menu-item-workspace-delete",workspaceTabCount <= 1);
|
||||
if (workspaceTabCount === 0) {
|
||||
hideWorkspace();
|
||||
}
|
||||
},
|
||||
@@ -266,6 +273,7 @@ RED.workspaces = (function() {
|
||||
addWorkspace();
|
||||
}
|
||||
});
|
||||
workspaceTabCount = 0;
|
||||
}
|
||||
function showWorkspace() {
|
||||
$("#workspace .red-ui-tabs").show()
|
||||
@@ -334,7 +342,7 @@ RED.workspaces = (function() {
|
||||
return workspace_tabs.contains(id);
|
||||
},
|
||||
count: function() {
|
||||
return workspace_tabs.count();
|
||||
return workspaceTabCount;
|
||||
},
|
||||
active: function() {
|
||||
return activeWorkspace
|
||||
|
||||
@@ -113,8 +113,8 @@
|
||||
|
||||
.debug-message-meta {
|
||||
background: #fff;
|
||||
font-size: 10px;
|
||||
color: #777;
|
||||
font-size: 11px;
|
||||
color: #707070;
|
||||
}
|
||||
.debug-message-date {
|
||||
padding: 1px 5px 1px 1px;
|
||||
@@ -125,7 +125,7 @@
|
||||
}
|
||||
.debug-message-name {
|
||||
padding: 1px 5px;
|
||||
color: #777;
|
||||
color: #707070;
|
||||
}
|
||||
.debug-message-tools {
|
||||
position: absolute;
|
||||
@@ -159,7 +159,7 @@
|
||||
.debug-message-element {
|
||||
color: #333;
|
||||
font-family: Menlo, monospace;
|
||||
font-size: 12px !important;
|
||||
font-size: 13px !important;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
.debug-message-object-key {
|
||||
@@ -188,11 +188,9 @@
|
||||
.debug-message-element.collapsed>span>.debug-message-object-handle {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.debug-message-object-entry.collapsed > .debug-message-object-entry {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.debug-message-element.collapsed .debug-message-object-entry {
|
||||
display:none;
|
||||
}
|
||||
@@ -202,14 +200,13 @@
|
||||
.debug-message-element.collapsed .debug-message-buffer-opts {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.debug-message-element.collapsed .debug-message-object-type-header {
|
||||
display:none;
|
||||
}
|
||||
.debug-message-object-entry pre {
|
||||
font-family: Menlo, monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.4em;
|
||||
font-size: 13px;
|
||||
line-height: 1.2em;
|
||||
margin: 0 0 0 -1em;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,17 +16,16 @@
|
||||
|
||||
|
||||
.node-dialog-view-diff-panel {
|
||||
padding: 5px;
|
||||
padding-top: 30px;
|
||||
position: relative;
|
||||
|
||||
.red-ui-editableList-container {
|
||||
border-radius:1px;
|
||||
padding:0;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
.node-dialog-view-diff-diff {
|
||||
position: absolute;
|
||||
top:30px;
|
||||
bottom:10px;
|
||||
left:10px;
|
||||
right:10px;
|
||||
li {
|
||||
background: #f9f9f9;
|
||||
padding: 0px;
|
||||
@@ -38,21 +37,20 @@
|
||||
padding: 5px;
|
||||
// padding-bottom: 5px;
|
||||
}
|
||||
&.node-dialog-view-diff-panel-merge {
|
||||
.node-dialog-view-diff-diff {
|
||||
top: 80px
|
||||
}
|
||||
.node-dialog-view-diff-headers {
|
||||
top: 55px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.node-diff-container {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
right:0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.node-dialog-view-diff-headers {
|
||||
position: absolute;
|
||||
left:237px;
|
||||
right:18px;
|
||||
left:232px;
|
||||
right:12px;
|
||||
top: 5px;
|
||||
height: 25px;
|
||||
div {
|
||||
@@ -76,11 +74,6 @@
|
||||
}
|
||||
|
||||
.node-diff-toolbar {
|
||||
position:absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
right:0;
|
||||
height: 43px;
|
||||
box-sizing: border-box;
|
||||
color: #666;
|
||||
text-align: right;
|
||||
@@ -555,129 +548,129 @@ ul.node-dialog-configm-deploy-list {
|
||||
.node-text-diff {
|
||||
height: 100%;
|
||||
overflow-y:auto;
|
||||
table {
|
||||
|
||||
table.node-text-diff-content {
|
||||
margin: 10px;
|
||||
border: 1px solid $secondary-border-color;
|
||||
border-radius: 3px;
|
||||
table-layout: fixed;
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
td {
|
||||
vertical-align: top;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
td.lineno {
|
||||
font-family: monospace;
|
||||
text-align: right;
|
||||
color: #aaa;
|
||||
background: #f6f6f6;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
td.lineno:nth-child(3) {
|
||||
border-left: 1px solid $secondary-border-color;
|
||||
}
|
||||
td.linetext {
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
padding: 1px 5px;
|
||||
span.prefix {
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
td {
|
||||
vertical-align: top;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
td.blank {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
td.added {
|
||||
background: #eefaee;
|
||||
}
|
||||
td.removed {
|
||||
background: #fadddd;
|
||||
}
|
||||
tr.mergeHeader td {
|
||||
color: #800080;
|
||||
background: #e5f9ff;
|
||||
height: 26px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
tr.mergeHeader-separator td {
|
||||
color: #800080;
|
||||
background: darken(#e5f9ff, 10%);
|
||||
height: 0px;
|
||||
}
|
||||
tr.mergeHeader-ours td {
|
||||
border-top: 2px solid darken(#e5f9ff, 10%);
|
||||
}
|
||||
tr.mergeHeader-theirs td {
|
||||
border-bottom: 2px solid darken(#e5f9ff, 10%);
|
||||
}
|
||||
td.unchanged {
|
||||
color: #999;
|
||||
}
|
||||
tr.unchanged {
|
||||
background: #fefefe;
|
||||
}
|
||||
tr.start-block {
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
tr.end-block {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
tr.node-text-diff-file-header td {
|
||||
.filename {
|
||||
td.lineno {
|
||||
font-family: monospace;
|
||||
text-align: right;
|
||||
color: #aaa;
|
||||
background: #f6f6f6;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
background: #f3f3f3;
|
||||
padding: 5px 10px 5px 0;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
i.node-diff-chevron {
|
||||
width: 30px;
|
||||
td.lineno:nth-child(3) {
|
||||
border-left: 1px solid $secondary-border-color;
|
||||
}
|
||||
}
|
||||
tr.node-text-diff-file-header.collapsed {
|
||||
td i.node-diff-chevron {
|
||||
transform: rotate(-90deg);
|
||||
td.linetext {
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
padding: 1px 5px;
|
||||
span.prefix {
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
tr.node-text-diff-commit-header td {
|
||||
background: #f3f3f3;
|
||||
padding: 5px 10px;
|
||||
color: #333;
|
||||
h3 {
|
||||
font-size: 1.4em;
|
||||
margin: 0;
|
||||
td.blank {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
.commit-summary {
|
||||
border-top: 1px solid $secondary-border-color;
|
||||
padding-top: 5px;
|
||||
td.added {
|
||||
background: #eefaee;
|
||||
}
|
||||
td.removed {
|
||||
background: #fadddd;
|
||||
}
|
||||
tr.mergeHeader td {
|
||||
color: #800080;
|
||||
background: #e5f9ff;
|
||||
height: 26px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
tr.mergeHeader-separator td {
|
||||
color: #800080;
|
||||
background: darken(#e5f9ff, 10%);
|
||||
height: 0px;
|
||||
}
|
||||
tr.mergeHeader-ours td {
|
||||
border-top: 2px solid darken(#e5f9ff, 10%);
|
||||
}
|
||||
tr.mergeHeader-theirs td {
|
||||
border-bottom: 2px solid darken(#e5f9ff, 10%);
|
||||
}
|
||||
td.unchanged {
|
||||
color: #999;
|
||||
}
|
||||
.commit-body {
|
||||
margin-bottom:15px;
|
||||
white-space: pre;
|
||||
line-height: 1.2em;
|
||||
tr.unchanged {
|
||||
background: #fefefe;
|
||||
}
|
||||
tr.start-block {
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
tr.end-block {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
tr.node-text-diff-file-header td {
|
||||
.filename {
|
||||
font-family: monospace;
|
||||
}
|
||||
background: #f3f3f3;
|
||||
padding: 5px 10px 5px 0;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
i.node-diff-chevron {
|
||||
width: 30px;
|
||||
}
|
||||
}
|
||||
tr.node-text-diff-file-header.collapsed {
|
||||
td i.node-diff-chevron {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
tr.node-text-diff-commit-header td {
|
||||
background: #f3f3f3;
|
||||
padding: 5px 10px;
|
||||
color: #333;
|
||||
h3 {
|
||||
font-size: 1.4em;
|
||||
margin: 0;
|
||||
}
|
||||
.commit-summary {
|
||||
border-top: 1px solid $secondary-border-color;
|
||||
padding-top: 5px;
|
||||
color: #999;
|
||||
}
|
||||
.commit-body {
|
||||
margin-bottom:15px;
|
||||
white-space: pre;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
tr.node-text-diff-header > td:not(.flow-diff) {
|
||||
font-family: monospace;
|
||||
padding: 5px 10px;
|
||||
text-align: left;
|
||||
color: #666;
|
||||
background: #ffd;
|
||||
height: 30px;
|
||||
vertical-align: middle;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
tr.node-text-diff-expand td {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: #ffc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr.node-text-diff-header td {
|
||||
font-family: monospace;
|
||||
padding: 5px 10px;
|
||||
text-align: left;
|
||||
color: #666;
|
||||
background: #ffd;
|
||||
height: 30px;
|
||||
vertical-align: middle;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
tr.node-text-diff-expand td {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: #ffc;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -501,9 +501,9 @@
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
display: none;
|
||||
}
|
||||
button {
|
||||
width: 24px;
|
||||
button {
|
||||
width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
icon: "arrow-in.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
return this.name||this.command;
|
||||
return this.name||this.command||(this.useSpawn=="true"?this._("exec.spawn"):this._("exec.exec"));
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
||||
@@ -65,6 +65,8 @@ module.exports = function(RED) {
|
||||
"log:__node__.log,"+
|
||||
"error:__node__.error,"+
|
||||
"warn:__node__.warn,"+
|
||||
"debug:__node__.debug,"+
|
||||
"trace:__node__.trace,"+
|
||||
"on:__node__.on,"+
|
||||
"status:__node__.status,"+
|
||||
"send:function(msgs){ __node__.send(__msgid__,msgs);}"+
|
||||
@@ -91,6 +93,12 @@ module.exports = function(RED) {
|
||||
warn: function() {
|
||||
node.warn.apply(node, arguments);
|
||||
},
|
||||
debug: function() {
|
||||
node.debug.apply(node, arguments);
|
||||
},
|
||||
trace: function() {
|
||||
node.trace.apply(node, arguments);
|
||||
},
|
||||
send: function(id, msgs) {
|
||||
sendResults(node, id, msgs);
|
||||
},
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
outputs:1,
|
||||
icon: "template.png",
|
||||
label: function() {
|
||||
return this.name;
|
||||
return this.name||this._("template.template");;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
||||
@@ -50,6 +50,7 @@ module.exports = function(RED) {
|
||||
|
||||
// try node context:
|
||||
var dot = name.indexOf(".");
|
||||
/* istanbul ignore else */
|
||||
if (dot > 0) {
|
||||
var contextName = name.substr(0, dot);
|
||||
var variableName = name.substr(dot + 1);
|
||||
@@ -61,7 +62,8 @@ module.exports = function(RED) {
|
||||
return this.nodeContext.global.get(variableName);
|
||||
}
|
||||
}
|
||||
}catch(err) {
|
||||
}
|
||||
catch(err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@@ -87,24 +89,27 @@ module.exports = function(RED) {
|
||||
* Allow template contents to be defined externally
|
||||
* through inbound msg.template IFF node.template empty
|
||||
*/
|
||||
var template = node.template;
|
||||
if (msg.hasOwnProperty("template")) {
|
||||
if (node.template == "" || node.template === null) {
|
||||
node.template = msg.template;
|
||||
if (template == "" || template === null) {
|
||||
template = msg.template;
|
||||
}
|
||||
}
|
||||
|
||||
if (node.syntax === "mustache") {
|
||||
if (node.outputFormat === "json") {
|
||||
value = mustache.render(node.template,new NodeContext(msg, node.context(), null, true));
|
||||
value = mustache.render(template,new NodeContext(msg, node.context(), null, true));
|
||||
} else {
|
||||
value = mustache.render(node.template,new NodeContext(msg, node.context(), null, false));
|
||||
value = mustache.render(template,new NodeContext(msg, node.context(), null, false));
|
||||
}
|
||||
} else {
|
||||
value = node.template;
|
||||
value = template;
|
||||
}
|
||||
/* istanbul ignore else */
|
||||
if (node.outputFormat === "json") {
|
||||
value = JSON.parse(value);
|
||||
}
|
||||
/* istanbul ignore else */
|
||||
if (node.outputFormat === "yaml") {
|
||||
value = yaml.load(value);
|
||||
}
|
||||
@@ -117,7 +122,8 @@ module.exports = function(RED) {
|
||||
node.context().global.set(node.field,value);
|
||||
}
|
||||
node.send(msg);
|
||||
} catch(err) {
|
||||
}
|
||||
catch(err) {
|
||||
node.error(err.message);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
outstanding messages held by the node are cleared without being sent.</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>When configured to delay messages, the delay interval can be a fixed value
|
||||
<p>When configured to delay messages, the delay interval can be a fixed value,
|
||||
a random value within a range or dynamically set for each message.</p>
|
||||
<p>When configured to rate limit messages, their delivery is spread across
|
||||
the configured time period. The status shows the number of messages currently in the queue.
|
||||
|
||||
@@ -100,8 +100,6 @@ 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 */
|
||||
@@ -113,21 +111,25 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
msg2.payload = node.topics[topic].m2;
|
||||
}
|
||||
delete node.topics[topic];
|
||||
node.status({});
|
||||
node.send(msg2);
|
||||
}, node.duration);
|
||||
else { delete node.topics[topic]; }
|
||||
node.status({});
|
||||
}, 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 */
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
outputs:0,
|
||||
icon: "comment.png",
|
||||
label: function() {
|
||||
return this.name||"";
|
||||
return this.name||this._("comment.comment");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
||||
@@ -222,7 +222,6 @@ RED.debug = (function() {
|
||||
clearMessageList(false);
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
content: content,
|
||||
footer: footerToolbar
|
||||
@@ -238,6 +237,9 @@ RED.debug = (function() {
|
||||
workspaceOrder.forEach(function(ws,i) {
|
||||
workspaceOrderMap[ws] = i;
|
||||
});
|
||||
candidateNodes = candidateNodes.filter(function(node) {
|
||||
return workspaceOrderMap.hasOwnProperty(node.z);
|
||||
})
|
||||
candidateNodes.sort(function(A,B) {
|
||||
var wsA = workspaceOrderMap[A.z];
|
||||
var wsB = workspaceOrderMap[B.z];
|
||||
@@ -339,7 +341,7 @@ RED.debug = (function() {
|
||||
activeMenuMessage.clearPinned();
|
||||
}},
|
||||
null,
|
||||
{id:"debug-message-menu-item-filter",label:RED._("node-red:debug.messageMenu.filterNode"),onselect:function(){
|
||||
{id:"debug-message-menu-item-filter", label:RED._("node-red:debug.messageMenu.filterNode"),onselect:function(){
|
||||
var candidateNodes = RED.nodes.filterNodes({type:'debug'});
|
||||
candidateNodes.forEach(function(n) {
|
||||
filteredNodes[n.id] = true;
|
||||
@@ -361,6 +363,15 @@ RED.debug = (function() {
|
||||
menuOptionMenu.on('mouseup', function() { $(this).hide() });
|
||||
menuOptionMenu.appendTo("body");
|
||||
}
|
||||
|
||||
var filterOptionDisabled = false;
|
||||
var sourceNode = RED.nodes.node(sourceId);
|
||||
if (sourceNode && sourceNode.type !== 'debug') {
|
||||
filterOptionDisabled = true;
|
||||
}
|
||||
RED.menu.setDisabled('debug-message-menu-item-filter',filterOptionDisabled);
|
||||
RED.menu.setDisabled('debug-message-menu-item-clear-filter',filterOptionDisabled);
|
||||
|
||||
var elementPos = button.offset();
|
||||
menuOptionMenu.css({
|
||||
top: elementPos.top+"px",
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
<dt>payload <span class="property-type">number</span></dt>
|
||||
<dd>the payload will be a 1 or a 0.</dd>
|
||||
<dt>topic <span class="property-type">string</span></dt>
|
||||
<dd>the topic will be set to `pi/{the pin number}`.</dd>
|
||||
<dd>the topic will be set to <code>pi/{the pin number}</code>.</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>You may also enable the input pullup resistor or the pulldown resistor.</p>
|
||||
|
||||
@@ -142,9 +142,9 @@ module.exports = function(RED) {
|
||||
var limit = 1;
|
||||
if (node.out === "pwm") { limit = 100; }
|
||||
if ((out >= 0) && (out <= limit)) {
|
||||
if (RED.settings.verbose) { node.log("out: "+msg.payload); }
|
||||
if (RED.settings.verbose) { node.log("out: "+out); }
|
||||
if (node.child !== null) {
|
||||
node.child.stdin.write(msg.payload+"\n");
|
||||
node.child.stdin.write(out+"\n");
|
||||
node.status({fill:"green",shape:"dot",text:msg.payload.toString()});
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
<p>The node will listen on the configured path for requests of a particular type.
|
||||
The path can be fully specified, such as <code>/user</code>, or include
|
||||
named parameters that accept any value, such as <code>/user/:name</code>.
|
||||
When named parameters are used, their actual value in a request can be accessed under `msg.req.params`.</p>
|
||||
When named parameters are used, their actual value in a request can be accessed under <code>msg.req.params</code>.</p>
|
||||
<p>For requests that include a body, such as a POST or PUT, the contents of
|
||||
the request is made available as <code>msg.payload</code>.</p>
|
||||
<p>If the content type of the request can be determined, the body will be parsed to
|
||||
|
||||
@@ -88,6 +88,8 @@
|
||||
<dt class="optional">rejectUnauthorized</dt>
|
||||
<dd>If set to <code>true</code>, allows requests to be made to https sites that use
|
||||
self signed certificates.</dd>
|
||||
<dt class="optional">followRedirects</dt>
|
||||
<dd>If set to <code>false</code> prevent following Redirect (HTTP 301).<code>true</code> by default</dd>
|
||||
</dl>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
@@ -117,7 +119,7 @@
|
||||
the response headers. The next node will then use those headers for its request - this
|
||||
is not usually the right thing to do. If <code>msg.headers</code> property is left unchanged
|
||||
between nodes, it will be ignored by the second node. To set custom headers, <code>msg.headers</code>
|
||||
should first be deleted or reset to an empty object: `{}`.
|
||||
should first be deleted or reset to an empty object: <code>{}</code>.
|
||||
<h4>Cookie handling</h4>
|
||||
<p>The <code>cookies</code> property passed to the node must be an object of name/value pairs.
|
||||
The value can be either a string to set the value of the cookie or it can be an
|
||||
|
||||
@@ -108,6 +108,9 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (msg.hasOwnProperty('followRedirects')) {
|
||||
opts.followRedirects = msg.followRedirects;
|
||||
}
|
||||
if (msg.cookies) {
|
||||
var cookies = [];
|
||||
if (opts.headers.hasOwnProperty('cookie')) {
|
||||
@@ -263,9 +266,8 @@ module.exports = function(RED) {
|
||||
catch(e) { node.warn(RED._("httpin.errors.json-error")); }
|
||||
}
|
||||
}
|
||||
|
||||
node.send(msg);
|
||||
node.status({});
|
||||
node.send(msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -280,8 +282,8 @@ module.exports = function(RED) {
|
||||
node.error(err,msg);
|
||||
msg.payload = err.toString() + " : " + url;
|
||||
msg.statusCode = err.code;
|
||||
node.send(msg);
|
||||
node.status({fill:"red",shape:"ring",text:err.code});
|
||||
node.send(msg);
|
||||
});
|
||||
if (payload) {
|
||||
req.write(payload);
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
outputs:1,
|
||||
icon: "watch.png",
|
||||
label: function() {
|
||||
return this.name||this.files;
|
||||
return this.name||this.files||this._("watch.watch");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
||||
@@ -52,6 +52,7 @@ 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) {
|
||||
@@ -123,7 +124,8 @@ 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); }
|
||||
@@ -184,6 +186,7 @@ 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()}));
|
||||
@@ -237,6 +240,7 @@ 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()}));
|
||||
});
|
||||
@@ -288,7 +292,8 @@ 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];
|
||||
@@ -314,7 +319,8 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
var connectedSockets = [];
|
||||
node.status({text:RED._("tcpin.status.connections",{count:0})});
|
||||
var server = net.createServer(function (socket) {
|
||||
|
||||
@@ -70,8 +70,8 @@
|
||||
}
|
||||
},
|
||||
"catch": {
|
||||
"catch": "catch all",
|
||||
"catchNodes": "catch (__number__)",
|
||||
"catch": "catch: all",
|
||||
"catchNodes": "catch: __number__",
|
||||
"label": {
|
||||
"source": "Catch errors from",
|
||||
"node": "node",
|
||||
@@ -86,8 +86,8 @@
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"status": "status (all)",
|
||||
"statusNodes": "status (__number__)",
|
||||
"status": "status: all",
|
||||
"statusNodes": "status: __number__",
|
||||
"label": {
|
||||
"source": "Report status from",
|
||||
"node": "node",
|
||||
@@ -166,6 +166,8 @@
|
||||
}
|
||||
},
|
||||
"exec": {
|
||||
"exec": "exec",
|
||||
"spawn": "spawn",
|
||||
"label": {
|
||||
"command": "Command",
|
||||
"append": "Append",
|
||||
@@ -195,6 +197,7 @@
|
||||
"tip": "See the Info tab for help writing functions."
|
||||
},
|
||||
"template": {
|
||||
"template": "template",
|
||||
"label": {
|
||||
"template": "Template",
|
||||
"property": "Set property",
|
||||
@@ -301,6 +304,7 @@
|
||||
}
|
||||
},
|
||||
"comment": {
|
||||
"comment": "comment",
|
||||
"label": {
|
||||
"title": "Title",
|
||||
"body": "Body"
|
||||
@@ -416,6 +420,7 @@
|
||||
}
|
||||
},
|
||||
"watch": {
|
||||
"watch": "watch",
|
||||
"label": {
|
||||
"files": "File(s)",
|
||||
"recursive": "Watch sub-directories recursively"
|
||||
@@ -542,6 +547,7 @@
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"switch": "switch",
|
||||
"label": {
|
||||
"property": "Property",
|
||||
"rule": "rule",
|
||||
@@ -597,6 +603,7 @@
|
||||
}
|
||||
},
|
||||
"range": {
|
||||
"range": "range",
|
||||
"label": {
|
||||
"action": "Action",
|
||||
"inputrange": "Map the input range",
|
||||
@@ -763,7 +770,9 @@
|
||||
"status": {
|
||||
"stopped": "stopped",
|
||||
"closed": "closed",
|
||||
"not-running": "not running"
|
||||
"not-running": "not running",
|
||||
"not-available": "not available",
|
||||
"na": "N/A : __value__"
|
||||
},
|
||||
"errors": {
|
||||
"ignorenode": "Ignoring Raspberry Pi specific node",
|
||||
@@ -782,6 +791,7 @@
|
||||
}
|
||||
},
|
||||
"tail": {
|
||||
"tail": "tail",
|
||||
"label": {
|
||||
"filename": "Filename",
|
||||
"type": "File type",
|
||||
@@ -835,6 +845,7 @@
|
||||
"tip": "Tip: The filename should be an absolute path, otherwise it will be relative to the working directory of the Node-RED process."
|
||||
},
|
||||
"split": {
|
||||
"split": "split",
|
||||
"intro":"Split <code>msg.payload</code> based on type:",
|
||||
"object":"<b>Object</b>",
|
||||
"objectSend":"Send a message for each key/value pair",
|
||||
@@ -846,6 +857,7 @@
|
||||
"addname":" Copy key to "
|
||||
},
|
||||
"join":{
|
||||
"join": "join",
|
||||
"mode":{
|
||||
"mode":"Mode",
|
||||
"auto":"automatic",
|
||||
@@ -892,6 +904,7 @@
|
||||
}
|
||||
},
|
||||
"sort" : {
|
||||
"sort": "sort",
|
||||
"target" : "Sort",
|
||||
"seq" : "message sequence",
|
||||
"key" : "Key",
|
||||
@@ -905,6 +918,7 @@
|
||||
"clear" : "clear pending message in sort node"
|
||||
},
|
||||
"batch" : {
|
||||
"batch": "batch",
|
||||
"mode": {
|
||||
"label" : "Mode",
|
||||
"num-msgs" : "Group by number of messages",
|
||||
|
||||
35
nodes/core/locales/ja/analysis/72-sentiment.html
Normal file
35
nodes/core/locales/ja/analysis/72-sentiment.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="sentiment">
|
||||
<p>指定したプロパティ(デフォルトは<code>payload</code>)を分析し、<code>sentiment</code>オブジェクトを追加します。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>sentiment <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>AFINN-111による感情分析の結果</dd>
|
||||
<dt>sentiment.score <span class="property-type">数値</span></dt>
|
||||
<dd>感情分析スコア</dd>
|
||||
</dl>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>overrides <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>単語スコアの上書きをするためのオブジェクト - <code>{ word:score,... }</code></dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>ゼロ以上のスコアはポジティブ、ゼロ以下はネガティブを意味します。</p>
|
||||
<p>スコアの範囲は通常-5から+5ですが、より大きかったり小さかったりすることもあります。</p>
|
||||
<p>詳細は<a href="https://github.com/thisandagain/sentiment/blob/master/README.md" target="_blank">the Sentiment docs here</a>を参照してください。</p>
|
||||
</script>
|
||||
34
nodes/core/locales/ja/core/20-inject.html
Normal file
34
nodes/core/locales/ja/core/20-inject.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="inject">
|
||||
<p>手動もしくは一定間隔でメッセージをフローに注入します。メッセージのペイロードには、文字列、JavaScriptオブジェクト、現在の時刻など、さまざまな値を指定できます。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">各種</span></dt>
|
||||
<dd>指定したメッセージペイロード。</dd>
|
||||
<dt class="optional">topic <span class="property-type">文字列</span></dt>
|
||||
<dd>任意で指定可能なプロパティ。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>injectノードを用いることで、指定したペイロード値を用いてフローを開始できます。デフォルトのペイロード値は現在時刻のタイムスタンプを1970年1月1日からの経過ミリ秒で表現した値です。</p>
|
||||
<p>文字列、数値、論理値、JavaScriptオブジェクト、フロー/グローバルコンテキストの値などの送出も可能です。</p>
|
||||
<p> デフォルト設定では、エディタ内に表示されるボタンをクリックすることで、ノードを手動で起動できます。指定間隔もしくはスケジュールに従ってメッセージを送出するように設定することも可能です。</p>
|
||||
<p>また、フロー開始の際に一度だけメッセージを送出させることもできます。</p>
|
||||
<p>「<i>時間間隔</i>」に指定可能な値の最大値は、約596時間(もしくは24日)です。一日より長い間隔を扱いたい場合は、電源停止や再起動にも対応可能なスケジューラノードの利用を検討すると良いでしょう。</p>
|
||||
<p><b>注</b>:「<i>指定した時間間隔、日時</i>」と「<i>指定した日時</i>」オプションは標準的なcronシステムを内部で利用します。したがって「20分」という指定は、その時点から20分後ではなく、毎時きっかり、20分、40分を意味します。現時刻から20分毎を指定するには「<i>指定した時間間隔</i>」オプションを用います。</p>
|
||||
<p><b>注</b>: 文字列に改行を含めたい場合は、functionノードを使ってペイロードを設定してください。</p>
|
||||
</script>
|
||||
36
nodes/core/locales/ja/core/25-catch.html
Normal file
36
nodes/core/locales/ja/core/25-catch.html
Normal file
@@ -0,0 +1,36 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="catch">
|
||||
<p>同じタブ内のノードが送出したエラーをキャッチします。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>error.message <span class="property-type">文字列</span></dt>
|
||||
<dd>エラーメッセージ</dd>
|
||||
<dt>error.source.id <span class="property-type">文字列</span></dt>
|
||||
<dd>エラーを送出したノードのID</dd>
|
||||
<dt>error.source.type <span class="property-type">文字列</span></dt>
|
||||
<dd>エラーを送出したノードの種別</dd>
|
||||
<dt>error.source.name <span class="property-type">文字列</span></dt>
|
||||
<dd>エラーを送出したノードの名称(設定されている場合)</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>メッセージの処理中にノードがエラーを送出した場合、フロー実行は基本的に停止します。このノードを使うと、エラーをキャッチして対応するフローで処理させることができます。</p>
|
||||
<p>デフォルトでは、同じタブの全てのノードが送出したエラーをキャッチします。特定のノードをキャッチ対象とすることも可能です。</p>
|
||||
<p>エラー発生時には、マッチするすべてのcatchノードがメッセージを受け取ります。</p>
|
||||
<p>サブフロー内でエラーが送出された場合、まずサブフロー内のcatchノードで処理されます。対応するノードが存在しない場合には、そのサブフローが配置されたタブにエラーを伝播して処理します。</p>
|
||||
<p>メッセージが<code>error</code>プロパティを持っている場合、元の<code>error</code>は<code>_error</code>へコピーします。</p>
|
||||
</script>
|
||||
33
nodes/core/locales/ja/core/25-status.html
Normal file
33
nodes/core/locales/ja/core/25-status.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="status">
|
||||
<p>同じタブ内のノードのステータスメッセージを取得します。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>status.text <span class="property-type">文字列</span></dt>
|
||||
<dd>ステータス文字列</dd>
|
||||
<dt>status.source.type <span class="property-type">文字列</span></dt>
|
||||
<dd>ステータスを表示したノードの種別</dd>
|
||||
<dt>status.source.id <span class="property-type">文字列</span></dt>
|
||||
<dd>ステータスを表示したノードのID</dd>
|
||||
<dt>status.source.name <span class="property-type">文字列</span></dt>
|
||||
<dd>ステータスを表示したノードの名称(設定されている場合)</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>このノードは<code>payload</code>を設定しません。</p>
|
||||
<p>デフォルトでは、同じワークスペースタブ内の全てのノードのステータスを取得します。特定のノードのステータスを取得対象とすることも可能です。</p>
|
||||
</script>
|
||||
26
nodes/core/locales/ja/core/58-debug.html
Normal file
26
nodes/core/locales/ja/core/58-debug.html
Normal file
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="debug">
|
||||
<p>サイドバーの「デバッグ」タブに、選択したメッセージプロパティの値を表示します。設定により、ランタイムログへの出力も可能です。デフォルトの表示対象は<code>msg.payload</code>です。</p>
|
||||
<h3>詳細</h3>
|
||||
<p>「デバッグ」サイドバーは受け取ったメッセージの階層構造を表示する機能を備えます。この機能によりメッセージの構造を容易に理解できます。</p>
|
||||
<p>JavaScriptオブジェクトと配列は必要に応じて折り畳んだり展開したりできます。バッファオブジェクトを生データとして表示したり、表現可能な場合に文字列として表示することも可能です。</p>
|
||||
<p>メッセージを受信した時刻、送信ノード、メッセージの型に関する情報を「デバッグ」サイドバーに表示されたメッセージに付随して表示します。送信元ノードのIDを選択すると、ワークスペース内の対応ノードを確認できます。</p>
|
||||
<p>出力の有効/無効はノード上のボタンで切り替えられます。フロー上で未使用のdebugノードは、無効化するか削除することを推奨します。</p>
|
||||
<p>全てのメッセージをランタイムログに送付、もしくは、(32文字の)短いデータをdebugノードの下のステータステキストに表示することも可能です。</p>
|
||||
</script>
|
||||
|
||||
31
nodes/core/locales/ja/core/60-link.html
Normal file
31
nodes/core/locales/ja/core/60-link.html
Normal file
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="link in">
|
||||
<p>フロー間に仮想的なリンクを作成します。</p>
|
||||
<h3>詳細</h3>
|
||||
<p>任意のタブ上に存在する<code>link out</code>ノードに接続できます。この接続はあたかも直接リンクしたかのように動作します。</p>
|
||||
<p>linkノード間のリンクはlinkノードを選択した場合にのみ表示されます。他のタブへのリンクがある場合には、仮想的なノードを表示します。この仮想的ノードをクリックすると、対応するタブに移動できます。</p>
|
||||
<p><b>注: </b>サブフローの外から中、もしくは、中から外へのリンクを作成することはできません。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="link out">
|
||||
<p>フロー間に仮想的なリンクを作成します。</p>
|
||||
<h3>詳細</h3>
|
||||
<p>任意のタブ上に存在する<code>link in</code>ノードに接続できます。この接続はあたかも直接リンクしたかのように動作します。</p>
|
||||
<p>linkノード間のリンクはlinkノードを選択した場合にのみ表示されます。他のタブへのリンクがある場合には、仮想的なノードを表示します。この仮想的ノードをクリックすると、対応するタブに移動できます。</p>
|
||||
<p><b>注: </b>サブフローの外から中、もしくは、中から外へのリンクを作成することはできません。</p>
|
||||
</script>
|
||||
75
nodes/core/locales/ja/core/75-exec.html
Normal file
75
nodes/core/locales/ja/core/75-exec.html
Normal file
@@ -0,0 +1,75 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="exec">
|
||||
<p>システムのコマンドを実行し出力を返します。</p>
|
||||
<p>コマンドの完了まで待つか、コマンドが出力を行う毎にメッセージを出力するかを指定できます。</p>
|
||||
<p>実行対象のコマンドは、ノードの設定もしくは受信メッセージで指定します。</p>
|
||||
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt class="optional">payload <span class="property-type">文字列</span></dt>
|
||||
<dd>実行コマンドの最後に追加するよう設定できます</dd>
|
||||
<dt class="optional">kill <span class="property-type">文字列</span></dt>
|
||||
<dd>execノードのプロセスに対して送るシグナルの種別を指定します</dd>
|
||||
<dt class="optional">pid <span class="property-type">数値|文字列</span></dt>
|
||||
<dd>シグナル送信対象のexecノードのプロセスID</dd>
|
||||
</dl>
|
||||
|
||||
<h3>出力</h3>
|
||||
<ol class="node-ports">
|
||||
<li>標準出力(stdout)
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">文字列</span></dt>
|
||||
<dd>コマンドの標準出力</dd>
|
||||
</dl>
|
||||
<dl class="message-properties">
|
||||
<dt>rc <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>返却コードオブジェクト(3番目の端子でも受取り可能)のコピー(execモードのみ)</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>標準エラー出力(stderr)
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">文字列</span></dt>
|
||||
<dd>コマンドの標準エラー出力</dd>
|
||||
</dl>
|
||||
<dl class="message-properties">
|
||||
<dt>rc <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>返却コードオブジェクト(3番目の端子でも受取り可能)のコピー(execモードのみ)</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>返却コード(return code)
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>リターンコード、<code>message</code>、<code>signal</code>プロパティを含むオブジェクト(<code>message</code>、<code>signal</code>は利用可能な場合)</dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ol>
|
||||
<h3>詳細</h3>
|
||||
<p>デフォルトでは、<code>exec</code>システムコールを用いてコマンドを呼び出してその完了を待ち、出力を返します。例えば、コマンドの実行が成功した場合には、<code>{ code: 0 }</code>と言う返却値を返します。</p>
|
||||
<p><code>spawn</code>を使ってコマンドを実行し、
|
||||
標準出力および標準エラー出力へ出力を返すようにすることもできます。この場合、通常1行毎に値を返します。コマンドの実行が完了すると、3番目の端子にオブジェクトを出力します。例えば、コマンドの実行が成功した場合には、<code>{ code: 0 }</code>と言う返却値を返します。</p>
|
||||
<p>エラー発生時には、3番目の端子の<code>msg.payload</code>に<code>message</code>、<code>signal</code>など付加情報を返します。</p>
|
||||
<p>実行対象のコマンドはノード設定で定義します。<code>msg.payload</code>や追加引数をコマンドに追加することもできます。</p>
|
||||
<p>コマンドもしくはパラメータが空白を含む場合には、引用符で囲みます。- <code>"This is a single parameter"</code></p>
|
||||
<p>返却する<code>payload</code>は通常<i>文字列</i>ですが、UTF8文字以外が存在すると<i>バッファ</i>となります。</p>
|
||||
<p>ノードが実行中の場合、ステータスアイコンとPIDを表示します。この状態変化は<code>status</code>ノードで検知できます。</p>
|
||||
<h4>プロセスの停止</h4>
|
||||
<p><code>msg.kill</code>を受信すると、実行中のプロセスを停止することができます。<code>msg.kill</code>には送出するシグナルの種別を指定します。例えば、<code>SIGINT</code>、<code>SIGQUIT</code>、<code>SIGHUP</code>などです。空の文字列を指定した場合には、<code>SIGTERM</code>を指定したものとみなします。</p>
|
||||
<p>ノードが1つ以上のプロセスを実行している場合、<code>msg.pid</code>に停止対象のPIDを指定しなければなりません。</p>
|
||||
<p><code>タイムアウト</code>フィールドに値を指定すると、指定した秒数以内にコマンドが完了しない場合、プロセスを自動的に停止します。</p>
|
||||
<p>ヒント: Pythonアプリケーションを実行する場合、<code>-u</code>を指定すると出力がバッファされるのを抑止できます。</p>
|
||||
</script>
|
||||
43
nodes/core/locales/ja/core/80-function.html
Normal file
43
nodes/core/locales/ja/core/80-function.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="function">
|
||||
<p>受信メッセージに対して処理を行うJavaScriptコード(関数の本体)を定義します。</p>
|
||||
<p>入力メッセージは<code>msg</code>という名称のJavaScriptオブジェクトで受け渡されます。</p>
|
||||
<p><code>msg</code>オブジェクトは<code>msg.payload</code>プロパティにメッセージ本体を保持するのが慣例です。</p>
|
||||
<p>通常、コードはメッセージオブジェクト(もしくは複数のメッセージオブジェクト)を返却します。何も返却しない場合には、フロー実行を停止します。</p>
|
||||
<h3>詳細</h3>
|
||||
<p>コードの書き方の詳細については、<a target="_blank" href="http://nodered.org/docs/writing-functions.html">オンラインドキュメント</a>を参照してください。</p>
|
||||
<h4>メッセージの送信</h4>
|
||||
<p>フロー内の次ノードにメッセージを渡すためには、メッセージを返却するか<code>node.send(messages)</code>を呼び出します。</p>
|
||||
<p>返却/sendの対象は次のとおりです:</p>
|
||||
<ul>
|
||||
<li>単一メッセージオブジェクト - 最初の出力に接続されたノードに渡されます</li>
|
||||
<li>メッセージオブジェクトの配列 - 対応する出力に接続されたノードに渡されます</li>
|
||||
</ul>
|
||||
<p>配列要素が配列の場合には、複数のメッセージを対応する出力に送出します。</p>
|
||||
<p>返却方法が単一値か配列要素かにかかわらず、返却値がnullの場合メッセージの送出は行いません。</p>
|
||||
<h4>ログ出力とエラー処理</h4>
|
||||
<p>ログ情報の出力、エラー出力を行うには以下の関数を用います:</p>
|
||||
<ul>
|
||||
<li><code>node.log("ログメッセージ")</code></li>
|
||||
<li><code>node.warn("警告")</code></li>
|
||||
<li><code>node.error("エラー")</code></li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>catchノードを用いてエラー処理が可能です。catchノードで処理させるためには、<code>msg</code>を<code>node.error</code>の第二引数として渡します:</p>
|
||||
<pre>node.error("エラー",msg);</pre>
|
||||
</script>
|
||||
47
nodes/core/locales/ja/core/80-template.html
Normal file
47
nodes/core/locales/ja/core/80-template.html
Normal file
@@ -0,0 +1,47 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="template">
|
||||
<p>テンプレートに基づいてプロパティを設定します。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>msg <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>テンプレートを生成するための情報を含むメッセージオブジェクト</dd>
|
||||
<dt class="optional">template <span class="property-type">文字列</span></dt>
|
||||
<dd><code>msg.payload</code>を生成するためのテンプレート。編集パネルでテンプレートを設定しない場合に、出力メッセージとして利用します</dd>
|
||||
</dl>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>msg <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>指定したテンプレートと入力メッセージのプロパティから生成した値を設定したメッセージ</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>このノードは<i><a href="http://mustache.github.io/mustache.5.html" target="_blank">mustache</a></i>形式をデフォルトで利用しますが、使用しないようにすることもできます。</p>
|
||||
<p>例えば、
|
||||
<pre>こんにちは{{payload.name}}さん。今日は{{date}}です。</pre>
|
||||
<p>というテンプレートに対して、
|
||||
<pre>{
|
||||
date: "月曜日"
|
||||
payload: {
|
||||
name: "山田",
|
||||
}
|
||||
}</pre>
|
||||
<p>というメッセージを受信した場合、</p>
|
||||
<pre>こんにちは山田さん。今日は月曜日です。</pre>
|
||||
<p>というプロパティが生成されます。</p>
|
||||
<p>フローコンテキストもしくはグローバルコンテキストのプロパティ値を使うこともできます。それぞれ、<code>{{flow.名前}}</code>もしくは<code>{{global.名前}}</code>を用います。</p>
|
||||
<p><b>注: </b>デフォルトでは、<i>mustache</i>形式は置換対象のHTML要素をエスケープします。これを抑止するには<code>{{{三重}}}</code>括弧形式を使います。</p>
|
||||
</script>
|
||||
30
nodes/core/locales/ja/core/89-delay.html
Normal file
30
nodes/core/locales/ja/core/89-delay.html
Normal file
@@ -0,0 +1,30 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="delay">
|
||||
<p>ノードを通過するメッセージを遅延もしくは流量を制限します。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt class="optional">delay <span class="property-type">数値</span></dt>
|
||||
<dd>メッセージの遅延時間をミリ秒単位で設定します。これはノードの設定でデフォルトの遅延時間を上書きできるようノードを設定した場合にのみ適用します。</dd>
|
||||
<dt class="optional">reset</dt>
|
||||
<dd>受信メッセージでこのプロパティを任意の値に設定すると、ノードが保持する全ての未送信メッセージをクリアします。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>メッセージを遅延させるように設定する場合、遅延時間は固定値、範囲内の乱数値、メッセージ毎の動的な指定値のいずれかを指定できます。</p>
|
||||
<p>流量制御する場合、メッセージは指定した時間間隔内に分散して送信します。キューに残っているメッセージ数はノードのステータスに表示されます。受け取った中間メッセージを破棄することも可能です。</p>
|
||||
<p>流量制御は全てのメッセージに適用することも、<code>msg.topic</code>値でグループ化して適用することも可能です。グループ化すると、中間メッセージは自動的に破棄されます。各時間間隔毎に全てのトピックの最新メッセージを送信するか、次のトピックの最新メッセージを送信するかを指定できます。</p>
|
||||
</script>
|
||||
33
nodes/core/locales/ja/core/89-trigger.html
Normal file
33
nodes/core/locales/ja/core/89-trigger.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="trigger">
|
||||
<p>メッセージの受信すると、別のメッセージの送信を行います。延長もしくは初期化が指定されていない場合には、2つ目のメッセージを送信することもできます。</p>
|
||||
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt class="optional">reset</dt>
|
||||
<dd>このプロパティを持つメッセージを受け取ると、仕掛かり中の待機や繰り返しをクリアしメッセージの送信は行いません。</dd>
|
||||
</dl>
|
||||
|
||||
<h3>詳細</h3>
|
||||
<p>フロー内でタイムアウトを作成するのに利用します。メッセージを受け取ると、デフォルトでは<code>payload</code>に<code>1</code>を設定して送信します。送信後250ms待機し、<code>payload</code>を<code>0</code>に設定した2つ目のメッセージを送信します。この機能は、例えばRaspberry PIのGPIOピンに接続したLEDを点滅させるために活用できます。</p>
|
||||
<p>各送信メッセージのペイロードはさまざまな種類の値に設定できます。再送信データなしとすることも可能です。例えば、再送信データを「<i>なし</i>」とし、メッセージを受け取った時に遅延を延長することを選択した場合、triggerノードは監視タイマとして動作します。すなわち、指定間隔内にメッセージを受信しない場合にメッセージを送信します。</p>
|
||||
<p>ペイロードに<i>文字列</i>を指定する場合、mustache形式のテンプレートが利用できます。</p>
|
||||
<p><code>reset</code>プロパティを持つメッセージを受信した場合、もしくは、<code>payload</code>が設定した値にマッチする場合、仕掛かり中の待機や繰り返しをクリアしメッセージの送信は行いません。</p>
|
||||
<p>受信メッセージでリセットするまで一定間隔でメッセージを再送するように指定することもできます。</p>
|
||||
<p><code>msg.topic</code>毎に別のストリームとして扱うように設定することも可能です。</p>
|
||||
</script>
|
||||
21
nodes/core/locales/ja/core/90-comment.html
Normal file
21
nodes/core/locales/ja/core/90-comment.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="comment">
|
||||
<p>フローにコメントを記述するために利用します。</p>
|
||||
<h3>詳細</h3>
|
||||
<p>編集パネルはMarkdown形式を記入可能です。入力したテキストは、「情報」サイドパネルに表示されます。</p>
|
||||
</script>
|
||||
24
nodes/core/locales/ja/core/98-unknown.html
Normal file
24
nodes/core/locales/ja/core/98-unknown.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="unknown">
|
||||
<p>インストールされたNode-REDが認識できない種別のノードです。</p>
|
||||
<h3>詳細</h3>
|
||||
<p><i>この種別のノードをデプロイした場合、設定は保持されますが、足りないノードをインストールするまでフローを開始することはできません。</i></p>
|
||||
<p><code>メニュー - パレットの管理</code>を使ってノードの検索とインストールを行うか、<b>npm install <モジュール></b>で不足モジュールのインストールを行ってNode-REDを再起動した後、ノードを再インポートしてください。</p>
|
||||
<p>この種別のノードがインストール済みであるが依存ライブラリがインストールされていないケースもあります。Node-REDの起動ログを参照して不足ノードに関連したエラーメッセージをチェックすると良いでしょう。</p>
|
||||
<p>それでも解決しない場合、フローの作者に依頼して不足ノードのコピーを入手してください。</p>
|
||||
</script>
|
||||
71
nodes/core/locales/ja/hardware/36-rpi-gpio.html
Normal file
71
nodes/core/locales/ja/hardware/36-rpi-gpio.html
Normal file
@@ -0,0 +1,71 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-gpio in">
|
||||
<p>Raspberry Piの入力ノード。入力ピンの状態に応じて、0 または 1 の値を持つ<code>msg.payload</code>を生成します。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">数値</span></dt>
|
||||
<dd>ペイロードには、0 または 1 が設定されます。</dd>
|
||||
<dt>topic <span class="property-type">文字列</span></dt>
|
||||
<dd>トピックには、<code>pi/{ピン番号}</code>が設定されます。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>入力のプルアップ抵抗またはプルダウン抵抗を有効にすることもできます。</p>
|
||||
<p>動作にはRPi.GPIO pythonライブラリのバージョン 0.5.10 (またはそれ以上)が必要です。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-gpio out">
|
||||
<p>Raspberry Piの出力ノード。デジタルモードまたはPWMモードで利用できます。
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">数値 | 文字列 | 真偽値</span></dt>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>デジタルモード - <code>msg.payload</code>に 0 または 1 (あるいは true または false ) を指定すると、入力値に応じて選択された物理ピンにハイまたはローを設定します。</p>
|
||||
<p>デプロイ時にピンの初期値として 0 または 1 を設定することもできます。</p>
|
||||
<p>PWMモード - 入力値に 0 から 100 の数値を指定でき。小数値の指定も可能です。</p>
|
||||
<p>サーボの制御にPWMモードが利用でき、入力に小数値も含む 10 から 20 の値が指定可能です。
|
||||
PWMを行うハードウェアを利用していることから、PWMモードの指定にはGPIO2ピンが最も適しています。
|
||||
より良くサーボの制御を行いたい場合は、node-red-node-pi-gpiod ノードの利用も検討してください。</p>
|
||||
<p>動作にはRPi.GPIO pythonライブラリのバージョン 0.5.10 (またはそれ以上)が必要です。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-mouse">
|
||||
<p>Raspberry Pi のマウスボタンノード。USBマウスが必要です。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">数値</span></dt>
|
||||
<dd>選択されたマウスのボタンが押された、または離された場合に 1 または 0 が設定されます。</dd>
|
||||
<dt>button <span class="property-type">数値</span></dt>
|
||||
<dd>左、右、真ん中のボタンに応じて 1, 2, 4 が設定され、ボタンあるいはボタンの組み合わせに応じた処理ができます。</dd>
|
||||
<dt>topic <span class="property-type">文字列</span></dt>
|
||||
<dd><code>pi/mouse</code>が設定されます。</dd>
|
||||
</dl>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-keyboard">
|
||||
<p>Raspberry Pi のキーボードを制御するノード。USBキーボードが必要です。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">数値</span></dt>
|
||||
<dd>キーコードを含みます。</dd>
|
||||
<dt>action <span class="property-type">文字列</span></dt>
|
||||
<dd>"up", "down", または "repeat" が設定されます。</dd>
|
||||
<dt>topic <span class="property-type">文字列</span></dt>
|
||||
<dd><code>pi/key</code>が設定されます。</dd>
|
||||
</dl>
|
||||
</script>
|
||||
19
nodes/core/locales/ja/io/05-tls.html
Normal file
19
nodes/core/locales/ja/io/05-tls.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="tls-config">
|
||||
<p>TLS接続のためのオプション設定</p>
|
||||
</script>
|
||||
72
nodes/core/locales/ja/io/10-mqtt.html
Normal file
72
nodes/core/locales/ja/io/10-mqtt.html
Normal file
@@ -0,0 +1,72 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="mqtt in">
|
||||
<p>MQTTブローカに接続し、指定したトピックのメッセージをサブスクライブ(購読)します。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">文字列 | バッファ</span></dt>
|
||||
<dd>バイナリバッファでない場合は文字列</dd>
|
||||
<dt>topic <span class="property-type">文字列</span></dt>
|
||||
<dd>MQTTのトピック。/を階層の区切りに使用する</dd>
|
||||
<dt>qos <span class="property-type">数値</span> </dt>
|
||||
<dd>0: 最大1度到着, 1: 一度以上到着, 2: 1度のみ到着</dd>
|
||||
<dt>retain <span class="property-type">真偽値</span></dt>
|
||||
<dd>真の場合、メッセージを保持。メッセージが古い値の場合があります。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>購読トピックにはMQTTのワイルドカード(+: 1レベル, #: 複数レベル)を含めることができます。</p>
|
||||
<p>このノードの利用のためには、MQTTブローカへの接続設定が必要です。この設定は鉛筆アイコンをクリックすることで行えます。</p>
|
||||
<p>MQTT(inおよびout)ノードはブローカへの接続設定を必要に応じて共有できます。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="mqtt out">
|
||||
<p>MQTTブローカに接続し、メッセージをパブリッシュ(発行)します。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">文字列 | バッファ</span></dt>
|
||||
<dd>多くの場合単純なテキスト形式のペイロードが使われますが、バイナリバッファを発行することも可能です。</dd>
|
||||
|
||||
<dt class="optional">topic <span class="property-type">文字列</span></dt>
|
||||
<dd>発行対象のMQTTトピック</dd>
|
||||
|
||||
<dt class="optional">qos <span class="property-type">数値</span></dt>
|
||||
<dd>0: 最大1度到着, 1: 一度以上到着, 2: 1度のみ到着。デフォルトは0です。</dd>
|
||||
|
||||
<dt class="optional">retain <span class="property-type">真偽値</span></dt>
|
||||
<dd>真の場合、メッセージをブローカに保持します。デフォルトは偽です。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p><code>msg.payload</code>を発行するメッセージのペイロードとして用います。ペイロードがオブジェクトの場合、送信の際にJSON文字列に変換します。ペイロードがバイナリバッファの場合、そのまま送信します。</p>
|
||||
<p>発行に利用するトピックはノードに設定するか、もしくは、<code>msg.topic</code>で指定します。</p>
|
||||
<p>同様に、QoSとretainもノードの設定、もしくは、ノードの設定が空の場合には、それぞれ<code>msg.qos</code>および<code>msg.retain</code>で指定できます。以前ブローカに保存したトピックをクリアするには、retainフラグを設定して当該トピックにからのメッセージを発行します。</p>
|
||||
<p>このノードの利用のためには、MQTTブローカへの接続設定が必要です。この設定は鉛筆アイコンをクリックすることで行えます。</p>
|
||||
<p>MQTT(inおよびout)ノードはブローカへの接続設定を必要に応じて共有できます。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="mqtt-broker">
|
||||
<p>MQTTブローカへの接続設定</p>
|
||||
<p>ブローカへの接続設定を作成します。設定は<code>MQTT In</code>および<code>MQTT Out</code>ノードで再利用できます。</p>
|
||||
<p>ノードにクライアントIDを設定しておらずセッションの初期化を設定している場合、ランダムなクライアントIDを生成します。クライアントIDを設定する場合、接続先のブローカで一意となるようにしてください。</p>
|
||||
<h4>Birthメッセージ</h4>
|
||||
<p>接続を確立した際に、設定したトピックに対して発行するメッセージ</p>
|
||||
<h4>Willメッセージ</h4>
|
||||
<p>予期せず接続が切断された場合にブローカが発行するメッセージ</p>
|
||||
<h4>WebSocket</h4>
|
||||
<p>WebSocketによる接続を行うように設定できます。WebSocketを利用するには、サーバフィールドに接続先のURIを完全な形式で記述します。以下に例を示します。</p>
|
||||
<pre>ws://example.com:4000/mqtt</pre>
|
||||
|
||||
</script>
|
||||
81
nodes/core/locales/ja/io/21-httpin.html
Normal file
81
nodes/core/locales/ja/io/21-httpin.html
Normal file
@@ -0,0 +1,81 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="http in">
|
||||
<p>HTTPエンドポイントを作成し、Webサービスを構成します。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload</dt>
|
||||
<dd>GETリクエストの場合、クエリパラメータからなるオブジェクト。それ以外の場合、HTTPリクエストの本体を指します。</dd>
|
||||
<dt>req<span class="property-type">オブジェクト</span></dt>
|
||||
<dd>HTTPリクエストオブジェクト。オブジェクトはリクエストの情報に関する複数のプロパティを含みます。
|
||||
<ul>
|
||||
<li><code>body</code> - リクエスト本体。形式はリクエストに依存します</li>
|
||||
<li><code>headers</code> - HTTPリクエストヘッダを含むオブジェクト</li>
|
||||
<li><code>query</code> - クエリパラメータを含むオブジェクト</li>
|
||||
<li><code>params</code> - ルーティングパラメータを含むオブジェクト</li>
|
||||
<li><code>cookies</code> - リクエストのクッキーを含むオブジェクト</li>
|
||||
<li><code>files</code> - POSTリクエストでファイルのアップロードが設定で有効化されている場合、アップロード対象のファイル</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>res<span class="property-type">オブジェクト</span></dt>
|
||||
<dd>HTTPレスポンスオブジェクト。このプロパティを直接利用することは推奨しません。リクエストの処理方法については<code>HTTP Response</code>ノードのドキュメントを参照してください。このプロパティはresponseノードに渡すメッセージに付けたままとしてください。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>このノードは設定で指定したパスとリクエスト種別でリクエストを待ち受けます。パス指定は完全に指定する形式(例: <code>/user</code>)、もしくは、任意の値を受け付ける名前付きパラメータを含む形式(例: <code>/user/:name</code>)のいずれでも構いません。名前付きパラメータを指定する場合、リクエストで指定された実際の値は<code>msg.req.params</code>から参照できます。</p>
|
||||
<p>POSTやPUTのようにリクエストボディを含むリクエストの場合、リクエストの内容は<code>msg.payload</code>で参照できます。</p>
|
||||
<p>リクエストの要素タイプが識別可能な場合には、リクエストボディを適切な形式に変換します。例えば、<code>application/json</code>はJavaScriptオブジェクトに変換します。</p>
|
||||
<p><b>注:</b> このノードはリクエストに対するレスポンスの送信は行いません。リクエストを処理するにはフローにHTTP Responseノードを含めてください。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="http response">
|
||||
<p>HTTP Inノードで受け付けたリクエストに対するレスポンスを送り返します。</p>
|
||||
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">文字列</span></dt>
|
||||
<dd>レスポンス本体</dd>
|
||||
<dt class="optional">statusCode <span class="property-type">数値</span></dt>
|
||||
<dd>設定するとレスポンスのステータスコードとします。デフォルト: 200</dd>
|
||||
<dt class="optional">headers <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>設定するとレスポンスのHTTPヘッダとします</dd>
|
||||
<dt class="optional">cookies <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>設定するとクッキーを設定もしくは削除するために使用します</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p><code>statusCode</code>と<code>headers</code>はノードの設定で指定することも可能です。ノードの設定でプロパティを指定した場合には、対応するメッセージプロパティは使用しません。</p>
|
||||
<h4>クッキーの処理</h4>
|
||||
<p><code>cookies</code>はキー/値の組からなるオブジェクトとします。値にはデフォルトオプションを使ってクッキーの値として設定する文字列、もしくは、オプションを含むオブジェクトを指定できます。<p>
|
||||
<p>以下の例では2つのクッキーを設定しています。1つ目は<code>name</code>でその値は<code>nick</code>、2つ目は<code>session</code>で値は<code>1234,</code>、有効期限として15分を指定しています。</p>
|
||||
<pre>
|
||||
msg.cookies = {
|
||||
name: 'nick',
|
||||
session: {
|
||||
value: '1234',
|
||||
maxAge: 900000
|
||||
}
|
||||
}</pre>
|
||||
<p>有効なオプションには以下があります。</p>
|
||||
<ul>
|
||||
<li><code>domain</code> - (文字列) クッキーのドメイン指定</li>
|
||||
<li><code>expires</code> - (日時) GMT表現での有効期限。未指定もしくは0を指定した場合、セッション終了まで有効</li>
|
||||
<li><code>maxAge</code> - (文字列) 現時刻からの経過ミリ秒で表した有効期限</li>
|
||||
<li><code>path</code> - (文字列) クッキーのパス。デフォルトは「/」</li>
|
||||
<li><code>value</code> - (文字列) クッキーの値</li>
|
||||
</ul>
|
||||
<p>クッキーを削除するには、<code>value</code>に<code>null</code>を設定します。</p>
|
||||
|
||||
</script>
|
||||
60
nodes/core/locales/ja/io/21-httprequest.html
Normal file
60
nodes/core/locales/ja/io/21-httprequest.html
Normal file
@@ -0,0 +1,60 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="http request">
|
||||
<p>HTTPリクエストを送信し、レスポンスを返します。</p>
|
||||
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt class="optional">url <span class="property-type">文字列</span></dt>
|
||||
<dd>ノードの設定で指定していない場合、このプロパティでリクエストのurlを設定します。</dd>
|
||||
<dt class="optional">method <span class="property-type">文字列</span></dt>
|
||||
<dd>ノードの設定で指定していない場合、このプロパティでリクエストに用いるHTTPメソッドを設定します。<code>GET</code>, <code>PUT</code>, <code>POST</code>, <code>PATCH</code>, <code>DELETE</code>のいずれかを指定してください。</dd>
|
||||
<dt class="optional">headers <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>リクエストのHTTPヘッダを指定します。</dd>
|
||||
<dt class="optional">cookies <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>設定すると、リクエストと共にクッキーを送ることができます。</dd>
|
||||
<dt class="optional">payload</dt>
|
||||
<dd>リクエストボディとして送るデータ</dd>
|
||||
<dt class="optional">rejectUnauthorized</dt>
|
||||
<dd><code>true</code>をセットすると、自己署名証明書を使用するhttpsサイトへのリクエストを許可します。</dd>
|
||||
</dl>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">文字列 | オブジェクト | バッファ</span></dt>
|
||||
<dd>レスポンスボディ。返却するボディデータを文字列、JSON文字列として解釈した結果、バイナリバッファのままのいずれにするかを、ノード設定により指定できます。</dd>
|
||||
<dt>statusCode <span class="property-type">数値</span></dt>
|
||||
<dd>レスポンスのステータスコード、もしくは、リクエストが完了しなかった場合のエラーコード。</dd>
|
||||
<dt>headers <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>レスポンスヘッダを含むオブジェクト</dd>
|
||||
<dt>responseUrl <span class="property-type">文字列</span></dt>
|
||||
<dd>リクエストの処理時にリダイレクトが発生した場合、このプロパティが最後にリダイレクトされたURLを表します。リダイレクトが起こらなかった場合、最初リクエストのURLを表します。</dd>
|
||||
<dt>responseCookies <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>レスポンスがクッキーを含む場合、このプロパティは各クッキーの名前/値を含むオブジェクトを表します。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>ノードの設定でurlプロパティを指定する場合、<a href="http://mustache.github.io/mustache.5.html" target="_blank">mustache形式</a>のタグを含めることができます。これにより、URLを入力メッセージの値から構成することができます。例えば、urlが<code>example.com/{{{topic}}}</code>の場合、<code>msg.topic</code>の値による置き換えを自動的に行います。{{{...}}}表記を使うと、/、&といった文字をmustacheがエスケープするのを抑止できます。</p>
|
||||
<p><b>注</b>: proxyサーバを利用している場合、環境変数<code>http_proxy=...</code>を設定して、Node-REDを再起動してください。</p>
|
||||
<h4>複数のHTTPリクエストノードの利用</h4>
|
||||
<p>同一フローで本ノードを複数利用するためには、<code>msg.headers</code>プロパティの扱いに注意しなくてはなりません。例えば、最初のノードがレスポンスヘッダにこのプロパティを設定し、次のノードがこのプロパティをリクエストヘッダに利用するというのは一般的には期待する動作ではありません。<code>msg.headers</code>プロパティをノード間で変更しないままとすると、2つ目のノードで無視されることになります。カスタムヘッダを設定するためには、<code>msg.headers</code>をまず削除もしくは空のオブジェクト<code>{}</code>にリセットします。
|
||||
<h4>クッキーの扱い</h4>
|
||||
<p>ノードに<code>cookies</code>プロパティを渡す場合、その値はキー/値ペアからなるオブジェクトとしてください。値にはクッキーの値として設定する文字列、もしくは、単一の<code>value</code>プロパティを含むオブジェクトを指定できます。<p>
|
||||
<p>リクエストに対して返却されたクッキーは<code>responseCookies</code>プロパティに格納されます。</p>
|
||||
<h4>要素タイプの扱い</h4>
|
||||
<p><code>msg.payload</code>がオブジェクトの場合、リクエストの要素タイプを<code>msg.payload</code>に自動的に設定し、ボディーをJSONに変換します。</p>
|
||||
<p>リクエストをフォームデータにエンコードするには、<code>msg.headers["content-type"]</code>を<code>application/x-www-form-urlencoded</code>に設定します。</p>
|
||||
|
||||
</script>
|
||||
36
nodes/core/locales/ja/io/22-websocket.html
Normal file
36
nodes/core/locales/ja/io/22-websocket.html
Normal file
@@ -0,0 +1,36 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket in">
|
||||
<p>WebSocket入力ノード</p>
|
||||
<p>デフォルトでは、WebSocketにより受信したデータは<code>msg.payload</code>に格納します。ソケットはJSON形式の文字列を待ち受けるように設定することができます。JSON形式の文字列を受け付けると、オブジェクトへの変換を行い、メッセージ全体として送信します。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket out">
|
||||
<p>WebSocket出力ノード</p>
|
||||
<p>デフォルトでは、<code>msg.payload</code>をWebSocket経由で送信します。ソケットは<code>msg</code>全体をJSON文字列にエンコードしてWebSocketを介して送信することもできます。</p>
|
||||
|
||||
<p>このノードが受信したメッセージがWebSocket Inノードが生成したものである場合、メッセージはフローを起動したクライアントに送り返されます。それ以外の場合、メッセージは接続している全てのクライアントにブロードキャストされます。</p>
|
||||
<p>WebSocket Inノードが生成したメッセージをブロードキャストしたい場合には、フロー中で<code>msg._session</code>プロパティを削除します。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket-listener">
|
||||
<p>この設定ノードはパスを指定してWebSocketサーバのエンドポイントを作成します。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket-client">
|
||||
<p>この設定ノードは指定したURLにWebSocketクライアントを接続します。</p>
|
||||
</script>
|
||||
25
nodes/core/locales/ja/io/23-watch.html
Normal file
25
nodes/core/locales/ja/io/23-watch.html
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="watch">
|
||||
<p>ディレクトリもしくはファイルの変化を検知します。</p>
|
||||
<p>カンマ区切りでディレクトリおよびファイルのリストを指定します。空白を含む場合は、引用符で"..."のように囲んでください。</p>
|
||||
<p>Windowsでは、2重バックスラッシュ\\をディレクトリ名に使用します。</p>
|
||||
<p>実際に変化したファイルのフルパス名を<code>msg.payload</code>に、検知対象リストの文字列を<code>msg.topic</code>に返します。</p>
|
||||
<p><code>msg.file</code>は変化したファイルのファイル名表します。<code>msg.type</code>は変化した対象の種別(<i>file</i>もしくは<i>directory</i>)を、<code>msg.size</code>はファイルサイズ(バイト数)を表します。</p>
|
||||
<p>Linuxではファイルとして表されるもの<i>全て</i>が、検知対象にできます。</p>
|
||||
<p><b>注: </b>検知対象のディレクトリもしくはファイルは存在していなくてはなりません。対象ファイルもしくはディレクトリが削除された場合、再作成されても検知対象から外れたままです。</p>
|
||||
</script>
|
||||
35
nodes/core/locales/ja/io/31-tcpin.html
Normal file
35
nodes/core/locales/ja/io/31-tcpin.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="tcp in">
|
||||
<p>TCPからの入力を行います。リモートTCPポートに接続するか、外部らからのコネクションを受け付けます。</p>
|
||||
<p><b>注: </b>1024番より小さな番号のポートをアクセスするにはrootもしくはadministrator権限が必要なシステムもあります。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="tcp out">
|
||||
<p>TCPへの出力を行います。リモートTCPポートへ接続、外部からのコネクションの受け付け、もしくは、TCP Inノードで受け付けたメッセージへのリプライを行います。</p>
|
||||
<p><code>msg.payload</code>のみが送信対象となります。</p>
|
||||
<p><code>msg.payload</code>がバイナリデータをBase64エンコーディングの文字列に変換したものの場合、Base64デコードオプションを指定するとデータをバイナリに変換して送信します。</p>
|
||||
<p><code>msg._session</code>が存在しない場合、接続している<b>全ての</b>クライアントに送信します。</p>
|
||||
<p><b>注: </b>1024番より小さな番号のポートをアクセスするにはrootもしくはadministrator権限が必要なシステムもあります。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="tcp request">
|
||||
<p>シンプルなTCPリクエストノード。<code>msg.payload</code>をサーバのTCPポートに送信し、レスポンスを待ちます。</p>
|
||||
<p>サーバに接続、"リクエスト"送信、"レスポンス"受信を行います。固定長の文字数、指定文字へのマッチ、最初のリプライの到着から指定した時間待つ、データの到着待ち、データ送信を行いリプライを待たず接続を即時解除、などから動作を選択できます。</p>
|
||||
<p>レスポンスはバッファ形式で<code>msg.payload</code>に出力されます。文字列として扱いには、toString()を使用してください。</p>
|
||||
<p>TCPホストのポート番号設定を空にした場合、<code>msg.host</code>および<code>msg.port</code>プロパティを設定しなくてはなりません。</p>
|
||||
</script>
|
||||
28
nodes/core/locales/ja/io/32-udp.html
Normal file
28
nodes/core/locales/ja/io/32-udp.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="udp in">
|
||||
<p>UDP入力ノード。<code>msg.payload</code>にバッファ、文字列、もしくは、Base64エンコーディング文字列を生成します。マルチキャストをサポートしています。</p>
|
||||
<p><code>msg.ip</code>と<code>msg.port</code>に受信したメッセージのIPアドレスとポートを設定します。</p>
|
||||
<p><b>注</b>: 1024番より小さな番号のポートへのアクセス、ブロードキャストを行うにはrootもしくはadministrator権限が必要なシステムもあります。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="udp out">
|
||||
<p><code>msg.payload</code>を指定したUDPのホストとポートに送信します。マルチキャストをサポートします。</p>
|
||||
<p><code>msg.ip</code>と<code>msg.port</code>に接続先を設定できますが、ノード設定の方が優先されます。</p>
|
||||
<p>ブロードキャストを行うには、アドレスをローカルブロードキャストIPアドレスに設定するか、グローバルブロードキャストアドレスである255.255.255.255を試してください。</p>
|
||||
<p><b>注</b>: 1024番より小さな番号のポートへのアクセス、ブロードキャストを行うにはrootもしくはadministrator権限が必要なシステムもあります。</p>
|
||||
</script>
|
||||
35
nodes/core/locales/ja/logic/10-switch.html
Normal file
35
nodes/core/locales/ja/logic/10-switch.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="switch">
|
||||
<p>プロパティの値によってメッセージの振り分けを行います。</p>
|
||||
<h3>詳細</h3>
|
||||
<p>受信したメッセージに対し、指定されたルールを順に評価し、マッチしたルールに対応する出力ポートにメッセージを送出します。</p>
|
||||
<p>最初にルールがマッチしたところで評価を止めることも可能です。</p>
|
||||
<p>評価ルールには、メッセージプロパティ、フローコンテキスト/グローバルコンテキストのプロパティ、JSONata式の評価結果が利用できます。</p>
|
||||
<h3>ルール</h3>
|
||||
<p>振り分けルールは以下の4つに分類されます。</p>
|
||||
<ol>
|
||||
<li><b>値(value)</b>ルール - 指定したプロパティに対して評価</li>
|
||||
<li><b>列(sequence)</b>ルール - メッセージ列に対して適用(メッセージ列はsplitノードなどで生成)</li>
|
||||
<li><b>JSONata式</b> - メッセージ全体に対して評価を行い、結果が真の場合にマッチ</li>
|
||||
<li><b>その他</b> - これより前のルールにマッチするものがなかった場合に適用</li>
|
||||
</ol>
|
||||
|
||||
<h3>メッセージ列の扱い</h3>
|
||||
<p>switchノードは入力メッセージの列に関する情報を保持する<code>msg.parts</code>をデフォルトでは変更しません。</p>
|
||||
<p>「<b>メッセージ列の補正</b>」オプションを指定すると、マッチした各ルールに対して新しいメッセージ列を生成します。このモードでは、switchノードは新たなメッセージ列を送信する前に、入力メッセージ列全体を内部に蓄積します。<code>nodeMessageBufferMaxLength</code>を設定すると、蓄積するメッセージ数を制限できます。</p>
|
||||
</script>
|
||||
33
nodes/core/locales/ja/logic/15-change.html
Normal file
33
nodes/core/locales/ja/logic/15-change.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="change">
|
||||
<p>メッセージ、フローコンテキスト、グローバルコンテキストのプロパティを変更、削除、移動します。</p>
|
||||
<p>ルールを複数指定した場合、定義した順に適用します。</p>
|
||||
<h3>詳細</h3>
|
||||
<p>利用可能な処理</p>
|
||||
<dl class="message-properties">
|
||||
<dt>代入</dt>
|
||||
<dd>プロパティをセットします。設定値には、さまざまな型の値、メッセージやコンテキストの既存プロパティを利用できます。<dd>
|
||||
<dt>置換</dt>
|
||||
<dd>プロパティに対して検索と置換を行います。正規表現を指定した場合、「置換後の文字列」には<code>$1</code>のようなキャプチャグループが指定できます。置換処理では、ルールが完全マッチの場合のみプロパティの型を変更できます。</dd>
|
||||
<dt>削除</dt>
|
||||
<dd>プロパティを削除します。</dd>
|
||||
<dt>移動</dt>
|
||||
<dd>プロパティの移動または名前の変更を行います。</dd>
|
||||
</dl>
|
||||
<p>「expression」には<a href="http://jsonata.org/" target="_new">JSONata</a>言語を指定できます。</p>
|
||||
</script>
|
||||
33
nodes/core/locales/ja/logic/16-range.html
Normal file
33
nodes/core/locales/ja/logic/16-range.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="range">
|
||||
<p>数値を異なる範囲の値に変換します。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">数値</span></dt>
|
||||
<dd>数値以外の場合は、数値に変換します。変換不能な場合はラーとなります。</dd>
|
||||
</dl>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">数値</span></dt>
|
||||
<dd>新しい範囲に変換した結果の値。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>このノードは受け取った数値を線形スケーリングします。デフォルトでは、結果の値はノードに設定した範囲内に限定しません。</p>
|
||||
<p>「<i>入力値の範囲外の値を最小値/最大値として拡大/縮小</i>」を指定すると、値が指定した範囲外の値にならないようにします。</p>
|
||||
<p>「<i>入力値の範囲外の値を範囲幅で割った余りとし拡大/縮小</i>」を指定すると、結果を範囲幅で折り返します。</p>
|
||||
</script>
|
||||
137
nodes/core/locales/ja/logic/17-split.html
Normal file
137
nodes/core/locales/ja/logic/17-split.html
Normal file
@@ -0,0 +1,137 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="split">
|
||||
<p>メッセージをメッセージ列に分割します。</p>
|
||||
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">オブジェクト | 文字列 | 配列 | バッファ</span></dt>
|
||||
<dd><code>msg.payload</code>の型によってノードの動作が異なります。
|
||||
<ul>
|
||||
<li><b>文字列</b>/<b>バッファ</b> - 指定された文字列 (デフォルト: <code>\n</code>)、バッファ列、もしくは固定の長さによりメッセージを分割します。</li>
|
||||
<li><b>配列</b> - メッセージを配列要素毎もしくは固定の長さの配列に分割します。</li>
|
||||
<li><b>オブジェクト</b> - キー/値の各組に対してメッセージを送信します。</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>parts<span class="property-type">オブジェクト</span></dt>
|
||||
<dd>元のメッセージをどのように分割したかに関する情報をこのプロパティに保持します。例えば、<b>join</b>ノードに渡すことで、メッセージ列を一つのメッセージに再構成することができます。<code>parts</code>プロパティは次のプロパティを含みます。
|
||||
<ul>
|
||||
<li><code>id</code> - メッセージグループの識別子</li>
|
||||
<li><code>index</code> - グループ内の位置</li>
|
||||
<li><code>count</code> - 既知の場合、グループ内のメッセージ数を設定。下記「ストリームモード」を参照</li>
|
||||
<li><code>type</code> - メッセージの型 - 文字列/配列/オブジェクト/バッファ</li>
|
||||
<li><code>ch</code> - 文字列もしくはバッファの場合、メッセージを分割するのに用いた文字列もしくはバイト配列</li>
|
||||
<li><code>key</code> - オブジェクトの場合、メッセージ生成元のキー。
|
||||
ノードの設定によりキーを<code>msg.topic</code>など他のメッセージプロパティにコピーすることもできます。</li>
|
||||
<li><code>len</code> - メッセージを固定の長さで分割した場合の長さ。</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>このノードは、メッセージ列を構成するメッセージに対して共通処理を行い、<b>join</b>ノードで一つのメッセージに纏めるようなフローを作成する際に有用です。</p>
|
||||
<p><code>msg.parts</code>プロパティを用いて元のメッセージとメッセージ列との対応関係を記憶します。</p>
|
||||
<h4>ストリームモード</h4>
|
||||
<p>このノードはメッセージ列を再構成して送信する際にも有用です。例えば、改行終端のコマンドを送信するようなシリアルデバイスでは、メッセージの最後のコマンド部分が途切れたメッセージを送出する場合があります。「ストリームモード」を用いることで、完結した個別コマンドにメッセージを分割することができます。入力メッセージの最後に未完部分がある場合、<b>split</b>ノードは未完部分を記憶しておいて、次に受信したメッセージの先頭に付加します。</p>
|
||||
<p>このモードで処理する際には、メッセージ数を予め知ることができないため、<code>msg.parts.count</code>プロパティは設定されません。従って、<b>join</b>ノードの「自動モード」と組み合わせることはできません。</p>
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/x-red" data-help-name="join">
|
||||
<p>メッセージ列を結合して一つのメッセージにします。</p>
|
||||
<p>メッセージの結合には次の3つのモードが利用できます。</p>
|
||||
<dl>
|
||||
<dt>自動</dt>
|
||||
<dd><b>split</b>ノードと組み合わせると、splitと逆にメッセージを結合する処理を行います。</dd>
|
||||
<dt>手動</dt>
|
||||
<dd>メッセージ列をさまざまな方法で結合します。</dd>
|
||||
<dt>列の集約</dt>
|
||||
<dd>メッセージ列に対して指定した式を適用し、1つのメッセージに集約します。</dd>
|
||||
</dl>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt class="optional">parts<span class="property-type">オブジェクト</span></dt>
|
||||
<dd>自動的にメッセージ列を結合するには、全メッセージがこのプロパティを持っていなければなりません。<b>split</b>ノードでこのプロパティを生成することが可能ですが、独自に生成しても構いません。<code>parts</code>プロパティは以下のプロパティを含みます。
|
||||
<ul>
|
||||
<li><code>id</code> - メッセージグループの識別子</li>
|
||||
<li><code>index</code> - グループ内の順番</li>
|
||||
<li><code>count</code> - グループを構成するメッセージの数</li>
|
||||
<li><code>type</code> - メッセージの型 - string/array/object/buffer</li>
|
||||
<li><code>ch</code> - 文字列もしくはバッファの場合、メッセージを分割するのに用いた文字列もしくはバイト配列</li>
|
||||
<li><code>key</code> - オブジェクトの場合、メッセージ生成元のキー</li>
|
||||
<li><code>len</code> - メッセージを固定の長さで分割した場合の長さ</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="optional">complete</dt>
|
||||
<dd>設定されている場合、保持しているメッセージを結合して送信します。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
|
||||
<h4>自動モード</h4>
|
||||
<p>自動モードでは、入力メッセージの<code>parts</code>プロパティを用いてメッセージ列を結合します。このモードは<b>split</b>ノードの処理の逆を自動的に行います。</p>
|
||||
|
||||
<h4>手動モード</h4>
|
||||
<p>手動モードでは、メッセージ列をさまざまな結果に結合できます。</p>
|
||||
<ul>
|
||||
<li><b>文字列</b>もしくは<b>バッファ</b> - 指定した文字列もしくはバッファ値を区切りとして各メッセージの指定プロパティを結合</li>
|
||||
<li><b>配列</b> - 指定プロパティもしくはメッセージ全体を要素とする配列</li>
|
||||
<li><b>key/valueオブジェクト</b> - 入力メッセージの指定プロパティの値をキーとして、プロパティ値をストアしたオブジェクト</li>
|
||||
<li><b>統合オブジェクト</b> - 各メッセージのプロパティを一つのオブジェクトに統合</li>
|
||||
</ul>
|
||||
<p>出力メッセージのその他のプロパティはメッセージを送信する直前のメッセージをコピーします。</p>
|
||||
<p>「<i>合計値</i>」には出力メッセージを送信する前に受信すべきメッセージ数を指定します。オブジェクト出力の場合、この合計値に達すると後続メッセージの到着毎にメッセージを出力するように設定することもできます。</p>
|
||||
<p>「<i>秒</i>」には新規メッセージを送信するまでの経過時間を設定します。</p>
|
||||
<p><code>msg.complete</code>プロパティを設定したメッセージを受信すると、出力メッセージを送信します。</p>
|
||||
|
||||
<h4>列の集約モード</h4>
|
||||
<p>列の集約モードを選択すると、メッセージ列を構成する各々のメッセージに対して式を適用し、集約した値を用いて一つのメッセージを構成します。</p>
|
||||
<dl class="message-properties">
|
||||
<dt>初期値</dt>
|
||||
<dd>
|
||||
集約の初期値(<code>$A</code>)
|
||||
</dd>
|
||||
<dt>集約式</dt>
|
||||
<dd>メッセージグループを構成する各メッセージに適用するJSONata式。
|
||||
式の評価結果は次回の呼び出しの際に集約値として渡します。
|
||||
<ul>
|
||||
<li><code>$A</code> 集約値</li>
|
||||
<li><code>$I</code> グループ内のメッセージの順番</li>
|
||||
<li><code>$N</code> グループ内のメッセージ数</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>最終調整式</dt>
|
||||
<dd>メッセージグループの集約が完了した後で適用されるJSONata式。任意で指定可能です。式中では以下の特殊変数を参照できます。
|
||||
<ul>
|
||||
<li><code>$A</code> 集約値</li>
|
||||
<li><code>$N</code> グループ内のメッセージ数</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<p>メッセージグループのメッセージに対し、デフォルトでは集約式は最初のメッセージから最後のメッセージに対し順に適用します。指定により適用を逆順にすることも可能です。</p>
|
||||
</dl>
|
||||
<p><b>例:</b> 以下の設定で、数値のメッセージ列に対して平均値を計算します。
|
||||
<ul>
|
||||
<li><b>集約式</b>: <code>$A+payload</code></li>
|
||||
<li><b>初期値</b>: <code>0</code></li>
|
||||
<li><b>最終調整式</b>: <code>$A/$N</code></li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h4>メッセージの蓄積</h4>
|
||||
<p>このノードの処理ではメッセージ列の処理のためメッセージを内部に蓄積します。<code>nodeMessageBufferMaxLength</code>を指定することで蓄積するメッセージの最大値を制限することができます。</p>
|
||||
</script>
|
||||
40
nodes/core/locales/ja/logic/18-sort.html
Normal file
40
nodes/core/locales/ja/logic/18-sort.html
Normal file
@@ -0,0 +1,40 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="sort">
|
||||
<p>メッセージ列もしくは配列型のペイロードをソートします。</p>
|
||||
<p><b>split</b>ノードと組み合わせてメッセージの並べ替えを行うことができます。</p>
|
||||
<p>ソート順序は以下が指定可能です。</p>
|
||||
<ul>
|
||||
<li><b>昇順</b></li>
|
||||
<li><b>降順</b></li>
|
||||
</ul>
|
||||
<p>数値による並べ替えを選択することもできます。</p>
|
||||
<p>メッセージの並べ替えを行うためのソートキーは<code>payload</code>プロパティもしくはJSONata式が利用できます。配列型ペイロードのソートキーには、要素値もしくはJSONata式が利用できます。</p>
|
||||
<p>sortノードの処理では受信したメッセージが<code>msg.parts</code>プロパティを持っていることを想定しています。splitノードでこのプロパティを生成することが可能ですが、独自に生成しても構いません。<code>parts</code>プロパティは以下のプロパティを含みます。</p>
|
||||
<p>
|
||||
<ul>
|
||||
<li><code>id</code> - メッセージグループの識別子</li>
|
||||
<li><code>index</code> - グループ内の順番</li>
|
||||
<li><code>count</code> - グループを構成するメッセージの数</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p><b>注:</b> このノードの処理ではメッセージを内部に蓄積します。以下により蓄積するメッセージの最大数を指定することで、予期しないメモリ使用量の増大を防ぐことができます。デフォルトではメッセージ数を制限しません。
|
||||
<ul>
|
||||
<li><b>settings.js</b>の<code>nodeMessageBufferMaxLength</code>プロパティ</li>
|
||||
</ul>
|
||||
</p>
|
||||
</script>
|
||||
34
nodes/core/locales/ja/logic/19-batch.html
Normal file
34
nodes/core/locales/ja/logic/19-batch.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="batch">
|
||||
<p>指定したルールによりメッセージ列を生成します。</p>
|
||||
<h3>詳細</h3>
|
||||
<p>メッセージ列の生成には以下の3つのモードが利用できます。</p>
|
||||
<dl>
|
||||
<dt>入力メッセージ数でグループ化</dt>
|
||||
<dd>入力メッセージを指定した長さのメッセージ列にグループ化します。メッセージ列の最後の部分を次のメッセージ列の先頭で繰り返すメッセージ数を「<b>オーバラップ</b>」で指定できます。</dd>
|
||||
|
||||
<dt>入力間隔(秒)でグループ化</dt>
|
||||
<dd>指定時間間隔内に受信した入力メッセージをメッセージ列にグループ化します。指定した時間内にメッセージを受信しない場合に空のメッセージを送信するように設定することもできます。</dd>
|
||||
|
||||
<dt>メッセージグループの結合</dt>
|
||||
<dd>入力メッセージ列を結合し、1つのメッセージ列にします。メッセージ列の識別のため、各メッセージは<code>msg.topic</code>プロパティと<code>msg.parts</code>プロパティを持っていなければなりません。メッセージ列の結合順は、<code>topic</code>値のリストとしてbatchノードに指定します。
|
||||
</dd>
|
||||
</dl>
|
||||
<h4>メッセージの蓄積</h4>
|
||||
<p>このノードの処理ではメッセージ列の処理のためメッセージを内部に蓄積します。<code>nodeMessageBufferMaxLength</code>を指定することで蓄積するメッセージの最大値を制限することができます。</p>
|
||||
</script>
|
||||
@@ -234,7 +234,7 @@
|
||||
"and": "回/",
|
||||
"rate": "流量",
|
||||
"msgper": "メッセージ/",
|
||||
"dropmsg": "仲介メッセージを削除",
|
||||
"dropmsg": "中間メッセージを削除",
|
||||
"label": {
|
||||
"delay": "delay",
|
||||
"variable": "variable",
|
||||
|
||||
44
nodes/core/locales/ja/parsers/70-CSV.html
Normal file
44
nodes/core/locales/ja/parsers/70-CSV.html
Normal file
@@ -0,0 +1,44 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="csv">
|
||||
<p>CSV形式の文字列とそのJavaScriptオブジェクト表現の間で双方向の変換を行います。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">オブジェクト | 配列 | 文字列</span></dt>
|
||||
<dd>JavaScriptオブジェクト、配列、CSV文字列のいずれか</dd>
|
||||
</dl>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">オブジェクト | 配列 | 文字列</span></dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>入力が文字列の場合、CSVとして解釈し、CSVの各行をキー/バリューとしたJavaScriptオブジェクトを生成します。
|
||||
各行毎にメッセージを送信するかオブジェクトの配列からなる一つのメッセージを送信するかを選択できます。</li>
|
||||
<li>入力がJavaScriptオブジェクトの場合、CSV文字列への変換を行います。</li>
|
||||
<li>入力が基本型の配列の場合、1行のCSV文字列へ変換します。</li>
|
||||
<li>入力が配列の配列、もしくは、オブジェクトの配列の場合、複数行のCSV文字列へ変換します。</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>「列名」にカラム名のリストを指定することができます。CSVからオブジェクトに変換を行う際、カラム名をプロパティ名として使用します。「列名」の代わりに、CSVデータの1行目にカラム名を含めることもできます。</p>
|
||||
<p>CSVへの変換を行う際には、オブジェクトから取り出すべきプロパティとその順序を「列名」を参照して決めます。</p>
|
||||
<p>入力が配列の場合には、「列名」はカラム名を表す行の出力指定がされた場合だけ用います。</p>
|
||||
<p><code>parts</code>プロパティが正しく設定されている場合、メッセージ列を入力として受け付けます。</p>
|
||||
<p>CSVを複数のメッセージに変換して出力する場合、出力がメッセージ列となるよう<code>parts</code>プロパティを設定します。</p>
|
||||
<p><b>注:</b> カンマ以外の区切り文字を設定した場合であっても、「列名」はカンマ区切りとしてください。</p>
|
||||
</script>
|
||||
33
nodes/core/locales/ja/parsers/70-HTML.html
Normal file
33
nodes/core/locales/ja/parsers/70-HTML.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="html">
|
||||
<p><code>msg.payload</code>に格納したHTMLドキュメントからCSSセレクタを使用して要素を取り出します。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">文字列</span></dt>
|
||||
<dd>要素を取り出すHTML文字列</dd>
|
||||
<dt class="optional">select <span class="property-type">文字列</span></dt>
|
||||
<dd>編集パネルでセレクタを指定していない場合、メッセージのプロパティとして設定できます</dd>
|
||||
</dl>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">配列 | 文字列</span></dt>
|
||||
<dd>結果は、ペイロードにマッチした要素の配列を含む単一メッセージ、もしくは、マッチした要素毎のメッセージのいずれかを選択できます。複数メッセージを送信する場合、メッセージには<code>parts</code>を設定します</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>このノードはCSSおよびjQueryセレクタの組み合わせをサポートします。利用可能な構文の詳細については<a href="https://github.com/fb55/CSSselect#user-content-supported-selectors" target="_blank">css-select documentation</a>を参照してください。</p>
|
||||
</script>
|
||||
38
nodes/core/locales/ja/parsers/70-JSON.html
Normal file
38
nodes/core/locales/ja/parsers/70-JSON.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="json">
|
||||
<p>JSON文字列とJavaScriptオブジェクトとの間で相互変換を行います。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">オブジェクト | 文字列</span></dt>
|
||||
<dd>JavaScriptオブジェクトもしくはJSON文字列</dd>
|
||||
</dl>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">オブジェクト | 文字列</span></dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>入力が文字列の場合、JSONとして解釈し、JavaScriptオブジェクトに変換します。</li>
|
||||
<li>入力がJavaScriptオブジェクトの場合、JSON文字列に変換します。JSON文字列は整形することも可能です。</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>デフォルトの変換対象は<code>msg.payload</code>ですが、他のメッセージプロパティを変換対象とすることも可能です。</p>
|
||||
<p>双方向の変換を自動選択するのではなく、特定の変換のみ行うように設定できます。この機能は、例えば、<code>HTTP In</code>ノードに対するリクエストがcontent-typeを正しく設定していない場合であっても、JSONノードによる変換結果がJavaScriptオブジェクトであることを保証するために利用します。</p>
|
||||
<p>JSON文字列への変換が指定されている場合、受信した文字列に対してさらなるチェックは行いません。すなわち、文字列がJSONとして正しいかどうかの検査や、整形オプションを指定していたとしても整形処理を実施しません。</p>
|
||||
</script>
|
||||
49
nodes/core/locales/ja/parsers/70-XML.html
Normal file
49
nodes/core/locales/ja/parsers/70-XML.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="xml">
|
||||
<p>XML文字列とJavaScriptオブジェクトとの間で相互変換を行います。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">オブジェクト | 文字列</span></dt>
|
||||
<dd>JavaScriptオブジェクトもしくはXML文字列</dd>
|
||||
</dl>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">オブジェクト | 文字列</span></dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>入力が文字列の場合、XMLとして解釈し、JavaScriptオブジェクトに変換します。</li>
|
||||
<li>入力がJavaScriptオブジェクトの場合、XML文字列に変換します。</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="optional">options <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>内部で用いているXMLへの変換ライブラリに対してオプションを渡すことができます。詳しくは<a href="https://github.com/Leonidas-from-XIV/node-xml2js/blob/master/README.md#options" target="_blank">the xml2js docs</a>を参照してください。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>XMLとオブジェクトの間での変換を行う場合、デフォルトでは、XML属性は<code>$</code>という名称のプロパティに追加します。
|
||||
テキストの内容は<code>_</code>という名前のプロパティに追加します。これらのプロパティ名はノードの設定で変更できます。</p>
|
||||
<p>例として以下のXMLの変換結果を示します。</p>
|
||||
<pre><p class="tag">Hello World</p></pre>
|
||||
<pre>{
|
||||
"p": {
|
||||
"$": {
|
||||
"class": "tag"
|
||||
},
|
||||
"_": "Hello World"
|
||||
}
|
||||
}</pre>
|
||||
</script>
|
||||
34
nodes/core/locales/ja/parsers/70-YAML.html
Normal file
34
nodes/core/locales/ja/parsers/70-YAML.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="yaml">
|
||||
<p>YAML形式の文字列とJavaScriptオブジェクトの間で相互変換を行います。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">オブジェクト | 文字列</span></dt>
|
||||
<dd>JavaScriptオブジェクトもしくはYAML形式文字列</dd>
|
||||
</dl>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">オブジェクト | 文字列</span></dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>入力がYAML形式の文字列の場合、JavaScriptオブジェクトに変換します。</li>
|
||||
<li>入力がJavaScriptオブジェクトの場合、YAML形式の文字列に変換します。</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</script>
|
||||
25
nodes/core/locales/ja/storage/28-tail.html
Normal file
25
nodes/core/locales/ja/storage/28-tail.html
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="tail">
|
||||
<p>設定したファイルの末尾を出力(追加されたデータを監視)します。(Linux/Macのみ)</p>
|
||||
<p>このノードは<b>tail -F</b>コマンドを内部で利用しているため、Windowsファイルシステムでは動作しません。</p>
|
||||
<h3>出力</h3>
|
||||
<ul>
|
||||
<li>(UTF-8形式の)テキストファイルは文字列を返却。</li>
|
||||
<li>バイナルファイルはバッファオブジェクトを返却。</li>
|
||||
</ul>
|
||||
</script>
|
||||
55
nodes/core/locales/ja/storage/50-file.html
Normal file
55
nodes/core/locales/ja/storage/50-file.html
Normal file
@@ -0,0 +1,55 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="file">
|
||||
<p><code>msg.payload</code>をファイルに書き出します。書き出しは、ファイルの最後に追記もしくは既存の内容の置き換えを選択できます。この他、ファイルの削除を行うことも可能です。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt class="optional">filename <span class="property-type">文字列</span></dt>
|
||||
<dd>対象ファイル名をノードに設定していない場合、このプロパティでファイルを指定できます</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>入力メッセージのペイロードをファイルの最後に追記します。改行(\n)を各データの最後に追加することもできます。</p>
|
||||
<p><code>msg.filename</code>を使う場合、書き込みを行う毎にファイルをクローズします。より良い性能を得るためにはファイル名をノードに設定してください。</p>
|
||||
<p>追記を行う代わりに、ファイル全体を上書きするように設定することもできます。例えば、画像のようなバイナリデータをファイルに書き出す場合は、このオプションを指定し、改行を追記するオプションを指定しないようにします。</p>
|
||||
<p>この他、ファイルの削除を行うことも可能です。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="file in">
|
||||
<p>ファイルの内容を文字列もしくはバイナリバッファとして読み出します。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt class="optional">filename <span class="property-type">文字列</span></dt>
|
||||
<dd>読み出し対象のファイル名をノードに設定していない場合、このプロパティでファイルを指定できます</dd>
|
||||
</dl>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">文字列 | バッファ</span></dt>
|
||||
<dd>ファイルの内容を文字列もしくはバッファで表現します</dd>
|
||||
<dt class="optional">filename <span class="property-type">文字列</span></dt>
|
||||
<dd>読み出し対象のファイル名をノードに設定していない場合、このプロパティでファイルを指定します</dd>
|
||||
<dt class="optional">error <span class="property-type">オブジェクト</span></dt>
|
||||
<dd><i>非推奨</i>: 設定で有効にした場合、ファイルの読み込み時にエラーが発生すると<code>payload</code>を持たず<code>error</code>プロパティにエラーの詳細情報を設定したメッセージを送信します。この動作モードは非推奨であり、新しいノード実装ではデフォルトでは無効としています。詳細については、以下を参照してください。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>ファイルネームは絶対パスでの指定を推奨します。絶対パスを指定しない場合は、Node-REDプロセスのワーキングディレクトリからの相対パスとして扱います。</p>
|
||||
<p>Windowsではパスの区切り文字を(例えば、<code>\\ユーザー\\名前</code>のように)エスケープする必要があります。</p>
|
||||
<p>テキストファイルの場合、行毎に分割して各々メッセージを送信することができます。また、バイナリファイルの場合、小さな塊のバッファに分割して送信できます。バッファの分割単位はオペレーティングシステム依存ですが、一般に64k(Linux/Mac)もしくは41k(Windows)です。</p>
|
||||
<p>複数のメッセージに分割する場合、各メッセージには<code>parts</code>プロパティが設定され、メッセージ列を構成します。</p>
|
||||
<h4>旧式のエラー処理</h4>
|
||||
<p>Node-RED 0.17より前の版では、ファイルの読み込み時にエラーが発生すると<code>payload</code>を持たず<code>error</code>プロパティにエラーの詳細情報を設定したメッセージを送信します。この動作モードは非推奨であり、新しいノード実装ではデフォルトでは無効としています。ノードの設定により、必要に応じてこのモードを有効にできます。</p>
|
||||
<p>エラーはcatchノードで補足して処理することを推奨します。</p>
|
||||
</script>
|
||||
@@ -5,7 +5,8 @@
|
||||
"topic": "主题",
|
||||
"name": "名称",
|
||||
"username": "用户名",
|
||||
"password": "密码"
|
||||
"password": "密码",
|
||||
"property": "属性"
|
||||
},
|
||||
"status": {
|
||||
"connected": "已连接",
|
||||
@@ -13,7 +14,7 @@
|
||||
"disconnected": "已断开",
|
||||
"connecting": "连接中",
|
||||
"error": "错误",
|
||||
"ok": "确认"
|
||||
"ok": "确定"
|
||||
},
|
||||
"notification": {
|
||||
"error": "<strong>错误</strong>: __message__",
|
||||
@@ -37,17 +38,17 @@
|
||||
"repeat": "重复"
|
||||
},
|
||||
"timestamp": "时间戳",
|
||||
"none": "空白",
|
||||
"interval": "间隔",
|
||||
"interval-time": "特定时间内间隔",
|
||||
"time": "特定时间",
|
||||
"none": "无",
|
||||
"interval": "周期性执行",
|
||||
"interval-time": "指定时间段周期性执行",
|
||||
"time": "指定时间",
|
||||
"seconds": "秒",
|
||||
"minutes": "分钟",
|
||||
"hours": "小时",
|
||||
"between": "介于",
|
||||
"previous": "之前数值",
|
||||
"at": "在",
|
||||
"and": "之间",
|
||||
"and": "至",
|
||||
"every": "每隔",
|
||||
"days": [
|
||||
"星期一",
|
||||
@@ -59,18 +60,20 @@
|
||||
"星期天"
|
||||
],
|
||||
"on": "在",
|
||||
"onstart": "运行时注入?",
|
||||
"tip": "<b>注意:</b> \"特定时间内间隔\" 和 \"特定时间\" 会使用cron系统.<br/> 详情查看信息页.",
|
||||
"onstart": "立刻执行于",
|
||||
"onceDelay": "秒后, 此后",
|
||||
"tip": "<b>注意:</b> \"指定时间段周期性执行\" 和 \"指定时间\" 会使用cron系统.<br/> 详情查看信息页.",
|
||||
"success": "成功注入: __label__",
|
||||
"errors": {
|
||||
"failed": "注入失败, 请查看日志"
|
||||
"failed": "注入失败, 请查看日志",
|
||||
"toolong": "周期过长"
|
||||
}
|
||||
},
|
||||
"catch": {
|
||||
"catch": "检测异常",
|
||||
"catchNodes": "检测到 (__number__)",
|
||||
"catch": "监测所有节点",
|
||||
"catchNodes": "监测__number__个节点",
|
||||
"label": {
|
||||
"source": "检测错误来自",
|
||||
"source": "监测范围",
|
||||
"node": "节点",
|
||||
"type": "类型",
|
||||
"selectAll": "全选",
|
||||
@@ -79,14 +82,14 @@
|
||||
},
|
||||
"scope": {
|
||||
"all": "所有节点",
|
||||
"selected": "已选节点"
|
||||
"selected": "指定节点"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"status": "状态 (所有)",
|
||||
"statusNodes": "状态显示 (__number__)",
|
||||
"status": "报告所有节点状态",
|
||||
"statusNodes": "报告__number__个节点状态",
|
||||
"label": {
|
||||
"source": "状态报告来自",
|
||||
"source": "报告状态范围",
|
||||
"node": "节点",
|
||||
"type": "类型",
|
||||
"selectAll": "全选",
|
||||
@@ -95,7 +98,7 @@
|
||||
},
|
||||
"scope": {
|
||||
"all": "所有节点",
|
||||
"selected": "已选节点"
|
||||
"selected": "指定节点"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
@@ -104,7 +107,11 @@
|
||||
"msgobj": "完整信息",
|
||||
"to": "目标",
|
||||
"debtab": "调试窗口",
|
||||
"tabcon": "调试窗口及终端控制台",
|
||||
"tabcon": "调试窗口及Console",
|
||||
"toSidebar": "调试窗口",
|
||||
"toConsole": "Console",
|
||||
"toStatus": "节点状态 (32位字符)",
|
||||
"severity": "级别",
|
||||
"notification": {
|
||||
"activated": "成功激活: __label__",
|
||||
"deactivated": "成功取消: __label__"
|
||||
@@ -114,21 +121,21 @@
|
||||
"name": "名称",
|
||||
"filterAll": "所有节点",
|
||||
"filterSelected": "已选节点",
|
||||
"filterCurrent": "目前流程",
|
||||
"filterCurrent": "当前流程",
|
||||
"debugNodes": "调试节点",
|
||||
"clearLog": "清理日志",
|
||||
"clearLog": "清空日志",
|
||||
"openWindow": "在新窗口打开"
|
||||
},
|
||||
"messageMenu": {
|
||||
"collapseAll": "折叠所有路径",
|
||||
"clearPinned": "清理已固定路径",
|
||||
"clearPinned": "清空已固定路径",
|
||||
"filterNode": "过滤此节点",
|
||||
"clearFilter": "清除已设过滤"
|
||||
"clearFilter": "清空过滤条件"
|
||||
}
|
||||
},
|
||||
"link": {
|
||||
"linkIn": "连接入口",
|
||||
"linkOut": "连接出口",
|
||||
"linkIn": "输入",
|
||||
"linkOut": "输出",
|
||||
"label": {
|
||||
"event": "事件名称",
|
||||
"node": "节点名称",
|
||||
@@ -144,16 +151,18 @@
|
||||
"upload": "上传",
|
||||
"cert": "证书",
|
||||
"key": "私钥",
|
||||
"passphrase": "密码",
|
||||
"ca": "CA证书",
|
||||
"verify-server-cert":"验证服务器证书"
|
||||
},
|
||||
"placeholder": {
|
||||
"cert":"证书路径 (PEM 格式)",
|
||||
"key":"私匙路径 (PEM 格式)",
|
||||
"ca":"CA证书路径 (PEM 格式)"
|
||||
"key":"私钥路径 (PEM 格式)",
|
||||
"ca":"CA证书路径 (PEM 格式)",
|
||||
"passphrase":"私钥密码 (可选)"
|
||||
},
|
||||
"error": {
|
||||
"missing-file": "无证书/密匙文件提供"
|
||||
"missing-file": "未提供证书/密钥文件"
|
||||
}
|
||||
},
|
||||
"exec": {
|
||||
@@ -169,10 +178,10 @@
|
||||
"extraparams": "额外的输入参数"
|
||||
},
|
||||
"opt": {
|
||||
"exec": "当命令任务完成时 - exec 模式",
|
||||
"spawn": "当命令任务进行时 - spawn 模式"
|
||||
"exec": "当命令完成时 - exec模式",
|
||||
"spawn": "当命令进行时 - spawn模式"
|
||||
},
|
||||
"oldrc": "使用旧式输出模式 (传统模式)"
|
||||
"oldrc": "使用旧式输出 (兼容模式)"
|
||||
},
|
||||
"function": {
|
||||
"label": {
|
||||
@@ -180,7 +189,7 @@
|
||||
"outputs": "输出"
|
||||
},
|
||||
"error": {
|
||||
"inputListener":"无法在函数里面加入对‘注入’事件的监视",
|
||||
"inputListener":"无法在函数中监听对'注入'事件",
|
||||
"non-message-returned":"函数节点尝试返回类型为 __type__ 的信息"
|
||||
},
|
||||
"tip": "可从信息页面查看更多关于如何编写函数的帮助"
|
||||
@@ -194,7 +203,8 @@
|
||||
"output": "输出为",
|
||||
"mustache": "Mustache 模版",
|
||||
"plain": "纯文本",
|
||||
"json": "解析JSON",
|
||||
"json": "JSON",
|
||||
"yaml": "YAML",
|
||||
"none": "无"
|
||||
},
|
||||
"templatevalue": "This is the payload: {{payload}} !"
|
||||
@@ -204,13 +214,13 @@
|
||||
"for": "时长",
|
||||
"delaymsg": "延迟每一条信息",
|
||||
"delayfixed": "固定延迟时间",
|
||||
"delayvarmsg": "用 msg.delay 改写延迟时长",
|
||||
"delayvarmsg": "允许msg.delay复写延迟时长",
|
||||
"randomdelay": "随机延迟",
|
||||
"limitrate": "信息速度限制",
|
||||
"limitrate": "限制信息速率",
|
||||
"limitall": "所有信息",
|
||||
"limittopic": "每一个 msg.topic",
|
||||
"fairqueue": "轮流发每一个主题",
|
||||
"timedqueue": "发所有主题",
|
||||
"limittopic": "每一个msg.topic",
|
||||
"fairqueue": "依次发送每一个topic",
|
||||
"timedqueue": "发所有topic",
|
||||
"milisecs": "毫秒",
|
||||
"secs": "秒",
|
||||
"sec": "秒",
|
||||
@@ -218,10 +228,10 @@
|
||||
"min": "分",
|
||||
"hours": "小时",
|
||||
"hour": "小时",
|
||||
"days": "日",
|
||||
"day": "日",
|
||||
"days": "天",
|
||||
"day": "天",
|
||||
"between": "介于",
|
||||
"and": "和",
|
||||
"and": "至",
|
||||
"rate": "速度",
|
||||
"msgper": "信息 每",
|
||||
"dropmsg": "不传输中间信息",
|
||||
@@ -245,14 +255,14 @@
|
||||
"singular": "小时"
|
||||
},
|
||||
"day": {
|
||||
"plural" : "日",
|
||||
"singular": "日"
|
||||
"plural" : "天",
|
||||
"singular": "天"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"buffer": "缓冲超过了 1000 条信息",
|
||||
"buffer1": "缓冲超过了 10000 条信息"
|
||||
"buffer": "缓冲了超过 1000 条信息",
|
||||
"buffer1": "缓冲了超过 10000 条信息"
|
||||
}
|
||||
},
|
||||
"trigger": {
|
||||
@@ -267,9 +277,9 @@
|
||||
"latest": "最新信息对象",
|
||||
"nothing": "无"
|
||||
},
|
||||
"wait-reset": "等待至重置",
|
||||
"wait-reset": "等待被重置",
|
||||
"wait-for": "等待",
|
||||
"wait-loop": "重发每",
|
||||
"wait-loop": "周期性重发",
|
||||
"duration": {
|
||||
"ms": "毫秒",
|
||||
"s": "秒",
|
||||
@@ -279,11 +289,11 @@
|
||||
"extend": " 如有新信息,延长延迟",
|
||||
"label": {
|
||||
"trigger": "触发",
|
||||
"trigger-block": "出发并阻止",
|
||||
"trigger-loop": "重发每",
|
||||
"trigger-block": "触发并阻止",
|
||||
"trigger-loop": "周期性重发",
|
||||
"reset": "重置触发节点条件 如果:",
|
||||
"resetMessage":"msg.reset 已设置",
|
||||
"resetPayload":"msg.payload 等于",
|
||||
"resetMessage":"msg.reset已设置",
|
||||
"resetPayload":"msg.payload等于",
|
||||
"resetprompt": "可选填"
|
||||
}
|
||||
},
|
||||
@@ -292,7 +302,7 @@
|
||||
"title": "标题",
|
||||
"body": "主体"
|
||||
},
|
||||
"tip": "提示: 主题内容可以添加格式化为 <a href=\"https://help.github.com/articles/markdown-basics/\" target=\"_blank\">Github 风格 Markdown</a>"
|
||||
"tip": "提示: 主题内容可被格式化为 <a href=\"https://help.github.com/articles/markdown-basics/\" target=\"_blank\">Github风格的Markdown</a>"
|
||||
},
|
||||
"unknown": {
|
||||
"label": {
|
||||
@@ -307,24 +317,24 @@
|
||||
"qos": "QoS",
|
||||
"clientid": "客户端ID",
|
||||
"port": "端口",
|
||||
"keepalive": "存货定时器(秒)",
|
||||
"keepalive": "Keepalive计时(秒)",
|
||||
"cleansession": "使用新的会话",
|
||||
"use-tls": "使用安全连接 (SSL/TLS)",
|
||||
"tls-config":"TLS 设置",
|
||||
"verify-server-cert":"验证服务器证书",
|
||||
"compatmode": "使用旧式 MQTT 3.1 支持"
|
||||
"compatmode": "使用旧式MQTT 3.1支持"
|
||||
},
|
||||
"tabs-label": {
|
||||
"connection": "连接",
|
||||
"security": "安全",
|
||||
"will": "终结信息",
|
||||
"birth": "初始信息"
|
||||
"will": "Will信息",
|
||||
"birth": "Birth信息"
|
||||
},
|
||||
"placeholder": {
|
||||
"clientid": "留空白将会自动生成",
|
||||
"clientid": "留白则自动生成",
|
||||
"clientid-nonclean":"如非新会话,必须设置客户端ID",
|
||||
"will-topic": "留空白将禁止终止信息",
|
||||
"birth-topic": "留空白将禁止初始信息"
|
||||
"will-topic": "留白将禁止Will信息",
|
||||
"birth-topic": "留白将禁止Birth信息"
|
||||
},
|
||||
"state": {
|
||||
"connected": "已连接到服务端: __broker__",
|
||||
@@ -334,7 +344,7 @@
|
||||
"retain": "保留",
|
||||
"true": "是",
|
||||
"false": "否",
|
||||
"tip": "提示: 如果你想用msg属性来设置主题,qos 或者是否保存,请将这几个区域留空",
|
||||
"tip": "提示: 若希望通过msg属性对topic(信息), qos及retain(保留)进行设置, 则将上述项留白",
|
||||
"errors": {
|
||||
"not-defined": "主题未设置",
|
||||
"missing-config": "未设置服务端",
|
||||
@@ -344,13 +354,13 @@
|
||||
},
|
||||
"httpin": {
|
||||
"label": {
|
||||
"method": "方法",
|
||||
"method": "请求方式",
|
||||
"url": "URL",
|
||||
"doc": "文档",
|
||||
"return": "返回",
|
||||
"upload": "接受文件上传?",
|
||||
"status": "状态码",
|
||||
"headers": "头子段",
|
||||
"headers": "Header",
|
||||
"other": "其他"
|
||||
},
|
||||
"setby": "- 用 msg.method 设定 -",
|
||||
@@ -358,21 +368,21 @@
|
||||
"use-tls": "使用安全连接 (SSL/TLS) ",
|
||||
"tls-config":"TLS 设置",
|
||||
"utf8": "UTF-8 字符串",
|
||||
"binary": "二进制缓冲模块",
|
||||
"json": "解析JSON对象",
|
||||
"binary": "二进制数据",
|
||||
"json": "JSON对象",
|
||||
"tip": {
|
||||
"in": "相对URL",
|
||||
"res": "发送到此节点的消息<b>必须</b>来自 <i>http input</i> 节点",
|
||||
"res": "发送到此节点的消息<b>必须</b>来自<i>http input</i>节点",
|
||||
"req": "提示:如果JSON解析失败,则获取的字符串将按原样返回."
|
||||
},
|
||||
"httpreq": "http 请求",
|
||||
"errors": {
|
||||
"not-created": "当httpNodeRoot为否时,无法创建 http-in 节点",
|
||||
"not-created": "当httpNodeRoot为否时,无法创建http-in节点",
|
||||
"missing-path": "无路径",
|
||||
"no-response": "无响应对象",
|
||||
"json-error": "JSON 解析错误",
|
||||
"no-url": "未设定 URL",
|
||||
"deprecated-call":"__method__ 方法已弃用",
|
||||
"deprecated-call":"__method__方法已弃用",
|
||||
"invalid-transport":"非HTTP传输请求"
|
||||
},
|
||||
"status": {
|
||||
@@ -387,13 +397,14 @@
|
||||
},
|
||||
"listenon": "监听",
|
||||
"connectto": "连接",
|
||||
"payload": "发送/接受 有效载荷",
|
||||
"message": "发送/接受 完整信息",
|
||||
"sendrec": "发送/接受",
|
||||
"payload": "有效载荷",
|
||||
"message": "完整信息",
|
||||
"tip": {
|
||||
"path1": "默认情况下,<code> payload </code>将包含要发送或从Websocket接收的数据。侦听器可以配置为以JSON格式的字符串发送或接收整个消息对象.",
|
||||
"path1": "默认情况下,<code>payload</code>将包含要发送或从Websocket接收的数据。侦听器可以配置为以JSON格式的字符串发送或接收整个消息对象.",
|
||||
"path2": "这条路径将相对于 ",
|
||||
"url1": "URL 应该使用 ws:// 或者 wss:// 方案并指向现有的websocket侦听器.",
|
||||
"url2": "默认情况下,<code> payload </code>将包含要发送或从Websocket接收的数据。可以将客户端配置为以JSON格式的字符串发送或接收整个消息对象."
|
||||
"url1": "URL 应该使用ws://或者wss://方案并指向现有的websocket侦听器.",
|
||||
"url2": "默认情况下,<code>payload</code> 将包含要发送或从Websocket接收的数据。可以将客户端配置为以JSON格式的字符串发送或接收整个消息对象."
|
||||
},
|
||||
"errors": {
|
||||
"connect-error": "ws连接发生了错误: ",
|
||||
@@ -403,8 +414,8 @@
|
||||
},
|
||||
"watch": {
|
||||
"label": {
|
||||
"files": "文件(s)",
|
||||
"recursive": "递归查看文件夹"
|
||||
"files": "文件",
|
||||
"recursive": "递归所有子文件夹"
|
||||
},
|
||||
"placeholder": {
|
||||
"files": "逗号分开文件或文件夹"
|
||||
@@ -416,8 +427,8 @@
|
||||
"type": "类型",
|
||||
"output": "输出",
|
||||
"port": "端口",
|
||||
"host": "主服务器",
|
||||
"payload": "有效载荷(s)",
|
||||
"host": "主机地址",
|
||||
"payload": "的有效载荷",
|
||||
"delimited": "分隔符号",
|
||||
"close-connection": "是否在成功发送每条信息后断开连接?",
|
||||
"decode-base64": "用 Base64 解码信息?",
|
||||
@@ -429,19 +440,19 @@
|
||||
"type": {
|
||||
"listen": "监听",
|
||||
"connect": "连接",
|
||||
"reply": "回应到 TCP"
|
||||
"reply": "响应 TCP"
|
||||
},
|
||||
"output": {
|
||||
"stream": "字串流",
|
||||
"single": "单一",
|
||||
"buffer": "缓冲模块",
|
||||
"buffer": "Buffer",
|
||||
"string": "字符串",
|
||||
"base64": "Base64 字符串"
|
||||
},
|
||||
"return": {
|
||||
"timeout": "在固定时间超时后",
|
||||
"character": "当收到某个字符时",
|
||||
"number": "固定数目的字符",
|
||||
"timeout": "指定时间后",
|
||||
"character": "当收到某个字符为",
|
||||
"number": "指定字符数",
|
||||
"never": "永不 - 保持连接",
|
||||
"immed": "马上 - 不需要等待回复"
|
||||
},
|
||||
@@ -452,8 +463,8 @@
|
||||
"stopped-listening": "已停止监听端口",
|
||||
"connection-from": "连接来自 __host__:__port__",
|
||||
"connection-closed": "连接已关闭 __host__:__port__",
|
||||
"connections": "__count__ 段连接",
|
||||
"connections_plural": "__count__ 段连接"
|
||||
"connections": "__count__ 个连接",
|
||||
"connections_plural": "__count__ 个连接"
|
||||
|
||||
},
|
||||
"errors": {
|
||||
@@ -463,7 +474,7 @@
|
||||
"error": "错误: __error__",
|
||||
|
||||
"socket-error": "套接字连接错误来自 __host__:__port__",
|
||||
"no-host": "主服务器和/或者端口未设定",
|
||||
"no-host": "主机地址或端口未设定",
|
||||
"connect-timeout": "连接超时",
|
||||
"connect-fail": "连接失败"
|
||||
}
|
||||
@@ -476,23 +487,23 @@
|
||||
"output": "输出",
|
||||
"group": "组",
|
||||
"interface": "本地IP",
|
||||
"interfaceprompt": "(可选填)本地 IP 绑定到",
|
||||
"interfaceprompt": "(可选)本地 IP 绑定到",
|
||||
"send": "发送一个",
|
||||
"toport": "到端口",
|
||||
"address": "地址",
|
||||
"decode-base64": "是否解码编码为Base64的信息?"
|
||||
"decode-base64": "是否解码Base64编码的信息?"
|
||||
},
|
||||
"placeholder": {
|
||||
"interface": "(可选填)eth0 的 ip 地址",
|
||||
"address": "目的地 ip 地址"
|
||||
"interface": "(可选)eth0的IP地址",
|
||||
"address": "目标IP地址"
|
||||
},
|
||||
"udpmsgs": "udp 信息",
|
||||
"udpmsgs": "udp信息",
|
||||
"mcmsgs": "组播信息",
|
||||
"udpmsg": "udp 信息",
|
||||
"udpmsg": "udp信息",
|
||||
"bcmsg": "广播信息",
|
||||
"mcmsg": "组播信息",
|
||||
"output": {
|
||||
"buffer": "缓冲模块",
|
||||
"buffer": "Buffer",
|
||||
"string": "字符串",
|
||||
"base64": "Base64编码字符串"
|
||||
},
|
||||
@@ -503,8 +514,8 @@
|
||||
},
|
||||
"tip": {
|
||||
"in": "提示:确保您的防火墙将允许数据进入",
|
||||
"out": "提示:如果要使用<code> msg.ip </code>和<code> msg.port </code>设置,请将地址和端口留空",
|
||||
"port": "端口已在使用: "
|
||||
"out": "提示:如果要使用<code>msg.ip</code>和<code>msg.port</code>设置,请将地址和端口留空",
|
||||
"port": "正在使用端口: "
|
||||
},
|
||||
"status": {
|
||||
"listener-at": "udp 监听器正在监听 __host__:__port__",
|
||||
@@ -520,66 +531,72 @@
|
||||
"access-error": "UDP 访问错误, 你可能需要root权限才能接入1024以下的端口",
|
||||
"error": "错误: __error__",
|
||||
"bad-mcaddress": "无效的组播地址",
|
||||
"interface": "必须是需要接口的 ip 地址",
|
||||
"ip-notset": "udp: ip 地址未设定",
|
||||
"interface": "必须是指定接口的IP地址",
|
||||
"ip-notset": "udp: IP地址未设定",
|
||||
"port-notset": "udp: 端口未设定",
|
||||
"port-invalid": "udp: 无效端口号码",
|
||||
"alreadyused": "udp: 端口已经在使用"
|
||||
"alreadyused": "udp: 端口已被占用"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"label": {
|
||||
"property": "属性",
|
||||
"rule": "规矩"
|
||||
"rule": "规则",
|
||||
"repair" : "重建信息队列"
|
||||
},
|
||||
"and": "和",
|
||||
"and": "与",
|
||||
"checkall": "全选所有规则",
|
||||
"stopfirst": "接受第一条匹配信息后停止",
|
||||
"ignorecase": "忽视大小写",
|
||||
"ignorecase": "忽略大小写",
|
||||
"rules": {
|
||||
"btwn":"在之间",
|
||||
"cont":"包含",
|
||||
"regex":"匹配正则表达式",
|
||||
"true":"为真",
|
||||
"false":"为假",
|
||||
"null":"为空值",
|
||||
"nnull":"非空值",
|
||||
"null":"为空",
|
||||
"nnull":"非空",
|
||||
"head":"head",
|
||||
"tail":"tail",
|
||||
"index":"index between",
|
||||
"exp":"JSONata表达式",
|
||||
"else":"除此以外"
|
||||
},
|
||||
"errors": {
|
||||
"invalid-expr": "无效 JSONata 表达: __error__"
|
||||
"invalid-expr": "无效的JSONata表达式: __error__",
|
||||
"too-many" : "Switch节点中有太多待定信息"
|
||||
}
|
||||
},
|
||||
"change": {
|
||||
"label": {
|
||||
"rules": "规矩",
|
||||
"rule": "规矩",
|
||||
"rules": "规则",
|
||||
"rule": "规则",
|
||||
"set": "设定 __property__",
|
||||
"change": "改变 __property__",
|
||||
"change": "修改 __property__",
|
||||
"delete": "删除 __property__",
|
||||
"move": "移动 __property__",
|
||||
"changeCount": "改变: __count__ 条规矩",
|
||||
"regex": "用正则表达式"
|
||||
"changeCount": "修改: __count__条规矩",
|
||||
"regex": "使用正则表达式"
|
||||
},
|
||||
"action": {
|
||||
"set": "设定",
|
||||
"change": "更改",
|
||||
"change": "修改",
|
||||
"delete": "删除",
|
||||
"move": "转移",
|
||||
"to": "到",
|
||||
"search": "搜索",
|
||||
"replace": "更改为"
|
||||
"replace": "替代为"
|
||||
},
|
||||
"errors": {
|
||||
"invalid-from": "无效来源 ‘from’ 属性: __error__",
|
||||
"invalid-json": "无效 ‘to’ 属性",
|
||||
"invalid-expr": "无效 JSONata 表示: __error__"
|
||||
"invalid-from": "无效的'from'属性: __error__",
|
||||
"invalid-json": "无效的'to'JSON 属性",
|
||||
"invalid-expr": "无效的JSONata表达式: __error__"
|
||||
}
|
||||
},
|
||||
"range": {
|
||||
"label": {
|
||||
"action": "行为作用",
|
||||
"inputrange": "映射输入数据范围",
|
||||
"action": "操作",
|
||||
"inputrange": "映射输入数据",
|
||||
"resultrange": "至目标范围",
|
||||
"from": "从",
|
||||
"to": "到",
|
||||
@@ -591,26 +608,28 @@
|
||||
"maxout": "e.g. 255"
|
||||
},
|
||||
"scale": {
|
||||
"payload": "按比例 msg.payload",
|
||||
"payload": "按比例msg.payload",
|
||||
"limit": "按比例并设定界限至目标范围",
|
||||
"wrap": "按比例并包含在目标范围内"
|
||||
},
|
||||
"tip": "提示: 此节点仅对数字有效",
|
||||
"errors": {
|
||||
"notnumber": "不是一个数"
|
||||
"notnumber": "不是一个数字"
|
||||
}
|
||||
},
|
||||
"csv": {
|
||||
"label": {
|
||||
"columns": "列",
|
||||
"separator": "分隔符号",
|
||||
"c2o": "CSV 至对象选项",
|
||||
"o2c": "对象至 to CSV 选项",
|
||||
"separator": "分隔符",
|
||||
"c2o": "CSV至对象",
|
||||
"o2c": "对象至CSV",
|
||||
"input": "输入",
|
||||
"skip-s": "忽略前",
|
||||
"skip-e": "行",
|
||||
"firstrow": "第一行包含列名",
|
||||
"output": "输出",
|
||||
"includerow": "包含列名行",
|
||||
"newline": "新的一行"
|
||||
"newline": "换行符"
|
||||
},
|
||||
"placeholder": {
|
||||
"columns": "用逗号分割列名"
|
||||
@@ -625,8 +644,8 @@
|
||||
"other": "其他..."
|
||||
},
|
||||
"output": {
|
||||
"row": "每行包含一条信息",
|
||||
"array": "一条单独信息 [数组]"
|
||||
"row": "每行一条信息",
|
||||
"array": "仅一条信息 [数组]"
|
||||
},
|
||||
"newline": {
|
||||
"linux": "Linux (\\n)",
|
||||
@@ -634,8 +653,8 @@
|
||||
"windows": "Windows (\\r\\n)"
|
||||
},
|
||||
"errors": {
|
||||
"csv_js": "此节点仅处理 CSV 字符串或 js 对象",
|
||||
"obj_csv": "对象 -> CSV 转换未设定列模版"
|
||||
"csv_js": "此节点仅处理CSV字符串或JS对象",
|
||||
"obj_csv": "对象->CSV转换未设定列模版"
|
||||
}
|
||||
},
|
||||
"html": {
|
||||
@@ -644,13 +663,13 @@
|
||||
"output": "输出"
|
||||
},
|
||||
"output": {
|
||||
"html": "选定元素的 html 内容",
|
||||
"html": "选定元素的html内容",
|
||||
"text": "选定元素的纯文本内容",
|
||||
"attr": "选定元素的所有属性对象"
|
||||
"attr": "包含选定元素的所有属性的对象"
|
||||
},
|
||||
"format": {
|
||||
"single": "由一个单独信息包含一个数组",
|
||||
"multi": "由多条信息,每一条包含一个元素"
|
||||
"single": "一条信息 [数组]",
|
||||
"multi": "多条信息,每条一个元素"
|
||||
}
|
||||
},
|
||||
"json": {
|
||||
@@ -660,8 +679,15 @@
|
||||
"dropped-error": "转换有效负载失败"
|
||||
},
|
||||
"label": {
|
||||
"o2j": "对象至 JSON 选项",
|
||||
"pretty": "格式化 JSON 字符串"
|
||||
"o2j": "对象至JSON",
|
||||
"pretty": "格式化JSON字符串",
|
||||
"action": "操作",
|
||||
"property": "属性",
|
||||
"actions": {
|
||||
"toggle": "JSON字符串与对象互转",
|
||||
"str":"总是转为JSON字符串",
|
||||
"obj":"总是转为JS对象"
|
||||
}
|
||||
}
|
||||
},
|
||||
"yaml": {
|
||||
@@ -687,14 +713,14 @@
|
||||
"gpiopin": "GPIO",
|
||||
"selectpin": "选择引脚",
|
||||
"resistor": "电阻?",
|
||||
"readinitial": "在部署/重新启动时读取引脚的初始状态?",
|
||||
"readinitial": "在部署/重启时读取引脚的初始状态?",
|
||||
"type": "类型",
|
||||
"initpin": "初始化引脚状态?",
|
||||
"debounce": "去抖动",
|
||||
"freq": "频率",
|
||||
"button": "按钮",
|
||||
"pimouse": "Pi 鼠标",
|
||||
"pikeyboard": "Pi 键盘",
|
||||
"pimouse": "Pi鼠标",
|
||||
"pikeyboard": "Pi键盘",
|
||||
"left": "左",
|
||||
"right": "右",
|
||||
"middle": "中"
|
||||
@@ -705,21 +731,21 @@
|
||||
"pulldown": "下拉电阻"
|
||||
},
|
||||
"digout": "数字输出",
|
||||
"pwmout": "PWM 输出",
|
||||
"pwmout": "PWM输出",
|
||||
"servo": "伺服输出",
|
||||
"initpin0": "初始引脚电平 - 低 (0)",
|
||||
"initpin1": "初始引脚电平 - 高 (1)",
|
||||
"initpin0": "初始引脚电平 - 低(0)",
|
||||
"initpin1": "初始引脚电平 - 高(1)",
|
||||
"left": "左",
|
||||
"right": "右",
|
||||
"middle": "中",
|
||||
"any": "任何",
|
||||
"pinname": "引脚",
|
||||
"alreadyuse": "已经在用",
|
||||
"alreadyset": "已经设定为",
|
||||
"alreadyuse": "已被使用",
|
||||
"alreadyset": "已被设为",
|
||||
"tip": {
|
||||
"pin": "<b>引脚在使用</b>: ",
|
||||
"in": "提示: 仅接受数字输入 - 输出必须为 0 或 1.",
|
||||
"dig": "提示: 如用数字输出 - 输入必须为 0 或 1.",
|
||||
"pin": "<b>正在使用引脚</b>: ",
|
||||
"in": "提示: 仅接受数字输入 - 输出必须为0或1.",
|
||||
"dig": "提示: 如用数字输出 - 输入必须为0或1.",
|
||||
"pwm": "提示: 如用PWM输出 - 输入必须为0至100之间; 如用高频率可能会比预期占用更多CPU资源.",
|
||||
"ser": "<b>提示</b>: 如用伺服输出 - 输入必须为0至100之间. 50为中间值."
|
||||
},
|
||||
@@ -728,7 +754,7 @@
|
||||
"input": "输入",
|
||||
"pullup": "含有上拉电阻的输入",
|
||||
"pulldown": "含有下拉电阻的输入",
|
||||
"pwmout": "PWM 输出",
|
||||
"pwmout": "PWM输出",
|
||||
"servo": "伺服输出"
|
||||
},
|
||||
"status": {
|
||||
@@ -740,27 +766,27 @@
|
||||
"ignorenode": "忽略树莓派的特定节点",
|
||||
"version": "版本命令失败",
|
||||
"sawpitype": "查看Pi类型",
|
||||
"libnotfound": "找不到树莓派 RPi.GPIO python库",
|
||||
"alreadyset": "GPIO 引脚 __pin__ 已经被设定为类型: __type__",
|
||||
"invalidpin": "无效 GPIO 引脚",
|
||||
"libnotfound": "找不到树莓派RPi.GPIO的python库",
|
||||
"alreadyset": "GPIO引脚 __pin__ 已经被设定为类型: __type__",
|
||||
"invalidpin": "无效GPIO引脚",
|
||||
"invalidinput": "无效输入",
|
||||
"needtobeexecutable": "__command__ 需要为可运行命令",
|
||||
"mustbeexecutable": "nrgpio 需要为可运行",
|
||||
"commandnotfound": "nrgpio 命令不存在",
|
||||
"commandnotexecutable": "nrgpio 命令无法运行",
|
||||
"needtobeexecutable": "__command__须为可运行命令",
|
||||
"mustbeexecutable": "nrgpio须为可运行",
|
||||
"commandnotfound": "nrgpio命令不存在",
|
||||
"commandnotexecutable": "nrgpio命令不可运行",
|
||||
"error": "错误: __error__",
|
||||
"pythoncommandnotfound": "nrpgio python 命令不运行"
|
||||
"pythoncommandnotfound": "nrpgio python命令未处于运行状态"
|
||||
}
|
||||
},
|
||||
"tail": {
|
||||
"label": {
|
||||
"filename": "文件名",
|
||||
"type": "文件类型",
|
||||
"splitlines": "拆分线 \\n?"
|
||||
"splitlines": "以\\n来拆分行?"
|
||||
},
|
||||
"action": {
|
||||
"text": "文本 - 返回字符串",
|
||||
"binary": "二进制 - 返回缓冲区"
|
||||
"binary": "二进制 - 返回Buffer"
|
||||
},
|
||||
"errors": {
|
||||
"windowsnotsupport": "Windows目前不支持."
|
||||
@@ -770,7 +796,7 @@
|
||||
"label": {
|
||||
"filename": "文件名",
|
||||
"action": "行为",
|
||||
"addnewline": "向每个有效载荷添加换行符(\\ n)?",
|
||||
"addnewline": "向每个有效载荷添加换行符(\\n)?",
|
||||
"createdir": "创建目录(如果不存在)?",
|
||||
"outputas": "输出",
|
||||
"breakchunks": "分拆成块",
|
||||
@@ -781,14 +807,14 @@
|
||||
},
|
||||
"action": {
|
||||
"append": "追加至文件",
|
||||
"overwrite": "改写文件",
|
||||
"overwrite": "复写文件",
|
||||
"delete": "删除文件"
|
||||
},
|
||||
"output": {
|
||||
"utf8": "一条单独 utf8 字符串",
|
||||
"buffer": "一条单独缓冲区对象",
|
||||
"utf8": "一个utf8字符串",
|
||||
"buffer": "一个Buffer对象",
|
||||
"lines": "每行一条信息",
|
||||
"stream": "缓冲区流"
|
||||
"stream": "一个Buffer流"
|
||||
},
|
||||
"status": {
|
||||
"wrotefile": "写入至文件: __file__",
|
||||
@@ -806,41 +832,99 @@
|
||||
"tip": "提示: 文件名应该是绝对路径,否则它将相对于Node-RED进程的工作目录。"
|
||||
},
|
||||
"split": {
|
||||
"intro":"分裂 <code>msg.payload</code> 基于类型:",
|
||||
"intro":"基于以下类型拆分<code>msg.payload</code>:",
|
||||
"object":"<b>对象</b>",
|
||||
"objectSend":"发送每个键/值对的消息",
|
||||
"strBuff":"<b>字符串</b> / <b>缓冲区</b>",
|
||||
"objectSend":"每个键值对作为单个消息发送",
|
||||
"strBuff":"<b>字符串</b> / <b>Buffer</b>",
|
||||
"array":"<b>数组</b>",
|
||||
"splitUsing":"拆分使用",
|
||||
"splitLength":"固定长度",
|
||||
"stream":"处理为消息流",
|
||||
"stream":"作为消息流处理",
|
||||
"addname":" 复制键到 "
|
||||
},
|
||||
"join":{
|
||||
"mode":{
|
||||
"mode":"模式",
|
||||
"auto":"自动",
|
||||
"merge":"合并序列",
|
||||
"reduce":"缩减序列",
|
||||
"custom":"手动"
|
||||
},
|
||||
"combine":"结合每一个",
|
||||
"create":"创建输出",
|
||||
"combine":"合并每个",
|
||||
"create":"输出为",
|
||||
"type":{
|
||||
"string":"字符串",
|
||||
"array":"数组",
|
||||
"buffer":"缓冲区",
|
||||
"object":"键/值对象",
|
||||
"buffer":"Buffer",
|
||||
"object":"键值对对象",
|
||||
"merged":"合并对象"
|
||||
},
|
||||
"using":"使用数值",
|
||||
"key":"当作键",
|
||||
"using":"使用此值",
|
||||
"key":"作为键",
|
||||
"joinedUsing":"合并符号",
|
||||
"send":"发送信息:",
|
||||
"afterCount":"当达到一定数目的信息部件时",
|
||||
"count":"数目",
|
||||
"afterCount":"达到一定数量的信息时",
|
||||
"count":"数量",
|
||||
"subsequent":"和每个后续的消息",
|
||||
"afterTimeout":"第一条消息的超时后",
|
||||
"afterTimeout":"第一条消息的若干时间后",
|
||||
"seconds":"秒",
|
||||
"complete":"在使用<code> msg.complete </ code>属性设置的消息后",
|
||||
"tip":"此模式假定此节点与 <i>split</i> 或者接收到的消息将具有正确配置的 <code>msg.parts</code> 属性."
|
||||
"complete":"在收到存在<code>msg.complete</code>的消息后",
|
||||
"tip":"此模式假定此节点与<i>split</i>相连, 或者接收到的消息有正确配置的<code>msg.parts</code>属性.",
|
||||
"too-many" : "join节点中有太多待定信息",
|
||||
"merge": {
|
||||
"topics-label":"合并主题",
|
||||
"topics":"主题",
|
||||
"topic" : "主题",
|
||||
"on-change":"当收到一个新主题时发送已合并信息"
|
||||
},
|
||||
"reduce": {
|
||||
"exp": "Reduce表达式",
|
||||
"exp-value": "exp",
|
||||
"init": "初始值",
|
||||
"right": "反向求值(从后往前)",
|
||||
"fixup": "Fix-up exp"
|
||||
},
|
||||
"errors": {
|
||||
"invalid-expr": "无效的JSONata表达式: __error__"
|
||||
}
|
||||
},
|
||||
"sort" : {
|
||||
"target" : "排序属性",
|
||||
"seq" : "信息队列",
|
||||
"key" : "键值",
|
||||
"elem" : "元素值",
|
||||
"order" : "顺序",
|
||||
"ascending" : "升序",
|
||||
"descending" : "降序",
|
||||
"as-number" : "作为数值",
|
||||
"invalid-exp" : "sort节点中存在无效的JSONata表达式",
|
||||
"too-many" : "sort节点中有太多待定信息",
|
||||
"clear" : "清空sort节点中的待定信息"
|
||||
},
|
||||
"batch" : {
|
||||
"mode": {
|
||||
"label" : "模式",
|
||||
"num-msgs" : "按指定数量分组",
|
||||
"interval" : "按时间间隔分组",
|
||||
"concat" : "按主题分组"
|
||||
},
|
||||
"count": {
|
||||
"label" : "分组数量",
|
||||
"overlap" : "队末队首重叠数量",
|
||||
"count" : "数量",
|
||||
"invalid" : "无效的分组数量或重叠数量"
|
||||
},
|
||||
"interval": {
|
||||
"label" : "时间间隔",
|
||||
"seconds" : "秒",
|
||||
"empty" : "无数据到达时发送空信息"
|
||||
},
|
||||
"concat": {
|
||||
"topics-label": "主题",
|
||||
"topic" : "主题"
|
||||
},
|
||||
"too-many" : "batch节点中有太多待定信息",
|
||||
"unexpected" : "未知模式",
|
||||
"no-parts" : "信息中没有parts属性"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
that are part of a sequence.</p>
|
||||
<p>The <b>recreate message sequences</b> option can be enabled to generate new message sequences
|
||||
for each rule that matches. In this mode, the node will buffer the entire incoming
|
||||
sequence before sending the new sequences on. The runtime setting `nodeMessageBufferMaxLength`
|
||||
sequence before sending the new sequences on. The runtime setting <code>nodeMessageBufferMaxLength</code>
|
||||
can be used to limit how many messages nodes will buffer.</p>
|
||||
</script>
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
},
|
||||
icon: "switch.png",
|
||||
label: function() {
|
||||
return this.name||"switch";
|
||||
return this.name||this._("swicth.switch");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
@@ -199,7 +199,7 @@
|
||||
rule.t = 'eq';
|
||||
}
|
||||
if (!opt.hasOwnProperty('i')) {
|
||||
opt._i = Math.floor((0x99999-0x10000)*Math.random()).toString(16);
|
||||
opt._i = Math.floor((0x99999-0x10000)*Math.random()).toString();
|
||||
}
|
||||
container.css({
|
||||
overflow: 'hidden',
|
||||
|
||||
@@ -76,7 +76,8 @@
|
||||
outputs: 1,
|
||||
icon: "range.png",
|
||||
label: function() {
|
||||
return this.name || "range";
|
||||
if (this.minout !== "" && this.maxout !== "") { return this.name||this.minout + " - " + this.maxout; }
|
||||
else { return this.name||this._("range.range"); }
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name ? "node_label_italic" : "";
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
outputs:1,
|
||||
icon: "split.png",
|
||||
label: function() {
|
||||
return this.name||"split";
|
||||
return this.name||this._("split.split");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
@@ -337,7 +337,7 @@
|
||||
</p>
|
||||
<h4>Storing messages</h4>
|
||||
<p>This node will buffer messages internally in order to work across sequences. The
|
||||
runtime setting `nodeMessageBufferMaxLength` can be used to limit how many messages nodes
|
||||
runtime setting <code>nodeMessageBufferMaxLength</code> can be used to limit how many messages nodes
|
||||
will buffer.</p>
|
||||
</script>
|
||||
|
||||
@@ -367,7 +367,7 @@
|
||||
outputs:1,
|
||||
icon: "join.png",
|
||||
label: function() {
|
||||
return this.name||"join";
|
||||
return this.name||this._("join.join");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
outputs:1,
|
||||
icon: "sort.png",
|
||||
label: function() {
|
||||
return this.name || "sort";
|
||||
return this.name||this._("sort.sort");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name ? "node_label_italic" : "";
|
||||
|
||||
@@ -85,12 +85,11 @@
|
||||
must have a <code>msg.topic</code> property and a <code>msg.parts</code> property
|
||||
identifying its sequence. The node is configured with a list of <code>topic</code>
|
||||
values to identify the order sequences are concatenated.
|
||||
</dd>
|
||||
</dd>
|
||||
</dl>
|
||||
<h4>Storing messages</h4>
|
||||
<p>This node will buffer messages internally in order to work across sequences. The
|
||||
runtime setting `nodeMessageBufferMaxLength` can be used to limit how many messages nodes
|
||||
runtime setting <code>nodeMessageBufferMaxLength</code> can be used to limit how many messages nodes
|
||||
will buffer.</p>
|
||||
</script>
|
||||
|
||||
@@ -111,7 +110,7 @@
|
||||
outputs:1,
|
||||
icon: "batch.png",
|
||||
label: function() {
|
||||
return this.name || "batch";
|
||||
return this.name||this._("batch.batch");;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name ? "node_label_italic" : "";
|
||||
|
||||
@@ -116,7 +116,7 @@ module.exports = function(RED) {
|
||||
for (var topic of topics) {
|
||||
remove_topic(pending, topic);
|
||||
}
|
||||
send_msgs(node, msgs, false);
|
||||
send_msgs(node, msgs, true);
|
||||
node.pending_count -= msgs.length;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
color:"#DEBD5C",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
property: {value:"payload"},
|
||||
tag: {value:""},
|
||||
ret: {value:"html"},
|
||||
as: {value:"single"}
|
||||
@@ -70,6 +71,9 @@
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$("#node-input-property").typedInput({default:'msg',types:['msg']});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
outputs:1,
|
||||
icon: "file.png",
|
||||
label: function() {
|
||||
return this.name||this.filename||"tail";
|
||||
return this.name||this.filename||this._("tail.tail");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "0.18.1",
|
||||
"version": "0.18.4",
|
||||
"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.1.*",
|
||||
"node-red-node-rbe": "0.2.*",
|
||||
"node-red-node-twitter": "0.1.*",
|
||||
"nopt": "4.0.1",
|
||||
"oauth2orize": "1.11.0",
|
||||
|
||||
26
red.js
26
red.js
@@ -31,8 +31,10 @@ var app = express();
|
||||
|
||||
var settingsFile;
|
||||
var flowFile;
|
||||
var readonly;
|
||||
|
||||
var knownOpts = {
|
||||
"credentialSecret": String,
|
||||
"help": Boolean,
|
||||
"port": Number,
|
||||
"settings": [path],
|
||||
@@ -41,6 +43,7 @@ var knownOpts = {
|
||||
"verbose": Boolean
|
||||
};
|
||||
var shortHands = {
|
||||
"k":["--credentialSecret"],
|
||||
"?":["--help"],
|
||||
"p":["--port"],
|
||||
"s":["--settings"],
|
||||
@@ -59,9 +62,11 @@ var parsedArgs = nopt(knownOpts,shortHands,process.argv,2)
|
||||
if (parsedArgs.help) {
|
||||
console.log("Node-RED v"+RED.version());
|
||||
console.log("Usage: node-red [-v] [-?] [--settings settings.js] [--userDir DIR]");
|
||||
console.log(" [--port PORT] [--title TITLE] [flows.json]");
|
||||
console.log(" [--port PORT] [--credentialSecret SECRET_KEY]");
|
||||
console.log(" [--title TITLE] [flows.json]");
|
||||
console.log("");
|
||||
console.log("Options:");
|
||||
console.log(" -k, --credentialSecret SECRET_KEY key to unlock credentials file");
|
||||
console.log(" -p, --port PORT port to listen on");
|
||||
console.log(" -s, --settings FILE use specified settings file");
|
||||
console.log(" --title TITLE process window title");
|
||||
@@ -101,8 +106,15 @@ if (parsedArgs.settings) {
|
||||
var settingsStat = fs.statSync(defaultSettings);
|
||||
if (settingsStat.mtime.getTime() <= settingsStat.ctime.getTime()) {
|
||||
// Default settings file has not been modified - safe to copy
|
||||
fs.copySync(defaultSettings,userSettingsFile);
|
||||
settingsFile = userSettingsFile;
|
||||
try {
|
||||
fs.copySync(defaultSettings,userSettingsFile);
|
||||
settingsFile = userSettingsFile;
|
||||
}
|
||||
catch (err) {
|
||||
console.log("Can't copy settings file.");
|
||||
settingsFile = defaultSettings;
|
||||
readonly = true;
|
||||
}
|
||||
} else {
|
||||
// Use default settings.js as it has been modified
|
||||
settingsFile = defaultSettings;
|
||||
@@ -114,6 +126,10 @@ if (parsedArgs.settings) {
|
||||
try {
|
||||
var settings = require(settingsFile);
|
||||
settings.settingsFile = settingsFile;
|
||||
if (readonly === true) {
|
||||
console.log("Setting to read Only mode.");
|
||||
settings.readOnly = true;
|
||||
}
|
||||
} catch(err) {
|
||||
console.log("Error loading settings file: "+settingsFile)
|
||||
if (err.code == 'MODULE_NOT_FOUND') {
|
||||
@@ -126,6 +142,10 @@ try {
|
||||
process.exit();
|
||||
}
|
||||
|
||||
if (parsedArgs.credentialSecret) {
|
||||
settings.credentialSecret = parsedArgs.credentialSecret;
|
||||
}
|
||||
|
||||
if (parsedArgs.verbose) {
|
||||
settings.verbose = true;
|
||||
}
|
||||
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
var log;
|
||||
var redNodes;
|
||||
var settings;
|
||||
|
||||
module.exports = {
|
||||
init: function(runtime) {
|
||||
settings = runtime.settings;
|
||||
redNodes = runtime.nodes;
|
||||
log = runtime.log;
|
||||
},
|
||||
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
var log;
|
||||
var redNodes;
|
||||
var settings;
|
||||
|
||||
module.exports = {
|
||||
init: function(runtime) {
|
||||
settings = runtime.settings;
|
||||
redNodes = runtime.nodes;
|
||||
log = runtime.log;
|
||||
},
|
||||
@@ -80,7 +78,7 @@ module.exports = {
|
||||
}).catch(function(err) {
|
||||
log.warn(log._("api.flows.error-save",{message:err.message}));
|
||||
log.warn(err.stack);
|
||||
res.status(500).json({error:"unexpected_error", message:err.message});
|
||||
res.status(500).json({error:err.code || "unexpected_error", message:err.message});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,17 +18,13 @@ var when = require("when");
|
||||
var apiUtils = require("../util");
|
||||
var redNodes;
|
||||
var log;
|
||||
var i18n;
|
||||
var settings;
|
||||
var events;
|
||||
|
||||
module.exports = {
|
||||
init: function(runtime) {
|
||||
redNodes = runtime.nodes;
|
||||
log = runtime.log;
|
||||
i18n = runtime.i18n;
|
||||
settings = runtime.settings;
|
||||
events = runtime.events;
|
||||
},
|
||||
getAll: function(req,res) {
|
||||
if (req.get("accept") == "application/json") {
|
||||
@@ -72,11 +68,6 @@ module.exports = {
|
||||
return;
|
||||
}
|
||||
promise.then(function(info) {
|
||||
if (isUpgrade) {
|
||||
events.emit("runtime-event",{id:"node/upgraded",retain:false,payload:{module:node.module,version:node.version}});
|
||||
} else {
|
||||
events.emit("runtime-event",{id:"node/added",retain:false,payload:info.nodes});
|
||||
}
|
||||
if (node.module) {
|
||||
log.audit({event: "nodes.install",module:node.module,version:node.version},req);
|
||||
res.json(info);
|
||||
@@ -114,7 +105,6 @@ module.exports = {
|
||||
}
|
||||
|
||||
promise.then(function(list) {
|
||||
events.emit("runtime-event",{id:"node/removed",retain:false,payload:list});
|
||||
log.audit({event: "nodes.remove",module:mod},req);
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
@@ -248,21 +238,6 @@ function putNode(node, enabled) {
|
||||
} else {
|
||||
promise = redNodes.disableNode(node.id);
|
||||
}
|
||||
|
||||
return promise.then(function(info) {
|
||||
if (info.enabled === enabled && !info.err) {
|
||||
events.emit("runtime-event",{id:"node/"+(enabled?"enabled":"disabled"),retain:false,payload:info});
|
||||
log.info(" "+log._("api.nodes."+(enabled?"enabled":"disabled")));
|
||||
for (var i=0;i<info.types.length;i++) {
|
||||
log.info(" - "+info.types[i]);
|
||||
}
|
||||
} else if (enabled && info.err) {
|
||||
log.warn(log._("api.nodes.error-enable"));
|
||||
log.warn(" - "+info.name+" : "+info.err);
|
||||
}
|
||||
return info;
|
||||
});
|
||||
}
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
@@ -93,7 +93,8 @@
|
||||
"credentials_load_failed": "<p>Flows stopped as the credentials could not be decrypted.</p><p>The flow credential file is encrypted, but the project's encryption key is missing or invalid.</p>",
|
||||
"missing_flow_file": "<p>Project flow file not found.</p><p>The project is not configured with a flow file.</p>",
|
||||
"project_empty": "<p>The project is empty.</p><p>Do you want to create a default set of project files?<br/>Otherwise, you will have to manually add files to the project outside of the editor.</p>",
|
||||
"project_not_found": "<p>Project '__project__' not found.</p>"
|
||||
"project_not_found": "<p>Project '__project__' not found.</p>",
|
||||
"git_merge_conflict": "<p>Automatic merging of changes failed.</p><p>Fix the unmerged conflicts then commit the results.</p>"
|
||||
},
|
||||
|
||||
"error": "<strong>Error</strong>: __message__",
|
||||
|
||||
@@ -239,7 +239,7 @@
|
||||
"managePalette": "管理面板"
|
||||
},
|
||||
"library": {
|
||||
"openLibrary": "“打开库...",
|
||||
"openLibrary": "打开库...",
|
||||
"saveToLibrary": "保存到库...",
|
||||
"typeLibrary": "__type__类型库",
|
||||
"unnamedType": "无名__type__",
|
||||
|
||||
@@ -194,5 +194,25 @@
|
||||
"$globalContext": {
|
||||
"args": "string",
|
||||
"desc": "获取全局上下文的属性。"
|
||||
},
|
||||
"$pad": {
|
||||
"args": "string, width [, char]",
|
||||
"desc": "根据需要,向字符串`string`的副本中填充文字使该字符串的字数达到`width`的绝对值并返回填充文字后的字符串。\n\n如果`width`的值为正,则向字符串`string`的右侧填充文字,如果`width`为负,则向字符串`string`的左侧填充文字。\n\n可选参数`char`用来指定填充的文字。如果未指定该参数,则填充空白文字。"
|
||||
},
|
||||
"$fromMillis": {
|
||||
"args": "number",
|
||||
"desc": "将表示从UNIX时间 (1970年1月1日 UTC/GMT的午夜)开始到现在的毫秒数的数值转换成ISO 8601形式时间戳的字符串。"
|
||||
},
|
||||
"$formatNumber": {
|
||||
"args": "number, picture [, options]",
|
||||
"desc": "将`number`转换成具有`picture`所指定的数值格式的字符串。\n\n此函数的功能与XPath F&O 3.1规格中定义的XPath/XQuery函数的fn:format-number功能相一致。参数`picture`用于指定数值的转换格式,其语法与fn:format-number中的定义一致。\n\n可选的第三参数`options`用来覆盖默认的局部环境格式,如小数点分隔符。如果指定该参数,那么该参数必须是包含name/value对的对象,并且name/value对必须符合XPath F&O 3.1规格中记述的数值格式。"
|
||||
},
|
||||
"$formatBase": {
|
||||
"args": "number [, radix]",
|
||||
"desc": "将`number`变换为以参数`radix`的值为基数形式的字符串。如果不指定`radix`的值,则默认基数为10。指定的`radix`值必须在2~36之间,否则抛出错误。"
|
||||
},
|
||||
"$toMillis": {
|
||||
"args": "timestamp",
|
||||
"desc": "将ISO 8601格式的字符串`timestamp`转换为从UNIX时间 (1970年1月1日 UTC/GMT的午夜)开始到现在的毫秒数。如果该字符串的格式不正确,则抛出错误。"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,11 @@
|
||||
|
||||
var express = require("express");
|
||||
var runtime;
|
||||
var settings;
|
||||
var needsPermission = require("../../auth").needsPermission;
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtime) {
|
||||
runtime = _runtime;
|
||||
settings = runtime.settings;
|
||||
},
|
||||
app: function() {
|
||||
var app = express();
|
||||
@@ -149,7 +147,9 @@ module.exports = {
|
||||
|
||||
// Get project status - files, commit counts, branch info
|
||||
app.get("/:id/status", needsPermission("projects.read"), function(req,res) {
|
||||
runtime.storage.projects.getStatus(req.user, req.params.id).then(function(data) {
|
||||
var includeRemote = req.query.remote;
|
||||
|
||||
runtime.storage.projects.getStatus(req.user, req.params.id, includeRemote).then(function(data) {
|
||||
if (data) {
|
||||
res.json(data);
|
||||
} else {
|
||||
@@ -248,8 +248,11 @@ module.exports = {
|
||||
res.redirect(303,req.baseUrl+"/"+projectName+"/status");
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log(err.stack);
|
||||
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
||||
if (err.code) {
|
||||
res.status(400).json({error:err.code, message: err.message});
|
||||
} else {
|
||||
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -350,8 +353,9 @@ module.exports = {
|
||||
app.post("/:id/pull/?*", needsPermission("projects.write"), function(req,res) {
|
||||
var projectName = req.params.id;
|
||||
var remoteBranchName = req.params[0];
|
||||
var setRemote = req.query.u;
|
||||
runtime.storage.projects.pull(req.user, projectName,remoteBranchName,setRemote).then(function(data) {
|
||||
var setUpstream = req.query.setUpstream;
|
||||
var allowUnrelatedHistories = req.query.allowUnrelatedHistories;
|
||||
runtime.storage.projects.pull(req.user, projectName,remoteBranchName,setUpstream,allowUnrelatedHistories).then(function(data) {
|
||||
res.status(204).end();
|
||||
})
|
||||
.catch(function(err) {
|
||||
@@ -501,6 +505,10 @@ 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) {
|
||||
|
||||
@@ -54,10 +54,11 @@ module.exports = {
|
||||
var activeProject = runtime.storage.projects.getActiveProject();
|
||||
if (activeProject) {
|
||||
safeSettings.project = activeProject;
|
||||
}
|
||||
safeSettings.files = {
|
||||
flow: runtime.storage.projects.getFlowFilename(),
|
||||
credentials: runtime.storage.projects.getCredentialsFilename()
|
||||
} else if (runtime.storage.projects.flowFileExists()) {
|
||||
safeSettings.files = {
|
||||
flow: runtime.storage.projects.getFlowFilename(),
|
||||
credentials: runtime.storage.projects.getCredentialsFilename()
|
||||
}
|
||||
}
|
||||
safeSettings.git = {
|
||||
globalUser: runtime.storage.projects.getGlobalGitUser()
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
var express = require("express");
|
||||
var os = require("os");
|
||||
var runtime;
|
||||
var settings;
|
||||
var needsPermission = require("../auth").needsPermission;
|
||||
|
||||
function getUsername(userObj) {
|
||||
@@ -31,7 +30,6 @@ function getUsername(userObj) {
|
||||
module.exports = {
|
||||
init: function(_runtime) {
|
||||
runtime = _runtime;
|
||||
settings = runtime.settings;
|
||||
},
|
||||
app: function() {
|
||||
var app = express();
|
||||
|
||||
@@ -24,8 +24,6 @@ var cors = require('cors');
|
||||
var auth = require("./auth");
|
||||
var apiUtil = require("./util");
|
||||
|
||||
var i18n;
|
||||
var log;
|
||||
var adminApp;
|
||||
var server;
|
||||
var runtime;
|
||||
@@ -35,8 +33,6 @@ function init(_server,_runtime) {
|
||||
server = _server;
|
||||
runtime = _runtime;
|
||||
var settings = runtime.settings;
|
||||
i18n = runtime.i18n;
|
||||
log = runtime.log;
|
||||
if (settings.httpAdminRoot !== false) {
|
||||
apiUtil.init(runtime);
|
||||
adminApp = express();
|
||||
|
||||
@@ -83,7 +83,8 @@
|
||||
"credentials": {
|
||||
"error":"Error loading credentials: __message__",
|
||||
"error-saving":"Error saving credentials: __message__",
|
||||
"not-registered": "Credential type '__type__' is not registered"
|
||||
"not-registered": "Credential type '__type__' is not registered",
|
||||
"system-key-warning": "\n\n---------------------------------------------------------------------\nYour flow credentials file is encrypted using a system-generated key.\n\nIf the system-generated key is lost for any reason, your credentials\nfile will not be recoverable, you will have to delete it and re-enter\nyour credentials.\n\nYou should set your own key using the 'credentialSecret' option in\nyour settings file. Node-RED will then re-encrypt your credentials\nfile using your chosen key the next time you deploy a change.\n---------------------------------------------------------------------\n"
|
||||
},
|
||||
"flows": {
|
||||
"registered-missing": "Missing type registered: __type__",
|
||||
|
||||
@@ -201,6 +201,9 @@ var api = module.exports = {
|
||||
encryptedCredentials = credentials;
|
||||
}
|
||||
log.debug("red/runtime/nodes/credentials.load : keyType="+encryptionKeyType);
|
||||
if (encryptionKeyType === 'system') {
|
||||
log.warn(log._("nodes.credentials.system-key-warning"));
|
||||
}
|
||||
return setupEncryptionPromise.then(function() {
|
||||
var clearInvalidFlag = false;
|
||||
if (credentials.hasOwnProperty("$")) {
|
||||
|
||||
@@ -104,7 +104,43 @@ function init(runtime) {
|
||||
|
||||
function disableNode(id) {
|
||||
flows.checkTypeInUse(id);
|
||||
return registry.disableNode(id);
|
||||
return registry.disableNode(id).then(function(info) {
|
||||
reportNodeStateChange(info,false);
|
||||
return info;
|
||||
});
|
||||
}
|
||||
|
||||
function enableNode(id) {
|
||||
return registry.enableNode(id).then(function(info) {
|
||||
reportNodeStateChange(info,true);
|
||||
return info;
|
||||
});
|
||||
}
|
||||
|
||||
function reportNodeStateChange(info,enabled) {
|
||||
if (info.enabled === enabled && !info.err) {
|
||||
events.emit("runtime-event",{id:"node/"+(enabled?"enabled":"disabled"),retain:false,payload:info});
|
||||
log.info(" "+log._("api.nodes."+(enabled?"enabled":"disabled")));
|
||||
for (var i=0;i<info.types.length;i++) {
|
||||
log.info(" - "+info.types[i]);
|
||||
}
|
||||
} else if (enabled && info.err) {
|
||||
log.warn(log._("api.nodes.error-enable"));
|
||||
log.warn(" - "+info.name+" : "+info.err);
|
||||
}
|
||||
}
|
||||
|
||||
function installModule(module,version) {
|
||||
var ex_module = registry.getModuleInfo(module);
|
||||
var isUpgrade = !!ex_module;
|
||||
return registry.installModule(module,version).then(function(info) {
|
||||
if (isUpgrade) {
|
||||
events.emit("runtime-event",{id:"node/upgraded",retain:false,payload:{module:module,version:version}});
|
||||
} else {
|
||||
events.emit("runtime-event",{id:"node/added",retain:false,payload:info.nodes});
|
||||
}
|
||||
return info;
|
||||
});
|
||||
}
|
||||
|
||||
function uninstallModule(module) {
|
||||
@@ -115,7 +151,10 @@ function uninstallModule(module) {
|
||||
for (var i=0;i<info.nodes.length;i++) {
|
||||
flows.checkTypeInUse(module+"/"+info.nodes[i].name);
|
||||
}
|
||||
return registry.uninstallModule(module);
|
||||
return registry.uninstallModule(module).then(function(list) {
|
||||
events.emit("runtime-event",{id:"node/removed",retain:false,payload:list});
|
||||
return list;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,10 +169,10 @@ module.exports = {
|
||||
eachNode: flows.eachNode,
|
||||
|
||||
paletteEditorEnabled: registry.paletteEditorEnabled,
|
||||
installModule: registry.installModule,
|
||||
installModule: installModule,
|
||||
uninstallModule: uninstallModule,
|
||||
|
||||
enableNode: registry.enableNode,
|
||||
enableNode: enableNode,
|
||||
disableNode: disableNode,
|
||||
|
||||
// Node type registry
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user