mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
81 Commits
Add-pfxp12
...
4.0.4
Author | SHA1 | Date | |
---|---|---|---|
|
27b54199f5 | ||
|
90ea3c15b3 | ||
|
acd500fe3d | ||
|
8988176c22 | ||
|
35f35705a5 | ||
|
a0033697ea | ||
|
49a3eded59 | ||
|
d50ccea017 | ||
|
3ef205fb33 | ||
|
b1bfba8b01 | ||
|
21832a0bd0 | ||
|
a0b4fc8372 | ||
|
3812ed5ed3 | ||
|
bdb545d6eb | ||
|
7650620a78 | ||
|
34d8b3ed5e | ||
|
e3acc49d5e | ||
|
c3da827222 | ||
|
1053fc5121 | ||
|
cec7a86b54 | ||
|
16c49306f3 | ||
|
32540dd0e6 | ||
|
a3c5b75368 | ||
|
f7a43f83e5 | ||
|
98ca0f163e | ||
|
5a3e6925e5 | ||
|
d270da74b4 | ||
|
204e0f636b | ||
|
1132d39118 | ||
|
f2227c8f65 | ||
|
55cfd6fa99 | ||
|
83b30f1c18 | ||
|
aa74d8160a | ||
|
f44868384e | ||
|
674eb36e15 | ||
|
e6882337c1 | ||
|
d48594220e | ||
|
64cdee6d36 | ||
|
a16c72b6a8 | ||
|
89839f433b | ||
|
3597759692 | ||
|
d4b001a74e | ||
|
d76b0d39cd | ||
|
92911f6714 | ||
|
380d3be819 | ||
|
6dfc5e0a41 | ||
|
d4f18c1731 | ||
|
e5a0d4094f | ||
|
163c1c5b98 | ||
|
912a30b28d | ||
|
de0546b251 | ||
|
1b375b81f3 | ||
|
b4bbae247d | ||
|
20ae4a7272 | ||
|
7f77a414ec | ||
|
2e5a3f4949 | ||
|
593726ecb8 | ||
|
9745904c5b | ||
|
8c53d95610 | ||
|
27604fef23 | ||
|
2c4dc3334d | ||
|
1ebb66f6ca | ||
|
aed9a868ab | ||
|
e6ca3af1ed | ||
|
edc01552f9 | ||
|
b4d29d4d4a | ||
|
b5785dab9c | ||
|
e67afb2611 | ||
|
f88e536ee0 | ||
|
509d609020 | ||
|
a4ec0f7959 | ||
|
884c887e0d | ||
|
e0059943df | ||
|
d11934beeb | ||
|
964271f9c7 | ||
|
97b773d257 | ||
|
b6a25518e3 | ||
|
b62c17f94b | ||
|
886fb45ad2 | ||
|
7b95e64a60 | ||
|
af42664d73 |
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18, 20, 22.4.x]
|
||||
node-version: [18, 20, 22]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
|
52
CHANGELOG.md
52
CHANGELOG.md
@@ -1,3 +1,55 @@
|
||||
#### 4.0.4: Maintenance Release
|
||||
|
||||
Editor
|
||||
|
||||
- Fix `link call` node can call out of a subflow (#4892) @GogoVega
|
||||
- Fix wrong unlock state when event is triggered after deployment (#4889) @GogoVega
|
||||
- i18n(App) update with latest language file changes (#4903) @joebordes
|
||||
- fix typo: depreciated (#4895) @dxdc
|
||||
|
||||
Runtime
|
||||
|
||||
- Update dev dependencies (#4893) @knolleary
|
||||
|
||||
Nodes
|
||||
|
||||
- MQTT: Allow msg.userProperties to have number values (#4900) @hardillb
|
||||
|
||||
#### 4.0.3: Maintenance Release
|
||||
|
||||
Editor
|
||||
|
||||
- Refresh page title after changing tab name (#4850) @kazuhitoyokoi
|
||||
- Add Japanese translations for v4.0.2 (again) (#4853) @kazuhitoyokoi
|
||||
- Stay in quick-add mode following context menu insert (#4883) @knolleary
|
||||
- Do not include Junction type in quick-add for virtual links (#4879) @knolleary
|
||||
- Multiplayer cursor tracking (#4845) @knolleary
|
||||
- Hide add-flow options when disabled via editorTheme (#4869) @knolleary
|
||||
- Fix env-var config select when multiple defined (#4872) @knolleary
|
||||
- Fix subflow outbound-link filter (#4857) @GogoVega
|
||||
- Add French translations for v4.0.2 (#4856) @GogoVega
|
||||
- Fix moving link wires (#4851) @knolleary
|
||||
- Adjust type search dialog position to prevent x-overflow (#4844) @Steve-Mcl
|
||||
- fix: modulesInUse might be undefined (#4838) @lorenz-maurer
|
||||
- Add Japanese translations for v4.0.2 (#4849) @kazuhitoyokoi
|
||||
- Fix menu to enable/disable selection when it's a group (#4828) @GogoVega
|
||||
|
||||
Runtime
|
||||
|
||||
- Update dependencies (#4874) @knolleary
|
||||
- GitHub: Add citation file to enable "Cite this repository" feature (#4861) @lobis
|
||||
- Remove use of util.log (#4875) @knolleary
|
||||
|
||||
Nodes
|
||||
|
||||
- Fix invalid property error in range node example (#4855)
|
||||
- Fix typo in flow example name (#4854) @kazuhitoyokoi
|
||||
- Move SNI, ALPN and Verify Server cert out of check (#4882) @hardillb
|
||||
- Set status of mqtt nodes to "disconnected" when deregistered from broker (#4878) @Steve-Mcl
|
||||
- MQTT: Ensure will payload is a string (#4873) @knolleary
|
||||
- Let batch node terminate "early" if msg.parts set to end of sequence (#4829) @dceejay
|
||||
- Fix unintentional Capitalisation in Split node name (#4835) @dceejay
|
||||
|
||||
#### 4.0.2: Maintenance Release
|
||||
|
||||
Editor
|
||||
|
7
CITATION.cff
Normal file
7
CITATION.cff
Normal file
@@ -0,0 +1,7 @@
|
||||
cff-version: 1.2.0
|
||||
message: "If you use this software, please cite it as below."
|
||||
title: "Node-RED"
|
||||
authors:
|
||||
- family-names: "OpenJS Foundation"
|
||||
- family-names: "Contributors"
|
||||
url: "https://nodered.org"
|
42
package.json
42
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.4",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "https://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -26,26 +26,26 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"acorn": "8.11.3",
|
||||
"acorn-walk": "8.3.2",
|
||||
"ajv": "8.14.0",
|
||||
"acorn": "8.12.1",
|
||||
"acorn-walk": "8.3.4",
|
||||
"ajv": "8.17.1",
|
||||
"async-mutex": "0.5.0",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.20.2",
|
||||
"body-parser": "1.20.3",
|
||||
"cheerio": "1.0.0-rc.10",
|
||||
"clone": "2.1.2",
|
||||
"content-type": "1.0.5",
|
||||
"cookie": "0.6.0",
|
||||
"cookie-parser": "1.4.6",
|
||||
"cookie": "0.7.2",
|
||||
"cookie-parser": "1.4.7",
|
||||
"cors": "2.8.5",
|
||||
"cronosjs": "1.7.1",
|
||||
"denque": "2.1.0",
|
||||
"express": "4.19.2",
|
||||
"express-session": "1.18.0",
|
||||
"express": "4.21.1",
|
||||
"express-session": "1.18.1",
|
||||
"form-data": "4.0.0",
|
||||
"fs-extra": "11.2.0",
|
||||
"got": "12.6.0",
|
||||
"got": "12.6.1",
|
||||
"hash-sum": "2.0.0",
|
||||
"hpagent": "1.2.0",
|
||||
"https-proxy-agent": "5.0.1",
|
||||
@@ -60,11 +60,11 @@
|
||||
"memorystore": "1.6.7",
|
||||
"mime": "3.0.0",
|
||||
"moment": "2.30.1",
|
||||
"moment-timezone": "0.5.45",
|
||||
"moment-timezone": "0.5.46",
|
||||
"mqtt": "5.7.0",
|
||||
"multer": "1.4.5-lts.1",
|
||||
"mustache": "4.2.0",
|
||||
"node-red-admin": "^4.0.0",
|
||||
"node-red-admin": "^4.0.1",
|
||||
"node-watch": "0.7.4",
|
||||
"nopt": "5.0.0",
|
||||
"oauth2orize": "1.12.0",
|
||||
@@ -72,11 +72,11 @@
|
||||
"passport": "0.7.0",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"raw-body": "2.5.2",
|
||||
"raw-body": "3.0.0",
|
||||
"rfdc": "^1.3.1",
|
||||
"semver": "7.5.4",
|
||||
"tar": "7.2.0",
|
||||
"tough-cookie": "4.1.4",
|
||||
"semver": "7.6.3",
|
||||
"tar": "7.4.3",
|
||||
"tough-cookie": "^5.0.0",
|
||||
"uglify-js": "3.17.4",
|
||||
"uuid": "9.0.1",
|
||||
"ws": "7.5.10",
|
||||
@@ -86,10 +86,10 @@
|
||||
"@node-rs/bcrypt": "1.10.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dompurify": "2.4.1",
|
||||
"dompurify": "2.5.7",
|
||||
"grunt": "1.6.1",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-cli": "~1.4.3",
|
||||
"grunt-cli": "~1.5.0",
|
||||
"grunt-concurrent": "3.0.0",
|
||||
"grunt-contrib-clean": "2.0.1",
|
||||
"grunt-contrib-compress": "2.0.0",
|
||||
@@ -100,7 +100,7 @@
|
||||
"grunt-contrib-watch": "1.1.0",
|
||||
"grunt-jsdoc": "2.4.1",
|
||||
"grunt-jsdoc-to-markdown": "6.0.0",
|
||||
"grunt-jsonlint": "2.1.3",
|
||||
"grunt-jsonlint": "3.0.0",
|
||||
"grunt-mkdir": "~1.1.0",
|
||||
"grunt-npm-command": "~0.1.2",
|
||||
"grunt-sass": "~3.1.0",
|
||||
@@ -110,11 +110,11 @@
|
||||
"jquery-i18next": "1.2.1",
|
||||
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
||||
"marked": "4.3.0",
|
||||
"mermaid": "^10.4.0",
|
||||
"mermaid": "11.3.0",
|
||||
"minami": "1.2.3",
|
||||
"mocha": "9.2.2",
|
||||
"node-red-node-test-helper": "^0.3.3",
|
||||
"nodemon": "2.0.20",
|
||||
"nodemon": "3.1.7",
|
||||
"proxy": "^1.0.2",
|
||||
"sass": "1.62.1",
|
||||
"should": "13.2.3",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-api",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.4",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,14 +16,14 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "4.0.2",
|
||||
"@node-red/editor-client": "4.0.2",
|
||||
"@node-red/util": "4.0.4",
|
||||
"@node-red/editor-client": "4.0.4",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.20.2",
|
||||
"body-parser": "1.20.3",
|
||||
"clone": "2.1.2",
|
||||
"cors": "2.8.5",
|
||||
"express-session": "1.18.0",
|
||||
"express": "4.19.2",
|
||||
"express-session": "1.18.1",
|
||||
"express": "4.21.1",
|
||||
"memorystore": "1.6.7",
|
||||
"mime": "3.0.0",
|
||||
"multer": "1.4.5-lts.1",
|
||||
|
@@ -375,7 +375,10 @@
|
||||
"flowAdded": "flow added",
|
||||
"moved": "moved",
|
||||
"movedTo": "moved to __id__",
|
||||
"movedFrom": "moved from __id__"
|
||||
"movedFrom": "moved from __id__",
|
||||
"none": "none",
|
||||
"position": "position",
|
||||
"wires": "wires"
|
||||
},
|
||||
"nodeCount": "__count__ node",
|
||||
"nodeCount_plural": "__count__ nodes",
|
||||
@@ -384,9 +387,14 @@
|
||||
"reviewChanges": "Review Changes",
|
||||
"noBinaryFileShowed": "Cannot show binary file contents",
|
||||
"viewCommitDiff": "View Commit Changes",
|
||||
"commit": "Commit",
|
||||
"compareChanges": "Compare Changes",
|
||||
"saveConflict": "Save conflict resolution",
|
||||
"conflictHeader": "<span>__resolved__</span> of <span>__unresolved__</span> conflicts resolved",
|
||||
"localChanges": "Local Changes",
|
||||
"remoteChanges": "Remote Changes",
|
||||
"useLocalChanges": "use local changes",
|
||||
"useRemoteChanges": "use remote changes",
|
||||
"commonVersionError": "Common Version doesn't contain valid JSON:",
|
||||
"oldVersionError": "Old Version doesn't contain valid JSON:",
|
||||
"newVersionError": "New Version doesn't contain valid JSON:"
|
||||
@@ -554,7 +562,9 @@
|
||||
"types": {
|
||||
"local": "Local",
|
||||
"examples": "Examples"
|
||||
}
|
||||
},
|
||||
"type": "Type",
|
||||
"name": "Name"
|
||||
},
|
||||
"palette": {
|
||||
"noInfo": "no information available",
|
||||
@@ -803,6 +813,7 @@
|
||||
"branches": "Branches",
|
||||
"noBranches": "No branches",
|
||||
"deleteConfirm": "Are you sure you want to delete the local branch '__name__'? This cannot be undone.",
|
||||
"deleteBranch": "Delete branch",
|
||||
"unmergedConfirm": "The local branch '__name__' has unmerged changes that will be lost. Are you sure you want to delete it?",
|
||||
"deleteUnmergedBranch": "Delete unmerged branch",
|
||||
"gitRemotes": "Git remotes",
|
||||
|
@@ -27,7 +27,8 @@
|
||||
"lock": "Bloquear",
|
||||
"unlock": "Desbloquear",
|
||||
"locked": "Bloqueado",
|
||||
"unlocked": "Desbloqueado"
|
||||
"unlocked": "Desbloqueado",
|
||||
"format": "Formato"
|
||||
},
|
||||
"type": {
|
||||
"string": "texto",
|
||||
@@ -303,7 +304,8 @@
|
||||
"missingType": "La entrada no es un flujo válido - elemento __index__ falta la propiedad 'type'"
|
||||
},
|
||||
"conflictNotification1": "Algunos de los nodos que estás importando ya existen en tu espacio de trabajo.",
|
||||
"conflictNotification2": "Selecciona qué nodos importar y si reemplazar los nodos existentes o importar una copia de los mismos."
|
||||
"conflictNotification2": "Selecciona qué nodos importar y si reemplazar los nodos existentes o importar una copia de los mismos.",
|
||||
"alreadyExists": "Este nodo ya existe"
|
||||
},
|
||||
"copyMessagePath": "Ruta copiada",
|
||||
"copyMessageValue": "Valor copiado",
|
||||
@@ -371,8 +373,12 @@
|
||||
"deleted": "eliminado",
|
||||
"flowDeleted": "flujo eliminado",
|
||||
"flowAdded": "flujo añadido",
|
||||
"moved": "movido",
|
||||
"movedTo": "movido a __id__",
|
||||
"movedFrom": "movido desde __id__"
|
||||
"movedFrom": "movido desde __id__",
|
||||
"none": "ninguno",
|
||||
"position": "posición",
|
||||
"wires": "conectores"
|
||||
},
|
||||
"nodeCount": "__count__ nodo",
|
||||
"nodeCount_plural": "__count__ nodos",
|
||||
@@ -381,9 +387,14 @@
|
||||
"reviewChanges": "Revisar Cambios",
|
||||
"noBinaryFileShowed": "No se puede mostrar el contenido del archivo binario",
|
||||
"viewCommitDiff": "Ver cambios de commit",
|
||||
"commit": "Commit",
|
||||
"compareChanges": "Comparar Cambios",
|
||||
"saveConflict": "Guardar resolución de conflictos",
|
||||
"conflictHeader": "<span>__resolved__</span> de <span>__unresolved__</span> conflictos resueltos",
|
||||
"localChanges": "Cambios Locales",
|
||||
"remoteChanges": "Cambios Remotos",
|
||||
"useLocalChanges": "utilizar cambios locales",
|
||||
"useRemoteChanges": "utilizar cambios remotos",
|
||||
"commonVersionError": "La versión común no contiene JSON válido:",
|
||||
"oldVersionError": "La versión anterior no contiene JSON válido:",
|
||||
"newVersionError": "La versión nueva no contiene JSON válido:"
|
||||
@@ -551,7 +562,9 @@
|
||||
"types": {
|
||||
"local": "Local",
|
||||
"examples": "Ejemplos"
|
||||
}
|
||||
},
|
||||
"type": "Tipo",
|
||||
"name": "Nombre"
|
||||
},
|
||||
"palette": {
|
||||
"noInfo": "no hay información disponible",
|
||||
@@ -613,6 +626,8 @@
|
||||
},
|
||||
"nodeCount": "__label__ nodo",
|
||||
"nodeCount_plural": "__label__ nodos",
|
||||
"pluginCount": "__count__ extensión",
|
||||
"pluginCount_plural": "__count__ extensiones",
|
||||
"moduleCount": "__count__ módulo disponible",
|
||||
"moduleCount_plural": "__count__ módulos disponibles",
|
||||
"inuse": "en uso",
|
||||
@@ -640,6 +655,7 @@
|
||||
"errors": {
|
||||
"catalogLoadFailed": "<p>La carga del catálogo de nodos ha fallado</p><p>Revise la consola del navegador para mas información</p>",
|
||||
"installFailed": "<p>Fallo al instalar: __module__</p><p>__message__</p><p>Revise el log para mas información</p>",
|
||||
"installTimeout": "<p>La instalación continúa en segundo plano.</p><p>Los nodos aparecerán en la paleta cuando finalice. Consulta el registro para obtener más información.</p>",
|
||||
"removeFailed": "<p>Fallo al eliminar: __module__</p><p>__message__</p><p>Revise el log para mas información</p>",
|
||||
"updateFailed": "<p>Fallo al actualizar: __module__</p><p>__message__</p><p>Revise el log para mas información</p>",
|
||||
"enableFailed": "<p>Fallo al activar: __module__</p><p>__message__</p><p>Revise el log para mas información</p>",
|
||||
@@ -654,6 +670,9 @@
|
||||
"body":"<p>Eliminando '__module__'</p><p>La eliminación del nodo lo desinstalará de Node-RED. Es posible que el nodo siga utilizando recursos hasta que Node-RED sea reiniciado.</p>",
|
||||
"title": "Eliminar nodos"
|
||||
},
|
||||
"removePlugin": {
|
||||
"body": "<p>Extensión __module__ eliminada. Vuelve a cargar el editor para borrar los elementos sobrantes.</p>"
|
||||
},
|
||||
"update": {
|
||||
"body":"<p>Actualizando '__module__'</p><p>La actualización del nodo requerirá un reinicio manual de Node-RED para completarse. Debe ser reiniciado manualmente.</p>",
|
||||
"title": "Actualizar nodos"
|
||||
@@ -665,7 +684,8 @@
|
||||
"review": "Abrir información del nodo",
|
||||
"install": "Instalar",
|
||||
"remove": "Eliminar",
|
||||
"update": "Actualizar"
|
||||
"update": "Actualizar",
|
||||
"understood": "Entendido"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -718,6 +738,7 @@
|
||||
"nodeHelp": "Ayuda de nodo",
|
||||
"showHelp": "Mostrar ayuda",
|
||||
"showInOutline": "Mostrar en controno",
|
||||
"hideTopics": "Esconder temas",
|
||||
"showTopics": "Mostrar temas",
|
||||
"noHelp": "No hay ningun tema de ayuda seleccionado",
|
||||
"changeLog": "Registro de Cambios"
|
||||
@@ -792,6 +813,7 @@
|
||||
"branches": "Ramas",
|
||||
"noBranches": "Sin ramas",
|
||||
"deleteConfirm": "¿Estás seguro de que quieres eliminar la rama local '__name__'? Esta acción no puede deshacerse.",
|
||||
"deleteBranch": "Eliminar rama",
|
||||
"unmergedConfirm": "La rama local '__name__' tiene cambios no fusionados que se perderán. ¿Estás seguro de que quieres eliminarla?",
|
||||
"deleteUnmergedBranch": "Eliminar rama no fusionada",
|
||||
"gitRemotes": "Git remotes",
|
||||
@@ -913,6 +935,8 @@
|
||||
}
|
||||
},
|
||||
"typedInput": {
|
||||
"selected": "__count__ seleccionado",
|
||||
"selected_plural": "__count__ seleccionados",
|
||||
"type": {
|
||||
"str": "texto",
|
||||
"num": "número",
|
||||
@@ -923,7 +947,14 @@
|
||||
"date": "marca tiempo",
|
||||
"jsonata": "expresión",
|
||||
"env": "variable de entorno",
|
||||
"cred": "credencial"
|
||||
"cred": "credencial",
|
||||
"conf-types": "nodo configuración"
|
||||
},
|
||||
"date": {
|
||||
"format": {
|
||||
"timestamp": "milisegundos desde epoch",
|
||||
"object": "Objeto de fecha de JavaScript"
|
||||
}
|
||||
}
|
||||
},
|
||||
"editableList": {
|
||||
@@ -1205,6 +1236,18 @@
|
||||
"diagnostics": {
|
||||
"title": "Información Sistema"
|
||||
},
|
||||
"languages": {
|
||||
"de": "Deutsch",
|
||||
"en-US": "English",
|
||||
"es-ES": "Español (España)",
|
||||
"fr": "Français",
|
||||
"ja": "日本語",
|
||||
"ko": "Korean",
|
||||
"pt-BR": "Português (Brasil)",
|
||||
"ru": "Русский",
|
||||
"zh-CN": "简体中文",
|
||||
"zh-TW": "繁體中文"
|
||||
},
|
||||
"validator": {
|
||||
"errors": {
|
||||
"invalid-json": "Datos JSON inválidos: __error__",
|
||||
|
@@ -375,7 +375,10 @@
|
||||
"flowAdded": "flux ajouté",
|
||||
"moved": "déplacé",
|
||||
"movedTo": "déplacé vers __id__",
|
||||
"movedFrom": "déplacé depuis __id__"
|
||||
"movedFrom": "déplacé depuis __id__",
|
||||
"none": "aucun",
|
||||
"position": "position",
|
||||
"wires": "câbles"
|
||||
},
|
||||
"nodeCount": "__count__ noeud",
|
||||
"nodeCount_plural": "__count__ noeuds",
|
||||
@@ -384,9 +387,14 @@
|
||||
"reviewChanges": "Examiner les modifications",
|
||||
"noBinaryFileShowed": "Impossible d'afficher le contenu du fichier binaire",
|
||||
"viewCommitDiff": "Afficher les modifications de la validation",
|
||||
"commit": "Validation",
|
||||
"compareChanges": "Comparer les modifications",
|
||||
"saveConflict": "Enregistrer la résolution des conflits",
|
||||
"conflictHeader": "<span>__resolved__</span> sur <span>__unresolved__</span> conflit(s) résolu(s)",
|
||||
"localChanges": "Modifications locales",
|
||||
"remoteChanges": "Modifications distantes",
|
||||
"useLocalChanges": "utiliser les modifications locales",
|
||||
"useRemoteChanges": "utiliser les modifications distantes",
|
||||
"commonVersionError": "La version commune ne contient pas de JSON valide :",
|
||||
"oldVersionError": "L'ancienne version ne contient pas de JSON valide :",
|
||||
"newVersionError": "La nouvelle version ne contient pas de JSON valide :"
|
||||
@@ -554,7 +562,9 @@
|
||||
"types": {
|
||||
"local": "Local",
|
||||
"examples": "Exemples"
|
||||
}
|
||||
},
|
||||
"type": "Type",
|
||||
"name": "Nom"
|
||||
},
|
||||
"palette": {
|
||||
"noInfo": "Pas d'information disponible",
|
||||
@@ -803,6 +813,7 @@
|
||||
"branches": "Branches",
|
||||
"noBranches": "Pas de branche",
|
||||
"deleteConfirm": "Êtes-vous sûr de vouloir supprimer la branche locale '__name__' ? Ça ne peut pas être annulé.",
|
||||
"deleteBranch": "Supprimer la branche",
|
||||
"unmergedConfirm": "La branche locale '__name__' contient des modifications non fusionnées qui seront perdues. Êtes-vous sûr de vouloir la supprimer?",
|
||||
"deleteUnmergedBranch": "Supprimer la branche non fusionnée",
|
||||
"gitRemotes": "Git distant",
|
||||
|
@@ -375,7 +375,10 @@
|
||||
"flowAdded": "追加されたフロー",
|
||||
"moved": "移動",
|
||||
"movedTo": "__id__ へ移動",
|
||||
"movedFrom": "__id__ から移動"
|
||||
"movedFrom": "__id__ から移動",
|
||||
"none": "なし",
|
||||
"position": "位置",
|
||||
"wires": "ワイヤー"
|
||||
},
|
||||
"nodeCount": "__count__ 個のノード",
|
||||
"nodeCount_plural": "__count__ 個のノード",
|
||||
@@ -384,9 +387,14 @@
|
||||
"reviewChanges": "変更を表示",
|
||||
"noBinaryFileShowed": "バイナリファイルの中身は表示することができません",
|
||||
"viewCommitDiff": "コミットの内容を表示",
|
||||
"commit": "コミット",
|
||||
"compareChanges": "変更を比較",
|
||||
"saveConflict": "解決して保存",
|
||||
"conflictHeader": "<span>__unresolved__</span> 個中 <span>__resolved__</span> 個のコンフリクトを解決",
|
||||
"localChanges": "ローカルの変更",
|
||||
"remoteChanges": "リモートの変更",
|
||||
"useLocalChanges": "ローカルの変更を使用",
|
||||
"useRemoteChanges": "リモートの変更を使用",
|
||||
"commonVersionError": "共通バージョンは正しいJSON形式ではありません:",
|
||||
"oldVersionError": "古いバージョンは正しいJSON形式ではありません:",
|
||||
"newVersionError": "新しいバージョンは正しいJSON形式ではありません:"
|
||||
@@ -554,7 +562,9 @@
|
||||
"types": {
|
||||
"local": "ローカル",
|
||||
"examples": "サンプル"
|
||||
}
|
||||
},
|
||||
"type": "型",
|
||||
"name": "名前"
|
||||
},
|
||||
"palette": {
|
||||
"noInfo": "情報がありません",
|
||||
@@ -803,6 +813,7 @@
|
||||
"branches": "ブランチ",
|
||||
"noBranches": "ブランチなし",
|
||||
"deleteConfirm": "本当にローカルブランチ'__name__'を削除しますか?削除すると元に戻すことはできません。",
|
||||
"deleteBranch": "ブランチを削除",
|
||||
"unmergedConfirm": "ローカルブランチ'__name__'にはマージされていない変更があります。この変更は削除されます。本当に削除しますか?",
|
||||
"deleteUnmergedBranch": "マージされていないブランチを削除",
|
||||
"gitRemotes": "Gitリモート",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-client",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.4",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@@ -100,16 +100,36 @@ RED.multiplayer = (function () {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (isInWorkspace) {
|
||||
const chart = $('#red-ui-workspace-chart')
|
||||
const chartOffset = chart.offset()
|
||||
const scaleFactor = RED.view.scale()
|
||||
location.cursor = {
|
||||
x: (lastPosition[0] - chartOffset.left + chart.scrollLeft()) / scaleFactor,
|
||||
y: (lastPosition[1] - chartOffset.top + chart.scrollTop()) / scaleFactor
|
||||
}
|
||||
}
|
||||
return location
|
||||
}
|
||||
|
||||
let publishLocationTimeout
|
||||
let lastPosition = [0,0]
|
||||
let isInWorkspace = false
|
||||
|
||||
function publishLocation () {
|
||||
const location = getLocation()
|
||||
if (location.workspace !== 0) {
|
||||
log('send', 'multiplayer/location', location)
|
||||
RED.comms.send('multiplayer/location', location)
|
||||
if (!publishLocationTimeout) {
|
||||
publishLocationTimeout = setTimeout(() => {
|
||||
const location = getLocation()
|
||||
if (location.workspace !== 0) {
|
||||
log('send', 'multiplayer/location', location)
|
||||
RED.comms.send('multiplayer/location', location)
|
||||
}
|
||||
publishLocationTimeout = null
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function revealUser(location, skipWorkspace) {
|
||||
if (location.node) {
|
||||
// Need to check if this is a known node, so we can fall back to revealing
|
||||
@@ -271,7 +291,16 @@ RED.multiplayer = (function () {
|
||||
|
||||
function removeUserLocation (sessionId) {
|
||||
updateUserLocation(sessionId, {})
|
||||
removeUserCursor(sessionId)
|
||||
}
|
||||
function removeUserCursor (sessionId) {
|
||||
// return
|
||||
if (sessions[sessionId]?.cursor) {
|
||||
sessions[sessionId].cursor.parentNode.removeChild(sessions[sessionId].cursor)
|
||||
delete sessions[sessionId].cursor
|
||||
}
|
||||
}
|
||||
|
||||
function updateUserLocation (sessionId, location) {
|
||||
let viewTouched = false
|
||||
const oldLocation = sessions[sessionId].location
|
||||
@@ -291,6 +320,28 @@ RED.multiplayer = (function () {
|
||||
// console.log(`updateUserLocation sessionId:${sessionId} oldWS:${oldLocation?.workspace} newWS:${location.workspace}`)
|
||||
if (location.workspace) {
|
||||
getWorkspaceTray(location.workspace).addUser(sessionId)
|
||||
if (location.cursor && location.workspace === RED.workspaces.active()) {
|
||||
if (!sessions[sessionId].cursor) {
|
||||
const user = sessions[sessionId].user
|
||||
const cursorIcon = document.createElementNS("http://www.w3.org/2000/svg","g");
|
||||
cursorIcon.setAttribute("class", "red-ui-multiplayer-annotation")
|
||||
cursorIcon.appendChild(createAnnotationUser(user, true))
|
||||
$(cursorIcon).css({
|
||||
transform: `translate( ${location.cursor.x}px, ${location.cursor.y}px)`,
|
||||
transition: 'transform 0.1s linear'
|
||||
})
|
||||
$("#red-ui-workspace-chart svg").append(cursorIcon)
|
||||
sessions[sessionId].cursor = cursorIcon
|
||||
} else {
|
||||
const cursorIcon = sessions[sessionId].cursor
|
||||
$(cursorIcon).css({
|
||||
transform: `translate( ${location.cursor.x}px, ${location.cursor.y}px)`
|
||||
})
|
||||
|
||||
}
|
||||
} else if (sessions[sessionId].cursor) {
|
||||
removeUserCursor(sessionId)
|
||||
}
|
||||
}
|
||||
if (location.node) {
|
||||
addUserToNode(sessionId, location.node)
|
||||
@@ -309,67 +360,69 @@ RED.multiplayer = (function () {
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
function createAnnotationUser(user, pointer = false) {
|
||||
const radius = 20
|
||||
const halfRadius = radius/2
|
||||
const group = document.createElementNS("http://www.w3.org/2000/svg","g");
|
||||
const badge = document.createElementNS("http://www.w3.org/2000/svg","path");
|
||||
let shapePath
|
||||
if (!pointer) {
|
||||
shapePath = `M 0 ${halfRadius} a ${halfRadius} ${halfRadius} 0 1 1 ${radius} 0 a ${halfRadius} ${halfRadius} 0 1 1 -${radius} 0 z`
|
||||
} else {
|
||||
shapePath = `M 0 0 h ${halfRadius} a ${halfRadius} ${halfRadius} 0 1 1 -${halfRadius} ${halfRadius} z`
|
||||
}
|
||||
badge.setAttribute('d', shapePath)
|
||||
badge.setAttribute("class", "red-ui-multiplayer-annotation-background")
|
||||
group.appendChild(badge)
|
||||
if (user && user.profileColor !== undefined) {
|
||||
badge.setAttribute("class", "red-ui-multiplayer-annotation-background red-ui-user-profile-color-" + user.profileColor)
|
||||
}
|
||||
if (user && user.image) {
|
||||
const image = document.createElementNS("http://www.w3.org/2000/svg","image");
|
||||
image.setAttribute("width", radius)
|
||||
image.setAttribute("height", radius)
|
||||
image.setAttribute("href", user.image)
|
||||
image.setAttribute("clip-path", "circle("+Math.floor(radius/2)+")")
|
||||
group.appendChild(image)
|
||||
} else if (user && user.anonymous) {
|
||||
const anonIconHead = document.createElementNS("http://www.w3.org/2000/svg","circle");
|
||||
anonIconHead.setAttribute("cx", radius/2)
|
||||
anonIconHead.setAttribute("cy", radius/2 - 2)
|
||||
anonIconHead.setAttribute("r", 2.4)
|
||||
anonIconHead.setAttribute("class","red-ui-multiplayer-annotation-anon-label");
|
||||
group.appendChild(anonIconHead)
|
||||
const anonIconBody = document.createElementNS("http://www.w3.org/2000/svg","path");
|
||||
anonIconBody.setAttribute("class","red-ui-multiplayer-annotation-anon-label");
|
||||
// anonIconBody.setAttribute("d",`M ${radius/2 - 4} ${radius/2 + 1} h 8 v4 h -8 z`);
|
||||
anonIconBody.setAttribute("d",`M ${radius/2} ${radius/2 + 5} h -2.5 c -2 1 -2 -5 0.5 -4.5 c 2 1 2 1 4 0 c 2.5 -0.5 2.5 5.5 0 4.5 z`);
|
||||
group.appendChild(anonIconBody)
|
||||
} else {
|
||||
const labelText = user.username ? user.username.substring(0,2) : user
|
||||
const label = document.createElementNS("http://www.w3.org/2000/svg","text");
|
||||
if (user.username) {
|
||||
label.setAttribute("class","red-ui-multiplayer-annotation-label");
|
||||
label.textContent = user.username.substring(0,2)
|
||||
} else {
|
||||
label.setAttribute("class","red-ui-multiplayer-annotation-label red-ui-multiplayer-user-count")
|
||||
label.textContent = user
|
||||
}
|
||||
label.setAttribute("text-anchor", "middle")
|
||||
label.setAttribute("x",radius/2);
|
||||
label.setAttribute("y",radius/2 + 3);
|
||||
group.appendChild(label)
|
||||
}
|
||||
const border = document.createElementNS("http://www.w3.org/2000/svg","path");
|
||||
border.setAttribute('d', shapePath)
|
||||
border.setAttribute("class", "red-ui-multiplayer-annotation-border")
|
||||
group.appendChild(border)
|
||||
return group
|
||||
}
|
||||
|
||||
return {
|
||||
init: function () {
|
||||
|
||||
function createAnnotationUser(user) {
|
||||
|
||||
const group = document.createElementNS("http://www.w3.org/2000/svg","g");
|
||||
const badge = document.createElementNS("http://www.w3.org/2000/svg","circle");
|
||||
const radius = 20
|
||||
badge.setAttribute("cx",radius/2);
|
||||
badge.setAttribute("cy",radius/2);
|
||||
badge.setAttribute("r",radius/2);
|
||||
badge.setAttribute("class", "red-ui-multiplayer-annotation-background")
|
||||
group.appendChild(badge)
|
||||
if (user && user.profileColor !== undefined) {
|
||||
badge.setAttribute("class", "red-ui-multiplayer-annotation-background red-ui-user-profile-color-" + user.profileColor)
|
||||
}
|
||||
if (user && user.image) {
|
||||
const image = document.createElementNS("http://www.w3.org/2000/svg","image");
|
||||
image.setAttribute("width", radius)
|
||||
image.setAttribute("height", radius)
|
||||
image.setAttribute("href", user.image)
|
||||
image.setAttribute("clip-path", "circle("+Math.floor(radius/2)+")")
|
||||
group.appendChild(image)
|
||||
} else if (user && user.anonymous) {
|
||||
const anonIconHead = document.createElementNS("http://www.w3.org/2000/svg","circle");
|
||||
anonIconHead.setAttribute("cx", radius/2)
|
||||
anonIconHead.setAttribute("cy", radius/2 - 2)
|
||||
anonIconHead.setAttribute("r", 2.4)
|
||||
anonIconHead.setAttribute("class","red-ui-multiplayer-annotation-anon-label");
|
||||
group.appendChild(anonIconHead)
|
||||
const anonIconBody = document.createElementNS("http://www.w3.org/2000/svg","path");
|
||||
anonIconBody.setAttribute("class","red-ui-multiplayer-annotation-anon-label");
|
||||
// anonIconBody.setAttribute("d",`M ${radius/2 - 4} ${radius/2 + 1} h 8 v4 h -8 z`);
|
||||
anonIconBody.setAttribute("d",`M ${radius/2} ${radius/2 + 5} h -2.5 c -2 1 -2 -5 0.5 -4.5 c 2 1 2 1 4 0 c 2.5 -0.5 2.5 5.5 0 4.5 z`);
|
||||
group.appendChild(anonIconBody)
|
||||
} else {
|
||||
const labelText = user.username ? user.username.substring(0,2) : user
|
||||
const label = document.createElementNS("http://www.w3.org/2000/svg","text");
|
||||
if (user.username) {
|
||||
label.setAttribute("class","red-ui-multiplayer-annotation-label");
|
||||
label.textContent = user.username.substring(0,2)
|
||||
} else {
|
||||
label.setAttribute("class","red-ui-multiplayer-annotation-label red-ui-multiplayer-user-count")
|
||||
label.textContent = user
|
||||
}
|
||||
label.setAttribute("text-anchor", "middle")
|
||||
label.setAttribute("x",radius/2);
|
||||
label.setAttribute("y",radius/2 + 3);
|
||||
group.appendChild(label)
|
||||
}
|
||||
const border = document.createElementNS("http://www.w3.org/2000/svg","circle");
|
||||
border.setAttribute("cx",radius/2);
|
||||
border.setAttribute("cy",radius/2);
|
||||
border.setAttribute("r",radius/2);
|
||||
border.setAttribute("class", "red-ui-multiplayer-annotation-border")
|
||||
group.appendChild(border)
|
||||
|
||||
|
||||
|
||||
return group
|
||||
}
|
||||
|
||||
|
||||
RED.view.annotations.register("red-ui-multiplayer",{
|
||||
type: 'badge',
|
||||
@@ -479,6 +532,24 @@ RED.multiplayer = (function () {
|
||||
RED.comms.send('multiplayer/disconnect', disconnectInfo)
|
||||
RED.settings.removeLocal('multiplayer:sessionId')
|
||||
})
|
||||
|
||||
const chart = $('#red-ui-workspace-chart')
|
||||
chart.on('mousemove', function (evt) {
|
||||
lastPosition[0] = evt.clientX
|
||||
lastPosition[1] = evt.clientY
|
||||
publishLocation()
|
||||
})
|
||||
chart.on('scroll', function (evt) {
|
||||
publishLocation()
|
||||
})
|
||||
chart.on('mouseenter', function () {
|
||||
isInWorkspace = true
|
||||
publishLocation()
|
||||
})
|
||||
chart.on('mouseleave', function () {
|
||||
isInWorkspace = false
|
||||
publishLocation()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2406,11 +2406,28 @@ RED.nodes = (function() {
|
||||
} else {
|
||||
delete n.g
|
||||
}
|
||||
// If importing into a subflow, ensure an outbound-link doesn't get added
|
||||
if (activeSubflow && /^link /.test(n.type) && n.links) {
|
||||
// If importing a link node, ensure both ends of each link are either:
|
||||
// - not in a subflow
|
||||
// - both in the same subflow (not for link call node)
|
||||
if (/^link /.test(n.type) && n.links) {
|
||||
n.links = n.links.filter(function(id) {
|
||||
const otherNode = node_map[id] || RED.nodes.node(id);
|
||||
return (otherNode && otherNode.z === activeWorkspace);
|
||||
if (!otherNode) {
|
||||
// Cannot find other end - remove the link
|
||||
return false
|
||||
}
|
||||
if (otherNode.z === n.z) {
|
||||
// Both ends in the same flow/subflow
|
||||
return true
|
||||
} else if (n.type === "link call" && !!getSubflow(otherNode.z)) {
|
||||
// Link call node can call out of a subflow as long as otherNode is
|
||||
// not in a subflow
|
||||
return false
|
||||
} else if (!!getSubflow(n.z) || !!getSubflow(otherNode.z)) {
|
||||
// One end is in a subflow - remove the link
|
||||
return false
|
||||
}
|
||||
return true
|
||||
});
|
||||
}
|
||||
for (var d3 in n._def.defaults) {
|
||||
|
@@ -205,7 +205,9 @@ RED.actionList = (function() {
|
||||
}
|
||||
|
||||
function init() {
|
||||
RED.actions.add("core:show-action-list",show);
|
||||
if (RED.settings.theme("menu.menu-item-action-list", true)) {
|
||||
RED.actions.add("core:show-action-list",show);
|
||||
}
|
||||
|
||||
RED.events.on("editor:open",function() { disabled = true; });
|
||||
RED.events.on("editor:close",function() { disabled = false; });
|
||||
|
@@ -65,10 +65,11 @@ RED.contextMenu = (function () {
|
||||
addY = gridSize * Math.floor(addY / gridSize)
|
||||
}
|
||||
|
||||
menuItems.push(
|
||||
{ onselect: 'core:show-action-list', label: RED._("contextMenu.showActionList"), onpostselect: function () { } }
|
||||
)
|
||||
|
||||
if (RED.settings.theme("menu.menu-item-action-list", true)) {
|
||||
menuItems.push(
|
||||
{ onselect: 'core:show-action-list', label: RED._("contextMenu.showActionList"), onpostselect: function () { } }
|
||||
)
|
||||
}
|
||||
const insertOptions = []
|
||||
menuItems.push({ label: RED._("contextMenu.insert"), options: insertOptions })
|
||||
insertOptions.push(
|
||||
|
@@ -589,7 +589,9 @@ RED.deploy = (function() {
|
||||
RED.notify('<p>' + RED._("deploy.successfulDeploy") + '</p>', "success");
|
||||
}
|
||||
const flowsToLock = new Set()
|
||||
// Node's properties cannot be modified if its workspace is locked.
|
||||
function ensureUnlocked(id) {
|
||||
// TODO: `RED.nodes.subflow` is useless
|
||||
const flow = id && (RED.nodes.workspace(id) || RED.nodes.subflow(id) || null);
|
||||
const isLocked = flow ? flow.locked : false;
|
||||
if (flow && isLocked) {
|
||||
@@ -642,6 +644,7 @@ RED.deploy = (function() {
|
||||
delete confNode.credentials;
|
||||
}
|
||||
});
|
||||
// Subflow cannot be locked
|
||||
RED.nodes.eachSubflow(function (subflow) {
|
||||
if (subflow.changed) {
|
||||
subflow.changed = false;
|
||||
@@ -650,12 +653,18 @@ RED.deploy = (function() {
|
||||
});
|
||||
RED.nodes.eachWorkspace(function (ws) {
|
||||
if (ws.changed || ws.added) {
|
||||
ensureUnlocked(ws.z)
|
||||
// Ensure the Workspace is unlocked to modify its properties.
|
||||
ensureUnlocked(ws.id);
|
||||
ws.changed = false;
|
||||
delete ws.added
|
||||
if (flowsToLock.has(ws)) {
|
||||
ws.locked = true;
|
||||
flowsToLock.delete(ws);
|
||||
}
|
||||
RED.events.emit("flows:change", ws)
|
||||
}
|
||||
});
|
||||
// Ensures all workspaces to be locked have been locked.
|
||||
flowsToLock.forEach(flow => {
|
||||
flow.locked = true
|
||||
})
|
||||
|
@@ -497,7 +497,7 @@ RED.diff = (function() {
|
||||
}
|
||||
})
|
||||
if (c === 0) {
|
||||
result.text("none");
|
||||
result.text(RED._("diff.type.none"));
|
||||
} else {
|
||||
list.appendTo(result);
|
||||
}
|
||||
@@ -821,7 +821,7 @@ RED.diff = (function() {
|
||||
conflict = true;
|
||||
}
|
||||
row = $("<tr>").appendTo(nodePropertiesTableBody);
|
||||
$("<td>",{class:"red-ui-diff-list-cell-label"}).text("position").appendTo(row);
|
||||
$("<td>",{class:"red-ui-diff-list-cell-label"}).text(RED._("diff.type.position")).appendTo(row);
|
||||
localCell = $("<td>",{class:"red-ui-diff-list-cell red-ui-diff-list-node-local"}).appendTo(row);
|
||||
if (localNode) {
|
||||
localCell.addClass("red-ui-diff-status-"+(localChanged?"moved":"unchanged"));
|
||||
@@ -899,7 +899,7 @@ RED.diff = (function() {
|
||||
conflict = true;
|
||||
}
|
||||
row = $("<tr>").appendTo(nodePropertiesTableBody);
|
||||
$("<td>",{class:"red-ui-diff-list-cell-label"}).text("wires").appendTo(row);
|
||||
$("<td>",{class:"red-ui-diff-list-cell-label"}).text(RED._("diff.type.wires")).appendTo(row);
|
||||
localCell = $("<td>",{class:"red-ui-diff-list-cell red-ui-diff-list-node-local"}).appendTo(row);
|
||||
if (localNode) {
|
||||
if (!conflict) {
|
||||
@@ -2029,15 +2029,14 @@ RED.diff = (function() {
|
||||
if (!isSeparator) {
|
||||
var isOurs = /^..<<<<<<</.test(lineText);
|
||||
if (isOurs) {
|
||||
$('<span>').text("<<<<<<< Local Changes").appendTo(line);
|
||||
$('<span>').text("<<<<<<< " + RED._("diff.localChanges")).appendTo(line);
|
||||
hunk.localChangeStart = actualLineNumber;
|
||||
} else {
|
||||
hunk.remoteChangeEnd = actualLineNumber;
|
||||
$('<span>').text(">>>>>>> Remote Changes").appendTo(line);
|
||||
|
||||
$('<span>').text(">>>>>>> " + RED._("diff.remoteChanges")).appendTo(line);
|
||||
}
|
||||
diffRow.addClass("mergeHeader-"+(isOurs?"ours":"theirs"));
|
||||
$('<button class="red-ui-button red-ui-button-small" style="float: right; margin-right: 20px;"><i class="fa fa-angle-double-'+(isOurs?"down":"up")+'"></i> use '+(isOurs?"local":"remote")+' changes</button>')
|
||||
$('<button class="red-ui-button red-ui-button-small" style="float: right; margin-right: 20px;"><i class="fa fa-angle-double-'+(isOurs?"down":"up")+'"></i> '+RED._(isOurs?"diff.useLocalChanges":"diff.useRemoteChanges")+'</button>')
|
||||
.appendTo(line)
|
||||
.on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
@@ -2119,7 +2118,7 @@ RED.diff = (function() {
|
||||
$("<h3>").text(commit.title).appendTo(content);
|
||||
$('<div class="commit-body"></div>').text(commit.comment).appendTo(content);
|
||||
var summary = $('<div class="commit-summary"></div>').appendTo(content);
|
||||
$('<div style="float: right">').text("Commit "+commit.sha).appendTo(summary);
|
||||
$('<div style="float: right">').text(RED._('diff.commit')+" "+commit.sha).appendTo(summary);
|
||||
$('<div>').text((commit.authorName||commit.author)+" - "+options.date).appendTo(summary);
|
||||
|
||||
if (commit.files) {
|
||||
|
@@ -899,7 +899,7 @@ RED.editor = (function() {
|
||||
const labelText = RED.editor.envVarList.lookupLabel(labels, labels["en-US"] || tenv.name, locale)
|
||||
const config = {
|
||||
env: tenv,
|
||||
id: '${' + parentEnv[0].name + '}',
|
||||
id: '${' + tenv.name + '}',
|
||||
type: type,
|
||||
label: labelText,
|
||||
__label__: `[env] ${labelText}`
|
||||
|
@@ -839,10 +839,10 @@ RED.library = (function() {
|
||||
if (file && file.label && !file.children) {
|
||||
$.get("library/"+file.library+"/"+file.type+"/"+file.path, function(data) {
|
||||
//TODO: nls + sanitize
|
||||
var propRow = $('<tr class="red-ui-help-info-row"><td>Type</td><td></td></tr>').appendTo(table);
|
||||
var propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("library.type")+'</td><td></td></tr>').appendTo(table);
|
||||
$(propRow.children()[1]).text(activeLibrary.type);
|
||||
if (file.props.hasOwnProperty('name')) {
|
||||
propRow = $('<tr class="red-ui-help-info-row"><td>Name</td><td>'+file.props.name+'</td></tr>').appendTo(table);
|
||||
propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("library.name")+'</td><td>'+file.props.name+'</td></tr>').appendTo(table);
|
||||
$(propRow.children()[1]).text(file.props.name);
|
||||
}
|
||||
for (var p in file.props) {
|
||||
|
@@ -308,7 +308,7 @@ RED.projects.settings = (function() {
|
||||
if (activeProject.dependencies) {
|
||||
for (var m in activeProject.dependencies) {
|
||||
if (activeProject.dependencies.hasOwnProperty(m)) {
|
||||
var installed = !!RED.nodes.registry.getModule(m) && activeProject.dependencies[m] === modulesInUse[m].version;
|
||||
var installed = !!RED.nodes.registry.getModule(m) && activeProject.dependencies[m] === modulesInUse[m]?.version;
|
||||
depsList.editableList('addItem',{
|
||||
id: m,
|
||||
version: activeProject.dependencies[m], //RED.nodes.registry.getModule(module).version,
|
||||
@@ -1256,7 +1256,7 @@ RED.projects.settings = (function() {
|
||||
notification.close();
|
||||
}
|
||||
},{
|
||||
text: 'Delete branch',
|
||||
text: RED._("sidebar.project.projectSettings.deleteBranch"),
|
||||
click: function() {
|
||||
notification.close();
|
||||
var url = "projects/"+activeProject.name+"/branches/"+entry.name;
|
||||
|
@@ -204,7 +204,7 @@ RED.sidebar.info = (function() {
|
||||
|
||||
propertiesPanelHeaderIcon.empty();
|
||||
RED.utils.createNodeIcon({type:"_selection_"}).appendTo(propertiesPanelHeaderIcon);
|
||||
propertiesPanelHeaderLabel.text("Selection");
|
||||
propertiesPanelHeaderLabel.text(RED._("sidebar.info.selection"));
|
||||
propertiesPanelHeaderReveal.hide();
|
||||
propertiesPanelHeaderHelp.hide();
|
||||
propertiesPanelHeaderCopyLink.hide();
|
||||
|
@@ -279,6 +279,11 @@ RED.typeSearch = (function() {
|
||||
if ($("#red-ui-main-container").height() - opts.y - 195 < 0) {
|
||||
opts.y = opts.y - 275;
|
||||
}
|
||||
const dialogWidth = dialog.width() || 300 // default is 300 (defined in class .red-ui-search)
|
||||
const workspaceWidth = $('#red-ui-workspace').width()
|
||||
if (workspaceWidth > dialogWidth && workspaceWidth - opts.x - dialogWidth < 0) {
|
||||
opts.x = opts.x - (dialogWidth - RED.view.node_width)
|
||||
}
|
||||
dialog.css({left:opts.x+"px",top:opts.y+"px"}).show();
|
||||
searchResultsDiv.slideDown(300);
|
||||
setTimeout(function() {
|
||||
@@ -330,13 +335,25 @@ RED.typeSearch = (function() {
|
||||
}
|
||||
}
|
||||
function applyFilter(filter,type,def) {
|
||||
return !def || !filter ||
|
||||
(
|
||||
(!filter.spliceMultiple) &&
|
||||
(!filter.type || type === filter.type) &&
|
||||
(!filter.input || type === 'junction' || def.inputs > 0) &&
|
||||
(!filter.output || type === 'junction' || def.outputs > 0)
|
||||
)
|
||||
if (!filter) {
|
||||
// No filter; allow everything
|
||||
return true
|
||||
}
|
||||
if (type === 'junction') {
|
||||
// Only allow Junction is there's no specific type filter
|
||||
return !filter.type
|
||||
}
|
||||
if (filter.type) {
|
||||
// Handle explicit type filter
|
||||
return filter.type === type
|
||||
}
|
||||
if (!def) {
|
||||
// No node definition available - allow it
|
||||
return true
|
||||
}
|
||||
// Check if the filter is for input/outputs and apply
|
||||
return (!filter.input || def.inputs > 0) &&
|
||||
(!filter.output || def.outputs > 0)
|
||||
}
|
||||
function refreshTypeList(opts) {
|
||||
var i;
|
||||
|
@@ -1209,7 +1209,10 @@ RED.view = (function() {
|
||||
lasso = null;
|
||||
}
|
||||
if (d3.event.touches || d3.event.button === 0) {
|
||||
if ((mouse_mode === 0 || mouse_mode === RED.state.QUICK_JOINING) && isControlPressed(d3.event) && !(d3.event.altKey || d3.event.shiftKey)) {
|
||||
if (
|
||||
(mouse_mode === 0 && isControlPressed(d3.event) && !(d3.event.altKey || d3.event.shiftKey)) ||
|
||||
mouse_mode === RED.state.QUICK_JOINING
|
||||
) {
|
||||
// Trigger quick add dialog
|
||||
d3.event.stopPropagation();
|
||||
clearSelection();
|
||||
@@ -1285,7 +1288,6 @@ RED.view = (function() {
|
||||
}
|
||||
|
||||
var mainPos = $("#red-ui-main-container").position();
|
||||
|
||||
if (mouse_mode !== RED.state.QUICK_JOINING) {
|
||||
mouse_mode = RED.state.QUICK_JOINING;
|
||||
$(window).on('keyup',disableQuickJoinEventHandler);
|
||||
@@ -3057,8 +3059,8 @@ RED.view = (function() {
|
||||
}
|
||||
|
||||
function disableQuickJoinEventHandler(evt) {
|
||||
// Check for ctrl (all browsers), "Meta" (Chrome/FF), keyCode 91 (Safari)
|
||||
if (evt.keyCode === 17 || evt.key === "Meta" || evt.keyCode === 91) {
|
||||
// Check for ctrl (all browsers), "Meta" (Chrome/FF), keyCode 91 (Safari), or Escape
|
||||
if (evt.keyCode === 17 || evt.key === "Meta" || evt.keyCode === 91 || evt.keyCode === 27) {
|
||||
resetMouseVars();
|
||||
hideDragLines();
|
||||
redraw();
|
||||
@@ -3189,27 +3191,59 @@ RED.view = (function() {
|
||||
|
||||
for (i=0;i<drag_lines.length;i++) {
|
||||
if (portType != drag_lines[i].portType && mouseup_node !== drag_lines[i].node) {
|
||||
var drag_line = drag_lines[i];
|
||||
var src,dst,src_port;
|
||||
let drag_line = drag_lines[i];
|
||||
let src,dst,src_port;
|
||||
let oldDst;
|
||||
let oldSrc;
|
||||
if (drag_line.portType === PORT_TYPE_OUTPUT) {
|
||||
src = drag_line.node;
|
||||
src_port = drag_line.port;
|
||||
dst = mouseup_node;
|
||||
oldSrc = src;
|
||||
if (drag_line.link) {
|
||||
oldDst = drag_line.link.target;
|
||||
}
|
||||
} else if (drag_line.portType === PORT_TYPE_INPUT) {
|
||||
src = mouseup_node;
|
||||
dst = drag_line.node;
|
||||
src_port = portIndex || 0;
|
||||
oldSrc = dst;
|
||||
if (drag_line.link) {
|
||||
oldDst = drag_line.link.source
|
||||
}
|
||||
}
|
||||
var link = {source: src, sourcePort:src_port, target: dst};
|
||||
if (drag_line.virtualLink) {
|
||||
if (/^link (in|out)$/.test(src.type) && /^link (in|out)$/.test(dst.type) && src.type !== dst.type) {
|
||||
if (src.links.indexOf(dst.id) === -1 && dst.links.indexOf(src.id) === -1) {
|
||||
var oldSrcLinks = $.extend(true,{},{v:src.links}).v
|
||||
var oldDstLinks = $.extend(true,{},{v:dst.links}).v
|
||||
var oldSrcLinks = [...src.links]
|
||||
var oldDstLinks = [...dst.links]
|
||||
|
||||
src.links.push(dst.id);
|
||||
dst.links.push(src.id);
|
||||
|
||||
if (oldDst) {
|
||||
src.links = src.links.filter(id => id !== oldDst.id)
|
||||
dst.links = dst.links.filter(id => id !== oldDst.id)
|
||||
var oldOldDstLinks = [...oldDst.links]
|
||||
oldDst.links = oldDst.links.filter(id => id !== oldSrc.id)
|
||||
oldDst.dirty = true;
|
||||
modifiedNodes.push(oldDst);
|
||||
linkEditEvents.push({
|
||||
t:'edit',
|
||||
node: oldDst,
|
||||
dirty: RED.nodes.dirty(),
|
||||
changed: oldDst.changed,
|
||||
changes: {
|
||||
links:oldOldDstLinks
|
||||
}
|
||||
});
|
||||
oldDst.changed = true;
|
||||
}
|
||||
|
||||
src.dirty = true;
|
||||
dst.dirty = true;
|
||||
|
||||
modifiedNodes.push(src);
|
||||
modifiedNodes.push(dst);
|
||||
|
||||
@@ -3237,6 +3271,7 @@ RED.view = (function() {
|
||||
links:oldDstLinks
|
||||
}
|
||||
});
|
||||
|
||||
src.changed = true;
|
||||
dst.changed = true;
|
||||
}
|
||||
|
@@ -183,25 +183,29 @@ RED.workspaces = (function() {
|
||||
},
|
||||
null)
|
||||
}
|
||||
menuItems.push(
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-flow",
|
||||
label: RED._("workspace.addFlow"),
|
||||
onselect: "core:add-flow"
|
||||
}
|
||||
)
|
||||
if (isMenuButton || !!tab) {
|
||||
if (RED.settings.theme("menu.menu-item-workspace-add", true)) {
|
||||
menuItems.push(
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-flow-right",
|
||||
label: RED._("workspace.addFlowToRight"),
|
||||
shortcut: RED.keyboard.getShortcut("core:add-flow-to-right"),
|
||||
onselect: function() {
|
||||
RED.actions.invoke("core:add-flow-to-right", tab)
|
||||
}
|
||||
},
|
||||
null
|
||||
id:"red-ui-tabs-menu-option-add-flow",
|
||||
label: RED._("workspace.addFlow"),
|
||||
onselect: "core:add-flow"
|
||||
}
|
||||
)
|
||||
}
|
||||
if (isMenuButton || !!tab) {
|
||||
if (RED.settings.theme("menu.menu-item-workspace-add", true)) {
|
||||
menuItems.push(
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-flow-right",
|
||||
label: RED._("workspace.addFlowToRight"),
|
||||
shortcut: RED.keyboard.getShortcut("core:add-flow-to-right"),
|
||||
onselect: function() {
|
||||
RED.actions.invoke("core:add-flow-to-right", tab)
|
||||
}
|
||||
},
|
||||
null
|
||||
)
|
||||
}
|
||||
if (activeWorkspace && activeWorkspace.type === 'tab') {
|
||||
menuItems.push(
|
||||
isFlowDisabled ? {
|
||||
@@ -255,7 +259,9 @@ RED.workspaces = (function() {
|
||||
}
|
||||
)
|
||||
}
|
||||
menuItems.push(null)
|
||||
if (menuItems.length > 0) {
|
||||
menuItems.push(null)
|
||||
}
|
||||
if (isMenuButton || !!tab) {
|
||||
menuItems.push(
|
||||
{
|
||||
@@ -299,19 +305,24 @@ RED.workspaces = (function() {
|
||||
}
|
||||
)
|
||||
if (tab) {
|
||||
menuItems.push(null)
|
||||
|
||||
if (RED.settings.theme("menu.menu-item-workspace-delete", true)) {
|
||||
menuItems.push(
|
||||
{
|
||||
label: RED._("common.label.delete"),
|
||||
onselect: function() {
|
||||
if (tab.type === 'tab') {
|
||||
RED.workspaces.delete(tab)
|
||||
} else if (tab.type === 'subflow') {
|
||||
RED.subflow.delete(tab.id)
|
||||
}
|
||||
},
|
||||
disabled: isCurrentLocked || (workspaceTabCount === 1)
|
||||
}
|
||||
)
|
||||
}
|
||||
menuItems.push(
|
||||
null,
|
||||
{
|
||||
label: RED._("common.label.delete"),
|
||||
onselect: function() {
|
||||
if (tab.type === 'tab') {
|
||||
RED.workspaces.delete(tab)
|
||||
} else if (tab.type === 'subflow') {
|
||||
RED.subflow.delete(tab.id)
|
||||
}
|
||||
},
|
||||
disabled: isCurrentLocked || (workspaceTabCount === 1)
|
||||
},
|
||||
{
|
||||
label: RED._("menu.label.export"),
|
||||
shortcut: RED.keyboard.getShortcut("core:show-export-dialog"),
|
||||
@@ -468,7 +479,7 @@ RED.workspaces = (function() {
|
||||
},
|
||||
minimumActiveTabWidth: 150,
|
||||
scrollable: true,
|
||||
addButton: "core:add-flow",
|
||||
addButton: RED.settings.theme("menu.menu-item-workspace-add", true) ? "core:add-flow" : undefined,
|
||||
addButtonCaption: RED._("workspace.addFlow"),
|
||||
menu: function() { return getMenuItems(true) },
|
||||
contextmenu: function(tab) { return getMenuItems(false, tab) }
|
||||
@@ -525,19 +536,24 @@ RED.workspaces = (function() {
|
||||
$(window).on("resize", function() {
|
||||
workspace_tabs.resize();
|
||||
});
|
||||
|
||||
RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)});
|
||||
RED.actions.add("core:add-flow-to-right",function(workspace) {
|
||||
let index
|
||||
if (workspace) {
|
||||
index = workspace_tabs.getTabIndex(workspace.id)+1
|
||||
} else {
|
||||
index = workspace_tabs.activeIndex()+1
|
||||
}
|
||||
addWorkspace(undefined,undefined,index)
|
||||
});
|
||||
RED.actions.add("core:edit-flow",editWorkspace);
|
||||
RED.actions.add("core:remove-flow",removeWorkspace);
|
||||
if (RED.settings.theme("menu.menu-item-workspace-add", true)) {
|
||||
RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)});
|
||||
RED.actions.add("core:add-flow-to-right",function(workspace) {
|
||||
let index
|
||||
if (workspace) {
|
||||
index = workspace_tabs.getTabIndex(workspace.id)+1
|
||||
} else {
|
||||
index = workspace_tabs.activeIndex()+1
|
||||
}
|
||||
addWorkspace(undefined,undefined,index)
|
||||
});
|
||||
}
|
||||
if (RED.settings.theme("menu.menu-item-workspace-edit", true)) {
|
||||
RED.actions.add("core:edit-flow",editWorkspace);
|
||||
}
|
||||
if (RED.settings.theme("menu.menu-item-workspace-delete", true)) {
|
||||
RED.actions.add("core:remove-flow",removeWorkspace);
|
||||
}
|
||||
RED.actions.add("core:enable-flow",enableWorkspace);
|
||||
RED.actions.add("core:disable-flow",disableWorkspace);
|
||||
RED.actions.add("core:lock-flow",lockWorkspace);
|
||||
@@ -904,6 +920,17 @@ RED.workspaces = (function() {
|
||||
}
|
||||
},
|
||||
refresh: function() {
|
||||
var workspace = RED.nodes.workspace(RED.workspaces.active());
|
||||
if (workspace) {
|
||||
document.title = `${documentTitle} : ${workspace.label}`;
|
||||
} else {
|
||||
var subflow = RED.nodes.subflow(RED.workspaces.active());
|
||||
if (subflow) {
|
||||
document.title = `${documentTitle} : ${subflow.name}`;
|
||||
} else {
|
||||
document.title = documentTitle
|
||||
}
|
||||
}
|
||||
RED.nodes.eachWorkspace(function(ws) {
|
||||
workspace_tabs.renameTab(ws.id,ws.label);
|
||||
$("#red-ui-tab-"+(ws.id.replace(".","-"))).attr("flowname",ws.label)
|
||||
|
@@ -151,8 +151,9 @@
|
||||
&.red-ui-tabs-add {
|
||||
padding-right: 29px;
|
||||
}
|
||||
&.red-ui-tabs-add.red-ui-tabs-scrollable {
|
||||
padding-right: 53px;
|
||||
&.red-ui-tabs-add.red-ui-tabs-scrollable,
|
||||
&.red-ui-tabs-menu.red-ui-tabs-scrollable {
|
||||
padding-right: 53px;
|
||||
}
|
||||
&.red-ui-tabs-add.red-ui-tabs-menu.red-ui-tabs-scrollable,
|
||||
&.red-ui-tabs-add.red-ui-tabs-search.red-ui-tabs-scrollable {
|
||||
@@ -310,8 +311,9 @@
|
||||
}
|
||||
|
||||
}
|
||||
.red-ui-tabs.red-ui-tabs-add .red-ui-tab-scroll-right {
|
||||
right: 32px;
|
||||
.red-ui-tabs.red-ui-tabs-add .red-ui-tab-scroll-right,
|
||||
.red-ui-tabs.red-ui-tabs-menu .red-ui-tab-scroll-right {
|
||||
right: 32px;
|
||||
}
|
||||
|
||||
.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-menu .red-ui-tab-scroll-right,
|
||||
|
@@ -104,14 +104,14 @@ module.exports = function(RED) {
|
||||
if (this.credentials && this.credentials.passphrase) {
|
||||
opts.passphrase = this.credentials.passphrase;
|
||||
}
|
||||
if (this.servername) {
|
||||
opts.servername = this.servername;
|
||||
}
|
||||
if (this.alpnprotocol) {
|
||||
opts.ALPNProtocols = [this.alpnprotocol];
|
||||
}
|
||||
opts.rejectUnauthorized = this.verifyservercert;
|
||||
}
|
||||
if (this.servername) {
|
||||
opts.servername = this.servername;
|
||||
}
|
||||
if (this.alpnprotocol) {
|
||||
opts.ALPNProtocols = [this.alpnprotocol];
|
||||
}
|
||||
opts.rejectUnauthorized = this.verifyservercert;
|
||||
return opts;
|
||||
}
|
||||
|
||||
|
@@ -158,9 +158,16 @@ module.exports = function(RED) {
|
||||
if(!keys || !keys.length) return null;
|
||||
keys.forEach(key => {
|
||||
let val = srcUserProperties[key];
|
||||
if(typeof val == "string") {
|
||||
if(typeof val === "string") {
|
||||
count++;
|
||||
_clone[key] = val;
|
||||
} else if (val !== undefined && val !== null) {
|
||||
try {
|
||||
_clone[key] = JSON.stringify(val)
|
||||
count++;
|
||||
} catch (err) {
|
||||
// Silently drop property
|
||||
}
|
||||
}
|
||||
});
|
||||
if(count) properties.userProperties = _clone;
|
||||
@@ -673,6 +680,8 @@ module.exports = function(RED) {
|
||||
delete node.options.protocolId; //V4+ default
|
||||
delete node.options.protocolVersion; //V4 default
|
||||
delete node.options.properties;//V5 only
|
||||
|
||||
|
||||
if (node.compatmode == "true" || node.compatmode === true || node.protocolVersion == 3) {
|
||||
node.options.protocolId = 'MQIsdp';//V3 compat only
|
||||
node.options.protocolVersion = 3;
|
||||
@@ -691,6 +700,21 @@ module.exports = function(RED) {
|
||||
setIntProp(node,node.options.properties,"sessionExpiryInterval");
|
||||
}
|
||||
}
|
||||
// Ensure will payload, if set, is a string
|
||||
if (node.options.will && Object.hasOwn(node.options.will, 'payload')) {
|
||||
let payload = node.options.will.payload
|
||||
if (payload === null || typeof payload === 'undefined') {
|
||||
payload = "";
|
||||
} else if (!Buffer.isBuffer(payload)) {
|
||||
if (typeof payload === "object") {
|
||||
payload = JSON.stringify(payload);
|
||||
} else if (typeof payload !== "string") {
|
||||
payload = "" + payload;
|
||||
}
|
||||
}
|
||||
node.options.will.payload = payload
|
||||
}
|
||||
|
||||
if (node.usetls && n.tls) {
|
||||
var tlsNode = RED.nodes.getNode(n.tls);
|
||||
if (tlsNode) {
|
||||
@@ -725,6 +749,7 @@ module.exports = function(RED) {
|
||||
};
|
||||
|
||||
node.deregister = function(mqttNode, done, autoDisconnect) {
|
||||
setStatusDisconnected(mqttNode, false);
|
||||
delete node.users[mqttNode.id];
|
||||
if (autoDisconnect && !node.closing && node.connected && Object.keys(node.users).length === 0) {
|
||||
node.disconnect(done);
|
||||
|
@@ -1 +1 @@
|
||||
[{"id":"827a48c0.912d88","type":"comment","z":"ff17dfa9.8fa6d","name":"Map property between different numeric ranges","info":"Range node can scale a number from one numeric range to another.\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/map-between-different-number-ranges).","x":240,"y":60,"wires":[]},{"id":"bb23bd77.ce725","type":"inject","z":"ff17dfa9.8fa6d","name":"","repeat":"","crontab":"","once":false,"topic":"","payload":"0","payloadType":"num","x":170,"y":120,"wires":[["42ed281c.790b38"]]},{"id":"42ed281c.790b38","type":"range","z":"ff17dfa9.8fa6d","minin":"0","maxin":"1023","minout":"0","maxout":"5","action":"clamp","round":false,"name":"","x":390,"y":160,"wires":[["56e6dd0f.436c24"]]},{"id":"54659d5c.0283e4","type":"inject","z":"ff17dfa9.8fa6d","name":"","repeat":"","crontab":"","once":false,"topic":"","payload":"512","payloadType":"num","x":170,"y":160,"wires":[["42ed281c.790b38"]]},{"id":"85ce0127.07b06","type":"inject","z":"ff17dfa9.8fa6d","name":"","repeat":"","crontab":"","once":false,"topic":"","payload":"1023","payloadType":"num","x":170,"y":200,"wires":[["42ed281c.790b38"]]},{"id":"56e6dd0f.436c24","type":"debug","z":"ff17dfa9.8fa6d","name":"","active":true,"console":"false","complete":"false","x":590,"y":160,"wires":[]}]
|
||||
[{"id":"827a48c0.912d88","type":"comment","z":"ff17dfa9.8fa6d","name":"Map property between different numeric ranges","info":"Range node can scale a number from one numeric range to another.\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/map-between-different-number-ranges).","x":240,"y":60,"wires":[]},{"id":"bb23bd77.ce725","type":"inject","z":"ff17dfa9.8fa6d","name":"","repeat":"","crontab":"","once":false,"topic":"","payload":"0","payloadType":"num","x":170,"y":120,"wires":[["42ed281c.790b38"]]},{"id":"42ed281c.790b38","type":"range","z":"ff17dfa9.8fa6d","minin":"0","maxin":"1023","minout":"0","maxout":"5","action":"clamp","round":false,"property":"payload","name":"","x":390,"y":160,"wires":[["56e6dd0f.436c24"]]},{"id":"54659d5c.0283e4","type":"inject","z":"ff17dfa9.8fa6d","name":"","repeat":"","crontab":"","once":false,"topic":"","payload":"512","payloadType":"num","x":170,"y":160,"wires":[["42ed281c.790b38"]]},{"id":"85ce0127.07b06","type":"inject","z":"ff17dfa9.8fa6d","name":"","repeat":"","crontab":"","once":false,"topic":"","payload":"1023","payloadType":"num","x":170,"y":200,"wires":[["42ed281c.790b38"]]},{"id":"56e6dd0f.436c24","type":"debug","z":"ff17dfa9.8fa6d","name":"","active":true,"console":"false","complete":"false","x":590,"y":160,"wires":[]}]
|
@@ -456,7 +456,7 @@
|
||||
"staticTopic": "Subscribe to single topic",
|
||||
"dynamicTopic": "Dynamic subscription",
|
||||
"auto-connect": "Connect automatically",
|
||||
"auto-mode-depreciated": "This option is depreciated. Please use the new auto-detect mode.",
|
||||
"auto-mode-depreciated": "This option is deprecated. Please use the new auto-detect mode.",
|
||||
"none": "none",
|
||||
"other": "other"
|
||||
},
|
||||
|
@@ -513,15 +513,15 @@
|
||||
"method": "Método",
|
||||
"url": "URL",
|
||||
"doc": "Docs",
|
||||
"return": "Return",
|
||||
"upload": "Accept file uploads?",
|
||||
"status": "Status code",
|
||||
"headers": "Headers",
|
||||
"return": "Devolver",
|
||||
"upload": "¿Aceptar cargas de archivos?",
|
||||
"status": "Código de estado",
|
||||
"headers": "Encabezados",
|
||||
"other": "otro",
|
||||
"paytoqs": {
|
||||
"ignore": "Ignore",
|
||||
"query": "Append to query-string parameters",
|
||||
"body": "Send as request body"
|
||||
"ignore": "Ignorar",
|
||||
"query": "Agregar a los parámetros de la cadena de consulta",
|
||||
"body": "Enviar como cuerpo de la solicitud"
|
||||
},
|
||||
"utf8String": "texto UTF8",
|
||||
"binaryBuffer": "buffer binario",
|
||||
@@ -529,45 +529,45 @@
|
||||
"authType": "Tipo",
|
||||
"bearerToken": "Token"
|
||||
},
|
||||
"setby": "- set by msg.method -",
|
||||
"basicauth": "Use authentication",
|
||||
"use-tls": "Enable secure (SSL/TLS) connection",
|
||||
"tls-config": "TLS Configuration",
|
||||
"basic": "basic authentication",
|
||||
"digest": "digest authentication",
|
||||
"bearer": "bearer authentication",
|
||||
"use-proxy": "Use proxy",
|
||||
"persist": "Enable connection keep-alive",
|
||||
"proxy-config": "Proxy Configuration",
|
||||
"use-proxyauth": "Use proxy authentication",
|
||||
"noproxy-hosts": "Ignore hosts",
|
||||
"senderr": "Only send non-2xx responses to Catch node",
|
||||
"utf8": "a UTF-8 string",
|
||||
"binary": "a binary buffer",
|
||||
"json": "a parsed JSON object",
|
||||
"setby": "- establecido por msg.method -",
|
||||
"basicauth": "Usar autenticación",
|
||||
"use-tls": "Habilitar conexión segura (SSL/TLS)",
|
||||
"tls-config": "Configuración TLS",
|
||||
"basic": "autenticación básica",
|
||||
"digest": "autenticación digest",
|
||||
"bearer": "autenticación bearer",
|
||||
"use-proxy": "Usar proxy",
|
||||
"persist": "Habilitar conexión activa (keep-alive)",
|
||||
"proxy-config": "Configuración Proxy",
|
||||
"use-proxyauth": "Usar autenticación de proxy",
|
||||
"noproxy-hosts": "Ignorar hosts",
|
||||
"senderr": "Enviar solo respuestas que no sean 2xx al nodo Catch",
|
||||
"utf8": "una cadena UTF-8",
|
||||
"binary": "un búfer binario",
|
||||
"json": "un objeto JSON analizado",
|
||||
"tip": {
|
||||
"in": "The url will be relative to ",
|
||||
"res": "The messages sent to this node <b>must</b> originate from an <i>http input</i> node",
|
||||
"in": "La URL será relativa a ",
|
||||
"res": "Los mensajes enviados a este nodo <b>deben</b> originarse desde un nodo de <i>http input</i>",
|
||||
"req": "Tip: If the JSON parse fails the fetched string is returned as-is."
|
||||
},
|
||||
"httpreq": "http request",
|
||||
"httpreq": "solicitud http",
|
||||
"errors": {
|
||||
"not-created": "Cannot create http-in node when httpNodeRoot set to false",
|
||||
"missing-path": "missing path",
|
||||
"no-response": "No response object",
|
||||
"json-error": "JSON parse error",
|
||||
"no-url": "No url specified",
|
||||
"deprecated-call": "Deprecated call to __method__",
|
||||
"invalid-transport": "non-http transport requested",
|
||||
"timeout-isnan": "Timeout value is not a valid number, ignoring",
|
||||
"timeout-isnegative": "Timeout value is negative, ignoring",
|
||||
"invalid-payload": "Invalid payload",
|
||||
"invalid-url": "Invalid url"
|
||||
"not-created": "No se puede crear el nodo http-in cuando httpNodeRoot está establecido en falso",
|
||||
"missing-path": "falta la ruta",
|
||||
"no-response": "No hay objeto de respuesta",
|
||||
"json-error": "Error de análisis en JSON",
|
||||
"no-url": "No se especificó ninguna URL",
|
||||
"deprecated-call": "Llamada obsoleta a __method__",
|
||||
"invalid-transport": "protocolo no-http solicitado",
|
||||
"timeout-isnan": "El valor de tiempo de espera no es un número válido, se ignora",
|
||||
"timeout-isnegative": "El valor de tiempo de espera es negativo, se ignora",
|
||||
"invalid-payload": "payload Invalido",
|
||||
"invalid-url": "URL Inválida"
|
||||
},
|
||||
"status": {
|
||||
"requesting": "requesting"
|
||||
"requesting": "solicitando"
|
||||
},
|
||||
"insecureHTTPParser": "Disable strict HTTP parsing"
|
||||
"insecureHTTPParser": "Deshabilitar el análisis estricto de HTTP"
|
||||
},
|
||||
"websocket": {
|
||||
"label": {
|
||||
@@ -576,41 +576,42 @@
|
||||
"url": "URL",
|
||||
"subprotocol": "Subprotocolo"
|
||||
},
|
||||
"listenon": "Listen on",
|
||||
"connectto": "Connect to",
|
||||
"sendrec": "Send/Receive",
|
||||
"listenon": "Escuchar",
|
||||
"connectto": "Conectar a",
|
||||
"sendrec": "Enviar/Recibir",
|
||||
"payload": "payload",
|
||||
"message": "entire message",
|
||||
"sendheartbeat": "Send heartbeat",
|
||||
"message": "mensaje completo",
|
||||
"sendheartbeat": "Enviar latido",
|
||||
"tip": {
|
||||
"path1": "By default, <code>payload</code> will contain the data to be sent over, or received from a websocket. The listener can be configured to send or receive the entire message object as a JSON formatted string.",
|
||||
"path2": "This path will be relative to <code>__path__</code>.",
|
||||
"url1": "URL should use ws:// or wss:// scheme and point to an existing websocket listener.",
|
||||
"url2": "By default, <code>payload</code> will contain the data to be sent over, or received from a websocket. The client can be configured to send or receive the entire message object as a JSON formatted string."
|
||||
"path1": "De manera predeterminada, <code>payload</code> contendrá los datos que se enviarán o recibirán de un websocket. El receptor puede configurarse para enviar o recibir el objeto de mensaje completo como una cadena en formato JSON.",
|
||||
"path2": "Esta ruta será relativa a <code>__path__</code>.",
|
||||
"url1": "La URL debe usar el esquema ws:// o wss:// y apuntar a un receptor de websocket existente.",
|
||||
"url2": "De manera predeterminada, <code>payload</code> contendrá los datos que se enviarán o recibirán de un websocket. El cliente puede configurarse para enviar o recibir el objeto de mensaje completo como una cadena en formato JSON",
|
||||
"headers": "Los encabezados solo se envían durante el mecanismo de actualización del protocolo, de HTTP al protocolo WS/WSS."
|
||||
},
|
||||
"status": {
|
||||
"connected": "connected __count__",
|
||||
"connected_plural": "connected __count__"
|
||||
"connected": "__count__ conectado",
|
||||
"connected_plural": "__count__ conectados"
|
||||
},
|
||||
"errors": {
|
||||
"connect-error": "An error occurred on the ws connection: ",
|
||||
"send-error": "An error occurred while sending: ",
|
||||
"missing-conf": "Missing server configuration",
|
||||
"duplicate-path": "Cannot have two WebSocket listeners on the same path: __path__",
|
||||
"missing-server": "Missing server configuration",
|
||||
"missing-client": "Missing client configuration"
|
||||
"connect-error": "Se produjo un error en la conexión ws:",
|
||||
"send-error": "Se produjo un error al enviar: ",
|
||||
"missing-conf": "Falta la configuración del servidor",
|
||||
"duplicate-path": "No se pueden tener dos escuchas de WebSocket en la misma ruta: __path__",
|
||||
"missing-server": "Falta la configuración del servidor",
|
||||
"missing-client": "Falta la configuración del cliente"
|
||||
}
|
||||
},
|
||||
"watch": {
|
||||
"watch": "watch",
|
||||
"watch": "observar",
|
||||
"label": {
|
||||
"files": "File(s)",
|
||||
"recursive": "Watch sub-directories recursively"
|
||||
"files": "Fichero(s)",
|
||||
"recursive": "Observar subdirectorios recursivamente"
|
||||
},
|
||||
"placeholder": {
|
||||
"files": "Comma-separated list of files and/or directories"
|
||||
"files": "Lista de archivos y/o directorios separados por comas"
|
||||
},
|
||||
"tip": "On Windows you must use double back-slashes \\\\ in any directory names."
|
||||
"tip": "En Windows, debes utilizar barras invertidas dobles \\\\ en cualquier nombre de directorio."
|
||||
},
|
||||
"tcpin": {
|
||||
"label": {
|
||||
@@ -849,7 +850,13 @@
|
||||
"newline": "Nueva línea",
|
||||
"usestrings": "analizar valores numéricos",
|
||||
"include_empty_strings": "incluir cadenas vacías",
|
||||
"include_null_values": "incluir valores nulos"
|
||||
"include_null_values": "incluir valores nulos",
|
||||
"spec": "Analizador"
|
||||
},
|
||||
"spec": {
|
||||
"rfc": "RFC4180",
|
||||
"legacy": "Legado",
|
||||
"legacy_warning": "El modo legado se eliminará en una versión futura."
|
||||
},
|
||||
"placeholder": {
|
||||
"columns": "nombres de columnas separados por comas"
|
||||
@@ -878,6 +885,7 @@
|
||||
"once": "enviar encabezados una vez, hasta msg.reset"
|
||||
},
|
||||
"errors": {
|
||||
"bad_template": "Plantilla de columnas mal formada.",
|
||||
"csv_js": "Este nodo solo maneja cadenas CSV u objetos JS.",
|
||||
"obj_csv": "No se ha especificado ninguna plantilla de columnas para el objeto -> CSV.",
|
||||
"bad_csv": "Datos CSV con formato incorrecto: la salida probablemente esté corrupta."
|
||||
@@ -887,12 +895,14 @@
|
||||
"label": {
|
||||
"select": "Selector",
|
||||
"output": "Salida",
|
||||
"in": "en"
|
||||
"in": "en",
|
||||
"prefix": "Nombre de la propiedad para el contenido HTML"
|
||||
},
|
||||
"output": {
|
||||
"html": "el contenido HTML de los elementos",
|
||||
"text": "sólo el contenido textual de los elementos",
|
||||
"attr": "un objeto de cualquier atributo de los elementos"
|
||||
"attr": "un objeto de cualquier atributo de los elementos",
|
||||
"compl": "un objeto de cualquier atributo de los elementos y contenidos html"
|
||||
},
|
||||
"format": {
|
||||
"single": "como un mensaje único que contiene una matriz",
|
||||
@@ -1007,6 +1017,7 @@
|
||||
"objectSend": "Enviar un mensaje para cada par clave/valor",
|
||||
"strBuff": "<b>Texto</b> / <b>Buffer</b>",
|
||||
"array": "<b>Array</b>",
|
||||
"splitThe": "Dividir el",
|
||||
"splitUsing": "Dividir usando",
|
||||
"splitLength": "Longitud fija de",
|
||||
"stream": "Manejar como un flujo de mensajes",
|
||||
@@ -1036,6 +1047,7 @@
|
||||
"joinedUsing": "se unió usando",
|
||||
"send": "Enviar el mensaje:",
|
||||
"afterCount": "Después de varias partes del mensaje",
|
||||
"useparts": "Usar la propiedad msg.parts existente",
|
||||
"count": "contar",
|
||||
"subsequent": "y cada mensaje posterior.",
|
||||
"afterTimeout": "Después de un tiempo de espera trás el primer mensaje",
|
||||
@@ -1102,6 +1114,7 @@
|
||||
"too-many": "demasiados mensajes pendientes en el nodo de lotes",
|
||||
"unexpected": "modo inesperado",
|
||||
"no-parts": "ninguna propiedad 'parte' en el mensaje",
|
||||
"honourParts": "Permitir que msg.parts también complete la operación por lotes.",
|
||||
"error": {
|
||||
"invalid-count": "Recuento no válido",
|
||||
"invalid-overlap": "Solapamiento no válido",
|
||||
|
@@ -24,12 +24,14 @@
|
||||
<p>Solo se envía el <code>msg.payload</code>.</p>
|
||||
<p>Si <code>msg.payload</code> es una cadena que contiene una codificación Base64 de datos binarios, la opción de decodificación Base64 hará que se vuelva a convertir a binario antes de enviarse.</p>
|
||||
<p>Si <code>msg._session</code> no está presente, la carga se envía a <b>todos</b> los clientes conectados.</p>
|
||||
<p>En el modo Responder a, configurar <code>msg.reset = true</code> restablecerá la conexión especificada por _session.id, o todas las conexiones si no se especifica _session.id.</p>
|
||||
<p><b>Nota: </b>En algunos sistemas, es posible que necesites acceso raíz o de administrador para acceder a los puertos inferiores a 1024.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="tcp request">
|
||||
<p>Un nodo de solicitud TCP simple: envía el <code>msg.payload</code> a un puerto tcp del servidor y espera una respuesta.</p>
|
||||
<p>Se conecta, envía la "solicitud" y lee la "respuesta". Puede contar una cantidad de caracteres devueltos en un búfer fijo, hacer coincidir un carácter específico antes de regresar, esperar un tiempo de espera fijo desde la primera respuesta y luego regresar, esperar datos, o enviar y luego cerrar la conexión inmediatamente, sin esperar una respuesta.</p>
|
||||
<p>Si está en modo sentado y esperando (permanecer conectado), puede enviar <code>msg.reset = true</code> o <code>msg.reset = "host:port"</code> para forzar una interrupción en la conexión y una reconexión automática.</p>
|
||||
<p>La respuesta se generará en <code>msg.payload</code> como un búfer, por lo que es posible que quieras utilizar .toString().</p>
|
||||
<p>Si dejas el host TCP o el puerto en blanco, debes configurarlos utilizando las propiedades <code>msg.host</code> y <code>msg.port</code> en cada mensaje enviado al nodo.</p>
|
||||
</script>
|
||||
|
@@ -35,7 +35,9 @@
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Detalles</h3>
|
||||
<p>La plantilla de columnas puede contener una lista ordenada de nombres de columnas. Al convertir CSV en un objeto, los nombres de las columnas se utilizarán como nombres de propiedades. Alternativamente, los nombres de las columnas se pueden tomar de la primera fila del CSV.</p>
|
||||
<p>La plantilla de columnas puede contener una lista ordenada de nombres de columnas. Al convertir CSV en un objeto, los nombres de las columnas se utilizarán como nombres de propiedades. Alternativamente, los nombres de las columnas se pueden tomar de la primera fila del CSV.
|
||||
<p>Cuando se selecciona el analizador RFC, la plantilla de columna debe ser compatible con RFC4180.</p>
|
||||
</p>
|
||||
<p>Al convertir a CSV, la plantilla de columnas se utiliza para identificar qué propiedades extraer del objeto y en qué orden.</p>
|
||||
<p>Si la plantilla de columnas está en blanco, puede utilizar una lista simple de propiedades separadas por comas proporcionada en <code>msg.columns</code> para determinar qué extraer y en qué orden. Si ninguno de los dos está presente, todas las propiedades del objeto se muestran en el orden en que se encuentran en la primera fila.</p>
|
||||
<p>Si la entrada es una matriz, entonces la plantilla de columnas solo se usa para generar opcionalmente una fila de títulos de columnas.</p>
|
||||
@@ -46,4 +48,5 @@
|
||||
<p>Si genera varios mensajes, tendrán su propiedad <code>parts</code> configurada y formarán una secuencia de mensajes completa.</p>
|
||||
<p>Si el nodo está configurado para enviar encabezados de columna solo una vez, si se configura <code>msg.reset</code> en cualquier valor hará que el nodo reenvíe los encabezados.</p>
|
||||
<p><b>Nota:</b> la plantilla de columna debe estar separada por comas, incluso si se elige un separador diferente para los datos.</p>
|
||||
<p><b>Nota:</b> en el modo RFC, se generarán errores detectables para encabezados CSV mal formados y datos de carga útil de entrada no válidos</p>
|
||||
</script>
|
||||
|
@@ -1017,6 +1017,7 @@
|
||||
"objectSend": "Envoie un message pour chaque paire clé/valeur",
|
||||
"strBuff": "<b>Chaîne</b> / <b>Tampon</b>",
|
||||
"array": "<b>Tableau</b>",
|
||||
"splitThe": "Diviser le",
|
||||
"splitUsing": "Diviser en utilisant",
|
||||
"splitLength": "Longueur fixe de",
|
||||
"stream": "Gérer comme un flux de messages",
|
||||
@@ -1046,6 +1047,7 @@
|
||||
"joinedUsing": "joint en utilisant",
|
||||
"send": "Envoyer le message :",
|
||||
"afterCount": "Après un nombre de parties du message",
|
||||
"useparts": "Utiliser la propriété msg.parts existante",
|
||||
"count": "nombre",
|
||||
"subsequent": "Et tous les messages suivants.",
|
||||
"afterTimeout": "Après un délai d'attente après le premier message",
|
||||
@@ -1112,6 +1114,7 @@
|
||||
"too-many": "Trop de messages en attente dans le noeud batch",
|
||||
"unexpected": "Mode inattendu",
|
||||
"no-parts": "Aucune propriété de pièces dans le message",
|
||||
"honourParts": "Autoriser msg.parts à compléter les opération par lots",
|
||||
"error": {
|
||||
"invalid-count": "Compte invalide",
|
||||
"invalid-overlap": "Recouvrement invalide",
|
||||
|
@@ -1047,6 +1047,7 @@
|
||||
"joinedUsing": "連結文字",
|
||||
"send": "メッセージ送信:",
|
||||
"afterCount": "指定数のメッセージパーツを受信後",
|
||||
"useparts": "既存のmsg.partsプロパティを使用",
|
||||
"count": "合計値",
|
||||
"subsequent": "後続のメッセージ毎",
|
||||
"afterTimeout": "最初のメッセージ受信からのタイムアウト後",
|
||||
@@ -1113,6 +1114,7 @@
|
||||
"too-many": "batchノード内で保持しているメッセージが多すぎます",
|
||||
"unexpected": "想定外のモード",
|
||||
"no-parts": "メッセージにpartsプロパティがありません",
|
||||
"honourParts": "msg.partsを用いたbatch操作を許可",
|
||||
"error": {
|
||||
"invalid-count": "メッセージ数が不正",
|
||||
"invalid-overlap": "オーバラップが不正",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/nodes",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.4",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -15,20 +15,20 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"acorn": "8.11.3",
|
||||
"acorn-walk": "8.3.2",
|
||||
"ajv": "8.14.0",
|
||||
"body-parser": "1.20.2",
|
||||
"acorn": "8.12.1",
|
||||
"acorn-walk": "8.3.4",
|
||||
"ajv": "8.17.1",
|
||||
"body-parser": "1.20.3",
|
||||
"cheerio": "1.0.0-rc.10",
|
||||
"content-type": "1.0.5",
|
||||
"cookie-parser": "1.4.6",
|
||||
"cookie": "0.6.0",
|
||||
"cookie-parser": "1.4.7",
|
||||
"cookie": "0.7.2",
|
||||
"cors": "2.8.5",
|
||||
"cronosjs": "1.7.1",
|
||||
"denque": "2.1.0",
|
||||
"form-data": "4.0.0",
|
||||
"fs-extra": "11.2.0",
|
||||
"got": "12.6.0",
|
||||
"got": "12.6.1",
|
||||
"hash-sum": "2.0.0",
|
||||
"hpagent": "1.2.0",
|
||||
"https-proxy-agent": "5.0.1",
|
||||
@@ -40,8 +40,8 @@
|
||||
"mustache": "4.2.0",
|
||||
"node-watch": "0.7.4",
|
||||
"on-headers": "1.0.2",
|
||||
"raw-body": "2.5.2",
|
||||
"tough-cookie": "4.1.4",
|
||||
"raw-body": "3.0.0",
|
||||
"tough-cookie": "^5.0.0",
|
||||
"uuid": "9.0.1",
|
||||
"ws": "7.5.10",
|
||||
"xml2js": "0.6.2",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/registry",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.4",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,11 +16,11 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "4.0.2",
|
||||
"@node-red/util": "4.0.4",
|
||||
"clone": "2.1.2",
|
||||
"fs-extra": "11.2.0",
|
||||
"semver": "7.5.4",
|
||||
"tar": "7.2.0",
|
||||
"semver": "7.6.3",
|
||||
"tar": "7.4.3",
|
||||
"uglify-js": "3.17.4"
|
||||
}
|
||||
}
|
||||
|
@@ -110,7 +110,8 @@ module.exports = {
|
||||
const payload = {
|
||||
session: sessionId,
|
||||
workspace: opts.data.workspace,
|
||||
node: opts.data.node
|
||||
node: opts.data.node,
|
||||
cursor: opts.data.cursor
|
||||
}
|
||||
runtime.events.emit('comms', {
|
||||
topic: 'multiplayer/location',
|
||||
|
@@ -25,6 +25,7 @@
|
||||
"removing-modules": "Eliminando módulos de la configuración",
|
||||
"added-types": "Tipos de nodos añadidos:",
|
||||
"removed-types": "Tipos de nodos eliminados:",
|
||||
"removed-plugins": "Extensiones eliminadas:",
|
||||
"install": {
|
||||
"invalid": "Nombre de módulo no válido",
|
||||
"installing": "Instalando módulo: __name__, versión: __version__",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/runtime",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.4",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,11 +16,11 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/registry": "4.0.2",
|
||||
"@node-red/util": "4.0.2",
|
||||
"@node-red/registry": "4.0.4",
|
||||
"@node-red/util": "4.0.4",
|
||||
"async-mutex": "0.5.0",
|
||||
"clone": "2.1.2",
|
||||
"express": "4.19.2",
|
||||
"express": "4.21.1",
|
||||
"fs-extra": "11.2.0",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"rfdc": "^1.3.1"
|
||||
|
22
packages/node_modules/@node-red/util/lib/log.js
vendored
22
packages/node_modules/@node-red/util/lib/log.js
vendored
@@ -75,12 +75,28 @@ LogHandler.prototype.shouldReportMessage = function(msglevel) {
|
||||
msglevel <= this.logLevel;
|
||||
}
|
||||
|
||||
|
||||
// Older versions of Node-RED used the deprecated util.log function.
|
||||
// With Node.js 22, use of that function causes warnings. So here we
|
||||
// are replicating the same format output to ensure we don't break any
|
||||
// log parsing that happens in the real world.
|
||||
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
const utilLog = function (msg) {
|
||||
const d = new Date();
|
||||
const time = [
|
||||
d.getHours().toString().padStart(2, '0'),
|
||||
d.getMinutes().toString().padStart(2, '0'),
|
||||
d.getSeconds().toString().padStart(2, '0')
|
||||
].join(':');
|
||||
console.log(`${d.getDate()} ${months[d.getMonth()]} ${time} - ${msg}`)
|
||||
}
|
||||
|
||||
var consoleLogger = function(msg) {
|
||||
if (msg.level == log.METRIC || msg.level == log.AUDIT) {
|
||||
util.log("["+levelNames[msg.level]+"] "+JSON.stringify(msg));
|
||||
utilLog("["+levelNames[msg.level]+"] "+JSON.stringify(msg));
|
||||
} else {
|
||||
if (verbose && msg.msg && msg.msg.stack) {
|
||||
util.log("["+levelNames[msg.level]+"] "+(msg.type?"["+msg.type+":"+(msg.name||msg.id)+"] ":"")+msg.msg.stack);
|
||||
utilLog("["+levelNames[msg.level]+"] "+(msg.type?"["+msg.type+":"+(msg.name||msg.id)+"] ":"")+msg.msg.stack);
|
||||
} else {
|
||||
var message = msg.msg;
|
||||
try {
|
||||
@@ -91,7 +107,7 @@ var consoleLogger = function(msg) {
|
||||
message = 'Exception trying to log: '+util.inspect(message);
|
||||
}
|
||||
|
||||
util.log("["+levelNames[msg.level]+"] "+(msg.type?"["+msg.type+":"+(msg.name||msg.id)+"] ":"")+message);
|
||||
utilLog("["+levelNames[msg.level]+"] "+(msg.type?"["+msg.type+":"+(msg.name||msg.id)+"] ":"")+message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/util",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.4",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -21,6 +21,6 @@
|
||||
"jsonata": "2.0.5",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"moment": "2.30.1",
|
||||
"moment-timezone": "0.5.45"
|
||||
"moment-timezone": "0.5.46"
|
||||
}
|
||||
}
|
||||
|
16
packages/node_modules/node-red/package.json
vendored
16
packages/node_modules/node-red/package.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.4",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "https://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -31,18 +31,18 @@
|
||||
"flow"
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/editor-api": "4.0.2",
|
||||
"@node-red/runtime": "4.0.2",
|
||||
"@node-red/util": "4.0.2",
|
||||
"@node-red/nodes": "4.0.2",
|
||||
"@node-red/editor-api": "4.0.4",
|
||||
"@node-red/runtime": "4.0.4",
|
||||
"@node-red/util": "4.0.4",
|
||||
"@node-red/nodes": "4.0.4",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"cors": "2.8.5",
|
||||
"express": "4.19.2",
|
||||
"express": "4.21.1",
|
||||
"fs-extra": "11.2.0",
|
||||
"node-red-admin": "^4.0.0",
|
||||
"node-red-admin": "^4.0.1",
|
||||
"nopt": "5.0.0",
|
||||
"semver": "7.5.4"
|
||||
"semver": "7.6.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@node-rs/bcrypt": "1.10.4"
|
||||
|
@@ -24,38 +24,38 @@ var log = NR_TEST_UTILS.require("@node-red/util").log;
|
||||
|
||||
describe("@node-red/util/log", function() {
|
||||
beforeEach(function () {
|
||||
var spy = sinon.stub(util, 'log').callsFake(function(arg){});
|
||||
var spy = sinon.stub(console, 'log').callsFake(function(arg){});
|
||||
var settings = {logging: { console: { level: 'metric', metrics: true } } };
|
||||
log.init(settings);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
util.log.restore();
|
||||
console.log.restore();
|
||||
});
|
||||
|
||||
it('it can raise an error', function() {
|
||||
var ret = log.error("This is an error");
|
||||
sinon.assert.calledWithMatch(util.log,"[error] This is an error");
|
||||
sinon.assert.calledWithMatch(console.log,"[error] This is an error");
|
||||
});
|
||||
|
||||
it('it can raise a trace', function() {
|
||||
var ret = log.trace("This is a trace");
|
||||
sinon.assert.calledWithMatch(util.log,"[trace] This is a trace");
|
||||
sinon.assert.calledWithMatch(console.log,"[trace] This is a trace");
|
||||
});
|
||||
|
||||
it('it can raise a debug', function() {
|
||||
var ret = log.debug("This is a debug");
|
||||
sinon.assert.calledWithMatch(util.log,"[debug] This is a debug");
|
||||
sinon.assert.calledWithMatch(console.log,"[debug] This is a debug");
|
||||
});
|
||||
|
||||
it('it can raise a info', function() {
|
||||
var ret = log.info("This is an info");
|
||||
sinon.assert.calledWithMatch(util.log,"[info] This is an info");
|
||||
sinon.assert.calledWithMatch(console.log,"[info] This is an info");
|
||||
});
|
||||
|
||||
it('it can raise a warn', function() {
|
||||
var ret = log.warn("This is a warn");
|
||||
sinon.assert.calledWithMatch(util.log,"[warn] This is a warn");
|
||||
sinon.assert.calledWithMatch(console.log,"[warn] This is a warn");
|
||||
});
|
||||
|
||||
it('it can raise a metric', function() {
|
||||
@@ -66,9 +66,10 @@ describe("@node-red/util/log", function() {
|
||||
metrics.msgid = "12345";
|
||||
metrics.value = "the metric payload";
|
||||
var ret = log.log(metrics);
|
||||
util.log.calledOnce.should.be.true();
|
||||
util.log.firstCall.args[0].indexOf("[metric] ").should.equal(0);
|
||||
var body = JSON.parse(util.log.firstCall.args[0].substring(9));
|
||||
console.log.calledOnce.should.be.true();
|
||||
console.log.firstCall.args[0].indexOf("[metric]").should.not.equal(-1);
|
||||
const parts = console.log.firstCall.args[0].split("[metric] ")
|
||||
var body = JSON.parse(parts[1])
|
||||
body.should.have.a.property("nodeid","testid");
|
||||
body.should.have.a.property("event","node.test.testevent");
|
||||
body.should.have.a.property("msgid","12345");
|
||||
@@ -86,13 +87,13 @@ describe("@node-red/util/log", function() {
|
||||
|
||||
it('it logs node type and name if provided',function() {
|
||||
log.log({level:log.INFO,type:"nodeType",msg:"test",name:"nodeName",id:"nodeId"});
|
||||
util.log.calledOnce.should.be.true();
|
||||
util.log.firstCall.args[0].indexOf("[nodeType:nodeName]").should.not.equal(-1);
|
||||
console.log.calledOnce.should.be.true();
|
||||
console.log.firstCall.args[0].indexOf("[nodeType:nodeName]").should.not.equal(-1);
|
||||
});
|
||||
it('it logs node type and id if no name provided',function() {
|
||||
log.log({level:log.INFO,type:"nodeType",msg:"test",id:"nodeId"});
|
||||
util.log.calledOnce.should.be.true();
|
||||
util.log.firstCall.args[0].indexOf("[nodeType:nodeId]").should.not.equal(-1);
|
||||
console.log.calledOnce.should.be.true();
|
||||
console.log.firstCall.args[0].indexOf("[nodeType:nodeId]").should.not.equal(-1);
|
||||
});
|
||||
|
||||
it('ignores lower level messages and metrics', function() {
|
||||
@@ -104,12 +105,12 @@ describe("@node-red/util/log", function() {
|
||||
log.debug("This is a debug");
|
||||
log.trace("This is a trace");
|
||||
log.log({level:log.METRIC,msg:"testMetric"});
|
||||
sinon.assert.calledWithMatch(util.log,"[error] This is an error");
|
||||
sinon.assert.calledWithMatch(util.log,"[warn] This is a warn");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[info] This is an info");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[metric] ");
|
||||
sinon.assert.calledWithMatch(console.log,"[error] This is an error");
|
||||
sinon.assert.calledWithMatch(console.log,"[warn] This is a warn");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[info] This is an info");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[debug] This is a debug");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[trace] This is a trace");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[metric] ");
|
||||
});
|
||||
it('ignores lower level messages but accepts metrics', function() {
|
||||
var settings = {logging: { console: { level: 'log', metrics: true } } };
|
||||
@@ -120,12 +121,12 @@ describe("@node-red/util/log", function() {
|
||||
log.debug("This is a debug");
|
||||
log.trace("This is a trace");
|
||||
log.log({level:log.METRIC,msg:"testMetric"});
|
||||
sinon.assert.calledWithMatch(util.log,"[error] This is an error");
|
||||
sinon.assert.calledWithMatch(util.log,"[warn] This is a warn");
|
||||
sinon.assert.calledWithMatch(util.log,"[info] This is an info");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace");
|
||||
sinon.assert.calledWithMatch(util.log,"[metric] ");
|
||||
sinon.assert.calledWithMatch(console.log,"[error] This is an error");
|
||||
sinon.assert.calledWithMatch(console.log,"[warn] This is a warn");
|
||||
sinon.assert.calledWithMatch(console.log,"[info] This is an info");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[debug] This is a debug");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[trace] This is a trace");
|
||||
sinon.assert.calledWithMatch(console.log,"[metric] ");
|
||||
});
|
||||
|
||||
it('default settings set to INFO and metrics off', function() {
|
||||
@@ -136,12 +137,12 @@ describe("@node-red/util/log", function() {
|
||||
log.debug("This is a debug");
|
||||
log.trace("This is a trace");
|
||||
log.log({level:log.METRIC,msg:"testMetric"});
|
||||
sinon.assert.calledWithMatch(util.log,"[error] This is an error");
|
||||
sinon.assert.calledWithMatch(util.log,"[warn] This is a warn");
|
||||
sinon.assert.calledWithMatch(util.log,"[info] This is an info");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[metric] ");
|
||||
sinon.assert.calledWithMatch(console.log,"[error] This is an error");
|
||||
sinon.assert.calledWithMatch(console.log,"[warn] This is a warn");
|
||||
sinon.assert.calledWithMatch(console.log,"[info] This is an info");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[debug] This is a debug");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[trace] This is a trace");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[metric] ");
|
||||
});
|
||||
it('no logger used if custom logger handler does not exist', function() {
|
||||
var settings = {logging: { customLogger: { level: 'trace', metrics: true } } };
|
||||
@@ -152,12 +153,12 @@ describe("@node-red/util/log", function() {
|
||||
log.debug("This is a debug");
|
||||
log.trace("This is a trace");
|
||||
log.log({level:log.METRIC,msg:"testMetric"});
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[error] This is an error");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[warn] This is a warn");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[info] This is an info");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace");
|
||||
sinon.assert.neverCalledWithMatch(util.log,"[metric] ");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[error] This is an error");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[warn] This is a warn");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[info] This is an info");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[debug] This is a debug");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[trace] This is a trace");
|
||||
sinon.assert.neverCalledWithMatch(console.log,"[metric] ");
|
||||
});
|
||||
|
||||
it('add a custom log handler directly', function() {
|
||||
@@ -244,7 +245,7 @@ describe("@node-red/util/log", function() {
|
||||
},
|
||||
};
|
||||
var ret = log.info(msg.msg);
|
||||
sinon.assert.calledWithMatch(util.log,"my special message");
|
||||
sinon.assert.calledWithMatch(console.log,"my special message");
|
||||
});
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user